From 98955f30482e8229374cc56c7b30b92868ee4a06 Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Thu, 19 Mar 2020 15:44:04 -0700 Subject: [PATCH 01/30] converting component storage to pack data and return refs --- encompass-cs/Collections/ComponentStore.cs | 9 +++- .../Collections/TypedComponentStore.cs | 50 ++++++++++++------- encompass-cs/ComponentManager.cs | 17 +++---- encompass-cs/Engine.cs | 12 ++--- encompass-cs/Renderer.cs | 4 +- encompass-cs/encompass-cs.csproj | 4 +- 6 files changed, 58 insertions(+), 38 deletions(-) diff --git a/encompass-cs/Collections/ComponentStore.cs b/encompass-cs/Collections/ComponentStore.cs index aee17e8..fd0965d 100644 --- a/encompass-cs/Collections/ComponentStore.cs +++ b/encompass-cs/Collections/ComponentStore.cs @@ -4,6 +4,11 @@ using System.Collections.Generic; namespace Encompass { + public struct MutableComponentEntityPair where TComponent : struct, IComponent + { + public TComponent component; + } + internal class ComponentStore { private Dictionary Stores = new Dictionary(512); @@ -51,9 +56,9 @@ namespace Encompass return ComponentBitSet.EntityBitArray(entityID); } - public TComponent Get(int entityID) where TComponent : struct, IComponent + public ref readonly TComponent Get(int entityID) where TComponent : struct, IComponent { - return Lookup().Get(entityID); + return ref Lookup().Get(entityID); } public virtual void Set(int entityID, TComponent component) where TComponent : struct, IComponent diff --git a/encompass-cs/Collections/TypedComponentStore.cs b/encompass-cs/Collections/TypedComponentStore.cs index 78a8f20..a32fea4 100644 --- a/encompass-cs/Collections/TypedComponentStore.cs +++ b/encompass-cs/Collections/TypedComponentStore.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; namespace Encompass { @@ -16,27 +17,30 @@ namespace Encompass internal class TypedComponentStore : TypedComponentStore where TComponent : struct, IComponent { - private readonly Dictionary store = new Dictionary(128); - private readonly Dictionary priorities = new Dictionary(128); + private readonly Dictionary indices = new Dictionary(512); + private readonly Dictionary priorities = new Dictionary(512); + private TComponent[] components = new TComponent[512]; + private readonly IDManager _idManager = new IDManager(); - public override int Count { get => store.Count; } + public override int Count { get => indices.Count; } - public TComponent Get(int entityID) + public unsafe ref readonly TComponent Get(int entityID) { - if (!store.ContainsKey(entityID)) { throw new Exceptions.NoComponentOfTypeOnEntityException("No component of type {0} exists on Entity with ID {1}", typeof(TComponent), entityID); } - return store[entityID]; + if (!indices.ContainsKey(entityID)) { throw new Exceptions.NoComponentOfTypeOnEntityException("No component of type {0} exists on Entity with ID {1}", typeof(TComponent), entityID); } + ref var refVal = ref components[indices[entityID]]; + return ref Unsafe.AsRef(Unsafe.AsPointer(ref refVal)); } - public void Set(int entityID, TComponent component) + public unsafe void Set(int entityID, TComponent component) { - store[entityID] = component; + InternalSet(entityID, component); } - public bool Set(int entityID, TComponent component, int priority) + public unsafe bool Set(int entityID, TComponent component, int priority) { if (!priorities.ContainsKey(entityID) || priority < priorities[entityID]) { - store[entityID] = component; + InternalSet(entityID, component); priorities[entityID] = priority; return true; } @@ -44,13 +48,22 @@ namespace Encompass return false; } + private unsafe void InternalSet(int entityID, TComponent component) + { + var index = _idManager.NextID(); + var ptr = Unsafe.AsPointer(ref component); + indices[entityID] = index; + components[index] = Unsafe.AsRef(ptr); + } + public override bool Remove(int entityID, int priority) { if (!priorities.ContainsKey(entityID) || priority < priorities[entityID]) { priorities[entityID] = priority; - store.Remove(entityID); + indices.Remove(entityID); priorities.Remove(entityID); + _idManager.Free(entityID); return true; } @@ -59,18 +72,19 @@ namespace Encompass public override void ForceRemove(int entityID) { - store.Remove(entityID); + indices.Remove(entityID); priorities.Remove(entityID); + _idManager.Free(entityID); } public override bool Has(int entityID) { - return store.ContainsKey(entityID); + return indices.ContainsKey(entityID); } public override void Clear() { - store.Clear(); + indices.Clear(); priorities.Clear(); } @@ -81,17 +95,17 @@ namespace Encompass public IEnumerable<(TComponent, int)> All() { - foreach (var kvp in store) + foreach (var kvp in indices) { - yield return (kvp.Value, kvp.Key); + yield return (components[kvp.Value], kvp.Key); } } public override IEnumerable<(int, Type, IComponent)> AllInterfaceTyped() { - foreach (var kvp in store) + foreach (var kvp in indices) { - yield return (kvp.Key, typeof(TComponent), (IComponent)kvp.Value); + yield return (kvp.Key, typeof(TComponent), (IComponent)components[kvp.Value]); } } } diff --git a/encompass-cs/ComponentManager.cs b/encompass-cs/ComponentManager.cs index 046704e..a82511b 100644 --- a/encompass-cs/ComponentManager.cs +++ b/encompass-cs/ComponentManager.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using MoonTools.FastCollections; namespace Encompass { @@ -154,19 +153,19 @@ namespace Encompass // component getters - internal TComponent ReadImmediateOrExistingComponentByEntityAndType(int entityID) where TComponent : struct, IComponent + internal ref readonly TComponent ReadImmediateOrExistingComponentByEntityAndType(int entityID) where TComponent : struct, IComponent { - return upToDateComponentStore.Get(entityID); + return ref upToDateComponentStore.Get(entityID); } - internal TComponent ReadExistingComponentByEntityAndType(int entityID) where TComponent : struct, IComponent + internal ref readonly TComponent ReadExistingComponentByEntityAndType(int entityID) where TComponent : struct, IComponent { - return existingComponentStore.Get(entityID); + return ref existingComponentStore.Get(entityID); } - internal TComponent ReadImmediateComponentByEntityAndType(int entityID) where TComponent : struct, IComponent + internal ref readonly TComponent ReadImmediateComponentByEntityAndType(int entityID) where TComponent : struct, IComponent { - return immediateComponentStore.Get(entityID); + return ref immediateComponentStore.Get(entityID); } // has checkers @@ -214,9 +213,9 @@ namespace Encompass } } - internal TComponent GetComponentByEntityAndType(int entityID) where TComponent : struct, IComponent + internal ref readonly TComponent GetComponentByEntityAndType(int entityID) where TComponent : struct, IComponent { - return existingComponentStore.Get(entityID); + return ref existingComponentStore.Get(entityID); } internal bool EntityHasComponentOfType(int entityID) where TComponent : struct, IComponent diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index 8a3cdf6..2d55290 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -344,21 +344,21 @@ namespace Encompass } } - private TComponent GetComponentHelper(int entityID) where TComponent : struct, IComponent + private ref readonly TComponent GetComponentHelper(int entityID) where TComponent : struct, IComponent { var immediateRead = readImmediateTypes.Contains(typeof(TComponent)); var existingRead = readTypes.Contains(typeof(TComponent)); if (existingRead && immediateRead) { - return componentManager.ReadImmediateOrExistingComponentByEntityAndType(entityID); + return ref componentManager.ReadImmediateOrExistingComponentByEntityAndType(entityID); } else if (existingRead) { - return componentManager.ReadExistingComponentByEntityAndType(entityID); + return ref componentManager.ReadExistingComponentByEntityAndType(entityID); } else if (immediateRead) { - return componentManager.ReadImmediateComponentByEntityAndType(entityID); + return ref componentManager.ReadImmediateComponentByEntityAndType(entityID); } else { @@ -375,9 +375,9 @@ namespace Encompass /// /// Thrown when the Engine does not declare that it reads the given Component Type. /// - protected TComponent GetComponent(Entity entity) where TComponent : struct, IComponent + protected ref readonly TComponent GetComponent(Entity entity) where TComponent : struct, IComponent { - return GetComponentHelper(entity.ID); + return ref GetComponentHelper(entity.ID); } /// diff --git a/encompass-cs/Renderer.cs b/encompass-cs/Renderer.cs index 3dba03c..9ac5887 100644 --- a/encompass-cs/Renderer.cs +++ b/encompass-cs/Renderer.cs @@ -57,9 +57,9 @@ namespace Encompass return enumerator.Current; } - protected TComponent GetComponent(Entity entity) where TComponent : struct, IComponent + protected ref readonly TComponent GetComponent(Entity entity) where TComponent : struct, IComponent { - return componentManager.GetComponentByEntityAndType(entity.ID); + return ref componentManager.GetComponentByEntityAndType(entity.ID); } protected bool HasComponent(Entity entity) where TComponent : struct, IComponent diff --git a/encompass-cs/encompass-cs.csproj b/encompass-cs/encompass-cs.csproj index 9fda87b..c7be512 100644 --- a/encompass-cs/encompass-cs.csproj +++ b/encompass-cs/encompass-cs.csproj @@ -1,6 +1,8 @@ - netstandard2.0 + netstandard2.1 + 8.0 + true Encompass EncompassECS.Framework 0.20.0 From ffc052ded35e9d120978424e60473dbcf21fa171 Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Thu, 19 Mar 2020 17:26:22 -0700 Subject: [PATCH 02/30] fix creating new component index on every set --- encompass-cs/Collections/TypedComponentStore.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/encompass-cs/Collections/TypedComponentStore.cs b/encompass-cs/Collections/TypedComponentStore.cs index a32fea4..fa766b5 100644 --- a/encompass-cs/Collections/TypedComponentStore.cs +++ b/encompass-cs/Collections/TypedComponentStore.cs @@ -50,10 +50,13 @@ namespace Encompass private unsafe void InternalSet(int entityID, TComponent component) { - var index = _idManager.NextID(); + if (!indices.ContainsKey(entityID)) + { + indices[entityID] = _idManager.NextID(); + } + var ptr = Unsafe.AsPointer(ref component); - indices[entityID] = index; - components[index] = Unsafe.AsRef(ptr); + components[indices[entityID]] = Unsafe.AsRef(ptr); } public override bool Remove(int entityID, int priority) @@ -84,6 +87,10 @@ namespace Encompass public override void Clear() { + foreach (var entityID in indices.Keys) + { + _idManager.Free(entityID); + } indices.Clear(); priorities.Clear(); } From 7f89e9b4a043ff8d7a0d48a31deb9bf2ea424945 Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Fri, 20 Mar 2020 00:09:57 -0700 Subject: [PATCH 03/30] fix style issues --- .../Attributes/DefaultWritePriority.cs | 4 +- encompass-cs/Attributes/QueryWith.cs | 4 +- encompass-cs/Attributes/QueryWithout.cs | 4 +- encompass-cs/Attributes/Reads.cs | 4 +- encompass-cs/Attributes/ReadsImmediate.cs | 4 +- encompass-cs/Attributes/Receives.cs | 4 +- encompass-cs/Attributes/Sends.cs | 4 +- encompass-cs/Attributes/Writes.cs | 10 +- encompass-cs/Attributes/WritesImmediate.cs | 4 +- encompass-cs/Collections/ComponentBitSet.cs | 24 +- encompass-cs/Collections/ComponentStore.cs | 27 +- encompass-cs/Collections/MessageStore.cs | 12 +- .../Collections/TypedComponentStore.cs | 52 ++-- encompass-cs/Collections/TypedMessageStore.cs | 48 ++-- encompass-cs/ComponentManager.cs | 138 +++++----- encompass-cs/DrawLayerManager.cs | 62 ++--- encompass-cs/Engine.cs | 260 +++++++++--------- encompass-cs/Engines/Spawner.cs | 4 +- encompass-cs/Entity.cs | 2 +- encompass-cs/EntityManager.cs | 40 +-- encompass-cs/IDManager.cs | 14 +- encompass-cs/MessageManager.cs | 28 +- encompass-cs/RenderManager.cs | 28 +- encompass-cs/Renderer.cs | 20 +- encompass-cs/TimeDilationData.cs | 51 +++- encompass-cs/TimeManager.cs | 41 ++- encompass-cs/TrackingManager.cs | 10 +- encompass-cs/UberEngine.cs | 14 +- encompass-cs/UberRenderer.cs | 2 +- encompass-cs/World.cs | 52 ++-- encompass-cs/WorldBuilder.cs | 194 ++++++------- 31 files changed, 591 insertions(+), 574 deletions(-) diff --git a/encompass-cs/Attributes/DefaultWritePriority.cs b/encompass-cs/Attributes/DefaultWritePriority.cs index cf0c065..65500c7 100644 --- a/encompass-cs/Attributes/DefaultWritePriority.cs +++ b/encompass-cs/Attributes/DefaultWritePriority.cs @@ -5,11 +5,11 @@ namespace Encompass [AttributeUsage(AttributeTargets.Class)] public class DefaultWritePriority : Attribute { - public int writePriority; + public int WritePriority { get; } public DefaultWritePriority(int writePriority) { - this.writePriority = writePriority; + WritePriority = writePriority; } } } diff --git a/encompass-cs/Attributes/QueryWith.cs b/encompass-cs/Attributes/QueryWith.cs index 3ae11a6..5574c5b 100644 --- a/encompass-cs/Attributes/QueryWith.cs +++ b/encompass-cs/Attributes/QueryWith.cs @@ -8,7 +8,7 @@ namespace Encompass [AttributeUsage(AttributeTargets.Class)] public class QueryWith : Attribute { - public readonly HashSet queryWithTypes = new HashSet(); + public readonly HashSet QueryWithTypes = new HashSet(); public QueryWith(params Type[] queryWithTypes) { @@ -21,7 +21,7 @@ namespace Encompass throw new IllegalReadTypeException("{0} must be a Component", queryWithType.Name); } - this.queryWithTypes.Add(queryWithType); + QueryWithTypes.Add(queryWithType); } } } diff --git a/encompass-cs/Attributes/QueryWithout.cs b/encompass-cs/Attributes/QueryWithout.cs index 77f1e9f..3588285 100644 --- a/encompass-cs/Attributes/QueryWithout.cs +++ b/encompass-cs/Attributes/QueryWithout.cs @@ -8,7 +8,7 @@ namespace Encompass [AttributeUsage(AttributeTargets.Class)] public class QueryWithout : Attribute { - public readonly HashSet queryWithoutTypes = new HashSet(); + public readonly HashSet QueryWithoutTypes = new HashSet(); public QueryWithout(params Type[] queryWithoutTypes) { @@ -21,7 +21,7 @@ namespace Encompass throw new IllegalReadTypeException("{0} must be a Component", type.Name); } - this.queryWithoutTypes.Add(type); + this.QueryWithoutTypes.Add(type); } } } diff --git a/encompass-cs/Attributes/Reads.cs b/encompass-cs/Attributes/Reads.cs index b35e81f..b958a26 100644 --- a/encompass-cs/Attributes/Reads.cs +++ b/encompass-cs/Attributes/Reads.cs @@ -8,7 +8,7 @@ namespace Encompass [AttributeUsage(AttributeTargets.Class)] public class Reads : Attribute { - public readonly HashSet readTypes = new HashSet(); + public readonly HashSet ReadTypes = new HashSet(); public Reads(params Type[] readTypes) { @@ -21,7 +21,7 @@ namespace Encompass throw new IllegalReadTypeException("{0} must be a Component", readType.Name); } - this.readTypes.Add(readType); + this.ReadTypes.Add(readType); } } } diff --git a/encompass-cs/Attributes/ReadsImmediate.cs b/encompass-cs/Attributes/ReadsImmediate.cs index e47d4ba..5d4b0ff 100644 --- a/encompass-cs/Attributes/ReadsImmediate.cs +++ b/encompass-cs/Attributes/ReadsImmediate.cs @@ -8,7 +8,7 @@ namespace Encompass [AttributeUsage(AttributeTargets.Class)] public class ReadsImmediate : Attribute { - public readonly HashSet readImmediateTypes = new HashSet(); + public readonly HashSet ReadImmediateTypes = new HashSet(); public ReadsImmediate(params Type[] readImmediateTypes) { @@ -21,7 +21,7 @@ namespace Encompass throw new IllegalReadTypeException("{0} must be a Component", readImmediateType.Name); } - this.readImmediateTypes.Add(readImmediateType); + this.ReadImmediateTypes.Add(readImmediateType); } } } diff --git a/encompass-cs/Attributes/Receives.cs b/encompass-cs/Attributes/Receives.cs index e8d0542..79d4b66 100644 --- a/encompass-cs/Attributes/Receives.cs +++ b/encompass-cs/Attributes/Receives.cs @@ -8,7 +8,7 @@ namespace Encompass [AttributeUsage(AttributeTargets.Class)] public class Receives : Attribute { - public readonly HashSet receiveTypes; + public readonly HashSet ReceiveTypes; public Receives(params Type[] receiveTypes) { @@ -21,7 +21,7 @@ namespace Encompass } } - this.receiveTypes = new HashSet(receiveTypes); + ReceiveTypes = new HashSet(receiveTypes); } } } diff --git a/encompass-cs/Attributes/Sends.cs b/encompass-cs/Attributes/Sends.cs index 7bb1a0e..8fbacd3 100644 --- a/encompass-cs/Attributes/Sends.cs +++ b/encompass-cs/Attributes/Sends.cs @@ -8,7 +8,7 @@ namespace Encompass [AttributeUsage(AttributeTargets.Class)] public class Sends : Attribute { - public readonly HashSet sendTypes; + public readonly HashSet SendTypes; public Sends(params Type[] sendTypes) { @@ -21,7 +21,7 @@ namespace Encompass } } - this.sendTypes = new HashSet(sendTypes); + this.SendTypes = new HashSet(sendTypes); } } } diff --git a/encompass-cs/Attributes/Writes.cs b/encompass-cs/Attributes/Writes.cs index ee73ded..8eec04a 100644 --- a/encompass-cs/Attributes/Writes.cs +++ b/encompass-cs/Attributes/Writes.cs @@ -8,8 +8,8 @@ namespace Encompass [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] public class Writes : Attribute { - public readonly HashSet writeTypes = new HashSet(); - public Dictionary priorities = new Dictionary(); + public readonly HashSet WriteTypes = new HashSet(); + public readonly Dictionary Priorities = new Dictionary(); public Writes(params Type[] writeTypes) { @@ -21,7 +21,7 @@ namespace Encompass throw new IllegalWriteTypeException("{0} must be a Component", writeType.Name); } - this.writeTypes.Add(writeType); + this.WriteTypes.Add(writeType); } } @@ -33,8 +33,8 @@ namespace Encompass throw new IllegalWriteTypeException("{0} must be a Component", writeType.Name); } - writeTypes.Add(writeType); - priorities.Add(writeType, priority); + WriteTypes.Add(writeType); + Priorities.Add(writeType, priority); } } } diff --git a/encompass-cs/Attributes/WritesImmediate.cs b/encompass-cs/Attributes/WritesImmediate.cs index 66a46a6..0b5db7c 100644 --- a/encompass-cs/Attributes/WritesImmediate.cs +++ b/encompass-cs/Attributes/WritesImmediate.cs @@ -8,7 +8,7 @@ namespace Encompass [AttributeUsage(AttributeTargets.Class)] public class WritesImmediate : Attribute { - public readonly HashSet writeImmediateTypes = new HashSet(); + public readonly HashSet WriteImmediateTypes = new HashSet(); public WritesImmediate(params Type[] writeImmediateTypes) { @@ -20,7 +20,7 @@ namespace Encompass throw new IllegalWriteImmediateTypeException("{0} must be a Component", writeImmediateType.Name); } - this.writeImmediateTypes.Add(writeImmediateType); + this.WriteImmediateTypes.Add(writeImmediateType); } } } diff --git a/encompass-cs/Collections/ComponentBitSet.cs b/encompass-cs/Collections/ComponentBitSet.cs index 1d0c39d..8c90cf5 100644 --- a/encompass-cs/Collections/ComponentBitSet.cs +++ b/encompass-cs/Collections/ComponentBitSet.cs @@ -6,49 +6,49 @@ namespace Encompass { internal class ComponentBitSet { - Dictionary entities = new Dictionary(); - Dictionary TypeToIndex { get; } + private readonly Dictionary _entities = new Dictionary(); + private readonly Dictionary _typeToIndex; public ComponentBitSet(Dictionary typeToIndex) { - TypeToIndex = typeToIndex; + _typeToIndex = typeToIndex; } public void Clear() { - entities.Clear(); + _entities.Clear(); } public void AddEntity(int entityID) { - entities.Add(entityID, BitSet512.Zero); + _entities.Add(entityID, BitSet512.Zero); } public void Set(int entityID) where TComponent : struct, IComponent { - if (!entities.ContainsKey(entityID)) { AddEntity(entityID); } - entities[entityID] = entities[entityID].Set(TypeToIndex[typeof(TComponent)]); + if (!_entities.ContainsKey(entityID)) { AddEntity(entityID); } + _entities[entityID] = _entities[entityID].Set(_typeToIndex[typeof(TComponent)]); } public void RemoveComponent(int entityID) where TComponent : struct, IComponent { - if (entities.ContainsKey(entityID)) + if (_entities.ContainsKey(entityID)) { - entities[entityID] = entities[entityID].UnSet(TypeToIndex[typeof(TComponent)]); + _entities[entityID] = _entities[entityID].UnSet(_typeToIndex[typeof(TComponent)]); } } public void RemoveEntity(int entityID) { - if (entities.ContainsKey(entityID)) + if (_entities.ContainsKey(entityID)) { - entities.Remove(entityID); + _entities.Remove(entityID); } } public BitSet512 EntityBitArray(int entityID) { - return entities.ContainsKey(entityID) ? entities[entityID] : BitSet512.Zero; + return _entities.ContainsKey(entityID) ? _entities[entityID] : BitSet512.Zero; } } } diff --git a/encompass-cs/Collections/ComponentStore.cs b/encompass-cs/Collections/ComponentStore.cs index fd0965d..3a65abe 100644 --- a/encompass-cs/Collections/ComponentStore.cs +++ b/encompass-cs/Collections/ComponentStore.cs @@ -4,14 +4,9 @@ using System.Collections.Generic; namespace Encompass { - public struct MutableComponentEntityPair where TComponent : struct, IComponent - { - public TComponent component; - } - internal class ComponentStore { - private Dictionary Stores = new Dictionary(512); + private Dictionary _stores = new Dictionary(512); public ComponentBitSet ComponentBitSet { get; private set; } public ComponentStore(Dictionary typeToIndex) @@ -21,7 +16,7 @@ namespace Encompass public IEnumerable<(Type, TypedComponentStore)> StoresEnumerable() { - foreach (var entry in Stores) + foreach (var entry in _stores) { yield return (entry.Key, entry.Value); } @@ -29,16 +24,16 @@ namespace Encompass public virtual void RegisterComponentType() where TComponent : struct, IComponent { - if (!Stores.ContainsKey(typeof(TComponent))) + if (!_stores.ContainsKey(typeof(TComponent))) { var store = new TypedComponentStore(); - Stores.Add(typeof(TComponent), store); + _stores.Add(typeof(TComponent), store); } } private TypedComponentStore Lookup() where TComponent : struct, IComponent { - return Stores[typeof(TComponent)] as TypedComponentStore; + return _stores[typeof(TComponent)] as TypedComponentStore; } public bool Has(int entityID) where TComponent : struct, IComponent @@ -48,7 +43,7 @@ namespace Encompass public bool Has(Type type, int entityID) { - return Stores.ContainsKey(type) && Stores[type].Has(entityID); + return _stores.ContainsKey(type) && _stores[type].Has(entityID); } public BitSet512 EntityBitArray(int entityID) @@ -95,7 +90,7 @@ namespace Encompass public virtual void Remove(int entityID) { - foreach (var entry in Stores.Values) + foreach (var entry in _stores.Values) { entry.ForceRemove(entityID); } @@ -109,7 +104,7 @@ namespace Encompass public IEnumerable<(int, Type, IComponent)> AllInterfaceTyped() { - foreach (var store in Stores.Values) + foreach (var store in _stores.Values) { foreach (var thing in store.AllInterfaceTyped()) { @@ -130,7 +125,7 @@ namespace Encompass public virtual void ClearAllPriorities() { - foreach (var store in Stores.Values) + foreach (var store in _stores.Values) { store.ClearPriorities(); } @@ -139,7 +134,7 @@ namespace Encompass public virtual void ClearAll() { ComponentBitSet.Clear(); - foreach (var store in Stores.Values) + foreach (var store in _stores.Values) { store.Clear(); } @@ -147,7 +142,7 @@ namespace Encompass public void SwapWith(ComponentStore other) { - (Stores, other.Stores) = (other.Stores, Stores); + (_stores, other._stores) = (other._stores, _stores); (ComponentBitSet, other.ComponentBitSet) = (other.ComponentBitSet, ComponentBitSet); } diff --git a/encompass-cs/Collections/MessageStore.cs b/encompass-cs/Collections/MessageStore.cs index 5e7186f..a966fe6 100644 --- a/encompass-cs/Collections/MessageStore.cs +++ b/encompass-cs/Collections/MessageStore.cs @@ -5,17 +5,17 @@ namespace Encompass { internal class MessageStore { - private Dictionary Stores = new Dictionary(512); + private readonly Dictionary _stores = new Dictionary(512); private void RegisterMessageType() where TMessage : struct, IMessage { - Stores.Add(typeof(TMessage), new TypedMessageStore()); + _stores.Add(typeof(TMessage), new TypedMessageStore()); } private TypedMessageStore Lookup() where TMessage : struct, IMessage { - if (!Stores.ContainsKey(typeof(TMessage))) { RegisterMessageType(); } - return Stores[typeof(TMessage)] as TypedMessageStore; + if (!_stores.ContainsKey(typeof(TMessage))) { RegisterMessageType(); } + return _stores[typeof(TMessage)] as TypedMessageStore; } public void AddMessage(TMessage message) where TMessage : struct, IMessage @@ -60,7 +60,7 @@ namespace Encompass public void ProcessDelayedMessages(double dilatedDelta, double realtimeDelta) { - foreach (var store in Stores.Values) + foreach (var store in _stores.Values) { store.ProcessDelayedMessages(dilatedDelta, realtimeDelta); } @@ -68,7 +68,7 @@ namespace Encompass public void ClearAll() { - foreach (var store in Stores.Values) + foreach (var store in _stores.Values) { store.Clear(); } diff --git a/encompass-cs/Collections/TypedComponentStore.cs b/encompass-cs/Collections/TypedComponentStore.cs index fa766b5..9f3c9af 100644 --- a/encompass-cs/Collections/TypedComponentStore.cs +++ b/encompass-cs/Collections/TypedComponentStore.cs @@ -17,17 +17,17 @@ namespace Encompass internal class TypedComponentStore : TypedComponentStore where TComponent : struct, IComponent { - private readonly Dictionary indices = new Dictionary(512); - private readonly Dictionary priorities = new Dictionary(512); - private TComponent[] components = new TComponent[512]; + private readonly Dictionary _indices = new Dictionary(512); + private readonly Dictionary _priorities = new Dictionary(512); + private readonly TComponent[] _components = new TComponent[512]; private readonly IDManager _idManager = new IDManager(); - public override int Count { get => indices.Count; } + public override int Count { get => _indices.Count; } public unsafe ref readonly TComponent Get(int entityID) { - if (!indices.ContainsKey(entityID)) { throw new Exceptions.NoComponentOfTypeOnEntityException("No component of type {0} exists on Entity with ID {1}", typeof(TComponent), entityID); } - ref var refVal = ref components[indices[entityID]]; + if (!_indices.ContainsKey(entityID)) { throw new Exceptions.NoComponentOfTypeOnEntityException("No component of type {0} exists on Entity with ID {1}", typeof(TComponent), entityID); } + ref var refVal = ref _components[_indices[entityID]]; return ref Unsafe.AsRef(Unsafe.AsPointer(ref refVal)); } @@ -38,10 +38,10 @@ namespace Encompass public unsafe bool Set(int entityID, TComponent component, int priority) { - if (!priorities.ContainsKey(entityID) || priority < priorities[entityID]) + if (!_priorities.ContainsKey(entityID) || priority < _priorities[entityID]) { InternalSet(entityID, component); - priorities[entityID] = priority; + _priorities[entityID] = priority; return true; } @@ -50,22 +50,22 @@ namespace Encompass private unsafe void InternalSet(int entityID, TComponent component) { - if (!indices.ContainsKey(entityID)) + if (!_indices.ContainsKey(entityID)) { - indices[entityID] = _idManager.NextID(); + _indices[entityID] = _idManager.NextID(); } var ptr = Unsafe.AsPointer(ref component); - components[indices[entityID]] = Unsafe.AsRef(ptr); + _components[_indices[entityID]] = Unsafe.AsRef(ptr); } public override bool Remove(int entityID, int priority) { - if (!priorities.ContainsKey(entityID) || priority < priorities[entityID]) + if (!_priorities.ContainsKey(entityID) || priority < _priorities[entityID]) { - priorities[entityID] = priority; - indices.Remove(entityID); - priorities.Remove(entityID); + _priorities[entityID] = priority; + _indices.Remove(entityID); + _priorities.Remove(entityID); _idManager.Free(entityID); return true; } @@ -75,44 +75,44 @@ namespace Encompass public override void ForceRemove(int entityID) { - indices.Remove(entityID); - priorities.Remove(entityID); + _indices.Remove(entityID); + _priorities.Remove(entityID); _idManager.Free(entityID); } public override bool Has(int entityID) { - return indices.ContainsKey(entityID); + return _indices.ContainsKey(entityID); } public override void Clear() { - foreach (var entityID in indices.Keys) + foreach (var entityID in _indices.Keys) { _idManager.Free(entityID); } - indices.Clear(); - priorities.Clear(); + _indices.Clear(); + _priorities.Clear(); } public override void ClearPriorities() { - priorities.Clear(); + _priorities.Clear(); } public IEnumerable<(TComponent, int)> All() { - foreach (var kvp in indices) + foreach (var kvp in _indices) { - yield return (components[kvp.Value], kvp.Key); + yield return (_components[kvp.Value], kvp.Key); } } public override IEnumerable<(int, Type, IComponent)> AllInterfaceTyped() { - foreach (var kvp in indices) + foreach (var kvp in _indices) { - yield return (kvp.Key, typeof(TComponent), (IComponent)components[kvp.Value]); + yield return (kvp.Key, typeof(TComponent), (IComponent)_components[kvp.Value]); } } } diff --git a/encompass-cs/Collections/TypedMessageStore.cs b/encompass-cs/Collections/TypedMessageStore.cs index bfa7a8b..0a7a1e8 100644 --- a/encompass-cs/Collections/TypedMessageStore.cs +++ b/encompass-cs/Collections/TypedMessageStore.cs @@ -10,98 +10,98 @@ namespace Encompass internal class TypedMessageStore : TypedMessageStore where TMessage : struct, IMessage { - private readonly List store = new List(128); - private readonly List<(TMessage, double)> delayedStore = new List<(TMessage, double)>(128); - private readonly List<(TMessage, double)> delayedStoreIgnoringTimeDilation = new List<(TMessage, double)>(128); - private readonly Dictionary> entityToMessage = new Dictionary>(); + private readonly List _store = new List(128); + private readonly List<(TMessage, double)> _delayedStore = new List<(TMessage, double)>(128); + private readonly List<(TMessage, double)> _delayedStoreIgnoringTimeDilation = new List<(TMessage, double)>(128); + private readonly Dictionary> _entityToMessage = new Dictionary>(); public override void ProcessDelayedMessages(double dilatedDelta, double realtimeDelta) { - for (int i = delayedStore.Count - 1; i >= 0; i--) + for (var i = _delayedStore.Count - 1; i >= 0; i--) { - var (message, time) = delayedStore[i]; + var (message, time) = _delayedStore[i]; var updatedTime = time - dilatedDelta; if (updatedTime <= 0) { Add(message); - delayedStore.RemoveAt(i); + _delayedStore.RemoveAt(i); } else { - delayedStore[i] = (message, updatedTime); + _delayedStore[i] = (message, updatedTime); } } - for (int i = delayedStoreIgnoringTimeDilation.Count - 1; i >= 0; i--) + for (var i = _delayedStoreIgnoringTimeDilation.Count - 1; i >= 0; i--) { - var (message, time) = delayedStoreIgnoringTimeDilation[i]; + var (message, time) = _delayedStoreIgnoringTimeDilation[i]; var updatedTime = time - realtimeDelta; if (updatedTime <= 0) { Add(message); - delayedStoreIgnoringTimeDilation.RemoveAt(i); + _delayedStoreIgnoringTimeDilation.RemoveAt(i); } else { - delayedStoreIgnoringTimeDilation[i] = (message, updatedTime); + _delayedStoreIgnoringTimeDilation[i] = (message, updatedTime); } } } public void Add(TMessage message) { - store.Add(message); + _store.Add(message); if (message is IHasEntity entityMessage) { var entityID = entityMessage.Entity.ID; - if (!entityToMessage.ContainsKey(entityID)) { entityToMessage.Add(entityID, new List()); } - entityToMessage[entityID].Add(message); + if (!_entityToMessage.ContainsKey(entityID)) { _entityToMessage.Add(entityID, new List()); } + _entityToMessage[entityID].Add(message); } } public void Add(TMessage message, double time) { - delayedStore.Add((message, time)); + _delayedStore.Add((message, time)); } public void AddIgnoringTimeDilation(TMessage message, double time) { - delayedStoreIgnoringTimeDilation.Add((message, time)); + _delayedStoreIgnoringTimeDilation.Add((message, time)); } public TMessage First() { - return store[0]; + return _store[0]; } public bool Any() { - return store.Count > 0; + return _store.Count > 0; } public IEnumerable All() { - return store; + return _store; } public IEnumerable WithEntity(int entityID) { - return entityToMessage.ContainsKey(entityID) ? entityToMessage[entityID] : System.Linq.Enumerable.Empty(); + return _entityToMessage.ContainsKey(entityID) ? _entityToMessage[entityID] : System.Linq.Enumerable.Empty(); } public bool SomeWithEntity(int entityID) { - return entityToMessage.ContainsKey(entityID) && entityToMessage[entityID].Count > 0; + return _entityToMessage.ContainsKey(entityID) && _entityToMessage[entityID].Count > 0; } public override void Clear() { - store.Clear(); - foreach (var set in entityToMessage.Values) + _store.Clear(); + foreach (var set in _entityToMessage.Values) { set.Clear(); } diff --git a/encompass-cs/ComponentManager.cs b/encompass-cs/ComponentManager.cs index a82511b..1e7aa8c 100644 --- a/encompass-cs/ComponentManager.cs +++ b/encompass-cs/ComponentManager.cs @@ -5,68 +5,68 @@ namespace Encompass { internal class ComponentManager { - private readonly DrawLayerManager drawLayerManager; + private readonly DrawLayerManager _drawLayerManager; - private readonly ComponentStore existingComponentStore; - private readonly ComponentStore immediateComponentStore; - private readonly ComponentDeltaStore replayStore; - private ComponentStore upToDateComponentStore; + private readonly ComponentStore _existingComponentStore; + private readonly ComponentStore _immediateComponentStore; + private readonly ComponentDeltaStore _replayStore; + private readonly ComponentStore _upToDateComponentStore; public Dictionary TypeToIndex { get; } - private readonly HashSet entitiesMarkedForRemoval = new HashSet(); + private readonly HashSet _entitiesMarkedForRemoval = new HashSet(); - internal ComponentBitSet ImmediateBits { get { return immediateComponentStore.ComponentBitSet; } } - internal ComponentBitSet ExistingBits { get { return existingComponentStore.ComponentBitSet; } } + internal ComponentBitSet ImmediateBits { get { return _immediateComponentStore.ComponentBitSet; } } + internal ComponentBitSet ExistingBits { get { return _existingComponentStore.ComponentBitSet; } } public ComponentManager(DrawLayerManager drawLayerManager, Dictionary typeToIndex) { - this.drawLayerManager = drawLayerManager; - existingComponentStore = new ComponentStore(typeToIndex); - immediateComponentStore = new ComponentStore(typeToIndex); - replayStore = new ComponentDeltaStore(typeToIndex); - upToDateComponentStore = new ComponentStore(typeToIndex); + this._drawLayerManager = drawLayerManager; + _existingComponentStore = new ComponentStore(typeToIndex); + _immediateComponentStore = new ComponentStore(typeToIndex); + _replayStore = new ComponentDeltaStore(typeToIndex); + _upToDateComponentStore = new ComponentStore(typeToIndex); TypeToIndex = typeToIndex; } public void RegisterComponentType() where TComponent : struct, IComponent { - existingComponentStore.RegisterComponentType(); - immediateComponentStore.RegisterComponentType(); - replayStore.RegisterComponentType(); - upToDateComponentStore.RegisterComponentType(); + _existingComponentStore.RegisterComponentType(); + _immediateComponentStore.RegisterComponentType(); + _replayStore.RegisterComponentType(); + _upToDateComponentStore.RegisterComponentType(); } internal void SetExistingComponentStore(ComponentStore componentStore) { - existingComponentStore.SwapWith(componentStore); + _existingComponentStore.SwapWith(componentStore); } internal void SetUpToDateComponentStore(ComponentStore componentStore) { - upToDateComponentStore.SwapWith(componentStore); + _upToDateComponentStore.SwapWith(componentStore); } internal void RegisterDrawableComponent(int entityID, TComponent component, int layer) where TComponent : struct, IComponent { - drawLayerManager.RegisterComponentWithLayer(entityID, component, layer); + _drawLayerManager.RegisterComponentWithLayer(entityID, component, layer); } internal void WriteComponents() { - existingComponentStore.UpdateUsing(replayStore); - existingComponentStore.ClearAllPriorities(); - upToDateComponentStore.ClearAllPriorities(); - immediateComponentStore.ClearAll(); - replayStore.ClearAll(); + _existingComponentStore.UpdateUsing(_replayStore); + _existingComponentStore.ClearAllPriorities(); + _upToDateComponentStore.ClearAllPriorities(); + _immediateComponentStore.ClearAll(); + _replayStore.ClearAll(); } internal bool AddImmediateComponent(int entityID, TComponent component, int priority) where TComponent : struct, IComponent { - if (immediateComponentStore.Set(entityID, component, priority)) + if (_immediateComponentStore.Set(entityID, component, priority)) { - replayStore.Set(entityID, component); - upToDateComponentStore.Set(entityID, component); + _replayStore.Set(entityID, component); + _upToDateComponentStore.Set(entityID, component); return true; } @@ -75,32 +75,32 @@ namespace Encompass internal void AddImmediateComponent(int entityID, TComponent component) where TComponent : struct, IComponent { - immediateComponentStore.Set(entityID, component); - replayStore.Set(entityID, component); - upToDateComponentStore.Set(entityID, component); + _immediateComponentStore.Set(entityID, component); + _replayStore.Set(entityID, component); + _upToDateComponentStore.Set(entityID, component); } internal bool UpdateComponent(int entityID, TComponent component, int priority) where TComponent : struct, IComponent { - var result = upToDateComponentStore.Set(entityID, component, priority); + var result = _upToDateComponentStore.Set(entityID, component, priority); if (result) { - replayStore.Set(entityID, component); + _replayStore.Set(entityID, component); } return result; } internal void AddComponent(int entityID, TComponent component) where TComponent : struct, IComponent { - upToDateComponentStore.Set(entityID, component); - replayStore.Set(entityID, component); + _upToDateComponentStore.Set(entityID, component); + _replayStore.Set(entityID, component); } // existing or immediate reads internal IEnumerable<(TComponent, int)> ReadExistingAndImmediateComponentsByType() where TComponent : struct, IComponent { - return upToDateComponentStore.All(); + return _upToDateComponentStore.All(); } internal (TComponent, int) ReadFirstExistingOrImmediateComponentByType() where TComponent : struct, IComponent @@ -113,7 +113,7 @@ namespace Encompass internal bool SomeExistingOrImmediateComponent() where TComponent : struct, IComponent { - return upToDateComponentStore.Any(); + return _upToDateComponentStore.Any(); } // existing reads @@ -128,14 +128,14 @@ namespace Encompass internal bool SomeExistingComponent() where TComponent : struct, IComponent { - return existingComponentStore.Any(); + return _existingComponentStore.Any(); } // immediate reads internal IEnumerable<(TComponent, int)> ReadImmediateComponentsByType() where TComponent : struct, IComponent { - return immediateComponentStore.All(); + return _immediateComponentStore.All(); } internal (TComponent, int) ReadFirstImmediateComponentByType() where TComponent : struct, IComponent @@ -148,66 +148,66 @@ namespace Encompass internal bool SomeImmediateComponent() where TComponent : struct, IComponent { - return immediateComponentStore.Any(); + return _immediateComponentStore.Any(); } // component getters internal ref readonly TComponent ReadImmediateOrExistingComponentByEntityAndType(int entityID) where TComponent : struct, IComponent { - return ref upToDateComponentStore.Get(entityID); + return ref _upToDateComponentStore.Get(entityID); } internal ref readonly TComponent ReadExistingComponentByEntityAndType(int entityID) where TComponent : struct, IComponent { - return ref existingComponentStore.Get(entityID); + return ref _existingComponentStore.Get(entityID); } internal ref readonly TComponent ReadImmediateComponentByEntityAndType(int entityID) where TComponent : struct, IComponent { - return ref immediateComponentStore.Get(entityID); + return ref _immediateComponentStore.Get(entityID); } // has checkers internal bool HasExistingOrImmediateComponent(int entityID) where TComponent : struct, IComponent { - return upToDateComponentStore.Has(entityID); + return _upToDateComponentStore.Has(entityID); } internal bool HasExistingOrImmediateComponent(int entityID, Type type) { - return upToDateComponentStore.Has(type, entityID); + return _upToDateComponentStore.Has(type, entityID); } internal bool HasExistingComponent(int entityID) where TComponent : struct, IComponent { - return existingComponentStore.Has(entityID); + return _existingComponentStore.Has(entityID); } internal bool HasExistingComponent(int entityID, Type type) { - return existingComponentStore.Has(type, entityID); + return _existingComponentStore.Has(type, entityID); } internal bool HasImmediateComponent(int entityID) where TComponent : struct, IComponent { - return immediateComponentStore.Has(entityID); + return _immediateComponentStore.Has(entityID); } internal bool HasImmediateComponent(int entityID, Type type) { - return immediateComponentStore.Has(type, entityID); + return _immediateComponentStore.Has(type, entityID); } internal IEnumerable<(TComponent, int)> GetComponentsIncludingEntity() where TComponent : struct, IComponent { - return existingComponentStore.All(); + return _existingComponentStore.All(); } internal IEnumerable GetComponentsByType() where TComponent : struct, IComponent { - foreach (var pair in existingComponentStore.All()) + foreach (var pair in _existingComponentStore.All()) { yield return pair.Item1; } @@ -215,40 +215,40 @@ namespace Encompass internal ref readonly TComponent GetComponentByEntityAndType(int entityID) where TComponent : struct, IComponent { - return ref existingComponentStore.Get(entityID); + return ref _existingComponentStore.Get(entityID); } internal bool EntityHasComponentOfType(int entityID) where TComponent : struct, IComponent { - return existingComponentStore.Has(entityID); + return _existingComponentStore.Has(entityID); } internal void MarkAllComponentsOnEntityForRemoval(int entityID) { - entitiesMarkedForRemoval.Add(entityID); + _entitiesMarkedForRemoval.Add(entityID); } internal void RemoveMarkedComponents() { - foreach (var entityID in entitiesMarkedForRemoval) + foreach (var entityID in _entitiesMarkedForRemoval) { - existingComponentStore.Remove(entityID); - immediateComponentStore.Remove(entityID); - replayStore.Remove(entityID); - upToDateComponentStore.Remove(entityID); - drawLayerManager.UnRegisterEntityWithLayer(entityID); + _existingComponentStore.Remove(entityID); + _immediateComponentStore.Remove(entityID); + _replayStore.Remove(entityID); + _upToDateComponentStore.Remove(entityID); + _drawLayerManager.UnRegisterEntityWithLayer(entityID); } - entitiesMarkedForRemoval.Clear(); + _entitiesMarkedForRemoval.Clear(); } public bool RemoveImmediate(int entityID, int priority) where TComponent : struct, IComponent { - if (immediateComponentStore.Remove(entityID, priority)) + if (_immediateComponentStore.Remove(entityID, priority)) { - replayStore.Remove(entityID, priority); - upToDateComponentStore.Remove(entityID, priority); - drawLayerManager.UnRegisterComponentWithLayer(entityID); + _replayStore.Remove(entityID, priority); + _upToDateComponentStore.Remove(entityID, priority); + _drawLayerManager.UnRegisterComponentWithLayer(entityID); return true; } return false; @@ -256,16 +256,16 @@ namespace Encompass public void Remove(int entityID, int priority) where TComponent : struct, IComponent { - if (upToDateComponentStore.Remove(entityID, priority)) + if (_upToDateComponentStore.Remove(entityID, priority)) { - replayStore.Remove(entityID, priority); - drawLayerManager.UnRegisterComponentWithLayer(entityID); + _replayStore.Remove(entityID, priority); + _drawLayerManager.UnRegisterComponentWithLayer(entityID); } } public bool UpToDateEntityIsEmpty(int entityID) { - return upToDateComponentStore.EntityBitArray(entityID).AllFalse(); + return _upToDateComponentStore.EntityBitArray(entityID).AllFalse(); } } } diff --git a/encompass-cs/DrawLayerManager.cs b/encompass-cs/DrawLayerManager.cs index b738fce..32bdec3 100644 --- a/encompass-cs/DrawLayerManager.cs +++ b/encompass-cs/DrawLayerManager.cs @@ -7,39 +7,39 @@ namespace Encompass { internal class DrawLayerManager { - private readonly SortedList layerOrder = new SortedList(); + private readonly SortedList _layerOrder = new SortedList(); - private readonly Dictionary layerIndexToComponentStore = new Dictionary(512); - private readonly Dictionary> layerIndexToGeneralRenderers = new Dictionary>(512); + private readonly Dictionary _layerIndexToComponentStore = new Dictionary(512); + private readonly Dictionary> _layerIndexToGeneralRenderers = new Dictionary>(512); - private readonly Dictionary> typeToEntityToLayer = new Dictionary>(512); - private Dictionary typeToIndex; - public IEnumerable LayerOrder { get { return layerOrder.Values; } } + private readonly Dictionary> _typeToEntityToLayer = new Dictionary>(512); + private readonly Dictionary _typeToIndex; + public IEnumerable LayerOrder { get { return _layerOrder.Values; } } public DrawLayerManager(Dictionary typeToIndex) { - this.typeToIndex = typeToIndex; + _typeToIndex = typeToIndex; RegisterDrawLayer(0); } public void RegisterDrawLayer(int layer) { - if (!layerIndexToComponentStore.ContainsKey(layer)) + if (!_layerIndexToComponentStore.ContainsKey(layer)) { - layerOrder.Add(layer, layer); - layerIndexToGeneralRenderers.Add(layer, new HashSet()); - layerIndexToComponentStore.Add(layer, new ComponentStore(typeToIndex)); + _layerOrder.Add(layer, layer); + _layerIndexToGeneralRenderers.Add(layer, new HashSet()); + _layerIndexToComponentStore.Add(layer, new ComponentStore(_typeToIndex)); } } public void RegisterOrderedDrawable() where TComponent : struct, IComponent { - if (!typeToEntityToLayer.ContainsKey(typeof(TComponent))) + if (!_typeToEntityToLayer.ContainsKey(typeof(TComponent))) { - typeToEntityToLayer.Add(typeof(TComponent), new Dictionary(128)); + _typeToEntityToLayer.Add(typeof(TComponent), new Dictionary(128)); } - foreach (var pair in layerIndexToComponentStore) + foreach (var pair in _layerIndexToComponentStore) { pair.Value.RegisterComponentType(); } @@ -48,15 +48,15 @@ namespace Encompass public void RegisterGeneralRendererWithLayer(GeneralRenderer renderer, int layer) { RegisterDrawLayer(layer); - var set = layerIndexToGeneralRenderers[layer]; + var set = _layerIndexToGeneralRenderers[layer]; set.Add(renderer); } public void UnregisterGeneralRendererWithLayer(GeneralRenderer renderer, int layer) { - if (layerIndexToGeneralRenderers.ContainsKey(layer)) + if (_layerIndexToGeneralRenderers.ContainsKey(layer)) { - layerIndexToGeneralRenderers[layer].Remove(renderer); + _layerIndexToGeneralRenderers[layer].Remove(renderer); } } @@ -68,34 +68,34 @@ namespace Encompass public void RegisterComponentWithLayer(int entityID, TComponent component, int layer) where TComponent : struct, IComponent { - if (!layerIndexToComponentStore.ContainsKey(layer)) + if (!_layerIndexToComponentStore.ContainsKey(layer)) { throw new UndefinedLayerException("Layer {0} is not defined. Use WorldBuilder.RegisterDrawLayer to register the layer.", layer); } - if (typeToEntityToLayer[typeof(TComponent)].ContainsKey(entityID)) { UnRegisterComponentWithLayer(entityID); } + if (_typeToEntityToLayer[typeof(TComponent)].ContainsKey(entityID)) { UnRegisterComponentWithLayer(entityID); } - var set = layerIndexToComponentStore[layer]; + var set = _layerIndexToComponentStore[layer]; set.Set(entityID, component); - typeToEntityToLayer[typeof(TComponent)].Add(entityID, layer); + _typeToEntityToLayer[typeof(TComponent)].Add(entityID, layer); } public void UnRegisterComponentWithLayer(int entityID) where TComponent : struct, IComponent { - if (!typeToEntityToLayer.ContainsKey(typeof(TComponent))) { return; } + if (!_typeToEntityToLayer.ContainsKey(typeof(TComponent))) { return; } - if (typeToEntityToLayer[typeof(TComponent)].ContainsKey(entityID)) + if (_typeToEntityToLayer[typeof(TComponent)].ContainsKey(entityID)) { - var layer = typeToEntityToLayer[typeof(TComponent)][entityID]; - layerIndexToComponentStore[layer].ForceRemove(entityID); + var layer = _typeToEntityToLayer[typeof(TComponent)][entityID]; + _layerIndexToComponentStore[layer].ForceRemove(entityID); } - typeToEntityToLayer[typeof(TComponent)].Remove(entityID); + _typeToEntityToLayer[typeof(TComponent)].Remove(entityID); } public void UnRegisterEntityWithLayer(int entityID) { - foreach (var store in layerIndexToComponentStore.Values) + foreach (var store in _layerIndexToComponentStore.Values) { store.Remove(entityID); } @@ -103,15 +103,15 @@ namespace Encompass public IEnumerable GeneralRenderersByLayer(int layer) { - return layerIndexToGeneralRenderers.ContainsKey(layer) ? - layerIndexToGeneralRenderers[layer] : + return _layerIndexToGeneralRenderers.ContainsKey(layer) ? + _layerIndexToGeneralRenderers[layer] : Enumerable.Empty(); } public IEnumerable<(int, Type, IComponent)> AllInLayer(int layer) { - return layerIndexToComponentStore.ContainsKey(layer) ? - layerIndexToComponentStore[layer].AllInterfaceTyped() : + return _layerIndexToComponentStore.ContainsKey(layer) ? + _layerIndexToComponentStore[layer].AllInterfaceTyped() : Enumerable.Empty<(int, Type, IComponent)>(); } } diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index 2d55290..c371b50 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -14,104 +14,104 @@ namespace Encompass /// public abstract class Engine : IEquatable { - internal Guid ID; + internal Guid _id; - internal readonly HashSet readTypes = new HashSet(); - internal readonly HashSet readImmediateTypes = new HashSet(); - internal readonly HashSet sendTypes = new HashSet(); - internal readonly HashSet receiveTypes = new HashSet(); - internal readonly HashSet writeTypes = new HashSet(); - internal readonly HashSet writeImmediateTypes = new HashSet(); - internal readonly HashSet queryWithTypes = new HashSet(); - internal readonly HashSet queryWithoutTypes = new HashSet(); - internal readonly Dictionary writePriorities = new Dictionary(); - internal readonly int defaultWritePriority = 0; + internal readonly HashSet ReadTypes = new HashSet(); + internal readonly HashSet ReadImmediateTypes = new HashSet(); + internal readonly HashSet SendTypes = new HashSet(); + internal readonly HashSet ReceiveTypes = new HashSet(); + internal readonly HashSet WriteTypes = new HashSet(); + internal readonly HashSet WriteImmediateTypes = new HashSet(); + internal readonly HashSet QueryWithTypes = new HashSet(); + internal readonly HashSet QueryWithoutTypes = new HashSet(); + internal readonly Dictionary WritePriorities = new Dictionary(); + internal readonly int DefaultWritePriority = 0; /// /// If false, the Engine will ignore time dilation. /// - internal bool usesTimeDilation = true; - public bool TimeDilationActive { get => usesTimeDilation && timeManager.TimeDilationActive; } + internal bool _usesTimeDilation = true; + public bool TimeDilationActive { get => _usesTimeDilation && _timeManager.TimeDilationActive; } - private EntityManager entityManager; - private MessageManager messageManager; - private ComponentManager componentManager; - private TimeManager timeManager; - private TrackingManager trackingManager; + private EntityManager _entityManager; + private MessageManager _messageManager; + private ComponentManager _componentManager; + private TimeManager _timeManager; + private TrackingManager _trackingManager; - private EntitySetQuery entityQuery; + private EntitySetQuery _entityQuery; - private HashSet _trackedEntities = new HashSet(); + private readonly HashSet _trackedEntities = new HashSet(); protected IEnumerable TrackedEntities { get { foreach (var entityID in _trackedEntities) { - yield return entityManager.GetEntity(entityID); + yield return _entityManager.GetEntity(entityID); } } } - private HashSet _newlyCreatedEntities = new HashSet(); + private readonly HashSet _newlyCreatedEntities = new HashSet(); protected Engine() { - ID = Guid.NewGuid(); + _id = Guid.NewGuid(); var sendsAttribute = GetType().GetCustomAttribute(false); if (sendsAttribute != null) { - sendTypes = sendsAttribute.sendTypes; + SendTypes = sendsAttribute.SendTypes; } var activatesAttribute = GetType().GetCustomAttribute(false); if (activatesAttribute != null) { - writeImmediateTypes = activatesAttribute.writeImmediateTypes; + WriteImmediateTypes = activatesAttribute.WriteImmediateTypes; } var defaultWritePriorityAttribute = GetType().GetCustomAttribute(false); if (defaultWritePriorityAttribute != null) { - defaultWritePriority = defaultWritePriorityAttribute.writePriority; + DefaultWritePriority = defaultWritePriorityAttribute.WritePriority; } foreach (var writesAttribute in GetType().GetCustomAttributes(false)) { - writeTypes.UnionWith(writesAttribute.writeTypes); - writePriorities = new Dictionary[2] { writePriorities, writesAttribute.priorities }.SelectMany(dict => dict).ToDictionary(pair => pair.Key, pair => pair.Value); + WriteTypes.UnionWith(writesAttribute.WriteTypes); + WritePriorities = new Dictionary[2] { WritePriorities, writesAttribute.Priorities }.SelectMany(dict => dict).ToDictionary(pair => pair.Key, pair => pair.Value); } var receivesAttribute = GetType().GetCustomAttribute(false); if (receivesAttribute != null) { - receiveTypes = receivesAttribute.receiveTypes; + ReceiveTypes = receivesAttribute.ReceiveTypes; } var readsAttribute = GetType().GetCustomAttribute(false); if (readsAttribute != null) { - readTypes = readsAttribute.readTypes; + ReadTypes = readsAttribute.ReadTypes; } var readsImmediateAttribute = GetType().GetCustomAttribute(false); if (readsImmediateAttribute != null) { - readImmediateTypes = readsImmediateAttribute.readImmediateTypes; + ReadImmediateTypes = readsImmediateAttribute.ReadImmediateTypes; } var queryWithAttribute = GetType().GetCustomAttribute(false); if (queryWithAttribute != null) { - queryWithTypes = queryWithAttribute.queryWithTypes; + QueryWithTypes = queryWithAttribute.QueryWithTypes.ToHashSet(); } var queryWithoutAttribute = GetType().GetCustomAttribute(false); if (queryWithoutAttribute != null) { - queryWithoutTypes = queryWithoutAttribute.queryWithoutTypes; + QueryWithoutTypes = queryWithoutAttribute.QueryWithoutTypes; } } @@ -127,42 +127,42 @@ namespace Encompass public bool Equals(Engine other) { - return other.ID == ID; + return other._id == _id; } public override int GetHashCode() { - return ID.GetHashCode(); + return HashCode.Combine(_id); } internal void AssignEntityManager(EntityManager entityManager) { - this.entityManager = entityManager; + _entityManager = entityManager; } internal void AssignComponentManager(ComponentManager componentManager) { - this.componentManager = componentManager; + _componentManager = componentManager; } internal void AssignMessageManager(MessageManager messageManager) { - this.messageManager = messageManager; + _messageManager = messageManager; } internal void AssignTimeManager(TimeManager timeManager) { - this.timeManager = timeManager; + _timeManager = timeManager; } internal void AssignTrackingManager(TrackingManager trackingManager) { - this.trackingManager = trackingManager; + _trackingManager = trackingManager; } internal void CheckMessageRead() where TMessage : struct, IMessage { - if (!receiveTypes.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); } @@ -189,7 +189,7 @@ namespace Encompass /// protected Entity CreateEntity() { - var entity = entityManager.CreateEntity(); + var entity = _entityManager.CreateEntity(); _newlyCreatedEntities.Add(entity.ID); return entity; } @@ -199,7 +199,7 @@ namespace Encompass /// protected bool EntityExists(Entity entity) { - return entityManager.EntityExists(entity.ID); + return _entityManager.EntityExists(entity.ID); } /// @@ -207,7 +207,7 @@ namespace Encompass /// protected bool EntityExists(int entityID) { - return entityManager.EntityExists(entityID); + return _entityManager.EntityExists(entityID); } /// @@ -215,7 +215,7 @@ namespace Encompass /// protected Entity ReadEntity() where TComponent : struct, IComponent { - return entityManager.GetEntity(ReadComponentHelper().Item2); + return _entityManager.GetEntity(ReadComponentHelper().Item2); } /// @@ -225,7 +225,7 @@ namespace Encompass { foreach (var pair in ReadComponentsHelper()) { - yield return entityManager.GetEntity(pair.Item2); + yield return _entityManager.GetEntity(pair.Item2); } } @@ -233,24 +233,24 @@ namespace Encompass internal IEnumerable ReadComponentsFromWorld() where TComponent : struct, IComponent { - return componentManager.GetComponentsByType(); + return _componentManager.GetComponentsByType(); } private IEnumerable<(TComponent, int)> ReadComponentsHelper() where TComponent : struct, IComponent { - var immediateRead = readImmediateTypes.Contains(typeof(TComponent)); - var existingRead = readTypes.Contains(typeof(TComponent)); + var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); + var existingRead = ReadTypes.Contains(typeof(TComponent)); if (existingRead && immediateRead) { - return componentManager.ReadExistingAndImmediateComponentsByType(); + return _componentManager.ReadExistingAndImmediateComponentsByType(); } else if (existingRead) { - return componentManager.GetComponentsIncludingEntity(); + return _componentManager.GetComponentsIncludingEntity(); } else if (immediateRead) { - return componentManager.ReadImmediateComponentsByType(); + return _componentManager.ReadImmediateComponentsByType(); } else { @@ -276,25 +276,25 @@ namespace Encompass { foreach (var (component, id) in ReadComponentsHelper()) { - yield return (component, entityManager.GetEntity(id)); + yield return (component, _entityManager.GetEntity(id)); } } private (TComponent, int) ReadComponentHelper() where TComponent : struct, IComponent { - var immediateRead = readImmediateTypes.Contains(typeof(TComponent)); - var existingRead = readTypes.Contains(typeof(TComponent)); + var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); + var existingRead = ReadTypes.Contains(typeof(TComponent)); if (existingRead && immediateRead) { - return componentManager.ReadFirstExistingOrImmediateComponentByType(); + return _componentManager.ReadFirstExistingOrImmediateComponentByType(); } else if (existingRead) { - return componentManager.ReadFirstExistingComponentByType(); + return _componentManager.ReadFirstExistingComponentByType(); } else if (immediateRead) { - return componentManager.ReadFirstImmediateComponentByType(); + return _componentManager.ReadFirstImmediateComponentByType(); } else { @@ -316,7 +316,7 @@ namespace Encompass protected (TComponent, Entity) ReadComponentIncludingEntity() where TComponent : struct, IComponent { var (component, id) = ReadComponentHelper(); - return (component, entityManager.GetEntity(id)); + return (component, _entityManager.GetEntity(id)); } /// @@ -324,19 +324,19 @@ namespace Encompass /// protected bool SomeComponent() where TComponent : struct, IComponent { - var immediateRead = readImmediateTypes.Contains(typeof(TComponent)); - var existingRead = readTypes.Contains(typeof(TComponent)); + var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); + var existingRead = ReadTypes.Contains(typeof(TComponent)); if (existingRead && immediateRead) { - return componentManager.SomeExistingOrImmediateComponent(); + return _componentManager.SomeExistingOrImmediateComponent(); } else if (existingRead) { - return componentManager.SomeExistingComponent(); + return _componentManager.SomeExistingComponent(); } else if (immediateRead) { - return componentManager.SomeImmediateComponent(); + return _componentManager.SomeImmediateComponent(); } else { @@ -346,19 +346,19 @@ namespace Encompass private ref readonly TComponent GetComponentHelper(int entityID) where TComponent : struct, IComponent { - var immediateRead = readImmediateTypes.Contains(typeof(TComponent)); - var existingRead = readTypes.Contains(typeof(TComponent)); + var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); + var existingRead = ReadTypes.Contains(typeof(TComponent)); if (existingRead && immediateRead) { - return ref componentManager.ReadImmediateOrExistingComponentByEntityAndType(entityID); + return ref _componentManager.ReadImmediateOrExistingComponentByEntityAndType(entityID); } else if (existingRead) { - return ref componentManager.ReadExistingComponentByEntityAndType(entityID); + return ref _componentManager.ReadExistingComponentByEntityAndType(entityID); } else if (immediateRead) { - return ref componentManager.ReadImmediateComponentByEntityAndType(entityID); + return ref _componentManager.ReadImmediateComponentByEntityAndType(entityID); } else { @@ -388,20 +388,20 @@ namespace Encompass /// protected bool HasComponent(Entity entity) where TComponent : struct, IComponent { - var immediateRead = readImmediateTypes.Contains(typeof(TComponent)); - var existingRead = readTypes.Contains(typeof(TComponent)); + var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); + var existingRead = ReadTypes.Contains(typeof(TComponent)); if (immediateRead && existingRead) { - return componentManager.HasExistingOrImmediateComponent(entity.ID); + return _componentManager.HasExistingOrImmediateComponent(entity.ID); } else if (existingRead) { - return componentManager.HasExistingComponent(entity.ID); + return _componentManager.HasExistingComponent(entity.ID); } else if (immediateRead) { - return componentManager.HasImmediateComponent(entity.ID); + return _componentManager.HasImmediateComponent(entity.ID); } else { @@ -417,20 +417,20 @@ namespace Encompass /// protected bool HasComponent(Entity entity, Type type) { - var immediateRead = readImmediateTypes.Contains(type); - var existingRead = readTypes.Contains(type); + var immediateRead = ReadImmediateTypes.Contains(type); + var existingRead = ReadTypes.Contains(type); if (immediateRead && existingRead) { - return componentManager.HasExistingOrImmediateComponent(entity.ID, type); + return _componentManager.HasExistingOrImmediateComponent(entity.ID, type); } else if (existingRead) { - return componentManager.HasExistingComponent(entity.ID, type); + return _componentManager.HasExistingComponent(entity.ID, type); } else if (immediateRead) { - return componentManager.HasImmediateComponent(entity.ID, type); + return _componentManager.HasImmediateComponent(entity.ID, type); } else { @@ -446,35 +446,35 @@ namespace Encompass /// protected void SetComponent(Entity entity, TComponent component) where TComponent : struct, IComponent { - var priority = writePriorities.ContainsKey(typeof(TComponent)) ? writePriorities[typeof(TComponent)] : defaultWritePriority; + var priority = WritePriorities.ContainsKey(typeof(TComponent)) ? WritePriorities[typeof(TComponent)] : DefaultWritePriority; - if (!writeTypes.Contains(typeof(TComponent))) + if (!WriteTypes.Contains(typeof(TComponent))) { throw new IllegalWriteException("Engine {0} tried to update undeclared Component {1}", GetType().Name, typeof(TComponent).Name); } bool written; - if (writeImmediateTypes.Contains(typeof(TComponent))) + if (WriteImmediateTypes.Contains(typeof(TComponent))) { - written = componentManager.AddImmediateComponent(entity.ID, component, priority); + written = _componentManager.AddImmediateComponent(entity.ID, component, priority); if (written) { - trackingManager.ImmediateUpdateTracking(entity.ID, typeof(TComponent)); + _trackingManager.ImmediateUpdateTracking(entity.ID, typeof(TComponent)); } } else { - written = componentManager.UpdateComponent(entity.ID, component, priority); + written = _componentManager.UpdateComponent(entity.ID, component, priority); } - if (!componentManager.HasExistingComponent(entity.ID)) + if (!_componentManager.HasExistingComponent(entity.ID)) { - trackingManager.RegisterAddition(entity.ID, typeof(TComponent)); + _trackingManager.RegisterAddition(entity.ID, typeof(TComponent)); } if (written && component is IDrawableComponent drawableComponent) { - componentManager.RegisterDrawableComponent(entity.ID, component, drawableComponent.Layer); + _componentManager.RegisterDrawableComponent(entity.ID, component, drawableComponent.Layer); } } @@ -491,21 +491,21 @@ namespace Encompass throw new IllegalWriteException("AddComponent used on Entity that was not created in this context. Use SetComponent instead."); } - if (writeImmediateTypes.Contains(typeof(TComponent))) + if (WriteImmediateTypes.Contains(typeof(TComponent))) { - componentManager.AddImmediateComponent(entity.ID, component); - trackingManager.ImmediateUpdateTracking(entity.ID, typeof(TComponent)); + _componentManager.AddImmediateComponent(entity.ID, component); + _trackingManager.ImmediateUpdateTracking(entity.ID, typeof(TComponent)); } else { - componentManager.AddComponent(entity.ID, component); + _componentManager.AddComponent(entity.ID, component); } - trackingManager.RegisterAddition(entity.ID, typeof(TComponent)); + _trackingManager.RegisterAddition(entity.ID, typeof(TComponent)); if (component is IDrawableComponent drawableComponent) { - componentManager.RegisterDrawableComponent(entity.ID, component, drawableComponent.Layer); + _componentManager.RegisterDrawableComponent(entity.ID, component, drawableComponent.Layer); } } @@ -517,12 +517,12 @@ namespace Encompass /// protected void SendMessage(TMessage message) where TMessage : struct, IMessage { - if (!sendTypes.Contains(typeof(TMessage))) + if (!SendTypes.Contains(typeof(TMessage))) { throw new IllegalSendException("Engine {0} tried to send undeclared Message {1}", GetType().Name, typeof(TMessage).Name); } - messageManager.AddMessage(message); + _messageManager.AddMessage(message); } /// @@ -531,7 +531,7 @@ namespace Encompass /// The time in seconds that will elapse before the message is sent. protected void SendMessage(TMessage message, double time) where TMessage : struct, IMessage { - messageManager.AddMessage(message, time); + _messageManager.AddMessage(message, time); } /// @@ -540,7 +540,7 @@ namespace Encompass /// The time in seconds that will elapse before the message is sent. protected void SendMessageIgnoringTimeDilation(TMessage message, double time) where TMessage : struct, IMessage { - messageManager.AddMessageIgnoringTimeDilation(message, time); + _messageManager.AddMessageIgnoringTimeDilation(message, time); } /// @@ -552,7 +552,7 @@ namespace Encompass protected IEnumerable ReadMessages() where TMessage : struct, IMessage { CheckMessageRead(); - return messageManager.GetMessagesByType(); + return _messageManager.GetMessagesByType(); } /// @@ -564,7 +564,7 @@ namespace Encompass protected TMessage ReadMessage() where TMessage : struct, IMessage { CheckMessageRead(); - return messageManager.First(); + return _messageManager.First(); } /// @@ -576,7 +576,7 @@ namespace Encompass protected bool SomeMessage() where TMessage : struct, IMessage { CheckMessageRead(); - return messageManager.Any(); + return _messageManager.Any(); } /// @@ -585,7 +585,7 @@ namespace Encompass /// protected void Destroy(Entity entity) { - entityManager.MarkForDestroy(entity.ID); + _entityManager.MarkForDestroy(entity.ID); } /// @@ -616,28 +616,28 @@ namespace Encompass /// protected void RemoveComponent(Entity entity) where TComponent : struct, IComponent { - var priority = writePriorities.ContainsKey(typeof(TComponent)) ? writePriorities[typeof(TComponent)] : defaultWritePriority; + var priority = WritePriorities.ContainsKey(typeof(TComponent)) ? WritePriorities[typeof(TComponent)] : DefaultWritePriority; - if (!writeTypes.Contains(typeof(TComponent))) + if (!WriteTypes.Contains(typeof(TComponent))) { throw new IllegalWriteException("Engine {0} tried to remove undeclared Component {1}. Declare with Writes attribute.", GetType().Name, typeof(TComponent).Name); } - if (writeImmediateTypes.Contains(typeof(TComponent))) + if (WriteImmediateTypes.Contains(typeof(TComponent))) { - if (componentManager.RemoveImmediate(entity.ID, priority)) + if (_componentManager.RemoveImmediate(entity.ID, priority)) { - trackingManager.ImmediateUpdateTracking(entity.ID, typeof(TComponent)); + _trackingManager.ImmediateUpdateTracking(entity.ID, typeof(TComponent)); } } else { - componentManager.Remove(entity.ID, priority); + _componentManager.Remove(entity.ID, priority); } - if (componentManager.HasExistingComponent(entity.ID)) + if (_componentManager.HasExistingComponent(entity.ID)) { - trackingManager.RegisterRemoval(entity.ID, typeof(TComponent)); + _trackingManager.RegisterRemoval(entity.ID, typeof(TComponent)); } } @@ -652,7 +652,7 @@ namespace Encompass /// The time that will elapse before time is fully undilated. protected void ActivateTimeDilation(double factor, double easeInTime, double activeTime, double easeOutTime) { - timeManager.ActivateTimeDilation(factor, easeInTime, activeTime, easeOutTime); + _timeManager.ActivateTimeDilation(factor, easeInTime, activeTime, easeOutTime); } /// @@ -667,7 +667,7 @@ namespace Encompass /// The time that will elapse before time is fully undilated. protected void ActivateTimeDilation(double factor, double easeInTime, System.Func easeInFunction, double activeTime, double easeOutTime) { - timeManager.ActivateTimeDilation(factor, easeInTime, easeInFunction, activeTime, easeOutTime); + _timeManager.ActivateTimeDilation(factor, easeInTime, easeInFunction, activeTime, easeOutTime); } /// @@ -682,7 +682,7 @@ namespace Encompass /// An easing function for the easing out of time dilation. protected void ActivateTimeDilation(double factor, double easeInTime, double activeTime, double easeOutTime, System.Func easeOutFunction) { - timeManager.ActivateTimeDilation(factor, easeInTime, activeTime, easeOutTime, easeOutFunction); + _timeManager.ActivateTimeDilation(factor, easeInTime, activeTime, easeOutTime, easeOutFunction); } /// @@ -698,7 +698,7 @@ namespace Encompass /// An easing function for the easing out of time dilation. protected void ActivateTimeDilation(double factor, double easeInTime, System.Func easeInFunction, double activeTime, double easeOutTime, System.Func easeOutFunction) { - timeManager.ActivateTimeDilation(factor, easeInTime, easeInFunction, activeTime, easeOutTime, easeOutFunction); + _timeManager.ActivateTimeDilation(factor, easeInTime, easeInFunction, activeTime, easeOutTime, easeOutFunction); } /// @@ -710,7 +710,7 @@ namespace Encompass protected IEnumerable ReadMessagesWithEntity(Entity entity) where TMessage : struct, IMessage, IHasEntity { CheckMessageRead(); - return messageManager.WithEntity(entity.ID); + return _messageManager.WithEntity(entity.ID); } /// @@ -720,7 +720,7 @@ namespace Encompass protected TMessage ReadMessageWithEntity(Entity entity) where TMessage : struct, IMessage, IHasEntity { CheckMessageRead(); - return messageManager.WithEntitySingular(entity.ID); + return _messageManager.WithEntitySingular(entity.ID); } /// @@ -729,16 +729,16 @@ namespace Encompass protected bool SomeMessageWithEntity(Entity entity) where TMessage : struct, IMessage, IHasEntity { CheckMessageRead(); - return messageManager.SomeWithEntity(entity.ID); + return _messageManager.SomeWithEntity(entity.ID); } internal void CheckAndUpdateTracking(int entityID) { - if (_trackedEntities.Contains(entityID) && !entityQuery.CheckEntity(entityID, componentManager.ExistingBits)) + if (_trackedEntities.Contains(entityID) && !_entityQuery.CheckEntity(entityID, _componentManager.ExistingBits)) { _trackedEntities.Remove(entityID); } - else if (!_trackedEntities.Contains(entityID) && entityQuery.CheckEntity(entityID, componentManager.ExistingBits)) + else if (!_trackedEntities.Contains(entityID) && _entityQuery.CheckEntity(entityID, _componentManager.ExistingBits)) { _trackedEntities.Add(entityID); } @@ -746,11 +746,11 @@ namespace Encompass internal void ImmediateCheckAndUpdateTracking(int entityID) { - if (_trackedEntities.Contains(entityID) && !entityQuery.ImmediateCheckEntity(entityID, componentManager.ImmediateBits, componentManager.ExistingBits)) + if (_trackedEntities.Contains(entityID) && !_entityQuery.ImmediateCheckEntity(entityID, _componentManager.ImmediateBits, _componentManager.ExistingBits)) { _trackedEntities.Remove(entityID); } - else if (!_trackedEntities.Contains(entityID) && entityQuery.ImmediateCheckEntity(entityID, componentManager.ImmediateBits, componentManager.ExistingBits)) + else if (!_trackedEntities.Contains(entityID) && _entityQuery.ImmediateCheckEntity(entityID, _componentManager.ImmediateBits, _componentManager.ExistingBits)) { _trackedEntities.Add(entityID); } @@ -762,30 +762,30 @@ namespace Encompass internal void BuildEntityQuery() { var withMask = BitSet512.Zero; - foreach (var type in queryWithTypes) + foreach (var type in QueryWithTypes) { - withMask = withMask.Set(componentManager.TypeToIndex[type]); + withMask = withMask.Set(_componentManager.TypeToIndex[type]); } var withoutMask = BitSet512.Zero; - foreach (var type in queryWithoutTypes) + foreach (var type in QueryWithoutTypes) { - withoutMask = withoutMask.Set(componentManager.TypeToIndex[type]); + withoutMask = withoutMask.Set(_componentManager.TypeToIndex[type]); } var immediateMask = BitSet512.Zero; - foreach (var type in readImmediateTypes) + foreach (var type in ReadImmediateTypes) { - immediateMask = immediateMask.Set(componentManager.TypeToIndex[type]); + immediateMask = immediateMask.Set(_componentManager.TypeToIndex[type]); } var existingMask = BitSet512.Zero; - foreach (var type in readTypes) + foreach (var type in ReadTypes) { - existingMask = existingMask.Set(componentManager.TypeToIndex[type]); + existingMask = existingMask.Set(_componentManager.TypeToIndex[type]); } - entityQuery = new EntitySetQuery( + _entityQuery = new EntitySetQuery( withMask & immediateMask, withMask & existingMask, withoutMask & immediateMask, diff --git a/encompass-cs/Engines/Spawner.cs b/encompass-cs/Engines/Spawner.cs index 3ad21bf..a1f6e4e 100644 --- a/encompass-cs/Engines/Spawner.cs +++ b/encompass-cs/Engines/Spawner.cs @@ -13,10 +13,10 @@ namespace Encompass var readsAttribute = GetType().GetCustomAttribute(false); if (readsAttribute != null) { - readsAttribute.readTypes.Add(typeof(TMessage)); + readsAttribute.ReadTypes.Add(typeof(TMessage)); } - receiveTypes.Add(typeof(TMessage)); + ReceiveTypes.Add(typeof(TMessage)); } public override void Update(double dt) diff --git a/encompass-cs/Entity.cs b/encompass-cs/Entity.cs index 7287499..d7913ea 100644 --- a/encompass-cs/Entity.cs +++ b/encompass-cs/Entity.cs @@ -37,7 +37,7 @@ namespace Encompass public override int GetHashCode() { - return ID.GetHashCode(); + return HashCode.Combine(ID); } } } diff --git a/encompass-cs/EntityManager.cs b/encompass-cs/EntityManager.cs index c800281..a45f0a4 100644 --- a/encompass-cs/EntityManager.cs +++ b/encompass-cs/EntityManager.cs @@ -5,48 +5,48 @@ namespace Encompass { internal class EntityManager { - private readonly int entityCapacity; - private readonly IDManager idManager = new IDManager(); - private readonly HashSet IDs = new HashSet(); + private readonly int _entityCapacity; + private readonly IDManager _idManager = new IDManager(); + private readonly HashSet _ids = new HashSet(); - private readonly HashSet entitiesMarkedForDestroy = new HashSet(); + private readonly HashSet _entitiesMarkedForDestroy = new HashSet(); - private readonly ComponentManager componentManager; + private readonly ComponentManager _componentManager; public IEnumerable EntityIDs { - get { return IDs; } + get { return _ids; } } public EntityManager(ComponentManager componentManager, int entityCapacity) { - this.componentManager = componentManager; - this.entityCapacity = entityCapacity; + _componentManager = componentManager; + _entityCapacity = entityCapacity; } private int NextID() { - return idManager.NextID(); + return _idManager.NextID(); } public Entity CreateEntity() { - if (IDs.Count < entityCapacity) + if (_ids.Count < _entityCapacity) { var id = NextID(); var entity = new Entity(id); - IDs.Add(id); + _ids.Add(id); return entity; } else { - throw new EntityOverflowException("The number of entities has exceeded the entity capacity of {0}", entityCapacity); + throw new EntityOverflowException("The number of entities has exceeded the entity capacity of {0}", _entityCapacity); } } public bool EntityExists(int id) { - return IDs.Contains(id); + return _ids.Contains(id); } public Entity GetEntity(int id) @@ -61,20 +61,20 @@ namespace Encompass public void MarkForDestroy(int entityID) { - entitiesMarkedForDestroy.Add(entityID); + _entitiesMarkedForDestroy.Add(entityID); } public void DestroyMarkedEntities(IEnumerable engines) { - foreach (var entityID in entitiesMarkedForDestroy) + foreach (var entityID in _entitiesMarkedForDestroy) { foreach (var engine in engines) { engine.RegisterDestroyedEntity(entityID); } - componentManager.MarkAllComponentsOnEntityForRemoval(entityID); - IDs.Remove(entityID); - idManager.Free(entityID); + _componentManager.MarkAllComponentsOnEntityForRemoval(entityID); + _ids.Remove(entityID); + _idManager.Free(entityID); } - entitiesMarkedForDestroy.Clear(); + _entitiesMarkedForDestroy.Clear(); } // NOTE: this is very suboptimal @@ -82,7 +82,7 @@ namespace Encompass { foreach (var id in EntityIDs) { - if (componentManager.UpToDateEntityIsEmpty(id)) + if (_componentManager.UpToDateEntityIsEmpty(id)) { MarkForDestroy(id); } diff --git a/encompass-cs/IDManager.cs b/encompass-cs/IDManager.cs index 01bb529..360f580 100644 --- a/encompass-cs/IDManager.cs +++ b/encompass-cs/IDManager.cs @@ -4,25 +4,25 @@ namespace Encompass { internal class IDManager { - int nextID = 0; + int _nextID = 0; - private Stack availableIDs = new Stack(); + private readonly Stack _availableIDs = new Stack(); public int NextID() { - if (availableIDs.Count > 0) + if (_availableIDs.Count > 0) { - return availableIDs.Pop(); + return _availableIDs.Pop(); } else { - return nextID++; + return _nextID++; } } - public void Free(int ID) + public void Free(int id) { - availableIDs.Push(ID); + _availableIDs.Push(id); } } } diff --git a/encompass-cs/MessageManager.cs b/encompass-cs/MessageManager.cs index c9e53ae..c662b6e 100644 --- a/encompass-cs/MessageManager.cs +++ b/encompass-cs/MessageManager.cs @@ -4,69 +4,69 @@ namespace Encompass { internal class MessageManager { - private readonly TimeManager timeManager; - private readonly MessageStore messageStore = new MessageStore(); + private readonly TimeManager _timeManager; + private readonly MessageStore _messageStore = new MessageStore(); public MessageManager(TimeManager timeManager) { - this.timeManager = timeManager; + _timeManager = timeManager; } internal void AddMessage(TMessage message) where TMessage : struct, IMessage { - messageStore.AddMessage(message); + _messageStore.AddMessage(message); } internal void AddMessage(TMessage message, double time) where TMessage : struct, IMessage { - messageStore.AddMessage(message, time); + _messageStore.AddMessage(message, time); } internal void AddMessageIgnoringTimeDilation(TMessage message, double time) where TMessage : struct, IMessage { - messageStore.AddMessageIgnoringTimeDilation(message, time); + _messageStore.AddMessageIgnoringTimeDilation(message, time); } internal void ClearMessages() { - messageStore.ClearAll(); + _messageStore.ClearAll(); } internal void ProcessDelayedMessages(double dt) { - messageStore.ProcessDelayedMessages(dt * timeManager.TimeDilationFactor, dt); + _messageStore.ProcessDelayedMessages(dt * _timeManager.TimeDilationFactor, dt); } internal IEnumerable GetMessagesByType() where TMessage : struct, IMessage { - return messageStore.All(); + return _messageStore.All(); } internal bool Any() where TMessage : struct, IMessage { - return messageStore.Any(); + return _messageStore.Any(); } internal TMessage First() where TMessage : struct, IMessage { - return messageStore.First(); + return _messageStore.First(); } internal IEnumerable WithEntity(int entityID) where TMessage : struct, IMessage, IHasEntity { - return messageStore.WithEntity(entityID); + return _messageStore.WithEntity(entityID); } internal TMessage WithEntitySingular(int entityID) where TMessage : struct, IMessage, IHasEntity { - var enumerator = messageStore.WithEntity(entityID).GetEnumerator(); + var enumerator = _messageStore.WithEntity(entityID).GetEnumerator(); enumerator.MoveNext(); return enumerator.Current; } internal bool SomeWithEntity(int entityID) where TMessage : struct, IMessage, IHasEntity { - return messageStore.SomeWithEntity(entityID); + return _messageStore.SomeWithEntity(entityID); } } } diff --git a/encompass-cs/RenderManager.cs b/encompass-cs/RenderManager.cs index 529a431..6469c2f 100644 --- a/encompass-cs/RenderManager.cs +++ b/encompass-cs/RenderManager.cs @@ -5,40 +5,40 @@ namespace Encompass { internal class RenderManager { - private readonly EntityManager entityManager; - private readonly DrawLayerManager drawLayerManager; + private readonly EntityManager _entityManager; + private readonly DrawLayerManager _drawLayerManager; - private readonly Dictionary> drawComponentTypeToOrderedRenderer = new Dictionary>(256); + private readonly Dictionary> _drawComponentTypeToOrderedRenderer = new Dictionary>(256); public RenderManager(EntityManager entityManager, DrawLayerManager drawLayerManager) { - this.entityManager = entityManager; - this.drawLayerManager = drawLayerManager; + _entityManager = entityManager; + _drawLayerManager = drawLayerManager; } public void RegisterOrderedRenderer(Action renderAction) where TComponent : struct, IComponent { - drawComponentTypeToOrderedRenderer.Add(typeof(TComponent), renderAction); - drawLayerManager.RegisterOrderedDrawable(); + _drawComponentTypeToOrderedRenderer.Add(typeof(TComponent), renderAction); + _drawLayerManager.RegisterOrderedDrawable(); } public void RegisterGeneralRendererWithLayer(GeneralRenderer renderer, int layer) { - drawLayerManager.RegisterGeneralRendererWithLayer(renderer, layer); + _drawLayerManager.RegisterGeneralRendererWithLayer(renderer, layer); } public void Draw() { - foreach (var layer in drawLayerManager.LayerOrder) + foreach (var layer in _drawLayerManager.LayerOrder) { - var generalRendererSet = drawLayerManager.GeneralRenderersByLayer(layer); + var generalRendererSet = _drawLayerManager.GeneralRenderersByLayer(layer); - foreach (var (entityID, componentType, component) in drawLayerManager.AllInLayer(layer)) + foreach (var (entityID, componentType, component) in _drawLayerManager.AllInLayer(layer)) { - if (drawComponentTypeToOrderedRenderer.ContainsKey(componentType)) + if (_drawComponentTypeToOrderedRenderer.ContainsKey(componentType)) { - var internalRenderAction = drawComponentTypeToOrderedRenderer[componentType]; - internalRenderAction(entityManager.GetEntity(entityID), component); + var internalRenderAction = _drawComponentTypeToOrderedRenderer[componentType]; + internalRenderAction(_entityManager.GetEntity(entityID), component); } } diff --git a/encompass-cs/Renderer.cs b/encompass-cs/Renderer.cs index 9ac5887..f7f3b88 100644 --- a/encompass-cs/Renderer.cs +++ b/encompass-cs/Renderer.cs @@ -4,17 +4,17 @@ namespace Encompass { public abstract class Renderer { - internal EntityManager entityManager; - internal ComponentManager componentManager; + internal EntityManager _entityManager; + internal ComponentManager _componentManager; internal void AssignEntityManager(EntityManager entityManager) { - this.entityManager = entityManager; + _entityManager = entityManager; } internal void AssignComponentManager(ComponentManager componentManager) { - this.componentManager = componentManager; + _componentManager = componentManager; } protected IEnumerable ReadEntities() where TComponent : struct, IComponent @@ -32,14 +32,14 @@ namespace Encompass protected IEnumerable ReadComponents() where TComponent : struct, IComponent { - return componentManager.GetComponentsByType(); + return _componentManager.GetComponentsByType(); } protected IEnumerable<(TComponent, Entity)> ReadComponentsIncludingEntity() where TComponent : struct, IComponent { - foreach (var (component, id) in componentManager.GetComponentsIncludingEntity()) + foreach (var (component, id) in _componentManager.GetComponentsIncludingEntity()) { - yield return (component, entityManager.GetEntity(id)); + yield return (component, _entityManager.GetEntity(id)); } } @@ -59,17 +59,17 @@ namespace Encompass protected ref readonly TComponent GetComponent(Entity entity) where TComponent : struct, IComponent { - return ref componentManager.GetComponentByEntityAndType(entity.ID); + return ref _componentManager.GetComponentByEntityAndType(entity.ID); } protected bool HasComponent(Entity entity) where TComponent : struct, IComponent { - return componentManager.EntityHasComponentOfType(entity.ID); + return _componentManager.EntityHasComponentOfType(entity.ID); } protected bool SomeComponent() where TComponent : struct, IComponent { - return componentManager.SomeExistingComponent(); + return _componentManager.SomeExistingComponent(); } } } diff --git a/encompass-cs/TimeDilationData.cs b/encompass-cs/TimeDilationData.cs index b344589..e57901f 100644 --- a/encompass-cs/TimeDilationData.cs +++ b/encompass-cs/TimeDilationData.cs @@ -1,35 +1,56 @@ +using System; + namespace Encompass { internal struct TimeDilationData { - public double elapsedTime; - public double easeInTime; - public System.Func easeInFunction; - public double activeTime; - public double easeOutTime; - public System.Func easeOutFunction; - public double factor; + private readonly double _factor; public double Factor { get { - if (elapsedTime < easeInTime) + if (ElapsedTime < EaseInTime) { - return easeInFunction(elapsedTime, 1, factor - 1, easeInTime); + return EaseInFunction(ElapsedTime, 1, _factor - 1, EaseInTime); } - else if (elapsedTime < easeInTime + activeTime) + else if (ElapsedTime < EaseInTime + ActiveTime) { - return factor; + return _factor; } - else if (elapsedTime < easeInTime + activeTime + easeOutTime) + else if (ElapsedTime < EaseInTime + ActiveTime + EaseOutTime) { - var elapsedOutTime = elapsedTime - easeInTime - activeTime; - return easeOutFunction(elapsedOutTime, factor, 1 - factor, easeOutTime); + var elapsedOutTime = ElapsedTime - EaseInTime - ActiveTime; + return EaseOutFunction(elapsedOutTime, _factor, 1 - _factor, EaseOutTime); } return 1; } } + + public double ElapsedTime { get; set; } + public double EaseInTime { get; } + public Func EaseInFunction { get; } + public double ActiveTime { get; } + public double EaseOutTime { get; } + public Func EaseOutFunction { get; } + + public TimeDilationData( + double factor, + double easeInTime, + Func easeInfunction, + double activeTime, + double easeOutTime, + Func easeOutFunction + ) + { + _factor = factor; + EaseInTime = easeInTime; + EaseInFunction = easeInfunction; + ActiveTime = activeTime; + EaseOutTime = easeOutTime; + EaseOutFunction = easeOutFunction; + ElapsedTime = 0; + } } -} \ No newline at end of file +} diff --git a/encompass-cs/TimeManager.cs b/encompass-cs/TimeManager.cs index ee05939..19363d2 100644 --- a/encompass-cs/TimeManager.cs +++ b/encompass-cs/TimeManager.cs @@ -4,7 +4,7 @@ namespace Encompass { internal class TimeManager { - private readonly List timeDilationDatas = new List(32); + private readonly List _timeDilationDatas = new List(32); private double Linear(double t, double b, double c, double d) { @@ -15,36 +15,36 @@ namespace Encompass { get { - if (timeDilationDatas.Count == 0) { return 1; } + if (_timeDilationDatas.Count == 0) { return 1; } var average = 0.0; - foreach (var data in timeDilationDatas) + foreach (var data in _timeDilationDatas) { average += data.Factor; } - return average / timeDilationDatas.Count; + return average / _timeDilationDatas.Count; } } public bool TimeDilationActive { - get => timeDilationDatas.Count != 0; + get => _timeDilationDatas.Count != 0; } public void Update(double dt) { - for (var i = timeDilationDatas.Count - 1; i >= 0; i--) + for (var i = _timeDilationDatas.Count - 1; i >= 0; i--) { - var data = timeDilationDatas[i]; + var data = _timeDilationDatas[i]; - data.elapsedTime += dt; + data.ElapsedTime += dt; - if (data.elapsedTime > data.easeInTime + data.activeTime + data.easeOutTime) + if (data.ElapsedTime > data.EaseInTime + data.ActiveTime + data.EaseOutTime) { - timeDilationDatas.RemoveAt(i); + _timeDilationDatas.RemoveAt(i); } else { - timeDilationDatas[i] = data; + _timeDilationDatas[i] = data; } } } @@ -66,16 +66,15 @@ namespace Encompass public void ActivateTimeDilation(double factor, double easeInTime, System.Func easeInFunction, double activeTime, double easeOutTime, System.Func easeOutFunction) { - timeDilationDatas.Add(new TimeDilationData - { - elapsedTime = 0, - easeInTime = easeInTime, - easeInFunction = easeInFunction, - activeTime = activeTime, - easeOutTime = easeOutTime, - easeOutFunction = easeOutFunction, - factor = factor - }); + _timeDilationDatas.Add(new TimeDilationData + ( + factor, + easeInTime, + easeInFunction, + activeTime, + easeOutTime, + easeOutFunction + )); } } } diff --git a/encompass-cs/TrackingManager.cs b/encompass-cs/TrackingManager.cs index c9e7830..3acf34d 100644 --- a/encompass-cs/TrackingManager.cs +++ b/encompass-cs/TrackingManager.cs @@ -5,13 +5,13 @@ namespace Encompass { internal class TrackingManager { - private Dictionary> _immediateComponentTypesToEngines = new Dictionary>(); - private Dictionary> _componentTypesToEngines = new Dictionary>(); + private readonly Dictionary> _immediateComponentTypesToEngines = new Dictionary>(); + private readonly Dictionary> _componentTypesToEngines = new Dictionary>(); - private HashSet<(int, Type)> _additions = new HashSet<(int, Type)>(); - private HashSet<(int, Type)> _removals = new HashSet<(int, Type)>(); + private readonly HashSet<(int, Type)> _additions = new HashSet<(int, Type)>(); + private readonly HashSet<(int, Type)> _removals = new HashSet<(int, Type)>(); - private HashSet<(int, Engine)> _pairsToCheck = new HashSet<(int, Engine)>(); + private readonly HashSet<(int, Engine)> _pairsToCheck = new HashSet<(int, Engine)>(); public void RegisterComponentTypeToEngine(Type type, Engine engine) { diff --git a/encompass-cs/UberEngine.cs b/encompass-cs/UberEngine.cs index 7abfc7d..c6f55b4 100644 --- a/encompass-cs/UberEngine.cs +++ b/encompass-cs/UberEngine.cs @@ -7,18 +7,18 @@ namespace Encompass { internal class UberEngine : Engine { - private IEnumerable _componentTypes; - private IEnumerable _messageTypes; + private readonly IEnumerable _componentTypes; + private readonly IEnumerable _messageTypes; public Entity Entity { get; private set; } public UberEngine(IEnumerable componentTypes, IEnumerable messageTypes) { _componentTypes = componentTypes; _messageTypes = messageTypes; - readTypes.UnionWith(componentTypes); - writeTypes.UnionWith(componentTypes); - sendTypes.UnionWith(messageTypes); - receiveTypes.UnionWith(messageTypes); + ReadTypes.UnionWith(componentTypes); + WriteTypes.UnionWith(componentTypes); + SendTypes.UnionWith(messageTypes); + ReceiveTypes.UnionWith(messageTypes); } public void Write() @@ -63,6 +63,8 @@ namespace Encompass if (typeof(IHasEntity).IsAssignableFrom(type)) { CallGenericMethod(type, "ReadMessagesWithEntity", new Type[] { typeof(Entity) }, new object[] { Entity }); + CallGenericMethod(type, "ReadMessageWithEntity", new Type[] { typeof(Entity) }, new object[] { Entity }); + CallGenericMethod(type, "SomeMessageWithEntity", new Type[] { typeof(Entity) }, new object[] { Entity }); } } } diff --git a/encompass-cs/UberRenderer.cs b/encompass-cs/UberRenderer.cs index be4bde4..870e999 100644 --- a/encompass-cs/UberRenderer.cs +++ b/encompass-cs/UberRenderer.cs @@ -6,7 +6,7 @@ namespace Encompass { class UberRenderer : Renderer { - private IEnumerable _componentTypes; + private readonly IEnumerable _componentTypes; private Entity _entity; public UberRenderer(IEnumerable componentTypes) diff --git a/encompass-cs/World.cs b/encompass-cs/World.cs index b611d96..b0b181b 100644 --- a/encompass-cs/World.cs +++ b/encompass-cs/World.cs @@ -7,13 +7,13 @@ namespace Encompass /// public class World { - private readonly List enginesInOrder; - private readonly EntityManager entityManager; - private readonly ComponentManager componentManager; - private readonly TrackingManager trackingManager; - private readonly MessageManager messageManager; - private readonly TimeManager timeManager; - private readonly RenderManager renderManager; + private readonly List _enginesInOrder; + private readonly EntityManager _entityManager; + private readonly ComponentManager _componentManager; + private readonly TrackingManager _trackingManager; + private readonly MessageManager _messageManager; + private readonly TimeManager _timeManager; + private readonly RenderManager _renderManager; internal World( List enginesInOrder, @@ -25,13 +25,13 @@ namespace Encompass RenderManager renderManager ) { - this.enginesInOrder = enginesInOrder; - this.entityManager = entityManager; - this.componentManager = componentManager; - this.trackingManager = trackingManager; - this.messageManager = messageManager; - this.timeManager = timeManager; - this.renderManager = renderManager; + _enginesInOrder = enginesInOrder; + _entityManager = entityManager; + _componentManager = componentManager; + _trackingManager = trackingManager; + _messageManager = messageManager; + _timeManager = timeManager; + _renderManager = renderManager; } /// @@ -40,15 +40,15 @@ namespace Encompass /// The time in seconds that has passed since the previous frame. public void Update(double dt) { - trackingManager.UpdateTracking(); - messageManager.ProcessDelayedMessages(dt); - timeManager.Update(dt); + _trackingManager.UpdateTracking(); + _messageManager.ProcessDelayedMessages(dt); + _timeManager.Update(dt); - foreach (var engine in enginesInOrder) + foreach (var engine in _enginesInOrder) { - if (engine.usesTimeDilation) + if (engine._usesTimeDilation) { - engine.Update(dt * timeManager.TimeDilationFactor); + engine.Update(dt * _timeManager.TimeDilationFactor); } else { @@ -58,12 +58,12 @@ namespace Encompass engine.ClearNewlyCreatedEntities(); } - messageManager.ClearMessages(); - entityManager.PruneEmptyEntities(); - entityManager.DestroyMarkedEntities(enginesInOrder); + _messageManager.ClearMessages(); + _entityManager.PruneEmptyEntities(); + _entityManager.DestroyMarkedEntities(_enginesInOrder); - componentManager.RemoveMarkedComponents(); - componentManager.WriteComponents(); + _componentManager.RemoveMarkedComponents(); + _componentManager.WriteComponents(); } /// @@ -71,7 +71,7 @@ namespace Encompass /// public void Draw() { - renderManager.Draw(); + _renderManager.Draw(); } } } diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs index 3145626..bdb9ee1 100644 --- a/encompass-cs/WorldBuilder.cs +++ b/encompass-cs/WorldBuilder.cs @@ -18,43 +18,43 @@ namespace Encompass /// public class WorldBuilder { - private readonly int entityCapacity; - private readonly List engines = new List(); - private readonly DirectedGraph engineGraph = GraphBuilder.DirectedGraph(); - private readonly ComponentStore startingExistingComponentStore; - private readonly ComponentStore startingUpToDateComponentStore; + private readonly int _entityCapacity; + private readonly List _engines = new List(); + private readonly DirectedGraph _engineGraph = GraphBuilder.DirectedGraph(); + private readonly ComponentStore _startingExistingComponentStore; + private readonly ComponentStore _startingUpToDateComponentStore; - private readonly ComponentManager componentManager; - private readonly EntityManager entityManager; - private readonly MessageManager messageManager; - private readonly TimeManager timeManager; - private readonly DrawLayerManager drawLayerManager; - private readonly RenderManager renderManager; - private readonly TrackingManager trackingManager; + private readonly ComponentManager _componentManager; + private readonly EntityManager _entityManager; + private readonly MessageManager _messageManager; + private readonly TimeManager _timeManager; + private readonly DrawLayerManager _drawLayerManager; + private readonly RenderManager _renderManager; + private readonly TrackingManager _trackingManager; - private readonly Dictionary> typeToReaders = new Dictionary>(); + private readonly Dictionary> _typeToReaders = new Dictionary>(); - private readonly HashSet senders = new HashSet(); + private readonly HashSet _senders = new HashSet(); - private readonly HashSet componentTypesToPreload = new HashSet(); + private readonly HashSet _componentTypesToPreload = new HashSet(); - private readonly HashSet messageTypes = new HashSet(); + private readonly HashSet _messageTypes = new HashSet(); - private readonly Dictionary typeToIndex = new Dictionary(); + private readonly Dictionary _typeToIndex = new Dictionary(); public WorldBuilder(int entityCapacity = 32768) { - this.entityCapacity = entityCapacity; - drawLayerManager = new DrawLayerManager(typeToIndex); - timeManager = new TimeManager(); - trackingManager = new TrackingManager(); - componentManager = new ComponentManager(drawLayerManager, typeToIndex); - messageManager = new MessageManager(timeManager); - entityManager = new EntityManager(componentManager, entityCapacity); - renderManager = new RenderManager(entityManager, drawLayerManager); + _entityCapacity = entityCapacity; + _drawLayerManager = new DrawLayerManager(_typeToIndex); + _timeManager = new TimeManager(); + _trackingManager = new TrackingManager(); + _componentManager = new ComponentManager(_drawLayerManager, _typeToIndex); + _messageManager = new MessageManager(_timeManager); + _entityManager = new EntityManager(_componentManager, entityCapacity); + _renderManager = new RenderManager(_entityManager, _drawLayerManager); - startingExistingComponentStore = new ComponentStore(typeToIndex); - startingUpToDateComponentStore = new ComponentStore(typeToIndex); + _startingExistingComponentStore = new ComponentStore(_typeToIndex); + _startingUpToDateComponentStore = new ComponentStore(_typeToIndex); } /// @@ -62,7 +62,7 @@ namespace Encompass /// public Entity CreateEntity() { - return entityManager.CreateEntity(); + return _entityManager.CreateEntity(); } /// @@ -70,7 +70,7 @@ namespace Encompass /// public void SendMessage(TMessage message) where TMessage : struct, IMessage { - messageManager.AddMessage(message); + _messageManager.AddMessage(message); } /// @@ -78,7 +78,7 @@ namespace Encompass /// public void SendMessage(TMessage message, double time) where TMessage : struct, IMessage { - messageManager.AddMessage(message, time); + _messageManager.AddMessage(message, time); } /// @@ -87,31 +87,31 @@ namespace Encompass public void SetComponent(Entity entity, TComponent component) where TComponent : struct, IComponent { RegisterComponentType(); - startingExistingComponentStore.Set(entity.ID, component); - startingUpToDateComponentStore.Set(entity.ID, component); + _startingExistingComponentStore.Set(entity.ID, component); + _startingUpToDateComponentStore.Set(entity.ID, component); if (component is IDrawableComponent drawableComponent) { - componentManager.RegisterDrawableComponent(entity.ID, component, drawableComponent.Layer); - drawLayerManager.RegisterOrderedDrawable(); + _componentManager.RegisterDrawableComponent(entity.ID, component, drawableComponent.Layer); + _drawLayerManager.RegisterOrderedDrawable(); } } internal void RegisterComponentType() where TComponent : struct, IComponent { - if (!typeToIndex.ContainsKey(typeof(TComponent))) + if (!_typeToIndex.ContainsKey(typeof(TComponent))) { - typeToIndex.Add(typeof(TComponent), typeToIndex.Count); - componentTypesToPreload.Add(typeof(TComponent)); - componentManager.RegisterComponentType(); - startingExistingComponentStore.RegisterComponentType(); - startingUpToDateComponentStore.RegisterComponentType(); + _typeToIndex.Add(typeof(TComponent), _typeToIndex.Count); + _componentTypesToPreload.Add(typeof(TComponent)); + _componentManager.RegisterComponentType(); + _startingExistingComponentStore.RegisterComponentType(); + _startingUpToDateComponentStore.RegisterComponentType(); } } internal void RegisterMessageTypes(IEnumerable types) { - messageTypes.UnionWith(types); + _messageTypes.UnionWith(types); } /// @@ -120,21 +120,21 @@ namespace Encompass /// An instance of an Engine. public Engine AddEngine(TEngine engine) where TEngine : Engine { - engine.AssignEntityManager(entityManager); - engine.AssignComponentManager(componentManager); - engine.AssignMessageManager(messageManager); - engine.AssignTimeManager(timeManager); - engine.AssignTrackingManager(trackingManager); + engine.AssignEntityManager(_entityManager); + engine.AssignComponentManager(_componentManager); + engine.AssignMessageManager(_messageManager); + engine.AssignTimeManager(_timeManager); + engine.AssignTrackingManager(_trackingManager); - engines.Add(engine); - engineGraph.AddNode(engine); + _engines.Add(engine); + _engineGraph.AddNode(engine); - var messageReceiveTypes = engine.receiveTypes; - var messageSendTypes = engine.sendTypes; + var messageReceiveTypes = engine.ReceiveTypes; + var messageSendTypes = engine.SendTypes; - RegisterMessageTypes(engine.receiveTypes.Union(engine.sendTypes)); + RegisterMessageTypes(engine.ReceiveTypes.Union(engine.SendTypes)); - foreach (var writeImmediateType in engine.writeImmediateTypes.Intersect(engine.readImmediateTypes)) + foreach (var writeImmediateType in engine.WriteImmediateTypes.Intersect(engine.ReadImmediateTypes)) { throw new EngineSelfCycleException("Engine {0} both writes and reads immediate Component {1}", engine.GetType().Name, writeImmediateType.Name); } @@ -144,28 +144,28 @@ namespace Encompass throw new EngineSelfCycleException("Engine {0} both receives and sends Message {1}", engine.GetType().Name, messageType.Name); } - if (messageSendTypes.Count > 0 || engine.writeImmediateTypes.Count > 0) + if (messageSendTypes.Count > 0 || engine.WriteImmediateTypes.Count > 0) { - senders.Add(engine); + _senders.Add(engine); } - foreach (var componentType in engine.queryWithTypes.Union(engine.queryWithoutTypes)) + foreach (var componentType in engine.QueryWithTypes.Union(engine.QueryWithoutTypes)) { - trackingManager.RegisterComponentTypeToEngine(componentType, engine); - if (engine.readImmediateTypes.Contains(componentType)) + _trackingManager.RegisterComponentTypeToEngine(componentType, engine); + if (engine.ReadImmediateTypes.Contains(componentType)) { - trackingManager.RegisterImmediateComponentTypeToEngine(componentType, engine); + _trackingManager.RegisterImmediateComponentTypeToEngine(componentType, engine); } } - foreach (var receiveType in engine.receiveTypes.Union(engine.readImmediateTypes)) + foreach (var receiveType in engine.ReceiveTypes.Union(engine.ReadImmediateTypes)) { - if (!typeToReaders.ContainsKey(receiveType)) + if (!_typeToReaders.ContainsKey(receiveType)) { - typeToReaders.Add(receiveType, new HashSet()); + _typeToReaders.Add(receiveType, new HashSet()); } - typeToReaders[receiveType].Add(engine); + _typeToReaders[receiveType].Add(engine); } return engine; @@ -177,7 +177,7 @@ namespace Encompass /// The draw layer to register. public void RegisterDrawLayer(int layer) { - drawLayerManager.RegisterDrawLayer(layer); + _drawLayerManager.RegisterDrawLayer(layer); } /// @@ -186,9 +186,9 @@ namespace Encompass public OrderedRenderer AddOrderedRenderer(OrderedRenderer renderer) where TComponent : struct, IComponent, IDrawableComponent { RegisterComponentType(); - renderer.AssignEntityManager(entityManager); - renderer.AssignComponentManager(componentManager); - renderManager.RegisterOrderedRenderer(renderer.InternalRender); + renderer.AssignEntityManager(_entityManager); + renderer.AssignComponentManager(_componentManager); + _renderManager.RegisterOrderedRenderer(renderer.InternalRender); return renderer; } @@ -200,29 +200,29 @@ namespace Encompass /// The layer at which the GeneralRenderer should render. Higher numbers draw over lower numbers. public TRenderer AddGeneralRenderer(TRenderer renderer, int layer) where TRenderer : GeneralRenderer { - renderer.AssignEntityManager(entityManager); - renderer.AssignComponentManager(componentManager); + renderer.AssignEntityManager(_entityManager); + renderer.AssignComponentManager(_componentManager); - renderManager.RegisterGeneralRendererWithLayer(renderer, layer); + _renderManager.RegisterGeneralRendererWithLayer(renderer, layer); return renderer; } private void BuildEngineGraph() { - foreach (var senderEngine in senders) + foreach (var senderEngine in _senders) { - foreach (var messageType in senderEngine.sendTypes.Union(senderEngine.writeImmediateTypes)) + foreach (var messageType in senderEngine.SendTypes.Union(senderEngine.WriteImmediateTypes)) { - if (typeToReaders.ContainsKey(messageType)) + if (_typeToReaders.ContainsKey(messageType)) { - foreach (var readerEngine in typeToReaders[messageType]) + foreach (var readerEngine in _typeToReaders[messageType]) { if (senderEngine != readerEngine) { - if (!engineGraph.Exists(senderEngine, readerEngine)) + if (!_engineGraph.Exists(senderEngine, readerEngine)) { - engineGraph.AddEdge(senderEngine, readerEngine); + _engineGraph.AddEdge(senderEngine, readerEngine); } } } @@ -240,9 +240,9 @@ namespace Encompass { BuildEngineGraph(); - if (engineGraph.Cyclic()) + if (_engineGraph.Cyclic()) { - var cycles = engineGraph.SimpleCycles(); + var cycles = _engineGraph.SimpleCycles(); var errorString = "Cycle(s) found in Engines: "; foreach (var cycle in cycles) { @@ -262,25 +262,25 @@ namespace Encompass var writePriorities = new Dictionary>(); var writeMessageToEngines = new Dictionary>(); - foreach (var engine in engines) + foreach (var engine in _engines) { if (engine.GetType().GetCustomAttribute() != null) { - engine.usesTimeDilation = false; + engine._usesTimeDilation = false; } var defaultWritePriorityAttribute = engine.GetType().GetCustomAttribute(false); - foreach (var writeType in engine.writeTypes) + foreach (var writeType in engine.WriteTypes) { int? priority = null; - if (engine.writePriorities.ContainsKey(writeType)) + if (engine.WritePriorities.ContainsKey(writeType)) { - priority = engine.writePriorities[writeType]; + priority = engine.WritePriorities[writeType]; } else if (defaultWritePriorityAttribute != null) { - priority = defaultWritePriorityAttribute.writePriority; + priority = defaultWritePriorityAttribute.WritePriority; } if (priority.HasValue) @@ -368,11 +368,11 @@ namespace Encompass } } - PreloadJIT(componentTypesToPreload, messageTypes); + PreloadJIT(_componentTypesToPreload, _messageTypes); var engineOrder = new List(); - foreach (var engine in engineGraph.TopologicalSort()) + foreach (var engine in _engineGraph.TopologicalSort()) { engineOrder.Add(engine); engine.BuildEntityQuery(); @@ -380,18 +380,18 @@ namespace Encompass var world = new World( engineOrder, - entityManager, - componentManager, - trackingManager, - messageManager, - timeManager, - renderManager + _entityManager, + _componentManager, + _trackingManager, + _messageManager, + _timeManager, + _renderManager ); - componentManager.SetExistingComponentStore(startingExistingComponentStore); - componentManager.SetUpToDateComponentStore(startingUpToDateComponentStore); + _componentManager.SetExistingComponentStore(_startingExistingComponentStore); + _componentManager.SetUpToDateComponentStore(_startingUpToDateComponentStore); - trackingManager.InitializeTracking(entityManager.EntityIDs); + _trackingManager.InitializeTracking(_entityManager.EntityIDs); return world; } @@ -406,10 +406,10 @@ namespace Encompass { var dummyTimeManager = new TimeManager(); var dummyMessageManager = new MessageManager(dummyTimeManager); - var dummyDrawLayerManager = new DrawLayerManager(typeToIndex); + var dummyDrawLayerManager = new DrawLayerManager(_typeToIndex); var dummyTrackingManager = new TrackingManager(); - var dummyComponentManager = new ComponentManager(dummyDrawLayerManager, typeToIndex); - var dummyEntityManager = new EntityManager(dummyComponentManager, entityCapacity); + var dummyComponentManager = new ComponentManager(dummyDrawLayerManager, _typeToIndex); + var dummyEntityManager = new EntityManager(dummyComponentManager, _entityCapacity); var dummyRenderManager = new RenderManager(dummyEntityManager, dummyDrawLayerManager); var prepEngineOrder = new List(); From 63e9ca63c036902105457bc0d2714269c4ad14d4 Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Fri, 20 Mar 2020 00:58:33 -0700 Subject: [PATCH 04/30] get rid of component stores on DrawLayerManager --- encompass-cs/Collections/ComponentStore.cs | 19 ------- .../Collections/TypedComponentStore.cs | 9 ---- encompass-cs/ComponentManager.cs | 4 +- encompass-cs/DrawLayerManager.cs | 52 ++++++++----------- encompass-cs/Engine.cs | 4 +- encompass-cs/RenderManager.cs | 8 +-- encompass-cs/Renderers/OrderedRenderer.cs | 4 +- encompass-cs/WorldBuilder.cs | 6 +-- 8 files changed, 36 insertions(+), 70 deletions(-) diff --git a/encompass-cs/Collections/ComponentStore.cs b/encompass-cs/Collections/ComponentStore.cs index 3a65abe..8f34731 100644 --- a/encompass-cs/Collections/ComponentStore.cs +++ b/encompass-cs/Collections/ComponentStore.cs @@ -14,14 +14,6 @@ namespace Encompass ComponentBitSet = new ComponentBitSet(typeToIndex); } - public IEnumerable<(Type, TypedComponentStore)> StoresEnumerable() - { - foreach (var entry in _stores) - { - yield return (entry.Key, entry.Value); - } - } - public virtual void RegisterComponentType() where TComponent : struct, IComponent { if (!_stores.ContainsKey(typeof(TComponent))) @@ -102,17 +94,6 @@ namespace Encompass return Lookup().Count > 0; } - public IEnumerable<(int, Type, IComponent)> AllInterfaceTyped() - { - foreach (var store in _stores.Values) - { - foreach (var thing in store.AllInterfaceTyped()) - { - yield return thing; - } - } - } - public IEnumerable<(TComponent, int)> All() where TComponent : struct, IComponent { return Lookup().All(); diff --git a/encompass-cs/Collections/TypedComponentStore.cs b/encompass-cs/Collections/TypedComponentStore.cs index 9f3c9af..3f41e56 100644 --- a/encompass-cs/Collections/TypedComponentStore.cs +++ b/encompass-cs/Collections/TypedComponentStore.cs @@ -7,7 +7,6 @@ namespace Encompass internal abstract class TypedComponentStore { public abstract int Count { get; } - public abstract IEnumerable<(int, Type, IComponent)> AllInterfaceTyped(); public abstract bool Has(int entity); public abstract bool Remove(int entity, int priority); public abstract void ForceRemove(int entity); @@ -107,13 +106,5 @@ namespace Encompass yield return (_components[kvp.Value], kvp.Key); } } - - public override IEnumerable<(int, Type, IComponent)> AllInterfaceTyped() - { - foreach (var kvp in _indices) - { - yield return (kvp.Key, typeof(TComponent), (IComponent)_components[kvp.Value]); - } - } } } diff --git a/encompass-cs/ComponentManager.cs b/encompass-cs/ComponentManager.cs index 1e7aa8c..928c9a0 100644 --- a/encompass-cs/ComponentManager.cs +++ b/encompass-cs/ComponentManager.cs @@ -47,9 +47,9 @@ namespace Encompass _upToDateComponentStore.SwapWith(componentStore); } - internal void RegisterDrawableComponent(int entityID, TComponent component, int layer) where TComponent : struct, IComponent + internal void RegisterDrawableComponent(int entityID, int layer) where TComponent : struct, IComponent { - _drawLayerManager.RegisterComponentWithLayer(entityID, component, layer); + _drawLayerManager.RegisterComponentWithLayer(entityID, layer); } internal void WriteComponents() diff --git a/encompass-cs/DrawLayerManager.cs b/encompass-cs/DrawLayerManager.cs index 32bdec3..b8b8653 100644 --- a/encompass-cs/DrawLayerManager.cs +++ b/encompass-cs/DrawLayerManager.cs @@ -9,16 +9,14 @@ namespace Encompass { private readonly SortedList _layerOrder = new SortedList(); - private readonly Dictionary _layerIndexToComponentStore = new Dictionary(512); + private readonly Dictionary>> _layerIndexToComponentStore = new Dictionary>>(); private readonly Dictionary> _layerIndexToGeneralRenderers = new Dictionary>(512); private readonly Dictionary> _typeToEntityToLayer = new Dictionary>(512); - private readonly Dictionary _typeToIndex; public IEnumerable LayerOrder { get { return _layerOrder.Values; } } - public DrawLayerManager(Dictionary typeToIndex) + public DrawLayerManager() { - _typeToIndex = typeToIndex; RegisterDrawLayer(0); } @@ -28,7 +26,7 @@ namespace Encompass { _layerOrder.Add(layer, layer); _layerIndexToGeneralRenderers.Add(layer, new HashSet()); - _layerIndexToComponentStore.Add(layer, new ComponentStore(_typeToIndex)); + _layerIndexToComponentStore.Add(layer, new Dictionary>()); } } @@ -41,7 +39,10 @@ namespace Encompass foreach (var pair in _layerIndexToComponentStore) { - pair.Value.RegisterComponentType(); + if (!pair.Value.ContainsKey(typeof(TComponent))) + { + pair.Value.Add(typeof(TComponent), new HashSet()); + } } } @@ -52,21 +53,7 @@ namespace Encompass set.Add(renderer); } - public void UnregisterGeneralRendererWithLayer(GeneralRenderer renderer, int layer) - { - if (_layerIndexToGeneralRenderers.ContainsKey(layer)) - { - _layerIndexToGeneralRenderers[layer].Remove(renderer); - } - } - - public void AdjustRendererLayer(GeneralRenderer renderer, int oldLayer, int newLayer) - { - UnregisterGeneralRendererWithLayer(renderer, oldLayer); - RegisterGeneralRendererWithLayer(renderer, newLayer); - } - - public void RegisterComponentWithLayer(int entityID, TComponent component, int layer) where TComponent : struct, IComponent + public void RegisterComponentWithLayer(int entityID, int layer) where TComponent : struct, IComponent { if (!_layerIndexToComponentStore.ContainsKey(layer)) { @@ -75,8 +62,8 @@ namespace Encompass if (_typeToEntityToLayer[typeof(TComponent)].ContainsKey(entityID)) { UnRegisterComponentWithLayer(entityID); } - var set = _layerIndexToComponentStore[layer]; - set.Set(entityID, component); + var set = _layerIndexToComponentStore[layer][typeof(TComponent)]; + set.Add(entityID); _typeToEntityToLayer[typeof(TComponent)].Add(entityID, layer); } @@ -88,7 +75,7 @@ namespace Encompass if (_typeToEntityToLayer[typeof(TComponent)].ContainsKey(entityID)) { var layer = _typeToEntityToLayer[typeof(TComponent)][entityID]; - _layerIndexToComponentStore[layer].ForceRemove(entityID); + _layerIndexToComponentStore[layer][typeof(TComponent)].Remove(entityID); } _typeToEntityToLayer[typeof(TComponent)].Remove(entityID); } @@ -97,7 +84,10 @@ namespace Encompass { foreach (var store in _layerIndexToComponentStore.Values) { - store.Remove(entityID); + foreach (var set in store.Values) + { + set.Remove(entityID); + } } } @@ -108,11 +98,15 @@ namespace Encompass Enumerable.Empty(); } - public IEnumerable<(int, Type, IComponent)> AllInLayer(int layer) + public IEnumerable<(int, Type)> AllInLayer(int layer) { - return _layerIndexToComponentStore.ContainsKey(layer) ? - _layerIndexToComponentStore[layer].AllInterfaceTyped() : - Enumerable.Empty<(int, Type, IComponent)>(); + foreach (var kvp in _layerIndexToComponentStore[layer]) + { + foreach (var id in kvp.Value) + { + yield return (id, kvp.Key); + } + } } } } diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index c371b50..91b97b7 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -474,7 +474,7 @@ namespace Encompass if (written && component is IDrawableComponent drawableComponent) { - _componentManager.RegisterDrawableComponent(entity.ID, component, drawableComponent.Layer); + _componentManager.RegisterDrawableComponent(entity.ID, drawableComponent.Layer); } } @@ -505,7 +505,7 @@ namespace Encompass if (component is IDrawableComponent drawableComponent) { - _componentManager.RegisterDrawableComponent(entity.ID, component, drawableComponent.Layer); + _componentManager.RegisterDrawableComponent(entity.ID, drawableComponent.Layer); } } diff --git a/encompass-cs/RenderManager.cs b/encompass-cs/RenderManager.cs index 6469c2f..3f603b4 100644 --- a/encompass-cs/RenderManager.cs +++ b/encompass-cs/RenderManager.cs @@ -8,7 +8,7 @@ namespace Encompass private readonly EntityManager _entityManager; private readonly DrawLayerManager _drawLayerManager; - private readonly Dictionary> _drawComponentTypeToOrderedRenderer = new Dictionary>(256); + private readonly Dictionary> _drawComponentTypeToOrderedRenderer = new Dictionary>(256); public RenderManager(EntityManager entityManager, DrawLayerManager drawLayerManager) { @@ -16,7 +16,7 @@ namespace Encompass _drawLayerManager = drawLayerManager; } - public void RegisterOrderedRenderer(Action renderAction) where TComponent : struct, IComponent + public void RegisterOrderedRenderer(Action renderAction) where TComponent : struct, IComponent { _drawComponentTypeToOrderedRenderer.Add(typeof(TComponent), renderAction); _drawLayerManager.RegisterOrderedDrawable(); @@ -33,12 +33,12 @@ namespace Encompass { var generalRendererSet = _drawLayerManager.GeneralRenderersByLayer(layer); - foreach (var (entityID, componentType, component) in _drawLayerManager.AllInLayer(layer)) + foreach (var (entityID, componentType) in _drawLayerManager.AllInLayer(layer)) { if (_drawComponentTypeToOrderedRenderer.ContainsKey(componentType)) { var internalRenderAction = _drawComponentTypeToOrderedRenderer[componentType]; - internalRenderAction(_entityManager.GetEntity(entityID), component); + internalRenderAction(_entityManager.GetEntity(entityID)); } } diff --git a/encompass-cs/Renderers/OrderedRenderer.cs b/encompass-cs/Renderers/OrderedRenderer.cs index 20ca636..cfeb73b 100644 --- a/encompass-cs/Renderers/OrderedRenderer.cs +++ b/encompass-cs/Renderers/OrderedRenderer.cs @@ -9,9 +9,9 @@ namespace Encompass { public abstract void Render(Entity entity, TComponent drawComponent); - internal void InternalRender(Entity entity, IComponent component) + internal void InternalRender(Entity entity) { - Render(entity, (TComponent)component); + Render(entity, GetComponent(entity)); } } } diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs index bdb9ee1..ad8a5ba 100644 --- a/encompass-cs/WorldBuilder.cs +++ b/encompass-cs/WorldBuilder.cs @@ -45,7 +45,7 @@ namespace Encompass public WorldBuilder(int entityCapacity = 32768) { _entityCapacity = entityCapacity; - _drawLayerManager = new DrawLayerManager(_typeToIndex); + _drawLayerManager = new DrawLayerManager(); _timeManager = new TimeManager(); _trackingManager = new TrackingManager(); _componentManager = new ComponentManager(_drawLayerManager, _typeToIndex); @@ -92,7 +92,7 @@ namespace Encompass if (component is IDrawableComponent drawableComponent) { - _componentManager.RegisterDrawableComponent(entity.ID, component, drawableComponent.Layer); + _componentManager.RegisterDrawableComponent(entity.ID, drawableComponent.Layer); _drawLayerManager.RegisterOrderedDrawable(); } } @@ -406,7 +406,7 @@ namespace Encompass { var dummyTimeManager = new TimeManager(); var dummyMessageManager = new MessageManager(dummyTimeManager); - var dummyDrawLayerManager = new DrawLayerManager(_typeToIndex); + var dummyDrawLayerManager = new DrawLayerManager(); var dummyTrackingManager = new TrackingManager(); var dummyComponentManager = new ComponentManager(dummyDrawLayerManager, _typeToIndex); var dummyEntityManager = new EntityManager(dummyComponentManager, _entityCapacity); From b6ae9eaebc8b25d1c905e7b45376c7fd3741674f Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Fri, 20 Mar 2020 02:28:10 -0700 Subject: [PATCH 05/30] more cleanup --- .../Collections/TypedComponentStore.cs | 7 ++----- encompass-cs/DrawLayerManager.cs | 18 +++++++++--------- encompass-cs/Interfaces/IDrawableComponent.cs | 4 ++-- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/encompass-cs/Collections/TypedComponentStore.cs b/encompass-cs/Collections/TypedComponentStore.cs index 3f41e56..e1caa24 100644 --- a/encompass-cs/Collections/TypedComponentStore.cs +++ b/encompass-cs/Collections/TypedComponentStore.cs @@ -54,8 +54,7 @@ namespace Encompass _indices[entityID] = _idManager.NextID(); } - var ptr = Unsafe.AsPointer(ref component); - _components[_indices[entityID]] = Unsafe.AsRef(ptr); + _components[_indices[entityID]] = Unsafe.AsRef(Unsafe.AsPointer(ref component)); } public override bool Remove(int entityID, int priority) @@ -63,9 +62,7 @@ namespace Encompass if (!_priorities.ContainsKey(entityID) || priority < _priorities[entityID]) { _priorities[entityID] = priority; - _indices.Remove(entityID); - _priorities.Remove(entityID); - _idManager.Free(entityID); + ForceRemove(entityID); return true; } diff --git a/encompass-cs/DrawLayerManager.cs b/encompass-cs/DrawLayerManager.cs index b8b8653..3c14f21 100644 --- a/encompass-cs/DrawLayerManager.cs +++ b/encompass-cs/DrawLayerManager.cs @@ -9,7 +9,7 @@ namespace Encompass { private readonly SortedList _layerOrder = new SortedList(); - private readonly Dictionary>> _layerIndexToComponentStore = new Dictionary>>(); + private readonly Dictionary>> _layerIndexToTypeToID = new Dictionary>>(); private readonly Dictionary> _layerIndexToGeneralRenderers = new Dictionary>(512); private readonly Dictionary> _typeToEntityToLayer = new Dictionary>(512); @@ -22,11 +22,11 @@ namespace Encompass public void RegisterDrawLayer(int layer) { - if (!_layerIndexToComponentStore.ContainsKey(layer)) + if (!_layerIndexToTypeToID.ContainsKey(layer)) { _layerOrder.Add(layer, layer); _layerIndexToGeneralRenderers.Add(layer, new HashSet()); - _layerIndexToComponentStore.Add(layer, new Dictionary>()); + _layerIndexToTypeToID.Add(layer, new Dictionary>()); } } @@ -37,7 +37,7 @@ namespace Encompass _typeToEntityToLayer.Add(typeof(TComponent), new Dictionary(128)); } - foreach (var pair in _layerIndexToComponentStore) + foreach (var pair in _layerIndexToTypeToID) { if (!pair.Value.ContainsKey(typeof(TComponent))) { @@ -55,14 +55,14 @@ namespace Encompass public void RegisterComponentWithLayer(int entityID, int layer) where TComponent : struct, IComponent { - if (!_layerIndexToComponentStore.ContainsKey(layer)) + if (!_layerIndexToTypeToID.ContainsKey(layer)) { throw new UndefinedLayerException("Layer {0} is not defined. Use WorldBuilder.RegisterDrawLayer to register the layer.", layer); } if (_typeToEntityToLayer[typeof(TComponent)].ContainsKey(entityID)) { UnRegisterComponentWithLayer(entityID); } - var set = _layerIndexToComponentStore[layer][typeof(TComponent)]; + var set = _layerIndexToTypeToID[layer][typeof(TComponent)]; set.Add(entityID); _typeToEntityToLayer[typeof(TComponent)].Add(entityID, layer); @@ -75,14 +75,14 @@ namespace Encompass if (_typeToEntityToLayer[typeof(TComponent)].ContainsKey(entityID)) { var layer = _typeToEntityToLayer[typeof(TComponent)][entityID]; - _layerIndexToComponentStore[layer][typeof(TComponent)].Remove(entityID); + _layerIndexToTypeToID[layer][typeof(TComponent)].Remove(entityID); } _typeToEntityToLayer[typeof(TComponent)].Remove(entityID); } public void UnRegisterEntityWithLayer(int entityID) { - foreach (var store in _layerIndexToComponentStore.Values) + foreach (var store in _layerIndexToTypeToID.Values) { foreach (var set in store.Values) { @@ -100,7 +100,7 @@ namespace Encompass public IEnumerable<(int, Type)> AllInLayer(int layer) { - foreach (var kvp in _layerIndexToComponentStore[layer]) + foreach (var kvp in _layerIndexToTypeToID[layer]) { foreach (var id in kvp.Value) { diff --git a/encompass-cs/Interfaces/IDrawableComponent.cs b/encompass-cs/Interfaces/IDrawableComponent.cs index e292d90..d150624 100644 --- a/encompass-cs/Interfaces/IDrawableComponent.cs +++ b/encompass-cs/Interfaces/IDrawableComponent.cs @@ -2,6 +2,6 @@ namespace Encompass { public interface IDrawableComponent { - int Layer { get; set; } + int Layer { get; } } -} \ No newline at end of file +} From 6d699e4b1753d6587d25decb6a6dc9387c7519a3 Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Fri, 20 Mar 2020 14:13:26 -0700 Subject: [PATCH 06/30] passing draw components by ref --- encompass-cs/Engine.cs | 2 +- encompass-cs/Renderers/OrderedRenderer.cs | 2 +- encompass-cs/encompass-cs.csproj | 3 ++- test/OrderedRendererTest.cs | 6 +++--- test/WorldTest.cs | 2 +- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index 91b97b7..fab7457 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -105,7 +105,7 @@ namespace Encompass var queryWithAttribute = GetType().GetCustomAttribute(false); if (queryWithAttribute != null) { - QueryWithTypes = queryWithAttribute.QueryWithTypes.ToHashSet(); + QueryWithTypes = queryWithAttribute.QueryWithTypes; } var queryWithoutAttribute = GetType().GetCustomAttribute(false); diff --git a/encompass-cs/Renderers/OrderedRenderer.cs b/encompass-cs/Renderers/OrderedRenderer.cs index cfeb73b..162322a 100644 --- a/encompass-cs/Renderers/OrderedRenderer.cs +++ b/encompass-cs/Renderers/OrderedRenderer.cs @@ -7,7 +7,7 @@ namespace Encompass /// public abstract class OrderedRenderer : Renderer where TComponent : struct, IComponent, IDrawableComponent { - public abstract void Render(Entity entity, TComponent drawComponent); + public abstract void Render(Entity entity, in TComponent drawComponent); internal void InternalRender(Entity entity) { diff --git a/encompass-cs/encompass-cs.csproj b/encompass-cs/encompass-cs.csproj index c7be512..67ada2d 100644 --- a/encompass-cs/encompass-cs.csproj +++ b/encompass-cs/encompass-cs.csproj @@ -1,6 +1,6 @@ - netstandard2.1 + netstandard2.0 8.0 true Encompass @@ -28,5 +28,6 @@ + diff --git a/test/OrderedRendererTest.cs b/test/OrderedRendererTest.cs index 6f7dc8a..92cb3b8 100644 --- a/test/OrderedRendererTest.cs +++ b/test/OrderedRendererTest.cs @@ -20,13 +20,13 @@ namespace Tests class TestRenderer : OrderedRenderer { - public override void Render(Entity entity, TestDrawComponent testDrawComponent) { } + public override void Render(Entity entity, in TestDrawComponent testDrawComponent) { } } static bool called = false; class DeactivatedRenderer : TestRenderer { - public override void Render(Entity entity, TestDrawComponent testDrawComponent) + public override void Render(Entity entity, in TestDrawComponent testDrawComponent) { called = true; } @@ -37,7 +37,7 @@ namespace Tests class CalledRenderer : OrderedRenderer { - public override void Render(Entity entity, TestDrawComponent testDrawComponent) + public override void Render(Entity entity, in TestDrawComponent testDrawComponent) { resultComponent = (testDrawComponent, entity); calledOnDraw = true; diff --git a/test/WorldTest.cs b/test/WorldTest.cs index def4165..6ce089b 100644 --- a/test/WorldTest.cs +++ b/test/WorldTest.cs @@ -21,7 +21,7 @@ namespace Tests class TestEntityRenderer : OrderedRenderer { - public override void Render(Entity entity, TestDrawComponent testDrawComponent) + public override void Render(Entity entity, in TestDrawComponent testDrawComponent) { drawOrder.Add(entity); } From 408dd9bfeb6b1940e027003391a9148693ad6b57 Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Fri, 20 Mar 2020 15:45:58 -0700 Subject: [PATCH 07/30] unmanaged structs --- encompass-cs/Attributes/QueryWith.cs | 7 --- encompass-cs/Attributes/QueryWithout.cs | 9 +--- encompass-cs/Attributes/Reads.cs | 9 +--- encompass-cs/Attributes/ReadsImmediate.cs | 11 +--- encompass-cs/Attributes/Writes.cs | 14 +---- encompass-cs/Attributes/WritesImmediate.cs | 10 +--- encompass-cs/Collections/ComponentBitSet.cs | 4 +- encompass-cs/Collections/ComponentStore.cs | 27 ++++++---- encompass-cs/Collections/Replayer.cs | 4 +- .../Collections/TypedComponentStore.cs | 2 +- encompass-cs/ComponentManager.cs | 52 +++++++++--------- encompass-cs/DrawLayerManager.cs | 6 +-- encompass-cs/Engine.cs | 40 +++++++------- .../Exceptions/IllegalReadTypeException.cs | 12 ----- encompass-cs/IComponent.cs | 7 --- encompass-cs/RenderManager.cs | 2 +- encompass-cs/Renderer.cs | 18 +++---- encompass-cs/Renderers/OrderedRenderer.cs | 2 +- encompass-cs/WorldBuilder.cs | 20 ++----- test/ComponentTest.cs | 23 ++++---- test/EngineTest.cs | 53 +++++++------------ test/GeneralRendererTest.cs | 2 +- test/OrderedRendererTest.cs | 8 +-- test/SpawnerTest.cs | 2 +- test/WorldBuilderTest.cs | 32 ++--------- test/WorldTest.cs | 4 +- test/test.csproj | 1 + 27 files changed, 132 insertions(+), 249 deletions(-) delete mode 100644 encompass-cs/Exceptions/IllegalReadTypeException.cs delete mode 100644 encompass-cs/IComponent.cs diff --git a/encompass-cs/Attributes/QueryWith.cs b/encompass-cs/Attributes/QueryWith.cs index 5574c5b..ac8797d 100644 --- a/encompass-cs/Attributes/QueryWith.cs +++ b/encompass-cs/Attributes/QueryWith.cs @@ -14,13 +14,6 @@ namespace Encompass { foreach (var queryWithType in queryWithTypes) { - var isComponent = queryWithType.GetInterfaces().Contains(typeof(IComponent)); - - if (!isComponent) - { - throw new IllegalReadTypeException("{0} must be a Component", queryWithType.Name); - } - QueryWithTypes.Add(queryWithType); } } diff --git a/encompass-cs/Attributes/QueryWithout.cs b/encompass-cs/Attributes/QueryWithout.cs index 3588285..3332b45 100644 --- a/encompass-cs/Attributes/QueryWithout.cs +++ b/encompass-cs/Attributes/QueryWithout.cs @@ -14,14 +14,7 @@ namespace Encompass { foreach (var type in queryWithoutTypes) { - var isComponent = type.GetInterfaces().Contains(typeof(IComponent)); - - if (!isComponent) - { - throw new IllegalReadTypeException("{0} must be a Component", type.Name); - } - - this.QueryWithoutTypes.Add(type); + QueryWithoutTypes.Add(type); } } } diff --git a/encompass-cs/Attributes/Reads.cs b/encompass-cs/Attributes/Reads.cs index b958a26..e508775 100644 --- a/encompass-cs/Attributes/Reads.cs +++ b/encompass-cs/Attributes/Reads.cs @@ -14,14 +14,7 @@ namespace Encompass { 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.ReadTypes.Add(readType); + ReadTypes.Add(readType); } } } diff --git a/encompass-cs/Attributes/ReadsImmediate.cs b/encompass-cs/Attributes/ReadsImmediate.cs index 5d4b0ff..d399ae4 100644 --- a/encompass-cs/Attributes/ReadsImmediate.cs +++ b/encompass-cs/Attributes/ReadsImmediate.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using Encompass.Exceptions; namespace Encompass { @@ -14,14 +12,7 @@ namespace Encompass { foreach (var readImmediateType in readImmediateTypes) { - var isComponent = readImmediateType.GetInterfaces().Contains(typeof(IComponent)); - - if (!isComponent) - { - throw new IllegalReadTypeException("{0} must be a Component", readImmediateType.Name); - } - - this.ReadImmediateTypes.Add(readImmediateType); + ReadImmediateTypes.Add(readImmediateType); } } } diff --git a/encompass-cs/Attributes/Writes.cs b/encompass-cs/Attributes/Writes.cs index 8eec04a..0cc1250 100644 --- a/encompass-cs/Attributes/Writes.cs +++ b/encompass-cs/Attributes/Writes.cs @@ -15,24 +15,12 @@ namespace Encompass { foreach (var writeType in writeTypes) { - var isComponent = writeType.GetInterfaces().Contains(typeof(IComponent)); - if (!isComponent) - { - throw new IllegalWriteTypeException("{0} must be a Component", writeType.Name); - } - - this.WriteTypes.Add(writeType); + WriteTypes.Add(writeType); } } public Writes(Type writeType, int priority) { - var isComponent = writeType.GetInterfaces().Contains(typeof(IComponent)); - if (!isComponent) - { - throw new IllegalWriteTypeException("{0} must be a Component", writeType.Name); - } - WriteTypes.Add(writeType); Priorities.Add(writeType, priority); } diff --git a/encompass-cs/Attributes/WritesImmediate.cs b/encompass-cs/Attributes/WritesImmediate.cs index 0b5db7c..1011b55 100644 --- a/encompass-cs/Attributes/WritesImmediate.cs +++ b/encompass-cs/Attributes/WritesImmediate.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using Encompass.Exceptions; namespace Encompass { @@ -14,13 +12,7 @@ namespace Encompass { foreach (var writeImmediateType in writeImmediateTypes) { - var isComponent = writeImmediateType.GetInterfaces().Contains(typeof(IComponent)); - if (!isComponent) - { - throw new IllegalWriteImmediateTypeException("{0} must be a Component", writeImmediateType.Name); - } - - this.WriteImmediateTypes.Add(writeImmediateType); + WriteImmediateTypes.Add(writeImmediateType); } } } diff --git a/encompass-cs/Collections/ComponentBitSet.cs b/encompass-cs/Collections/ComponentBitSet.cs index 8c90cf5..2867686 100644 --- a/encompass-cs/Collections/ComponentBitSet.cs +++ b/encompass-cs/Collections/ComponentBitSet.cs @@ -24,13 +24,13 @@ namespace Encompass _entities.Add(entityID, BitSet512.Zero); } - public void Set(int entityID) where TComponent : struct, IComponent + public void Set(int entityID) where TComponent : struct { if (!_entities.ContainsKey(entityID)) { AddEntity(entityID); } _entities[entityID] = _entities[entityID].Set(_typeToIndex[typeof(TComponent)]); } - public void RemoveComponent(int entityID) where TComponent : struct, IComponent + public void RemoveComponent(int entityID) where TComponent : struct { if (_entities.ContainsKey(entityID)) { diff --git a/encompass-cs/Collections/ComponentStore.cs b/encompass-cs/Collections/ComponentStore.cs index 8f34731..e7d6491 100644 --- a/encompass-cs/Collections/ComponentStore.cs +++ b/encompass-cs/Collections/ComponentStore.cs @@ -8,27 +8,32 @@ namespace Encompass { private Dictionary _stores = new Dictionary(512); public ComponentBitSet ComponentBitSet { get; private set; } + private Dictionary _typeToIndex; public ComponentStore(Dictionary typeToIndex) { + _typeToIndex = typeToIndex; ComponentBitSet = new ComponentBitSet(typeToIndex); } - public virtual void RegisterComponentType() where TComponent : struct, IComponent + public virtual void RegisterComponentType() where TComponent : unmanaged { if (!_stores.ContainsKey(typeof(TComponent))) { var store = new TypedComponentStore(); _stores.Add(typeof(TComponent), store); } + + if (!_typeToIndex.ContainsKey(typeof(TComponent))) { _typeToIndex.Add(typeof(TComponent), _typeToIndex.Count); } } - private TypedComponentStore Lookup() where TComponent : struct, IComponent + private TypedComponentStore Lookup() where TComponent : unmanaged { + RegisterComponentType(); return _stores[typeof(TComponent)] as TypedComponentStore; } - public bool Has(int entityID) where TComponent : struct, IComponent + public bool Has(int entityID) where TComponent : unmanaged { return Lookup().Has(entityID); } @@ -43,18 +48,18 @@ namespace Encompass return ComponentBitSet.EntityBitArray(entityID); } - public ref readonly TComponent Get(int entityID) where TComponent : struct, IComponent + public ref readonly TComponent Get(int entityID) where TComponent : unmanaged { return ref Lookup().Get(entityID); } - public virtual void Set(int entityID, TComponent component) where TComponent : struct, IComponent + public virtual void Set(int entityID, TComponent component) where TComponent : unmanaged { Lookup().Set(entityID, component); ComponentBitSet.Set(entityID); } - public virtual bool Set(int entityID, TComponent component, int priority) where TComponent : struct, IComponent + public virtual bool Set(int entityID, TComponent component, int priority) where TComponent : unmanaged { if (Lookup().Set(entityID, component, priority)) { @@ -64,7 +69,7 @@ namespace Encompass return false; } - public virtual bool Remove(int entityID, int priority) where TComponent : struct, IComponent + public virtual bool Remove(int entityID, int priority) where TComponent : unmanaged { if (Lookup().Remove(entityID, priority)) { @@ -74,7 +79,7 @@ namespace Encompass return false; } - public void ForceRemove(int entityID) where TComponent : struct, IComponent + public void ForceRemove(int entityID) where TComponent : unmanaged { Lookup().ForceRemove(entityID); ComponentBitSet.RemoveComponent(entityID); @@ -89,17 +94,17 @@ namespace Encompass ComponentBitSet.RemoveEntity(entityID); } - public bool Any() where TComponent : struct, IComponent + public bool Any() where TComponent : unmanaged { return Lookup().Count > 0; } - public IEnumerable<(TComponent, int)> All() where TComponent : struct, IComponent + public IEnumerable<(TComponent, int)> All() where TComponent : unmanaged { return Lookup().All(); } - public void Clear() where TComponent : struct, IComponent + public void Clear() where TComponent : unmanaged { Lookup().Clear(); } diff --git a/encompass-cs/Collections/Replayer.cs b/encompass-cs/Collections/Replayer.cs index b5cd3f7..0bb9414 100644 --- a/encompass-cs/Collections/Replayer.cs +++ b/encompass-cs/Collections/Replayer.cs @@ -2,7 +2,7 @@ namespace Encompass { - internal abstract class Replayer + internal abstract class Replayer { public abstract void Replay(ComponentStore store); public abstract void MarkRemoval(int entityID); @@ -10,7 +10,7 @@ namespace Encompass public abstract void Clear(); } - internal class Replayer : Replayer where TComponent : struct, IComponent + internal class Replayer : Replayer where TComponent : unmanaged { private readonly ComponentDeltaStore _deltaStore; private readonly HashSet _removals = new HashSet(); diff --git a/encompass-cs/Collections/TypedComponentStore.cs b/encompass-cs/Collections/TypedComponentStore.cs index e1caa24..0fd06fa 100644 --- a/encompass-cs/Collections/TypedComponentStore.cs +++ b/encompass-cs/Collections/TypedComponentStore.cs @@ -14,7 +14,7 @@ namespace Encompass public abstract void ClearPriorities(); } - internal class TypedComponentStore : TypedComponentStore where TComponent : struct, IComponent + internal class TypedComponentStore : TypedComponentStore where TComponent : unmanaged { private readonly Dictionary _indices = new Dictionary(512); private readonly Dictionary _priorities = new Dictionary(512); diff --git a/encompass-cs/ComponentManager.cs b/encompass-cs/ComponentManager.cs index 928c9a0..da1a782 100644 --- a/encompass-cs/ComponentManager.cs +++ b/encompass-cs/ComponentManager.cs @@ -29,7 +29,7 @@ namespace Encompass TypeToIndex = typeToIndex; } - public void RegisterComponentType() where TComponent : struct, IComponent + public void RegisterComponentType() where TComponent : unmanaged { _existingComponentStore.RegisterComponentType(); _immediateComponentStore.RegisterComponentType(); @@ -47,7 +47,7 @@ namespace Encompass _upToDateComponentStore.SwapWith(componentStore); } - internal void RegisterDrawableComponent(int entityID, int layer) where TComponent : struct, IComponent + internal void RegisterDrawableComponent(int entityID, int layer) where TComponent : unmanaged { _drawLayerManager.RegisterComponentWithLayer(entityID, layer); } @@ -61,7 +61,7 @@ namespace Encompass _replayStore.ClearAll(); } - internal bool AddImmediateComponent(int entityID, TComponent component, int priority) where TComponent : struct, IComponent + internal bool AddImmediateComponent(int entityID, TComponent component, int priority) where TComponent : unmanaged { if (_immediateComponentStore.Set(entityID, component, priority)) { @@ -73,14 +73,14 @@ namespace Encompass return false; } - internal void AddImmediateComponent(int entityID, TComponent component) where TComponent : struct, IComponent + internal void AddImmediateComponent(int entityID, TComponent component) where TComponent : unmanaged { _immediateComponentStore.Set(entityID, component); _replayStore.Set(entityID, component); _upToDateComponentStore.Set(entityID, component); } - internal bool UpdateComponent(int entityID, TComponent component, int priority) where TComponent : struct, IComponent + internal bool UpdateComponent(int entityID, TComponent component, int priority) where TComponent : unmanaged { var result = _upToDateComponentStore.Set(entityID, component, priority); if (result) @@ -90,7 +90,7 @@ namespace Encompass return result; } - internal void AddComponent(int entityID, TComponent component) where TComponent : struct, IComponent + internal void AddComponent(int entityID, TComponent component) where TComponent : unmanaged { _upToDateComponentStore.Set(entityID, component); _replayStore.Set(entityID, component); @@ -98,12 +98,12 @@ namespace Encompass // existing or immediate reads - internal IEnumerable<(TComponent, int)> ReadExistingAndImmediateComponentsByType() where TComponent : struct, IComponent + internal IEnumerable<(TComponent, int)> ReadExistingAndImmediateComponentsByType() where TComponent : unmanaged { return _upToDateComponentStore.All(); } - internal (TComponent, int) ReadFirstExistingOrImmediateComponentByType() where TComponent : struct, IComponent + internal (TComponent, int) ReadFirstExistingOrImmediateComponentByType() where TComponent : unmanaged { if (!SomeExistingOrImmediateComponent()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } var enumerator = ReadExistingAndImmediateComponentsByType().GetEnumerator(); @@ -111,14 +111,14 @@ namespace Encompass return enumerator.Current; } - internal bool SomeExistingOrImmediateComponent() where TComponent : struct, IComponent + internal bool SomeExistingOrImmediateComponent() where TComponent : unmanaged { return _upToDateComponentStore.Any(); } // existing reads - internal (TComponent, int) ReadFirstExistingComponentByType() where TComponent : struct, IComponent + internal (TComponent, int) ReadFirstExistingComponentByType() where TComponent : unmanaged { if (!SomeExistingComponent()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } var enumerator = GetComponentsIncludingEntity().GetEnumerator(); @@ -126,19 +126,19 @@ namespace Encompass return enumerator.Current; } - internal bool SomeExistingComponent() where TComponent : struct, IComponent + internal bool SomeExistingComponent() where TComponent : unmanaged { return _existingComponentStore.Any(); } // immediate reads - internal IEnumerable<(TComponent, int)> ReadImmediateComponentsByType() where TComponent : struct, IComponent + internal IEnumerable<(TComponent, int)> ReadImmediateComponentsByType() where TComponent : unmanaged { return _immediateComponentStore.All(); } - internal (TComponent, int) ReadFirstImmediateComponentByType() where TComponent : struct, IComponent + internal (TComponent, int) ReadFirstImmediateComponentByType() where TComponent : unmanaged { if (!SomeImmediateComponent()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } var enumerator = ReadImmediateComponentsByType().GetEnumerator(); @@ -146,31 +146,31 @@ namespace Encompass return enumerator.Current; } - internal bool SomeImmediateComponent() where TComponent : struct, IComponent + internal bool SomeImmediateComponent() where TComponent : unmanaged { return _immediateComponentStore.Any(); } // component getters - internal ref readonly TComponent ReadImmediateOrExistingComponentByEntityAndType(int entityID) where TComponent : struct, IComponent + internal ref readonly TComponent ReadImmediateOrExistingComponentByEntityAndType(int entityID) where TComponent : unmanaged { return ref _upToDateComponentStore.Get(entityID); } - internal ref readonly TComponent ReadExistingComponentByEntityAndType(int entityID) where TComponent : struct, IComponent + internal ref readonly TComponent ReadExistingComponentByEntityAndType(int entityID) where TComponent : unmanaged { return ref _existingComponentStore.Get(entityID); } - internal ref readonly TComponent ReadImmediateComponentByEntityAndType(int entityID) where TComponent : struct, IComponent + internal ref readonly TComponent ReadImmediateComponentByEntityAndType(int entityID) where TComponent : unmanaged { return ref _immediateComponentStore.Get(entityID); } // has checkers - internal bool HasExistingOrImmediateComponent(int entityID) where TComponent : struct, IComponent + internal bool HasExistingOrImmediateComponent(int entityID) where TComponent : unmanaged { return _upToDateComponentStore.Has(entityID); } @@ -180,7 +180,7 @@ namespace Encompass return _upToDateComponentStore.Has(type, entityID); } - internal bool HasExistingComponent(int entityID) where TComponent : struct, IComponent + internal bool HasExistingComponent(int entityID) where TComponent : unmanaged { return _existingComponentStore.Has(entityID); } @@ -190,7 +190,7 @@ namespace Encompass return _existingComponentStore.Has(type, entityID); } - internal bool HasImmediateComponent(int entityID) where TComponent : struct, IComponent + internal bool HasImmediateComponent(int entityID) where TComponent : unmanaged { return _immediateComponentStore.Has(entityID); } @@ -200,12 +200,12 @@ namespace Encompass return _immediateComponentStore.Has(type, entityID); } - internal IEnumerable<(TComponent, int)> GetComponentsIncludingEntity() where TComponent : struct, IComponent + internal IEnumerable<(TComponent, int)> GetComponentsIncludingEntity() where TComponent : unmanaged { return _existingComponentStore.All(); } - internal IEnumerable GetComponentsByType() where TComponent : struct, IComponent + internal IEnumerable GetComponentsByType() where TComponent : unmanaged { foreach (var pair in _existingComponentStore.All()) { @@ -213,12 +213,12 @@ namespace Encompass } } - internal ref readonly TComponent GetComponentByEntityAndType(int entityID) where TComponent : struct, IComponent + internal ref readonly TComponent GetComponentByEntityAndType(int entityID) where TComponent : unmanaged { return ref _existingComponentStore.Get(entityID); } - internal bool EntityHasComponentOfType(int entityID) where TComponent : struct, IComponent + internal bool EntityHasComponentOfType(int entityID) where TComponent : unmanaged { return _existingComponentStore.Has(entityID); } @@ -242,7 +242,7 @@ namespace Encompass _entitiesMarkedForRemoval.Clear(); } - public bool RemoveImmediate(int entityID, int priority) where TComponent : struct, IComponent + public bool RemoveImmediate(int entityID, int priority) where TComponent : unmanaged { if (_immediateComponentStore.Remove(entityID, priority)) { @@ -254,7 +254,7 @@ namespace Encompass return false; } - public void Remove(int entityID, int priority) where TComponent : struct, IComponent + public void Remove(int entityID, int priority) where TComponent : unmanaged { if (_upToDateComponentStore.Remove(entityID, priority)) { diff --git a/encompass-cs/DrawLayerManager.cs b/encompass-cs/DrawLayerManager.cs index 3c14f21..71eaec0 100644 --- a/encompass-cs/DrawLayerManager.cs +++ b/encompass-cs/DrawLayerManager.cs @@ -30,7 +30,7 @@ namespace Encompass } } - public void RegisterOrderedDrawable() where TComponent : struct, IComponent + public void RegisterOrderedDrawable() where TComponent : struct { if (!_typeToEntityToLayer.ContainsKey(typeof(TComponent))) { @@ -53,7 +53,7 @@ namespace Encompass set.Add(renderer); } - public void RegisterComponentWithLayer(int entityID, int layer) where TComponent : struct, IComponent + public void RegisterComponentWithLayer(int entityID, int layer) where TComponent : struct { if (!_layerIndexToTypeToID.ContainsKey(layer)) { @@ -68,7 +68,7 @@ namespace Encompass _typeToEntityToLayer[typeof(TComponent)].Add(entityID, layer); } - public void UnRegisterComponentWithLayer(int entityID) where TComponent : struct, IComponent + public void UnRegisterComponentWithLayer(int entityID) where TComponent : struct { if (!_typeToEntityToLayer.ContainsKey(typeof(TComponent))) { return; } diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index fab7457..bc29221 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -213,7 +213,7 @@ namespace Encompass /// /// Returns an Entity containing the specified Component type. /// - protected Entity ReadEntity() where TComponent : struct, IComponent + protected Entity ReadEntity() where TComponent : unmanaged { return _entityManager.GetEntity(ReadComponentHelper().Item2); } @@ -221,7 +221,7 @@ namespace Encompass /// /// Returns all Entities containing the specified Component type. /// - protected IEnumerable ReadEntities() where TComponent : struct, IComponent + protected IEnumerable ReadEntities() where TComponent : unmanaged { foreach (var pair in ReadComponentsHelper()) { @@ -231,12 +231,12 @@ namespace Encompass // these next two are for the ComponentMessageEmitter only - internal IEnumerable ReadComponentsFromWorld() where TComponent : struct, IComponent + internal IEnumerable ReadComponentsFromWorld() where TComponent : unmanaged { return _componentManager.GetComponentsByType(); } - private IEnumerable<(TComponent, int)> ReadComponentsHelper() where TComponent : struct, IComponent + private IEnumerable<(TComponent, int)> ReadComponentsHelper() where TComponent : unmanaged { var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent)); @@ -261,7 +261,7 @@ namespace Encompass /// /// Returns all of the Components with the specified Component Type. /// - protected IEnumerable ReadComponents() where TComponent : struct, IComponent + protected IEnumerable ReadComponents() where TComponent : unmanaged { foreach (var pair in ReadComponentsHelper()) { @@ -272,7 +272,7 @@ namespace Encompass /// /// Returns all of the components of the specified type including an Entity reference for each Component. /// - protected IEnumerable<(TComponent, Entity)> ReadComponentsIncludingEntity() where TComponent : struct, IComponent + protected IEnumerable<(TComponent, Entity)> ReadComponentsIncludingEntity() where TComponent : unmanaged { foreach (var (component, id) in ReadComponentsHelper()) { @@ -280,7 +280,7 @@ namespace Encompass } } - private (TComponent, int) ReadComponentHelper() where TComponent : struct, IComponent + private (TComponent, int) ReadComponentHelper() where TComponent : unmanaged { var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent)); @@ -305,7 +305,7 @@ namespace Encompass /// /// Returns a Component with the specified Component Type. If multiples exist, an arbitrary Component is returned. /// - protected TComponent ReadComponent() where TComponent : struct, IComponent + protected TComponent ReadComponent() where TComponent : unmanaged { return ReadComponentHelper().Item1; } @@ -313,7 +313,7 @@ namespace Encompass /// /// Returns a component of the specified type including its Entity reference. If multiples exist, an arbitrary Component is returned. /// - protected (TComponent, Entity) ReadComponentIncludingEntity() where TComponent : struct, IComponent + protected (TComponent, Entity) ReadComponentIncludingEntity() where TComponent : unmanaged { var (component, id) = ReadComponentHelper(); return (component, _entityManager.GetEntity(id)); @@ -322,7 +322,7 @@ namespace Encompass /// /// Returns true if any Component with the specified Component Type exists. /// - protected bool SomeComponent() where TComponent : struct, IComponent + protected bool SomeComponent() where TComponent : unmanaged { var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent)); @@ -344,7 +344,7 @@ namespace Encompass } } - private ref readonly TComponent GetComponentHelper(int entityID) where TComponent : struct, IComponent + private ref readonly TComponent GetComponentHelper(int entityID) where TComponent : unmanaged { var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent)); @@ -375,7 +375,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that it reads the given Component Type. /// - protected ref readonly TComponent GetComponent(Entity entity) where TComponent : struct, IComponent + protected ref readonly TComponent GetComponent(Entity entity) where TComponent : unmanaged { return ref GetComponentHelper(entity.ID); } @@ -386,7 +386,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that is Reads the given Component Type. /// - protected bool HasComponent(Entity entity) where TComponent : struct, IComponent + protected bool HasComponent(Entity entity) where TComponent : unmanaged { var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent)); @@ -444,7 +444,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that it Writes the given Component Type. /// - protected void SetComponent(Entity entity, TComponent component) where TComponent : struct, IComponent + protected void SetComponent(Entity entity, TComponent component) where TComponent : unmanaged { var priority = WritePriorities.ContainsKey(typeof(TComponent)) ? WritePriorities[typeof(TComponent)] : DefaultWritePriority; @@ -484,7 +484,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that it Writes the given Component Type. /// - protected void AddComponent(Entity entity, TComponent component) where TComponent : struct, IComponent + protected void AddComponent(Entity entity, TComponent component) where TComponent : unmanaged { if (!EntityCreatedThisFrame(entity.ID)) { @@ -592,7 +592,7 @@ namespace Encompass /// Destroys an arbitrary Entity containing a Component of the specified Type. /// Entity destruction takes place after all the Engines have been processed by World Update. /// - protected void DestroyWith() where TComponent : struct, IComponent + protected void DestroyWith() where TComponent : unmanaged { Destroy(ReadEntity()); } @@ -601,7 +601,7 @@ namespace Encompass /// Destroys all Entities containing a Component of the specified Type. /// Entity destruction takes place after all the Engines have been processed by World Update. /// - protected void DestroyAllWith() where TComponent : struct, IComponent + protected void DestroyAllWith() where TComponent : unmanaged { foreach (var entity in ReadEntities()) { @@ -614,7 +614,7 @@ namespace Encompass /// Note that the Engine must Read the Component type that is being removed. /// If a Component with the specified type does not exist on the Entity, returns false and does not mutate the Entity. /// - protected void RemoveComponent(Entity entity) where TComponent : struct, IComponent + protected void RemoveComponent(Entity entity) where TComponent : unmanaged { var priority = WritePriorities.ContainsKey(typeof(TComponent)) ? WritePriorities[typeof(TComponent)] : DefaultWritePriority; @@ -764,24 +764,28 @@ namespace Encompass var withMask = BitSet512.Zero; foreach (var type in QueryWithTypes) { + if (!_componentManager.TypeToIndex.ContainsKey(type)) { _componentManager.TypeToIndex.Add(type, _componentManager.TypeToIndex.Count); } withMask = withMask.Set(_componentManager.TypeToIndex[type]); } var withoutMask = BitSet512.Zero; foreach (var type in QueryWithoutTypes) { + if (!_componentManager.TypeToIndex.ContainsKey(type)) { _componentManager.TypeToIndex.Add(type, _componentManager.TypeToIndex.Count); } withoutMask = withoutMask.Set(_componentManager.TypeToIndex[type]); } var immediateMask = BitSet512.Zero; foreach (var type in ReadImmediateTypes) { + if (!_componentManager.TypeToIndex.ContainsKey(type)) { _componentManager.TypeToIndex.Add(type, _componentManager.TypeToIndex.Count); } immediateMask = immediateMask.Set(_componentManager.TypeToIndex[type]); } var existingMask = BitSet512.Zero; foreach (var type in ReadTypes) { + if (!_componentManager.TypeToIndex.ContainsKey(type)) { _componentManager.TypeToIndex.Add(type, _componentManager.TypeToIndex.Count); } existingMask = existingMask.Set(_componentManager.TypeToIndex[type]); } diff --git a/encompass-cs/Exceptions/IllegalReadTypeException.cs b/encompass-cs/Exceptions/IllegalReadTypeException.cs deleted file mode 100644 index 3bc2512..0000000 --- a/encompass-cs/Exceptions/IllegalReadTypeException.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace Encompass.Exceptions -{ - public class IllegalReadTypeException : Exception - { - public IllegalReadTypeException( - string format, - params object[] args - ) : base(string.Format(format, args)) { } - } -} diff --git a/encompass-cs/IComponent.cs b/encompass-cs/IComponent.cs deleted file mode 100644 index 4fcce29..0000000 --- a/encompass-cs/IComponent.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Encompass -{ - /// - /// Structs that implement IComponent are considered to be Components. - /// - public interface IComponent { } -} diff --git a/encompass-cs/RenderManager.cs b/encompass-cs/RenderManager.cs index 3f603b4..0fa030b 100644 --- a/encompass-cs/RenderManager.cs +++ b/encompass-cs/RenderManager.cs @@ -16,7 +16,7 @@ namespace Encompass _drawLayerManager = drawLayerManager; } - public void RegisterOrderedRenderer(Action renderAction) where TComponent : struct, IComponent + public void RegisterOrderedRenderer(Action renderAction) where TComponent : unmanaged { _drawComponentTypeToOrderedRenderer.Add(typeof(TComponent), renderAction); _drawLayerManager.RegisterOrderedDrawable(); diff --git a/encompass-cs/Renderer.cs b/encompass-cs/Renderer.cs index f7f3b88..07939f2 100644 --- a/encompass-cs/Renderer.cs +++ b/encompass-cs/Renderer.cs @@ -17,7 +17,7 @@ namespace Encompass _componentManager = componentManager; } - protected IEnumerable ReadEntities() where TComponent : struct, IComponent + protected IEnumerable ReadEntities() where TComponent : unmanaged { foreach (var pair in ReadComponentsIncludingEntity()) { @@ -25,17 +25,17 @@ namespace Encompass } } - protected Entity ReadEntity() where TComponent : struct, IComponent + protected Entity ReadEntity() where TComponent : unmanaged { return ReadComponentIncludingEntity().Item2; } - protected IEnumerable ReadComponents() where TComponent : struct, IComponent + protected IEnumerable ReadComponents() where TComponent : unmanaged { return _componentManager.GetComponentsByType(); } - protected IEnumerable<(TComponent, Entity)> ReadComponentsIncludingEntity() where TComponent : struct, IComponent + protected IEnumerable<(TComponent, Entity)> ReadComponentsIncludingEntity() where TComponent : unmanaged { foreach (var (component, id) in _componentManager.GetComponentsIncludingEntity()) { @@ -43,31 +43,31 @@ namespace Encompass } } - protected TComponent ReadComponent() where TComponent : struct, IComponent + protected TComponent ReadComponent() where TComponent : unmanaged { var enumerator = ReadComponents().GetEnumerator(); enumerator.MoveNext(); return enumerator.Current; } - protected (TComponent, Entity) ReadComponentIncludingEntity() where TComponent : struct, IComponent + protected (TComponent, Entity) ReadComponentIncludingEntity() where TComponent : unmanaged { var enumerator = ReadComponentsIncludingEntity().GetEnumerator(); enumerator.MoveNext(); return enumerator.Current; } - protected ref readonly TComponent GetComponent(Entity entity) where TComponent : struct, IComponent + protected ref readonly TComponent GetComponent(Entity entity) where TComponent : unmanaged { return ref _componentManager.GetComponentByEntityAndType(entity.ID); } - protected bool HasComponent(Entity entity) where TComponent : struct, IComponent + protected bool HasComponent(Entity entity) where TComponent : unmanaged { return _componentManager.EntityHasComponentOfType(entity.ID); } - protected bool SomeComponent() where TComponent : struct, IComponent + protected bool SomeComponent() where TComponent : unmanaged { return _componentManager.SomeExistingComponent(); } diff --git a/encompass-cs/Renderers/OrderedRenderer.cs b/encompass-cs/Renderers/OrderedRenderer.cs index 162322a..a8458ae 100644 --- a/encompass-cs/Renderers/OrderedRenderer.cs +++ b/encompass-cs/Renderers/OrderedRenderer.cs @@ -5,7 +5,7 @@ namespace Encompass /// /// OrdereredRenderer provides a structure for the common pattern of wishing to draw a specific DrawComponent at a specific layer. /// - public abstract class OrderedRenderer : Renderer where TComponent : struct, IComponent, IDrawableComponent + public abstract class OrderedRenderer : Renderer where TComponent : unmanaged, IDrawableComponent { public abstract void Render(Entity entity, in TComponent drawComponent); diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs index ad8a5ba..461c159 100644 --- a/encompass-cs/WorldBuilder.cs +++ b/encompass-cs/WorldBuilder.cs @@ -84,7 +84,7 @@ namespace Encompass /// /// Sets Component data for the specified Component Type on the specified Entity. /// - public void SetComponent(Entity entity, TComponent component) where TComponent : struct, IComponent + public void SetComponent(Entity entity, TComponent component) where TComponent : unmanaged { RegisterComponentType(); _startingExistingComponentStore.Set(entity.ID, component); @@ -97,7 +97,7 @@ namespace Encompass } } - internal void RegisterComponentType() where TComponent : struct, IComponent + internal void RegisterComponentType() where TComponent : unmanaged { if (!_typeToIndex.ContainsKey(typeof(TComponent))) { @@ -183,7 +183,7 @@ namespace Encompass /// /// Adds the specified OrderedRenderer to the World. /// - public OrderedRenderer AddOrderedRenderer(OrderedRenderer renderer) where TComponent : struct, IComponent, IDrawableComponent + public OrderedRenderer AddOrderedRenderer(OrderedRenderer renderer) where TComponent : unmanaged, IDrawableComponent { RegisterComponentType(); renderer.AssignEntityManager(_entityManager); @@ -354,20 +354,6 @@ namespace Encompass throw new EngineWriteConflictException(errorString); } - // doing reflection to grab all component types, because not all writes need to be declared - foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) - { - foreach (var componentType in assembly.GetTypes()) - { - if (typeof(IComponent).IsAssignableFrom(componentType) && componentType.IsValueType && !componentType.IsEnum && !componentType.IsPrimitive) - { - var method = typeof(WorldBuilder).GetMethod("RegisterComponentType", BindingFlags.NonPublic | BindingFlags.Instance); - var generic = method.MakeGenericMethod(componentType); - generic.Invoke(this, null); - } - } - } - PreloadJIT(_componentTypesToPreload, _messageTypes); var engineOrder = new List(); diff --git a/test/ComponentTest.cs b/test/ComponentTest.cs index 1b94e51..684a07f 100644 --- a/test/ComponentTest.cs +++ b/test/ComponentTest.cs @@ -2,14 +2,14 @@ using NUnit.Framework; using FluentAssertions; using Encompass; +using System.Runtime.CompilerServices; namespace Tests { public class ComponentTests { - struct MockComponent : Encompass.IComponent + struct MockComponent { - public string myString; public int myInt; } @@ -54,16 +54,17 @@ namespace Tests } [Test] - public void AddComponent() + public unsafe void AddComponent() { var worldBuilder = new WorldBuilder(); worldBuilder.AddEngine(new AddComponentTestEngine()); var entity = worldBuilder.CreateEntity(); + const string MyString = "hello"; + MockComponent mockComponent; mockComponent.myInt = 3; - mockComponent.myString = "hello"; worldBuilder.SetComponent(entity, mockComponent); @@ -85,16 +86,15 @@ namespace Tests worldBuilder.AddEngine(new ReadMockComponentEngine()); var entity = worldBuilder.CreateEntity(); - worldBuilder.SetComponent(entity, new MockComponent { myInt = 20, myString = "what" }); - worldBuilder.SetComponent(entity, new MockComponent { myInt = 50, myString = "hi" }); - worldBuilder.SetComponent(entity, new MockComponent { myInt = 40, myString = "wassup" }); + worldBuilder.SetComponent(entity, new MockComponent { myInt = 20 }); + worldBuilder.SetComponent(entity, new MockComponent { myInt = 50 }); + worldBuilder.SetComponent(entity, new MockComponent { myInt = 40 }); var world = worldBuilder.Build(); world.Update(0.01); Assert.That(gottenMockComponent.myInt, Is.EqualTo(40)); - Assert.That(gottenMockComponent.myString, Is.EqualTo("wassup")); } [Reads(typeof(MockComponent))] @@ -191,7 +191,6 @@ namespace Tests { MockComponent mockComponent; mockComponent.myInt = 10; - mockComponent.myString = "four"; AddMockComponentMessage addMockComponentMessage; addMockComponentMessage.entity = entity; @@ -255,9 +254,8 @@ namespace Tests MockComponent mockComponent; mockComponent.myInt = 3; - mockComponent.myString = "hello"; - worldBuilder.SetComponent(entity, mockComponent); + worldBuilder.SetComponent(entity, mockComponent); EntityMessage entityMessage; entityMessage.entity = entity; @@ -298,7 +296,6 @@ namespace Tests MockComponent mockComponent; mockComponent.myInt = 3; - mockComponent.myString = "hello"; worldBuilder.SetComponent(entity, mockComponent); @@ -336,7 +333,6 @@ namespace Tests MockComponent mockComponent; mockComponent.myInt = 3; - mockComponent.myString = "hello"; worldBuilder.SetComponent(entity, mockComponent); @@ -446,7 +442,6 @@ namespace Tests MockComponent mockComponent; mockComponent.myInt = 3; - mockComponent.myString = "hello"; worldBuilder.SetComponent(entity, mockComponent); diff --git a/test/EngineTest.cs b/test/EngineTest.cs index 77ceeb1..208f455 100644 --- a/test/EngineTest.cs +++ b/test/EngineTest.cs @@ -10,10 +10,9 @@ using Encompass.Exceptions; namespace Tests { - struct MockComponent : IComponent + struct MockComponent { public int myInt; - public string myString; } public class EngineTest @@ -72,12 +71,10 @@ namespace Tests var entityB = worldBuilder.CreateEntity(); MockComponent mockComponent; - mockComponent.myInt = 0; - mockComponent.myString = "hello"; + mockComponent.myInt = 2; MockComponent mockComponentB; mockComponentB.myInt = 1; - mockComponentB.myString = "howdy"; worldBuilder.SetComponent(entity, mockComponent); worldBuilder.SetComponent(entityB, mockComponentB); @@ -100,12 +97,10 @@ namespace Tests var entityB = worldBuilder.CreateEntity(); MockComponent mockComponent; - mockComponent.myInt = 0; - mockComponent.myString = "hello"; + mockComponent.myInt = 2; MockComponent mockComponentB; mockComponentB.myInt = 1; - mockComponentB.myString = "howdy"; worldBuilder.SetComponent(entity, mockComponent); worldBuilder.SetComponent(entityB, mockComponentB); @@ -135,8 +130,7 @@ namespace Tests var entity = worldBuilder.CreateEntity(); MockComponent mockComponent; - mockComponent.myInt = 0; - mockComponent.myString = "hello"; + mockComponent.myInt = 3; worldBuilder.SetComponent(entity, mockComponent); @@ -157,12 +151,10 @@ namespace Tests var entityB = worldBuilder.CreateEntity(); MockComponent mockComponent; - mockComponent.myInt = 0; - mockComponent.myString = "hello"; + mockComponent.myInt = 2; MockComponent mockComponentB; mockComponentB.myInt = 1; - mockComponentB.myString = "howdy"; worldBuilder.SetComponent(entity, mockComponent); worldBuilder.SetComponent(entityB, mockComponentB); @@ -183,8 +175,7 @@ namespace Tests var entity = worldBuilder.CreateEntity(); MockComponent mockComponent; - mockComponent.myInt = 0; - mockComponent.myString = "hello"; + mockComponent.myInt = 2; worldBuilder.SetComponent(entity, mockComponent); @@ -204,7 +195,6 @@ namespace Tests var (component, entity) = ReadComponentIncludingEntity(); component.myInt = 420; - component.myString = "blaze it"; SetComponent(entity, component); } } @@ -222,8 +212,7 @@ namespace Tests var entity = worldBuilder.CreateEntity(); MockComponent mockComponent; - mockComponent.myInt = 0; - mockComponent.myString = "hello"; + mockComponent.myInt = 3; worldBuilder.SetComponent(entity, mockComponent); @@ -233,7 +222,6 @@ namespace Tests world.Update(0.01); Assert.AreEqual(420, resultComponent.myInt); - Assert.AreEqual("blaze it", resultComponent.myString); } [Reads(typeof(MockComponent))] @@ -244,7 +232,6 @@ namespace Tests var (component, entity) = ReadComponentIncludingEntity(); component.myInt = 420; - component.myString = "blaze it"; SetComponent(entity, component); component = ReadComponent(); @@ -260,8 +247,7 @@ namespace Tests var entity = worldBuilder.CreateEntity(); MockComponent mockComponent; - mockComponent.myInt = 0; - mockComponent.myString = "hello"; + mockComponent.myInt = 3; worldBuilder.SetComponent(entity, mockComponent); @@ -594,11 +580,9 @@ namespace Tests MockComponent componentA; componentA.myInt = 20; - componentA.myString = "hello"; MockComponent componentB; componentB.myInt = 20; - componentB.myString = "hello"; var entity = worldBuilder.CreateEntity(); worldBuilder.SetComponent(entity, componentA); @@ -636,7 +620,7 @@ namespace Tests Assert.That(emptyComponentReadResult, Is.Empty); } - struct DestroyerComponent : IComponent { } + struct DestroyerComponent { } [Reads(typeof(DestroyerComponent))] class DestroyerEngine : Engine @@ -675,7 +659,6 @@ namespace Tests DestroyerComponent destroyerComponent; MockComponent mockComponent; mockComponent.myInt = 2; - mockComponent.myString = "blah"; worldBuilder.SetComponent(entity, destroyerComponent); worldBuilder.SetComponent(entity, mockComponent); @@ -975,14 +958,14 @@ namespace Tests entity.Should().BeEquivalentTo(readEntity); } - struct MockComponentB : IComponent + struct MockComponentB { + private int value; + public MockComponentB(int value) { this.value = value; } - - int value; } static MockComponentB getComponentResult; @@ -1420,9 +1403,9 @@ namespace Tests public class QueryTests { - struct MockComponentB : IComponent { } - struct MockComponentC : IComponent { } - struct MockComponentD : IComponent { } + struct MockComponentB { } + struct MockComponentC { } + struct MockComponentD { } [Reads(typeof(MockComponent), typeof(MockComponentB))] [Writes(typeof(MockComponentB))] @@ -1877,14 +1860,14 @@ namespace Tests _components.Should().NotBeEmpty(); } - struct MockTimerComponent : IComponent + struct MockTimerComponent { + public double Timer { get; set; } + public MockTimerComponent(double time) { Timer = time; } - - public double Timer { get; set; } } [Reads(typeof(MockTimerComponent))] diff --git a/test/GeneralRendererTest.cs b/test/GeneralRendererTest.cs index bc1aedc..9627d34 100644 --- a/test/GeneralRendererTest.cs +++ b/test/GeneralRendererTest.cs @@ -5,7 +5,7 @@ namespace Tests { public static class GeneralRendererTest { - struct AComponent : IComponent { } + struct AComponent { } public class SingletonRead { diff --git a/test/OrderedRendererTest.cs b/test/OrderedRendererTest.cs index 92cb3b8..2ee2af7 100644 --- a/test/OrderedRendererTest.cs +++ b/test/OrderedRendererTest.cs @@ -9,11 +9,11 @@ namespace Tests { public class OrderedRendererTest { - struct AComponent : IComponent { } - struct BComponent : IComponent { } - struct CComponent : IComponent { } + struct AComponent { } + struct BComponent { } + struct CComponent { } - struct TestDrawComponent : IComponent, IDrawableComponent + struct TestDrawComponent : IDrawableComponent { public int Layer { get; set; } } diff --git a/test/SpawnerTest.cs b/test/SpawnerTest.cs index c0c5f0c..e31ed37 100644 --- a/test/SpawnerTest.cs +++ b/test/SpawnerTest.cs @@ -5,7 +5,7 @@ namespace Tests { public class SpawnerTest { - struct TestComponent : IComponent { } + struct TestComponent { } struct SpawnMessageA : IMessage { } static Entity resultEntity; diff --git a/test/WorldBuilderTest.cs b/test/WorldBuilderTest.cs index 2fd62fd..9a705f2 100644 --- a/test/WorldBuilderTest.cs +++ b/test/WorldBuilderTest.cs @@ -114,7 +114,7 @@ namespace Tests public class MultipleEngineWriteConflict { - struct AComponent : IComponent { } + struct AComponent { } [Writes(typeof(AComponent))] class AEngine : Engine @@ -146,7 +146,7 @@ namespace Tests public Entity entity; } - struct AComponent : IComponent + struct AComponent { public int myInt; } @@ -215,7 +215,7 @@ namespace Tests public Entity entity; } - struct AComponent : IComponent + struct AComponent { public int myInt; } @@ -318,28 +318,6 @@ namespace Tests } } - public class IllegalReadType - { - struct ANonMessage { } - - [Reads(typeof(ANonMessage))] - class MyEngine : Engine - { - public override void Update(double dt) - { - - } - } - - [Test] - public void ThrowsError() - { - var worldBuilder = new WorldBuilder(); - - Assert.Throws(() => worldBuilder.AddEngine(new MyEngine()), "ANonMessage must be a Message or Component"); - } - } - public class IllegalWriteType { struct ANonMessage { } @@ -428,8 +406,8 @@ namespace Tests { static List order = new List(); - struct AComponent : IComponent { } - struct BComponent : IComponent { } + struct AComponent { } + struct BComponent { } struct AMessage : IMessage { } struct BMessage : IMessage { } diff --git a/test/WorldTest.cs b/test/WorldTest.cs index 6ce089b..f985dc1 100644 --- a/test/WorldTest.cs +++ b/test/WorldTest.cs @@ -11,8 +11,8 @@ namespace Tests { public class WorldTest { - struct TestComponent : IComponent { } - struct TestDrawComponent : IComponent, IDrawableComponent + struct TestComponent { } + struct TestDrawComponent : IDrawableComponent { public int Layer { get; set; } } diff --git a/test/test.csproj b/test/test.csproj index 8f6a401..9479dc3 100644 --- a/test/test.csproj +++ b/test/test.csproj @@ -5,6 +5,7 @@ false Tests EncompassECS.Framework.Tests + true From 255760a3d7f92cc9027f68f141c6cffc8ea333ec Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Fri, 20 Mar 2020 18:09:24 -0700 Subject: [PATCH 08/30] unmanaged component store --- encompass-cs/Collections/ComponentStore.cs | 2 +- encompass-cs/Collections/FixedArray.cs | 69 +++++++++++++++++++ .../Collections/TypedComponentStore.cs | 9 ++- test/ComponentTest.cs | 3 +- 4 files changed, 76 insertions(+), 7 deletions(-) create mode 100644 encompass-cs/Collections/FixedArray.cs diff --git a/encompass-cs/Collections/ComponentStore.cs b/encompass-cs/Collections/ComponentStore.cs index e7d6491..2743e68 100644 --- a/encompass-cs/Collections/ComponentStore.cs +++ b/encompass-cs/Collections/ComponentStore.cs @@ -8,7 +8,7 @@ namespace Encompass { private Dictionary _stores = new Dictionary(512); public ComponentBitSet ComponentBitSet { get; private set; } - private Dictionary _typeToIndex; + private readonly Dictionary _typeToIndex; public ComponentStore(Dictionary typeToIndex) { diff --git a/encompass-cs/Collections/FixedArray.cs b/encompass-cs/Collections/FixedArray.cs new file mode 100644 index 0000000..242e9c6 --- /dev/null +++ b/encompass-cs/Collections/FixedArray.cs @@ -0,0 +1,69 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +internal unsafe class FixedArray : IDisposable where T : unmanaged +{ + private void* _buffer; + + public int Length { get; private set; } + + public T this[int i] + { + get { return ReadElement(_buffer, i); } + set { WriteElement(_buffer, i, value); } + } + + public unsafe FixedArray(int length, bool clearMemory = false) + { + var bufferSize = Marshal.SizeOf() * length; + _buffer = (void*)Alloc(bufferSize); + + if (clearMemory) + { + Memset(_buffer, 0, bufferSize); + } + + Length = length; + } + + public ref T ByRef(int i) + { + return ref *(T*)((byte*)_buffer + i * sizeof(T)); + } + + void IDisposable.Dispose() + { + Free((IntPtr)_buffer); + _buffer = null; + Length = 0; + } + + private static T ReadElement(void* buffer, int i) + { + return *(T*)((byte*)buffer + i * sizeof(T)); + } + + private static void WriteElement(void* buffer, int i, T value) + { + *(T*)((byte*)buffer + i * sizeof(T)) = value; + } + + private unsafe static IntPtr Alloc(int size) + { + return Marshal.AllocHGlobal(size); + } + + public unsafe static void Free(IntPtr ptr) + { + if (ptr != IntPtr.Zero) + { + Marshal.FreeHGlobal(ptr); + } + } + + private unsafe static void Memset(void* ptr, byte value, int count) + { + Unsafe.InitBlock(ptr, value, (uint)count); + } +} diff --git a/encompass-cs/Collections/TypedComponentStore.cs b/encompass-cs/Collections/TypedComponentStore.cs index 0fd06fa..8ae25b6 100644 --- a/encompass-cs/Collections/TypedComponentStore.cs +++ b/encompass-cs/Collections/TypedComponentStore.cs @@ -14,11 +14,11 @@ namespace Encompass public abstract void ClearPriorities(); } - internal class TypedComponentStore : TypedComponentStore where TComponent : unmanaged + internal unsafe class TypedComponentStore : TypedComponentStore where TComponent : unmanaged { private readonly Dictionary _indices = new Dictionary(512); private readonly Dictionary _priorities = new Dictionary(512); - private readonly TComponent[] _components = new TComponent[512]; + private readonly FixedArray _components = new FixedArray(512); // TODO: allow specify size private readonly IDManager _idManager = new IDManager(); public override int Count { get => _indices.Count; } @@ -26,8 +26,7 @@ namespace Encompass public unsafe ref readonly TComponent Get(int entityID) { if (!_indices.ContainsKey(entityID)) { throw new Exceptions.NoComponentOfTypeOnEntityException("No component of type {0} exists on Entity with ID {1}", typeof(TComponent), entityID); } - ref var refVal = ref _components[_indices[entityID]]; - return ref Unsafe.AsRef(Unsafe.AsPointer(ref refVal)); + return ref _components.ByRef(_indices[entityID]); } public unsafe void Set(int entityID, TComponent component) @@ -54,7 +53,7 @@ namespace Encompass _indices[entityID] = _idManager.NextID(); } - _components[_indices[entityID]] = Unsafe.AsRef(Unsafe.AsPointer(ref component)); + _components[_indices[entityID]] = component; } public override bool Remove(int entityID, int priority) diff --git a/test/ComponentTest.cs b/test/ComponentTest.cs index 684a07f..95c8f68 100644 --- a/test/ComponentTest.cs +++ b/test/ComponentTest.cs @@ -48,7 +48,8 @@ namespace Tests foreach (var addComponentTestMessage in ReadMessages()) { Assert.IsTrue(HasComponent(addComponentTestMessage.entity)); - Assert.That(GetComponent(addComponentTestMessage.entity), Is.EqualTo(addComponentTestMessage.mockComponent)); + var gottenComponent = GetComponent(addComponentTestMessage.entity); + gottenComponent.Should().BeEquivalentTo(addComponentTestMessage.mockComponent); } } } From 812fe10ca1d55a7a13c1d186f0e7f76ff5fb0d14 Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Sat, 21 Mar 2020 17:38:35 -0700 Subject: [PATCH 09/30] remove unmanaged constraint from component storage --- encompass-cs/Collections/ComponentStore.cs | 22 +++--- encompass-cs/Collections/FixedArray.cs | 69 ------------------- encompass-cs/Collections/Replayer.cs | 2 +- .../Collections/TypedComponentStore.cs | 6 +- encompass-cs/ComponentManager.cs | 52 +++++++------- encompass-cs/Engine.cs | 36 +++++----- encompass-cs/RenderManager.cs | 2 +- encompass-cs/Renderer.cs | 18 ++--- encompass-cs/Renderers/OrderedRenderer.cs | 2 +- encompass-cs/WorldBuilder.cs | 6 +- 10 files changed, 73 insertions(+), 142 deletions(-) delete mode 100644 encompass-cs/Collections/FixedArray.cs diff --git a/encompass-cs/Collections/ComponentStore.cs b/encompass-cs/Collections/ComponentStore.cs index 2743e68..719180d 100644 --- a/encompass-cs/Collections/ComponentStore.cs +++ b/encompass-cs/Collections/ComponentStore.cs @@ -16,7 +16,7 @@ namespace Encompass ComponentBitSet = new ComponentBitSet(typeToIndex); } - public virtual void RegisterComponentType() where TComponent : unmanaged + public virtual void RegisterComponentType() where TComponent : struct { if (!_stores.ContainsKey(typeof(TComponent))) { @@ -27,13 +27,13 @@ namespace Encompass if (!_typeToIndex.ContainsKey(typeof(TComponent))) { _typeToIndex.Add(typeof(TComponent), _typeToIndex.Count); } } - private TypedComponentStore Lookup() where TComponent : unmanaged + private TypedComponentStore Lookup() where TComponent : struct { RegisterComponentType(); return _stores[typeof(TComponent)] as TypedComponentStore; } - public bool Has(int entityID) where TComponent : unmanaged + public bool Has(int entityID) where TComponent : struct { return Lookup().Has(entityID); } @@ -48,18 +48,18 @@ namespace Encompass return ComponentBitSet.EntityBitArray(entityID); } - public ref readonly TComponent Get(int entityID) where TComponent : unmanaged + public ref readonly TComponent Get(int entityID) where TComponent : struct { return ref Lookup().Get(entityID); } - public virtual void Set(int entityID, TComponent component) where TComponent : unmanaged + public virtual void Set(int entityID, TComponent component) where TComponent : struct { Lookup().Set(entityID, component); ComponentBitSet.Set(entityID); } - public virtual bool Set(int entityID, TComponent component, int priority) where TComponent : unmanaged + public virtual bool Set(int entityID, TComponent component, int priority) where TComponent : struct { if (Lookup().Set(entityID, component, priority)) { @@ -69,7 +69,7 @@ namespace Encompass return false; } - public virtual bool Remove(int entityID, int priority) where TComponent : unmanaged + public virtual bool Remove(int entityID, int priority) where TComponent : struct { if (Lookup().Remove(entityID, priority)) { @@ -79,7 +79,7 @@ namespace Encompass return false; } - public void ForceRemove(int entityID) where TComponent : unmanaged + public void ForceRemove(int entityID) where TComponent : struct { Lookup().ForceRemove(entityID); ComponentBitSet.RemoveComponent(entityID); @@ -94,17 +94,17 @@ namespace Encompass ComponentBitSet.RemoveEntity(entityID); } - public bool Any() where TComponent : unmanaged + public bool Any() where TComponent : struct { return Lookup().Count > 0; } - public IEnumerable<(TComponent, int)> All() where TComponent : unmanaged + public IEnumerable<(TComponent, int)> All() where TComponent : struct { return Lookup().All(); } - public void Clear() where TComponent : unmanaged + public void Clear() where TComponent : struct { Lookup().Clear(); } diff --git a/encompass-cs/Collections/FixedArray.cs b/encompass-cs/Collections/FixedArray.cs deleted file mode 100644 index 242e9c6..0000000 --- a/encompass-cs/Collections/FixedArray.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -internal unsafe class FixedArray : IDisposable where T : unmanaged -{ - private void* _buffer; - - public int Length { get; private set; } - - public T this[int i] - { - get { return ReadElement(_buffer, i); } - set { WriteElement(_buffer, i, value); } - } - - public unsafe FixedArray(int length, bool clearMemory = false) - { - var bufferSize = Marshal.SizeOf() * length; - _buffer = (void*)Alloc(bufferSize); - - if (clearMemory) - { - Memset(_buffer, 0, bufferSize); - } - - Length = length; - } - - public ref T ByRef(int i) - { - return ref *(T*)((byte*)_buffer + i * sizeof(T)); - } - - void IDisposable.Dispose() - { - Free((IntPtr)_buffer); - _buffer = null; - Length = 0; - } - - private static T ReadElement(void* buffer, int i) - { - return *(T*)((byte*)buffer + i * sizeof(T)); - } - - private static void WriteElement(void* buffer, int i, T value) - { - *(T*)((byte*)buffer + i * sizeof(T)) = value; - } - - private unsafe static IntPtr Alloc(int size) - { - return Marshal.AllocHGlobal(size); - } - - public unsafe static void Free(IntPtr ptr) - { - if (ptr != IntPtr.Zero) - { - Marshal.FreeHGlobal(ptr); - } - } - - private unsafe static void Memset(void* ptr, byte value, int count) - { - Unsafe.InitBlock(ptr, value, (uint)count); - } -} diff --git a/encompass-cs/Collections/Replayer.cs b/encompass-cs/Collections/Replayer.cs index 0bb9414..46f184a 100644 --- a/encompass-cs/Collections/Replayer.cs +++ b/encompass-cs/Collections/Replayer.cs @@ -10,7 +10,7 @@ namespace Encompass public abstract void Clear(); } - internal class Replayer : Replayer where TComponent : unmanaged + internal class Replayer : Replayer where TComponent : struct { private readonly ComponentDeltaStore _deltaStore; private readonly HashSet _removals = new HashSet(); diff --git a/encompass-cs/Collections/TypedComponentStore.cs b/encompass-cs/Collections/TypedComponentStore.cs index 8ae25b6..cc77e07 100644 --- a/encompass-cs/Collections/TypedComponentStore.cs +++ b/encompass-cs/Collections/TypedComponentStore.cs @@ -14,11 +14,11 @@ namespace Encompass public abstract void ClearPriorities(); } - internal unsafe class TypedComponentStore : TypedComponentStore where TComponent : unmanaged + internal unsafe class TypedComponentStore : TypedComponentStore where TComponent : struct { private readonly Dictionary _indices = new Dictionary(512); private readonly Dictionary _priorities = new Dictionary(512); - private readonly FixedArray _components = new FixedArray(512); // TODO: allow specify size + private readonly TComponent[] _components = new TComponent[512]; // TODO: allow specify size private readonly IDManager _idManager = new IDManager(); public override int Count { get => _indices.Count; } @@ -26,7 +26,7 @@ namespace Encompass public unsafe ref readonly TComponent Get(int entityID) { if (!_indices.ContainsKey(entityID)) { throw new Exceptions.NoComponentOfTypeOnEntityException("No component of type {0} exists on Entity with ID {1}", typeof(TComponent), entityID); } - return ref _components.ByRef(_indices[entityID]); + return ref _components[_indices[entityID]]; } public unsafe void Set(int entityID, TComponent component) diff --git a/encompass-cs/ComponentManager.cs b/encompass-cs/ComponentManager.cs index da1a782..aacdc6a 100644 --- a/encompass-cs/ComponentManager.cs +++ b/encompass-cs/ComponentManager.cs @@ -29,7 +29,7 @@ namespace Encompass TypeToIndex = typeToIndex; } - public void RegisterComponentType() where TComponent : unmanaged + public void RegisterComponentType() where TComponent : struct { _existingComponentStore.RegisterComponentType(); _immediateComponentStore.RegisterComponentType(); @@ -47,7 +47,7 @@ namespace Encompass _upToDateComponentStore.SwapWith(componentStore); } - internal void RegisterDrawableComponent(int entityID, int layer) where TComponent : unmanaged + internal void RegisterDrawableComponent(int entityID, int layer) where TComponent : struct { _drawLayerManager.RegisterComponentWithLayer(entityID, layer); } @@ -61,7 +61,7 @@ namespace Encompass _replayStore.ClearAll(); } - internal bool AddImmediateComponent(int entityID, TComponent component, int priority) where TComponent : unmanaged + internal bool AddImmediateComponent(int entityID, TComponent component, int priority) where TComponent : struct { if (_immediateComponentStore.Set(entityID, component, priority)) { @@ -73,14 +73,14 @@ namespace Encompass return false; } - internal void AddImmediateComponent(int entityID, TComponent component) where TComponent : unmanaged + internal void AddImmediateComponent(int entityID, TComponent component) where TComponent : struct { _immediateComponentStore.Set(entityID, component); _replayStore.Set(entityID, component); _upToDateComponentStore.Set(entityID, component); } - internal bool UpdateComponent(int entityID, TComponent component, int priority) where TComponent : unmanaged + internal bool UpdateComponent(int entityID, TComponent component, int priority) where TComponent : struct { var result = _upToDateComponentStore.Set(entityID, component, priority); if (result) @@ -90,7 +90,7 @@ namespace Encompass return result; } - internal void AddComponent(int entityID, TComponent component) where TComponent : unmanaged + internal void AddComponent(int entityID, TComponent component) where TComponent : struct { _upToDateComponentStore.Set(entityID, component); _replayStore.Set(entityID, component); @@ -98,12 +98,12 @@ namespace Encompass // existing or immediate reads - internal IEnumerable<(TComponent, int)> ReadExistingAndImmediateComponentsByType() where TComponent : unmanaged + internal IEnumerable<(TComponent, int)> ReadExistingAndImmediateComponentsByType() where TComponent : struct { return _upToDateComponentStore.All(); } - internal (TComponent, int) ReadFirstExistingOrImmediateComponentByType() where TComponent : unmanaged + internal (TComponent, int) ReadFirstExistingOrImmediateComponentByType() where TComponent : struct { if (!SomeExistingOrImmediateComponent()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } var enumerator = ReadExistingAndImmediateComponentsByType().GetEnumerator(); @@ -111,14 +111,14 @@ namespace Encompass return enumerator.Current; } - internal bool SomeExistingOrImmediateComponent() where TComponent : unmanaged + internal bool SomeExistingOrImmediateComponent() where TComponent : struct { return _upToDateComponentStore.Any(); } // existing reads - internal (TComponent, int) ReadFirstExistingComponentByType() where TComponent : unmanaged + internal (TComponent, int) ReadFirstExistingComponentByType() where TComponent : struct { if (!SomeExistingComponent()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } var enumerator = GetComponentsIncludingEntity().GetEnumerator(); @@ -126,19 +126,19 @@ namespace Encompass return enumerator.Current; } - internal bool SomeExistingComponent() where TComponent : unmanaged + internal bool SomeExistingComponent() where TComponent : struct { return _existingComponentStore.Any(); } // immediate reads - internal IEnumerable<(TComponent, int)> ReadImmediateComponentsByType() where TComponent : unmanaged + internal IEnumerable<(TComponent, int)> ReadImmediateComponentsByType() where TComponent : struct { return _immediateComponentStore.All(); } - internal (TComponent, int) ReadFirstImmediateComponentByType() where TComponent : unmanaged + internal (TComponent, int) ReadFirstImmediateComponentByType() where TComponent : struct { if (!SomeImmediateComponent()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } var enumerator = ReadImmediateComponentsByType().GetEnumerator(); @@ -146,31 +146,31 @@ namespace Encompass return enumerator.Current; } - internal bool SomeImmediateComponent() where TComponent : unmanaged + internal bool SomeImmediateComponent() where TComponent : struct { return _immediateComponentStore.Any(); } // component getters - internal ref readonly TComponent ReadImmediateOrExistingComponentByEntityAndType(int entityID) where TComponent : unmanaged + internal ref readonly TComponent ReadImmediateOrExistingComponentByEntityAndType(int entityID) where TComponent : struct { return ref _upToDateComponentStore.Get(entityID); } - internal ref readonly TComponent ReadExistingComponentByEntityAndType(int entityID) where TComponent : unmanaged + internal ref readonly TComponent ReadExistingComponentByEntityAndType(int entityID) where TComponent : struct { return ref _existingComponentStore.Get(entityID); } - internal ref readonly TComponent ReadImmediateComponentByEntityAndType(int entityID) where TComponent : unmanaged + internal ref readonly TComponent ReadImmediateComponentByEntityAndType(int entityID) where TComponent : struct { return ref _immediateComponentStore.Get(entityID); } // has checkers - internal bool HasExistingOrImmediateComponent(int entityID) where TComponent : unmanaged + internal bool HasExistingOrImmediateComponent(int entityID) where TComponent : struct { return _upToDateComponentStore.Has(entityID); } @@ -180,7 +180,7 @@ namespace Encompass return _upToDateComponentStore.Has(type, entityID); } - internal bool HasExistingComponent(int entityID) where TComponent : unmanaged + internal bool HasExistingComponent(int entityID) where TComponent : struct { return _existingComponentStore.Has(entityID); } @@ -190,7 +190,7 @@ namespace Encompass return _existingComponentStore.Has(type, entityID); } - internal bool HasImmediateComponent(int entityID) where TComponent : unmanaged + internal bool HasImmediateComponent(int entityID) where TComponent : struct { return _immediateComponentStore.Has(entityID); } @@ -200,12 +200,12 @@ namespace Encompass return _immediateComponentStore.Has(type, entityID); } - internal IEnumerable<(TComponent, int)> GetComponentsIncludingEntity() where TComponent : unmanaged + internal IEnumerable<(TComponent, int)> GetComponentsIncludingEntity() where TComponent : struct { return _existingComponentStore.All(); } - internal IEnumerable GetComponentsByType() where TComponent : unmanaged + internal IEnumerable GetComponentsByType() where TComponent : struct { foreach (var pair in _existingComponentStore.All()) { @@ -213,12 +213,12 @@ namespace Encompass } } - internal ref readonly TComponent GetComponentByEntityAndType(int entityID) where TComponent : unmanaged + internal ref readonly TComponent GetComponentByEntityAndType(int entityID) where TComponent : struct { return ref _existingComponentStore.Get(entityID); } - internal bool EntityHasComponentOfType(int entityID) where TComponent : unmanaged + internal bool EntityHasComponentOfType(int entityID) where TComponent : struct { return _existingComponentStore.Has(entityID); } @@ -242,7 +242,7 @@ namespace Encompass _entitiesMarkedForRemoval.Clear(); } - public bool RemoveImmediate(int entityID, int priority) where TComponent : unmanaged + public bool RemoveImmediate(int entityID, int priority) where TComponent : struct { if (_immediateComponentStore.Remove(entityID, priority)) { @@ -254,7 +254,7 @@ namespace Encompass return false; } - public void Remove(int entityID, int priority) where TComponent : unmanaged + public void Remove(int entityID, int priority) where TComponent : struct { if (_upToDateComponentStore.Remove(entityID, priority)) { diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index bc29221..1116c0c 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -213,7 +213,7 @@ namespace Encompass /// /// Returns an Entity containing the specified Component type. /// - protected Entity ReadEntity() where TComponent : unmanaged + protected Entity ReadEntity() where TComponent : struct { return _entityManager.GetEntity(ReadComponentHelper().Item2); } @@ -221,7 +221,7 @@ namespace Encompass /// /// Returns all Entities containing the specified Component type. /// - protected IEnumerable ReadEntities() where TComponent : unmanaged + protected IEnumerable ReadEntities() where TComponent : struct { foreach (var pair in ReadComponentsHelper()) { @@ -231,12 +231,12 @@ namespace Encompass // these next two are for the ComponentMessageEmitter only - internal IEnumerable ReadComponentsFromWorld() where TComponent : unmanaged + internal IEnumerable ReadComponentsFromWorld() where TComponent : struct { return _componentManager.GetComponentsByType(); } - private IEnumerable<(TComponent, int)> ReadComponentsHelper() where TComponent : unmanaged + private IEnumerable<(TComponent, int)> ReadComponentsHelper() where TComponent : struct { var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent)); @@ -261,7 +261,7 @@ namespace Encompass /// /// Returns all of the Components with the specified Component Type. /// - protected IEnumerable ReadComponents() where TComponent : unmanaged + protected IEnumerable ReadComponents() where TComponent : struct { foreach (var pair in ReadComponentsHelper()) { @@ -272,7 +272,7 @@ namespace Encompass /// /// Returns all of the components of the specified type including an Entity reference for each Component. /// - protected IEnumerable<(TComponent, Entity)> ReadComponentsIncludingEntity() where TComponent : unmanaged + protected IEnumerable<(TComponent, Entity)> ReadComponentsIncludingEntity() where TComponent : struct { foreach (var (component, id) in ReadComponentsHelper()) { @@ -280,7 +280,7 @@ namespace Encompass } } - private (TComponent, int) ReadComponentHelper() where TComponent : unmanaged + private (TComponent, int) ReadComponentHelper() where TComponent : struct { var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent)); @@ -305,7 +305,7 @@ namespace Encompass /// /// Returns a Component with the specified Component Type. If multiples exist, an arbitrary Component is returned. /// - protected TComponent ReadComponent() where TComponent : unmanaged + protected TComponent ReadComponent() where TComponent : struct { return ReadComponentHelper().Item1; } @@ -313,7 +313,7 @@ namespace Encompass /// /// Returns a component of the specified type including its Entity reference. If multiples exist, an arbitrary Component is returned. /// - protected (TComponent, Entity) ReadComponentIncludingEntity() where TComponent : unmanaged + protected (TComponent, Entity) ReadComponentIncludingEntity() where TComponent : struct { var (component, id) = ReadComponentHelper(); return (component, _entityManager.GetEntity(id)); @@ -322,7 +322,7 @@ namespace Encompass /// /// Returns true if any Component with the specified Component Type exists. /// - protected bool SomeComponent() where TComponent : unmanaged + protected bool SomeComponent() where TComponent : struct { var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent)); @@ -344,7 +344,7 @@ namespace Encompass } } - private ref readonly TComponent GetComponentHelper(int entityID) where TComponent : unmanaged + private ref readonly TComponent GetComponentHelper(int entityID) where TComponent : struct { var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent)); @@ -375,7 +375,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that it reads the given Component Type. /// - protected ref readonly TComponent GetComponent(Entity entity) where TComponent : unmanaged + protected ref readonly TComponent GetComponent(Entity entity) where TComponent : struct { return ref GetComponentHelper(entity.ID); } @@ -386,7 +386,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that is Reads the given Component Type. /// - protected bool HasComponent(Entity entity) where TComponent : unmanaged + protected bool HasComponent(Entity entity) where TComponent : struct { var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent)); @@ -444,7 +444,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that it Writes the given Component Type. /// - protected void SetComponent(Entity entity, TComponent component) where TComponent : unmanaged + protected void SetComponent(Entity entity, TComponent component) where TComponent : struct { var priority = WritePriorities.ContainsKey(typeof(TComponent)) ? WritePriorities[typeof(TComponent)] : DefaultWritePriority; @@ -484,7 +484,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that it Writes the given Component Type. /// - protected void AddComponent(Entity entity, TComponent component) where TComponent : unmanaged + protected void AddComponent(Entity entity, TComponent component) where TComponent : struct { if (!EntityCreatedThisFrame(entity.ID)) { @@ -592,7 +592,7 @@ namespace Encompass /// Destroys an arbitrary Entity containing a Component of the specified Type. /// Entity destruction takes place after all the Engines have been processed by World Update. /// - protected void DestroyWith() where TComponent : unmanaged + protected void DestroyWith() where TComponent : struct { Destroy(ReadEntity()); } @@ -601,7 +601,7 @@ namespace Encompass /// Destroys all Entities containing a Component of the specified Type. /// Entity destruction takes place after all the Engines have been processed by World Update. /// - protected void DestroyAllWith() where TComponent : unmanaged + protected void DestroyAllWith() where TComponent : struct { foreach (var entity in ReadEntities()) { @@ -614,7 +614,7 @@ namespace Encompass /// Note that the Engine must Read the Component type that is being removed. /// If a Component with the specified type does not exist on the Entity, returns false and does not mutate the Entity. /// - protected void RemoveComponent(Entity entity) where TComponent : unmanaged + protected void RemoveComponent(Entity entity) where TComponent : struct { var priority = WritePriorities.ContainsKey(typeof(TComponent)) ? WritePriorities[typeof(TComponent)] : DefaultWritePriority; diff --git a/encompass-cs/RenderManager.cs b/encompass-cs/RenderManager.cs index 0fa030b..f2031ae 100644 --- a/encompass-cs/RenderManager.cs +++ b/encompass-cs/RenderManager.cs @@ -16,7 +16,7 @@ namespace Encompass _drawLayerManager = drawLayerManager; } - public void RegisterOrderedRenderer(Action renderAction) where TComponent : unmanaged + public void RegisterOrderedRenderer(Action renderAction) where TComponent : struct { _drawComponentTypeToOrderedRenderer.Add(typeof(TComponent), renderAction); _drawLayerManager.RegisterOrderedDrawable(); diff --git a/encompass-cs/Renderer.cs b/encompass-cs/Renderer.cs index 07939f2..2b9d513 100644 --- a/encompass-cs/Renderer.cs +++ b/encompass-cs/Renderer.cs @@ -17,7 +17,7 @@ namespace Encompass _componentManager = componentManager; } - protected IEnumerable ReadEntities() where TComponent : unmanaged + protected IEnumerable ReadEntities() where TComponent : struct { foreach (var pair in ReadComponentsIncludingEntity()) { @@ -25,17 +25,17 @@ namespace Encompass } } - protected Entity ReadEntity() where TComponent : unmanaged + protected Entity ReadEntity() where TComponent : struct { return ReadComponentIncludingEntity().Item2; } - protected IEnumerable ReadComponents() where TComponent : unmanaged + protected IEnumerable ReadComponents() where TComponent : struct { return _componentManager.GetComponentsByType(); } - protected IEnumerable<(TComponent, Entity)> ReadComponentsIncludingEntity() where TComponent : unmanaged + protected IEnumerable<(TComponent, Entity)> ReadComponentsIncludingEntity() where TComponent : struct { foreach (var (component, id) in _componentManager.GetComponentsIncludingEntity()) { @@ -43,31 +43,31 @@ namespace Encompass } } - protected TComponent ReadComponent() where TComponent : unmanaged + protected TComponent ReadComponent() where TComponent : struct { var enumerator = ReadComponents().GetEnumerator(); enumerator.MoveNext(); return enumerator.Current; } - protected (TComponent, Entity) ReadComponentIncludingEntity() where TComponent : unmanaged + protected (TComponent, Entity) ReadComponentIncludingEntity() where TComponent : struct { var enumerator = ReadComponentsIncludingEntity().GetEnumerator(); enumerator.MoveNext(); return enumerator.Current; } - protected ref readonly TComponent GetComponent(Entity entity) where TComponent : unmanaged + protected ref readonly TComponent GetComponent(Entity entity) where TComponent : struct { return ref _componentManager.GetComponentByEntityAndType(entity.ID); } - protected bool HasComponent(Entity entity) where TComponent : unmanaged + protected bool HasComponent(Entity entity) where TComponent : struct { return _componentManager.EntityHasComponentOfType(entity.ID); } - protected bool SomeComponent() where TComponent : unmanaged + protected bool SomeComponent() where TComponent : struct { return _componentManager.SomeExistingComponent(); } diff --git a/encompass-cs/Renderers/OrderedRenderer.cs b/encompass-cs/Renderers/OrderedRenderer.cs index a8458ae..da480df 100644 --- a/encompass-cs/Renderers/OrderedRenderer.cs +++ b/encompass-cs/Renderers/OrderedRenderer.cs @@ -5,7 +5,7 @@ namespace Encompass /// /// OrdereredRenderer provides a structure for the common pattern of wishing to draw a specific DrawComponent at a specific layer. /// - public abstract class OrderedRenderer : Renderer where TComponent : unmanaged, IDrawableComponent + public abstract class OrderedRenderer : Renderer where TComponent : struct, IDrawableComponent { public abstract void Render(Entity entity, in TComponent drawComponent); diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs index 461c159..17eb320 100644 --- a/encompass-cs/WorldBuilder.cs +++ b/encompass-cs/WorldBuilder.cs @@ -84,7 +84,7 @@ namespace Encompass /// /// Sets Component data for the specified Component Type on the specified Entity. /// - public void SetComponent(Entity entity, TComponent component) where TComponent : unmanaged + public void SetComponent(Entity entity, TComponent component) where TComponent : struct { RegisterComponentType(); _startingExistingComponentStore.Set(entity.ID, component); @@ -97,7 +97,7 @@ namespace Encompass } } - internal void RegisterComponentType() where TComponent : unmanaged + internal void RegisterComponentType() where TComponent : struct { if (!_typeToIndex.ContainsKey(typeof(TComponent))) { @@ -183,7 +183,7 @@ namespace Encompass /// /// Adds the specified OrderedRenderer to the World. /// - public OrderedRenderer AddOrderedRenderer(OrderedRenderer renderer) where TComponent : unmanaged, IDrawableComponent + public OrderedRenderer AddOrderedRenderer(OrderedRenderer renderer) where TComponent : struct, IDrawableComponent { RegisterComponentType(); renderer.AssignEntityManager(_entityManager); From 4178e8f02c3af961f0f2127b4c6871f5e5bace3c Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Sat, 21 Mar 2020 20:29:15 -0700 Subject: [PATCH 10/30] rework delta store to not use inheritance --- .../Collections/ComponentDeltaStore.cs | 37 ++++++++++++------- encompass-cs/Collections/ComponentStore.cs | 16 ++++---- encompass-cs/DrawLayerManager.cs | 21 +++++++++-- 3 files changed, 48 insertions(+), 26 deletions(-) diff --git a/encompass-cs/Collections/ComponentDeltaStore.cs b/encompass-cs/Collections/ComponentDeltaStore.cs index 9b212d0..d59d97a 100644 --- a/encompass-cs/Collections/ComponentDeltaStore.cs +++ b/encompass-cs/Collections/ComponentDeltaStore.cs @@ -3,39 +3,43 @@ using System.Collections.Generic; namespace Encompass { - internal class ComponentDeltaStore : ComponentStore + internal class ComponentDeltaStore { + private readonly ComponentStore _store; private readonly Dictionary _replayers = new Dictionary(); private readonly HashSet _currentReplayers = new HashSet(); public IEnumerable CurrentReplayers { get { return _currentReplayers; } } - public ComponentDeltaStore(Dictionary typeToIndex) : base(typeToIndex) + public ComponentDeltaStore(Dictionary typeToIndex) { + _store = new ComponentStore(typeToIndex); } - public override void RegisterComponentType() + public void RegisterComponentType() where TComponent : struct { - base.RegisterComponentType(); + _store.RegisterComponentType(); if (!_replayers.ContainsKey(typeof(TComponent))) { _replayers.Add(typeof(TComponent), new Replayer(this)); } } - public override void Set(int entityID, TComponent component) + public void Set(int entityID, TComponent component) where TComponent : struct { - base.Set(entityID, component); + _store.Set(entityID, component); + RegisterComponentType(); var replayer = _replayers[typeof(TComponent)]; _currentReplayers.Add(replayer); replayer.UnMarkRemoval(entityID); } - public override bool Set(int entityID, TComponent component, int priority) + public bool Set(int entityID, TComponent component, int priority) where TComponent : struct { - var result = base.Set(entityID, component, priority); + var result = _store.Set(entityID, component, priority); if (result) { + RegisterComponentType(); var replayer = _replayers[typeof(TComponent)]; _currentReplayers.Add(replayer); replayer.UnMarkRemoval(entityID); @@ -43,9 +47,9 @@ namespace Encompass return result; } - public override bool Remove(int entityID, int priority) + public bool Remove(int entityID, int priority) where TComponent : struct { - var result = base.Remove(entityID, priority); + var result = _store.Remove(entityID, priority); if (result) { var replayer = _replayers[typeof(TComponent)]; @@ -55,18 +59,23 @@ namespace Encompass return result; } - public override void Remove(int entityID) + public void Remove(int entityID) { - base.Remove(entityID); + _store.Remove(entityID); foreach (var replayer in CurrentReplayers) { replayer.MarkRemoval(entityID); } } - public override void ClearAll() + public IEnumerable<(TComponent, int)> All() where TComponent : struct { - base.ClearAll(); + return _store.All(); + } + + public void ClearAll() + { + _store.ClearAll(); foreach (var replayer in _currentReplayers) { replayer.Clear(); diff --git a/encompass-cs/Collections/ComponentStore.cs b/encompass-cs/Collections/ComponentStore.cs index 719180d..a0fbcb0 100644 --- a/encompass-cs/Collections/ComponentStore.cs +++ b/encompass-cs/Collections/ComponentStore.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; namespace Encompass { - internal class ComponentStore + internal sealed class ComponentStore { private Dictionary _stores = new Dictionary(512); public ComponentBitSet ComponentBitSet { get; private set; } @@ -16,7 +16,7 @@ namespace Encompass ComponentBitSet = new ComponentBitSet(typeToIndex); } - public virtual void RegisterComponentType() where TComponent : struct + public void RegisterComponentType() where TComponent : struct { if (!_stores.ContainsKey(typeof(TComponent))) { @@ -53,13 +53,13 @@ namespace Encompass return ref Lookup().Get(entityID); } - public virtual void Set(int entityID, TComponent component) where TComponent : struct + public void Set(int entityID, TComponent component) where TComponent : struct { Lookup().Set(entityID, component); ComponentBitSet.Set(entityID); } - public virtual bool Set(int entityID, TComponent component, int priority) where TComponent : struct + public bool Set(int entityID, TComponent component, int priority) where TComponent : struct { if (Lookup().Set(entityID, component, priority)) { @@ -69,7 +69,7 @@ namespace Encompass return false; } - public virtual bool Remove(int entityID, int priority) where TComponent : struct + public bool Remove(int entityID, int priority) where TComponent : struct { if (Lookup().Remove(entityID, priority)) { @@ -85,7 +85,7 @@ namespace Encompass ComponentBitSet.RemoveComponent(entityID); } - public virtual void Remove(int entityID) + public void Remove(int entityID) { foreach (var entry in _stores.Values) { @@ -109,7 +109,7 @@ namespace Encompass Lookup().Clear(); } - public virtual void ClearAllPriorities() + public void ClearAllPriorities() { foreach (var store in _stores.Values) { @@ -117,7 +117,7 @@ namespace Encompass } } - public virtual void ClearAll() + public void ClearAll() { ComponentBitSet.Clear(); foreach (var store in _stores.Values) diff --git a/encompass-cs/DrawLayerManager.cs b/encompass-cs/DrawLayerManager.cs index 71eaec0..571ac20 100644 --- a/encompass-cs/DrawLayerManager.cs +++ b/encompass-cs/DrawLayerManager.cs @@ -60,12 +60,25 @@ namespace Encompass throw new UndefinedLayerException("Layer {0} is not defined. Use WorldBuilder.RegisterDrawLayer to register the layer.", layer); } - if (_typeToEntityToLayer[typeof(TComponent)].ContainsKey(entityID)) { UnRegisterComponentWithLayer(entityID); } + if (_typeToEntityToLayer[typeof(TComponent)].ContainsKey(entityID)) + { + if (_typeToEntityToLayer[typeof(TComponent)][entityID] != layer) + { + UnRegisterComponentWithLayer(entityID); - var set = _layerIndexToTypeToID[layer][typeof(TComponent)]; - set.Add(entityID); + var set = _layerIndexToTypeToID[layer][typeof(TComponent)]; + set.Add(entityID); - _typeToEntityToLayer[typeof(TComponent)].Add(entityID, layer); + _typeToEntityToLayer[typeof(TComponent)].Add(entityID, layer); + } + } + else + { + var set = _layerIndexToTypeToID[layer][typeof(TComponent)]; + set.Add(entityID); + + _typeToEntityToLayer[typeof(TComponent)].Add(entityID, layer); + } } public void UnRegisterComponentWithLayer(int entityID) where TComponent : struct From 150043b0e5fe24db573556c03d54024deb055491 Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Sat, 21 Mar 2020 22:19:31 -0700 Subject: [PATCH 11/30] fix bugs in component storage and draw layer manager --- .../Collections/ComponentDeltaStore.cs | 2 +- encompass-cs/Collections/ComponentStore.cs | 6 ++--- .../Collections/TypedComponentStore.cs | 24 ++++++++++--------- encompass-cs/ComponentManager.cs | 14 +++++------ encompass-cs/DrawLayerManager.cs | 11 +++++++-- encompass-cs/Engine.cs | 20 +++++++++++++--- encompass-cs/Renderers/OrderedRenderer.cs | 3 ++- encompass-cs/WorldBuilder.cs | 2 +- 8 files changed, 53 insertions(+), 29 deletions(-) diff --git a/encompass-cs/Collections/ComponentDeltaStore.cs b/encompass-cs/Collections/ComponentDeltaStore.cs index d59d97a..a0b022c 100644 --- a/encompass-cs/Collections/ComponentDeltaStore.cs +++ b/encompass-cs/Collections/ComponentDeltaStore.cs @@ -25,7 +25,7 @@ namespace Encompass } } - public void Set(int entityID, TComponent component) where TComponent : struct + public void Set(int entityID, in TComponent component) where TComponent : struct { _store.Set(entityID, component); RegisterComponentType(); diff --git a/encompass-cs/Collections/ComponentStore.cs b/encompass-cs/Collections/ComponentStore.cs index a0fbcb0..b4f541e 100644 --- a/encompass-cs/Collections/ComponentStore.cs +++ b/encompass-cs/Collections/ComponentStore.cs @@ -48,18 +48,18 @@ namespace Encompass return ComponentBitSet.EntityBitArray(entityID); } - public ref readonly TComponent Get(int entityID) where TComponent : struct + public ref TComponent Get(int entityID) where TComponent : struct { return ref Lookup().Get(entityID); } - public void Set(int entityID, TComponent component) where TComponent : struct + public void Set(int entityID, in TComponent component) where TComponent : struct { Lookup().Set(entityID, component); ComponentBitSet.Set(entityID); } - public bool Set(int entityID, TComponent component, int priority) where TComponent : struct + public bool Set(int entityID, in TComponent component, int priority) where TComponent : struct { if (Lookup().Set(entityID, component, priority)) { diff --git a/encompass-cs/Collections/TypedComponentStore.cs b/encompass-cs/Collections/TypedComponentStore.cs index cc77e07..727859d 100644 --- a/encompass-cs/Collections/TypedComponentStore.cs +++ b/encompass-cs/Collections/TypedComponentStore.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Runtime.CompilerServices; @@ -14,7 +13,7 @@ namespace Encompass public abstract void ClearPriorities(); } - internal unsafe class TypedComponentStore : TypedComponentStore where TComponent : struct + internal class TypedComponentStore : TypedComponentStore where TComponent : struct { private readonly Dictionary _indices = new Dictionary(512); private readonly Dictionary _priorities = new Dictionary(512); @@ -23,18 +22,18 @@ namespace Encompass public override int Count { get => _indices.Count; } - public unsafe ref readonly TComponent Get(int entityID) + public ref TComponent Get(int entityID) { if (!_indices.ContainsKey(entityID)) { throw new Exceptions.NoComponentOfTypeOnEntityException("No component of type {0} exists on Entity with ID {1}", typeof(TComponent), entityID); } return ref _components[_indices[entityID]]; } - public unsafe void Set(int entityID, TComponent component) + public void Set(int entityID, in TComponent component) { InternalSet(entityID, component); } - public unsafe bool Set(int entityID, TComponent component, int priority) + public bool Set(int entityID, in TComponent component, int priority) { if (!_priorities.ContainsKey(entityID) || priority < _priorities[entityID]) { @@ -46,7 +45,7 @@ namespace Encompass return false; } - private unsafe void InternalSet(int entityID, TComponent component) + private unsafe void InternalSet(int entityID, in TComponent component) { if (!_indices.ContainsKey(entityID)) { @@ -70,9 +69,12 @@ namespace Encompass public override void ForceRemove(int entityID) { - _indices.Remove(entityID); - _priorities.Remove(entityID); - _idManager.Free(entityID); + if (_indices.ContainsKey(entityID)) + { + _idManager.Free(_indices[entityID]); + _indices.Remove(entityID); + _priorities.Remove(entityID); + } } public override bool Has(int entityID) @@ -82,9 +84,9 @@ namespace Encompass public override void Clear() { - foreach (var entityID in _indices.Keys) + foreach (var mappedID in _indices.Values) { - _idManager.Free(entityID); + _idManager.Free(mappedID); } _indices.Clear(); _priorities.Clear(); diff --git a/encompass-cs/ComponentManager.cs b/encompass-cs/ComponentManager.cs index aacdc6a..fe98902 100644 --- a/encompass-cs/ComponentManager.cs +++ b/encompass-cs/ComponentManager.cs @@ -61,7 +61,7 @@ namespace Encompass _replayStore.ClearAll(); } - internal bool AddImmediateComponent(int entityID, TComponent component, int priority) where TComponent : struct + internal bool AddImmediateComponent(int entityID, in TComponent component, int priority) where TComponent : struct { if (_immediateComponentStore.Set(entityID, component, priority)) { @@ -73,14 +73,14 @@ namespace Encompass return false; } - internal void AddImmediateComponent(int entityID, TComponent component) where TComponent : struct + internal void AddImmediateComponent(int entityID, in TComponent component) where TComponent : struct { _immediateComponentStore.Set(entityID, component); _replayStore.Set(entityID, component); _upToDateComponentStore.Set(entityID, component); } - internal bool UpdateComponent(int entityID, TComponent component, int priority) where TComponent : struct + internal bool UpdateComponent(int entityID, in TComponent component, int priority) where TComponent : struct { var result = _upToDateComponentStore.Set(entityID, component, priority); if (result) @@ -90,7 +90,7 @@ namespace Encompass return result; } - internal void AddComponent(int entityID, TComponent component) where TComponent : struct + internal void AddComponent(int entityID, in TComponent component) where TComponent : struct { _upToDateComponentStore.Set(entityID, component); _replayStore.Set(entityID, component); @@ -153,17 +153,17 @@ namespace Encompass // component getters - internal ref readonly TComponent ReadImmediateOrExistingComponentByEntityAndType(int entityID) where TComponent : struct + internal ref TComponent ReadImmediateOrExistingComponentByEntityAndType(int entityID) where TComponent : struct { return ref _upToDateComponentStore.Get(entityID); } - internal ref readonly TComponent ReadExistingComponentByEntityAndType(int entityID) where TComponent : struct + internal ref TComponent ReadExistingComponentByEntityAndType(int entityID) where TComponent : struct { return ref _existingComponentStore.Get(entityID); } - internal ref readonly TComponent ReadImmediateComponentByEntityAndType(int entityID) where TComponent : struct + internal ref TComponent ReadImmediateComponentByEntityAndType(int entityID) where TComponent : struct { return ref _immediateComponentStore.Get(entityID); } diff --git a/encompass-cs/DrawLayerManager.cs b/encompass-cs/DrawLayerManager.cs index 571ac20..e500371 100644 --- a/encompass-cs/DrawLayerManager.cs +++ b/encompass-cs/DrawLayerManager.cs @@ -97,9 +97,16 @@ namespace Encompass { foreach (var store in _layerIndexToTypeToID.Values) { - foreach (var set in store.Values) + foreach (var typeToSet in store) { - set.Remove(entityID); + var type = typeToSet.Key; + var set = typeToSet.Value; + + if (set.Contains(entityID)) + { + _typeToEntityToLayer[type].Remove(entityID); + set.Remove(entityID); + } } } } diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index 1116c0c..b5e6779 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -344,7 +344,7 @@ namespace Encompass } } - private ref readonly TComponent GetComponentHelper(int entityID) where TComponent : struct + private ref TComponent GetComponentHelper(int entityID) where TComponent : struct { var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent)); @@ -380,6 +380,20 @@ namespace Encompass return ref GetComponentHelper(entity.ID); } + /// + /// Returns a Component by reference with the specified Type that exists on the Entity. + /// + /// + /// Thrown when the Entity does not have a Component of the specified Type + /// + /// + /// Thrown when the Engine does not declare that it reads the given Component Type. + /// + protected ref TComponent GetComponentMutable(Entity entity) where TComponent : struct + { + return ref GetComponentHelper(entity.ID); + } + /// /// Returns true if the Entity has a Component of the given Type. /// @@ -444,7 +458,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that it Writes the given Component Type. /// - protected void SetComponent(Entity entity, TComponent component) where TComponent : struct + protected void SetComponent(Entity entity, in TComponent component) where TComponent : struct { var priority = WritePriorities.ContainsKey(typeof(TComponent)) ? WritePriorities[typeof(TComponent)] : DefaultWritePriority; @@ -484,7 +498,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that it Writes the given Component Type. /// - protected void AddComponent(Entity entity, TComponent component) where TComponent : struct + protected void AddComponent(Entity entity, in TComponent component) where TComponent : struct { if (!EntityCreatedThisFrame(entity.ID)) { diff --git a/encompass-cs/Renderers/OrderedRenderer.cs b/encompass-cs/Renderers/OrderedRenderer.cs index da480df..56935f2 100644 --- a/encompass-cs/Renderers/OrderedRenderer.cs +++ b/encompass-cs/Renderers/OrderedRenderer.cs @@ -11,7 +11,8 @@ namespace Encompass internal void InternalRender(Entity entity) { - Render(entity, GetComponent(entity)); + ref readonly var component = ref GetComponent(entity); + Render(entity, component); } } } diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs index 17eb320..68cb330 100644 --- a/encompass-cs/WorldBuilder.cs +++ b/encompass-cs/WorldBuilder.cs @@ -84,7 +84,7 @@ namespace Encompass /// /// Sets Component data for the specified Component Type on the specified Entity. /// - public void SetComponent(Entity entity, TComponent component) where TComponent : struct + public void SetComponent(Entity entity, in TComponent component) where TComponent : struct { RegisterComponentType(); _startingExistingComponentStore.Set(entity.ID, component); From e3d8f42bd9e64f34c81c594348665beb2dd1aa85 Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Sat, 21 Mar 2020 22:53:05 -0700 Subject: [PATCH 12/30] fix not allowing same engine to write twice --- encompass-cs/Collections/TypedComponentStore.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/encompass-cs/Collections/TypedComponentStore.cs b/encompass-cs/Collections/TypedComponentStore.cs index 727859d..536b536 100644 --- a/encompass-cs/Collections/TypedComponentStore.cs +++ b/encompass-cs/Collections/TypedComponentStore.cs @@ -35,7 +35,7 @@ namespace Encompass public bool Set(int entityID, in TComponent component, int priority) { - if (!_priorities.ContainsKey(entityID) || priority < _priorities[entityID]) + if (!_priorities.ContainsKey(entityID) || priority <= _priorities[entityID]) // if priorities are equal that means it's the same engine { InternalSet(entityID, component); _priorities[entityID] = priority; @@ -45,7 +45,7 @@ namespace Encompass return false; } - private unsafe void InternalSet(int entityID, in TComponent component) + private void InternalSet(int entityID, in TComponent component) { if (!_indices.ContainsKey(entityID)) { @@ -57,7 +57,7 @@ namespace Encompass public override bool Remove(int entityID, int priority) { - if (!_priorities.ContainsKey(entityID) || priority < _priorities[entityID]) + if (!_priorities.ContainsKey(entityID) || priority <= _priorities[entityID]) // if priorities are equal that means it's the same engine { _priorities[entityID] = priority; ForceRemove(entityID); From 002cff1c2e206a5b15c05fb0908ec8283af32ff8 Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Sun, 22 Mar 2020 12:12:26 -0700 Subject: [PATCH 13/30] rework typed message store --- encompass-cs/Collections/TypedMessageStore.cs | 43 ++++++++++++------- test/ComponentTest.cs | 2 +- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/encompass-cs/Collections/TypedMessageStore.cs b/encompass-cs/Collections/TypedMessageStore.cs index 0a7a1e8..1a2c60c 100644 --- a/encompass-cs/Collections/TypedMessageStore.cs +++ b/encompass-cs/Collections/TypedMessageStore.cs @@ -10,10 +10,12 @@ namespace Encompass internal class TypedMessageStore : TypedMessageStore where TMessage : struct, IMessage { - private readonly List _store = new List(128); + private readonly List _indices = new List(); + private readonly TMessage[] _store = new TMessage[128]; private readonly List<(TMessage, double)> _delayedStore = new List<(TMessage, double)>(128); private readonly List<(TMessage, double)> _delayedStoreIgnoringTimeDilation = new List<(TMessage, double)>(128); - private readonly Dictionary> _entityToMessage = new Dictionary>(); + private readonly Dictionary> _entityToIndices = new Dictionary>(); + private readonly IDManager _idManager = new IDManager(); public override void ProcessDelayedMessages(double dilatedDelta, double realtimeDelta) { @@ -52,56 +54,67 @@ namespace Encompass } } - public void Add(TMessage message) + public void Add(in TMessage message) { - _store.Add(message); + var index = _idManager.NextID(); + _indices.Add(index); + _store[index] = message; if (message is IHasEntity entityMessage) { var entityID = entityMessage.Entity.ID; - if (!_entityToMessage.ContainsKey(entityID)) { _entityToMessage.Add(entityID, new List()); } - _entityToMessage[entityID].Add(message); + if (!_entityToIndices.ContainsKey(entityID)) { _entityToIndices.Add(entityID, new HashSet()); } + _entityToIndices[entityID].Add(index); } } - public void Add(TMessage message, double time) + public void Add(in TMessage message, double time) { _delayedStore.Add((message, time)); } - public void AddIgnoringTimeDilation(TMessage message, double time) + public void AddIgnoringTimeDilation(in TMessage message, double time) { _delayedStoreIgnoringTimeDilation.Add((message, time)); } public TMessage First() { - return _store[0]; + return _store[_indices[0]]; } public bool Any() { - return _store.Count > 0; + return _indices.Count > 0; } public IEnumerable All() { - return _store; + foreach (var index in _indices) + { + yield return _store[index]; + } } public IEnumerable WithEntity(int entityID) { - return _entityToMessage.ContainsKey(entityID) ? _entityToMessage[entityID] : System.Linq.Enumerable.Empty(); + if (_entityToIndices.ContainsKey(entityID)) + { + foreach (var index in _entityToIndices[entityID]) + { + yield return _store[index]; + } + } } public bool SomeWithEntity(int entityID) { - return _entityToMessage.ContainsKey(entityID) && _entityToMessage[entityID].Count > 0; + return _entityToIndices.ContainsKey(entityID) && _entityToIndices[entityID].Count > 0; } public override void Clear() { - _store.Clear(); - foreach (var set in _entityToMessage.Values) + _indices.Clear(); + foreach (var set in _entityToIndices.Values) { set.Clear(); } diff --git a/test/ComponentTest.cs b/test/ComponentTest.cs index 95c8f68..b8826b2 100644 --- a/test/ComponentTest.cs +++ b/test/ComponentTest.cs @@ -48,7 +48,7 @@ namespace Tests foreach (var addComponentTestMessage in ReadMessages()) { Assert.IsTrue(HasComponent(addComponentTestMessage.entity)); - var gottenComponent = GetComponent(addComponentTestMessage.entity); + ref readonly var gottenComponent = ref GetComponent(addComponentTestMessage.entity); gottenComponent.Should().BeEquivalentTo(addComponentTestMessage.mockComponent); } } From 67bc55e780226bec77db03cb8afd5766a3d17eaa Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Sun, 22 Mar 2020 12:14:57 -0700 Subject: [PATCH 14/30] actually free IDs on message clear --- encompass-cs/Collections/TypedMessageStore.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/encompass-cs/Collections/TypedMessageStore.cs b/encompass-cs/Collections/TypedMessageStore.cs index 1a2c60c..f47e2da 100644 --- a/encompass-cs/Collections/TypedMessageStore.cs +++ b/encompass-cs/Collections/TypedMessageStore.cs @@ -113,6 +113,10 @@ namespace Encompass public override void Clear() { + foreach (var index in _indices) + { + _idManager.Free(index); + } _indices.Clear(); foreach (var set in _entityToIndices.Values) { From cdc68e46e5d47072a4da8228aead93cb65242675 Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Sun, 22 Mar 2020 13:41:55 -0700 Subject: [PATCH 15/30] rework ReadMessages to return a Span --- encompass-cs/Collections/MessageStore.cs | 8 +++--- encompass-cs/Collections/TypedMessageStore.cs | 26 +++++++------------ encompass-cs/Engine.cs | 8 +++--- encompass-cs/MessageManager.cs | 9 ++++--- encompass-cs/UberEngine.cs | 4 ++- encompass-cs/WorldBuilder.cs | 4 +-- test/ComponentTest.cs | 2 +- test/EngineTest.cs | 12 ++++----- test/WorldBuilderTest.cs | 7 +++-- 9 files changed, 40 insertions(+), 40 deletions(-) diff --git a/encompass-cs/Collections/MessageStore.cs b/encompass-cs/Collections/MessageStore.cs index a966fe6..4d44657 100644 --- a/encompass-cs/Collections/MessageStore.cs +++ b/encompass-cs/Collections/MessageStore.cs @@ -18,17 +18,17 @@ namespace Encompass return _stores[typeof(TMessage)] as TypedMessageStore; } - public void AddMessage(TMessage message) where TMessage : struct, IMessage + public void AddMessage(in TMessage message) where TMessage : struct, IMessage { Lookup().Add(message); } - public void AddMessage(TMessage message, double time) where TMessage : struct, IMessage + public void AddMessage(in TMessage message, double time) where TMessage : struct, IMessage { Lookup().Add(message, time); } - public void AddMessageIgnoringTimeDilation(TMessage message, double time) where TMessage : struct, IMessage + public void AddMessageIgnoringTimeDilation(in TMessage message, double time) where TMessage : struct, IMessage { Lookup().AddIgnoringTimeDilation(message, time); } @@ -38,7 +38,7 @@ namespace Encompass return Lookup().First(); } - public IEnumerable All() where TMessage : struct, IMessage + public Span All() where TMessage : struct, IMessage { return Lookup().All(); } diff --git a/encompass-cs/Collections/TypedMessageStore.cs b/encompass-cs/Collections/TypedMessageStore.cs index f47e2da..b43f129 100644 --- a/encompass-cs/Collections/TypedMessageStore.cs +++ b/encompass-cs/Collections/TypedMessageStore.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; namespace Encompass @@ -10,12 +11,13 @@ namespace Encompass internal class TypedMessageStore : TypedMessageStore where TMessage : struct, IMessage { - private readonly List _indices = new List(); + // messages are placed in a contiguous region + // so we can return the collection as a Span + private int _nextIndex = 0; private readonly TMessage[] _store = new TMessage[128]; private readonly List<(TMessage, double)> _delayedStore = new List<(TMessage, double)>(128); private readonly List<(TMessage, double)> _delayedStoreIgnoringTimeDilation = new List<(TMessage, double)>(128); private readonly Dictionary> _entityToIndices = new Dictionary>(); - private readonly IDManager _idManager = new IDManager(); public override void ProcessDelayedMessages(double dilatedDelta, double realtimeDelta) { @@ -56,8 +58,7 @@ namespace Encompass public void Add(in TMessage message) { - var index = _idManager.NextID(); - _indices.Add(index); + var index = _nextIndex++; _store[index] = message; if (message is IHasEntity entityMessage) { @@ -79,20 +80,17 @@ namespace Encompass public TMessage First() { - return _store[_indices[0]]; + return _store[0]; } public bool Any() { - return _indices.Count > 0; + return _nextIndex != 0; } - public IEnumerable All() + public Span All() { - foreach (var index in _indices) - { - yield return _store[index]; - } + return new Span(_store, 0, _nextIndex); } public IEnumerable WithEntity(int entityID) @@ -113,11 +111,7 @@ namespace Encompass public override void Clear() { - foreach (var index in _indices) - { - _idManager.Free(index); - } - _indices.Clear(); + _nextIndex = 0; foreach (var set in _entityToIndices.Values) { set.Clear(); diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index b5e6779..d98fe87 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -529,7 +529,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that it Sends the Message Type. /// - protected void SendMessage(TMessage message) where TMessage : struct, IMessage + protected void SendMessage(in TMessage message) where TMessage : struct, IMessage { if (!SendTypes.Contains(typeof(TMessage))) { @@ -543,7 +543,7 @@ namespace Encompass /// Sends a message after the specified number of seconds, respecting time dilation. /// /// The time in seconds that will elapse before the message is sent. - protected void SendMessage(TMessage message, double time) where TMessage : struct, IMessage + protected void SendMessage(in TMessage message, double time) where TMessage : struct, IMessage { _messageManager.AddMessage(message, time); } @@ -552,7 +552,7 @@ namespace Encompass /// Sends a message after the specified number of seconds, ignoring time dilation. /// /// The time in seconds that will elapse before the message is sent. - protected void SendMessageIgnoringTimeDilation(TMessage message, double time) where TMessage : struct, IMessage + protected void SendMessageIgnoringTimeDilation(in TMessage message, double time) where TMessage : struct, IMessage { _messageManager.AddMessageIgnoringTimeDilation(message, time); } @@ -563,7 +563,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that it Receives the specified Message Type. /// - protected IEnumerable ReadMessages() where TMessage : struct, IMessage + protected Span ReadMessages() where TMessage : struct, IMessage { CheckMessageRead(); return _messageManager.GetMessagesByType(); diff --git a/encompass-cs/MessageManager.cs b/encompass-cs/MessageManager.cs index c662b6e..0ee4dc2 100644 --- a/encompass-cs/MessageManager.cs +++ b/encompass-cs/MessageManager.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; namespace Encompass @@ -12,17 +13,17 @@ namespace Encompass _timeManager = timeManager; } - internal void AddMessage(TMessage message) where TMessage : struct, IMessage + internal void AddMessage(in TMessage message) where TMessage : struct, IMessage { _messageStore.AddMessage(message); } - internal void AddMessage(TMessage message, double time) where TMessage : struct, IMessage + internal void AddMessage(in TMessage message, double time) where TMessage : struct, IMessage { _messageStore.AddMessage(message, time); } - internal void AddMessageIgnoringTimeDilation(TMessage message, double time) where TMessage : struct, IMessage + internal void AddMessageIgnoringTimeDilation(in TMessage message, double time) where TMessage : struct, IMessage { _messageStore.AddMessageIgnoringTimeDilation(message, time); } @@ -37,7 +38,7 @@ namespace Encompass _messageStore.ProcessDelayedMessages(dt * _timeManager.TimeDilationFactor, dt); } - internal IEnumerable GetMessagesByType() where TMessage : struct, IMessage + internal Span GetMessagesByType() where TMessage : struct, IMessage { return _messageStore.All(); } diff --git a/encompass-cs/UberEngine.cs b/encompass-cs/UberEngine.cs index c6f55b4..0003928 100644 --- a/encompass-cs/UberEngine.cs +++ b/encompass-cs/UberEngine.cs @@ -58,7 +58,9 @@ namespace Encompass CallGenericMethod(type, "SendMessage", 1, new object[] { Activator.CreateInstance(type) }); CallGenericMethod(type, "SendMessage", 2, new object[] { Activator.CreateInstance(type), 1 }); CallGenericMethod(type, "ReadMessage", null); - CallGenericMethod(type, "ReadMessages", null); + + // can't reflect on methods that return a span... + //CallGenericMethod(type, "ReadMessages", null); CallGenericMethod(type, "SomeMessage", null); if (typeof(IHasEntity).IsAssignableFrom(type)) { diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs index 68cb330..5da3d3a 100644 --- a/encompass-cs/WorldBuilder.cs +++ b/encompass-cs/WorldBuilder.cs @@ -68,7 +68,7 @@ namespace Encompass /// /// Specifies that the given Message should be sent immediately on the first World Update. /// - public void SendMessage(TMessage message) where TMessage : struct, IMessage + public void SendMessage(in TMessage message) where TMessage : struct, IMessage { _messageManager.AddMessage(message); } @@ -76,7 +76,7 @@ namespace Encompass /// /// Specifies that the given Message should be sent after the specified number of seconds after the first World Update. /// - public void SendMessage(TMessage message, double time) where TMessage : struct, IMessage + public void SendMessage(in TMessage message, double time) where TMessage : struct, IMessage { _messageManager.AddMessage(message, time); } diff --git a/test/ComponentTest.cs b/test/ComponentTest.cs index b8826b2..e881f64 100644 --- a/test/ComponentTest.cs +++ b/test/ComponentTest.cs @@ -45,7 +45,7 @@ namespace Tests { public override void Update(double dt) { - foreach (var addComponentTestMessage in ReadMessages()) + foreach (ref readonly var addComponentTestMessage in ReadMessages()) { Assert.IsTrue(HasComponent(addComponentTestMessage.entity)); ref readonly var gottenComponent = ref GetComponent(addComponentTestMessage.entity); diff --git a/test/EngineTest.cs b/test/EngineTest.cs index 208f455..dd4d7d6 100644 --- a/test/EngineTest.cs +++ b/test/EngineTest.cs @@ -20,7 +20,7 @@ namespace Tests static List resultComponents; static MockComponent resultComponent; - static List resultMessages = new List(); + static MockMessage[] resultMessages; [Reads(typeof(MockComponent))] public class ReadComponentsTestEngine : Engine @@ -279,7 +279,7 @@ namespace Tests { public override void Update(double dt) { - resultMessages = this.ReadMessages().ToList(); + resultMessages = ReadMessages().ToArray(); } } @@ -308,14 +308,14 @@ namespace Tests } } - static IEnumerable emptyReadMessagesResult; + static MockMessage[] emptyReadMessagesResult; [Receives(typeof(MockMessage))] class ReadMessagesWhenNoneExistEngine : Engine { public override void Update(double dt) { - emptyReadMessagesResult = ReadMessages(); + emptyReadMessagesResult = ReadMessages().ToArray(); } } @@ -799,7 +799,7 @@ namespace Tests [Test] public void EngineSendMessageDelayed() { - resultMessages.Clear(); + Array.Clear(resultMessages, 0, resultMessages.Length); var worldBuilder = new WorldBuilder(); worldBuilder.AddEngine(new ActivateTimeDilationEngine()); @@ -846,7 +846,7 @@ namespace Tests [Test] public void EngineSendMessageDelayedIgnoringTimeDilation() { - resultMessages.Clear(); + Array.Clear(resultMessages, 0, resultMessages.Length); var worldBuilder = new WorldBuilder(); worldBuilder.AddEngine(new ActivateTimeDilationEngine()); diff --git a/test/WorldBuilderTest.cs b/test/WorldBuilderTest.cs index 9a705f2..68b333b 100644 --- a/test/WorldBuilderTest.cs +++ b/test/WorldBuilderTest.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Encompass.Exceptions; using System.Linq; using FluentAssertions; +using System; namespace Tests { @@ -479,20 +480,22 @@ namespace Tests Assert.That(order.IndexOf(engineC), Is.LessThan(order.IndexOf(engineD))); } - static List resultMessages = new List(); + static AMessage[] resultMessages; [Receives(typeof(AMessage))] class ReadMessageEngine : Engine { public override void Update(double dt) { - resultMessages = ReadMessages().ToList(); + resultMessages = ReadMessages().ToArray(); } } [Test] public void SendMessageDelayed() { + resultMessages = Array.Empty(); + var worldBuilder = new WorldBuilder(); worldBuilder.AddEngine(new ReadMessageEngine()); From 971993f6050b2db47c8a3003d1ba26a719b696dd Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Sun, 22 Mar 2020 13:45:28 -0700 Subject: [PATCH 16/30] update ReadMessages loops to use ref readonly --- test/ComponentTest.cs | 14 +++++++------- test/EngineTest.cs | 4 ++-- test/WorldBuilderTest.cs | 10 +++++----- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/test/ComponentTest.cs b/test/ComponentTest.cs index e881f64..fadb126 100644 --- a/test/ComponentTest.cs +++ b/test/ComponentTest.cs @@ -26,7 +26,7 @@ namespace Tests { public override void Update(double dt) { - foreach (var entityMessage in ReadMessages()) + foreach (ref readonly var entityMessage in ReadMessages()) { gottenMockComponent = GetComponent(entityMessage.entity); } @@ -207,7 +207,7 @@ namespace Tests { public override void Update(double dt) { - foreach (var message in ReadMessages()) + foreach (ref readonly var message in ReadMessages()) { SetComponent(message.entity, message.mockComponent); } @@ -280,7 +280,7 @@ namespace Tests { public override void Update(double dt) { - foreach (var hasComponentTestEngine in ReadMessages()) + foreach (ref readonly var hasComponentTestEngine in ReadMessages()) { Assert.IsTrue(HasComponent(hasComponentTestEngine.entity)); } @@ -317,7 +317,7 @@ namespace Tests { public override void Update(double dt) { - foreach (var hasComponentTestEngine in ReadMessages()) + foreach (ref readonly var hasComponentTestEngine in ReadMessages()) { hasComponentRuntimeTypeResult = HasComponent(hasComponentTestEngine.entity, typeof(MockComponent)); } @@ -379,7 +379,7 @@ namespace Tests { public override void Update(double dt) { - foreach (var removeComponentMessage in ReadMessages()) + foreach (ref readonly var removeComponentMessage in ReadMessages()) { RemoveComponent(removeComponentMessage.entity); } @@ -424,7 +424,7 @@ namespace Tests { public override void Update(double dt) { - foreach (var checkHasMockComponentMessage in ReadMessages()) + foreach (ref readonly var checkHasMockComponentMessage in ReadMessages()) { hasComponentResult = HasComponent(checkHasMockComponentMessage.entity); } @@ -473,7 +473,7 @@ namespace Tests { public override void Update(double dt) { - foreach (var checkHasMockComponentMessage in ReadMessages()) + foreach (ref readonly var checkHasMockComponentMessage in ReadMessages()) { Assert.IsTrue(HasComponent(checkHasMockComponentMessage.entity)); } diff --git a/test/EngineTest.cs b/test/EngineTest.cs index dd4d7d6..5c2d2d6 100644 --- a/test/EngineTest.cs +++ b/test/EngineTest.cs @@ -683,7 +683,7 @@ namespace Tests { public override void Update(double dt) { - foreach (var message in ReadMessages()) + foreach (ref readonly var message in ReadMessages()) { Destroy(message.entity); } @@ -879,7 +879,7 @@ namespace Tests { public override void Update(double dt) { - foreach (var message in ReadMessages()) + foreach (ref readonly var message in ReadMessages()) { var entity = CreateEntity(); SetComponent(entity, new MockComponent { }); diff --git a/test/WorldBuilderTest.cs b/test/WorldBuilderTest.cs index 68b333b..871dce4 100644 --- a/test/WorldBuilderTest.cs +++ b/test/WorldBuilderTest.cs @@ -159,7 +159,7 @@ namespace Tests { public override void Update(double dt) { - foreach (var setMessage in ReadMessages()) + foreach (ref readonly var setMessage in ReadMessages()) { SetComponent(setMessage.entity, new AComponent { myInt = 0 }); } @@ -173,7 +173,7 @@ namespace Tests { public override void Update(double dt) { - foreach (var setMessage in ReadMessages()) + foreach (ref readonly var setMessage in ReadMessages()) { SetComponent(setMessage.entity, new AComponent { myInt = 1 }); } @@ -229,7 +229,7 @@ namespace Tests { public override void Update(double dt) { - foreach (var setMessage in ReadMessages()) + foreach (ref readonly var setMessage in ReadMessages()) { SetComponent(setMessage.entity, new AComponent { myInt = 5 }); } @@ -244,7 +244,7 @@ namespace Tests { public override void Update(double dt) { - foreach (var setMessage in ReadMessages()) + foreach (ref readonly var setMessage in ReadMessages()) { SetComponent(setMessage.entity, new AComponent { myInt = 1 }); } @@ -258,7 +258,7 @@ namespace Tests { public override void Update(double dt) { - foreach (var setMessage in ReadMessages()) + foreach (ref readonly var setMessage in ReadMessages()) { SetComponent(setMessage.entity, new AComponent { myInt = 3 }); } From 5a536e6123a3feb40b46e34562d081010873d90c Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Sun, 22 Mar 2020 13:53:23 -0700 Subject: [PATCH 17/30] optimize singular entity message read --- encompass-cs/Collections/MessageStore.cs | 5 +++++ encompass-cs/Collections/TypedMessageStore.cs | 9 +++++++-- encompass-cs/MessageManager.cs | 6 ++---- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/encompass-cs/Collections/MessageStore.cs b/encompass-cs/Collections/MessageStore.cs index 4d44657..632cfd3 100644 --- a/encompass-cs/Collections/MessageStore.cs +++ b/encompass-cs/Collections/MessageStore.cs @@ -53,6 +53,11 @@ namespace Encompass return Lookup().WithEntity(entityID); } + public ref readonly TMessage FirstWithEntity(int entityID) where TMessage : struct, IMessage + { + return ref Lookup().FirstWithEntity(entityID); + } + public bool SomeWithEntity(int entityID) where TMessage : struct, IMessage, IHasEntity { return Lookup().SomeWithEntity(entityID); diff --git a/encompass-cs/Collections/TypedMessageStore.cs b/encompass-cs/Collections/TypedMessageStore.cs index b43f129..3e8d815 100644 --- a/encompass-cs/Collections/TypedMessageStore.cs +++ b/encompass-cs/Collections/TypedMessageStore.cs @@ -17,7 +17,7 @@ namespace Encompass private readonly TMessage[] _store = new TMessage[128]; private readonly List<(TMessage, double)> _delayedStore = new List<(TMessage, double)>(128); private readonly List<(TMessage, double)> _delayedStoreIgnoringTimeDilation = new List<(TMessage, double)>(128); - private readonly Dictionary> _entityToIndices = new Dictionary>(); + private readonly Dictionary> _entityToIndices = new Dictionary>(); public override void ProcessDelayedMessages(double dilatedDelta, double realtimeDelta) { @@ -63,7 +63,7 @@ namespace Encompass if (message is IHasEntity entityMessage) { var entityID = entityMessage.Entity.ID; - if (!_entityToIndices.ContainsKey(entityID)) { _entityToIndices.Add(entityID, new HashSet()); } + if (!_entityToIndices.ContainsKey(entityID)) { _entityToIndices.Add(entityID, new List()); } _entityToIndices[entityID].Add(index); } } @@ -104,6 +104,11 @@ namespace Encompass } } + public ref readonly TMessage FirstWithEntity(int entityID) + { + return ref _store[_entityToIndices[entityID][0]]; + } + public bool SomeWithEntity(int entityID) { return _entityToIndices.ContainsKey(entityID) && _entityToIndices[entityID].Count > 0; diff --git a/encompass-cs/MessageManager.cs b/encompass-cs/MessageManager.cs index 0ee4dc2..1e7d704 100644 --- a/encompass-cs/MessageManager.cs +++ b/encompass-cs/MessageManager.cs @@ -58,11 +58,9 @@ namespace Encompass return _messageStore.WithEntity(entityID); } - internal TMessage WithEntitySingular(int entityID) where TMessage : struct, IMessage, IHasEntity + internal ref readonly TMessage WithEntitySingular(int entityID) where TMessage : struct, IMessage, IHasEntity { - var enumerator = _messageStore.WithEntity(entityID).GetEnumerator(); - enumerator.MoveNext(); - return enumerator.Current; + return ref _messageStore.FirstWithEntity(entityID); } internal bool SomeWithEntity(int entityID) where TMessage : struct, IMessage, IHasEntity From 0d969322ad1c2ff26eeb323214438b888998ddaa Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Sun, 22 Mar 2020 14:04:09 -0700 Subject: [PATCH 18/30] trying PrepareMethod instead of Invoke --- encompass-cs/UberEngine.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/encompass-cs/UberEngine.cs b/encompass-cs/UberEngine.cs index 0003928..48d64c4 100644 --- a/encompass-cs/UberEngine.cs +++ b/encompass-cs/UberEngine.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Runtime.CompilerServices; namespace Encompass { @@ -59,8 +60,7 @@ namespace Encompass CallGenericMethod(type, "SendMessage", 2, new object[] { Activator.CreateInstance(type), 1 }); CallGenericMethod(type, "ReadMessage", null); - // can't reflect on methods that return a span... - //CallGenericMethod(type, "ReadMessages", null); + CallGenericMethod(type, "ReadMessages", null); CallGenericMethod(type, "SomeMessage", null); if (typeof(IHasEntity).IsAssignableFrom(type)) { @@ -71,25 +71,29 @@ namespace Encompass } } + // trying to use PrepareMethod because we can't reflect invoke methods that return a span... private void CallGenericMethod(Type type, string methodName, object[] parameters) { var readComponentMethod = typeof(Engine).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance); var genericReadComponentMethod = readComponentMethod.MakeGenericMethod(type); - genericReadComponentMethod.Invoke(this, parameters); + //genericReadComponentMethod.Invoke(this, parameters); + RuntimeHelpers.PrepareMethod(genericReadComponentMethod.MethodHandle); } private void CallGenericMethod(Type type, string methodName, Type[] types, object[] parameters) { var readComponentMethod = typeof(Engine).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance, null, types, null); var genericReadComponentMethod = readComponentMethod.MakeGenericMethod(type); - genericReadComponentMethod.Invoke(this, parameters); + //genericReadComponentMethod.Invoke(this, parameters); + RuntimeHelpers.PrepareMethod(genericReadComponentMethod.MethodHandle); } private void CallGenericMethod(Type type, string methodName, int argumentNum, object[] parameters) { var method = typeof(Engine).GetRuntimeMethods().Where(m => m.Name == methodName && m.GetParameters().Length == argumentNum).First(); var genericMethod = method.MakeGenericMethod(type); - genericMethod.Invoke(this, parameters); + //genericMethod.Invoke(this, parameters); + RuntimeHelpers.PrepareMethod(genericMethod.MethodHandle); } } } From 26216a295f71d5ef97fb1ea17d4d57a9e89f1c86 Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Sun, 22 Mar 2020 14:20:22 -0700 Subject: [PATCH 19/30] singular message reads are ref readonly --- encompass-cs/Collections/MessageStore.cs | 4 ++-- encompass-cs/Collections/TypedMessageStore.cs | 4 ++-- encompass-cs/Engine.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/encompass-cs/Collections/MessageStore.cs b/encompass-cs/Collections/MessageStore.cs index 632cfd3..8495966 100644 --- a/encompass-cs/Collections/MessageStore.cs +++ b/encompass-cs/Collections/MessageStore.cs @@ -33,9 +33,9 @@ namespace Encompass Lookup().AddIgnoringTimeDilation(message, time); } - public TMessage First() where TMessage : struct, IMessage + public ref readonly TMessage First() where TMessage : struct, IMessage { - return Lookup().First(); + return ref Lookup().First(); } public Span All() where TMessage : struct, IMessage diff --git a/encompass-cs/Collections/TypedMessageStore.cs b/encompass-cs/Collections/TypedMessageStore.cs index 3e8d815..f5bd150 100644 --- a/encompass-cs/Collections/TypedMessageStore.cs +++ b/encompass-cs/Collections/TypedMessageStore.cs @@ -78,9 +78,9 @@ namespace Encompass _delayedStoreIgnoringTimeDilation.Add((message, time)); } - public TMessage First() + public ref readonly TMessage First() { - return _store[0]; + return ref _store[0]; } public bool Any() diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index d98fe87..b0aa6e5 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -731,10 +731,10 @@ namespace Encompass /// Efficiently reads a single Message of a given type that references a given Entity. /// It is recommended to use this method in conjunction with SomeMessageWithEntity to prevent errors. /// - protected TMessage ReadMessageWithEntity(Entity entity) where TMessage : struct, IMessage, IHasEntity + protected ref readonly TMessage ReadMessageWithEntity(Entity entity) where TMessage : struct, IMessage, IHasEntity { CheckMessageRead(); - return _messageManager.WithEntitySingular(entity.ID); + return ref _messageManager.WithEntitySingular(entity.ID); } /// From a00735650ad91b79448b0956fcfb91b1b6dc5e4d Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Sun, 22 Mar 2020 14:21:59 -0700 Subject: [PATCH 20/30] update another ref readonly --- encompass-cs/MessageManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/encompass-cs/MessageManager.cs b/encompass-cs/MessageManager.cs index 1e7d704..234f46f 100644 --- a/encompass-cs/MessageManager.cs +++ b/encompass-cs/MessageManager.cs @@ -48,9 +48,9 @@ namespace Encompass return _messageStore.Any(); } - internal TMessage First() where TMessage : struct, IMessage + internal ref readonly TMessage First() where TMessage : struct, IMessage { - return _messageStore.First(); + return ref _messageStore.First(); } internal IEnumerable WithEntity(int entityID) where TMessage : struct, IMessage, IHasEntity From 5bc0294158b98e879e1e64a37d69722d45e121dc Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Sun, 22 Mar 2020 14:24:59 -0700 Subject: [PATCH 21/30] buhhhh --- encompass-cs/Engine.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index b0aa6e5..cefb2ed 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -575,10 +575,10 @@ namespace Encompass /// /// Thrown when the Engine does not declare that it Receives the specified Message Type. /// - protected TMessage ReadMessage() where TMessage : struct, IMessage + protected ref readonly TMessage ReadMessage() where TMessage : struct, IMessage { CheckMessageRead(); - return _messageManager.First(); + return ref _messageManager.First(); } /// From e4d4df9fdd81f1b1ed860d05e3f1f1d3e59750fc Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Sun, 22 Mar 2020 16:07:58 -0700 Subject: [PATCH 22/30] resizeable message store --- encompass-cs/Collections/TypedMessageStore.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/encompass-cs/Collections/TypedMessageStore.cs b/encompass-cs/Collections/TypedMessageStore.cs index f5bd150..c8a263e 100644 --- a/encompass-cs/Collections/TypedMessageStore.cs +++ b/encompass-cs/Collections/TypedMessageStore.cs @@ -14,7 +14,7 @@ namespace Encompass // messages are placed in a contiguous region // so we can return the collection as a Span private int _nextIndex = 0; - private readonly TMessage[] _store = new TMessage[128]; + private TMessage[] _store = new TMessage[128]; private readonly List<(TMessage, double)> _delayedStore = new List<(TMessage, double)>(128); private readonly List<(TMessage, double)> _delayedStoreIgnoringTimeDilation = new List<(TMessage, double)>(128); private readonly Dictionary> _entityToIndices = new Dictionary>(); @@ -59,6 +59,10 @@ namespace Encompass public void Add(in TMessage message) { var index = _nextIndex++; + if (index >= _store.Length) + { + Array.Resize(ref _store, _store.Length * 2); + } _store[index] = message; if (message is IHasEntity entityMessage) { From 61845d752a00c1fdd10b1b1cc34d9f4d266ef475 Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Sun, 22 Mar 2020 17:03:18 -0700 Subject: [PATCH 23/30] contiguous component storage --- .../Collections/TypedComponentStore.cs | 61 +++++++++++++------ 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/encompass-cs/Collections/TypedComponentStore.cs b/encompass-cs/Collections/TypedComponentStore.cs index 536b536..9cb2788 100644 --- a/encompass-cs/Collections/TypedComponentStore.cs +++ b/encompass-cs/Collections/TypedComponentStore.cs @@ -15,17 +15,18 @@ namespace Encompass internal class TypedComponentStore : TypedComponentStore where TComponent : struct { - private readonly Dictionary _indices = new Dictionary(512); - private readonly Dictionary _priorities = new Dictionary(512); - private readonly TComponent[] _components = new TComponent[512]; // TODO: allow specify size - private readonly IDManager _idManager = new IDManager(); + private int _nextID = 0; + private readonly Dictionary _entityIDToStorageIndex = new Dictionary(128); + private readonly Dictionary _storageIndexToEntityID = new Dictionary(128); + private readonly Dictionary _priorities = new Dictionary(128); + private TComponent[] _components = new TComponent[128]; - public override int Count { get => _indices.Count; } + public override int Count { get => _entityIDToStorageIndex.Count; } public ref TComponent Get(int entityID) { - if (!_indices.ContainsKey(entityID)) { throw new Exceptions.NoComponentOfTypeOnEntityException("No component of type {0} exists on Entity with ID {1}", typeof(TComponent), entityID); } - return ref _components[_indices[entityID]]; + if (!_entityIDToStorageIndex.ContainsKey(entityID)) { throw new Exceptions.NoComponentOfTypeOnEntityException("No component of type {0} exists on Entity with ID {1}", typeof(TComponent), entityID); } + return ref _components[_entityIDToStorageIndex[entityID]]; } public void Set(int entityID, in TComponent component) @@ -47,12 +48,18 @@ namespace Encompass private void InternalSet(int entityID, in TComponent component) { - if (!_indices.ContainsKey(entityID)) + if (!_entityIDToStorageIndex.ContainsKey(entityID)) { - _indices[entityID] = _idManager.NextID(); + var index = _nextID++; + if (index >= _components.Length) + { + System.Array.Resize(ref _components, _components.Length * 2); + } + _entityIDToStorageIndex[entityID] = index; + _storageIndexToEntityID[index] = entityID; } - _components[_indices[entityID]] = component; + _components[_entityIDToStorageIndex[entityID]] = component; } public override bool Remove(int entityID, int priority) @@ -69,26 +76,40 @@ namespace Encompass public override void ForceRemove(int entityID) { - if (_indices.ContainsKey(entityID)) + if (_entityIDToStorageIndex.ContainsKey(entityID)) { - _idManager.Free(_indices[entityID]); - _indices.Remove(entityID); + var storageIndex = _entityIDToStorageIndex[entityID]; + _entityIDToStorageIndex.Remove(entityID); + _storageIndexToEntityID.Remove(storageIndex); _priorities.Remove(entityID); + + // move a component into the hole to maintain contiguous memory + if (_nextID > 1 && storageIndex != _nextID - 1) + { + var lastStorageIndex = _nextID - 1; + var lastEntityID = _storageIndexToEntityID[lastStorageIndex]; + _storageIndexToEntityID.Remove(lastStorageIndex); + + _entityIDToStorageIndex[lastEntityID] = storageIndex; + _storageIndexToEntityID[storageIndex] = lastEntityID; + _components[storageIndex] = _components[lastStorageIndex]; + + } + + _nextID--; } } public override bool Has(int entityID) { - return _indices.ContainsKey(entityID); + return _entityIDToStorageIndex.ContainsKey(entityID); } public override void Clear() { - foreach (var mappedID in _indices.Values) - { - _idManager.Free(mappedID); - } - _indices.Clear(); + _nextID = 0; + _entityIDToStorageIndex.Clear(); + _storageIndexToEntityID.Clear(); _priorities.Clear(); } @@ -99,7 +120,7 @@ namespace Encompass public IEnumerable<(TComponent, int)> All() { - foreach (var kvp in _indices) + foreach (var kvp in _entityIDToStorageIndex) { yield return (_components[kvp.Value], kvp.Key); } From d5a45d641988fbcc9b68b2d0c789a18120e74955 Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Sun, 22 Mar 2020 17:18:23 -0700 Subject: [PATCH 24/30] fix bug in delta store + storage index map is now an array --- encompass-cs/Collections/ComponentDeltaStore.cs | 1 + encompass-cs/Collections/TypedComponentStore.cs | 10 ++++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/encompass-cs/Collections/ComponentDeltaStore.cs b/encompass-cs/Collections/ComponentDeltaStore.cs index a0b022c..eadc90f 100644 --- a/encompass-cs/Collections/ComponentDeltaStore.cs +++ b/encompass-cs/Collections/ComponentDeltaStore.cs @@ -52,6 +52,7 @@ namespace Encompass var result = _store.Remove(entityID, priority); if (result) { + RegisterComponentType(); var replayer = _replayers[typeof(TComponent)]; _currentReplayers.Add(replayer); replayer.MarkRemoval(entityID); diff --git a/encompass-cs/Collections/TypedComponentStore.cs b/encompass-cs/Collections/TypedComponentStore.cs index 9cb2788..679ee1c 100644 --- a/encompass-cs/Collections/TypedComponentStore.cs +++ b/encompass-cs/Collections/TypedComponentStore.cs @@ -17,8 +17,8 @@ namespace Encompass { private int _nextID = 0; private readonly Dictionary _entityIDToStorageIndex = new Dictionary(128); - private readonly Dictionary _storageIndexToEntityID = new Dictionary(128); private readonly Dictionary _priorities = new Dictionary(128); + private int[] _storageIndexToEntityID = new int[128]; private TComponent[] _components = new TComponent[128]; public override int Count { get => _entityIDToStorageIndex.Count; } @@ -54,6 +54,7 @@ namespace Encompass if (index >= _components.Length) { System.Array.Resize(ref _components, _components.Length * 2); + System.Array.Resize(ref _storageIndexToEntityID, _storageIndexToEntityID.Length * 2); } _entityIDToStorageIndex[entityID] = index; _storageIndexToEntityID[index] = entityID; @@ -80,7 +81,6 @@ namespace Encompass { var storageIndex = _entityIDToStorageIndex[entityID]; _entityIDToStorageIndex.Remove(entityID); - _storageIndexToEntityID.Remove(storageIndex); _priorities.Remove(entityID); // move a component into the hole to maintain contiguous memory @@ -88,7 +88,6 @@ namespace Encompass { var lastStorageIndex = _nextID - 1; var lastEntityID = _storageIndexToEntityID[lastStorageIndex]; - _storageIndexToEntityID.Remove(lastStorageIndex); _entityIDToStorageIndex[lastEntityID] = storageIndex; _storageIndexToEntityID[storageIndex] = lastEntityID; @@ -109,7 +108,6 @@ namespace Encompass { _nextID = 0; _entityIDToStorageIndex.Clear(); - _storageIndexToEntityID.Clear(); _priorities.Clear(); } @@ -120,9 +118,9 @@ namespace Encompass public IEnumerable<(TComponent, int)> All() { - foreach (var kvp in _entityIDToStorageIndex) + for (var i = 0; i < _nextID; i++) { - yield return (_components[kvp.Value], kvp.Key); + yield return (_components[i], _storageIndexToEntityID[i]); } } } From ca9c9c84a3868913a43038d386976144d0b5f2b0 Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Sun, 22 Mar 2020 19:10:28 -0700 Subject: [PATCH 25/30] getting rid of tuple returns --- .../Collections/ComponentDeltaStore.cs | 9 +- encompass-cs/Collections/ComponentStore.cs | 19 ++- encompass-cs/Collections/Replayer.cs | 5 +- .../Collections/TypedComponentStore.cs | 35 ++++-- encompass-cs/ComponentManager.cs | 60 ++++++---- encompass-cs/Engine.cs | 113 +++++++----------- encompass-cs/Renderer.cs | 37 ++---- encompass-cs/UberEngine.cs | 33 +++-- encompass-cs/UberRenderer.cs | 7 +- test/ComponentTest.cs | 6 +- test/EngineTest.cs | 92 +++++++------- test/GeneralRendererTest.cs | 3 +- 12 files changed, 212 insertions(+), 207 deletions(-) diff --git a/encompass-cs/Collections/ComponentDeltaStore.cs b/encompass-cs/Collections/ComponentDeltaStore.cs index eadc90f..48d44c4 100644 --- a/encompass-cs/Collections/ComponentDeltaStore.cs +++ b/encompass-cs/Collections/ComponentDeltaStore.cs @@ -25,6 +25,11 @@ namespace Encompass } } + public ref readonly TComponent GetComponent(int entityID) where TComponent : struct + { + return ref _store.Get(entityID); + } + public void Set(int entityID, in TComponent component) where TComponent : struct { _store.Set(entityID, component); @@ -69,9 +74,9 @@ namespace Encompass } } - public IEnumerable<(TComponent, int)> All() where TComponent : struct + public Span AllEntities() where TComponent : struct { - return _store.All(); + return _store.AllEntities(); } public void ClearAll() diff --git a/encompass-cs/Collections/ComponentStore.cs b/encompass-cs/Collections/ComponentStore.cs index b4f541e..fc20a17 100644 --- a/encompass-cs/Collections/ComponentStore.cs +++ b/encompass-cs/Collections/ComponentStore.cs @@ -53,6 +53,16 @@ namespace Encompass return ref Lookup().Get(entityID); } + public ref readonly TComponent Singular() where TComponent : struct + { + return ref Lookup().Singular(); + } + + public ref readonly Entity SingularEntity() where TComponent : struct + { + return ref Lookup().SingularEntity(); + } + public void Set(int entityID, in TComponent component) where TComponent : struct { Lookup().Set(entityID, component); @@ -99,9 +109,14 @@ namespace Encompass return Lookup().Count > 0; } - public IEnumerable<(TComponent, int)> All() where TComponent : struct + public Span All() where TComponent : struct { - return Lookup().All(); + return Lookup().AllComponents(); + } + + public Span AllEntities() where TComponent : struct + { + return Lookup().AllEntities(); } public void Clear() where TComponent : struct diff --git a/encompass-cs/Collections/Replayer.cs b/encompass-cs/Collections/Replayer.cs index 46f184a..f90018a 100644 --- a/encompass-cs/Collections/Replayer.cs +++ b/encompass-cs/Collections/Replayer.cs @@ -22,9 +22,10 @@ namespace Encompass public override void Replay(ComponentStore store) { - foreach (var (component, entityID) in _deltaStore.All()) + foreach (ref readonly var entity in _deltaStore.AllEntities()) { - store.Set(entityID, component); + ref readonly var component = ref _deltaStore.GetComponent(entity.ID); + store.Set(entity.ID, component); } foreach (var entityID in _removals) diff --git a/encompass-cs/Collections/TypedComponentStore.cs b/encompass-cs/Collections/TypedComponentStore.cs index 679ee1c..232fa2b 100644 --- a/encompass-cs/Collections/TypedComponentStore.cs +++ b/encompass-cs/Collections/TypedComponentStore.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Runtime.CompilerServices; @@ -18,7 +19,7 @@ namespace Encompass private int _nextID = 0; private readonly Dictionary _entityIDToStorageIndex = new Dictionary(128); private readonly Dictionary _priorities = new Dictionary(128); - private int[] _storageIndexToEntityID = new int[128]; + private Entity[] _storageIndexToEntities = new Entity[128]; private TComponent[] _components = new TComponent[128]; public override int Count { get => _entityIDToStorageIndex.Count; } @@ -29,6 +30,16 @@ namespace Encompass return ref _components[_entityIDToStorageIndex[entityID]]; } + public ref TComponent Singular() + { + return ref _components[0]; + } + + public ref Entity SingularEntity() + { + return ref _storageIndexToEntities[0]; + } + public void Set(int entityID, in TComponent component) { InternalSet(entityID, component); @@ -54,10 +65,10 @@ namespace Encompass if (index >= _components.Length) { System.Array.Resize(ref _components, _components.Length * 2); - System.Array.Resize(ref _storageIndexToEntityID, _storageIndexToEntityID.Length * 2); + System.Array.Resize(ref _storageIndexToEntities, _storageIndexToEntities.Length * 2); } _entityIDToStorageIndex[entityID] = index; - _storageIndexToEntityID[index] = entityID; + _storageIndexToEntities[index] = new Entity(entityID); } _components[_entityIDToStorageIndex[entityID]] = component; @@ -87,10 +98,10 @@ namespace Encompass if (_nextID > 1 && storageIndex != _nextID - 1) { var lastStorageIndex = _nextID - 1; - var lastEntityID = _storageIndexToEntityID[lastStorageIndex]; + ref readonly var lastEntity = ref _storageIndexToEntities[lastStorageIndex]; - _entityIDToStorageIndex[lastEntityID] = storageIndex; - _storageIndexToEntityID[storageIndex] = lastEntityID; + _entityIDToStorageIndex[lastEntity.ID] = storageIndex; + _storageIndexToEntities[storageIndex] = lastEntity; _components[storageIndex] = _components[lastStorageIndex]; } @@ -116,12 +127,14 @@ namespace Encompass _priorities.Clear(); } - public IEnumerable<(TComponent, int)> All() + public Span AllEntities() { - for (var i = 0; i < _nextID; i++) - { - yield return (_components[i], _storageIndexToEntityID[i]); - } + return new Span(_storageIndexToEntities, 0, _nextID); + } + + public Span AllComponents() + { + return new Span(_components, 0, _nextID); } } } diff --git a/encompass-cs/ComponentManager.cs b/encompass-cs/ComponentManager.cs index fe98902..6aea1d0 100644 --- a/encompass-cs/ComponentManager.cs +++ b/encompass-cs/ComponentManager.cs @@ -98,17 +98,19 @@ namespace Encompass // existing or immediate reads - internal IEnumerable<(TComponent, int)> ReadExistingAndImmediateComponentsByType() where TComponent : struct + internal Span ReadExistingAndImmediateComponentsByType() where TComponent : struct { return _upToDateComponentStore.All(); } - internal (TComponent, int) ReadFirstExistingOrImmediateComponentByType() where TComponent : struct + internal ref readonly TComponent ExistingOrImmediateSingular() where TComponent : struct { - if (!SomeExistingOrImmediateComponent()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } - var enumerator = ReadExistingAndImmediateComponentsByType().GetEnumerator(); - enumerator.MoveNext(); - return enumerator.Current; + return ref _upToDateComponentStore.Singular(); + } + + internal Span GetExistingAndImmediateEntities() where TComponent : struct + { + return _upToDateComponentStore.AllEntities(); } internal bool SomeExistingOrImmediateComponent() where TComponent : struct @@ -118,12 +120,24 @@ namespace Encompass // existing reads - internal (TComponent, int) ReadFirstExistingComponentByType() where TComponent : struct + internal Span GetExistingComponents() where TComponent : struct { - if (!SomeExistingComponent()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } - var enumerator = GetComponentsIncludingEntity().GetEnumerator(); - enumerator.MoveNext(); - return enumerator.Current; + return _existingComponentStore.All(); + } + + internal ref readonly TComponent ExistingSingular() where TComponent : struct + { + return ref _existingComponentStore.Singular(); + } + + internal Span GetExistingEntities() where TComponent : struct + { + return _existingComponentStore.AllEntities(); + } + + internal ref readonly Entity SingularEntity() where TComponent : struct + { + return ref _existingComponentStore.SingularEntity(); } internal bool SomeExistingComponent() where TComponent : struct @@ -133,17 +147,19 @@ namespace Encompass // immediate reads - internal IEnumerable<(TComponent, int)> ReadImmediateComponentsByType() where TComponent : struct + internal Span ReadImmediateComponentsByType() where TComponent : struct { return _immediateComponentStore.All(); } - internal (TComponent, int) ReadFirstImmediateComponentByType() where TComponent : struct + internal Span GetImmediateEntities() where TComponent : struct { - if (!SomeImmediateComponent()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } - var enumerator = ReadImmediateComponentsByType().GetEnumerator(); - enumerator.MoveNext(); - return enumerator.Current; + return _immediateComponentStore.AllEntities(); + } + + internal ref readonly TComponent ImmediateSingular() where TComponent : struct + { + return ref _immediateComponentStore.Singular(); } internal bool SomeImmediateComponent() where TComponent : struct @@ -200,19 +216,11 @@ namespace Encompass return _immediateComponentStore.Has(type, entityID); } - internal IEnumerable<(TComponent, int)> GetComponentsIncludingEntity() where TComponent : struct + internal Span GetComponentsByType() where TComponent : struct { return _existingComponentStore.All(); } - internal IEnumerable GetComponentsByType() where TComponent : struct - { - foreach (var pair in _existingComponentStore.All()) - { - yield return pair.Item1; - } - } - internal ref readonly TComponent GetComponentByEntityAndType(int entityID) where TComponent : struct { return ref _existingComponentStore.Get(entityID); diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index cefb2ed..5fb740b 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -197,7 +197,7 @@ namespace Encompass /// /// Returns true if an Entity with the specified ID exists. /// - protected bool EntityExists(Entity entity) + protected bool EntityExists(in Entity entity) { return _entityManager.EntityExists(entity.ID); } @@ -213,30 +213,45 @@ namespace Encompass /// /// Returns an Entity containing the specified Component type. /// - protected Entity ReadEntity() where TComponent : struct + protected ref readonly Entity ReadEntity() where TComponent : struct { - return _entityManager.GetEntity(ReadComponentHelper().Item2); + return ref _componentManager.SingularEntity(); } /// /// Returns all Entities containing the specified Component type. /// - protected IEnumerable ReadEntities() where TComponent : struct + protected Span ReadEntities() where TComponent : struct { - foreach (var pair in ReadComponentsHelper()) + return ReadEntitiesHelper(); + } + + private Span ReadEntitiesHelper() where TComponent : struct + { + var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); + var existingRead = ReadTypes.Contains(typeof(TComponent)); + if (existingRead && immediateRead) { - yield return _entityManager.GetEntity(pair.Item2); + return _componentManager.GetExistingAndImmediateEntities(); + } + else if (existingRead) + { + return _componentManager.GetExistingEntities(); + } + else if (immediateRead) + { + return _componentManager.GetImmediateEntities(); + } + else + { + throw new IllegalReadException("Engine {0} tried to read undeclared Component {1}", GetType().Name, typeof(TComponent).Name); } } - // these next two are for the ComponentMessageEmitter only - - internal IEnumerable ReadComponentsFromWorld() where TComponent : struct - { - return _componentManager.GetComponentsByType(); - } - - private IEnumerable<(TComponent, int)> ReadComponentsHelper() where TComponent : struct + /// + /// Returns all of the Components with the specified Component Type. + /// + protected Span ReadComponents() where TComponent : struct { var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent)); @@ -246,7 +261,7 @@ namespace Encompass } else if (existingRead) { - return _componentManager.GetComponentsIncludingEntity(); + return _componentManager.GetExistingComponents(); } else if (immediateRead) { @@ -259,42 +274,23 @@ namespace Encompass } /// - /// Returns all of the Components with the specified Component Type. + /// Returns a Component with the specified Component Type. If multiples exist, an arbitrary Component is returned. /// - protected IEnumerable ReadComponents() where TComponent : struct - { - foreach (var pair in ReadComponentsHelper()) - { - yield return pair.Item1; - } - } - - /// - /// Returns all of the components of the specified type including an Entity reference for each Component. - /// - protected IEnumerable<(TComponent, Entity)> ReadComponentsIncludingEntity() where TComponent : struct - { - foreach (var (component, id) in ReadComponentsHelper()) - { - yield return (component, _entityManager.GetEntity(id)); - } - } - - private (TComponent, int) ReadComponentHelper() where TComponent : struct + protected ref readonly TComponent ReadComponent() where TComponent : struct { var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent)); if (existingRead && immediateRead) { - return _componentManager.ReadFirstExistingOrImmediateComponentByType(); + return ref _componentManager.ExistingOrImmediateSingular(); } else if (existingRead) { - return _componentManager.ReadFirstExistingComponentByType(); + return ref _componentManager.ExistingSingular(); } else if (immediateRead) { - return _componentManager.ReadFirstImmediateComponentByType(); + return ref _componentManager.ImmediateSingular(); } else { @@ -302,23 +298,6 @@ namespace Encompass } } - /// - /// Returns a Component with the specified Component Type. If multiples exist, an arbitrary Component is returned. - /// - protected TComponent ReadComponent() where TComponent : struct - { - return ReadComponentHelper().Item1; - } - - /// - /// Returns a component of the specified type including its Entity reference. If multiples exist, an arbitrary Component is returned. - /// - protected (TComponent, Entity) ReadComponentIncludingEntity() where TComponent : struct - { - var (component, id) = ReadComponentHelper(); - return (component, _entityManager.GetEntity(id)); - } - /// /// Returns true if any Component with the specified Component Type exists. /// @@ -375,7 +354,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that it reads the given Component Type. /// - protected ref readonly TComponent GetComponent(Entity entity) where TComponent : struct + protected ref readonly TComponent GetComponent(in Entity entity) where TComponent : struct { return ref GetComponentHelper(entity.ID); } @@ -389,7 +368,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that it reads the given Component Type. /// - protected ref TComponent GetComponentMutable(Entity entity) where TComponent : struct + protected ref TComponent GetComponentMutable(in Entity entity) where TComponent : struct { return ref GetComponentHelper(entity.ID); } @@ -400,7 +379,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that is Reads the given Component Type. /// - protected bool HasComponent(Entity entity) where TComponent : struct + protected bool HasComponent(in Entity entity) where TComponent : struct { var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent)); @@ -429,7 +408,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that is Reads the given Component Type. /// - protected bool HasComponent(Entity entity, Type type) + protected bool HasComponent(in Entity entity, Type type) { var immediateRead = ReadImmediateTypes.Contains(type); var existingRead = ReadTypes.Contains(type); @@ -458,7 +437,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that it Writes the given Component Type. /// - protected void SetComponent(Entity entity, in TComponent component) where TComponent : struct + protected void SetComponent(in Entity entity, in TComponent component) where TComponent : struct { var priority = WritePriorities.ContainsKey(typeof(TComponent)) ? WritePriorities[typeof(TComponent)] : DefaultWritePriority; @@ -498,7 +477,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that it Writes the given Component Type. /// - protected void AddComponent(Entity entity, in TComponent component) where TComponent : struct + protected void AddComponent(in Entity entity, in TComponent component) where TComponent : struct { if (!EntityCreatedThisFrame(entity.ID)) { @@ -597,7 +576,7 @@ namespace Encompass /// Destroys the specified Entity. This also removes all of the Components associated with the Entity. /// Entity destruction takes place after all the Engines have been processed by World Update. /// - protected void Destroy(Entity entity) + protected void Destroy(in Entity entity) { _entityManager.MarkForDestroy(entity.ID); } @@ -628,7 +607,7 @@ namespace Encompass /// Note that the Engine must Read the Component type that is being removed. /// If a Component with the specified type does not exist on the Entity, returns false and does not mutate the Entity. /// - protected void RemoveComponent(Entity entity) where TComponent : struct + protected void RemoveComponent(in Entity entity) where TComponent : struct { var priority = WritePriorities.ContainsKey(typeof(TComponent)) ? WritePriorities[typeof(TComponent)] : DefaultWritePriority; @@ -721,7 +700,7 @@ namespace Encompass /// The Message subtype. /// The entity that all messages in the IEnumerable refer to. /// - protected IEnumerable ReadMessagesWithEntity(Entity entity) where TMessage : struct, IMessage, IHasEntity + protected IEnumerable ReadMessagesWithEntity(in Entity entity) where TMessage : struct, IMessage, IHasEntity { CheckMessageRead(); return _messageManager.WithEntity(entity.ID); @@ -731,7 +710,7 @@ namespace Encompass /// Efficiently reads a single Message of a given type that references a given Entity. /// It is recommended to use this method in conjunction with SomeMessageWithEntity to prevent errors. /// - protected ref readonly TMessage ReadMessageWithEntity(Entity entity) where TMessage : struct, IMessage, IHasEntity + protected ref readonly TMessage ReadMessageWithEntity(in Entity entity) where TMessage : struct, IMessage, IHasEntity { CheckMessageRead(); return ref _messageManager.WithEntitySingular(entity.ID); @@ -740,7 +719,7 @@ namespace Encompass /// /// Efficiently checks if any Message of a given type referencing a given Entity exists. /// - protected bool SomeMessageWithEntity(Entity entity) where TMessage : struct, IMessage, IHasEntity + protected bool SomeMessageWithEntity(in Entity entity) where TMessage : struct, IMessage, IHasEntity { CheckMessageRead(); return _messageManager.SomeWithEntity(entity.ID); diff --git a/encompass-cs/Renderer.cs b/encompass-cs/Renderer.cs index 2b9d513..caad2f7 100644 --- a/encompass-cs/Renderer.cs +++ b/encompass-cs/Renderer.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace Encompass { @@ -17,44 +18,24 @@ namespace Encompass _componentManager = componentManager; } - protected IEnumerable ReadEntities() where TComponent : struct + protected Span ReadEntities() where TComponent : struct { - foreach (var pair in ReadComponentsIncludingEntity()) - { - yield return pair.Item2; - } + return _componentManager.GetExistingEntities(); } - protected Entity ReadEntity() where TComponent : struct + protected ref readonly Entity ReadEntity() where TComponent : struct { - return ReadComponentIncludingEntity().Item2; + return ref _componentManager.SingularEntity(); } - protected IEnumerable ReadComponents() where TComponent : struct + protected Span ReadComponents() where TComponent : struct { return _componentManager.GetComponentsByType(); } - protected IEnumerable<(TComponent, Entity)> ReadComponentsIncludingEntity() where TComponent : struct + protected ref readonly TComponent ReadComponent() where TComponent : struct { - foreach (var (component, id) in _componentManager.GetComponentsIncludingEntity()) - { - yield return (component, _entityManager.GetEntity(id)); - } - } - - protected TComponent ReadComponent() where TComponent : struct - { - var enumerator = ReadComponents().GetEnumerator(); - enumerator.MoveNext(); - return enumerator.Current; - } - - protected (TComponent, Entity) ReadComponentIncludingEntity() where TComponent : struct - { - var enumerator = ReadComponentsIncludingEntity().GetEnumerator(); - enumerator.MoveNext(); - return enumerator.Current; + return ref _componentManager.ExistingSingular(); } protected ref readonly TComponent GetComponent(Entity entity) where TComponent : struct diff --git a/encompass-cs/UberEngine.cs b/encompass-cs/UberEngine.cs index 48d64c4..d0957bf 100644 --- a/encompass-cs/UberEngine.cs +++ b/encompass-cs/UberEngine.cs @@ -35,22 +35,21 @@ namespace Encompass } } + // we can't reflect invoke on Span returns right now... tragic public override void Update(double dt) { foreach (var type in _componentTypes) { CallGenericMethod(type, "ReadComponent", null); - CallGenericMethod(type, "ReadComponentIncludingEntity", null); - CallGenericMethod(type, "ReadComponents", null); - CallGenericMethod(type, "ReadComponentsIncludingEntity", null); + //CallGenericMethod(type, "ReadComponents", null); CallGenericMethod(type, "ReadEntity", null); - CallGenericMethod(type, "ReadEntities", null); - CallGenericMethod(type, "GetComponent", new Type[] { typeof(Entity) }, new object[] { Entity }); - CallGenericMethod(type, "HasComponent", new Type[] { typeof(Entity) }, new object[] { Entity }); + //CallGenericMethod(type, "ReadEntities", null); + CallGenericMethod(type, "GetComponent", new object[] { Entity }); + CallGenericMethod(type, "HasComponent", 1, new object[] { Entity }); CallGenericMethod(type, "SomeComponent", null); CallGenericMethod(type, "DestroyWith", null); CallGenericMethod(type, "DestroyAllWith", null); - CallGenericMethod(type, "RemoveComponent", new Type[] { typeof(Entity) }, new object[] { Entity }); + CallGenericMethod(type, "RemoveComponent", new object[] { Entity }); } foreach (var type in _messageTypes) @@ -60,13 +59,13 @@ namespace Encompass CallGenericMethod(type, "SendMessage", 2, new object[] { Activator.CreateInstance(type), 1 }); CallGenericMethod(type, "ReadMessage", null); - CallGenericMethod(type, "ReadMessages", null); + //CallGenericMethod(type, "ReadMessages", null); CallGenericMethod(type, "SomeMessage", null); if (typeof(IHasEntity).IsAssignableFrom(type)) { - CallGenericMethod(type, "ReadMessagesWithEntity", new Type[] { typeof(Entity) }, new object[] { Entity }); - CallGenericMethod(type, "ReadMessageWithEntity", new Type[] { typeof(Entity) }, new object[] { Entity }); - CallGenericMethod(type, "SomeMessageWithEntity", new Type[] { typeof(Entity) }, new object[] { Entity }); + CallGenericMethod(type, "ReadMessagesWithEntity", new object[] { Entity }); + CallGenericMethod(type, "ReadMessageWithEntity", new object[] { Entity }); + CallGenericMethod(type, "SomeMessageWithEntity", new object[] { Entity }); } } } @@ -76,24 +75,24 @@ namespace Encompass { var readComponentMethod = typeof(Engine).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance); var genericReadComponentMethod = readComponentMethod.MakeGenericMethod(type); - //genericReadComponentMethod.Invoke(this, parameters); - RuntimeHelpers.PrepareMethod(genericReadComponentMethod.MethodHandle); + genericReadComponentMethod.Invoke(this, parameters); + // RuntimeHelpers.PrepareMethod(genericReadComponentMethod.MethodHandle); } private void CallGenericMethod(Type type, string methodName, Type[] types, object[] parameters) { var readComponentMethod = typeof(Engine).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance, null, types, null); var genericReadComponentMethod = readComponentMethod.MakeGenericMethod(type); - //genericReadComponentMethod.Invoke(this, parameters); - RuntimeHelpers.PrepareMethod(genericReadComponentMethod.MethodHandle); + genericReadComponentMethod.Invoke(this, parameters); + // RuntimeHelpers.PrepareMethod(genericReadComponentMethod.MethodHandle); } private void CallGenericMethod(Type type, string methodName, int argumentNum, object[] parameters) { var method = typeof(Engine).GetRuntimeMethods().Where(m => m.Name == methodName && m.GetParameters().Length == argumentNum).First(); var genericMethod = method.MakeGenericMethod(type); - //genericMethod.Invoke(this, parameters); - RuntimeHelpers.PrepareMethod(genericMethod.MethodHandle); + genericMethod.Invoke(this, parameters); + // RuntimeHelpers.PrepareMethod(genericMethod.MethodHandle); } } } diff --git a/encompass-cs/UberRenderer.cs b/encompass-cs/UberRenderer.cs index 870e999..f9cac44 100644 --- a/encompass-cs/UberRenderer.cs +++ b/encompass-cs/UberRenderer.cs @@ -19,16 +19,15 @@ namespace Encompass _entity = entity; } + // can't reflect invoke on Span returns... public void Render() { foreach (var type in _componentTypes) { - CallGenericMethod(type, "ReadEntities", null); + // CallGenericMethod(type, "ReadEntities", null); CallGenericMethod(type, "ReadEntity", null); + // CallGenericMethod(type, "ReadComponents", null); CallGenericMethod(type, "ReadComponent", null); - CallGenericMethod(type, "ReadComponentIncludingEntity", null); - CallGenericMethod(type, "ReadComponents", null); - CallGenericMethod(type, "ReadComponentsIncludingEntity", null); CallGenericMethod(type, "GetComponent", new object[] { _entity }); CallGenericMethod(type, "HasComponent", new object[] { _entity }); CallGenericMethod(type, "SomeComponent", null); diff --git a/test/ComponentTest.cs b/test/ComponentTest.cs index fadb126..62050f6 100644 --- a/test/ComponentTest.cs +++ b/test/ComponentTest.cs @@ -104,8 +104,9 @@ namespace Tests { public override void Update(double dt) { - foreach (var (mockComponent, entity) in ReadComponentsIncludingEntity()) + foreach (ref readonly var entity in ReadEntities()) { + ref readonly var mockComponent = ref GetComponent(entity); SetComponent(entity, new MockComponent { myInt = mockComponent.myInt + 1 }); } } @@ -150,8 +151,9 @@ namespace Tests { public override void Update(double dt) { - foreach (var (mockComponent, entity) in ReadComponentsIncludingEntity()) + foreach (ref readonly var entity in ReadEntities()) { + ref readonly var mockComponent = ref GetComponent(entity); SetComponent(entity, mockComponent); RemoveComponent(entity); } diff --git a/test/EngineTest.cs b/test/EngineTest.cs index 5c2d2d6..ebc5f29 100644 --- a/test/EngineTest.cs +++ b/test/EngineTest.cs @@ -17,7 +17,7 @@ namespace Tests public class EngineTest { - static List resultComponents; + static MockComponent[] resultComponents; static MockComponent resultComponent; static MockMessage[] resultMessages; @@ -27,11 +27,11 @@ namespace Tests { public override void Update(double dt) { - resultComponents = ReadComponents().ToList(); + resultComponents = ReadComponents().ToArray(); } } - static List<(MockComponent, Entity)> resultComponentsIncludingEntity; + static List<(MockComponent, Entity)> resultComponentsIncludingEntity = new List<(MockComponent, Entity)>(); static (MockComponent, Entity) resultComponentIncludingEntity; [Reads(typeof(MockComponent))] @@ -39,7 +39,11 @@ namespace Tests { public override void Update(double dt) { - resultComponentsIncludingEntity = ReadComponentsIncludingEntity().ToList(); + foreach (ref readonly var entity in ReadEntities()) + { + ref readonly var mockComponent = ref GetComponent(entity); + resultComponentsIncludingEntity.Add((mockComponent, entity)); + } } } @@ -57,7 +61,9 @@ namespace Tests { public override void Update(double dt) { - resultComponentIncludingEntity = ReadComponentIncludingEntity(); + ref readonly var entity = ref ReadEntity(); + ref readonly var mockComponent = ref GetComponent(entity); + resultComponentIncludingEntity = (mockComponent, entity); } } @@ -90,6 +96,8 @@ namespace Tests [Test] public void ReadComponentsIncludingEntity() { + resultComponentsIncludingEntity.Clear(); + var worldBuilder = new WorldBuilder(); worldBuilder.AddEngine(new ReadComponentsIncludingEntityEngine()); @@ -192,10 +200,8 @@ namespace Tests { public override void Update(double dt) { - var (component, entity) = ReadComponentIncludingEntity(); - - component.myInt = 420; - SetComponent(entity, component); + ref readonly var entity = ref ReadEntity(); + SetComponent(entity, new MockComponent { myInt = 420 }); } } @@ -229,12 +235,8 @@ namespace Tests { public override void Update(double dt) { - var (component, entity) = ReadComponentIncludingEntity(); - - component.myInt = 420; - SetComponent(entity, component); - - component = ReadComponent(); + ref readonly var entity = ref ReadEntity(); + SetComponent(entity, new MockComponent { myInt = 420 }); } } @@ -564,10 +566,10 @@ namespace Tests { public override void Update(double dt) { - var components = ReadComponentsIncludingEntity(); + var entities = ReadEntities(); - pairA = components.First(); - pairB = components.Last(); + pairA = (GetComponent(entities[0]), entities[0]); + pairB = (GetComponent(entities[1]), entities[1]); } } @@ -597,14 +599,12 @@ namespace Tests Assert.That(EngineTest.pairA.Item1, Is.EqualTo(EngineTest.pairB.Item1)); } - static IEnumerable<(MockComponent, Entity)> emptyComponentReadResult; - [Reads(typeof(MockComponent))] class ReadEmptyMockComponentsEngine : Engine { public override void Update(double dt) { - emptyComponentReadResult = ReadComponentsIncludingEntity(); + ReadEntities().ToArray().Should().BeEmpty(); } } @@ -616,8 +616,6 @@ namespace Tests var world = worldBuilder.Build(); world.Update(0.01f); - - Assert.That(emptyComponentReadResult, Is.Empty); } struct DestroyerComponent { } @@ -627,21 +625,27 @@ namespace Tests { public override void Update(double dt) { - foreach (var (component, entity) in ReadComponentsIncludingEntity()) + foreach (ref readonly var entity in ReadEntities()) { Destroy(entity); } } } - static List<(MockComponent, Entity)> results; + static List<(MockComponent, Entity)> results = new List<(MockComponent, Entity)>(); [Reads(typeof(MockComponent))] class ReaderEngine : Engine { public override void Update(double dt) { - results = ReadComponentsIncludingEntity().ToList(); + results.Clear(); + + foreach (ref readonly var entity in ReadEntities()) + { + ref readonly var mockComponent = ref GetComponent(entity); + results.Add((mockComponent, entity)); + } } } @@ -693,6 +697,8 @@ namespace Tests [Test] public void DestroyEntityWithoutID() { + results.Clear(); + var worldBuilder = new WorldBuilder(); worldBuilder.AddEngine(new AddComponentEngine()); worldBuilder.AddEngine(new DestroyEntityEngine()); @@ -716,7 +722,7 @@ namespace Tests { public override void Update(double dt) { - foreach (var (componentPair, entity) in ReadComponentsIncludingEntity()) + foreach (ref readonly var entity in ReadEntities()) { RemoveComponent(entity); Destroy(entity); @@ -748,7 +754,7 @@ namespace Tests { public override void Update(double dt) { - foreach (var (mockComponent, entity) in ReadComponentsIncludingEntity()) + foreach (ref readonly var entity in ReadEntities()) { RemoveComponent(entity); SetComponent(entity, new MockComponent()); @@ -763,7 +769,7 @@ namespace Tests { public override void Update(double dt) { - var (_, entity) = ReadComponentIncludingEntity(); + ref readonly var entity = ref ReadEntity(); } } @@ -788,7 +794,7 @@ namespace Tests { public override void Update(double dt) { - foreach (var (component, entity) in ReadComponentsIncludingEntity()) + foreach (ref readonly var entity in ReadEntities()) { RemoveComponent(entity); SendMessage(new MockMessage { }, 1); @@ -835,7 +841,7 @@ namespace Tests { public override void Update(double dt) { - foreach (var (component, entity) in ReadComponentsIncludingEntity()) + foreach (ref readonly var entity in ReadEntities()) { RemoveComponent(entity); SendMessageIgnoringTimeDilation(new MockMessage { }, 1); @@ -1117,7 +1123,7 @@ namespace Tests { public override void Update(double dt) { - foreach (var (_, entity) in ReadComponentsIncludingEntity()) + foreach (ref readonly var entity in ReadEntities()) { RemoveComponent(entity); } @@ -1312,8 +1318,7 @@ namespace Tests { public override void Update(double dt) { - var (component, entity) = ReadComponentIncludingEntity(); - + ref readonly var entity = ref ReadEntity(); AddComponent(entity, new MockComponent()); } } @@ -1347,8 +1352,7 @@ namespace Tests { public override void Update(double dt) { - var (component, entity) = ReadComponentIncludingEntity(); - + ref readonly var component = ref ReadComponent(); getComponentResult = component; } } @@ -1794,7 +1798,7 @@ namespace Tests } public override void Update(double dt) { - _components.AddRange(ReadComponents()); + _components.AddRange(ReadComponents().ToArray()); } } @@ -1830,12 +1834,11 @@ namespace Tests public override void Update(double dt) { - foreach (var (component, entity) in ReadComponentsIncludingEntity()) + foreach (ref readonly var entity in ReadEntities()) { if (HasComponent(entity)) { _components.Add(GetComponent(entity)); - } } } @@ -1862,7 +1865,7 @@ namespace Tests struct MockTimerComponent { - public double Timer { get; set; } + public double Timer { get; } public MockTimerComponent(double time) { @@ -1876,19 +1879,18 @@ namespace Tests { public override void Update(double dt) { - foreach (var (component, entity) in ReadComponentsIncludingEntity()) + foreach (ref readonly var entity in ReadEntities()) { - var updatedComponent = component; - updatedComponent.Timer -= dt; + ref readonly var component = ref GetComponent(entity); - if (updatedComponent.Timer <= 0) + if (component.Timer - dt <= 0) { RemoveComponent(entity); } else { - SetComponent(entity, updatedComponent); + SetComponent(entity, new MockTimerComponent(component.Timer - dt)); } } } diff --git a/test/GeneralRendererTest.cs b/test/GeneralRendererTest.cs index 9627d34..7ccc3ea 100644 --- a/test/GeneralRendererTest.cs +++ b/test/GeneralRendererTest.cs @@ -15,7 +15,8 @@ namespace Tests { public override void Render() { - result = ReadComponentIncludingEntity(); + ref readonly var entity = ref ReadEntity(); + result = (GetComponent(entity), entity); } } From 7c8154efdd9411d586e35ca67e7ac27dc92d6d8d Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Sun, 22 Mar 2020 19:20:55 -0700 Subject: [PATCH 26/30] fix some reads --- encompass-cs/ComponentManager.cs | 16 +++++++++++--- encompass-cs/Engine.cs | 38 +++++++++++++++++++++----------- encompass-cs/Renderer.cs | 2 +- 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/encompass-cs/ComponentManager.cs b/encompass-cs/ComponentManager.cs index 6aea1d0..49fe78d 100644 --- a/encompass-cs/ComponentManager.cs +++ b/encompass-cs/ComponentManager.cs @@ -113,6 +113,11 @@ namespace Encompass return _upToDateComponentStore.AllEntities(); } + internal ref readonly Entity ExistingOrImmediateSingularEntity() where TComponent : struct + { + return ref _upToDateComponentStore.SingularEntity(); + } + internal bool SomeExistingOrImmediateComponent() where TComponent : struct { return _upToDateComponentStore.Any(); @@ -135,7 +140,7 @@ namespace Encompass return _existingComponentStore.AllEntities(); } - internal ref readonly Entity SingularEntity() where TComponent : struct + internal ref readonly Entity ExistingSingularEntity() where TComponent : struct { return ref _existingComponentStore.SingularEntity(); } @@ -152,14 +157,19 @@ namespace Encompass return _immediateComponentStore.All(); } + internal ref readonly TComponent ImmediateSingular() where TComponent : struct + { + return ref _immediateComponentStore.Singular(); + } + internal Span GetImmediateEntities() where TComponent : struct { return _immediateComponentStore.AllEntities(); } - internal ref readonly TComponent ImmediateSingular() where TComponent : struct + internal ref readonly Entity ImmediateSingularEntity() where TComponent : struct { - return ref _immediateComponentStore.Singular(); + return ref _immediateComponentStore.SingularEntity(); } internal bool SomeImmediateComponent() where TComponent : struct diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index 5fb740b..6428abc 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -210,23 +210,10 @@ namespace Encompass return _entityManager.EntityExists(entityID); } - /// - /// Returns an Entity containing the specified Component type. - /// - protected ref readonly Entity ReadEntity() where TComponent : struct - { - return ref _componentManager.SingularEntity(); - } - /// /// Returns all Entities containing the specified Component type. /// protected Span ReadEntities() where TComponent : struct - { - return ReadEntitiesHelper(); - } - - private Span ReadEntitiesHelper() where TComponent : struct { var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent)); @@ -248,6 +235,31 @@ namespace Encompass } } + /// + /// Returns an Entity containing the specified Component type. + /// + protected ref readonly Entity ReadEntity() where TComponent : struct + { + var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); + var existingRead = ReadTypes.Contains(typeof(TComponent)); + if (existingRead && immediateRead) + { + return ref _componentManager.ExistingOrImmediateSingularEntity(); + } + else if (existingRead) + { + return ref _componentManager.ExistingSingularEntity(); + } + else if (immediateRead) + { + return ref _componentManager.ImmediateSingularEntity(); + } + else + { + throw new IllegalReadException("Engine {0} tried to read undeclared Component {1}", GetType().Name, typeof(TComponent).Name); + } + } + /// /// Returns all of the Components with the specified Component Type. /// diff --git a/encompass-cs/Renderer.cs b/encompass-cs/Renderer.cs index caad2f7..ccc8e59 100644 --- a/encompass-cs/Renderer.cs +++ b/encompass-cs/Renderer.cs @@ -25,7 +25,7 @@ namespace Encompass protected ref readonly Entity ReadEntity() where TComponent : struct { - return ref _componentManager.SingularEntity(); + return ref _componentManager.ExistingSingularEntity(); } protected Span ReadComponents() where TComponent : struct From 0df09163474c073147e4f7ceb6d5e5b10be97273 Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Tue, 24 Mar 2020 21:28:56 -0700 Subject: [PATCH 27/30] update JIT preload --- encompass-cs/Engine.cs | 28 +++++++------- encompass-cs/Interfaces/IComponent.cs | 4 ++ encompass-cs/Renderer.cs | 14 +++---- encompass-cs/Renderers/OrderedRenderer.cs | 2 +- encompass-cs/UberEngine.cs | 31 ++++++++++++++-- encompass-cs/WorldBuilder.cs | 45 +++++++++++++---------- test/ComponentTest.cs | 2 +- test/EngineTest.cs | 14 +++---- test/GeneralRendererTest.cs | 2 +- test/OrderedRendererTest.cs | 8 ++-- test/SpawnerTest.cs | 2 +- test/WorldBuilderTest.cs | 8 ++-- test/WorldTest.cs | 4 +- 13 files changed, 99 insertions(+), 65 deletions(-) create mode 100644 encompass-cs/Interfaces/IComponent.cs diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index 6428abc..2557b9f 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -213,7 +213,7 @@ namespace Encompass /// /// Returns all Entities containing the specified Component type. /// - protected Span ReadEntities() where TComponent : struct + protected Span ReadEntities() where TComponent : struct, IComponent { var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent)); @@ -238,7 +238,7 @@ namespace Encompass /// /// Returns an Entity containing the specified Component type. /// - protected ref readonly Entity ReadEntity() where TComponent : struct + protected ref readonly Entity ReadEntity() where TComponent : struct, IComponent { var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent)); @@ -263,7 +263,7 @@ namespace Encompass /// /// Returns all of the Components with the specified Component Type. /// - protected Span ReadComponents() where TComponent : struct + protected Span ReadComponents() where TComponent : struct, IComponent { var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent)); @@ -288,7 +288,7 @@ namespace Encompass /// /// Returns a Component with the specified Component Type. If multiples exist, an arbitrary Component is returned. /// - protected ref readonly TComponent ReadComponent() where TComponent : struct + protected ref readonly TComponent ReadComponent() where TComponent : struct, IComponent { var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent)); @@ -313,7 +313,7 @@ namespace Encompass /// /// Returns true if any Component with the specified Component Type exists. /// - protected bool SomeComponent() where TComponent : struct + protected bool SomeComponent() where TComponent : struct, IComponent { var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent)); @@ -335,7 +335,7 @@ namespace Encompass } } - private ref TComponent GetComponentHelper(int entityID) where TComponent : struct + private ref TComponent GetComponentHelper(int entityID) where TComponent : struct, IComponent { var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent)); @@ -366,7 +366,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that it reads the given Component Type. /// - protected ref readonly TComponent GetComponent(in Entity entity) where TComponent : struct + protected ref readonly TComponent GetComponent(in Entity entity) where TComponent : struct, IComponent { return ref GetComponentHelper(entity.ID); } @@ -380,7 +380,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that it reads the given Component Type. /// - protected ref TComponent GetComponentMutable(in Entity entity) where TComponent : struct + protected ref TComponent GetComponentMutable(in Entity entity) where TComponent : struct, IComponent { return ref GetComponentHelper(entity.ID); } @@ -391,7 +391,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that is Reads the given Component Type. /// - protected bool HasComponent(in Entity entity) where TComponent : struct + protected bool HasComponent(in Entity entity) where TComponent : struct, IComponent { var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent)); @@ -449,7 +449,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that it Writes the given Component Type. /// - protected void SetComponent(in Entity entity, in TComponent component) where TComponent : struct + protected void SetComponent(in Entity entity, in TComponent component) where TComponent : struct, IComponent { var priority = WritePriorities.ContainsKey(typeof(TComponent)) ? WritePriorities[typeof(TComponent)] : DefaultWritePriority; @@ -489,7 +489,7 @@ namespace Encompass /// /// Thrown when the Engine does not declare that it Writes the given Component Type. /// - protected void AddComponent(in Entity entity, in TComponent component) where TComponent : struct + protected void AddComponent(in Entity entity, in TComponent component) where TComponent : struct, IComponent { if (!EntityCreatedThisFrame(entity.ID)) { @@ -597,7 +597,7 @@ namespace Encompass /// Destroys an arbitrary Entity containing a Component of the specified Type. /// Entity destruction takes place after all the Engines have been processed by World Update. /// - protected void DestroyWith() where TComponent : struct + protected void DestroyWith() where TComponent : struct, IComponent { Destroy(ReadEntity()); } @@ -606,7 +606,7 @@ namespace Encompass /// Destroys all Entities containing a Component of the specified Type. /// Entity destruction takes place after all the Engines have been processed by World Update. /// - protected void DestroyAllWith() where TComponent : struct + protected void DestroyAllWith() where TComponent : struct, IComponent { foreach (var entity in ReadEntities()) { @@ -619,7 +619,7 @@ namespace Encompass /// Note that the Engine must Read the Component type that is being removed. /// If a Component with the specified type does not exist on the Entity, returns false and does not mutate the Entity. /// - protected void RemoveComponent(in Entity entity) where TComponent : struct + protected void RemoveComponent(in Entity entity) where TComponent : struct, IComponent { var priority = WritePriorities.ContainsKey(typeof(TComponent)) ? WritePriorities[typeof(TComponent)] : DefaultWritePriority; diff --git a/encompass-cs/Interfaces/IComponent.cs b/encompass-cs/Interfaces/IComponent.cs new file mode 100644 index 0000000..d51b93c --- /dev/null +++ b/encompass-cs/Interfaces/IComponent.cs @@ -0,0 +1,4 @@ +namespace Encompass +{ + public interface IComponent { } +} diff --git a/encompass-cs/Renderer.cs b/encompass-cs/Renderer.cs index ccc8e59..85b5489 100644 --- a/encompass-cs/Renderer.cs +++ b/encompass-cs/Renderer.cs @@ -18,37 +18,37 @@ namespace Encompass _componentManager = componentManager; } - protected Span ReadEntities() where TComponent : struct + protected Span ReadEntities() where TComponent : struct, IComponent { return _componentManager.GetExistingEntities(); } - protected ref readonly Entity ReadEntity() where TComponent : struct + protected ref readonly Entity ReadEntity() where TComponent : struct, IComponent { return ref _componentManager.ExistingSingularEntity(); } - protected Span ReadComponents() where TComponent : struct + protected Span ReadComponents() where TComponent : struct, IComponent { return _componentManager.GetComponentsByType(); } - protected ref readonly TComponent ReadComponent() where TComponent : struct + protected ref readonly TComponent ReadComponent() where TComponent : struct, IComponent { return ref _componentManager.ExistingSingular(); } - protected ref readonly TComponent GetComponent(Entity entity) where TComponent : struct + protected ref readonly TComponent GetComponent(Entity entity) where TComponent : struct, IComponent { return ref _componentManager.GetComponentByEntityAndType(entity.ID); } - protected bool HasComponent(Entity entity) where TComponent : struct + protected bool HasComponent(Entity entity) where TComponent : struct, IComponent { return _componentManager.EntityHasComponentOfType(entity.ID); } - protected bool SomeComponent() where TComponent : struct + protected bool SomeComponent() where TComponent : struct, IComponent { return _componentManager.SomeExistingComponent(); } diff --git a/encompass-cs/Renderers/OrderedRenderer.cs b/encompass-cs/Renderers/OrderedRenderer.cs index 56935f2..5b462b3 100644 --- a/encompass-cs/Renderers/OrderedRenderer.cs +++ b/encompass-cs/Renderers/OrderedRenderer.cs @@ -5,7 +5,7 @@ namespace Encompass /// /// OrdereredRenderer provides a structure for the common pattern of wishing to draw a specific DrawComponent at a specific layer. /// - public abstract class OrderedRenderer : Renderer where TComponent : struct, IDrawableComponent + public abstract class OrderedRenderer : Renderer where TComponent : struct, IComponent, IDrawableComponent { public abstract void Render(Entity entity, in TComponent drawComponent); diff --git a/encompass-cs/UberEngine.cs b/encompass-cs/UberEngine.cs index d0957bf..5d5378e 100644 --- a/encompass-cs/UberEngine.cs +++ b/encompass-cs/UberEngine.cs @@ -35,15 +35,14 @@ namespace Encompass } } - // we can't reflect invoke on Span returns right now... tragic public override void Update(double dt) { foreach (var type in _componentTypes) { CallGenericMethod(type, "ReadComponent", null); - //CallGenericMethod(type, "ReadComponents", null); + CallGenericWrappedMethod(type, "ReadComponentsWrapper", null); CallGenericMethod(type, "ReadEntity", null); - //CallGenericMethod(type, "ReadEntities", null); + CallGenericWrappedMethod(type, "ReadEntitiesWrapper", null); CallGenericMethod(type, "GetComponent", new object[] { Entity }); CallGenericMethod(type, "HasComponent", 1, new object[] { Entity }); CallGenericMethod(type, "SomeComponent", null); @@ -59,7 +58,7 @@ namespace Encompass CallGenericMethod(type, "SendMessage", 2, new object[] { Activator.CreateInstance(type), 1 }); CallGenericMethod(type, "ReadMessage", null); - //CallGenericMethod(type, "ReadMessages", null); + CallGenericWrappedMethod(type, "ReadMessagesWrapper", null); CallGenericMethod(type, "SomeMessage", null); if (typeof(IHasEntity).IsAssignableFrom(type)) { @@ -70,6 +69,23 @@ namespace Encompass } } + // we can't reflect invoke on Span returns right now... so we have non-return wrapper methods + + protected void ReadComponentsWrapper() where TComponent : struct, IComponent + { + ReadComponents(); + } + + protected void ReadMessagesWrapper() where TMessage : struct, IMessage + { + ReadMessages(); + } + + protected void ReadEntitiesWrapper() where TComponent : struct, IComponent + { + ReadEntities(); + } + // trying to use PrepareMethod because we can't reflect invoke methods that return a span... private void CallGenericMethod(Type type, string methodName, object[] parameters) { @@ -79,6 +95,13 @@ namespace Encompass // RuntimeHelpers.PrepareMethod(genericReadComponentMethod.MethodHandle); } + private void CallGenericWrappedMethod(Type type, string methodName, object[] parameters) + { + var readComponentMethod = typeof(UberEngine).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance); + var genericReadComponentMethod = readComponentMethod.MakeGenericMethod(type); + genericReadComponentMethod.Invoke(this, parameters); + } + private void CallGenericMethod(Type type, string methodName, Type[] types, object[] parameters) { var readComponentMethod = typeof(Engine).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance, null, types, null); diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs index 5da3d3a..9295844 100644 --- a/encompass-cs/WorldBuilder.cs +++ b/encompass-cs/WorldBuilder.cs @@ -183,7 +183,7 @@ namespace Encompass /// /// Adds the specified OrderedRenderer to the World. /// - public OrderedRenderer AddOrderedRenderer(OrderedRenderer renderer) where TComponent : struct, IDrawableComponent + public OrderedRenderer AddOrderedRenderer(OrderedRenderer renderer) where TComponent : struct, IComponent, IDrawableComponent { RegisterComponentType(); renderer.AssignEntityManager(_entityManager); @@ -354,7 +354,7 @@ namespace Encompass throw new EngineWriteConflictException(errorString); } - PreloadJIT(_componentTypesToPreload, _messageTypes); + PreloadJIT(_messageTypes); var engineOrder = new List(); @@ -388,7 +388,7 @@ namespace Encompass /// It does so by grabbing all component and message types known to the WorldBuilder and /// executing every possible generic method that could be executed with those types. /// - private void PreloadJIT(IEnumerable componentTypes, IEnumerable messageTypes) + private void PreloadJIT(IEnumerable messageTypes) { var dummyTimeManager = new TimeManager(); var dummyMessageManager = new MessageManager(dummyTimeManager); @@ -398,9 +398,30 @@ namespace Encompass var dummyEntityManager = new EntityManager(dummyComponentManager, _entityCapacity); var dummyRenderManager = new RenderManager(dummyEntityManager, dummyDrawLayerManager); + // doing reflection to grab all component types, because not all writes need to be declared + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + foreach (var componentType in assembly.GetTypes()) + { + if (typeof(IComponent).IsAssignableFrom(componentType) && componentType.IsValueType && !componentType.IsEnum && !componentType.IsPrimitive) + { + var method = typeof(WorldBuilder).GetMethod("RegisterComponentType", BindingFlags.NonPublic | BindingFlags.Instance); + var generic = method.MakeGenericMethod(componentType); + generic.Invoke(this, null); + } + + if (componentType.GetInterface("IDrawableComponent") != null) + { + var drawLayerManagerRegisterMethod = typeof(DrawLayerManager).GetMethod("RegisterOrderedDrawable"); + var drawLayerManagerRegisterGenericMethod = drawLayerManagerRegisterMethod.MakeGenericMethod(componentType); + drawLayerManagerRegisterGenericMethod.Invoke(dummyDrawLayerManager, null); + } + } + } + var prepEngineOrder = new List(); - var uberEngine = new UberEngine(componentTypes, messageTypes); + var uberEngine = new UberEngine(_componentTypesToPreload, messageTypes); uberEngine.AssignEntityManager(dummyEntityManager); uberEngine.AssignComponentManager(dummyComponentManager); @@ -408,24 +429,10 @@ namespace Encompass uberEngine.AssignTimeManager(dummyTimeManager); uberEngine.AssignTrackingManager(dummyTrackingManager); - var uberRenderer = new UberRenderer(componentTypes); + var uberRenderer = new UberRenderer(_componentTypesToPreload); uberRenderer.AssignComponentManager(dummyComponentManager); uberRenderer.AssignEntityManager(dummyEntityManager); - foreach (var type in componentTypes) - { - var componentManagerRegisterMethod = typeof(ComponentManager).GetMethod("RegisterComponentType"); - var componentManagerRegisterGenericMethod = componentManagerRegisterMethod.MakeGenericMethod(type); - componentManagerRegisterGenericMethod.Invoke(dummyComponentManager, null); - - if (type.GetInterface("IDrawableComponent") != null) - { - var drawLayerManagerRegisterMethod = typeof(DrawLayerManager).GetMethod("RegisterOrderedDrawable"); - var drawLayerManagerRegisterGenericMethod = drawLayerManagerRegisterMethod.MakeGenericMethod(type); - drawLayerManagerRegisterGenericMethod.Invoke(dummyDrawLayerManager, null); - } - } - prepEngineOrder.Add(uberEngine); var dummyWorld = new World( diff --git a/test/ComponentTest.cs b/test/ComponentTest.cs index 62050f6..9c6e2e7 100644 --- a/test/ComponentTest.cs +++ b/test/ComponentTest.cs @@ -8,7 +8,7 @@ namespace Tests { public class ComponentTests { - struct MockComponent + struct MockComponent : IComponent { public int myInt; } diff --git a/test/EngineTest.cs b/test/EngineTest.cs index ebc5f29..c5621fe 100644 --- a/test/EngineTest.cs +++ b/test/EngineTest.cs @@ -10,7 +10,7 @@ using Encompass.Exceptions; namespace Tests { - struct MockComponent + struct MockComponent : IComponent { public int myInt; } @@ -618,7 +618,7 @@ namespace Tests world.Update(0.01f); } - struct DestroyerComponent { } + struct DestroyerComponent : IComponent { } [Reads(typeof(DestroyerComponent))] class DestroyerEngine : Engine @@ -964,7 +964,7 @@ namespace Tests entity.Should().BeEquivalentTo(readEntity); } - struct MockComponentB + struct MockComponentB : IComponent { private int value; @@ -1407,9 +1407,9 @@ namespace Tests public class QueryTests { - struct MockComponentB { } - struct MockComponentC { } - struct MockComponentD { } + struct MockComponentB : IComponent { } + struct MockComponentC : IComponent { } + struct MockComponentD : IComponent { } [Reads(typeof(MockComponent), typeof(MockComponentB))] [Writes(typeof(MockComponentB))] @@ -1863,7 +1863,7 @@ namespace Tests _components.Should().NotBeEmpty(); } - struct MockTimerComponent + struct MockTimerComponent : IComponent { public double Timer { get; } diff --git a/test/GeneralRendererTest.cs b/test/GeneralRendererTest.cs index 7ccc3ea..32659c0 100644 --- a/test/GeneralRendererTest.cs +++ b/test/GeneralRendererTest.cs @@ -5,7 +5,7 @@ namespace Tests { public static class GeneralRendererTest { - struct AComponent { } + struct AComponent : IComponent { } public class SingletonRead { diff --git a/test/OrderedRendererTest.cs b/test/OrderedRendererTest.cs index 2ee2af7..92cb3b8 100644 --- a/test/OrderedRendererTest.cs +++ b/test/OrderedRendererTest.cs @@ -9,11 +9,11 @@ namespace Tests { public class OrderedRendererTest { - struct AComponent { } - struct BComponent { } - struct CComponent { } + struct AComponent : IComponent { } + struct BComponent : IComponent { } + struct CComponent : IComponent { } - struct TestDrawComponent : IDrawableComponent + struct TestDrawComponent : IComponent, IDrawableComponent { public int Layer { get; set; } } diff --git a/test/SpawnerTest.cs b/test/SpawnerTest.cs index e31ed37..c0c5f0c 100644 --- a/test/SpawnerTest.cs +++ b/test/SpawnerTest.cs @@ -5,7 +5,7 @@ namespace Tests { public class SpawnerTest { - struct TestComponent { } + struct TestComponent : IComponent { } struct SpawnMessageA : IMessage { } static Entity resultEntity; diff --git a/test/WorldBuilderTest.cs b/test/WorldBuilderTest.cs index 871dce4..2f3e7d2 100644 --- a/test/WorldBuilderTest.cs +++ b/test/WorldBuilderTest.cs @@ -147,7 +147,7 @@ namespace Tests public Entity entity; } - struct AComponent + struct AComponent : IComponent { public int myInt; } @@ -216,7 +216,7 @@ namespace Tests public Entity entity; } - struct AComponent + struct AComponent : IComponent { public int myInt; } @@ -407,8 +407,8 @@ namespace Tests { static List order = new List(); - struct AComponent { } - struct BComponent { } + struct AComponent : IComponent { } + struct BComponent : IComponent { } struct AMessage : IMessage { } struct BMessage : IMessage { } diff --git a/test/WorldTest.cs b/test/WorldTest.cs index f985dc1..6ce089b 100644 --- a/test/WorldTest.cs +++ b/test/WorldTest.cs @@ -11,8 +11,8 @@ namespace Tests { public class WorldTest { - struct TestComponent { } - struct TestDrawComponent : IDrawableComponent + struct TestComponent : IComponent { } + struct TestDrawComponent : IComponent, IDrawableComponent { public int Layer { get; set; } } From 20d382f51a680db6d8033220d4abe67df4567ecf Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Tue, 24 Mar 2020 22:19:24 -0700 Subject: [PATCH 28/30] JIT Renderer methods --- encompass-cs/UberRenderer.cs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/encompass-cs/UberRenderer.cs b/encompass-cs/UberRenderer.cs index f9cac44..9d96e2c 100644 --- a/encompass-cs/UberRenderer.cs +++ b/encompass-cs/UberRenderer.cs @@ -24,9 +24,9 @@ namespace Encompass { foreach (var type in _componentTypes) { - // CallGenericMethod(type, "ReadEntities", null); + CallGenericWrappedMethod(type, "ReadEntitiesWrapper", null); CallGenericMethod(type, "ReadEntity", null); - // CallGenericMethod(type, "ReadComponents", null); + CallGenericWrappedMethod(type, "ReadComponentsWrapper", null); CallGenericMethod(type, "ReadComponent", null); CallGenericMethod(type, "GetComponent", new object[] { _entity }); CallGenericMethod(type, "HasComponent", new object[] { _entity }); @@ -34,11 +34,28 @@ namespace Encompass } } + protected void ReadEntitiesWrapper() where TComponent : struct, IComponent + { + ReadEntities(); + } + + protected void ReadComponentsWrapper() where TComponent : struct, IComponent + { + ReadComponents(); + } + private void CallGenericMethod(Type type, string methodName, object[] parameters) { var readComponentMethod = typeof(Renderer).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance); var genericReadComponentMethod = readComponentMethod.MakeGenericMethod(type); genericReadComponentMethod.Invoke(this, parameters); } + + private void CallGenericWrappedMethod(Type type, string methodName, object[] parameters) + { + var readComponentMethod = typeof(UberRenderer).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance); + var genericReadComponentMethod = readComponentMethod.MakeGenericMethod(type); + genericReadComponentMethod.Invoke(this, parameters); + } } } From df4a953628332e89a5edd82b936a9d3c7c0309cb Mon Sep 17 00:00:00 2001 From: Evan Hemsley <2342303+ehemsley@users.noreply.github.com> Date: Wed, 25 Mar 2020 11:52:42 -0700 Subject: [PATCH 29/30] remove unnecessary lookup checks --- encompass-cs/Collections/ComponentStore.cs | 3 +-- encompass-cs/WorldBuilder.cs | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/encompass-cs/Collections/ComponentStore.cs b/encompass-cs/Collections/ComponentStore.cs index fc20a17..3f35b4b 100644 --- a/encompass-cs/Collections/ComponentStore.cs +++ b/encompass-cs/Collections/ComponentStore.cs @@ -29,7 +29,6 @@ namespace Encompass private TypedComponentStore Lookup() where TComponent : struct { - RegisterComponentType(); return _stores[typeof(TComponent)] as TypedComponentStore; } @@ -40,7 +39,7 @@ namespace Encompass public bool Has(Type type, int entityID) { - return _stores.ContainsKey(type) && _stores[type].Has(entityID); + return _stores[type].Has(entityID); } public BitSet512 EntityBitArray(int entityID) diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs index 9295844..dbcebcd 100644 --- a/encompass-cs/WorldBuilder.cs +++ b/encompass-cs/WorldBuilder.cs @@ -408,6 +408,10 @@ namespace Encompass var method = typeof(WorldBuilder).GetMethod("RegisterComponentType", BindingFlags.NonPublic | BindingFlags.Instance); var generic = method.MakeGenericMethod(componentType); generic.Invoke(this, null); + + var dummyRegisterMethod = typeof(ComponentManager).GetMethod("RegisterComponentType", BindingFlags.Public | BindingFlags.Instance); + var dummyGeneric = dummyRegisterMethod.MakeGenericMethod(componentType); + dummyGeneric.Invoke(dummyComponentManager, null); } if (componentType.GetInterface("IDrawableComponent") != null) From 18fd4ceaa6e2799e85e08440e14eba13167b7089 Mon Sep 17 00:00:00 2001 From: Evan Hemsley <2342303+ehemsley@users.noreply.github.com> Date: Wed, 25 Mar 2020 11:56:56 -0700 Subject: [PATCH 30/30] remove mutable get --- encompass-cs/Engine.cs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index 2557b9f..36d0ccd 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -371,20 +371,6 @@ namespace Encompass return ref GetComponentHelper(entity.ID); } - /// - /// Returns a Component by reference with the specified Type that exists on the Entity. - /// - /// - /// Thrown when the Entity does not have a Component of the specified Type - /// - /// - /// Thrown when the Engine does not declare that it reads the given Component Type. - /// - protected ref TComponent GetComponentMutable(in Entity entity) where TComponent : struct, IComponent - { - return ref GetComponentHelper(entity.ID); - } - /// /// Returns true if the Entity has a Component of the given Type. ///