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); } }