using System; using System.Collections.Generic; using MoonTools.FastCollections; namespace Encompass { internal class ComponentManager { private readonly DrawLayerManager drawLayerManager; private readonly ComponentStore existingComponentStore; private readonly ComponentStore immediateComponentStore; private readonly ComponentDeltaStore replayStore; private ComponentStore upToDateComponentStore; public Dictionary TypeToIndex { get; } private readonly HashSet entitiesMarkedForRemoval = new HashSet(); internal ComponentBitSet ImmediateBits { get { return immediateComponentStore.ComponentBitSet; } } internal ComponentBitSet ExistingBits { get { return existingComponentStore.ComponentBitSet; } } public ComponentManager(DrawLayerManager drawLayerManager, Dictionary typeToIndex) { this.drawLayerManager = drawLayerManager; existingComponentStore = new ComponentStore(typeToIndex); immediateComponentStore = new ComponentStore(typeToIndex); replayStore = new ComponentDeltaStore(typeToIndex); upToDateComponentStore = new ComponentStore(typeToIndex); TypeToIndex = typeToIndex; } public void RegisterComponentType() where TComponent : struct, IComponent { existingComponentStore.RegisterComponentType(); immediateComponentStore.RegisterComponentType(); replayStore.RegisterComponentType(); upToDateComponentStore.RegisterComponentType(); } internal void SetExistingComponentStore(ComponentStore componentStore) { existingComponentStore.SwapWith(componentStore); } internal void SetUpToDateComponentStore(ComponentStore componentStore) { upToDateComponentStore.SwapWith(componentStore); } internal void RegisterDrawableComponent(int entityID, TComponent component, int layer) where TComponent : struct, IComponent { drawLayerManager.RegisterComponentWithLayer(entityID, component, layer); } internal void WriteComponents() { existingComponentStore.UpdateUsing(replayStore); existingComponentStore.ClearAllPriorities(); upToDateComponentStore.ClearAllPriorities(); immediateComponentStore.ClearAll(); replayStore.ClearAll(); } internal bool AddImmediateComponent(int entityID, TComponent component, int priority) where TComponent : struct, IComponent { if (immediateComponentStore.Set(entityID, component, priority)) { replayStore.Set(entityID, component); upToDateComponentStore.Set(entityID, component); return true; } return false; } internal void AddImmediateComponent(int entityID, TComponent component) where TComponent : struct, IComponent { immediateComponentStore.Set(entityID, component); replayStore.Set(entityID, component); upToDateComponentStore.Set(entityID, component); } internal bool UpdateComponent(int entityID, TComponent component, int priority) where TComponent : struct, IComponent { var result = upToDateComponentStore.Set(entityID, component, priority); if (result) { replayStore.Set(entityID, component); } return result; } internal void AddComponent(int entityID, TComponent component) where TComponent : struct, IComponent { upToDateComponentStore.Set(entityID, component); replayStore.Set(entityID, component); } // existing or immediate reads internal IEnumerable<(TComponent, int)> ReadExistingAndImmediateComponentsByType() where TComponent : struct, IComponent { return upToDateComponentStore.All(); } internal (TComponent, int) ReadFirstExistingOrImmediateComponentByType() where TComponent : struct, IComponent { if (!SomeExistingOrImmediateComponent()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } var enumerator = ReadExistingAndImmediateComponentsByType().GetEnumerator(); enumerator.MoveNext(); return enumerator.Current; } internal bool SomeExistingOrImmediateComponent() where TComponent : struct, IComponent { return upToDateComponentStore.Any(); } // existing reads internal (TComponent, int) ReadFirstExistingComponentByType() where TComponent : struct, IComponent { if (!SomeExistingComponent()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } var enumerator = GetComponentsIncludingEntity().GetEnumerator(); enumerator.MoveNext(); return enumerator.Current; } internal bool SomeExistingComponent() where TComponent : struct, IComponent { return existingComponentStore.Any(); } // immediate reads internal IEnumerable<(TComponent, int)> ReadImmediateComponentsByType() where TComponent : struct, IComponent { return immediateComponentStore.All(); } internal (TComponent, int) ReadFirstImmediateComponentByType() where TComponent : struct, IComponent { if (!SomeImmediateComponent()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } var enumerator = ReadImmediateComponentsByType().GetEnumerator(); enumerator.MoveNext(); return enumerator.Current; } internal bool SomeImmediateComponent() where TComponent : struct, IComponent { return immediateComponentStore.Any(); } // component getters internal TComponent ReadImmediateOrExistingComponentByEntityAndType(int entityID) where TComponent : struct, IComponent { return upToDateComponentStore.Get(entityID); } internal TComponent ReadExistingComponentByEntityAndType(int entityID) where TComponent : struct, IComponent { return existingComponentStore.Get(entityID); } internal TComponent ReadImmediateComponentByEntityAndType(int entityID) where TComponent : struct, IComponent { return immediateComponentStore.Get(entityID); } // has checkers internal bool HasExistingOrImmediateComponent(int entityID) where TComponent : struct, IComponent { return upToDateComponentStore.Has(entityID); } internal bool HasExistingOrImmediateComponent(int entityID, Type type) { return upToDateComponentStore.Has(type, entityID); } internal bool HasExistingComponent(int entityID) where TComponent : struct, IComponent { return existingComponentStore.Has(entityID); } internal bool HasExistingComponent(int entityID, Type type) { return existingComponentStore.Has(type, entityID); } internal bool HasImmediateComponent(int entityID) where TComponent : struct, IComponent { return immediateComponentStore.Has(entityID); } internal bool HasImmediateComponent(int entityID, Type type) { return immediateComponentStore.Has(type, entityID); } internal IEnumerable<(TComponent, int)> GetComponentsIncludingEntity() where TComponent : struct, IComponent { return existingComponentStore.All(); } internal IEnumerable GetComponentsByType() where TComponent : struct, IComponent { foreach (var pair in existingComponentStore.All()) { yield return pair.Item1; } } internal TComponent GetComponentByEntityAndType(int entityID) where TComponent : struct, IComponent { return existingComponentStore.Get(entityID); } internal bool EntityHasComponentOfType(int entityID) where TComponent : struct, IComponent { return existingComponentStore.Has(entityID); } internal void MarkAllComponentsOnEntityForRemoval(int entityID) { entitiesMarkedForRemoval.Add(entityID); } internal void RemoveMarkedComponents() { foreach (var entityID in entitiesMarkedForRemoval) { existingComponentStore.Remove(entityID); immediateComponentStore.Remove(entityID); replayStore.Remove(entityID); upToDateComponentStore.Remove(entityID); drawLayerManager.UnRegisterEntityWithLayer(entityID); } entitiesMarkedForRemoval.Clear(); } public bool RemoveImmediate(int entityID, int priority) where TComponent : struct, IComponent { if (immediateComponentStore.Remove(entityID, priority)) { replayStore.Remove(entityID, priority); upToDateComponentStore.Remove(entityID, priority); drawLayerManager.UnRegisterComponentWithLayer(entityID); return true; } return false; } public void Remove(int entityID, int priority) where TComponent : struct, IComponent { if (upToDateComponentStore.Remove(entityID, priority)) { replayStore.Remove(entityID, priority); drawLayerManager.UnRegisterComponentWithLayer(entityID); } } public bool UpToDateEntityIsEmpty(int entityID) { return upToDateComponentStore.EntityBitArray(entityID).AllFalse(); } } }