using System; using System.Collections.Generic; 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(); public void RegisterComponentType() where TComponent : struct, IComponent { existingAndPendingComponentStore.RegisterComponentType(); existingComponentStore.RegisterComponentType(); pendingComponentStore.RegisterComponentType(); UpToDateComponentStore.RegisterComponentType(); } 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<(TComponent, Entity)> ReadExistingAndPendingComponentsByType() where TComponent : struct, IComponent { return existingAndPendingComponentStore.All(); } internal IEnumerable<(TComponent, Entity)> ReadExistingComponentsByType() where TComponent : struct, IComponent { return existingComponentStore.All(); } internal IEnumerable<(TComponent, Entity)> ReadPendingComponentsByType() where TComponent : struct, IComponent { return pendingComponentStore.All(); } // singular component reads by type internal (TComponent, Entity) ReadFirstExistingOrPendingComponentByType() where TComponent : struct, IComponent { if (!SomeExistingOrPendingComponent()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } var enumerator = ReadExistingAndPendingComponentsByType().GetEnumerator(); enumerator.MoveNext(); return enumerator.Current; } internal (TComponent, Entity) ReadFirstExistingComponentByType() where TComponent : struct, IComponent { if (!SomeExistingComponent()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } var enumerator = ReadExistingComponentsByType().GetEnumerator(); enumerator.MoveNext(); return enumerator.Current; } internal (TComponent, Entity) ReadFirstPendingComponentByType() where TComponent : struct, IComponent { if (!SomePendingComponent()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } var enumerator = ReadPendingComponentsByType().GetEnumerator(); enumerator.MoveNext(); return enumerator.Current; } // 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); } } }