getting rid of tuple returns
continuous-integration/drone/push Build is passing Details

pull/3/head
Evan Hemsley 2020-03-22 19:10:28 -07:00
parent d5a45d6419
commit ca9c9c84a3
12 changed files with 212 additions and 207 deletions

View File

@ -25,6 +25,11 @@ namespace Encompass
} }
} }
public ref readonly TComponent GetComponent<TComponent>(int entityID) where TComponent : struct
{
return ref _store.Get<TComponent>(entityID);
}
public void Set<TComponent>(int entityID, in TComponent component) where TComponent : struct public void Set<TComponent>(int entityID, in TComponent component) where TComponent : struct
{ {
_store.Set(entityID, component); _store.Set(entityID, component);
@ -69,9 +74,9 @@ namespace Encompass
} }
} }
public IEnumerable<(TComponent, int)> All<TComponent>() where TComponent : struct public Span<Entity> AllEntities<TComponent>() where TComponent : struct
{ {
return _store.All<TComponent>(); return _store.AllEntities<TComponent>();
} }
public void ClearAll() public void ClearAll()

View File

@ -53,6 +53,16 @@ namespace Encompass
return ref Lookup<TComponent>().Get(entityID); return ref Lookup<TComponent>().Get(entityID);
} }
public ref readonly TComponent Singular<TComponent>() where TComponent : struct
{
return ref Lookup<TComponent>().Singular();
}
public ref readonly Entity SingularEntity<TComponent>() where TComponent : struct
{
return ref Lookup<TComponent>().SingularEntity();
}
public void Set<TComponent>(int entityID, in TComponent component) where TComponent : struct public void Set<TComponent>(int entityID, in TComponent component) where TComponent : struct
{ {
Lookup<TComponent>().Set(entityID, component); Lookup<TComponent>().Set(entityID, component);
@ -99,9 +109,14 @@ namespace Encompass
return Lookup<TComponent>().Count > 0; return Lookup<TComponent>().Count > 0;
} }
public IEnumerable<(TComponent, int)> All<TComponent>() where TComponent : struct public Span<TComponent> All<TComponent>() where TComponent : struct
{ {
return Lookup<TComponent>().All(); return Lookup<TComponent>().AllComponents();
}
public Span<Entity> AllEntities<TComponent>() where TComponent : struct
{
return Lookup<TComponent>().AllEntities();
} }
public void Clear<TComponent>() where TComponent : struct public void Clear<TComponent>() where TComponent : struct

View File

@ -22,9 +22,10 @@ namespace Encompass
public override void Replay(ComponentStore store) public override void Replay(ComponentStore store)
{ {
foreach (var (component, entityID) in _deltaStore.All<TComponent>()) foreach (ref readonly var entity in _deltaStore.AllEntities<TComponent>())
{ {
store.Set(entityID, component); ref readonly var component = ref _deltaStore.GetComponent<TComponent>(entity.ID);
store.Set(entity.ID, component);
} }
foreach (var entityID in _removals) foreach (var entityID in _removals)

View File

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
@ -18,7 +19,7 @@ namespace Encompass
private int _nextID = 0; private int _nextID = 0;
private readonly Dictionary<int, int> _entityIDToStorageIndex = new Dictionary<int, int>(128); private readonly Dictionary<int, int> _entityIDToStorageIndex = new Dictionary<int, int>(128);
private readonly Dictionary<int, int> _priorities = new Dictionary<int, int>(128); private readonly Dictionary<int, int> _priorities = new Dictionary<int, int>(128);
private int[] _storageIndexToEntityID = new int[128]; private Entity[] _storageIndexToEntities = new Entity[128];
private TComponent[] _components = new TComponent[128]; private TComponent[] _components = new TComponent[128];
public override int Count { get => _entityIDToStorageIndex.Count; } public override int Count { get => _entityIDToStorageIndex.Count; }
@ -29,6 +30,16 @@ namespace Encompass
return ref _components[_entityIDToStorageIndex[entityID]]; 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) public void Set(int entityID, in TComponent component)
{ {
InternalSet(entityID, component); InternalSet(entityID, component);
@ -54,10 +65,10 @@ namespace Encompass
if (index >= _components.Length) if (index >= _components.Length)
{ {
System.Array.Resize(ref _components, _components.Length * 2); 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; _entityIDToStorageIndex[entityID] = index;
_storageIndexToEntityID[index] = entityID; _storageIndexToEntities[index] = new Entity(entityID);
} }
_components[_entityIDToStorageIndex[entityID]] = component; _components[_entityIDToStorageIndex[entityID]] = component;
@ -87,10 +98,10 @@ namespace Encompass
if (_nextID > 1 && storageIndex != _nextID - 1) if (_nextID > 1 && storageIndex != _nextID - 1)
{ {
var lastStorageIndex = _nextID - 1; var lastStorageIndex = _nextID - 1;
var lastEntityID = _storageIndexToEntityID[lastStorageIndex]; ref readonly var lastEntity = ref _storageIndexToEntities[lastStorageIndex];
_entityIDToStorageIndex[lastEntityID] = storageIndex; _entityIDToStorageIndex[lastEntity.ID] = storageIndex;
_storageIndexToEntityID[storageIndex] = lastEntityID; _storageIndexToEntities[storageIndex] = lastEntity;
_components[storageIndex] = _components[lastStorageIndex]; _components[storageIndex] = _components[lastStorageIndex];
} }
@ -116,12 +127,14 @@ namespace Encompass
_priorities.Clear(); _priorities.Clear();
} }
public IEnumerable<(TComponent, int)> All() public Span<Entity> AllEntities()
{ {
for (var i = 0; i < _nextID; i++) return new Span<Entity>(_storageIndexToEntities, 0, _nextID);
{ }
yield return (_components[i], _storageIndexToEntityID[i]);
} public Span<TComponent> AllComponents()
{
return new Span<TComponent>(_components, 0, _nextID);
} }
} }
} }

