Implement core entity management features

Added `Archetype` struct with chunk management and disposal.
Added `BitSet` class for managing collections of bits.
Added `Class1.cs` as a placeholder for graphics functionality.
Added `ComponentData` struct and `ComponentPool` class for component management.
Added `ComponentRegistry` for efficient component registration.
Added `EntityChangeQueue` as a placeholder for future changes.
Added `Helpers.ttinclude` and `QueryRefComponent.tt` for code generation.
Added `Signature` struct for managing component signatures.
Added `World` struct to manage the game world and entities.
Added `QueryRefComponent` delegates for querying entities.

Changed `Archetype.cs` to implement `IDisposable`.
Changed `AssemblyInfo.cs` to update global using directives.
Changed `Chunk.cs` to introduce `ChunkCollection` for chunk management.
Changed `Component.cs` to refine component management methods.
Changed `Entity.cs` to improve properties and methods.
Changed `Ghost.Entities.csproj` to update project properties.
Changed `Program.cs` to demonstrate entity creation and querying.
Changed `World.Query.cs` to facilitate querying with components.
This commit is contained in:
2025-05-21 11:46:48 +09:00
parent 56a21bab2b
commit 0cf3104a6a
30 changed files with 1702 additions and 240 deletions

View File

@@ -0,0 +1,7 @@
global using EntityID = System.UInt32;
global using GenerationID = System.UInt16;
global using WorldID = System.UInt16;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Ghost.Engine")]

View File

@@ -5,27 +5,27 @@ using System.Runtime.CompilerServices;
namespace Ghost.Entities; namespace Ghost.Entities;
internal struct Chunks : IDisposable internal unsafe struct ChunkCollection : IDisposable
{ {
private UnsafeArray<Chunk> _chunks; private UnsafeArray<Chunk> _chunkStorage;
private int _count; private int _count;
private int _capacity; private int _capacity;
public readonly int Count => _count; public readonly int Count => _count;
public readonly int Capacity => _capacity; public readonly int Capacity => _capacity;
public ref Chunk this[int index] => ref _chunks[index]; public readonly ref Chunk this[int index] => ref _chunkStorage[index];
public Chunks(int capacity) public ChunkCollection(int capacity)
{ {
_chunks = new(capacity, Allocator.Persistent); _chunkStorage = new(capacity, Allocator.Persistent);
_count = 0; _count = 0;
_capacity = capacity; _capacity = capacity;
} }
public void Add(Chunk chunk) public void Add(Chunk chunk)
{ {
_chunks[_count] = chunk; _chunkStorage[_count] = chunk;
_count++; _count++;
} }
@@ -36,7 +36,7 @@ internal struct Chunks : IDisposable
return; return;
} }
_chunks.Resize(newCapacity); _chunkStorage.Resize(newCapacity);
} }
public void TrimExcess() public void TrimExcess()
@@ -46,14 +46,14 @@ internal struct Chunks : IDisposable
return; return;
} }
_chunks.Resize(_count); _chunkStorage.Resize(_count);
} }
public void Clear() public void Clear()
{ {
for (var i = 0; i < _count; i++) for (var i = 0; i < _count; i++)
{ {
_chunks[i].Clear(); _chunkStorage[i].Clear();
} }
_count = 0; _count = 0;
@@ -63,17 +63,17 @@ internal struct Chunks : IDisposable
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly Span<Chunk> AsSpan() public readonly Span<Chunk> AsSpan()
{ {
return _chunks.AsSpan(); return _chunkStorage.AsSpan();
} }
public void Dispose() public void Dispose()
{ {
for (var i = 0; i < _count; i++) for (var i = 0; i < _count; i++)
{ {
_chunks[i].Dispose(); _chunkStorage[i].Dispose();
} }
_chunks.Dispose(); _chunkStorage.Dispose();
_count = 0; _count = 0;
_capacity = 0; _capacity = 0;
} }
@@ -104,7 +104,7 @@ internal struct Chunk : IDisposable
_count = 0; _count = 0;
_capacity = capacity; _capacity = capacity;
entities = new(capacity, Allocator.Persistent); entities = new((int)capacity, Allocator.Persistent);
components = new(data.Length, Allocator.Persistent); components = new(data.Length, Allocator.Persistent);
_componentLookup = lookup; _componentLookup = lookup;
@@ -112,7 +112,7 @@ internal struct Chunk : IDisposable
for (var i = 0; i < data.Length; i++) for (var i = 0; i < data.Length; i++)
{ {
var component = data[i]; var component = data[i];
components[component.id] = new UnsafeArray<byte>(capacity * component.sizeInByte, Allocator.Persistent); components[component.id] = new UnsafeArray<byte>(capacity * (int)component.sizeInByte, Allocator.Persistent);
} }
} }

View File

@@ -0,0 +1,116 @@
using Ghost.Entities.Helpers;
using Ghost.Entities.Registries;
using Misaki.HighPerformance.Unsafe.Collections;
using Misaki.HighPerformance.Unsafe.Helpers;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Ghost.Entities;
public interface IComponent
{
}
[SkipLocalsInit]
internal readonly record struct ComponentData
{
public readonly int id;
public readonly int sizeInByte;
public ComponentData(int id, int sizeInByte)
{
this.id = id;
this.sizeInByte = sizeInByte;
}
}
internal static class Component
{
internal static int GetTotalSize(in Span<ComponentData> datas)
{
var size = 0;
foreach (var type in datas)
{
var typeSize = type.sizeInByte;
typeSize = typeSize != 1 ? typeSize : 0; // Ignore tag components
size += typeSize;
}
return size;
}
internal static unsafe UnsafeArray<int> ToLookupArray(in Span<ComponentData> datas, Allocator allocator)
{
var max = 0;
foreach (var data in datas)
{
var componentId = data.id;
if (componentId >= max)
{
max = componentId;
}
}
// Create lookup table where the component ID points to the component index.
var array = new UnsafeArray<int>(max + 1, allocator);
array.AsSpan().Fill(-1);
for (var index = 0; index < datas.Length; index++)
{
ref var type = ref datas[index];
var componentId = type.id;
array[componentId] = index;
}
return array;
}
internal static int GetHashCode(Span<ComponentData> components)
{
// Search for the highest id to determine how much uints we need for the stack.
var highestId = 0;
foreach (ref var cmp in components)
{
if (cmp.id > highestId)
{
highestId = cmp.id;
}
}
// Allocate the stack and set bits to replicate a bitset
var length = BitSet.RequiredLength(highestId + 1);
Span<uint> stack = stackalloc uint[length];
var spanBitSet = new SpanBitSet(stack);
foreach (ref var type in components)
{
var x = type.id;
spanBitSet.SetBit(x);
}
return GetHashCode(stack);
}
public static int GetHashCode(Span<uint> span)
{
var hashCode = new HashCode();
hashCode.AddBytes(MemoryMarshal.AsBytes(span));
return hashCode.ToHashCode();
}
}
internal static class Component<T>
where T : unmanaged, IComponent
{
public static readonly ComponentData data;
public static readonly Signature signature;
static Component()
{
data = ComponentRegistry.GetOrAdd<T>();
signature = new Signature(data);
}
}

View File

@@ -0,0 +1,19 @@
using Misaki.HighPerformance.Unsafe.Collections;
namespace Ghost.Entities.Core;
internal partial struct Archetype : IEquatable<Archetype>
{
public void AddInsertionEdge(Archetype archetype)
{
if (_insertionEdges.IsCreated)
{
_insertionEdges = new UnsafeHashSet<Archetype>(_BUCKET_SIZE, Allocator.Persistent);
}
_insertionEdges.Add(archetype);
}
public readonly bool Equals(Archetype other)
{
return signature.Equals(other.signature);
}
}

View File

@@ -0,0 +1,76 @@
using Ghost.Entities.Helpers;
using Misaki.HighPerformance.Unsafe.Collections;
using Misaki.HighPerformance.Unsafe.Helpers;
namespace Ghost.Entities.Core;
internal partial struct Archetype : IDisposable
{
private const int _BUCKET_SIZE = 16;
// The component ID to array index lookup array.
private UnsafeArray<int> _lookupArray;
public readonly int sizeOfBaseChunk;
public readonly int sizeOfChunk;
public readonly int entitiesPerChunk;
public int totalEntityCount;
public Signature signature;
// For fast lookups
public BitSet bitSet;
public ChunkCollection chunks;
private UnsafeHashSet<Archetype> _insertionEdges;
private UnsafeHashSet<Archetype> _deletionEdges;
public readonly UnsafeArray<int> LookupArray => _lookupArray;
internal Archetype(Signature signature, int sizeOfBaseChunk, int minimalEntityCountPerChunk)
{
this.signature = signature;
this.sizeOfBaseChunk = sizeOfBaseChunk;
var sizeOfTotalData = Component.GetTotalSize(signature.componentDatas.AsSpan());
sizeOfChunk = GetSizeOfChunk(sizeOfBaseChunk, minimalEntityCountPerChunk, sizeOfTotalData);
entitiesPerChunk = GetEntityCount(sizeOfChunk, sizeOfTotalData);
_lookupArray = Component.ToLookupArray(signature.componentDatas.AsSpan(), Allocator.Persistent);
bitSet = new BitSet();
for (var i = 0; i < signature.componentDatas.Count; i++)
{
bitSet.SetBit(signature.componentDatas[i].id);
}
chunks = new ChunkCollection(1);
AddNewChunk();
}
private unsafe static int GetEntityCount(int sizeOfChunk, int sizeOfTotalData)
{
return sizeOfChunk / (sizeof(Entity) + sizeOfTotalData);
}
private static unsafe int GetSizeOfChunk(int sizeOfBaseChunk, int entityCount, int sizeOfTotalData)
{
var entityBytes = (sizeof(Entity) + sizeOfTotalData) * entityCount;
return (int)Math.Ceiling((float)entityBytes / sizeOfBaseChunk) * sizeOfBaseChunk; // Calculates and rounds to a multiple of BaseSize to store the number of entities
}
public ref Chunk AddNewChunk()
{
chunks.EnsureCapacity(chunks.Count + 1);
chunks.Add(new Chunk(entitiesPerChunk, signature.componentDatas.AsSpan(), _lookupArray));
return ref chunks[^1];
}
public void Dispose()
{
_lookupArray.Dispose();
signature.Dispose();
bitSet.Dispose();
chunks.Dispose();
}
}

View File

@@ -0,0 +1,105 @@
using System.Runtime.CompilerServices;
namespace Ghost.Entities.Core;
/// <summary>
/// The <see cref="Slot"/> struct references an <see cref="Entity"/> entry within an <see cref="Archetype"/> using a reference to its <see cref="Chunk"/> and its index.
/// </summary>
[SkipLocalsInit]
internal record struct Slot
{
/// <summary>
/// The index of the <see cref="Entity"/> in the <see cref="Chunk"/>.
/// </summary>
public int index;
/// <summary>
/// The index of the <see cref="Chunk"/> in which the <see cref="Entity"/> is located.
/// </summary>
public int chunkIndex;
/// <summary>
/// Initializes a new instance of the <see cref="Slot"/> struct.
/// </summary>
/// <param name="index">The index of the <see cref="Entity"/> in the <see cref="Chunk"/>.</param>
/// <param name="chunkIndex">The index of the <see cref="Chunk"/> in which the <see cref="Entity"/> is located.</param>
public Slot(int index, int chunkIndex)
{
this.index = index;
this.chunkIndex = chunkIndex;
}
/// <summary>
/// Adds a plus operator for easy calculation of new <see cref="Slot"/>. Adds the positions of both <see cref="Slot"/>s.
/// </summary>
/// <param name="first">The first <see cref="Slot"/>.</param>
/// <param name="second">The second <see cref="Slot"/>.</param>
/// <returns>The result <see cref="Slot"/>.</returns>
public static Slot operator +(Slot first, Slot second)
{
return new Slot(first.index + second.index, first.chunkIndex + second.chunkIndex);
}
/// <summary>
/// Adds a plus plus operator for easy calculation of new <see cref="Slot"/>. Increases the index by one.
/// </summary>
/// <param name="slot">The <see cref="Slot"/>.</param>
/// <returns>The <see cref="Slot"/> with index increased by one..</returns>
public static Slot operator ++(Slot slot)
{
slot.index++;
return slot;
}
/// <summary>
/// Validates the <see cref="Slot"/>, moves the <see cref="Slot"/> if it is outside a <see cref="Chunk.Capacity"/> to match it.
/// </summary>
/// <returns></returns>
public void Wrap(int capacity)
{
// Result outside valid chunk, wrap into next one
if (index < capacity)
{
return;
}
// Index outside of its chunk, so we calculate how many times a chunk fit into the index for adjusting the chunkindex to that position.
// Floor since we do not need a rounded value since the index is within that chunk and not the next one.
chunkIndex += (int)Math.Floor(index / (float)capacity);
// After moving the chunk index we can simply take the rest and assign it as a index.
index %= capacity;
}
/// <summary>
/// Moves or shifts this <see cref="Slot"/> by one slot forward.
/// Ensures that the slots chunkindex updated properly once the end was reached.
/// </summary>
/// <param name="source">The <see cref="Slot"/> to shift by one.</param>
/// <param name="sourceCapacity">The capacity of the chunk the slot is in.</param>
/// <returns></returns>
public static Slot Shift(ref Slot source, int sourceCapacity)
{
source.index++;
source.Wrap(sourceCapacity);
return source;
}
/// <summary>
/// Moves or shifts the source <see cref="Slot"/> based on the destination <see cref="Slot"/> and calculates its new position.
/// Used for copy operations to predict where the source <see cref="Slot"/> will end up.
/// </summary>
/// <param name="source">The source <see cref="Slot"/>, from which we want to calculate where it lands..</param>
/// <param name="destination">The destination <see cref="Slot"/>, a reference point at which the copy or shift operation starts.</param>
/// <param name="sourceCapacity">The source <see cref="Chunk.Capacity"/>.</param>
/// <param name="destinationCapacity">The destination <see cref="Chunk.Capacity"/></param>
public static Slot Shift(in Slot source, int sourceCapacity, in Slot destination, int destinationCapacity)
{
var freeSpot = destination;
var resultSlot = source + freeSpot;
resultSlot.index += source.chunkIndex * (sourceCapacity - destinationCapacity);
resultSlot.Wrap(destinationCapacity);
return resultSlot;
}
}

