diff --git a/encompass-cs/Entity.cs b/encompass-cs/Entity.cs index a08954c..7287499 100644 --- a/encompass-cs/Entity.cs +++ b/encompass-cs/Entity.cs @@ -8,21 +8,16 @@ namespace Encompass /// public struct Entity : IEquatable { - public readonly Guid ID; + public readonly int ID; - internal Entity(Guid id) + internal Entity(int id) { ID = id; } public override bool Equals(object obj) { - if (obj is Entity entity) - { - return Equals(entity); - } - - return false; + return obj is Entity entity && Equals(entity); } public bool Equals(Entity other) diff --git a/encompass-cs/EntityManager.cs b/encompass-cs/EntityManager.cs index 919d4c1..a264046 100644 --- a/encompass-cs/EntityManager.cs +++ b/encompass-cs/EntityManager.cs @@ -1,30 +1,45 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; +using Encompass.Exceptions; namespace Encompass { internal class EntityManager { - 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 ComponentManager componentManager; - public EntityManager(ComponentManager componentManager) + public EntityManager(ComponentManager componentManager, int entityCapacity) { this.componentManager = componentManager; + this.entityCapacity = entityCapacity; + } + + private int NextID() + { + return idManager.NextID(); } public Entity CreateEntity() { - var id = NextID(); - var entity = new Entity(id); - IDs.Add(id); - return entity; + if (IDs.Count < entityCapacity) + { + var id = NextID(); + var entity = new Entity(id); + IDs.Add(id); + return entity; + } + else + { + throw new EntityOverflowException("The number of entities has exceeded the entity capacity of {0}", entityCapacity); + } } - public bool EntityExists(Guid id) + public bool EntityExists(int id) { return IDs.Contains(id); } @@ -40,14 +55,10 @@ namespace Encompass { componentManager.MarkAllComponentsOnEntityForRemoval(entity); IDs.Remove(entity.ID); + idManager.Free(entity.ID); } entitiesMarkedForDestroy.Clear(); } - - private Guid NextID() - { - return Guid.NewGuid(); - } } } diff --git a/encompass-cs/Exceptions/EntityOverflowException.cs b/encompass-cs/Exceptions/EntityOverflowException.cs new file mode 100644 index 0000000..37b942c --- /dev/null +++ b/encompass-cs/Exceptions/EntityOverflowException.cs @@ -0,0 +1,12 @@ +using System; + +namespace Encompass.Exceptions +{ + public class EntityOverflowException : Exception + { + public EntityOverflowException( + string format, + params object[] args + ) : base(string.Format(format, args)) { } + } +} diff --git a/encompass-cs/IDManager.cs b/encompass-cs/IDManager.cs new file mode 100644 index 0000000..01bb529 --- /dev/null +++ b/encompass-cs/IDManager.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; + +namespace Encompass +{ + internal class IDManager + { + int nextID = 0; + + private Stack availableIDs = new Stack(); + + public int NextID() + { + if (availableIDs.Count > 0) + { + return availableIDs.Pop(); + } + else + { + return nextID++; + } + } + + public void Free(int ID) + { + availableIDs.Push(ID); + } + } +} diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs index 664ee8b..cae7d70 100644 --- a/encompass-cs/WorldBuilder.cs +++ b/encompass-cs/WorldBuilder.cs @@ -18,6 +18,7 @@ namespace Encompass /// public class WorldBuilder { + private readonly int entityCapacity; private readonly List engines = new List(); private readonly DirectedGraph engineGraph = GraphBuilder.DirectedGraph(); private readonly ComponentStore startingComponentStoreForComponentManager = new ComponentStore(); @@ -39,14 +40,15 @@ namespace Encompass private readonly HashSet messageTypes = new HashSet(); - public WorldBuilder() + public WorldBuilder(int entityCapacity = 32768) { + this.entityCapacity = entityCapacity; drawLayerManager = new DrawLayerManager(); timeManager = new TimeManager(); componentUpdateManager = new ComponentUpdateManager(); componentManager = new ComponentManager(drawLayerManager, componentUpdateManager); messageManager = new MessageManager(timeManager); - entityManager = new EntityManager(componentManager); + entityManager = new EntityManager(componentManager, entityCapacity); renderManager = new RenderManager(drawLayerManager); } @@ -402,7 +404,7 @@ namespace Encompass var dummyDrawLayerManager = new DrawLayerManager(); var dummyComponentUpdateManager = new ComponentUpdateManager(); var dummyComponentManager = new ComponentManager(dummyDrawLayerManager, dummyComponentUpdateManager); - var dummyEntityManager = new EntityManager(dummyComponentManager); + var dummyEntityManager = new EntityManager(dummyComponentManager, entityCapacity); var dummyRenderManager = new RenderManager(dummyDrawLayerManager); var prepEngineOrder = new List(); diff --git a/test/EntityTest.cs b/test/EntityTest.cs index 89b0520..afced33 100644 --- a/test/EntityTest.cs +++ b/test/EntityTest.cs @@ -2,6 +2,7 @@ using NUnit.Framework; using FluentAssertions; using Encompass; +using Encompass.Exceptions; namespace Tests { @@ -20,5 +21,18 @@ namespace Tests Assert.AreEqual(entity, entity); Assert.IsTrue(entity == copyEntity); } + + [Test] + public void EntityOverflowException() + { + var worldBuilder = new WorldBuilder(16); + + for (var i = 0; i < 16; i++) + { + worldBuilder.CreateEntity(); + } + + Assert.Throws(() => worldBuilder.CreateEntity()); + } } -} \ No newline at end of file +}