introduce concept of pending component

pull/5/head
thatcosmonaut 2019-07-19 16:15:48 -07:00
parent 1845d5f766
commit 89154f21d7
15 changed files with 123 additions and 112 deletions

5
TODO
View File

@ -1,6 +1 @@
- Change "Writes" To "Sends" and make it only take Messages
- Add "Updates" for updating components
- so we have four attributes: Activates, Reads, Updates, and Sends
- docs - docs

View File

@ -19,7 +19,7 @@ namespace Encompass
throw new IllegalActivateTypeException("{0} must be a Component", activateType.Name); throw new IllegalActivateTypeException("{0} must be a Component", activateType.Name);
} }
this.activateTypes.Add(typeof(NewComponentMessage<>).MakeGenericType(activateType)); this.activateTypes.Add(typeof(PendingComponentMessage<>).MakeGenericType(activateType));
} }
} }
} }

View File

@ -1,16 +0,0 @@
using System;
using System.Collections.Generic;
namespace Encompass
{
[AttributeUsage(AttributeTargets.Class)]
public class Detects : Attribute
{
public readonly List<Type> componentTypes;
public Detects(params Type[] componentTypes)
{
this.componentTypes = new List<Type>(componentTypes);
}
}
}

View File

@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Encompass.Exceptions;
namespace Encompass
{
[AttributeUsage(AttributeTargets.Class)]
public class ReadsNew : Attribute
{
public readonly HashSet<Type> newComponentReadTypes = new HashSet<Type>();
public ReadsNew(params Type[] readTypes)
{
foreach (var readType in readTypes)
{
var isComponent = readType.GetInterfaces().Contains(typeof(IComponent));
if (!isComponent)
{
throw new IllegalReadTypeException("{0} must be a Component", readType.Name);
}
this.newComponentReadTypes.Add(typeof(ComponentMessage<>).MakeGenericType(readType));
}
}
}
}

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Encompass.Exceptions;
namespace Encompass
{
[AttributeUsage(AttributeTargets.Class)]
public class ReadsPending : Attribute
{
public readonly HashSet<Type> readPendingTypes = new HashSet<Type>();
public ReadsPending(params Type[] readPendingTypes)
{
foreach (var readPendingType in readPendingTypes)
{
var isComponent = readPendingType.GetInterfaces().Contains(typeof(IComponent));
if (!isComponent)
{
throw new IllegalReadTypeException("{0} must be a Component", readPendingType.Name);
}
this.readPendingTypes.Add(typeof(PendingComponentMessage<>).MakeGenericType(readPendingType));
}
}
}
}

View File

