initial serialization structure
parent
5243259acb
commit
2fc1b68f41
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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>();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
35
src/World.cs
35
src/World.cs
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue