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 : struct { private readonly Dictionary _indices = new Dictionary(512); private readonly Dictionary _priorities = new Dictionary(512); private readonly TComponent[] _components = new TComponent[512]; // TODO: allow specify size private readonly IDManager _idManager = new IDManager(); public override int Count { get => _indices.Count; } public ref 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); } return ref _components[_indices[entityID]]; } public void Set(int entityID, in TComponent component) { InternalSet(entityID, component); } public bool Set(int entityID, in TComponent component, int priority) { if (!_priorities.ContainsKey(entityID) || priority <= _priorities[entityID]) // if priorities are equal that means it's the same engine { InternalSet(entityID, component); _priorities[entityID] = priority; return true; } return false; } private void InternalSet(int entityID, in TComponent component) { if (!_indices.ContainsKey(entityID)) { _indices[entityID] = _idManager.NextID(); } _components[_indices[entityID]] = component; } public override bool Remove(int entityID, int priority) { if (!_priorities.ContainsKey(entityID) || priority <= _priorities[entityID]) // if priorities are equal that means it's the same engine { _priorities[entityID] = priority; ForceRemove(entityID); return true; } return false; } public override void ForceRemove(int entityID) { if (_indices.ContainsKey(entityID)) { _idManager.Free(_indices[entityID]); _indices.Remove(entityID); _priorities.Remove(entityID); } } public override bool Has(int entityID) { return _indices.ContainsKey(entityID); } public override void Clear() { foreach (var mappedID in _indices.Values) { _idManager.Free(mappedID); } _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); } } } }