using System; using System.Collections.Generic; using System.Linq; namespace Encompass { class ComponentMessageManager { private readonly Dictionary componentIDToComponent = new Dictionary(); private readonly Dictionary> componentMessageTypeToExistingComponentIDs = new Dictionary>(); private readonly Dictionary> componentMessageTypeToPendingComponentIDs = new Dictionary>(); private readonly Dictionary> componentMessageTypeToComponentIDs = new Dictionary>(); private readonly Dictionary>> entityToTypeToExistingComponentIDs = new Dictionary>>(); private readonly Dictionary>> entityToTypeToPendingComponentIDs = new Dictionary>>(); private readonly Dictionary>> entityToTypeToComponentIDs = new Dictionary>>(); internal void ClearMessages() { componentIDToComponent.Clear(); foreach (var set in componentMessageTypeToExistingComponentIDs.Values) { set.Clear(); } foreach (var set in componentMessageTypeToPendingComponentIDs.Values) { set.Clear(); } foreach (var set in componentMessageTypeToComponentIDs.Values) { set.Clear(); } foreach (var dictionary in entityToTypeToExistingComponentIDs.Values) { foreach (var set in dictionary.Values) { set.Clear(); } } foreach (var dictionary in entityToTypeToPendingComponentIDs.Values) { foreach (var set in dictionary.Values) { set.Clear(); } } foreach (var dictionary in entityToTypeToComponentIDs.Values) { foreach (var set in dictionary.Values) { set.Clear(); } } } internal void RegisterDestroyedEntity(Entity entity) { entityToTypeToComponentIDs.Remove(entity); entityToTypeToPendingComponentIDs.Remove(entity); entityToTypeToExistingComponentIDs.Remove(entity); } internal void AddExistingComponentMessage(ComponentMessage componentMessage) where TComponent : struct, IComponent { RegisterExistingOrPendingComponentMessage(componentMessage.componentID, componentMessage.component); if (!componentMessageTypeToExistingComponentIDs.ContainsKey(typeof(TComponent))) { componentMessageTypeToExistingComponentIDs.Add(typeof(TComponent), new HashSet()); } componentMessageTypeToExistingComponentIDs[typeof(TComponent)].Add(componentMessage.componentID); if (!entityToTypeToExistingComponentIDs.ContainsKey(componentMessage.entity)) { entityToTypeToExistingComponentIDs.Add(componentMessage.entity, new Dictionary>()); } if (!entityToTypeToExistingComponentIDs[componentMessage.entity].ContainsKey(typeof(TComponent))) { entityToTypeToExistingComponentIDs[componentMessage.entity].Add(typeof(TComponent), new HashSet()); } entityToTypeToExistingComponentIDs[componentMessage.entity][typeof(TComponent)].Add(componentMessage.componentID); } internal void AddPendingComponentMessage(PendingComponentMessage pendingComponentMessage) where TComponent : struct, IComponent { RegisterExistingOrPendingComponentMessage(pendingComponentMessage.componentID, pendingComponentMessage.component); if (!componentMessageTypeToPendingComponentIDs.ContainsKey(typeof(TComponent))) { componentMessageTypeToPendingComponentIDs.Add(typeof(TComponent), new HashSet()); } componentMessageTypeToPendingComponentIDs[typeof(TComponent)].Add(pendingComponentMessage.componentID); if (!entityToTypeToPendingComponentIDs.ContainsKey(pendingComponentMessage.entity)) { entityToTypeToPendingComponentIDs.Add(pendingComponentMessage.entity, new Dictionary>()); } if (!entityToTypeToPendingComponentIDs[pendingComponentMessage.entity].ContainsKey(typeof(TComponent))) { entityToTypeToPendingComponentIDs[pendingComponentMessage.entity].Add(typeof(TComponent), new HashSet()); } entityToTypeToPendingComponentIDs[pendingComponentMessage.entity][typeof(TComponent)].Add(pendingComponentMessage.componentID); } private void RegisterExistingOrPendingComponentMessage(Guid componentID, TComponent component) where TComponent: struct, IComponent { componentIDToComponent[componentID] = component; if (!componentMessageTypeToComponentIDs.ContainsKey(typeof(TComponent))) { componentMessageTypeToComponentIDs.Add(typeof(TComponent), new HashSet()); } componentMessageTypeToComponentIDs[typeof(TComponent)].Add(componentID); } // general component reads by type internal IEnumerable<(Guid, TComponent)> ReadExistingAndPendingComponentsByType() where TComponent : struct, IComponent { HashSet idSet; if (componentMessageTypeToComponentIDs.TryGetValue(typeof(TComponent), out idSet)) { return idSet.Select(id => (id, (TComponent)componentIDToComponent[id])); } return Enumerable.Empty<(Guid, TComponent)>(); } internal IEnumerable<(Guid, TComponent)> ReadExistingComponentsByType() where TComponent: struct, IComponent { HashSet idSet; if (componentMessageTypeToExistingComponentIDs.TryGetValue(typeof(TComponent), out idSet)) { return idSet.Select(id => (id, (TComponent)componentIDToComponent[id])); } return Enumerable.Empty<(Guid, TComponent)>(); } internal IEnumerable<(Guid, TComponent)> ReadPendingComponentsByType() where TComponent : struct, IComponent { HashSet idSet; if (componentMessageTypeToPendingComponentIDs.TryGetValue(typeof(TComponent), out idSet)) { return idSet.Select(id => (id, (TComponent)componentIDToComponent[id])); } return Enumerable.Empty<(Guid, TComponent)>(); } // singular component reads by type internal (Guid, TComponent) ReadFirstExistingOrPendingComponentByType() where TComponent : struct, IComponent { return ReadExistingAndPendingComponentsByType().First(); } internal (Guid, TComponent) ReadFirstExistingComponentByType() where TComponent : struct, IComponent { return ReadExistingComponentsByType().First(); } internal (Guid, TComponent) ReadFirstPendingComponentByType() where TComponent : struct, IComponent { return ReadPendingComponentsByType().First(); } // check if some component of type exists in the world internal bool SomeExistingOrPendingComponent() where TComponent : struct, IComponent { HashSet idSet; if (componentMessageTypeToComponentIDs.TryGetValue(typeof(TComponent), out idSet)) { return idSet.Count > 0; } return false; } internal bool SomeExistingComponent() where TComponent : struct, IComponent { HashSet idSet; if (componentMessageTypeToExistingComponentIDs.TryGetValue(typeof(TComponent), out idSet)) { return idSet.Count > 0; } return false; } internal bool SomePendingComponent() where TComponent : struct, IComponent { HashSet idSet; if (componentMessageTypeToPendingComponentIDs.TryGetValue(typeof(TComponent), out idSet)) { return idSet.Count > 0; } return false; } // read components by entity and type internal IEnumerable<(Guid, TComponent)> ReadExistingAndPendingComponentsByEntityAndType(Entity entity) where TComponent : struct, IComponent { HashSet idSet; if (entityToTypeToComponentIDs.ContainsKey(entity) && entityToTypeToComponentIDs[entity].TryGetValue(typeof(TComponent), out idSet)) { return idSet.Select(id => (id, (TComponent)componentIDToComponent[id])); } return Enumerable.Empty<(Guid, TComponent)>(); } internal IEnumerable<(Guid, TComponent)> ReadExistingComponentsByEntityAndType(Entity entity) where TComponent : struct, IComponent { HashSet idSet; if (entityToTypeToExistingComponentIDs.ContainsKey(entity) && entityToTypeToExistingComponentIDs[entity].TryGetValue(typeof(TComponent), out idSet)) { return idSet.Select(id => (id, (TComponent)componentIDToComponent[id])); } return Enumerable.Empty<(Guid, TComponent)>(); } internal IEnumerable<(Guid, TComponent)> ReadPendingComponentsByEntityAndType(Entity entity) where TComponent : struct, IComponent { HashSet idSet; if (entityToTypeToPendingComponentIDs.ContainsKey(entity) && entityToTypeToPendingComponentIDs[entity].TryGetValue(typeof(TComponent), out idSet)) { return idSet.Select(id => (id, (TComponent)componentIDToComponent[id])); } return Enumerable.Empty<(Guid, TComponent)>(); } // singular read components by entity and type internal (Guid, TComponent) ReadFirstExistingOrPendingComponentByEntityAndType(Entity entity) where TComponent : struct, IComponent { return ReadExistingAndPendingComponentsByEntityAndType(entity).First(); } internal (Guid, TComponent) ReadFirstExistingComponentByEntityAndType(Entity entity) where TComponent : struct, IComponent { return ReadExistingComponentsByEntityAndType(entity).First(); } internal (Guid, TComponent) ReadFirstPendingComponentByEntityAndType(Entity entity) where TComponent : struct, IComponent { return ReadPendingComponentsByEntityAndType(entity).First(); } // check if entity has component of type internal bool HasExistingOrPendingComponent(Entity entity) where TComponent : struct, IComponent { HashSet idSet; if (entityToTypeToComponentIDs.TryGetValue(entity, out _) && entityToTypeToComponentIDs[entity].TryGetValue(typeof(TComponent), out idSet)) { return idSet.Count > 0; } return false; } internal bool HasExistingComponent(Entity entity) where TComponent : struct, IComponent { HashSet idSet; if (entityToTypeToExistingComponentIDs.TryGetValue(entity, out _) && entityToTypeToExistingComponentIDs[entity].TryGetValue(typeof(TComponent), out idSet)) { return idSet.Count > 0; } return false; } internal bool HasPendingComponent(Entity entity) where TComponent : struct, IComponent { HashSet idSet; if (entityToTypeToPendingComponentIDs.TryGetValue(entity, out _) && entityToTypeToPendingComponentIDs[entity].TryGetValue(typeof(TComponent), out idSet)) { return idSet.Count > 0; } return false; } } }