add unloading for mod assemblies
This commit is contained in:
67
CringeLauncher/Patches/ModScriptCompilerPatch.cs
Normal file
67
CringeLauncher/Patches/ModScriptCompilerPatch.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.Loader;
|
||||
using CringeLauncher.Utils;
|
||||
using HarmonyLib;
|
||||
using NLog;
|
||||
using Sandbox.Game.World;
|
||||
using VRage.Scripting;
|
||||
|
||||
namespace CringeLauncher.Patches;
|
||||
|
||||
[HarmonyPatch]
|
||||
public static class ModScriptCompilerPatch
|
||||
{
|
||||
private static ILogger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private static AssemblyLoadContext _context = new(null, true);
|
||||
|
||||
static ModScriptCompilerPatch()
|
||||
{
|
||||
MySession.OnUnloaded += OnUnloaded;
|
||||
}
|
||||
|
||||
private static void OnUnloaded()
|
||||
{
|
||||
if (!_context.Assemblies.Any())
|
||||
return;
|
||||
|
||||
Log.Info("Unloading mod scripts context");
|
||||
_context.Unload();
|
||||
|
||||
_context = new(null, true);
|
||||
}
|
||||
|
||||
private static MethodInfo TargetMethod()
|
||||
{
|
||||
return MethodTools.AsyncMethodBody(
|
||||
AccessTools.Method(typeof(MyScriptCompiler), nameof(MyScriptCompiler.Compile)));
|
||||
}
|
||||
|
||||
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var ins = instructions.ToList();
|
||||
|
||||
for (var i = 0; i < ins.Count; i++)
|
||||
{
|
||||
var instruction = ins[i];
|
||||
|
||||
if (instruction.Calls(AccessTools.Method(typeof(Assembly), nameof(Assembly.Load),
|
||||
new[] { typeof(byte[]) })))
|
||||
{
|
||||
ins[i - 1] = new(OpCodes.Nop); // memStream toArray call
|
||||
ins[i] = CodeInstruction.CallClosure((Stream assembly) => _context.LoadFromStream(assembly));
|
||||
}
|
||||
else if (instruction.Calls(AccessTools.Method(typeof(Assembly), nameof(Assembly.Load),
|
||||
new[] { typeof(byte[]), typeof(byte[]) })))
|
||||
{
|
||||
ins[i - 4] = new(OpCodes.Nop); // memStream toArray calls
|
||||
ins[i - 1] = new(OpCodes.Nop);
|
||||
ins[i] = CodeInstruction.CallClosure((Stream assembly, Stream assemblySymbols) =>
|
||||
_context.LoadFromStream(assembly, assemblySymbols));
|
||||
}
|
||||
}
|
||||
|
||||
return ins;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user