From 43f671069799bc9ce0700ab22d8dfe8dc9c76e68 Mon Sep 17 00:00:00 2001 From: Aaro Varis Date: Thu, 27 Feb 2025 16:26:04 +0200 Subject: [PATCH] progress --- BoneSync/BoneSync.csproj | 17 +- BoneSync/MelonLoaderMod.cs | 22 ++- BoneSync/Networking/ByteEncoder.cs | 59 ++++++- .../Networking/LobbyManager/LobbyManager.cs | 9 +- .../LobbyManager/SteamLobbyManager.cs | 96 ++++++++--- .../Networking/Messages/LobbyInfoMessage.cs | 3 +- .../Networking/Messages/ObjectSyncMessage.cs | 59 +++++++ .../Networking/Messages/PlayerSyncMessage.cs | 47 +++++ .../Messages/RegisterSyncableMessage.cs | 38 ++++ .../{Messages => }/NetworkMessage.cs | 16 +- BoneSync/Networking/PacketTypes.cs | 2 +- BoneSync/Networking/Structs.cs | 32 ++++ .../Networking/Transport/SteamTransport.cs | 2 +- .../Networking/Transport/TransportBase.cs | 1 + BoneSync/Patching/InteractableHostPatches.cs | 41 +++++ BoneSync/Patching/PoolPatches.cs | 10 +- BoneSync/{PlayerRigs => Player}/PlayerRig.cs | 14 +- BoneSync/Sync/Components/Syncable.cs | 162 ++++++++++++++++++ BoneSync/Sync/ObjectSync.cs | 51 ++++++ BoneSync/Sync/PlayerSync.cs | 61 +++++++ BoneSync/Sync/SceneSync.cs | 46 +++++ 21 files changed, 742 insertions(+), 46 deletions(-) create mode 100644 BoneSync/Networking/Messages/ObjectSyncMessage.cs create mode 100644 BoneSync/Networking/Messages/PlayerSyncMessage.cs create mode 100644 BoneSync/Networking/Messages/RegisterSyncableMessage.cs rename BoneSync/Networking/{Messages => }/NetworkMessage.cs (91%) create mode 100644 BoneSync/Networking/Structs.cs create mode 100644 BoneSync/Patching/InteractableHostPatches.cs rename BoneSync/{PlayerRigs => Player}/PlayerRig.cs (90%) create mode 100644 BoneSync/Sync/Components/Syncable.cs create mode 100644 BoneSync/Sync/ObjectSync.cs create mode 100644 BoneSync/Sync/PlayerSync.cs create mode 100644 BoneSync/Sync/SceneSync.cs diff --git a/BoneSync/BoneSync.csproj b/BoneSync/BoneSync.csproj index 73cabc7..01c145f 100644 --- a/BoneSync/BoneSync.csproj +++ b/BoneSync/BoneSync.csproj @@ -95,6 +95,10 @@ ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\BONEWORKS\BONEWORKS\MelonLoader\Managed\UnityEngine.CoreModule.dll + + False + ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\BONEWORKS\BONEWORKS\MelonLoader\Managed\UnityEngine.PhysicsModule.dll + ..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll @@ -109,6 +113,12 @@ + + + + + + @@ -258,15 +268,18 @@ - + + + - + + diff --git a/BoneSync/MelonLoaderMod.cs b/BoneSync/MelonLoaderMod.cs index dea54f0..7b79639 100644 --- a/BoneSync/MelonLoaderMod.cs +++ b/BoneSync/MelonLoaderMod.cs @@ -4,7 +4,9 @@ using BoneSync.Networking.Transport; using MelonLoader; using HarmonyLib; using UnityEngine; -using BoneSync.PlayerRigs; +using BoneSync.Player; +using BoneSync.Sync; +using Facepunch.Steamworks; namespace BoneSync { @@ -23,6 +25,8 @@ namespace BoneSync public static TransportBase transport; public override void OnApplicationStart() { + SteamClient.Init(823500, true); + PatchAll(); SteamLobbyManager steamLobbyManager = new SteamLobbyManager(); @@ -30,6 +34,7 @@ namespace BoneSync lobby = steamLobbyManager; transport = new SteamTransport(); + SceneSync.Initialize(); } public static void PatchAll() @@ -55,6 +60,7 @@ namespace BoneSync public override void OnUpdate() { + transport.Tick(); PlayerRig.Tick(); @@ -72,6 +78,20 @@ namespace BoneSync MelonLogger.Msg("Player rig instantiated"); } } + if (Input.GetKeyDown(KeyCode.I)) + { + lobby.CreateLobby(); + } + } + + public override void OnLevelWasInitialized(int level) + { + SceneSync.OnSceneInit(level); + } + + public override void BONEWORKS_OnLoadingScreen() + { + base.BONEWORKS_OnLoadingScreen(); } public override void OnFixedUpdate() diff --git a/BoneSync/Networking/ByteEncoder.cs b/BoneSync/Networking/ByteEncoder.cs index 225a5e1..6021e0f 100644 --- a/BoneSync/Networking/ByteEncoder.cs +++ b/BoneSync/Networking/ByteEncoder.cs @@ -1,4 +1,5 @@ -using System; +using StressLevelZero; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -77,6 +78,14 @@ namespace BoneSync.Networking return BitConverter.ToSingle(ReadBytes(sizeof(float)), 0); } + public void WriteUShort(ushort value) + { + WriteBytes(BitConverter.GetBytes(value)); + } + public ushort ReadUShort() { + return BitConverter.ToUInt16(ReadBytes(sizeof(ushort)), 0); + } + public void WriteDouble(double value) { WriteBytes(BitConverter.GetBytes(value)); @@ -105,9 +114,55 @@ namespace BoneSync.Networking WriteBytes(BitConverter.GetBytes(value)); } - public ulong ReadUlong() { + public ulong ReadUlong() + { return BitConverter.ToUInt64(ReadBytes(sizeof(ulong)), 0); } + public void WriteVector3(UnityEngine.Vector3 value) + { + WriteFloat(value.x); + WriteFloat(value.y); + WriteFloat(value.z); + } + + public UnityEngine.Vector3 ReadVector3() + { + float x = ReadFloat(); + float y = ReadFloat(); + float z = ReadFloat(); + return new UnityEngine.Vector3(x, y, z); + } + + public void WriteQuaternion(UnityEngine.Quaternion value) + { + WriteVector3(value.eulerAngles); + } + + public UnityEngine.Quaternion ReadQuaternion() + { + UnityEngine.Vector3 eulerAngles = ReadVector3(); + return UnityEngine.Quaternion.Euler(eulerAngles); + } + + public void WriteSimpleTransform(SimpleTransform value) + { + WriteVector3(value.position); + WriteQuaternion(value.rotation); + WriteVector3(value.scale); + } + + public SimpleTransform ReadSimpleTransform() + { + UnityEngine.Vector3 position = ReadVector3(); + UnityEngine.Quaternion rotation = ReadQuaternion(); + UnityEngine.Vector3 scale = ReadVector3(); + return new SimpleTransform() + { + position = position, + rotation = rotation, + scale = scale + }; + } } } diff --git a/BoneSync/Networking/LobbyManager/LobbyManager.cs b/BoneSync/Networking/LobbyManager/LobbyManager.cs index d1eb813..88eeee3 100644 --- a/BoneSync/Networking/LobbyManager/LobbyManager.cs +++ b/BoneSync/Networking/LobbyManager/LobbyManager.cs @@ -13,10 +13,9 @@ namespace BoneSync.Networking.LobbyManager public abstract ulong GetHostId(); public abstract ulong GetLocalId(); - public virtual void Initialize() - { - - } - + public abstract void CreateLobby(); + public abstract void JoinLobby(ulong lobbyId); + public abstract void LeaveLobby(); + } } diff --git a/BoneSync/Networking/LobbyManager/SteamLobbyManager.cs b/BoneSync/Networking/LobbyManager/SteamLobbyManager.cs index 5afd397..38ce6bb 100644 --- a/BoneSync/Networking/LobbyManager/SteamLobbyManager.cs +++ b/BoneSync/Networking/LobbyManager/SteamLobbyManager.cs @@ -1,5 +1,7 @@ -using Facepunch.Steamworks; +using BoneSync.Sync; +using Facepunch.Steamworks; using Facepunch.Steamworks.Data; +using MelonLoader; using System; using System.Collections.Generic; using System.Linq; @@ -10,6 +12,39 @@ namespace BoneSync.Networking.LobbyManager { internal class SteamLobbyManager : LobbyManager { + public SteamLobbyManager() + { + SteamMatchmaking.OnLobbyCreated += (Result result, Lobby lobby) => + { + _lobbyInstance = lobby; + MelonLogger.Msg("Created lobby " + lobby.Id); + UpdateLobbyData(); + }; + SteamMatchmaking.OnLobbyEntered += (Lobby lobby) => + { + _lobbyInstance = lobby; + MelonLogger.Msg("Entered lobby " + lobby.Id); + UpdateLobbyData(); + }; + SteamMatchmaking.OnLobbyMemberLeave += (Lobby lobby, Friend friend) => + { + if (friend.Id == SteamClient.SteamId) + { + MelonLogger.Msg("Left lobby " + lobby.Id); + _lobbyInstance = new Lobby(); + } + MelonLogger.Msg("Member left " + friend.Id); + UpdateLobbyData(); + }; + SteamMatchmaking.OnLobbyMemberJoined += (Lobby lobby, Friend friend) => + { + MelonLogger.Msg("Member joined " + friend.Id); + UpdateLobbyData(); + }; + MelonLogger.Msg("SteamLobbyManager initialized"); + } + + private Lobby _lobbyInstance; public Friend[] LobbyMembers { @@ -31,32 +66,45 @@ namespace BoneSync.Networking.LobbyManager { LobbyMembers = _lobbyInstance.Members.ToArray(); steamIds = LobbyMembers.Select(x => x.Id).ToArray(); + + if (_lobbyInstance.Id.IsValid) + { + SteamFriends.SetRichPresence("steam_display", "BoneSync - " + SceneSync.CurrentSceneDisplayName); + SteamFriends.SetRichPresence("steam_player_group", _lobbyInstance.Id.Value.ToString()); + SteamFriends.SetRichPresence("steam_player_group_size", LobbyMembers.Length.ToString()); + SteamFriends.SetRichPresence("connect", "lobby:" + _lobbyInstance.Id.Value); + SteamFriends.SetRichPresence("status", "In a lobby"); + } + else + { + SteamFriends.SetRichPresence("steam_display", "BoneSync - SinglePlayer"); + SteamFriends.SetRichPresence("steam_player_group", null); + SteamFriends.SetRichPresence("steam_player_group_size", null); + SteamFriends.SetRichPresence("connect", null); + SteamFriends.SetRichPresence("status", "Not in a multiplayer lobby"); + } + } - public override void Initialize() + + public override void CreateLobby() { - SteamMatchmaking.OnLobbyCreated += (Result result, Lobby lobby) => - { - _lobbyInstance = lobby; - UpdateLobbyData(); - }; - SteamMatchmaking.OnLobbyEntered += (Lobby lobby) => - { - _lobbyInstance = lobby; - UpdateLobbyData(); - }; - SteamMatchmaking.OnLobbyMemberLeave += (Lobby lobby, Friend friend) => - { - if (friend.Id == SteamClient.SteamId) - { - _lobbyInstance = new Lobby(); - } - UpdateLobbyData(); - }; - SteamMatchmaking.OnLobbyMemberJoined += (Lobby lobby, Friend friend) => - { - UpdateLobbyData(); - }; + MelonLogger.Msg("Trying to create lobby"); + _ = SteamMatchmaking.CreateLobbyAsync(16); + } + public override void JoinLobby(ulong lobbyId) + { + MelonLogger.Msg("Trying to join lobby " + lobbyId); + _ = SteamMatchmaking.JoinLobbyAsync(lobbyId); + } + + public override void LeaveLobby() + { + _lobbyInstance.Leave(); + BoneSync.transport.CleanUp(); + } + + } } diff --git a/BoneSync/Networking/Messages/LobbyInfoMessage.cs b/BoneSync/Networking/Messages/LobbyInfoMessage.cs index ea6d841..2b57acc 100644 --- a/BoneSync/Networking/Messages/LobbyInfoMessage.cs +++ b/BoneSync/Networking/Messages/LobbyInfoMessage.cs @@ -28,8 +28,7 @@ namespace BoneSync.Networking.Messages public LobbyInfoMessage(Packet packet) { - byteEncoder = new ByteEncoder(packet.Data); - + byteEncoder.WriteBytes(packet.Data); LobbyName = byteEncoder.ReadString(); HostName = byteEncoder.ReadString(); MaxPlayers = byteEncoder.ReadInt(); diff --git a/BoneSync/Networking/Messages/ObjectSyncMessage.cs b/BoneSync/Networking/Messages/ObjectSyncMessage.cs new file mode 100644 index 0000000..4b0db66 --- /dev/null +++ b/BoneSync/Networking/Messages/ObjectSyncMessage.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace BoneSync.Networking.Messages +{ + + public struct ObjectSyncTransform + { + public SimpleTransform transform; + public Vector3 velocity; + } + public struct ObjectSyncMessageData + { + public ulong objectId; + public ObjectSyncTransform[] objectSyncTransforms; + } + internal class ObjectSyncMessage : NetworkMessage + { + private ObjectSyncMessageData _objectSyncMessageData = new ObjectSyncMessageData(); + public ObjectSyncMessageData objectSyncMessageData => _objectSyncMessageData; + + public ObjectSyncMessage(ObjectSyncMessageData objectSyncMessageData) + { + _objectSyncMessageData = objectSyncMessageData; + byteEncoder.WriteUlong(_objectSyncMessageData.objectId); + byte length = (byte)_objectSyncMessageData.objectSyncTransforms.Length; + byteEncoder.WriteByte(length); + for (int i = 0; i < length; i++) + { + byteEncoder.WriteSimpleTransform(_objectSyncMessageData.objectSyncTransforms[i].transform); + byteEncoder.WriteVector3(_objectSyncMessageData.objectSyncTransforms[i].velocity); + } + } + + public ObjectSyncMessage(Packet packet) + { + byteEncoder.WriteBytes(packet.Data); + _objectSyncMessageData.objectId = byteEncoder.ReadUlong(); + byte length = byteEncoder.ReadByte(); + _objectSyncMessageData.objectSyncTransforms = new ObjectSyncTransform[length]; + for (int i = 0; i < length; i++) + { + _objectSyncMessageData.objectSyncTransforms[i].transform = byteEncoder.ReadSimpleTransform(); + _objectSyncMessageData.objectSyncTransforms[i].velocity = byteEncoder.ReadVector3(); + } + } + + + + public override void Execute() + { + throw new NotImplementedException(); + } + } +} diff --git a/BoneSync/Networking/Messages/PlayerSyncMessage.cs b/BoneSync/Networking/Messages/PlayerSyncMessage.cs new file mode 100644 index 0000000..0cf2ae3 --- /dev/null +++ b/BoneSync/Networking/Messages/PlayerSyncMessage.cs @@ -0,0 +1,47 @@ + + +using BoneSync.Sync; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BoneSync.Networking.Messages +{ + + public struct PlayerSyncInfo + { + public SimpleTransform headPos; + public SimpleTransform leftHandPos; + public SimpleTransform rightHandPos; + } + + [PacketType(PacketType.PlayerSync)] + internal class PlayerSyncMessage : NetworkMessage + { + private PlayerSyncInfo _playerSyncInfo; + public PlayerSyncInfo playerSyncInfo => _playerSyncInfo; + + public PlayerSyncMessage(PlayerSyncInfo playerSyncInfo) + { + _playerSyncInfo = playerSyncInfo; + byteEncoder.WriteSimpleTransform(_playerSyncInfo.headPos); + byteEncoder.WriteSimpleTransform(_playerSyncInfo.leftHandPos); + byteEncoder.WriteSimpleTransform(_playerSyncInfo.rightHandPos); + } + + public PlayerSyncMessage(Packet packet) + { + byteEncoder.WriteBytes(packet.Data); + _playerSyncInfo.headPos = byteEncoder.ReadSimpleTransform(); + _playerSyncInfo.leftHandPos = byteEncoder.ReadSimpleTransform(); + _playerSyncInfo.rightHandPos = byteEncoder.ReadSimpleTransform(); + } + + public override void Execute() + { + PlayerSync.OnPlayerSync(this); + } + } +} diff --git a/BoneSync/Networking/Messages/RegisterSyncableMessage.cs b/BoneSync/Networking/Messages/RegisterSyncableMessage.cs new file mode 100644 index 0000000..6b94170 --- /dev/null +++ b/BoneSync/Networking/Messages/RegisterSyncableMessage.cs @@ -0,0 +1,38 @@ +using BoneSync.Sync; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BoneSync.Networking.Messages +{ + public struct RegisterSyncableInfo + { + public string transformPath; + public ushort id; + } + internal class RegisterSyncableMessage : NetworkMessage + { + private RegisterSyncableInfo _info; + public RegisterSyncableMessage(RegisterSyncableInfo info) + { + _info = info; + byteEncoder.WriteString(_info.transformPath); + byteEncoder.WriteUShort(_info.id); + + } + + public RegisterSyncableMessage(Packet packet) + { + byteEncoder.WriteBytes(packet.Data); + _info.transformPath = byteEncoder.ReadString(); + _info.id = byteEncoder.ReadUShort(); + } + + public override void Execute() + { + + } + } +} diff --git a/BoneSync/Networking/Messages/NetworkMessage.cs b/BoneSync/Networking/NetworkMessage.cs similarity index 91% rename from BoneSync/Networking/Messages/NetworkMessage.cs rename to BoneSync/Networking/NetworkMessage.cs index b426714..92d69f9 100644 --- a/BoneSync/Networking/Messages/NetworkMessage.cs +++ b/BoneSync/Networking/NetworkMessage.cs @@ -1,4 +1,5 @@ using BoneSync.Networking.Transport; +using MelonLoader; using System; using System.Collections.Generic; using System.Diagnostics; @@ -8,7 +9,7 @@ using System.Text; using System.Threading.Tasks; using Xunit; -namespace BoneSync.Networking.Messages +namespace BoneSync.Networking { public class PacketTypeAttribute : Attribute { @@ -22,6 +23,11 @@ namespace BoneSync.Networking.Messages public abstract class NetworkMessage { + public ulong senderId + { + private set; + get; + } private static bool PacketTypesRegistered => PacketTypeMap.Count > 0; internal static Dictionary PacketTypeMap = new Dictionary(); @@ -29,7 +35,6 @@ namespace BoneSync.Networking.Messages internal PacketType _packetType; internal ByteEncoder byteEncoder = new ByteEncoder(); - public byte[] GetBytes() => byteEncoder.ToArray(); public PacketType GetPacketType() @@ -74,10 +79,12 @@ namespace BoneSync.Networking.Messages { throw new Exception("No class found for packet type '" + packet.Info.packetType+"'"); } + Type type = PacketTypeMap[packet.Info.packetType]; // get the constructor that takes a Packet ConstructorInfo constructor = type.GetConstructor(new Type[] { typeof(Packet) }) ?? throw new Exception("No constructor found for type " + type.Name); NetworkMessage networkMessage = (NetworkMessage)constructor.Invoke(new object[] { packet }); + networkMessage.senderId = packet.Info.senderId; return networkMessage; } @@ -101,7 +108,10 @@ namespace BoneSync.Networking.Messages BoneSync.transport.Send(packet); } - public abstract void Execute(); + public virtual void Execute() + { + MelonLogger.Warning("Execute not implemented for " + GetType().Name); + } } public class NetworkMessageTests diff --git a/BoneSync/Networking/PacketTypes.cs b/BoneSync/Networking/PacketTypes.cs index 05e3cbc..48704bb 100644 --- a/BoneSync/Networking/PacketTypes.cs +++ b/BoneSync/Networking/PacketTypes.cs @@ -10,6 +10,6 @@ namespace BoneSync.Networking { Unknown = 0, LobbyInfo = 1, - CharacterInfo = 2, + PlayerSync = 2, } } diff --git a/BoneSync/Networking/Structs.cs b/BoneSync/Networking/Structs.cs new file mode 100644 index 0000000..4b85b73 --- /dev/null +++ b/BoneSync/Networking/Structs.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace BoneSync.Networking +{ + + public static class SimpleTransformExtensions + { + public static void ApplySimpleTransform(this UnityEngine.Transform transform, SimpleTransform simpleTransform) + { + transform.position = simpleTransform.position; + transform.rotation = simpleTransform.rotation; + transform.localScale = simpleTransform.scale; + } + } + public struct SimpleTransform + { + public Vector3 position; + public Quaternion rotation; + public Vector3 scale; + public SimpleTransform(UnityEngine.Transform transform) + { + position = transform.position; + rotation = transform.rotation; + scale = transform.localScale; + } + } +} diff --git a/BoneSync/Networking/Transport/SteamTransport.cs b/BoneSync/Networking/Transport/SteamTransport.cs index 4f12f75..f6edbfe 100644 --- a/BoneSync/Networking/Transport/SteamTransport.cs +++ b/BoneSync/Networking/Transport/SteamTransport.cs @@ -34,7 +34,7 @@ namespace BoneSync.Networking.Transport } - private void CleanUp() + public override void CleanUp() { ulong[] peers = BoneSync.lobby.GetPeers(); for (int i = 0; i < OpenP2PConnections.Count; i++) diff --git a/BoneSync/Networking/Transport/TransportBase.cs b/BoneSync/Networking/Transport/TransportBase.cs index e6bedde..af0517b 100644 --- a/BoneSync/Networking/Transport/TransportBase.cs +++ b/BoneSync/Networking/Transport/TransportBase.cs @@ -11,5 +11,6 @@ namespace BoneSync.Networking.Transport public const int BORADCAST_ID = 0; public abstract void Send(Packet packet); public abstract bool Tick(); + public abstract void CleanUp(); } } diff --git a/BoneSync/Patching/InteractableHostPatches.cs b/BoneSync/Patching/InteractableHostPatches.cs new file mode 100644 index 0000000..8d99cd4 --- /dev/null +++ b/BoneSync/Patching/InteractableHostPatches.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using BoneSync.Sync; +using BoneSync.Sync.Components; +using HarmonyLib; +using StressLevelZero.Interaction; +using UnityEngine; + +namespace BoneSync.Patching +{ + [HarmonyPatch(typeof(InteractableHost))] + public class InteractableHostPatches + { + [HarmonyPatch(nameof(InteractableHost.OnEnable)), HarmonyPostfix] + public static void OnEnablePatch(InteractableHost __instance) + { + //MelonLoader.MelonLogger.Msg("InteractableHost enabled: " + __instance.name + " Manager: " + __instance?.manager?.name); + ObjectSync.MakeOrGetSyncable(__instance); + } + + [HarmonyPatch(nameof(InteractableHost.OnDestroy)), HarmonyPostfix] + public static void OnDestroyPatch(InteractableHost __instance) + { + MelonLoader.MelonLogger.Msg("InteractableHost destroyed: " + __instance.name); + } + } + + [HarmonyPatch(typeof(InteractableHostManager))] + public class InteractableHostManagerPatches + { + [HarmonyPatch(nameof(InteractableHostManager.Start)), HarmonyPostfix] + public static void OnEnablePatch(InteractableHostManager __instance) + { + MelonLoader.MelonLogger.Msg("InteractableHostManager started: " + __instance.transform.GetPath()); + ObjectSync.MakeOrGetSyncable(__instance); + } + } +} diff --git a/BoneSync/Patching/PoolPatches.cs b/BoneSync/Patching/PoolPatches.cs index eb9c285..0d6d2f3 100644 --- a/BoneSync/Patching/PoolPatches.cs +++ b/BoneSync/Patching/PoolPatches.cs @@ -11,6 +11,7 @@ using UnityEngine; namespace BoneSync.Patching { + /* [HarmonyPatch(typeof(Pool))] internal class PoolPatches { @@ -28,8 +29,13 @@ namespace BoneSync.Patching { MelonLogger.Msg("Flagged object for respawn: " + p.name); } + [HarmonyPatch(nameof(Pool.InstantiatePoolee))] + [HarmonyPostfix] + private static void InstantiatePooleePatch(Pool __instance, ref Poolee __result) + { + MelonLogger.Msg("Instantiated object: " + __result.name); + } - - } + }*/ } diff --git a/BoneSync/PlayerRigs/PlayerRig.cs b/BoneSync/Player/PlayerRig.cs similarity index 90% rename from BoneSync/PlayerRigs/PlayerRig.cs rename to BoneSync/Player/PlayerRig.cs index 2cc480a..cc54b6f 100644 --- a/BoneSync/PlayerRigs/PlayerRig.cs +++ b/BoneSync/Player/PlayerRig.cs @@ -9,13 +9,16 @@ using StressLevelZero; using StressLevelZero.Rig; using StressLevelZero.Player; using StressLevelZero.VRMK; +using BoneSync.Networking; +using BoneSync.Networking.Messages; -namespace BoneSync.PlayerRigs +namespace BoneSync.Player { internal class PlayerRig { - private const string RIGMANAGER_SCENE_NAME = "[RigManager (Default Brett)]"; + public const string RIGMANAGER_SCENE_NAME = "[RigManager (Default Brett)]"; + private static GameObject _rigPrefabCache = null; private static List _playerRigs = new List(); @@ -27,7 +30,10 @@ namespace BoneSync.PlayerRigs - + public void UpdatePlayerSync(PlayerSyncInfo playerSyncInfo) + { + playerRig.transform.ApplySimpleTransform(playerSyncInfo.headPos); + } public static void Tick() { @@ -47,6 +53,7 @@ namespace BoneSync.PlayerRigs } public static void TryRegisterRigPrefab() { + return; // disable this for now if (_rigPrefabCache) return; GetPlayerRigPrefab(); } @@ -93,6 +100,7 @@ namespace BoneSync.PlayerRigs return playerRig; } + private void UpdateRig() { Vector3 velocity = Vector3.zero; diff --git a/BoneSync/Sync/Components/Syncable.cs b/BoneSync/Sync/Components/Syncable.cs new file mode 100644 index 0000000..fe8575c --- /dev/null +++ b/BoneSync/Sync/Components/Syncable.cs @@ -0,0 +1,162 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; +using MelonLoader; +using StressLevelZero.Interaction; +using StressLevelZero.Pool; +using UnityEngine.Experimental.PlayerLoop; +using BoneSync.Networking.Messages; +using BoneSync.Networking; +using StressLevelZero.Data; + + +namespace BoneSync.Sync.Components +{ + + public static class TransformExtensions + { + public static string GetPath(this Transform current) + { + if (current.parent == null) + return "/" + current.name; + return current.parent.GetPath() + "/" + current.name; + } + + public static Transform FromPath(string path) + { + Transform current = null; + foreach (string name in path.Split('/')) + { + if (current == null) + { + current = GameObject.Find(name).transform; + } + else + { + current = current.Find(name); + } + } + return current; + } + } + + [RegisterTypeInIl2Cpp] + public class Syncable : MonoBehaviour + { + + public Syncable(IntPtr intPtr) : base(intPtr) { } + + private ushort _syncId; + public bool Registered => _syncId != 0; + + private ulong _lastSyncTime; + private ulong _ownerId; + + public bool isStale => Time.time - _lastSyncTime > 5f; + + public InteractableHost interactableHost; + public InteractableHostManager interactableManager; + public Poolee poolee; + + private Transform[] transforms; + public void OnEnable() + { + FindComponents(); + MelonLogger.Msg("Syncable enabled: " + transform.GetPath()); + } + + private void UpdateTransformList() + { + if (interactableManager) + { + transforms = interactableManager.hosts.Select(host => host.transform).ToArray(); + } + else if (interactableHost) + { + transforms = new Transform[] { interactableHost.transform }; + } + else if (poolee) + { + transforms = new Transform[] { poolee.transform }; + } + } + + public string GetSyncableWorldPath() + { + if (poolee && poolee.pool) + { + return null; + } + if (interactableHost) + { + // get full path from root + return interactableHost.transform.GetPath(); + } + return null; + } + + public void FindComponents() + { + interactableManager = GetComponent(); + interactableHost = GetComponent(); + poolee = GetComponent(); + UpdateTransformList(); + } + + public bool ShouldSync() + { + FindComponents(); + if (interactableManager && interactableManager.hosts.Count > 0) + { + return true; + } + if (interactableHost && interactableHost.hasRigidbody) + { + return true; + } + + return false; + } + + public void DiscardSyncable() + { + Destroy(this); + } + + public void OnDisable() + { + DiscardSyncable(); + } + + public ObjectSyncMessageData GetObjectSyncData() + { + ObjectSyncMessageData data = new ObjectSyncMessageData() + { + objectId = _syncId, + objectSyncTransforms = new ObjectSyncTransform[transforms.Length], + }; + + for (int i = 0; i < transforms.Length; i++) + { + data.objectSyncTransforms[i] = new ObjectSyncTransform() + { + transform = new SimpleTransform(transforms[i]), + velocity = Vector3.zero + }; + } + return data; + } + + public void RegisterSyncable() + { + if (Registered) return; + if (!ShouldSync()) return; + MelonLogger.Msg("Registering syncable object: " + gameObject.name); + ObjectSync.RegisterSyncable(this); + } + + } +} diff --git a/BoneSync/Sync/ObjectSync.cs b/BoneSync/Sync/ObjectSync.cs new file mode 100644 index 0000000..45689fa --- /dev/null +++ b/BoneSync/Sync/ObjectSync.cs @@ -0,0 +1,51 @@ +using BoneSync.Sync.Components; +using StressLevelZero.Interaction; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace BoneSync.Sync +{ + internal class ObjectSync + { + + public static void RegisterSyncable(Syncable syncable) + { + + } + private static Syncable _MakeOrGetSyncable(GameObject gameObject, bool deleteSubSyncabled = true) + { + Syncable[] subSyncables = gameObject.GetComponentsInChildren(); + Syncable syncable = gameObject.GetComponent(); + + // delete all sub syncables + for (int i = 0; i < subSyncables.Length; i++) + { + if (subSyncables[i] != syncable) + { + subSyncables[i].DiscardSyncable(); + } + } + + if (syncable == null) + { + syncable = gameObject.AddComponent(); + } + return syncable; + } + + public static Syncable MakeOrGetSyncable(InteractableHost interactableHost) + { + if (interactableHost.manager) return MakeOrGetSyncable(interactableHost.manager); + return _MakeOrGetSyncable(interactableHost.gameObject); + } + + public static Syncable MakeOrGetSyncable(InteractableHostManager interactableHostManager) + { + return _MakeOrGetSyncable(interactableHostManager.gameObject); + } + } +} diff --git a/BoneSync/Sync/PlayerSync.cs b/BoneSync/Sync/PlayerSync.cs new file mode 100644 index 0000000..2af3204 --- /dev/null +++ b/BoneSync/Sync/PlayerSync.cs @@ -0,0 +1,61 @@ +using BoneSync.Networking; +using BoneSync.Networking.Messages; +using BoneSync.Player; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace BoneSync.Sync +{ + internal static class PlayerSync + { + + private static GameObject _localPlayerRig; + + private static Dictionary _playerRigMap = new Dictionary(); + private static PlayerRig GetPlayerRig(ulong playerId) + { + if (!_playerRigMap.ContainsKey(playerId)) + { + PlayerRig playerRig = PlayerRig.InstantiatePlayerRigPrefab(); + _playerRigMap.Add(playerId, playerRig); + } + + return _playerRigMap[playerId]; + } + + public static void CleanUp() + { + foreach (PlayerRig playerRig in _playerRigMap.Values) + { + playerRig.Destroy(); + } + _playerRigMap.Clear(); + } + + public static void SyncPlayer() + { + if (!_localPlayerRig) + { + _localPlayerRig = GameObject.Find(PlayerRig.RIGMANAGER_SCENE_NAME); + } + PlayerSyncInfo playerSyncInfo = new PlayerSyncInfo(); + playerSyncInfo.headPos = new SimpleTransform(_localPlayerRig.transform); + playerSyncInfo.leftHandPos = new SimpleTransform(); + playerSyncInfo.rightHandPos = new SimpleTransform(); + + PlayerSyncMessage playerSyncMessage = new PlayerSyncMessage(playerSyncInfo); + playerSyncMessage.Broadcast(); + } + + public static void OnPlayerSync(PlayerSyncMessage playerSyncMessage) + { + PlayerRig playerRig = GetPlayerRig(playerSyncMessage.senderId); + playerRig.UpdatePlayerSync(playerSyncMessage.playerSyncInfo); + + } + } +} diff --git a/BoneSync/Sync/SceneSync.cs b/BoneSync/Sync/SceneSync.cs new file mode 100644 index 0000000..4590b8c --- /dev/null +++ b/BoneSync/Sync/SceneSync.cs @@ -0,0 +1,46 @@ +using MelonLoader; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine.SceneManagement; + +namespace BoneSync.Sync +{ + internal class SceneSync + { + private static List scenes = new List(); + private static string _currentSceneName; + + public static string CurrentSceneDisplayName + { + get + { + // remove scene_ from the name if it exists + string sceneName = _currentSceneName; + if (sceneName.Contains("scene_")) + { + sceneName = sceneName.Substring(6); + } + sceneName = char.ToUpper(sceneName[0]) + sceneName.Substring(1); + + return sceneName; + } + } + public static void OnSceneInit(int buildIndex) + { + string SceneName = SceneManager.GetSceneByBuildIndex(buildIndex).name; + _currentSceneName = SceneName; + MelonLogger.Msg("Scene initialized: " + SceneName); + } + + public static void Initialize() + { + for (int i = 0; i < SceneManager.sceneCountInBuildSettings; i++) + { + scenes.Add(SceneManager.GetSceneByBuildIndex(i)); + } + } + } +}