initial serialization structure

pull/2/head
cosmonaut 2022-04-26 18:43:39 -07:00
parent 5243259acb
commit 2fc1b68f41
8 changed files with 147 additions and 70 deletions

View File

@ -231,6 +231,30 @@ namespace MoonTools.ECS
filterSignatureToEntityIDs[filterSignature].Add(entityID); filterSignatureToEntityIDs[filterSignature].Add(entityID);
} }
public ComponentDepotState CreateState()
{
return new ComponentDepotState();
}
public void Serialize(ComponentDepotState state)
{
state.StorageStates.Clear();
foreach (var (type, storage) in storages)
{
var storageState = storage.CreateState();
storage.Serialize(storageState);
state.StorageStates.Add(type, storageState);
}
}
public void Deserialize(ComponentDepotState state)
{
foreach (var (type, storageState) in state.StorageStates)
{
storages[type].Deserialize(storageState);
}
}
#if DEBUG #if DEBUG
public IEnumerable<object> Debug_GetAllComponents(int entityID) public IEnumerable<object> Debug_GetAllComponents(int entityID)
{ {

View File

@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
namespace MoonTools.ECS
{
public class ComponentDepotState
{
public Dictionary<Type, ComponentStorageState> StorageStates = new Dictionary<Type, ComponentStorageState>();
}
}

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace MoonTools.ECS namespace MoonTools.ECS
{ {
@ -8,9 +9,11 @@ namespace MoonTools.ECS
public abstract bool Has(int entityID); public abstract bool Has(int entityID);
public abstract void Remove(int entityID); public abstract void Remove(int entityID);
public abstract object Debug_Get(int entityID); public abstract object Debug_Get(int entityID);
public abstract ComponentStorageState CreateState();
public abstract void Serialize(ComponentStorageState state);
public abstract void Deserialize(ComponentStorageState state);
} }
// FIXME: we can probably get rid of this weird entity storage system by using filters
internal class ComponentStorage<TComponent> : ComponentStorage where TComponent : struct internal class ComponentStorage<TComponent> : ComponentStorage where TComponent : struct
{ {
private int nextID; private int nextID;
@ -106,5 +109,37 @@ namespace MoonTools.ECS
{ {
return new Entity(entityIDs[0]); return new Entity(entityIDs[0]);
} }
public override ComponentStorageState CreateState()
{
return ComponentStorageState.Create<TComponent>(nextID);
}
public override void Serialize(ComponentStorageState serializedComponentStorage)
{
ReadOnlySpan<byte> entityIDBytes = MemoryMarshal.Cast<int, byte>(new ReadOnlySpan<int>(entityIDs, 0, nextID));
entityIDBytes.CopyTo(serializedComponentStorage.EntityIDs);
ReadOnlySpan<byte> componentBytes = MemoryMarshal.Cast<TComponent, byte>(AllComponents());
componentBytes.CopyTo(serializedComponentStorage.Components);
serializedComponentStorage.EntityIdToStorageIndex.Clear();
foreach (var kvp in entityIDToStorageIndex)
{
serializedComponentStorage.EntityIdToStorageIndex[kvp.Key] = kvp.Value;
}
}
public override void Deserialize(ComponentStorageState serializedComponentStorage)
{
serializedComponentStorage.EntityIDs.CopyTo(MemoryMarshal.Cast<int, byte>(entityIDs));
serializedComponentStorage.Components.CopyTo(MemoryMarshal.Cast<TComponent, byte>(components));
entityIDToStorageIndex.Clear();
foreach (var kvp in serializedComponentStorage.EntityIdToStorageIndex)
{
entityIDToStorageIndex[kvp.Key] = kvp.Value;
}
}
} }
} }

View File

