From 37d10db95527f22b721ce7bf6c3207a00deae84a Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Thu, 7 Apr 2022 22:52:03 -0700 Subject: [PATCH] remove implicit usings --- MoonTools.ECS.csproj | 1 - src/ComponentDepot.cs | 408 ++++++++++++++++++----------------- src/ComponentStorage.cs | 164 +++++++------- src/DebugSystem.cs | 5 +- src/Entity.cs | 39 ++-- src/EntityComponentReader.cs | 126 +++++------ src/EntityStorage.cs | 31 +-- src/Filter.cs | 34 +-- src/FilterBuilder.cs | 68 +++--- src/FilterSignature.cs | 72 ++++--- src/IDStorage.cs | 55 ++--- src/IHasEntity.cs | 9 +- src/IndexableSet.cs | 2 + src/MessageDepot.cs | 102 ++++----- src/MessageStorage.cs | 136 ++++++------ src/Random.cs | 3 + src/Relation.cs | 2 + src/RelationDepot.cs | 3 + src/RelationStorage.cs | 2 + src/Renderer.cs | 11 +- src/System.cs | 150 ++++++------- src/World.cs | 79 +++---- 22 files changed, 781 insertions(+), 721 deletions(-) diff --git a/MoonTools.ECS.csproj b/MoonTools.ECS.csproj index bafd05b..b9251e9 100644 --- a/MoonTools.ECS.csproj +++ b/MoonTools.ECS.csproj @@ -2,7 +2,6 @@ net6.0 - enable enable diff --git a/src/ComponentDepot.cs b/src/ComponentDepot.cs index dae13fb..38eaef6 100644 --- a/src/ComponentDepot.cs +++ b/src/ComponentDepot.cs @@ -1,259 +1,263 @@ -namespace MoonTools.ECS; +using System; +using System.Collections.Generic; -internal class ComponentDepot +namespace MoonTools.ECS { - private Dictionary storages = new Dictionary(); - - private Dictionary> filterSignatureToEntityIDs = new Dictionary>(); - - private Dictionary> typeToFilterSignatures = new Dictionary>(); - - private Dictionary> entityComponentMap = new Dictionary>(); - - #if DEBUG - private Dictionary singleComponentFilters = new Dictionary(); - #endif - - internal void Register() where TComponent : struct + internal class ComponentDepot { - if (!storages.ContainsKey(typeof(TComponent))) + private Dictionary storages = new Dictionary(); + + private Dictionary> filterSignatureToEntityIDs = new Dictionary>(); + + private Dictionary> typeToFilterSignatures = new Dictionary>(); + + private Dictionary> entityComponentMap = new Dictionary>(); + +#if DEBUG + private Dictionary singleComponentFilters = new Dictionary(); +#endif + + internal void Register() where TComponent : struct { - storages.Add(typeof(TComponent), new ComponentStorage()); - #if DEBUG - singleComponentFilters.Add(typeof(TComponent), CreateFilter(new HashSet() { typeof(TComponent) }, new HashSet())); - #endif - } - } - - private ComponentStorage Lookup(Type type) - { - return storages[type]; - } - - private ComponentStorage Lookup() where TComponent : struct - { - // TODO: is it possible to optimize this? - Register(); - return storages[typeof(TComponent)] as ComponentStorage; - } - - public bool Some() where TComponent : struct - { - return Lookup().Any(); - } - - public bool Has(int entityID) where TComponent : struct - { - return Lookup().Has(entityID); - } - - private bool Has(Type type, int entityID) - { - return Lookup(type).Has(entityID); - } - - public ref readonly TComponent Get(int entityID) where TComponent : struct - { - return ref Lookup().Get(entityID); - } - - public ref readonly TComponent Get() where TComponent : struct - { - return ref Lookup().Get(); - } - - public void Set(int entityID, in TComponent component) where TComponent : struct - { - Lookup().Set(entityID, component); - - if (!entityComponentMap.ContainsKey(entityID)) - { - entityComponentMap.Add(entityID, new HashSet()); - } - - var notFound = entityComponentMap[entityID].Add(typeof(TComponent)); - - // update filters - if (notFound) - { - if (typeToFilterSignatures.TryGetValue(typeof(TComponent), out var filterSignatures)) + if (!storages.ContainsKey(typeof(TComponent))) { - foreach (var filterSignature in filterSignatures) + storages.Add(typeof(TComponent), new ComponentStorage()); +#if DEBUG + singleComponentFilters.Add(typeof(TComponent), CreateFilter(new HashSet() { typeof(TComponent) }, new HashSet())); +#endif + } + } + + private ComponentStorage Lookup(Type type) + { + return storages[type]; + } + + private ComponentStorage Lookup() where TComponent : struct + { + // TODO: is it possible to optimize this? + Register(); + return storages[typeof(TComponent)] as ComponentStorage; + } + + public bool Some() where TComponent : struct + { + return Lookup().Any(); + } + + public bool Has(int entityID) where TComponent : struct + { + return Lookup().Has(entityID); + } + + private bool Has(Type type, int entityID) + { + return Lookup(type).Has(entityID); + } + + public ref readonly TComponent Get(int entityID) where TComponent : struct + { + return ref Lookup().Get(entityID); + } + + public ref readonly TComponent Get() where TComponent : struct + { + return ref Lookup().Get(); + } + + public void Set(int entityID, in TComponent component) where TComponent : struct + { + Lookup().Set(entityID, component); + + if (!entityComponentMap.ContainsKey(entityID)) + { + entityComponentMap.Add(entityID, new HashSet()); + } + + var notFound = entityComponentMap[entityID].Add(typeof(TComponent)); + + // update filters + if (notFound) + { + if (typeToFilterSignatures.TryGetValue(typeof(TComponent), out var filterSignatures)) { - CheckFilter(filterSignature, entityID); + foreach (var filterSignature in filterSignatures) + { + CheckFilter(filterSignature, entityID); + } } } } - } - public Entity GetSingletonEntity() where TComponent : struct - { - return Lookup().FirstEntity(); - } - - public ReadOnlySpan ReadComponents() where TComponent : struct - { - return Lookup().AllComponents(); - } - - private void Remove(Type type, int entityID) - { - Lookup(type).Remove(entityID); - - var found = entityComponentMap[entityID].Remove(type); - - // update filters - if (found) + public Entity GetSingletonEntity() where TComponent : struct { - if (typeToFilterSignatures.TryGetValue(type, out var filterSignatures)) + return Lookup().FirstEntity(); + } + + public ReadOnlySpan ReadComponents() where TComponent : struct + { + return Lookup().AllComponents(); + } + + private void Remove(Type type, int entityID) + { + Lookup(type).Remove(entityID); + + var found = entityComponentMap[entityID].Remove(type); + + // update filters + if (found) { - foreach (var filterSignature in filterSignatures) + if (typeToFilterSignatures.TryGetValue(type, out var filterSignatures)) { - CheckFilter(filterSignature, entityID); + foreach (var filterSignature in filterSignatures) + { + CheckFilter(filterSignature, entityID); + } } } } - } - public void Remove(int entityID) where TComponent : struct - { - Lookup().Remove(entityID); - - var found = entityComponentMap[entityID].Remove(typeof(TComponent)); - - // update filters - if (found) + public void Remove(int entityID) where TComponent : struct { - if (typeToFilterSignatures.TryGetValue(typeof(TComponent), out var filterSignatures)) + Lookup().Remove(entityID); + + var found = entityComponentMap[entityID].Remove(typeof(TComponent)); + + // update filters + if (found) { - foreach (var filterSignature in filterSignatures) + if (typeToFilterSignatures.TryGetValue(typeof(TComponent), out var filterSignatures)) { - CheckFilter(filterSignature, entityID); + foreach (var filterSignature in filterSignatures) + { + CheckFilter(filterSignature, entityID); + } } } } - } - public void OnEntityDestroy(int entityID) - { - if (entityComponentMap.ContainsKey(entityID)) + public void OnEntityDestroy(int entityID) { - foreach (var type in entityComponentMap[entityID]) + if (entityComponentMap.ContainsKey(entityID)) { - Remove(type, entityID); - } - - entityComponentMap.Remove(entityID); - } - } - - public Filter CreateFilter(HashSet included, HashSet excluded) - { - var filterSignature = new FilterSignature(included, excluded); - if (!filterSignatureToEntityIDs.ContainsKey(filterSignature)) - { - filterSignatureToEntityIDs.Add(filterSignature, new IndexableSet()); - - foreach (var type in included) - { - if (!typeToFilterSignatures.ContainsKey(type)) + foreach (var type in entityComponentMap[entityID]) { - typeToFilterSignatures.Add(type, new HashSet()); + Remove(type, entityID); } - typeToFilterSignatures[type].Add(filterSignature); + entityComponentMap.Remove(entityID); } + } - foreach (var type in excluded) + public Filter CreateFilter(HashSet included, HashSet excluded) + { + var filterSignature = new FilterSignature(included, excluded); + if (!filterSignatureToEntityIDs.ContainsKey(filterSignature)) { - if (!typeToFilterSignatures.ContainsKey(type)) + filterSignatureToEntityIDs.Add(filterSignature, new IndexableSet()); + + foreach (var type in included) { - typeToFilterSignatures.Add(type, new HashSet()); + if (!typeToFilterSignatures.ContainsKey(type)) + { + typeToFilterSignatures.Add(type, new HashSet()); + } + + typeToFilterSignatures[type].Add(filterSignature); } - typeToFilterSignatures[type].Add(filterSignature); + foreach (var type in excluded) + { + if (!typeToFilterSignatures.ContainsKey(type)) + { + typeToFilterSignatures.Add(type, new HashSet()); + } + + typeToFilterSignatures[type].Add(filterSignature); + } } + return new Filter(this, included, excluded); } - return new Filter(this, included, excluded); - } - // FIXME: this dictionary should probably just store entities - public IEnumerable FilterEntities(Filter filter) - { - foreach (var id in filterSignatureToEntityIDs[filter.Signature]) + // FIXME: this dictionary should probably just store entities + public IEnumerable FilterEntities(Filter filter) { - yield return new Entity(id); - } - } - - public IEnumerable FilterEntitiesRandom(Filter filter) - { - foreach (var index in RandomGenerator.LinearCongruentialGenerator(FilterCount(filter))) - { - yield return new Entity(filterSignatureToEntityIDs[filter.Signature][index]); - } - } - - public Entity FilterRandomEntity(Filter filter) - { - var randomIndex = RandomGenerator.Next(FilterCount(filter)); - return new Entity(filterSignatureToEntityIDs[filter.Signature][randomIndex]); - } - - public int FilterCount(Filter filter) - { - return filterSignatureToEntityIDs[filter.Signature].Count; - } - - private void CheckFilter(FilterSignature filterSignature, int entityID) - { - foreach (var type in filterSignature.Included) - { - if (!Has(type, entityID)) + foreach (var id in filterSignatureToEntityIDs[filter.Signature]) { - filterSignatureToEntityIDs[filterSignature].Remove(entityID); - return; + yield return new Entity(id); } } - foreach (var type in filterSignature.Excluded) + public IEnumerable FilterEntitiesRandom(Filter filter) { - if (Has(type, entityID)) + foreach (var index in RandomGenerator.LinearCongruentialGenerator(FilterCount(filter))) { - filterSignatureToEntityIDs[filterSignature].Remove(entityID); - return; + yield return new Entity(filterSignatureToEntityIDs[filter.Signature][index]); } } - filterSignatureToEntityIDs[filterSignature].Add(entityID); - } - - #if DEBUG - public IEnumerable Debug_GetAllComponents(int entityID) - { - foreach (var (type, storage) in storages) + public Entity FilterRandomEntity(Filter filter) { - if (storage.Has(entityID)) - { - yield return storage.Debug_Get(entityID); - } + var randomIndex = RandomGenerator.Next(FilterCount(filter)); + return new Entity(filterSignatureToEntityIDs[filter.Signature][randomIndex]); } - } - public IEnumerable Debug_GetEntities(Type componentType) - { - return singleComponentFilters[componentType].Entities; - } - - public IEnumerable Debug_SearchComponentType(string typeString) - { - foreach (var type in storages.Keys) + public int FilterCount(Filter filter) { - if (type.ToString().ToLower().Contains(typeString.ToLower())) + return filterSignatureToEntityIDs[filter.Signature].Count; + } + + private void CheckFilter(FilterSignature filterSignature, int entityID) + { + foreach (var type in filterSignature.Included) { - yield return type; + if (!Has(type, entityID)) + { + filterSignatureToEntityIDs[filterSignature].Remove(entityID); + return; + } + } + + foreach (var type in filterSignature.Excluded) + { + if (Has(type, entityID)) + { + filterSignatureToEntityIDs[filterSignature].Remove(entityID); + return; + } + } + + filterSignatureToEntityIDs[filterSignature].Add(entityID); + } + +#if DEBUG + public IEnumerable Debug_GetAllComponents(int entityID) + { + foreach (var (type, storage) in storages) + { + if (storage.Has(entityID)) + { + yield return storage.Debug_Get(entityID); + } } } + + public IEnumerable Debug_GetEntities(Type componentType) + { + return singleComponentFilters[componentType].Entities; + } + + public IEnumerable Debug_SearchComponentType(string typeString) + { + foreach (var type in storages.Keys) + { + if (type.ToString().ToLower().Contains(typeString.ToLower())) + { + yield return type; + } + } + } +#endif } - #endif } diff --git a/src/ComponentStorage.cs b/src/ComponentStorage.cs index a777494..15a5db2 100644 --- a/src/ComponentStorage.cs +++ b/src/ComponentStorage.cs @@ -1,106 +1,110 @@ -namespace MoonTools.ECS; +using System; +using System.Collections.Generic; -internal abstract class ComponentStorage +namespace MoonTools.ECS { - public abstract bool Has(int entityID); - public abstract void Remove(int entityID); - public abstract object Debug_Get(int entityID); -} - -// FIXME: we can probably get rid of this weird entity storage system by using filters -internal class ComponentStorage : ComponentStorage where TComponent : struct -{ - private int nextID; - private readonly Dictionary entityIDToStorageIndex = new Dictionary(16); - private int[] entityIDs = new int[16]; - private TComponent[] components = new TComponent[16]; - - public bool Any() + internal abstract class ComponentStorage { - return nextID > 0; + public abstract bool Has(int entityID); + public abstract void Remove(int entityID); + public abstract object Debug_Get(int entityID); } - public override bool Has(int entityID) + // FIXME: we can probably get rid of this weird entity storage system by using filters + internal class ComponentStorage : ComponentStorage where TComponent : struct { - return entityIDToStorageIndex.ContainsKey(entityID); - } + private int nextID; + private readonly Dictionary entityIDToStorageIndex = new Dictionary(16); + private int[] entityIDs = new int[16]; + private TComponent[] components = new TComponent[16]; - public ref readonly TComponent Get(int entityID) - { - return ref components[entityIDToStorageIndex[entityID]]; - } - - public override object Debug_Get(int entityID) - { - return components[entityIDToStorageIndex[entityID]]; - } - - public ref readonly TComponent Get() - { - #if DEBUG - if (nextID == 0) + public bool Any() { - throw new ArgumentOutOfRangeException("Component storage is empty!"); + return nextID > 0; } - #endif - return ref components[0]; - } - public void Set(int entityID, in TComponent component) - { - if (!entityIDToStorageIndex.ContainsKey(entityID)) + public override bool Has(int entityID) { - var index = nextID; - nextID += 1; + return entityIDToStorageIndex.ContainsKey(entityID); + } - if (index >= components.Length) + public ref readonly TComponent Get(int entityID) + { + return ref components[entityIDToStorageIndex[entityID]]; + } + + public override object Debug_Get(int entityID) + { + return components[entityIDToStorageIndex[entityID]]; + } + + public ref readonly TComponent Get() + { +#if DEBUG + if (nextID == 0) { - Array.Resize(ref components, components.Length * 2); - Array.Resize(ref entityIDs, entityIDs.Length * 2); + throw new ArgumentOutOfRangeException("Component storage is empty!"); + } +#endif + return ref components[0]; + } + + public void Set(int entityID, in TComponent component) + { + if (!entityIDToStorageIndex.ContainsKey(entityID)) + { + var index = nextID; + nextID += 1; + + if (index >= components.Length) + { + Array.Resize(ref components, components.Length * 2); + Array.Resize(ref entityIDs, entityIDs.Length * 2); + } + + entityIDToStorageIndex[entityID] = index; + entityIDs[index] = entityID; } - entityIDToStorageIndex[entityID] = index; - entityIDs[index] = entityID; + components[entityIDToStorageIndex[entityID]] = component; } - components[entityIDToStorageIndex[entityID]] = component; - } - - public override void Remove(int entityID) - { - if (entityIDToStorageIndex.ContainsKey(entityID)) + public override void Remove(int entityID) { - var storageIndex = entityIDToStorageIndex[entityID]; - entityIDToStorageIndex.Remove(entityID); - - var lastElementIndex = nextID - 1; - - // move a component into the hole to maintain contiguous memory - if (lastElementIndex != storageIndex) + if (entityIDToStorageIndex.ContainsKey(entityID)) { - var lastEntityID = entityIDs[lastElementIndex]; - entityIDToStorageIndex[lastEntityID] = storageIndex; - components[storageIndex] = components[lastElementIndex]; - entityIDs[storageIndex] = lastEntityID; + var storageIndex = entityIDToStorageIndex[entityID]; + entityIDToStorageIndex.Remove(entityID); + + var lastElementIndex = nextID - 1; + + // move a component into the hole to maintain contiguous memory + if (lastElementIndex != storageIndex) + { + var lastEntityID = entityIDs[lastElementIndex]; + entityIDToStorageIndex[lastEntityID] = storageIndex; + components[storageIndex] = components[lastElementIndex]; + entityIDs[storageIndex] = lastEntityID; + } + + nextID -= 1; } - - nextID -= 1; } - } - public void Clear() - { - nextID = 0; - entityIDToStorageIndex.Clear(); - } + public void Clear() + { + nextID = 0; + entityIDToStorageIndex.Clear(); + } - public ReadOnlySpan AllComponents() - { - return new ReadOnlySpan(components, 0, nextID); - } + public ReadOnlySpan AllComponents() + { + return new ReadOnlySpan(components, 0, nextID); + } - public Entity FirstEntity() - { - return new Entity(entityIDs[0]); + public Entity FirstEntity() + { + return new Entity(entityIDs[0]); + } } } diff --git a/src/DebugSystem.cs b/src/DebugSystem.cs index 6db9882..2db79cc 100644 --- a/src/DebugSystem.cs +++ b/src/DebugSystem.cs @@ -1,7 +1,10 @@ -// NOTE: these methods are very inefficient +// NOTE: these methods are very inefficient // this class should only be used in debugging contexts!! #if DEBUG +using System; +using System.Collections.Generic; + namespace MoonTools.ECS { public abstract class DebugSystem : System diff --git a/src/Entity.cs b/src/Entity.cs index 903fb03..6137212 100644 --- a/src/Entity.cs +++ b/src/Entity.cs @@ -1,26 +1,29 @@ -namespace MoonTools.ECS; +using System; -public struct Entity : IEquatable +namespace MoonTools.ECS { - public int ID { get; } - - internal Entity(int id) + public struct Entity : IEquatable { - ID = id; - } + public int ID { get; } - public override bool Equals(object? obj) - { - return obj is Entity entity && Equals(entity); - } + internal Entity(int id) + { + ID = id; + } - public override int GetHashCode() - { - return HashCode.Combine(ID); - } + public override bool Equals(object? obj) + { + return obj is Entity entity && Equals(entity); + } - public bool Equals(Entity other) - { - return ID == other.ID; + public override int GetHashCode() + { + return HashCode.Combine(ID); + } + + public bool Equals(Entity other) + { + return ID == other.ID; + } } } diff --git a/src/EntityComponentReader.cs b/src/EntityComponentReader.cs index 7d77511..1c65d05 100644 --- a/src/EntityComponentReader.cs +++ b/src/EntityComponentReader.cs @@ -1,79 +1,83 @@ -namespace MoonTools.ECS; +using System; +using System.Collections.Generic; -public abstract class EntityComponentReader +namespace MoonTools.ECS { - internal EntityStorage EntityStorage; - internal ComponentDepot ComponentDepot; - internal RelationDepot RelationDepot; - protected FilterBuilder FilterBuilder => new FilterBuilder(ComponentDepot); - - internal void RegisterEntityStorage(EntityStorage entityStorage) + public abstract class EntityComponentReader { - EntityStorage = entityStorage; - } + internal EntityStorage EntityStorage; + internal ComponentDepot ComponentDepot; + internal RelationDepot RelationDepot; + protected FilterBuilder FilterBuilder => new FilterBuilder(ComponentDepot); - internal void RegisterComponentDepot(ComponentDepot componentDepot) - { - ComponentDepot = componentDepot; - } + internal void RegisterEntityStorage(EntityStorage entityStorage) + { + EntityStorage = entityStorage; + } - internal void RegisterRelationDepot(RelationDepot relationDepot) - { - RelationDepot = relationDepot; - } + internal void RegisterComponentDepot(ComponentDepot componentDepot) + { + ComponentDepot = componentDepot; + } - protected ReadOnlySpan ReadComponents() where TComponent : struct - { - return ComponentDepot.ReadComponents(); - } + internal void RegisterRelationDepot(RelationDepot relationDepot) + { + RelationDepot = relationDepot; + } - protected bool Has(in Entity entity) where TComponent : struct - { - return ComponentDepot.Has(entity.ID); - } + protected ReadOnlySpan ReadComponents() where TComponent : struct + { + return ComponentDepot.ReadComponents(); + } - protected bool Some() where TComponent : struct - { - return ComponentDepot.Some(); - } + protected bool Has(in Entity entity) where TComponent : struct + { + return ComponentDepot.Has(entity.ID); + } - protected ref readonly TComponent Get(in Entity entity) where TComponent : struct - { - return ref ComponentDepot.Get(entity.ID); - } + protected bool Some() where TComponent : struct + { + return ComponentDepot.Some(); + } - protected ref readonly TComponent GetSingleton() where TComponent : struct - { - return ref ComponentDepot.Get(); - } + protected ref readonly TComponent Get(in Entity entity) where TComponent : struct + { + return ref ComponentDepot.Get(entity.ID); + } - protected Entity GetSingletonEntity() where TComponent : struct - { - return ComponentDepot.GetSingletonEntity(); - } + protected ref readonly TComponent GetSingleton() where TComponent : struct + { + return ref ComponentDepot.Get(); + } - protected bool Exists(in Entity entity) - { - return EntityStorage.Exists(entity); - } + protected Entity GetSingletonEntity() where TComponent : struct + { + return ComponentDepot.GetSingletonEntity(); + } - protected IEnumerable Relations() - { - return RelationDepot.Relations(); - } + protected bool Exists(in Entity entity) + { + return EntityStorage.Exists(entity); + } - protected bool Related(in Entity a, in Entity b) - { - return RelationDepot.Related(a.ID, b.ID); - } + protected IEnumerable Relations() + { + return RelationDepot.Relations(); + } - protected IEnumerable RelatedToA(in Entity entity) - { - return RelationDepot.RelatedToA(entity.ID); - } + protected bool Related(in Entity a, in Entity b) + { + return RelationDepot.Related(a.ID, b.ID); + } - protected IEnumerable RelatedToB(in Entity entity) - { - return RelationDepot.RelatedToB(entity.ID); + protected IEnumerable RelatedToA(in Entity entity) + { + return RelationDepot.RelatedToA(entity.ID); + } + + protected IEnumerable RelatedToB(in Entity entity) + { + return RelationDepot.RelatedToB(entity.ID); + } } } diff --git a/src/EntityStorage.cs b/src/EntityStorage.cs index ccadb1a..5d48a49 100644 --- a/src/EntityStorage.cs +++ b/src/EntityStorage.cs @@ -1,21 +1,22 @@ -namespace MoonTools.ECS; - -internal class EntityStorage +namespace MoonTools.ECS { - public IDStorage idStorage = new IDStorage(); - - public Entity Create() + internal class EntityStorage { - return new Entity(idStorage.NextID()); - } + public IDStorage idStorage = new IDStorage(); - public bool Exists(in Entity entity) - { - return idStorage.Taken(entity.ID); - } + public Entity Create() + { + return new Entity(idStorage.NextID()); + } - public void Destroy(in Entity entity) - { - idStorage.Release(entity.ID); + public bool Exists(in Entity entity) + { + return idStorage.Taken(entity.ID); + } + + public void Destroy(in Entity entity) + { + idStorage.Release(entity.ID); + } } } diff --git a/src/Filter.cs b/src/Filter.cs index fc15b79..bf7fefa 100644 --- a/src/Filter.cs +++ b/src/Filter.cs @@ -1,20 +1,24 @@ -namespace MoonTools.ECS; +using System; +using System.Collections.Generic; -public class Filter +namespace MoonTools.ECS { - internal FilterSignature Signature; - private ComponentDepot ComponentDepot; - - internal Filter(ComponentDepot componentDepot, HashSet included, HashSet excluded) + public class Filter { - ComponentDepot = componentDepot; - Signature = new FilterSignature(included, excluded); + internal FilterSignature Signature; + private ComponentDepot ComponentDepot; + + internal Filter(ComponentDepot componentDepot, HashSet included, HashSet excluded) + { + ComponentDepot = componentDepot; + Signature = new FilterSignature(included, excluded); + } + + public IEnumerable Entities => ComponentDepot.FilterEntities(this); + public IEnumerable EntitiesInRandomOrder => ComponentDepot.FilterEntitiesRandom(this); + public Entity RandomEntity => ComponentDepot.FilterRandomEntity(this); + + public int Count => ComponentDepot.FilterCount(this); + public bool Empty => Count == 0; } - - public IEnumerable Entities => ComponentDepot.FilterEntities(this); - public IEnumerable EntitiesInRandomOrder => ComponentDepot.FilterEntitiesRandom(this); - public Entity RandomEntity => ComponentDepot.FilterRandomEntity(this); - - public int Count => ComponentDepot.FilterCount(this); - public bool Empty => Count == 0; } diff --git a/src/FilterBuilder.cs b/src/FilterBuilder.cs index 753fb74..4ba782d 100644 --- a/src/FilterBuilder.cs +++ b/src/FilterBuilder.cs @@ -1,41 +1,45 @@ -namespace MoonTools.ECS; +using System; +using System.Collections.Generic; -public struct FilterBuilder +namespace MoonTools.ECS { - private ComponentDepot ComponentDepot; - private HashSet Included; - private HashSet Excluded; - - internal FilterBuilder(ComponentDepot componentDepot) + public struct FilterBuilder { - ComponentDepot = componentDepot; - Included = new HashSet(); - Excluded = new HashSet(); - } + private ComponentDepot ComponentDepot; + private HashSet Included; + private HashSet Excluded; - private FilterBuilder(ComponentDepot componentDepot, HashSet included, HashSet excluded) - { - ComponentDepot = componentDepot; - Included = included; - Excluded = excluded; - } + internal FilterBuilder(ComponentDepot componentDepot) + { + ComponentDepot = componentDepot; + Included = new HashSet(); + Excluded = new HashSet(); + } - public FilterBuilder Include() where TComponent : struct - { - ComponentDepot.Register(); - Included.Add(typeof(TComponent)); - return new FilterBuilder(ComponentDepot, Included, Excluded); - } + private FilterBuilder(ComponentDepot componentDepot, HashSet included, HashSet excluded) + { + ComponentDepot = componentDepot; + Included = included; + Excluded = excluded; + } - public FilterBuilder Exclude() where TComponent : struct - { - ComponentDepot.Register(); - Excluded.Add(typeof(TComponent)); - return new FilterBuilder(ComponentDepot, Included, Excluded); - } + public FilterBuilder Include() where TComponent : struct + { + ComponentDepot.Register(); + Included.Add(typeof(TComponent)); + return new FilterBuilder(ComponentDepot, Included, Excluded); + } - public Filter Build() - { - return ComponentDepot.CreateFilter(Included, Excluded); + public FilterBuilder Exclude() where TComponent : struct + { + ComponentDepot.Register(); + Excluded.Add(typeof(TComponent)); + return new FilterBuilder(ComponentDepot, Included, Excluded); + } + + public Filter Build() + { + return ComponentDepot.CreateFilter(Included, Excluded); + } } } diff --git a/src/FilterSignature.cs b/src/FilterSignature.cs index 0ce7ae2..4857119 100644 --- a/src/FilterSignature.cs +++ b/src/FilterSignature.cs @@ -1,47 +1,51 @@ -namespace MoonTools.ECS; +using System; +using System.Collections.Generic; -public struct FilterSignature +namespace MoonTools.ECS { - private const int HASH_FACTOR = 97; - - public HashSet Included; - public HashSet Excluded; - - public FilterSignature(HashSet included, HashSet excluded) + public struct FilterSignature { - Included = included; - Excluded = excluded; - } + private const int HASH_FACTOR = 97; - public override bool Equals(object? obj) - { - return obj is FilterSignature signature && Equals(signature); - } + public HashSet Included; + public HashSet Excluded; - public bool Equals(FilterSignature other) - { - return Included.SetEquals(other.Included) && Excluded.SetEquals(other.Excluded); - } - - private int GuidToInt(Guid guid) - { - return BitConverter.ToInt32(guid.ToByteArray()); - } - - public override int GetHashCode() - { - int result = 1; - foreach (var type in Included) + public FilterSignature(HashSet included, HashSet excluded) { - result *= HASH_FACTOR + GuidToInt(type.GUID); + Included = included; + Excluded = excluded; } - // FIXME: Is there a way to avoid collisions when this is the same set as included? - foreach (var type in Excluded) + public override bool Equals(object? obj) { - result *= HASH_FACTOR + GuidToInt(type.GUID); + return obj is FilterSignature signature && Equals(signature); } - return result; + public bool Equals(FilterSignature other) + { + return Included.SetEquals(other.Included) && Excluded.SetEquals(other.Excluded); + } + + private int GuidToInt(Guid guid) + { + return BitConverter.ToInt32(guid.ToByteArray()); + } + + public override int GetHashCode() + { + int result = 1; + foreach (var type in Included) + { + result *= HASH_FACTOR + GuidToInt(type.GUID); + } + + // FIXME: Is there a way to avoid collisions when this is the same set as included? + foreach (var type in Excluded) + { + result *= HASH_FACTOR + GuidToInt(type.GUID); + } + + return result; + } } } diff --git a/src/IDStorage.cs b/src/IDStorage.cs index 26da620..93e17bf 100644 --- a/src/IDStorage.cs +++ b/src/IDStorage.cs @@ -1,36 +1,39 @@ -namespace MoonTools.ECS; +using System.Collections.Generic; -internal class IDStorage +namespace MoonTools.ECS { - private int nextID = 0; - - private readonly Stack availableIDs = new Stack(); - private readonly HashSet availableIDHash = new HashSet(); - - public int NextID() + internal class IDStorage { - if (availableIDs.Count > 0) + private int nextID = 0; + + private readonly Stack availableIDs = new Stack(); + private readonly HashSet availableIDHash = new HashSet(); + + public int NextID() { - var id = availableIDs.Pop(); - availableIDHash.Remove(id); - return id; + if (availableIDs.Count > 0) + { + var id = availableIDs.Pop(); + availableIDHash.Remove(id); + return id; + } + else + { + var id = nextID; + nextID += 1; + return id; + } } - else + + public bool Taken(int id) { - var id = nextID; - nextID += 1; - return id; + return !availableIDHash.Contains(id) && id < nextID; } - } - public bool Taken(int id) - { - return !availableIDHash.Contains(id) && id < nextID; - } - - public void Release(int id) - { - availableIDs.Push(id); - availableIDHash.Add(id); + public void Release(int id) + { + availableIDs.Push(id); + availableIDHash.Add(id); + } } } diff --git a/src/IHasEntity.cs b/src/IHasEntity.cs index ac186a8..35a676f 100644 --- a/src/IHasEntity.cs +++ b/src/IHasEntity.cs @@ -1,6 +1,7 @@ -namespace MoonTools.ECS; - -public interface IHasEntity +namespace MoonTools.ECS { - Entity Entity { get; } + public interface IHasEntity + { + Entity Entity { get; } + } } diff --git a/src/IndexableSet.cs b/src/IndexableSet.cs index 1ab3159..cf8f56c 100644 --- a/src/IndexableSet.cs +++ b/src/IndexableSet.cs @@ -1,4 +1,6 @@ +using System; using System.Collections; +using System.Collections.Generic; namespace MoonTools.ECS { diff --git a/src/MessageDepot.cs b/src/MessageDepot.cs index 28e8cc9..5f925ff 100644 --- a/src/MessageDepot.cs +++ b/src/MessageDepot.cs @@ -1,59 +1,63 @@ -namespace MoonTools.ECS; +using System; +using System.Collections.Generic; -internal class MessageDepot +namespace MoonTools.ECS { - private Dictionary storages = new Dictionary(); - - private MessageStorage Lookup() where TMessage : struct + internal class MessageDepot { - if (!storages.ContainsKey(typeof(TMessage))) + private Dictionary storages = new Dictionary(); + + private MessageStorage Lookup() where TMessage : struct { - storages.Add(typeof(TMessage), new MessageStorage()); + if (!storages.ContainsKey(typeof(TMessage))) + { + storages.Add(typeof(TMessage), new MessageStorage()); + } + + return storages[typeof(TMessage)] as MessageStorage; } - return storages[typeof(TMessage)] as MessageStorage; - } - - public void Add(in TMessage message) where TMessage : struct - { - Lookup().Add(message); - } - - public bool Some() where TMessage : struct - { - return Lookup().Some(); - } - - public ReadOnlySpan All() where TMessage : struct - { - return Lookup().All(); - } - - public TMessage First() where TMessage : struct - { - return Lookup().First(); - } - - public IEnumerable WithEntity(int entityID) where TMessage : struct, IHasEntity - { - return Lookup().WithEntity(entityID); - } - - public ref readonly TMessage FirstWithEntity(int entityID) where TMessage : struct, IHasEntity - { - return ref Lookup().FirstWithEntity(entityID); - } - - public bool SomeWithEntity(int entityID) where TMessage : struct, IHasEntity - { - return Lookup().SomeWithEntity(entityID); - } - - public void Clear() - { - foreach (var storage in storages.Values) + public void Add(in TMessage message) where TMessage : struct { - storage.Clear(); + Lookup().Add(message); + } + + public bool Some() where TMessage : struct + { + return Lookup().Some(); + } + + public ReadOnlySpan All() where TMessage : struct + { + return Lookup().All(); + } + + public TMessage First() where TMessage : struct + { + return Lookup().First(); + } + + public IEnumerable WithEntity(int entityID) where TMessage : struct, IHasEntity + { + return Lookup().WithEntity(entityID); + } + + public ref readonly TMessage FirstWithEntity(int entityID) where TMessage : struct, IHasEntity + { + return ref Lookup().FirstWithEntity(entityID); + } + + public bool SomeWithEntity(int entityID) where TMessage : struct, IHasEntity + { + return Lookup().SomeWithEntity(entityID); + } + + public void Clear() + { + foreach (var storage in storages.Values) + { + storage.Clear(); + } } } } diff --git a/src/MessageStorage.cs b/src/MessageStorage.cs index 9441500..0e29a1a 100644 --- a/src/MessageStorage.cs +++ b/src/MessageStorage.cs @@ -1,87 +1,91 @@ -namespace MoonTools.ECS; +using System; +using System.Collections.Generic; -internal abstract class MessageStorage +namespace MoonTools.ECS { - public abstract void Clear(); -} - -internal class MessageStorage : MessageStorage where TMessage : struct -{ - private int count = 0; - private int capacity = 128; - private TMessage[] messages; - private Dictionary> entityToIndices = new Dictionary>(); - - public MessageStorage() + internal abstract class MessageStorage { - messages = new TMessage[capacity]; + public abstract void Clear(); } - public void Add(in TMessage message) + internal class MessageStorage : MessageStorage where TMessage : struct { - if (count == capacity) + private int count = 0; + private int capacity = 128; + private TMessage[] messages; + private Dictionary> entityToIndices = new Dictionary>(); + + public MessageStorage() { - capacity *= 2; - Array.Resize(ref messages, capacity); + messages = new TMessage[capacity]; } - messages[count] = message; - - if (message is IHasEntity entityMessage) + public void Add(in TMessage message) { - if (!entityToIndices.ContainsKey(entityMessage.Entity.ID)) + if (count == capacity) { - entityToIndices.Add(entityMessage.Entity.ID, new List()); + capacity *= 2; + Array.Resize(ref messages, capacity); } - entityToIndices[entityMessage.Entity.ID].Add(count); + messages[count] = message; + + if (message is IHasEntity entityMessage) + { + if (!entityToIndices.ContainsKey(entityMessage.Entity.ID)) + { + entityToIndices.Add(entityMessage.Entity.ID, new List()); + } + + entityToIndices[entityMessage.Entity.ID].Add(count); + } + + count += 1; } - count += 1; - } - - public bool Some() - { - return count > 0; - } - - public ReadOnlySpan All() - { - return new ReadOnlySpan(messages, 0, count); - } - - public TMessage First() - { - return messages[0]; - } - - public IEnumerable WithEntity(int entityID) - { - if (entityToIndices.ContainsKey(entityID)) + public bool Some() { - foreach (var index in entityToIndices[entityID]) + return count > 0; + } + + public ReadOnlySpan All() + { + return new ReadOnlySpan(messages, 0, count); + } + + public TMessage First() + { + return messages[0]; + } + + public IEnumerable WithEntity(int entityID) + { + if (entityToIndices.ContainsKey(entityID)) { - yield return messages[index]; + foreach (var index in entityToIndices[entityID]) + { + yield return messages[index]; + } + } + } + + public ref readonly TMessage FirstWithEntity(int entityID) + { + return ref messages[entityToIndices[entityID][0]]; + } + + public bool SomeWithEntity(int entityID) + { + return entityToIndices.ContainsKey(entityID) && entityToIndices[entityID].Count > 0; + } + + public override void Clear() + { + count = 0; + foreach (var set in entityToIndices.Values) + { + set.Clear(); } } } - - public ref readonly TMessage FirstWithEntity(int entityID) - { - return ref messages[entityToIndices[entityID][0]]; - } - - public bool SomeWithEntity(int entityID) - { - return entityToIndices.ContainsKey(entityID) && entityToIndices[entityID].Count > 0; - } - - public override void Clear() - { - count = 0; - foreach (var set in entityToIndices.Values) - { - set.Clear(); - } - } } diff --git a/src/Random.cs b/src/Random.cs index 3fe611c..97c0ddd 100644 --- a/src/Random.cs +++ b/src/Random.cs @@ -1,3 +1,6 @@ +using System; +using System.Collections.Generic; + namespace MoonTools.ECS { internal static class RandomGenerator diff --git a/src/Relation.cs b/src/Relation.cs index 2023801..3b0850c 100644 --- a/src/Relation.cs +++ b/src/Relation.cs @@ -1,3 +1,5 @@ +using System; + namespace MoonTools.ECS { public struct Relation : IEquatable diff --git a/src/RelationDepot.cs b/src/RelationDepot.cs index 49fe7ac..1ae4ab9 100644 --- a/src/RelationDepot.cs +++ b/src/RelationDepot.cs @@ -1,3 +1,6 @@ +using System; +using System.Collections.Generic; + namespace MoonTools.ECS { internal class RelationDepot diff --git a/src/RelationStorage.cs b/src/RelationStorage.cs index 3b1db1f..872f2d7 100644 --- a/src/RelationStorage.cs +++ b/src/RelationStorage.cs @@ -1,3 +1,5 @@ +using System.Collections.Generic; + namespace MoonTools.ECS { internal class RelationStorage diff --git a/src/Renderer.cs b/src/Renderer.cs index 36894c1..07531f3 100644 --- a/src/Renderer.cs +++ b/src/Renderer.cs @@ -1,9 +1,10 @@ -namespace MoonTools.ECS; - -public abstract class Renderer : EntityComponentReader +namespace MoonTools.ECS { - public Renderer(World world) + public abstract class Renderer : EntityComponentReader { - world.AddRenderer(this); + public Renderer(World world) + { + world.AddRenderer(this); + } } } diff --git a/src/System.cs b/src/System.cs index e76706e..2cefe1d 100644 --- a/src/System.cs +++ b/src/System.cs @@ -1,92 +1,96 @@ -namespace MoonTools.ECS; +using System; +using System.Collections.Generic; -public abstract class System : EntityComponentReader +namespace MoonTools.ECS { - internal MessageDepot MessageDepot; - - internal void RegisterMessageDepot(MessageDepot messageDepot) + public abstract class System : EntityComponentReader { - MessageDepot = messageDepot; - } + internal MessageDepot MessageDepot; - public System(World world) - { - world.AddSystem(this); - } - - public abstract void Update(TimeSpan delta); - - protected Entity CreateEntity() - { - return EntityStorage.Create(); - } - - protected void Set(in Entity entity, in TComponent component) where TComponent : struct - { - #if DEBUG - // check for use after destroy - if (!Exists(entity)) + internal void RegisterMessageDepot(MessageDepot messageDepot) { - throw new ArgumentException("This entity is not valid!"); + MessageDepot = messageDepot; } - #endif - ComponentDepot.Set(entity.ID, component); - } - protected void Remove(in Entity entity) where TComponent : struct - { - ComponentDepot.Remove(entity.ID); - } + public System(World world) + { + world.AddSystem(this); + } - protected ReadOnlySpan ReadMessages() where TMessage : struct - { - return MessageDepot.All(); - } + public abstract void Update(TimeSpan delta); - protected TMessage ReadMessage() where TMessage : struct - { - return MessageDepot.First(); - } + protected Entity CreateEntity() + { + return EntityStorage.Create(); + } - protected bool SomeMessage() where TMessage : struct - { - return MessageDepot.Some(); - } + protected void Set(in Entity entity, in TComponent component) where TComponent : struct + { +#if DEBUG + // check for use after destroy + if (!Exists(entity)) + { + throw new ArgumentException("This entity is not valid!"); + } +#endif + ComponentDepot.Set(entity.ID, component); + } - protected IEnumerable ReadMessagesWithEntity(in Entity entity) where TMessage : struct, IHasEntity - { - return MessageDepot.WithEntity(entity.ID); - } + protected void Remove(in Entity entity) where TComponent : struct + { + ComponentDepot.Remove(entity.ID); + } - protected ref readonly TMessage ReadMessageWithEntity(in Entity entity) where TMessage : struct, IHasEntity - { - return ref MessageDepot.FirstWithEntity(entity.ID); - } + protected ReadOnlySpan ReadMessages() where TMessage : struct + { + return MessageDepot.All(); + } - protected bool SomeMessageWithEntity(in Entity entity) where TMessage : struct, IHasEntity - { - return MessageDepot.SomeWithEntity(entity.ID); - } + protected TMessage ReadMessage() where TMessage : struct + { + return MessageDepot.First(); + } - protected void Send(in TMessage message) where TMessage : struct - { - MessageDepot.Add(message); - } + protected bool SomeMessage() where TMessage : struct + { + return MessageDepot.Some(); + } - protected void Relate(in Entity entityA, in Entity entityB) - { - RelationDepot.Add(new Relation(entityA, entityB)); - } + protected IEnumerable ReadMessagesWithEntity(in Entity entity) where TMessage : struct, IHasEntity + { + return MessageDepot.WithEntity(entity.ID); + } - protected void Unrelate(in Entity entityA, in Entity entityB) - { - RelationDepot.Remove(new Relation(entityA, entityB)); - } + protected ref readonly TMessage ReadMessageWithEntity(in Entity entity) where TMessage : struct, IHasEntity + { + return ref MessageDepot.FirstWithEntity(entity.ID); + } - protected void Destroy(in Entity entity) - { - ComponentDepot.OnEntityDestroy(entity.ID); - RelationDepot.OnEntityDestroy(entity.ID); - EntityStorage.Destroy(entity); + protected bool SomeMessageWithEntity(in Entity entity) where TMessage : struct, IHasEntity + { + return MessageDepot.SomeWithEntity(entity.ID); + } + + protected void Send(in TMessage message) where TMessage : struct + { + MessageDepot.Add(message); + } + + protected void Relate(in Entity entityA, in Entity entityB) + { + RelationDepot.Add(new Relation(entityA, entityB)); + } + + protected void Unrelate(in Entity entityA, in Entity entityB) + { + RelationDepot.Remove(new Relation(entityA, entityB)); + } + + protected void Destroy(in Entity entity) + { + ComponentDepot.OnEntityDestroy(entity.ID); + RelationDepot.OnEntityDestroy(entity.ID); + EntityStorage.Destroy(entity); + } } } diff --git a/src/World.cs b/src/World.cs index dc497c2..d228b33 100644 --- a/src/World.cs +++ b/src/World.cs @@ -1,49 +1,50 @@ -namespace MoonTools.ECS; - -public class World +namespace MoonTools.ECS { - private readonly EntityStorage EntityStorage = new EntityStorage(); - private readonly ComponentDepot ComponentDepot = new ComponentDepot(); - private readonly MessageDepot MessageDepot = new MessageDepot(); - private readonly RelationDepot RelationDepot = new RelationDepot(); - - internal void AddSystem(System system) + public class World { - system.RegisterEntityStorage(EntityStorage); - system.RegisterComponentDepot(ComponentDepot); - system.RegisterMessageDepot(MessageDepot); - system.RegisterRelationDepot(RelationDepot); - } + private readonly EntityStorage EntityStorage = new EntityStorage(); + private readonly ComponentDepot ComponentDepot = new ComponentDepot(); + private readonly MessageDepot MessageDepot = new MessageDepot(); + private readonly RelationDepot RelationDepot = new RelationDepot(); - internal void AddRenderer(Renderer renderer) - { - renderer.RegisterEntityStorage(EntityStorage); - renderer.RegisterComponentDepot(ComponentDepot); - renderer.RegisterRelationDepot(RelationDepot); - } + internal void AddSystem(System system) + { + system.RegisterEntityStorage(EntityStorage); + system.RegisterComponentDepot(ComponentDepot); + system.RegisterMessageDepot(MessageDepot); + system.RegisterRelationDepot(RelationDepot); + } - public void AddRelationKind() - { - RelationDepot.Register(); - } + internal void AddRenderer(Renderer renderer) + { + renderer.RegisterEntityStorage(EntityStorage); + renderer.RegisterComponentDepot(ComponentDepot); + renderer.RegisterRelationDepot(RelationDepot); + } - public Entity CreateEntity() - { - return EntityStorage.Create(); - } + public void AddRelationKind() + { + RelationDepot.Register(); + } - public void Set(Entity entity, in TComponent component) where TComponent : struct - { - ComponentDepot.Set(entity.ID, component); - } + public Entity CreateEntity() + { + return EntityStorage.Create(); + } - public void Send(in TMessage message) where TMessage : struct - { - MessageDepot.Add(message); - } + public void Set(Entity entity, in TComponent component) where TComponent : struct + { + ComponentDepot.Set(entity.ID, component); + } - public void FinishUpdate() - { - MessageDepot.Clear(); + public void Send(in TMessage message) where TMessage : struct + { + MessageDepot.Add(message); + } + + public void FinishUpdate() + { + MessageDepot.Clear(); + } } }