This commit is contained in:
2025-02-27 16:26:04 +02:00
parent b721e2d25e
commit 43f6710697
21 changed files with 742 additions and 46 deletions

View File

@@ -95,6 +95,10 @@
<Reference Include="UnityEngine.CoreModule"> <Reference Include="UnityEngine.CoreModule">
<HintPath>..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\BONEWORKS\BONEWORKS\MelonLoader\Managed\UnityEngine.CoreModule.dll</HintPath> <HintPath>..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\BONEWORKS\BONEWORKS\MelonLoader\Managed\UnityEngine.CoreModule.dll</HintPath>
</Reference> </Reference>
<Reference Include="UnityEngine.PhysicsModule, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\BONEWORKS\BONEWORKS\MelonLoader\Managed\UnityEngine.PhysicsModule.dll</HintPath>
</Reference>
<Reference Include="xunit.abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL"> <Reference Include="xunit.abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll</HintPath> <HintPath>..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll</HintPath>
</Reference> </Reference>
@@ -109,6 +113,12 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Networking\Messages\ObjectSyncMessage.cs" />
<Compile Include="Networking\Messages\RegisterSyncableMessage.cs" />
<Compile Include="Patching\InteractableHostPatches.cs" />
<Compile Include="Sync\Components\Syncable.cs" />
<Compile Include="Sync\ObjectSync.cs" />
<Compile Include="Sync\PlayerSync.cs" />
<Compile Include="Facepunch.Steamworks\Callbacks\CallResult.cs" /> <Compile Include="Facepunch.Steamworks\Callbacks\CallResult.cs" />
<Compile Include="Facepunch.Steamworks\Callbacks\ICallbackData.cs" /> <Compile Include="Facepunch.Steamworks\Callbacks\ICallbackData.cs" />
<Compile Include="Facepunch.Steamworks\Classes\AuthTicket.cs" /> <Compile Include="Facepunch.Steamworks\Classes\AuthTicket.cs" />
@@ -258,15 +268,18 @@
<Compile Include="Networking\LobbyManager\LobbyManager.cs" /> <Compile Include="Networking\LobbyManager\LobbyManager.cs" />
<Compile Include="Networking\LobbyManager\SteamLobbyManager.cs" /> <Compile Include="Networking\LobbyManager\SteamLobbyManager.cs" />
<Compile Include="Networking\Messages\LobbyInfoMessage.cs" /> <Compile Include="Networking\Messages\LobbyInfoMessage.cs" />
<Compile Include="Networking\Messages\NetworkMessage.cs" /> <Compile Include="Networking\NetworkMessage.cs" />
<Compile Include="Networking\Messages\PlayerSyncMessage.cs" />
<Compile Include="Networking\Packet.cs" /> <Compile Include="Networking\Packet.cs" />
<Compile Include="Networking\PacketTypes.cs" /> <Compile Include="Networking\PacketTypes.cs" />
<Compile Include="Networking\Structs.cs" />
<Compile Include="Networking\Transport\SteamTransport.cs" /> <Compile Include="Networking\Transport\SteamTransport.cs" />
<Compile Include="Networking\Transport\TransportBase.cs" /> <Compile Include="Networking\Transport\TransportBase.cs" />
<Compile Include="Patching\PoolPatches.cs" /> <Compile Include="Patching\PoolPatches.cs" />
<Compile Include="PlayerRigs\PlayerRig.cs" /> <Compile Include="Player\PlayerRig.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Networking\ByteEncoder.cs" /> <Compile Include="Networking\ByteEncoder.cs" />
<Compile Include="Sync\SceneSync.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />

View File

@@ -4,7 +4,9 @@ using BoneSync.Networking.Transport;
using MelonLoader; using MelonLoader;
using HarmonyLib; using HarmonyLib;
using UnityEngine; using UnityEngine;
using BoneSync.PlayerRigs; using BoneSync.Player;
using BoneSync.Sync;
using Facepunch.Steamworks;
namespace BoneSync namespace BoneSync
{ {
@@ -23,6 +25,8 @@ namespace BoneSync
public static TransportBase transport; public static TransportBase transport;
public override void OnApplicationStart() public override void OnApplicationStart()
{ {
SteamClient.Init(823500, true);
PatchAll(); PatchAll();
SteamLobbyManager steamLobbyManager = new SteamLobbyManager(); SteamLobbyManager steamLobbyManager = new SteamLobbyManager();
@@ -30,6 +34,7 @@ namespace BoneSync
lobby = steamLobbyManager; lobby = steamLobbyManager;
transport = new SteamTransport(); transport = new SteamTransport();
SceneSync.Initialize();
} }
public static void PatchAll() public static void PatchAll()
@@ -55,6 +60,7 @@ namespace BoneSync
public override void OnUpdate() public override void OnUpdate()
{ {
transport.Tick(); transport.Tick();
PlayerRig.Tick(); PlayerRig.Tick();
@@ -72,6 +78,20 @@ namespace BoneSync
MelonLogger.Msg("Player rig instantiated"); 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() public override void OnFixedUpdate()

View File

@@ -1,4 +1,5 @@
using System; using StressLevelZero;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@@ -77,6 +78,14 @@ namespace BoneSync.Networking
return BitConverter.ToSingle(ReadBytes(sizeof(float)), 0); 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) public void WriteDouble(double value)
{ {
WriteBytes(BitConverter.GetBytes(value)); WriteBytes(BitConverter.GetBytes(value));
@@ -105,9 +114,55 @@ namespace BoneSync.Networking
WriteBytes(BitConverter.GetBytes(value)); WriteBytes(BitConverter.GetBytes(value));
} }
public ulong ReadUlong() { public ulong ReadUlong()
{
return BitConverter.ToUInt64(ReadBytes(sizeof(ulong)), 0); 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
};
}
} }
} }

