engines must declare component reads + validation for Reads and Writes arguments
parent
7ab512e522
commit
9b58473ae8
|
@ -74,37 +74,47 @@ namespace Encompass
|
||||||
|
|
||||||
protected TComponent GetComponentByID<TComponent>(Guid componentID) where TComponent : struct, IComponent
|
protected TComponent GetComponentByID<TComponent>(Guid componentID) where TComponent : struct, IComponent
|
||||||
{
|
{
|
||||||
|
if (!readTypes.Contains(typeof(TComponent)))
|
||||||
if (componentManager.GetComponentTypeByID(componentID) == typeof(TComponent))
|
|
||||||
{
|
{
|
||||||
return (TComponent)componentManager.GetComponentByID(componentID);
|
throw new IllegalReadException("Engine {0} tried to read undeclared Component {1}", this.GetType().Name, typeof(TComponent).Name);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
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);
|
throw new ComponentTypeMismatchException("Expected Component to be of type {0} but was actually of type {1}", typeof(TComponent).Name, componentManager.GetComponentTypeByID(componentID).Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (TComponent)componentManager.GetComponentByID(componentID);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IEnumerable<ValueTuple<Guid, TComponent>> ReadComponents<TComponent>() where TComponent : struct, IComponent
|
protected IEnumerable<ValueTuple<Guid, TComponent>> ReadComponents<TComponent>() 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<TComponent>();
|
return componentManager.GetActiveComponentsByType<TComponent>();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ValueTuple<Guid, TComponent> ReadComponent<TComponent>() where TComponent : struct, IComponent
|
protected ValueTuple<Guid, TComponent> ReadComponent<TComponent>() 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<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 (writeTypes.Contains(typeof(TComponent)))
|
if (!writeTypes.Contains(typeof(TComponent)))
|
||||||
{
|
{
|
||||||
componentManager.UpdateComponent(componentID, newComponent);
|
throw new IllegalWriteException("Engine {0} tried to write undeclared Component {1}", this.GetType().Name, typeof(TComponent).Name);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new IllegalComponentMutationException("Engine {0} tried to write undeclared Component {1}", this.GetType().Name, typeof(TComponent).Name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentManager.UpdateComponent(componentID, newComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void UpdateComponent<TComponent>(Guid componentID, TComponent newComponentValue) where TComponent : struct, IComponent
|
protected void UpdateComponent<TComponent>(Guid componentID, TComponent newComponentValue) where TComponent : struct, IComponent
|
||||||
|
@ -114,38 +124,33 @@ namespace Encompass
|
||||||
|
|
||||||
protected void EmitMessage<TMessage>(TMessage message) where TMessage : struct, IMessage
|
protected void EmitMessage<TMessage>(TMessage message) where TMessage : struct, IMessage
|
||||||
{
|
{
|
||||||
if (writeTypes.Contains(typeof(TMessage)))
|
if (!writeTypes.Contains(typeof(TMessage)))
|
||||||
{
|
{
|
||||||
messageManager.AddMessage(message);
|
throw new IllegalWriteException("Engine {0} tried to emit undeclared Message {1}", this.GetType().Name, typeof(TMessage).Name);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new IllegalMessageEmitException("Engine {0} tried to emit undeclared Message {1}", this.GetType().Name, typeof(TMessage).Name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
messageManager.AddMessage(message);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IEnumerable<TMessage> ReadMessages<TMessage>() where TMessage : struct, IMessage
|
protected IEnumerable<TMessage> ReadMessages<TMessage>() where TMessage : struct, IMessage
|
||||||
{
|
{
|
||||||
if (readTypes.Contains(typeof(TMessage)))
|
if (!readTypes.Contains(typeof(TMessage)))
|
||||||
{
|
{
|
||||||
return messageManager.GetMessagesByType<TMessage>();
|
throw new IllegalReadException("Engine {0} tried to read undeclared Message {1}", this.GetType().Name, typeof(TMessage).Name);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new IllegalMessageReadException("Engine {0} tried to read undeclared Message {1}", this.GetType().Name, typeof(TMessage).Name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return messageManager.GetMessagesByType<TMessage>();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected bool Some<TMessage>() where TMessage : struct, IMessage
|
protected bool Some<TMessage>() where TMessage : struct, IMessage
|
||||||
{
|
{
|
||||||
if (readTypes.Contains(typeof(TMessage)))
|
if (!readTypes.Contains(typeof(TMessage)))
|
||||||
{
|
{
|
||||||
return messageManager.GetMessagesByType<TMessage>().Any();
|
throw new IllegalReadException("Engine {0} tried to read undeclared Message {1}", this.GetType().Name, typeof(TMessage).Name);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new IllegalMessageReadException("Engine {0} tried to read undeclared Message {1}", this.GetType().Name, typeof(TMessage).Name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return messageManager.GetMessagesByType<TMessage>().Any();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void Destroy(Guid entityID)
|
protected void Destroy(Guid entityID)
|
||||||
|
|
|
@ -17,8 +17,8 @@ namespace Encompass
|
||||||
private readonly DrawLayerManager drawLayerManager;
|
private readonly DrawLayerManager drawLayerManager;
|
||||||
private readonly RenderManager renderManager;
|
private readonly RenderManager renderManager;
|
||||||
|
|
||||||
private readonly Dictionary<Type, HashSet<Engine>> messageTypeToEmitters = new Dictionary<Type, HashSet<Engine>>();
|
private readonly Dictionary<Type, HashSet<Engine>> typeToEmitters = new Dictionary<Type, HashSet<Engine>>();
|
||||||
private readonly Dictionary<Type, HashSet<Engine>> messageTypeToReaders = new Dictionary<Type, HashSet<Engine>>();
|
private readonly Dictionary<Type, HashSet<Engine>> typeToReaders = new Dictionary<Type, HashSet<Engine>>();
|
||||||
|
|
||||||
public WorldBuilder()
|
public WorldBuilder()
|
||||||
{
|
{
|
||||||
|
@ -55,38 +55,58 @@ namespace Encompass
|
||||||
entityManager.RegisterEntityTracker(engine as IEntityTracker);
|
entityManager.RegisterEntityTracker(engine as IEntityTracker);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var emitMessageType in engine.writeTypes)
|
foreach (var writeType in engine.writeTypes)
|
||||||
{
|
{
|
||||||
if (!messageTypeToEmitters.ContainsKey(emitMessageType))
|
if (!typeToEmitters.ContainsKey(writeType))
|
||||||
{
|
{
|
||||||
messageTypeToEmitters.Add(emitMessageType, new HashSet<Engine>());
|
typeToEmitters.Add(writeType, new HashSet<Engine>());
|
||||||
}
|
}
|
||||||
|
|
||||||
messageTypeToEmitters[emitMessageType].Add(engine);
|
typeToEmitters[writeType].Add(engine);
|
||||||
|
|
||||||
if (messageTypeToReaders.ContainsKey(emitMessageType))
|
if (typeToReaders.ContainsKey(writeType))
|
||||||
{
|
{
|
||||||
foreach (var reader in messageTypeToReaders[emitMessageType])
|
foreach (var reader in typeToReaders[writeType])
|
||||||
{
|
{
|
||||||
engineGraph.AddEdge(engine, reader);
|
if (engine == reader)
|
||||||
|
{
|
||||||
|
if (writeType.GetInterfaces().Contains(typeof(IMessage)))
|
||||||
|
{
|
||||||
|
throw new EngineMessageSelfCycleException("Engine both reads and writes Message {0}", writeType.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
engineGraph.AddEdge(engine, reader);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var readMessageType in engine.readTypes)
|
foreach (var readType in engine.readTypes)
|
||||||
{
|
{
|
||||||
if (!messageTypeToReaders.ContainsKey(readMessageType))
|
if (!typeToReaders.ContainsKey(readType))
|
||||||
{
|
{
|
||||||
messageTypeToReaders.Add(readMessageType, new HashSet<Engine>());
|
typeToReaders.Add(readType, new HashSet<Engine>());
|
||||||
}
|
}
|
||||||
|
|
||||||
messageTypeToReaders[readMessageType].Add(engine);
|
typeToReaders[readType].Add(engine);
|
||||||
|
|
||||||
if (messageTypeToEmitters.ContainsKey(readMessageType))
|
if (typeToEmitters.ContainsKey(readType))
|
||||||
{
|
{
|
||||||
foreach (var emitter in messageTypeToEmitters[readMessageType])
|
foreach (var emitter in typeToEmitters[readType])
|
||||||
{
|
{
|
||||||
engineGraph.AddEdge(emitter, engine);
|
if (emitter == engine)
|
||||||
|
{
|
||||||
|
if (readType.GetInterfaces().Contains(typeof(IMessage)))
|
||||||
|
{
|
||||||
|
throw new EngineMessageSelfCycleException("Engine both reads and writes Message {0}", readType.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
engineGraph.AddEdge(emitter, engine);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,7 +197,7 @@ namespace Encompass
|
||||||
string.Join(", ", componentToEngines[componentType].Select((engine) => engine.GetType().Name));
|
string.Join(", ", componentToEngines[componentType].Select((engine) => engine.GetType().Name));
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new EngineMutationConflictException(errorString);
|
throw new EngineWriteConflictException(errorString);
|
||||||
}
|
}
|
||||||
|
|
||||||
var engineOrder = new List<Engine>();
|
var engineOrder = new List<Engine>();
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Encompass
|
|
||||||
{
|
|
||||||
[AttributeUsage(AttributeTargets.Class)]
|
|
||||||
public class Writes : Attribute
|
|
||||||
{
|
|
||||||
public readonly List<Type> writeTypes;
|
|
||||||
|
|
||||||
public Writes(params Type[] writeTypes)
|
|
||||||
{
|
|
||||||
this.writeTypes = new List<Type>(writeTypes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Encompass.Exceptions;
|
||||||
|
|
||||||
namespace Encompass
|
namespace Encompass
|
||||||
{
|
{
|
||||||
|
@ -8,9 +10,17 @@ namespace Encompass
|
||||||
{
|
{
|
||||||
public readonly List<Type> readTypes;
|
public readonly List<Type> readTypes;
|
||||||
|
|
||||||
public Reads(params Type[] readMessageTypes)
|
public Reads(params Type[] readTypes)
|
||||||
{
|
{
|
||||||
this.readTypes = new List<Type>(readMessageTypes);
|
foreach (var readType in readTypes)
|
||||||
|
{
|
||||||
|
if (!readType.GetInterfaces().Contains(typeof(IMessage)) && !readType.GetInterfaces().Contains(typeof(IComponent)))
|
||||||
|
{
|
||||||
|
throw new IllegalReadTypeException("{0} must be a Message or Component", readType.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.readTypes = new List<Type>(readTypes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Encompass.Exceptions;
|
||||||
|
|
||||||
|
namespace Encompass
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public class Writes : Attribute
|
||||||
|
{
|
||||||
|
public readonly List<Type> writeTypes;
|
||||||
|
|
||||||
|
public Writes(params Type[] writeTypes)
|
||||||
|
{
|
||||||
|
foreach (var writeType in writeTypes)
|
||||||
|
{
|
||||||
|
if (!writeType.GetInterfaces().Contains(typeof(IMessage)) && !writeType.GetInterfaces().Contains(typeof(IComponent)))
|
||||||
|
{
|
||||||
|
throw new IllegalWriteTypeException("{0} must be a Message or Component", writeType.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.writeTypes = new List<Type>(writeTypes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,9 +2,9 @@ using System;
|
||||||
|
|
||||||
namespace Encompass.Exceptions
|
namespace Encompass.Exceptions
|
||||||
{
|
{
|
||||||
public class EngineMutationConflictException : Exception
|
public class EngineMessageSelfCycleException : Exception
|
||||||
{
|
{
|
||||||
public EngineMutationConflictException(
|
public EngineMessageSelfCycleException(
|
||||||
string format,
|
string format,
|
||||||
params object[] args
|
params object[] args
|
||||||
) : base(string.Format(format, args)) { }
|
) : base(string.Format(format, args)) { }
|
|
@ -2,9 +2,9 @@ using System;
|
||||||
|
|
||||||
namespace Encompass.Exceptions
|
namespace Encompass.Exceptions
|
||||||
{
|
{
|
||||||
public class IllegalComponentMutationException : Exception
|
public class EngineWriteConflictException : Exception
|
||||||
{
|
{
|
||||||
public IllegalComponentMutationException(
|
public EngineWriteConflictException(
|
||||||
string format,
|
string format,
|
||||||
params object[] args
|
params object[] args
|
||||||
) : base(string.Format(format, args)) { }
|
) : base(string.Format(format, args)) { }
|
|
@ -2,9 +2,9 @@ using System;
|
||||||
|
|
||||||
namespace Encompass.Exceptions
|
namespace Encompass.Exceptions
|
||||||
{
|
{
|
||||||
public class IllegalMessageReadException : Exception
|
public class IllegalReadException : Exception
|
||||||
{
|
{
|
||||||
public IllegalMessageReadException(
|
public IllegalReadException(
|
||||||
string format,
|
string format,
|
||||||
params object[] args
|
params object[] args
|
||||||
) : base(string.Format(format, args)) { }
|
) : base(string.Format(format, args)) { }
|
|
@ -2,9 +2,9 @@ using System;
|
||||||
|
|
||||||
namespace Encompass.Exceptions
|
namespace Encompass.Exceptions
|
||||||
{
|
{
|
||||||
public class IllegalMessageEmitException : Exception
|
public class IllegalReadTypeException : Exception
|
||||||
{
|
{
|
||||||
public IllegalMessageEmitException(
|
public IllegalReadTypeException(
|
||||||
string format,
|
string format,
|
||||||
params object[] args
|
params object[] args
|
||||||
) : base(string.Format(format, args)) { }
|
) : base(string.Format(format, args)) { }
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Encompass.Exceptions
|
||||||
|
{
|
||||||
|
public class IllegalWriteException : Exception
|
||||||
|
{
|
||||||
|
public IllegalWriteException(
|
||||||
|
string format,
|
||||||
|
params object[] args
|
||||||
|
) : base(string.Format(format, args)) { }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Encompass.Exceptions
|
||||||
|
{
|
||||||
|
public class IllegalWriteTypeException : Exception
|
||||||
|
{
|
||||||
|
public IllegalWriteTypeException(
|
||||||
|
string format,
|
||||||
|
params object[] args
|
||||||
|
) : base(string.Format(format, args)) { }
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,7 +27,7 @@ namespace Encompass
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<T> _vertices = new List<T>();
|
protected List<T> _vertices = new List<T>();
|
||||||
protected Dictionary<T, List<T>> _neighbors = new Dictionary<T, List<T>>();
|
protected Dictionary<T, HashSet<T>> _neighbors = new Dictionary<T, HashSet<T>>();
|
||||||
|
|
||||||
public IEnumerable<T> Vertices { get { return _vertices; } }
|
public IEnumerable<T> Vertices { get { return _vertices; } }
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ namespace Encompass
|
||||||
if (!VertexExists(vertex))
|
if (!VertexExists(vertex))
|
||||||
{
|
{
|
||||||
_vertices.Add(vertex);
|
_vertices.Add(vertex);
|
||||||
_neighbors.Add(vertex, new List<T>());
|
_neighbors.Add(vertex, new HashSet<T>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ namespace Tests
|
||||||
|
|
||||||
static List<MockMessage> resultMessages;
|
static List<MockMessage> resultMessages;
|
||||||
|
|
||||||
|
[Reads(typeof(MockComponent))]
|
||||||
public class ReadComponentsTestEngine : Engine
|
public class ReadComponentsTestEngine : Engine
|
||||||
{
|
{
|
||||||
public override void Update(double dt)
|
public override void Update(double dt)
|
||||||
|
@ -25,6 +26,7 @@ namespace Tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Reads(typeof(MockComponent))]
|
||||||
public class ReadComponentTestEngine : Engine
|
public class ReadComponentTestEngine : Engine
|
||||||
{
|
{
|
||||||
public override void Update(double dt)
|
public override void Update(double dt)
|
||||||
|
@ -110,6 +112,7 @@ namespace Tests
|
||||||
Assert.Throws<InvalidOperationException>(() => world.Update(0.01f));
|
Assert.Throws<InvalidOperationException>(() => world.Update(0.01f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Reads(typeof(MockComponent))]
|
||||||
[Writes(typeof(MockComponent))]
|
[Writes(typeof(MockComponent))]
|
||||||
public class UpdateComponentTestEngine : Engine
|
public class UpdateComponentTestEngine : Engine
|
||||||
{
|
{
|
||||||
|
@ -147,6 +150,7 @@ namespace Tests
|
||||||
Assert.AreEqual("blaze it", resultComponent.myString);
|
Assert.AreEqual("blaze it", resultComponent.myString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Reads(typeof(MockComponent))]
|
||||||
public class UndeclaredUpdateComponentTestEngine : Engine
|
public class UndeclaredUpdateComponentTestEngine : Engine
|
||||||
{
|
{
|
||||||
public override void Update(double dt)
|
public override void Update(double dt)
|
||||||
|
@ -177,7 +181,7 @@ namespace Tests
|
||||||
|
|
||||||
var world = worldBuilder.Build();
|
var world = worldBuilder.Build();
|
||||||
|
|
||||||
var ex = Assert.Throws<IllegalComponentMutationException>(() => world.Update(0.01f));
|
var ex = Assert.Throws<IllegalWriteException>(() => 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 write undeclared Component MockComponent"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,7 +267,7 @@ namespace Tests
|
||||||
|
|
||||||
var world = worldBuilder.Build();
|
var world = worldBuilder.Build();
|
||||||
|
|
||||||
var ex = Assert.Throws<IllegalMessageEmitException>(() => world.Update(0.01f));
|
var ex = Assert.Throws<IllegalWriteException>(() => 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 emit undeclared Message MockMessage"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,12 +325,13 @@ namespace Tests
|
||||||
|
|
||||||
var world = worldBuilder.Build();
|
var world = worldBuilder.Build();
|
||||||
|
|
||||||
Assert.Throws<IllegalMessageReadException>(() => world.Update(0.01f));
|
Assert.Throws<IllegalReadException>(() => world.Update(0.01f));
|
||||||
}
|
}
|
||||||
|
|
||||||
static ValueTuple<Guid, MockComponent> pairA;
|
static ValueTuple<Guid, MockComponent> pairA;
|
||||||
static ValueTuple<Guid, MockComponent> pairB;
|
static ValueTuple<Guid, MockComponent> pairB;
|
||||||
|
|
||||||
|
[Reads(typeof(MockComponent))]
|
||||||
class SameValueComponentReadEngine : Engine
|
class SameValueComponentReadEngine : Engine
|
||||||
{
|
{
|
||||||
public override void Update(double dt)
|
public override void Update(double dt)
|
||||||
|
@ -366,6 +371,7 @@ namespace Tests
|
||||||
|
|
||||||
static IEnumerable<ValueTuple<Guid, MockComponent>> emptyComponentReadResult;
|
static IEnumerable<ValueTuple<Guid, MockComponent>> emptyComponentReadResult;
|
||||||
|
|
||||||
|
[Reads(typeof(MockComponent))]
|
||||||
class ReadEmptyMockComponentsEngine : Engine
|
class ReadEmptyMockComponentsEngine : Engine
|
||||||
{
|
{
|
||||||
public override void Update(double dt)
|
public override void Update(double dt)
|
||||||
|
@ -388,6 +394,7 @@ namespace Tests
|
||||||
|
|
||||||
struct DestroyerComponent : IComponent { }
|
struct DestroyerComponent : IComponent { }
|
||||||
|
|
||||||
|
[Reads(typeof(DestroyerComponent))]
|
||||||
class DestroyerEngine : Engine
|
class DestroyerEngine : Engine
|
||||||
{
|
{
|
||||||
public override void Update(double dt)
|
public override void Update(double dt)
|
||||||
|
@ -402,6 +409,8 @@ namespace Tests
|
||||||
}
|
}
|
||||||
|
|
||||||
static IEnumerable<ValueTuple<Guid, MockComponent>> results;
|
static IEnumerable<ValueTuple<Guid, MockComponent>> results;
|
||||||
|
|
||||||
|
[Reads(typeof(MockComponent))]
|
||||||
class ReaderEngine : Engine
|
class ReaderEngine : Engine
|
||||||
{
|
{
|
||||||
public override void Update(double dt)
|
public override void Update(double dt)
|
||||||
|
@ -439,6 +448,7 @@ namespace Tests
|
||||||
Assert.That(results, Does.Not.Contain((componentBID, mockComponent)));
|
Assert.That(results, Does.Not.Contain((componentBID, mockComponent)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Reads(typeof(DestroyerComponent))]
|
||||||
class DestroyAndAddComponentEngine : Engine
|
class DestroyAndAddComponentEngine : Engine
|
||||||
{
|
{
|
||||||
public override void Update(double dt)
|
public override void Update(double dt)
|
||||||
|
@ -472,6 +482,8 @@ namespace Tests
|
||||||
}
|
}
|
||||||
|
|
||||||
static Entity entityFromComponentIDResult;
|
static Entity entityFromComponentIDResult;
|
||||||
|
|
||||||
|
[Reads(typeof(MockComponent))]
|
||||||
class GetEntityFromComponentIDEngine : Engine
|
class GetEntityFromComponentIDEngine : Engine
|
||||||
{
|
{
|
||||||
public override void Update(double dt)
|
public override void Update(double dt)
|
||||||
|
@ -501,6 +513,8 @@ namespace Tests
|
||||||
}
|
}
|
||||||
|
|
||||||
static MockComponent mockComponentByIDResult;
|
static MockComponent mockComponentByIDResult;
|
||||||
|
|
||||||
|
[Reads(typeof(MockComponent))]
|
||||||
class GetComponentByIDEngine : Engine
|
class GetComponentByIDEngine : Engine
|
||||||
{
|
{
|
||||||
public override void Update(double dt)
|
public override void Update(double dt)
|
||||||
|
@ -530,6 +544,7 @@ namespace Tests
|
||||||
|
|
||||||
struct OtherComponent : IComponent { }
|
struct OtherComponent : IComponent { }
|
||||||
|
|
||||||
|
[Reads(typeof(MockComponent), typeof(OtherComponent))]
|
||||||
class GetComponentByIDWithTypeMismatchEngine : Engine
|
class GetComponentByIDWithTypeMismatchEngine : Engine
|
||||||
{
|
{
|
||||||
public override void Update(double dt)
|
public override void Update(double dt)
|
||||||
|
@ -559,6 +574,8 @@ namespace Tests
|
||||||
|
|
||||||
struct EntityIDComponent : IComponent { public Guid entityID; }
|
struct EntityIDComponent : IComponent { public Guid entityID; }
|
||||||
static bool hasEntity;
|
static bool hasEntity;
|
||||||
|
|
||||||
|
[Reads(typeof(EntityIDComponent))]
|
||||||
class HasEntityTestEngine : Engine
|
class HasEntityTestEngine : Engine
|
||||||
{
|
{
|
||||||
public override void Update(double dt)
|
public override void Update(double dt)
|
||||||
|
|
|
@ -133,7 +133,74 @@ namespace Tests
|
||||||
worldBuilder.AddEngine(new AEngine());
|
worldBuilder.AddEngine(new AEngine());
|
||||||
worldBuilder.AddEngine(new BEngine());
|
worldBuilder.AddEngine(new BEngine());
|
||||||
|
|
||||||
Assert.Throws<EngineMutationConflictException>(() => worldBuilder.Build());
|
Assert.Throws<EngineWriteConflictException>(() => worldBuilder.Build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EngineMessageSelfCycle
|
||||||
|
{
|
||||||
|
struct AMessage : IMessage { }
|
||||||
|
|
||||||
|
[Reads(typeof(AMessage))]
|
||||||
|
[Writes(typeof(AMessage))]
|
||||||
|
class AEngine : Engine
|
||||||
|
{
|
||||||
|
public override void Update(double dt)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ThrowsError()
|
||||||
|
{
|
||||||
|
var worldBuilder = new WorldBuilder();
|
||||||
|
|
||||||
|
Assert.Throws<EngineMessageSelfCycleException>(() => worldBuilder.AddEngine(new AEngine()), "Engine both reads and writes Message AMessage");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class IllegalReadType
|
||||||
|
{
|
||||||
|
struct ANonMessage { }
|
||||||
|
|
||||||
|
[Reads(typeof(ANonMessage))]
|
||||||
|
class MyEngine : Engine
|
||||||
|
{
|
||||||
|
public override void Update(double dt)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ThrowsError()
|
||||||
|
{
|
||||||
|
var worldBuilder = new WorldBuilder();
|
||||||
|
|
||||||
|
Assert.Throws<IllegalReadTypeException>(() => worldBuilder.AddEngine(new MyEngine()), "ANonMessage must be a Message or Component");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class IllegalWriteType
|
||||||
|
{
|
||||||
|
struct ANonMessage { }
|
||||||
|
|
||||||
|
[Writes(typeof(ANonMessage))]
|
||||||
|
class MyEngine : Engine
|
||||||
|
{
|
||||||
|
public override void Update(double dt)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ThrowsError()
|
||||||
|
{
|
||||||
|
var worldBuilder = new WorldBuilder();
|
||||||
|
|
||||||
|
Assert.Throws<IllegalWriteTypeException>(() => worldBuilder.AddEngine(new MyEngine()), "ANonMessage must be a Message or Component");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue