From d0eb7f89beceabad1c102fd08e729972871a4590 Mon Sep 17 00:00:00 2001 From: Aaro Varis Date: Fri, 28 Feb 2025 14:35:14 +0200 Subject: [PATCH] Bunch more networking stuff --- BoneSync/Networking/ByteEncoder.cs | 11 +---- .../Messages/ObjectDamageMessage.cs | 4 +- .../Messages/RegisterSyncableMessage.cs | 39 ++++++++++++++--- BoneSync/Patching/CallPatchedMethod.cs | 9 ++-- BoneSync/Patching/PoolPatches.cs | 28 +++++++++++- BoneSync/Sync/Components/SyncableBase.cs | 24 +++++++---- BoneSync/Sync/Components/SyncableDamage.cs | 4 +- BoneSync/Sync/ObjectSync.cs | 43 +++++++++++++++++-- 8 files changed, 126 insertions(+), 36 deletions(-) diff --git a/BoneSync/Networking/ByteEncoder.cs b/BoneSync/Networking/ByteEncoder.cs index f664478..7d7ca75 100644 --- a/BoneSync/Networking/ByteEncoder.cs +++ b/BoneSync/Networking/ByteEncoder.cs @@ -180,18 +180,9 @@ namespace BoneSync.Networking }; } - public void WriteEnum(T value) where T : Enum - { - WriteByte((byte)(object)value); - } - public T ReadEnum() where T : Enum - { - return (T)(object)ReadByte(); - } - public void WriteSLZAttack(Attack attack) { - WriteEnum(attack.attackType); + WriteByte((byte)attack.attackType); WriteFloat(attack.damage); } diff --git a/BoneSync/Networking/Messages/ObjectDamageMessage.cs b/BoneSync/Networking/Messages/ObjectDamageMessage.cs index 06a6bdc..4a0acf9 100644 --- a/BoneSync/Networking/Messages/ObjectDamageMessage.cs +++ b/BoneSync/Networking/Messages/ObjectDamageMessage.cs @@ -50,7 +50,7 @@ namespace BoneSync.Networking.Messages { _objectEventInfo = objectEventInfo; byteEncoder.WriteUShort(_objectEventInfo.objectId); - byteEncoder.WriteEnum(_objectEventInfo.eventType); + byteEncoder.WriteByte((byte)_objectEventInfo.eventType); byteEncoder.WriteFloat(_objectEventInfo.objectHealthInfo._health); byteEncoder.WriteInt(_objectEventInfo.objectHealthInfo._hits); if (_objectEventInfo.eventType == ObjectDamageType.SyncHealth) return; // No need to write the rest of the data @@ -63,7 +63,7 @@ namespace BoneSync.Networking.Messages { byteEncoder.WriteBytes(packet.Data); _objectEventInfo.objectId = byteEncoder.ReadUShort(); - _objectEventInfo.eventType = byteEncoder.ReadEnum(); + _objectEventInfo.eventType = (ObjectDamageType)byteEncoder.ReadByte(); _objectEventInfo.objectHealthInfo._health = byteEncoder.ReadFloat(); _objectEventInfo.objectHealthInfo._hits = byteEncoder.ReadInt(); if (_objectEventInfo.eventType == ObjectDamageType.SyncHealth) return; // No need to read the rest of the data diff --git a/BoneSync/Networking/Messages/RegisterSyncableMessage.cs b/BoneSync/Networking/Messages/RegisterSyncableMessage.cs index 495bee8..6b758f1 100644 --- a/BoneSync/Networking/Messages/RegisterSyncableMessage.cs +++ b/BoneSync/Networking/Messages/RegisterSyncableMessage.cs @@ -1,4 +1,5 @@ -using BoneSync.Sync; +using BoneSync.Patching; +using BoneSync.Sync; using System; using System.Collections.Generic; using System.Linq; @@ -12,12 +13,19 @@ namespace BoneSync.Networking.Messages RegisterFromPath = 0, RegisterAndSpawn = 1, } + + public struct SpawnPoolableInfo + { + public string poolName; + public SimpleTransform spawnLocation; + } public struct RegisterSyncableInfo { public string transformPath; public ushort id; public ulong ownerId; public RegisterSyncType type; + public SpawnPoolableInfo? spawnInfo; } [PacketType(PacketType.RegisterSyncable)] @@ -28,20 +36,41 @@ namespace BoneSync.Networking.Messages public RegisterSyncableMessage(RegisterSyncableInfo info) { _info = info; - byteEncoder.WriteEnum(_info.type); - byteEncoder.WriteString(_info.transformPath); + byteEncoder.WriteByte((byte)_info.type); byteEncoder.WriteUlong(_info.ownerId); byteEncoder.WriteUShort(_info.id); + switch (_info.type) + { + case RegisterSyncType.RegisterAndSpawn: + byteEncoder.WriteString(_info.spawnInfo.Value.poolName); + byteEncoder.WriteSimpleTransform(_info.spawnInfo.Value.spawnLocation); + break; + case RegisterSyncType.RegisterFromPath: + byteEncoder.WriteString(_info.transformPath); + break; + } } public RegisterSyncableMessage(Packet packet) { byteEncoder.WriteBytes(packet.Data); - _info.type = byteEncoder.ReadEnum(); - _info.transformPath = byteEncoder.ReadString(); + _info.type = (RegisterSyncType)byteEncoder.ReadByte(); _info.ownerId = byteEncoder.ReadUlong(); _info.id = byteEncoder.ReadUShort(); + switch (_info.type) + { + case RegisterSyncType.RegisterAndSpawn: + _info.spawnInfo = new SpawnPoolableInfo() + { + poolName = byteEncoder.ReadString(), + spawnLocation = byteEncoder.ReadSimpleTransform(), + }; + break; + case RegisterSyncType.RegisterFromPath: + _info.transformPath = byteEncoder.ReadString(); + break; + } } public override void Execute() diff --git a/BoneSync/Patching/CallPatchedMethod.cs b/BoneSync/Patching/CallPatchedMethod.cs index af58b1b..7ab2d0f 100644 --- a/BoneSync/Patching/CallPatchedMethod.cs +++ b/BoneSync/Patching/CallPatchedMethod.cs @@ -17,24 +17,25 @@ namespace BoneSync.Patching private set; get; } - public static void TakeDamage(ObjectDestructable __instance, ref Vector3 normal, ref float damage, ref bool crit, ref AttackType attackType) + public static void TakeDamage(ObjectDestructable __instance, Vector3 normal, float damage, bool crit, AttackType attackType) { allowPatchedMethodCall = true; __instance.TakeDamage(normal, damage, crit, attackType); allowPatchedMethodCall = false; } - public static void TakeDamage(Prop_Health __instance, ref float damage, ref bool crit, ref AttackType attackType) + public static void TakeDamage(Prop_Health __instance, float damage, bool crit, AttackType attackType) { allowPatchedMethodCall = true; __instance.TAKEDAMAGE(damage, crit, attackType); allowPatchedMethodCall = false; } - public static GameObject PoolSpawn(Pool __instance, ref Vector3 position, ref Quaternion rotation, ref Il2CppSystem.Nullable scale, ref Il2CppSystem.Nullable autoEnable) + public static GameObject PoolSpawn(Pool __instance, Vector3 position, Quaternion rotation, Vector3 scale) { allowPatchedMethodCall = true; - GameObject result = __instance.Spawn(position, rotation, scale, autoEnable); + Il2CppSystem.Nullable scaleNullable = new Il2CppSystem.Nullable(scale); + GameObject result = __instance.Spawn(position, rotation, scaleNullable, new Il2CppSystem.Nullable(true)); allowPatchedMethodCall = false; return result; } diff --git a/BoneSync/Patching/PoolPatches.cs b/BoneSync/Patching/PoolPatches.cs index a4942c3..dd8278d 100644 --- a/BoneSync/Patching/PoolPatches.cs +++ b/BoneSync/Patching/PoolPatches.cs @@ -4,6 +4,8 @@ using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; +using BoneSync.Networking.Messages; +using BoneSync.Sync; using HarmonyLib; using MelonLoader; using StressLevelZero; @@ -17,6 +19,27 @@ namespace BoneSync.Patching internal class PoolPatches { + public readonly static string[] ignoredPools = new string[] { + "RigidbodyProjectile", + "VFX Despawn Mesh", + "AudioPlayer", + "Decal", + "PopupText", + }; + + public static bool IsIgnoredPool(string poolName) + { + string lowercasePoolName = poolName.ToLower(); + foreach (string ignoredPool in ignoredPools) + { + if (lowercasePoolName.Contains(ignoredPool.ToLower())) + { + return true; + } + } + return false; + } + [HarmonyPatch(nameof(Pool.Spawn))] [HarmonyPostfix] private static void SpawnPatchPost(Pool __instance, ref GameObject __result) @@ -29,11 +52,12 @@ namespace BoneSync.Patching private static bool SpawnPatchPre(Pool __instance, ref Vector3 position, ref Quaternion rotation, ref Il2CppSystem.Nullable scale, ref Il2CppSystem.Nullable autoEnable) { if (CallPatchedMethods.allowPatchedMethodCall) return true; - + if (IsIgnoredPool(__instance.name)) return true; if (BoneSync.lobby.IsConnected()) { + MelonLogger.Msg("Patched Spawning object in pool: " + __instance.name); - return false; + return BoneSync.lobby.IsHost; // only allow host to spawn objects naturally } return true; } diff --git a/BoneSync/Sync/Components/SyncableBase.cs b/BoneSync/Sync/Components/SyncableBase.cs index 53feeaa..c37b186 100644 --- a/BoneSync/Sync/Components/SyncableBase.cs +++ b/BoneSync/Sync/Components/SyncableBase.cs @@ -115,6 +115,21 @@ namespace BoneSync.Sync.Components public void OnEnable() { FindComponents(); + + bool shouldAutoSync = CheckIfShouldAutoSync(); + if (shouldAutoSync) + { + MelonLogger.Msg("AutoSyncing: " + transform.GetPath()); + RegisterSyncable(); + } + } + + public bool CheckIfShouldAutoSync() + { + if (poolee && poolee.pool) { + return true; + } + return false; } public string GetSyncableWorldPath() @@ -151,14 +166,7 @@ namespace BoneSync.Sync.Components public bool CanBeSynced() { FindComponents(); - if (interactableManager && interactableManager.hosts.Count > 0) - { - return true; - } - if (interactableHost && interactableHost.hasRigidbody) - { - return true; - } + if (rigidbodies.Length > 0) return true; return false; } diff --git a/BoneSync/Sync/Components/SyncableDamage.cs b/BoneSync/Sync/Components/SyncableDamage.cs index 22e6836..7520c97 100644 --- a/BoneSync/Sync/Components/SyncableDamage.cs +++ b/BoneSync/Sync/Components/SyncableDamage.cs @@ -42,14 +42,14 @@ namespace BoneSync.Sync.Components if (eventType == ObjectDamageType.DestructibleTakeDamage && objectDestructable) { MelonLogger.Msg("NetworkDestructableTakeDamage: " + healthInfo.damage); - CallPatchedMethods.TakeDamage(objectDestructable, ref healthInfo.normal, ref healthInfo.damage, ref healthInfo.crit, ref healthInfo.attackType); + CallPatchedMethods.TakeDamage(objectDestructable, healthInfo.normal, healthInfo.damage, healthInfo.crit, healthInfo.attackType); return; } if (eventType == ObjectDamageType.PropHealthTakeDamage && propHealth) { MelonLogger.Msg("NetworkPropHealthTakeDamage: " + healthInfo.damage); - CallPatchedMethods.TakeDamage(propHealth, ref healthInfo.damage, ref healthInfo.crit, ref healthInfo.attackType); + CallPatchedMethods.TakeDamage(propHealth, healthInfo.damage, healthInfo.crit, healthInfo.attackType); return; } diff --git a/BoneSync/Sync/ObjectSync.cs b/BoneSync/Sync/ObjectSync.cs index db4eb78..dd9f0b8 100644 --- a/BoneSync/Sync/ObjectSync.cs +++ b/BoneSync/Sync/ObjectSync.cs @@ -1,4 +1,6 @@ -using BoneSync.Networking.Messages; +using BoneSync.Networking; +using BoneSync.Networking.Messages; +using BoneSync.Patching; using BoneSync.Sync.Components; using MelonLoader; using StressLevelZero.Interaction; @@ -34,12 +36,16 @@ namespace BoneSync.Sync ownerId = syncable._ownerId, }; } - else if (syncable.poolee) + else if (syncable.poolee && syncable.poolee.pool) { info = new RegisterSyncableInfo() { type = RegisterSyncType.RegisterAndSpawn, - transformPath = syncable.poolee.transform.GetPath(), + spawnInfo = new SpawnPoolableInfo() + { + poolName = syncable.poolee.pool.name, + spawnLocation = new SimpleTransform(syncable.poolee.transform), + }, }; } return info; @@ -57,6 +63,8 @@ namespace BoneSync.Sync RegisterSyncableInfo info = infoNullable.Value; + + RegisterSyncableMessage message = new RegisterSyncableMessage(info); if (BoneSync.lobby.IsHost) { @@ -65,9 +73,16 @@ namespace BoneSync.Sync } else { + if (message.senderId != BoneSync.lobby.GetHostId()) + { + MelonLogger.Warning("Non host tried to send register syncable message"); + } info.id = 0; message.Send(BoneSync.lobby.GetHostId()); } + + MelonLogger.Msg("Sending register syncable message for: " + syncable.transform.name + " with id: " + info.id + " and type : " + info.type); + return info.id; } @@ -135,6 +150,20 @@ namespace BoneSync.Sync return _MakeOrGetSyncable(interactableHostManager.gameObject); } + public static Syncable SpawnPooleeAndMakeSyncable(string poolName, RegisterSyncableInfo info) + { + SimpleTransform spawnLocation = info.spawnInfo.Value.spawnLocation; + Pool pool = PoolManager.GetPool(poolName); + if (pool == null) + { + MelonLogger.Warning("Pool not found: " + poolName); + return null; + } + GameObject spawned = CallPatchedMethods.PoolSpawn(pool, spawnLocation.position, spawnLocation.rotation, spawnLocation.scale); + MelonLogger.Msg("Spawned object: " + spawned.transform.GetPath() + " in pool: " + poolName); + Poolee poolee = spawned.GetComponent(); + return _MakeOrGetSyncable(poolee.gameObject); + } public static void OnRegisterSyncMessage(RegisterSyncableMessage registerSyncableMessage) { Syncable syncable = null; @@ -152,9 +181,17 @@ namespace BoneSync.Sync syncable = ObjectSyncCache.GetSyncable(info.transformPath); break; case RegisterSyncType.RegisterAndSpawn: + MelonLogger.Msg("Registering and spawning syncable from pool: " + info.spawnInfo.Value.poolName + " with id: " + info.id); + syncable = SpawnPooleeAndMakeSyncable(info.spawnInfo.Value.poolName, info); break; } + if (!syncable) + { + MelonLogger.Warning("Failed to create/obtain syncable for register sync message "+ info.id); + return; + } + syncable.SetSyncId(info.id); syncable.SetOwner(info.ownerId); }