From ad95e34fa426b7732c609857dbd2c8701cce5db7 Mon Sep 17 00:00:00 2001 From: js6pak Date: Sun, 13 Jun 2021 16:15:46 +0200 Subject: [PATCH] ChainloaderHooks --- AmongUs.props | 2 +- Reactor.Debugger/DebuggerPlugin.cs | 2 -- Reactor.Example/ExamplePlugin.cs | 3 --- Reactor/ChainloaderHooks.cs | 34 +++++++++++++++++++++++++++ Reactor/PluginSingleton.cs | 21 +++++++---------- Reactor/ReactorPlugin.cs | 19 ++++++++++++--- Reactor/RegisterCustomRpcAttribute.cs | 7 +++++- Reactor/RegisterInIl2CppAttribute.cs | 13 ++++++---- 8 files changed, 74 insertions(+), 27 deletions(-) create mode 100644 Reactor/ChainloaderHooks.cs diff --git a/AmongUs.props b/AmongUs.props index 2cf081b..55b3d8e 100644 --- a/AmongUs.props +++ b/AmongUs.props @@ -14,7 +14,7 @@ - + diff --git a/Reactor.Debugger/DebuggerPlugin.cs b/Reactor.Debugger/DebuggerPlugin.cs index b88bafd..d0e6fa6 100644 --- a/Reactor.Debugger/DebuggerPlugin.cs +++ b/Reactor.Debugger/DebuggerPlugin.cs @@ -24,8 +24,6 @@ namespace Reactor.Debugger public override void Load() { - RegisterInIl2CppAttribute.Register(); - var gameObject = new GameObject(nameof(DebuggerPlugin)).DontDestroy(); Component = gameObject.AddComponent(); diff --git a/Reactor.Example/ExamplePlugin.cs b/Reactor.Example/ExamplePlugin.cs index 72ef050..2ffa382 100644 --- a/Reactor.Example/ExamplePlugin.cs +++ b/Reactor.Example/ExamplePlugin.cs @@ -17,9 +17,6 @@ namespace Reactor.Example public override void Load() { - RegisterInIl2CppAttribute.Register(); - RegisterCustomRpcAttribute.Register(this); - var gameObject = new GameObject(nameof(ReactorPlugin)).DontDestroy(); gameObject.AddComponent().Plugin = this; } diff --git a/Reactor/ChainloaderHooks.cs b/Reactor/ChainloaderHooks.cs new file mode 100644 index 0000000..2eb6b5c --- /dev/null +++ b/Reactor/ChainloaderHooks.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using System.Reflection.Emit; +using BepInEx.IL2CPP; +using HarmonyLib; + +namespace Reactor +{ + public static class ChainloaderHooks + { + public delegate void PluginLoadHandler(BasePlugin plugin); + + public static event PluginLoadHandler PluginLoad; + + internal static void OnPluginLoad(BasePlugin plugin) + { + PluginLoad?.Invoke(plugin); + } + + [HarmonyPatch(typeof(IL2CPPChainloader), nameof(IL2CPPChainloader.LoadPlugin))] + private static class LoadPluginPatch + { + public static IEnumerable Transpiler(IEnumerable instructions) + { + return new CodeMatcher(instructions) + .MatchForward(false, new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(BasePlugin), nameof(BasePlugin.Load)))) + .Insert( + new CodeInstruction(OpCodes.Dup), + new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(ChainloaderHooks), nameof(OnPluginLoad))) + ) + .InstructionEnumeration(); + } + } + } +} diff --git a/Reactor/PluginSingleton.cs b/Reactor/PluginSingleton.cs index 5a93640..a051367 100644 --- a/Reactor/PluginSingleton.cs +++ b/Reactor/PluginSingleton.cs @@ -1,5 +1,5 @@ -using System; using System.Linq; +using System.Reflection; using BepInEx.IL2CPP; namespace Reactor @@ -8,19 +8,16 @@ namespace Reactor { private static T _instance; - public static T Instance + public static T Instance => _instance ??= IL2CPPChainloader.Instance.Plugins.Values.Select(x => x.Instance).OfType().Single(); + + internal static void Initialize() { - get => _instance ??= IL2CPPChainloader.Instance.Plugins.Values.Select(x => x.Instance).OfType().Single(); - - set + ChainloaderHooks.PluginLoad += plugin => { - if (_instance != null) - { - throw new Exception($"Instance for {typeof(T).FullName} is already set"); - } - - _instance = value; - } + typeof(PluginSingleton<>).MakeGenericType(plugin.GetType())! + .GetField(nameof(_instance), BindingFlags.Static | BindingFlags.NonPublic)! + .SetValue(null, plugin); + }; } } } diff --git a/Reactor/ReactorPlugin.cs b/Reactor/ReactorPlugin.cs index a17f6b9..75fe6e3 100644 --- a/Reactor/ReactorPlugin.cs +++ b/Reactor/ReactorPlugin.cs @@ -27,17 +27,25 @@ namespace Reactor private GameObject _gameObject; private RegionInfoWatcher RegionInfoWatcher { get; } = new RegionInfoWatcher(); + public ReactorPlugin() + { + PluginSingleton.Initialize(); + RegisterInIl2CppAttribute.Initialize(); + RegisterCustomRpcAttribute.Initialize(); + + ChainloaderHooks.OnPluginLoad(this); + } + public override void Load() { - RegisterInIl2CppAttribute.Register(); - AllowVanillaServers = Config.Bind("Features", "Allow vanilla servers", false, "Whether reactor should ignore servers not responding to modded handshake. This config is ignored if any plugin uses custom rpcs!"); + Harmony.PatchAll(); + _gameObject = new GameObject(nameof(ReactorPlugin)).DontDestroy(); _gameObject.AddComponent().Plugin = this; _gameObject.AddComponent(); - Harmony.PatchAll(); ReactorVersionShower.Initialize(); SplashSkip.Initialize(); DefaultBundle.Load(); @@ -62,6 +70,11 @@ namespace Reactor { } + private void OnRenderImage(RenderTexture src, RenderTexture dest) + { + Plugin.Log.LogWarning(src.GetInstanceID()); + } + private void Update() { if (Plugin.RegionInfoWatcher.Reload) diff --git a/Reactor/RegisterCustomRpcAttribute.cs b/Reactor/RegisterCustomRpcAttribute.cs index 09f144a..c32f00a 100644 --- a/Reactor/RegisterCustomRpcAttribute.cs +++ b/Reactor/RegisterCustomRpcAttribute.cs @@ -19,9 +19,9 @@ namespace Reactor Id = id; } + [Obsolete("You don't need to call this anymore", true)] public static void Register(BasePlugin plugin) { - Register(Assembly.GetCallingAssembly(), plugin); } public static void Register(Assembly assembly, BasePlugin plugin) @@ -42,5 +42,10 @@ namespace Reactor } } } + + internal static void Initialize() + { + ChainloaderHooks.PluginLoad += plugin => Register(plugin.GetType().Assembly, plugin); + } } } diff --git a/Reactor/RegisterInIl2CppAttribute.cs b/Reactor/RegisterInIl2CppAttribute.cs index 43842ed..1a7b5b5 100644 --- a/Reactor/RegisterInIl2CppAttribute.cs +++ b/Reactor/RegisterInIl2CppAttribute.cs @@ -7,14 +7,14 @@ using UnhollowerRuntimeLib; namespace Reactor { /// - /// Utility attribute for automatically calling + /// Utility attribute for automatically calling /// [AttributeUsage(AttributeTargets.Class)] public class RegisterInIl2CppAttribute : Attribute { + [Obsolete("You don't need to call this anymore", true)] public static void Register() { - Register(Assembly.GetCallingAssembly()); } private static readonly AccessTools.FieldRef> _injectedTypes @@ -58,9 +58,7 @@ namespace Reactor try { - typeof(ClassInjector).GetMethod(nameof(ClassInjector.RegisterTypeInIl2Cpp))! - .MakeGenericMethod(type) - .Invoke(null, new object[0]); + ClassInjector.RegisterTypeInIl2Cpp(type); } catch (Exception e) { @@ -78,5 +76,10 @@ namespace Reactor } } } + + internal static void Initialize() + { + ChainloaderHooks.PluginLoad += plugin => Register(plugin.GetType().Assembly); + } } }