[RelativeSync] Fixed execution order of RelativeSyncController & PuppetMaster.ProcessAvatarVisibility, so moving at high speeds with passengers does not disrupt voice or avatar distance hider

This commit is contained in:
NotAKidoS 2025-04-03 05:08:25 -05:00
parent 063669e8a6
commit ea5a9eef97
5 changed files with 52 additions and 35 deletions

View file

@ -18,9 +18,6 @@ public class RelativeSyncMod : MelonMod
// Experimental sync hack // Experimental sync hack
ApplyPatches(typeof(CVRSpawnablePatches)); ApplyPatches(typeof(CVRSpawnablePatches));
// Experimental no interpolation on Better Better Character Controller
ApplyPatches(typeof(BetterBetterCharacterControllerPatches));
// Send relative sync update after network root data update // Send relative sync update after network root data update
ApplyPatches(typeof(NetworkRootDataUpdatePatches)); ApplyPatches(typeof(NetworkRootDataUpdatePatches));
@ -31,6 +28,9 @@ public class RelativeSyncMod : MelonMod
// Add components if missing (for relative sync markers) // Add components if missing (for relative sync markers)
ApplyPatches(typeof(CVRSeatPatches)); ApplyPatches(typeof(CVRSeatPatches));
ApplyPatches(typeof(CVRMovementParentPatches)); ApplyPatches(typeof(CVRMovementParentPatches));
// So we run after the client moves the remote player
ApplyPatches(typeof(NetIKController_Patches));
} }
private void ApplyPatches(Type type) private void ApplyPatches(Type type)

View file

@ -24,10 +24,6 @@ internal static class ModSettings
Category.CreateEntry("ExpSyncedObjectHack", true, 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."); "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<bool> 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 #endregion Melon Preferences
internal static void Initialize() internal static void Initialize()
@ -43,6 +39,5 @@ internal static class ModSettings
ModNetwork.Debug_NetworkInbound = DebugLogInbound.Value; ModNetwork.Debug_NetworkInbound = DebugLogInbound.Value;
ModNetwork.Debug_NetworkOutbound = DebugLogOutbound.Value; ModNetwork.Debug_NetworkOutbound = DebugLogOutbound.Value;
Patches.CVRSpawnablePatches.UseHack = ExpSyncedObjectHack.Value; Patches.CVRSpawnablePatches.UseHack = ExpSyncedObjectHack.Value;
Patches.BetterBetterCharacterControllerPatches.NoInterpolation = ExpNoInterpolationOnBBCC.Value;
} }
} }

View file

@ -2,12 +2,10 @@
using ABI_RC.Core.InteractionSystem; using ABI_RC.Core.InteractionSystem;
using ABI_RC.Core.Networking.Jobs; using ABI_RC.Core.Networking.Jobs;
using ABI_RC.Core.Player; using ABI_RC.Core.Player;
using ABI_RC.Systems.Movement;
using ABI.CCK.Components; using ABI.CCK.Components;
using HarmonyLib; using HarmonyLib;
using NAK.RelativeSync.Components; using NAK.RelativeSync.Components;
using NAK.RelativeSync.Networking; using NAK.RelativeSync.Networking;
using UnityEngine;
namespace NAK.RelativeSync.Patches; namespace NAK.RelativeSync.Patches;
@ -19,7 +17,6 @@ internal static class PlayerSetupPatches
{ {
__instance.AddComponentIfMissing<RelativeSyncMonitor>(); __instance.AddComponentIfMissing<RelativeSyncMonitor>();
} }
} }
internal static class PuppetMasterPatches internal static class PuppetMasterPatches
@ -30,6 +27,20 @@ internal static class PuppetMasterPatches
{ {
__instance.AddComponentIfMissing<RelativeSyncController>(); __instance.AddComponentIfMissing<RelativeSyncController>();
} }
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 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] [HarmonyPostfix]
[HarmonyPatch(typeof(BetterBetterCharacterController), nameof(BetterBetterCharacterController.Start))] [HarmonyPatch(typeof(NetIKController), nameof(NetIKController.LateUpdate))]
private static void Postfix_BetterBetterCharacterController_Update(ref BetterBetterCharacterController __instance) private static void Postfix_NetIKController_LateUpdate(ref NetIKController __instance)
{ {
_rigidbody = __instance.GetComponent<Rigidbody>(); if (!RelativeSyncManager.NetIkControllersToRelativeSyncControllers.TryGetValue(__instance,
_initialInterpolation = _rigidbody.interpolation; out RelativeSyncController syncController))
NoInterpolation = _noInterpolation; // get initial value as patch runs later than settings init {
// 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);
} }
} }

View file

@ -26,14 +26,29 @@ public class RelativeSyncController : MonoBehaviour
_userId = puppetMaster._playerDescriptor.ownerId; _userId = puppetMaster._playerDescriptor.ownerId;
RelativeSyncManager.RelativeSyncControllers.Add(_userId, this); RelativeSyncManager.RelativeSyncControllers.Add(_userId, this);
RelativeSyncManager.NetIkControllersToRelativeSyncControllers.Add(puppetMaster.netIkController, this);
} }
private void OnDestroy() private void OnDestroy()
{ {
RelativeSyncManager.RelativeSyncControllers.Remove(_userId); 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) // if (puppetMaster._isHidden)
// return; // return;

View file

@ -11,6 +11,7 @@ public static class RelativeSyncManager
public static readonly Dictionary<int, RelativeSyncMarker> RelativeSyncTransforms = new(); public static readonly Dictionary<int, RelativeSyncMarker> RelativeSyncTransforms = new();
public static readonly Dictionary<string, RelativeSyncController> RelativeSyncControllers = new(); public static readonly Dictionary<string, RelativeSyncController> RelativeSyncControllers = new();
public static readonly Dictionary<NetIKController, RelativeSyncController> NetIkControllersToRelativeSyncControllers = new();
public static void ApplyRelativeSync(string userId, int target, Vector3 position, Vector3 rotation) public static void ApplyRelativeSync(string userId, int target, Vector3 position, Vector3 rotation)
{ {