initial snapshot system
parent
f045335881
commit
8061590195
|
@ -87,5 +87,28 @@ namespace MoonTools.ECS
|
||||||
{
|
{
|
||||||
Lookup<TComponent>().Remove(entityID);
|
Lookup<TComponent>().Remove(entityID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
for (var i = 0; i < ComponentTypeIndices.Count; i += 1)
|
||||||
|
{
|
||||||
|
if (storages[i] != null)
|
||||||
|
{
|
||||||
|
storages[i].Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// used to fill snapshot depot with correct storages
|
||||||
|
public void FillMissingStorages(ComponentDepot other)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < ComponentTypeIndices.Count; i += 1)
|
||||||
|
{
|
||||||
|
if (storages[i] == null && other.storages[i] != null)
|
||||||
|
{
|
||||||
|
storages[i] = other.storages[i].CreateStorage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,12 @@ namespace MoonTools.ECS
|
||||||
{
|
{
|
||||||
internal abstract void Set(int entityID, object component);
|
internal abstract void Set(int entityID, object component);
|
||||||
public abstract bool Remove(int entityID);
|
public abstract bool Remove(int entityID);
|
||||||
public abstract ComponentStorageState CreateState();
|
public abstract void Clear();
|
||||||
public abstract void Save(ComponentStorageState state);
|
|
||||||
public abstract void Load(ComponentStorageState state);
|
|
||||||
|
|
||||||
// used for debugging and template instantiation
|
// used for debugging and template instantiation
|
||||||
internal abstract object UntypedGet(int entityID);
|
internal abstract object UntypedGet(int entityID);
|
||||||
|
// used to create correctly typed storage on snapshot
|
||||||
|
public abstract ComponentStorage CreateStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ComponentStorage<TComponent> : ComponentStorage where TComponent : unmanaged
|
internal class ComponentStorage<TComponent> : ComponentStorage where TComponent : unmanaged
|
||||||
|
@ -101,7 +101,7 @@ namespace MoonTools.ECS
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear()
|
public override void Clear()
|
||||||
{
|
{
|
||||||
nextID = 0;
|
nextID = 0;
|
||||||
entityIDToStorageIndex.Clear();
|
entityIDToStorageIndex.Clear();
|
||||||
|
@ -123,43 +123,9 @@ namespace MoonTools.ECS
|
||||||
return new Entity(entityIDs[0]);
|
return new Entity(entityIDs[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override ComponentStorageState CreateState()
|
public override ComponentStorage<TComponent> CreateStorage()
|
||||||
{
|
{
|
||||||
return ComponentStorageState.Create<TComponent>(nextID);
|
return new ComponentStorage<TComponent>();
|
||||||
}
|
|
||||||
|
|
||||||
public override void Save(ComponentStorageState state)
|
|
||||||
{
|
|
||||||
ReadOnlySpan<byte> entityIDBytes = MemoryMarshal.Cast<int, byte>(new ReadOnlySpan<int>(entityIDs, 0, nextID));
|
|
||||||
|
|
||||||
if (entityIDBytes.Length > state.EntityIDs.Length)
|
|
||||||
{
|
|
||||||
Array.Resize(ref state.EntityIDs, entityIDBytes.Length);
|
|
||||||
}
|
|
||||||
entityIDBytes.CopyTo(state.EntityIDs);
|
|
||||||
|
|
||||||
ReadOnlySpan<byte> componentBytes = MemoryMarshal.Cast<TComponent, byte>(AllComponents());
|
|
||||||
if (componentBytes.Length > state.Components.Length)
|
|
||||||
{
|
|
||||||
Array.Resize(ref state.Components, componentBytes.Length);
|
|
||||||
}
|
|
||||||
componentBytes.CopyTo(state.Components);
|
|
||||||
|
|
||||||
state.Count = nextID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Load(ComponentStorageState state)
|
|
||||||
{
|
|
||||||
state.EntityIDs.CopyTo(MemoryMarshal.Cast<int, byte>(entityIDs));
|
|
||||||
state.Components.CopyTo(MemoryMarshal.Cast<TComponent, byte>(components));
|
|
||||||
|
|
||||||
entityIDToStorageIndex.Clear();
|
|
||||||
for (var i = 0; i < state.Count; i += 1)
|
|
||||||
{
|
|
||||||
entityIDToStorageIndex[entityIDs[i]] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
nextID = state.Count;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,11 +52,6 @@ namespace MoonTools.ECS
|
||||||
return ComponentDepot.GetSingletonEntity<TComponent>();
|
return ComponentDepot.GetSingletonEntity<TComponent>();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected bool Exists(in Entity entity)
|
|
||||||
{
|
|
||||||
return EntityStorage.Exists(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected IEnumerable<(Entity, Entity, TRelationKind)> Relations<TRelationKind>() where TRelationKind : unmanaged
|
protected IEnumerable<(Entity, Entity, TRelationKind)> Relations<TRelationKind>() where TRelationKind : unmanaged
|
||||||
{
|
{
|
||||||
return RelationDepot.Relations<TRelationKind>();
|
return RelationDepot.Relations<TRelationKind>();
|
||||||
|
|
|
@ -7,11 +7,14 @@ namespace MoonTools.ECS
|
||||||
private int nextID = 0;
|
private int nextID = 0;
|
||||||
// FIXME: why is this duplicated?
|
// FIXME: why is this duplicated?
|
||||||
private readonly Stack<int> availableIDs = new Stack<int>();
|
private readonly Stack<int> availableIDs = new Stack<int>();
|
||||||
|
// FIXME: this is only needed in debug mode
|
||||||
private readonly HashSet<int> availableIDHash = new HashSet<int>();
|
private readonly HashSet<int> availableIDHash = new HashSet<int>();
|
||||||
|
|
||||||
private Dictionary<int, HashSet<int>> EntityToComponentTypeIndices = new Dictionary<int, HashSet<int>>();
|
private Dictionary<int, HashSet<int>> EntityToComponentTypeIndices = new Dictionary<int, HashSet<int>>();
|
||||||
private Dictionary<int, HashSet<int>> EntityToRelationTypeIndices = new Dictionary<int, HashSet<int>>();
|
private Dictionary<int, HashSet<int>> EntityToRelationTypeIndices = new Dictionary<int, HashSet<int>>();
|
||||||
|
|
||||||
|
public int Count => nextID - availableIDs.Count;
|
||||||
|
|
||||||
public Entity Create()
|
public Entity Create()
|
||||||
{
|
{
|
||||||
var entity = new Entity(NextID());
|
var entity = new Entity(NextID());
|
||||||
|
@ -70,6 +73,21 @@ namespace MoonTools.ECS
|
||||||
return EntityToRelationTypeIndices[entityID];
|
return EntityToRelationTypeIndices[entityID];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
nextID = 0;
|
||||||
|
foreach (var componentSet in EntityToComponentTypeIndices.Values)
|
||||||
|
{
|
||||||
|
componentSet.Clear();
|
||||||
|
}
|
||||||
|
foreach (var relationSet in EntityToRelationTypeIndices.Values)
|
||||||
|
{
|
||||||
|
relationSet.Clear();
|
||||||
|
}
|
||||||
|
availableIDs.Clear();
|
||||||
|
availableIDHash.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
private int NextID()
|
private int NextID()
|
||||||
{
|
{
|
||||||
if (availableIDs.Count > 0)
|
if (availableIDs.Count > 0)
|
||||||
|
|
|
@ -84,32 +84,5 @@ namespace MoonTools.ECS
|
||||||
{
|
{
|
||||||
Count = 0;
|
Count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Save(IndexableSetState<T> state)
|
|
||||||
{
|
|
||||||
ReadOnlySpan<byte> arrayBytes = MemoryMarshal.Cast<T, byte>(array);
|
|
||||||
|
|
||||||
if (arrayBytes.Length > state.Array.Length)
|
|
||||||
{
|
|
||||||
Array.Resize(ref state.Array, arrayBytes.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
arrayBytes.CopyTo(state.Array);
|
|
||||||
|
|
||||||
state.Count = Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Load(IndexableSetState<T> state)
|
|
||||||
{
|
|
||||||
state.Array.CopyTo(MemoryMarshal.Cast<T, byte>(array));
|
|
||||||
|
|
||||||
indices.Clear();
|
|
||||||
for (var i = 0; i < state.Count; i += 1)
|
|
||||||
{
|
|
||||||
indices[array[i]] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
Count = state.Count;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,6 @@ namespace MoonTools.ECS
|
||||||
{
|
{
|
||||||
internal abstract class RelationStorage
|
internal abstract class RelationStorage
|
||||||
{
|
{
|
||||||
public abstract RelationStorageState CreateState();
|
|
||||||
public abstract void Save(RelationStorageState state);
|
|
||||||
public abstract void Load(RelationStorageState state);
|
|
||||||
public abstract void UnrelateAll(int entityID);
|
public abstract void UnrelateAll(int entityID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,60 +225,5 @@ namespace MoonTools.ECS
|
||||||
hashSet.Clear();
|
hashSet.Clear();
|
||||||
listPool.Push(hashSet);
|
listPool.Push(hashSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override RelationStorageState CreateState()
|
|
||||||
{
|
|
||||||
return RelationStorageState.Create<TRelation>(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Save(RelationStorageState state)
|
|
||||||
{
|
|
||||||
ReadOnlySpan<byte> relationBytes = MemoryMarshal.Cast<Relation, byte>(relations);
|
|
||||||
|
|
||||||
if (relationBytes.Length > state.Relations.Length)
|
|
||||||
{
|
|
||||||
Array.Resize(ref state.Relations, relationBytes.Length);
|
|
||||||
}
|
|
||||||
relationBytes.CopyTo(state.Relations);
|
|
||||||
|
|
||||||
ReadOnlySpan<byte> relationDataBytes = MemoryMarshal.Cast<TRelation, byte>(relationDatas);
|
|
||||||
|
|
||||||
if (relationDataBytes.Length > state.RelationDatas.Length)
|
|
||||||
{
|
|
||||||
Array.Resize(ref state.RelationDatas, relationDataBytes.Length);
|
|
||||||
}
|
|
||||||
relationDataBytes.CopyTo(state.RelationDatas);
|
|
||||||
|
|
||||||
state.Count = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Load(RelationStorageState state)
|
|
||||||
{
|
|
||||||
state.Relations.CopyTo(MemoryMarshal.Cast<Relation, byte>(relations));
|
|
||||||
state.RelationDatas.CopyTo(MemoryMarshal.Cast<TRelation, byte>(relationDatas));
|
|
||||||
|
|
||||||
indices.Clear();
|
|
||||||
outRelations.Clear();
|
|
||||||
inRelations.Clear();
|
|
||||||
for (var i = 0; i < state.Count; i += 1)
|
|
||||||
{
|
|
||||||
var relation = relations[i];
|
|
||||||
indices[relation] = i;
|
|
||||||
|
|
||||||
if (!outRelations.ContainsKey(relation.A.ID))
|
|
||||||
{
|
|
||||||
outRelations[relation.A.ID] = AcquireHashSetFromPool();
|
|
||||||
}
|
|
||||||
outRelations[relation.A.ID].Add(relation.B.ID);
|
|
||||||
|
|
||||||
if (!inRelations.ContainsKey(relation.B.ID))
|
|
||||||
{
|
|
||||||
inRelations[relation.B.ID] = AcquireHashSetFromPool();
|
|
||||||
}
|
|
||||||
inRelations[relation.B.ID].Add(relation.A.ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
count = state.Count;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
namespace MoonTools.ECS
|
||||||
|
{
|
||||||
|
public class Snapshot
|
||||||
|
{
|
||||||
|
private World World;
|
||||||
|
private Filter? Filter;
|
||||||
|
|
||||||
|
private EntityStorage SnapshotEntityStorage;
|
||||||
|
private ComponentDepot SnapshotComponentDepot;
|
||||||
|
|
||||||
|
internal Snapshot(World world)
|
||||||
|
{
|
||||||
|
World = world;
|
||||||
|
SnapshotEntityStorage = new EntityStorage();
|
||||||
|
SnapshotComponentDepot = new ComponentDepot(World.ComponentTypeIndices);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Take(Filter filter)
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
Filter = filter;
|
||||||
|
SnapshotComponentDepot.FillMissingStorages(World.ComponentDepot);
|
||||||
|
|
||||||
|
foreach (var worldEntity in filter.Entities)
|
||||||
|
{
|
||||||
|
var snapshotEntity = SnapshotEntityStorage.Create();
|
||||||
|
foreach (var componentTypeIndex in World.EntityStorage.ComponentTypeIndices(worldEntity.ID))
|
||||||
|
{
|
||||||
|
SnapshotEntityStorage.SetComponent(snapshotEntity.ID, componentTypeIndex);
|
||||||
|
SnapshotComponentDepot.Set(snapshotEntity.ID, componentTypeIndex, World.ComponentDepot.UntypedGet(worldEntity.ID, componentTypeIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Restore()
|
||||||
|
{
|
||||||
|
if (Filter == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var entity in Filter.Entities)
|
||||||
|
{
|
||||||
|
World.Destroy(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < SnapshotEntityStorage.Count; i += 1)
|
||||||
|
{
|
||||||
|
var entity = World.CreateEntity();
|
||||||
|
|
||||||
|
foreach (var componentTypeIndex in SnapshotEntityStorage.ComponentTypeIndices(i))
|
||||||
|
{
|
||||||
|
World.EntityStorage.SetComponent(entity.ID, componentTypeIndex);
|
||||||
|
World.FilterStorage.Check(entity.ID, componentTypeIndex);
|
||||||
|
World.ComponentDepot.Set(entity.ID, componentTypeIndex, SnapshotComponentDepot.UntypedGet(i, componentTypeIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Clear()
|
||||||
|
{
|
||||||
|
SnapshotEntityStorage.Clear();
|
||||||
|
SnapshotComponentDepot.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace MoonTools.ECS
|
|
||||||
{
|
|
||||||
internal class ComponentDepotState
|
|
||||||
{
|
|
||||||
public Dictionary<Type, ComponentStorageState> StorageStates = new Dictionary<Type, ComponentStorageState>();
|
|
||||||
public Dictionary<FilterSignature, IndexableSetState<int>> FilterStates = new Dictionary<FilterSignature, IndexableSetState<int>>();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace MoonTools.ECS
|
|
||||||
{
|
|
||||||
internal class ComponentStorageState
|
|
||||||
{
|
|
||||||
public int Count;
|
|
||||||
public byte[] EntityIDs;
|
|
||||||
public byte[] Components;
|
|
||||||
|
|
||||||
public unsafe static ComponentStorageState Create<TComponent>(int count) where TComponent : unmanaged
|
|
||||||
{
|
|
||||||
return new ComponentStorageState(
|
|
||||||
count,
|
|
||||||
count * sizeof(int),
|
|
||||||
count * sizeof(TComponent)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ComponentStorageState(int count, int entityIDSize, int componentSize)
|
|
||||||
{
|
|
||||||
Count = count;
|
|
||||||
EntityIDs = new byte[entityIDSize];
|
|
||||||
Components = new byte[componentSize];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace MoonTools.ECS
|
|
||||||
{
|
|
||||||
internal class EntityStorageState
|
|
||||||
{
|
|
||||||
public int NextID;
|
|
||||||
public List<int> availableIDs = new List<int>();
|
|
||||||
|
|
||||||
public Dictionary<int, HashSet<int>> EntityToComponentTypeIndices = new Dictionary<int, HashSet<int>>();
|
|
||||||
public Dictionary<int, HashSet<int>> EntityToRelationTypeIndices = new Dictionary<int, HashSet<int>>();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace MoonTools.ECS
|
|
||||||
{
|
|
||||||
internal class IndexableSetState<T> where T : unmanaged
|
|
||||||
{
|
|
||||||
public int Count;
|
|
||||||
public byte[] Array;
|
|
||||||
|
|
||||||
public unsafe IndexableSetState(int count)
|
|
||||||
{
|
|
||||||
Count = count;
|
|
||||||
Array = new byte[sizeof(T) * count];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace MoonTools.ECS
|
|
||||||
{
|
|
||||||
internal class RelationDepotState
|
|
||||||
{
|
|
||||||
public Dictionary<Type, RelationStorageState> StorageStates = new Dictionary<Type, RelationStorageState>();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace MoonTools.ECS
|
|
||||||
{
|
|
||||||
internal class RelationStorageState
|
|
||||||
{
|
|
||||||
public int Count;
|
|
||||||
public byte[] Relations;
|
|
||||||
public byte[] RelationDatas;
|
|
||||||
|
|
||||||
public unsafe static RelationStorageState Create<TRelation>(int count) where TRelation : unmanaged
|
|
||||||
{
|
|
||||||
return new RelationStorageState(
|
|
||||||
count,
|
|
||||||
count * sizeof(Relation),
|
|
||||||
count * sizeof(TRelation)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private RelationStorageState(int count, int relationSize, int relationDataSize)
|
|
||||||
{
|
|
||||||
Count = count;
|
|
||||||
Relations = new byte[relationSize];
|
|
||||||
RelationDatas = new byte[relationDataSize];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
namespace MoonTools.ECS
|
|
||||||
{
|
|
||||||
public class WorldState
|
|
||||||
{
|
|
||||||
internal readonly ComponentDepotState ComponentDepotState;
|
|
||||||
internal readonly EntityStorageState EntityStorageState;
|
|
||||||
internal readonly RelationDepotState RelationDepotState;
|
|
||||||
|
|
||||||
public WorldState()
|
|
||||||
{
|
|
||||||
ComponentDepotState = new ComponentDepotState();
|
|
||||||
EntityStorageState = new EntityStorageState();
|
|
||||||
RelationDepotState = new RelationDepotState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -11,27 +11,9 @@ namespace MoonTools.ECS
|
||||||
|
|
||||||
public abstract void Update(TimeSpan delta);
|
public abstract void Update(TimeSpan delta);
|
||||||
|
|
||||||
protected Entity CreateEntity()
|
protected Entity CreateEntity() => World.CreateEntity();
|
||||||
{
|
|
||||||
return EntityStorage.Create();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void Set<TComponent>(in Entity entity, in TComponent component) where TComponent : unmanaged
|
protected void Set<TComponent>(in Entity entity, in TComponent component) where TComponent : unmanaged => World.Set<TComponent>(entity, component);
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
// check for use after destroy
|
|
||||||
if (!Exists(entity))
|
|
||||||
{
|
|
||||||
throw new ArgumentException("This entity is not valid!");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (EntityStorage.SetComponent(entity.ID, ComponentTypeIndices.GetIndex<TComponent>()))
|
|
||||||
{
|
|
||||||
FilterStorage.Check<TComponent>(entity.ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
ComponentDepot.Set<TComponent>(entity.ID, component);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void Remove<TComponent>(in Entity entity) where TComponent : unmanaged
|
protected void Remove<TComponent>(in Entity entity) where TComponent : unmanaged
|
||||||
{
|
{
|
||||||
|
@ -42,27 +24,9 @@ namespace MoonTools.ECS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void Set<TComponent>(in Template template, in TComponent component) where TComponent : unmanaged
|
protected void Set<TComponent>(in Template template, in TComponent component) where TComponent : unmanaged => World.Set<TComponent>(template, component);
|
||||||
{
|
|
||||||
var componentTypeIndex = ComponentTypeIndices.GetIndex<TComponent>();
|
|
||||||
TemplateStorage.SetComponent(template.ID, componentTypeIndex);
|
|
||||||
TemplateComponentDepot.Set(template.ID, component);
|
|
||||||
ComponentDepot.Register<TComponent>(componentTypeIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Entity Instantiate(in Template template)
|
protected Entity Instantiate(in Template template) => World.Instantiate(template);
|
||||||
{
|
|
||||||
var entity = EntityStorage.Create();
|
|
||||||
|
|
||||||
foreach (var componentTypeIndex in TemplateStorage.ComponentTypeIndices(template.ID))
|
|
||||||
{
|
|
||||||
EntityStorage.SetComponent(entity.ID, componentTypeIndex);
|
|
||||||
FilterStorage.Check(entity.ID, componentTypeIndex);
|
|
||||||
ComponentDepot.Set(entity.ID, componentTypeIndex, TemplateComponentDepot.UntypedGet(template.ID, componentTypeIndex));
|
|
||||||
}
|
|
||||||
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ReadOnlySpan<TMessage> ReadMessages<TMessage>() where TMessage : unmanaged
|
protected ReadOnlySpan<TMessage> ReadMessages<TMessage>() where TMessage : unmanaged
|
||||||
{
|
{
|
||||||
|
@ -128,20 +92,6 @@ namespace MoonTools.ECS
|
||||||
EntityStorage.RemoveRelation(entity.ID, RelationTypeIndices.GetIndex<TRelationKind>());
|
EntityStorage.RemoveRelation(entity.ID, RelationTypeIndices.GetIndex<TRelationKind>());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void Destroy(in Entity entity)
|
protected void Destroy(in Entity entity) => World.Destroy(entity);
|
||||||
{
|
|
||||||
foreach (var componentTypeIndex in EntityStorage.ComponentTypeIndices(entity.ID))
|
|
||||||
{
|
|
||||||
ComponentDepot.Remove(entity.ID, componentTypeIndex);
|
|
||||||
FilterStorage.RemoveEntity(entity.ID, componentTypeIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var relationTypeIndex in EntityStorage.RelationTypeIndices(entity.ID))
|
|
||||||
{
|
|
||||||
RelationDepot.UnrelateAll(entity.ID, relationTypeIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityStorage.Destroy(entity);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ namespace MoonTools.ECS
|
||||||
{
|
{
|
||||||
Dictionary<Type, int> TypeToIndex = new Dictionary<Type, int>();
|
Dictionary<Type, int> TypeToIndex = new Dictionary<Type, int>();
|
||||||
int nextID = 0;
|
int nextID = 0;
|
||||||
|
public int Count => TypeToIndex.Count;
|
||||||
|
|
||||||
public int GetIndex<T>() where T : unmanaged
|
public int GetIndex<T>() where T : unmanaged
|
||||||
{
|
{
|
||||||
|
@ -24,6 +25,7 @@ namespace MoonTools.ECS
|
||||||
return TypeToIndex[type];
|
return TypeToIndex[type];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
public IEnumerable<Type> Types => TypeToIndex.Keys;
|
public IEnumerable<Type> Types => TypeToIndex.Keys;
|
||||||
#endif
|
#endif
|
||||||
|
|
39
src/World.cs
39
src/World.cs
|
@ -1,4 +1,6 @@
|
||||||
namespace MoonTools.ECS
|
using System;
|
||||||
|
|
||||||
|
namespace MoonTools.ECS
|
||||||
{
|
{
|
||||||
public class World
|
public class World
|
||||||
{
|
{
|
||||||
|
@ -9,11 +11,11 @@
|
||||||
internal readonly MessageDepot MessageDepot = new MessageDepot();
|
internal readonly MessageDepot MessageDepot = new MessageDepot();
|
||||||
internal readonly RelationDepot RelationDepot;
|
internal readonly RelationDepot RelationDepot;
|
||||||
internal readonly FilterStorage FilterStorage;
|
internal readonly FilterStorage FilterStorage;
|
||||||
|
public FilterBuilder FilterBuilder => new FilterBuilder(FilterStorage, ComponentTypeIndices);
|
||||||
|
|
||||||
internal readonly TemplateStorage TemplateStorage = new TemplateStorage();
|
internal readonly TemplateStorage TemplateStorage = new TemplateStorage();
|
||||||
internal readonly ComponentDepot TemplateComponentDepot;
|
internal readonly ComponentDepot TemplateComponentDepot;
|
||||||
|
|
||||||
|
|
||||||
public World()
|
public World()
|
||||||
{
|
{
|
||||||
ComponentDepot = new ComponentDepot(ComponentTypeIndices);
|
ComponentDepot = new ComponentDepot(ComponentTypeIndices);
|
||||||
|
@ -29,6 +31,13 @@
|
||||||
|
|
||||||
public void Set<TComponent>(Entity entity, in TComponent component) where TComponent : unmanaged
|
public void Set<TComponent>(Entity entity, in TComponent component) where TComponent : unmanaged
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
// check for use after destroy
|
||||||
|
if (!EntityStorage.Exists(entity))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("This entity is not valid!");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (EntityStorage.SetComponent(entity.ID, ComponentTypeIndices.GetIndex<TComponent>()))
|
if (EntityStorage.SetComponent(entity.ID, ComponentTypeIndices.GetIndex<TComponent>()))
|
||||||
{
|
{
|
||||||
FilterStorage.Check<TComponent>(entity.ID);
|
FilterStorage.Check<TComponent>(entity.ID);
|
||||||
|
@ -44,11 +53,12 @@
|
||||||
|
|
||||||
public void Set<TComponent>(in Template template, in TComponent component) where TComponent : unmanaged
|
public void Set<TComponent>(in Template template, in TComponent component) where TComponent : unmanaged
|
||||||
{
|
{
|
||||||
TemplateStorage.SetComponent(template.ID, ComponentTypeIndices.GetIndex<TComponent>());
|
var componentTypeIndex = ComponentTypeIndices.GetIndex<TComponent>();
|
||||||
|
TemplateStorage.SetComponent(template.ID, componentTypeIndex);
|
||||||
TemplateComponentDepot.Set(template.ID, component);
|
TemplateComponentDepot.Set(template.ID, component);
|
||||||
|
ComponentDepot.Register<TComponent>(componentTypeIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: TEST ME!!!
|
|
||||||
public Entity Instantiate(in Template template)
|
public Entity Instantiate(in Template template)
|
||||||
{
|
{
|
||||||
var entity = EntityStorage.Create();
|
var entity = EntityStorage.Create();
|
||||||
|
@ -68,14 +78,31 @@
|
||||||
MessageDepot.Add(message);
|
MessageDepot.Add(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Destroy(in Entity entity)
|
||||||
|
{
|
||||||
|
foreach (var componentTypeIndex in EntityStorage.ComponentTypeIndices(entity.ID))
|
||||||
|
{
|
||||||
|
ComponentDepot.Remove(entity.ID, componentTypeIndex);
|
||||||
|
FilterStorage.RemoveEntity(entity.ID, componentTypeIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var relationTypeIndex in EntityStorage.RelationTypeIndices(entity.ID))
|
||||||
|
{
|
||||||
|
RelationDepot.UnrelateAll(entity.ID, relationTypeIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityStorage.Destroy(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void FinishUpdate()
|
public void FinishUpdate()
|
||||||
{
|
{
|
||||||
MessageDepot.Clear();
|
MessageDepot.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public WorldState CreateState()
|
public Snapshot CreateSnapshot()
|
||||||
{
|
{
|
||||||
return new WorldState();
|
return new Snapshot(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue