Skip to content

Commit

Permalink
parent/child relationship is also serialized now
Browse files Browse the repository at this point in the history
  • Loading branch information
Doraku committed Aug 24, 2018
1 parent d83d100 commit 32e4b97
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 7 deletions.
11 changes: 9 additions & 2 deletions source/DefaultEcs.Test/Serialization/SerializerTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using DefaultEcs.Serialization;
Expand Down Expand Up @@ -130,7 +131,9 @@ public void Serialize_Should_serialize_World(Type serializerType)
entities[2].SetSameAs<Test>(entities[1]);

entities[0].Set<InnerClass>();
entities[0].Set(new int[] { 1, 2, 3 });
entities[0].Set(new List<int> { 1, 2, 3 });

entities[0].SetAsParentOf(entities[1]);

ISerializer serializer = (ISerializer)Activator.CreateInstance(serializerType);

Expand Down Expand Up @@ -179,7 +182,11 @@ public void Serialize_Should_serialize_World(Type serializerType)
Check.That(entitiesCopy[1].Get<InnerTest>()).IsEqualTo(entitiesCopy[2].Get<InnerTest>());

Check.That(entitiesCopy[0].Get<InnerClass>()).IsEqualTo(entities[0].Get<InnerClass>());
Check.That(entitiesCopy[0].Get<int[]>()).ContainsExactly(entities[0].Get<int[]>());
Check.That(entitiesCopy[0].Get<List<int>>()).ContainsExactly(entities[0].Get<List<int>>());

entitiesCopy[0].Dispose();

Check.That(copyWorld.GetAllEntities().Count()).IsEqualTo(1);
}
}
finally
Expand Down
17 changes: 17 additions & 0 deletions source/DefaultEcs/Entity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,23 @@ public void SetAsChildOf(in Entity parent)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetAsParentOf(in Entity child) => child.SetAsChildOf(this);

/// <summary>
/// Gets all the <see cref="Entity"/> setted as children of the current <see cref="Entity"/>.
/// </summary>
/// <returns></returns>
public IEnumerable<Entity> GetChildren()
{
HashSet<int> children = World.EntityInfos[WorldId][EntityId].Children;

if (children != null)
{
foreach (int childId in children)
{
yield return new Entity(WorldId, childId);
}
}
}

/// <summary>
/// Creates a copy of current <see cref="Entity"/> with all of its components in the given <see cref="World"/>.
/// </summary>
Expand Down
31 changes: 31 additions & 0 deletions source/DefaultEcs/Serialization/BinarySerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,20 @@ public void WriteEntity(in Entity entity)
entity.ReadAllComponents(this);
}

public void WriteChildren(in Entity entity)
{
*_bufferP = _parentChild;
int* ids = (int*)(_bufferP + 1);
*ids++ = _entities[entity];

foreach (Entity child in entity.GetChildren())
{
*ids = _entities[child];

_stream.Write(_buffer, 0, sizeof(byte) + sizeof(int) * 2);
}
}

#endregion

#region IComponentReader
Expand Down Expand Up @@ -185,6 +199,7 @@ public void SetComponent(in Entity entity, Stream stream, byte[] buffer, byte* b
private const byte _entity = 3;
private const byte _component = 4;
private const byte _componentSameAs = 5;
private const byte _parentChild = 6;

private static readonly ConcurrentDictionary<Type, IOperation> _operations = new ConcurrentDictionary<Type, IOperation>();

Expand Down Expand Up @@ -264,6 +279,14 @@ private static void SetSameAsComponent(in Entity entity, Stream stream, byte[] b
}
}

private static void SetAsParentOf(Stream stream, byte[] buffer, int* bufferP, Entity[] entities)
{
if (stream.Read(buffer, 0, sizeof(int) * 2) == sizeof(int) * 2)
{
entities[*bufferP++].SetAsParentOf(entities[*bufferP]);
}
}

