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);
}
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
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.Collections.Generic;
using System.Runtime.InteropServices;
namespace MoonTools.ECS
{
@ -8,9 +9,11 @@ namespace MoonTools.ECS
public abstract bool Has(int entityID);
public abstract void Remove(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
{
private int nextID;
@ -106,5 +109,37 @@ namespace MoonTools.ECS
{
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
{
internal EntityStorage EntityStorage;
internal ComponentDepot ComponentDepot;
internal RelationDepot RelationDepot;
protected readonly World World;
internal EntityStorage EntityStorage => World.EntityStorage;
internal ComponentDepot ComponentDepot => World.ComponentDepot;
internal RelationDepot RelationDepot => World.RelationDepot;
protected FilterBuilder FilterBuilder => new FilterBuilder(ComponentDepot);
internal void RegisterEntityStorage(EntityStorage entityStorage)
public EntityComponentReader(World world)
{
EntityStorage = entityStorage;
World = world;
}
internal void RegisterComponentDepot(ComponentDepot componentDepot)
{
ComponentDepot = componentDepot;
}
internal void RegisterRelationDepot(RelationDepot relationDepot)
{
RelationDepot = relationDepot;
}
protected ReadOnlySpan<TComponent> ReadComponents<TComponent>() where TComponent : struct
protected ReadOnlySpan<TComponent> ReadComponents<TComponent>() where TComponent : unmanaged
{
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);
}
protected bool Some<TComponent>() where TComponent : struct
protected bool Some<TComponent>() where TComponent : unmanaged
{
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);
}
protected ref readonly TComponent GetSingleton<TComponent>() where TComponent : struct
protected ref readonly TComponent GetSingleton<TComponent>() where TComponent : unmanaged
{
return ref ComponentDepot.Get<TComponent>();
}
protected Entity GetSingletonEntity<TComponent>() where TComponent : struct
protected Entity GetSingletonEntity<TComponent>() where TComponent : unmanaged
{
return ComponentDepot.GetSingletonEntity<TComponent>();
}
@ -60,22 +51,22 @@ namespace MoonTools.ECS
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>();
}
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);
}
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);
}
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);
}

View File

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

View File

@ -5,17 +5,9 @@ namespace MoonTools.ECS
{
public abstract class System : EntityComponentReader
{
internal MessageDepot MessageDepot;
internal MessageDepot MessageDepot => World.MessageDepot;
internal void RegisterMessageDepot(MessageDepot messageDepot)
{
MessageDepot = messageDepot;
}
public System(World world)
{
world.AddSystem(this);
}
public System(World world) : base(world) { }
public abstract void Update(TimeSpan delta);
@ -24,7 +16,7 @@ namespace MoonTools.ECS
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
// check for use after destroy
@ -36,52 +28,52 @@ namespace MoonTools.ECS
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);
}
protected ReadOnlySpan<TMessage> ReadMessages<TMessage>() where TMessage : struct
protected ReadOnlySpan<TMessage> ReadMessages<TMessage>() where TMessage : unmanaged
{
return MessageDepot.All<TMessage>();
}
protected TMessage ReadMessage<TMessage>() where TMessage : struct
protected TMessage ReadMessage<TMessage>() where TMessage : unmanaged
{
return MessageDepot.First<TMessage>();
}
protected bool SomeMessage<TMessage>() where TMessage : struct
protected bool SomeMessage<TMessage>() where TMessage : unmanaged
{
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);
}
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);
}
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);
}
protected void Send<TMessage>(in TMessage message) where TMessage : struct
protected void Send<TMessage>(in TMessage message) where TMessage : unmanaged
{
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);
}
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));
}

View File

@ -2,25 +2,10 @@
{
public class World
{
private readonly EntityStorage EntityStorage = new EntityStorage();
private readonly ComponentDepot ComponentDepot = new ComponentDepot();
private readonly MessageDepot MessageDepot = new MessageDepot();
private 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);
}
internal readonly EntityStorage EntityStorage = new EntityStorage();
internal readonly ComponentDepot ComponentDepot = new ComponentDepot();
internal readonly MessageDepot MessageDepot = new MessageDepot();
internal readonly RelationDepot RelationDepot = new RelationDepot();
public Entity CreateEntity()
{
@ -41,5 +26,17 @@
{
MessageDepot.Clear();
}
public ComponentDepotState Serialize()
{
var state = ComponentDepot.CreateState();
ComponentDepot.Serialize(state);
return state;
}
public void Deserialize(ComponentDepotState state)
{
ComponentDepot.Deserialize(state);
}
}
}