From fea5c578601070b4204c5348b61501f485c87ee2 Mon Sep 17 00:00:00 2001 From: thatcosmonaut Date: Fri, 19 Jul 2019 17:50:13 -0700 Subject: [PATCH] update engine generator --- encompass-cs/Attributes/Updates.cs | 6 ++-- encompass-cs/Engine.cs | 34 +++++++++---------- encompass-cs/Engines/ComponentUpdater.cs | 18 ++++++++++ .../Engines/NewComponentMessageEmitter.cs | 24 ------------- .../Exceptions/IllegalUpdateException.cs | 12 +++++++ .../{ => Messages}/ComponentMessage.cs | 0 .../Messages/ComponentUpdateMessage.cs | 10 ++++++ .../PendingComponentMessage.cs} | 0 encompass-cs/WorldBuilder.cs | 26 +++++++------- test/ComponentTest.cs | 17 ++++++++-- test/EngineTest.cs | 17 +--------- 11 files changed, 87 insertions(+), 77 deletions(-) create mode 100644 encompass-cs/Engines/ComponentUpdater.cs delete mode 100644 encompass-cs/Engines/NewComponentMessageEmitter.cs create mode 100644 encompass-cs/Exceptions/IllegalUpdateException.cs rename encompass-cs/{ => Messages}/ComponentMessage.cs (100%) create mode 100644 encompass-cs/Messages/ComponentUpdateMessage.cs rename encompass-cs/{NewComponentMessage.cs => Messages/PendingComponentMessage.cs} (100%) diff --git a/encompass-cs/Attributes/Updates.cs b/encompass-cs/Attributes/Updates.cs index b78ccae..302769b 100644 --- a/encompass-cs/Attributes/Updates.cs +++ b/encompass-cs/Attributes/Updates.cs @@ -8,7 +8,7 @@ namespace Encompass [AttributeUsage(AttributeTargets.Class)] public class Updates : Attribute { - public readonly HashSet updateTypes; + public readonly HashSet updateTypes = new HashSet(); public Updates(params Type[] updateTypes) { @@ -19,9 +19,9 @@ namespace Encompass { throw new IllegalUpdateTypeException("{0} must be a Component", updateType.Name); } - } - this.updateTypes = new HashSet(updateTypes); + this.updateTypes.Add(typeof(ComponentUpdateMessage<>).MakeGenericType(updateType)); + } } } } \ No newline at end of file diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index 3770bc1..d00fc62 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -10,7 +10,6 @@ namespace Encompass { internal readonly HashSet sendTypes = new HashSet(); internal readonly HashSet receiveTypes = new HashSet(); - internal readonly HashSet updateTypes = new HashSet(); private EntityManager entityManager; private ComponentManager componentManager; @@ -30,6 +29,12 @@ namespace Encompass sendTypes.UnionWith(activatesAttribute.activateTypes); } + var updatesAttribute = GetType().GetCustomAttribute(false); + if (updatesAttribute != null) + { + sendTypes.UnionWith(updatesAttribute.updateTypes); + } + var receivesAttribute = GetType().GetCustomAttribute(false); if (receivesAttribute != null) { @@ -47,16 +52,6 @@ namespace Encompass { receiveTypes.UnionWith(readsPendingAttribute.readPendingTypes); } - - var updatesAttribute = GetType().GetCustomAttribute(false); - if (updatesAttribute != null) - { - updateTypes = updatesAttribute.updateTypes; - if (sendTypes.Any()) - { - throw new IllegalEngineAttributesException("Engine {0} sends Message(s) and updates Component(s)", GetType().Name); - } - } } internal void AssignEntityManager(EntityManager entityManager) @@ -228,24 +223,27 @@ namespace Encompass internal void UpdateComponentInWorld(Guid componentID, TComponent newComponent) where TComponent : struct, IComponent { - if (!updateTypes.Contains(typeof(TComponent))) - { - throw new IllegalSendException("Engine {0} tried to update undeclared Component {1}", this.GetType().Name, typeof(TComponent).Name); - } - componentManager.AddUpdateComponentOperation(componentID, newComponent); } protected void UpdateComponent(Guid componentID, TComponent newComponentValue) where TComponent : struct, IComponent { - UpdateComponentInWorld(componentID, newComponentValue); + if (!sendTypes.Contains(typeof(ComponentUpdateMessage))) + { + throw new IllegalUpdateException("Engine {0} tried to update undeclared Component {1}", GetType().Name, typeof(TComponent).Name); + } + + ComponentUpdateMessage componentUpdateMessage; + componentUpdateMessage.componentID = componentID; + componentUpdateMessage.component = newComponentValue; + SendMessage(componentUpdateMessage); } protected void SendMessage(TMessage message) where TMessage : struct, IMessage { if (!sendTypes.Contains(typeof(TMessage))) { - throw new IllegalSendException("Engine {0} tried to send undeclared Message {1}", this.GetType().Name, typeof(TMessage).Name); + throw new IllegalSendException("Engine {0} tried to send undeclared Message {1}", GetType().Name, typeof(TMessage).Name); } messageManager.AddMessage(message); diff --git a/encompass-cs/Engines/ComponentUpdater.cs b/encompass-cs/Engines/ComponentUpdater.cs new file mode 100644 index 0000000..2656c7e --- /dev/null +++ b/encompass-cs/Engines/ComponentUpdater.cs @@ -0,0 +1,18 @@ +namespace Encompass.Engines +{ + internal class ComponentUpdater : Engine where TComponent : struct, IComponent + { + public ComponentUpdater() : base() + { + receiveTypes.Add(typeof(ComponentUpdateMessage)); + } + + public override void Update(double dt) + { + foreach (var componentUpdateMessage in ReadMessages>()) + { + UpdateComponentInWorld(componentUpdateMessage.componentID, componentUpdateMessage.component); + } + } + } +} \ No newline at end of file diff --git a/encompass-cs/Engines/NewComponentMessageEmitter.cs b/encompass-cs/Engines/NewComponentMessageEmitter.cs deleted file mode 100644 index e6eec90..0000000 --- a/encompass-cs/Engines/NewComponentMessageEmitter.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Reflection; - -namespace Encompass.Engines -{ - internal class NewComponentMessageEmitter : Engine where TComponent : struct, IComponent - { - public NewComponentMessageEmitter() : base() - { - sendTypes.Add(typeof(PendingComponentMessage)); - } - - public override void Update(double dt) - { - foreach (var (entity, componentID, component) in ReadComponentsFromWorld()) - { - PendingComponentMessage newComponentMessage; - newComponentMessage.entity = entity; - newComponentMessage.componentID = componentID; - newComponentMessage.component = component; - SendMessage(newComponentMessage); - } - } - } -} \ No newline at end of file diff --git a/encompass-cs/Exceptions/IllegalUpdateException.cs b/encompass-cs/Exceptions/IllegalUpdateException.cs new file mode 100644 index 0000000..82c5387 --- /dev/null +++ b/encompass-cs/Exceptions/IllegalUpdateException.cs @@ -0,0 +1,12 @@ +using System; + +namespace Encompass.Exceptions +{ + public class IllegalUpdateException : Exception + { + public IllegalUpdateException( + string format, + params object[] args + ) : base(string.Format(format, args)) { } + } +} diff --git a/encompass-cs/ComponentMessage.cs b/encompass-cs/Messages/ComponentMessage.cs similarity index 100% rename from encompass-cs/ComponentMessage.cs rename to encompass-cs/Messages/ComponentMessage.cs diff --git a/encompass-cs/Messages/ComponentUpdateMessage.cs b/encompass-cs/Messages/ComponentUpdateMessage.cs new file mode 100644 index 0000000..b63b894 --- /dev/null +++ b/encompass-cs/Messages/ComponentUpdateMessage.cs @@ -0,0 +1,10 @@ +using System; + +namespace Encompass +{ + public struct ComponentUpdateMessage : IMessage where TComponent : struct, IComponent + { + public Guid componentID; + public TComponent component; + } +} \ No newline at end of file diff --git a/encompass-cs/NewComponentMessage.cs b/encompass-cs/Messages/PendingComponentMessage.cs similarity index 100% rename from encompass-cs/NewComponentMessage.cs rename to encompass-cs/Messages/PendingComponentMessage.cs diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs index 7e34110..091ce53 100644 --- a/encompass-cs/WorldBuilder.cs +++ b/encompass-cs/WorldBuilder.cs @@ -67,10 +67,9 @@ namespace Encompass AddEngine((Engine)Activator.CreateInstance(typeof(ComponentMessageEmitter<>).MakeGenericType(componentType))); } - internal void RegisterNewComponentEmitter(Type componentType) + internal void RegisterNewComponentUpdater(Type componentType) { - registeredNewComponentTypes.Add(componentType); - AddEngine((Engine)Activator.CreateInstance(typeof(NewComponentMessageEmitter<>).MakeGenericType(componentType))); + AddEngine((Engine)Activator.CreateInstance(typeof(ComponentUpdater<>).MakeGenericType(componentType))); } public Engine AddEngine(TEngine engine) where TEngine : Engine @@ -129,13 +128,10 @@ namespace Encompass if (sendType.IsGenericType) { var genericTypeDefinition = sendType.GetGenericTypeDefinition(); - if (genericTypeDefinition == typeof(ComponentMessage<>) || genericTypeDefinition == typeof(PendingComponentMessage<>)) + if (genericTypeDefinition == typeof(ComponentUpdateMessage<>)) { var componentType = sendType.GetGenericArguments().Single(); - if (!registeredNewComponentTypes.Contains(componentType)) - { - RegisterNewComponentEmitter(componentType); - } + RegisterNewComponentUpdater(componentType); } } } @@ -208,11 +204,13 @@ namespace Encompass var mutatedComponentTypes = new HashSet(); var duplicateMutations = new List(); - var componentToEngines = new Dictionary>(); + var updateMessageToEngines = new Dictionary>(); foreach (var engine in engines) { - foreach (var updateType in engine.updateTypes) + var updateTypes = engine.sendTypes.Where((type) => type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ComponentUpdateMessage<>)); + + foreach (var updateType in updateTypes) { if (mutatedComponentTypes.Contains(updateType)) { @@ -223,12 +221,12 @@ namespace Encompass mutatedComponentTypes.Add(updateType); } - if (!componentToEngines.ContainsKey(updateType)) + if (!updateMessageToEngines.ContainsKey(updateType)) { - componentToEngines[updateType] = new List(); + updateMessageToEngines[updateType] = new List(); } - componentToEngines[updateType].Add(engine); + updateMessageToEngines[updateType].Add(engine); } } @@ -239,7 +237,7 @@ namespace Encompass { errorString += "\n" + componentType.Name + " updated by: " + - string.Join(", ", componentToEngines[componentType].Select((engine) => engine.GetType().Name)); + string.Join(", ", updateMessageToEngines[componentType].Select((engine) => engine.GetType().Name)); } throw new EngineUpdateConflictException(errorString); diff --git a/test/ComponentTest.cs b/test/ComponentTest.cs index 36a41a0..332231e 100644 --- a/test/ComponentTest.cs +++ b/test/ComponentTest.cs @@ -394,6 +394,19 @@ namespace Tests } } + [Receives(typeof(CheckHasMockComponentMessage))] + [Reads(typeof(MockComponent))] + class CheckHasMockComponentEngine : Engine + { + public override void Update(double dt) + { + foreach (var checkHasMockComponentMessage in ReadMessages()) + { + Assert.IsTrue(HasComponent(checkHasMockComponentMessage.entity)); + } + } + } + [Test] public void RemoveComponent() { @@ -470,7 +483,7 @@ namespace Tests [Receives(typeof(CheckHasMockComponentMessage))] [ReadsPending(typeof(MockComponent))] - class CheckHasMockComponentEngine : Engine + class CheckHasPendingMockComponentEngine : Engine { public override void Update(double dt) { @@ -488,7 +501,7 @@ namespace Tests var entity = worldBuilder.CreateEntity(); worldBuilder.AddEngine(new ActivateComponentEngine()); - worldBuilder.AddEngine(new CheckHasMockComponentEngine()); + worldBuilder.AddEngine(new CheckHasPendingMockComponentEngine()); worldBuilder.AddEngine(new DoActivateCheckEngine(entity)); MockComponent mockComponent; diff --git a/test/EngineTest.cs b/test/EngineTest.cs index e754b46..060383a 100644 --- a/test/EngineTest.cs +++ b/test/EngineTest.cs @@ -191,7 +191,7 @@ namespace Tests var world = worldBuilder.Build(); - var ex = Assert.Throws(() => world.Update(0.01f)); + var ex = Assert.Throws(() => world.Update(0.01f)); Assert.That(ex.Message, Is.EqualTo("Engine UndeclaredUpdateComponentTestEngine tried to update undeclared Component MockComponent")); } @@ -645,21 +645,6 @@ namespace Tests Assert.IsFalse(hasEntity); } - [Sends(typeof(MockMessage))] - [Updates(typeof(MockComponent))] - class EngineThatWritesComponentAndMessage : Engine - { - public override void Update(double dt) { } - } - - [Test] - public void EngineWritesComponentAndMessage() - { - var worldBuilder = new WorldBuilder(); - - Assert.Throws(() => worldBuilder.AddEngine(new EngineThatWritesComponentAndMessage())); - } - struct MockComponentUpdateMessage : IMessage { public Guid componentID;