store entity state + some garbage optimizations
parent
be95e80265
commit
190d1413ca
|
@ -221,36 +221,31 @@ namespace MoonTools.ECS
|
||||||
TypesWithDisabledSerialization.Add(typeof(TComponent));
|
TypesWithDisabledSerialization.Add(typeof(TComponent));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ComponentDepotState CreateState()
|
|
||||||
{
|
|
||||||
return new ComponentDepotState();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Serialize(ComponentDepotState state)
|
public void Serialize(ComponentDepotState state)
|
||||||
{
|
{
|
||||||
// FIXME: this is creating garbage
|
|
||||||
state.StorageStates.Clear();
|
|
||||||
foreach (var (type, storage) in storages)
|
foreach (var (type, storage) in storages)
|
||||||
{
|
{
|
||||||
// FIXME: we could cache this
|
|
||||||
if (!TypesWithDisabledSerialization.Contains(type))
|
if (!TypesWithDisabledSerialization.Contains(type))
|
||||||
{
|
{
|
||||||
var storageState = storage.CreateState();
|
if (!state.StorageStates.ContainsKey(type))
|
||||||
storage.Serialize(storageState);
|
{
|
||||||
state.StorageStates.Add(type, storageState);
|
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)
|
foreach (var (signature, set) in filterSignatureToEntityIDs)
|
||||||
{
|
{
|
||||||
// FIXME: we could cache this
|
// FIXME: we could cache this
|
||||||
if (!signature.Included.Overlaps(TypesWithDisabledSerialization) && !signature.Excluded.Overlaps(TypesWithDisabledSerialization))
|
if (!signature.Included.Overlaps(TypesWithDisabledSerialization) && !signature.Excluded.Overlaps(TypesWithDisabledSerialization))
|
||||||
{
|
{
|
||||||
var setState = new IndexableSetState<int>(set.Count);
|
if (!state.FilterStates.ContainsKey(signature))
|
||||||
set.Save(setState);
|
{
|
||||||
state.FilterStates[signature] = setState;
|
state.FilterStates[signature] = new IndexableSetState<int>(set.Count);
|
||||||
|
}
|
||||||
|
set.Save(state.FilterStates[signature]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,75 @@
|
||||||
namespace MoonTools.ECS
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MoonTools.ECS
|
||||||
{
|
{
|
||||||
internal class EntityStorage
|
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()
|
public Entity Create()
|
||||||
{
|
{
|
||||||
return new Entity(idStorage.NextID());
|
return new Entity(NextID());
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Exists(in Entity entity)
|
public bool Exists(in Entity entity)
|
||||||
{
|
{
|
||||||
return idStorage.Taken(entity.ID);
|
return Taken(entity.ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Destroy(in Entity entity)
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace MoonTools.ECS
|
namespace MoonTools.ECS
|
||||||
{
|
{
|
||||||
public class ComponentDepotState
|
internal class ComponentDepotState
|
||||||
{
|
{
|
||||||
public Dictionary<Type, ComponentStorageState> StorageStates = new Dictionary<Type, ComponentStorageState>();
|
public Dictionary<Type, ComponentStorageState> StorageStates = new Dictionary<Type, ComponentStorageState>();
|
||||||
public Dictionary<FilterSignature, IndexableSetState<int>> FilterStates = new Dictionary<FilterSignature, IndexableSetState<int>>();
|
public Dictionary<FilterSignature, IndexableSetState<int>> FilterStates = new Dictionary<FilterSignature, IndexableSetState<int>>();
|
|
@ -2,8 +2,7 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace MoonTools.ECS
|
namespace MoonTools.ECS
|
||||||
{
|
{
|
||||||
// for saving and loading component storage
|
internal class ComponentStorageState
|
||||||
public class ComponentStorageState
|
|
||||||
{
|
{
|
||||||
public int Count;
|
public int Count;
|
||||||
public Dictionary<int, int> EntityIdToStorageIndex;
|
public Dictionary<int, int> EntityIdToStorageIndex;
|
|
@ -0,0 +1,10 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MoonTools.ECS
|
||||||
|
{
|
||||||
|
internal class EntityStorageState
|
||||||
|
{
|
||||||
|
public int NextID;
|
||||||
|
public List<int> availableIDs = new List<int>();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,8 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace MoonTools.ECS
|
namespace MoonTools.ECS
|
||||||
{
|
{
|
||||||
public class IndexableSetState<T> where T : unmanaged
|
internal class IndexableSetState<T> where T : unmanaged
|
||||||
{
|
{
|
||||||
public int Count;
|
public int Count;
|
||||||
public Dictionary<T, int> Indices;
|
public Dictionary<T, int> Indices;
|
|
@ -0,0 +1,14 @@
|
||||||
|
namespace MoonTools.ECS
|
||||||
|
{
|
||||||
|
public class WorldState
|
||||||
|
{
|
||||||
|
internal ComponentDepotState ComponentDepotState;
|
||||||
|
internal EntityStorageState EntityStorageState;
|
||||||
|
|
||||||
|
public WorldState()
|
||||||
|
{
|
||||||
|
ComponentDepotState = new ComponentDepotState();
|
||||||
|
EntityStorageState = new EntityStorageState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
src/World.cs
17
src/World.cs
|
@ -32,16 +32,21 @@
|
||||||
ComponentDepot.DisableSerialization<TComponent>();
|
ComponentDepot.DisableSerialization<TComponent>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ComponentDepotState Serialize()
|
public WorldState CreateState()
|
||||||
{
|
{
|
||||||
var state = ComponentDepot.CreateState();
|
return new WorldState();
|
||||||
ComponentDepot.Serialize(state);
|
|
||||||
return state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue