diff --git a/BoneSync/BoneSync.csproj b/BoneSync/BoneSync.csproj index 5c8db6c..88bd138 100644 --- a/BoneSync/BoneSync.csproj +++ b/BoneSync/BoneSync.csproj @@ -89,6 +89,7 @@ + diff --git a/BoneSync/Patching/HolsterSlotPatches.cs b/BoneSync/Patching/HolsterSlotPatches.cs new file mode 100644 index 0000000..0130d29 --- /dev/null +++ b/BoneSync/Patching/HolsterSlotPatches.cs @@ -0,0 +1,48 @@ +using BoneSync.Sync; +using BoneSync.Sync.Components; +using HarmonyLib; +using MelonLoader; +using StressLevelZero.Interaction; +using StressLevelZero.Props.Weapons; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.NetworkInformation; +using System.Text; +using System.Threading.Tasks; +namespace BoneSync.Patching +{ + internal class HolsterSlotPatches + { + [HarmonyPatch(typeof(HandWeaponSlotReciever), nameof(HandWeaponSlotReciever.MakeStatic))] + public static void StaticPatch(HandWeaponSlotReciever __instance) + { + MelonLogger.Msg("HandWeaponSlotReciever.MakeStatic: " + __instance.name); + InteractableHost interactableHost = __instance.m_WeaponHost; + if (interactableHost == null) + { + MelonLogger.Error("InteractableHost is null for " + __instance.transform.GetPath()); + return; + } + + Syncable syncable = ObjectSync.MakeOrGetSyncable(interactableHost); + syncable?.SetInHolster(true); + } + + [HarmonyPatch(typeof(HandWeaponSlotReciever), nameof(HandWeaponSlotReciever.MakeDynamic))] + public static void DynamicPatch(HandWeaponSlotReciever __instance) + { + MelonLogger.Msg("HandWeaponSlotReciever.MakeDynamic: " + __instance.name); + InteractableHost interactableHost = __instance.m_WeaponHost; + if (interactableHost == null) + { + MelonLogger.Error("InteractableHost is null for " + __instance.transform.GetPath()); + return; + } + + Syncable syncable = ObjectSync.MakeOrGetSyncable(interactableHost); + syncable?.SetInHolster(false); + + } + } +} diff --git a/BoneSync/Patching/PoolPatches.cs b/BoneSync/Patching/PoolPatches.cs index 86829f5..c09bed0 100644 --- a/BoneSync/Patching/PoolPatches.cs +++ b/BoneSync/Patching/PoolPatches.cs @@ -134,10 +134,15 @@ namespace BoneSync.Patching bool spawnNormally = BoneSync.lobby.IsHost || PoolBlacklist.IsClientSpawnPool(__instance.pool); - if (spawnNormally) return; + if (!spawnNormally) { + MelonCoroutines.Start(OnSpawnClient(__instance)); // block object from spawning + return; + } + if (syncable == null) return; + + MelonLogger.Msg("Poolee.OnSpawn: " + __instance.gameObject.transform.GetPath() + " " + syncable.GetSyncId()); - MelonCoroutines.Start(OnSpawnClient(__instance)); // block object from spawning } diff --git a/BoneSync/Sync/Components/SyncableBase.cs b/BoneSync/Sync/Components/SyncableBase.cs index af78395..e68c012 100644 --- a/BoneSync/Sync/Components/SyncableBase.cs +++ b/BoneSync/Sync/Components/SyncableBase.cs @@ -75,12 +75,20 @@ namespace BoneSync.Sync.Components private ushort _syncId; private float _lastSyncTime; + private bool _isInHolster; private bool _attemptedRegister; public bool Registered => _syncId != 0; public bool isStale => Time.time - _lastSyncTime > 5f; public bool isOwner => _ownerId == BoneSync.lobby.GetLocalId(); + public void SetInHolster(bool val) + { + MelonLogger.Msg(transform.GetPath() + " hosterState:" + val); + _isInHolster = val; + FindAndUpdateComponents(); + } + public bool IsHolding() { if (interactableManager) @@ -119,7 +127,7 @@ namespace BoneSync.Sync.Components private void CheckAutoSync() { - bool shouldAutoSync = CheckIfShouldAutoSync(); + bool shouldAutoSync = ShouldAutoSync(); if (shouldAutoSync && (BoneSync.lobby.IsHost || ClientSpawningAllowed())) { MelonLogger.Msg("AutoSyncing: " + transform.GetPath()); @@ -128,7 +136,10 @@ namespace BoneSync.Sync.Components } private IEnumerator _OnEnableCo() { - yield return null; // wait a frame to make sure all components are initialized, I hate this but it works + // wait for a couple frames to make sure all components are initialized, I hate this but it works + yield return null; + yield return null; + yield return null; FindAndUpdateComponents(); CheckAutoSync(); yield break; @@ -143,7 +154,7 @@ namespace BoneSync.Sync.Components MelonCoroutines.Start(_OnEnableCo()); } - public bool CheckIfShouldAutoSync() + public bool ShouldAutoSync() { if (InPoolManagerTransform()) return false; if (!gameObject.activeInHierarchy) return false; @@ -225,6 +236,7 @@ namespace BoneSync.Sync.Components public bool IsPlugged() { + if (plugs.Length == 0) return false; for (int i = 0; i < plugs.Length; i++) { AlignPlug alignPlug = plugs[i]; @@ -239,13 +251,13 @@ namespace BoneSync.Sync.Components { if (!this) return; // if object is destroyed, don't do anything bool isRegistered = Registered; - + if (isRegistered) { bool isPlugged = IsPlugged(); bool canDiscard = isOwner && (!isPlugged || force); // only owner can discard - MelonLogger.Msg("Discarding syncable: " + transform.GetPath() + " force:" + force + " registered:" + isRegistered + " despawn:" + despawn + " isPlugged:" + isPlugged + " canDiscard:" + canDiscard); + //MelonLogger.Msg("Discarding syncable: " + transform.GetPath() + " force:" + force + " registered:" + isRegistered + " despawn:" + despawn + " isPlugged:" + isPlugged + " canDiscard:" + canDiscard); //MelonLogger.Warning("Discarding registered syncable: " + transform.GetPath() + " force: " + force); if (canDiscard) @@ -256,6 +268,8 @@ namespace BoneSync.Sync.Components if (!canDiscard && !force) return; } + //MelonLogger.Msg("Discarding syncable: " + transform.GetPath() + " force:" + force + " registered:" + isRegistered + " despawn:" + despawn + " isPlugged:" + IsPlugged()); + try { EjectAllPlugs(true); @@ -317,6 +331,7 @@ namespace BoneSync.Sync.Components public void RegisterSyncable() { if (!BoneSync.lobby.IsConnected()) return; + FindAndUpdateComponents(); if (Registered) { TryBecomeOwner(); diff --git a/BoneSync/Sync/Components/SyncableNetworking.cs b/BoneSync/Sync/Components/SyncableNetworking.cs index eebeb1a..82d982a 100644 --- a/BoneSync/Sync/Components/SyncableNetworking.cs +++ b/BoneSync/Sync/Components/SyncableNetworking.cs @@ -61,7 +61,7 @@ namespace BoneSync.Sync.Components private void _SendRegisterSync() { MelonLogger.Msg("Registering syncable object: " + gameObject.name); - MelonCoroutines.Start(__SendRegisterSyncCo()); + MelonCoroutines.Start(__SendRegisterSyncCo()); } private void _SendDiscard(bool despawn = false) @@ -119,6 +119,7 @@ namespace BoneSync.Sync.Components if (!Registered) return false; if (!isOwner) return false; if (isStale) return true; + if (_isInHolster) return true; if (AllRigidbodiesSleeping()) return false; return true; } diff --git a/BoneSync/Sync/Components/SyncablePhysics.cs b/BoneSync/Sync/Components/SyncablePhysics.cs index 838a851..d8651bd 100644 --- a/BoneSync/Sync/Components/SyncablePhysics.cs +++ b/BoneSync/Sync/Components/SyncablePhysics.cs @@ -93,6 +93,7 @@ namespace BoneSync.Sync.Components public void ApplyObjectSyncTransforms(ObjectSyncTransform[] objectSyncTransforms) { + if (IsPlugged()) { return; } if (objectSyncTransforms.Length != rigidbodies.Length) { MelonLogger.Warning("ObjectSyncTransforms length mismatch: " + objectSyncTransforms.Length + " != " + _transforms.Length); @@ -142,7 +143,7 @@ namespace BoneSync.Sync.Components private void UpdateTransformList() { // get non-null rigidbodies - Rigidbody[] rbs = GetRigidbodies().Where(rb => rb != null && RigidbodyBelongsToSyncable(rb)).ToArray(); + Rigidbody[] rbs = GetRigidbodies().Where(rb => rb != null).ToArray(); rigidbodies = rbs; _transforms = rbs.Select(rb => rb.transform).ToArray(); } diff --git a/BoneSync/Sync/ObjectSync.cs b/BoneSync/Sync/ObjectSync.cs index f75e37c..bf15177 100644 --- a/BoneSync/Sync/ObjectSync.cs +++ b/BoneSync/Sync/ObjectSync.cs @@ -112,7 +112,7 @@ namespace BoneSync.Sync private static Syncable _MakeOrGetSyncable(GameObject gameObject, bool deleteSubSyncabled = true) { //Scene scene = gameObject.scene; - //MelonLogger.Msg("Making or getting syncable for: " + gameObject.name + " in scene: " + scene.name); + //MelonLogger.Msg("Making or getting syncable for: " + gameObject.name); if (gameObject == null) { return null; @@ -122,23 +122,32 @@ namespace BoneSync.Sync // delete all sub syncables if (deleteSubSyncabled) { - Syncable[] subSyncables = gameObject.GetComponentsInChildren(true); - for (int i = 0; i < subSyncables.Length; i++) + try { - Syncable subSyncable = subSyncables[i]; - if (subSyncable == syncable) continue; - bool isRegistered = subSyncable.Registered; - bool isPlugged = subSyncable.IsPlugged(); + Syncable[] subSyncables = gameObject.GetComponentsInChildren(true); + for (int i = 0; i < subSyncables.Length; i++) + { + Syncable subSyncable = subSyncables[i]; + if (subSyncable == syncable) continue; + if (subSyncable == null) continue; + bool isRegistered = subSyncable.Registered; + bool isPlugged = subSyncable.IsPlugged(); - MelonLogger.Msg("Discarding subSyncable: " + subSyncable.transform.GetPath() + " registered:" + isRegistered + " plugged:" + isPlugged); - if (isRegistered || isPlugged) continue; - subSyncable.DiscardSyncableImmediate(true, false); + MelonLogger.Msg("Discarding subSyncable: " + subSyncable.transform.GetPath() + " registered:" + isRegistered + " plugged:" + isPlugged); + if (isRegistered || isPlugged) continue; + subSyncable.DiscardSyncable(); + } + } + catch (Exception e) + { + MelonLogger.Warning("Failed to delete sub syncables: " + e.Message); } } if (syncable == null) { syncable = gameObject.AddComponent(); + // MelonLogger.Msg("Created syncable for: " + gameObject.name); } return syncable; } @@ -175,7 +184,7 @@ namespace BoneSync.Sync public static Syncable MakeOrGetSyncable(InteractableHostManager interactableHostManager) { - return _MakeOrGetSyncable(interactableHostManager.gameObject); + return _MakeOrGetSyncable(interactableHostManager.gameObject, true); } public static Syncable SpawnPooleeAndMakeSyncable(SpawnPoolableInfo spawnInfo)