diff --git a/BoneSync/Data/SpawnableManager.cs b/BoneSync/Data/SpawnableManager.cs index 7efb234..cb8a0f6 100644 --- a/BoneSync/Data/SpawnableManager.cs +++ b/BoneSync/Data/SpawnableManager.cs @@ -66,7 +66,7 @@ namespace BoneSync.Data Pool pool = GetPool(spawnableObject); if (pool == null) { - SyncLogger.Warning("[SpawnPooleeAndMakeSyncable] Failed to find pool: " + spawnableObject.title); + SyncLogger.Warning("Failed to find pool: " + spawnableObject.title); return null; } Poolee poolee = CallPatchedMethods.InstantiatePoolee(pool, position, rotation, pool.Prefab.transform.localScale); diff --git a/BoneSync/MelonLoaderMod.cs b/BoneSync/MelonLoaderMod.cs index 29ed8c6..1547f0e 100644 --- a/BoneSync/MelonLoaderMod.cs +++ b/BoneSync/MelonLoaderMod.cs @@ -116,7 +116,7 @@ namespace BoneSync IsConnected = lobby.IsConnected(); transport.Tick(); Packet.TryCatchup(); - PlayerRig.Tick(); + PlayerRig.Tick(Time.fixedDeltaTime); } public override void OnLateUpdate() diff --git a/BoneSync/Networking/Messages/SimpleSyncableEventMessage.cs b/BoneSync/Networking/Messages/SimpleSyncableEventMessage.cs index cbe217a..4ab8cfb 100644 --- a/BoneSync/Networking/Messages/SimpleSyncableEventMessage.cs +++ b/BoneSync/Networking/Messages/SimpleSyncableEventMessage.cs @@ -28,7 +28,7 @@ namespace BoneSync.Networking.Messages public SimpleEventType eventType; public byte index; public byte length; - //public object[] args; + public byte[] extraData; } [PacketType(PacketType.SimpleObjectEventSync), PacketReliability(PacketReliability.ReliableFast), PacketCatchup(20)] public class SimpleSyncableEventMessage : NetworkMessage @@ -41,6 +41,12 @@ namespace BoneSync.Networking.Messages byteEncoder.WriteByte((byte)simpleSyncableEvent.eventType); byteEncoder.WriteByte(simpleSyncableEvent.index); byteEncoder.WriteByte(simpleSyncableEvent.length); + if (simpleSyncableEvent.extraData == null) + { + simpleSyncableEvent.extraData = new byte[0]; + } + byteEncoder.WriteByte((byte)simpleSyncableEvent.extraData.Length); + byteEncoder.WriteBytes(simpleSyncableEvent.extraData); } public SimpleSyncableEventMessage(Packet packet) @@ -50,6 +56,8 @@ namespace BoneSync.Networking.Messages eventData.eventType = (SimpleEventType)byteEncoder.ReadByte(); eventData.index = byteEncoder.ReadByte(); eventData.length = byteEncoder.ReadByte(); + ushort extraDataLength = byteEncoder.ReadByte(); + eventData.extraData = byteEncoder.ReadBytes(extraDataLength); } public override void Execute() diff --git a/BoneSync/Player/PlayerRig.cs b/BoneSync/Player/PlayerRig.cs index add4306..0185da6 100644 --- a/BoneSync/Player/PlayerRig.cs +++ b/BoneSync/Player/PlayerRig.cs @@ -55,11 +55,17 @@ namespace BoneSync.Player SyncLogger.Msg("Loaded playerRepBundle success"); } - public static void Tick() + public static void Tick(float deltaTime) { foreach (PlayerRig playerRig in _playerRigs.Values) { - playerRig.UpdateIK(); + try { + playerRig.UpdatePlayerTransforms(deltaTime); + playerRig.UpdateIK(deltaTime); + } catch (Exception e) + { + SyncLogger.Error("Error updating player rig for " + playerRig._ownerId); + } } } @@ -78,15 +84,53 @@ namespace BoneSync.Player characterAnimationManager.ApplyFingerCurl(handedness, 1f - fingerCurl.thumb, 1f - fingerCurl.index, 1f - fingerCurl.middle, 1f - fingerCurl.ring, 1f - fingerCurl.pinky); } + private Vector3 _targetRootPos = Vector3.zero; + + private Vector3 _targetHeadPos = Vector3.zero; + private Quaternion _targetHeadRot = Quaternion.identity; + + private Vector3 _targetLeftHandPos = Vector3.zero; + private Quaternion _targetLeftHandRot = Quaternion.identity; + + private Vector3 _targetRightHandPos = Vector3.zero; + private Quaternion _targetRightHandRot = Quaternion.identity; + + private void UpdatePlayerTransforms(float deltaTime) + { + float step = deltaTime * 5f; // smoothing factor + + playerRig.transform.position = Vector3.Lerp(playerRig.transform.position, _targetRootPos, step); + + headTransform.position = Vector3.Lerp(headTransform.position, _targetHeadPos, step); + leftHandTransform.position = Vector3.Lerp(leftHandTransform.position, _targetLeftHandPos, step); + rightHandTransform.position = Vector3.Lerp(rightHandTransform.position, _targetRightHandPos, step); + + + headTransform.rotation = Quaternion.Lerp(headTransform.rotation, _targetHeadRot, step); + leftHandTransform.rotation = Quaternion.Lerp(leftHandTransform.rotation, _targetLeftHandRot, step); + rightHandTransform.rotation = Quaternion.Lerp(rightHandTransform.rotation, _targetRightHandRot, step); + } + + public void UpdatePlayerSync(PlayerSyncInfo playerSyncInfo) { EnsurePlayerRig(); //SyncLogger.Msg("Updating player sync for " + _ownerId); - playerRig.transform.position = playerSyncInfo.rootPos; + //playerRig.transform.position = playerSyncInfo.rootPos; + _targetRootPos = playerSyncInfo.rootPos; - headTransform.ApplySimpleTransform(playerSyncInfo.headPos); - leftHandTransform.ApplySimpleTransform(playerSyncInfo.leftHandPos); - rightHandTransform.ApplySimpleTransform(playerSyncInfo.rightHandPos); + _targetHeadRot = playerSyncInfo.headPos.rotation; + _targetHeadPos = playerSyncInfo.headPos.position; + + _targetLeftHandPos = playerSyncInfo.leftHandPos.position; + _targetLeftHandRot = playerSyncInfo.leftHandPos.rotation; + + _targetRightHandPos = playerSyncInfo.rightHandPos.position; + _targetRightHandRot = playerSyncInfo.rightHandPos.rotation; + + //headTransform.ApplySimpleTransform(playerSyncInfo.headPos); + //leftHandTransform.ApplySimpleTransform(playerSyncInfo.leftHandPos); + //rightHandTransform.ApplySimpleTransform(playerSyncInfo.rightHandPos); SetFingerCurl(Handedness.LEFT, playerSyncInfo.leftHandFingerCurl); SetFingerCurl(Handedness.RIGHT, playerSyncInfo.rightHandFingerCurl); @@ -96,6 +140,8 @@ namespace BoneSync.Player UpdatePoseRadius(Handedness.LEFT, playerSyncInfo.poseRadiusLeft); UpdatePoseRadius(Handedness.RIGHT, playerSyncInfo.poseRadiusRight); + + UpdatePlayerTransforms( 1f / RIG_SYNC_FPS); // immediately update transforms to avoid lag } public void UpdatePose(Handedness hand, int index) @@ -232,25 +278,18 @@ namespace BoneSync.Player } - public void UpdateIK() + public void UpdateIK(float deltaTime) { // Catch errors so other players arent broken - try - { - if (body == null || characterAnimationManager == null || animator == null || playerRig == null) return; + + if (body == null || characterAnimationManager == null || animator == null || playerRig == null) return; - animator.Update(Time.fixedDeltaTime); - characterAnimationManager.OnLateUpdate(); - Vector3 repInputVel = Vector3.zero; + animator.Update(deltaTime); + characterAnimationManager.OnLateUpdate(); + Vector3 repInputVel = Vector3.zero; - body.FullBodyUpdate(repInputVel, Vector3.zero); - body.ArtToBlender.UpdateBlender(); - } - catch (Exception e) - { - SyncLogger.Warning("Failed to update player rig " + _ownerId); - SyncLogger.Warning(e.ToString()); - } + body.FullBodyUpdate(repInputVel, Vector3.zero); + body.ArtToBlender.UpdateBlender(); } @@ -263,7 +302,7 @@ namespace BoneSync.Player public static void OnPlayerSync(PlayerSyncMessage playerSyncMessage) { //SyncLogger.Msg("Player Sync Received " + playerSyncMessage.senderId); - PlayerRig playerRig = PlayerRig.GetPlayerRig(playerSyncMessage.senderId); + PlayerRig playerRig = GetPlayerRig(playerSyncMessage.senderId); if (playerRig == null) return; playerRig.UpdatePlayerSync(playerSyncMessage.playerSyncInfo); diff --git a/BoneSync/Sync/Components/SyncableBase.cs b/BoneSync/Sync/Components/SyncableBase.cs index daa93de..be647a2 100644 --- a/BoneSync/Sync/Components/SyncableBase.cs +++ b/BoneSync/Sync/Components/SyncableBase.cs @@ -76,13 +76,13 @@ namespace BoneSync.Sync.Components get; } private ushort _syncId; - private float _lastSyncTime; + private float _lastObjectSyncTime; private bool _isInHolster; private bool _attemptedRegister; public bool Registered => _syncId != 0; - public bool isStale => Time.realtimeSinceStartup - _lastSyncTime > 30f; + public bool isStale => Time.realtimeSinceStartup - _lastObjectSyncTime > 30f; public bool isOwner => _ownerId == BoneSync.lobby.GetLocalId(); public bool isValid diff --git a/BoneSync/Sync/Components/SyncableNetworking.cs b/BoneSync/Sync/Components/SyncableNetworking.cs index 4744c4e..bf07a42 100644 --- a/BoneSync/Sync/Components/SyncableNetworking.cs +++ b/BoneSync/Sync/Components/SyncableNetworking.cs @@ -20,7 +20,7 @@ namespace BoneSync.Sync.Components private Queue _simpleEventQueue = new Queue(); private void SendObjectSync() { - _lastSyncTime = Time.realtimeSinceStartup; + _lastObjectSyncTime = Time.realtimeSinceStartup; ObjectSync.SendObjectSyncMessage(this); } private IEnumerator OwnerCoroutineAsync() @@ -164,11 +164,11 @@ namespace BoneSync.Sync.Components return true; } - public bool AddSimpleEventToQueue(SimpleEventType eType, byte index = 0, byte len = 0) + public bool AddSimpleEventToQueue(SimpleEventType eType, byte index = 0, byte len = 0, byte[] extraData = null) { RegisterSyncable(); if (!isOwner && Registered) { return false; } - _simpleEventQueue.Enqueue(new byte[] { (byte)eType, index, len }); + _simpleEventQueue.Enqueue(new byte[] { (byte)eType, index, len }.Concat(extraData ?? new byte[0]).ToArray()); TryCatchUpSimpleEvents(); return true; } @@ -184,11 +184,11 @@ namespace BoneSync.Sync.Components if (_simpleEventQueue.Count > 0 && Registered && isOwner) { byte[] eventData = _simpleEventQueue.Dequeue(); - _SendSimpleEvent((SimpleEventType)eventData[0], eventData[1], eventData[2]); + _SendSimpleEvent((SimpleEventType)eventData[0], eventData[1], eventData[2], eventData.Skip(3).ToArray()); TryCatchUpSimpleEvents(); } } - private void _SendSimpleEvent(SimpleEventType eType, byte index = 0, byte len = 0) + private void _SendSimpleEvent(SimpleEventType eType, byte index = 0, byte len = 0, byte[] extraData = null) { SyncLogger.Msg("Sending simple event: " + eType); SimpleSyncableEvent data = new SimpleSyncableEvent() @@ -196,7 +196,8 @@ namespace BoneSync.Sync.Components syncId = _syncId, eventType = eType, index = index, - length = len + length = len, + extraData = extraData }; SimpleSyncableEventMessage simpleSyncEvent = new SimpleSyncableEventMessage(data); diff --git a/BoneSync/Sync/Components/SyncablePhysics.cs b/BoneSync/Sync/Components/SyncablePhysics.cs index f4f5e6b..073bc93 100644 --- a/BoneSync/Sync/Components/SyncablePhysics.cs +++ b/BoneSync/Sync/Components/SyncablePhysics.cs @@ -23,7 +23,10 @@ namespace BoneSync.Sync.Components { SyncLogger.Msg("ButtonToggle:" + eventType + " " + toggle.transform.GetPath()); byte index = (byte)Array.IndexOf(buttonToggles, toggle); - return AddSimpleEventToQueue(eventType, index, (byte)buttonToggles.Length); + bool isPressed = toggle._isPressed; + bool hasBeenPressed = toggle._hasBeenPressed; + byte[] buttonState = BitPacking.PackBits(new bool[] { isPressed, hasBeenPressed }); + return AddSimpleEventToQueue(eventType, index, (byte)buttonToggles.Length, buttonState); } bool ButtonOnPress(ButtonToggle toggle) { @@ -144,7 +147,7 @@ namespace BoneSync.Sync.Components public void ApplyObjectSyncTransforms(ObjectSyncTransform[] objectSyncTransforms) { - _lastSyncTime = Time.realtimeSinceStartup; + _lastObjectSyncTime = Time.realtimeSinceStartup; if (IsPlugged()) { return; } if (objectSyncTransforms.Length != rigidbodies.Length) { @@ -234,14 +237,32 @@ namespace BoneSync.Sync.Components if (len != eventData.length) { SyncLogger.Warning("ButtonPress length mismatch: " + len + " != " + eventData.length); } if (index < buttonToggles.Length) { - buttonToggles[index]?.onPress.BypassPatchInvoke(); + ButtonToggle toggle = buttonToggles[index]; + if (toggle == null) + { + SyncLogger.Warning("ButtonToggle at index " + index + " is null"); + break; + } + bool[] buttonState = BitPacking.UnpackBits(eventData.extraData, 2); + toggle._isPressed = buttonState[0]; + toggle._hasBeenPressed = buttonState[1]; + toggle.onPress.BypassPatchInvoke(); } break; case SimpleEventType.OnButtonRelease: if (len != eventData.length) { SyncLogger.Warning("ButtonPress length mismatch: " + len + " != " + eventData.length); } if (index < buttonToggles.Length) { - buttonToggles[index]?.onDepress.BypassPatchInvoke(); + ButtonToggle toggle = buttonToggles[index]; + if (toggle == null) + { + SyncLogger.Warning("ButtonToggle at index " + index + " is null"); + break; + } + bool[] buttonState = BitPacking.UnpackBits(eventData.extraData, 2); + toggle._isPressed = buttonState[0]; + toggle._hasBeenPressed = buttonState[1]; + toggle.onDepress.BypassPatchInvoke(); } break; case SimpleEventType.OnButtonOneShot: @@ -250,7 +271,16 @@ namespace BoneSync.Sync.Components } if (index < buttonToggles.Length) { - buttonToggles[index]?.onPressOneShot.BypassPatchInvoke(); + ButtonToggle toggle = buttonToggles[index]; + if (toggle == null) + { + SyncLogger.Warning("ButtonToggle at index " + index + " is null"); + break; + } + bool[] buttonState = BitPacking.UnpackBits(eventData.extraData, 2); + toggle._isPressed = buttonState[0]; + toggle._hasBeenPressed = buttonState[1]; + toggle.onPressOneShot.BypassPatchInvoke(); } break; case SimpleEventType.CartGo: