start on message stuff
parent
e2ecd37556
commit
c1aa6a07c9
|
@ -7,9 +7,12 @@ namespace Encompass
|
|||
public abstract class Engine
|
||||
{
|
||||
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 ComponentManager componentManager;
|
||||
private MessageManager messageManager;
|
||||
|
||||
public Engine()
|
||||
{
|
||||
|
@ -18,6 +21,18 @@ namespace Encompass
|
|||
{
|
||||
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)
|
||||
|
@ -30,6 +45,11 @@ namespace Encompass
|
|||
this.componentManager = componentManager;
|
||||
}
|
||||
|
||||
internal void AssignMessageManager(MessageManager messageManager)
|
||||
{
|
||||
this.messageManager = messageManager;
|
||||
}
|
||||
|
||||
public abstract void Update(float dt);
|
||||
|
||||
protected Entity CreateEntity()
|
||||
|
@ -72,5 +92,29 @@ namespace Encompass
|
|||
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 EntityManager entityManager;
|
||||
private ComponentManager componentManager;
|
||||
private MessageManager messageManager;
|
||||
|
||||
internal World(
|
||||
List<Engine> engines,
|
||||
EntityManager entityManager,
|
||||
ComponentManager componentManager
|
||||
ComponentManager componentManager,
|
||||
MessageManager messageManager
|
||||
)
|
||||
{
|
||||
this.engines = engines;
|
||||
this.entityManager = entityManager;
|
||||
this.componentManager = componentManager;
|
||||
this.messageManager = messageManager;
|
||||
}
|
||||
|
||||
public void Update(float dt)
|
||||
|
@ -26,6 +29,7 @@ namespace Encompass
|
|||
engine.Update(dt);
|
||||
}
|
||||
|
||||
messageManager.ClearMessages();
|
||||
entityManager.DestroyMarkedEntities();
|
||||
componentManager.ActivateComponents();
|
||||
componentManager.RemoveComponents();
|
||||
|
|
|
@ -8,11 +8,13 @@ namespace Encompass
|
|||
|
||||
private ComponentManager componentManager;
|
||||
private EntityManager entityManager;
|
||||
private MessageManager messageManager;
|
||||
|
||||
public WorldBuilder()
|
||||
{
|
||||
componentManager = new ComponentManager();
|
||||
entityManager = new EntityManager(componentManager);
|
||||
messageManager = new MessageManager();
|
||||
}
|
||||
|
||||
public Entity CreateEntity()
|
||||
|
@ -26,6 +28,7 @@ namespace Encompass
|
|||
|
||||
engine.AssignEntityManager(this.entityManager);
|
||||
engine.AssignComponentManager(this.componentManager);
|
||||
engine.AssignMessageManager(this.messageManager);
|
||||
|
||||
engines.Add(engine);
|
||||
|
||||
|
@ -37,7 +40,8 @@ namespace Encompass
|
|||
var world = new World(
|
||||
this.engines,
|
||||
this.entityManager,
|
||||
this.componentManager
|
||||
this.componentManager,
|
||||
this.messageManager
|
||||
);
|
||||
|
||||
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="IComponent.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>
|
||||
</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 MockComponent resultComponent;
|
||||
|
||||
static IEnumerable<MockMessage> resultMessages;
|
||||
|
||||
public class ReadComponentsTestEngine : Engine
|
||||
{
|
||||
public override void Update(float dt)
|
||||
|
@ -172,5 +174,68 @@ namespace Tests
|
|||
var ex = Assert.Throws<IllegalComponentMutationException>(() => world.Update(0.01f));
|
||||
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