diff --git a/BoneSync/BoneSync.csproj b/BoneSync/BoneSync.csproj
index 7055f63..5c8db6c 100644
--- a/BoneSync/BoneSync.csproj
+++ b/BoneSync/BoneSync.csproj
@@ -93,7 +93,9 @@
+
+
diff --git a/BoneSync/Networking/Messages/PlugSyncMessage.cs b/BoneSync/Networking/Messages/PlugSyncMessage.cs
new file mode 100644
index 0000000..674d45a
--- /dev/null
+++ b/BoneSync/Networking/Messages/PlugSyncMessage.cs
@@ -0,0 +1,67 @@
+using BoneSync.Sync;
+using BoneSync.Sync.Components;
+using StressLevelZero.Interaction;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BoneSync.Networking.Messages
+{
+
+ public struct PlugSyncMessageData
+ {
+ public ushort plugSyncId;
+ public byte plugIndex;
+ public ushort socketSyncId;
+ public byte socketIndex;
+ }
+
+ [PacketType(PacketType.PlugSync), PacketReliability(PacketReliability.ReliableFast)]
+ internal class PlugSyncMessage : NetworkMessage
+ {
+ private PlugSyncMessageData messageData;
+ public PlugSyncMessage(PlugSyncMessageData plugSyncMessageData)
+ {
+ this.messageData = plugSyncMessageData;
+ byteEncoder.WriteUShort(plugSyncMessageData.plugSyncId);
+ byteEncoder.WriteByte(plugSyncMessageData.plugIndex);
+ byteEncoder.WriteUShort(plugSyncMessageData.socketSyncId);
+ byteEncoder.WriteByte(plugSyncMessageData.socketIndex);
+ }
+
+ public PlugSyncMessage(Packet packet) {
+ byteEncoder.WriteBytes(packet.Data);
+ messageData.plugSyncId = byteEncoder.ReadUShort();
+ messageData.plugIndex = byteEncoder.ReadByte();
+ messageData.socketSyncId = byteEncoder.ReadUShort();
+ messageData.socketIndex = byteEncoder.ReadByte();
+ }
+
+ public override void Execute()
+ {
+ Syncable plugSyncable = ObjectSyncCache.GetSyncable(messageData.plugSyncId);
+ Syncable socketSyncable = ObjectSyncCache.GetSyncable(messageData.socketSyncId);
+
+ if (!plugSyncable || messageData.plugIndex == byte.MaxValue) { return; }
+ AlignPlug plug = (AlignPlug)plugSyncable.GetPlugFromId(messageData.plugIndex);
+ if (plug == null) { return; }
+
+ if (!socketSyncable || messageData.socketIndex == byte.MaxValue) {
+ plug.SafeEject();
+ return;
+ }
+
+ Socket socket = socketSyncable.GetSocketFromId(messageData.socketIndex);
+ if (socket == null)
+ {
+ plug.SafeEject();
+ return;
+ }
+
+ plug.SafeInsert(socket);
+ }
+
+ }
+}
diff --git a/BoneSync/Networking/Messages/SimpleSyncableEventMessage.cs b/BoneSync/Networking/Messages/SimpleSyncableEventMessage.cs
new file mode 100644
index 0000000..ad7492c
--- /dev/null
+++ b/BoneSync/Networking/Messages/SimpleSyncableEventMessage.cs
@@ -0,0 +1,50 @@
+using BoneSync.Sync;
+using BoneSync.Sync.Components;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BoneSync.Networking.Messages
+{
+ public enum SimpleEventType
+ {
+ None = 0,
+ OnDevicePull = 1,
+ OnDeviceRelease = 2
+ }
+ public struct SimpleSyncableEvent
+ {
+ public ushort syncId;
+ public SimpleEventType eventType;
+ //public object[] args;
+ }
+ [PacketType(PacketType.SimpleObjectEventSync)]
+ public class SimpleSyncableEventMessage : NetworkMessage
+ {
+ private SimpleSyncableEvent eventData;
+ public SimpleSyncableEventMessage(SimpleSyncableEvent simpleSyncableEvent)
+ {
+ eventData = simpleSyncableEvent;
+ byteEncoder.WriteULong(simpleSyncableEvent.syncId);
+ byteEncoder.WriteByte((byte)simpleSyncableEvent.eventType);
+ }
+
+ public SimpleSyncableEventMessage(Packet packet)
+ {
+ byteEncoder.WriteBytes(packet.Data);
+ eventData.syncId = byteEncoder.ReadUShort();
+ eventData.eventType = (SimpleEventType)byteEncoder.ReadByte();
+ }
+
+ public override void Execute()
+ {
+ Syncable syncable = ObjectSyncCache.GetSyncable(eventData.syncId);
+ if (syncable == null) return;
+ syncable.OnSimpleSyncableEvent(eventData);
+ }
+
+
+ }
+}
diff --git a/BoneSync/Networking/PacketTypes.cs b/BoneSync/Networking/PacketTypes.cs
index cb3550e..49ab1bf 100644
--- a/BoneSync/Networking/PacketTypes.cs
+++ b/BoneSync/Networking/PacketTypes.cs
@@ -18,5 +18,7 @@ namespace BoneSync.Networking
DiscardSyncable = 7,
MagazineSync = 8,
GunSync = 9,
+ SimpleObjectEventSync = 10,
+ PlugSync = 11,
}
}
diff --git a/BoneSync/Patching/DebugPatches.cs b/BoneSync/Patching/DebugPatches.cs
index 3c0b7b1..9004b3a 100644
--- a/BoneSync/Patching/DebugPatches.cs
+++ b/BoneSync/Patching/DebugPatches.cs
@@ -11,7 +11,7 @@ using UnityEngine;
namespace BoneSync.Patching
{
- [HarmonyPatch(typeof(PoolSpawner))]
+ /*[HarmonyPatch(typeof(PoolSpawner))]
internal class DebugPatches
{
// patch the static method "PoolSpawner.SpawnProjectile"
@@ -20,5 +20,6 @@ namespace BoneSync.Patching
{
MelonLoader.MelonLogger.Msg("PoolSpawner.SpawnProjectile " + weaponName);
}
- }
+ }*/
+
}
diff --git a/BoneSync/Patching/PlugPatches.cs b/BoneSync/Patching/PlugPatches.cs
index 2f64586..6480cd0 100644
--- a/BoneSync/Patching/PlugPatches.cs
+++ b/BoneSync/Patching/PlugPatches.cs
@@ -3,11 +3,13 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using BoneSync.Networking.Messages;
using BoneSync.Sync;
using BoneSync.Sync.Components;
using HarmonyLib;
using MelonLoader;
using StressLevelZero.Interaction;
+using static MelonLoader.MelonLogger;
namespace BoneSync.Patching
{
@@ -70,16 +72,66 @@ namespace BoneSync.Patching
[HarmonyPatch(typeof(AlignPlug))]
public static class AlignPlugPatches
{
+ public static void OnPlugSocketChange(AlignPlug plug, Socket socket)
+ {
+
+ Syncable plugSyncable = plug.GetComponentInParent();
+ Syncable socketSyncable = socket.GetComponentInParent();
+
+ if (!plugSyncable)
+ {
+ MelonLogger.Warning("PlugSyncable not found");
+ return;
+ }
+
+ if (!plugSyncable.Registered)
+ {
+ MelonLogger.Warning("PlugSyncable not registered");
+ return;
+ }
+
+ if (!socketSyncable)
+ {
+ MelonLogger.Warning("SocketSyncable not found");
+ }
+
+ if (socketSyncable && socketSyncable.isOwner && !plugSyncable.isOwner)
+ {
+ plugSyncable.TryBecomeOwner(true); // forcefully take ownership of the plug
+ }
+
+ byte plugId = plugSyncable.GetPlugId(plug);
+ byte socketId = socketSyncable ? socketSyncable.GetSocketId(socket) : byte.MaxValue;
+
+ MelonLogger.Msg("AlignPlug state: " + plug.transform.GetPath() + " Socket: " + socket.transform.GetPath() + " Plug ID: " + plugId + " Socket ID: " + socketId);
+
+ if (!plugSyncable.isOwner) return;
+
+ PlugSyncMessageData messageData = new PlugSyncMessageData
+ {
+ plugSyncId = plugSyncable.GetSyncId(),
+ plugIndex = plugId,
+ socketSyncId = socketSyncable ? socketSyncable.GetSyncId() : ushort.MinValue,
+ socketIndex = socketId
+ };
+
+ PlugSyncMessage plugSyncMessage = new PlugSyncMessage(messageData);
+ plugSyncMessage.Broadcast();
+ }
+
[HarmonyPatch(nameof(AlignPlug.InsertPlug)), HarmonyPostfix]
public static void AlignPlugInsertPatch(AlignPlug __instance, Socket socket)
{
- MelonLogger.Msg("AlignPlug inserted: " + __instance.transform.GetPath() + " Socket: " + socket.transform.GetPath());
+ MelonLogger.Msg("AlignPlug inserted: " + __instance.transform.GetPath() + " Socket: " + socket.transform.GetPath());
+ OnPlugSocketChange(__instance, socket);
+
}
[HarmonyPatch(nameof(AlignPlug.EjectPlug)), HarmonyPostfix]
public static void AlignPlugEjectPatch(AlignPlug __instance)
{
MelonLogger.Msg("AlignPlug ejected: " + __instance.transform.GetPath());
+ OnPlugSocketChange(__instance, null);
}
}
diff --git a/BoneSync/Sync/Components/SyncableBase.cs b/BoneSync/Sync/Components/SyncableBase.cs
index 0b1f6a9..70625b0 100644
--- a/BoneSync/Sync/Components/SyncableBase.cs
+++ b/BoneSync/Sync/Components/SyncableBase.cs
@@ -185,6 +185,7 @@ namespace BoneSync.Sync.Components
spawnFragment = GetComponent();
UpdateTransformList();
+ _TryPatchPullDevice();
ObjectSyncCache.AddSyncable(this);
}
diff --git a/BoneSync/Sync/Components/SyncableNetworking.cs b/BoneSync/Sync/Components/SyncableNetworking.cs
index 59ecdb9..b3ac98e 100644
--- a/BoneSync/Sync/Components/SyncableNetworking.cs
+++ b/BoneSync/Sync/Components/SyncableNetworking.cs
@@ -86,19 +86,24 @@ namespace BoneSync.Sync.Components
}
}
- public void TryBecomeOwner()
+ public void TryBecomeOwner(bool force = false)
{
if (Registered && !isOwner)
{
- MelonLogger.Msg("Attempting to become owner of " + _syncId);
+ ulong localId = BoneSync.lobby.GetLocalId();
+ MelonLogger.Msg("Attempting to become owner of " + _syncId + " force: " + force);
OwnershipTransferMessageData data = new OwnershipTransferMessageData()
{
syncId = _syncId,
- NewOwnerId = BoneSync.lobby.GetLocalId(),
- force = false
+ NewOwnerId = localId,
+ force = force
};
OwnershipTransferMessage message = new OwnershipTransferMessage(data);
message.Broadcast();
+ if (force)
+ {
+ SetOwner(localId);
+ }
}
}
@@ -111,6 +116,18 @@ namespace BoneSync.Sync.Components
return true;
}
+ private void _SendSimpleEvent(SimpleEventType eType)
+ {
+ SimpleSyncableEvent data = new SimpleSyncableEvent()
+ {
+ syncId = _syncId,
+ eventType = eType
+ };
+
+ SimpleSyncableEventMessage simpleSyncEvent = new SimpleSyncableEventMessage(data);
+ simpleSyncEvent.Broadcast();
+ }
+
public ushort GetSyncId() => _syncId;
public void SetSyncId(ushort id)
{
diff --git a/BoneSync/Sync/Components/SyncablePhysics.cs b/BoneSync/Sync/Components/SyncablePhysics.cs
index 1bc946b..3c26f83 100644
--- a/BoneSync/Sync/Components/SyncablePhysics.cs
+++ b/BoneSync/Sync/Components/SyncablePhysics.cs
@@ -17,15 +17,25 @@ namespace BoneSync.Sync.Components
{
private bool pullDevicePatched = false;
- void OnPull()
+ void DeviceOnPull()
{
MelonLogger.Msg("OnPull");
+ if (!isOwner) { return; }
+ _SendSimpleEvent(SimpleEventType.OnDevicePull);
+ }
+ void DeviceOnRelease()
+ {
+ MelonLogger.Msg("OnRelease");
+ if (!isOwner) { return; }
+ _SendSimpleEvent(SimpleEventType.OnDeviceRelease);
}
private void _TryPatchPullDevice()
{
if (pullDevicePatched) return;
if (!pullDevice) return;
- pullDevice.OnHandlePull.AddListener((UnityAction)OnPull);
+ pullDevice.OnHandlePull.AddListener((UnityAction)DeviceOnPull);
+ pullDevice.OnHandleReturn.AddListener((UnityAction)DeviceOnRelease);
+ pullDevicePatched = true;
}
public bool AllRigidbodiesSleeping()
@@ -45,6 +55,7 @@ namespace BoneSync.Sync.Components
private void SetKinematic(bool kinematic)
{
if (!this) return;
+ if (rigidbodies.Length == 0) return;
foreach (Rigidbody rb in rigidbodies)
{
try
@@ -119,6 +130,19 @@ namespace BoneSync.Sync.Components
SetKinematic(_ownerId != BoneSync.lobby.GetLocalId() && Registered);
}
+ internal void OnSimpleSyncableEvent(SimpleSyncableEvent eventData)
+ {
+ MelonLogger.Msg("OnSimpleSyncableEvent: " + eventData.eventType);
+ SimpleEventType eType = eventData.eventType;
+ switch (eType) {
+ case SimpleEventType.OnDevicePull:
+ pullDevice?.OnHandlePull?.Invoke();
+ break;
+ case SimpleEventType.OnDeviceRelease:
+ pullDevice?.OnHandleReturn?.Invoke();
+ break;
+ }
+ }
// on collision
}
}
diff --git a/BoneSync/Sync/Components/SyncablePlugs.cs b/BoneSync/Sync/Components/SyncablePlugs.cs
index 183ce2a..a9ac711 100644
--- a/BoneSync/Sync/Components/SyncablePlugs.cs
+++ b/BoneSync/Sync/Components/SyncablePlugs.cs
@@ -9,6 +9,39 @@ using StressLevelZero.Interaction;
namespace BoneSync.Sync.Components
{
+ public static class PlugExtensions
+ {
+ public static Socket GetSocket(this AlignPlug plug)
+ {
+ Socket socket = plug._lastSocket;
+ if (!socket) return null;
+ if (socket.LockedPlug == plug)
+ {
+ return socket;
+ }
+ return null;
+ }
+
+ public static bool SafeEject(this AlignPlug plug)
+ {
+ if (!plug.GetSocket()) return false;
+ plug.EjectPlug();
+ return true;
+ }
+
+ public static bool SafeInsert(this AlignPlug plug, Socket socket)
+ {
+ if (!socket) return false;
+ if (socket.LockedPlug) return false;
+ if (plug.GetSocket() && plug._lastSocket != socket)
+ {
+ plug.EjectPlug();
+ plug.ClearFromSocket();
+ }
+ plug.InsertPlug(socket);
+ return true;
+ }
+ }
public partial class Syncable : MonoBehaviour
{
public Plug GetPlugFromId(byte id)
@@ -55,5 +88,6 @@ namespace BoneSync.Sync.Components
}
return 255;
}
+
}
}
diff --git a/BoneSync/Sync/ObjectSyncCache.cs b/BoneSync/Sync/ObjectSyncCache.cs
index 10ff950..3f2380c 100644
--- a/BoneSync/Sync/ObjectSyncCache.cs
+++ b/BoneSync/Sync/ObjectSyncCache.cs
@@ -1,6 +1,7 @@
using BoneSync.Sync.Components;
using StressLevelZero.Interaction;
using StressLevelZero.Pool;
+using StressLevelZero.Props.Weapons;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -26,18 +27,27 @@ namespace BoneSync.Sync
return component.GetType().Namespace;
}
- private static bool IsSlzComponent(Component component)
+ private static bool IsCachableComponent(MonoBehaviour component)
{
- string ns = GetComponentNamespace(component);
- return ns.StartsWith("StressLevelZero") || ns.StartsWith("BoneSync");
+ if (component is InteractableHost) return true;
+ if (component is Poolee) return true;
+ if (component is Plug) return true;
+ if (component is Socket) return true;
+ if (component is AlignPlug) return true;
+ if (component is Gun) return true;
+ if (component is Magazine) return true;
+
+ return false;
+ //string ns = GetComponentNamespace(component);
+ //return ns.StartsWith("StressLevelZero") || ns.StartsWith("BoneSync");
}
- private static MonoBehaviour[] GetSLZComponents(Syncable syncable)
+ private static MonoBehaviour[] GetComponentsToCache(Syncable syncable)
{
MonoBehaviour[] components = syncable.GetComponentsInChildren(true);
List slzComponents = new List();
for (int i = 0; i < components.Length; i++)
{
- if (IsSlzComponent(components[i]))
+ if (IsCachableComponent(components[i]))
{
slzComponents.Add(components[i]);
}
@@ -46,7 +56,7 @@ namespace BoneSync.Sync
}
private static void _AddSyncableComponents(Syncable syncable)
{
- MonoBehaviour[] components = GetSLZComponents(syncable);
+ MonoBehaviour[] components = GetComponentsToCache(syncable);
_syncableToComponent[syncable] = components;
foreach (MonoBehaviour component in components)
{