adjust sync

This commit is contained in:
2025-03-30 15:45:22 +03:00
parent b9390bbf03
commit b72add4e81
15 changed files with 293 additions and 120 deletions

View File

@@ -116,6 +116,7 @@
<Compile Include="Networking\Messages\SceneChangeMessage.cs" />
<Compile Include="Patching\AIHealthPatches.cs" />
<Compile Include="Patching\ButtonTogglePatches.cs" />
<Compile Include="Patching\CartPatches.cs" />
<Compile Include="Patching\HolsterSlotPatches.cs" />
<Compile Include="Networking\Messages\MagazineSyncMessage.cs" />
<Compile Include="Networking\Messages\ObjectDamageMessage.cs" />
@@ -134,6 +135,7 @@
<Compile Include="Patching\PrefabSpawnerPatches.cs" />
<Compile Include="Patching\SceneManagerPatches.cs" />
<Compile Include="Patching\SkeletonHandPatches.cs" />
<Compile Include="Patching\UnityEventPatching.cs" />
<Compile Include="Patching\ZonePatches.cs" />
<Compile Include="Sync\Components\SyncableAI.cs" />
<Compile Include="Sync\Components\SyncableBase.cs" />

View File

@@ -3,6 +3,7 @@ using StressLevelZero;
using StressLevelZero.Combat;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -46,6 +47,8 @@ namespace BoneSync.Data
}
internal class ByteEncoder
{
//public BinaryWriter writer;
//public BinaryReader reader;
public List<byte> Data;
public ByteEncoder()

View File

@@ -16,6 +16,11 @@ namespace BoneSync.Networking.Messages
OnButtonPress = 3,
OnButtonRelease = 4,
OnButtonOneShot = 5,
CartGo = 6,
CartGoBackwards = 7,
CartLaunch = 8,
CartGoForward = 9,
CartDrop = 10,
}
public struct SimpleSyncableEvent
{

View File

@@ -7,71 +7,13 @@ using BoneSync.Sync;
using BoneSync.Sync.Components;
using HarmonyLib;
using MelonLoader;
using StressLevelZero.Environment;
using StressLevelZero.Interaction;
using UnityEngine;
using UnityEngine.Events;
namespace BoneSync.Patching
{
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 UnityAction listener;
//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;
//listener = (UnityAction)Listener;
}
public bool TryInvoke()
{
bool allowInvokeResult = handler(arg);
Debug.Log("TryInvoke " + allowInvokeResult);
return allowInvokeResult;
}
private void PatchUnityEvent()
{
if (unityEvent == null) return;
patches[unityEvent.GetHashCode()] = this;
//unityEvent.AddListener(listener);
}
private void UnpatchUnityEvent()
{
if (unityEvent == null) return;
patches.Remove(unityEvent.GetHashCode());
}
public static UnityEventPatch<T> Patch(T arg, UnityEvent unityEvent, Func<T, bool> handler)
{
if (patches.TryGetValue(unityEvent.GetHashCode(), out UnityEventPatch<T> oldPatch))
{
oldPatch.UnpatchUnityEvent();
}
UnityEventPatch<T> patch = new UnityEventPatch<T>(arg, unityEvent, handler);
patch.PatchUnityEvent();
return patch;
}
public static UnityEventPatch<T> TryGetPatch(UnityEvent unityEvent)
{
if (!patches.ContainsKey(unityEvent.GetHashCode())) return null;
return patches[unityEvent.GetHashCode()];
}
}
[HarmonyPatch(typeof(ButtonToggle))]
internal class ButtonTogglePatches
{
@@ -81,20 +23,4 @@ namespace BoneSync.Patching
Syncable syncable = ObjectSync.MakeOrGetSyncable(__instance);
}
}
/*[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

@@ -1,4 +1,6 @@
using StressLevelZero.Combat;
using BoneSync.Data;
using StressLevelZero.Combat;
using StressLevelZero.Environment;
using StressLevelZero.Pool;
using StressLevelZero.Props;
using StressLevelZero.Props.Weapons;
@@ -9,6 +11,7 @@ using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Events;
using Cart = StressLevelZero.Environment.Cart;
namespace BoneSync.Patching
{
@@ -40,8 +43,41 @@ namespace BoneSync.Patching
allowPatchedMethodCall = false;
}
public static void CartGo(Cart __instance)
{
if (__instance == null) return;
allowPatchedMethodCall = true;
__instance.Go();
allowPatchedMethodCall = false;
}
public static void CartLaunch(Cart __instance)
{
if (__instance == null) return;
allowPatchedMethodCall = true;
__instance.Launch();
allowPatchedMethodCall = false;
}
public static void CartGoBackward(Cart __instance)
{
if (__instance == null) return;
allowPatchedMethodCall = true;
__instance.GoBackward();
allowPatchedMethodCall = false;
}
public static void CartGoForward(Cart __instance)
{
if (__instance == null) return;
allowPatchedMethodCall = true;
__instance.GoForward();
allowPatchedMethodCall = false;
}
public static void BypassPatchInvoke(this UnityEvent e)
{
SyncLogger.Msg("BypassPatchInvoke "+ e.GetHashCode());
allowPatchedMethodCall = true;
e.Invoke();
allowPatchedMethodCall = false;

View File

@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BoneSync.Data;
using BoneSync.Networking.Messages;
using BoneSync.Sync;
using BoneSync.Sync.Components;
using HarmonyLib;
using StressLevelZero.Environment;
namespace BoneSync.Patching
{
[HarmonyPatch(typeof(Cart))]
public class CartPatches
{
public static bool CartEvent(Cart cart, SimpleEventType eventType)
{
if (CallPatchedMethods.allowPatchedMethodCall) return true;
SyncLogger.Msg("CartEvent: " + cart.transform.GetPath() + " " + eventType);
Syncable syncable = ObjectSync.MakeOrGetSyncable(cart);
if (syncable == null)
{
SyncLogger.Error("CartEvent: syncable is null");
return false;
}
return syncable.AddSimpleEventToQueue(eventType);
}
[HarmonyPatch(nameof(Cart.Go)), HarmonyPrefix]
public static bool CartStartPostfix(Cart __instance)
{
return CartEvent(__instance, SimpleEventType.CartGo);
}
[HarmonyPatch(nameof(Cart.Launch)), HarmonyPrefix]
public static bool CartStopPostfix(Cart __instance)
{
return CartEvent(__instance, SimpleEventType.CartLaunch);
}
[HarmonyPatch(nameof(Cart.GoBackward)), HarmonyPrefix]
public static bool CartGoBackwardPostfix(Cart __instance)
{
return CartEvent(__instance, SimpleEventType.CartGoBackwards);
}
[HarmonyPatch(nameof(Cart.GoForward)), HarmonyPrefix]
public static bool CartGoForwardPostfix(Cart __instance)
{
return CartEvent(__instance, SimpleEventType.CartGoForward);
}
}
}

View File

@@ -0,0 +1,88 @@
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 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 UnityAction listener;
//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;
//listener = (UnityAction)Listener;
}
public bool TryInvoke()
{
bool allowInvokeResult = handler(arg);
SyncLogger.Debug("TryInvoke " + allowInvokeResult);
return allowInvokeResult;
}
private void PatchUnityEvent()
{
if (unityEvent == null) return;
patches[unityEvent.GetHashCode()] = this;
//unityEvent.AddListener(listener);
}
private void UnpatchUnityEvent()
{
if (unityEvent == null) return;
patches.Remove(unityEvent.GetHashCode());
}
public static UnityEventPatch<T> Patch(T arg, UnityEvent unityEvent, Func<T, bool> handler)
{
if (patches.TryGetValue(unityEvent.GetHashCode(), out UnityEventPatch<T> oldPatch))
{
oldPatch.UnpatchUnityEvent();
}
UnityEventPatch<T> patch = new UnityEventPatch<T>(arg, unityEvent, handler);
patch.PatchUnityEvent();
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

@@ -59,17 +59,32 @@ namespace BoneSync.Patching
[HarmonyPatch(typeof(SceneZone))]
public static class SceneZonePatch
{
public static bool IsChildOfLocalRigRoot(Transform transform)
public static bool IsChildOfLocalRig(Transform transform)
{
if (PlayerRig.localRigWorldRoot == null) return false;
return transform.root == PlayerRig.localRigWorldRoot;
}
public static bool IsChildOfHostRig(Transform transform)
{
if (!BoneSync.IsConnected|| BoneSync.lobby.IsHost)
{
return IsChildOfLocalRig(transform);
}
else
{
PlayerRig hostRig = PlayerRig.GetPlayerRig(BoneSync.lobby.GetHostId());
Transform hostRoot = hostRig?.transform.root;
return hostRoot != null && transform.root == hostRoot;
}
}
[HarmonyPatch(nameof(SceneZone.OnTriggerEnter)), HarmonyPrefix]
public static bool EnterPrefix(SceneZone __instance, Collider other)
{
if (other.CompareTag("Player"))
{
return IsChildOfLocalRigRoot(other.transform);
return IsChildOfLocalRig(other.transform);
}
return true;
@@ -80,7 +95,7 @@ namespace BoneSync.Patching
{
if (other.CompareTag("Player"))
{
return IsChildOfLocalRigRoot(other.transform);
return IsChildOfLocalRig(other.transform);
}
return true;
@@ -97,7 +112,7 @@ namespace BoneSync.Patching
if (other.CompareTag("Player"))
{
return SceneZonePatch.IsChildOfLocalRigRoot(other.transform);
return SceneZonePatch.IsChildOfLocalRig(other.transform);
}
return true;
@@ -110,7 +125,7 @@ namespace BoneSync.Patching
{
if (other.CompareTag("Player"))
{
return SceneZonePatch.IsChildOfLocalRigRoot(other.transform);
return SceneZonePatch.IsChildOfLocalRig(other.transform);
}
return true;

View File

@@ -42,6 +42,8 @@ namespace BoneSync.Player
private Transform leftHandTransform;
private Transform rightHandTransform;
public Transform transform => playerRig.transform;
public static void LoadBundle()
{
rigBundle = EmebeddedAssetBundle.LoadFromAssembly("BoneSync.playerrep.eres");

View File

@@ -16,8 +16,6 @@ namespace BoneSync.Sync.Components
private void TrySendAISync()
{
if (!Registered) return;
if (!isOwner) return;
if (!aiBrain) return;
if (Time.realtimeSinceStartup - _lastAISyncTime > 1 / AI_SYNC_FPS)
{

View File

@@ -19,6 +19,7 @@ using StressLevelZero.AI;
using PuppetMasta;
using UnityEngine.SceneManagement;
using BoneSync.Data;
using StressLevelZero.Environment;
namespace BoneSync.Sync.Components
@@ -142,6 +143,9 @@ namespace BoneSync.Sync.Components
private SpawnFragment spawnFragment;
private Powerable powerable;
private Cart physicsCart;
private void CheckAutoSync()
{
if (!isValid) return;
@@ -182,6 +186,7 @@ namespace BoneSync.Sync.Components
return true;
}
if (buttonToggles.Length > 0) return true;
if (physicsCart != null) return true;
return false;
}
@@ -222,6 +227,7 @@ namespace BoneSync.Sync.Components
sockets = GetComponentsInChildren<Socket>();
aiBrain = GetComponent<AIBrain>();
buttonToggles = GetComponentsInChildren<ButtonToggle>();
physicsCart = GetComponent<Cart>();
if (sockets.Length == 0)
{
plugs = GetComponentsInChildren<AlignPlug>();
@@ -259,8 +265,8 @@ namespace BoneSync.Sync.Components
if (spawnFragment) return false; // if has spawn fragment, don't sync
FindAndUpdateComponents();
if (buttonToggles?.Length > 0) return true;
if (rigidbodies?.Length > 0) return true;
if (ShouldAutoSync()) return true;
return false;
}

View File

@@ -23,31 +23,31 @@ namespace BoneSync.Sync.Components
ObjectSync.SendObjectSyncMessage(this);
}
private void TrySendObjectSync()
{
if (ShouldSendSync()) SendObjectSync();
}
public IEnumerator SyncCoroutineAsync()
{
SyncLogger.Msg("Running sync coroutine for: " + transform.GetPath());
if (_syncCoroutineRunning) yield break;
_syncCoroutineRunning = true;
while (isOwner)
while (ShouldSendSync())
{
TrySendAISync();
TrySendObjectSync();
SendObjectSync();
TrySendPlugSync();
yield return new WaitForSeconds(!Registered ? 1 : 1 / OBJECT_SYNC_FPS);
yield return new WaitForSeconds( 1 / OBJECT_SYNC_FPS );
}
_syncCoroutineRunning = false;
yield break;
}
private void RunSyncLoop()
{
MelonCoroutines.Start(SyncCoroutineAsync());
}
public void SetOwner(ulong ownerId)
{
SyncLogger.Msg("Setting owner for " + _syncId + " to " + ownerId);
_ownerId = ownerId;
FindAndUpdateComponents();
MelonCoroutines.Start(SyncCoroutineAsync());
RunSyncLoop();
UpdateKinematic();
TryCatchUpSimpleEvents();
}
@@ -123,6 +123,7 @@ namespace BoneSync.Sync.Components
SetOwner(localId);
}
}
RunSyncLoop();
}
public bool ShouldSendSync()
@@ -135,10 +136,13 @@ namespace BoneSync.Sync.Components
return true;
}
private void AddSimpleEventToQueue(SimpleEventType eType, byte index = 0, byte len = 0)
public bool AddSimpleEventToQueue(SimpleEventType eType, byte index = 0, byte len = 0)
{
RegisterSyncable();
if (!isOwner && Registered) { return false; }
_simpleEventQueue.Enqueue(new byte[] { (byte)eType, index, len });
TryCatchUpSimpleEvents();
return true;
}
private void TryCatchUpSimpleEvents()

View File

@@ -23,10 +23,7 @@ namespace BoneSync.Sync.Components
{
SyncLogger.Msg("ButtonToggle:" + eventType + " " + toggle.transform.GetPath());
byte index = (byte)Array.IndexOf(buttonToggles, toggle);
RegisterSyncable();
if (!isOwner && Registered) return false;
AddSimpleEventToQueue(eventType, index, (byte)buttonToggles.Length);
return true;
return AddSimpleEventToQueue(eventType, index, (byte)buttonToggles.Length);
}
bool ButtonOnPress(ButtonToggle toggle)
{
@@ -44,15 +41,11 @@ namespace BoneSync.Sync.Components
bool DeviceOnPull(PullDevice device)
{
if (!isOwner && Registered) { return false; }
AddSimpleEventToQueue(SimpleEventType.OnDevicePull);
return true;
return AddSimpleEventToQueue(SimpleEventType.OnDevicePull);
}
bool DeviceOnRelease(PullDevice device)
{
if (!isOwner && Registered) { return false; }
AddSimpleEventToQueue(SimpleEventType.OnDeviceRelease);
return true;
return AddSimpleEventToQueue(SimpleEventType.OnDeviceRelease);
}
private void TryPatchUnityEvents()
@@ -160,10 +153,11 @@ namespace BoneSync.Sync.Components
for (int i = 0; i < objectSyncTransforms.Length; i++)
{
ObjectSyncTransform objectSyncTransform = objectSyncTransforms[i];
rigidbodies[i].angularVelocity = objectSyncTransform.angularVelocity;
rigidbodies[i].velocity = objectSyncTransform.velocity;
rigidbodies[i].position = objectSyncTransform.transform.position;
rigidbodies[i].rotation = objectSyncTransform.transform.rotation;
Rigidbody rb = rigidbodies[i];
rb.angularVelocity = objectSyncTransform.angularVelocity;
rb.velocity = objectSyncTransform.velocity;
rb.MovePosition(objectSyncTransform.transform.position);
rb.MoveRotation(objectSyncTransform.transform.rotation);
_transforms[i].localScale = objectSyncTransform.transform.scale;
//_transforms[i].ApplySimpleTransform(objectSyncTransform.transform);
}
@@ -248,6 +242,24 @@ namespace BoneSync.Sync.Components
buttonToggles[index]?.onPressOneShot.BypassPatchInvoke();
}
break;
case SimpleEventType.CartGo:
CallPatchedMethods.CartGo(physicsCart);
break;
case SimpleEventType.CartGoBackwards:
CallPatchedMethods.CartGoBackward(physicsCart);
break;
case SimpleEventType.CartLaunch:
CallPatchedMethods.CartLaunch(physicsCart);
break;
case SimpleEventType.CartGoForward:
CallPatchedMethods.CartGoForward(physicsCart);
break;
case SimpleEventType.CartDrop:
//CallPatchedMethods.Drop();
break;
default:
SyncLogger.Warning("Unknown SimpleEventType: " + eType);
break;
}
}
// on collision

View File

@@ -71,8 +71,6 @@ namespace BoneSync.Sync.Components
private const float PLUG_SYNC_FPS = 1f;
private void TrySendPlugSync()
{
if (!Registered) return;
if (!isOwner) return;
if (Time.realtimeSinceStartup - _lastPlugSyncTime > 1 / PLUG_SYNC_FPS)
{
_SendPlugSync();

View File

@@ -5,6 +5,7 @@ using BoneSync.Patching;
using BoneSync.Sync.Components;
using MelonLoader;
using StressLevelZero.Data;
using StressLevelZero.Environment;
using StressLevelZero.Interaction;
using StressLevelZero.Pool;
using System;
@@ -109,7 +110,22 @@ namespace BoneSync.Sync
ObjectSyncMessage message = new ObjectSyncMessage(data);
message.Broadcast();
}
private static Syncable _MakeOrGetSyncable(GameObject gameObject, bool deleteSubSyncabled = true)
private static Transform _GetPerferredParentTransform(Transform t)
{
if (t == null) return null;
Transform parent = t.parent;
if (parent == null) return t;
Cart cart = parent.GetComponentInParent<Cart>();
if (cart) return cart.transform;
InteractableHostManager manager = parent.GetComponentInParent<InteractableHostManager>();
if (manager) return manager.transform;
return parent;
}
private static Syncable _MakeOrGetSyncable(GameObject gameObject, bool deleteSubSyncables = true)
{
//Scene scene = gameObject.scene;
//SyncLogger.Msg("Making or getting syncable for: " + gameObject.name);
@@ -120,7 +136,7 @@ namespace BoneSync.Sync
Syncable syncable = gameObject.GetComponent<Syncable>();
// delete all sub syncables
if (deleteSubSyncabled)
if (deleteSubSyncables)
{
try
{
@@ -146,8 +162,9 @@ namespace BoneSync.Sync
if (syncable == null)
{
syncable = gameObject.AddComponent<Syncable>();
// SyncLogger.Msg("Created syncable for: " + gameObject.name);
Transform perferredObjectParent = _GetPerferredParentTransform(gameObject.transform);
syncable = _MakeOrGetSyncable(perferredObjectParent.gameObject, deleteSubSyncables);
}
return syncable;
}
@@ -169,31 +186,31 @@ namespace BoneSync.Sync
{
return parentSyncable;
}
return _MakeOrGetSyncable(buttonToggle.gameObject);
return MakeOrGetSyncable(buttonToggle.gameObject);
}
public static Syncable MakeOrGetSyncable(GameObject gameObject)
public static Syncable MakeOrGetSyncable(GameObject gameObject, bool deleteSubSyncables = true)
{
Syncable syncable = _GetSyncableFromCache(gameObject);
if (syncable == null)
{
syncable = _MakeOrGetSyncable(gameObject);
syncable = _MakeOrGetSyncable(gameObject, deleteSubSyncables);
}
return syncable;
}
public static Syncable MakeOrGetSyncable(Poolee poolee)
{
return _MakeOrGetSyncable(poolee.gameObject);
return MakeOrGetSyncable(poolee.gameObject);
}
public static Syncable MakeOrGetSyncable(InteractableHost interactableHost)
{
if (interactableHost.manager) return MakeOrGetSyncable(interactableHost.manager);
return _MakeOrGetSyncable(interactableHost.gameObject);
return MakeOrGetSyncable(interactableHost.gameObject);
}
public static Syncable MakeOrGetSyncable(InteractableHostManager interactableHostManager)
{
return _MakeOrGetSyncable(interactableHostManager.gameObject, true);
return MakeOrGetSyncable(interactableHostManager.gameObject, true);
}
public static Syncable SpawnPooleeAndMakeSyncable(SpawnPoolableInfo spawnInfo)
@@ -350,5 +367,11 @@ namespace BoneSync.Sync
syncable.OnOwnershipTransferRequest(newOwnerId);
}
}
internal static Syncable MakeOrGetSyncable(Cart instance)
{
Syncable syncable = MakeOrGetSyncable(instance.gameObject);
return syncable;
}
}
}