@@ -16,9 +16,11 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1616You should have received a copy of the GNU General Public License
1717along with this program. If not, see <http://www.gnu.org/licenses/>.
1818*/
19+ using ModFramework . Relinker ;
1920using Mono . Cecil ;
2021using Mono . Cecil . Cil ;
2122using MonoMod ;
23+ using MonoMod . Utils ;
2224using System ;
2325using System . Linq ;
2426
@@ -171,6 +173,68 @@ public static Instruction CreateStoreIndirectFunction(TypeReference type)
171173 } ;
172174 }
173175
176+ public static TypeDefinition CreateHookDelegate ( MonoModder modder )
177+ {
178+ var test = modder . Module . ImportReference ( typeof ( HookDelegate < , > ) ) ;
179+ var hookDelegate = modder . Module . Types . SingleOrDefault ( x => x . Name == "HookDelegate" ) ;
180+ if ( hookDelegate is not null )
181+ return hookDelegate ;
182+
183+ var multicast = modder . ResolveTypeReference < MulticastDelegate > ( ) ;
184+
185+ hookDelegate = new (
186+ "HookEvents" ,
187+ "HookDelegate" ,
188+ TypeAttributes . Class | TypeAttributes . Public | TypeAttributes . Sealed
189+ ) ;
190+ hookDelegate . BaseType = multicast ;
191+ hookDelegate . GenericParameters . Add ( new GenericParameter ( "TSender" , hookDelegate ) ) ;
192+ hookDelegate . GenericParameters . Add ( new GenericParameter ( "TArgs" , hookDelegate ) ) ;
193+
194+ modder . Module . Types . Add ( hookDelegate ) ;
195+
196+ // create ctor, Invoke, BeginInvoke, EndInvoke (no body)
197+
198+ var ctor = new MethodDefinition ( ".ctor" , MethodAttributes . Public | MethodAttributes . HideBySig | MethodAttributes . SpecialName | MethodAttributes . RTSpecialName , hookDelegate . Module . TypeSystem . Void )
199+ {
200+ IsRuntime = true
201+ } ;
202+ ctor . Parameters . Add ( new ParameterDefinition ( "object" , ParameterAttributes . None , hookDelegate . Module . TypeSystem . Object ) ) ;
203+ ctor . Parameters . Add ( new ParameterDefinition ( "method" , ParameterAttributes . None , hookDelegate . Module . TypeSystem . IntPtr ) ) ;
204+ hookDelegate . Methods . Add ( ctor ) ;
205+
206+ var invoke = new MethodDefinition ( "Invoke" , MethodAttributes . Public | MethodAttributes . HideBySig | MethodAttributes . NewSlot | MethodAttributes . Virtual , hookDelegate . Module . TypeSystem . Void )
207+ {
208+ IsRuntime = true
209+ } ;
210+ invoke . Parameters . Add ( new ParameterDefinition ( "sender" , ParameterAttributes . None , hookDelegate . GenericParameters [ 0 ] ) ) ;
211+ invoke . Parameters . Add ( new ParameterDefinition ( "args" , ParameterAttributes . None , hookDelegate . GenericParameters [ 1 ] ) ) ;
212+ hookDelegate . Methods . Add ( invoke ) ;
213+
214+ var iAsyncResult = modder . ResolveTypeReference < IAsyncResult > ( ) ;
215+ var iAsyncCallback = modder . ResolveTypeReference < AsyncCallback > ( ) ;
216+
217+ var beginInvoke = new MethodDefinition ( "BeginInvoke" , MethodAttributes . Public | MethodAttributes . HideBySig | MethodAttributes . NewSlot | MethodAttributes . Virtual , iAsyncResult )
218+ {
219+ IsRuntime = true
220+ } ;
221+ beginInvoke . Parameters . Add ( new ParameterDefinition ( "sender" , ParameterAttributes . None , hookDelegate . GenericParameters [ 0 ] ) ) ;
222+ beginInvoke . Parameters . Add ( new ParameterDefinition ( "args" , ParameterAttributes . None , hookDelegate . GenericParameters [ 1 ] ) ) ;
223+ beginInvoke . Parameters . Add ( new ParameterDefinition ( "callback" , ParameterAttributes . None , iAsyncCallback ) ) ;
224+ beginInvoke . Parameters . Add ( new ParameterDefinition ( "object" , ParameterAttributes . None , hookDelegate . Module . TypeSystem . Object ) ) ;
225+ hookDelegate . Methods . Add ( beginInvoke ) ;
226+
227+ var endInvoke = new MethodDefinition ( "EndInvoke" , MethodAttributes . Public | MethodAttributes . HideBySig | MethodAttributes . NewSlot | MethodAttributes . Virtual , hookDelegate . Module . TypeSystem . Void )
228+ {
229+ IsRuntime = true
230+ } ;
231+ endInvoke . Parameters . Add ( new ParameterDefinition ( "result" , ParameterAttributes . None , iAsyncResult ) ) ;
232+ hookDelegate . Methods . Add ( endInvoke ) ;
233+
234+
235+ return hookDelegate ;
236+ }
237+
174238 static MethodDefinition CreateInvokeMethod ( TypeDefinition hookType , FieldDefinition eventField , TypeDefinition hookEventArgsType , MonoModder modder , string ? name = null )
175239 {
176240 var methodName = name ?? $ "Invoke{ eventField . Name . TrimStart ( '_' ) } ";
@@ -206,15 +270,15 @@ static MethodDefinition CreateInvokeMethod(TypeDefinition hookType, FieldDefinit
206270 }
207271
208272 // Create a GenericInstanceType for EventHandler<HookEventArgsType>
209- var eventHandlerGenericType = EventEmitter . GetEventHandlerReference ( modder ) ;
210-
211- GenericInstanceType genericEventHandlerType = new ( eventHandlerGenericType )
273+ // var eventHandlerGenericType = EventEmitter.GetEventHandlerReference(modder);
274+ var eventHandlerType = modder . ResolveTypeReference ( typeof ( EventHandler < > ) ) ;
275+ GenericInstanceType genericEventHandlerType = new ( eventHandlerType )
212276 {
213277 GenericArguments = { hookEventArgsType }
214278 } ;
215279
216280 // Import the "Invoke" method of EventHandler<HookEventArgsType>
217- var eventHandlerInvokeMethod = eventHandlerGenericType . Resolve ( ) . Methods . First ( m => m . Name == "Invoke" ) ;
281+ var eventHandlerInvokeMethod = eventHandlerType . Resolve ( ) . Methods . First ( m => m . Name == "Invoke" ) ;
218282 MethodReference invokeMethodReference = new (
219283 eventHandlerInvokeMethod . Name ,
220284 hookType . Module . TypeSystem . Void ,
@@ -237,7 +301,7 @@ static MethodDefinition CreateInvokeMethod(TypeDefinition hookType, FieldDefinit
237301 invokeMethod . Body . Variables . Add ( vrb ) ;
238302 invokeMethod . Body . InitLocals = true ;
239303 il . Emit ( OpCodes . Newobj , hookEventArgsType . Methods . Single ( x => x . Name == ".ctor" ) ) ; // Create a new instance of the event args
240- // Set the fields of the event args instance
304+ // Set the fields of the event args instance
241305 foreach ( var prm in invokeMethod . Parameters . Skip ( 1 /*sender*/ ) )
242306 {
243307 il . Emit ( OpCodes . Dup ) ; // Load the event args instance
@@ -387,6 +451,8 @@ public static void CreateHook(this MethodDefinition definition, ModFwModder modd
387451 // call an event
388452 // check whether to continue or not, using a simple bool flag
389453
454+ CreateHookDelegate ( modder ) ;
455+
390456 var uniqueName = GetUniqueName ( definition ) ;
391457 var hookType = GetOrCreateHookType ( definition . DeclaringType ) ;
392458
0 commit comments