@ -0,0 +1,31 @@
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace MoonTools.ECS
{
// for saving and loading component storage
public class ComponentStorageState
{
public int Count;
public Dictionary<int, int> EntityIdToStorageIndex;
public byte[] EntityIDs;
public byte[] Components;
public static ComponentStorageState Create<TComponent>(int count)
{
return new ComponentStorageState(
count,
count * Marshal.SizeOf<int>(),
count * Marshal.SizeOf<TComponent>()
);
}
private ComponentStorageState(int count, int entityIDSize, int componentSize)
{
Count = count;
EntityIdToStorageIndex = new Dictionary<int, int>(count);
EntityIDs = new byte[entityIDSize];
Components = new byte[componentSize];
}
}
}

View File

@ -5,52 +5,43 @@ namespace MoonTools.ECS
{ {
public abstract class EntityComponentReader public abstract class EntityComponentReader
{ {
internal EntityStorage EntityStorage; protected readonly World World;
internal ComponentDepot ComponentDepot; internal EntityStorage EntityStorage => World.EntityStorage;
internal RelationDepot RelationDepot; internal ComponentDepot ComponentDepot => World.ComponentDepot;
internal RelationDepot RelationDepot => World.RelationDepot;
protected FilterBuilder FilterBuilder => new FilterBuilder(ComponentDepot); protected FilterBuilder FilterBuilder => new FilterBuilder(ComponentDepot);
internal void RegisterEntityStorage(EntityStorage entityStorage) public EntityComponentReader(World world)
{ {
EntityStorage = entityStorage; World = world;
} }
internal void RegisterComponentDepot(ComponentDepot componentDepot) protected ReadOnlySpan<TComponent> ReadComponents<TComponent>() where TComponent : unmanaged
{
ComponentDepot = componentDepot;
}
internal void RegisterRelationDepot(RelationDepot relationDepot)
{
RelationDepot = relationDepot;
}
protected ReadOnlySpan<TComponent> ReadComponents<TComponent>() where TComponent : struct
{ {
return ComponentDepot.ReadComponents<TComponent>(); return ComponentDepot.ReadComponents<TComponent>();
} }
protected bool Has<TComponent>(in Entity entity) where TComponent : struct protected bool Has<TComponent>(in Entity entity) where TComponent : unmanaged
{ {
return ComponentDepot.Has<TComponent>(entity.ID); return ComponentDepot.Has<TComponent>(entity.ID);
} }
protected bool Some<TComponent>() where TComponent : struct protected bool Some<TComponent>() where TComponent : unmanaged
{ {
return ComponentDepot.Some<TComponent>(); return ComponentDepot.Some<TComponent>();
} }
protected ref readonly TComponent Get<TComponent>(in Entity entity) where TComponent : struct protected ref readonly TComponent Get<TComponent>(in Entity entity) where TComponent : unmanaged
{ {
return ref ComponentDepot.Get<TComponent>(entity.ID); return ref ComponentDepot.Get<TComponent>(entity.ID);
} }
protected ref readonly TComponent GetSingleton<TComponent>() where TComponent : struct protected ref readonly TComponent GetSingleton<TComponent>() where TComponent : unmanaged
{ {
return ref ComponentDepot.Get<TComponent>(); return ref ComponentDepot.Get<TComponent>();
} }
protected Entity GetSingletonEntity<TComponent>() where TComponent : struct protected Entity GetSingletonEntity<TComponent>() where TComponent : unmanaged
{ {
return ComponentDepot.GetSingletonEntity<TComponent>(); return ComponentDepot.GetSingletonEntity<TComponent>();
} }
@ -60,22 +51,22 @@ namespace MoonTools.ECS
return EntityStorage.Exists(entity); return EntityStorage.Exists(entity);
} }
protected IEnumerable<(Entity, Entity, TRelationKind)> Relations<TRelationKind>() where TRelationKind : struct protected IEnumerable<(Entity, Entity, TRelationKind)> Relations<TRelationKind>() where TRelationKind : unmanaged
{ {
return RelationDepot.Relations<TRelationKind>(); return RelationDepot.Relations<TRelationKind>();
} }
protected bool Related<TRelationKind>(in Entity a, in Entity b) where TRelationKind : struct protected bool Related<TRelationKind>(in Entity a, in Entity b) where TRelationKind : unmanaged
{ {
return RelationDepot.Related<TRelationKind>(a.ID, b.ID); return RelationDepot.Related<TRelationKind>(a.ID, b.ID);
} }
protected IEnumerable<(Entity, TRelationKind)> RelatedToA<TRelationKind>(in Entity entity) where TRelationKind : struct protected IEnumerable<(Entity, TRelationKind)> RelatedToA<TRelationKind>(in Entity entity) where TRelationKind : unmanaged
{ {
return RelationDepot.RelatedToA<TRelationKind>(entity.ID); return RelationDepot.RelatedToA<TRelationKind>(entity.ID);
} }
protected IEnumerable<(Entity, TRelationKind)> RelatedToB<TRelationKind>(in Entity entity) where TRelationKind : struct protected IEnumerable<(Entity, TRelationKind)> RelatedToB<TRelationKind>(in Entity entity) where TRelationKind : unmanaged
{ {
return RelationDepot.RelatedToB<TRelationKind>(entity.ID); return RelationDepot.RelatedToB<TRelationKind>(entity.ID);
} }

View File

@ -2,9 +2,6 @@
{ {
public abstract class Renderer : EntityComponentReader public abstract class Renderer : EntityComponentReader
{ {
public Renderer(World world) public Renderer(World world) : base(world) { }
{
world.AddRenderer(this);
}
} }
} }

View File

@ -5,17 +5,9 @@ namespace MoonTools.ECS
{ {
public abstract class System : EntityComponentReader public abstract class System : EntityComponentReader
{ {
internal MessageDepot MessageDepot; internal MessageDepot MessageDepot => World.MessageDepot;
internal void RegisterMessageDepot(MessageDepot messageDepot) public System(World world) : base(world) { }
{
MessageDepot = messageDepot;
}
public System(World world)
{
world.AddSystem(this);
}
public abstract void Update(TimeSpan delta); public abstract void Update(TimeSpan delta);
@ -24,7 +16,7 @@ namespace MoonTools.ECS
return EntityStorage.Create(); return EntityStorage.Create();
} }
protected void Set<TComponent>(in Entity entity, in TComponent component) where TComponent : struct protected void Set<TComponent>(in Entity entity, in TComponent component) where TComponent : unmanaged
{ {
#if DEBUG #if DEBUG
// check for use after destroy // check for use after destroy
@ -36,52 +28,52 @@ namespace MoonTools.ECS
ComponentDepot.Set<TComponent>(entity.ID, component); ComponentDepot.Set<TComponent>(entity.ID, component);
} }
protected void Remove<TComponent>(in Entity entity) where TComponent : struct protected void Remove<TComponent>(in Entity entity) where TComponent : unmanaged
{ {
ComponentDepot.Remove<TComponent>(entity.ID); ComponentDepot.Remove<TComponent>(entity.ID);
} }
protected ReadOnlySpan<TMessage> ReadMessages<TMessage>() where TMessage : struct protected ReadOnlySpan<TMessage> ReadMessages<TMessage>() where TMessage : unmanaged
{ {
return MessageDepot.All<TMessage>(); return MessageDepot.All<TMessage>();
} }
protected TMessage ReadMessage<TMessage>() where TMessage : struct protected TMessage ReadMessage<TMessage>() where TMessage : unmanaged
{ {
return MessageDepot.First<TMessage>(); return MessageDepot.First<TMessage>();
} }
protected bool SomeMessage<TMessage>() where TMessage : struct protected bool SomeMessage<TMessage>() where TMessage : unmanaged
{ {
return MessageDepot.Some<TMessage>(); return MessageDepot.Some<TMessage>();
} }
protected IEnumerable<TMessage> ReadMessagesWithEntity<TMessage>(in Entity entity) where TMessage : struct, IHasEntity protected IEnumerable<TMessage> ReadMessagesWithEntity<TMessage>(in Entity entity) where TMessage : unmanaged, IHasEntity
{ {
return MessageDepot.WithEntity<TMessage>(entity.ID); return MessageDepot.WithEntity<TMessage>(entity.ID);
} }
protected ref readonly TMessage ReadMessageWithEntity<TMessage>(in Entity entity) where TMessage : struct, IHasEntity protected ref readonly TMessage ReadMessageWithEntity<TMessage>(in Entity entity) where TMessage : unmanaged, IHasEntity
{ {
return ref MessageDepot.FirstWithEntity<TMessage>(entity.ID); return ref MessageDepot.FirstWithEntity<TMessage>(entity.ID);
} }
protected bool SomeMessageWithEntity<TMessage>(in Entity entity) where TMessage : struct, IHasEntity protected bool SomeMessageWithEntity<TMessage>(in Entity entity) where TMessage : unmanaged, IHasEntity
{ {
return MessageDepot.SomeWithEntity<TMessage>(entity.ID); return MessageDepot.SomeWithEntity<TMessage>(entity.ID);
} }
protected void Send<TMessage>(in TMessage message) where TMessage : struct protected void Send<TMessage>(in TMessage message) where TMessage : unmanaged
{ {
MessageDepot.Add(message); MessageDepot.Add(message);
} }
protected void Relate<TRelationKind>(in Entity entityA, in Entity entityB, TRelationKind relationData) where TRelationKind : struct protected void Relate<TRelationKind>(in Entity entityA, in Entity entityB, TRelationKind relationData) where TRelationKind : unmanaged
{ {
RelationDepot.Add<TRelationKind>(new Relation(entityA, entityB), relationData); RelationDepot.Add<TRelationKind>(new Relation(entityA, entityB), relationData);
} }
protected void Unrelate<TRelationKind>(in Entity entityA, in Entity entityB) where TRelationKind : struct protected void Unrelate<TRelationKind>(in Entity entityA, in Entity entityB) where TRelationKind : unmanaged
{ {
RelationDepot.Remove<TRelationKind>(new Relation(entityA, entityB)); RelationDepot.Remove<TRelationKind>(new Relation(entityA, entityB));
} }

View File

@ -2,25 +2,10 @@
{ {
public class World public class World
{ {
private readonly EntityStorage EntityStorage = new EntityStorage(); internal readonly EntityStorage EntityStorage = new EntityStorage();
private readonly ComponentDepot ComponentDepot = new ComponentDepot(); internal readonly ComponentDepot ComponentDepot = new ComponentDepot();
private readonly MessageDepot MessageDepot = new MessageDepot(); internal readonly MessageDepot MessageDepot = new MessageDepot();
private readonly RelationDepot RelationDepot = new RelationDepot(); internal readonly RelationDepot RelationDepot = new RelationDepot();
internal void AddSystem(System system)
{
system.RegisterEntityStorage(EntityStorage);
system.RegisterComponentDepot(ComponentDepot);
system.RegisterMessageDepot(MessageDepot);
system.RegisterRelationDepot(RelationDepot);
}
internal void AddRenderer(Renderer renderer)
{
renderer.RegisterEntityStorage(EntityStorage);
renderer.RegisterComponentDepot(ComponentDepot);
renderer.RegisterRelationDepot(RelationDepot);
}
public Entity CreateEntity() public Entity CreateEntity()
{ {
@ -41,5 +26,17 @@
{ {
MessageDepot.Clear(); MessageDepot.Clear();
} }
public ComponentDepotState Serialize()
{
var state = ComponentDepot.CreateState();
ComponentDepot.Serialize(state);
return state;
}
public void Deserialize(ComponentDepotState state)
{
ComponentDepot.Deserialize(state);
}
} }
} }