Rewrite
Implement the sparse set and entity registry that entt uses/describes
This commit is contained in:
parent
239ddd1b18
commit
9bf9452cbe
6 changed files with 150 additions and 94 deletions
31
src/Entity.bf
Normal file
31
src/Entity.bf
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
namespace Theater_ECS;
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
public struct Entity : uint32
|
||||||
|
{
|
||||||
|
public static readonly Entity Null => 0x000FFFFF;
|
||||||
|
public static readonly uint32 VersionMask => 0xFFF00000;
|
||||||
|
public static readonly uint32 IndexMask => 0x000FFFFF;
|
||||||
|
public static readonly uint8 VersionOffset => 20;
|
||||||
|
|
||||||
|
public uint32 Index => (.)this & IndexMask;
|
||||||
|
public uint32 Version => (.)(this & VersionMask) >> VersionOffset
|
||||||
|
public Entity Next => .(Index, Version + 1);
|
||||||
|
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
this = Entity.Null;
|
||||||
|
};
|
||||||
|
|
||||||
|
public this(uint32 index, uint32 version)
|
||||||
|
{
|
||||||
|
this = (index & IndexMask) | ((version << VersionOffset) & VersionMask);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ToString(String strBuffer)
|
||||||
|
{
|
||||||
|
strBuffer.Append(scope $"{Index}:{Version}");
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,35 +3,6 @@ namespace Theater_ECS;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
|
||||||
static
|
|
||||||
{
|
|
||||||
|
|
||||||
public struct Entity : uint32
|
|
||||||
{
|
|
||||||
public static readonly Entity Null => 0xFFFFF;
|
|
||||||
public static readonly uint32 VersionMask => 0xFFF00000;
|
|
||||||
public static readonly uint32 IndexMask => 0x000FFFFF;
|
|
||||||
public static readonly uint8 VersionOffset => 20;
|
|
||||||
|
|
||||||
public uint32 Index => (.)this & IndexMask;
|
|
||||||
public uint32 Version => (.)(this & VersionMask) >> VersionOffset
|
|
||||||
public Entity Next => .(Index, Version + 1);
|
|
||||||
|
|
||||||
public this() {};
|
|
||||||
|
|
||||||
public this(uint32 index, uint32 version)
|
|
||||||
{
|
|
||||||
this = (index & IndexMask) | ((version << VersionOffset) & VersionMask);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ToString(String strBuffer)
|
|
||||||
{
|
|
||||||
strBuffer.Append(scope $"{Index}:{Version}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class EntityRegister
|
class EntityRegister
|
||||||
{
|
{
|
||||||
private List<Entity> _entities = new .() ~ delete _;
|
private List<Entity> _entities = new .() ~ delete _;
|
||||||
|
@ -39,7 +10,7 @@ class EntityRegister
|
||||||
private Entity _next = .Null;
|
private Entity _next = .Null;
|
||||||
|
|
||||||
|
|
||||||
public Entity CreateEntity()
|
public Entity Create()
|
||||||
{
|
{
|
||||||
if(_available == 0)
|
if(_available == 0)
|
||||||
{
|
{
|
||||||
|
@ -59,7 +30,7 @@ class EntityRegister
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveEntity(Entity e)
|
public void Remove(Entity e)
|
||||||
{
|
{
|
||||||
let temp = _next;
|
let temp = _next;
|
||||||
_next = .(e.Index, 255);
|
_next = .(e.Index, 255);
|
||||||
|
|
|
@ -7,7 +7,7 @@ class MoverSystem : System
|
||||||
[SystemMethod("MoveItems", typeof(Velocity), typeof(Position))]
|
[SystemMethod("MoveItems", typeof(Velocity), typeof(Position))]
|
||||||
public void MoveItems(ref Velocity v,ref Position p)
|
public void MoveItems(ref Velocity v,ref Position p)
|
||||||
{
|
{
|
||||||
//p.x = v.x + p.x;
|
p.x = v.x + p.x;
|
||||||
//p.y = v.y = p.y;
|
p.y = v.y = p.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -11,53 +11,18 @@ class Program
|
||||||
|
|
||||||
public static void Main()
|
public static void Main()
|
||||||
{
|
{
|
||||||
/*
|
EntityRegister e = scope .();
|
||||||
Entity e = Entity(45454, 797979790);
|
PagedSparseSet<Position> p = scope .();
|
||||||
Console.WriteLine(e);
|
PagedSparseSet<Velocity> v =scope .();
|
||||||
Console.Read();
|
List<Entity> es = new .();
|
||||||
|
defer delete es;
|
||||||
EntityRegister r = scope .();
|
for(int i < 1000000)
|
||||||
while(true)
|
|
||||||
{
|
{
|
||||||
Console.WriteLine(scope $"Next: {r.[Friend]_next}");
|
var ent = e.Create();
|
||||||
for(var i in r.[Friend]_entities)
|
p.Add(ent, .());
|
||||||
Console.WriteLine(i);
|
v.Add(ent, .());
|
||||||
var l = Console.ReadLine(.. scope .());
|
es.Add(ent);
|
||||||
|
|
||||||
Console.Clear();
|
|
||||||
|
|
||||||
if(l == "c")
|
|
||||||
Console.WriteLine(r.CreateEntity());
|
|
||||||
else if(l == "d")
|
|
||||||
r.RemoveEntity(.((.)gRand.Next(0 , r.[Friend]_entities.Count), 0));
|
|
||||||
Console.WriteLine();
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
ECS ecs = scope .();
|
|
||||||
var pos = ecs.RegisterComponent<Position>(100);
|
|
||||||
//var waste = ecs.RegisterComponent<waste>(100);
|
|
||||||
var vel = ecs.RegisterComponent<Velocity>(100);
|
|
||||||
|
|
||||||
|
|
||||||
List<Entity> entities = scope .();
|
|
||||||
for(int i < 500000)
|
|
||||||
entities.Add(ecs.CreateEntity());
|
|
||||||
|
|
||||||
for(var i in entities)
|
|
||||||
*(Position*)ecs.AddComponentToEntity(i, pos).Value = .();
|
|
||||||
|
|
||||||
for(var i in entities)
|
|
||||||
*(Velocity*)ecs.AddComponentToEntity(i, vel).Value = .();
|
|
||||||
|
|
||||||
/*
|
|
||||||
for(var i in entities)
|
|
||||||
if(gRand.NextI32() % 2 == 1)
|
|
||||||
*(waste*)ecs.AddComponentToEntity(i, waste).Value = .();
|
|
||||||
*/
|
|
||||||
|
|
||||||
MoverSystem s = scope .();
|
|
||||||
s.IntializeSystem(ecs);
|
|
||||||
|
|
||||||
System.Diagnostics.Stopwatch watch = scope .();
|
System.Diagnostics.Stopwatch watch = scope .();
|
||||||
for(int a < 10)
|
for(int a < 10)
|
||||||
|
@ -65,9 +30,14 @@ class Program
|
||||||
watch.Start();
|
watch.Start();
|
||||||
for(int i < 10)
|
for(int i < 10)
|
||||||
{
|
{
|
||||||
|
var pos = p.GetAll();
|
||||||
|
var vel = v.GetAll();
|
||||||
|
|
||||||
s.RunSystem(ecs);
|
for(var ps in pos)
|
||||||
|
{
|
||||||
|
ps.1.x += vel[@ps.Index].1.x;
|
||||||
|
ps.1.y += vel[@ps.Index].1.y;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Console.WriteLine(scope $"{watch.ElapsedMilliseconds}ms");
|
Console.WriteLine(scope $"{watch.ElapsedMilliseconds}ms");
|
||||||
watch.Stop();
|
watch.Stop();
|
||||||
|
|
|
@ -1,5 +1,77 @@
|
||||||
namespace Theater_ECS;
|
namespace Theater_ECS;
|
||||||
|
|
||||||
class PagedSparseSet<T>
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
class PagedSparseSet<T> where T : struct
|
||||||
{
|
{
|
||||||
|
public const uint32 PageSize = 4096;
|
||||||
|
|
||||||
|
private List<List<Entity>> _sparse = new .()~ DeleteContainerAndItems!(_);
|
||||||
|
private List<(Entity, T)> _packed = new .() ~ delete _;
|
||||||
|
private List<T> _packedEntities = new .() ~ delete _;
|
||||||
|
|
||||||
|
public (Entity, T) this[Entity e]
|
||||||
|
{
|
||||||
|
public get => _packed[_sparse[e.Index/PageSize][e.Index % PageSize].Index];
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(Entity e)
|
||||||
|
{
|
||||||
|
return _sparse[e.Index/PageSize][e.Index % PageSize] != Entity.Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(Entity e, T toAdd)
|
||||||
|
{
|
||||||
|
EnsureLoadedPage(e.Index/PageSize);
|
||||||
|
_packed.Add((e, toAdd));
|
||||||
|
_sparse[e.Index/PageSize][e.Index % PageSize] = (.)_packed.Count-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Remove(Entity e)
|
||||||
|
{
|
||||||
|
EnsurePage(e.Index/PageSize);
|
||||||
|
if(_sparse[e.Index/PageSize] == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let toRm = _packed[_sparse[e.Index/PageSize][e.Index % PageSize].Index];
|
||||||
|
let b = _packed.Back;
|
||||||
|
_packed[_sparse[e.Index/PageSize][e.Index % PageSize].Index] = b;
|
||||||
|
_packed.Back = toRm;
|
||||||
|
|
||||||
|
_sparse[b.0.Index/PageSize][b.0.Index % PageSize] = Entity(e.Index, b.0.Version);
|
||||||
|
_sparse[e.Index/PageSize][e.Index % PageSize] = Entity.Null;
|
||||||
|
|
||||||
|
_packed.PopBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T* Get(Entity e)
|
||||||
|
{
|
||||||
|
return &_packed[_sparse[e.Index/PageSize][e.Index % PageSize].Index].1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Span<(Entity, T)> GetAll()
|
||||||
|
{
|
||||||
|
return _packed;
|
||||||
|
}
|
||||||
|
|
||||||
|
///Ensure that a page exist and is loaded
|
||||||
|
public void EnsureLoadedPage(uint32 page)
|
||||||
|
{
|
||||||
|
EnsurePage(page);
|
||||||
|
if(_sparse[page] == null)
|
||||||
|
{
|
||||||
|
_sparse[page] = new List<Entity>(PageSize);
|
||||||
|
_sparse[page].[Friend]Count = 4096;
|
||||||
|
_sparse[page].SetAll(Entity.Null);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///Ensure that a page exists, it might be null though
|
||||||
|
private void EnsurePage(uint32 page)
|
||||||
|
{
|
||||||
|
while(_sparse.Count < page+1)
|
||||||
|
_sparse.Add(null);
|
||||||
|
}
|
||||||
}
|
}
|
12
src/World.bf
Normal file
12
src/World.bf
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
namespace Theater_ECS;
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
class World
|
||||||
|
{
|
||||||
|
EntityRegister Registry = new .() ~ delete _;
|
||||||
|
|
||||||
|
private Dictionary<Type, uint32> _components = new .() ~ delete _;
|
||||||
|
private List<Variant> _componentStorage = new .() ~ DeleteContainerAndDisposeItems!(_);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue