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