implement runtime type GetComponent

pull/5/head
thatcosmonaut 2019-11-13 13:24:20 -08:00
parent 591cd980d9
commit 3b6d473aeb
3 changed files with 108 additions and 0 deletions

View File

@ -249,6 +249,18 @@ namespace Encompass
}
}
internal (Guid, IComponent) ReadExistingComponentByEntityAndType(Entity entity, Type type)
{
if (entityToTypeToExistingComponentID.ContainsKey(entity) && entityToTypeToExistingComponentID[entity].TryGetValue(type, out Guid id))
{
return (id, componentIDToComponent[id]);
}
else
{
throw new NoComponentOfTypeOnEntityException("No Component of type {0} exists on Entity {1}", type.Name, entity.ID);
}
}
internal (Guid, TComponent) ReadPendingComponentByEntityAndType<TComponent>(Entity entity) where TComponent : struct, IComponent
{
if (entityToTypeToPendingComponentID.ContainsKey(entity) && entityToTypeToPendingComponentID[entity].TryGetValue(typeof(TComponent), out Guid id))
@ -261,6 +273,18 @@ namespace Encompass
}
}
internal (Guid, IComponent) ReadPendingComponentByEntityAndType(Entity entity, Type type)
{
if (entityToTypeToPendingComponentID.ContainsKey(entity) && entityToTypeToPendingComponentID[entity].TryGetValue(type, out Guid id))
{
return (id, componentIDToComponent[id]);
}
else
{
throw new NoComponentOfTypeOnEntityException("No Component of type {0} exists on Entity {1}", type.Name, entity.ID);
}
}
// check if entity has component of type
internal bool HasExistingOrPendingComponent<TComponent>(Entity entity) where TComponent : struct, IComponent

View File

@ -333,6 +333,52 @@ namespace Encompass
}
}
/// <summary>
/// Returns a Component with the specified Type that exists on the Entity.
/// </summary>
/// <exception cref="Encompass.Exceptions.NoComponentOfTypeOnEntityException">
/// Thrown when the Entity does not have a Component of the specified Type
/// </exception>
/// <exception cref="Encompass.Exceptions.IllegalReadException">
/// Thrown when the Engine does not declare that it reads the given Component Type.
/// </exception>
protected (Guid, IComponent) GetComponent(Entity entity, Type type)
{
var pending = typeof(PendingComponentMessage<>).MakeGenericType(type);
var existing = typeof(ComponentMessage<>).MakeGenericType(type);
var pendingRead = receiveTypes.Contains(pending);
var existingRead = receiveTypes.Contains(existing);
if (existingRead && pendingRead)
{
if (componentMessageManager.HasPendingComponent(entity, pending))
{
return componentMessageManager.ReadPendingComponentByEntityAndType(entity, pending);
}
else if (componentMessageManager.HasExistingComponent(entity, existing))
{
return componentMessageManager.ReadExistingComponentByEntityAndType(entity, existing);
}
else
{
throw new NoComponentOfTypeOnEntityException("No Component of type {0} exists on Entity {1}", type.Name, entity.ID);
}
}
else if (existingRead)
{
return componentMessageManager.ReadExistingComponentByEntityAndType(entity, existing);
}
else if (pendingRead)
{
return componentMessageManager.ReadPendingComponentByEntityAndType(entity, pending);
}
else
{
throw new IllegalReadException("Engine {0} tried to read undeclared Component {1}", GetType().Name, type.Name);
}
}
/// <summary>
/// Returns true if the Entity has a Component of the given Type.
/// </summary>

View File

@ -271,6 +271,44 @@ namespace Tests
Assert.AreEqual((componentID, mockComponent), gottenMockComponentIDPair);
}
[Receives(typeof(EntityMessage))]
[Reads(typeof(MockComponent))]
class GetMockComponentByRuntimeType : Engine
{
public override void Update(double dt)
{
foreach (var entityMessage in ReadMessages<EntityMessage>())
{
gottenMockComponentIDPair = ((Guid, MockComponent))GetComponent(entityMessage.entity, typeof(MockComponent));
}
}
}
[Test]
public void GetComponentByRuntimeType()
{
var worldBuilder = new WorldBuilder();
worldBuilder.AddEngine(new GetMockComponentEngine());
var entity = worldBuilder.CreateEntity();
MockComponent mockComponent;
mockComponent.myInt = 3;
mockComponent.myString = "hello";
var componentID = worldBuilder.SetComponent<MockComponent>(entity, mockComponent);
EntityMessage entityMessage;
entityMessage.entity = entity;
worldBuilder.SendMessage(entityMessage);
var world = worldBuilder.Build();
world.Update(0.01);
Assert.AreEqual((componentID, mockComponent), gottenMockComponentIDPair);
}
struct HasComponentTestMessage : IMessage
{
public Entity entity;