View File

@ -98,17 +98,19 @@ namespace Encompass
// existing or immediate reads // existing or immediate reads
internal IEnumerable<(TComponent, int)> ReadExistingAndImmediateComponentsByType<TComponent>() where TComponent : struct internal Span<TComponent> ReadExistingAndImmediateComponentsByType<TComponent>() where TComponent : struct
{ {
return _upToDateComponentStore.All<TComponent>(); return _upToDateComponentStore.All<TComponent>();
} }
internal (TComponent, int) ReadFirstExistingOrImmediateComponentByType<TComponent>() where TComponent : struct internal ref readonly TComponent ExistingOrImmediateSingular<TComponent>() where TComponent : struct
{ {
if (!SomeExistingOrImmediateComponent<TComponent>()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } return ref _upToDateComponentStore.Singular<TComponent>();
var enumerator = ReadExistingAndImmediateComponentsByType<TComponent>().GetEnumerator(); }
enumerator.MoveNext();
return enumerator.Current; internal Span<Entity> GetExistingAndImmediateEntities<TComponent>() where TComponent : struct
{
return _upToDateComponentStore.AllEntities<TComponent>();
} }
internal bool SomeExistingOrImmediateComponent<TComponent>() where TComponent : struct internal bool SomeExistingOrImmediateComponent<TComponent>() where TComponent : struct
@ -118,12 +120,24 @@ namespace Encompass
// existing reads // existing reads
internal (TComponent, int) ReadFirstExistingComponentByType<TComponent>() where TComponent : struct internal Span<TComponent> GetExistingComponents<TComponent>() where TComponent : struct
{ {
if (!SomeExistingComponent<TComponent>()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } return _existingComponentStore.All<TComponent>();
var enumerator = GetComponentsIncludingEntity<TComponent>().GetEnumerator(); }
enumerator.MoveNext();
return enumerator.Current; internal ref readonly TComponent ExistingSingular<TComponent>() where TComponent : struct
{
return ref _existingComponentStore.Singular<TComponent>();
}
internal Span<Entity> GetExistingEntities<TComponent>() where TComponent : struct
{
return _existingComponentStore.AllEntities<TComponent>();
}
internal ref readonly Entity SingularEntity<TComponent>() where TComponent : struct
{
return ref _existingComponentStore.SingularEntity<TComponent>();
} }
internal bool SomeExistingComponent<TComponent>() where TComponent : struct internal bool SomeExistingComponent<TComponent>() where TComponent : struct
@ -133,17 +147,19 @@ namespace Encompass
// immediate reads // immediate reads
internal IEnumerable<(TComponent, int)> ReadImmediateComponentsByType<TComponent>() where TComponent : struct internal Span<TComponent> ReadImmediateComponentsByType<TComponent>() where TComponent : struct
{ {
return _immediateComponentStore.All<TComponent>(); return _immediateComponentStore.All<TComponent>();
} }
internal (TComponent, int) ReadFirstImmediateComponentByType<TComponent>() where TComponent : struct internal Span<Entity> GetImmediateEntities<TComponent>() where TComponent : struct
{ {
if (!SomeImmediateComponent<TComponent>()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } return _immediateComponentStore.AllEntities<TComponent>();
var enumerator = ReadImmediateComponentsByType<TComponent>().GetEnumerator(); }
enumerator.MoveNext();
return enumerator.Current; internal ref readonly TComponent ImmediateSingular<TComponent>() where TComponent : struct
{
return ref _immediateComponentStore.Singular<TComponent>();
} }
internal bool SomeImmediateComponent<TComponent>() where TComponent : struct internal bool SomeImmediateComponent<TComponent>() where TComponent : struct
@ -200,19 +216,11 @@ namespace Encompass
return _immediateComponentStore.Has(type, entityID); return _immediateComponentStore.Has(type, entityID);
} }
internal IEnumerable<(TComponent, int)> GetComponentsIncludingEntity<TComponent>() where TComponent : struct internal Span<TComponent> GetComponentsByType<TComponent>() where TComponent : struct
{ {
return _existingComponentStore.All<TComponent>(); return _existingComponentStore.All<TComponent>();
} }
internal IEnumerable<TComponent> GetComponentsByType<TComponent>() where TComponent : struct
{
foreach (var pair in _existingComponentStore.All<TComponent>())
{
yield return pair.Item1;
}
}
internal ref readonly TComponent GetComponentByEntityAndType<TComponent>(int entityID) where TComponent : struct internal ref readonly TComponent GetComponentByEntityAndType<TComponent>(int entityID) where TComponent : struct
{ {
return ref _existingComponentStore.Get<TComponent>(entityID); return ref _existingComponentStore.Get<TComponent>(entityID);

View File

@ -197,7 +197,7 @@ namespace Encompass
/// <summary> /// <summary>
/// Returns true if an Entity with the specified ID exists. /// Returns true if an Entity with the specified ID exists.
/// </summary> /// </summary>
protected bool EntityExists(Entity entity) protected bool EntityExists(in Entity entity)
{ {
return _entityManager.EntityExists(entity.ID); return _entityManager.EntityExists(entity.ID);
} }
@ -213,30 +213,45 @@ namespace Encompass
/// <summary> /// <summary>
/// Returns an Entity containing the specified Component type. /// Returns an Entity containing the specified Component type.
/// </summary> /// </summary>
protected Entity ReadEntity<TComponent>() where TComponent : struct protected ref readonly Entity ReadEntity<TComponent>() where TComponent : struct
{ {
return _entityManager.GetEntity(ReadComponentHelper<TComponent>().Item2); return ref _componentManager.SingularEntity<TComponent>();
} }
/// <summary> /// <summary>
/// Returns all Entities containing the specified Component type. /// Returns all Entities containing the specified Component type.
/// </summary> /// </summary>
protected IEnumerable<Entity> ReadEntities<TComponent>() where TComponent : struct protected Span<Entity> ReadEntities<TComponent>() where TComponent : struct
{ {
foreach (var pair in ReadComponentsHelper<TComponent>()) return ReadEntitiesHelper<TComponent>();
}
private Span<Entity> ReadEntitiesHelper<TComponent>() 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<TComponent>();
}
else if (existingRead)
{
return _componentManager.GetExistingEntities<TComponent>();
}
else if (immediateRead)
{
return _componentManager.GetImmediateEntities<TComponent>();
}
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 /// <summary>
/// Returns all of the Components with the specified Component Type.
internal IEnumerable<TComponent> ReadComponentsFromWorld<TComponent>() where TComponent : struct /// </summary>
{ protected Span<TComponent> ReadComponents<TComponent>() where TComponent : struct
return _componentManager.GetComponentsByType<TComponent>();
}
private IEnumerable<(TComponent, int)> ReadComponentsHelper<TComponent>() where TComponent : struct
{ {
var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent));
var existingRead = ReadTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent));
@ -246,7 +261,7 @@ namespace Encompass
} }
else if (existingRead) else if (existingRead)
{ {
return _componentManager.GetComponentsIncludingEntity<TComponent>(); return _componentManager.GetExistingComponents<TComponent>();
} }
else if (immediateRead) else if (immediateRead)
{ {
@ -259,42 +274,23 @@ namespace Encompass
} }
/// <summary> /// <summary>
/// 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.
/// </summary> /// </summary>
protected IEnumerable<TComponent> ReadComponents<TComponent>() where TComponent : struct protected ref readonly TComponent ReadComponent<TComponent>() where TComponent : struct
{
foreach (var pair in ReadComponentsHelper<TComponent>())
{
yield return pair.Item1;
}
}
/// <summary>
/// Returns all of the components of the specified type including an Entity reference for each Component.
/// </summary>
protected IEnumerable<(TComponent, Entity)> ReadComponentsIncludingEntity<TComponent>() where TComponent : struct
{
foreach (var (component, id) in ReadComponentsHelper<TComponent>())
{
yield return (component, _entityManager.GetEntity(id));
}
}
private (TComponent, int) ReadComponentHelper<TComponent>() where TComponent : struct
{ {
var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent));
var existingRead = ReadTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent));
if (existingRead && immediateRead) if (existingRead && immediateRead)
{ {
return _componentManager.ReadFirstExistingOrImmediateComponentByType<TComponent>(); return ref _componentManager.ExistingOrImmediateSingular<TComponent>();
} }
else if (existingRead) else if (existingRead)
{ {
return _componentManager.ReadFirstExistingComponentByType<TComponent>(); return ref _componentManager.ExistingSingular<TComponent>();
} }
else if (immediateRead) else if (immediateRead)
{ {
return _componentManager.ReadFirstImmediateComponentByType<TComponent>(); return ref _componentManager.ImmediateSingular<TComponent>();
} }
else else
{ {
@ -302,23 +298,6 @@ namespace Encompass
} }
} }
/// <summary>
/// Returns a Component with the specified Component Type. If multiples exist, an arbitrary Component is returned.
/// </summary>
protected TComponent ReadComponent<TComponent>() where TComponent : struct
{
return ReadComponentHelper<TComponent>().Item1;
}
/// <summary>
/// Returns a component of the specified type including its Entity reference. If multiples exist, an arbitrary Component is returned.
/// </summary>
protected (TComponent, Entity) ReadComponentIncludingEntity<TComponent>() where TComponent : struct
{
var (component, id) = ReadComponentHelper<TComponent>();
return (component, _entityManager.GetEntity(id));
}
/// <summary> /// <summary>
/// Returns true if any Component with the specified Component Type exists. /// Returns true if any Component with the specified Component Type exists.
/// </summary> /// </summary>
@ -375,7 +354,7 @@ namespace Encompass
/// <exception cref="Encompass.Exceptions.IllegalReadException"> /// <exception cref="Encompass.Exceptions.IllegalReadException">
/// Thrown when the Engine does not declare that it reads the given Component Type. /// Thrown when the Engine does not declare that it reads the given Component Type.
/// </exception> /// </exception>
protected ref readonly TComponent GetComponent<TComponent>(Entity entity) where TComponent : struct protected ref readonly TComponent GetComponent<TComponent>(in Entity entity) where TComponent : struct
{ {
return ref GetComponentHelper<TComponent>(entity.ID); return ref GetComponentHelper<TComponent>(entity.ID);
} }
@ -389,7 +368,7 @@ namespace Encompass
/// <exception cref="Encompass.Exceptions.IllegalReadException"> /// <exception cref="Encompass.Exceptions.IllegalReadException">
/// Thrown when the Engine does not declare that it reads the given Component Type. /// Thrown when the Engine does not declare that it reads the given Component Type.
/// </exception> /// </exception>
protected ref TComponent GetComponentMutable<TComponent>(Entity entity) where TComponent : struct protected ref TComponent GetComponentMutable<TComponent>(in Entity entity) where TComponent : struct
{ {
return ref GetComponentHelper<TComponent>(entity.ID); return ref GetComponentHelper<TComponent>(entity.ID);
} }
@ -400,7 +379,7 @@ namespace Encompass
/// <exception cref="Encompass.Exceptions.IllegalReadException"> /// <exception cref="Encompass.Exceptions.IllegalReadException">
/// Thrown when the Engine does not declare that is Reads the given Component Type. /// Thrown when the Engine does not declare that is Reads the given Component Type.
/// </exception> /// </exception>
protected bool HasComponent<TComponent>(Entity entity) where TComponent : struct protected bool HasComponent<TComponent>(in Entity entity) where TComponent : struct
{ {
var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent)); var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent));
var existingRead = ReadTypes.Contains(typeof(TComponent)); var existingRead = ReadTypes.Contains(typeof(TComponent));
@ -429,7 +408,7 @@ namespace Encompass
/// <exception cref="Encompass.Exceptions.IllegalReadException"> /// <exception cref="Encompass.Exceptions.IllegalReadException">
/// Thrown when the Engine does not declare that is Reads the given Component Type. /// Thrown when the Engine does not declare that is Reads the given Component Type.
/// </exception> /// </exception>
protected bool HasComponent(Entity entity, Type type) protected bool HasComponent(in Entity entity, Type type)
{ {
var immediateRead = ReadImmediateTypes.Contains(type); var immediateRead = ReadImmediateTypes.Contains(type);
var existingRead = ReadTypes.Contains(type); var existingRead = ReadTypes.Contains(type);
@ -458,7 +437,7 @@ namespace Encompass
/// <exception cref="Encompass.Exceptions.IllegalWriteException"> /// <exception cref="Encompass.Exceptions.IllegalWriteException">
/// Thrown when the Engine does not declare that it Writes the given Component Type. /// Thrown when the Engine does not declare that it Writes the given Component Type.
/// </exception> /// </exception>
protected void SetComponent<TComponent>(Entity entity, in TComponent component) where TComponent : struct protected void SetComponent<TComponent>(in Entity entity, in TComponent component) where TComponent : struct
{ {
var priority = WritePriorities.ContainsKey(typeof(TComponent)) ? WritePriorities[typeof(TComponent)] : DefaultWritePriority; var priority = WritePriorities.ContainsKey(typeof(TComponent)) ? WritePriorities[typeof(TComponent)] : DefaultWritePriority;
@ -498,7 +477,7 @@ namespace Encompass
/// <exception cref="Encompass.Exceptions.IllegalWriteException"> /// <exception cref="Encompass.Exceptions.IllegalWriteException">
/// Thrown when the Engine does not declare that it Writes the given Component Type. /// Thrown when the Engine does not declare that it Writes the given Component Type.
/// </exception> /// </exception>
protected void AddComponent<TComponent>(Entity entity, in TComponent component) where TComponent : struct protected void AddComponent<TComponent>(in Entity entity, in TComponent component) where TComponent : struct
{ {
if (!EntityCreatedThisFrame(entity.ID)) 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. /// 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. /// Entity destruction takes place after all the Engines have been processed by World Update.
/// </summary> /// </summary>
protected void Destroy(Entity entity) protected void Destroy(in Entity entity)
{ {
_entityManager.MarkForDestroy(entity.ID); _entityManager.MarkForDestroy(entity.ID);
} }
@ -628,7 +607,7 @@ namespace Encompass
/// Note that the Engine must Read the Component type that is being removed. /// 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. /// If a Component with the specified type does not exist on the Entity, returns false and does not mutate the Entity.
/// </summary> /// </summary>
protected void RemoveComponent<TComponent>(Entity entity) where TComponent : struct protected void RemoveComponent<TComponent>(in Entity entity) where TComponent : struct
{ {
var priority = WritePriorities.ContainsKey(typeof(TComponent)) ? WritePriorities[typeof(TComponent)] : DefaultWritePriority; var priority = WritePriorities.ContainsKey(typeof(TComponent)) ? WritePriorities[typeof(TComponent)] : DefaultWritePriority;
@ -721,7 +700,7 @@ namespace Encompass
/// <typeparam name="TMessage">The Message subtype.</typeparam> /// <typeparam name="TMessage">The Message subtype.</typeparam>
/// <param name="entity">The entity that all messages in the IEnumerable refer to.</param> /// <param name="entity">The entity that all messages in the IEnumerable refer to.</param>
/// <returns></returns> /// <returns></returns>
protected IEnumerable<TMessage> ReadMessagesWithEntity<TMessage>(Entity entity) where TMessage : struct, IMessage, IHasEntity protected IEnumerable<TMessage> ReadMessagesWithEntity<TMessage>(in Entity entity) where TMessage : struct, IMessage, IHasEntity
{ {
CheckMessageRead<TMessage>(); CheckMessageRead<TMessage>();
return _messageManager.WithEntity<TMessage>(entity.ID); return _messageManager.WithEntity<TMessage>(entity.ID);
@ -731,7 +710,7 @@ namespace Encompass
/// Efficiently reads a single Message of a given type that references a given Entity. /// 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. /// It is recommended to use this method in conjunction with SomeMessageWithEntity to prevent errors.
/// </summary> /// </summary>
protected ref readonly TMessage ReadMessageWithEntity<TMessage>(Entity entity) where TMessage : struct, IMessage, IHasEntity protected ref readonly TMessage ReadMessageWithEntity<TMessage>(in Entity entity) where TMessage : struct, IMessage, IHasEntity
{ {
CheckMessageRead<TMessage>(); CheckMessageRead<TMessage>();
return ref _messageManager.WithEntitySingular<TMessage>(entity.ID); return ref _messageManager.WithEntitySingular<TMessage>(entity.ID);
@ -740,7 +719,7 @@ namespace Encompass
/// <summary> /// <summary>
/// Efficiently checks if any Message of a given type referencing a given Entity exists. /// Efficiently checks if any Message of a given type referencing a given Entity exists.
/// </summary> /// </summary>
protected bool SomeMessageWithEntity<TMessage>(Entity entity) where TMessage : struct, IMessage, IHasEntity protected bool SomeMessageWithEntity<TMessage>(in Entity entity) where TMessage : struct, IMessage, IHasEntity
{ {
CheckMessageRead<TMessage>(); CheckMessageRead<TMessage>();
return _messageManager.SomeWithEntity<TMessage>(entity.ID); return _messageManager.SomeWithEntity<TMessage>(entity.ID);

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
namespace Encompass namespace Encompass
{ {
@ -17,44 +18,24 @@ namespace Encompass
_componentManager = componentManager; _componentManager = componentManager;
} }
protected IEnumerable<Entity> ReadEntities<TComponent>() where TComponent : struct protected Span<Entity> ReadEntities<TComponent>() where TComponent : struct
{ {
foreach (var pair in ReadComponentsIncludingEntity<TComponent>()) return _componentManager.GetExistingEntities<TComponent>();
{
yield return pair.Item2;
}
} }
protected Entity ReadEntity<TComponent>() where TComponent : struct protected ref readonly Entity ReadEntity<TComponent>() where TComponent : struct
{ {
return ReadComponentIncludingEntity<TComponent>().Item2; return ref _componentManager.SingularEntity<TComponent>();
} }
protected IEnumerable<TComponent> ReadComponents<TComponent>() where TComponent : struct protected Span<TComponent> ReadComponents<TComponent>() where TComponent : struct
{ {
return _componentManager.GetComponentsByType<TComponent>(); return _componentManager.GetComponentsByType<TComponent>();
} }
protected IEnumerable<(TComponent, Entity)> ReadComponentsIncludingEntity<TComponent>() where TComponent : struct protected ref readonly TComponent ReadComponent<TComponent>() where TComponent : struct
{ {
foreach (var (component, id) in _componentManager.GetComponentsIncludingEntity<TComponent>()) return ref _componentManager.ExistingSingular<TComponent>();
{
yield return (component, _entityManager.GetEntity(id));
}
}
protected TComponent ReadComponent<TComponent>() where TComponent : struct
{
var enumerator = ReadComponents<TComponent>().GetEnumerator();
enumerator.MoveNext();
return enumerator.Current;
}
protected (TComponent, Entity) ReadComponentIncludingEntity<TComponent>() where TComponent : struct
{
var enumerator = ReadComponentsIncludingEntity<TComponent>().GetEnumerator();
enumerator.MoveNext();
return enumerator.Current;
} }
protected ref readonly TComponent GetComponent<TComponent>(Entity entity) where TComponent : struct protected ref readonly TComponent GetComponent<TComponent>(Entity entity) where TComponent : struct

View File

@ -35,22 +35,21 @@ namespace Encompass
} }
} }
// we can't reflect invoke on Span returns right now... tragic
public override void Update(double dt) public override void Update(double dt)
{ {
foreach (var type in _componentTypes) foreach (var type in _componentTypes)
{ {
CallGenericMethod(type, "ReadComponent", null); CallGenericMethod(type, "ReadComponent", null);
CallGenericMethod(type, "ReadComponentIncludingEntity", null); //CallGenericMethod(type, "ReadComponents", null);
CallGenericMethod(type, "ReadComponents", null);
CallGenericMethod(type, "ReadComponentsIncludingEntity", null);
CallGenericMethod(type, "ReadEntity", null); CallGenericMethod(type, "ReadEntity", null);
CallGenericMethod(type, "ReadEntities", null); //CallGenericMethod(type, "ReadEntities", null);
CallGenericMethod(type, "GetComponent", new Type[] { typeof(Entity) }, new object[] { Entity }); CallGenericMethod(type, "GetComponent", new object[] { Entity });
CallGenericMethod(type, "HasComponent", new Type[] { typeof(Entity) }, new object[] { Entity }); CallGenericMethod(type, "HasComponent", 1, new object[] { Entity });
CallGenericMethod(type, "SomeComponent", null); CallGenericMethod(type, "SomeComponent", null);
CallGenericMethod(type, "DestroyWith", null); CallGenericMethod(type, "DestroyWith", null);
CallGenericMethod(type, "DestroyAllWith", 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) foreach (var type in _messageTypes)
@ -60,13 +59,13 @@ namespace Encompass
CallGenericMethod(type, "SendMessage", 2, new object[] { Activator.CreateInstance(type), 1 }); CallGenericMethod(type, "SendMessage", 2, new object[] { Activator.CreateInstance(type), 1 });
CallGenericMethod(type, "ReadMessage", null); CallGenericMethod(type, "ReadMessage", null);
CallGenericMethod(type, "ReadMessages", null); //CallGenericMethod(type, "ReadMessages", null);
CallGenericMethod(type, "SomeMessage", null); CallGenericMethod(type, "SomeMessage", null);
if (typeof(IHasEntity).IsAssignableFrom(type)) if (typeof(IHasEntity).IsAssignableFrom(type))
{ {
CallGenericMethod(type, "ReadMessagesWithEntity", new Type[] { typeof(Entity) }, new object[] { Entity }); CallGenericMethod(type, "ReadMessagesWithEntity", new object[] { Entity });
CallGenericMethod(type, "ReadMessageWithEntity", new Type[] { typeof(Entity) }, new object[] { Entity }); CallGenericMethod(type, "ReadMessageWithEntity", new object[] { Entity });
CallGenericMethod(type, "SomeMessageWithEntity", new Type[] { typeof(Entity) }, 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 readComponentMethod = typeof(Engine).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
var genericReadComponentMethod = readComponentMethod.MakeGenericMethod(type); var genericReadComponentMethod = readComponentMethod.MakeGenericMethod(type);
//genericReadComponentMethod.Invoke(this, parameters); genericReadComponentMethod.Invoke(this, parameters);
RuntimeHelpers.PrepareMethod(genericReadComponentMethod.MethodHandle); // RuntimeHelpers.PrepareMethod(genericReadComponentMethod.MethodHandle);
} }
private void CallGenericMethod(Type type, string methodName, Type[] types, object[] parameters) private void CallGenericMethod(Type type, string methodName, Type[] types, object[] parameters)
{ {
var readComponentMethod = typeof(Engine).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance, null, types, null); var readComponentMethod = typeof(Engine).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance, null, types, null);
var genericReadComponentMethod = readComponentMethod.MakeGenericMethod(type); var genericReadComponentMethod = readComponentMethod.MakeGenericMethod(type);
//genericReadComponentMethod.Invoke(this, parameters); genericReadComponentMethod.Invoke(this, parameters);
RuntimeHelpers.PrepareMethod(genericReadComponentMethod.MethodHandle); // RuntimeHelpers.PrepareMethod(genericReadComponentMethod.MethodHandle);
} }
private void CallGenericMethod(Type type, string methodName, int argumentNum, object[] parameters) 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 method = typeof(Engine).GetRuntimeMethods().Where(m => m.Name == methodName && m.GetParameters().Length == argumentNum).First();
var genericMethod = method.MakeGenericMethod(type); var genericMethod = method.MakeGenericMethod(type);
//genericMethod.Invoke(this, parameters); genericMethod.Invoke(this, parameters);
RuntimeHelpers.PrepareMethod(genericMethod.MethodHandle); // RuntimeHelpers.PrepareMethod(genericMethod.MethodHandle);
} }
} }
} }

View File

@ -19,16 +19,15 @@ namespace Encompass
_entity = entity; _entity = entity;
} }
// can't reflect invoke on Span returns...
public void Render() public void Render()
{ {
foreach (var type in _componentTypes) foreach (var type in _componentTypes)
{ {
CallGenericMethod(type, "ReadEntities", null); // CallGenericMethod(type, "ReadEntities", null);
CallGenericMethod(type, "ReadEntity", null); CallGenericMethod(type, "ReadEntity", null);
// CallGenericMethod(type, "ReadComponents", null);
CallGenericMethod(type, "ReadComponent", 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, "GetComponent", new object[] { _entity });
CallGenericMethod(type, "HasComponent", new object[] { _entity }); CallGenericMethod(type, "HasComponent", new object[] { _entity });
CallGenericMethod(type, "SomeComponent", null); CallGenericMethod(type, "SomeComponent", null);

View File

@ -104,8 +104,9 @@ namespace Tests
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
foreach (var (mockComponent, entity) in ReadComponentsIncludingEntity<MockComponent>()) foreach (ref readonly var entity in ReadEntities<MockComponent>())
{ {
ref readonly var mockComponent = ref GetComponent<MockComponent>(entity);
SetComponent(entity, new MockComponent { myInt = mockComponent.myInt + 1 }); SetComponent(entity, new MockComponent { myInt = mockComponent.myInt + 1 });
} }
} }
@ -150,8 +151,9 @@ namespace Tests
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
foreach (var (mockComponent, entity) in ReadComponentsIncludingEntity<MockComponent>()) foreach (ref readonly var entity in ReadEntities<MockComponent>())
{ {
ref readonly var mockComponent = ref GetComponent<MockComponent>(entity);
SetComponent(entity, mockComponent); SetComponent(entity, mockComponent);
RemoveComponent<MockComponent>(entity); RemoveComponent<MockComponent>(entity);
} }

View File

@ -17,7 +17,7 @@ namespace Tests
public class EngineTest public class EngineTest
{ {
static List<MockComponent> resultComponents; static MockComponent[] resultComponents;
static MockComponent resultComponent; static MockComponent resultComponent;
static MockMessage[] resultMessages; static MockMessage[] resultMessages;
@ -27,11 +27,11 @@ namespace Tests
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
resultComponents = ReadComponents<MockComponent>().ToList(); resultComponents = ReadComponents<MockComponent>().ToArray();
} }
} }
static List<(MockComponent, Entity)> resultComponentsIncludingEntity; static List<(MockComponent, Entity)> resultComponentsIncludingEntity = new List<(MockComponent, Entity)>();
static (MockComponent, Entity) resultComponentIncludingEntity; static (MockComponent, Entity) resultComponentIncludingEntity;
[Reads(typeof(MockComponent))] [Reads(typeof(MockComponent))]
@ -39,7 +39,11 @@ namespace Tests
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
resultComponentsIncludingEntity = ReadComponentsIncludingEntity<MockComponent>().ToList(); foreach (ref readonly var entity in ReadEntities<MockComponent>())
{
ref readonly var mockComponent = ref GetComponent<MockComponent>(entity);
resultComponentsIncludingEntity.Add((mockComponent, entity));
}
} }
} }
@ -57,7 +61,9 @@ namespace Tests
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
resultComponentIncludingEntity = ReadComponentIncludingEntity<MockComponent>(); ref readonly var entity = ref ReadEntity<MockComponent>();
ref readonly var mockComponent = ref GetComponent<MockComponent>(entity);
resultComponentIncludingEntity = (mockComponent, entity);
} }
} }
@ -90,6 +96,8 @@ namespace Tests
[Test] [Test]
public void ReadComponentsIncludingEntity() public void ReadComponentsIncludingEntity()
{ {
resultComponentsIncludingEntity.Clear();
var worldBuilder = new WorldBuilder(); var worldBuilder = new WorldBuilder();
worldBuilder.AddEngine(new ReadComponentsIncludingEntityEngine()); worldBuilder.AddEngine(new ReadComponentsIncludingEntityEngine());
@ -192,10 +200,8 @@ namespace Tests
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
var (component, entity) = ReadComponentIncludingEntity<MockComponent>(); ref readonly var entity = ref ReadEntity<MockComponent>();
SetComponent(entity, new MockComponent { myInt = 420 });
component.myInt = 420;
SetComponent(entity, component);
} }
} }
@ -229,12 +235,8 @@ namespace Tests
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
var (component, entity) = ReadComponentIncludingEntity<MockComponent>(); ref readonly var entity = ref ReadEntity<MockComponent>();
SetComponent(entity, new MockComponent { myInt = 420 });
component.myInt = 420;
SetComponent(entity, component);
component = ReadComponent<MockComponent>();
} }
} }
@ -564,10 +566,10 @@ namespace Tests
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
var components = ReadComponentsIncludingEntity<MockComponent>(); var entities = ReadEntities<MockComponent>();
pairA = components.First(); pairA = (GetComponent<MockComponent>(entities[0]), entities[0]);
pairB = components.Last(); pairB = (GetComponent<MockComponent>(entities[1]), entities[1]);
} }
} }
@ -597,14 +599,12 @@ namespace Tests
Assert.That(EngineTest.pairA.Item1, Is.EqualTo(EngineTest.pairB.Item1)); Assert.That(EngineTest.pairA.Item1, Is.EqualTo(EngineTest.pairB.Item1));
} }
static IEnumerable<(MockComponent, Entity)> emptyComponentReadResult;
[Reads(typeof(MockComponent))] [Reads(typeof(MockComponent))]
class ReadEmptyMockComponentsEngine : Engine class ReadEmptyMockComponentsEngine : Engine
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
emptyComponentReadResult = ReadComponentsIncludingEntity<MockComponent>(); ReadEntities<MockComponent>().ToArray().Should().BeEmpty();
} }
} }
@ -616,8 +616,6 @@ namespace Tests
var world = worldBuilder.Build(); var world = worldBuilder.Build();
world.Update(0.01f); world.Update(0.01f);
Assert.That(emptyComponentReadResult, Is.Empty);
} }
struct DestroyerComponent { } struct DestroyerComponent { }
@ -627,21 +625,27 @@ namespace Tests
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
foreach (var (component, entity) in ReadComponentsIncludingEntity<DestroyerComponent>()) foreach (ref readonly var entity in ReadEntities<DestroyerComponent>())
{ {
Destroy(entity); Destroy(entity);
} }
} }
} }
static List<(MockComponent, Entity)> results; static List<(MockComponent, Entity)> results = new List<(MockComponent, Entity)>();
[Reads(typeof(MockComponent))] [Reads(typeof(MockComponent))]
class ReaderEngine : Engine class ReaderEngine : Engine
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
results = ReadComponentsIncludingEntity<MockComponent>().ToList(); results.Clear();
foreach (ref readonly var entity in ReadEntities<MockComponent>())
{
ref readonly var mockComponent = ref GetComponent<MockComponent>(entity);
results.Add((mockComponent, entity));
}
} }
} }
@ -693,6 +697,8 @@ namespace Tests
[Test] [Test]
public void DestroyEntityWithoutID() public void DestroyEntityWithoutID()
{ {
results.Clear();
var worldBuilder = new WorldBuilder(); var worldBuilder = new WorldBuilder();
worldBuilder.AddEngine(new AddComponentEngine()); worldBuilder.AddEngine(new AddComponentEngine());
worldBuilder.AddEngine(new DestroyEntityEngine()); worldBuilder.AddEngine(new DestroyEntityEngine());
@ -716,7 +722,7 @@ namespace Tests
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
foreach (var (componentPair, entity) in ReadComponentsIncludingEntity<DestroyerComponent>()) foreach (ref readonly var entity in ReadEntities<DestroyerComponent>())
{ {
RemoveComponent<MockComponent>(entity); RemoveComponent<MockComponent>(entity);
Destroy(entity); Destroy(entity);
@ -748,7 +754,7 @@ namespace Tests
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
foreach (var (mockComponent, entity) in ReadComponentsIncludingEntity<MockComponent>()) foreach (ref readonly var entity in ReadEntities<MockComponent>())
{ {
RemoveComponent<MockComponent>(entity); RemoveComponent<MockComponent>(entity);
SetComponent(entity, new MockComponent()); SetComponent(entity, new MockComponent());
@ -763,7 +769,7 @@ namespace Tests
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
var (_, entity) = ReadComponentIncludingEntity<MockComponent>(); ref readonly var entity = ref ReadEntity<MockComponent>();
} }
} }
@ -788,7 +794,7 @@ namespace Tests
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
foreach (var (component, entity) in ReadComponentsIncludingEntity<MockComponent>()) foreach (ref readonly var entity in ReadEntities<MockComponent>())
{ {
RemoveComponent<MockComponent>(entity); RemoveComponent<MockComponent>(entity);
SendMessage(new MockMessage { }, 1); SendMessage(new MockMessage { }, 1);
@ -835,7 +841,7 @@ namespace Tests
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
foreach (var (component, entity) in ReadComponentsIncludingEntity<MockComponent>()) foreach (ref readonly var entity in ReadEntities<MockComponent>())
{ {
RemoveComponent<MockComponent>(entity); RemoveComponent<MockComponent>(entity);
SendMessageIgnoringTimeDilation(new MockMessage { }, 1); SendMessageIgnoringTimeDilation(new MockMessage { }, 1);
@ -1117,7 +1123,7 @@ namespace Tests
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
foreach (var (_, entity) in ReadComponentsIncludingEntity<MockComponent>()) foreach (ref readonly var entity in ReadEntities<MockComponent>())
{ {
RemoveComponent<MockComponent>(entity); RemoveComponent<MockComponent>(entity);
} }
@ -1312,8 +1318,7 @@ namespace Tests
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
var (component, entity) = ReadComponentIncludingEntity<MockComponent>(); ref readonly var entity = ref ReadEntity<MockComponent>();
AddComponent(entity, new MockComponent()); AddComponent(entity, new MockComponent());
} }
} }
@ -1347,8 +1352,7 @@ namespace Tests
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
var (component, entity) = ReadComponentIncludingEntity<MockComponentB>(); ref readonly var component = ref ReadComponent<MockComponentB>();
getComponentResult = component; getComponentResult = component;
} }
} }
@ -1794,7 +1798,7 @@ namespace Tests
} }
public override void Update(double dt) public override void Update(double dt)
{ {
_components.AddRange(ReadComponents<MockComponentB>()); _components.AddRange(ReadComponents<MockComponentB>().ToArray());
} }
} }
@ -1830,12 +1834,11 @@ namespace Tests
public override void Update(double dt) public override void Update(double dt)
{ {
foreach (var (component, entity) in ReadComponentsIncludingEntity<MockComponent>()) foreach (ref readonly var entity in ReadEntities<MockComponent>())
{ {
if (HasComponent<MockComponentB>(entity)) if (HasComponent<MockComponentB>(entity))
{ {
_components.Add(GetComponent<MockComponentB>(entity)); _components.Add(GetComponent<MockComponentB>(entity));
} }
} }
} }
@ -1862,7 +1865,7 @@ namespace Tests
struct MockTimerComponent struct MockTimerComponent
{ {
public double Timer { get; set; } public double Timer { get; }
public MockTimerComponent(double time) public MockTimerComponent(double time)
{ {
@ -1876,19 +1879,18 @@ namespace Tests
{ {
public override void Update(double dt) public override void Update(double dt)
{ {
foreach (var (component, entity) in ReadComponentsIncludingEntity<MockTimerComponent>()) foreach (ref readonly var entity in ReadEntities<MockTimerComponent>())
{ {
var updatedComponent = component; ref readonly var component = ref GetComponent<MockTimerComponent>(entity);
updatedComponent.Timer -= dt;
if (updatedComponent.Timer <= 0) if (component.Timer - dt <= 0)
{ {
RemoveComponent<MockTimerComponent>(entity); RemoveComponent<MockTimerComponent>(entity);
} }
else else
{ {
SetComponent<MockTimerComponent>(entity, updatedComponent); SetComponent<MockTimerComponent>(entity, new MockTimerComponent(component.Timer - dt));
} }
} }
} }

View File

@ -15,7 +15,8 @@ namespace Tests
{ {
public override void Render() public override void Render()
{ {
result = ReadComponentIncludingEntity<AComponent>(); ref readonly var entity = ref ReadEntity<AComponent>();
result = (GetComponent<AComponent>(entity), entity);
} }
} }