start on message stuff
parent
e2ecd37556
commit
c1aa6a07c9
|
@ -7,9 +7,12 @@ namespace Encompass
|
||||||
public abstract class Engine
|
public abstract class Engine
|
||||||
{
|
{
|
||||||
public readonly List<Type> mutateComponentTypes = new List<Type>();
|
public readonly List<Type> mutateComponentTypes = new List<Type>();
|
||||||
|
public readonly List<Type> emitMessageTypes = new List<Type>();
|
||||||
|
public readonly List<Type> readMessageTypes = new List<Type>();
|
||||||
|
|
||||||
private EntityManager entityManager;
|
private EntityManager entityManager;
|
||||||
private ComponentManager componentManager;
|
private ComponentManager componentManager;
|
||||||
|
private MessageManager messageManager;
|
||||||
|
|
||||||
public Engine()
|
public Engine()
|
||||||
{
|
{
|
||||||
|
@ -18,6 +21,18 @@ namespace Encompass
|
||||||
{
|
{
|
||||||
mutateComponentTypes = mutatesAttribute.mutateComponentTypes;
|
mutateComponentTypes = mutatesAttribute.mutateComponentTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var emitsAttribute = this.GetType().GetCustomAttribute<Emits>(false);
|
||||||
|
if (emitsAttribute != null)
|
||||||
|
{
|
||||||
|
emitMessageTypes = emitsAttribute.emitMessageTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
var readsAttribute = this.GetType().GetCustomAttribute<Reads>(false);
|
||||||
|
if (readsAttribute != null)
|
||||||
|
{
|
||||||
|
readMessageTypes = readsAttribute.readMessageTypes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void AssignEntityManager(EntityManager entityManager)
|
internal void AssignEntityManager(EntityManager entityManager)
|
||||||
|
@ -30,6 +45,11 @@ namespace Encompass
|
||||||
this.componentManager = componentManager;
|
this.componentManager = componentManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void AssignMessageManager(MessageManager messageManager)
|
||||||
|
{
|
||||||
|
this.messageManager = messageManager;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract void Update(float dt);
|
public abstract void Update(float dt);
|
||||||
|
|
||||||
protected Entity CreateEntity()
|
protected Entity CreateEntity()
|
||||||
|
@ -72,5 +92,29 @@ namespace Encompass
|
||||||
this.UpdateComponent(component, updateFunction);
|
this.UpdateComponent(component, updateFunction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void EmitMessage<TMessage>(TMessage message) where TMessage : struct, IMessage
|
||||||
|
{
|
||||||
|
if (emitMessageTypes.Contains(typeof(TMessage)))
|
||||||
|
{
|
||||||
|
this.messageManager.AddMessage(message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalMessageEmitException("Engine {0} tried to emit undeclared Message {1}", this.GetType().Name, typeof(TMessage).Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IEnumerable<TMessage> ReadMessages<TMessage>() where TMessage : struct, IMessage
|
||||||
|
{
|
||||||
|
if (readMessageTypes.Contains(typeof(TMessage)))
|
||||||
|
{
|
||||||
|
return this.messageManager.GetMessagesByType<TMessage>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalMessageReadException("Engine {0} tried to read undeclared Message {1}", this.GetType().Name, typeof(TMessage).Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Encompass
|
||||||
|
{
|
||||||
|
internal class MessageManager
|
||||||
|
{
|
||||||
|
private Dictionary<Type, List<IMessage>> messageTypeToMessages = new Dictionary<Type, List<IMessage>>();
|
||||||
|
|
||||||
|
internal void AddMessage<TMessage>(TMessage message) where TMessage : struct, IMessage
|
||||||
|
{
|
||||||
|
if (!messageTypeToMessages.ContainsKey(typeof(TMessage)))
|
||||||
|
{
|
||||||
|
messageTypeToMessages.Add(typeof(TMessage), new List<IMessage>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ClearMessages()
|
||||||
|
{
|
||||||
|
foreach (var entry in messageTypeToMessages)
|
||||||
|
{
|
||||||
|
entry.Value.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal IEnumerable<TMessage> GetMessagesByType<TMessage>() where TMessage : struct, IMessage
|
||||||
|
{
|
||||||
|
return messageTypeToMessages[typeof(TMessage)].Cast<TMessage>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,16 +7,19 @@ namespace Encompass
|
||||||
private List<Engine> engines;
|
private List<Engine> engines;
|
||||||
private EntityManager entityManager;
|
private EntityManager entityManager;
|
||||||
private ComponentManager componentManager;
|
private ComponentManager componentManager;
|
||||||
|
private MessageManager messageManager;
|
||||||
|
|
||||||
internal World(
|
internal World(
|
||||||
List<Engine> engines,
|
List<Engine> engines,
|
||||||
EntityManager entityManager,
|
EntityManager entityManager,
|
||||||
ComponentManager componentManager
|
ComponentManager componentManager,
|
||||||
|
MessageManager messageManager
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
this.engines = engines;
|
this.engines = engines;
|
||||||
this.entityManager = entityManager;
|
this.entityManager = entityManager;
|
||||||
this.componentManager = componentManager;
|
this.componentManager = componentManager;
|
||||||
|
this.messageManager = messageManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update(float dt)
|
public void Update(float dt)
|
||||||
|
@ -26,6 +29,7 @@ namespace Encompass
|
||||||
engine.Update(dt);
|
engine.Update(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
messageManager.ClearMessages();
|
||||||
entityManager.DestroyMarkedEntities();
|
entityManager.DestroyMarkedEntities();
|
||||||
componentManager.ActivateComponents();
|
componentManager.ActivateComponents();
|
||||||
componentManager.RemoveComponents();
|
componentManager.RemoveComponents();
|
||||||
|
|
|
@ -8,11 +8,13 @@ namespace Encompass
|
||||||
|
|
||||||
private ComponentManager componentManager;
|
private ComponentManager componentManager;
|
||||||
private EntityManager entityManager;
|
private EntityManager entityManager;
|
||||||
|
private MessageManager messageManager;
|
||||||
|
|
||||||
public WorldBuilder()
|
public WorldBuilder()
|
||||||
{
|
{
|
||||||
componentManager = new ComponentManager();
|
componentManager = new ComponentManager();
|
||||||
entityManager = new EntityManager(componentManager);
|
entityManager = new EntityManager(componentManager);
|
||||||
|
messageManager = new MessageManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Entity CreateEntity()
|
public Entity CreateEntity()
|
||||||
|
@ -26,6 +28,7 @@ namespace Encompass
|
||||||
|
|
||||||
engine.AssignEntityManager(this.entityManager);
|
engine.AssignEntityManager(this.entityManager);
|
||||||
engine.AssignComponentManager(this.componentManager);
|
engine.AssignComponentManager(this.componentManager);
|
||||||
|
engine.AssignMessageManager(this.messageManager);
|
||||||
|
|
||||||
engines.Add(engine);
|
engines.Add(engine);
|
||||||
|
|
||||||
|
@ -37,7 +40,8 @@ namespace Encompass
|
||||||
var world = new World(
|
var world = new World(
|
||||||
this.engines,
|
this.engines,
|
||||||
this.entityManager,
|
this.entityManager,
|
||||||
this.componentManager
|
this.componentManager,
|
||||||
|
this.messageManager
|
||||||
);
|
);
|
||||||
|
|
||||||
this.componentManager.ActivateComponents();
|
this.componentManager.ActivateComponents();
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Encompass
|
||||||
|
{
|
||||||
|
[System.AttributeUsage(System.AttributeTargets.Class)]
|
||||||
|
public class Emits : System.Attribute
|
||||||
|
{
|
||||||
|
public readonly List<Type> emitMessageTypes;
|
||||||
|
|
||||||
|
public Emits(params Type[] emitMessageTypes)
|
||||||
|
{
|
||||||
|
this.emitMessageTypes = new List<Type>(emitMessageTypes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Encompass
|
||||||
|
{
|
||||||
|
[System.AttributeUsage(System.AttributeTargets.Class)]
|
||||||
|
public class Reads : System.Attribute
|
||||||
|
{
|
||||||
|
public readonly List<Type> readMessageTypes;
|
||||||
|
|
||||||
|
public Reads(params Type[] readMessageTypes)
|
||||||
|
{
|
||||||
|
this.readMessageTypes = new List<Type>(readMessageTypes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,5 +17,9 @@
|
||||||
<Content Include="graph\DirectedGraph.cs" />
|
<Content Include="graph\DirectedGraph.cs" />
|
||||||
<Content Include="IComponent.cs" />
|
<Content Include="IComponent.cs" />
|
||||||
<Content Include="IMessage.cs" />
|
<Content Include="IMessage.cs" />
|
||||||
|
<Content Include="MessageManager.cs" />
|
||||||
|
<Content Include="attributes\Emits.cs" />
|
||||||
|
<Content Include="exceptions\IllegalMessageEmitException.cs" />
|
||||||
|
<Content Include="exceptions\IllegalMessageReadException.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Encompass
|
||||||
|
{
|
||||||
|
public class IllegalMessageEmitException : Exception
|
||||||
|
{
|
||||||
|
public IllegalMessageEmitException(
|
||||||
|
string format,
|
||||||
|
params object[] args
|
||||||
|
) : base(string.Format(format, args)) { }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Encompass
|
||||||
|
{
|
||||||
|
public class IllegalMessageReadException : Exception
|
||||||
|
{
|
||||||
|
public IllegalMessageReadException(
|
||||||
|
string format,
|
||||||
|
params object[] args
|
||||||
|
) : base(string.Format(format, args)) { }
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,8 @@ namespace Tests
|
||||||
static IEnumerable<MockComponent> resultComponents;
|
static IEnumerable<MockComponent> resultComponents;
|
||||||
static MockComponent resultComponent;
|
static MockComponent resultComponent;
|
||||||
|
|
||||||
|
static IEnumerable<MockMessage> resultMessages;
|
||||||
|
|
||||||
public class ReadComponentsTestEngine : Engine
|
public class ReadComponentsTestEngine : Engine
|
||||||
{
|
{
|
||||||
public override void Update(float dt)
|
public override void Update(float dt)
|
||||||
|
@ -172,5 +174,68 @@ namespace Tests
|
||||||
var ex = Assert.Throws<IllegalComponentMutationException>(() => world.Update(0.01f));
|
var ex = Assert.Throws<IllegalComponentMutationException>(() => world.Update(0.01f));
|
||||||
Assert.That(ex.Message, Is.EqualTo("Engine UndeclaredUpdateComponentTestEngine tried to mutate undeclared Component MockComponent"));
|
Assert.That(ex.Message, Is.EqualTo("Engine UndeclaredUpdateComponentTestEngine tried to mutate undeclared Component MockComponent"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MockMessage : IMessage
|
||||||
|
{
|
||||||
|
public string myString;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Emits(typeof(MockMessage))]
|
||||||
|
public class MessageEmitEngine : Engine
|
||||||
|
{
|
||||||
|
public override void Update(float dt)
|
||||||
|
{
|
||||||
|
MockMessage message;
|
||||||
|
message.myString = "howdy";
|
||||||
|
|
||||||
|
this.EmitMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Reads(typeof(MockMessage))]
|
||||||
|
public class MessageReadEngine : Engine
|
||||||
|
{
|
||||||
|
public override void Update(float dt)
|
||||||
|
{
|
||||||
|
resultMessages = this.ReadMessages<MockMessage>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void EmitAndReadMessage()
|
||||||
|
{
|
||||||
|
var worldBuilder = new WorldBuilder();
|
||||||
|
worldBuilder.AddEngine<MessageEmitEngine>();
|
||||||
|
worldBuilder.AddEngine<MessageReadEngine>();
|
||||||
|
|
||||||
|
var world = worldBuilder.Build();
|
||||||
|
|
||||||
|
world.Update(0.01f);
|
||||||
|
|
||||||
|
Assert.AreEqual(resultMessages.First().myString, "howdy");
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UndeclaredMessageEmitEngine : Engine
|
||||||
|
{
|
||||||
|
public override void Update(float dt)
|
||||||
|
{
|
||||||
|
MockMessage message;
|
||||||
|
message.myString = "howdy";
|
||||||
|
|
||||||
|
this.EmitMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void EmitUndeclaredMessage()
|
||||||
|
{
|
||||||
|
var worldBuilder = new WorldBuilder();
|
||||||
|
worldBuilder.AddEngine<UndeclaredMessageEmitEngine>();
|
||||||
|
|
||||||
|
var world = worldBuilder.Build();
|
||||||
|
|
||||||
|
var ex = Assert.Throws<IllegalMessageEmitException>(() => world.Update(0.01f));
|
||||||
|
Assert.That(ex.Message, Is.EqualTo("Engine UndeclaredMessageEmitEngine tried to emit undeclared Message MockMessage"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue