diff --git a/encompass-cs/Attributes/Reads.cs b/encompass-cs/Attributes/Reads.cs index bd10431..b222f38 100644 --- a/encompass-cs/Attributes/Reads.cs +++ b/encompass-cs/Attributes/Reads.cs @@ -14,9 +14,9 @@ namespace Encompass { foreach (var readType in readTypes) { - if (!readType.GetInterfaces().Contains(typeof(IMessage)) && !readType.GetInterfaces().Contains(typeof(IComponent))) + if (!readType.GetInterfaces().Contains(typeof(IMessage))) { - throw new IllegalReadTypeException("{0} must be a Message or Component", readType.Name); + throw new IllegalReadTypeException("{0} must be a Message", readType.Name); } } diff --git a/encompass-cs/Attributes/Writes.cs b/encompass-cs/Attributes/Writes.cs index 67d03ae..7467e33 100644 --- a/encompass-cs/Attributes/Writes.cs +++ b/encompass-cs/Attributes/Writes.cs @@ -20,6 +20,11 @@ namespace Encompass } } + if (writeTypes.Any((type) => type.GetInterfaces().Contains(typeof(IMessage))) && writeTypes.Any((type) => type.GetInterfaces().Contains(typeof(IComponent)))) + { + throw new ComponentAndMessageWriteException("An Engine which writes Components cannot also write Messages"); + } + this.writeTypes = new HashSet(writeTypes); } } diff --git a/encompass-cs/ComponentManager.cs b/encompass-cs/ComponentManager.cs index 9bf4550..87433aa 100644 --- a/encompass-cs/ComponentManager.cs +++ b/encompass-cs/ComponentManager.cs @@ -10,14 +10,18 @@ namespace Encompass private readonly Dictionary componentIDToType = new Dictionary(); private readonly Dictionary IDToComponent = new Dictionary(); - private readonly Dictionary> entityIDToComponentIDs = new Dictionary>(); + private readonly Dictionary> entityIDToComponentIDs = new Dictionary>(); // TODO: hashset private readonly Dictionary componentIDToEntityID = new Dictionary(); - private readonly Dictionary> typeToComponentIDs = new Dictionary>(); + private readonly Dictionary> typeToComponentIDs = new Dictionary>(); // TODO: hashset private readonly List activeComponents = new List(); private readonly List inactiveComponents = new List(); + private readonly HashSet componentsMarkedForActivation = new HashSet(); + private readonly HashSet componentsMarkedForDeactivation = new HashSet(); + private readonly HashSet componentsMarkedForRemoval = new HashSet(); + //shared references with EntityManager private readonly HashSet entitiesWithAddedComponents; private readonly HashSet entitiesWithRemovedComponents; @@ -56,7 +60,7 @@ namespace Encompass componentIDToEntityID[componentID] = entityID; inactiveComponents.Add(componentID); - Activate(componentID); + MarkForActivation(componentID); entitiesWithAddedComponents.Add(entityID); @@ -150,17 +154,30 @@ namespace Encompass IDToComponent[componentID] = newComponentValue; } - internal void RemoveAllComponentsFromEntity(Guid entityID) + internal void MarkAllComponentsOnEntityForRemoval(Guid entityID) { - var componentIDs = entityIDToComponentIDs[entityID]; - - for (int i = componentIDs.Count - 1; i >= 0; i--) + foreach (var componentID in GetComponentIDsByEntityID(entityID)) { - Remove(componentIDs[i]); + MarkForRemoval(componentID); } } - internal void Activate(Guid componentID) + internal void MarkForActivation(Guid componentID) + { + componentsMarkedForActivation.Add(componentID); + } + + internal void ActivateMarkedComponents() + { + foreach (var componentID in componentsMarkedForActivation) + { + Activate(componentID); + } + + componentsMarkedForActivation.Clear(); + } + + private void Activate(Guid componentID) { if (inactiveComponents.Remove(componentID)) { @@ -171,7 +188,22 @@ namespace Encompass entitiesWithAddedComponents.Add(entityID); } - internal void Deactivate(Guid componentID) + internal void MarkForDeactivation(Guid componentID) + { + componentsMarkedForDeactivation.Add(componentID); + } + + internal void DeactivateMarkedComponents() + { + foreach (var componentID in componentsMarkedForDeactivation) + { + Deactivate(componentID); + } + + componentsMarkedForDeactivation.Clear(); + } + + private void Deactivate(Guid componentID) { if (activeComponents.Remove(componentID)) { @@ -182,7 +214,22 @@ namespace Encompass entitiesWithRemovedComponents.Add(entityID); } - internal void Remove(Guid componentID) + internal void MarkForRemoval(Guid componentID) + { + componentsMarkedForRemoval.Add(componentID); + } + + internal void RemoveMarkedComponents() + { + foreach (var componentID in componentsMarkedForRemoval) + { + Remove(componentID); + } + + componentsMarkedForRemoval.Clear(); + } + + private void Remove(Guid componentID) { var component = IDToComponent[componentID]; var type = componentIDToType[componentID]; diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index 4e56064..219535c 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -74,11 +74,6 @@ namespace Encompass protected TComponent GetComponentByID(Guid componentID) where TComponent : struct, IComponent { - if (!readTypes.Contains(typeof(TComponent))) - { - throw new IllegalReadException("Engine {0} tried to read undeclared Component {1}", this.GetType().Name, typeof(TComponent).Name); - } - if (componentManager.GetComponentTypeByID(componentID) != typeof(TComponent)) { throw new ComponentTypeMismatchException("Expected Component to be of type {0} but was actually of type {1}", typeof(TComponent).Name, componentManager.GetComponentTypeByID(componentID).Name); @@ -89,73 +84,36 @@ namespace Encompass protected IEnumerable> ReadComponents() where TComponent : struct, IComponent { - if (!readTypes.Contains(typeof(TComponent))) - { - throw new IllegalReadException("Engine {0} tried to read undeclared Component {1}", this.GetType().Name, typeof(TComponent).Name); - } - return componentManager.GetActiveComponentsByType(); } protected ValueTuple ReadComponent() where TComponent : struct, IComponent { - if (!readTypes.Contains(typeof(TComponent))) - { - throw new IllegalReadException("Engine {0} tried to read undeclared Component {1}", this.GetType().Name, typeof(TComponent).Name); - } - return componentManager.GetActiveComponentByType(); } protected Guid AddComponent(Entity entity, TComponent component) where TComponent : struct, IComponent { - if (!writeTypes.Contains(typeof(TComponent))) - { - throw new IllegalWriteException("Engine {0} tried to write undeclared Component {1}", this.GetType().Name, typeof(TComponent).Name); - } - return componentManager.AddComponent(entity.ID, component); } protected Guid AddDrawComponent(Entity entity, TComponent component, int layer = 0) where TComponent : struct, IComponent { - if (!writeTypes.Contains(typeof(TComponent))) - { - throw new IllegalWriteException("Engine {0} tried to write undeclared Component {1}", this.GetType().Name, typeof(TComponent).Name); - } - return componentManager.AddDrawComponent(entity.ID, component, layer); } protected void ActivateComponent(Guid componentID) { - var type = componentManager.GetComponentTypeByID(componentID); - if (!writeTypes.Contains(type)) - { - throw new IllegalWriteException("Engine {0} tried to write undeclared Component {1}", this.GetType().Name, type.Name); - } - - componentManager.Activate(componentID); + componentManager.MarkForActivation(componentID); } protected void DeactivateComponent(Guid componentID) { - var type = componentManager.GetComponentTypeByID(componentID); - if (!writeTypes.Contains(type)) - { - throw new IllegalWriteException("Engine {0} tried to write undeclared Component {1}", this.GetType().Name, type.Name); - } - - componentManager.Deactivate(componentID); + componentManager.MarkForDeactivation(componentID); } protected IEnumerable> GetComponents(Entity entity) where TComponent : struct, IComponent { - if (!readTypes.Contains(typeof(TComponent))) - { - throw new IllegalReadException("Engine {0} tried to read undeclared Component {1}", this.GetType().Name, typeof(TComponent).Name); - } - return componentManager.GetComponentsByEntityAndType(entity.ID); } @@ -166,11 +124,6 @@ namespace Encompass protected bool HasComponent(Entity entity) where TComponent : struct, IComponent { - if (!readTypes.Contains(typeof(TComponent))) - { - throw new IllegalReadException("Engine {0} tried to read undeclared Component {1}", this.GetType().Name, typeof(TComponent).Name); - } - return componentManager.EntityHasComponentOfType(entity.ID); } @@ -193,11 +146,10 @@ namespace Encompass { if (!writeTypes.Contains(typeof(TMessage))) { - throw new IllegalWriteException("Engine {0} tried to emit undeclared Message {1}", this.GetType().Name, typeof(TMessage).Name); + throw new IllegalWriteException("Engine {0} tried to write undeclared Message {1}", this.GetType().Name, typeof(TMessage).Name); } messageManager.AddMessage(message); - } protected IEnumerable ReadMessages() where TMessage : struct, IMessage @@ -222,11 +174,6 @@ namespace Encompass protected bool SomeComponent() where TComponent : struct, IComponent { - if (!readTypes.Contains(typeof(TComponent))) - { - throw new IllegalReadException("Engine {0} tried to read undeclared Component {1}", this.GetType().Name, typeof(TComponent).Name); - } - return componentManager.GetActiveComponentsByType().Any(); } @@ -237,13 +184,7 @@ namespace Encompass protected void RemoveComponent(Guid componentID) { - var type = componentManager.GetComponentTypeByID(componentID); - if (!writeTypes.Contains(type)) - { - throw new IllegalWriteException("Engine {0} tried to write undeclared Component {1}", this.GetType().Name, type.Name); - } - - componentManager.Remove(componentID); + componentManager.MarkForRemoval(componentID); } } } diff --git a/encompass-cs/EntityManager.cs b/encompass-cs/EntityManager.cs index a01969f..f319b13 100644 --- a/encompass-cs/EntityManager.cs +++ b/encompass-cs/EntityManager.cs @@ -56,7 +56,7 @@ namespace Encompass { foreach (var entityID in entitiesMarkedForDestroy) { - componentManager.RemoveAllComponentsFromEntity(entityID); + componentManager.MarkAllComponentsOnEntityForRemoval(entityID); IDToEntity.Remove(entityID); entityToEntityTrackers.Remove(entityID); componentManager.RegisterDestroyedEntity(entityID); diff --git a/encompass-cs/Exceptions/ComponentAndMessageWriteException.cs b/encompass-cs/Exceptions/ComponentAndMessageWriteException.cs new file mode 100644 index 0000000..31c0abc --- /dev/null +++ b/encompass-cs/Exceptions/ComponentAndMessageWriteException.cs @@ -0,0 +1,13 @@ + +using System; + +namespace Encompass.Exceptions +{ + public class ComponentAndMessageWriteException : Exception + { + public ComponentAndMessageWriteException( + string format, + params object[] args + ) : base(string.Format(format, args)) { } + } +} diff --git a/encompass-cs/World.cs b/encompass-cs/World.cs index 9d9abe6..f349877 100644 --- a/encompass-cs/World.cs +++ b/encompass-cs/World.cs @@ -35,6 +35,10 @@ namespace Encompass messageManager.ClearMessages(); entityManager.DestroyMarkedEntities(); + componentManager.ActivateMarkedComponents(); + componentManager.DeactivateMarkedComponents(); + componentManager.RemoveMarkedComponents(); + entityManager.CheckEntitiesWithAddedComponents(); entityManager.CheckEntitiesWithRemovedComponents(); } diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs index 4732fe4..16c4b98 100644 --- a/encompass-cs/WorldBuilder.cs +++ b/encompass-cs/WorldBuilder.cs @@ -53,7 +53,7 @@ namespace Encompass public void DeactivateComponent(Guid componentID) { - componentManager.Deactivate(componentID); + componentManager.MarkForDeactivation(componentID); } public Engine AddEngine(TEngine engine) where TEngine : Engine @@ -65,12 +65,7 @@ namespace Encompass engines.Add(engine); engineGraph.AddVertex(engine); - if (engine is IEntityTracker) - { - entityManager.RegisterEntityTracker(engine as IEntityTracker); - } - - foreach (var writeType in engine.writeTypes) + foreach (var writeType in engine.writeTypes.Where((type) => type.GetInterfaces().Contains(typeof(IMessage)))) { if (!typeToEmitters.ContainsKey(writeType)) { @@ -98,7 +93,7 @@ namespace Encompass } } - foreach (var readType in engine.readTypes) + foreach (var readType in engine.readTypes.Where((type) => type.GetInterfaces().Contains(typeof(IMessage)))) { if (!typeToReaders.ContainsKey(readType)) { @@ -229,6 +224,10 @@ namespace Encompass renderManager ); + componentManager.ActivateMarkedComponents(); + componentManager.DeactivateMarkedComponents(); + componentManager.RemoveMarkedComponents(); + entityManager.CheckEntitiesWithAddedComponents(); entityManager.CheckEntitiesWithRemovedComponents(); diff --git a/test/ComponentTest.cs b/test/ComponentTest.cs index 554e083..a32018f 100644 --- a/test/ComponentTest.cs +++ b/test/ComponentTest.cs @@ -24,7 +24,7 @@ namespace Tests static IEnumerable<(Guid, MockComponent)> gottenMockComponentIDPairs = Enumerable.Empty<(Guid, MockComponent)>(); static (Guid, MockComponent) gottenMockComponentIDPair; - [Reads(typeof(EntityMessage), typeof(MockComponent))] + [Reads(typeof(EntityMessage))] class GetMockComponentsEngine : Engine { public override void Update(double dt) @@ -38,7 +38,7 @@ namespace Tests } } - [Reads(typeof(EntityMessage), typeof(MockComponent))] + [Reads(typeof(EntityMessage))] class GetMockComponentEngine : Engine { public override void Update(double dt) @@ -56,7 +56,7 @@ namespace Tests public MockComponent mockComponent; } - [Reads(typeof(AddComponentTestMessage), typeof(MockComponent))] + [Reads(typeof(AddComponentTestMessage))] class AddComponentEngine : Engine { public override void Update(double dt) @@ -161,7 +161,7 @@ namespace Tests public Entity entity; } - [Reads(typeof(HasComponentTestMessage), typeof(MockComponent))] + [Reads(typeof(HasComponentTestMessage))] class HasComponentTestEngine : Engine { public override void Update(double dt) @@ -201,7 +201,7 @@ namespace Tests public Entity entity; } - [Reads(typeof(HasComponentWhenInactiveTestMessage), typeof(MockComponent))] + [Reads(typeof(HasComponentWhenInactiveTestMessage))] class HasComponentWhenInactiveTestEngine : Engine { public override void Update(double dt) @@ -243,7 +243,7 @@ namespace Tests public Guid componentID; } - [Reads(typeof(RemoveComponentTestMessage), typeof(MockComponent))] + [Reads(typeof(RemoveComponentTestMessage))] [Writes(typeof(MockComponent))] class RemoveComponentTestEngine : Engine { @@ -252,9 +252,36 @@ namespace Tests foreach (var removeComponentMessage in ReadMessages()) { RemoveComponent(removeComponentMessage.componentID); + } + } + } - Assert.IsFalse(HasComponent(removeComponentMessage.entity)); - Assert.IsEmpty(GetComponents(removeComponentMessage.entity)); + [Reads(typeof(RemoveComponentTestMessage))] + [Writes(typeof(CheckHasMockComponentMessage))] + class DoRemoveCheckEngine : Engine + { + private Entity entity; + + public DoRemoveCheckEngine(Entity entity) + { + this.entity = entity; + } + + public override void Update(double dt) + { + if (SomeMessage()) + { + CheckHasMockComponentMessage checkHasMockComponentMessage; + checkHasMockComponentMessage.entity = entity; + checkHasMockComponentMessage.shouldHaveComponent = true; + EmitMessage(checkHasMockComponentMessage); + } + else + { + CheckHasMockComponentMessage checkHasMockComponentMessage; + checkHasMockComponentMessage.entity = entity; + checkHasMockComponentMessage.shouldHaveComponent = false; + EmitMessage(checkHasMockComponentMessage); } } } @@ -263,10 +290,12 @@ namespace Tests public void RemoveComponent() { var worldBuilder = new WorldBuilder(); - worldBuilder.AddEngine(new RemoveComponentTestEngine()); - var entity = worldBuilder.CreateEntity(); + worldBuilder.AddEngine(new RemoveComponentTestEngine()); + worldBuilder.AddEngine(new CheckHasMockComponentEngine()); + worldBuilder.AddEngine(new DoRemoveCheckEngine(entity)); + MockComponent mockComponent; mockComponent.myInt = 3; mockComponent.myString = "hello"; @@ -280,7 +309,6 @@ namespace Tests var world = worldBuilder.Build(); - world.Update(0.01f); } @@ -290,7 +318,7 @@ namespace Tests public Guid componentID; } - [Reads(typeof(ActivateComponentMessage), typeof(MockComponent))] + [Reads(typeof(ActivateComponentMessage))] [Writes(typeof(MockComponent))] class ActivateComponentEngine : Engine { @@ -299,7 +327,61 @@ namespace Tests foreach (var activateComponentMessage in ReadMessages()) { ActivateComponent(activateComponentMessage.componentID); - Assert.IsTrue(HasComponent(activateComponentMessage.entity)); + } + } + } + + struct CheckHasMockComponentMessage : IMessage + { + public Entity entity; + public bool shouldHaveComponent; + } + + [Reads(typeof(ActivateComponentMessage))] + [Writes(typeof(CheckHasMockComponentMessage))] + class DoActivateCheckEngine : Engine + { + private Entity entity; + + public DoActivateCheckEngine(Entity entity) + { + this.entity = entity; + } + + public override void Update(double dt) + { + if (SomeMessage()) + { + CheckHasMockComponentMessage checkHasMockComponentMessage; + checkHasMockComponentMessage.entity = entity; + checkHasMockComponentMessage.shouldHaveComponent = false; + EmitMessage(checkHasMockComponentMessage); + } + else + { + CheckHasMockComponentMessage checkHasMockComponentMessage; + checkHasMockComponentMessage.entity = entity; + checkHasMockComponentMessage.shouldHaveComponent = true; + EmitMessage(checkHasMockComponentMessage); + } + } + } + + [Reads(typeof(CheckHasMockComponentMessage))] + class CheckHasMockComponentEngine : Engine + { + public override void Update(double dt) + { + foreach (var checkHasMockComponentMessage in ReadMessages()) + { + if (checkHasMockComponentMessage.shouldHaveComponent) + { + Assert.IsTrue(HasComponent(checkHasMockComponentMessage.entity)); + } + else + { + Assert.IsFalse(HasComponent(checkHasMockComponentMessage.entity)); + } } } } @@ -308,10 +390,12 @@ namespace Tests public void ActivateComponent() { var worldBuilder = new WorldBuilder(); - worldBuilder.AddEngine(new ActivateComponentEngine()); - var entity = worldBuilder.CreateEntity(); + worldBuilder.AddEngine(new ActivateComponentEngine()); + worldBuilder.AddEngine(new CheckHasMockComponentEngine()); + worldBuilder.AddEngine(new DoActivateCheckEngine(entity)); + MockComponent mockComponent; mockComponent.myInt = 3; mockComponent.myString = "hello"; @@ -327,7 +411,8 @@ namespace Tests var world = worldBuilder.Build(); - world.Update(0.01f); + world.Update(0.01); + world.Update(0.01); } struct DeactivateComponentMessage : IMessage @@ -336,7 +421,7 @@ namespace Tests public Guid componentID; } - [Reads(typeof(DeactivateComponentMessage), typeof(MockComponent))] + [Reads(typeof(DeactivateComponentMessage))] [Writes(typeof(MockComponent))] class DeactivateComponentEngine : Engine { @@ -345,7 +430,36 @@ namespace Tests foreach (var deactivateComponentMessage in ReadMessages()) { DeactivateComponent(deactivateComponentMessage.componentID); - Assert.IsFalse(HasComponent(deactivateComponentMessage.entity)); + } + } + } + + [Reads(typeof(DeactivateComponentMessage))] + [Writes(typeof(CheckHasMockComponentMessage))] + class DoDeactivateCheckEngine : Engine + { + private Entity entity; + + public DoDeactivateCheckEngine(Entity entity) + { + this.entity = entity; + } + + public override void Update(double dt) + { + if (SomeMessage()) + { + CheckHasMockComponentMessage checkHasMockComponentMessage; + checkHasMockComponentMessage.entity = entity; + checkHasMockComponentMessage.shouldHaveComponent = true; + EmitMessage(checkHasMockComponentMessage); + } + else + { + CheckHasMockComponentMessage checkHasMockComponentMessage; + checkHasMockComponentMessage.entity = entity; + checkHasMockComponentMessage.shouldHaveComponent = false; + EmitMessage(checkHasMockComponentMessage); } } } @@ -354,10 +468,12 @@ namespace Tests public void DeactivateComponent() { var worldBuilder = new WorldBuilder(); - worldBuilder.AddEngine(new DeactivateComponentEngine()); - var entity = worldBuilder.CreateEntity(); + worldBuilder.AddEngine(new DeactivateComponentEngine()); + worldBuilder.AddEngine(new CheckHasMockComponentEngine()); + worldBuilder.AddEngine(new DoDeactivateCheckEngine(entity)); + MockComponent mockComponent; mockComponent.myInt = 3; mockComponent.myString = "hello"; diff --git a/test/EngineTest.cs b/test/EngineTest.cs index 95b6fe9..432555d 100644 --- a/test/EngineTest.cs +++ b/test/EngineTest.cs @@ -23,7 +23,6 @@ namespace Tests static List resultMessages; - [Reads(typeof(MockComponent))] public class ReadComponentsTestEngine : Engine { public override void Update(double dt) @@ -32,7 +31,6 @@ namespace Tests } } - [Reads(typeof(MockComponent))] public class ReadComponentTestEngine : Engine { public override void Update(double dt) @@ -118,7 +116,6 @@ namespace Tests Assert.Throws(() => world.Update(0.01f)); } - [Reads(typeof(MockComponent))] [Writes(typeof(MockComponent))] public class UpdateComponentTestEngine : Engine { @@ -156,7 +153,6 @@ namespace Tests Assert.AreEqual("blaze it", resultComponent.myString); } - [Reads(typeof(MockComponent))] public class UndeclaredUpdateComponentTestEngine : Engine { public override void Update(double dt) @@ -243,6 +239,7 @@ namespace Tests } static IEnumerable emptyReadMessagesResult; + [Reads(typeof(MockMessage))] class ReadMessagesWhenNoneExistEngine : Engine { @@ -274,7 +271,7 @@ namespace Tests var world = worldBuilder.Build(); var ex = Assert.Throws(() => world.Update(0.01f)); - Assert.That(ex.Message, Is.EqualTo("Engine UndeclaredMessageEmitEngine tried to emit undeclared Message MockMessage")); + Assert.That(ex.Message, Is.EqualTo("Engine UndeclaredMessageEmitEngine tried to write undeclared Message MockMessage")); } static bool someTest; @@ -334,7 +331,6 @@ namespace Tests Assert.Throws(() => world.Update(0.01f)); } - [Reads(typeof(MockComponent))] class SomeComponentTestEngine : Engine { public override void Update(double dt) @@ -356,32 +352,9 @@ namespace Tests world.Update(0.01); } - class UndeclaredSomeComponentEngine : Engine - { - public override void Update(double dt) - { - SomeComponent(); - } - } - - [Test] - public void UndeclaredSomeComponent() - { - var worldBuilder = new WorldBuilder(); - worldBuilder.AddEngine(new UndeclaredSomeComponentEngine()); - - var entity = worldBuilder.CreateEntity(); - worldBuilder.AddComponent(entity, new MockComponent()); - - var world = worldBuilder.Build(); - - Assert.Throws(() => world.Update(0.01)); - } - static ValueTuple pairA; static ValueTuple pairB; - [Reads(typeof(MockComponent))] class SameValueComponentReadEngine : Engine { public override void Update(double dt) @@ -421,7 +394,6 @@ namespace Tests static IEnumerable> emptyComponentReadResult; - [Reads(typeof(MockComponent))] class ReadEmptyMockComponentsEngine : Engine { public override void Update(double dt) @@ -444,7 +416,6 @@ namespace Tests struct DestroyerComponent : IComponent { } - [Reads(typeof(DestroyerComponent))] class DestroyerEngine : Engine { public override void Update(double dt) @@ -460,7 +431,6 @@ namespace Tests static IEnumerable> results; - [Reads(typeof(MockComponent))] class ReaderEngine : Engine { public override void Update(double dt) @@ -498,7 +468,6 @@ namespace Tests Assert.That(results, Does.Not.Contain((componentBID, mockComponent))); } - [Reads(typeof(DestroyerComponent), typeof(MockComponent))] [Writes(typeof(MockComponent))] class DestroyAndAddComponentEngine : Engine { @@ -534,7 +503,6 @@ namespace Tests static Entity entityFromComponentIDResult; - [Reads(typeof(MockComponent))] class GetEntityFromComponentIDEngine : Engine { public override void Update(double dt) @@ -565,7 +533,6 @@ namespace Tests static MockComponent mockComponentByIDResult; - [Reads(typeof(MockComponent))] class GetComponentByIDEngine : Engine { public override void Update(double dt) @@ -595,7 +562,6 @@ namespace Tests struct OtherComponent : IComponent { } - [Reads(typeof(MockComponent), typeof(OtherComponent))] class GetComponentByIDWithTypeMismatchEngine : Engine { public override void Update(double dt) @@ -626,7 +592,6 @@ namespace Tests struct EntityIDComponent : IComponent { public Guid entityID; } static bool hasEntity; - [Reads(typeof(EntityIDComponent))] class HasEntityTestEngine : Engine { public override void Update(double dt) @@ -663,5 +628,19 @@ namespace Tests Assert.IsFalse(hasEntity); } + + [Writes(typeof(MockComponent), typeof(MockMessage))] + class EngineThatWritesComponentAndMessage : Engine + { + public override void Update(double dt) { } + } + + [Test] + public void EngineWritesComponentAndMessage() + { + var worldBuilder = new WorldBuilder(); + + Assert.Throws(() => worldBuilder.AddEngine(new EngineThatWritesComponentAndMessage())); + } } } diff --git a/test/WorldBuilderTest.cs b/test/WorldBuilderTest.cs index 0519d4e..2950d1c 100644 --- a/test/WorldBuilderTest.cs +++ b/test/WorldBuilderTest.cs @@ -216,7 +216,7 @@ namespace Tests struct CMessage : IMessage { } struct DMessage : IMessage { } - [Writes(typeof(AComponent), typeof(AMessage))] + [Writes(typeof(AMessage))] class AEngine : Engine { public override void Update(double dt) @@ -225,7 +225,7 @@ namespace Tests } } - [Writes(typeof(BComponent), typeof(BMessage))] + [Writes(typeof(BMessage))] class BEngine : Engine { public override void Update(double dt)