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; 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 { 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 partial class Syncable : MonoBehaviour { public const int SYNC_FPS = 20; public static Dictionary syncablesCache = new Dictionary(); public Syncable(IntPtr intPtr) : base(intPtr) { syncablesCache[gameObject] = this; } private bool _syncCoroutineRunning; public ulong _ownerId { private set; get; } private ushort _syncId; private float _lastSyncTime; private bool _attemptedRegister; public bool Registered => _syncId != 0; 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) { _syncId = id; ObjectSyncCache.UpdateSyncId(this); } 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 Gun gun; private Magazine magazine; private Plug[] plugs; private AIBrain aiBrain; private PuppetMaster puppetMaster; public void OnEnable() { FindComponents(); } public string GetSyncableWorldPath() { if (poolee && poolee.pool) { return ""; } if (interactableHost || interactableManager) { return transform.GetPath(); } return ""; } public void FindComponents() { ObjectSyncCache.RemoveSyncable(this); interactableManager = GetComponent(); interactableHost = GetComponent(); poolee = GetComponent(); propHealth = GetComponent(); objectDestructable = GetComponent(); gun = GetComponent(); magazine = GetComponent(); plugs = GetComponentsInChildren(); //rigidbodies = GetComponentsInChildren(); UpdateTransformList(); ObjectSyncCache.AddSyncable(this); } public bool CanBeSynced() { FindComponents(); if (interactableManager && interactableManager.hosts.Count > 0) { return true; } if (interactableHost && interactableHost.hasRigidbody) { return true; } return false; } public void OnDestroy() { DiscardSyncable(); MelonLogger.Msg("Syncable destroyed: " + transform.GetPath()); } public void DiscardSyncable() { syncablesCache.Remove(gameObject); ObjectSyncCache.RemoveSyncable(this); Destroy(this); } public void OnDisable() { if (!Registered) { DiscardSyncable(); return; } MelonLogger.Warning("Registered Syncable disabled: " + transform.GetPath()); } public void RegisterSyncable() { if (!BoneSync.lobby.IsConnected()) return; if (_attemptedRegister) return; if (Registered) return; if (!CanBeSynced()) return; _attemptedRegister = true; _SendRegisterSync(); } } }