From 3cf0f1c3e14b675a17f1a3ed11c9518a2cd74fb2 Mon Sep 17 00:00:00 2001 From: "George L. Albany" Date: Thu, 4 Nov 2021 23:40:49 -0400 Subject: [PATCH] Fix not patching plugin loading Corrected to run right before Load is called Now patches HacknetChainloader with ILManipulator instead Actually compile the Pathfinder.Meta.Load namespace Made EventAttribute able to function on Types as well If an EventAttribute is on a type, checks type for any applicable event methods Valid methods are static void methods whose only parameter is of type PathfinderEvent Can ignore specific events for a auto-register with IgnoreEventAttribute Renamed Meta.Load.ComputerExecutor to ComputerExecutorAttribute --- PathfinderAPI/Meta/Load/AttributeManager.cs | 18 ++++++++--- ...ecutor.cs => ComputerExecutorAttribute.cs} | 6 ++-- PathfinderAPI/Meta/Load/EventAttribute.cs | 32 ++++++++++++++++--- .../Meta/Load/IgnoreEventAttribute.cs | 8 +++++ PathfinderAPI/PathfinderAPI.csproj | 20 ++++++++++++ 5 files changed, 73 insertions(+), 11 deletions(-) rename PathfinderAPI/Meta/Load/{ComputerExecutor.cs => ComputerExecutorAttribute.cs} (77%) create mode 100644 PathfinderAPI/Meta/Load/IgnoreEventAttribute.cs diff --git a/PathfinderAPI/Meta/Load/AttributeManager.cs b/PathfinderAPI/Meta/Load/AttributeManager.cs index 7035dcbb..97f98f95 100644 --- a/PathfinderAPI/Meta/Load/AttributeManager.cs +++ b/PathfinderAPI/Meta/Load/AttributeManager.cs @@ -2,17 +2,27 @@ using System.Reflection; using BepInEx.Hacknet; using HarmonyLib; +using Mono.Cecil.Cil; +using MonoMod.Cil; namespace Pathfinder.Meta.Load { [HarmonyPatch] internal static class AttributeManager { - [HarmonyPrefix] - [HarmonyPatch(typeof(HacknetPlugin), nameof(HacknetPlugin.Load))] - private static void OnPluginLoad(ref HacknetPlugin __instance) + [HarmonyILManipulator] + [HarmonyPatch(typeof(HacknetChainloader), nameof(HacknetChainloader.LoadPlugin))] + private static void OnPluginLoadIL(ILContext il) { - ReadAttributesFor(__instance); + var c = new ILCursor(il); + + c.GotoNext( + x => x.MatchLdloc(1), + x => x.MatchCallvirt(AccessTools.Method(typeof(HacknetPlugin), nameof(HacknetPlugin.Load))) + ); + + c.Emit(OpCodes.Ldloc, 1); + c.Emit(OpCodes.Call, AccessTools.Method(typeof(AttributeManager), nameof(ReadAttributesFor))); } public static void ReadAttributesFor(HacknetPlugin plugin) diff --git a/PathfinderAPI/Meta/Load/ComputerExecutor.cs b/PathfinderAPI/Meta/Load/ComputerExecutorAttribute.cs similarity index 77% rename from PathfinderAPI/Meta/Load/ComputerExecutor.cs rename to PathfinderAPI/Meta/Load/ComputerExecutorAttribute.cs index 98937a73..3b7b5b0f 100644 --- a/PathfinderAPI/Meta/Load/ComputerExecutor.cs +++ b/PathfinderAPI/Meta/Load/ComputerExecutorAttribute.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Reflection; using BepInEx.Hacknet; using Pathfinder.Replacements; @@ -7,12 +7,12 @@ namespace Pathfinder.Meta.Load { [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] - public class ComputerExecutor : BaseAttribute + public class ComputerExecutorAttribute : BaseAttribute { public string Element { get; } public ParseOption ParseOptions { get; set; } - public ComputerExecutor(string element, ParseOption parseOptions = ParseOption.None) + public ComputerExecutorAttribute(string element, ParseOption parseOptions = ParseOption.None) { Element = element; ParseOptions = parseOptions; diff --git a/PathfinderAPI/Meta/Load/EventAttribute.cs b/PathfinderAPI/Meta/Load/EventAttribute.cs index bcd0dd30..f70bf1ee 100644 --- a/PathfinderAPI/Meta/Load/EventAttribute.cs +++ b/PathfinderAPI/Meta/Load/EventAttribute.cs @@ -6,7 +6,7 @@ namespace Pathfinder.Meta.Load { - [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)] public class EventAttribute : BaseAttribute { private EventHandlerOptions eventHandlerOptions; @@ -44,11 +44,35 @@ public EventAttribute(bool continueOnCancel = false, bool continueOnThrow = fals }; } + private void CallOn(HacknetPlugin plugin, MethodInfo info) + { + var eventType = info.GetParameters().FirstOrDefault()?.ParameterType; + EventManager.AddHandler(eventType, info); + } + + private void CallOn(HacknetPlugin plugin, Type type) + { + foreach(var method in type.GetMethods( + BindingFlags.Public + | BindingFlags.NonPublic + | BindingFlags.Static + )) + { + if(method.GetCustomAttribute() != null) + continue; + var parameter = method.GetParameters().FirstOrDefault(); + if(method.ReturnType == typeof(void) + && (parameter?.ParameterType?.IsSubclassOf(typeof(PathfinderEvent)) ?? false)) + CallOn(plugin, method); + } + } + protected internal override void CallOn(HacknetPlugin plugin, MemberInfo targettedInfo) { - var methodInfo = (MethodInfo)targettedInfo; - var eventType = methodInfo.GetParameters().FirstOrDefault()?.ParameterType; - EventManager.AddHandler(eventType, methodInfo); + if(targettedInfo is MethodInfo method) + CallOn(plugin, method); + else + CallOn(plugin, (Type) targettedInfo); } } } \ No newline at end of file diff --git a/PathfinderAPI/Meta/Load/IgnoreEventAttribute.cs b/PathfinderAPI/Meta/Load/IgnoreEventAttribute.cs new file mode 100644 index 00000000..903f702b --- /dev/null +++ b/PathfinderAPI/Meta/Load/IgnoreEventAttribute.cs @@ -0,0 +1,8 @@ +using System; +namespace Pathfinder.Meta.Load +{ + [AttributeUsage(AttributeTargets.Method)] + public class IgnoreEventAttribute : System.Attribute + { + } +} \ No newline at end of file diff --git a/PathfinderAPI/PathfinderAPI.csproj b/PathfinderAPI/PathfinderAPI.csproj index da9acd73..6e9ac818 100644 --- a/PathfinderAPI/PathfinderAPI.csproj +++ b/PathfinderAPI/PathfinderAPI.csproj @@ -110,6 +110,26 @@ + + + + + + + + + + + + + + + + + + + +