delayed message system
parent
6a51ceb590
commit
d084286c83
|
@ -113,7 +113,7 @@ namespace Encompass
|
||||||
}
|
}
|
||||||
|
|
||||||
// these next two are for the ComponentMessageEmitter only
|
// these next two are for the ComponentMessageEmitter only
|
||||||
|
|
||||||
internal IEnumerable<(Guid, TComponent)> ReadComponentsFromWorld<TComponent>() where TComponent : struct, IComponent
|
internal IEnumerable<(Guid, TComponent)> ReadComponentsFromWorld<TComponent>() where TComponent : struct, IComponent
|
||||||
{
|
{
|
||||||
return componentManager.GetComponentsByType<TComponent>();
|
return componentManager.GetComponentsByType<TComponent>();
|
||||||
|
@ -308,6 +308,11 @@ namespace Encompass
|
||||||
messageManager.AddMessage(message);
|
messageManager.AddMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void SendMessageDelayed<TMessage>(TMessage message, double time) where TMessage : struct, IMessage
|
||||||
|
{
|
||||||
|
messageManager.AddMessageDelayed(message, time);
|
||||||
|
}
|
||||||
|
|
||||||
// unparameterized version to enable dynamic dispatch
|
// unparameterized version to enable dynamic dispatch
|
||||||
protected void SendMessage(IMessage message)
|
protected void SendMessage(IMessage message)
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,6 +8,8 @@ namespace Encompass
|
||||||
{
|
{
|
||||||
private readonly Dictionary<Type, List<IMessage>> messageTypeToMessages = new Dictionary<Type, List<IMessage>>();
|
private readonly Dictionary<Type, List<IMessage>> messageTypeToMessages = new Dictionary<Type, List<IMessage>>();
|
||||||
|
|
||||||
|
private readonly List<(IMessage, double)> delayedMessages = new List<(IMessage, double)>();
|
||||||
|
|
||||||
internal void RegisterMessageType(Type messageType)
|
internal void RegisterMessageType(Type messageType)
|
||||||
{
|
{
|
||||||
if (!messageTypeToMessages.ContainsKey(messageType)) {
|
if (!messageTypeToMessages.ContainsKey(messageType)) {
|
||||||
|
@ -22,6 +24,13 @@ namespace Encompass
|
||||||
messageTypeToMessages[type].Add(message);
|
messageTypeToMessages[type].Add(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void AddMessageDelayed(IMessage message, double time)
|
||||||
|
{
|
||||||
|
if (!messageTypeToMessages.ContainsKey(message.GetType())) { messageTypeToMessages.Add(message.GetType(), new List<IMessage>()); }
|
||||||
|
|
||||||
|
delayedMessages.Add((message, time));
|
||||||
|
}
|
||||||
|
|
||||||
internal void AddMessage<TMessage>(IMessage message) where TMessage : struct, IMessage
|
internal void AddMessage<TMessage>(IMessage message) where TMessage : struct, IMessage
|
||||||
{
|
{
|
||||||
messageTypeToMessages[typeof(TMessage)].Add(message);
|
messageTypeToMessages[typeof(TMessage)].Add(message);
|
||||||
|
@ -35,6 +44,26 @@ namespace Encompass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void ProcessDelayedMessages(double dt)
|
||||||
|
{
|
||||||
|
for (int i = delayedMessages.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var (message, time) = delayedMessages[i];
|
||||||
|
|
||||||
|
var updatedTime = time - dt;
|
||||||
|
|
||||||
|
if (updatedTime <= 0)
|
||||||
|
{
|
||||||
|
AddMessage(message);
|
||||||
|
delayedMessages.RemoveAt(i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delayedMessages[i] = (message, updatedTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal IEnumerable<TMessage> GetMessagesByType<TMessage>() where TMessage : struct, IMessage
|
internal IEnumerable<TMessage> GetMessagesByType<TMessage>() where TMessage : struct, IMessage
|
||||||
{
|
{
|
||||||
return messageTypeToMessages.ContainsKey(typeof(TMessage)) ?
|
return messageTypeToMessages.ContainsKey(typeof(TMessage)) ?
|
||||||
|
|
|
@ -30,6 +30,8 @@ namespace Encompass
|
||||||
|
|
||||||
public void Update(double dt)
|
public void Update(double dt)
|
||||||
{
|
{
|
||||||
|
messageManager.ProcessDelayedMessages(dt);
|
||||||
|
|
||||||
foreach (var engine in enginesInOrder)
|
foreach (var engine in enginesInOrder)
|
||||||
{
|
{
|
||||||
engine.Update(dt);
|
engine.Update(dt);
|
||||||
|
|
|
@ -45,6 +45,11 @@ namespace Encompass
|
||||||
messageManager.AddMessage(message);
|
messageManager.AddMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SendMessageDelayed<TMessage>(TMessage message, double time) where TMessage : struct, IMessage
|
||||||
|
{
|
||||||
|
messageManager.AddMessageDelayed(message, time);
|
||||||
|
}
|
||||||
|
|
||||||
public Guid AddComponent<TComponent>(Entity entity, TComponent component) where TComponent : struct, IComponent
|
public Guid AddComponent<TComponent>(Entity entity, TComponent component) where TComponent : struct, IComponent
|
||||||
{
|
{
|
||||||
return componentManager.MarkComponentForAdd(entity, component);
|
return componentManager.MarkComponentForAdd(entity, component);
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace Tests
|
||||||
static List<ValueTuple<Guid, MockComponent>> resultComponents;
|
static List<ValueTuple<Guid, MockComponent>> resultComponents;
|
||||||
static MockComponent resultComponent;
|
static MockComponent resultComponent;
|
||||||
|
|
||||||
static List<MockMessage> resultMessages;
|
static List<MockMessage> resultMessages = new List<MockMessage>();
|
||||||
|
|
||||||
[Reads(typeof(MockComponent))]
|
[Reads(typeof(MockComponent))]
|
||||||
public class ReadComponentsTestEngine : Engine
|
public class ReadComponentsTestEngine : Engine
|
||||||
|
@ -763,5 +763,46 @@ namespace Tests
|
||||||
var world = worldBuilder.Build();
|
var world = worldBuilder.Build();
|
||||||
Assert.Throws<RepeatUpdateComponentException>(() => world.Update(0.01));
|
Assert.Throws<RepeatUpdateComponentException>(() => world.Update(0.01));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Reads(typeof(MockComponent))]
|
||||||
|
class DelayedMessageEngine : Engine
|
||||||
|
{
|
||||||
|
public override void Update(double dt)
|
||||||
|
{
|
||||||
|
foreach (var (componentID, component) in ReadComponents<MockComponent>())
|
||||||
|
{
|
||||||
|
RemoveComponent(componentID);
|
||||||
|
SendMessageDelayed(new MockMessage {}, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void EngineSendMessageDelayed()
|
||||||
|
{
|
||||||
|
resultMessages.Clear();
|
||||||
|
|
||||||
|
var worldBuilder = new WorldBuilder();
|
||||||
|
worldBuilder.AddEngine(new DelayedMessageEngine());
|
||||||
|
worldBuilder.AddEngine(new MessageReadEngine());
|
||||||
|
|
||||||
|
var entity = worldBuilder.CreateEntity();
|
||||||
|
worldBuilder.AddComponent(entity, new MockComponent {});
|
||||||
|
|
||||||
|
var world = worldBuilder.Build();
|
||||||
|
|
||||||
|
world.Update(0.01);
|
||||||
|
|
||||||
|
resultMessages.Should().BeEmpty();
|
||||||
|
|
||||||
|
world.Update(0.5);
|
||||||
|
|
||||||
|
resultMessages.Should().BeEmpty();
|
||||||
|
|
||||||
|
world.Update(0.5);
|
||||||
|
|
||||||
|
resultMessages.Should().NotBeEmpty();
|
||||||
|
resultMessages.First().Should().BeOfType<MockMessage>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ using NUnit.Framework;
|
||||||
using Encompass;
|
using Encompass;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Encompass.Exceptions;
|
using Encompass.Exceptions;
|
||||||
|
using System.Linq;
|
||||||
|
using FluentAssertions;
|
||||||
|
|
||||||
namespace Tests
|
namespace Tests
|
||||||
{
|
{
|
||||||
|
@ -273,6 +275,39 @@ namespace Tests
|
||||||
Assert.That(order.IndexOf(engineB), Is.LessThan(order.IndexOf(engineC)));
|
Assert.That(order.IndexOf(engineB), Is.LessThan(order.IndexOf(engineC)));
|
||||||
Assert.That(order.IndexOf(engineC), Is.LessThan(order.IndexOf(engineD)));
|
Assert.That(order.IndexOf(engineC), Is.LessThan(order.IndexOf(engineD)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static List<AMessage> resultMessages = new List<AMessage>();
|
||||||
|
|
||||||
|
[Receives(typeof(AMessage))]
|
||||||
|
class ReadMessageEngine : Engine
|
||||||
|
{
|
||||||
|
public override void Update(double dt)
|
||||||
|
{
|
||||||
|
resultMessages = ReadMessages<AMessage>().ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void SendMessageDelayed()
|
||||||
|
{
|
||||||
|
var worldBuilder = new WorldBuilder();
|
||||||
|
worldBuilder.AddEngine(new ReadMessageEngine());
|
||||||
|
|
||||||
|
worldBuilder.SendMessageDelayed(new AMessage {}, 0.5);
|
||||||
|
|
||||||
|
var world = worldBuilder.Build();
|
||||||
|
|
||||||
|
resultMessages.Should().BeEmpty();
|
||||||
|
|
||||||
|
world.Update(0.25);
|
||||||
|
|
||||||
|
resultMessages.Should().BeEmpty();
|
||||||
|
|
||||||
|
world.Update(0.25);
|
||||||
|
|
||||||
|
resultMessages.Should().NotBeEmpty();
|
||||||
|
resultMessages.First().Should().BeOfType<AMessage>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue