From ea5a9eef970fe60d2b341492bd8880424c0cc88a Mon Sep 17 00:00:00 2001 From: NotAKidoS <37721153+NotAKidoS@users.noreply.github.com> Date: Thu, 3 Apr 2025 05:08:25 -0500 Subject: [PATCH] [RelativeSync] Fixed execution order of RelativeSyncController & PuppetMaster.ProcessAvatarVisibility, so moving at high speeds with passengers does not disrupt voice or avatar distance hider --- RelativeSync/Main.cs | 8 +-- RelativeSync/ModSettings.cs | 7 +-- RelativeSync/Patches.cs | 54 ++++++++++--------- .../Components/RelativeSyncController.cs | 17 +++++- .../RelativeSync/RelativeSyncManager.cs | 1 + 5 files changed, 52 insertions(+), 35 deletions(-) diff --git a/RelativeSync/Main.cs b/RelativeSync/Main.cs index 83ec331..0a50472 100644 --- a/RelativeSync/Main.cs +++ b/RelativeSync/Main.cs @@ -17,10 +17,7 @@ public class RelativeSyncMod : MelonMod // Experimental sync hack ApplyPatches(typeof(CVRSpawnablePatches)); - - // Experimental no interpolation on Better Better Character Controller - ApplyPatches(typeof(BetterBetterCharacterControllerPatches)); - + // Send relative sync update after network root data update ApplyPatches(typeof(NetworkRootDataUpdatePatches)); @@ -31,6 +28,9 @@ public class RelativeSyncMod : MelonMod // Add components if missing (for relative sync markers) ApplyPatches(typeof(CVRSeatPatches)); ApplyPatches(typeof(CVRMovementParentPatches)); + + // So we run after the client moves the remote player + ApplyPatches(typeof(NetIKController_Patches)); } private void ApplyPatches(Type type) diff --git a/RelativeSync/ModSettings.cs b/RelativeSync/ModSettings.cs index 91a60a7..f8567ad 100644 --- a/RelativeSync/ModSettings.cs +++ b/RelativeSync/ModSettings.cs @@ -23,11 +23,7 @@ internal static class ModSettings private static readonly MelonPreferences_Entry ExpSyncedObjectHack = Category.CreateEntry("ExpSyncedObjectHack", true, "Exp Spawnable Sync Fix", description: "Forces CVRSpawnable to update position in FixedUpdate. May help reduce local jitter on synced movement parents."); - - private static readonly MelonPreferences_Entry ExpNoInterpolationOnBBCC = - Category.CreateEntry("ExpNoInterpolationOnBBCC", true, - "Exp Disable Interpolation on BBCC", description: "Disable interpolation on Better Better Character Controller. May help reduce local jitter on synced movement parents."); - + #endregion Melon Preferences internal static void Initialize() @@ -43,6 +39,5 @@ internal static class ModSettings ModNetwork.Debug_NetworkInbound = DebugLogInbound.Value; ModNetwork.Debug_NetworkOutbound = DebugLogOutbound.Value; Patches.CVRSpawnablePatches.UseHack = ExpSyncedObjectHack.Value; - Patches.BetterBetterCharacterControllerPatches.NoInterpolation = ExpNoInterpolationOnBBCC.Value; } } \ No newline at end of file diff --git a/RelativeSync/Patches.cs b/RelativeSync/Patches.cs index 71d4ec8..43937dd 100644 --- a/RelativeSync/Patches.cs +++ b/RelativeSync/Patches.cs @@ -2,12 +2,10 @@ using ABI_RC.Core.InteractionSystem; using ABI_RC.Core.Networking.Jobs; using ABI_RC.Core.Player; -using ABI_RC.Systems.Movement; using ABI.CCK.Components; using HarmonyLib; using NAK.RelativeSync.Components; using NAK.RelativeSync.Networking; -using UnityEngine; namespace NAK.RelativeSync.Patches; @@ -19,7 +17,6 @@ internal static class PlayerSetupPatches { __instance.AddComponentIfMissing(); } - } internal static class PuppetMasterPatches @@ -30,6 +27,20 @@ internal static class PuppetMasterPatches { __instance.AddComponentIfMissing(); } + + private static bool ShouldProcessAvatarVisibility { get; set; } + + [HarmonyPrefix] + [HarmonyPatch(typeof(PuppetMaster), nameof(PuppetMaster.ProcessAvatarVisibility))] + private static bool Prefix_PuppetMaster_ProcessAvatarVisibility() + => ShouldProcessAvatarVisibility; + + public static void ForceProcessAvatarVisibility(PuppetMaster puppetMaster) + { + ShouldProcessAvatarVisibility = true; + puppetMaster.ProcessAvatarVisibility(); + ShouldProcessAvatarVisibility = false; + } } internal static class CVRSeatPatches @@ -85,29 +96,24 @@ internal static class CVRSpawnablePatches } } -internal static class BetterBetterCharacterControllerPatches +internal static class NetIKController_Patches { - private static bool _noInterpolation; - internal static bool NoInterpolation - { - get => _noInterpolation; - set - { - _noInterpolation = value; - if (_rigidbody == null) return; - _rigidbody.interpolation = value ? RigidbodyInterpolation.None : _initialInterpolation; - } - } - - private static Rigidbody _rigidbody; - private static RigidbodyInterpolation _initialInterpolation; - [HarmonyPostfix] - [HarmonyPatch(typeof(BetterBetterCharacterController), nameof(BetterBetterCharacterController.Start))] - private static void Postfix_BetterBetterCharacterController_Update(ref BetterBetterCharacterController __instance) + [HarmonyPatch(typeof(NetIKController), nameof(NetIKController.LateUpdate))] + private static void Postfix_NetIKController_LateUpdate(ref NetIKController __instance) { - _rigidbody = __instance.GetComponent(); - _initialInterpolation = _rigidbody.interpolation; - NoInterpolation = _noInterpolation; // get initial value as patch runs later than settings init + if (!RelativeSyncManager.NetIkControllersToRelativeSyncControllers.TryGetValue(__instance, + out RelativeSyncController syncController)) + { + // Process visibility only after applying network IK + PuppetMasterPatches.ForceProcessAvatarVisibility(__instance._puppetMaster); + return; + } + + // Apply relative sync after the network IK has been applied + syncController.OnPostNetIkControllerLateUpdate(); + + // Process visibility after we have moved the remote player + PuppetMasterPatches.ForceProcessAvatarVisibility(__instance._puppetMaster); } } \ No newline at end of file diff --git a/RelativeSync/RelativeSync/Components/RelativeSyncController.cs b/RelativeSync/RelativeSync/Components/RelativeSyncController.cs index 2e11301..66af2c7 100644 --- a/RelativeSync/RelativeSync/Components/RelativeSyncController.cs +++ b/RelativeSync/RelativeSync/Components/RelativeSyncController.cs @@ -26,14 +26,29 @@ public class RelativeSyncController : MonoBehaviour _userId = puppetMaster._playerDescriptor.ownerId; RelativeSyncManager.RelativeSyncControllers.Add(_userId, this); + RelativeSyncManager.NetIkControllersToRelativeSyncControllers.Add(puppetMaster.netIkController, this); } private void OnDestroy() { RelativeSyncManager.RelativeSyncControllers.Remove(_userId); + + if (puppetMaster == null + || puppetMaster.netIkController == null) + { + // remove by value ? + foreach (var kvp in RelativeSyncManager.NetIkControllersToRelativeSyncControllers) + { + if (kvp.Value != this) continue; + RelativeSyncManager.NetIkControllersToRelativeSyncControllers.Remove(kvp.Key); + break; + } + return; + } + RelativeSyncManager.NetIkControllersToRelativeSyncControllers.Remove(puppetMaster.netIkController); } - private void LateUpdate() + internal void OnPostNetIkControllerLateUpdate() { // if (puppetMaster._isHidden) // return; diff --git a/RelativeSync/RelativeSync/RelativeSyncManager.cs b/RelativeSync/RelativeSync/RelativeSyncManager.cs index 9a532f4..052ca3c 100644 --- a/RelativeSync/RelativeSync/RelativeSyncManager.cs +++ b/RelativeSync/RelativeSync/RelativeSyncManager.cs @@ -11,6 +11,7 @@ public static class RelativeSyncManager public static readonly Dictionary RelativeSyncTransforms = new(); public static readonly Dictionary RelativeSyncControllers = new(); + public static readonly Dictionary NetIkControllersToRelativeSyncControllers = new(); public static void ApplyRelativeSync(string userId, int target, Vector3 position, Vector3 rotation) {