From 335df69fcdfe0df9fa0636ceecb06db90b41377e Mon Sep 17 00:00:00 2001 From: Aaro Varis Date: Tue, 13 Jan 2026 17:34:02 +0200 Subject: [PATCH] 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 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. --- BoneSync/Networking/NetworkMessage.cs | 2 +- .../Networking/Transport/SteamTransport.cs | 13 ++-- .../Networking/Transport/TransportBase.cs | 10 +-- BoneSync/Patching/CallPatchedMethod.cs | 6 +- BoneSync/Patching/UnityEventPatching.cs | 76 +++++++++---------- BoneSync/Sync/Components/SyncablePhysics.cs | 10 +-- 6 files changed, 56 insertions(+), 61 deletions(-) diff --git a/BoneSync/Networking/NetworkMessage.cs b/BoneSync/Networking/NetworkMessage.cs index 0864e80..2e0473e 100644 --- a/BoneSync/Networking/NetworkMessage.cs +++ b/BoneSync/Networking/NetworkMessage.cs @@ -165,7 +165,7 @@ namespace BoneSync.Networking } public void Broadcast() { - Send(TransportBase.BORADCAST_ID); + Send(BoneSync.transport.BROADCAST_ID); } public void SendToHost() diff --git a/BoneSync/Networking/Transport/SteamTransport.cs b/BoneSync/Networking/Transport/SteamTransport.cs index acad202..b3e76a2 100644 --- a/BoneSync/Networking/Transport/SteamTransport.cs +++ b/BoneSync/Networking/Transport/SteamTransport.cs @@ -22,6 +22,9 @@ namespace BoneSync.Networking.Transport SteamNetworkingUtils.InitRelayNetworkAccess(); } private List OpenP2PConnections = new List(); + + 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()) { diff --git a/BoneSync/Networking/Transport/TransportBase.cs b/BoneSync/Networking/Transport/TransportBase.cs index 02f6217..4238098 100644 --- a/BoneSync/Networking/Transport/TransportBase.cs +++ b/BoneSync/Networking/Transport/TransportBase.cs @@ -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(); } } diff --git a/BoneSync/Patching/CallPatchedMethod.cs b/BoneSync/Patching/CallPatchedMethod.cs index baaeeaf..eeddd3f 100644 --- a/BoneSync/Patching/CallPatchedMethod.cs +++ b/BoneSync/Patching/CallPatchedMethod.cs @@ -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) diff --git a/BoneSync/Patching/UnityEventPatching.cs b/BoneSync/Patching/UnityEventPatching.cs index 40bf9d1..ec93a00 100644 --- a/BoneSync/Patching/UnityEventPatching.cs +++ b/BoneSync/Patching/UnityEventPatching.cs @@ -11,6 +11,19 @@ using UnityEngine.Events; namespace BoneSync.Patching { + public class UnityEventPatching + { + internal static Dictionary _patchToOriginalMap = new Dictionary(); + public static UnityEvent GetOriginalEvent(UnityEvent unityEvent) + { + int eventHash = unityEvent.GetHashCode(); + if (_patchToOriginalMap.TryGetValue(eventHash, out UnityEvent originalEvent)) + { + return originalEvent; + } + return unityEvent; + } + } public class UnityEventPatch { private static Dictionary> patches = new Dictionary>(); @@ -18,7 +31,7 @@ namespace BoneSync.Patching private T arg; private UnityEvent unityEvent; private Func handler; - //private UnityAction listener; + private UnityEvent proxyUnityEvent; //private float lastInvokeTime = 0f; //private float invokeCooldown = 0.05f; private UnityEventPatch(T arg, UnityEvent unityEvent, Func 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 Patch(T arg, UnityEvent unityEvent, Func handler) { - if (patches.TryGetValue(unityEvent.GetHashCode(), out UnityEventPatch oldPatch)) + int eventHash = unityEvent.GetHashCode(); + UnityEventPatch existingPatch = patches.TryGetValue(eventHash, out UnityEventPatch foundPatch) ? foundPatch : null; + if (existingPatch != null) { - oldPatch.UnpatchUnityEvent(); + return existingPatch; } UnityEventPatch patch = new UnityEventPatch(arg, unityEvent, handler); - patch.PatchUnityEvent(); - + patches[eventHash] = patch; return patch; } - - public static UnityEventPatch 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 patch = UnityEventPatch.TryGetPatch(__instance); - if (patch != null) - { - return patch.TryInvoke(); - } - return true; - } - }*/ } diff --git a/BoneSync/Sync/Components/SyncablePhysics.cs b/BoneSync/Sync/Components/SyncablePhysics.cs index e7169a7..f4f5e6b 100644 --- a/BoneSync/Sync/Components/SyncablePhysics.cs +++ b/BoneSync/Sync/Components/SyncablePhysics.cs @@ -70,8 +70,8 @@ namespace BoneSync.Sync.Components //pullDevice.OnHandlePull.AddListener((UnityAction)DeviceOnPull); //pullDevice.OnHandleReturn.AddListener((UnityAction)DeviceOnRelease); - UnityEventPatch.Patch(pullDevice, pullDevice.OnHandlePull, DeviceOnPull); - UnityEventPatch.Patch(pullDevice, pullDevice.OnHandleReturn, DeviceOnRelease); + pullDevice.OnHandlePull =UnityEventPatch.Patch(pullDevice, pullDevice.OnHandlePull, DeviceOnPull).GetPatchedEvent(); + pullDevice.OnHandleReturn = UnityEventPatch.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((btn, args) => ButtonOnPress(btn), buttonToggle); //buttonToggle.onDepress.AddListenerWithArgs((btn, args) => ButtonOnRelease(btn), buttonToggle); - UnityEventPatch.Patch(buttonToggle, buttonToggle.onPress, ButtonOnPress); - UnityEventPatch.Patch(buttonToggle, buttonToggle.onDepress, ButtonOnRelease); - UnityEventPatch.Patch(buttonToggle, buttonToggle.onPressOneShot, ButtonOnOneShot); + buttonToggle.onPress = UnityEventPatch.Patch(buttonToggle, buttonToggle.onPress, ButtonOnPress).GetPatchedEvent(); + buttonToggle.onDepress = UnityEventPatch.Patch(buttonToggle, buttonToggle.onDepress, ButtonOnRelease).GetPatchedEvent(); + buttonToggle.onPressOneShot = UnityEventPatch.Patch(buttonToggle, buttonToggle.onPressOneShot, ButtonOnOneShot).GetPatchedEvent(); patchedButtonToggles.Add(buttonToggle.GetHashCode()); }