messages with time dilation system
							parent
							
								
									fc50bf9b81
								
							
						
					
					
						commit
						d45295ae87
					
				| 
						 | 
					@ -554,14 +554,23 @@ namespace Encompass
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Sends a message after the specified number of seconds.
 | 
					        /// Sends a message after the specified number of seconds, respecting time dilation.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <param name="time">The time in seconds that will elapse before the message is sent.</param>
 | 
					        /// <param name="time">The time in seconds that will elapse before the message is sent.</param>
 | 
				
			||||||
        protected void SendMessageDelayed<TMessage>(TMessage message, double time) where TMessage : struct, IMessage
 | 
					        protected void SendMessage<TMessage>(TMessage message, double time) where TMessage : struct, IMessage
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            messageManager.AddMessageDelayed(message, time);
 | 
					            messageManager.AddMessageDelayed(message, time);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Sends a message after the specified number of seconds, ignoring time dilation.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="time">The time in seconds that will elapse before the message is sent.</param>
 | 
				
			||||||
 | 
					        protected void SendMessageIgnoringTimeDilation<TMessage>(TMessage message, double time) where TMessage : struct, IMessage
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            messageManager.AddMessageDelayedIgnoringTimeDilation(message, time);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // unparameterized version to enable dynamic dispatch
 | 
					        // unparameterized version to enable dynamic dispatch
 | 
				
			||||||
        protected void SendMessage(IMessage message)
 | 
					        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."); }
 | 
					            if (!timeDilationPriority.HasValue) { throw new TimeDilationPriorityUndefinedException("Engines that activate time dilation must use the TimeDilationPriority attribute."); }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// 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.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="factor">The time dilation factor, which is multiplied by real delta time.</param>
 | 
				
			||||||
 | 
					        /// <param name="easeInTime">The time that will elapse before time is fully dilated, in real time.</param>
 | 
				
			||||||
 | 
					        /// <param name="activeTime">The length of real time that time will be fully dilated.</param>
 | 
				
			||||||
 | 
					        /// <param name="easeOutTime">The time that will elapse before time is fully undilated.</param>
 | 
				
			||||||
        public void ActivateTimeDilation(double factor, double easeInTime, double activeTime, double easeOutTime)
 | 
					        public void ActivateTimeDilation(double factor, double easeInTime, double activeTime, double easeOutTime)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            CheckTimeDilationPriorityExists();
 | 
					            CheckTimeDilationPriorityExists();
 | 
				
			||||||
            timeManager.ActivateTimeDilation(factor, easeInTime, activeTime, easeOutTime, timeDilationPriority.Value);
 | 
					            timeManager.ActivateTimeDilation(factor, easeInTime, activeTime, easeOutTime, timeDilationPriority.Value);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// 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.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="factor">The time dilation factor, which is multiplied by real delta time.</param>
 | 
				
			||||||
 | 
					        /// <param name="easeInTime">The time that will elapse before time is fully dilated, in real time.</param>
 | 
				
			||||||
 | 
					        /// <param name="easeInFunction">An easing function for the easing in of time dilation.</param>
 | 
				
			||||||
 | 
					        /// <param name="activeTime">The length of real time that time will be fully dilated.</param>
 | 
				
			||||||
 | 
					        /// <param name="easeOutTime">The time that will elapse before time is fully undilated.</param>
 | 
				
			||||||
        public void ActivateTimeDilation(double factor, double easeInTime, System.Func<double, double, double, double, double> easeInFunction, double activeTime, double easeOutTime)
 | 
					        public void ActivateTimeDilation(double factor, double easeInTime, System.Func<double, double, double, double, double> easeInFunction, double activeTime, double easeOutTime)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            CheckTimeDilationPriorityExists();
 | 
					            CheckTimeDilationPriorityExists();
 | 
				
			||||||
            timeManager.ActivateTimeDilation(factor, easeInTime, easeInFunction, activeTime, easeOutTime, timeDilationPriority.Value);
 | 
					            timeManager.ActivateTimeDilation(factor, easeInTime, easeInFunction, activeTime, easeOutTime, timeDilationPriority.Value);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// 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.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="factor">The time dilation factor, which is multiplied by real delta time.</param>
 | 
				
			||||||
 | 
					        /// <param name="easeInTime">The time that will elapse before time is fully dilated, in real time.</param>
 | 
				
			||||||
 | 
					        /// <param name="activeTime">The length of real time that time will be fully dilated.</param>
 | 
				
			||||||
 | 
					        /// <param name="easeOutTime">The time that will elapse before time is fully undilated.</param>
 | 
				
			||||||
 | 
					        /// <param name="easeOutFunction">An easing function for the easing out of time dilation.</param>
 | 
				
			||||||
        public void ActivateTimeDilation(double factor, double easeInTime, double activeTime, double easeOutTime, System.Func<double, double, double, double, double> easeOutFunction)
 | 
					        public void ActivateTimeDilation(double factor, double easeInTime, double activeTime, double easeOutTime, System.Func<double, double, double, double, double> easeOutFunction)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            CheckTimeDilationPriorityExists();
 | 
					            CheckTimeDilationPriorityExists();
 | 
				
			||||||
            timeManager.ActivateTimeDilation(factor, easeInTime, activeTime, easeOutTime, easeOutFunction, timeDilationPriority.Value);
 | 
					            timeManager.ActivateTimeDilation(factor, easeInTime, activeTime, easeOutTime, easeOutFunction, timeDilationPriority.Value);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// 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.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="factor">The time dilation factor, which is multiplied by real delta time.</param>
 | 
				
			||||||
 | 
					        /// <param name="easeInTime">The time that will elapse before time is fully dilated, in real time.</param>
 | 
				
			||||||
 | 
					        /// <param name="easeInFunction">An easing function for the easing in of time dilation.</param>
 | 
				
			||||||
 | 
					        /// <param name="activeTime">The length of real time that time will be fully dilated.</param>
 | 
				
			||||||
 | 
					        /// <param name="easeOutTime">The time that will elapse before time is fully undilated.</param>
 | 
				
			||||||
 | 
					        /// <param name="easeOutFunction">An easing function for the easing out of time dilation.</param>
 | 
				
			||||||
        public void ActivateTimeDilation(double factor, double easeInTime, System.Func<double, double, double, double, double> easeInFunction, double activeTime, double easeOutTime, System.Func<double, double, double, double, double> easeOutFunction)
 | 
					        public void ActivateTimeDilation(double factor, double easeInTime, System.Func<double, double, double, double, double> easeInFunction, double activeTime, double easeOutTime, System.Func<double, double, double, double, double> easeOutFunction)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            CheckTimeDilationPriorityExists();
 | 
					            CheckTimeDilationPriorityExists();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,13 +6,22 @@ namespace Encompass
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    internal class MessageManager
 | 
					    internal class MessageManager
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        private TimeManager timeManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        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)>();
 | 
					        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)
 | 
					        internal void RegisterMessageType(Type messageType)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (!messageTypeToMessages.ContainsKey(messageType)) {
 | 
					            if (!messageTypeToMessages.ContainsKey(messageType))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
                messageTypeToMessages.Add(messageType, new List<IMessage>());
 | 
					                messageTypeToMessages.Add(messageType, new List<IMessage>());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -31,9 +40,11 @@ namespace Encompass
 | 
				
			||||||
            delayedMessages.Add((message, time));
 | 
					            delayedMessages.Add((message, time));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        internal void AddMessage<TMessage>(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<IMessage>()); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            delayedMessagesIgnoringTimeDilation.Add((message, time));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        internal void ClearMessages()
 | 
					        internal void ClearMessages()
 | 
				
			||||||
| 
						 | 
					@ -50,7 +61,7 @@ namespace Encompass
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var (message, time) = delayedMessages[i];
 | 
					                var (message, time) = delayedMessages[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var updatedTime = time - dt;
 | 
					                var updatedTime = time - (dt * timeManager.TimeDilationFactor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (updatedTime <= 0)
 | 
					                if (updatedTime <= 0)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
| 
						 | 
					@ -62,6 +73,23 @@ namespace Encompass
 | 
				
			||||||
                    delayedMessages[i] = (message, updatedTime);
 | 
					                    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<TMessage> GetMessagesByType<TMessage>() where TMessage : struct, IMessage
 | 
					        internal IEnumerable<TMessage> GetMessagesByType<TMessage>() where TMessage : struct, IMessage
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,11 +38,11 @@ namespace Encompass
 | 
				
			||||||
        public WorldBuilder()
 | 
					        public WorldBuilder()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            drawLayerManager = new DrawLayerManager();
 | 
					            drawLayerManager = new DrawLayerManager();
 | 
				
			||||||
 | 
					            timeManager = new TimeManager();
 | 
				
			||||||
            componentManager = new ComponentManager(drawLayerManager);
 | 
					            componentManager = new ComponentManager(drawLayerManager);
 | 
				
			||||||
            messageManager = new MessageManager();
 | 
					            messageManager = new MessageManager(timeManager);
 | 
				
			||||||
            componentMessageManager = new ComponentMessageManager();
 | 
					            componentMessageManager = new ComponentMessageManager();
 | 
				
			||||||
            entityManager = new EntityManager(componentManager, componentMessageManager);
 | 
					            entityManager = new EntityManager(componentManager, componentMessageManager);
 | 
				
			||||||
            timeManager = new TimeManager();
 | 
					 | 
				
			||||||
            renderManager = new RenderManager(componentManager, drawLayerManager, entityManager);
 | 
					            renderManager = new RenderManager(componentManager, drawLayerManager, entityManager);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -672,7 +672,7 @@ namespace Tests
 | 
				
			||||||
                foreach (var (component, entity) in ReadComponentsIncludingEntity<MockComponent>())
 | 
					                foreach (var (component, entity) in ReadComponentsIncludingEntity<MockComponent>())
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    RemoveComponent<MockComponent>(entity);
 | 
					                    RemoveComponent<MockComponent>(entity);
 | 
				
			||||||
                    SendMessageDelayed(new MockMessage { }, 1);
 | 
					                    SendMessage(new MockMessage { }, 1);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -683,6 +683,7 @@ namespace Tests
 | 
				
			||||||
            resultMessages.Clear();
 | 
					            resultMessages.Clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var worldBuilder = new WorldBuilder();
 | 
					            var worldBuilder = new WorldBuilder();
 | 
				
			||||||
 | 
					            worldBuilder.AddEngine(new ActivateTimeDilationEngine());
 | 
				
			||||||
            worldBuilder.AddEngine(new DelayedMessageEngine());
 | 
					            worldBuilder.AddEngine(new DelayedMessageEngine());
 | 
				
			||||||
            worldBuilder.AddEngine(new MessageReadEngine());
 | 
					            worldBuilder.AddEngine(new MessageReadEngine());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -701,6 +702,52 @@ namespace Tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            world.Update(0.5);
 | 
					            world.Update(0.5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            resultMessages.Should().BeEmpty();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            world.Update(2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            resultMessages.Should().NotBeEmpty();
 | 
				
			||||||
 | 
					            resultMessages.First().Should().BeOfType<MockMessage>();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Reads(typeof(MockComponent))]
 | 
				
			||||||
 | 
					        class DelayedMessageIgnoringTimeDilationEngine : Engine
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            public override void Update(double dt)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                foreach (var (component, entity) in ReadComponentsIncludingEntity<MockComponent>())
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    RemoveComponent<MockComponent>(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.Should().NotBeEmpty();
 | 
				
			||||||
            resultMessages.First().Should().BeOfType<MockMessage>();
 | 
					            resultMessages.First().Should().BeOfType<MockMessage>();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue