misc backend fixes + more tests

pull/5/head
Evan Hemsley 2019-06-19 20:37:46 -07:00
parent 116f424262
commit dd75a94d18
5 changed files with 176 additions and 14 deletions

View File

@ -161,8 +161,6 @@ namespace Encompass
{ {
MarkForRemoval(componentID); MarkForRemoval(componentID);
} }
entityIDToComponentIDs.Remove(entityID);
} }
internal void MarkForActivation(Guid componentID) internal void MarkForActivation(Guid componentID)
@ -217,7 +215,7 @@ namespace Encompass
componentsToDeactivate.Clear(); componentsToDeactivate.Clear();
} }
internal void RemoveMarkedComponents() public void RemoveMarkedComponents()
{ {
foreach (var componentID in componentsToRemove) foreach (var componentID in componentsToRemove)
{ {
@ -228,7 +226,10 @@ namespace Encompass
inactiveComponents.Remove(componentID); inactiveComponents.Remove(componentID);
var entityID = componentIDToEntityID[componentID]; var entityID = componentIDToEntityID[componentID];
entityIDToComponentIDs[entityID].Remove(componentID); if (entityIDToComponentIDs.ContainsKey(entityID))
{
entityIDToComponentIDs[entityID].Remove(componentID);
}
IDToComponent.Remove(componentID); IDToComponent.Remove(componentID);
componentIDToType.Remove(componentID); componentIDToType.Remove(componentID);
@ -243,5 +244,10 @@ namespace Encompass
componentsToRemove.Clear(); componentsToRemove.Clear();
} }
public void RegisterDestroyedEntity(Guid entityID)
{
entityIDToComponentIDs.Remove(entityID);
}
} }
} }

View File

@ -17,19 +17,19 @@ namespace Encompass
public Engine() public Engine()
{ {
var mutatesAttribute = this.GetType().GetCustomAttribute<Mutates>(false); var mutatesAttribute = GetType().GetCustomAttribute<Mutates>(false);
if (mutatesAttribute != null) if (mutatesAttribute != null)
{ {
mutateComponentTypes = mutatesAttribute.mutateComponentTypes; mutateComponentTypes = mutatesAttribute.mutateComponentTypes;
} }
var emitsAttribute = this.GetType().GetCustomAttribute<Emits>(false); var emitsAttribute = GetType().GetCustomAttribute<Emits>(false);
if (emitsAttribute != null) if (emitsAttribute != null)
{ {
emitMessageTypes = emitsAttribute.emitMessageTypes; emitMessageTypes = emitsAttribute.emitMessageTypes;
} }
var readsAttribute = this.GetType().GetCustomAttribute<Reads>(false); var readsAttribute = GetType().GetCustomAttribute<Reads>(false);
if (readsAttribute != null) if (readsAttribute != null)
{ {
readMessageTypes = readsAttribute.readMessageTypes; readMessageTypes = readsAttribute.readMessageTypes;
@ -55,24 +55,34 @@ namespace Encompass
protected Entity CreateEntity() protected Entity CreateEntity()
{ {
return this.entityManager.CreateEntity(); return entityManager.CreateEntity();
}
protected Entity GetEntity(Guid entityID)
{
return entityManager.GetEntity(entityID);
}
protected Guid GetEntityIDFromComponentID(Guid componentID)
{
return componentManager.GetEntityIDFromComponentID(componentID);
} }
protected IEnumerable<KeyValuePair<Guid, TComponent>> ReadComponents<TComponent>() where TComponent : struct, IComponent protected IEnumerable<KeyValuePair<Guid, TComponent>> ReadComponents<TComponent>() where TComponent : struct, IComponent
{ {
return this.componentManager.GetActiveComponentsByType<TComponent>(); return componentManager.GetActiveComponentsByType<TComponent>();
} }
protected KeyValuePair<Guid, TComponent> ReadComponent<TComponent>() where TComponent : struct, IComponent protected KeyValuePair<Guid, TComponent> ReadComponent<TComponent>() where TComponent : struct, IComponent
{ {
return this.componentManager.GetActiveComponentByType<TComponent>(); return componentManager.GetActiveComponentByType<TComponent>();
} }
internal void UpdateComponentInWorld<TComponent>(Guid componentID, TComponent newComponent) where TComponent : struct, IComponent internal void UpdateComponentInWorld<TComponent>(Guid componentID, TComponent newComponent) where TComponent : struct, IComponent
{ {
if (mutateComponentTypes.Contains(typeof(TComponent))) if (mutateComponentTypes.Contains(typeof(TComponent)))
{ {
this.componentManager.UpdateComponent(componentID, newComponent); componentManager.UpdateComponent(componentID, newComponent);
} }
else else
{ {
@ -82,14 +92,14 @@ namespace Encompass
protected void UpdateComponent<TComponent>(Guid componentID, TComponent newComponentValue) where TComponent : struct, IComponent protected void UpdateComponent<TComponent>(Guid componentID, TComponent newComponentValue) where TComponent : struct, IComponent
{ {
this.UpdateComponentInWorld(componentID, newComponentValue); UpdateComponentInWorld(componentID, newComponentValue);
} }
protected void EmitMessage<TMessage>(TMessage message) where TMessage : struct, IMessage protected void EmitMessage<TMessage>(TMessage message) where TMessage : struct, IMessage
{ {
if (emitMessageTypes.Contains(typeof(TMessage))) if (emitMessageTypes.Contains(typeof(TMessage)))
{ {
this.messageManager.AddMessage(message); messageManager.AddMessage(message);
} }
else else
{ {
@ -101,7 +111,7 @@ namespace Encompass
{ {
if (readMessageTypes.Contains(typeof(TMessage))) if (readMessageTypes.Contains(typeof(TMessage)))
{ {
return this.messageManager.GetMessagesByType<TMessage>(); return messageManager.GetMessagesByType<TMessage>();
} }
else else
{ {
@ -120,5 +130,10 @@ namespace Encompass
throw new IllegalMessageReadException("Engine {0} tried to read undeclared Message {1}", this.GetType().Name, typeof(TMessage).Name); throw new IllegalMessageReadException("Engine {0} tried to read undeclared Message {1}", this.GetType().Name, typeof(TMessage).Name);
} }
} }
protected void Destroy(Guid entityID)
{
entityManager.MarkForDestroy(entityID);
}
} }
} }

View File

@ -54,6 +54,7 @@ namespace Encompass
entity.RemoveAllComponents(); entity.RemoveAllComponents();
IDToEntity.Remove(entityID); IDToEntity.Remove(entityID);
entityToEntityTrackers.Remove(entityID); entityToEntityTrackers.Remove(entityID);
componentManager.RegisterDestroyedEntity(entityID);
} }
entitiesMarkedForDestroy.Clear(); entitiesMarkedForDestroy.Clear();

View File

@ -357,5 +357,60 @@ namespace Tests
Assert.That(emptyComponentReadResult, Is.Empty); Assert.That(emptyComponentReadResult, Is.Empty);
} }
struct DestroyerComponent : IComponent { }
class DestroyerEngine : Engine
{
public override void Update(float dt)
{
var componentPairs = ReadComponents<DestroyerComponent>();
foreach (var componentPair in componentPairs)
{
var componentID = componentPair.Key;
var entityID = GetEntityIDFromComponentID(componentID);
Destroy(entityID);
}
}
}
static IEnumerable<KeyValuePair<Guid, MockComponent>> results;
class ReaderEngine : Engine
{
public override void Update(float dt)
{
results = ReadComponents<MockComponent>();
}
}
[Test]
public void DestroyEntity()
{
var worldBuilder = new WorldBuilder();
worldBuilder.AddEngine<DestroyerEngine>();
worldBuilder.AddEngine<ReaderEngine>();
var entity = worldBuilder.CreateEntity();
var entityB = worldBuilder.CreateEntity();
DestroyerComponent destroyerComponent;
MockComponent mockComponent;
mockComponent.myInt = 2;
mockComponent.myString = "blah";
entity.AddComponent(destroyerComponent);
var componentID = entity.AddComponent(mockComponent);
entityB.AddComponent(destroyerComponent);
var componentBID = entityB.AddComponent(mockComponent);
var world = worldBuilder.Build();
world.Update(0.01f);
Assert.That(results, Does.Not.Contain(new KeyValuePair<Guid, MockComponent>(componentID, mockComponent)));
Assert.That(results, Does.Not.Contain(new KeyValuePair<Guid, MockComponent>(componentBID, mockComponent)));
}
} }
} }

85
test/WorldTest.cs Normal file
View File

@ -0,0 +1,85 @@
using NUnit.Framework;
using FluentAssertions;
using System;
using System.Collections.Generic;
using System.Text;
using Encompass;
namespace Tests
{
public class WorldTest
{
struct TestComponent : IComponent { }
struct TestDrawComponent : IDrawComponent
{
public int Layer { get ; set; }
}
static List<object> drawOrder = new List<object>();
[Renders(typeof(TestDrawComponent), typeof(TestComponent))]
class TestEntityRenderer : EntityRenderer
{
public override void Render(Entity entity)
{
drawOrder.Add(entity);
}
}
class TestGeneralRenderer : GeneralRenderer
{
public new int Layer { get { return 9; } }
public override void Render()
{
drawOrder.Add(this);
}
}
[Test]
public void DrawOrder()
{
var worldBuilder = new WorldBuilder();
worldBuilder.AddRenderer<TestEntityRenderer>();
var testGeneralRenderer = worldBuilder.AddRenderer<TestGeneralRenderer>();
TestComponent testComponent;
TestDrawComponent testDrawComponent = default(TestDrawComponent);
testDrawComponent.Layer = 3;
var entity = worldBuilder.CreateEntity();
entity.AddComponent(testComponent);
entity.AddComponent(testDrawComponent);
TestDrawComponent testDrawComponentTwo = default(TestDrawComponent);
testDrawComponentTwo.Layer = 1;
var entityTwo = worldBuilder.CreateEntity();
entityTwo.AddComponent(testComponent);
entityTwo.AddComponent(testDrawComponentTwo);
TestDrawComponent testDrawComponentThree = default(TestDrawComponent);
testDrawComponentThree.Layer = 5;
var entityThree = worldBuilder.CreateEntity();
entityThree.AddComponent(testComponent);
entityThree.AddComponent(testDrawComponentThree);
TestDrawComponent testDrawComponentFour = default(TestDrawComponent);
testDrawComponentFour.Layer = -5;
var entityFour = worldBuilder.CreateEntity();
entityFour.AddComponent(testComponent);
entityFour.AddComponent(testDrawComponentFour);
var world = worldBuilder.Build();
world.Update(0.01f);
world.Draw();
drawOrder.Should().BeEquivalentTo(entityFour, entityTwo, entity, entityThree, testGeneralRenderer);
}
}
}