store entity state + some garbage optimizations

pull/2/head
cosmonaut 2022-05-02 11:07:19 -07:00
parent be95e80265
commit 190d1413ca
9 changed files with 107 additions and 71 deletions

View File

@ -221,36 +221,31 @@ namespace MoonTools.ECS
TypesWithDisabledSerialization.Add(typeof(TComponent));
}
public ComponentDepotState CreateState()
{
return new ComponentDepotState();
}
public void Serialize(ComponentDepotState state)
{
// FIXME: this is creating garbage
state.StorageStates.Clear();
foreach (var (type, storage) in storages)
{
// FIXME: we could cache this
if (!TypesWithDisabledSerialization.Contains(type))
{
var storageState = storage.CreateState();
storage.Serialize(storageState);
state.StorageStates.Add(type, storageState);
if (!state.StorageStates.ContainsKey(type))
{
state.StorageStates.Add(type, storage.CreateState());
}
storage.Serialize(state.StorageStates[type]);
}
}
// FIXME: this is creating garbage
state.FilterStates.Clear();
foreach (var (signature, set) in filterSignatureToEntityIDs)
{
// FIXME: we could cache this
if (!signature.Included.Overlaps(TypesWithDisabledSerialization) && !signature.Excluded.Overlaps(TypesWithDisabledSerialization))
{
var setState = new IndexableSetState<int>(set.Count);
set.Save(setState);
state.FilterStates[signature] = setState;
if (!state.FilterStates.ContainsKey(signature))
{
state.FilterStates[signature] = new IndexableSetState<int>(set.Count);
}
set.Save(state.FilterStates[signature]);
}
}
}

View File

@ -1,22 +1,75 @@
namespace MoonTools.ECS
using System.Collections.Generic;
namespace MoonTools.ECS
{
internal class EntityStorage
{
public IDStorage idStorage = new IDStorage();
private int nextID = 0;
private readonly Stack<int> availableIDs = new Stack<int>();
private readonly HashSet<int> availableIDHash = new HashSet<int>();
public Entity Create()
{
return new Entity(idStorage.NextID());
return new Entity(NextID());
}
public bool Exists(in Entity entity)
{
return idStorage.Taken(entity.ID);
return Taken(entity.ID);
}
public void Destroy(in Entity entity)
{
idStorage.Release(entity.ID);
Release(entity.ID);
}
public void Serialize(EntityStorageState state)
{
state.NextID = nextID;
state.availableIDs.Clear();
foreach (var id in availableIDs)
{
state.availableIDs.Add(id);
}
}
public void Deserialize(EntityStorageState state)
{
nextID = state.NextID;
availableIDs.Clear();
availableIDHash.Clear();
foreach (var id in state.availableIDs)
{
availableIDs.Push(id);
availableIDHash.Add(id);
}
}
private int NextID()
{
if (availableIDs.Count > 0)
{
var id = availableIDs.Pop();
availableIDHash.Remove(id);
return id;
}
else
{
var id = nextID;
nextID += 1;
return id;
}
}
private bool Taken(int id)
{
return !availableIDHash.Contains(id) && id < nextID;
}
private void Release(int id)
{
availableIDs.Push(id);
availableIDHash.Add(id);
}
}
}

View File

@ -1,39 +0,0 @@
using System.Collections.Generic;
namespace MoonTools.ECS
{
internal class IDStorage
{
private int nextID = 0;
private readonly Stack<int> availableIDs = new Stack<int>();
private readonly HashSet<int> availableIDHash = new HashSet<int>();
public int NextID()
{
if (availableIDs.Count > 0)
{
var id = availableIDs.Pop();
availableIDHash.Remove(id);
return id;
}
else
{
var id = nextID;
nextID += 1;
return id;
}
}
public bool Taken(int id)
{
return !availableIDHash.Contains(id) && id < nextID;
}
public void Release(int id)
{
availableIDs.Push(id);
availableIDHash.Add(id);
}
}
}

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
namespace MoonTools.ECS
{
public class ComponentDepotState
internal class ComponentDepotState
{
public Dictionary<Type, ComponentStorageState> StorageStates = new Dictionary<Type, ComponentStorageState>();
public Dictionary<FilterSignature, IndexableSetState<int>> FilterStates = new Dictionary<FilterSignature, IndexableSetState<int>>();

View File

@ -2,8 +2,7 @@ using System.Collections.Generic;
namespace MoonTools.ECS
{
// for saving and loading component storage
public class ComponentStorageState
internal class ComponentStorageState
{
public int Count;
public Dictionary<int, int> EntityIdToStorageIndex;

View File

@ -0,0 +1,10 @@
using System.Collections.Generic;
namespace MoonTools.ECS
{
internal class EntityStorageState
{
public int NextID;
public List<int> availableIDs = new List<int>();
}
}

View File

@ -1,9 +1,8 @@
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace MoonTools.ECS
{
public class IndexableSetState<T> where T : unmanaged
internal class IndexableSetState<T> where T : unmanaged
{
public int Count;
public Dictionary<T, int> Indices;

14
src/State/WorldState.cs Normal file
View File

@ -0,0 +1,14 @@
namespace MoonTools.ECS
{
public class WorldState
{
internal ComponentDepotState ComponentDepotState;
internal EntityStorageState EntityStorageState;
public WorldState()
{
ComponentDepotState = new ComponentDepotState();
EntityStorageState = new EntityStorageState();
}
}
}

View File

@ -32,16 +32,21 @@
ComponentDepot.DisableSerialization<TComponent>();
}
public ComponentDepotState Serialize()
public WorldState CreateState()
{
var state = ComponentDepot.CreateState();
ComponentDepot.Serialize(state);
return state;
return new WorldState();
}
public void Deserialize(ComponentDepotState state)
public void Serialize(WorldState state)
{
ComponentDepot.Deserialize(state);
ComponentDepot.Serialize(state.ComponentDepotState);
EntityStorage.Serialize(state.EntityStorageState);
}
public void Deserialize(WorldState state)
{
ComponentDepot.Deserialize(state.ComponentDepotState);
EntityStorage.Deserialize(state.EntityStorageState);
}
}
}