diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs
index e26146f..9ec8870 100644
--- a/encompass-cs/Engine.cs
+++ b/encompass-cs/Engine.cs
@@ -554,14 +554,23 @@ namespace Encompass
}
///
- /// Sends a message after the specified number of seconds.
+ /// Sends a message after the specified number of seconds, respecting time dilation.
///
/// The time in seconds that will elapse before the message is sent.
- protected void SendMessageDelayed(TMessage message, double time) where TMessage : struct, IMessage
+ protected void SendMessage(TMessage message, double time) where TMessage : struct, IMessage
{
messageManager.AddMessageDelayed(message, time);
}
+ ///
+ /// Sends a message after the specified number of seconds, ignoring time dilation.
+ ///
+ /// The time in seconds that will elapse before the message is sent.
+ protected void SendMessageIgnoringTimeDilation(TMessage message, double time) where TMessage : struct, IMessage
+ {
+ messageManager.AddMessageDelayedIgnoringTimeDilation(message, time);
+ }
+
// unparameterized version to enable dynamic dispatch
protected void SendMessage(IMessage message)
{
@@ -695,24 +704,64 @@ namespace Encompass
if (!timeDilationPriority.HasValue) { throw new TimeDilationPriorityUndefinedException("Engines that activate time dilation must use the TimeDilationPriority attribute."); }
}
+ ///
+ /// Activates the Encompass time dilation system.
+ /// If activating time dilation, make sure the TimeDilationPriority attribute is set or an exception will be thrown.
+ /// Engines that have the IgnoresTimeDilation property will ignore all time dilation.
+ ///
+ /// The time dilation factor, which is multiplied by real delta time.
+ /// The time that will elapse before time is fully dilated, in real time.
+ /// The length of real time that time will be fully dilated.
+ /// The time that will elapse before time is fully undilated.
public void ActivateTimeDilation(double factor, double easeInTime, double activeTime, double easeOutTime)
{
CheckTimeDilationPriorityExists();
timeManager.ActivateTimeDilation(factor, easeInTime, activeTime, easeOutTime, timeDilationPriority.Value);
}
+ ///
+ /// Activates the Encompass time dilation system.
+ /// If activating time dilation, make sure the TimeDilationPriority attribute is set or an exception will be thrown.
+ /// Engines that have the IgnoresTimeDilation property will ignore all time dilation.
+ ///
+ /// The time dilation factor, which is multiplied by real delta time.
+ /// The time that will elapse before time is fully dilated, in real time.
+ /// An easing function for the easing in of time dilation.
+ /// The length of real time that time will be fully dilated.
+ /// The time that will elapse before time is fully undilated.
public void ActivateTimeDilation(double factor, double easeInTime, System.Func easeInFunction, double activeTime, double easeOutTime)
{
CheckTimeDilationPriorityExists();
timeManager.ActivateTimeDilation(factor, easeInTime, easeInFunction, activeTime, easeOutTime, timeDilationPriority.Value);
}
+ ///
+ /// Activates the Encompass time dilation system.
+ /// If activating time dilation, make sure the TimeDilationPriority attribute is set or an exception will be thrown.
+ /// Engines that have the IgnoresTimeDilation property will ignore all time dilation.
+ ///
+ /// The time dilation factor, which is multiplied by real delta time.
+ /// The time that will elapse before time is fully dilated, in real time.
+ /// The length of real time that time will be fully dilated.
+ /// The time that will elapse before time is fully undilated.
+ /// An easing function for the easing out of time dilation.
public void ActivateTimeDilation(double factor, double easeInTime, double activeTime, double easeOutTime, System.Func easeOutFunction)
{
CheckTimeDilationPriorityExists();
timeManager.ActivateTimeDilation(factor, easeInTime, activeTime, easeOutTime, easeOutFunction, timeDilationPriority.Value);
}
+ ///
+ /// Activates the Encompass time dilation system.
+ /// If activating time dilation, make sure the TimeDilationPriority attribute is set or an exception will be thrown.
+ /// Engines that have the IgnoresTimeDilation property will ignore all time dilation.
+ ///
+ /// The time dilation factor, which is multiplied by real delta time.
+ /// The time that will elapse before time is fully dilated, in real time.
+ /// An easing function for the easing in of time dilation.
+ /// The length of real time that time will be fully dilated.
+ /// The time that will elapse before time is fully undilated.
+ /// An easing function for the easing out of time dilation.
public void ActivateTimeDilation(double factor, double easeInTime, System.Func easeInFunction, double activeTime, double easeOutTime, System.Func easeOutFunction)
{
CheckTimeDilationPriorityExists();
diff --git a/encompass-cs/MessageManager.cs b/encompass-cs/MessageManager.cs
index 1f86cb9..7846092 100644
--- a/encompass-cs/MessageManager.cs
+++ b/encompass-cs/MessageManager.cs
@@ -6,13 +6,22 @@ namespace Encompass
{
internal class MessageManager
{
+ private TimeManager timeManager;
+
private readonly Dictionary> messageTypeToMessages = new Dictionary>();
private readonly List<(IMessage, double)> delayedMessages = new List<(IMessage, double)>();
+ private readonly List<(IMessage, double)> delayedMessagesIgnoringTimeDilation = new List<(IMessage, double)>();
+
+ public MessageManager(TimeManager timeManager)
+ {
+ this.timeManager = timeManager;
+ }
internal void RegisterMessageType(Type messageType)
{
- if (!messageTypeToMessages.ContainsKey(messageType)) {
+ if (!messageTypeToMessages.ContainsKey(messageType))
+ {
messageTypeToMessages.Add(messageType, new List());
}
}
@@ -31,9 +40,11 @@ namespace Encompass
delayedMessages.Add((message, time));
}
- internal void AddMessage(IMessage message) where TMessage : struct, IMessage
+ internal void AddMessageDelayedIgnoringTimeDilation(IMessage message, double time)
{
- messageTypeToMessages[typeof(TMessage)].Add(message);
+ if (!messageTypeToMessages.ContainsKey(message.GetType())) { messageTypeToMessages.Add(message.GetType(), new List()); }
+
+ delayedMessagesIgnoringTimeDilation.Add((message, time));
}
internal void ClearMessages()
@@ -50,7 +61,7 @@ namespace Encompass
{
var (message, time) = delayedMessages[i];
- var updatedTime = time - dt;
+ var updatedTime = time - (dt * timeManager.TimeDilationFactor);
if (updatedTime <= 0)
{
@@ -62,6 +73,23 @@ namespace Encompass
delayedMessages[i] = (message, updatedTime);
}
}
+
+ for (int i = delayedMessagesIgnoringTimeDilation.Count - 1; i >= 0; i--)
+ {
+ var (message, time) = delayedMessagesIgnoringTimeDilation[i];
+
+ var updatedTime = time - dt;
+
+ if (updatedTime <= 0)
+ {
+ AddMessage(message);
+ delayedMessagesIgnoringTimeDilation.RemoveAt(i);
+ }
+ else
+ {
+ delayedMessagesIgnoringTimeDilation[i] = (message, updatedTime);
+ }
+ }
}
internal IEnumerable GetMessagesByType() where TMessage : struct, IMessage
diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs
index 8e1d510..a44e452 100644
--- a/encompass-cs/WorldBuilder.cs
+++ b/encompass-cs/WorldBuilder.cs
@@ -38,11 +38,11 @@ namespace Encompass
public WorldBuilder()
{
drawLayerManager = new DrawLayerManager();
+ timeManager = new TimeManager();
componentManager = new ComponentManager(drawLayerManager);
- messageManager = new MessageManager();
+ messageManager = new MessageManager(timeManager);
componentMessageManager = new ComponentMessageManager();
entityManager = new EntityManager(componentManager, componentMessageManager);
- timeManager = new TimeManager();
renderManager = new RenderManager(componentManager, drawLayerManager, entityManager);
}
diff --git a/test/EngineTest.cs b/test/EngineTest.cs
index c23f6e9..849371a 100644
--- a/test/EngineTest.cs
+++ b/test/EngineTest.cs
@@ -672,7 +672,7 @@ namespace Tests
foreach (var (component, entity) in ReadComponentsIncludingEntity())
{
RemoveComponent(entity);
- SendMessageDelayed(new MockMessage { }, 1);
+ SendMessage(new MockMessage { }, 1);
}
}
}
@@ -683,6 +683,7 @@ namespace Tests
resultMessages.Clear();
var worldBuilder = new WorldBuilder();
+ worldBuilder.AddEngine(new ActivateTimeDilationEngine());
worldBuilder.AddEngine(new DelayedMessageEngine());
worldBuilder.AddEngine(new MessageReadEngine());
@@ -701,6 +702,52 @@ namespace Tests
world.Update(0.5);
+ resultMessages.Should().BeEmpty();
+
+ world.Update(2);
+
+ resultMessages.Should().NotBeEmpty();
+ resultMessages.First().Should().BeOfType();
+ }
+
+ [Reads(typeof(MockComponent))]
+ class DelayedMessageIgnoringTimeDilationEngine : Engine
+ {
+ public override void Update(double dt)
+ {
+ foreach (var (component, entity) in ReadComponentsIncludingEntity())
+ {
+ RemoveComponent(entity);
+ SendMessageIgnoringTimeDilation(new MockMessage { }, 1);
+ }
+ }
+ }
+
+ [Test]
+ public void EngineSendMessageDelayedIgnoringTimeDilation()
+ {
+ resultMessages.Clear();
+
+ var worldBuilder = new WorldBuilder();
+ worldBuilder.AddEngine(new ActivateTimeDilationEngine());
+ worldBuilder.AddEngine(new DelayedMessageIgnoringTimeDilationEngine());
+ worldBuilder.AddEngine(new MessageReadEngine());
+
+ var entity = worldBuilder.CreateEntity();
+ worldBuilder.SetComponent(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();
}