Refactor event patching and transport systems

- Convert TransportBase from abstract class to interface; replace BORADCAST_ID constant with BROADCAST_ID property in transport implementations.
- Update SteamTransport to implement the new interface and provide its own BROADCAST_ID.
- Refactor event patching: introduce UnityEventPatching to map proxy events to originals, and update UnityEventPatch<T> to use proxy events for patching.
- Ensure patched UnityEvents replace originals in SyncablePhysics, so all invocations go through patch logic.
- Improve robustness and maintainability of both networking and event patching systems.
This commit is contained in:
2026-01-13 17:34:02 +02:00
parent 54ec8da1fe
commit 335df69fcd
6 changed files with 56 additions and 61 deletions

View File

@@ -165,7 +165,7 @@ namespace BoneSync.Networking
}
public void Broadcast()
{
Send(TransportBase.BORADCAST_ID);
Send(BoneSync.transport.BROADCAST_ID);
}
public void SendToHost()

View File

@@ -22,6 +22,9 @@ namespace BoneSync.Networking.Transport
SteamNetworkingUtils.InitRelayNetworkAccess();
}
private List<SteamId> OpenP2PConnections = new List<SteamId>();
public ulong BROADCAST_ID => 0;
private void OnP2PSessionRequest(SteamId steamId)
{
SyncLogger.Msg("P2P Request from " + steamId);
@@ -37,7 +40,7 @@ namespace BoneSync.Networking.Transport
}
public override void CleanUp()
public void CleanUp()
{
ulong[] peers = BoneSync.lobby.GetPeers();
for (int i = 0; i < OpenP2PConnections.Count; i++)
@@ -54,14 +57,14 @@ namespace BoneSync.Networking.Transport
private void ProcessPacket(P2Packet steamPacket)
{
Packet packet = Packet.FromBytes(steamPacket.Data);
bool isTarget = packet.Info.receiverId == BORADCAST_ID || packet.Info.receiverId == BoneSync.lobby.GetLocalId();
bool isTarget = packet.Info.receiverId == BROADCAST_ID || packet.Info.receiverId == BoneSync.lobby.GetLocalId();
if (isTarget)
{
Packet.OnPacketReceived(packet);
}
}
public override int Tick()
public int Tick()
{
if (!SteamClient.IsValid) return 0;
int processed = 0;
@@ -110,7 +113,7 @@ namespace BoneSync.Networking.Transport
}
public override void Send(Packet packet)
public void Send(Packet packet)
{
LobbyManager.LobbyManager _instance = BoneSync.lobby;
@@ -119,7 +122,7 @@ namespace BoneSync.Networking.Transport
SyncLogger.Msg("Lobby instance is null");
return;
}
if (packet.Info.receiverId == BORADCAST_ID)
if (packet.Info.receiverId == BROADCAST_ID)
{
foreach (SteamId peer in _instance.GetPeers())
{

View File

@@ -6,11 +6,11 @@ using System.Threading.Tasks;
namespace BoneSync.Networking.Transport
{
public abstract class TransportBase
public interface TransportBase
{
public const int BORADCAST_ID = 0;
public abstract void Send(Packet packet);
public abstract int Tick();
public abstract void CleanUp();
ulong BROADCAST_ID { get; }
void Send(Packet packet);
int Tick();
void CleanUp();
}
}

View File

@@ -77,10 +77,8 @@ namespace BoneSync.Patching
public static void BypassPatchInvoke(this UnityEvent e)
{
SyncLogger.Msg("BypassPatchInvoke "+ e.GetHashCode());
allowPatchedMethodCall = true;
e.Invoke();
allowPatchedMethodCall = false;
SyncLogger.Msg("Bypassing patched UnityEvent invoke for event " + e.GetHashCode());
UnityEventPatching.GetOriginalEvent(e).Invoke(); // invoke the original event directly
}
public static Poolee InstantiatePoolee(Pool pool, Vector3 position, Quaternion rotation, Vector3 scale)

View File

@@ -11,6 +11,19 @@ using UnityEngine.Events;
namespace BoneSync.Patching
{
public class UnityEventPatching
{
internal static Dictionary<int, UnityEvent> _patchToOriginalMap = new Dictionary<int, UnityEvent>();
public static UnityEvent GetOriginalEvent(UnityEvent unityEvent)
{
int eventHash = unityEvent.GetHashCode();
if (_patchToOriginalMap.TryGetValue(eventHash, out UnityEvent originalEvent))
{
return originalEvent;
}
return unityEvent;
}
}
public class UnityEventPatch<T>
{
private static Dictionary<int, UnityEventPatch<T>> patches = new Dictionary<int, UnityEventPatch<T>>();
@@ -18,7 +31,7 @@ namespace BoneSync.Patching
private T arg;
private UnityEvent unityEvent;
private Func<T, bool> handler;
//private UnityAction listener;
private UnityEvent proxyUnityEvent;
//private float lastInvokeTime = 0f;
//private float invokeCooldown = 0.05f;
private UnityEventPatch(T arg, UnityEvent unityEvent, Func<T, bool> handler)
@@ -26,63 +39,44 @@ namespace BoneSync.Patching
this.arg = arg;
this.unityEvent = unityEvent;
this.handler = handler;
//listener = (UnityAction)Listener;
this.proxyUnityEvent = new UnityEvent();
this.proxyUnityEvent.AddListener((UnityAction)OnEventInvoked);
int patchEventHash = proxyUnityEvent.GetHashCode();
patches[patchEventHash] = this; // avoid creating multiple patches for same event
UnityEventPatching._patchToOriginalMap[patchEventHash] = unityEvent;
}
public bool TryInvoke()
public UnityEvent GetOriginalEvent()
{
bool allowInvokeResult = handler(arg);
SyncLogger.Debug("TryInvoke " + allowInvokeResult);
return allowInvokeResult;
return unityEvent;
}
private void PatchUnityEvent()
private void OnEventInvoked()
{
if (unityEvent == null) return;
patches[unityEvent.GetHashCode()] = this;
//unityEvent.AddListener(listener);
bool allowInvoke = handler.Invoke(arg);
SyncLogger.Msg("UnityEventPatch invoked for event " + unityEvent.GetHashCode() + ", allowInvoke: " + allowInvoke);
if (allowInvoke)
{
unityEvent.Invoke(); // only invoke the original event if allowed
}
}
private void UnpatchUnityEvent()
public UnityEvent GetPatchedEvent()
{
if (unityEvent == null) return;
patches.Remove(unityEvent.GetHashCode());
return proxyUnityEvent;
}
public static UnityEventPatch<T> Patch(T arg, UnityEvent unityEvent, Func<T, bool> handler)
{
if (patches.TryGetValue(unityEvent.GetHashCode(), out UnityEventPatch<T> oldPatch))
int eventHash = unityEvent.GetHashCode();
UnityEventPatch<T> existingPatch = patches.TryGetValue(eventHash, out UnityEventPatch<T> foundPatch) ? foundPatch : null;
if (existingPatch != null)
{
oldPatch.UnpatchUnityEvent();
return existingPatch;
}
UnityEventPatch<T> patch = new UnityEventPatch<T>(arg, unityEvent, handler);
patch.PatchUnityEvent();
patches[eventHash] = patch;
return patch;
}
public static UnityEventPatch<T> TryGetPatch(UnityEvent unityEvent)
{
if (!patches.ContainsKey(unityEvent.GetHashCode())) return null;
return patches[unityEvent.GetHashCode()];
}
}
/*[HarmonyPatch(typeof(UnityEvent))]
internal class UnityEventPatches
{
[HarmonyPatch(nameof(UnityEvent.Invoke)), HarmonyPrefix]
private static bool InvokePrefix(UnityEvent __instance)
{
if (CallPatchedMethods.allowPatchedMethodCall) return true;
UnityEventPatch<ButtonToggle> patch = UnityEventPatch<ButtonToggle>.TryGetPatch(__instance);
if (patch != null)
{
return patch.TryInvoke();
}
return true;
}
}*/
}

View File

@@ -70,8 +70,8 @@ namespace BoneSync.Sync.Components
//pullDevice.OnHandlePull.AddListener((UnityAction)DeviceOnPull);
//pullDevice.OnHandleReturn.AddListener((UnityAction)DeviceOnRelease);
UnityEventPatch<PullDevice>.Patch(pullDevice, pullDevice.OnHandlePull, DeviceOnPull);
UnityEventPatch<PullDevice>.Patch(pullDevice, pullDevice.OnHandleReturn, DeviceOnRelease);
pullDevice.OnHandlePull =UnityEventPatch<PullDevice>.Patch(pullDevice, pullDevice.OnHandlePull, DeviceOnPull).GetPatchedEvent();
pullDevice.OnHandleReturn = UnityEventPatch<PullDevice>.Patch(pullDevice, pullDevice.OnHandleReturn, DeviceOnRelease).GetPatchedEvent();
pullDevicePatched = true;
}
@@ -82,9 +82,9 @@ namespace BoneSync.Sync.Components
SyncLogger.Msg("Patching ButtonToggle: " + buttonToggle.transform.GetPath());
//buttonToggle.onPress.AddListenerWithArgs<ButtonToggle>((btn, args) => ButtonOnPress(btn), buttonToggle);
//buttonToggle.onDepress.AddListenerWithArgs<ButtonToggle>((btn, args) => ButtonOnRelease(btn), buttonToggle);
UnityEventPatch<ButtonToggle>.Patch(buttonToggle, buttonToggle.onPress, ButtonOnPress);
UnityEventPatch<ButtonToggle>.Patch(buttonToggle, buttonToggle.onDepress, ButtonOnRelease);
UnityEventPatch<ButtonToggle>.Patch(buttonToggle, buttonToggle.onPressOneShot, ButtonOnOneShot);
buttonToggle.onPress = UnityEventPatch<ButtonToggle>.Patch(buttonToggle, buttonToggle.onPress, ButtonOnPress).GetPatchedEvent();
buttonToggle.onDepress = UnityEventPatch<ButtonToggle>.Patch(buttonToggle, buttonToggle.onDepress, ButtonOnRelease).GetPatchedEvent();
buttonToggle.onPressOneShot = UnityEventPatch<ButtonToggle>.Patch(buttonToggle, buttonToggle.onPressOneShot, ButtonOnOneShot).GetPatchedEvent();
patchedButtonToggles.Add(buttonToggle.GetHashCode());
}