From 005405512eb1e2bd050e82b51dfad9235a23c101 Mon Sep 17 00:00:00 2001 From: Evan Hemsley <2342303+ehemsley@users.noreply.github.com> Date: Thu, 5 Dec 2019 19:55:17 -0800 Subject: [PATCH] remove component messages --- encompass-cs/Attributes/Reads.cs | 2 +- encompass-cs/Attributes/ReadsPending.cs | 2 +- encompass-cs/Attributes/Writes.cs | 6 +- encompass-cs/Attributes/WritesPending.cs | 2 +- encompass-cs/ComponentManager.cs | 5 -- encompass-cs/ComponentMessageManager.cs | 13 ++-- encompass-cs/Engine.cs | 64 ++++++++--------- encompass-cs/Engines/ComponentEmitter.cs | 18 +++++ .../Engines/ComponentMessageEmitter.cs | 22 ------ encompass-cs/Messages/ComponentMessage.cs | 8 --- .../Messages/ComponentWriteMessage.cs | 10 --- .../Messages/PendingComponentMessage.cs | 9 --- encompass-cs/WorldBuilder.cs | 72 ++++++++----------- encompass-cs/encompass-cs.csproj | 6 +- test/ComponentTest.cs | 12 +++- 15 files changed, 105 insertions(+), 146 deletions(-) create mode 100644 encompass-cs/Engines/ComponentEmitter.cs delete mode 100644 encompass-cs/Engines/ComponentMessageEmitter.cs delete mode 100644 encompass-cs/Messages/ComponentMessage.cs delete mode 100644 encompass-cs/Messages/ComponentWriteMessage.cs delete mode 100644 encompass-cs/Messages/PendingComponentMessage.cs diff --git a/encompass-cs/Attributes/Reads.cs b/encompass-cs/Attributes/Reads.cs index a8892dc..b35e81f 100644 --- a/encompass-cs/Attributes/Reads.cs +++ b/encompass-cs/Attributes/Reads.cs @@ -21,7 +21,7 @@ namespace Encompass throw new IllegalReadTypeException("{0} must be a Component", readType.Name); } - this.readTypes.Add(typeof(ComponentMessage<>).MakeGenericType(readType)); + this.readTypes.Add(readType); } } } diff --git a/encompass-cs/Attributes/ReadsPending.cs b/encompass-cs/Attributes/ReadsPending.cs index f1798f8..e7e8653 100644 --- a/encompass-cs/Attributes/ReadsPending.cs +++ b/encompass-cs/Attributes/ReadsPending.cs @@ -21,7 +21,7 @@ namespace Encompass throw new IllegalReadTypeException("{0} must be a Component", readPendingType.Name); } - this.readPendingTypes.Add(typeof(PendingComponentMessage<>).MakeGenericType(readPendingType)); + this.readPendingTypes.Add(readPendingType); } } } diff --git a/encompass-cs/Attributes/Writes.cs b/encompass-cs/Attributes/Writes.cs index b6edfe1..ee73ded 100644 --- a/encompass-cs/Attributes/Writes.cs +++ b/encompass-cs/Attributes/Writes.cs @@ -21,7 +21,7 @@ namespace Encompass throw new IllegalWriteTypeException("{0} must be a Component", writeType.Name); } - this.writeTypes.Add(typeof(ComponentWriteMessage<>).MakeGenericType(writeType)); + this.writeTypes.Add(writeType); } } @@ -33,8 +33,8 @@ namespace Encompass throw new IllegalWriteTypeException("{0} must be a Component", writeType.Name); } - this.writeTypes.Add(typeof(ComponentWriteMessage<>).MakeGenericType(writeType)); - this.priorities.Add(writeType, priority); + writeTypes.Add(writeType); + priorities.Add(writeType, priority); } } } diff --git a/encompass-cs/Attributes/WritesPending.cs b/encompass-cs/Attributes/WritesPending.cs index 0983aab..ea5a370 100644 --- a/encompass-cs/Attributes/WritesPending.cs +++ b/encompass-cs/Attributes/WritesPending.cs @@ -19,7 +19,7 @@ namespace Encompass throw new IllegalWritePendingTypeException("{0} must be a Component", writePendingType.Name); } - this.writePendingTypes.Add(typeof(PendingComponentMessage<>).MakeGenericType(writePendingType)); + this.writePendingTypes.Add(writePendingType); } } } diff --git a/encompass-cs/ComponentManager.cs b/encompass-cs/ComponentManager.cs index a860cf3..bcd07be 100644 --- a/encompass-cs/ComponentManager.cs +++ b/encompass-cs/ComponentManager.cs @@ -84,10 +84,5 @@ namespace Encompass componentMessageManager.Remove(entity); drawLayerManager.UnRegisterComponentWithLayer(entity); } - - private void Remove(Entity entity) - { - componentStore.Remove(entity); - } } } diff --git a/encompass-cs/ComponentMessageManager.cs b/encompass-cs/ComponentMessageManager.cs index 7c4b58a..ab93fec 100644 --- a/encompass-cs/ComponentMessageManager.cs +++ b/encompass-cs/ComponentMessageManager.cs @@ -22,6 +22,7 @@ namespace Encompass componentStore.ClearAll(); existingComponentStore.ClearAll(); pendingComponentStore.ClearAll(); + UpToDateComponentStore.ClearAll(); foreach (var dictionary in typeToEntityToPendingComponentPriority.Values) { @@ -34,18 +35,18 @@ namespace Encompass upToDateComponentStore = componentStore; } - internal void AddExistingComponentMessage(ComponentMessage componentMessage) where TComponent : struct, IComponent + internal void AddExistingComponent(Entity entity, TComponent component) where TComponent : struct, IComponent { - RegisterExistingOrPendingComponentMessage(componentMessage.entity, componentMessage.component); + RegisterExistingOrPendingComponentMessage(entity, component); - existingComponentStore.Set(componentMessage.entity, componentMessage.component); + existingComponentStore.Set(entity, component); } - internal void AddPendingComponentMessage(PendingComponentMessage pendingComponentMessage) where TComponent : struct, IComponent + internal void AddPendingComponent(Entity entity, TComponent component, int priority) where TComponent : struct, IComponent { - if (pendingComponentStore.Set(pendingComponentMessage.entity, pendingComponentMessage.component, pendingComponentMessage.priority)) + if (pendingComponentStore.Set(entity, component, priority)) { - RegisterExistingOrPendingComponentMessage(pendingComponentMessage.entity, pendingComponentMessage.component); + RegisterExistingOrPendingComponentMessage(entity, component); } } diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index 8387b4d..ea22c3f 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -15,8 +15,12 @@ namespace Encompass { internal Guid ID; + internal readonly HashSet readTypes = new HashSet(); + internal readonly HashSet readPendingTypes = new HashSet(); internal readonly HashSet sendTypes = new HashSet(); internal readonly HashSet receiveTypes = new HashSet(); + internal readonly HashSet writeTypes = new HashSet(); + internal readonly HashSet writePendingTypes = new HashSet(); internal readonly Dictionary writePriorities = new Dictionary(); /// @@ -47,13 +51,12 @@ namespace Encompass var activatesAttribute = GetType().GetCustomAttribute(false); if (activatesAttribute != null) { - sendTypes.UnionWith(activatesAttribute.writePendingTypes); + writePendingTypes = activatesAttribute.writePendingTypes; } - var writesAttributes = GetType().GetCustomAttributes(false); - foreach (var writesAttribute in writesAttributes) + foreach (var writesAttribute in GetType().GetCustomAttributes(false)) { - sendTypes.UnionWith(writesAttribute.writeTypes); + writeTypes.UnionWith(writesAttribute.writeTypes); writePriorities = new Dictionary[2] { writePriorities, writesAttribute.priorities }.SelectMany(dict => dict).ToDictionary(pair => pair.Key, pair => pair.Value); } @@ -66,13 +69,13 @@ namespace Encompass var readsAttribute = GetType().GetCustomAttribute(false); if (readsAttribute != null) { - receiveTypes.UnionWith(readsAttribute.readTypes); + readTypes = readsAttribute.readTypes; } var readsPendingAttribute = GetType().GetCustomAttribute(false); if (readsPendingAttribute != null) { - receiveTypes.UnionWith(readsPendingAttribute.readPendingTypes); + readPendingTypes = readsPendingAttribute.readPendingTypes; } } @@ -179,8 +182,8 @@ namespace Encompass private IEnumerable<(Entity, TComponent)> ReadComponentsHelper() where TComponent : struct, IComponent { - var pendingRead = receiveTypes.Contains(typeof(PendingComponentMessage)); - var existingRead = receiveTypes.Contains(typeof(ComponentMessage)); + var pendingRead = readPendingTypes.Contains(typeof(TComponent)); + var existingRead = readTypes.Contains(typeof(TComponent)); if (existingRead && pendingRead) { return componentMessageManager.ReadExistingAndPendingComponentsByType(); @@ -222,8 +225,8 @@ namespace Encompass private (Entity, TComponent) ReadComponentHelper() where TComponent : struct, IComponent { - var pendingRead = receiveTypes.Contains(typeof(PendingComponentMessage)); - var existingRead = receiveTypes.Contains(typeof(ComponentMessage)); + var pendingRead = readPendingTypes.Contains(typeof(TComponent)); + var existingRead = readTypes.Contains(typeof(TComponent)); if (existingRead && pendingRead) { return componentMessageManager.ReadFirstExistingOrPendingComponentByType(); @@ -264,8 +267,8 @@ namespace Encompass /// protected bool SomeComponent() where TComponent : struct, IComponent { - var pendingRead = receiveTypes.Contains(typeof(PendingComponentMessage)); - var existingRead = receiveTypes.Contains(typeof(ComponentMessage)); + var pendingRead = readPendingTypes.Contains(typeof(TComponent)); + var existingRead = readTypes.Contains(typeof(TComponent)); if (existingRead && pendingRead) { return componentMessageManager.SomeExistingOrPendingComponent(); @@ -286,8 +289,8 @@ namespace Encompass private TComponent GetComponentHelper(Entity entity) where TComponent : struct, IComponent { - var pendingRead = receiveTypes.Contains(typeof(PendingComponentMessage)); - var existingRead = receiveTypes.Contains(typeof(ComponentMessage)); + var pendingRead = readPendingTypes.Contains(typeof(TComponent)); + var existingRead = readTypes.Contains(typeof(TComponent)); if (existingRead && pendingRead) { if (componentMessageManager.HasPendingComponent(entity)) @@ -339,8 +342,8 @@ namespace Encompass /// protected bool HasComponent(Entity entity) where TComponent : struct, IComponent { - var pendingRead = receiveTypes.Contains(typeof(PendingComponentMessage)); - var existingRead = receiveTypes.Contains(typeof(ComponentMessage)); + var pendingRead = readPendingTypes.Contains(typeof(TComponent)); + var existingRead = readTypes.Contains(typeof(TComponent)); if (pendingRead && existingRead) { @@ -368,11 +371,8 @@ namespace Encompass /// protected bool HasComponent(Entity entity, Type type) { - var pending = typeof(PendingComponentMessage<>).MakeGenericType(type); - var existing = typeof(ComponentMessage<>).MakeGenericType(type); - - var pendingRead = receiveTypes.Contains(pending); - var existingRead = receiveTypes.Contains(existing); + var pendingRead = readPendingTypes.Contains(type); + var existingRead = readTypes.Contains(type); if (pendingRead && existingRead) { @@ -402,27 +402,23 @@ namespace Encompass { var priority = writePriorities.ContainsKey(typeof(TComponent)) ? writePriorities[typeof(TComponent)] : 0; - if (!sendTypes.Contains(typeof(ComponentWriteMessage))) + if (!writeTypes.Contains(typeof(TComponent))) { throw new IllegalWriteException("Engine {0} tried to update undeclared Component {1}", GetType().Name, typeof(TComponent).Name); } - if (sendTypes.Contains(typeof(PendingComponentMessage))) + if (writePendingTypes.Contains(typeof(TComponent))) { - PendingComponentMessage newComponentMessage; - newComponentMessage.entity = entity; - newComponentMessage.component = component; - newComponentMessage.priority = priority; - SendPendingComponentMessage(newComponentMessage); + AddPendingComponent(entity, component, priority); } else { - componentMessageManager.UpdateComponent(entity, component, priority); + componentMessageManager.UpdateComponent(entity, component, priority); } if (component is IDrawableComponent drawableComponent) { - componentManager.RegisterDrawableComponent(entity, component, drawableComponent.Layer); + componentManager.RegisterDrawableComponent(entity, component, drawableComponent.Layer); } } @@ -473,14 +469,14 @@ namespace Encompass messageManager.AddMessage(message); } - internal void SendExistingComponentMessage(ComponentMessage message) where TComponent : struct, IComponent + internal void AddExistingComponent(Entity entity, TComponent component) where TComponent : struct, IComponent { - componentMessageManager.AddExistingComponentMessage(message); + componentMessageManager.AddExistingComponent(entity, component); } - internal void SendPendingComponentMessage(PendingComponentMessage message) where TComponent : struct, IComponent + internal void AddPendingComponent(Entity entity, TComponent component, int priority) where TComponent : struct, IComponent { - componentMessageManager.AddPendingComponentMessage(message); + componentMessageManager.AddPendingComponent(entity, component, priority); } /// diff --git a/encompass-cs/Engines/ComponentEmitter.cs b/encompass-cs/Engines/ComponentEmitter.cs new file mode 100644 index 0000000..b1f7f64 --- /dev/null +++ b/encompass-cs/Engines/ComponentEmitter.cs @@ -0,0 +1,18 @@ +namespace Encompass +{ + internal class ComponentEmitter : Engine where TComponent : struct, IComponent + { + public ComponentEmitter() + { + sendTypes.Add(typeof(TComponent)); + } + + public override void Update(double dt) + { + foreach (var (component, entity) in InternalRead()) + { + AddExistingComponent(entity, component); + } + } + } +} diff --git a/encompass-cs/Engines/ComponentMessageEmitter.cs b/encompass-cs/Engines/ComponentMessageEmitter.cs deleted file mode 100644 index d6bee6a..0000000 --- a/encompass-cs/Engines/ComponentMessageEmitter.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace Encompass -{ - internal class ComponentMessageEmitter : Engine where TComponent : struct, IComponent - { - public ComponentMessageEmitter() : base() - { - sendTypes.Add(typeof(ComponentMessage)); - } - - public override void Update(double dt) - { - foreach (var (component, entity) in InternalRead()) - { - ComponentMessage componentMessage; - componentMessage.entity = entity; - componentMessage.component = component; - SendMessage(componentMessage); - SendExistingComponentMessage(componentMessage); - } - } - } -} diff --git a/encompass-cs/Messages/ComponentMessage.cs b/encompass-cs/Messages/ComponentMessage.cs deleted file mode 100644 index 1153815..0000000 --- a/encompass-cs/Messages/ComponentMessage.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Encompass -{ - internal struct ComponentMessage : IMessage where TComponent : struct, IComponent - { - public Entity entity; - public TComponent component; - } -} diff --git a/encompass-cs/Messages/ComponentWriteMessage.cs b/encompass-cs/Messages/ComponentWriteMessage.cs deleted file mode 100644 index 424fa7b..0000000 --- a/encompass-cs/Messages/ComponentWriteMessage.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace Encompass -{ - internal struct ComponentWriteMessage : IMessage where TComponent : struct, IComponent - { - public Guid componentID; - public TComponent component; - } -} \ No newline at end of file diff --git a/encompass-cs/Messages/PendingComponentMessage.cs b/encompass-cs/Messages/PendingComponentMessage.cs deleted file mode 100644 index 8dfcc36..0000000 --- a/encompass-cs/Messages/PendingComponentMessage.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Encompass -{ - internal struct PendingComponentMessage : IMessage where TComponent : struct, IComponent - { - public Entity entity; - public TComponent component; - public int priority; - } -} diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs index a64e97e..dda5ee2 100644 --- a/encompass-cs/WorldBuilder.cs +++ b/encompass-cs/WorldBuilder.cs @@ -89,7 +89,7 @@ namespace Encompass internal void RegisterComponent(Type componentType) { registeredComponentTypes.Add(componentType); - AddEngine((Engine)Activator.CreateInstance(typeof(ComponentMessageEmitter<>).MakeGenericType(componentType))); + AddEngine((Engine)Activator.CreateInstance(typeof(ComponentEmitter<>).MakeGenericType(componentType))); } /// @@ -115,37 +115,31 @@ namespace Encompass messageManager.RegisterMessageType(messageType); } + foreach (var writePendingType in engine.writePendingTypes.Intersect(engine.readPendingTypes)) + { + throw new EngineSelfCycleException("Engine {0} both writes and reads pending Component {1}", engine.GetType().Name, writePendingType.Name); + } + foreach (var messageType in messageReceiveTypes.Intersect(messageSendTypes)) { - if ((messageType.IsGenericType && messageType.GetGenericTypeDefinition() == typeof(PendingComponentMessage<>))) - { - var componentType = messageType.GetGenericArguments().Single(); - throw new EngineSelfCycleException("Engine {0} both activates and reads pending Component {1}", engine.GetType().Name, componentType.Name); - } - throw new EngineSelfCycleException("Engine {0} both receives and sends Message {1}", engine.GetType().Name, messageType.Name); } - if (messageSendTypes.Any()) + if (messageSendTypes.Count > 0 || engine.writePendingTypes.Count > 0) { senders.Add(engine); } - foreach (var receiveType in engine.receiveTypes) + foreach (var readTypes in engine.readTypes) { - if (receiveType.IsGenericType) + if (!registeredComponentTypes.Contains(readTypes)) { - var genericTypeDefinition = receiveType.GetGenericTypeDefinition(); - if (genericTypeDefinition == typeof(ComponentMessage<>) || genericTypeDefinition == typeof(PendingComponentMessage<>)) - { - var componentType = receiveType.GetGenericArguments().Single(); - if (!registeredComponentTypes.Contains(componentType)) - { - RegisterComponent(componentType); - } - } + RegisterComponent(readTypes); } + } + foreach (var receiveType in engine.receiveTypes.Union(engine.readPendingTypes).Union(engine.readTypes)) + { if (!typeToReaders.ContainsKey(receiveType)) { typeToReaders.Add(receiveType, new HashSet()); @@ -188,7 +182,7 @@ namespace Encompass { foreach (var senderEngine in senders) { - foreach (var messageType in senderEngine.sendTypes) + foreach (var messageType in senderEngine.sendTypes.Union(senderEngine.writePendingTypes)) { if (typeToReaders.ContainsKey(messageType)) { @@ -247,16 +241,12 @@ namespace Encompass var defaultWritePriorityAttribute = engine.GetType().GetCustomAttribute(false); - var writeTypes = engine.sendTypes.Where((type) => type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ComponentWriteMessage<>)); - - foreach (var writeType in writeTypes) + foreach (var writeType in engine.writeTypes) { - var componentType = writeType.GetGenericArguments()[0]; - int? priority = null; - if (engine.writePriorities.ContainsKey(componentType)) + if (engine.writePriorities.ContainsKey(writeType)) { - priority = engine.writePriorities[componentType]; + priority = engine.writePriorities[writeType]; } else if (defaultWritePriorityAttribute != null) { @@ -265,44 +255,44 @@ namespace Encompass if (priority.HasValue) { - writtenComponentTypesWithPriority.Add(componentType); + writtenComponentTypesWithPriority.Add(writeType); - if (!writePriorities.ContainsKey(componentType)) + if (!writePriorities.ContainsKey(writeType)) { - writePriorities[componentType] = new HashSet(); + writePriorities[writeType] = new HashSet(); } - if (writePriorities[componentType].Contains(priority.Value)) + if (writePriorities[writeType].Contains(priority.Value)) { - duplicateWritesWithSamePriority.Add(componentType); + duplicateWritesWithSamePriority.Add(writeType); } - else if (writtenComponentTypesWithoutPriority.Contains(componentType)) + else if (writtenComponentTypesWithoutPriority.Contains(writeType)) { - duplicateWritesWithoutPriority.Add(componentType); + duplicateWritesWithoutPriority.Add(writeType); } else { - writePriorities[componentType].Add(priority.Value); + writePriorities[writeType].Add(priority.Value); } } else { - if (writtenComponentTypesWithoutPriority.Contains(componentType) || writtenComponentTypesWithPriority.Contains(componentType)) + if (writtenComponentTypesWithoutPriority.Contains(writeType) || writtenComponentTypesWithPriority.Contains(writeType)) { - duplicateWritesWithoutPriority.Add(componentType); + duplicateWritesWithoutPriority.Add(writeType); } else { - writtenComponentTypesWithoutPriority.Add(componentType); + writtenComponentTypesWithoutPriority.Add(writeType); } } - if (!writeMessageToEngines.ContainsKey(componentType)) + if (!writeMessageToEngines.ContainsKey(writeType)) { - writeMessageToEngines[componentType] = new List(); + writeMessageToEngines[writeType] = new List(); } - writeMessageToEngines[componentType].Add(engine); + writeMessageToEngines[writeType].Add(engine); } } diff --git a/encompass-cs/encompass-cs.csproj b/encompass-cs/encompass-cs.csproj index 729eb03..e10181e 100644 --- a/encompass-cs/encompass-cs.csproj +++ b/encompass-cs/encompass-cs.csproj @@ -9,7 +9,7 @@ Moonside Games Encompass ECS https://github.com/encompass-ecs - + Evan Hemsley 2019 Encompass is an engine-agnostic Hyper ECS framework to help you code games, or other kinds of simulations. true @@ -19,10 +19,10 @@ True - + - + diff --git a/test/ComponentTest.cs b/test/ComponentTest.cs index a27ecf6..ef3e9f8 100644 --- a/test/ComponentTest.cs +++ b/test/ComponentTest.cs @@ -415,6 +415,8 @@ namespace Tests } } + static bool hasComponentResult; + [Receives(typeof(CheckHasMockComponentMessage))] [Reads(typeof(MockComponent))] class CheckHasMockComponentEngine : Engine @@ -423,13 +425,13 @@ namespace Tests { foreach (var checkHasMockComponentMessage in ReadMessages()) { - Assert.IsTrue(HasComponent(checkHasMockComponentMessage.entity)); + hasComponentResult = HasComponent(checkHasMockComponentMessage.entity); } } } [Test] - public void RemoveComponent() + public void RemovedComponentShouldStillExistOnSameFrame() { var worldBuilder = new WorldBuilder(); var entity = worldBuilder.CreateEntity(); @@ -451,6 +453,12 @@ namespace Tests var world = worldBuilder.Build(); world.Update(0.01f); + + hasComponentResult.Should().BeTrue(); + + world.Update(0.01f); + + hasComponentResult.Should().BeFalse(); } struct CheckHasMockComponentMessage : IMessage