optimize component message system
parent
ec3b0df585
commit
d86c002305
|
@ -1,13 +1,300 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Encompass
|
namespace Encompass
|
||||||
{
|
{
|
||||||
class ComponentMessageManager
|
class ComponentMessageManager
|
||||||
{
|
{
|
||||||
private readonly Dictionary<Type, HashSet<IMessage>> componentMessageTypeToComponentMessages = new Dictionary<Type, HashSet<IMessage>>();
|
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.TryGetValue(entity, out _) && 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.TryGetValue(entity, out _) && 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.TryGetValue(entity, out _) && 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace Encompass
|
||||||
private EntityManager entityManager;
|
private EntityManager entityManager;
|
||||||
private ComponentManager componentManager;
|
private ComponentManager componentManager;
|
||||||
private MessageManager messageManager;
|
private MessageManager messageManager;
|
||||||
|
private ComponentMessageManager componentMessageManager;
|
||||||
|
|
||||||
protected Engine()
|
protected Engine()
|
||||||
{
|
{
|
||||||
|
@ -69,6 +70,11 @@ namespace Encompass
|
||||||
this.messageManager = messageManager;
|
this.messageManager = messageManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void AssignComponentMessageManager(ComponentMessageManager componentMessageManager)
|
||||||
|
{
|
||||||
|
this.componentMessageManager = componentMessageManager;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract void Update(double dt);
|
public abstract void Update(double dt);
|
||||||
|
|
||||||
protected Entity CreateEntity()
|
protected Entity CreateEntity()
|
||||||
|
@ -119,11 +125,12 @@ namespace Encompass
|
||||||
|
|
||||||
if (sendTypes.Contains(typeof(PendingComponentMessage<TComponent>)))
|
if (sendTypes.Contains(typeof(PendingComponentMessage<TComponent>)))
|
||||||
{
|
{
|
||||||
PendingComponentMessage<TComponent> componentMessage;
|
PendingComponentMessage<TComponent> newComponentMessage;
|
||||||
componentMessage.entity = entity;
|
newComponentMessage.entity = entity;
|
||||||
componentMessage.componentID = componentID;
|
newComponentMessage.componentID = componentID;
|
||||||
componentMessage.component = component;
|
newComponentMessage.component = component;
|
||||||
SendMessage(componentMessage);
|
SendMessage(newComponentMessage);
|
||||||
|
SendPendingComponentMessage(newComponentMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
return componentID;
|
return componentID;
|
||||||
|
@ -142,36 +149,28 @@ namespace Encompass
|
||||||
newComponentMessage.componentID = componentID;
|
newComponentMessage.componentID = componentID;
|
||||||
newComponentMessage.component = component;
|
newComponentMessage.component = component;
|
||||||
SendMessage(newComponentMessage);
|
SendMessage(newComponentMessage);
|
||||||
|
SendPendingComponentMessage(newComponentMessage);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return componentID;
|
return componentID;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<ValueTuple<Entity, Guid, TComponent>> ExistingComponents<TComponent>() where TComponent : struct, IComponent
|
protected IEnumerable<ValueTuple<Guid, TComponent>> ReadComponents<TComponent>() where TComponent : struct, IComponent
|
||||||
{
|
|
||||||
return ReadMessages<ComponentMessage<TComponent>>().Select((message) => (message.entity, message.componentID, message.component));
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<ValueTuple<Entity, Guid, TComponent>> PendingComponents<TComponent>() where TComponent : struct, IComponent
|
|
||||||
{
|
|
||||||
return ReadMessages<PendingComponentMessage<TComponent>>().Select((message) => (message.entity, message.componentID, message.component));
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<ValueTuple<Entity, Guid, TComponent>> ReadComponentMessages<TComponent>() where TComponent : struct, IComponent
|
|
||||||
{
|
{
|
||||||
var pendingRead = receiveTypes.Contains(typeof(PendingComponentMessage<TComponent>));
|
var pendingRead = receiveTypes.Contains(typeof(PendingComponentMessage<TComponent>));
|
||||||
var existingRead = receiveTypes.Contains(typeof(ComponentMessage<TComponent>));
|
var existingRead = receiveTypes.Contains(typeof(ComponentMessage<TComponent>));
|
||||||
if (existingRead && pendingRead)
|
if (existingRead && pendingRead)
|
||||||
{
|
{
|
||||||
return ExistingComponents<TComponent>().Union(PendingComponents<TComponent>());
|
return componentMessageManager.ReadExistingAndPendingComponentsByType<TComponent>();
|
||||||
}
|
}
|
||||||
else if (existingRead)
|
else if (existingRead)
|
||||||
{
|
{
|
||||||
return ExistingComponents<TComponent>();
|
return componentMessageManager.ReadExistingComponentsByType<TComponent>();
|
||||||
}
|
}
|
||||||
else if (pendingRead)
|
else if (pendingRead)
|
||||||
{
|
{
|
||||||
return PendingComponents<TComponent>();
|
return componentMessageManager.ReadPendingComponentsByType<TComponent>();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -179,44 +178,115 @@ namespace Encompass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<ValueTuple<Guid, TComponent>> ExistingComponentsOnEntity<TComponent>(Entity entity) where TComponent : struct, IComponent
|
|
||||||
{
|
|
||||||
return ReadComponentMessages<TComponent>().Where((triple) => triple.Item1 == entity).Select((triple) => (triple.Item2, triple.Item3));
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<ValueTuple<Guid, TComponent>> PendingComponentsOnEntity<TComponent>(Entity entity) where TComponent : struct, IComponent
|
|
||||||
{
|
|
||||||
return ReadComponentMessages<TComponent>().Where((triple) => triple.Item1 == entity).Select((triple) => (triple.Item2, triple.Item3));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected IEnumerable<ValueTuple<Guid, TComponent>> ReadComponents<TComponent>() where TComponent : struct, IComponent
|
|
||||||
{
|
|
||||||
return ReadComponentMessages<TComponent>().Select((triple) => (triple.Item2, triple.Item3));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ValueTuple<Guid, TComponent> ReadComponent<TComponent>() where TComponent : struct, IComponent
|
protected ValueTuple<Guid, TComponent> ReadComponent<TComponent>() where TComponent : struct, IComponent
|
||||||
{
|
{
|
||||||
return ReadComponents<TComponent>().Single();
|
var pendingRead = receiveTypes.Contains(typeof(PendingComponentMessage<TComponent>));
|
||||||
|
var existingRead = receiveTypes.Contains(typeof(ComponentMessage<TComponent>));
|
||||||
|
if (existingRead && pendingRead)
|
||||||
|
{
|
||||||
|
return componentMessageManager.ReadFirstExistingOrPendingComponentByType<TComponent>();
|
||||||
|
}
|
||||||
|
else if (existingRead)
|
||||||
|
{
|
||||||
|
return componentMessageManager.ReadFirstExistingComponentByType<TComponent>();
|
||||||
|
}
|
||||||
|
else if (pendingRead)
|
||||||
|
{
|
||||||
|
return componentMessageManager.ReadFirstPendingComponentByType<TComponent>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalReadException("Engine {0} tried to read undeclared Component {1}", GetType().Name, typeof(TComponent).Name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected bool SomeComponent<TComponent>() where TComponent : struct, IComponent
|
protected bool SomeComponent<TComponent>() where TComponent : struct, IComponent
|
||||||
{
|
{
|
||||||
return ReadComponentMessages<TComponent>().Any();
|
var pendingRead = receiveTypes.Contains(typeof(PendingComponentMessage<TComponent>));
|
||||||
|
var existingRead = receiveTypes.Contains(typeof(ComponentMessage<TComponent>));
|
||||||
|
if (existingRead && pendingRead)
|
||||||
|
{
|
||||||
|
return componentMessageManager.SomeExistingOrPendingComponent<TComponent>();
|
||||||
|
}
|
||||||
|
else if (existingRead)
|
||||||
|
{
|
||||||
|
return componentMessageManager.SomeExistingComponent<TComponent>();
|
||||||
|
}
|
||||||
|
else if (pendingRead)
|
||||||
|
{
|
||||||
|
return componentMessageManager.SomePendingComponent<TComponent>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalReadException("Engine {0} tried to read undeclared Component {1}", GetType().Name, typeof(TComponent).Name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IEnumerable<ValueTuple<Guid, TComponent>> GetComponents<TComponent>(Entity entity) where TComponent : struct, IComponent
|
protected IEnumerable<ValueTuple<Guid, TComponent>> GetComponents<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||||
{
|
{
|
||||||
return ExistingComponentsOnEntity<TComponent>(entity);
|
var pendingRead = receiveTypes.Contains(typeof(PendingComponentMessage<TComponent>));
|
||||||
|
var existingRead = receiveTypes.Contains(typeof(ComponentMessage<TComponent>));
|
||||||
|
if (existingRead && pendingRead)
|
||||||
|
{
|
||||||
|
return componentMessageManager.ReadExistingAndPendingComponentsByEntityAndType<TComponent>(entity);
|
||||||
|
}
|
||||||
|
else if (existingRead)
|
||||||
|
{
|
||||||
|
return componentMessageManager.ReadExistingComponentsByEntityAndType<TComponent>(entity);
|
||||||
|
}
|
||||||
|
else if (pendingRead)
|
||||||
|
{
|
||||||
|
return componentMessageManager.ReadPendingComponentsByEntityAndType<TComponent>(entity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalReadException("Engine {0} tried to read undeclared Component {1}", GetType().Name, typeof(TComponent).Name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ValueTuple<Guid, TComponent> GetComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
|
protected ValueTuple<Guid, TComponent> GetComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||||
{
|
{
|
||||||
return GetComponents<TComponent>(entity).First();
|
var pendingRead = receiveTypes.Contains(typeof(PendingComponentMessage<TComponent>));
|
||||||
|
var existingRead = receiveTypes.Contains(typeof(ComponentMessage<TComponent>));
|
||||||
|
if (existingRead && pendingRead)
|
||||||
|
{
|
||||||
|
return componentMessageManager.ReadFirstExistingOrPendingComponentByEntityAndType<TComponent>(entity);
|
||||||
|
}
|
||||||
|
else if (existingRead)
|
||||||
|
{
|
||||||
|
return componentMessageManager.ReadFirstExistingComponentByEntityAndType<TComponent>(entity);
|
||||||
|
}
|
||||||
|
else if (pendingRead)
|
||||||
|
{
|
||||||
|
return componentMessageManager.ReadFirstPendingComponentByEntityAndType<TComponent>(entity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalReadException("Engine {0} tried to read undeclared Component {1}", GetType().Name, typeof(TComponent).Name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected bool HasComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
|
protected bool HasComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||||
{
|
{
|
||||||
return GetComponents<TComponent>(entity).Any();
|
var pendingRead = receiveTypes.Contains(typeof(PendingComponentMessage<TComponent>));
|
||||||
|
var existingRead = receiveTypes.Contains(typeof(ComponentMessage<TComponent>));
|
||||||
|
|
||||||
|
if (pendingRead && existingRead)
|
||||||
|
{
|
||||||
|
return componentMessageManager.HasExistingOrPendingComponent<TComponent>(entity);
|
||||||
|
}
|
||||||
|
else if (existingRead)
|
||||||
|
{
|
||||||
|
return componentMessageManager.HasExistingComponent<TComponent>(entity);
|
||||||
|
}
|
||||||
|
else if (pendingRead)
|
||||||
|
{
|
||||||
|
return componentMessageManager.HasPendingComponent<TComponent>(entity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalReadException("Engine {0} tried to read undeclared Component {1}", GetType().Name, typeof(TComponent).Name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void UpdateComponentInWorld<TComponent>(Guid componentID, TComponent newComponent) where TComponent : struct, IComponent
|
internal void UpdateComponentInWorld<TComponent>(Guid componentID, TComponent newComponent) where TComponent : struct, IComponent
|
||||||
|
@ -260,6 +330,16 @@ namespace Encompass
|
||||||
messageManager.AddMessage(message);
|
messageManager.AddMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void SendExistingComponentMessage<TComponent>(ComponentMessage<TComponent> message) where TComponent : struct, IComponent
|
||||||
|
{
|
||||||
|
componentMessageManager.AddExistingComponentMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void SendPendingComponentMessage<TComponent>(PendingComponentMessage<TComponent> message) where TComponent : struct, IComponent
|
||||||
|
{
|
||||||
|
componentMessageManager.AddPendingComponentMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
protected IEnumerable<TMessage> ReadMessages<TMessage>() where TMessage : struct, IMessage
|
protected IEnumerable<TMessage> ReadMessages<TMessage>() where TMessage : struct, IMessage
|
||||||
{
|
{
|
||||||
if (!receiveTypes.Contains(typeof(TMessage)))
|
if (!receiveTypes.Contains(typeof(TMessage)))
|
||||||
|
|
|
@ -18,6 +18,7 @@ namespace Encompass.Engines
|
||||||
componentMessage.componentID = componentID;
|
componentMessage.componentID = componentID;
|
||||||
componentMessage.component = component;
|
componentMessage.component = component;
|
||||||
SendMessage(componentMessage);
|
SendMessage(componentMessage);
|
||||||
|
SendExistingComponentMessage(componentMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,12 @@ namespace Encompass
|
||||||
private readonly HashSet<Guid> entitiesMarkedForDestroy = new HashSet<Guid>();
|
private readonly HashSet<Guid> entitiesMarkedForDestroy = new HashSet<Guid>();
|
||||||
|
|
||||||
private readonly ComponentManager componentManager;
|
private readonly ComponentManager componentManager;
|
||||||
|
private readonly ComponentMessageManager componentMessageManager;
|
||||||
|
|
||||||
public EntityManager(ComponentManager componentManager)
|
public EntityManager(ComponentManager componentManager, ComponentMessageManager componentMessageManager)
|
||||||
{
|
{
|
||||||
this.componentManager = componentManager;
|
this.componentManager = componentManager;
|
||||||
|
this.componentMessageManager = componentMessageManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Entity CreateEntity()
|
public Entity CreateEntity()
|
||||||
|
@ -44,6 +46,7 @@ namespace Encompass
|
||||||
{
|
{
|
||||||
foreach (var entityID in entitiesMarkedForDestroy)
|
foreach (var entityID in entitiesMarkedForDestroy)
|
||||||
{
|
{
|
||||||
|
componentMessageManager.RegisterDestroyedEntity(GetEntity(entityID));
|
||||||
componentManager.MarkAllComponentsOnEntityForRemoval(entityID);
|
componentManager.MarkAllComponentsOnEntityForRemoval(entityID);
|
||||||
IDToEntity.Remove(entityID);
|
IDToEntity.Remove(entityID);
|
||||||
componentManager.RegisterDestroyedEntity(entityID);
|
componentManager.RegisterDestroyedEntity(entityID);
|
||||||
|
|
|
@ -8,6 +8,7 @@ namespace Encompass
|
||||||
private readonly EntityManager entityManager;
|
private readonly EntityManager entityManager;
|
||||||
private readonly ComponentManager componentManager;
|
private readonly ComponentManager componentManager;
|
||||||
private readonly MessageManager messageManager;
|
private readonly MessageManager messageManager;
|
||||||
|
private readonly ComponentMessageManager componentMessageManager;
|
||||||
private readonly RenderManager renderManager;
|
private readonly RenderManager renderManager;
|
||||||
|
|
||||||
internal World(
|
internal World(
|
||||||
|
@ -15,6 +16,7 @@ namespace Encompass
|
||||||
EntityManager entityManager,
|
EntityManager entityManager,
|
||||||
ComponentManager componentManager,
|
ComponentManager componentManager,
|
||||||
MessageManager messageManager,
|
MessageManager messageManager,
|
||||||
|
ComponentMessageManager componentMessageManager,
|
||||||
RenderManager renderManager
|
RenderManager renderManager
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -22,6 +24,7 @@ namespace Encompass
|
||||||
this.entityManager = entityManager;
|
this.entityManager = entityManager;
|
||||||
this.componentManager = componentManager;
|
this.componentManager = componentManager;
|
||||||
this.messageManager = messageManager;
|
this.messageManager = messageManager;
|
||||||
|
this.componentMessageManager = componentMessageManager;
|
||||||
this.renderManager = renderManager;
|
this.renderManager = renderManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +36,7 @@ namespace Encompass
|
||||||
}
|
}
|
||||||
|
|
||||||
messageManager.ClearMessages();
|
messageManager.ClearMessages();
|
||||||
|
componentMessageManager.ClearMessages();
|
||||||
entityManager.DestroyMarkedEntities();
|
entityManager.DestroyMarkedEntities();
|
||||||
|
|
||||||
componentManager.PerformComponentUpdates();
|
componentManager.PerformComponentUpdates();
|
||||||
|
|
|
@ -15,6 +15,7 @@ namespace Encompass
|
||||||
private readonly ComponentManager componentManager;
|
private readonly ComponentManager componentManager;
|
||||||
private readonly EntityManager entityManager;
|
private readonly EntityManager entityManager;
|
||||||
private readonly MessageManager messageManager;
|
private readonly MessageManager messageManager;
|
||||||
|
private readonly ComponentMessageManager componentMessageManager;
|
||||||
private readonly DrawLayerManager drawLayerManager;
|
private readonly DrawLayerManager drawLayerManager;
|
||||||
private readonly RenderManager renderManager;
|
private readonly RenderManager renderManager;
|
||||||
|
|
||||||
|
@ -23,16 +24,14 @@ namespace Encompass
|
||||||
private readonly HashSet<Engine> senders = new HashSet<Engine>();
|
private readonly HashSet<Engine> senders = new HashSet<Engine>();
|
||||||
|
|
||||||
private readonly HashSet<Type> registeredComponentTypes = new HashSet<Type>();
|
private readonly HashSet<Type> registeredComponentTypes = new HashSet<Type>();
|
||||||
private readonly HashSet<Type> registeredNewComponentTypes = new HashSet<Type>();
|
|
||||||
|
|
||||||
public WorldBuilder()
|
public WorldBuilder()
|
||||||
{
|
{
|
||||||
var entitiesWithAddedComponents = new HashSet<Guid>();
|
|
||||||
var entitiesWithRemovedComponents = new HashSet<Guid>();
|
|
||||||
drawLayerManager = new DrawLayerManager();
|
drawLayerManager = new DrawLayerManager();
|
||||||
componentManager = new ComponentManager(drawLayerManager);
|
componentManager = new ComponentManager(drawLayerManager);
|
||||||
entityManager = new EntityManager(componentManager);
|
|
||||||
messageManager = new MessageManager();
|
messageManager = new MessageManager();
|
||||||
|
componentMessageManager = new ComponentMessageManager();
|
||||||
|
entityManager = new EntityManager(componentManager, componentMessageManager);
|
||||||
renderManager = new RenderManager(entityManager, componentManager, drawLayerManager);
|
renderManager = new RenderManager(entityManager, componentManager, drawLayerManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,6 +73,7 @@ namespace Encompass
|
||||||
engine.AssignEntityManager(entityManager);
|
engine.AssignEntityManager(entityManager);
|
||||||
engine.AssignComponentManager(componentManager);
|
engine.AssignComponentManager(componentManager);
|
||||||
engine.AssignMessageManager(messageManager);
|
engine.AssignMessageManager(messageManager);
|
||||||
|
engine.AssignComponentMessageManager(componentMessageManager);
|
||||||
|
|
||||||
engines.Add(engine);
|
engines.Add(engine);
|
||||||
engineGraph.AddVertex(engine);
|
engineGraph.AddVertex(engine);
|
||||||
|
@ -250,6 +250,7 @@ namespace Encompass
|
||||||
entityManager,
|
entityManager,
|
||||||
componentManager,
|
componentManager,
|
||||||
messageManager,
|
messageManager,
|
||||||
|
componentMessageManager,
|
||||||
renderManager
|
renderManager
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,9 @@ namespace Tests
|
||||||
|
|
||||||
var world = worldBuilder.Build();
|
var world = worldBuilder.Build();
|
||||||
|
|
||||||
Assert.Throws<InvalidOperationException>(() => world.Update(0.01f));
|
world.Update(0.01);
|
||||||
|
|
||||||
|
Assert.That(resultComponent, Is.EqualTo(mockComponent).Or.EqualTo(mockComponentB));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Reads(typeof(MockComponent))]
|
[Reads(typeof(MockComponent))]
|
||||||
|
|
Loading…
Reference in New Issue