301 lines
12 KiB
C#
301 lines
12 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace Encompass
|
|
{
|
|
class ComponentMessageManager
|
|
{
|
|
private readonly Dictionary<Guid, IComponent> componentIDToComponent = new Dictionary<Guid, IComponent>();
|
|
|
|
private readonly Dictionary<Type, HashSet<Guid>> componentMessageTypeToExistingComponentIDs = new Dictionary<Type, HashSet<Guid>>();
|
|
private readonly Dictionary<Type, HashSet<Guid>> componentMessageTypeToPendingComponentIDs = new Dictionary<Type, HashSet<Guid>>();
|
|
private readonly Dictionary<Type, HashSet<Guid>> componentMessageTypeToComponentIDs = new Dictionary<Type, HashSet<Guid>>();
|
|
|
|
private readonly Dictionary<Entity, Dictionary<Type, HashSet<Guid>>> entityToTypeToExistingComponentIDs = new Dictionary<Entity, Dictionary<Type, HashSet<Guid>>>();
|
|
private readonly Dictionary<Entity, Dictionary<Type, HashSet<Guid>>> entityToTypeToPendingComponentIDs = new Dictionary<Entity, Dictionary<Type, HashSet<Guid>>>();
|
|
private readonly Dictionary<Entity, Dictionary<Type, HashSet<Guid>>> entityToTypeToComponentIDs = new Dictionary<Entity, Dictionary<Type, HashSet<Guid>>>();
|
|
|
|
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<TComponent>(ComponentMessage<TComponent> componentMessage) where TComponent : struct, IComponent
|
|
{
|
|
RegisterExistingOrPendingComponentMessage(componentMessage.componentID, componentMessage.component);
|
|
|
|
if (!componentMessageTypeToExistingComponentIDs.ContainsKey(typeof(TComponent)))
|
|
{
|
|
componentMessageTypeToExistingComponentIDs.Add(typeof(TComponent), new HashSet<Guid>());
|
|
}
|
|
|
|
componentMessageTypeToExistingComponentIDs[typeof(TComponent)].Add(componentMessage.componentID);
|
|
|
|
if (!entityToTypeToExistingComponentIDs.ContainsKey(componentMessage.entity))
|
|
{
|
|
entityToTypeToExistingComponentIDs.Add(componentMessage.entity, new Dictionary<Type, HashSet<Guid>>());
|
|
}
|
|
if (!entityToTypeToExistingComponentIDs[componentMessage.entity].ContainsKey(typeof(TComponent)))
|
|
{
|
|
entityToTypeToExistingComponentIDs[componentMessage.entity].Add(typeof(TComponent), new HashSet<Guid>());
|
|
}
|
|
|
|
entityToTypeToExistingComponentIDs[componentMessage.entity][typeof(TComponent)].Add(componentMessage.componentID);
|
|
}
|
|
|
|
internal void AddPendingComponentMessage<TComponent>(PendingComponentMessage<TComponent> pendingComponentMessage) where TComponent : struct, IComponent
|
|
{
|
|
RegisterExistingOrPendingComponentMessage(pendingComponentMessage.componentID, pendingComponentMessage.component);
|
|
|
|
if (!componentMessageTypeToPendingComponentIDs.ContainsKey(typeof(TComponent)))
|
|
{
|
|
componentMessageTypeToPendingComponentIDs.Add(typeof(TComponent), new HashSet<Guid>());
|
|
}
|
|
|
|
componentMessageTypeToPendingComponentIDs[typeof(TComponent)].Add(pendingComponentMessage.componentID);
|
|
|
|
if (!entityToTypeToPendingComponentIDs.ContainsKey(pendingComponentMessage.entity))
|
|
{
|
|
entityToTypeToPendingComponentIDs.Add(pendingComponentMessage.entity, new Dictionary<Type, HashSet<Guid>>());
|
|
}
|
|
if (!entityToTypeToPendingComponentIDs[pendingComponentMessage.entity].ContainsKey(typeof(TComponent)))
|
|
{
|
|
entityToTypeToPendingComponentIDs[pendingComponentMessage.entity].Add(typeof(TComponent), new HashSet<Guid>());
|
|
}
|
|
|
|
entityToTypeToPendingComponentIDs[pendingComponentMessage.entity][typeof(TComponent)].Add(pendingComponentMessage.componentID);
|
|
}
|
|
|
|
private void RegisterExistingOrPendingComponentMessage<TComponent>(Guid componentID, TComponent component) where TComponent: struct, IComponent
|
|
{
|
|
componentIDToComponent[componentID] = component;
|
|
if (!componentMessageTypeToComponentIDs.ContainsKey(typeof(TComponent)))
|
|
{
|
|
componentMessageTypeToComponentIDs.Add(typeof(TComponent), new HashSet<Guid>());
|
|
}
|
|
componentMessageTypeToComponentIDs[typeof(TComponent)].Add(componentID);
|
|
}
|
|
|
|
// general component reads by type
|
|
|
|
internal IEnumerable<(Guid, TComponent)> ReadExistingAndPendingComponentsByType<TComponent>() where TComponent : struct, IComponent
|
|
{
|
|
HashSet<Guid> 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<TComponent>() where TComponent: struct, IComponent
|
|
{
|
|
HashSet<Guid> 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<TComponent>() where TComponent : struct, IComponent
|
|
{
|
|
HashSet<Guid> 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<TComponent>() where TComponent : struct, IComponent
|
|
{
|
|
return ReadExistingAndPendingComponentsByType<TComponent>().First();
|
|
}
|
|
|
|
internal (Guid, TComponent) ReadFirstExistingComponentByType<TComponent>() where TComponent : struct, IComponent
|
|
{
|
|
return ReadExistingComponentsByType<TComponent>().First();
|
|
}
|
|
|
|
internal (Guid, TComponent) ReadFirstPendingComponentByType<TComponent>() where TComponent : struct, IComponent
|
|
{
|
|
return ReadPendingComponentsByType<TComponent>().First();
|
|
}
|
|
|
|
// check if some component of type exists in the world
|
|
|
|
internal bool SomeExistingOrPendingComponent<TComponent>() where TComponent : struct, IComponent
|
|
{
|
|
HashSet<Guid> idSet;
|
|
if (componentMessageTypeToComponentIDs.TryGetValue(typeof(TComponent), out idSet))
|
|
{
|
|
return idSet.Count > 0;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
internal bool SomeExistingComponent<TComponent>() where TComponent : struct, IComponent
|
|
{
|
|
HashSet<Guid> idSet;
|
|
if (componentMessageTypeToExistingComponentIDs.TryGetValue(typeof(TComponent), out idSet))
|
|
{
|
|
return idSet.Count > 0;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
internal bool SomePendingComponent<TComponent>() where TComponent : struct, IComponent
|
|
{
|
|
HashSet<Guid> 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<TComponent>(Entity entity) where TComponent : struct, IComponent
|
|
{
|
|
HashSet<Guid> 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<TComponent>(Entity entity) where TComponent : struct, IComponent
|
|
{
|
|
HashSet<Guid> 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<TComponent>(Entity entity) where TComponent : struct, IComponent
|
|
{
|
|
HashSet<Guid> 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<TComponent>(Entity entity) where TComponent : struct, IComponent
|
|
{
|
|
return ReadExistingAndPendingComponentsByEntityAndType<TComponent>(entity).First();
|
|
}
|
|
|
|
internal (Guid, TComponent) ReadFirstExistingComponentByEntityAndType<TComponent>(Entity entity) where TComponent : struct, IComponent
|
|
{
|
|
return ReadExistingComponentsByEntityAndType<TComponent>(entity).First();
|
|
}
|
|
|
|
internal (Guid, TComponent) ReadFirstPendingComponentByEntityAndType<TComponent>(Entity entity) where TComponent : struct, IComponent
|
|
{
|
|
return ReadPendingComponentsByEntityAndType<TComponent>(entity).First();
|
|
}
|
|
|
|
// check if entity has component of type
|
|
|
|
internal bool HasExistingOrPendingComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
|
|
{
|
|
HashSet<Guid> idSet;
|
|
if (entityToTypeToComponentIDs.TryGetValue(entity, out _) && entityToTypeToComponentIDs[entity].TryGetValue(typeof(TComponent), out idSet))
|
|
{
|
|
return idSet.Count > 0;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
internal bool HasExistingComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
|
|
{
|
|
HashSet<Guid> idSet;
|
|
if (entityToTypeToExistingComponentIDs.TryGetValue(entity, out _) && entityToTypeToExistingComponentIDs[entity].TryGetValue(typeof(TComponent), out idSet))
|
|
{
|
|
return idSet.Count > 0;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
internal bool HasPendingComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
|
|
{
|
|
HashSet<Guid> idSet;
|
|
if (entityToTypeToPendingComponentIDs.TryGetValue(entity, out _) && entityToTypeToPendingComponentIDs[entity].TryGetValue(typeof(TComponent), out idSet))
|
|
{
|
|
return idSet.Count > 0;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
}
|