3
3
using System . Collections . Generic ;
4
4
using System . Reflection ;
5
5
using Oxide . Pooling ;
6
+ using HarmonyLib ;
6
7
7
8
namespace Oxide . Core . Plugins
8
9
{
@@ -27,6 +28,17 @@ public HookMethodAttribute(string name)
27
28
}
28
29
}
29
30
31
+ /// <summary>
32
+ /// Indicates that the specified class should automatically apply it's harmony patches
33
+ /// </summary>
34
+ [ AttributeUsage ( AttributeTargets . Class ) ]
35
+ public class AutoPatchAttribute : Attribute
36
+ {
37
+ public AutoPatchAttribute ( )
38
+ {
39
+ }
40
+ }
41
+
30
42
/// <summary>
31
43
/// Represents a plugin implemented in .NET
32
44
/// </summary>
@@ -42,6 +54,22 @@ public abstract class CSPlugin : Plugin
42
54
// All hooked methods
43
55
protected Dictionary < string , List < HookMethod > > Hooks = new Dictionary < string , List < HookMethod > > ( ) ;
44
56
57
+ // Harmony
58
+ private Harmony _harmonyInstance ;
59
+ protected string HarmonyId => $ "com.oxidemod.{ Name } ";
60
+ protected Harmony HarmonyInstance
61
+ {
62
+ get
63
+ {
64
+ if ( _harmonyInstance == null )
65
+ {
66
+ _harmonyInstance = new Harmony ( HarmonyId ) ;
67
+ }
68
+
69
+ return _harmonyInstance ;
70
+ }
71
+ }
72
+
45
73
// All matched hooked methods
46
74
protected HookCache HooksCache = new HookCache ( ) ;
47
75
@@ -97,6 +125,29 @@ public override void HandleAddedToManager(PluginManager manager)
97
125
Subscribe ( hookname ) ;
98
126
}
99
127
128
+ // Find all classes with the AutoPatch attribute and apply the patches
129
+ foreach ( Type nestedType in GetType ( ) . GetNestedTypes ( BindingFlags . DeclaredOnly | BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Static ) )
130
+ {
131
+ object [ ] attr = nestedType . GetCustomAttributes ( typeof ( AutoPatchAttribute ) , false ) ;
132
+ if ( attr . Length < 1 )
133
+ {
134
+ continue ;
135
+ }
136
+
137
+ List < MethodInfo > harmonyMethods = HarmonyInstance . CreateClassProcessor ( nestedType ) ? . Patch ( ) ;
138
+
139
+ if ( harmonyMethods == null || harmonyMethods . Count == 0 )
140
+ {
141
+ Interface . Oxide . LogWarning ( $ "[{ Title } ] AutoPatch attribute found on '{ nestedType . Name } ' but no HarmonyPatch methods found. Skipping.") ;
142
+ continue ;
143
+ }
144
+
145
+ foreach ( MethodInfo method in harmonyMethods )
146
+ {
147
+ Interface . Oxide . LogInfo ( $ "[{ Title } ] Automatically Harmony patched '{ method . Name } ' method. ({ nestedType . Name } )") ;
148
+ }
149
+ }
150
+
100
151
try
101
152
{
102
153
// Let the plugin know that it is loading
@@ -112,6 +163,19 @@ public override void HandleAddedToManager(PluginManager manager)
112
163
}
113
164
}
114
165
166
+ /// <summary>
167
+ /// Called when this plugin has been removed from a manager
168
+ /// </summary>
169
+ /// <param name="manager"></param>
170
+ public override void HandleRemovedFromManager ( PluginManager manager )
171
+ {
172
+ // Unpatch all automatically patched Harmony patches
173
+ _harmonyInstance ? . UnpatchAll ( HarmonyId ) ;
174
+
175
+ // Let base work
176
+ base . HandleRemovedFromManager ( manager ) ;
177
+ }
178
+
115
179
protected void AddHookMethod ( string name , MethodInfo method )
116
180
{
117
181
if ( ! Hooks . TryGetValue ( name , out List < HookMethod > hookMethods ) )
0 commit comments