Skip to content

Commit

Permalink
Replace and remove DynDelegate (#432)
Browse files Browse the repository at this point in the history
* Replace and remove DynDelegate

`DynDelegate` was required to handle 2 possible signatures for the sync worker delegate:
- Explicit sync worker delegates would have no return type
- Implicit sync worker delegates would return `bool`
- Those rules only apply to sync workers registered by using `SyncWorkerAttribute`, not `MP.RegisterSyncWorker` calls - which would treat all as having no return type (and handled in a different location than the one being changed here)

`DynDelegate` was used here as when it changed it took a method with no return type - it would return true (`il.Emit(OpCodes.Ldc_I4_1)`).

My solution here is to have 2 delegates - one of which has no return type. I then create the appropriate delegate with a call to `Delegate.CreateDelegate`. For delegates that already return a boolean - I pass it further. However, delegates with no return value are first wrapped with a delegate that will then return true (matching `DynDelegate` behaviour.

From my initial testing everything seems to work fine as-is. However, I believe some extra testing should be done before applying those changes - specifically with existing mods using `SyncWorkerAttribute`.
  • Loading branch information
SokyranTheDragon authored May 24, 2024
1 parent 2f7ab7e commit 7a82bb2
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 294 deletions.
16 changes: 14 additions & 2 deletions Source/Common/Syncing/Worker/SyncWorkerEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace Multiplayer.Client;
public class SyncWorkerEntry
{
delegate bool SyncWorkerDelegate(SyncWorker sync, ref object? obj);
delegate void SyncWorkerDelegateNoReturn(SyncWorker sync, ref object? obj);

public Type type;
public bool shouldConstruct;
Expand Down Expand Up @@ -38,8 +39,19 @@ public SyncWorkerEntry(SyncWorkerEntry other)

public void Add(MethodInfo method)
{
// todo: Find a way to do this without DynDelegate
Add(DynDelegate.DynamicDelegate.Create<SyncWorkerDelegate>(method), method.ReturnType == typeof(void));
if (method.ReturnType == typeof(void))
{
var func = (SyncWorkerDelegateNoReturn)Delegate.CreateDelegate(typeof(SyncWorkerDelegateNoReturn), method);
Add((SyncWorker sync, ref object obj) =>
{
func(sync, ref obj);
return true;
}, true);
}
else
{
Add((SyncWorkerDelegate)Delegate.CreateDelegate(typeof(SyncWorkerDelegate), method), false);
}
}

public void Add<T>(SyncWorkerDelegate<T> func)
Expand Down
292 changes: 0 additions & 292 deletions Source/Common/Util/DynDelegate.cs

This file was deleted.

0 comments on commit 7a82bb2

Please sign in to comment.