View File

@@ -13,10 +13,9 @@ namespace BoneSync.Networking.LobbyManager
public abstract ulong GetHostId(); public abstract ulong GetHostId();
public abstract ulong GetLocalId(); public abstract ulong GetLocalId();
public virtual void Initialize() public abstract void CreateLobby();
{ public abstract void JoinLobby(ulong lobbyId);
public abstract void LeaveLobby();
}
} }
} }

View File

@@ -1,5 +1,7 @@
using Facepunch.Steamworks; using BoneSync.Sync;
using Facepunch.Steamworks;
using Facepunch.Steamworks.Data; using Facepunch.Steamworks.Data;
using MelonLoader;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -10,6 +12,39 @@ namespace BoneSync.Networking.LobbyManager
{ {
internal class SteamLobbyManager : 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; private Lobby _lobbyInstance;
public Friend[] LobbyMembers public Friend[] LobbyMembers
{ {
@@ -31,32 +66,45 @@ namespace BoneSync.Networking.LobbyManager
{ {
LobbyMembers = _lobbyInstance.Members.ToArray(); LobbyMembers = _lobbyInstance.Members.ToArray();
steamIds = LobbyMembers.Select(x => x.Id).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");
} }
public override void Initialize() else
{ {
SteamMatchmaking.OnLobbyCreated += (Result result, Lobby lobby) => SteamFriends.SetRichPresence("steam_display", "BoneSync - SinglePlayer");
{ SteamFriends.SetRichPresence("steam_player_group", null);
_lobbyInstance = lobby; SteamFriends.SetRichPresence("steam_player_group_size", null);
UpdateLobbyData(); SteamFriends.SetRichPresence("connect", null);
}; SteamFriends.SetRichPresence("status", "Not in a multiplayer lobby");
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();
};
} }
} }
public override void CreateLobby()
{
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();
}
}
} }

View File

@@ -28,8 +28,7 @@ namespace BoneSync.Networking.Messages
public LobbyInfoMessage(Packet packet) public LobbyInfoMessage(Packet packet)
{ {
byteEncoder = new ByteEncoder(packet.Data); byteEncoder.WriteBytes(packet.Data);
LobbyName = byteEncoder.ReadString(); LobbyName = byteEncoder.ReadString();
HostName = byteEncoder.ReadString(); HostName = byteEncoder.ReadString();
MaxPlayers = byteEncoder.ReadInt(); MaxPlayers = byteEncoder.ReadInt();

View File

@@ -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();
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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()
{
}
}
}

View File

@@ -1,4 +1,5 @@
using BoneSync.Networking.Transport; using BoneSync.Networking.Transport;
using MelonLoader;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
@@ -8,7 +9,7 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Xunit; using Xunit;
namespace BoneSync.Networking.Messages namespace BoneSync.Networking
{ {
public class PacketTypeAttribute : Attribute public class PacketTypeAttribute : Attribute
{ {
@@ -22,6 +23,11 @@ namespace BoneSync.Networking.Messages
public abstract class NetworkMessage public abstract class NetworkMessage
{ {
public ulong senderId
{
private set;
get;
}
private static bool PacketTypesRegistered => PacketTypeMap.Count > 0; private static bool PacketTypesRegistered => PacketTypeMap.Count > 0;
internal static Dictionary<PacketType, Type> PacketTypeMap = new Dictionary<PacketType, Type>(); internal static Dictionary<PacketType, Type> PacketTypeMap = new Dictionary<PacketType, Type>();
@@ -29,7 +35,6 @@ namespace BoneSync.Networking.Messages
internal PacketType _packetType; internal PacketType _packetType;
internal ByteEncoder byteEncoder = new ByteEncoder(); internal ByteEncoder byteEncoder = new ByteEncoder();
public byte[] GetBytes() => byteEncoder.ToArray(); public byte[] GetBytes() => byteEncoder.ToArray();
public PacketType GetPacketType() public PacketType GetPacketType()
@@ -74,10 +79,12 @@ namespace BoneSync.Networking.Messages
{ {
throw new Exception("No class found for packet type '" + packet.Info.packetType+"'"); throw new Exception("No class found for packet type '" + packet.Info.packetType+"'");
} }
Type type = PacketTypeMap[packet.Info.packetType]; Type type = PacketTypeMap[packet.Info.packetType];
// get the constructor that takes a Packet // 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); 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 networkMessage = (NetworkMessage)constructor.Invoke(new object[] { packet });
networkMessage.senderId = packet.Info.senderId;
return networkMessage; return networkMessage;
} }
@@ -101,7 +108,10 @@ namespace BoneSync.Networking.Messages
BoneSync.transport.Send(packet); BoneSync.transport.Send(packet);
} }
public abstract void Execute(); public virtual void Execute()
{
MelonLogger.Warning("Execute not implemented for " + GetType().Name);
}
} }
public class NetworkMessageTests public class NetworkMessageTests

