using System; using System.Collections.Generic; using System.Linq; namespace Encompass { internal class ComponentManager { private Dictionary IDToComponent = new Dictionary(); private Dictionary> entityIDToComponentIDs = new Dictionary>(); private Dictionary componentIDToEntityID = new Dictionary(); private Dictionary> activeComponents = new Dictionary>(); private Dictionary> inactiveComponents = new Dictionary>(); private List componentsToActivate = new List(); private List componentsToDeactivate = new List(); private List componentsToRemove = new List(); internal Guid AddComponent(Guid entityID, TComponent component) where TComponent : struct, IComponent { var componentID = Guid.NewGuid(); IDToComponent[componentID] = component; if (!entityIDToComponentIDs.ContainsKey(entityID)) { entityIDToComponentIDs.Add(entityID, new List()); } entityIDToComponentIDs[entityID].Add(componentID); componentIDToEntityID[componentID] = entityID; if (!activeComponents.ContainsKey(typeof(TComponent))) { activeComponents.Add(typeof(TComponent), new List()); inactiveComponents.Add(typeof(TComponent), new List()); } MarkForActivation(componentID); return componentID; } internal IEnumerable> GetComponentsByEntity(Guid entityID) { return entityIDToComponentIDs[entityID].Select((id) => new KeyValuePair(id, IDToComponent[id])); } internal IEnumerable> GetActiveComponentsByType() where TComponent : struct, IComponent { return activeComponents[typeof(TComponent)].Select((id) => new KeyValuePair(id, (TComponent)IDToComponent[id])); } 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 bool EntityHasComponentOfType(Guid entityID) where TComponent : struct, IComponent { return GetComponentsByEntityAndType(entityID).Any(); } internal void UpdateComponent(Guid componentID, TComponent newComponentValue) where TComponent : struct, IComponent { var entityID = componentIDToEntityID[componentID]; IDToComponent[componentID] = newComponentValue; } internal void RemoveAllComponentsFromEntity(Guid entityID) { var componentIDs = entityIDToComponentIDs[entityID]; foreach (var componentID in componentIDs) { var component = IDToComponent[componentID]; activeComponents[component.GetType()].Remove(componentID); inactiveComponents[component.GetType()].Remove(componentID); } entityIDToComponentIDs.Remove(entityID); } internal void MarkForActivation(Guid componentID) { componentsToActivate.Add(componentID); } internal void MarkForDeactivation(Guid componentID) { componentsToDeactivate.Add(componentID); } internal void MarkForRemoval(Guid componentID) { componentsToRemove.Add(componentID); } internal void ActivateComponents() { foreach (var componentID in componentsToActivate) { var component = IDToComponent[componentID]; activeComponents[component.GetType()].Add(componentID); inactiveComponents[component.GetType()].Remove(componentID); } componentsToActivate.Clear(); } internal void DeactivateComponents() { foreach (var componentID in componentsToDeactivate) { var component = IDToComponent[componentID]; activeComponents[component.GetType()].Remove(componentID); inactiveComponents[component.GetType()].Add(componentID); } componentsToDeactivate.Clear(); } internal void RemoveComponents() { foreach (var componentID in componentsToRemove) { var component = IDToComponent[componentID]; activeComponents[component.GetType()].Remove(componentID); inactiveComponents[component.GetType()].Remove(componentID); } componentsToRemove.Clear(); } } }