using System; using System.Collections.Generic; using System.Runtime.CompilerServices; namespace Encompass { internal abstract class TypedComponentStore { public abstract int Count { get; } public abstract bool Has(int entity); public abstract bool Remove(int entity, int priority); public abstract void ForceRemove(int entity); public abstract void Clear(); public abstract void ClearPriorities(); } internal class TypedComponentStore : TypedComponentStore where TComponent : unmanaged { private readonly Dictionary _indices = new Dictionary(512); private readonly Dictionary _priorities = new Dictionary(512); private readonly TComponent[] _components = new TComponent[512]; private readonly IDManager _idManager = new IDManager(); public override int Count { get => _indices.Count; } public unsafe ref readonly TComponent Get(int entityID) { if (!_indices.ContainsKey(entityID)) { throw new Exceptions.NoComponentOfTypeOnEntityException("No component of type {0} exists on Entity with ID {1}", typeof(TComponent), entityID); } ref var refVal = ref _components[_indices[entityID]]; return ref Unsafe.AsRef(Unsafe.AsPointer(ref refVal)); } public unsafe void Set(int entityID, TComponent component) { InternalSet(entityID, component); } public unsafe bool Set(int entityID, TComponent component, int priority) { if (!_priorities.ContainsKey(entityID) || priority < _priorities[entityID]) { InternalSet(entityID, component); _priorities[entityID] = priority; return true; } return false; } private unsafe void InternalSet(int entityID, TComponent component) { if (!_indices.ContainsKey(entityID)) { _indices[entityID] = _idManager.NextID(); } _components[_indices[entityID]] = Unsafe.AsRef(Unsafe.AsPointer(ref component)); } public override bool Remove(int entityID, int priority) { if (!_priorities.ContainsKey(entityID) || priority < _priorities[entityID]) { _priorities[entityID] = priority; ForceRemove(entityID); return true; } return false; } public override void ForceRemove(int entityID) { _indices.Remove(entityID); _priorities.Remove(entityID); _idManager.Free(entityID); } public override bool Has(int entityID) { return _indices.ContainsKey(entityID); } public override void Clear() { foreach (var entityID in _indices.Keys) { _idManager.Free(entityID); } _indices.Clear(); _priorities.Clear(); } public override void ClearPriorities() { _priorities.Clear(); } public IEnumerable<(TComponent, int)> All() { foreach (var kvp in _indices) { yield return (_components[kvp.Value], kvp.Key); } } } }