View File

@@ -10,6 +10,6 @@ namespace BoneSync.Networking
{ {
Unknown = 0, Unknown = 0,
LobbyInfo = 1, LobbyInfo = 1,
CharacterInfo = 2, PlayerSync = 2,
} }
} }

View File

@@ -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;
}
}
}

View File

@@ -34,7 +34,7 @@ namespace BoneSync.Networking.Transport
} }
private void CleanUp() public override void CleanUp()
{ {
ulong[] peers = BoneSync.lobby.GetPeers(); ulong[] peers = BoneSync.lobby.GetPeers();
for (int i = 0; i < OpenP2PConnections.Count; i++) for (int i = 0; i < OpenP2PConnections.Count; i++)

View File

@@ -11,5 +11,6 @@ namespace BoneSync.Networking.Transport
public const int BORADCAST_ID = 0; public const int BORADCAST_ID = 0;
public abstract void Send(Packet packet); public abstract void Send(Packet packet);
public abstract bool Tick(); public abstract bool Tick();
public abstract void CleanUp();
} }
} }

View File

@@ -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);
}
}
}

View File

@@ -11,6 +11,7 @@ using UnityEngine;
namespace BoneSync.Patching namespace BoneSync.Patching
{ {
/*
[HarmonyPatch(typeof(Pool))] [HarmonyPatch(typeof(Pool))]
internal class PoolPatches internal class PoolPatches
{ {
@@ -28,8 +29,13 @@ namespace BoneSync.Patching
{ {
MelonLogger.Msg("Flagged object for respawn: " + p.name); 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);
} }
}*/
} }

View File

@@ -9,13 +9,16 @@ using StressLevelZero;
using StressLevelZero.Rig; using StressLevelZero.Rig;
using StressLevelZero.Player; using StressLevelZero.Player;
using StressLevelZero.VRMK; using StressLevelZero.VRMK;
using BoneSync.Networking;
using BoneSync.Networking.Messages;
namespace BoneSync.PlayerRigs namespace BoneSync.Player
{ {
internal class PlayerRig 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 GameObject _rigPrefabCache = null;
private static List<PlayerRig> _playerRigs = new List<PlayerRig>(); private static List<PlayerRig> _playerRigs = new List<PlayerRig>();
@@ -27,7 +30,10 @@ namespace BoneSync.PlayerRigs
public void UpdatePlayerSync(PlayerSyncInfo playerSyncInfo)
{
playerRig.transform.ApplySimpleTransform(playerSyncInfo.headPos);
}
public static void Tick() public static void Tick()
{ {
@@ -47,6 +53,7 @@ namespace BoneSync.PlayerRigs
} }
public static void TryRegisterRigPrefab() public static void TryRegisterRigPrefab()
{ {
return; // disable this for now
if (_rigPrefabCache) return; if (_rigPrefabCache) return;
GetPlayerRigPrefab(); GetPlayerRigPrefab();
} }
@@ -93,6 +100,7 @@ namespace BoneSync.PlayerRigs
return playerRig; return playerRig;
} }
private void UpdateRig() private void UpdateRig()
{ {
Vector3 velocity = Vector3.zero; Vector3 velocity = Vector3.zero;

View File

@@ -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<InteractableHostManager>();
interactableHost = GetComponent<InteractableHost>();
poolee = GetComponent<Poolee>();
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);
}
}
}

View File

@@ -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 syncable = gameObject.GetComponent<Syncable>();
// 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<Syncable>();
}
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);
}
}
}

View File

@@ -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<ulong, PlayerRig> _playerRigMap = new Dictionary<ulong, PlayerRig>();
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);
}
}
}

View File

@@ -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<Scene> scenes = new List<Scene>();
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));
}
}
}
}