using System; using System.Collections.Generic; using System.Linq; namespace Encompass { internal class ComponentManager { private DrawLayerManager drawLayerManager; private Dictionary componentIDToType = new Dictionary(); private Dictionary IDToComponent = new Dictionary(); private Dictionary> entityIDToComponentIDs = new Dictionary>(); private Dictionary componentIDToEntityID = new Dictionary(); private Dictionary> typeToComponentIDs = new Dictionary>(); private List activeComponents = new List(); private List inactiveComponents = new List(); private List componentsToActivate = new List(); private List componentsToDeactivate = new List(); private List componentsToRemove = new List(); //shared references with EntityManager private List entitiesWithAddedComponents; private List entitiesWithRemovedComponents; public ComponentManager( DrawLayerManager drawLayerManager, List entitiesWithAddedComponents, List entitiesWithRemovedComponents ) { this.drawLayerManager = drawLayerManager; this.entitiesWithAddedComponents = entitiesWithAddedComponents; this.entitiesWithRemovedComponents = entitiesWithRemovedComponents; } internal Guid AddComponent(Guid entityID, TComponent component) where TComponent : struct, IComponent { var componentID = Guid.NewGuid(); IDToComponent[componentID] = component; componentIDToType[componentID] = typeof(TComponent); if (!typeToComponentIDs.ContainsKey(typeof(TComponent))) { typeToComponentIDs.Add(typeof(TComponent), new List()); } typeToComponentIDs[typeof(TComponent)].Add(componentID); if (!entityIDToComponentIDs.ContainsKey(entityID)) { entityIDToComponentIDs.Add(entityID, new List()); } entityIDToComponentIDs[entityID].Add(componentID); componentIDToEntityID[componentID] = entityID; inactiveComponents.Add(componentID); MarkForActivation(componentID); entitiesWithAddedComponents.Add(entityID); return componentID; } internal Guid AddDrawComponent(Guid entityID, TComponent component, int layer = 0) where TComponent : struct, IComponent { var componentID = AddComponent(entityID, component); drawLayerManager.RegisterComponentWithLayer(componentID, layer); return componentID; } internal IEnumerable GetComponentIDsByEntityID(Guid entityID) { return entityIDToComponentIDs.ContainsKey(entityID) ? entityIDToComponentIDs[entityID] : Enumerable.Empty(); } internal IEnumerable> GetComponentsByEntity(Guid entityID) { return GetComponentIDsByEntityID(entityID).Intersect(activeComponents).Select((id) => new KeyValuePair(id, IDToComponent[id])); } internal IEnumerable> GetActiveComponentsByType() where TComponent : struct, IComponent { return typeToComponentIDs.ContainsKey(typeof(TComponent)) ? typeToComponentIDs[typeof(TComponent)].Select((id) => new KeyValuePair(id, (TComponent)IDToComponent[id])) : Enumerable.Empty>(); } internal IEnumerable> GetActiveComponentsByType(Type type) { return typeToComponentIDs.ContainsKey(type) ? typeToComponentIDs[type].Select((id) => new KeyValuePair(id, IDToComponent[id])) : Enumerable.Empty>(); } internal KeyValuePair GetActiveComponentByType() where TComponent : struct, IComponent { return GetActiveComponentsByType().Single(); } internal IEnumerable> GetComponentsByEntityAndType(Guid entityID) where TComponent : struct, IComponent { var entity_components = GetComponentsByEntity(entityID).Select((kv) => new KeyValuePair(kv.Key, (TComponent)kv.Value)); var active_components_by_type = GetActiveComponentsByType(); return entity_components.Intersect(active_components_by_type); } internal IEnumerable> GetComponentsByEntityAndType(Guid entityID, Type type) { var entityComponents = GetComponentsByEntity(entityID); var activeComponentsByType = GetActiveComponentsByType(type); return entityComponents.Intersect(activeComponentsByType); } internal IEnumerable GetAllComponentTypesOfEntity(Guid entityID) { return GetComponentIDsByEntityID(entityID).Select((id) => componentIDToType[id]); } internal bool EntityHasComponentOfType(Guid entityID) where TComponent : struct, IComponent { return GetComponentsByEntityAndType(entityID).Any(); } internal bool EntityHasComponentOfType(Guid entityID, Type type) { return GetComponentsByEntityAndType(entityID, type).Any(); } internal IComponent GetComponentByID(Guid componentID) { return IDToComponent[componentID]; } internal Type GetComponentTypeByID(Guid componentID) { return componentIDToType[componentID]; } internal Guid GetEntityIDFromComponentID(Guid componentID) { return componentIDToEntityID[componentID]; } internal void UpdateComponent(Guid componentID, TComponent newComponentValue) where TComponent : struct, IComponent { var entityID = GetEntityIDFromComponentID(componentID); IDToComponent[componentID] = newComponentValue; } internal void RemoveAllComponentsFromEntity(Guid entityID) { var componentIDs = entityIDToComponentIDs[entityID]; foreach (var componentID in componentIDs) { MarkForRemoval(componentID); } } internal void MarkForActivation(Guid componentID) { componentsToActivate.Add(componentID); var entityID = GetEntityIDFromComponentID(componentID); entitiesWithAddedComponents.Add(entityID); } internal void MarkForDeactivation(Guid componentID) { componentsToDeactivate.Add(componentID); var entityID = GetEntityIDFromComponentID(componentID); entitiesWithRemovedComponents.Add(entityID); } internal void MarkForRemoval(Guid componentID) { componentsToRemove.Add(componentID); var entityID = GetEntityIDFromComponentID(componentID); entitiesWithRemovedComponents.Add(entityID); } internal void ActivateMarkedComponents() { foreach (var componentID in componentsToActivate) { var component = IDToComponent[componentID]; if (inactiveComponents.Remove(componentID)) { activeComponents.Add(componentID); } } componentsToActivate.Clear(); } internal void DeactivateMarkedComponents() { foreach (var componentID in componentsToDeactivate) { var component = IDToComponent[componentID]; if (activeComponents.Remove(componentID)) { inactiveComponents.Add(componentID); } } componentsToDeactivate.Clear(); } public void RemoveMarkedComponents() { foreach (var componentID in componentsToRemove) { var component = IDToComponent[componentID]; var type = componentIDToType[componentID]; activeComponents.Remove(componentID); inactiveComponents.Remove(componentID); var entityID = componentIDToEntityID[componentID]; if (entityIDToComponentIDs.ContainsKey(entityID)) { entityIDToComponentIDs[entityID].Remove(componentID); } IDToComponent.Remove(componentID); componentIDToType.Remove(componentID); componentIDToEntityID.Remove(componentID); typeToComponentIDs[type].Remove(componentID); drawLayerManager.UnRegisterComponentWithLayer(componentID); } componentsToRemove.Clear(); } public void RegisterDestroyedEntity(Guid entityID) { entityIDToComponentIDs.Remove(entityID); } } }