/// <summary>
/// Writes an object of type <typeparamref name="T"/> on the given stream.
/// </summary>
Expand Down Expand Up @@ -338,6 +361,10 @@ public void Serialize(Stream stream, World world)
{
componentReader.WriteEntity(entities[i]);
}
for (int i = 0; i < entities.Length; i++)
{
componentReader.WriteChildren(entities[i]);
}
}
}
}
Expand Down Expand Up @@ -392,6 +419,10 @@ public World Deserialize(Stream stream)
case _componentSameAs:
SetSameAsComponent(currentEntity, stream, buffer, bufferP, entities, operations);
break;

case _parentChild:
SetAsParentOf(stream, buffer, (int*)bufferP, entities);
break;
}
}
}
Expand Down
52 changes: 47 additions & 5 deletions source/DefaultEcs/Serialization/TextSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public void OnRead<T>(int maxComponentCount)
#endregion
}

private sealed class ComponentWriter : IComponentReader
private sealed class EntityWriter : IComponentReader
{
#region Fields

Expand All @@ -74,7 +74,7 @@ private sealed class ComponentWriter : IComponentReader

#region Initialisation

public ComponentWriter(StreamWriter writer, Dictionary<Type, string> types)
public EntityWriter(StreamWriter writer, Dictionary<Type, string> types)
{
_writer = writer;
_types = types;
Expand All @@ -97,6 +97,16 @@ public void WriteEntity(in Entity entity)
entity.ReadAllComponents(this);
}

public void WriteChildren(in Entity entity)
{
int parentId = _entities[entity];

foreach (Entity child in entity.GetChildren())
{
_writer.WriteLine($"{_parentChild} {parentId} {_entities[child]}");
}
}

#endregion

#region IComponentReader
Expand Down Expand Up @@ -159,6 +169,7 @@ public void SetComponent(string line, StreamReader reader, in Entity entity)
private const string _entity = "Entity";
private const string _component = "Component";
private const string _componentSameAs = "ComponentSameAs";
private const string _parentChild = "ParentChild";

private static readonly char[] _split = new[] { ' ', '\t' };
private static readonly ConcurrentDictionary<Type, IOperation> _operations = new ConcurrentDictionary<Type, IOperation>();
Expand Down Expand Up @@ -261,6 +272,25 @@ private static void SetSameAsComponent(in Entity entity, string entry, Dictionar
operation.SetSameAsComponent(entity, reference);
}

private static void SetAsParentOf(string entry, Dictionary<string, Entity> entities)
{
string[] componentEntry = entry.Split(_split, StringSplitOptions.RemoveEmptyEntries);
if (componentEntry.Length < 2)
{
throw new ArgumentException($"Unable to get Entity ids from '{entry}'");
}
if (!entities.TryGetValue(componentEntry[0], out Entity parent))
{
throw new ArgumentException($"Unknown parent Entity '{componentEntry[0]}'");
}
if (!entities.TryGetValue(componentEntry[1], out Entity child))
{
throw new ArgumentException($"Unknown child Entity '{componentEntry[1]}'");
}

parent.SetAsParentOf(child);
}

/// <summary>
/// Writes an object of type <typeparamref name="T"/> on the given stream.
/// </summary>
Expand Down Expand Up @@ -314,11 +344,19 @@ public void Serialize(Stream stream, World world)
writer.WriteLine($"{_maxEntityCount} {world.MaxEntityCount}");
world.ReadAllComponentTypes(new ComponentTypeWriter(writer, types, world.MaxEntityCount));

ComponentWriter componentReader = new ComponentWriter(writer, types);
EntityWriter componentReader = new EntityWriter(writer, types);

foreach (Entity entity in world.GetAllEntities())
using (EntitySet set = world.GetEntities().Build())
{
componentReader.WriteEntity(entity);
ReadOnlySpan<Entity> entities = set.GetEntities();
for (int i = 0; i < entities.Length; i++)
{
componentReader.WriteEntity(entities[i]);
}
for (int i = 0; i < entities.Length; i++)
{
componentReader.WriteChildren(entities[i]);
}
}
}
}
Expand Down Expand Up @@ -373,6 +411,10 @@ public World Deserialize(Stream stream)
{
SetSameAsComponent(currentEntity, lineParts[1], entities, operations);
}
else if (_parentChild.Equals(entry))
{
SetAsParentOf(lineParts[1], entities);
}
}
}
}
Expand Down

0 comments on commit 32e4b97

Please sign in to comment.