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() public void Broadcast()
{ {
Send(TransportBase.BORADCAST_ID); Send(BoneSync.transport.BROADCAST_ID);
} }
public void SendToHost() public void SendToHost()

View File

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

View File

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

View File

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

View File

@@ -11,6 +11,19 @@ using UnityEngine.Events;
namespace BoneSync.Patching 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> public class UnityEventPatch<T>
{ {
private static Dictionary<int, UnityEventPatch<T>> patches = new Dictionary<int, 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 T arg;
private UnityEvent unityEvent; private UnityEvent unityEvent;
private Func<T, bool> handler; private Func<T, bool> handler;
//private UnityAction listener; private UnityEvent proxyUnityEvent;
//private float lastInvokeTime = 0f; //private float lastInvokeTime = 0f;
//private float invokeCooldown = 0.05f; //private float invokeCooldown = 0.05f;
private UnityEventPatch(T arg, UnityEvent unityEvent, Func<T, bool> handler) private UnityEventPatch(T arg, UnityEvent unityEvent, Func<T, bool> handler)
@@ -26,63 +39,44 @@ namespace BoneSync.Patching
this.arg = arg; this.arg = arg;
this.unityEvent = unityEvent; this.unityEvent = unityEvent;
this.handler = handler; this.handler = handler;
this.proxyUnityEvent = new UnityEvent();
//listener = (UnityAction)Listener; 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); return unityEvent;
SyncLogger.Debug("TryInvoke " + allowInvokeResult);
return allowInvokeResult;
} }
private void PatchUnityEvent() private void OnEventInvoked()
{ {
if (unityEvent == null) return; bool allowInvoke = handler.Invoke(arg);
patches[unityEvent.GetHashCode()] = this; SyncLogger.Msg("UnityEventPatch invoked for event " + unityEvent.GetHashCode() + ", allowInvoke: " + allowInvoke);
//unityEvent.AddListener(listener); if (allowInvoke)
{
unityEvent.Invoke(); // only invoke the original event if allowed
}
} }
private void UnpatchUnityEvent() public UnityEvent GetPatchedEvent()
{ {
if (unityEvent == null) return; return proxyUnityEvent;
patches.Remove(unityEvent.GetHashCode());
} }
public static UnityEventPatch<T> Patch(T arg, UnityEvent unityEvent, Func<T, bool> handler) 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); UnityEventPatch<T> patch = new UnityEventPatch<T>(arg, unityEvent, handler);
patch.PatchUnityEvent(); patches[eventHash] = patch;
return 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.OnHandlePull.AddListener((UnityAction)DeviceOnPull);
//pullDevice.OnHandleReturn.AddListener((UnityAction)DeviceOnRelease); //pullDevice.OnHandleReturn.AddListener((UnityAction)DeviceOnRelease);
UnityEventPatch<PullDevice>.Patch(pullDevice, pullDevice.OnHandlePull, DeviceOnPull); pullDevice.OnHandlePull =UnityEventPatch<PullDevice>.Patch(pullDevice, pullDevice.OnHandlePull, DeviceOnPull).GetPatchedEvent();
UnityEventPatch<PullDevice>.Patch(pullDevice, pullDevice.OnHandleReturn, DeviceOnRelease); pullDevice.OnHandleReturn = UnityEventPatch<PullDevice>.Patch(pullDevice, pullDevice.OnHandleReturn, DeviceOnRelease).GetPatchedEvent();
pullDevicePatched = true; pullDevicePatched = true;
} }
@@ -82,9 +82,9 @@ namespace BoneSync.Sync.Components
SyncLogger.Msg("Patching ButtonToggle: " + buttonToggle.transform.GetPath()); SyncLogger.Msg("Patching ButtonToggle: " + buttonToggle.transform.GetPath());
//buttonToggle.onPress.AddListenerWithArgs<ButtonToggle>((btn, args) => ButtonOnPress(btn), buttonToggle); //buttonToggle.onPress.AddListenerWithArgs<ButtonToggle>((btn, args) => ButtonOnPress(btn), buttonToggle);
//buttonToggle.onDepress.AddListenerWithArgs<ButtonToggle>((btn, args) => ButtonOnRelease(btn), buttonToggle); //buttonToggle.onDepress.AddListenerWithArgs<ButtonToggle>((btn, args) => ButtonOnRelease(btn), buttonToggle);
UnityEventPatch<ButtonToggle>.Patch(buttonToggle, buttonToggle.onPress, ButtonOnPress); buttonToggle.onPress = UnityEventPatch<ButtonToggle>.Patch(buttonToggle, buttonToggle.onPress, ButtonOnPress).GetPatchedEvent();
UnityEventPatch<ButtonToggle>.Patch(buttonToggle, buttonToggle.onDepress, ButtonOnRelease); buttonToggle.onDepress = UnityEventPatch<ButtonToggle>.Patch(buttonToggle, buttonToggle.onDepress, ButtonOnRelease).GetPatchedEvent();
UnityEventPatch<ButtonToggle>.Patch(buttonToggle, buttonToggle.onPressOneShot, ButtonOnOneShot); buttonToggle.onPressOneShot = UnityEventPatch<ButtonToggle>.Patch(buttonToggle, buttonToggle.onPressOneShot, ButtonOnOneShot).GetPatchedEvent();
patchedButtonToggles.Add(buttonToggle.GetHashCode()); patchedButtonToggles.Add(buttonToggle.GetHashCode());
} }