View File

@@ -0,0 +1,93 @@
using System.Runtime.CompilerServices;
namespace Ghost.Entities;
[SkipLocalsInit]
public struct Entity : IEquatable<Entity>, IComparable<Entity>
{
private const EntityID _WORLD_INDEX_BITS = 4u;
private const EntityID _GENERATION_BITS = 8u;
private const EntityID _INDEX_BITS = sizeof(EntityID) * 8 - _WORLD_INDEX_BITS - _GENERATION_BITS;
private const EntityID _WORLD_INDEX_MASK = (1u << (int)_WORLD_INDEX_BITS) - 1;
private const EntityID _GENERATION_MASK = (1u << (int)_GENERATION_BITS) - 1;
private const EntityID _INDEX_MASK = (1u << (int)_INDEX_BITS) - 1;
private const EntityID _ID_MASK = EntityID.MaxValue;
private EntityID _id;
public readonly bool IsValid
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _id != _ID_MASK;
}
public readonly EntityID Index
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _id & _INDEX_MASK;
}
public readonly GenerationID Generation
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => (GenerationID)(_id >> (int)_INDEX_BITS & _GENERATION_MASK);
}
public readonly WorldID WorldIndex
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => (WorldID)(_id >> (int)(_INDEX_BITS + _GENERATION_BITS) & _WORLD_INDEX_MASK);
}
public void IncrementGeneration()
{
var generation = Generation + 1u;
if (generation >= _GENERATION_MASK)
{
throw new InvalidOperationException("Generation overflow");
}
_id = _id & ~(_GENERATION_MASK << (int)_INDEX_BITS) | generation << (int)_INDEX_BITS;
}
internal Entity(EntityID index, EntityID generation, EntityID worldIndex)
{
_id = worldIndex << (int)(_INDEX_BITS + _GENERATION_BITS) | generation << (int)_INDEX_BITS | index;
}
public readonly bool Equals(Entity other)
{
return _id == other._id;
}
public readonly int CompareTo(Entity other)
{
return _id.CompareTo(other._id);
}
public override readonly bool Equals(object? obj)
{
return obj is Entity other && Equals(other);
}
public override readonly int GetHashCode()
{
return _id.GetHashCode();
}
public static bool operator ==(Entity left, Entity right)
{
return left.Equals(right);
}
public static bool operator !=(Entity left, Entity right)
{
return !(left == right);
}
public override readonly string ToString()
{
return $"Entity {{ Index: {Index}, Generation: {Generation}, WorldIndex: {WorldIndex} }}";
}
}

View File

@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<IsAotCompatible>True</IsAotCompatible>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<IsAotCompatible>True</IsAotCompatible>
</PropertyGroup>
<ItemGroup>
<Reference Include="Misaki.HighPerformance.Unsafe">
<HintPath>..\..\Class\Misaki.HighPerformance\Misaki.HighPerformance.Unsafe\bin\Release\net9.0\Misaki.HighPerformance.Unsafe.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View File

