diff --git a/BoneSync/BoneSync.csproj b/BoneSync/BoneSync.csproj index 818b769..26d93f2 100644 --- a/BoneSync/BoneSync.csproj +++ b/BoneSync/BoneSync.csproj @@ -93,8 +93,10 @@ + + diff --git a/BoneSync/Data/ByteEncoder.cs b/BoneSync/Data/ByteEncoder.cs index 1b1f682..b5e1101 100644 --- a/BoneSync/Data/ByteEncoder.cs +++ b/BoneSync/Data/ByteEncoder.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using UnityEngine; namespace BoneSync.Data { @@ -45,6 +46,7 @@ namespace BoneSync.Data } internal class ByteEncoder { + public List Data; public ByteEncoder() { @@ -61,6 +63,11 @@ namespace BoneSync.Data return Data.ToArray(); } + public void SetBytes(byte[] data) + { + Data = data.ToList(); + } + public void WriteByte(byte value) { Data.Add(value); @@ -169,30 +176,30 @@ namespace BoneSync.Data return BitConverter.ToUInt64(ReadBytes(sizeof(ulong)), 0); } - public void WriteVector3(UnityEngine.Vector3 value) + public void WriteVector3(Vector3 value) { WriteFloat(value.x); WriteFloat(value.y); WriteFloat(value.z); } - public UnityEngine.Vector3 ReadVector3() + public Vector3 ReadVector3() { float x = ReadFloat(); float y = ReadFloat(); float z = ReadFloat(); - return new UnityEngine.Vector3(x, y, z); + return new Vector3(x, y, z); } - public void WriteQuaternion(UnityEngine.Quaternion value) + public void WriteQuaternion(Quaternion value) { WriteVector3(value.eulerAngles); } - public UnityEngine.Quaternion ReadQuaternion() + public Quaternion ReadQuaternion() { - UnityEngine.Vector3 eulerAngles = ReadVector3(); - return UnityEngine.Quaternion.Euler(eulerAngles); + Vector3 eulerAngles = ReadVector3(); + return Quaternion.Euler(eulerAngles); } public void WriteSimpleTransform(SimpleSyncTransform value) @@ -204,9 +211,9 @@ namespace BoneSync.Data public SimpleSyncTransform ReadSimpleTransform() { - UnityEngine.Vector3 position = ReadVector3(); - UnityEngine.Quaternion rotation = ReadQuaternion(); - UnityEngine.Vector3 scale = ReadVector3(); + Vector3 position = ReadVector3(); + Quaternion rotation = ReadQuaternion(); + Vector3 scale = ReadVector3(); return new SimpleSyncTransform() { position = position, @@ -215,7 +222,7 @@ namespace BoneSync.Data }; } - public void WriteMatrix4x4(UnityEngine.Matrix4x4 matrix) + public void WriteMatrix4x4(Matrix4x4 matrix) { for (int i = 0; i < 16; i++) { @@ -223,9 +230,9 @@ namespace BoneSync.Data } } - public UnityEngine.Matrix4x4 ReadMatrix4x4() + public Matrix4x4 ReadMatrix4x4() { - UnityEngine.Matrix4x4 matrix = new UnityEngine.Matrix4x4(); + Matrix4x4 matrix = new Matrix4x4(); for (int i = 0; i < 16; i++) { matrix[i] = ReadFloat(); @@ -307,12 +314,14 @@ namespace BoneSync.Data public void WriteCompressedFloat(float value) { // write a float in the range of 0-1 with 2 decimal places - WriteByte((byte)(value * 100)); + value = Mathf.Clamp01(value); + int rounded = Mathf.FloorToInt(value * 255f); + WriteByte((byte)rounded); } public float ReadCompressedFloat() { - return ReadByte() / 100f; + return ReadByte() / 255f; } public void WriteFingerCurl(SimpleFingerCurl fingerCurl) diff --git a/BoneSync/Data/PlayerScripts.cs b/BoneSync/Data/PlayerScripts.cs index a114bf7..e504973 100644 --- a/BoneSync/Data/PlayerScripts.cs +++ b/BoneSync/Data/PlayerScripts.cs @@ -10,12 +10,14 @@ using StressLevelZero.Rig; using StressLevelZero.VRMK; using UnhollowerBaseLib; using UnityEngine; +using StressLevelZero.Player; namespace BoneSync.Data { // copied from Entanglement mod public static class PlayerScripts { + public static GameObject localPlayerGameObject; public static RigManager playerRig; public static PhysBody playerPhysBody; public static Player_Health playerHealth; @@ -28,13 +30,15 @@ namespace BoneSync.Data public static void GetPlayerScripts() { - GameObject localPlayerRig = GameObject.Find("[RigManager (Default Brett)]/[SkeletonRig (GameWorld Brett)]"); - playerRig = localPlayerRig.GetComponentInChildren(); + if (playerRig != null) + return; + localPlayerGameObject = GameObject.Find("[RigManager (Default Brett)]"); + playerRig = localPlayerGameObject.GetComponentInChildren(); playerHealth = playerRig.playerHealth; reloadLevelOnDeath = playerHealth.reloadLevelOnDeath; - playerHealth.reloadLevelOnDeath = !BoneSync.lobby.IsConnected(); + playerHealth.reloadLevelOnDeath = !BoneSync.IsConnected; try { @@ -54,6 +58,7 @@ namespace BoneSync.Data public static void GetHandPoses() { + GetPlayerScripts(); // Checks if we already got the hand poses to prevent crashes if (playerHandPoses == null) CharacterAnimationManager.FetchHandPoseList(out playerHandPoses); // Lets hope this is constant! diff --git a/BoneSync/MelonLoaderMod.cs b/BoneSync/MelonLoaderMod.cs index a543204..64b9e0d 100644 --- a/BoneSync/MelonLoaderMod.cs +++ b/BoneSync/MelonLoaderMod.cs @@ -24,6 +24,12 @@ namespace BoneSync public class BoneSync : MelonMod { + public static bool IsConnected + { + get; private set; + } + + public static LobbyManager lobby; public static TransportBase transport; public override void OnApplicationStart() @@ -70,8 +76,8 @@ namespace BoneSync public override void OnUpdate() { - - bool processPackets = transport.Tick(); + PlayerRig.LocalSyncTick(); + transport.Tick(); //PlayerRig.Tick(); @@ -85,12 +91,6 @@ namespace BoneSync lobby.CreateLobby(); } - if (Input.GetKeyDown(KeyCode.L)) - { - MelonLogger.Msg("Reloading bundle"); - PlayerRig.LoadBundle(); - } - if (Input.GetKeyDown(KeyCode.N)) { MelonLogger.Msg("Creating debug player rig"); @@ -111,6 +111,8 @@ namespace BoneSync public override void OnFixedUpdate() { + IsConnected = lobby.IsConnected(); + transport.Tick(); PlayerRig.Tick(); } diff --git a/BoneSync/Networking/Messages/AISyncMessage.cs b/BoneSync/Networking/Messages/AISyncMessage.cs new file mode 100644 index 0000000..4714fc2 --- /dev/null +++ b/BoneSync/Networking/Messages/AISyncMessage.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using BoneSync.Sync; +using BoneSync.Sync.Components; +using PuppetMasta; +using StressLevelZero.AI; + +namespace BoneSync.Networking.Messages +{ + public struct AIBehaviourHealth + { + public float cur_hp; + public float cur_arm_lf; + public float cur_arm_rt; + public float cur_leg_lf; + public float cur_leg_rt; + + public AIBehaviourHealth(SubBehaviourHealth behaviourHealth) + { + cur_hp = behaviourHealth.cur_hp; + cur_arm_lf = behaviourHealth.cur_arm_lf; + cur_arm_rt = behaviourHealth.cur_arm_rt; + cur_leg_lf = behaviourHealth.cur_leg_lf; + cur_leg_rt = behaviourHealth.cur_leg_rt; + } + } + + public struct AISyncInfo + { + public ushort syncId; + public AIBehaviourHealth health; + public PuppetMaster.State puppetState; + public PuppetMaster.Mode puppetMode; + public BehaviourBaseNav.MentalState mentalState; + + public AISyncInfo(ushort syncid, AIBrain aiBrain) + { + this.syncId = syncid; + this.health = new AIBehaviourHealth(aiBrain.behaviour.health); + this.puppetState = aiBrain.puppetMaster.activeState; + this.puppetMode = aiBrain.puppetMaster.activeMode; + this.mentalState = aiBrain.behaviour.mentalState; + } + } + [PacketType(PacketType.AISync), PacketReliability(PacketReliability.Unreliable)] + public class AISyncMessage : NetworkMessage + { + private AISyncInfo _aiSyncInfo; + public AISyncInfo aiSyncInfo => _aiSyncInfo; + + public AISyncMessage(AISyncInfo aiSyncInfo) + { + _aiSyncInfo = aiSyncInfo; + byteEncoder.WriteUShort(_aiSyncInfo.syncId); + byteEncoder.WriteCompressedFloat(_aiSyncInfo.health.cur_hp); + byteEncoder.WriteCompressedFloat(_aiSyncInfo.health.cur_arm_lf); + byteEncoder.WriteCompressedFloat(_aiSyncInfo.health.cur_arm_rt); + byteEncoder.WriteCompressedFloat(_aiSyncInfo.health.cur_leg_lf); + byteEncoder.WriteCompressedFloat(_aiSyncInfo.health.cur_leg_rt); + byteEncoder.WriteByte((byte)_aiSyncInfo.puppetState); + byteEncoder.WriteByte((byte)_aiSyncInfo.puppetMode); + byteEncoder.WriteByte((byte)_aiSyncInfo.mentalState); + } + + public AISyncMessage(Packet packet) + { + byteEncoder.WriteBytes(packet.Data); + _aiSyncInfo = new AISyncInfo(); + _aiSyncInfo.syncId = byteEncoder.ReadUShort(); + _aiSyncInfo.health.cur_hp = byteEncoder.ReadCompressedFloat(); + _aiSyncInfo.health.cur_arm_lf = byteEncoder.ReadCompressedFloat(); + _aiSyncInfo.health.cur_arm_rt = byteEncoder.ReadCompressedFloat(); + _aiSyncInfo.health.cur_leg_lf = byteEncoder.ReadCompressedFloat(); + _aiSyncInfo.health.cur_leg_rt = byteEncoder.ReadCompressedFloat(); + _aiSyncInfo.puppetState = (PuppetMaster.State)byteEncoder.ReadByte(); + _aiSyncInfo.puppetMode = (PuppetMaster.Mode)byteEncoder.ReadByte(); + _aiSyncInfo.mentalState = (BehaviourBaseNav.MentalState)byteEncoder.ReadByte(); + } + + public override void Execute() + { + Syncable syncable = ObjectSyncCache.GetSyncable(_aiSyncInfo.syncId); + if (syncable == null) return; + syncable.OnAISyncData(_aiSyncInfo); + } + } +} diff --git a/BoneSync/Networking/Messages/PlayerSyncMessage.cs b/BoneSync/Networking/Messages/PlayerSyncMessage.cs index 66ccd2a..d0f43e7 100644 --- a/BoneSync/Networking/Messages/PlayerSyncMessage.cs +++ b/BoneSync/Networking/Messages/PlayerSyncMessage.cs @@ -56,12 +56,12 @@ namespace BoneSync.Networking.Messages byteEncoder.WriteSimpleTransform(_playerSyncInfo.headPos); byteEncoder.WriteSimpleTransform(_playerSyncInfo.leftHandPos); byteEncoder.WriteSimpleTransform(_playerSyncInfo.rightHandPos); - byteEncoder.WriteFingerCurl(_playerSyncInfo.leftHandFingerCurl); - byteEncoder.WriteFingerCurl(_playerSyncInfo.rightHandFingerCurl); byteEncoder.WriteByte(_playerSyncInfo.poseIndexRight); byteEncoder.WriteByte(_playerSyncInfo.poseIndexLeft); - byteEncoder.WriteFloat(_playerSyncInfo.poseRadiusRight); - byteEncoder.WriteFloat(_playerSyncInfo.poseRadiusLeft); + byteEncoder.WriteCompressedFloat(_playerSyncInfo.poseRadiusRight); + byteEncoder.WriteCompressedFloat(_playerSyncInfo.poseRadiusLeft); + byteEncoder.WriteFingerCurl(_playerSyncInfo.leftHandFingerCurl); + byteEncoder.WriteFingerCurl(_playerSyncInfo.rightHandFingerCurl); } public PlayerSyncMessage(Packet packet) @@ -71,12 +71,12 @@ namespace BoneSync.Networking.Messages _playerSyncInfo.headPos = byteEncoder.ReadSimpleTransform(); _playerSyncInfo.leftHandPos = byteEncoder.ReadSimpleTransform(); _playerSyncInfo.rightHandPos = byteEncoder.ReadSimpleTransform(); - _playerSyncInfo.leftHandFingerCurl = byteEncoder.ReadFingerCurl(); - _playerSyncInfo.rightHandFingerCurl = byteEncoder.ReadFingerCurl(); _playerSyncInfo.poseIndexRight = byteEncoder.ReadByte(); _playerSyncInfo.poseIndexLeft = byteEncoder.ReadByte(); - _playerSyncInfo.poseRadiusRight = byteEncoder.ReadFloat(); - _playerSyncInfo.poseRadiusLeft = byteEncoder.ReadFloat(); + _playerSyncInfo.poseRadiusRight = byteEncoder.ReadCompressedFloat(); + _playerSyncInfo.poseRadiusLeft = byteEncoder.ReadCompressedFloat(); + _playerSyncInfo.leftHandFingerCurl = byteEncoder.ReadFingerCurl(); + _playerSyncInfo.rightHandFingerCurl = byteEncoder.ReadFingerCurl(); } public override void Execute() diff --git a/BoneSync/Networking/NetworkMessage.cs b/BoneSync/Networking/NetworkMessage.cs index 19a49c0..8d18cd4 100644 --- a/BoneSync/Networking/NetworkMessage.cs +++ b/BoneSync/Networking/NetworkMessage.cs @@ -145,7 +145,7 @@ namespace BoneSync.Networking } public void Send(ulong receiverId) { - if (BoneSync.lobby.IsConnected() == false) + if (BoneSync.IsConnected == false) { MelonLogger.Warning("Cannot send packet, not connected to lobby"); return; diff --git a/BoneSync/Networking/PacketTypes.cs b/BoneSync/Networking/PacketTypes.cs index 49ab1bf..2ae2fb3 100644 --- a/BoneSync/Networking/PacketTypes.cs +++ b/BoneSync/Networking/PacketTypes.cs @@ -20,5 +20,6 @@ namespace BoneSync.Networking GunSync = 9, SimpleObjectEventSync = 10, PlugSync = 11, + AISync = 12, } } diff --git a/BoneSync/Patching/AIHealthPatches.cs b/BoneSync/Patching/AIHealthPatches.cs new file mode 100644 index 0000000..e7fad6b --- /dev/null +++ b/BoneSync/Patching/AIHealthPatches.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using HarmonyLib; +using PuppetMasta; +namespace BoneSync.Patching +{ + /* + [HarmonyPatch(typeof(SubBehaviourHealth))] + internal class AIHealthPatches + { + [HarmonyPatch(nameof(SubBehaviourHealth.TakeDamage)), HarmonyPostfix] + private static void DamagePrefix(SubBehaviourHealth __instance) + { + + } + }*/ +} diff --git a/BoneSync/Patching/GunPatches.cs b/BoneSync/Patching/GunPatches.cs index 78b3dd0..d703c8e 100644 --- a/BoneSync/Patching/GunPatches.cs +++ b/BoneSync/Patching/GunPatches.cs @@ -27,7 +27,7 @@ namespace BoneSync.Patching public static void OnFirePatch(Gun __instance) { MelonLoader.MelonLogger.Msg("Gun.OnFire: " + __instance.name); - if (!BoneSync.lobby.IsConnected()) return; + if (!BoneSync.IsConnected) return; Syncable syncable = ObjectSync.MakeOrGetSyncable(__instance.gameObject); if (syncable == null) return; diff --git a/BoneSync/Patching/ObjectHealthPatches.cs b/BoneSync/Patching/ObjectHealthPatches.cs index fb7085f..7cb494d 100644 --- a/BoneSync/Patching/ObjectHealthPatches.cs +++ b/BoneSync/Patching/ObjectHealthPatches.cs @@ -24,6 +24,7 @@ namespace BoneSync.Patching private static bool TakeDamagePatch(ObjectDestructable __instance, ref Vector3 normal, ref float damage, ref bool crit, ref AttackType attackType) { if (CallPatchedMethods.allowPatchedMethodCall) return true; + if (!BoneSync.IsConnected) return true; if (damage < 0.05f) return true; // ignore small damage (e.g. a little bit of fall damage) MelonLoader.MelonLogger.Msg("ObjectDestructable.TakeDamage: " + damage); Syncable syncable = ObjectSync.MakeOrGetSyncable(__instance.gameObject); @@ -46,7 +47,7 @@ namespace BoneSync.Patching [HarmonyPrefix] private static bool LootTablePatch(ObjectDestructable __instance, ref LootTableData __result) { - if (!BoneSync.lobby.IsConnected()) return true; + if (!BoneSync.IsConnected) return true; Syncable syncable = ObjectSync.MakeOrGetSyncable(__instance.gameObject); if (syncable != null && !BoneSync.lobby.IsHost) { @@ -65,6 +66,7 @@ namespace BoneSync.Patching private static bool TakeDamagePatch(Prop_Health __instance, ref float damage, ref bool crit, ref AttackType attackType) { if (CallPatchedMethods.allowPatchedMethodCall) return true; + if (!BoneSync.IsConnected) return true; MelonLoader.MelonLogger.Msg("Prop_Health.TAKEDAMAGE: " + damage); Syncable syncable = ObjectSync.MakeOrGetSyncable(__instance.gameObject); if (syncable != null) diff --git a/BoneSync/Patching/PoolPatches.cs b/BoneSync/Patching/PoolPatches.cs index 16e9fa1..f826c65 100644 --- a/BoneSync/Patching/PoolPatches.cs +++ b/BoneSync/Patching/PoolPatches.cs @@ -92,7 +92,7 @@ namespace BoneSync.Patching if (__instance.Prefab == null) return; if (CallPatchedMethods.allowPatchedMethodCall) return; if (PoolBlacklist.isBlacklistedPool(__instance)) return; - if (BoneSync.lobby.IsConnected()) + if (BoneSync.IsConnected) { MelonLogger.Msg("Patched Spawning object in pool: " + __instance.name); bool isHost = BoneSync.lobby.IsHost; @@ -108,7 +108,7 @@ namespace BoneSync.Patching if (__instance.Prefab == null) return true; if (CallPatchedMethods.allowPatchedMethodCall) return true; if (PoolBlacklist.isBlacklistedPool(__instance)) return true; - if (BoneSync.lobby.IsConnected()) + if (BoneSync.IsConnected) { MelonLogger.Msg("Patched Spawning object in pool: " + __instance.name); return BoneSync.lobby.IsHost; // only allow host to spawn objects naturally @@ -126,7 +126,7 @@ namespace BoneSync.Patching public static void OnSpawnPatchPost(Poolee __instance) { if (CallPatchedMethods.allowPatchedMethodCall) return; - if (!BoneSync.lobby.IsConnected()) return; + if (!BoneSync.IsConnected) return; MelonLogger.Msg("Poolee.OnSpawn: " + __instance.gameObject.transform.GetPath()); @@ -149,7 +149,7 @@ namespace BoneSync.Patching public static void OnDespawnPatchPost(Poolee __instance) { if (CallPatchedMethods.allowPatchedMethodCall) return; - if (!BoneSync.lobby.IsConnected()) return; + if (!BoneSync.IsConnected) return; MelonLogger.Msg("Poolee.OnDespawn: " + __instance.gameObject.transform.GetPath()); diff --git a/BoneSync/Patching/SkeletonHandPatches.cs b/BoneSync/Patching/SkeletonHandPatches.cs index 7231eec..ec622cb 100644 --- a/BoneSync/Patching/SkeletonHandPatches.cs +++ b/BoneSync/Patching/SkeletonHandPatches.cs @@ -21,13 +21,43 @@ namespace BoneSync.Patching public static byte poseIndexLeft = 0; public static float radiusLeft = 0.0f; - [HarmonyPatch(nameof(SkeletonHand.SetHandPose)), HarmonyPostfix] + private static Dictionary handPoses = new Dictionary(); + + private static byte GetHandPoseIndex(string handPoseName) + { + if (handPoses.ContainsKey(handPoseName)) + return handPoses[handPoseName]; + + if (PlayerScripts.playerHandPoses == null) + { + MelonLogger.Error("PlayerScripts.playerHandPoses is null!"); + return 0; + } + if (PlayerScripts.playerHandPoses.Count == 0) + { + MelonLogger.Msg("PlayerScripts.playerHandPoses is empty, getting hand poses..."); + PlayerScripts.GetHandPoses(); + } + + bool found = PlayerScripts.playerHandPoses.Contains(handPoseName); + if (!found) + { + //MelonLogger.Error($"Hand pose {handPoseName} not found in playerHandPoses!"); + return 0; + } + byte index = (byte)PlayerScripts.playerHandPoses.IndexOf(handPoseName); + handPoses.Add(handPoseName, index); + return index; + } + + + [HarmonyPatch(nameof(SkeletonHand.SetHandPose)), HarmonyPrefix] private static void SetHandPosePostfix(SkeletonHand __instance, string handPoseName) { if (!__instance.GetCharacterAnimationManager()) return; MelonLogger.Msg($"SetHandPosePostfix: {handPoseName}"); - int poseIndex = PlayerScripts.playerHandPoses.IndexOf(handPoseName); + int poseIndex = GetHandPoseIndex(handPoseName); switch (__instance.handedness) { case Handedness.LEFT: @@ -40,18 +70,23 @@ namespace BoneSync.Patching } - [HarmonyPatch(nameof(SkeletonHand.SetCylinderRadius)), HarmonyPostfix] + [HarmonyPatch(nameof(SkeletonHand.SetCylinderRadius)), HarmonyPrefix] private static void SetCylinderRadiusPrefix(SkeletonHand __instance, float radius) { if (!__instance.GetCharacterAnimationManager()) return; - MelonLogger.Msg($"SetCylinderRadiusPrefix: {radius}"); + + //MelonLogger.Msg($"SetCylinderRadiusPrefix: {radius}"); switch (__instance.handedness) { case Handedness.LEFT: + if (radiusLeft == radius) return; + MelonLogger.Msg($"SetCylinderRadiusPrefixLeft: {radius}"); radiusLeft = radius; break; case Handedness.RIGHT: + if (radiusRight == radius) return; + MelonLogger.Msg($"SetCylinderRadiusPrefixRight: {radius}"); radiusRight = radius; break; } diff --git a/BoneSync/Patching/ZonePatches.cs b/BoneSync/Patching/ZonePatches.cs index 122048f..015680a 100644 --- a/BoneSync/Patching/ZonePatches.cs +++ b/BoneSync/Patching/ZonePatches.cs @@ -18,7 +18,7 @@ namespace BoneSync.Patching [HarmonyPatch(nameof(ZoneSpawner.Spawn)), HarmonyPrefix] public static bool ZoneSpawnPrefix(ZoneSpawner __instance) { - if (!BoneSync.lobby.IsConnected()) return true; // do not block if not connected + if (!BoneSync.IsConnected) return true; // do not block if not connected MelonLogger.Msg("ZoneSpawner.Spawn: " + __instance.transform.GetPath()); @@ -38,7 +38,7 @@ namespace BoneSync.Patching [HarmonyPatch(nameof(ZoneEncounter.StartEncounter)), HarmonyPrefix] public static bool ZoneEncounterSpawnPrefix(ZoneEncounter __instance) { - if (!BoneSync.lobby.IsConnected()) return true; + if (!BoneSync.IsConnected) return true; MelonLogger.Msg("ZoneEncounter.StartEncounter: " + __instance.transform.GetPath()); diff --git a/BoneSync/Player/PlayerRig.cs b/BoneSync/Player/PlayerRig.cs index 79ab243..d679bec 100644 --- a/BoneSync/Player/PlayerRig.cs +++ b/BoneSync/Player/PlayerRig.cs @@ -17,13 +17,15 @@ using BoneSync.Data; using StressLevelZero.Interaction; using UnhollowerBaseLib; using BoneSync.Patching; +using BoneSync.Sync.Components; +using Oculus.Platform.Models; namespace BoneSync.Player { internal class PlayerRig { - private const float RIG_SYNC_FPS = 30; + private const float RIG_SYNC_FPS = Syncable.SYNC_FPS; public static AssetBundle rigBundle; private static float _lastLocalSyncTime = 0; @@ -57,15 +59,18 @@ namespace BoneSync.Player { playerRig.UpdateIK(); } - - if (Time.time - _lastLocalSyncTime > 1 / RIG_SYNC_FPS) - { - SendLocalPlayerSync(); - _lastLocalSyncTime = Time.time; - } } + public static void LocalSyncTick() + { + if (Time.realtimeSinceStartup - _lastLocalSyncTime > 1 / RIG_SYNC_FPS) + { + SendLocalPlayerSync(); + _lastLocalSyncTime = Time.realtimeSinceStartup; + } + } + private void SetFingerCurl(Handedness handedness, SimpleFingerCurl fingerCurl) { characterAnimationManager.ApplyFingerCurl(handedness, 1f - fingerCurl.thumb, 1f - fingerCurl.index, 1f - fingerCurl.middle, 1f - fingerCurl.ring, 1f - fingerCurl.pinky); @@ -82,6 +87,12 @@ namespace BoneSync.Player SetFingerCurl(Handedness.LEFT, playerSyncInfo.leftHandFingerCurl); SetFingerCurl(Handedness.RIGHT, playerSyncInfo.rightHandFingerCurl); + + UpdatePose(Handedness.LEFT, playerSyncInfo.poseIndexLeft); + UpdatePose(Handedness.RIGHT, playerSyncInfo.poseIndexRight); + + UpdatePoseRadius(Handedness.LEFT, playerSyncInfo.poseRadiusLeft); + UpdatePoseRadius(Handedness.RIGHT, playerSyncInfo.poseRadiusRight); } public void UpdatePose(Handedness hand, int index) @@ -97,21 +108,34 @@ namespace BoneSync.Player public void UpdatePoseRadius(Handedness hand, float radius) => characterAnimationManager?.SetCylinderRadius(hand, radius); + private static GameObject localPlayerRig; + private static Transform localRigRoot; + private static Transform localRigHeadTransform; + private static Transform localRigLeftHandTransform; + private static Transform localRigRightHandTransform; + public static void SetLocalRigReferences() + { + if (localPlayerRig != null) return; + localPlayerRig = GameObject.Find("[RigManager (Default Brett)]/[SkeletonRig (GameWorld Brett)]"); + localRigRoot = localPlayerRig.transform; + + localRigHeadTransform = localRigRoot.Find("Head"); + localRigLeftHandTransform = localRigRoot.Find("Hand (left)"); + localRigRightHandTransform = localRigRoot.Find("Hand (right)"); + } + public static PlayerSyncInfo? GetLocalSyncInfo() { - GameObject localPlayerRig = GameObject.Find("[RigManager (Default Brett)]/[SkeletonRig (GameWorld Brett)]"); + SetLocalRigReferences(); + if (localPlayerRig == null) { MelonLogger.Msg("Local player rig not found"); return null; } - Transform root = localPlayerRig.transform; + - Transform localHeadTransform = root.Find("Head"); - Transform localLeftHandTransform = root.Find("Hand (left)"); - Transform localRightHandTransform = root.Find("Hand (right)"); - - if (localHeadTransform == null || localLeftHandTransform == null || localRightHandTransform == null) + if (localRigHeadTransform == null || localRigLeftHandTransform == null || localRigRightHandTransform == null) { MelonLogger.Msg("Local player rig components not found"); return null; @@ -119,10 +143,10 @@ namespace BoneSync.Player PlayerSyncInfo playerSyncInfo = new PlayerSyncInfo() { - rootPos = root.position, - headPos = new SimpleSyncTransform(localHeadTransform), - leftHandPos = new SimpleSyncTransform(localLeftHandTransform), - rightHandPos = new SimpleSyncTransform(localRightHandTransform), + rootPos = localRigRoot.position, + headPos = new SimpleSyncTransform(localRigHeadTransform), + leftHandPos = new SimpleSyncTransform(localRigLeftHandTransform), + rightHandPos = new SimpleSyncTransform(localRigRightHandTransform), //leftHandFingerCurl = new SimpleFingerCurl(PlayerScripts.playerLeftHand.fingerCurl), //rightHandFingerCurl = new SimpleFingerCurl(PlayerScripts.playerRightHand.fingerCurl) poseIndexLeft = SkeletonHandPatches.poseIndexLeft, @@ -142,7 +166,7 @@ namespace BoneSync.Player private static void SendLocalPlayerSync() { - if (!BoneSync.lobby.IsConnected()) return; + if (!BoneSync.IsConnected) return; //MelonLogger.Msg("Sending local player sync"); PlayerSyncInfo? playerSyncInfo = GetLocalSyncInfo(); if (!playerSyncInfo.HasValue) return; diff --git a/BoneSync/Sync/Components/SyncableAI.cs b/BoneSync/Sync/Components/SyncableAI.cs index 67692a9..0f618bf 100644 --- a/BoneSync/Sync/Components/SyncableAI.cs +++ b/BoneSync/Sync/Components/SyncableAI.cs @@ -3,13 +3,62 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using BoneSync.Networking.Messages; using UnityEngine; namespace BoneSync.Sync.Components { public partial class Syncable : MonoBehaviour { - + private AISyncInfo _aiSyncInfo; + private float _lastAISyncTime; + private const float AI_SYNC_FPS = 5f; + + private void TrySendAISync() + { + if (!isOwner) return; + if (!aiBrain) return; + if (Time.realtimeSinceStartup - _lastAISyncTime > 1 / AI_SYNC_FPS) + { + _SendAIStateSync(); + } + } + private void _SendAIStateSync() + { + if (!aiBrain) return; + _lastAISyncTime = Time.realtimeSinceStartup; + AISyncInfo aiSyncInfo = new AISyncInfo(_syncId, aiBrain); + AISyncMessage message = new AISyncMessage(aiSyncInfo); + message.Broadcast(); + } + + private void _ApplyAISyncInfo(AISyncInfo aiSyncInfo) + { + if (!aiBrain) return; + aiBrain.behaviour.health.cur_hp = aiSyncInfo.health.cur_hp; + aiBrain.behaviour.health.cur_arm_lf = aiSyncInfo.health.cur_arm_lf; + aiBrain.behaviour.health.cur_arm_rt = aiSyncInfo.health.cur_arm_rt; + aiBrain.behaviour.health.cur_leg_lf = aiSyncInfo.health.cur_leg_lf; + aiBrain.behaviour.health.cur_leg_rt = aiSyncInfo.health.cur_leg_rt; + + if (aiSyncInfo.health.cur_hp <= 0 && !aiBrain.puppetMaster.isDead) + { + aiBrain.puppetMaster.Kill(); + } + else if (aiSyncInfo.health.cur_hp > 0 && aiBrain.puppetMaster.isDead) + { + aiBrain.puppetMaster.Resurrect(); + } + + aiBrain.puppetMaster.activeState = aiSyncInfo.puppetState; + aiBrain.puppetMaster.activeMode = aiSyncInfo.puppetMode; + aiBrain.behaviour.mentalState = aiSyncInfo.mentalState; + } + public void OnAISyncData(AISyncInfo aiSyncInfo) + { + _aiSyncInfo = aiSyncInfo; + _ApplyAISyncInfo(_aiSyncInfo); + } } } diff --git a/BoneSync/Sync/Components/SyncableBase.cs b/BoneSync/Sync/Components/SyncableBase.cs index 43bc62c..c178182 100644 --- a/BoneSync/Sync/Components/SyncableBase.cs +++ b/BoneSync/Sync/Components/SyncableBase.cs @@ -79,7 +79,7 @@ namespace BoneSync.Sync.Components private bool _attemptedRegister; public bool Registered => _syncId != 0; - public bool isStale => Time.time - _lastSyncTime > 5f; + public bool isStale => Time.realtimeSinceStartup - _lastSyncTime > 5f; public bool isOwner => _ownerId == BoneSync.lobby.GetLocalId(); public void SetInHolster(bool val) @@ -119,7 +119,6 @@ namespace BoneSync.Sync.Components private Socket[] sockets; private AIBrain aiBrain; - private PuppetMaster puppetMaster; private PullDevice pullDevice; private ButtonToggle[] buttonToggles; @@ -167,6 +166,7 @@ namespace BoneSync.Sync.Components public string GetSyncableWorldPath() { + if (transform == null) return ""; if (poolee && poolee.pool) { return ""; @@ -195,7 +195,6 @@ namespace BoneSync.Sync.Components sockets = GetComponentsInChildren(); aiBrain = GetComponent(); buttonToggles = GetComponentsInChildren(); - puppetMaster = aiBrain?.puppetMaster; if (sockets.Length == 0) { plugs = GetComponentsInChildren(); @@ -342,7 +341,7 @@ namespace BoneSync.Sync.Components public void RegisterSyncable() { - if (!BoneSync.lobby.IsConnected()) return; + if (!BoneSync.IsConnected) return; FindAndUpdateComponents(); if (Registered) { diff --git a/BoneSync/Sync/Components/SyncableDamage.cs b/BoneSync/Sync/Components/SyncableDamage.cs index ccdd709..01d543e 100644 --- a/BoneSync/Sync/Components/SyncableDamage.cs +++ b/BoneSync/Sync/Components/SyncableDamage.cs @@ -23,7 +23,7 @@ namespace BoneSync.Sync.Components originalLootTableData = objectDestructable.lootTable; } - if (!BoneSync.lobby.IsConnected() || BoneSync.lobby.IsHost) + if (!BoneSync.IsConnected || BoneSync.lobby.IsHost) { objectDestructable.lootTable = originalLootTableData; } diff --git a/BoneSync/Sync/Components/SyncableNetworking.cs b/BoneSync/Sync/Components/SyncableNetworking.cs index e83693c..0da83a3 100644 --- a/BoneSync/Sync/Components/SyncableNetworking.cs +++ b/BoneSync/Sync/Components/SyncableNetworking.cs @@ -16,7 +16,7 @@ namespace BoneSync.Sync.Components { private void SendObjectSync() { - _lastSyncTime = Time.time; + _lastSyncTime = Time.realtimeSinceStartup; ObjectSync.SendObjectSyncMessage(this); } public IEnumerator SyncCoroutineAsync()