using System; using System.Collections.Generic; using System.Linq; namespace Encompass { internal class ComponentUpdateManager { private readonly ComponentStore existingAndPendingComponentStore = new ComponentStore(); private readonly ComponentStore existingComponentStore = new ComponentStore(); private readonly ComponentStore pendingComponentStore = new ComponentStore(); private readonly Dictionary> typeToEntityToPendingComponentPriority = new Dictionary>(128); public ComponentStore UpToDateComponentStore { get; private set; } = new ComponentStore(); internal void Clear() { existingAndPendingComponentStore.ClearAll(); existingComponentStore.ClearAll(); pendingComponentStore.ClearAll(); UpToDateComponentStore.ClearAll(); foreach (var dictionary in typeToEntityToPendingComponentPriority.Values) { dictionary.Clear(); } } internal void SetStartingComponentStore(ComponentStore componentStore) { UpToDateComponentStore = componentStore; } internal void AddExistingComponent(Entity entity, TComponent component) where TComponent : struct, IComponent { RegisterExistingOrPendingComponentMessage(entity, component); existingComponentStore.Set(entity, component); } internal bool AddPendingComponent(Entity entity, TComponent component, int priority) where TComponent : struct, IComponent { if (pendingComponentStore.Set(entity, component, priority)) { RegisterExistingOrPendingComponentMessage(entity, component); return true; } return false; } private void RegisterExistingOrPendingComponentMessage(Entity entity, TComponent component) where TComponent : struct, IComponent { existingAndPendingComponentStore.Set(entity, component); UpToDateComponentStore.Set(entity, component); } public bool UpdateComponent(Entity entity, TComponent component, int priority) where TComponent : struct, IComponent { return UpToDateComponentStore.Set(entity, component, priority); } // general component reads by type internal IEnumerable<(Entity, TComponent)> ReadExistingAndPendingComponentsByType() where TComponent : struct, IComponent { return existingAndPendingComponentStore.All(); } internal IEnumerable<(Entity, TComponent)> ReadExistingComponentsByType() where TComponent : struct, IComponent { return existingComponentStore.All(); } internal IEnumerable<(Entity, TComponent)> ReadPendingComponentsByType() where TComponent : struct, IComponent { return pendingComponentStore.All(); } // singular component reads by type internal (Entity, TComponent) ReadFirstExistingOrPendingComponentByType() where TComponent : struct, IComponent { if (!SomeExistingOrPendingComponent()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } return ReadExistingAndPendingComponentsByType().First(); } internal (Entity, TComponent) ReadFirstExistingComponentByType() where TComponent : struct, IComponent { if (!SomeExistingComponent()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } return ReadExistingComponentsByType().First(); } internal (Entity, TComponent) ReadFirstPendingComponentByType() where TComponent : struct, IComponent { if (!SomePendingComponent()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } return ReadPendingComponentsByType().First(); } // check if some component of type exists in the world internal bool SomeExistingOrPendingComponent() where TComponent : struct, IComponent { return existingAndPendingComponentStore.Any(); } internal bool SomeExistingComponent() where TComponent : struct, IComponent { return existingComponentStore.Any(); } internal bool SomePendingComponent() where TComponent : struct, IComponent { return pendingComponentStore.Any(); } // read components by entity and type internal TComponent ReadExistingComponentByEntityAndType(Entity entity) where TComponent : struct, IComponent { return existingComponentStore.Get(entity); } internal TComponent ReadPendingComponentByEntityAndType(Entity entity) where TComponent : struct, IComponent { return pendingComponentStore.Get(entity); } // check if entity has component of type internal bool HasExistingOrPendingComponent(Entity entity) where TComponent : struct, IComponent { return existingAndPendingComponentStore.Has(entity); } internal bool HasExistingOrPendingComponent(Entity entity, Type type) { return existingAndPendingComponentStore.Has(type, entity); } internal bool HasExistingComponent(Entity entity) where TComponent : struct, IComponent { return existingComponentStore.Has(entity); } internal bool HasExistingComponent(Entity entity, Type type) { return existingComponentStore.Has(type, entity); } internal bool HasPendingComponent(Entity entity) where TComponent : struct, IComponent { return pendingComponentStore.Has(entity); } internal bool HasPendingComponent(Entity entity, Type type) { return pendingComponentStore.Has(type, entity); } internal void Remove(Entity entity) where TComponent : struct, IComponent { UpToDateComponentStore.Remove(entity); } } }