diff --git a/BoneSync/BoneSync.csproj b/BoneSync/BoneSync.csproj index 2e7a74b..fa7a262 100644 --- a/BoneSync/BoneSync.csproj +++ b/BoneSync/BoneSync.csproj @@ -84,20 +84,27 @@ + + + - + + + + + @@ -254,13 +261,11 @@ - - diff --git a/BoneSync/Data/ByteEncoder.cs b/BoneSync/Data/ByteEncoder.cs index 4baada6..49a6874 100644 --- a/BoneSync/Data/ByteEncoder.cs +++ b/BoneSync/Data/ByteEncoder.cs @@ -214,12 +214,6 @@ namespace BoneSync.Data }; } - public void WriteSLZAttack(Attack attack) - { - WriteByte((byte)attack.attackType); - WriteFloat(attack.damage); - } - public void WriteMatrix4x4(UnityEngine.Matrix4x4 matrix) { for (int i = 0; i < 16; i++) @@ -251,5 +245,62 @@ namespace BoneSync.Data byte[] bytes = ReadBytes(length); return BitPacking.UnpackBits(bytes, length); } + + public void WriteAmmoVariables(AmmoVariables ammoVariables) + { + WriteBool(ammoVariables.Tracer); + WriteFloat(ammoVariables.ProjectileMass); + WriteFloat(ammoVariables.ExitVelocity); + WriteFloat(ammoVariables.AttackDamage); + WriteByte((byte)ammoVariables.AttackType); + WriteByte((byte)ammoVariables.cartridgeType); + } + + public AmmoVariables ReadAmmoVariables() + { + AmmoVariables ammoVariables = new AmmoVariables() + { + Tracer = ReadBool(), + ProjectileMass = ReadFloat(), + ExitVelocity = ReadFloat(), + AttackDamage = ReadFloat(), + AttackType = (AttackType)ReadByte(), + cartridgeType = (Cart)ReadByte() + }; + return ammoVariables; + } + + public void WriteMagazineData(MagazineData magazineData) + { + WriteByte((byte)magazineData.weight); + WriteByte((byte)magazineData.platform); + WriteUShort((byte)magazineData.cartridgeType); + BulletObject[] bulletObjects = magazineData.AmmoSlots; + WriteByte((byte)bulletObjects.Length); + for (int i = 0; i < bulletObjects.Length; i++) + { + WriteAmmoVariables(bulletObjects[i].ammoVariables); + } + } + + public MagazineData ReadMagazineData() + { + MagazineData mag = new MagazineData(); + mag.weight = (Weight)ReadByte(); + mag.platform = (Platform)ReadByte(); + mag.cartridgeType = (Cart)ReadUShort(); + byte bulletCount = ReadByte(); + + mag.AmmoSlots = new BulletObject[bulletCount]; + for (int i = 0; i < bulletCount; i++) + { + mag.AmmoSlots[i] = new BulletObject() + { + ammoVariables = ReadAmmoVariables() + }; + } + + return mag; + } } } diff --git a/BoneSync/Networking/Messages/MagazineSyncMessage.cs b/BoneSync/Networking/Messages/MagazineSyncMessage.cs new file mode 100644 index 0000000..023dd7a --- /dev/null +++ b/BoneSync/Networking/Messages/MagazineSyncMessage.cs @@ -0,0 +1,43 @@ +using BoneSync.Sync; +using BoneSync.Sync.Components; +using StressLevelZero.Combat; +using StressLevelZero.Props.Weapons; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BoneSync.Networking.Messages +{ + public struct MagazineSyncData + { + public ushort syncId; + public MagazineData magazineData; + } + + [PacketType(PacketType.MagazineSync), PacketReliability(PacketReliability.Unreliable)] + public class MagazineSyncMessage : NetworkMessage + { + public MagazineSyncData magazineData; + + public MagazineSyncMessage(MagazineSyncData magazineData) + { + this.magazineData = magazineData; + byteEncoder.WriteMagazineData(magazineData.magazineData); + } + + public MagazineSyncMessage(Packet packet) + { + byteEncoder.WriteBytes(packet.Data); + magazineData = new MagazineSyncData(); + } + + public override void Execute() + { + Syncable syncable = ObjectSyncCache.GetSyncable(magazineData.syncId); + if (!syncable) return; + syncable.ApplyMagazineData(magazineData.magazineData); + } + } +} diff --git a/BoneSync/Networking/Messages/ObjectAttributeMessage.cs b/BoneSync/Networking/Messages/ObjectAttributeMessage.cs deleted file mode 100644 index 5dbb0df..0000000 --- a/BoneSync/Networking/Messages/ObjectAttributeMessage.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace BoneSync.Networking.Messages -{ - public struct ObjectMagazineData - { - public byte ammoCount; - } - public struct ObjectAttributeMessageData - { - public ushort syncId; - public bool[] _attributes; - public ObjectMagazineData? magazineData; - } - - [PacketType(PacketType.ObjectAttribute), PacketReliability(PacketReliability.ReliableFast)] - internal class ObjectAttributeMessage : NetworkMessage - { - private ObjectAttributeMessageData _data; - - public ObjectAttributeMessage(ObjectAttributeMessageData objectAttributeMessageData) - { - List attributes = new List(); - _data = objectAttributeMessageData; - byteEncoder.WriteUShort(_data.syncId); - - attributes.Add(_data.magazineData.HasValue); - if (_data.magazineData.HasValue) - { - byteEncoder.WriteByte(_data.magazineData.Value.ammoCount); - } - - _data._attributes = attributes.ToArray(); - - - } - - public ObjectAttributeMessage(Packet packet) - { - byteEncoder.WriteBytes(packet.Data); - _data.syncId = byteEncoder.ReadUShort(); - _data._attributes = byteEncoder.ReadBoolArray(); - - if (_data._attributes[0]) - { - _data.magazineData = new ObjectMagazineData() - { - ammoCount = byteEncoder.ReadByte(), - }; - } - } - - } -} diff --git a/BoneSync/Networking/Messages/ObjectDamageMessage.cs b/BoneSync/Networking/Messages/ObjectDamageMessage.cs index 5369089..d4810ea 100644 --- a/BoneSync/Networking/Messages/ObjectDamageMessage.cs +++ b/BoneSync/Networking/Messages/ObjectDamageMessage.cs @@ -41,7 +41,7 @@ namespace BoneSync.Networking.Messages public ObjectHealthInfo objectHealthInfo; } - [PacketType(PacketType.ObjectEvent), PacketReliability(PacketReliability.Unreliable), PacketCatchup(4)] + [PacketType(PacketType.ObjectDamageEvent), PacketReliability(PacketReliability.Unreliable), PacketCatchup(4)] public class ObjectDamageMessage : NetworkMessage { public ObjectDamageInfo objectEventInfo => _objectEventInfo; diff --git a/BoneSync/Networking/PacketTypes.cs b/BoneSync/Networking/PacketTypes.cs index 3706946..62b07fd 100644 --- a/BoneSync/Networking/PacketTypes.cs +++ b/BoneSync/Networking/PacketTypes.cs @@ -13,9 +13,9 @@ namespace BoneSync.Networking PlayerSync = 2, RegisterSyncable = 3, ObjectSync = 4, - ObjectEvent = 5, + ObjectDamageEvent = 5, ObjectOwnership = 6, DiscardSyncable = 7, - ObjectAttribute = 8, + MagazineSync = 8, } } diff --git a/BoneSync/Patching/GunPatches.cs b/BoneSync/Patching/GunPatches.cs new file mode 100644 index 0000000..5010275 --- /dev/null +++ b/BoneSync/Patching/GunPatches.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using HarmonyLib; +using StressLevelZero.Props.Weapons; + +namespace BoneSync.Patching +{ + + [HarmonyPatch(typeof(Gun))] + public class GunPatches + { + [HarmonyPatch(nameof(Gun.Fire)), HarmonyPostfix] + public static void FirePatch(Gun __instance) + { + MelonLoader.MelonLogger.Msg("Gun fired: " + __instance.name); + } + + } +} diff --git a/BoneSync/Patching/ObjectHealthPatches.cs b/BoneSync/Patching/ObjectHealthPatches.cs index b36c01b..fb7085f 100644 --- a/BoneSync/Patching/ObjectHealthPatches.cs +++ b/BoneSync/Patching/ObjectHealthPatches.cs @@ -30,7 +30,7 @@ namespace BoneSync.Patching if (syncable != null) { if (damage > 0.5f) syncable.RegisterSyncable(); // register syncable if damage is very significant, e.g. a bullet hit - if (!syncable.isOwner) return false; + if (syncable.Registered && !syncable.isOwner) return false; MelonLoader.MelonLogger.Msg("Patch: ObjectDestructable.TakeDamage: " + damage + " " + syncable.gameObject.name); ObjectHealthInfo objectHealthInfo = new ObjectHealthInfo(__instance._health, __instance._hits, normal, damage, crit, attackType); @@ -70,7 +70,7 @@ namespace BoneSync.Patching if (syncable != null) { if (damage > 0.5f) syncable.RegisterSyncable(); - if (!syncable.isOwner) return true; + if (syncable.Registered && !syncable.isOwner) return false; MelonLoader.MelonLogger.Msg("Patch: Prop_Health.TAKEDAMAGE: " + damage + " " + syncable.gameObject.name); ObjectHealthInfo objectHealthInfo = new ObjectHealthInfo(__instance.cur_Health, __instance.hits, Vector3.zero, damage, crit, attackType); diff --git a/BoneSync/Patching/PlugPatches.cs b/BoneSync/Patching/PlugPatches.cs new file mode 100644 index 0000000..e154ac2 --- /dev/null +++ b/BoneSync/Patching/PlugPatches.cs @@ -0,0 +1,40 @@ +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 MelonLoader; +using StressLevelZero.Interaction; + +namespace BoneSync.Patching +{ + [HarmonyPatch(typeof(Socket))] + public class SocketPatches + { + [HarmonyPatch(nameof(Socket.OnPlugEnter)), HarmonyPostfix] + public static void SocketEnterPatch(Socket __instance, Plug plug) + { + if (!plug) return; + MelonLogger.Msg("Plug entered: " + __instance.name + " Plug: " + plug.name); + Syncable syncable = ObjectSyncCache.GetSyncable(plug); + if (!syncable) return; + byte id = syncable.GetPlugId(plug); + MelonLogger.Msg("Plug entered: " + __instance.name + " Plug: " + plug.name + " ID: " + id); + + } + + [HarmonyPatch(nameof(Socket.OnPlugExit)), HarmonyPostfix] + public static void SocketExitPatch(Socket __instance, Plug plug) + { + if (!plug) return; + MelonLogger.Msg("Plug exited: " + __instance.name + " Plug: " + plug.name); + Syncable syncable = ObjectSyncCache.GetSyncable(plug); + if (!syncable) return; + byte id = syncable.GetPlugId(plug); + MelonLogger.Msg("Plug exited: " + __instance.name + " Plug: " + plug.name + " ID: " + id); + } + } +} diff --git a/BoneSync/Sync/Components/SyncableBase.cs b/BoneSync/Sync/Components/SyncableBase.cs index 2636c14..1da68f7 100644 --- a/BoneSync/Sync/Components/SyncableBase.cs +++ b/BoneSync/Sync/Components/SyncableBase.cs @@ -108,6 +108,7 @@ namespace BoneSync.Sync.Components private Magazine magazine; private Plug[] plugs; + private Socket[] sockets; private AIBrain aiBrain; private PuppetMaster puppetMaster; @@ -177,6 +178,7 @@ namespace BoneSync.Sync.Components gun = GetComponent(); magazine = GetComponent(); plugs = GetComponentsInChildren(); + sockets = GetComponentsInChildren(); spawnFragment = GetComponent(); UpdateTransformList(); diff --git a/BoneSync/Sync/Components/SyncablePlugs.cs b/BoneSync/Sync/Components/SyncablePlugs.cs new file mode 100644 index 0000000..183ce2a --- /dev/null +++ b/BoneSync/Sync/Components/SyncablePlugs.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; +using MelonLoader; +using StressLevelZero.Interaction; + +namespace BoneSync.Sync.Components +{ + public partial class Syncable : MonoBehaviour + { + public Plug GetPlugFromId(byte id) + { + if (plugs.Length <= id) + { + MelonLogger.Error("Plug ID out of range"); + return null; + } + + return plugs[id]; + } + + public Socket GetSocketFromId(byte id) + { + if (sockets.Length <= id) + { + MelonLogger.Error("Socket ID out of range"); + return null; + } + return sockets[id]; + } + + public byte GetSocketId(Socket socket) + { + for (byte i = 0; i < sockets.Length; i++) + { + if (sockets[i] == socket) + { + return i; + } + } + return 255; + } + + public byte GetPlugId(Plug plug) + { + for (byte i = 0; i < plugs.Length; i++) + { + if (plugs[i] == plug) + { + return i; + } + } + return 255; + } + } +} diff --git a/BoneSync/Sync/Components/SyncableProperties.cs b/BoneSync/Sync/Components/SyncableProperties.cs new file mode 100644 index 0000000..49bd9c1 --- /dev/null +++ b/BoneSync/Sync/Components/SyncableProperties.cs @@ -0,0 +1,32 @@ +using BoneSync.Networking.Messages; +using StressLevelZero.Combat; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace BoneSync.Sync.Components +{ + public partial class Syncable : MonoBehaviour + { + public void ApplyMagazineData(MagazineData magazineData) + { + if (!magazineData) return; + if (!magazine) return; + magazine.magazineData.AmmoSlots = magazineData.AmmoSlots; + magazine.magazineData.cartridgeType = magazineData.cartridgeType; + magazine.magazineData.weight = magazineData.weight; + magazine.magazineData.platform = magazineData.platform; + } + + public MagazineSyncData GetMagazineData() + { + MagazineSyncData data = new MagazineSyncData(); + data.syncId = GetSyncId(); + data.magazineData = magazine.magazineData; + return data; + } + } +} diff --git a/BoneSync/Sync/ObjectSyncCache.cs b/BoneSync/Sync/ObjectSyncCache.cs index 54ca40e..8516d94 100644 --- a/BoneSync/Sync/ObjectSyncCache.cs +++ b/BoneSync/Sync/ObjectSyncCache.cs @@ -15,11 +15,57 @@ namespace BoneSync.Sync private static Dictionary _pathToSyncable = new Dictionary(); private static Dictionary _idToSyncable = new Dictionary(); - //private static Dictionary _componentToSyncable = new Dictionary(); + private static Dictionary _componentToSyncable = new Dictionary(); + private static Dictionary _syncableToComponent = new Dictionary(); public static Dictionary CallbackIdToSyncable = new Dictionary(); - public static void AddSyncable(Syncable syncable) + private static string GetComponentNamespace(Component component) + { + return component.GetType().Namespace; + } + + private static bool IsSlzComponent(Component component) + { + string ns = GetComponentNamespace(component); + return ns.StartsWith("StressLevelZero") || ns.StartsWith("BoneSync"); + } + private static Component[] GetSLZComponents(Syncable syncable) + { + Component[] components = syncable.GetComponentsInChildren(true); + List slzComponents = new List(); + for (int i = 0; i < components.Length; i++) + { + if (IsSlzComponent(components[i])) + { + slzComponents.Add(components[i]); + } + } + return slzComponents.ToArray(); + } + private static void _AddSyncableComponents(Syncable syncable) + { + Component[] components = GetSLZComponents(syncable); + _syncableToComponent[syncable] = components; + foreach (Component component in components) + { + _componentToSyncable[component] = syncable; + } + } + private static void _RemoveSyncableComponents(Syncable syncable) + { + if (_syncableToComponent.ContainsKey(syncable)) + { + Component[] components = _syncableToComponent[syncable]; + foreach (Component component in components) + { + _componentToSyncable.Remove(component); + } + _syncableToComponent.Remove(syncable); + } + } + + private static void _AddSyncableKeys(Syncable syncable) { string path = syncable.GetSyncableWorldPath(); if (path != null && path != "") @@ -32,7 +78,7 @@ namespace BoneSync.Sync } } - public static void RemoveSyncable(Syncable syncable) + private static void _RemoveSyncableKeys(Syncable syncable) { string path = syncable.GetSyncableWorldPath(); if (path != null && path != "") @@ -44,6 +90,17 @@ namespace BoneSync.Sync _idToSyncable.Remove(syncable.GetSyncId()); } } + public static void AddSyncable(Syncable syncable) + { + _AddSyncableKeys(syncable); + _AddSyncableComponents(syncable); + } + + public static void RemoveSyncable(Syncable syncable) + { + _RemoveSyncableKeys(syncable); + _RemoveSyncableComponents(syncable); + } public static void UpdateSyncId(Syncable syncable) { @@ -79,6 +136,15 @@ namespace BoneSync.Sync return null; } + public static Syncable GetSyncable(Component component) + { + if (_componentToSyncable.ContainsKey(component)) + { + return _componentToSyncable[component]; + } + return null; + } + public static void DISCARD_ALL_SYNCABLES() { foreach (Syncable syncable in Syncable.syncablesCache.Values)