read new and existing component system
							parent
							
								
									80effc06dc
								
							
						
					
					
						commit
						1845d5f766
					
				| 
						 | 
				
			
			@ -19,7 +19,7 @@ namespace Encompass
 | 
			
		|||
                    throw new IllegalActivateTypeException("{0} must be a Component", activateType.Name);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                this.activateTypes.Add(typeof(ComponentMessage<>).MakeGenericType(activateType));
 | 
			
		||||
                this.activateTypes.Add(typeof(NewComponentMessage<>).MakeGenericType(activateType));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,23 +14,15 @@ namespace Encompass
 | 
			
		|||
        {
 | 
			
		||||
            foreach (var readType in readTypes)
 | 
			
		||||
            {
 | 
			
		||||
                var isMessage = readType.GetInterfaces().Contains(typeof(IMessage));
 | 
			
		||||
                var isComponent = readType.GetInterfaces().Contains(typeof(IComponent));
 | 
			
		||||
 | 
			
		||||
                if (!isMessage && !isComponent)
 | 
			
		||||
                if (!isComponent)
 | 
			
		||||
                {
 | 
			
		||||
                    throw new IllegalReadTypeException("{0} must be a Message or Component", readType.Name);
 | 
			
		||||
                    throw new IllegalReadTypeException("{0} must be a Component", readType.Name);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (isComponent)
 | 
			
		||||
                {
 | 
			
		||||
                this.readTypes.Add(typeof(ComponentMessage<>).MakeGenericType(readType));
 | 
			
		||||
            }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    this.readTypes.Add(readType);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using Encompass.Exceptions;
 | 
			
		||||
 | 
			
		||||
namespace Encompass
 | 
			
		||||
{
 | 
			
		||||
    [AttributeUsage(AttributeTargets.Class)]
 | 
			
		||||
    public class ReadsNew : Attribute
 | 
			
		||||
    {
 | 
			
		||||
        public readonly HashSet<Type> newComponentReadTypes = new HashSet<Type>();
 | 
			
		||||
 | 
			
		||||
        public ReadsNew(params Type[] readTypes)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (var readType in readTypes)
 | 
			
		||||
            {
 | 
			
		||||
                var isComponent = readType.GetInterfaces().Contains(typeof(IComponent));
 | 
			
		||||
 | 
			
		||||
                if (!isComponent)
 | 
			
		||||
                {
 | 
			
		||||
                    throw new IllegalReadTypeException("{0} must be a Component", readType.Name);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                this.newComponentReadTypes.Add(typeof(ComponentMessage<>).MakeGenericType(readType));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using Encompass.Exceptions;
 | 
			
		||||
 | 
			
		||||
namespace Encompass
 | 
			
		||||
{
 | 
			
		||||
    [AttributeUsage(AttributeTargets.Class)]
 | 
			
		||||
    public class Receives : Attribute
 | 
			
		||||
    {
 | 
			
		||||
        public readonly HashSet<Type> receiveTypes;
 | 
			
		||||
 | 
			
		||||
        public Receives(params Type[] receiveTypes)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (var receiveType in receiveTypes)
 | 
			
		||||
            {
 | 
			
		||||
                var isMessage = receiveType.GetInterfaces().Contains(typeof(IMessage));
 | 
			
		||||
                if (!isMessage)
 | 
			
		||||
                {
 | 
			
		||||
                    throw new IllegalSendTypeException("{0} must be a Message", receiveType.Name);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.receiveTypes = new HashSet<Type>(receiveTypes);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -17,7 +17,7 @@ namespace Encompass
 | 
			
		|||
                var isMessage = sendType.GetInterfaces().Contains(typeof(IMessage));
 | 
			
		||||
                if (!isMessage)
 | 
			
		||||
                {
 | 
			
		||||
                    throw new IllegalWriteTypeException("{0} must be a Message", sendType.Name);
 | 
			
		||||
                    throw new IllegalSendTypeException("{0} must be a Message", sendType.Name);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,8 +9,7 @@ namespace Encompass
 | 
			
		|||
    public abstract class Engine
 | 
			
		||||
    {
 | 
			
		||||
        internal readonly HashSet<Type> sendTypes = new HashSet<Type>();
 | 
			
		||||
        internal readonly HashSet<Type> readTypes = new HashSet<Type>();
 | 
			
		||||
        internal readonly HashSet<Type> activateTypes = new HashSet<Type>();
 | 
			
		||||
        internal readonly HashSet<Type> receiveTypes = new HashSet<Type>();
 | 
			
		||||
        internal readonly HashSet<Type> updateTypes = new HashSet<Type>();
 | 
			
		||||
 | 
			
		||||
        private EntityManager entityManager;
 | 
			
		||||
| 
						 | 
				
			
			@ -19,22 +18,34 @@ namespace Encompass
 | 
			
		|||
 | 
			
		||||
        protected Engine()
 | 
			
		||||
        {
 | 
			
		||||
            var writesAttribute = GetType().GetCustomAttribute<Sends>(false);
 | 
			
		||||
            if (writesAttribute != null)
 | 
			
		||||
            var sendsAttribute = GetType().GetCustomAttribute<Sends>(false);
 | 
			
		||||
            if (sendsAttribute != null)
 | 
			
		||||
            {
 | 
			
		||||
                sendTypes = writesAttribute.sendTypes;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var readsAttribute = GetType().GetCustomAttribute<Reads>(false);
 | 
			
		||||
            if (readsAttribute != null)
 | 
			
		||||
            {
 | 
			
		||||
                readTypes = readsAttribute.readTypes;
 | 
			
		||||
                sendTypes = sendsAttribute.sendTypes;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var activatesAttribute = GetType().GetCustomAttribute<Activates>(false);
 | 
			
		||||
            if (activatesAttribute != null)
 | 
			
		||||
            {
 | 
			
		||||
                activateTypes = activatesAttribute.activateTypes;
 | 
			
		||||
                sendTypes.UnionWith(activatesAttribute.activateTypes);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var receivesAttribute = GetType().GetCustomAttribute<Receives>(false);
 | 
			
		||||
            if (receivesAttribute != null)
 | 
			
		||||
            {
 | 
			
		||||
                receiveTypes = receivesAttribute.receiveTypes;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var readsAttribute = GetType().GetCustomAttribute<Reads>(false);
 | 
			
		||||
            if (readsAttribute != null)
 | 
			
		||||
            {
 | 
			
		||||
                receiveTypes.UnionWith(readsAttribute.readTypes);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var readsNewAttribute = GetType().GetCustomAttribute<ReadsNew>(false);
 | 
			
		||||
            if (readsNewAttribute != null)
 | 
			
		||||
            {
 | 
			
		||||
                receiveTypes.UnionWith(readsNewAttribute.newComponentReadTypes);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var updatesAttribute = GetType().GetCustomAttribute<Updates>(false);
 | 
			
		||||
| 
						 | 
				
			
			@ -107,14 +118,14 @@ namespace Encompass
 | 
			
		|||
 | 
			
		||||
        protected Guid AddComponent<TComponent>(Entity entity, TComponent component) where TComponent : struct, IComponent
 | 
			
		||||
        {
 | 
			
		||||
            if (!activateTypes.Contains(typeof(ComponentMessage<TComponent>)))
 | 
			
		||||
            if (!sendTypes.Contains(typeof(NewComponentMessage<TComponent>)))
 | 
			
		||||
            {
 | 
			
		||||
                throw new IllegalActivateException("Engine {0} tried to activate undeclared Component {1}", GetType().Name, typeof(TComponent).Name);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var componentID = componentManager.AddComponent(entity.ID, component);
 | 
			
		||||
 | 
			
		||||
            ComponentMessage<TComponent> componentMessage;
 | 
			
		||||
            NewComponentMessage<TComponent> componentMessage;
 | 
			
		||||
            componentMessage.entity = entity;
 | 
			
		||||
            componentMessage.componentID = componentID;
 | 
			
		||||
            componentMessage.component = component;
 | 
			
		||||
| 
						 | 
				
			
			@ -125,25 +136,25 @@ namespace Encompass
 | 
			
		|||
 | 
			
		||||
        protected Guid AddDrawComponent<TComponent>(Entity entity, TComponent component, int layer = 0) where TComponent : struct, IComponent
 | 
			
		||||
        {
 | 
			
		||||
            if (!activateTypes.Contains(typeof(ComponentMessage<TComponent>)))
 | 
			
		||||
            if (!sendTypes.Contains(typeof(NewComponentMessage<TComponent>)))
 | 
			
		||||
            {
 | 
			
		||||
                throw new IllegalActivateException("Engine {0} tried to activate undeclared Component {1}", GetType().Name, typeof(TComponent).Name);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var componentID = componentManager.AddDrawComponent(entity.ID, component, layer);
 | 
			
		||||
 | 
			
		||||
            ComponentMessage<TComponent> componentMessage;
 | 
			
		||||
            componentMessage.entity = entity;
 | 
			
		||||
            componentMessage.componentID = componentID;
 | 
			
		||||
            componentMessage.component = component;
 | 
			
		||||
            SendMessage(componentMessage);
 | 
			
		||||
            NewComponentMessage<TComponent> newComponentMessage;
 | 
			
		||||
            newComponentMessage.entity = entity;
 | 
			
		||||
            newComponentMessage.componentID = componentID;
 | 
			
		||||
            newComponentMessage.component = component;
 | 
			
		||||
            SendMessage(newComponentMessage);
 | 
			
		||||
 | 
			
		||||
            return componentID;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected void ActivateComponent<TComponent>(Guid componentID) where TComponent : struct, IComponent
 | 
			
		||||
        {
 | 
			
		||||
            if (!activateTypes.Contains(typeof(ComponentMessage<TComponent>)))
 | 
			
		||||
            if (!sendTypes.Contains(typeof(NewComponentMessage<TComponent>)))
 | 
			
		||||
            {
 | 
			
		||||
                throw new IllegalActivateException("Engine {0} tried to activate undeclared Component {1}", GetType().Name, typeof(TComponent).Name);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -151,13 +162,13 @@ namespace Encompass
 | 
			
		|||
            var entity = GetEntity(componentManager.GetEntityIDByComponentID(componentID));
 | 
			
		||||
            var component = GetComponentByID<TComponent>(componentID);
 | 
			
		||||
 | 
			
		||||
            ComponentMessage<TComponent> componentMessage;
 | 
			
		||||
            componentMessage.entity = entity;
 | 
			
		||||
            componentMessage.componentID = componentID;
 | 
			
		||||
            componentMessage.component = component;
 | 
			
		||||
            SendMessage(componentMessage);
 | 
			
		||||
            NewComponentMessage<TComponent> newComponentMessage;
 | 
			
		||||
            newComponentMessage.entity = entity;
 | 
			
		||||
            newComponentMessage.componentID = componentID;
 | 
			
		||||
            newComponentMessage.component = component;
 | 
			
		||||
            SendMessage(newComponentMessage);
 | 
			
		||||
 | 
			
		||||
            componentManager.Activate(componentID);
 | 
			
		||||
            componentManager.Activate(componentID); // TODO: actually delay this to end of frame, make sure to update after activate
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected void DeactivateComponent(Guid componentID)
 | 
			
		||||
| 
						 | 
				
			
			@ -165,9 +176,9 @@ namespace Encompass
 | 
			
		|||
            componentManager.MarkForDeactivation(componentID);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected IEnumerable<ValueTuple<Guid, TComponent>> GetComponents<TComponent>(Entity entity) where TComponent : struct, IComponent
 | 
			
		||||
        private IEnumerable<ValueTuple<Guid, TComponent>> ExistingComponentsOnEntity<TComponent>(Entity entity) where TComponent : struct, IComponent
 | 
			
		||||
        {
 | 
			
		||||
            if (!readTypes.Contains(typeof(ComponentMessage<TComponent>)))
 | 
			
		||||
            if (!receiveTypes.Contains(typeof(ComponentMessage<TComponent>)))
 | 
			
		||||
            {
 | 
			
		||||
                throw new IllegalReadException("Engine {0} tried to read undeclared Component {1}", GetType().Name, typeof(TComponent).Name);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -175,6 +186,26 @@ namespace Encompass
 | 
			
		|||
            return ReadMessages<ComponentMessage<TComponent>>().Where((message) => message.entity == entity).Select((message) => (message.componentID, message.component));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private IEnumerable<ValueTuple<Guid, TComponent>> NewComponentsOnEntity<TComponent>(Entity entity) where TComponent : struct, IComponent
 | 
			
		||||
        {
 | 
			
		||||
            if (!receiveTypes.Contains(typeof(NewComponentMessage<TComponent>)))
 | 
			
		||||
            {
 | 
			
		||||
                throw new IllegalReadException("Engine {0} tried to read undeclared new Component {1}", GetType().Name, typeof(TComponent).Name);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return ReadMessages<NewComponentMessage<TComponent>>().Where((message) => message.entity == entity).Select((message) => (message.componentID, message.component));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected IEnumerable<ValueTuple<Guid, TComponent>> GetComponentsIncludingNew<TComponent>(Entity entity) where TComponent : struct, IComponent
 | 
			
		||||
        {
 | 
			
		||||
            return ExistingComponentsOnEntity<TComponent>(entity).Union(NewComponentsOnEntity<TComponent>(entity));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected IEnumerable<ValueTuple<Guid, TComponent>> GetComponents<TComponent>(Entity entity) where TComponent : struct, IComponent
 | 
			
		||||
        {
 | 
			
		||||
            return ExistingComponentsOnEntity<TComponent>(entity);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected ValueTuple<Guid, TComponent> GetComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
 | 
			
		||||
        {
 | 
			
		||||
            return GetComponents<TComponent>(entity).First();
 | 
			
		||||
| 
						 | 
				
			
			@ -182,19 +213,14 @@ namespace Encompass
 | 
			
		|||
 | 
			
		||||
        protected bool HasComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
 | 
			
		||||
        {
 | 
			
		||||
            if (!readTypes.Contains(typeof(ComponentMessage<TComponent>)))
 | 
			
		||||
            {
 | 
			
		||||
                throw new IllegalReadException("Engine {0} tried to read undeclared Component {1}", GetType().Name, typeof(TComponent).Name);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return ReadMessages<ComponentMessage<TComponent>>().Where((message) => message.entity == entity).Any();
 | 
			
		||||
            return GetComponents<TComponent>(entity).Any();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal void UpdateComponentInWorld<TComponent>(Guid componentID, TComponent newComponent) where TComponent : struct, IComponent
 | 
			
		||||
        {
 | 
			
		||||
            if (!updateTypes.Contains(typeof(TComponent)))
 | 
			
		||||
            {
 | 
			
		||||
                throw new IllegalWriteException("Engine {0} tried to write undeclared Component {1}", this.GetType().Name, typeof(TComponent).Name);
 | 
			
		||||
                throw new IllegalSendException("Engine {0} tried to write undeclared Component {1}", this.GetType().Name, typeof(TComponent).Name);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            componentManager.AddUpdateComponentOperation(componentID, newComponent);
 | 
			
		||||
| 
						 | 
				
			
			@ -209,7 +235,7 @@ namespace Encompass
 | 
			
		|||
        {
 | 
			
		||||
            if (!sendTypes.Contains(typeof(TMessage)))
 | 
			
		||||
            {
 | 
			
		||||
                throw new IllegalWriteException("Engine {0} tried to write undeclared Message {1}", this.GetType().Name, typeof(TMessage).Name);
 | 
			
		||||
                throw new IllegalSendException("Engine {0} tried to write undeclared Message {1}", this.GetType().Name, typeof(TMessage).Name);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            messageManager.AddMessage(message);
 | 
			
		||||
| 
						 | 
				
			
			@ -217,7 +243,7 @@ namespace Encompass
 | 
			
		|||
 | 
			
		||||
        protected IEnumerable<TMessage> ReadMessages<TMessage>() where TMessage : struct, IMessage
 | 
			
		||||
        {
 | 
			
		||||
            if (!readTypes.Contains(typeof(TMessage)))
 | 
			
		||||
            if (!receiveTypes.Contains(typeof(TMessage)))
 | 
			
		||||
            {
 | 
			
		||||
                throw new IllegalReadException("Engine {0} tried to read undeclared Message {1}", this.GetType().Name, typeof(TMessage).Name);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -230,9 +256,9 @@ namespace Encompass
 | 
			
		|||
            return ReadMessages<TMessage>().Single();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected IEnumerable<(Guid, TComponent)> ReadComponents<TComponent>() where TComponent : struct, IComponent
 | 
			
		||||
        protected IEnumerable<ValueTuple<Guid, TComponent>> ReadComponents<TComponent>() where TComponent : struct, IComponent
 | 
			
		||||
        {
 | 
			
		||||
            if (!readTypes.Contains(typeof(ComponentMessage<TComponent>)))
 | 
			
		||||
            if (!receiveTypes.Contains(typeof(ComponentMessage<TComponent>)))
 | 
			
		||||
            {
 | 
			
		||||
                throw new IllegalReadException("Engine {0} tried to read undeclared Component {1}", this.GetType().Name, typeof(TComponent).Name);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -240,14 +266,14 @@ namespace Encompass
 | 
			
		|||
            return ReadMessages<ComponentMessage<TComponent>>().Select((message) => (message.componentID, message.component));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected (Guid, TComponent) ReadComponent<TComponent>() where TComponent : struct, IComponent
 | 
			
		||||
        protected ValueTuple<Guid, TComponent> ReadComponent<TComponent>() where TComponent : struct, IComponent
 | 
			
		||||
        {
 | 
			
		||||
            return ReadComponents<TComponent>().Single();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected bool SomeMessage<TMessage>() where TMessage : struct, IMessage
 | 
			
		||||
        {
 | 
			
		||||
            if (!readTypes.Contains(typeof(TMessage)))
 | 
			
		||||
            if (!receiveTypes.Contains(typeof(TMessage)))
 | 
			
		||||
            {
 | 
			
		||||
                throw new IllegalReadException("Engine {0} tried to read undeclared Message {1}", GetType().Name, typeof(TMessage).Name);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -257,7 +283,7 @@ namespace Encompass
 | 
			
		|||
 | 
			
		||||
        protected bool SomeComponent<TComponent>() where TComponent : struct, IComponent
 | 
			
		||||
        {
 | 
			
		||||
            if (!readTypes.Contains(typeof(ComponentMessage<TComponent>)))
 | 
			
		||||
            if (!receiveTypes.Contains(typeof(ComponentMessage<TComponent>)))
 | 
			
		||||
            {
 | 
			
		||||
                throw new IllegalReadException("Engine {0} tried to read undeclared Component {1}", GetType().Name, typeof(TComponent).Name);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,12 +6,6 @@ namespace Encompass.Engines
 | 
			
		|||
    {
 | 
			
		||||
        public ComponentMessageEmitter() : base()
 | 
			
		||||
        {
 | 
			
		||||
            var writesAttribute = GetType().GetCustomAttribute<Sends>(false);
 | 
			
		||||
            if (writesAttribute != null)
 | 
			
		||||
            {
 | 
			
		||||
                writesAttribute.sendTypes.Add(typeof(ComponentMessage<TComponent>));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            sendTypes.Add(typeof(ComponentMessage<TComponent>));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
namespace Encompass.Engines
 | 
			
		||||
{
 | 
			
		||||
    internal class NewComponentMessageEmitter<TComponent> : Engine where TComponent : struct, IComponent
 | 
			
		||||
    {
 | 
			
		||||
        public NewComponentMessageEmitter() : base()
 | 
			
		||||
        {
 | 
			
		||||
            sendTypes.Add(typeof(NewComponentMessage<TComponent>));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void Update(double dt)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (var (entity, componentID, component) in ReadComponentsFromWorld<TComponent>())
 | 
			
		||||
            {
 | 
			
		||||
                NewComponentMessage<TComponent> newComponentMessage;
 | 
			
		||||
                newComponentMessage.entity = entity;
 | 
			
		||||
                newComponentMessage.componentID = componentID;
 | 
			
		||||
                newComponentMessage.component = component;
 | 
			
		||||
                SendMessage(newComponentMessage);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -12,7 +12,7 @@ namespace Encompass.Engines
 | 
			
		|||
                readsAttribute.readTypes.Add(typeof(TMessage));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            readTypes.Add(typeof(TMessage));
 | 
			
		||||
            receiveTypes.Add(typeof(TMessage));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void Update(double dt)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,9 +2,9 @@ using System;
 | 
			
		|||
 | 
			
		||||
namespace Encompass.Exceptions
 | 
			
		||||
{
 | 
			
		||||
    public class IllegalWriteException : Exception
 | 
			
		||||
    public class IllegalSendException : Exception
 | 
			
		||||
    {
 | 
			
		||||
        public IllegalWriteException(
 | 
			
		||||
        public IllegalSendException(
 | 
			
		||||
            string format,
 | 
			
		||||
            params object[] args
 | 
			
		||||
        ) : base(string.Format(format, args)) { }
 | 
			
		||||
| 
						 | 
				
			
			@ -2,9 +2,9 @@ using System;
 | 
			
		|||
 | 
			
		||||
namespace Encompass.Exceptions
 | 
			
		||||
{
 | 
			
		||||
    public class IllegalWriteTypeException : Exception
 | 
			
		||||
    public class IllegalSendTypeException : Exception
 | 
			
		||||
    {
 | 
			
		||||
        public IllegalWriteTypeException(
 | 
			
		||||
        public IllegalSendTypeException(
 | 
			
		||||
            string format,
 | 
			
		||||
            params object[] args
 | 
			
		||||
        ) : base(string.Format(format, args)) { }
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
using System;
 | 
			
		||||
 | 
			
		||||
namespace Encompass
 | 
			
		||||
{
 | 
			
		||||
    public struct NewComponentMessage<TComponent> : IMessage where TComponent : struct, IComponent
 | 
			
		||||
    {
 | 
			
		||||
        public Entity entity;
 | 
			
		||||
        public Guid componentID;
 | 
			
		||||
        public TComponent component;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -23,6 +23,7 @@ namespace Encompass
 | 
			
		|||
        private readonly HashSet<Engine> senders = new HashSet<Engine>();
 | 
			
		||||
 | 
			
		||||
        private readonly HashSet<Type> registeredComponentTypes = new HashSet<Type>();
 | 
			
		||||
        private readonly HashSet<Type> registeredNewComponentTypes = new HashSet<Type>();
 | 
			
		||||
 | 
			
		||||
        public WorldBuilder()
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -66,6 +67,12 @@ namespace Encompass
 | 
			
		|||
            AddEngine((Engine)Activator.CreateInstance(typeof(ComponentMessageEmitter<>).MakeGenericType(componentType)));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal void RegisterNewComponentEmitter(Type componentType)
 | 
			
		||||
        {
 | 
			
		||||
            registeredNewComponentTypes.Add(componentType);
 | 
			
		||||
            AddEngine((Engine)Activator.CreateInstance(typeof(NewComponentMessageEmitter<>).MakeGenericType(componentType)));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Engine AddEngine<TEngine>(TEngine engine) where TEngine : Engine
 | 
			
		||||
        {
 | 
			
		||||
            engine.AssignEntityManager(entityManager);
 | 
			
		||||
| 
						 | 
				
			
			@ -75,15 +82,10 @@ namespace Encompass
 | 
			
		|||
            engines.Add(engine);
 | 
			
		||||
            engineGraph.AddVertex(engine);
 | 
			
		||||
 | 
			
		||||
            foreach (var activateType in engine.activateTypes)
 | 
			
		||||
            {
 | 
			
		||||
                engine.sendTypes.Add(activateType);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var messageReadTypes = engine.readTypes;
 | 
			
		||||
            var messageReceiveTypes = engine.receiveTypes;
 | 
			
		||||
            var messageSendTypes = engine.sendTypes;
 | 
			
		||||
 | 
			
		||||
            foreach (var messageType in messageReadTypes.Intersect(messageSendTypes))
 | 
			
		||||
            foreach (var messageType in messageReceiveTypes.Intersect(messageSendTypes))
 | 
			
		||||
            {
 | 
			
		||||
                // ComponentMessages can safely self-cycle
 | 
			
		||||
                // this does introduce a gotcha though: if you AddComponent and then HasComponent or GetComponent you will receive a false negative
 | 
			
		||||
| 
						 | 
				
			
			@ -99,23 +101,43 @@ namespace Encompass
 | 
			
		|||
                senders.Add(engine);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach (var readType in engine.readTypes)
 | 
			
		||||
            foreach (var receiveType in engine.receiveTypes)
 | 
			
		||||
            {
 | 
			
		||||
                if (readType.IsGenericType && readType.GetGenericTypeDefinition() == typeof(ComponentMessage<>))
 | 
			
		||||
                if (receiveType.IsGenericType)
 | 
			
		||||
                {
 | 
			
		||||
                    var componentType = readType.GetGenericArguments().Single();
 | 
			
		||||
                    var genericTypeDefinition = receiveType.GetGenericTypeDefinition();
 | 
			
		||||
                    if (genericTypeDefinition == typeof(ComponentMessage<>) || genericTypeDefinition == typeof(NewComponentMessage<>))
 | 
			
		||||
                    {
 | 
			
		||||
                        var componentType = receiveType.GetGenericArguments().Single();
 | 
			
		||||
                        if (!registeredComponentTypes.Contains(componentType))
 | 
			
		||||
                        {
 | 
			
		||||
                            RegisterComponent(componentType);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                if (!typeToReaders.ContainsKey(readType))
 | 
			
		||||
                {
 | 
			
		||||
                    typeToReaders.Add(readType, new HashSet<Engine>());
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                typeToReaders[readType].Add(engine);
 | 
			
		||||
                if (!typeToReaders.ContainsKey(receiveType))
 | 
			
		||||
                {
 | 
			
		||||
                    typeToReaders.Add(receiveType, new HashSet<Engine>());
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                typeToReaders[receiveType].Add(engine);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach (var sendType in engine.sendTypes)
 | 
			
		||||
            {
 | 
			
		||||
                if (sendType.IsGenericType)
 | 
			
		||||
                {
 | 
			
		||||
                    var genericTypeDefinition = sendType.GetGenericTypeDefinition();
 | 
			
		||||
                    if (genericTypeDefinition == typeof(ComponentMessage<>) || genericTypeDefinition == typeof(NewComponentMessage<>))
 | 
			
		||||
                    {
 | 
			
		||||
                        var componentType = sendType.GetGenericArguments().Single();
 | 
			
		||||
                        if (!registeredNewComponentTypes.Contains(componentType))
 | 
			
		||||
                        {
 | 
			
		||||
                            RegisterNewComponentEmitter(componentType);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return engine;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,7 +24,8 @@ namespace Tests
 | 
			
		|||
        static IEnumerable<(Guid, MockComponent)> gottenMockComponentIDPairs = Enumerable.Empty<(Guid, MockComponent)>();
 | 
			
		||||
        static (Guid, MockComponent) gottenMockComponentIDPair;
 | 
			
		||||
 | 
			
		||||
        [Reads(typeof(EntityMessage), typeof(MockComponent))]
 | 
			
		||||
        [Receives(typeof(EntityMessage))]
 | 
			
		||||
        [Reads(typeof(MockComponent))]
 | 
			
		||||
        class GetMockComponentEngine : Engine
 | 
			
		||||
        {
 | 
			
		||||
            public override void Update(double dt)
 | 
			
		||||
| 
						 | 
				
			
			@ -42,7 +43,8 @@ namespace Tests
 | 
			
		|||
            public MockComponent mockComponent;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Reads(typeof(AddComponentTestMessage), typeof(MockComponent))]
 | 
			
		||||
        [Receives(typeof(AddComponentTestMessage))]
 | 
			
		||||
        [Reads(typeof(MockComponent))]
 | 
			
		||||
        class AddComponentTestEngine : Engine
 | 
			
		||||
        {
 | 
			
		||||
            public override void Update(double dt)
 | 
			
		||||
| 
						 | 
				
			
			@ -109,7 +111,7 @@ namespace Tests
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        [Activates(typeof(MockComponent))]
 | 
			
		||||
        [Reads(typeof(AddMockComponentMessage))]
 | 
			
		||||
        [Receives(typeof(AddMockComponentMessage))]
 | 
			
		||||
        class AddMockComponentEngine : Engine
 | 
			
		||||
        {
 | 
			
		||||
            public override void Update(double dt)
 | 
			
		||||
| 
						 | 
				
			
			@ -152,7 +154,8 @@ namespace Tests
 | 
			
		|||
            world.Update(0.01);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Reads(typeof(EntityMessage), typeof(MockComponent))]
 | 
			
		||||
        [Receives(typeof(EntityMessage))]
 | 
			
		||||
        [Reads(typeof(MockComponent))]
 | 
			
		||||
        class GetMockComponentsEngine : Engine
 | 
			
		||||
        {
 | 
			
		||||
            private Entity entity;
 | 
			
		||||
| 
						 | 
				
			
			@ -264,7 +267,8 @@ namespace Tests
 | 
			
		|||
            public Entity entity;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Reads(typeof(HasComponentTestMessage), typeof(MockComponent))]
 | 
			
		||||
        [Receives(typeof(HasComponentTestMessage))]
 | 
			
		||||
        [Reads(typeof(MockComponent))]
 | 
			
		||||
        class HasComponentTestEngine : Engine
 | 
			
		||||
        {
 | 
			
		||||
            public override void Update(double dt)
 | 
			
		||||
| 
						 | 
				
			
			@ -304,7 +308,8 @@ namespace Tests
 | 
			
		|||
            public Entity entity;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Reads(typeof(HasComponentWhenInactiveTestMessage), typeof(MockComponent))]
 | 
			
		||||
        [Receives(typeof(HasComponentWhenInactiveTestMessage))]
 | 
			
		||||
        [Reads(typeof(MockComponent))]
 | 
			
		||||
        class HasComponentWhenInactiveTestEngine : Engine
 | 
			
		||||
        {
 | 
			
		||||
            public override void Update(double dt)
 | 
			
		||||
| 
						 | 
				
			
			@ -346,7 +351,7 @@ namespace Tests
 | 
			
		|||
            public Guid componentID;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Reads(typeof(RemoveComponentTestMessage))]
 | 
			
		||||
        [Receives(typeof(RemoveComponentTestMessage))]
 | 
			
		||||
        class RemoveComponentTestEngine : Engine
 | 
			
		||||
        {
 | 
			
		||||
            public override void Update(double dt)
 | 
			
		||||
| 
						 | 
				
			
			@ -358,7 +363,7 @@ namespace Tests
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Reads(typeof(RemoveComponentTestMessage))]
 | 
			
		||||
        [Receives(typeof(RemoveComponentTestMessage))]
 | 
			
		||||
        [Sends(typeof(CheckHasMockComponentMessage))]
 | 
			
		||||
        class DoRemoveCheckEngine : Engine
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -421,7 +426,7 @@ namespace Tests
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        [Activates(typeof(MockComponent))]
 | 
			
		||||
        [Reads(typeof(ActivateComponentMessage))]
 | 
			
		||||
        [Receives(typeof(ActivateComponentMessage))]
 | 
			
		||||
        class ActivateComponentEngine : Engine
 | 
			
		||||
        {
 | 
			
		||||
            public override void Update(double dt)
 | 
			
		||||
| 
						 | 
				
			
			@ -439,7 +444,7 @@ namespace Tests
 | 
			
		|||
            public bool shouldHaveComponent;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Reads(typeof(ActivateComponentMessage))]
 | 
			
		||||
        [Receives(typeof(ActivateComponentMessage))]
 | 
			
		||||
        [Sends(typeof(CheckHasMockComponentMessage))]
 | 
			
		||||
        class DoActivateCheckEngine : Engine
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -462,7 +467,8 @@ namespace Tests
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Reads(typeof(CheckHasMockComponentMessage), typeof(MockComponent))]
 | 
			
		||||
        [Receives(typeof(CheckHasMockComponentMessage))]
 | 
			
		||||
        [Reads(typeof(MockComponent))]
 | 
			
		||||
        class CheckHasMockComponentEngine : Engine
 | 
			
		||||
        {
 | 
			
		||||
            public override void Update(double dt)
 | 
			
		||||
| 
						 | 
				
			
			@ -508,7 +514,7 @@ namespace Tests
 | 
			
		|||
            public Guid componentID;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Reads(typeof(DeactivateComponentMessage))]
 | 
			
		||||
        [Receives(typeof(DeactivateComponentMessage))]
 | 
			
		||||
        class DeactivateComponentEngine : Engine
 | 
			
		||||
        {
 | 
			
		||||
            public override void Update(double dt)
 | 
			
		||||
| 
						 | 
				
			
			@ -520,7 +526,7 @@ namespace Tests
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Reads(typeof(DeactivateComponentMessage))]
 | 
			
		||||
        [Receives(typeof(DeactivateComponentMessage))]
 | 
			
		||||
        [Sends(typeof(CheckHasMockComponentMessage))]
 | 
			
		||||
        class DoDeactivateCheckEngine : Engine
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -191,7 +191,7 @@ namespace Tests
 | 
			
		|||
 | 
			
		||||
            var world = worldBuilder.Build();
 | 
			
		||||
 | 
			
		||||
            var ex = Assert.Throws<IllegalWriteException>(() => world.Update(0.01f));
 | 
			
		||||
            var ex = Assert.Throws<IllegalSendException>(() => world.Update(0.01f));
 | 
			
		||||
            Assert.That(ex.Message, Is.EqualTo("Engine UndeclaredUpdateComponentTestEngine tried to write undeclared Component MockComponent"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -212,7 +212,7 @@ namespace Tests
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Reads(typeof(MockMessage))]
 | 
			
		||||
        [Receives(typeof(MockMessage))]
 | 
			
		||||
        public class MessageReadEngine : Engine
 | 
			
		||||
        {
 | 
			
		||||
            public override void Update(double dt)
 | 
			
		||||
| 
						 | 
				
			
			@ -248,7 +248,7 @@ namespace Tests
 | 
			
		|||
 | 
			
		||||
        static IEnumerable<MockMessage> emptyReadMessagesResult;
 | 
			
		||||
 | 
			
		||||
        [Reads(typeof(MockMessage))]
 | 
			
		||||
        [Receives(typeof(MockMessage))]
 | 
			
		||||
        class ReadMessagesWhenNoneExistEngine : Engine
 | 
			
		||||
        {
 | 
			
		||||
            public override void Update(double dt)
 | 
			
		||||
| 
						 | 
				
			
			@ -278,7 +278,7 @@ namespace Tests
 | 
			
		|||
 | 
			
		||||
            var world = worldBuilder.Build();
 | 
			
		||||
 | 
			
		||||
            var ex = Assert.Throws<IllegalWriteException>(() => world.Update(0.01f));
 | 
			
		||||
            var ex = Assert.Throws<IllegalSendException>(() => world.Update(0.01f));
 | 
			
		||||
            Assert.That(ex.Message, Is.EqualTo("Engine UndeclaredMessageEmitEngine tried to write undeclared Message MockMessage"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -296,7 +296,7 @@ namespace Tests
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Reads(typeof(MockMessage))]
 | 
			
		||||
        [Receives(typeof(MockMessage))]
 | 
			
		||||
        class SomeMessageTestEngine : Engine
 | 
			
		||||
        {
 | 
			
		||||
            public override void Update(double dt)
 | 
			
		||||
| 
						 | 
				
			
			@ -666,7 +666,7 @@ namespace Tests
 | 
			
		|||
            public MockComponent mockComponent;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Reads(typeof(MockComponentUpdateMessage))]
 | 
			
		||||
        [Receives(typeof(MockComponentUpdateMessage))]
 | 
			
		||||
        [Updates(typeof(MockComponent))]
 | 
			
		||||
        class RepeatUpdateEngine : Engine
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,7 +13,7 @@ namespace Tests
 | 
			
		|||
            struct AMessage : IMessage { }
 | 
			
		||||
            struct BMessage : IMessage { }
 | 
			
		||||
 | 
			
		||||
            [Reads(typeof(AMessage))]
 | 
			
		||||
            [Receives(typeof(AMessage))]
 | 
			
		||||
            [Sends(typeof(BMessage))]
 | 
			
		||||
            class AEngine : Engine
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -24,7 +24,7 @@ namespace Tests
 | 
			
		|||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [Reads(typeof(BMessage))]
 | 
			
		||||
            [Receives(typeof(BMessage))]
 | 
			
		||||
            [Sends(typeof(AMessage))]
 | 
			
		||||
            class BEngine : Engine
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -53,7 +53,7 @@ namespace Tests
 | 
			
		|||
            struct CMessage : IMessage { }
 | 
			
		||||
            struct DMessage : IMessage { }
 | 
			
		||||
 | 
			
		||||
            [Reads(typeof(AMessage))]
 | 
			
		||||
            [Receives(typeof(AMessage))]
 | 
			
		||||
            [Sends(typeof(BMessage))]
 | 
			
		||||
            class AEngine : Engine
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -64,7 +64,7 @@ namespace Tests
 | 
			
		|||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [Reads(typeof(BMessage))]
 | 
			
		||||
            [Receives(typeof(BMessage))]
 | 
			
		||||
            [Sends(typeof(CMessage))]
 | 
			
		||||
            class BEngine : Engine
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -75,7 +75,7 @@ namespace Tests
 | 
			
		|||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [Reads(typeof(CMessage))]
 | 
			
		||||
            [Receives(typeof(CMessage))]
 | 
			
		||||
            [Sends(typeof(DMessage))]
 | 
			
		||||
            class CEngine : Engine
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -86,7 +86,7 @@ namespace Tests
 | 
			
		|||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [Reads(typeof(DMessage))]
 | 
			
		||||
            [Receives(typeof(DMessage))]
 | 
			
		||||
            [Sends(typeof(AMessage))]
 | 
			
		||||
            class DEngine : Engine
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -141,7 +141,7 @@ namespace Tests
 | 
			
		|||
        {
 | 
			
		||||
            struct AMessage : IMessage { }
 | 
			
		||||
 | 
			
		||||
            [Reads(typeof(AMessage))]
 | 
			
		||||
            [Receives(typeof(AMessage))]
 | 
			
		||||
            [Sends(typeof(AMessage))]
 | 
			
		||||
            class AEngine : Engine
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -200,7 +200,7 @@ namespace Tests
 | 
			
		|||
            {
 | 
			
		||||
                var worldBuilder = new WorldBuilder();
 | 
			
		||||
 | 
			
		||||
                Assert.Throws<IllegalWriteTypeException>(() => worldBuilder.AddEngine(new MyEngine()), "ANonMessage must be a Message or Component");
 | 
			
		||||
                Assert.Throws<IllegalSendTypeException>(() => worldBuilder.AddEngine(new MyEngine()), "ANonMessage must be a Message or Component");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -234,7 +234,7 @@ namespace Tests
 | 
			
		|||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [Reads(typeof(AMessage), typeof(BMessage))]
 | 
			
		||||
            [Receives(typeof(AMessage), typeof(BMessage))]
 | 
			
		||||
            [Sends(typeof(DMessage))]
 | 
			
		||||
            class CEngine : Engine
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -244,7 +244,7 @@ namespace Tests
 | 
			
		|||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [Reads(typeof(DMessage))]
 | 
			
		||||
            [Receives(typeof(DMessage))]
 | 
			
		||||
            class DEngine : Engine
 | 
			
		||||
            {
 | 
			
		||||
                public override void Update(double dt)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue