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

View File

@ -17,19 +17,19 @@ namespace Encompass
public Engine()
{
var mutatesAttribute = this.GetType().GetCustomAttribute<Mutates>(false);
var mutatesAttribute = GetType().GetCustomAttribute<Mutates>(false);
if (mutatesAttribute != null)
{
mutateComponentTypes = mutatesAttribute.mutateComponentTypes;
}
var emitsAttribute = this.GetType().GetCustomAttribute<Emits>(false);
var emitsAttribute = GetType().GetCustomAttribute<Emits>(false);
if (emitsAttribute != null)
{
emitMessageTypes = emitsAttribute.emitMessageTypes;
}
var readsAttribute = this.GetType().GetCustomAttribute<Reads>(false);
var readsAttribute = GetType().GetCustomAttribute<Reads>(false);
if (readsAttribute != null)
{
readMessageTypes = readsAttribute.readMessageTypes;
@ -55,24 +55,34 @@ namespace Encompass
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
{
return this.componentManager.GetActiveComponentsByType<TComponent>();
return componentManager.GetActiveComponentsByType<TComponent>();
}
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
{
if (mutateComponentTypes.Contains(typeof(TComponent)))
{
this.componentManager.UpdateComponent(componentID, newComponent);
componentManager.UpdateComponent(componentID, newComponent);
}
else
{
@ -82,14 +92,14 @@ namespace Encompass
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
{
if (emitMessageTypes.Contains(typeof(TMessage)))
{
this.messageManager.AddMessage(message);
messageManager.AddMessage(message);
}
else
{
@ -101,7 +111,7 @@ namespace Encompass
{
if (readMessageTypes.Contains(typeof(TMessage)))
{
return this.messageManager.GetMessagesByType<TMessage>();
return messageManager.GetMessagesByType<TMessage>();
}
else
{
@ -120,5 +130,10 @@ namespace Encompass
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();
IDToEntity.Remove(entityID);
entityToEntityTrackers.Remove(entityID);
componentManager.RegisterDestroyedEntity(entityID);
}
entitiesMarkedForDestroy.Clear();

View File

@ -357,5 +357,60 @@ namespace Tests
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);
}
}
}