namespace Fusion.Addons.KCC { using System.Collections.Generic; /// /// Base container for all interactions. /// public abstract partial class KCCInteraction where TInteraction : KCCInteraction, new() { // PUBLIC MEMBERS public KCCNetworkID NetworkID; public NetworkObject NetworkObject; public IKCCInteractionProvider Provider; // KCCInteraction INTERFACE public abstract void Initialize(); public abstract void Deinitialize(); public abstract void CopyFromOther(TInteraction other); } /// /// Base collection for tracking all interactions and their providers. /// public abstract partial class KCCInteractions where TInteraction : KCCInteraction, new () { // PUBLIC MEMBERS public readonly List All = new List(); public int Count => All.Count; // PRIVATE MEMBERS private static readonly KCCFastStack _pool = new KCCFastStack(256, true); // PUBLIC METHODS public bool HasProvider() where T : class { for (int i = 0, count = All.Count; i < count; ++i) { if (All[i].Provider is T) return true; } return false; } public bool HasProvider(IKCCInteractionProvider provider) { for (int i = 0, count = All.Count; i < count; ++i) { if (object.ReferenceEquals(All[i].Provider, provider) == true) return true; } return false; } public T GetProvider() where T : class { for (int i = 0, count = All.Count; i < count; ++i) { if (All[i].Provider is T provider) return provider; } return default; } public void GetProviders(List providers, bool clearList = true) where T : class { if (clearList == true) { providers.Clear(); } for (int i = 0, count = All.Count; i < count; ++i) { if (All[i].Provider is T provider) { providers.Add(provider); } } } public TInteraction Find(IKCCInteractionProvider provider) { return Find(provider, out int index); } public TInteraction Add(NetworkRunner networkRunner, NetworkObject networkObject, IKCCInteractionProvider provider) { return AddInternal(networkRunner, networkObject, provider, true); } public bool Add(NetworkObject networkObject, KCCNetworkID networkID) { if (networkObject == null) return false; IKCCInteractionProvider provider = networkObject.GetComponentNoAlloc(); TInteraction interaction = _pool.PopOrCreate(); interaction.NetworkID = networkID; interaction.NetworkObject = networkObject; interaction.Provider = provider; interaction.Initialize(); All.Add(interaction); return true; } public bool Remove(TInteraction interaction) { for (int i = 0, count = All.Count; i < count; ++i) { if (All[i] == interaction) { All.RemoveAt(i); ReturnToPool(interaction); return true; } } return false; } public void CopyFromOther(T other) where T : KCCInteractions { int thisCount = All.Count; int otherCount = other.All.Count; if (thisCount == otherCount) { if (thisCount == 0) return; for (int i = 0; i < thisCount; ++i) { TInteraction interaction = All[i]; TInteraction otherInteraction = other.All[i]; interaction.NetworkID = otherInteraction.NetworkID; interaction.NetworkObject = otherInteraction.NetworkObject; interaction.Provider = otherInteraction.Provider; interaction.CopyFromOther(otherInteraction); } } else { Clear(); for (int i = 0; i < otherCount; ++i) { TInteraction otherInteraction = other.All[i]; TInteraction interaction = _pool.PopOrCreate(); interaction.NetworkID = otherInteraction.NetworkID; interaction.NetworkObject = otherInteraction.NetworkObject; interaction.Provider = otherInteraction.Provider; interaction.CopyFromOther(otherInteraction); All.Add(interaction); } } } public void Clear() { for (int i = 0, count = All.Count; i < count; ++i) { ReturnToPool(All[i]); } All.Clear(); } // PROTECTED METHODS protected TInteraction AddInternal(NetworkRunner networkRunner, NetworkObject networkObject, IKCCInteractionProvider provider, bool invokeInitialize) { TInteraction interaction = _pool.PopOrCreate(); interaction.NetworkID = KCCNetworkID.GetNetworkID(networkRunner, networkObject); interaction.NetworkObject = networkObject; interaction.Provider = provider; if (invokeInitialize == true) { interaction.Initialize(); } All.Add(interaction); return interaction; } protected void AddInternal(TInteraction interaction, NetworkRunner networkRunner, NetworkObject networkObject, IKCCInteractionProvider provider, bool invokeInitialize) { interaction.NetworkID = KCCNetworkID.GetNetworkID(networkRunner, networkObject); interaction.NetworkObject = networkObject; interaction.Provider = provider; if (invokeInitialize == true) { interaction.Initialize(); } All.Add(interaction); } protected TInteraction Find(IKCCInteractionProvider provider, out int index) { for (int i = 0, count = All.Count; i < count; ++i) { TInteraction interaction = All[i]; if (object.ReferenceEquals(interaction.Provider, provider) == true) { index = i; return interaction; } } index = -1; return default; } protected static TInteraction GetFromPool() { return _pool.PopOrCreate(); } // PRIVATE METHODS private static void ReturnToPool(TInteraction interaction) { interaction.Deinitialize(); interaction.NetworkID = default; interaction.NetworkObject = default; interaction.Provider = default; _pool.Push(interaction); } } }