using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading; using BITKit; using BITKit.Core.Entites; using BITKit.Entities; using UnityEngine; using Cysharp.Threading.Tasks; using UnityEngine.Pool; using IEntity = BITKit.Core.Entites.IEntity; using IEntityComponent = BITKit.Core.Entites.IEntityComponent; [Serializable] public class UnityEntitiesServiceSingleton:IEntitiesService { public event Action OnAdd { add => UnityEntitiesService.OnAdd += value; remove => UnityEntitiesService.OnAdd -= value; } public event Action OnRemove { add => UnityEntitiesService.OnRemove += value; remove => UnityEntitiesService.OnRemove -= value; } public IEntity[] Entities => UnityEntitiesService.Entities; public bool Register(IEntity entity) { return UnityEntitiesService.Register(entity); } public bool UnRegister(IEntity entity) { return UnityEntitiesService.UnRegister(entity); } public CancellationToken CancellationToken => UnityEntitiesService.CancellationToken; public IEntity Get(ulong id) => UnityEntitiesService.Get(id); public IEntity[] Query() { return UnityEntitiesService.Query(); } public T[] QueryComponents() { return UnityEntitiesService.QueryComponents(); } public (T, T1)[] QueryComponents() { return UnityEntitiesService.QueryComponents(); } public (T, T1, T2)[] QueryComponents() { return UnityEntitiesService.QueryComponents(); } } public class UnityEntitiesService : MonoBehaviour,IEntitiesService { [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] private static void Initialize() { Dictionary.Clear(); RegisterQueue.Clear(); UnRegisterQueue.Clear(); } public static bool Register(IEntity entity) { RegisterQueue.Enqueue(entity); return true; } public static bool UnRegister(IEntity entity) { UnRegisterQueue.Enqueue(entity); return false; } public static CancellationToken CancellationToken; private static readonly ConcurrentDictionary Dictionary=new(); private static readonly Queue RegisterQueue = new(); private static readonly Queue UnRegisterQueue = new(); private void Awake() { CancellationToken = gameObject.GetCancellationTokenOnDestroy(); } event Action IEntitiesService.OnAdd { add => OnAdd += value; remove => OnAdd -= value; } event Action IEntitiesService.OnRemove { add => OnRemove += value; remove => OnRemove -= value; } public static event Action OnAdd; public static event Action OnRemove; IEntity[] IEntitiesService.Entities => Entities; public static IEntity[] Entities => Dictionary.Values.ToArray(); bool IEntitiesService.Register(IEntity entity) => Register(entity); bool IEntitiesService.UnRegister(IEntity entity) => UnRegister(entity); private void LateUpdate() { while (RegisterQueue.TryDequeue(out var entity)) { Dictionary.AddOrUpdate(entity.Id,entity,(x,y)=>entity); OnAdd?.Invoke(entity); } while (UnRegisterQueue.TryDequeue(out var entity)) { if (Dictionary.TryRemove(entity.Id)) { OnRemove?.Invoke(entity); } } } CancellationToken IEntitiesService.CancellationToken => CancellationToken; public static IEntity Get(ulong id)=>Dictionary[id]; IEntity IEntitiesService.Get(ulong id)=>Get(id); IEntity[] IEntitiesService.Query()=>Query(); public static IEntity[] Query() { return Entities.Where(x => ((Entity)x).TryGetComponentAny(out _)).ToArray(); } T[] IEntitiesService.QueryComponents()=>QueryComponents(); public static T[] QueryComponents() { var list = ListPool.Get(); foreach (var iEntity in Entities) { switch (iEntity as Entity) { case { } x when x.TryGetComponentAny(out var t): list.Add((t)); break; } } var value = list.ToArray(); list.Clear(); ListPool.Release(list); return value; } (T, T1)[] IEntitiesService.QueryComponents()=>QueryComponents(); public static (T, T1)[] QueryComponents() { var list = ListPool<(T t, T1 t1)>.Get(); foreach (var iEntity in Entities) { switch (iEntity as Entity) { case var x when x != null && x.TryGetComponentAny(out var t) && x.TryGetComponentAny(out var t1): list.Add((t, t1)); break; } } var value = list.ToArray(); list.Clear(); ListPool<(T t, T1 t1)>.Release(list); return value; } (T, T1, T2)[] IEntitiesService.QueryComponents()=>QueryComponents(); public static (T, T1, T2)[] QueryComponents() { var list = ListPool<(T t, T1 t1, T2 t2)>.Get(); foreach (var iEntity in Entities) { switch (iEntity as Entity) { case var x when x != null && x.TryGetComponentAny(out var t) && x.TryGetComponentAny(out var t1) && x.TryGetComponentAny(out var t2): list.Add((t, t1, t2)); break; } } var value = list.ToArray(); list.Clear(); ListPool<(T t, T1 t1, T2 t2)>.Release(list); return value; } }