@ -42,10 +42,10 @@ namespace Encompass
receiveTypes.UnionWith(readsAttribute.readTypes); receiveTypes.UnionWith(readsAttribute.readTypes);
} }
var readsNewAttribute = GetType().GetCustomAttribute<ReadsNew>(false); var readsPendingAttribute = GetType().GetCustomAttribute<ReadsPending>(false);
if (readsNewAttribute != null) if (readsPendingAttribute != null)
{ {
receiveTypes.UnionWith(readsNewAttribute.newComponentReadTypes); receiveTypes.UnionWith(readsPendingAttribute.readPendingTypes);
} }
var updatesAttribute = GetType().GetCustomAttribute<Updates>(false); var updatesAttribute = GetType().GetCustomAttribute<Updates>(false);
@ -118,14 +118,14 @@ namespace Encompass
protected Guid AddComponent<TComponent>(Entity entity, TComponent component) where TComponent : struct, IComponent protected Guid AddComponent<TComponent>(Entity entity, TComponent component) where TComponent : struct, IComponent
{ {
if (!sendTypes.Contains(typeof(NewComponentMessage<TComponent>))) if (!sendTypes.Contains(typeof(PendingComponentMessage<TComponent>)))
{ {
throw new IllegalActivateException("Engine {0} tried to activate undeclared Component {1}", GetType().Name, typeof(TComponent).Name); throw new IllegalActivateException("Engine {0} tried to activate undeclared Component {1}", GetType().Name, typeof(TComponent).Name);
} }
var componentID = componentManager.AddComponent(entity.ID, component); var componentID = componentManager.AddComponent(entity.ID, component);
NewComponentMessage<TComponent> componentMessage; PendingComponentMessage<TComponent> componentMessage;
componentMessage.entity = entity; componentMessage.entity = entity;
componentMessage.componentID = componentID; componentMessage.componentID = componentID;
componentMessage.component = component; componentMessage.component = component;
@ -136,14 +136,14 @@ namespace Encompass
protected Guid AddDrawComponent<TComponent>(Entity entity, TComponent component, int layer = 0) where TComponent : struct, IComponent protected Guid AddDrawComponent<TComponent>(Entity entity, TComponent component, int layer = 0) where TComponent : struct, IComponent
{ {
if (!sendTypes.Contains(typeof(NewComponentMessage<TComponent>))) if (!sendTypes.Contains(typeof(PendingComponentMessage<TComponent>)))
{ {
throw new IllegalActivateException("Engine {0} tried to activate undeclared Component {1}", GetType().Name, typeof(TComponent).Name); throw new IllegalActivateException("Engine {0} tried to activate undeclared Component {1}", GetType().Name, typeof(TComponent).Name);
} }
var componentID = componentManager.AddDrawComponent(entity.ID, component, layer); var componentID = componentManager.AddDrawComponent(entity.ID, component, layer);
NewComponentMessage<TComponent> newComponentMessage; PendingComponentMessage<TComponent> newComponentMessage;
newComponentMessage.entity = entity; newComponentMessage.entity = entity;
newComponentMessage.componentID = componentID; newComponentMessage.componentID = componentID;
newComponentMessage.component = component; newComponentMessage.component = component;
@ -154,7 +154,7 @@ namespace Encompass
protected void ActivateComponent<TComponent>(Guid componentID) where TComponent : struct, IComponent protected void ActivateComponent<TComponent>(Guid componentID) where TComponent : struct, IComponent
{ {
if (!sendTypes.Contains(typeof(NewComponentMessage<TComponent>))) if (!sendTypes.Contains(typeof(PendingComponentMessage<TComponent>)))
{ {
throw new IllegalActivateException("Engine {0} tried to activate undeclared Component {1}", GetType().Name, typeof(TComponent).Name); throw new IllegalActivateException("Engine {0} tried to activate undeclared Component {1}", GetType().Name, typeof(TComponent).Name);
} }
@ -162,7 +162,7 @@ namespace Encompass
var entity = GetEntity(componentManager.GetEntityIDByComponentID(componentID)); var entity = GetEntity(componentManager.GetEntityIDByComponentID(componentID));
var component = GetComponentByID<TComponent>(componentID); var component = GetComponentByID<TComponent>(componentID);
NewComponentMessage<TComponent> newComponentMessage; PendingComponentMessage<TComponent> newComponentMessage;
newComponentMessage.entity = entity; newComponentMessage.entity = entity;
newComponentMessage.componentID = componentID; newComponentMessage.componentID = componentID;
newComponentMessage.component = component; newComponentMessage.component = component;
@ -186,19 +186,19 @@ namespace Encompass
return ReadMessages<ComponentMessage<TComponent>>().Where((message) => message.entity == entity).Select((message) => (message.componentID, message.component)); return ReadMessages<ComponentMessage<TComponent>>().Where((message) => message.entity == entity).Select((message) => (message.componentID, message.component));
} }
private IEnumerable<ValueTuple<Guid, TComponent>> NewComponentsOnEntity<TComponent>(Entity entity) where TComponent : struct, IComponent private IEnumerable<ValueTuple<Guid, TComponent>> PendingComponentsOnEntity<TComponent>(Entity entity) where TComponent : struct, IComponent
{ {
if (!receiveTypes.Contains(typeof(NewComponentMessage<TComponent>))) if (!receiveTypes.Contains(typeof(PendingComponentMessage<TComponent>)))
{ {
throw new IllegalReadException("Engine {0} tried to read undeclared new Component {1}", GetType().Name, typeof(TComponent).Name); throw new IllegalReadException("Engine {0} tried to read undeclared pending Component {1}", GetType().Name, typeof(TComponent).Name);
} }
return ReadMessages<NewComponentMessage<TComponent>>().Where((message) => message.entity == entity).Select((message) => (message.componentID, message.component)); return ReadMessages<PendingComponentMessage<TComponent>>().Where((message) => message.entity == entity).Select((message) => (message.componentID, message.component));
} }
protected IEnumerable<ValueTuple<Guid, TComponent>> GetComponentsIncludingNew<TComponent>(Entity entity) where TComponent : struct, IComponent protected IEnumerable<ValueTuple<Guid, TComponent>> GetPendingComponents<TComponent>(Entity entity) where TComponent : struct, IComponent
{ {
return ExistingComponentsOnEntity<TComponent>(entity).Union(NewComponentsOnEntity<TComponent>(entity)); return PendingComponentsOnEntity<TComponent>(entity);
} }
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
@ -206,11 +206,21 @@ namespace Encompass
return ExistingComponentsOnEntity<TComponent>(entity); return ExistingComponentsOnEntity<TComponent>(entity);
} }
protected ValueTuple<Guid, TComponent> GetPendingComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
{
return PendingComponentsOnEntity<TComponent>(entity).First();
}
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(); return GetComponents<TComponent>(entity).First();
} }
protected bool HasPendingComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
{
return GetPendingComponents<TComponent>(entity).Any();
}
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(); return GetComponents<TComponent>(entity).Any();
@ -220,7 +230,7 @@ namespace Encompass
{ {
if (!updateTypes.Contains(typeof(TComponent))) if (!updateTypes.Contains(typeof(TComponent)))
{ {
throw new IllegalSendException("Engine {0} tried to write undeclared Component {1}", this.GetType().Name, typeof(TComponent).Name); throw new IllegalSendException("Engine {0} tried to update undeclared Component {1}", this.GetType().Name, typeof(TComponent).Name);
} }
componentManager.AddUpdateComponentOperation(componentID, newComponent); componentManager.AddUpdateComponentOperation(componentID, newComponent);
@ -235,7 +245,7 @@ namespace Encompass
{ {
if (!sendTypes.Contains(typeof(TMessage))) if (!sendTypes.Contains(typeof(TMessage)))
{ {
throw new IllegalSendException("Engine {0} tried to write undeclared Message {1}", this.GetType().Name, typeof(TMessage).Name); throw new IllegalSendException("Engine {0} tried to send undeclared Message {1}", this.GetType().Name, typeof(TMessage).Name);
} }
messageManager.AddMessage(message); messageManager.AddMessage(message);
@ -256,6 +266,16 @@ namespace Encompass
return ReadMessages<TMessage>().Single(); return ReadMessages<TMessage>().Single();
} }
protected IEnumerable<ValueTuple<Guid, TComponent>> ReadPendingComponents<TComponent>() where TComponent : struct, IComponent
{
if (!receiveTypes.Contains(typeof(PendingComponentMessage<TComponent>)))
{
throw new IllegalReadException("Engine {0} tried to read undeclared pending Component {1}", GetType().Name, typeof(TComponent).Name);
}
return ReadMessages<PendingComponentMessage<TComponent>>().Select((message) => (message.componentID, message.component));
}
protected IEnumerable<ValueTuple<Guid, TComponent>> ReadComponents<TComponent>() where TComponent : struct, IComponent protected IEnumerable<ValueTuple<Guid, TComponent>> ReadComponents<TComponent>() where TComponent : struct, IComponent
{ {
if (!receiveTypes.Contains(typeof(ComponentMessage<TComponent>))) if (!receiveTypes.Contains(typeof(ComponentMessage<TComponent>)))
@ -266,6 +286,11 @@ namespace Encompass
return ReadMessages<ComponentMessage<TComponent>>().Select((message) => (message.componentID, message.component)); return ReadMessages<ComponentMessage<TComponent>>().Select((message) => (message.componentID, message.component));
} }
protected ValueTuple<Guid, TComponent> ReadPendingComponent<TComponent>() where TComponent : struct, IComponent
{
return ReadPendingComponents<TComponent>().Single();
}
protected ValueTuple<Guid, TComponent> ReadComponent<TComponent>() where TComponent : struct, IComponent protected ValueTuple<Guid, TComponent> ReadComponent<TComponent>() where TComponent : struct, IComponent
{ {
return ReadComponents<TComponent>().Single(); return ReadComponents<TComponent>().Single();
@ -281,6 +306,16 @@ namespace Encompass
return ReadMessages<TMessage>().Any(); return ReadMessages<TMessage>().Any();
} }
protected bool SomePendingComponent<TComponent>() where TComponent : struct, IComponent
{
if (!receiveTypes.Contains(typeof(PendingComponentMessage<TComponent>)))
{
throw new IllegalReadException("Engine {0} tried to read undeclared pending Component {1}", GetType().Name, typeof(TComponent).Name);
}
return ReadMessages<PendingComponentMessage<TComponent>>().Any();
}
protected bool SomeComponent<TComponent>() where TComponent : struct, IComponent protected bool SomeComponent<TComponent>() where TComponent : struct, IComponent
{ {
if (!receiveTypes.Contains(typeof(ComponentMessage<TComponent>))) if (!receiveTypes.Contains(typeof(ComponentMessage<TComponent>)))

View File

@ -6,14 +6,14 @@ namespace Encompass.Engines
{ {
public NewComponentMessageEmitter() : base() public NewComponentMessageEmitter() : base()
{ {
sendTypes.Add(typeof(NewComponentMessage<TComponent>)); sendTypes.Add(typeof(PendingComponentMessage<TComponent>));
} }
public override void Update(double dt) public override void Update(double dt)
{ {
foreach (var (entity, componentID, component) in ReadComponentsFromWorld<TComponent>()) foreach (var (entity, componentID, component) in ReadComponentsFromWorld<TComponent>())
{ {
NewComponentMessage<TComponent> newComponentMessage; PendingComponentMessage<TComponent> newComponentMessage;
newComponentMessage.entity = entity; newComponentMessage.entity = entity;
newComponentMessage.componentID = componentID; newComponentMessage.componentID = componentID;
newComponentMessage.component = component; newComponentMessage.component = component;

View File

@ -2,9 +2,9 @@ using System;
namespace Encompass.Exceptions namespace Encompass.Exceptions
{ {
public class EngineWriteConflictException : Exception public class EngineSelfCycleException : Exception
{ {
public EngineWriteConflictException( public EngineSelfCycleException(
string format, string format,
params object[] args params object[] args
) : base(string.Format(format, args)) { } ) : base(string.Format(format, args)) { }

View File

@ -2,9 +2,9 @@ using System;
namespace Encompass.Exceptions namespace Encompass.Exceptions
{ {
public class EngineMessageSelfCycleException : Exception public class EngineUpdateConflictException : Exception
{ {
public EngineMessageSelfCycleException( public EngineUpdateConflictException(
string format, string format,
params object[] args params object[] args
) : base(string.Format(format, args)) { } ) : base(string.Format(format, args)) { }

View File

@ -2,7 +2,7 @@ using System;
namespace Encompass namespace Encompass
{ {
public struct NewComponentMessage<TComponent> : IMessage where TComponent : struct, IComponent public struct PendingComponentMessage<TComponent> : IMessage where TComponent : struct, IComponent
{ {
public Entity entity; public Entity entity;
public Guid componentID; public Guid componentID;

View File

@ -87,13 +87,13 @@ namespace Encompass
foreach (var messageType in messageReceiveTypes.Intersect(messageSendTypes)) foreach (var messageType in messageReceiveTypes.Intersect(messageSendTypes))
{ {
// ComponentMessages can safely self-cycle if ((messageType.IsGenericType && messageType.GetGenericTypeDefinition() == typeof(PendingComponentMessage<>)))
// this does introduce a gotcha though: if you AddComponent and then HasComponent or GetComponent you will receive a false negative
// there is no point to doing this but it is a gotcha i suppose
if (!(messageType.IsGenericType && messageType.GetGenericTypeDefinition() == typeof(ComponentMessage<>)))
{ {
throw new EngineMessageSelfCycleException("Engine {0} both reads and writes Message {1}", engine.GetType().Name, messageType.Name); var componentType = messageType.GetGenericArguments().Single();
throw new EngineSelfCycleException("Engine {0} both activates and reads pending Component {1}", engine.GetType().Name, componentType.Name);
} }
throw new EngineSelfCycleException("Engine {0} both receives and sends Message {1}", engine.GetType().Name, messageType.Name);
} }
if (messageSendTypes.Any()) if (messageSendTypes.Any())
@ -106,7 +106,7 @@ namespace Encompass
if (receiveType.IsGenericType) if (receiveType.IsGenericType)
{ {
var genericTypeDefinition = receiveType.GetGenericTypeDefinition(); var genericTypeDefinition = receiveType.GetGenericTypeDefinition();
if (genericTypeDefinition == typeof(ComponentMessage<>) || genericTypeDefinition == typeof(NewComponentMessage<>)) if (genericTypeDefinition == typeof(ComponentMessage<>) || genericTypeDefinition == typeof(PendingComponentMessage<>))
{ {
var componentType = receiveType.GetGenericArguments().Single(); var componentType = receiveType.GetGenericArguments().Single();
if (!registeredComponentTypes.Contains(componentType)) if (!registeredComponentTypes.Contains(componentType))
@ -129,7 +129,7 @@ namespace Encompass
if (sendType.IsGenericType) if (sendType.IsGenericType)
{ {
var genericTypeDefinition = sendType.GetGenericTypeDefinition(); var genericTypeDefinition = sendType.GetGenericTypeDefinition();
if (genericTypeDefinition == typeof(ComponentMessage<>) || genericTypeDefinition == typeof(NewComponentMessage<>)) if (genericTypeDefinition == typeof(ComponentMessage<>) || genericTypeDefinition == typeof(PendingComponentMessage<>))
{ {
var componentType = sendType.GetGenericArguments().Single(); var componentType = sendType.GetGenericArguments().Single();
if (!registeredNewComponentTypes.Contains(componentType)) if (!registeredNewComponentTypes.Contains(componentType))
@ -195,12 +195,13 @@ namespace Encompass
{ {
var cycles = engineGraph.SimpleCycles(); var cycles = engineGraph.SimpleCycles();
var errorString = "Cycle(s) found in Engines: "; var errorString = "Cycle(s) found in Engines: ";
foreach (var cycle in cycles.Reverse()) foreach (var cycle in cycles)
{ {
var reversed = cycle.Reverse();
errorString += "\n" + errorString += "\n" +
string.Join(" -> ", cycle.Select((engine) => engine.GetType().Name)) + string.Join(" -> ", reversed.Select((engine) => engine.GetType().Name)) +
" -> " + " -> " +
cycle.First().GetType().Name; reversed.First().GetType().Name;
} }
throw new EngineCycleException(errorString); throw new EngineCycleException(errorString);
} }
@ -212,8 +213,6 @@ namespace Encompass
foreach (var engine in engines) foreach (var engine in engines)
{ {
foreach (var updateType in engine.updateTypes) foreach (var updateType in engine.updateTypes)
{
if (updateType.GetInterfaces().Contains(typeof(IComponent))) // if our write type is a component
{ {
if (mutatedComponentTypes.Contains(updateType)) if (mutatedComponentTypes.Contains(updateType))
{ {
@ -232,19 +231,18 @@ namespace Encompass
componentToEngines[updateType].Add(engine); componentToEngines[updateType].Add(engine);
} }
} }
}
if (duplicateMutations.Count > 0) if (duplicateMutations.Count > 0)
{ {
var errorString = "Multiple Engines write the same Component: "; var errorString = "Multiple Engines update the same Component: ";
foreach (var componentType in duplicateMutations) foreach (var componentType in duplicateMutations)
{ {
errorString += "\n" + errorString += "\n" +
componentType.Name + " written by: " + componentType.Name + " updated by: " +
string.Join(", ", componentToEngines[componentType].Select((engine) => engine.GetType().Name)); string.Join(", ", componentToEngines[componentType].Select((engine) => engine.GetType().Name));
} }
throw new EngineWriteConflictException(errorString); throw new EngineUpdateConflictException(errorString);
} }
var engineOrder = new List<Engine>(); var engineOrder = new List<Engine>();

View File

@ -124,6 +124,7 @@ namespace Tests
} }
[Reads(typeof(MockComponent))] [Reads(typeof(MockComponent))]
[ReadsPending(typeof(MockComponent))]
class HasMockComponentEngine : Engine class HasMockComponentEngine : Engine
{ {
private Entity entity; private Entity entity;
@ -135,7 +136,7 @@ namespace Tests
public override void Update(double dt) public override void Update(double dt)
{ {
Assert.IsTrue(HasComponent<MockComponent>(entity)); Assert.IsTrue(HasPendingComponent<MockComponent>(entity));
} }
} }
@ -468,14 +469,14 @@ namespace Tests
} }
[Receives(typeof(CheckHasMockComponentMessage))] [Receives(typeof(CheckHasMockComponentMessage))]
[Reads(typeof(MockComponent))] [ReadsPending(typeof(MockComponent))]
class CheckHasMockComponentEngine : Engine class CheckHasMockComponentEngine : Engine
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
foreach (var checkHasMockComponentMessage in ReadMessages<CheckHasMockComponentMessage>()) foreach (var checkHasMockComponentMessage in ReadMessages<CheckHasMockComponentMessage>())
{ {
Assert.IsTrue(HasComponent<MockComponent>(checkHasMockComponentMessage.entity)); Assert.IsTrue(HasPendingComponent<MockComponent>(checkHasMockComponentMessage.entity));
} }
} }
} }

View File

@ -192,7 +192,7 @@ namespace Tests
var world = worldBuilder.Build(); var world = worldBuilder.Build();
var ex = Assert.Throws<IllegalSendException>(() => world.Update(0.01f)); var ex = Assert.Throws<IllegalSendException>(() => world.Update(0.01f));
Assert.That(ex.Message, Is.EqualTo("Engine UndeclaredUpdateComponentTestEngine tried to write undeclared Component MockComponent")); Assert.That(ex.Message, Is.EqualTo("Engine UndeclaredUpdateComponentTestEngine tried to update undeclared Component MockComponent"));
} }
struct MockMessage : IMessage struct MockMessage : IMessage
@ -279,7 +279,7 @@ namespace Tests
var world = worldBuilder.Build(); var world = worldBuilder.Build();
var ex = Assert.Throws<IllegalSendException>(() => world.Update(0.01f)); var ex = Assert.Throws<IllegalSendException>(() => world.Update(0.01f));
Assert.That(ex.Message, Is.EqualTo("Engine UndeclaredMessageEmitEngine tried to write undeclared Message MockMessage")); Assert.That(ex.Message, Is.EqualTo("Engine UndeclaredMessageEmitEngine tried to send undeclared Message MockMessage"));
} }
static bool someTest; static bool someTest;

View File

@ -48,8 +48,6 @@ namespace Tests
world.Update(0.01f); world.Update(0.01f);
Console.WriteLine(renderer.IsTracking(entityNotToTrack.ID));
Assert.IsTrue(renderer.IsTracking(entityToTrack.ID)); Assert.IsTrue(renderer.IsTracking(entityToTrack.ID));
Assert.IsFalse(renderer.IsTracking(entityNotToTrack.ID)); Assert.IsFalse(renderer.IsTracking(entityNotToTrack.ID));
Assert.IsFalse(renderer.IsTracking(entityWithoutDrawComponent.ID)); Assert.IsFalse(renderer.IsTracking(entityWithoutDrawComponent.ID));

View File

@ -133,7 +133,7 @@ namespace Tests
worldBuilder.AddEngine(new AEngine()); worldBuilder.AddEngine(new AEngine());
worldBuilder.AddEngine(new BEngine()); worldBuilder.AddEngine(new BEngine());
Assert.Throws<EngineWriteConflictException>(() => worldBuilder.Build()); Assert.Throws<EngineUpdateConflictException>(() => worldBuilder.Build());
} }
} }
@ -156,7 +156,7 @@ namespace Tests
{ {
var worldBuilder = new WorldBuilder(); var worldBuilder = new WorldBuilder();
Assert.Throws<EngineMessageSelfCycleException>(() => worldBuilder.AddEngine(new AEngine()), "Engine both reads and writes Message AMessage"); Assert.Throws<EngineSelfCycleException>(() => worldBuilder.AddEngine(new AEngine()), "Engine both sends and receives Message AMessage");
} }
} }