@@ -1,5 +1,7 @@
// Code from https://github.com/genaray/Arch/blob/master/src/Arch/Core/Utils/BitSet.cs // Code from https://github.com/genaray/Arch/blob/master/src/Arch/Core/Utils/BitSet.cs
using Misaki.HighPerformance.Unsafe.Collections;
using Misaki.HighPerformance.Unsafe.Helpers;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text; using System.Text;
@@ -12,7 +14,7 @@ namespace Ghost.Entities.Helpers;
/// The <see cref="BitSet"/> class /// The <see cref="BitSet"/> class
/// represents a resizable collection of bits. /// represents a resizable collection of bits.
/// </summary> /// </summary>
public sealed class BitSet public struct BitSet : IDisposable
{ {
private const int _BIT_SIZE = (sizeof(uint) * 8) - 1; // 31 private const int _BIT_SIZE = (sizeof(uint) * 8) - 1; // 31
private const int _INDEX_SIZE = 5; // log_2(BitSize + 1) private const int _INDEX_SIZE = 5; // log_2(BitSize + 1)
@@ -33,7 +35,7 @@ public sealed class BitSet
/// <summary> /// <summary>
/// The bits from the bitset. /// The bits from the bitset.
/// </summary> /// </summary>
private uint[] _bits; private UnsafeArray<uint> _bits;
/// TODO: Update on ClearBit, however clearbit is only used in tests so its fine for now. /// TODO: Update on ClearBit, however clearbit is only used in tests so its fine for now.
/// <summary> /// <summary>
@@ -52,21 +54,22 @@ public sealed class BitSet
/// </summary> /// </summary>
public BitSet() public BitSet()
{ {
_bits = new uint[_padding]; _bits = new UnsafeArray<uint>(_padding, Allocator.Persistent);
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="BitSet" /> class. /// Initializes a new instance of the <see cref="BitSet" /> class.
/// </summary> /// </summary>
public BitSet(params uint[] bits) public BitSet(params Span<uint> bits)
{ {
_bits = bits; _bits = new UnsafeArray<uint>(bits.Length, Allocator.Persistent);
_bits.CopyFrom(bits);
} }
/// <summary> /// <summary>
/// The highest uint index in use inside the <see cref="_bits"/>-array. /// The highest uint index in use inside the <see cref="_bits"/>-array.
/// </summary> /// </summary>
public int HighestIndex public readonly int HighestIndex
{ {
get => _max; get => _max;
} }
@@ -74,17 +77,17 @@ public sealed class BitSet
/// <summary> /// <summary>
/// The highest bit set. /// The highest bit set.
/// </summary> /// </summary>
public int HighestBit public readonly int HighestBit
{ {
get => _highestBit; get => _highestBit;
} }
/// <summary> /// <summary>
/// Returns the length of the bitset, how many ints it consists of. /// Returns the length of the bitset, how many int's it consists of.
/// </summary> /// </summary>
public int Length public readonly int Count
{ {
get => _bits.Length; get => _bits.Count;
} }
/// <summary> /// <summary>
@@ -92,10 +95,10 @@ public sealed class BitSet
/// </summary> /// </summary>
/// <param name="index">The index.</param> /// <param name="index">The index.</param>
/// <returns>True if it is, otherwise false</returns> /// <returns>True if it is, otherwise false</returns>
public bool IsSet(int index) public readonly bool IsSet(int index)
{ {
var b = index >> _INDEX_SIZE; var b = index >> _INDEX_SIZE;
if (b >= _bits.Length) if (b >= _bits.Count)
{ {
return false; return false;
} }
@@ -111,9 +114,9 @@ public sealed class BitSet
public void SetBit(int index) public void SetBit(int index)
{ {
var b = index >> _INDEX_SIZE; var b = index >> _INDEX_SIZE;
if (b >= _bits.Length) if (b >= _bits.Count)
{ {
Array.Resize(ref _bits, (b + _padding) / _padding * _padding); // Round up to a multiply of Padding _bits.Resize((b + _padding) / _padding * _padding); // Round up to a multiply of Padding
} }
// Track highest set bit // Track highest set bit
@@ -126,10 +129,10 @@ public sealed class BitSet
/// Clears the bit at the given index. /// Clears the bit at the given index.
/// </summary> /// </summary>
/// <param name="index">The index.</param> /// <param name="index">The index.</param>
public void ClearBit(int index) public readonly void ClearBit(int index)
{ {
var b = index >> _INDEX_SIZE; var b = index >> _INDEX_SIZE;
if (b >= _bits.Length) if (b >= _bits.Count)
{ {
return; return;
} }
@@ -142,22 +145,22 @@ public sealed class BitSet
/// </summary> /// </summary>
public void SetAll() public void SetAll()
{ {
var count = _bits.Length; var count = _bits.Count;
for (var i = 0; i < count; i++) for (var i = 0; i < count; i++)
{ {
_bits[i] = 0xffffffff; _bits[i] = 0xffffffff;
} }
_highestBit = (_bits.Length * (_BIT_SIZE + 1)) - 1; _highestBit = (_bits.Count * (_BIT_SIZE + 1)) - 1;
_max = (_highestBit / (_BIT_SIZE + 1)) + 1; _max = (_highestBit / (_BIT_SIZE + 1)) + 1;
} }
/// <summary> /// <summary>
/// Clears all set bits. /// Clears all set bits.
/// </summary> /// </summary>
public void ClearAll() public readonly void ClearAll()
{ {
Array.Clear(_bits, 0, _bits.Length); _bits.Clear();
} }
/// <summary> /// <summary>
@@ -166,19 +169,16 @@ public sealed class BitSet
/// <param name="other">The other <see cref="BitSet"/>.</param> /// <param name="other">The other <see cref="BitSet"/>.</param>
/// <returns>True if they match, false if not.</returns> /// <returns>True if they match, false if not.</returns>
[SkipLocalsInit] [SkipLocalsInit]
public bool All(BitSet other) public readonly bool All(BitSet other)
{ {
var min = Math.Min(Math.Min(Length, other.Length), _max); var min = Math.Min(Math.Min(Count, other.Count), _max);
if (!Vector.IsHardwareAccelerated || min < _padding) if (!Vector.IsHardwareAccelerated || min < _padding)
{ {
var bits = _bits.AsSpan();
var otherBits = other._bits.AsSpan();
// Bitwise and // Bitwise and
for (var i = 0; i < min; i++) for (var i = 0; i < min; i++)
{ {
var bit = bits[i]; var bit = _bits[i];
if ((bit & otherBits[i]) != bit) if ((bit & other._bits[i]) != bit)
{ {
return false; return false;
} }
@@ -187,7 +187,7 @@ public sealed class BitSet
// Handle extra bits on our side that might just be all zero. // Handle extra bits on our side that might just be all zero.
for (var i = min; i < _max; i++) for (var i = min; i < _max; i++)
{ {
if (bits[i] != 0) if (_bits[i] != 0)
{ {
return false; return false;
} }
@@ -198,8 +198,8 @@ public sealed class BitSet
// Vectorized bitwise and // Vectorized bitwise and
for (var i = 0; i < min; i += _padding) for (var i = 0; i < min; i += _padding)
{ {
var vector = new Vector<uint>(_bits, i); var vector = new Vector<uint>(_bits.AsSpan()[i..]);
var otherVector = new Vector<uint>(other._bits, i); var otherVector = new Vector<uint>(other._bits.AsSpan()[i..]);
var resultVector = Vector.BitwiseAnd(vector, otherVector); var resultVector = Vector.BitwiseAnd(vector, otherVector);
if (!Vector.EqualsAll(resultVector, vector)) if (!Vector.EqualsAll(resultVector, vector))
@@ -211,7 +211,7 @@ public sealed class BitSet
// Handle extra bits on our side that might just be all zero. // Handle extra bits on our side that might just be all zero.
for (var i = min; i < _max; i += _padding) for (var i = min; i < _max; i += _padding)
{ {
var vector = new Vector<uint>(_bits, i); var vector = new Vector<uint>(_bits.AsSpan()[i..]);
if (!Vector.EqualsAll(vector, Vector<uint>.Zero)) // Vectors are not zero bits[0] != 0 basically if (!Vector.EqualsAll(vector, Vector<uint>.Zero)) // Vectors are not zero bits[0] != 0 basically
{ {
return false; return false;
@@ -227,9 +227,9 @@ public sealed class BitSet
/// </summary> /// </summary>
/// <param name="other">The other <see cref="BitSet"/>.</param> /// <param name="other">The other <see cref="BitSet"/>.</param>
/// <returns>True if they match, false if not.</returns> /// <returns>True if they match, false if not.</returns>
public bool Any(BitSet other) public readonly bool Any(BitSet other)
{ {
var min = Math.Min(Math.Min(Length, other.Length), _max); var min = Math.Min(Math.Min(Count, other.Count), _max);
if (!Vector.IsHardwareAccelerated || min < _padding) if (!Vector.IsHardwareAccelerated || min < _padding)
{ {
var bits = _bits.AsSpan(); var bits = _bits.AsSpan();
@@ -259,8 +259,8 @@ public sealed class BitSet
// Vectorized bitwise and, return true since any is met // Vectorized bitwise and, return true since any is met
for (var i = 0; i < min; i += _padding) for (var i = 0; i < min; i += _padding)
{ {
var vector = new Vector<uint>(_bits, i); var vector = new Vector<uint>(_bits.AsSpan()[i..]);
var otherVector = new Vector<uint>(other._bits, i); var otherVector = new Vector<uint>(other._bits.AsSpan()[i..]);
var resultVector = Vector.BitwiseAnd(vector, otherVector); var resultVector = Vector.BitwiseAnd(vector, otherVector);
if (!Vector.EqualsAll(resultVector, Vector<uint>.Zero)) if (!Vector.EqualsAll(resultVector, Vector<uint>.Zero))
@@ -272,7 +272,7 @@ public sealed class BitSet
// Handle extra bits on our side that might just be all zero. // Handle extra bits on our side that might just be all zero.
for (var i = min; i < _max; i += _padding) for (var i = min; i < _max; i += _padding)
{ {
var vector = new Vector<uint>(_bits, i); var vector = new Vector<uint>(_bits.AsSpan()[i..]);
if (!Vector.EqualsAll(vector, Vector<uint>.Zero)) // Vectors are not zero bits[0] != 0 basically if (!Vector.EqualsAll(vector, Vector<uint>.Zero)) // Vectors are not zero bits[0] != 0 basically
{ {
return false; return false;
@@ -288,9 +288,9 @@ public sealed class BitSet
/// </summary> /// </summary>
/// <param name="other">The other <see cref="BitSet"/>.</param> /// <param name="other">The other <see cref="BitSet"/>.</param>
/// <returns>True if none match, false if not.</returns> /// <returns>True if none match, false if not.</returns>
public bool None(BitSet other) public readonly bool None(BitSet other)
{ {
var min = Math.Min(Math.Min(Length, other.Length), _max); var min = Math.Min(Math.Min(Count, other.Count), _max);
if (!Vector.IsHardwareAccelerated || min < _padding) if (!Vector.IsHardwareAccelerated || min < _padding)
{ {
var bits = _bits.AsSpan(); var bits = _bits.AsSpan();
@@ -311,8 +311,8 @@ public sealed class BitSet
// Vectorized bitwise and, return true since any is met // Vectorized bitwise and, return true since any is met
for (var i = 0; i < min; i += _padding) for (var i = 0; i < min; i += _padding)
{ {
var vector = new Vector<uint>(_bits, i); var vector = new Vector<uint>(_bits.AsSpan()[i..]);
var otherVector = new Vector<uint>(other._bits, i); var otherVector = new Vector<uint>(other._bits.AsSpan()[i..]);
var resultVector = Vector.BitwiseAnd(vector, otherVector); var resultVector = Vector.BitwiseAnd(vector, otherVector);
if (!Vector.EqualsAll(resultVector, Vector<uint>.Zero)) if (!Vector.EqualsAll(resultVector, Vector<uint>.Zero))
@@ -330,9 +330,9 @@ public sealed class BitSet
/// </summary> /// </summary>
/// <param name="other">The other <see cref="BitSet"/>.</param> /// <param name="other">The other <see cref="BitSet"/>.</param>
/// <returns>True if they match, false if not.</returns> /// <returns>True if they match, false if not.</returns>
public bool Exclusive(BitSet other) public readonly bool Exclusive(BitSet other)
{ {
var min = Math.Min(Math.Min(Length, other.Length), _max); var min = Math.Min(Math.Min(Count, other.Count), _max);
if (!Vector.IsHardwareAccelerated || min < _padding) if (!Vector.IsHardwareAccelerated || min < _padding)
{ {
@@ -363,8 +363,8 @@ public sealed class BitSet
// Vectorized bitwise xor, return true since any is met // Vectorized bitwise xor, return true since any is met
for (var i = 0; i < min; i += _padding) for (var i = 0; i < min; i += _padding)
{ {
var vector = new Vector<uint>(_bits, i); var vector = new Vector<uint>(_bits.AsSpan()[i..]);
var otherVector = new Vector<uint>(other._bits, i); var otherVector = new Vector<uint>(other._bits.AsSpan()[i..]);
var resultVector = Vector.Xor(vector, otherVector); var resultVector = Vector.Xor(vector, otherVector);
if (!Vector.EqualsAll(resultVector, Vector<uint>.Zero)) if (!Vector.EqualsAll(resultVector, Vector<uint>.Zero))
@@ -376,7 +376,7 @@ public sealed class BitSet
// Handle extra bits on our side that might just be all zero. // Handle extra bits on our side that might just be all zero.
for (var i = min; i < _max; i += _padding) for (var i = min; i < _max; i += _padding)
{ {
var vector = new Vector<uint>(_bits, i); var vector = new Vector<uint>(_bits.AsSpan()[i..]);
if (!Vector.EqualsAll(vector, Vector<uint>.Zero)) // Vectors are not zero bits[0] != 0 basically if (!Vector.EqualsAll(vector, Vector<uint>.Zero)) // Vectors are not zero bits[0] != 0 basically
{ {
return false; return false;
@@ -391,7 +391,7 @@ public sealed class BitSet
/// Creates a <see cref="Span{T}"/> to access the <see cref="_bits"/>. /// Creates a <see cref="Span{T}"/> to access the <see cref="_bits"/>.
/// </summary> /// </summary>
/// <returns>The hash.</returns> /// <returns>The hash.</returns>
public Span<uint> AsSpan() public readonly Span<uint> AsSpan()
{ {
var max = (_highestBit / (_BIT_SIZE + 1)) + 1; var max = (_highestBit / (_BIT_SIZE + 1)) + 1;
return _bits.AsSpan()[0..max]; return _bits.AsSpan()[0..max];
@@ -403,10 +403,10 @@ public sealed class BitSet
/// <param name="span">The <see cref="Span{T}"/> to copy into.</param> /// <param name="span">The <see cref="Span{T}"/> to copy into.</param>
/// <param name="zero">If true, it will zero the unused space from the <see cref="span"/>.</param> /// <param name="zero">If true, it will zero the unused space from the <see cref="span"/>.</param>
/// <returns>The <see cref="Span{T}"/>.</returns> /// <returns>The <see cref="Span{T}"/>.</returns>
public Span<uint> AsSpan(Span<uint> span, bool zero = true) public readonly Span<uint> AsSpan(Span<uint> span, bool zero = true)
{ {
// Copy everything thats possible from one to another // Copy everything that's possible from one to another
var length = Math.Min(Length, span.Length); var length = Math.Min(Count, span.Length);
for (var index = 0; index < length; index++) for (var index = 0; index < length; index++)
{ {
span[index] = _bits[index]; span[index] = _bits[index];
@@ -425,7 +425,7 @@ public sealed class BitSet
/// Calculates the hash, this is unique for the set bits. Two <see cref="BitSet"/> with the same set bits, result in the same hash. /// Calculates the hash, this is unique for the set bits. Two <see cref="BitSet"/> with the same set bits, result in the same hash.
/// </summary> /// </summary>
/// <returns>The hash.</returns> /// <returns>The hash.</returns>
public override int GetHashCode() public readonly override int GetHashCode()
{ {
return Component.GetHashCode(AsSpan()); return Component.GetHashCode(AsSpan());
} }
@@ -434,7 +434,7 @@ public sealed class BitSet
/// Prints the content of this instance. /// Prints the content of this instance.
/// </summary> /// </summary>
/// <returns>The string.</returns> /// <returns>The string.</returns>
public override string ToString() public readonly override string ToString()
{ {
// Convert uint to binary form for pretty printing // Convert uint to binary form for pretty printing
var binaryBuilder = new StringBuilder(); var binaryBuilder = new StringBuilder();
@@ -444,7 +444,12 @@ public sealed class BitSet
} }
binaryBuilder.Length--; binaryBuilder.Length--;
return $"{nameof(_bits)}: {binaryBuilder}, {nameof(Length)}: {Length}"; return $"{nameof(_bits)}: {binaryBuilder}, {nameof(Count)}: {Count}";
}
public void Dispose()
{
_bits.Dispose();
} }
} }
@@ -455,9 +460,9 @@ public sealed class BitSet
/// </summary> /// </summary>
public readonly ref struct SpanBitSet public readonly ref struct SpanBitSet
{ {
private const int BitSize = (sizeof(uint) * 8) - 1; // 31 private const int _BIT_SIZE = (sizeof(uint) * 8) - 1; // 31
// NOTE: Is a byte not 8 bits? // NOTE: Is a byte not 8 bits?
private const int ByteSize = 5; // log_2(BitSize + 1) private const int _BYTE_SIZE = 5; // log_2(BitSize + 1)
/// <summary> /// <summary>
/// The bits from the bitset. /// The bits from the bitset.
@@ -477,16 +482,15 @@ public readonly ref struct SpanBitSet
/// </summary> /// </summary>
/// <param name="index">The index.</param> /// <param name="index">The index.</param>
/// <returns>True if it is, otherwise false</returns> /// <returns>True if it is, otherwise false</returns>
public bool IsSet(int index) public bool IsSet(int index)
{ {
var b = index >> ByteSize; var b = index >> _BYTE_SIZE;
if (b >= _bits.Length) if (b >= _bits.Length)
{ {
return false; return false;
} }
return (_bits[b] & (1 << (index & BitSize))) != 0; return (_bits[b] & (1 << (index & _BIT_SIZE))) != 0;
} }
/// <summary> /// <summary>
@@ -494,38 +498,35 @@ public readonly ref struct SpanBitSet
/// Resizes its internal array if necessary. /// Resizes its internal array if necessary.
/// </summary> /// </summary>
/// <param name="index">The index.</param> /// <param name="index">The index.</param>
public void SetBit(int index) public void SetBit(int index)
{ {
var b = index >> ByteSize; var b = index >> _BYTE_SIZE;
if (b >= _bits.Length) if (b >= _bits.Length)
{ {
return; return;
} }
_bits[b] |= 1u << (index & BitSize); _bits[b] |= 1u << (index & _BIT_SIZE);
} }
/// <summary> /// <summary>
/// Clears the bit at the given index. /// Clears the bit at the given index.
/// </summary> /// </summary>
/// <param name="index">The index.</param> /// <param name="index">The index.</param>
public void ClearBit(int index) public void ClearBit(int index)
{ {
var b = index >> ByteSize; var b = index >> _BYTE_SIZE;
if (b >= _bits.Length) if (b >= _bits.Length)
{ {
return; return;
} }
_bits[b] &= ~(1u << (index & BitSize)); _bits[b] &= ~(1u << (index & _BIT_SIZE));
} }
/// <summary> /// <summary>
/// /// Sets all bits.
/// </summary> /// </summary>
public void SetAll() public void SetAll()
{ {
var count = _bits.Length; var count = _bits.Length;
@@ -538,7 +539,6 @@ public readonly ref struct SpanBitSet
/// <summary> /// <summary>
/// Clears all set bits. /// Clears all set bits.
/// </summary> /// </summary>
public void ClearAll() public void ClearAll()
{ {
_bits.Clear(); _bits.Clear();
@@ -548,7 +548,6 @@ public readonly ref struct SpanBitSet
/// Creates a <see cref="Span{T}"/> to access the <see cref="_bits"/>. /// Creates a <see cref="Span{T}"/> to access the <see cref="_bits"/>.
/// </summary> /// </summary>
/// <returns>The hash.</returns> /// <returns>The hash.</returns>
public Span<uint> AsSpan() public Span<uint> AsSpan()
{ {
return _bits; return _bits;
@@ -559,7 +558,6 @@ public readonly ref struct SpanBitSet
/// </summary> /// </summary>
/// <param name=""></param> /// <param name=""></param>
/// <returns>The hash.</returns> /// <returns>The hash.</returns>
public Span<uint> AsSpan(Span<uint> span, bool zero = true) public Span<uint> AsSpan(Span<uint> span, bool zero = true)
{ {
// Prevent exception because target array is to small for copy operation // Prevent exception because target array is to small for copy operation
@@ -582,7 +580,6 @@ public readonly ref struct SpanBitSet
/// Calculates the hash, this is unique for the set bits. Two <see cref="BitSet"/> with the same set bits, result in the same hash. /// Calculates the hash, this is unique for the set bits. Two <see cref="BitSet"/> with the same set bits, result in the same hash.
/// </summary> /// </summary>
/// <returns>The hash.</returns> /// <returns>The hash.</returns>
public override int GetHashCode() public override int GetHashCode()
{ {
return Component.GetHashCode(AsSpan()); return Component.GetHashCode(AsSpan());
@@ -592,7 +589,6 @@ public readonly ref struct SpanBitSet
/// Prints the content of this instance. /// Prints the content of this instance.
/// </summary> /// </summary>
/// <returns>The string.</returns> /// <returns>The string.</returns>
public override string ToString() public override string ToString()
{ {
// Convert uint to binary form for pretty printing // Convert uint to binary form for pretty printing

View File

@@ -0,0 +1,53 @@
using Misaki.HighPerformance.Unsafe.Collections;
using Misaki.HighPerformance.Unsafe.Helpers;
namespace Ghost.Entities;
internal struct Signature : IDisposable, IEquatable<Signature>
{
public UnsafeArray<ComponentData> componentDatas;
private int _hashCode;
public Signature(params Span<ComponentData> components)
{
componentDatas = new UnsafeArray<ComponentData>(components.Length, Allocator.Persistent);
componentDatas.CopyFrom(components);
_hashCode = -1;
_hashCode = GetHashCode();
}
public bool Equals(Signature other)
{
return GetHashCode() == other.GetHashCode();
}
public override bool Equals(object? obj)
{
if (obj is Signature other)
{
return Equals(other);
}
return false;
}
public override int GetHashCode()
{
if (_hashCode != -1)
{
return _hashCode;
}
unchecked
{
_hashCode = Component.GetHashCode(componentDatas.AsSpan());
return _hashCode;
}
}
public void Dispose()
{
componentDatas.Dispose();
}
}

View File

@@ -1,5 +0,0 @@
namespace Ghost.Entities;
public struct Archetype
{
}

View File

@@ -1,4 +1,4 @@
global using EntityID = System.UInt32; global using EntityID = System.Int32;
global using GenerationID = System.UInt16; global using GenerationID = System.UInt16;
global using WorldID = System.UInt16; global using WorldID = System.UInt16;

View File

@@ -1,103 +1,112 @@
using Ghost.Entities.Helpers; namespace Ghost.Entities;
using Ghost.Entities.Registries;
using Misaki.HighPerformance.Unsafe.Collections;
using Misaki.HighPerformance.Unsafe.Helpers;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Ghost.Entities;
public interface IComponent public interface IComponent
{ {
} }
[SkipLocalsInit] internal class ComponentPool<T> : IDisposable
internal readonly record struct ComponentData where T : struct, IComponent
{ {
public readonly int id; private struct ComponentData
public readonly int sizeInByte; {
public T data;
public ComponentData(int id, int sizeInByte) public Entity owner;
}
private EntityID _nextId;
private EntityID _capacity;
private ComponentData[] _components;
private EntityID[] _lookup;
public ComponentPool(int initialSize = 16)
{
_nextId = 0;
_capacity = initialSize;
_components = new ComponentData[initialSize];
_lookup = new EntityID[initialSize];
_lookup.AsSpan().Fill(Entity.INVALID_ID);
}
public EntityID Count => _nextId;
private EntityID GetComponentIndex(Entity entity)
{
return _lookup[entity.ID];
}
public void Add(Entity entity, T component)
{
if (entity.ID >= _lookup.Length)
{
_lookup.AsSpan(_nextId, entity.ID - _lookup.Length + 1).Fill(Entity.INVALID_ID);
}
if (_lookup[entity.ID] != Entity.INVALID_ID)
{
// Overwrite the old data if generation is larger
if (entity.Generation > _components[_lookup[entity.ID]].owner.Generation)
{
var index = _lookup[entity.ID];
_components[index].data = component;
_components[index].owner = entity;
}
return;
}
if (_nextId >= _capacity)
{
var newCapacity = _capacity * 2;
Array.Resize(ref _components, newCapacity);
Array.Resize(ref _lookup, newCapacity);
_lookup.AsSpan(_capacity, newCapacity - _capacity).Fill(Entity.INVALID_ID);
_capacity = newCapacity;
}
_components[_nextId] = new ComponentData
{
data = component,
owner = entity
};
_lookup[entity.ID] = _nextId;
_nextId++;
}
public ref T GetRef(Entity entity)
{
return ref _components[_lookup[entity.ID]].data;
}
public bool Has(Entity entity)
{
if (entity.ID >= _lookup.Length)
{
return false;
}
var index = GetComponentIndex(entity);
return index != Entity.INVALID_ID && _components[index].owner.Generation == entity.Generation;
}
public void Set(Entity entity, T component)
{
if (entity.ID >= _lookup.Length || _lookup[entity.ID] == Entity.INVALID_ID)
{
return;
}
var index = _lookup[entity.ID];
_components[index].data = component;
_components[index].owner = entity;
}
public void Dispose()
{ {
this.id = id;
this.sizeInByte = sizeInByte;
}
}
internal static class Component
{
public static unsafe UnsafeArray<int> ToLookupArray(Span<ComponentData> datas, Allocator allocator)
{
var max = 0;
foreach (var data in datas)
{
var componentId = data.id;
if (componentId >= max)
{
max = componentId;
}
}
// Create lookup table where the component ID points to the component index.
var array = new UnsafeArray<int>(max + 1, allocator);
array.AsSpan().Fill(-1);
for (var index = 0; index < datas.Length; index++)
{
ref var type = ref datas[index];
var componentId = type.id;
array[componentId] = index;
}
return array;
}
public static int GetHashCode(Span<ComponentData> components)
{
// Search for the highest id to determine how much uints we need for the stack.
var highestId = 0;
foreach (ref var cmp in components)
{
if (cmp.id > highestId)
{
highestId = cmp.id;
}
}
// Allocate the stack and set bits to replicate a bitset
var length = BitSet.RequiredLength(highestId + 1);
Span<uint> stack = stackalloc uint[length];
var spanBitSet = new SpanBitSet(stack);
foreach (ref var type in components)
{
var x = type.id;
spanBitSet.SetBit(x);
}
return GetHashCode(stack);
}
public static int GetHashCode(Span<uint> span)
{
var hashCode = new HashCode();
hashCode.AddBytes(MemoryMarshal.AsBytes(span));
return hashCode.ToHashCode();
}
}
internal static class Component<T>
where T : unmanaged, IComponent
{
public static readonly ComponentData data;
public static readonly Signature signature;
static Component()
{
data = ComponentRegistry.GetOrAdd<T>();
signature = new Signature(data);
} }
} }

View File

@@ -5,24 +5,25 @@ namespace Ghost.Entities;
[SkipLocalsInit] [SkipLocalsInit]
public struct Entity : IEquatable<Entity>, IComparable<Entity> public struct Entity : IEquatable<Entity>, IComparable<Entity>
{ {
private const EntityID _WORLD_INDEX_BITS = 4u; private const int _WORLD_INDEX_BITS = 4;
private const EntityID _GENERATION_BITS = 8u; private const int _GENERATION_BITS = 8;
private const EntityID _INDEX_BITS = sizeof(EntityID) * 8 - _WORLD_INDEX_BITS - _GENERATION_BITS; private const int _INDEX_BITS = sizeof(EntityID) * 8 - _WORLD_INDEX_BITS - _GENERATION_BITS;
private const EntityID _WORLD_INDEX_MASK = (1u << (int)_WORLD_INDEX_BITS) - 1; private const int _WORLD_INDEX_MASK = (1 << _WORLD_INDEX_BITS) - 1;
private const EntityID _GENERATION_MASK = (1u << (int)_GENERATION_BITS) - 1; private const int _GENERATION_MASK = (1 << _GENERATION_BITS) - 1;
private const EntityID _INDEX_MASK = (1u << (int)_INDEX_BITS) - 1; private const int _INDEX_MASK = (1 << _INDEX_BITS) - 1;
private const EntityID _ID_MASK = EntityID.MaxValue;
public const EntityID INVALID_ID = -1;
private EntityID _id; private EntityID _id;
public readonly bool IsValid public readonly bool IsValid
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _id != _ID_MASK; get => ID != INVALID_ID;
} }
public readonly EntityID Index public readonly EntityID ID
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _id & _INDEX_MASK; get => _id & _INDEX_MASK;
@@ -31,29 +32,29 @@ public struct Entity : IEquatable<Entity>, IComparable<Entity>
public readonly GenerationID Generation public readonly GenerationID Generation
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get => (GenerationID)(_id >> (int)_INDEX_BITS & _GENERATION_MASK); get => (GenerationID)(_id >> _INDEX_BITS & _GENERATION_MASK);
} }
public readonly WorldID WorldIndex public readonly WorldID WorldIndex
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get => (WorldID)(_id >> (int)(_INDEX_BITS + _GENERATION_BITS) & _WORLD_INDEX_MASK); get => (WorldID)(_id >> (_INDEX_BITS + _GENERATION_BITS) & _WORLD_INDEX_MASK);
} }
public void IncrementGeneration() public void IncrementGeneration()
{ {
var generation = Generation + 1u; var generation = Generation + 1;
if (generation >= _GENERATION_MASK) if (generation >= _GENERATION_MASK)
{ {
throw new InvalidOperationException("Generation overflow"); throw new InvalidOperationException("Generation overflow");
} }
_id = _id & ~(_GENERATION_MASK << (int)_INDEX_BITS) | generation << (int)_INDEX_BITS; _id = _id & ~(_GENERATION_MASK << _INDEX_BITS) | generation << _INDEX_BITS;
} }
internal Entity(EntityID index, EntityID generation, EntityID worldIndex) internal Entity(EntityID index, EntityID generation, EntityID worldIndex)
{ {
_id = worldIndex << (int)(_INDEX_BITS + _GENERATION_BITS) | generation << (int)_INDEX_BITS | index; _id = worldIndex << (_INDEX_BITS + _GENERATION_BITS) | generation << _INDEX_BITS | index;
} }
public readonly bool Equals(Entity other) public readonly bool Equals(Entity other)
@@ -88,6 +89,6 @@ public struct Entity : IEquatable<Entity>, IComparable<Entity>
public override readonly string ToString() public override readonly string ToString()
{ {
return $"Entity {{ Index: {Index}, Generation: {Generation}, WorldIndex: {WorldIndex} }}"; return $"Entity {{ Index: {ID}, Generation: {Generation}, WorldIndex: {WorldIndex} }}";
} }
} }

View File

@@ -7,18 +7,60 @@
<AllowUnsafeBlocks>True</AllowUnsafeBlocks> <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <ItemGroup>
<IsAotCompatible>True</IsAotCompatible> <None Include="Template\QueryRefComponent.cs">
</PropertyGroup> <DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <DependentUpon>QueryRefComponent.tt</DependentUpon>
<IsAotCompatible>True</IsAotCompatible> </None>
</PropertyGroup> <None Include="Template\World.Query.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>World.Query.tt</DependentUpon>
</None>
</ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Misaki.HighPerformance.Unsafe"> <Reference Include="Misaki.HighPerformance.Unsafe">
<HintPath>..\..\source\Class\Misaki.HighPerformance\Misaki.HighPerformance.Unsafe\bin\Release\net9.0\Misaki.HighPerformance.Unsafe.dll</HintPath> <HintPath>..\..\Class\Misaki.HighPerformance\Misaki.HighPerformance.Unsafe\bin\Release\net9.0\Misaki.HighPerformance.Unsafe.dll</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Update="Template\Helpers.tt">
<Generator>TextTemplatingFilePreprocessor</Generator>
<LastGenOutput>Helpers.cs</LastGenOutput>
</None>
<None Update="Template\QueryRefComponent.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>QueryRefComponent.cs</LastGenOutput>
</None>
<None Update="Template\World.Query.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>World.Query.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>
<ItemGroup>
<Compile Update="Template\Helpers.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Helpers.tt</DependentUpon>
</Compile>
<Compile Update="Template\QueryRefComponent.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>QueryRefComponent.tt</DependentUpon>
</Compile>
<Compile Update="Template\World.Query.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>World.Query.tt</DependentUpon>
</Compile>
</ItemGroup>
</Project> </Project>

View File

@@ -1,38 +0,0 @@
using Misaki.HighPerformance.Unsafe.Collections;
using Misaki.HighPerformance.Unsafe.Helpers;
namespace Ghost.Entities;
internal struct Signature : IDisposable
{
internal UnsafeArray<ComponentData> _componentDatas;
private int _hashCode;
public Signature(params Span<ComponentData> components)
{
_componentDatas = new UnsafeArray<ComponentData>(components.Length, Allocator.Persistent);
_componentDatas.CopyFrom(components);
_hashCode = -1;
_hashCode = GetHashCode();
}
public override int GetHashCode()
{
if (_hashCode != -1)
{
return _hashCode;
}
unchecked
{
_hashCode = Component.GetHashCode(_componentDatas.AsSpan());
return _hashCode;
}
}
public void Dispose()
{
_componentDatas.Dispose();
}
}

View File

@@ -0,0 +1,118 @@
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#+
public int Amount = 25;
public string Indent(StringBuilder sb, int spaces)
{
var indent = new string(' ', spaces);
return sb.ToString().Replace("\n", "\n" + indent);
}
string AppendGenerics(int amount)
{
var sb = new StringBuilder();
for (var i = 0; i < amount; i++)
{
if (i > 0) sb.Append(", ");
sb.Append($"T{i}");
}
return sb.ToString();
}
public StringBuilder AppendGenericRefParameters(int amount)
{
var sb = new StringBuilder();
for (var localIndex = 0; localIndex < amount; localIndex++)
{
sb.Append($"ref T{localIndex} t{localIndex}Component,");
}
sb.Length--;
return sb;
}
public StringBuilder AppendRefParameters(int amount)
{
var sb = new StringBuilder();
for (var localIndex = 0; localIndex < amount; localIndex++)
{
sb.Append($"ref component{localIndex},");
}
sb.Length--;
return sb;
}
public StringBuilder AppendGenericRestrictions(int amount, string template)
{
var sb = new StringBuilder();
for (var localIndex = 0; localIndex < amount; localIndex++)
{
sb.Append($"where T{localIndex} : {template}");
if (localIndex < amount - 1)
{
sb.Append(' ');
}
}
return sb;
}
public StringBuilder TryGetComponentPools(int amount)
{
var sb = new StringBuilder();
for (var localIndex = 0; localIndex < amount; localIndex++)
{
sb.Append($"TryGetPool<T{localIndex}>(out var pool{localIndex})");
if (localIndex < amount - 1)
{
sb.Append(" && ");
}
}
return sb;
}
public StringBuilder HasEntity(int amount)
{
var sb = new StringBuilder();
for (var localIndex = 1; localIndex < amount; localIndex++)
{
sb.Append($"pool{localIndex}.Has(entity)");
if (localIndex < amount - 1)
{
sb.Append(" && ");
}
}
return sb;
}
public StringBuilder GetComponent(int amount)
{
var sb = new StringBuilder();
for (var localIndex = 0; localIndex < amount; localIndex++)
{
sb.Append($"pool{localIndex}.GetRef(entity)");
if (localIndex < amount - 1)
{
sb.Append(", ");
}
}
return sb;
}
public StringBuilder GetComponentRef(int amount)
{
var sb = new StringBuilder();
for (var localIndex = 0; localIndex < amount; localIndex++)
{
sb.Append($"ref pool{localIndex}.GetRef(entity)");
if (localIndex < amount - 1)
{
sb.Append(", ");
}
}
return sb;
}
#>

View File

@@ -0,0 +1,54 @@
namespace Ghost.Entities;
public delegate void QueryRefComponent<T0>(Entity entity, ref T0 t0Component)
where T0 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1>(Entity entity, ref T0 t0Component,ref T1 t1Component)
where T0 : struct, IComponent where T1 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2, T3>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2, T3, T4>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2, T3, T4, T5>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2, T3, T4, T5, T6>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component,ref T8 t8Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component,ref T8 t8Component,ref T9 t9Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component,ref T8 t8Component,ref T9 t9Component,ref T10 t10Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component,ref T8 t8Component,ref T9 t9Component,ref T10 t10Component,ref T11 t11Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component,ref T8 t8Component,ref T9 t9Component,ref T10 t10Component,ref T11 t11Component,ref T12 t12Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component,ref T8 t8Component,ref T9 t9Component,ref T10 t10Component,ref T11 t11Component,ref T12 t12Component,ref T13 t13Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component,ref T8 t8Component,ref T9 t9Component,ref T10 t10Component,ref T11 t11Component,ref T12 t12Component,ref T13 t13Component,ref T14 t14Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent where T14 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component,ref T8 t8Component,ref T9 t9Component,ref T10 t10Component,ref T11 t11Component,ref T12 t12Component,ref T13 t13Component,ref T14 t14Component,ref T15 t15Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent where T14 : struct, IComponent where T15 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component,ref T8 t8Component,ref T9 t9Component,ref T10 t10Component,ref T11 t11Component,ref T12 t12Component,ref T13 t13Component,ref T14 t14Component,ref T15 t15Component,ref T16 t16Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent where T14 : struct, IComponent where T15 : struct, IComponent where T16 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component,ref T8 t8Component,ref T9 t9Component,ref T10 t10Component,ref T11 t11Component,ref T12 t12Component,ref T13 t13Component,ref T14 t14Component,ref T15 t15Component,ref T16 t16Component,ref T17 t17Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent where T14 : struct, IComponent where T15 : struct, IComponent where T16 : struct, IComponent where T17 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component,ref T8 t8Component,ref T9 t9Component,ref T10 t10Component,ref T11 t11Component,ref T12 t12Component,ref T13 t13Component,ref T14 t14Component,ref T15 t15Component,ref T16 t16Component,ref T17 t17Component,ref T18 t18Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent where T14 : struct, IComponent where T15 : struct, IComponent where T16 : struct, IComponent where T17 : struct, IComponent where T18 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component,ref T8 t8Component,ref T9 t9Component,ref T10 t10Component,ref T11 t11Component,ref T12 t12Component,ref T13 t13Component,ref T14 t14Component,ref T15 t15Component,ref T16 t16Component,ref T17 t17Component,ref T18 t18Component,ref T19 t19Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent where T14 : struct, IComponent where T15 : struct, IComponent where T16 : struct, IComponent where T17 : struct, IComponent where T18 : struct, IComponent where T19 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component,ref T8 t8Component,ref T9 t9Component,ref T10 t10Component,ref T11 t11Component,ref T12 t12Component,ref T13 t13Component,ref T14 t14Component,ref T15 t15Component,ref T16 t16Component,ref T17 t17Component,ref T18 t18Component,ref T19 t19Component,ref T20 t20Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent where T14 : struct, IComponent where T15 : struct, IComponent where T16 : struct, IComponent where T17 : struct, IComponent where T18 : struct, IComponent where T19 : struct, IComponent where T20 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component,ref T8 t8Component,ref T9 t9Component,ref T10 t10Component,ref T11 t11Component,ref T12 t12Component,ref T13 t13Component,ref T14 t14Component,ref T15 t15Component,ref T16 t16Component,ref T17 t17Component,ref T18 t18Component,ref T19 t19Component,ref T20 t20Component,ref T21 t21Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent where T14 : struct, IComponent where T15 : struct, IComponent where T16 : struct, IComponent where T17 : struct, IComponent where T18 : struct, IComponent where T19 : struct, IComponent where T20 : struct, IComponent where T21 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component,ref T8 t8Component,ref T9 t9Component,ref T10 t10Component,ref T11 t11Component,ref T12 t12Component,ref T13 t13Component,ref T14 t14Component,ref T15 t15Component,ref T16 t16Component,ref T17 t17Component,ref T18 t18Component,ref T19 t19Component,ref T20 t20Component,ref T21 t21Component,ref T22 t22Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent where T14 : struct, IComponent where T15 : struct, IComponent where T16 : struct, IComponent where T17 : struct, IComponent where T18 : struct, IComponent where T19 : struct, IComponent where T20 : struct, IComponent where T21 : struct, IComponent where T22 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component,ref T8 t8Component,ref T9 t9Component,ref T10 t10Component,ref T11 t11Component,ref T12 t12Component,ref T13 t13Component,ref T14 t14Component,ref T15 t15Component,ref T16 t16Component,ref T17 t17Component,ref T18 t18Component,ref T19 t19Component,ref T20 t20Component,ref T21 t21Component,ref T22 t22Component,ref T23 t23Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent where T14 : struct, IComponent where T15 : struct, IComponent where T16 : struct, IComponent where T17 : struct, IComponent where T18 : struct, IComponent where T19 : struct, IComponent where T20 : struct, IComponent where T21 : struct, IComponent where T22 : struct, IComponent where T23 : struct, IComponent;
public delegate void QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component,ref T8 t8Component,ref T9 t9Component,ref T10 t10Component,ref T11 t11Component,ref T12 t12Component,ref T13 t13Component,ref T14 t14Component,ref T15 t15Component,ref T16 t16Component,ref T17 t17Component,ref T18 t18Component,ref T19 t19Component,ref T20 t20Component,ref T21 t21Component,ref T22 t22Component,ref T23 t23Component,ref T24 t24Component)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent where T14 : struct, IComponent where T15 : struct, IComponent where T16 : struct, IComponent where T17 : struct, IComponent where T18 : struct, IComponent where T19 : struct, IComponent where T20 : struct, IComponent where T21 : struct, IComponent where T22 : struct, IComponent where T23 : struct, IComponent where T24 : struct, IComponent;

View File

@@ -0,0 +1,19 @@
<#@ template language="C#" #>
<#@ output extension=".cs" #>
<#@ import namespace="System.Text" #>
<#@ include file="Helpers.ttinclude" #>
namespace Ghost.Entities;
<#
for (var index = 1; index <= Amount; index++)
{
var generics = AppendGenerics(index);
var parameters = AppendGenericRefParameters(index);
var restrictions = AppendGenericRestrictions(index, "struct, IComponent");
#>
public delegate void QueryRefComponent<<#= generics #>>(Entity entity, <#= parameters.ToString() #>)
<#= restrictions.ToString() #>;
<#
}
#>

View File

@@ -0,0 +1,502 @@
namespace Ghost.Entities;
public partial struct World
{
public readonly void Query<T0>(QueryRefComponent<T0> callback)
where T0 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
callback(entity, ref pool0.GetRef(entity));
}
}
public readonly void Query<T0, T1>(QueryRefComponent<T0, T1> callback)
where T0 : struct, IComponent where T1 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2>(QueryRefComponent<T0, T1, T2> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2, T3>(QueryRefComponent<T0, T1, T2, T3> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2) && TryGetPool<T3>(out var pool3)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity) && pool3.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity), ref pool3.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2, T3, T4>(QueryRefComponent<T0, T1, T2, T3, T4> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2) && TryGetPool<T3>(out var pool3) && TryGetPool<T4>(out var pool4)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity) && pool3.Has(entity) && pool4.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity), ref pool3.GetRef(entity), ref pool4.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2, T3, T4, T5>(QueryRefComponent<T0, T1, T2, T3, T4, T5> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2) && TryGetPool<T3>(out var pool3) && TryGetPool<T4>(out var pool4) && TryGetPool<T5>(out var pool5)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity) && pool3.Has(entity) && pool4.Has(entity) && pool5.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity), ref pool3.GetRef(entity), ref pool4.GetRef(entity), ref pool5.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2, T3, T4, T5, T6>(QueryRefComponent<T0, T1, T2, T3, T4, T5, T6> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2) && TryGetPool<T3>(out var pool3) && TryGetPool<T4>(out var pool4) && TryGetPool<T5>(out var pool5) && TryGetPool<T6>(out var pool6)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity) && pool3.Has(entity) && pool4.Has(entity) && pool5.Has(entity) && pool6.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity), ref pool3.GetRef(entity), ref pool4.GetRef(entity), ref pool5.GetRef(entity), ref pool6.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2, T3, T4, T5, T6, T7>(QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2) && TryGetPool<T3>(out var pool3) && TryGetPool<T4>(out var pool4) && TryGetPool<T5>(out var pool5) && TryGetPool<T6>(out var pool6) && TryGetPool<T7>(out var pool7)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity) && pool3.Has(entity) && pool4.Has(entity) && pool5.Has(entity) && pool6.Has(entity) && pool7.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity), ref pool3.GetRef(entity), ref pool4.GetRef(entity), ref pool5.GetRef(entity), ref pool6.GetRef(entity), ref pool7.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2, T3, T4, T5, T6, T7, T8>(QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2) && TryGetPool<T3>(out var pool3) && TryGetPool<T4>(out var pool4) && TryGetPool<T5>(out var pool5) && TryGetPool<T6>(out var pool6) && TryGetPool<T7>(out var pool7) && TryGetPool<T8>(out var pool8)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity) && pool3.Has(entity) && pool4.Has(entity) && pool5.Has(entity) && pool6.Has(entity) && pool7.Has(entity) && pool8.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity), ref pool3.GetRef(entity), ref pool4.GetRef(entity), ref pool5.GetRef(entity), ref pool6.GetRef(entity), ref pool7.GetRef(entity), ref pool8.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>(QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2) && TryGetPool<T3>(out var pool3) && TryGetPool<T4>(out var pool4) && TryGetPool<T5>(out var pool5) && TryGetPool<T6>(out var pool6) && TryGetPool<T7>(out var pool7) && TryGetPool<T8>(out var pool8) && TryGetPool<T9>(out var pool9)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity) && pool3.Has(entity) && pool4.Has(entity) && pool5.Has(entity) && pool6.Has(entity) && pool7.Has(entity) && pool8.Has(entity) && pool9.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity), ref pool3.GetRef(entity), ref pool4.GetRef(entity), ref pool5.GetRef(entity), ref pool6.GetRef(entity), ref pool7.GetRef(entity), ref pool8.GetRef(entity), ref pool9.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2) && TryGetPool<T3>(out var pool3) && TryGetPool<T4>(out var pool4) && TryGetPool<T5>(out var pool5) && TryGetPool<T6>(out var pool6) && TryGetPool<T7>(out var pool7) && TryGetPool<T8>(out var pool8) && TryGetPool<T9>(out var pool9) && TryGetPool<T10>(out var pool10)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity) && pool3.Has(entity) && pool4.Has(entity) && pool5.Has(entity) && pool6.Has(entity) && pool7.Has(entity) && pool8.Has(entity) && pool9.Has(entity) && pool10.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity), ref pool3.GetRef(entity), ref pool4.GetRef(entity), ref pool5.GetRef(entity), ref pool6.GetRef(entity), ref pool7.GetRef(entity), ref pool8.GetRef(entity), ref pool9.GetRef(entity), ref pool10.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2) && TryGetPool<T3>(out var pool3) && TryGetPool<T4>(out var pool4) && TryGetPool<T5>(out var pool5) && TryGetPool<T6>(out var pool6) && TryGetPool<T7>(out var pool7) && TryGetPool<T8>(out var pool8) && TryGetPool<T9>(out var pool9) && TryGetPool<T10>(out var pool10) && TryGetPool<T11>(out var pool11)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity) && pool3.Has(entity) && pool4.Has(entity) && pool5.Has(entity) && pool6.Has(entity) && pool7.Has(entity) && pool8.Has(entity) && pool9.Has(entity) && pool10.Has(entity) && pool11.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity), ref pool3.GetRef(entity), ref pool4.GetRef(entity), ref pool5.GetRef(entity), ref pool6.GetRef(entity), ref pool7.GetRef(entity), ref pool8.GetRef(entity), ref pool9.GetRef(entity), ref pool10.GetRef(entity), ref pool11.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2) && TryGetPool<T3>(out var pool3) && TryGetPool<T4>(out var pool4) && TryGetPool<T5>(out var pool5) && TryGetPool<T6>(out var pool6) && TryGetPool<T7>(out var pool7) && TryGetPool<T8>(out var pool8) && TryGetPool<T9>(out var pool9) && TryGetPool<T10>(out var pool10) && TryGetPool<T11>(out var pool11) && TryGetPool<T12>(out var pool12)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity) && pool3.Has(entity) && pool4.Has(entity) && pool5.Has(entity) && pool6.Has(entity) && pool7.Has(entity) && pool8.Has(entity) && pool9.Has(entity) && pool10.Has(entity) && pool11.Has(entity) && pool12.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity), ref pool3.GetRef(entity), ref pool4.GetRef(entity), ref pool5.GetRef(entity), ref pool6.GetRef(entity), ref pool7.GetRef(entity), ref pool8.GetRef(entity), ref pool9.GetRef(entity), ref pool10.GetRef(entity), ref pool11.GetRef(entity), ref pool12.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>(QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2) && TryGetPool<T3>(out var pool3) && TryGetPool<T4>(out var pool4) && TryGetPool<T5>(out var pool5) && TryGetPool<T6>(out var pool6) && TryGetPool<T7>(out var pool7) && TryGetPool<T8>(out var pool8) && TryGetPool<T9>(out var pool9) && TryGetPool<T10>(out var pool10) && TryGetPool<T11>(out var pool11) && TryGetPool<T12>(out var pool12) && TryGetPool<T13>(out var pool13)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity) && pool3.Has(entity) && pool4.Has(entity) && pool5.Has(entity) && pool6.Has(entity) && pool7.Has(entity) && pool8.Has(entity) && pool9.Has(entity) && pool10.Has(entity) && pool11.Has(entity) && pool12.Has(entity) && pool13.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity), ref pool3.GetRef(entity), ref pool4.GetRef(entity), ref pool5.GetRef(entity), ref pool6.GetRef(entity), ref pool7.GetRef(entity), ref pool8.GetRef(entity), ref pool9.GetRef(entity), ref pool10.GetRef(entity), ref pool11.GetRef(entity), ref pool12.GetRef(entity), ref pool13.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>(QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent where T14 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2) && TryGetPool<T3>(out var pool3) && TryGetPool<T4>(out var pool4) && TryGetPool<T5>(out var pool5) && TryGetPool<T6>(out var pool6) && TryGetPool<T7>(out var pool7) && TryGetPool<T8>(out var pool8) && TryGetPool<T9>(out var pool9) && TryGetPool<T10>(out var pool10) && TryGetPool<T11>(out var pool11) && TryGetPool<T12>(out var pool12) && TryGetPool<T13>(out var pool13) && TryGetPool<T14>(out var pool14)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity) && pool3.Has(entity) && pool4.Has(entity) && pool5.Has(entity) && pool6.Has(entity) && pool7.Has(entity) && pool8.Has(entity) && pool9.Has(entity) && pool10.Has(entity) && pool11.Has(entity) && pool12.Has(entity) && pool13.Has(entity) && pool14.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity), ref pool3.GetRef(entity), ref pool4.GetRef(entity), ref pool5.GetRef(entity), ref pool6.GetRef(entity), ref pool7.GetRef(entity), ref pool8.GetRef(entity), ref pool9.GetRef(entity), ref pool10.GetRef(entity), ref pool11.GetRef(entity), ref pool12.GetRef(entity), ref pool13.GetRef(entity), ref pool14.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>(QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent where T14 : struct, IComponent where T15 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2) && TryGetPool<T3>(out var pool3) && TryGetPool<T4>(out var pool4) && TryGetPool<T5>(out var pool5) && TryGetPool<T6>(out var pool6) && TryGetPool<T7>(out var pool7) && TryGetPool<T8>(out var pool8) && TryGetPool<T9>(out var pool9) && TryGetPool<T10>(out var pool10) && TryGetPool<T11>(out var pool11) && TryGetPool<T12>(out var pool12) && TryGetPool<T13>(out var pool13) && TryGetPool<T14>(out var pool14) && TryGetPool<T15>(out var pool15)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity) && pool3.Has(entity) && pool4.Has(entity) && pool5.Has(entity) && pool6.Has(entity) && pool7.Has(entity) && pool8.Has(entity) && pool9.Has(entity) && pool10.Has(entity) && pool11.Has(entity) && pool12.Has(entity) && pool13.Has(entity) && pool14.Has(entity) && pool15.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity), ref pool3.GetRef(entity), ref pool4.GetRef(entity), ref pool5.GetRef(entity), ref pool6.GetRef(entity), ref pool7.GetRef(entity), ref pool8.GetRef(entity), ref pool9.GetRef(entity), ref pool10.GetRef(entity), ref pool11.GetRef(entity), ref pool12.GetRef(entity), ref pool13.GetRef(entity), ref pool14.GetRef(entity), ref pool15.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>(QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent where T14 : struct, IComponent where T15 : struct, IComponent where T16 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2) && TryGetPool<T3>(out var pool3) && TryGetPool<T4>(out var pool4) && TryGetPool<T5>(out var pool5) && TryGetPool<T6>(out var pool6) && TryGetPool<T7>(out var pool7) && TryGetPool<T8>(out var pool8) && TryGetPool<T9>(out var pool9) && TryGetPool<T10>(out var pool10) && TryGetPool<T11>(out var pool11) && TryGetPool<T12>(out var pool12) && TryGetPool<T13>(out var pool13) && TryGetPool<T14>(out var pool14) && TryGetPool<T15>(out var pool15) && TryGetPool<T16>(out var pool16)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity) && pool3.Has(entity) && pool4.Has(entity) && pool5.Has(entity) && pool6.Has(entity) && pool7.Has(entity) && pool8.Has(entity) && pool9.Has(entity) && pool10.Has(entity) && pool11.Has(entity) && pool12.Has(entity) && pool13.Has(entity) && pool14.Has(entity) && pool15.Has(entity) && pool16.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity), ref pool3.GetRef(entity), ref pool4.GetRef(entity), ref pool5.GetRef(entity), ref pool6.GetRef(entity), ref pool7.GetRef(entity), ref pool8.GetRef(entity), ref pool9.GetRef(entity), ref pool10.GetRef(entity), ref pool11.GetRef(entity), ref pool12.GetRef(entity), ref pool13.GetRef(entity), ref pool14.GetRef(entity), ref pool15.GetRef(entity), ref pool16.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17>(QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent where T14 : struct, IComponent where T15 : struct, IComponent where T16 : struct, IComponent where T17 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2) && TryGetPool<T3>(out var pool3) && TryGetPool<T4>(out var pool4) && TryGetPool<T5>(out var pool5) && TryGetPool<T6>(out var pool6) && TryGetPool<T7>(out var pool7) && TryGetPool<T8>(out var pool8) && TryGetPool<T9>(out var pool9) && TryGetPool<T10>(out var pool10) && TryGetPool<T11>(out var pool11) && TryGetPool<T12>(out var pool12) && TryGetPool<T13>(out var pool13) && TryGetPool<T14>(out var pool14) && TryGetPool<T15>(out var pool15) && TryGetPool<T16>(out var pool16) && TryGetPool<T17>(out var pool17)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity) && pool3.Has(entity) && pool4.Has(entity) && pool5.Has(entity) && pool6.Has(entity) && pool7.Has(entity) && pool8.Has(entity) && pool9.Has(entity) && pool10.Has(entity) && pool11.Has(entity) && pool12.Has(entity) && pool13.Has(entity) && pool14.Has(entity) && pool15.Has(entity) && pool16.Has(entity) && pool17.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity), ref pool3.GetRef(entity), ref pool4.GetRef(entity), ref pool5.GetRef(entity), ref pool6.GetRef(entity), ref pool7.GetRef(entity), ref pool8.GetRef(entity), ref pool9.GetRef(entity), ref pool10.GetRef(entity), ref pool11.GetRef(entity), ref pool12.GetRef(entity), ref pool13.GetRef(entity), ref pool14.GetRef(entity), ref pool15.GetRef(entity), ref pool16.GetRef(entity), ref pool17.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18>(QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent where T14 : struct, IComponent where T15 : struct, IComponent where T16 : struct, IComponent where T17 : struct, IComponent where T18 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2) && TryGetPool<T3>(out var pool3) && TryGetPool<T4>(out var pool4) && TryGetPool<T5>(out var pool5) && TryGetPool<T6>(out var pool6) && TryGetPool<T7>(out var pool7) && TryGetPool<T8>(out var pool8) && TryGetPool<T9>(out var pool9) && TryGetPool<T10>(out var pool10) && TryGetPool<T11>(out var pool11) && TryGetPool<T12>(out var pool12) && TryGetPool<T13>(out var pool13) && TryGetPool<T14>(out var pool14) && TryGetPool<T15>(out var pool15) && TryGetPool<T16>(out var pool16) && TryGetPool<T17>(out var pool17) && TryGetPool<T18>(out var pool18)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity) && pool3.Has(entity) && pool4.Has(entity) && pool5.Has(entity) && pool6.Has(entity) && pool7.Has(entity) && pool8.Has(entity) && pool9.Has(entity) && pool10.Has(entity) && pool11.Has(entity) && pool12.Has(entity) && pool13.Has(entity) && pool14.Has(entity) && pool15.Has(entity) && pool16.Has(entity) && pool17.Has(entity) && pool18.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity), ref pool3.GetRef(entity), ref pool4.GetRef(entity), ref pool5.GetRef(entity), ref pool6.GetRef(entity), ref pool7.GetRef(entity), ref pool8.GetRef(entity), ref pool9.GetRef(entity), ref pool10.GetRef(entity), ref pool11.GetRef(entity), ref pool12.GetRef(entity), ref pool13.GetRef(entity), ref pool14.GetRef(entity), ref pool15.GetRef(entity), ref pool16.GetRef(entity), ref pool17.GetRef(entity), ref pool18.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>(QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent where T14 : struct, IComponent where T15 : struct, IComponent where T16 : struct, IComponent where T17 : struct, IComponent where T18 : struct, IComponent where T19 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2) && TryGetPool<T3>(out var pool3) && TryGetPool<T4>(out var pool4) && TryGetPool<T5>(out var pool5) && TryGetPool<T6>(out var pool6) && TryGetPool<T7>(out var pool7) && TryGetPool<T8>(out var pool8) && TryGetPool<T9>(out var pool9) && TryGetPool<T10>(out var pool10) && TryGetPool<T11>(out var pool11) && TryGetPool<T12>(out var pool12) && TryGetPool<T13>(out var pool13) && TryGetPool<T14>(out var pool14) && TryGetPool<T15>(out var pool15) && TryGetPool<T16>(out var pool16) && TryGetPool<T17>(out var pool17) && TryGetPool<T18>(out var pool18) && TryGetPool<T19>(out var pool19)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity) && pool3.Has(entity) && pool4.Has(entity) && pool5.Has(entity) && pool6.Has(entity) && pool7.Has(entity) && pool8.Has(entity) && pool9.Has(entity) && pool10.Has(entity) && pool11.Has(entity) && pool12.Has(entity) && pool13.Has(entity) && pool14.Has(entity) && pool15.Has(entity) && pool16.Has(entity) && pool17.Has(entity) && pool18.Has(entity) && pool19.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity), ref pool3.GetRef(entity), ref pool4.GetRef(entity), ref pool5.GetRef(entity), ref pool6.GetRef(entity), ref pool7.GetRef(entity), ref pool8.GetRef(entity), ref pool9.GetRef(entity), ref pool10.GetRef(entity), ref pool11.GetRef(entity), ref pool12.GetRef(entity), ref pool13.GetRef(entity), ref pool14.GetRef(entity), ref pool15.GetRef(entity), ref pool16.GetRef(entity), ref pool17.GetRef(entity), ref pool18.GetRef(entity), ref pool19.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20>(QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent where T14 : struct, IComponent where T15 : struct, IComponent where T16 : struct, IComponent where T17 : struct, IComponent where T18 : struct, IComponent where T19 : struct, IComponent where T20 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2) && TryGetPool<T3>(out var pool3) && TryGetPool<T4>(out var pool4) && TryGetPool<T5>(out var pool5) && TryGetPool<T6>(out var pool6) && TryGetPool<T7>(out var pool7) && TryGetPool<T8>(out var pool8) && TryGetPool<T9>(out var pool9) && TryGetPool<T10>(out var pool10) && TryGetPool<T11>(out var pool11) && TryGetPool<T12>(out var pool12) && TryGetPool<T13>(out var pool13) && TryGetPool<T14>(out var pool14) && TryGetPool<T15>(out var pool15) && TryGetPool<T16>(out var pool16) && TryGetPool<T17>(out var pool17) && TryGetPool<T18>(out var pool18) && TryGetPool<T19>(out var pool19) && TryGetPool<T20>(out var pool20)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity) && pool3.Has(entity) && pool4.Has(entity) && pool5.Has(entity) && pool6.Has(entity) && pool7.Has(entity) && pool8.Has(entity) && pool9.Has(entity) && pool10.Has(entity) && pool11.Has(entity) && pool12.Has(entity) && pool13.Has(entity) && pool14.Has(entity) && pool15.Has(entity) && pool16.Has(entity) && pool17.Has(entity) && pool18.Has(entity) && pool19.Has(entity) && pool20.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity), ref pool3.GetRef(entity), ref pool4.GetRef(entity), ref pool5.GetRef(entity), ref pool6.GetRef(entity), ref pool7.GetRef(entity), ref pool8.GetRef(entity), ref pool9.GetRef(entity), ref pool10.GetRef(entity), ref pool11.GetRef(entity), ref pool12.GetRef(entity), ref pool13.GetRef(entity), ref pool14.GetRef(entity), ref pool15.GetRef(entity), ref pool16.GetRef(entity), ref pool17.GetRef(entity), ref pool18.GetRef(entity), ref pool19.GetRef(entity), ref pool20.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21>(QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent where T14 : struct, IComponent where T15 : struct, IComponent where T16 : struct, IComponent where T17 : struct, IComponent where T18 : struct, IComponent where T19 : struct, IComponent where T20 : struct, IComponent where T21 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2) && TryGetPool<T3>(out var pool3) && TryGetPool<T4>(out var pool4) && TryGetPool<T5>(out var pool5) && TryGetPool<T6>(out var pool6) && TryGetPool<T7>(out var pool7) && TryGetPool<T8>(out var pool8) && TryGetPool<T9>(out var pool9) && TryGetPool<T10>(out var pool10) && TryGetPool<T11>(out var pool11) && TryGetPool<T12>(out var pool12) && TryGetPool<T13>(out var pool13) && TryGetPool<T14>(out var pool14) && TryGetPool<T15>(out var pool15) && TryGetPool<T16>(out var pool16) && TryGetPool<T17>(out var pool17) && TryGetPool<T18>(out var pool18) && TryGetPool<T19>(out var pool19) && TryGetPool<T20>(out var pool20) && TryGetPool<T21>(out var pool21)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity) && pool3.Has(entity) && pool4.Has(entity) && pool5.Has(entity) && pool6.Has(entity) && pool7.Has(entity) && pool8.Has(entity) && pool9.Has(entity) && pool10.Has(entity) && pool11.Has(entity) && pool12.Has(entity) && pool13.Has(entity) && pool14.Has(entity) && pool15.Has(entity) && pool16.Has(entity) && pool17.Has(entity) && pool18.Has(entity) && pool19.Has(entity) && pool20.Has(entity) && pool21.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity), ref pool3.GetRef(entity), ref pool4.GetRef(entity), ref pool5.GetRef(entity), ref pool6.GetRef(entity), ref pool7.GetRef(entity), ref pool8.GetRef(entity), ref pool9.GetRef(entity), ref pool10.GetRef(entity), ref pool11.GetRef(entity), ref pool12.GetRef(entity), ref pool13.GetRef(entity), ref pool14.GetRef(entity), ref pool15.GetRef(entity), ref pool16.GetRef(entity), ref pool17.GetRef(entity), ref pool18.GetRef(entity), ref pool19.GetRef(entity), ref pool20.GetRef(entity), ref pool21.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22>(QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent where T14 : struct, IComponent where T15 : struct, IComponent where T16 : struct, IComponent where T17 : struct, IComponent where T18 : struct, IComponent where T19 : struct, IComponent where T20 : struct, IComponent where T21 : struct, IComponent where T22 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2) && TryGetPool<T3>(out var pool3) && TryGetPool<T4>(out var pool4) && TryGetPool<T5>(out var pool5) && TryGetPool<T6>(out var pool6) && TryGetPool<T7>(out var pool7) && TryGetPool<T8>(out var pool8) && TryGetPool<T9>(out var pool9) && TryGetPool<T10>(out var pool10) && TryGetPool<T11>(out var pool11) && TryGetPool<T12>(out var pool12) && TryGetPool<T13>(out var pool13) && TryGetPool<T14>(out var pool14) && TryGetPool<T15>(out var pool15) && TryGetPool<T16>(out var pool16) && TryGetPool<T17>(out var pool17) && TryGetPool<T18>(out var pool18) && TryGetPool<T19>(out var pool19) && TryGetPool<T20>(out var pool20) && TryGetPool<T21>(out var pool21) && TryGetPool<T22>(out var pool22)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity) && pool3.Has(entity) && pool4.Has(entity) && pool5.Has(entity) && pool6.Has(entity) && pool7.Has(entity) && pool8.Has(entity) && pool9.Has(entity) && pool10.Has(entity) && pool11.Has(entity) && pool12.Has(entity) && pool13.Has(entity) && pool14.Has(entity) && pool15.Has(entity) && pool16.Has(entity) && pool17.Has(entity) && pool18.Has(entity) && pool19.Has(entity) && pool20.Has(entity) && pool21.Has(entity) && pool22.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity), ref pool3.GetRef(entity), ref pool4.GetRef(entity), ref pool5.GetRef(entity), ref pool6.GetRef(entity), ref pool7.GetRef(entity), ref pool8.GetRef(entity), ref pool9.GetRef(entity), ref pool10.GetRef(entity), ref pool11.GetRef(entity), ref pool12.GetRef(entity), ref pool13.GetRef(entity), ref pool14.GetRef(entity), ref pool15.GetRef(entity), ref pool16.GetRef(entity), ref pool17.GetRef(entity), ref pool18.GetRef(entity), ref pool19.GetRef(entity), ref pool20.GetRef(entity), ref pool21.GetRef(entity), ref pool22.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23>(QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent where T14 : struct, IComponent where T15 : struct, IComponent where T16 : struct, IComponent where T17 : struct, IComponent where T18 : struct, IComponent where T19 : struct, IComponent where T20 : struct, IComponent where T21 : struct, IComponent where T22 : struct, IComponent where T23 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2) && TryGetPool<T3>(out var pool3) && TryGetPool<T4>(out var pool4) && TryGetPool<T5>(out var pool5) && TryGetPool<T6>(out var pool6) && TryGetPool<T7>(out var pool7) && TryGetPool<T8>(out var pool8) && TryGetPool<T9>(out var pool9) && TryGetPool<T10>(out var pool10) && TryGetPool<T11>(out var pool11) && TryGetPool<T12>(out var pool12) && TryGetPool<T13>(out var pool13) && TryGetPool<T14>(out var pool14) && TryGetPool<T15>(out var pool15) && TryGetPool<T16>(out var pool16) && TryGetPool<T17>(out var pool17) && TryGetPool<T18>(out var pool18) && TryGetPool<T19>(out var pool19) && TryGetPool<T20>(out var pool20) && TryGetPool<T21>(out var pool21) && TryGetPool<T22>(out var pool22) && TryGetPool<T23>(out var pool23)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity) && pool3.Has(entity) && pool4.Has(entity) && pool5.Has(entity) && pool6.Has(entity) && pool7.Has(entity) && pool8.Has(entity) && pool9.Has(entity) && pool10.Has(entity) && pool11.Has(entity) && pool12.Has(entity) && pool13.Has(entity) && pool14.Has(entity) && pool15.Has(entity) && pool16.Has(entity) && pool17.Has(entity) && pool18.Has(entity) && pool19.Has(entity) && pool20.Has(entity) && pool21.Has(entity) && pool22.Has(entity) && pool23.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity), ref pool3.GetRef(entity), ref pool4.GetRef(entity), ref pool5.GetRef(entity), ref pool6.GetRef(entity), ref pool7.GetRef(entity), ref pool8.GetRef(entity), ref pool9.GetRef(entity), ref pool10.GetRef(entity), ref pool11.GetRef(entity), ref pool12.GetRef(entity), ref pool13.GetRef(entity), ref pool14.GetRef(entity), ref pool15.GetRef(entity), ref pool16.GetRef(entity), ref pool17.GetRef(entity), ref pool18.GetRef(entity), ref pool19.GetRef(entity), ref pool20.GetRef(entity), ref pool21.GetRef(entity), ref pool22.GetRef(entity), ref pool23.GetRef(entity));
}
}
public readonly void Query<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24>(QueryRefComponent<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> callback)
where T0 : struct, IComponent where T1 : struct, IComponent where T2 : struct, IComponent where T3 : struct, IComponent where T4 : struct, IComponent where T5 : struct, IComponent where T6 : struct, IComponent where T7 : struct, IComponent where T8 : struct, IComponent where T9 : struct, IComponent where T10 : struct, IComponent where T11 : struct, IComponent where T12 : struct, IComponent where T13 : struct, IComponent where T14 : struct, IComponent where T15 : struct, IComponent where T16 : struct, IComponent where T17 : struct, IComponent where T18 : struct, IComponent where T19 : struct, IComponent where T20 : struct, IComponent where T21 : struct, IComponent where T22 : struct, IComponent where T23 : struct, IComponent where T24 : struct, IComponent
{
if (!(TryGetPool<T0>(out var pool0) && TryGetPool<T1>(out var pool1) && TryGetPool<T2>(out var pool2) && TryGetPool<T3>(out var pool3) && TryGetPool<T4>(out var pool4) && TryGetPool<T5>(out var pool5) && TryGetPool<T6>(out var pool6) && TryGetPool<T7>(out var pool7) && TryGetPool<T8>(out var pool8) && TryGetPool<T9>(out var pool9) && TryGetPool<T10>(out var pool10) && TryGetPool<T11>(out var pool11) && TryGetPool<T12>(out var pool12) && TryGetPool<T13>(out var pool13) && TryGetPool<T14>(out var pool14) && TryGetPool<T15>(out var pool15) && TryGetPool<T16>(out var pool16) && TryGetPool<T17>(out var pool17) && TryGetPool<T18>(out var pool18) && TryGetPool<T19>(out var pool19) && TryGetPool<T20>(out var pool20) && TryGetPool<T21>(out var pool21) && TryGetPool<T22>(out var pool22) && TryGetPool<T23>(out var pool23) && TryGetPool<T24>(out var pool24)))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
if (!(pool1.Has(entity) && pool2.Has(entity) && pool3.Has(entity) && pool4.Has(entity) && pool5.Has(entity) && pool6.Has(entity) && pool7.Has(entity) && pool8.Has(entity) && pool9.Has(entity) && pool10.Has(entity) && pool11.Has(entity) && pool12.Has(entity) && pool13.Has(entity) && pool14.Has(entity) && pool15.Has(entity) && pool16.Has(entity) && pool17.Has(entity) && pool18.Has(entity) && pool19.Has(entity) && pool20.Has(entity) && pool21.Has(entity) && pool22.Has(entity) && pool23.Has(entity) && pool24.Has(entity)))
{
continue;
}
callback(entity, ref pool0.GetRef(entity), ref pool1.GetRef(entity), ref pool2.GetRef(entity), ref pool3.GetRef(entity), ref pool4.GetRef(entity), ref pool5.GetRef(entity), ref pool6.GetRef(entity), ref pool7.GetRef(entity), ref pool8.GetRef(entity), ref pool9.GetRef(entity), ref pool10.GetRef(entity), ref pool11.GetRef(entity), ref pool12.GetRef(entity), ref pool13.GetRef(entity), ref pool14.GetRef(entity), ref pool15.GetRef(entity), ref pool16.GetRef(entity), ref pool17.GetRef(entity), ref pool18.GetRef(entity), ref pool19.GetRef(entity), ref pool20.GetRef(entity), ref pool21.GetRef(entity), ref pool22.GetRef(entity), ref pool23.GetRef(entity), ref pool24.GetRef(entity));
}
}
}

View File

@@ -0,0 +1,48 @@
<#@ template language="C#" #>
<#@ output extension=".cs" #>
<#@ import namespace="System.Text" #>
<#@ include file="Helpers.ttinclude" #>
namespace Ghost.Entities;
public partial struct World
{
<#
for (var index = 1; index <= Amount; index++)
{
var generics = AppendGenerics(index);
var restrictions = AppendGenericRestrictions(index, "struct, IComponent");
var getPools = TryGetComponentPools(index);
var hasEntity = HasEntity(index);
#>
public readonly void Query<<#= generics #>>(QueryRefComponent<<#= generics #>> callback)
<#= restrictions.ToString() #>
{
if (!(<#=getPools.ToString()#>))
{
return;
}
for (var i = 0; i < pool0.Count; i++)
{
var entity = _entities[i];
<#
if (index > 1)
{
#>
if (!(<#=hasEntity.ToString()#>))
{
continue;
}
<#
}
#>
callback(entity, <#= GetComponentRef(index).ToString() #>);
}
}
<#
}
#>
}

103
Ghost.Entities/World.cs Normal file
View File

@@ -0,0 +1,103 @@
using System.Diagnostics.CodeAnalysis;
namespace Ghost.Entities;
public partial struct World : IDisposable
{
private static int _nextWorldIndex = 0;
private readonly int _worldIndex;
private List<Entity> _entities;
private readonly Stack<EntityID> _freeSlots;
private readonly Dictionary<Type, object> _pools;
public World()
{
_worldIndex = _nextWorldIndex++;
_entities = new List<Entity>();
_freeSlots = new Stack<int>();
_pools = new();
}
public readonly Entity CreateEntity()
{
if (_freeSlots.Count > 0)
{
var index = _freeSlots.Pop();
return _entities[index];
}
else
{
var index = _entities.Count;
var entity = new Entity(index, 0, _worldIndex);
_entities.Add(entity);
return entity;
}
}
public readonly void RemoveEntity(Entity e)
{
if (e.ID >= _entities.Count || _entities[e.ID].Generation != e.Generation)
{
return;
}
var entity = _entities[e.ID];
entity.IncrementGeneration();
_entities[e.ID] = entity;
_freeSlots.Push(e.ID);
}
public void AddComponent<T>(Entity entity, T component) where T : struct, IComponent
=> GetOrCreatePool<T>().Add(entity, component);
public void SetComponent<T>(Entity entity, T component) where T : struct, IComponent
=> GetOrCreatePool<T>().Set(entity, component);
public bool HasComponent<T>(Entity entity) where T : struct, IComponent
=> GetOrCreatePool<T>().Has(entity);
private readonly bool TryGetPool<T>([MaybeNullWhen(false)] out ComponentPool<T> pool)
where T : struct, IComponent
{
var type = typeof(T);
if (_pools.TryGetValue(type, out var obj))
{
pool = (ComponentPool<T>)obj;
return true;
}
pool = null;
return false;
}
private readonly ComponentPool<T> GetOrCreatePool<T>()
where T : struct, IComponent
{
var type = typeof(T);
if (!_pools.TryGetValue(type, out var obj))
{
var pool = new ComponentPool<T>();
_pools[type] = pool;
return pool;
}
return (ComponentPool<T>)obj;
}
public readonly void Dispose()
{
foreach (var pool in _pools.Values)
{
if (pool is IDisposable disposablePool)
{
disposablePool.Dispose();
}
}
_pools.Clear();
_freeSlots.Clear();
}
}

6
Ghost.Graphics/Class1.cs Normal file
View File

@@ -0,0 +1,6 @@
namespace Ghost.Graphics;
public class Class1
{
}

View File

@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<IsAotCompatible>True</IsAotCompatible>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<IsAotCompatible>True</IsAotCompatible>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Vortice.Direct3D12" Version="3.6.2" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ghost.Data\Ghost.Data.csproj" />
<ProjectReference Include="..\Ghost.Engine\Ghost.Engine.csproj" />
<ProjectReference Include="..\Ghost.Entities\Ghost.Entities.csproj" />
</ItemGroup>
</Project>

48
Ghost.Test/Program.cs Normal file
View File

@@ -0,0 +1,48 @@
using Ghost.Entities;
using System.Numerics;
var world = new World();
var entity1 = world.CreateEntity();
var entity2 = world.CreateEntity();
var entity3 = world.CreateEntity();
world.AddComponent(entity1, new Transform { position = new Vector3(1, 2, 3) });
world.AddComponent(entity1, new Mesh { index = 42 });
world.AddComponent(entity2, new Transform { position = new Vector3(4, 5, 6) });
world.AddComponent(entity2, new Mesh { index = 43 });
world.AddComponent(entity3, new Transform { position = new Vector3(7, 8, 9) });
world.Query<Transform>((Entity entity, ref Transform transform) =>
{
transform.position += new Vector3(1, 1, 1);
});
world.Query<Mesh>((Entity entity, ref Mesh mesh) =>
{
mesh.index += 1;
});
world.RemoveEntity(entity2);
var entity4 = world.CreateEntity();
world.AddComponent(entity4, new Transform { position = new Vector3(10, 11, 12) });
world.AddComponent(entity4, new Mesh { index = 44 });
world.Query<Transform, Mesh>((Entity entity, ref Transform transform, ref Mesh mesh) =>
{
Console.WriteLine($"Entity {entity.ID}: Transform Position = {transform.position}, Mesh Index = {mesh.index}");
});
world.Dispose();
public struct Transform : IComponent
{
public Vector3 position;
public Quaternion rotation;
public Vector3 scale;
}
public struct Mesh : IComponent
{
public uint index;
}

View File

@@ -9,7 +9,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ghost.Engine", "Ghost.Engin
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ghost.Data", "Ghost.Data\Ghost.Data.csproj", "{0D626DAF-EF18-435C-A85C-EEA1B141E8B5}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ghost.Data", "Ghost.Data\Ghost.Data.csproj", "{0D626DAF-EF18-435C-A85C-EEA1B141E8B5}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ghost.Entities", "Ghost.Entities\Ghost.Entities.csproj", "{329CA048-4BA8-3E60-8546-E448746D4444}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ghost.Entities", "Ghost.Entities\Ghost.Entities.csproj", "{8A1C494B-2888-4D0D-8325-9F5C8D1D1955}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ghost.Test", "Ghost.Test\Ghost.Test.csproj", "{276D09BD-7C8B-4D59-803D-96CCD83D41B0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ghost.Graphics", "Ghost.Graphics\Ghost.Graphics.csproj", "{9B0B2CA8-B200-4F19-9D09-A7B99F98BB44}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -63,18 +67,42 @@ Global
{0D626DAF-EF18-435C-A85C-EEA1B141E8B5}.Release|x64.Build.0 = Release|Any CPU {0D626DAF-EF18-435C-A85C-EEA1B141E8B5}.Release|x64.Build.0 = Release|Any CPU
{0D626DAF-EF18-435C-A85C-EEA1B141E8B5}.Release|x86.ActiveCfg = Release|Any CPU {0D626DAF-EF18-435C-A85C-EEA1B141E8B5}.Release|x86.ActiveCfg = Release|Any CPU
{0D626DAF-EF18-435C-A85C-EEA1B141E8B5}.Release|x86.Build.0 = Release|Any CPU {0D626DAF-EF18-435C-A85C-EEA1B141E8B5}.Release|x86.Build.0 = Release|Any CPU
{329CA048-4BA8-3E60-8546-E448746D4444}.Debug|ARM64.ActiveCfg = Debug|Any CPU {8A1C494B-2888-4D0D-8325-9F5C8D1D1955}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{329CA048-4BA8-3E60-8546-E448746D4444}.Debug|ARM64.Build.0 = Debug|Any CPU {8A1C494B-2888-4D0D-8325-9F5C8D1D1955}.Debug|ARM64.Build.0 = Debug|Any CPU
{329CA048-4BA8-3E60-8546-E448746D4444}.Debug|x64.ActiveCfg = Debug|Any CPU {8A1C494B-2888-4D0D-8325-9F5C8D1D1955}.Debug|x64.ActiveCfg = Debug|Any CPU
{329CA048-4BA8-3E60-8546-E448746D4444}.Debug|x64.Build.0 = Debug|Any CPU {8A1C494B-2888-4D0D-8325-9F5C8D1D1955}.Debug|x64.Build.0 = Debug|Any CPU
{329CA048-4BA8-3E60-8546-E448746D4444}.Debug|x86.ActiveCfg = Debug|Any CPU {8A1C494B-2888-4D0D-8325-9F5C8D1D1955}.Debug|x86.ActiveCfg = Debug|Any CPU
{329CA048-4BA8-3E60-8546-E448746D4444}.Debug|x86.Build.0 = Debug|Any CPU {8A1C494B-2888-4D0D-8325-9F5C8D1D1955}.Debug|x86.Build.0 = Debug|Any CPU
{329CA048-4BA8-3E60-8546-E448746D4444}.Release|ARM64.ActiveCfg = Release|Any CPU {8A1C494B-2888-4D0D-8325-9F5C8D1D1955}.Release|ARM64.ActiveCfg = Release|Any CPU
{329CA048-4BA8-3E60-8546-E448746D4444}.Release|ARM64.Build.0 = Release|Any CPU {8A1C494B-2888-4D0D-8325-9F5C8D1D1955}.Release|ARM64.Build.0 = Release|Any CPU
{329CA048-4BA8-3E60-8546-E448746D4444}.Release|x64.ActiveCfg = Release|Any CPU {8A1C494B-2888-4D0D-8325-9F5C8D1D1955}.Release|x64.ActiveCfg = Release|Any CPU
{329CA048-4BA8-3E60-8546-E448746D4444}.Release|x64.Build.0 = Release|Any CPU {8A1C494B-2888-4D0D-8325-9F5C8D1D1955}.Release|x64.Build.0 = Release|Any CPU
{329CA048-4BA8-3E60-8546-E448746D4444}.Release|x86.ActiveCfg = Release|Any CPU {8A1C494B-2888-4D0D-8325-9F5C8D1D1955}.Release|x86.ActiveCfg = Release|Any CPU
{329CA048-4BA8-3E60-8546-E448746D4444}.Release|x86.Build.0 = Release|Any CPU {8A1C494B-2888-4D0D-8325-9F5C8D1D1955}.Release|x86.Build.0 = Release|Any CPU
{276D09BD-7C8B-4D59-803D-96CCD83D41B0}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{276D09BD-7C8B-4D59-803D-96CCD83D41B0}.Debug|ARM64.Build.0 = Debug|Any CPU
{276D09BD-7C8B-4D59-803D-96CCD83D41B0}.Debug|x64.ActiveCfg = Debug|Any CPU
{276D09BD-7C8B-4D59-803D-96CCD83D41B0}.Debug|x64.Build.0 = Debug|Any CPU
{276D09BD-7C8B-4D59-803D-96CCD83D41B0}.Debug|x86.ActiveCfg = Debug|Any CPU
{276D09BD-7C8B-4D59-803D-96CCD83D41B0}.Debug|x86.Build.0 = Debug|Any CPU
{276D09BD-7C8B-4D59-803D-96CCD83D41B0}.Release|ARM64.ActiveCfg = Release|Any CPU
{276D09BD-7C8B-4D59-803D-96CCD83D41B0}.Release|ARM64.Build.0 = Release|Any CPU
{276D09BD-7C8B-4D59-803D-96CCD83D41B0}.Release|x64.ActiveCfg = Release|Any CPU
{276D09BD-7C8B-4D59-803D-96CCD83D41B0}.Release|x64.Build.0 = Release|Any CPU
{276D09BD-7C8B-4D59-803D-96CCD83D41B0}.Release|x86.ActiveCfg = Release|Any CPU
{276D09BD-7C8B-4D59-803D-96CCD83D41B0}.Release|x86.Build.0 = Release|Any CPU
{9B0B2CA8-B200-4F19-9D09-A7B99F98BB44}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{9B0B2CA8-B200-4F19-9D09-A7B99F98BB44}.Debug|ARM64.Build.0 = Debug|Any CPU
{9B0B2CA8-B200-4F19-9D09-A7B99F98BB44}.Debug|x64.ActiveCfg = Debug|Any CPU
{9B0B2CA8-B200-4F19-9D09-A7B99F98BB44}.Debug|x64.Build.0 = Debug|Any CPU
{9B0B2CA8-B200-4F19-9D09-A7B99F98BB44}.Debug|x86.ActiveCfg = Debug|Any CPU
{9B0B2CA8-B200-4F19-9D09-A7B99F98BB44}.Debug|x86.Build.0 = Debug|Any CPU
{9B0B2CA8-B200-4F19-9D09-A7B99F98BB44}.Release|ARM64.ActiveCfg = Release|Any CPU
{9B0B2CA8-B200-4F19-9D09-A7B99F98BB44}.Release|ARM64.Build.0 = Release|Any CPU
{9B0B2CA8-B200-4F19-9D09-A7B99F98BB44}.Release|x64.ActiveCfg = Release|Any CPU
{9B0B2CA8-B200-4F19-9D09-A7B99F98BB44}.Release|x64.Build.0 = Release|Any CPU
{9B0B2CA8-B200-4F19-9D09-A7B99F98BB44}.Release|x86.ActiveCfg = Release|Any CPU
{9B0B2CA8-B200-4F19-9D09-A7B99F98BB44}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE