diff --git a/MoonTools.ECS.csproj b/MoonTools.ECS.csproj
index 8867478..e7a1568 100644
--- a/MoonTools.ECS.csproj
+++ b/MoonTools.ECS.csproj
@@ -4,6 +4,7 @@
net6.0
enable
x64
+ true
diff --git a/src/ComponentDepot.cs b/src/ComponentDepot.cs
index 482214e..a5ada46 100644
--- a/src/ComponentDepot.cs
+++ b/src/ComponentDepot.cs
@@ -11,13 +11,13 @@ namespace MoonTools.ECS
private Dictionary> typeToFilterSignatures = new Dictionary>();
- private Dictionary> entityComponentMap = new Dictionary>();
-
#if DEBUG
private Dictionary singleComponentFilters = new Dictionary();
#endif
- internal void Register() where TComponent : struct
+ private HashSet TypesWithDisabledSerialization = new HashSet();
+
+ internal void Register() where TComponent : unmanaged
{
if (!storages.ContainsKey(typeof(TComponent)))
{
@@ -33,19 +33,19 @@ namespace MoonTools.ECS
return storages[type];
}
- private ComponentStorage Lookup() where TComponent : struct
+ private ComponentStorage Lookup() where TComponent : unmanaged
{
// TODO: is it possible to optimize this?
Register();
return (ComponentStorage) storages[typeof(TComponent)];
}
- public bool Some() where TComponent : struct
+ public bool Some() where TComponent : unmanaged
{
return Lookup().Any();
}
- public bool Has(int entityID) where TComponent : struct
+ public bool Has(int entityID) where TComponent : unmanaged
{
return Lookup().Has(entityID);
}
@@ -55,29 +55,22 @@ namespace MoonTools.ECS
return Lookup(type).Has(entityID);
}
- public ref readonly TComponent Get(int entityID) where TComponent : struct
+ public ref readonly TComponent Get(int entityID) where TComponent : unmanaged
{
return ref Lookup().Get(entityID);
}
- public ref readonly TComponent Get() where TComponent : struct
+ public ref readonly TComponent Get() where TComponent : unmanaged
{
return ref Lookup().Get();
}
- public void Set(int entityID, in TComponent component) where TComponent : struct
+ public void Set(int entityID, in TComponent component) where TComponent : unmanaged
{
- Lookup().Set(entityID, component);
-
- if (!entityComponentMap.ContainsKey(entityID))
- {
- entityComponentMap.Add(entityID, new HashSet());
- }
-
- var notFound = entityComponentMap[entityID].Add(typeof(TComponent));
+ var existed = Lookup().Set(entityID, component);
// update filters
- if (notFound)
+ if (!existed)
{
if (typeToFilterSignatures.TryGetValue(typeof(TComponent), out var filterSignatures))
{
@@ -89,24 +82,22 @@ namespace MoonTools.ECS
}
}
- public Entity GetSingletonEntity() where TComponent : struct
+ public Entity GetSingletonEntity() where TComponent : unmanaged
{
return Lookup().FirstEntity();
}
- public ReadOnlySpan ReadComponents() where TComponent : struct
+ public ReadOnlySpan ReadComponents() where TComponent : unmanaged
{
return Lookup().AllComponents();
}
private void Remove(Type type, int entityID)
{
- Lookup(type).Remove(entityID);
-
- var found = entityComponentMap[entityID].Remove(type);
+ var existed = Lookup(type).Remove(entityID);
// update filters
- if (found)
+ if (existed)
{
if (typeToFilterSignatures.TryGetValue(type, out var filterSignatures))
{
@@ -118,14 +109,12 @@ namespace MoonTools.ECS
}
}
- public void Remove(int entityID) where TComponent : struct
+ public void Remove(int entityID) where TComponent : unmanaged
{
- Lookup().Remove(entityID);
-
- var found = entityComponentMap[entityID].Remove(typeof(TComponent));
+ var existed = Lookup().Remove(entityID);
// update filters
- if (found)
+ if (existed)
{
if (typeToFilterSignatures.TryGetValue(typeof(TComponent), out var filterSignatures))
{
@@ -137,16 +126,12 @@ namespace MoonTools.ECS
}
}
+ // TODO: is there some way to optimize this without complicating serialization?
public void OnEntityDestroy(int entityID)
{
- if (entityComponentMap.ContainsKey(entityID))
+ foreach (var type in storages.Keys)
{
- foreach (var type in entityComponentMap[entityID])
- {
- Remove(type, entityID);
- }
-
- entityComponentMap.Remove(entityID);
+ Remove(type, entityID);
}
}
@@ -231,6 +216,53 @@ namespace MoonTools.ECS
filterSignatureToEntityIDs[filterSignature].Add(entityID);
}
+ public void DisableSerialization() where TComponent : unmanaged
+ {
+ TypesWithDisabledSerialization.Add(typeof(TComponent));
+ }
+
+ public void Save(ComponentDepotState state)
+ {
+ foreach (var (type, storage) in storages)
+ {
+ if (!TypesWithDisabledSerialization.Contains(type))
+ {
+ if (!state.StorageStates.ContainsKey(type))
+ {
+ state.StorageStates.Add(type, storage.CreateState());
+ }
+
+ storage.Save(state.StorageStates[type]);
+ }
+ }
+
+ foreach (var (signature, set) in filterSignatureToEntityIDs)
+ {
+ // FIXME: we could cache this
+ if (!signature.Included.Overlaps(TypesWithDisabledSerialization) && !signature.Excluded.Overlaps(TypesWithDisabledSerialization))
+ {
+ if (!state.FilterStates.ContainsKey(signature))
+ {
+ state.FilterStates[signature] = new IndexableSetState(set.Count);
+ }
+ set.Save(state.FilterStates[signature]);
+ }
+ }
+ }
+
+ public void Load(ComponentDepotState state)
+ {
+ foreach (var (type, storageState) in state.StorageStates)
+ {
+ storages[type].Load(storageState);
+ }
+
+ foreach (var (signature, setState) in state.FilterStates)
+ {
+ filterSignatureToEntityIDs[signature].Load(setState);
+ }
+ }
+
#if DEBUG
public IEnumerable