Compare commits
2 Commits
ee1b827c91
...
1dce1960f6
| Author | SHA1 | Date | |
|---|---|---|---|
| 1dce1960f6 | |||
| ff70bad234 |
@@ -113,11 +113,18 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Networking\Messages\ObjectDamageMessage.cs" />
|
||||
<Compile Include="Networking\Messages\ObjectSyncMessage.cs" />
|
||||
<Compile Include="Networking\Messages\RegisterSyncableMessage.cs" />
|
||||
<Compile Include="Patching\CallPatchedMethod.cs" />
|
||||
<Compile Include="Patching\InteractableHostPatches.cs" />
|
||||
<Compile Include="Sync\Components\Syncable.cs" />
|
||||
<Compile Include="Patching\ObjectHealthPatches.cs" />
|
||||
<Compile Include="Sync\Components\SyncableBase.cs" />
|
||||
<Compile Include="Sync\Components\SyncableDamage.cs" />
|
||||
<Compile Include="Sync\Components\SyncableNetworking.cs" />
|
||||
<Compile Include="Sync\Components\SyncablePhysics.cs" />
|
||||
<Compile Include="Sync\ObjectSync.cs" />
|
||||
<Compile Include="Sync\ObjectSyncCache.cs" />
|
||||
<Compile Include="Sync\PlayerSync.cs" />
|
||||
<Compile Include="Facepunch.Steamworks\Callbacks\CallResult.cs" />
|
||||
<Compile Include="Facepunch.Steamworks\Callbacks\ICallbackData.cs" />
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using StressLevelZero;
|
||||
using StressLevelZero.Combat;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -52,6 +53,16 @@ namespace BoneSync.Networking
|
||||
return value;
|
||||
}
|
||||
|
||||
public void WriteBool(bool value)
|
||||
{
|
||||
WriteByte((byte)(value ? 1 : 0));
|
||||
}
|
||||
|
||||
public bool ReadBool()
|
||||
{
|
||||
return ReadByte() == 1;
|
||||
}
|
||||
|
||||
public void WriteInt(int value)
|
||||
{
|
||||
WriteBytes(BitConverter.GetBytes(value));
|
||||
@@ -168,5 +179,38 @@ namespace BoneSync.Networking
|
||||
scale = scale
|
||||
};
|
||||
}
|
||||
|
||||
public void WriteEnum<T>(T value) where T : Enum
|
||||
{
|
||||
WriteByte((byte)(object)value);
|
||||
}
|
||||
public T ReadEnum<T>() where T : Enum
|
||||
{
|
||||
return (T)(object)ReadByte();
|
||||
}
|
||||
|
||||
public void WriteSLZAttack(Attack attack)
|
||||
{
|
||||
WriteEnum(attack.attackType);
|
||||
WriteFloat(attack.damage);
|
||||
}
|
||||
|
||||
public void WriteMatrix4x4(UnityEngine.Matrix4x4 matrix)
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
WriteFloat(matrix[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public UnityEngine.Matrix4x4 ReadMatrix4x4()
|
||||
{
|
||||
UnityEngine.Matrix4x4 matrix = new UnityEngine.Matrix4x4();
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
matrix[i] = ReadFloat();
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
80
BoneSync/Networking/Messages/ObjectDamageMessage.cs
Normal file
80
BoneSync/Networking/Messages/ObjectDamageMessage.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using StressLevelZero.Combat;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BoneSync.Networking.Messages
|
||||
{
|
||||
public struct ObjectHealthInfo
|
||||
{
|
||||
public float _health;
|
||||
public int _hits;
|
||||
public Vector3 normal;
|
||||
public float damage;
|
||||
public bool crit;
|
||||
public AttackType attackType;
|
||||
public ObjectHealthInfo(float health, int hits, Vector3 normal, float damage, bool crit, AttackType attackType)
|
||||
{
|
||||
_health = health;
|
||||
_hits = hits;
|
||||
this.normal = normal;
|
||||
this.damage = damage;
|
||||
this.crit = crit;
|
||||
this.attackType = attackType;
|
||||
}
|
||||
}
|
||||
public enum ObjectDamageType
|
||||
{
|
||||
Unknown = 0,
|
||||
SyncHealth = 1,
|
||||
DestructibleTakeDamage = 2,
|
||||
PropHealthTakeDamage = 3,
|
||||
}
|
||||
public struct ObjectDamageInfo
|
||||
{
|
||||
public ushort objectId;
|
||||
public ObjectDamageType eventType;
|
||||
public ObjectHealthInfo objectHealthInfo;
|
||||
}
|
||||
|
||||
[PacketType(PacketType.ObjectEvent), PacketReliability(PacketReliability.Reliable)]
|
||||
public class ObjectDamageMessage : NetworkMessage
|
||||
{
|
||||
public ObjectDamageInfo objectEventInfo => _objectEventInfo;
|
||||
private ObjectDamageInfo _objectEventInfo;
|
||||
|
||||
public ObjectDamageMessage(ObjectDamageInfo objectEventInfo)
|
||||
{
|
||||
_objectEventInfo = objectEventInfo;
|
||||
byteEncoder.WriteUShort(_objectEventInfo.objectId);
|
||||
byteEncoder.WriteEnum(_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
|
||||
byteEncoder.WriteVector3(_objectEventInfo.objectHealthInfo.normal);
|
||||
byteEncoder.WriteFloat(_objectEventInfo.objectHealthInfo.damage);
|
||||
byteEncoder.WriteBool(_objectEventInfo.objectHealthInfo.crit);
|
||||
}
|
||||
|
||||
public ObjectDamageMessage(Packet packet)
|
||||
{
|
||||
byteEncoder.WriteBytes(packet.Data);
|
||||
_objectEventInfo.objectId = byteEncoder.ReadUShort();
|
||||
_objectEventInfo.eventType = byteEncoder.ReadEnum<ObjectDamageType>();
|
||||
_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
|
||||
_objectEventInfo.objectHealthInfo.normal = byteEncoder.ReadVector3();
|
||||
_objectEventInfo.objectHealthInfo.damage = byteEncoder.ReadFloat();
|
||||
_objectEventInfo.objectHealthInfo.crit = byteEncoder.ReadBool();
|
||||
}
|
||||
|
||||
public override void Execute()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ namespace BoneSync.Networking.Messages
|
||||
{
|
||||
public SimpleTransform transform;
|
||||
public Vector3 velocity;
|
||||
public Vector3 angularVelocity;
|
||||
}
|
||||
public struct ObjectSyncMessageData
|
||||
{
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace BoneSync.Networking.Messages
|
||||
public RegisterSyncableMessage(RegisterSyncableInfo info)
|
||||
{
|
||||
_info = info;
|
||||
byteEncoder.WriteByte((byte)_info.type);
|
||||
byteEncoder.WriteEnum<RegisterSyncType>(_info.type);
|
||||
byteEncoder.WriteString(_info.transformPath);
|
||||
byteEncoder.WriteUlong(_info.ownerId);
|
||||
byteEncoder.WriteUShort(_info.id);
|
||||
@@ -38,7 +38,7 @@ namespace BoneSync.Networking.Messages
|
||||
public RegisterSyncableMessage(Packet packet)
|
||||
{
|
||||
byteEncoder.WriteBytes(packet.Data);
|
||||
_info.type = (RegisterSyncType)byteEncoder.ReadByte();
|
||||
_info.type = byteEncoder.ReadEnum<RegisterSyncType>();
|
||||
_info.transformPath = byteEncoder.ReadString();
|
||||
_info.ownerId = byteEncoder.ReadUlong();
|
||||
_info.id = byteEncoder.ReadUShort();
|
||||
|
||||
@@ -13,5 +13,6 @@ namespace BoneSync.Networking
|
||||
PlayerSync = 2,
|
||||
RegisterSyncable = 3,
|
||||
ObjectSync = 4,
|
||||
ObjectEvent = 5,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,17 +72,18 @@ namespace BoneSync.Networking.Transport
|
||||
return processed > 0;
|
||||
}
|
||||
|
||||
public void SendP2P(SteamId peer, byte[] data)
|
||||
public void SendP2P(SteamId peer, byte[] data, P2PSend sendType)
|
||||
{
|
||||
if (peer == BoneSync.lobby.GetLocalId())
|
||||
{
|
||||
//MelonLogger.Msg("Trying to send packet to self");
|
||||
return;
|
||||
}
|
||||
SteamNetworking.SendP2PPacket(peer, data, data.Length, 0, P2PSend.Reliable);
|
||||
SteamNetworking.SendP2PPacket(peer, data, data.Length, 0, sendType);
|
||||
}
|
||||
public override void Send(Packet packet)
|
||||
{
|
||||
P2PSend sendType = (P2PSend)packet.Info.reliability;
|
||||
LobbyManager.LobbyManager _instance = BoneSync.lobby;
|
||||
if (_instance == null)
|
||||
{
|
||||
@@ -93,14 +94,14 @@ namespace BoneSync.Networking.Transport
|
||||
{
|
||||
foreach (SteamId peer in _instance.GetPeers())
|
||||
{
|
||||
SendP2P(peer, packet.ToBytes());
|
||||
SendP2P(peer, packet.ToBytes(), sendType);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
SendP2P(packet.Info.receiverId, packet.ToBytes());
|
||||
SendP2P(packet.Info.receiverId, packet.ToBytes(), sendType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
42
BoneSync/Patching/CallPatchedMethod.cs
Normal file
42
BoneSync/Patching/CallPatchedMethod.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using StressLevelZero.Combat;
|
||||
using StressLevelZero.Pool;
|
||||
using StressLevelZero.Props;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BoneSync.Patching
|
||||
{
|
||||
public static class CallPatchedMethods
|
||||
{
|
||||
public static bool allowPatchedMethodCall
|
||||
{
|
||||
private set;
|
||||
get;
|
||||
}
|
||||
public static void TakeDamage(ObjectDestructable __instance, ref Vector3 normal, ref float damage, ref bool crit, ref 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)
|
||||
{
|
||||
allowPatchedMethodCall = true;
|
||||
__instance.TAKEDAMAGE(damage, crit, attackType);
|
||||
allowPatchedMethodCall = false;
|
||||
}
|
||||
|
||||
public static GameObject PoolSpawn(Pool __instance, ref Vector3 position, ref Quaternion rotation, ref Il2CppSystem.Nullable<Vector3> scale, ref Il2CppSystem.Nullable<bool> autoEnable)
|
||||
{
|
||||
allowPatchedMethodCall = true;
|
||||
GameObject result = __instance.Spawn(position, rotation, scale, autoEnable);
|
||||
allowPatchedMethodCall = false;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
64
BoneSync/Patching/ObjectHealthPatches.cs
Normal file
64
BoneSync/Patching/ObjectHealthPatches.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using BoneSync.Networking.Messages;
|
||||
using BoneSync.Sync;
|
||||
using BoneSync.Sync.Components;
|
||||
using HarmonyLib;
|
||||
using StressLevelZero.Combat;
|
||||
using StressLevelZero.Props;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BoneSync.Patching
|
||||
{
|
||||
[HarmonyPatch(typeof(ObjectDestructable))]
|
||||
public class ObjectDestructablePatches
|
||||
{
|
||||
[HarmonyPatch(nameof(ObjectDestructable.TakeDamage))]
|
||||
[HarmonyPrefix]
|
||||
private static bool TakeDamagePatch(ObjectDestructable __instance, ref Vector3 normal, ref float damage, ref bool crit, ref AttackType attackType)
|
||||
{
|
||||
if (CallPatchedMethods.allowPatchedMethodCall) return true;
|
||||
MelonLoader.MelonLogger.Msg("ObjectDestructable.TakeDamage: " + damage);
|
||||
Syncable syncable = ObjectSync.GetSyncableFromCache(__instance.gameObject);
|
||||
if (syncable != null)
|
||||
{
|
||||
if (!syncable.Registered) return true;
|
||||
MelonLoader.MelonLogger.Msg("Patch: ObjectDestructable.TakeDamage: " + damage + " " + syncable.gameObject.name);
|
||||
ObjectHealthInfo objectHealthInfo = new ObjectHealthInfo(__instance._health, __instance._hits, normal, damage, crit, attackType);
|
||||
|
||||
ObjectSync.SendObjectDamageMessage(syncable, ObjectDamageType.DestructibleTakeDamage, objectHealthInfo);
|
||||
|
||||
return false; // prevent networked objects from taking damage locally
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(Prop_Health))]
|
||||
public class PropHealthPatches
|
||||
{
|
||||
[HarmonyPatch(nameof(Prop_Health.TAKEDAMAGE))]
|
||||
[HarmonyPrefix]
|
||||
private static bool TakeDamagePatch(Prop_Health __instance, ref float damage, ref bool crit, ref AttackType attackType)
|
||||
{
|
||||
if (CallPatchedMethods.allowPatchedMethodCall) return true;
|
||||
MelonLoader.MelonLogger.Msg("Prop_Health.TAKEDAMAGE: " + damage);
|
||||
Syncable syncable = ObjectSync.GetSyncableFromCache(__instance.gameObject);
|
||||
if (syncable != null)
|
||||
{
|
||||
if (!syncable.Registered) return true;
|
||||
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);
|
||||
|
||||
ObjectSync.SendObjectDamageMessage(syncable, ObjectDamageType.PropHealthTakeDamage, objectHealthInfo);
|
||||
|
||||
return false; // prevent networked objects from taking damage locally
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using HarmonyLib;
|
||||
@@ -11,31 +12,31 @@ using UnityEngine;
|
||||
|
||||
namespace BoneSync.Patching
|
||||
{
|
||||
/*
|
||||
|
||||
[HarmonyPatch(typeof(Pool))]
|
||||
internal class PoolPatches
|
||||
{
|
||||
|
||||
[HarmonyPatch(nameof(Pool.Spawn))]
|
||||
[HarmonyPostfix]
|
||||
private static void SpawnPatch(Pool __instance, ref GameObject __result)
|
||||
private static void SpawnPatchPost(Pool __instance, ref GameObject __result)
|
||||
{
|
||||
MelonLogger.Msg("Spawned object: " + __result.name);
|
||||
//MelonLogger.Msg("Spawned object: " + __result.name);
|
||||
}
|
||||
|
||||
[HarmonyPatch(nameof(Pool.FlagPooleeForRespawn))]
|
||||
[HarmonyPostfix]
|
||||
private static void FlagPooleeForRespawnPatch(Pool __instance, ref GameObject p)
|
||||
[HarmonyPatch(nameof(Pool.Spawn))]
|
||||
[HarmonyPrefix]
|
||||
private static bool SpawnPatchPre(Pool __instance, ref Vector3 position, ref Quaternion rotation, ref Il2CppSystem.Nullable<Vector3> scale, ref Il2CppSystem.Nullable<bool> autoEnable)
|
||||
{
|
||||
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);
|
||||
if (CallPatchedMethods.allowPatchedMethodCall) return true;
|
||||
|
||||
if (BoneSync.lobby.IsConnected())
|
||||
{
|
||||
MelonLogger.Msg("Patched Spawning object in pool: " + __instance.name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,12 @@ using BoneSync.Networking.Messages;
|
||||
using BoneSync.Networking;
|
||||
using StressLevelZero.Data;
|
||||
using System.Collections;
|
||||
using StressLevelZero.Props;
|
||||
using BoneSync.Patching;
|
||||
using StressLevelZero.Props.Weapons;
|
||||
using StressLevelZero.AI;
|
||||
using PuppetMasta;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
|
||||
namespace BoneSync.Sync.Components
|
||||
@@ -45,13 +51,13 @@ namespace BoneSync.Sync.Components
|
||||
}
|
||||
|
||||
[RegisterTypeInIl2Cpp]
|
||||
public class Syncable : MonoBehaviour
|
||||
public partial class Syncable : MonoBehaviour
|
||||
{
|
||||
public const int SYNC_FPS = 20;
|
||||
|
||||
public static List<Syncable> syncablesCache = new List<Syncable>();
|
||||
public static Dictionary<GameObject, Syncable> syncablesCache = new Dictionary<GameObject, Syncable>();
|
||||
public Syncable(IntPtr intPtr) : base(intPtr) {
|
||||
syncablesCache.Add(this);
|
||||
syncablesCache[gameObject] = this;
|
||||
}
|
||||
|
||||
private bool _syncCoroutineRunning;
|
||||
@@ -62,7 +68,7 @@ namespace BoneSync.Sync.Components
|
||||
get;
|
||||
}
|
||||
private ushort _syncId;
|
||||
private ulong _lastSyncTime;
|
||||
private float _lastSyncTime;
|
||||
|
||||
private bool _attemptedRegister;
|
||||
|
||||
@@ -70,6 +76,15 @@ namespace BoneSync.Sync.Components
|
||||
public bool isStale => Time.time - _lastSyncTime > 5f;
|
||||
public bool isOwner => _ownerId == BoneSync.lobby.GetLocalId();
|
||||
|
||||
public bool ShouldSendSync()
|
||||
{
|
||||
if (!Registered) return false;
|
||||
if (!isOwner) return false;
|
||||
if (isStale) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public ushort GetSyncId() => _syncId;
|
||||
public void SetSyncId(ushort id)
|
||||
{
|
||||
@@ -78,84 +93,28 @@ namespace BoneSync.Sync.Components
|
||||
ObjectSyncCache.UpdateSyncId(this);
|
||||
}
|
||||
|
||||
public InteractableHost interactableHost;
|
||||
public InteractableHostManager interactableManager;
|
||||
public Poolee poolee;
|
||||
public InteractableHost interactableHost { private set; get; }
|
||||
public InteractableHostManager interactableManager { private set; get; }
|
||||
public Poolee poolee { private set; get; }
|
||||
|
||||
private Prop_Health propHealth;
|
||||
private ObjectDestructable objectDestructable;
|
||||
|
||||
private Rigidbody[] rigidbodies;
|
||||
private Transform[] transforms;
|
||||
private Transform[] _transforms;
|
||||
|
||||
private void SetKinematic(bool kinematic)
|
||||
{
|
||||
foreach (Rigidbody rb in rigidbodies)
|
||||
{
|
||||
rb.isKinematic = kinematic;
|
||||
}
|
||||
}
|
||||
private Gun gun;
|
||||
private Magazine magazine;
|
||||
|
||||
public ObjectSyncTransform[] GetObjectSyncTransforms()
|
||||
{
|
||||
ObjectSyncTransform[] objectSyncTransforms = new ObjectSyncTransform[transforms.Length];
|
||||
for (int i = 0; i < transforms.Length; i++)
|
||||
{
|
||||
objectSyncTransforms[i] = new ObjectSyncTransform()
|
||||
{
|
||||
transform = new SimpleTransform(transforms[i]),
|
||||
velocity = Vector3.zero
|
||||
};
|
||||
}
|
||||
return objectSyncTransforms;
|
||||
}
|
||||
private Plug[] plugs;
|
||||
|
||||
public void ApplyObjectSyncTransforms(ObjectSyncTransform[] objectSyncTransforms)
|
||||
{
|
||||
if (objectSyncTransforms.Length != transforms.Length)
|
||||
{
|
||||
MelonLogger.Warning("ObjectSyncTransforms length mismatch: " + objectSyncTransforms.Length + " != " + transforms.Length);
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < objectSyncTransforms.Length; i++)
|
||||
{
|
||||
ObjectSyncTransform objectSyncTransform = objectSyncTransforms[i];
|
||||
transforms[i].ApplySimpleTransform(objectSyncTransform.transform);
|
||||
}
|
||||
}
|
||||
private AIBrain aiBrain;
|
||||
private PuppetMaster puppetMaster;
|
||||
|
||||
public async Task SyncCoroutineAsync()
|
||||
{
|
||||
MelonLogger.Msg("Running sync coroutine for: " + gameObject.name);
|
||||
if (_syncCoroutineRunning) return;
|
||||
_syncCoroutineRunning = true;
|
||||
while (isOwner)
|
||||
{
|
||||
MelonLogger.Msg("Sending object sync message for: " + gameObject.name);
|
||||
ObjectSync.SendObjectSyncMessage(this);
|
||||
await Task.Delay( GetSyncId() == 0 ? 1000 : 1000 / SYNC_FPS);
|
||||
}
|
||||
_syncCoroutineRunning = false;
|
||||
return;
|
||||
}
|
||||
|
||||
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()
|
||||
@@ -178,13 +137,18 @@ namespace BoneSync.Sync.Components
|
||||
interactableManager = GetComponent<InteractableHostManager>();
|
||||
interactableHost = GetComponent<InteractableHost>();
|
||||
poolee = GetComponent<Poolee>();
|
||||
rigidbodies = GetComponentsInChildren<Rigidbody>();
|
||||
propHealth = GetComponent<Prop_Health>();
|
||||
objectDestructable = GetComponent<ObjectDestructable>();
|
||||
gun = GetComponent<Gun>();
|
||||
magazine = GetComponent<Magazine>();
|
||||
plugs = GetComponentsInChildren<Plug>();
|
||||
//rigidbodies = GetComponentsInChildren<Rigidbody>();
|
||||
UpdateTransformList();
|
||||
|
||||
ObjectSyncCache.AddSyncable(this);
|
||||
}
|
||||
|
||||
public bool ShouldSync()
|
||||
public bool CanBeSynced()
|
||||
{
|
||||
FindComponents();
|
||||
if (interactableManager && interactableManager.hosts.Count > 0)
|
||||
@@ -199,8 +163,15 @@ namespace BoneSync.Sync.Components
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnDestroy()
|
||||
{
|
||||
DiscardSyncable();
|
||||
MelonLogger.Msg("Syncable destroyed: " + transform.GetPath());
|
||||
}
|
||||
|
||||
public void DiscardSyncable()
|
||||
{
|
||||
syncablesCache.Remove(gameObject);
|
||||
ObjectSyncCache.RemoveSyncable(this);
|
||||
Destroy(this);
|
||||
}
|
||||
@@ -216,34 +187,14 @@ namespace BoneSync.Sync.Components
|
||||
MelonLogger.Warning("Registered Syncable disabled: " + transform.GetPath());
|
||||
}
|
||||
|
||||
public void SetOwner(ulong ownerId)
|
||||
{
|
||||
_ownerId = ownerId;
|
||||
MelonLogger.Msg("Set owner for " + gameObject.name + " to " + ownerId);
|
||||
_ = SyncCoroutineAsync();
|
||||
UpdateKinematic();
|
||||
}
|
||||
|
||||
private void UpdateKinematic()
|
||||
{
|
||||
SetKinematic(_ownerId != BoneSync.lobby.GetLocalId() && Registered);
|
||||
}
|
||||
|
||||
private void _SendRegisterSync()
|
||||
{
|
||||
MelonLogger.Msg("Registering syncable object: " + gameObject.name);
|
||||
SetOwner(BoneSync.lobby.GetLocalId());
|
||||
SetSyncId(ObjectSync.SendRegisterSyncableMessage(this));
|
||||
}
|
||||
public void RegisterSyncable()
|
||||
{
|
||||
if (!BoneSync.lobby.IsConnected()) return;
|
||||
if (_attemptedRegister) return;
|
||||
if (Registered) return;
|
||||
if (!ShouldSync()) return;
|
||||
if (!CanBeSynced()) return;
|
||||
_attemptedRegister = true;
|
||||
_SendRegisterSync();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
58
BoneSync/Sync/Components/SyncableDamage.cs
Normal file
58
BoneSync/Sync/Components/SyncableDamage.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using BoneSync.Networking.Messages;
|
||||
using BoneSync.Patching;
|
||||
using MelonLoader;
|
||||
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
|
||||
{
|
||||
private void SetHealth(float health, int hits = 0)
|
||||
{
|
||||
if (gameObject.activeSelf == false && health > 0)
|
||||
{
|
||||
gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
if (propHealth)
|
||||
{
|
||||
propHealth.cur_Health = health;
|
||||
propHealth.hits = hits;
|
||||
}
|
||||
if (objectDestructable)
|
||||
{
|
||||
objectDestructable._health = health;
|
||||
objectDestructable._hits = hits;
|
||||
}
|
||||
}
|
||||
|
||||
public void Damage(ObjectDamageInfo damageInfo)
|
||||
{
|
||||
ObjectHealthInfo healthInfo = damageInfo.objectHealthInfo;
|
||||
SetHealth(healthInfo._health, healthInfo._hits); // always set health first
|
||||
|
||||
ObjectDamageType eventType = damageInfo.eventType;
|
||||
if (eventType == ObjectDamageType.SyncHealth) return;
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
if (eventType == ObjectDamageType.PropHealthTakeDamage && propHealth)
|
||||
{
|
||||
MelonLogger.Msg("NetworkPropHealthTakeDamage: " + healthInfo.damage);
|
||||
CallPatchedMethods.TakeDamage(propHealth, ref healthInfo.damage, ref healthInfo.crit, ref healthInfo.attackType);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
46
BoneSync/Sync/Components/SyncableNetworking.cs
Normal file
46
BoneSync/Sync/Components/SyncableNetworking.cs
Normal 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;
|
||||
|
||||
namespace BoneSync.Sync.Components
|
||||
{
|
||||
// SyncableNetworking.cs
|
||||
public partial class Syncable : MonoBehaviour
|
||||
{
|
||||
private void SendObjectSync()
|
||||
{
|
||||
_lastSyncTime = Time.time;
|
||||
ObjectSync.SendObjectSyncMessage(this);
|
||||
}
|
||||
public async Task SyncCoroutineAsync()
|
||||
{
|
||||
MelonLogger.Msg("Running sync coroutine for: " + transform.GetPath());
|
||||
if (_syncCoroutineRunning) return;
|
||||
_syncCoroutineRunning = true;
|
||||
while (isOwner)
|
||||
{
|
||||
if (ShouldSendSync()) SendObjectSync();
|
||||
await Task.Delay(!Registered ? 1000 : 1000 / SYNC_FPS);
|
||||
}
|
||||
_syncCoroutineRunning = false;
|
||||
return;
|
||||
}
|
||||
public void SetOwner(ulong ownerId)
|
||||
{
|
||||
MelonLogger.Msg("Setting owner for " + _syncId + " to " + ownerId);
|
||||
_ownerId = ownerId;
|
||||
_ = SyncCoroutineAsync();
|
||||
UpdateKinematic();
|
||||
}
|
||||
private void _SendRegisterSync()
|
||||
{
|
||||
MelonLogger.Msg("Registering syncable object: " + gameObject.name);
|
||||
SetOwner(BoneSync.lobby.GetLocalId());
|
||||
SetSyncId(ObjectSync.SendRegisterSyncableMessage(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
89
BoneSync/Sync/Components/SyncablePhysics.cs
Normal file
89
BoneSync/Sync/Components/SyncablePhysics.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using BoneSync.Networking;
|
||||
using BoneSync.Networking.Messages;
|
||||
using BoneSync.Patching;
|
||||
using MelonLoader;
|
||||
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
|
||||
{
|
||||
private void SetKinematic(bool kinematic)
|
||||
{
|
||||
foreach (Rigidbody rb in rigidbodies)
|
||||
{
|
||||
rb.isKinematic = kinematic;
|
||||
}
|
||||
}
|
||||
|
||||
public ObjectSyncTransform[] GetObjectSyncTransforms()
|
||||
{
|
||||
ObjectSyncTransform[] objectSyncTransforms = new ObjectSyncTransform[rigidbodies.Length];
|
||||
for (int i = 0; i < _transforms.Length; i++)
|
||||
{
|
||||
objectSyncTransforms[i] = new ObjectSyncTransform()
|
||||
{
|
||||
transform = new SimpleTransform(_transforms[i]),
|
||||
velocity = Vector3.zero
|
||||
};
|
||||
}
|
||||
return objectSyncTransforms;
|
||||
}
|
||||
|
||||
public void ApplyObjectSyncTransforms(ObjectSyncTransform[] objectSyncTransforms)
|
||||
{
|
||||
if (objectSyncTransforms.Length != rigidbodies.Length)
|
||||
{
|
||||
MelonLogger.Warning("ObjectSyncTransforms length mismatch: " + objectSyncTransforms.Length + " != " + _transforms.Length);
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < objectSyncTransforms.Length; i++)
|
||||
{
|
||||
ObjectSyncTransform objectSyncTransform = objectSyncTransforms[i];
|
||||
rigidbodies[i].angularVelocity = objectSyncTransform.angularVelocity;
|
||||
rigidbodies[i].velocity = objectSyncTransform.velocity;
|
||||
rigidbodies[i].position = objectSyncTransform.transform.position;
|
||||
rigidbodies[i].rotation = objectSyncTransform.transform.rotation;
|
||||
_transforms[i].localScale = objectSyncTransform.transform.scale;
|
||||
//_transforms[i].ApplySimpleTransform(objectSyncTransform.transform);
|
||||
}
|
||||
}
|
||||
|
||||
private Rigidbody[] UpdateRigidbodyList()
|
||||
{
|
||||
if (interactableManager)
|
||||
{
|
||||
return interactableManager.hosts.Select(host => host.rb).ToArray();
|
||||
}
|
||||
if (interactableHost)
|
||||
{
|
||||
return new Rigidbody[] { interactableHost.rb };
|
||||
}
|
||||
if (poolee)
|
||||
{
|
||||
return new Rigidbody[] { poolee.GetComponentInChildren<Rigidbody>() };
|
||||
}
|
||||
|
||||
return new Rigidbody[0];
|
||||
}
|
||||
|
||||
private void UpdateTransformList()
|
||||
{
|
||||
// get non-null rigidbodies
|
||||
Rigidbody[] rbs = UpdateRigidbodyList().Where(rb => rb != null).ToArray();
|
||||
rigidbodies = rbs;
|
||||
_transforms = rbs.Select(rb => rb.transform).ToArray();
|
||||
}
|
||||
|
||||
private void UpdateKinematic()
|
||||
{
|
||||
SetKinematic(_ownerId != BoneSync.lobby.GetLocalId() && Registered);
|
||||
}
|
||||
|
||||
// on collision
|
||||
}
|
||||
}
|
||||
@@ -9,138 +9,10 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace BoneSync.Sync
|
||||
{
|
||||
|
||||
public static class ObjectSyncCache
|
||||
{
|
||||
private static Dictionary<string, Syncable> _pathToSyncable = new Dictionary<string, Syncable>();
|
||||
private static Dictionary<ushort, Syncable> _idToSyncable = new Dictionary<ushort, Syncable>();
|
||||
private static Dictionary<Poolee, Syncable> _pooleeToSyncable = new Dictionary<Poolee, Syncable>();
|
||||
private static Dictionary<InteractableHost, Syncable> _interactableHostToSyncable = new Dictionary<InteractableHost, Syncable>();
|
||||
private static Dictionary<InteractableHostManager, Syncable> _interactableHostManagerToSyncable = new Dictionary<InteractableHostManager, Syncable>();
|
||||
|
||||
|
||||
public static void AddSyncable(Syncable syncable)
|
||||
{
|
||||
string path = syncable.transform.GetPath();
|
||||
if (path != null && path != "")
|
||||
{
|
||||
_pathToSyncable[path] = syncable;
|
||||
}
|
||||
if (syncable.GetSyncId() != 0)
|
||||
{
|
||||
_idToSyncable[syncable.GetSyncId()] = syncable;
|
||||
}
|
||||
if (syncable.interactableHost)
|
||||
{
|
||||
_interactableHostToSyncable[syncable.interactableHost] = syncable;
|
||||
}
|
||||
if (syncable.interactableManager)
|
||||
{
|
||||
_interactableHostManagerToSyncable[syncable.interactableManager] = syncable;
|
||||
}
|
||||
if (syncable.poolee)
|
||||
{
|
||||
_pooleeToSyncable[syncable.poolee] = syncable;
|
||||
}
|
||||
}
|
||||
|
||||
public static void RemoveSyncable(Syncable syncable)
|
||||
{
|
||||
if (syncable.transform)
|
||||
{
|
||||
_pathToSyncable.Remove(syncable.transform.GetPath());
|
||||
}
|
||||
if (syncable.GetSyncId() != 0)
|
||||
{
|
||||
_idToSyncable.Remove(syncable.GetSyncId());
|
||||
}
|
||||
if (syncable.interactableHost)
|
||||
{
|
||||
_interactableHostToSyncable.Remove(syncable.interactableHost);
|
||||
}
|
||||
if (syncable.interactableManager)
|
||||
{
|
||||
_interactableHostManagerToSyncable.Remove(syncable.interactableManager);
|
||||
}
|
||||
if (syncable.poolee)
|
||||
{
|
||||
_pooleeToSyncable.Remove(syncable.poolee);
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateSyncId(Syncable syncable)
|
||||
{
|
||||
// remove other enties where value is the same
|
||||
foreach (KeyValuePair<ushort, Syncable> entry in _idToSyncable)
|
||||
{
|
||||
if (entry.Value == syncable)
|
||||
{
|
||||
_idToSyncable.Remove(entry.Key);
|
||||
}
|
||||
}
|
||||
ushort id = syncable.GetSyncId();
|
||||
if (_idToSyncable.ContainsKey(id))
|
||||
{
|
||||
_idToSyncable.Remove(id);
|
||||
}
|
||||
_idToSyncable[id] = syncable;
|
||||
}
|
||||
|
||||
public static Syncable GetSyncable(string path)
|
||||
{
|
||||
if (_pathToSyncable.ContainsKey(path))
|
||||
{
|
||||
return _pathToSyncable[path];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Syncable GetSyncable(ushort id)
|
||||
{
|
||||
if (_idToSyncable.ContainsKey(id))
|
||||
{
|
||||
return _idToSyncable[id];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Syncable GetSyncable(Poolee poolee)
|
||||
{
|
||||
if (_pooleeToSyncable.ContainsKey(poolee))
|
||||
{
|
||||
return _pooleeToSyncable[poolee];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Syncable GetSyncable(InteractableHost interactableHost)
|
||||
{
|
||||
if (_interactableHostToSyncable.ContainsKey(interactableHost))
|
||||
{
|
||||
return _interactableHostToSyncable[interactableHost];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Syncable GetSyncable(InteractableHostManager interactableHostManager)
|
||||
{
|
||||
if (_interactableHostManagerToSyncable.ContainsKey(interactableHostManager))
|
||||
{
|
||||
return _interactableHostManagerToSyncable[interactableHostManager];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void DISCARD_ALL_SYNCABLES() {
|
||||
foreach (Syncable syncable in Syncable.syncablesCache)
|
||||
{
|
||||
syncable.DiscardSyncable();
|
||||
}
|
||||
}
|
||||
}
|
||||
internal class ObjectSync
|
||||
{
|
||||
private static ushort _nextSyncableId = 1;
|
||||
@@ -201,7 +73,8 @@ namespace BoneSync.Sync
|
||||
|
||||
public static void SendObjectSyncMessage(Syncable syncable)
|
||||
{
|
||||
MelonLogger.Msg("Sending object sync message for: " + syncable.transform.name);
|
||||
if (!syncable.Registered) return;
|
||||
//MelonLogger.Msg("Sending object sync message for: " + syncable.transform.name);
|
||||
ObjectSyncTransform[] objectSyncTransforms = syncable.GetObjectSyncTransforms();
|
||||
|
||||
ObjectSyncMessageData data = new ObjectSyncMessageData()
|
||||
@@ -215,6 +88,9 @@ namespace BoneSync.Sync
|
||||
}
|
||||
private static Syncable _MakeOrGetSyncable(GameObject gameObject, bool deleteSubSyncabled = true)
|
||||
{
|
||||
//Scene scene = gameObject.scene;
|
||||
//MelonLogger.Msg("Making or getting syncable for: " + gameObject.name + " in scene: " + scene.name);
|
||||
|
||||
Syncable[] subSyncables = gameObject.GetComponentsInChildren<Syncable>();
|
||||
Syncable syncable = gameObject.GetComponent<Syncable>();
|
||||
|
||||
@@ -238,6 +114,16 @@ namespace BoneSync.Sync
|
||||
return syncable;
|
||||
}
|
||||
|
||||
public static Syncable GetSyncableFromCache(GameObject gameObject)
|
||||
{
|
||||
bool success = Syncable.syncablesCache.TryGetValue(gameObject, out Syncable syncable);
|
||||
if (!success)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return syncable;
|
||||
}
|
||||
|
||||
public static Syncable MakeOrGetSyncable(InteractableHost interactableHost)
|
||||
{
|
||||
if (interactableHost.manager) return MakeOrGetSyncable(interactableHost.manager);
|
||||
@@ -279,10 +165,37 @@ namespace BoneSync.Sync
|
||||
Syncable syncable = ObjectSyncCache.GetSyncable(data.objectId);
|
||||
if (syncable == null)
|
||||
{
|
||||
MelonLogger.Msg("Syncable not found for id: " + data.objectId);
|
||||
MelonLogger.Msg("SyncEvent: Syncable not found for id: " + data.objectId);
|
||||
return;
|
||||
}
|
||||
syncable.ApplyObjectSyncTransforms(data.objectSyncTransforms);
|
||||
}
|
||||
|
||||
public static void OnObjectDamageMessage(ObjectDamageMessage damageMessge)
|
||||
{
|
||||
|
||||
ObjectDamageInfo damageInfo = damageMessge.objectEventInfo;
|
||||
if (damageInfo.objectId == 0) return;
|
||||
Syncable syncable = ObjectSyncCache.GetSyncable(damageInfo.objectId);
|
||||
if (syncable == null)
|
||||
{
|
||||
MelonLogger.Msg("DamageEvent: Syncable not found for id: " + damageInfo.objectId);
|
||||
return;
|
||||
}
|
||||
syncable.Damage(damageInfo);
|
||||
}
|
||||
|
||||
public static void SendObjectDamageMessage(Syncable syncable, ObjectDamageType damageType, ObjectHealthInfo healthInfo)
|
||||
{
|
||||
ObjectDamageInfo damageInfo = new ObjectDamageInfo()
|
||||
{
|
||||
objectId = syncable.GetSyncId(),
|
||||
objectHealthInfo = healthInfo,
|
||||
eventType = damageType,
|
||||
};
|
||||
ObjectDamageMessage message = new ObjectDamageMessage(damageInfo);
|
||||
message.Broadcast();
|
||||
message.Execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
140
BoneSync/Sync/ObjectSyncCache.cs
Normal file
140
BoneSync/Sync/ObjectSyncCache.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
using BoneSync.Sync.Components;
|
||||
using StressLevelZero.Interaction;
|
||||
using StressLevelZero.Pool;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BoneSync.Sync
|
||||
{
|
||||
public static class ObjectSyncCache
|
||||
{
|
||||
private static Dictionary<string, Syncable> _pathToSyncable = new Dictionary<string, Syncable>();
|
||||
private static Dictionary<ushort, Syncable> _idToSyncable = new Dictionary<ushort, Syncable>();
|
||||
private static Dictionary<Poolee, Syncable> _pooleeToSyncable = new Dictionary<Poolee, Syncable>();
|
||||
private static Dictionary<InteractableHost, Syncable> _interactableHostToSyncable = new Dictionary<InteractableHost, Syncable>();
|
||||
private static Dictionary<InteractableHostManager, Syncable> _interactableHostManagerToSyncable = new Dictionary<InteractableHostManager, Syncable>();
|
||||
|
||||
public static void AddSyncable(Syncable syncable)
|
||||
{
|
||||
string path = syncable.transform.GetPath();
|
||||
if (path != null && path != "")
|
||||
{
|
||||
_pathToSyncable[path] = syncable;
|
||||
}
|
||||
if (syncable.GetSyncId() != 0)
|
||||
{
|
||||
_idToSyncable[syncable.GetSyncId()] = syncable;
|
||||
}
|
||||
if (syncable.interactableHost)
|
||||
{
|
||||
_interactableHostToSyncable[syncable.interactableHost] = syncable;
|
||||
}
|
||||
if (syncable.interactableManager)
|
||||
{
|
||||
_interactableHostManagerToSyncable[syncable.interactableManager] = syncable;
|
||||
}
|
||||
if (syncable.poolee)
|
||||
{
|
||||
_pooleeToSyncable[syncable.poolee] = syncable;
|
||||
}
|
||||
}
|
||||
|
||||
public static void RemoveSyncable(Syncable syncable)
|
||||
{
|
||||
if (syncable.transform)
|
||||
{
|
||||
_pathToSyncable.Remove(syncable.transform.GetPath());
|
||||
}
|
||||
if (syncable.GetSyncId() != 0)
|
||||
{
|
||||
_idToSyncable.Remove(syncable.GetSyncId());
|
||||
}
|
||||
if (syncable.interactableHost)
|
||||
{
|
||||
_interactableHostToSyncable.Remove(syncable.interactableHost);
|
||||
}
|
||||
if (syncable.interactableManager)
|
||||
{
|
||||
_interactableHostManagerToSyncable.Remove(syncable.interactableManager);
|
||||
}
|
||||
if (syncable.poolee)
|
||||
{
|
||||
_pooleeToSyncable.Remove(syncable.poolee);
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateSyncId(Syncable syncable)
|
||||
{
|
||||
// remove other enties where value is the same
|
||||
foreach (KeyValuePair<ushort, Syncable> entry in _idToSyncable)
|
||||
{
|
||||
if (entry.Value == syncable)
|
||||
{
|
||||
_idToSyncable.Remove(entry.Key);
|
||||
}
|
||||
}
|
||||
ushort id = syncable.GetSyncId();
|
||||
if (_idToSyncable.ContainsKey(id))
|
||||
{
|
||||
_idToSyncable.Remove(id);
|
||||
}
|
||||
_idToSyncable[id] = syncable;
|
||||
}
|
||||
|
||||
public static Syncable GetSyncable(string path)
|
||||
{
|
||||
if (_pathToSyncable.ContainsKey(path))
|
||||
{
|
||||
return _pathToSyncable[path];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Syncable GetSyncable(ushort id)
|
||||
{
|
||||
if (_idToSyncable.ContainsKey(id))
|
||||
{
|
||||
return _idToSyncable[id];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Syncable GetSyncable(Poolee poolee)
|
||||
{
|
||||
if (_pooleeToSyncable.ContainsKey(poolee))
|
||||
{
|
||||
return _pooleeToSyncable[poolee];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Syncable GetSyncable(InteractableHost interactableHost)
|
||||
{
|
||||
if (_interactableHostToSyncable.ContainsKey(interactableHost))
|
||||
{
|
||||
return _interactableHostToSyncable[interactableHost];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Syncable GetSyncable(InteractableHostManager interactableHostManager)
|
||||
{
|
||||
if (_interactableHostManagerToSyncable.ContainsKey(interactableHostManager))
|
||||
{
|
||||
return _interactableHostManagerToSyncable[interactableHostManager];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void DISCARD_ALL_SYNCABLES()
|
||||
{
|
||||
foreach (Syncable syncable in Syncable.syncablesCache.Values)
|
||||
{
|
||||
syncable.DiscardSyncable();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user