Files
BoneSync/BoneSync/Patching/UnityEventPatching.cs
Aaro Varis 335df69fcd 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.
2026-01-13 17:34:02 +02:00

83 lines
2.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BoneSync.Data;
using HarmonyLib;
using StressLevelZero.Interaction;
using UnityEngine;
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>>();
private T arg;
private UnityEvent unityEvent;
private Func<T, bool> handler;
private UnityEvent proxyUnityEvent;
//private float lastInvokeTime = 0f;
//private float invokeCooldown = 0.05f;
private UnityEventPatch(T arg, UnityEvent unityEvent, Func<T, bool> handler)
{
this.arg = arg;
this.unityEvent = unityEvent;
this.handler = handler;
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 UnityEvent GetOriginalEvent()
{
return unityEvent;
}
private void OnEventInvoked()
{
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
}
}
public UnityEvent GetPatchedEvent()
{
return proxyUnityEvent;
}
public static UnityEventPatch<T> Patch(T arg, UnityEvent unityEvent, Func<T, bool> handler)
{
int eventHash = unityEvent.GetHashCode();
UnityEventPatch<T> existingPatch = patches.TryGetValue(eventHash, out UnityEventPatch<T> foundPatch) ? foundPatch : null;
if (existingPatch != null)
{
return existingPatch;
}
UnityEventPatch<T> patch = new UnityEventPatch<T>(arg, unityEvent, handler);
patches[eventHash] = patch;
return patch;
}
}
}