From c42705ffdffa77fc1df844c2d284fa162f734917 Mon Sep 17 00:00:00 2001
From: zznty <94796179+zznty@users.noreply.github.com>
Date: Mon, 30 Dec 2024 05:47:30 +0700
Subject: [PATCH] Revert "rework plugin type patch"
This reverts commit d4bf30a2
---
CringeLauncher/CringeLauncher.csproj | 2 +-
CringeLauncher/Patches/PluginTypePatch.cs | 93 ++++++++---------------
2 files changed, 34 insertions(+), 61 deletions(-)
diff --git a/CringeLauncher/CringeLauncher.csproj b/CringeLauncher/CringeLauncher.csproj
index 2e39316..886fcaf 100644
--- a/CringeLauncher/CringeLauncher.csproj
+++ b/CringeLauncher/CringeLauncher.csproj
@@ -18,7 +18,7 @@
-
+
diff --git a/CringeLauncher/Patches/PluginTypePatch.cs b/CringeLauncher/Patches/PluginTypePatch.cs
index f7aea71..dacf7a3 100644
--- a/CringeLauncher/Patches/PluginTypePatch.cs
+++ b/CringeLauncher/Patches/PluginTypePatch.cs
@@ -3,7 +3,7 @@ using HarmonyLib;
using Sandbox.Game.World;
using System.Reflection;
using System.Reflection.Emit;
-using VRage.Game;
+using System.Runtime.Loader;
using VRage.Game.ObjectBuilder;
using VRage.Plugins;
@@ -12,67 +12,40 @@ namespace CringeLauncher.Patches;
[HarmonyPatch]
internal static class PluginTypePatch
{
- [HarmonyPatch(typeof(MyGlobalTypeMetadata), nameof(MyGlobalTypeMetadata.Init))]
- [HarmonyTranspiler]
- private static IEnumerable MetadataTranspiler(IEnumerable instructions, ILGenerator generator)
+ [HarmonyTargetMethods]
+ public static IEnumerable TargetMethods()
{
- return new CodeMatcher(instructions, generator)
- .SearchForward(b => b.opcode == OpCodes.Ldloc_2)
- .Advance(-1)
- .CreateLabel(out var regularPluginLabel)
- .DeclareLocal(typeof(PluginWrapper), out var wrapper)
- .DefineLabel(out var continueLabel)
- .Insert(new(OpCodes.Ldloc_2),
- new(OpCodes.Isinst, typeof(PluginWrapper)), new(OpCodes.Stloc, wrapper),
- new(OpCodes.Ldloc_S, wrapper),
- new(OpCodes.Brfalse_S, regularPluginLabel),
- new(OpCodes.Ldloc_0),
- new(OpCodes.Ldloc_S, wrapper),
- new(OpCodes.Call,
- AccessTools.PropertyGetter(typeof(PluginWrapper), nameof(PluginWrapper.InstanceType))),
- new(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(Type), nameof(Type.Assembly))),
- CodeInstruction.Call(typeof(MyGlobalTypeMetadata), nameof(MyGlobalTypeMetadata.RegisterAssembly),
- [typeof(Assembly)]),
- new(OpCodes.Br_S, continueLabel))
- .SearchForward(b => b.opcode == OpCodes.Ldloca_S)
- .AddLabels([continueLabel])
+ yield return AccessTools.Method(typeof(MySession), "RegisterComponentsFromAssemblies");
+ yield return AccessTools.Method(typeof(MyGlobalTypeMetadata), nameof(MyGlobalTypeMetadata.Init));
+ }
+
+ [HarmonyTranspiler]
+ public static IEnumerable Transpiler(IEnumerable instructions, MethodBase original)
+ {
+ //replaces plugin.GetType() with GetPluginType(plugin)
+ var pve = AccessTools.Method(typeof(Assembly), nameof(Assembly.Load), [typeof(AssemblyName)]);
+ var method = AccessTools.Method(typeof(object), nameof(GetType));
+ var getter = AccessTools.PropertyGetter(typeof(MyPlugins), nameof(MyPlugins.Plugins));
+
+
+ var matcher = new CodeMatcher(instructions);
+
+ if (original.DeclaringType == typeof(MySession))
+ {
+ matcher = matcher
+ .SearchForward(b => b.Calls(pve))
+ .Set(OpCodes.Call, AccessTools.Method(typeof(PluginTypePatch), nameof(LoadAssembly)));
+ }
+
+ return matcher
+ .SearchForward(b => b.Calls(getter))
+ .SearchForward(b => b.Calls(method))
+ .Set(OpCodes.Call, AccessTools.Method(typeof(PluginTypePatch), nameof(GetPluginType)))
.InstructionEnumeration();
}
- [HarmonyPatch(typeof(MySession), "RegisterComponentsFromAssemblies")]
- [HarmonyPrefix]
- private static bool RegisterComponentsPrefix(MySession __instance)
- {
- __instance.m_componentsToLoad = [..__instance.GameDefinition.SessionComponents.Keys];
- __instance.m_componentsToLoad.ExceptWith(__instance.SessionComponentDisabled);
- __instance.m_componentsToLoad.UnionWith(__instance.SessionComponentEnabled);
-
- __instance.RegisterComponentsFromAssembly(MyPlugins.SandboxAssembly);
- __instance.RegisterComponentsFromAssembly(MyPlugins.SandboxGameAssembly);
- __instance.RegisterComponentsFromAssembly(MyPlugins.GameAssembly);
-
- foreach (var (context, ids) in __instance.ScriptManager.ScriptsPerMod)
- {
- foreach (var id in ids)
- {
- __instance.RegisterComponentsFromAssembly(__instance.ScriptManager.Scripts[id], true, context);
- }
- }
-
- foreach (var plugin in MyPlugins.Plugins)
- {
- var type = plugin is PluginWrapper wrapper ? wrapper.InstanceType : plugin.GetType();
-
- __instance.RegisterComponentsFromAssembly(type.Assembly, true);
- }
-
- foreach (var component in __instance.m_sessionComponents.Values)
- {
- if (component.ModContext is null or { IsBaseGame: true })
- __instance.m_sessionComponentForDrawAsync.Add(component);
- else
- __instance.m_sessionComponentForDraw.Add(component);
- }
- return false;
- }
+ //Assembly.Load is called in MySession.RegisterComponentsFromAssemblies. When patching, it uses the wrong context
+ //todo: maybe there's a better way to do this?
+ private static Assembly LoadAssembly(AssemblyName name) => AssemblyLoadContext.GetLoadContext(typeof(Launcher).Assembly)!.LoadFromAssemblyName(name);
+ private static Type GetPluginType(IPlugin plugin) => plugin is PluginWrapper wrapper ? wrapper.InstanceType : plugin.GetType();
}