From ab85d19031c0c8b2f0c11a9ff19431d94579520a Mon Sep 17 00:00:00 2001 From: Laszlo Paillat Date: Sat, 5 Jun 2021 23:53:13 +0200 Subject: [PATCH] fixed serialisation of World component --- .../Serialization/ISerializerTest.cs | 30 +++++++++++- .../BinarySerializationContext.cs | 14 +++++- .../Serialization/BinarySerializer.cs | 38 ++++++++++++++- .../Serialization/TextSerializationContext.cs | 14 +++++- .../Serialization/TextSerializer.cs | 46 +++++++++++++++++-- .../BinarySerializer/ComponentTypeWriter.cs | 19 ++++++-- .../BinarySerializer/EntityWriter.cs | 28 +++++++---- .../Technical/Serialization/EntryType.cs | 4 +- .../TextSerializer/ComponentTypeWriter.cs | 22 +++++++-- .../TextSerializer/EntityWriter.cs | 37 +++++++++------ 10 files changed, 207 insertions(+), 45 deletions(-) diff --git a/source/DefaultEcs.Test/Serialization/ISerializerTest.cs b/source/DefaultEcs.Test/Serialization/ISerializerTest.cs index 81c03a6b..8988e06c 100644 --- a/source/DefaultEcs.Test/Serialization/ISerializerTest.cs +++ b/source/DefaultEcs.Test/Serialization/ISerializerTest.cs @@ -210,6 +210,8 @@ public void Serialize_Should_serialize_World(Type serializerType) { using World world = new(42); + world.Set("hello"); + world.SetMaxCapacity(13); world.SetMaxCapacity(60); @@ -238,12 +240,15 @@ public void Serialize_Should_serialize_World(Type serializerType) entities[0].Set(new ClassTest { Id = 12345, Inner = new Test(66), Test = new InnerTest2() }); entities[2].Set(new InnerTest { Lol = 313 }); entities[1].SetSameAs(entities[2]); + entities[1].SetSameAsWorld(); entities[1].Set(new Test(42)); entities[2].SetSameAs(entities[1]); entities[2].SetSameAs(entities[0]); entities[2].Disable(); entities[2].Set(42); entities[2].Disable(); + entities[2].SetSameAsWorld(); + entities[2].Disable(); entities[0].Set(); entities[0].Set>(new int[] { 1, 2, 3 }); @@ -270,6 +275,8 @@ public void Serialize_Should_serialize_World(Type serializerType) { Check.That(copyWorld.MaxCapacity).IsEqualTo(world.MaxCapacity); + Check.That(copyWorld.Get()).IsEqualTo(world.Get()); + Entity[] entitiesCopy = copyWorld.ToArray(); Check.That(entitiesCopy[0].Has()); @@ -292,6 +299,7 @@ public void Serialize_Should_serialize_World(Type serializerType) Check.That(entitiesCopy[0].Get()).IsEqualTo(entities[0].Get()); Check.That(entitiesCopy[1].Get()).IsEqualTo(entities[1].Get()); + Check.That(entitiesCopy[1].Get()).IsEqualTo(entities[1].Get()); Check.That(entitiesCopy[1].Get()).IsEqualTo(entities[1].Get()); Check.That(entitiesCopy[1].Get()).IsEqualTo(entitiesCopy[2].Get()); @@ -306,6 +314,8 @@ public void Serialize_Should_serialize_World(Type serializerType) Check.That(entitiesCopy[2].IsEnabled()).IsFalse(); Check.That(entitiesCopy[2].Get()).IsEqualTo(entities[2].Get()); Check.That(entitiesCopy[2].IsEnabled()).IsFalse(); + Check.That(entitiesCopy[2].Get()).IsEqualTo(entities[2].Get()); + Check.That(entitiesCopy[2].IsEnabled()).IsFalse(); } } finally @@ -539,9 +549,11 @@ public void Should_use_context_marshalling(ISerializer serializer, IDisposable c { using World world = new(); + world.SetMaxCapacity(10); + world.Set(42); + Entity entity0 = world.CreateEntity(); - world.SetMaxCapacity(10); entity0.Set(42); entity0.Set(1); @@ -559,6 +571,15 @@ public void Should_use_context_marshalling(ISerializer serializer, IDisposable c entity3.SetSameAs(entity0); entity3.Disable(); + Entity entity4 = world.CreateEntity(); + + entity4.SetSameAsWorld(); + + Entity entity5 = world.CreateEntity(); + + entity5.SetSameAsWorld(); + entity5.Disable(); + using Stream stream = new MemoryStream(); serializer.Serialize(stream, world); @@ -567,9 +588,11 @@ public void Should_use_context_marshalling(ISerializer serializer, IDisposable c using World copy = serializer.Deserialize(stream); + Check.That(copy.Get()).IsEqualTo("42"); + Entity[] entities = copy.ToArray(); Check.That(copy.GetMaxCapacity()).IsEqualTo(10); - Check.That(entities.Length).IsEqualTo(4); + Check.That(entities.Length).IsEqualTo(6); Check.That(entities[0].Get()).IsEqualTo(entity0.Get()); Check.That(entities[0].Has()).IsFalse(); Check.That(entities[0].Has()).IsFalse(); @@ -591,6 +614,9 @@ public void Should_use_context_marshalling(ISerializer serializer, IDisposable c Check.That(entities[3].Has()).IsTrue(); Check.That(entities[3].IsEnabled()).IsFalse(); Check.That(entities[3].Get()).IsEqualTo("42"); + Check.That(entities[4].Get()).IsEqualTo("42"); + Check.That(entities[5].Get()).IsEqualTo("42"); + Check.That(entities[5].IsEnabled()).IsFalse(); } } diff --git a/source/DefaultEcs/Serialization/BinarySerializationContext.cs b/source/DefaultEcs/Serialization/BinarySerializationContext.cs index 2c6ae264..ff6f35ef 100644 --- a/source/DefaultEcs/Serialization/BinarySerializationContext.cs +++ b/source/DefaultEcs/Serialization/BinarySerializationContext.cs @@ -34,10 +34,14 @@ public MarshalComponentOperation(Func converter) public void SetMaxCapacity(World world, int maxCapacity) => world.SetMaxCapacity(maxCapacity); + public void Set(World world, in StreamReaderWrapper reader) => world.Set(_converter(Converter.Read(reader))); + public void Set(in Entity entity, in StreamReaderWrapper reader) => entity.Set(_converter(Converter.Read(reader))); public void SetSameAs(in Entity entity, in Entity reference) => entity.SetSameAs(reference); + public void SetSameAsWorld(in Entity entity) => entity.SetSameAsWorld(); + public void SetDisabled(in Entity entity, in StreamReaderWrapper reader) { Set(entity, reader); @@ -50,6 +54,12 @@ public void SetDisabledSameAs(in Entity entity, in Entity reference) entity.Disable(); } + public void SetDisabledSameAsWorld(in Entity entity) + { + SetSameAsWorld(entity); + entity.Disable(); + } + public BinarySerializer.IComponentOperation ApplyContext(BinarySerializationContext context) => this; #endregion @@ -79,7 +89,7 @@ public BinarySerializationContext() #region Methods - internal Action GetWorldWrite() => _id < SerializationContext.Actions.Length ? SerializationContext.Actions[_id].WorldWrite as Action : null; + internal Action GetWorldWrite() => _id < SerializationContext.Actions.Length ? SerializationContext.Actions[_id].WorldWrite as Action : null; internal Action GetEntityWrite() => _id < SerializationContext.Actions.Length ? SerializationContext.Actions[_id].EntityWrite as Action : null; @@ -106,7 +116,7 @@ public BinarySerializationContext Marshal(Func converter) { SerializationContext.SetWriteActions( _id, - new Action((writer, maxCapacity) => writer.WriteComponent(maxCapacity)), + new Action((writer, maxCapacity, hasComponent) => writer.WriteComponent(maxCapacity, hasComponent, w => converter(w.Get()))), new Action((writer, value, owner, isEnabled) => writer.WriteComponent(converter(value), owner, isEnabled)), new WriteAction((in StreamWriterWrapper writer, in TIn value) => { diff --git a/source/DefaultEcs/Serialization/BinarySerializer.cs b/source/DefaultEcs/Serialization/BinarySerializer.cs index c8bd4be3..4f60a87f 100644 --- a/source/DefaultEcs/Serialization/BinarySerializer.cs +++ b/source/DefaultEcs/Serialization/BinarySerializer.cs @@ -17,10 +17,13 @@ public sealed class BinarySerializer : ISerializer internal interface IComponentOperation { void SetMaxCapacity(World world, int maxCapacity); + void Set(World world, in StreamReaderWrapper reader); void Set(in Entity entity, in StreamReaderWrapper reader); void SetSameAs(in Entity entity, in Entity reference); + void SetSameAsWorld(in Entity entity); void SetDisabled(in Entity entity, in StreamReaderWrapper reader); void SetDisabledSameAs(in Entity entity, in Entity reference); + void SetDisabledSameAsWorld(in Entity entity); IComponentOperation ApplyContext(BinarySerializationContext context); } @@ -30,10 +33,14 @@ private sealed class ComponentOperation : IComponentOperation public void SetMaxCapacity(World world, int maxCapacity) => world.SetMaxCapacity(maxCapacity); + public void Set(World world, in StreamReaderWrapper reader) => world.Set(Converter.Read(reader)); + public void Set(in Entity entity, in StreamReaderWrapper reader) => entity.Set(Converter.Read(reader)); public void SetSameAs(in Entity entity, in Entity reference) => entity.SetSameAs(reference); + public void SetSameAsWorld(in Entity entity) => entity.SetSameAsWorld(); + public void SetDisabled(in Entity entity, in StreamReaderWrapper reader) { Set(entity, reader); @@ -46,6 +53,12 @@ public void SetDisabledSameAs(in Entity entity, in Entity reference) entity.Disable(); } + public void SetDisabledSameAsWorld(in Entity entity) + { + SetSameAsWorld(entity); + entity.Disable(); + } + public IComponentOperation ApplyContext(BinarySerializationContext context) => context?.GetComponentOperation() ?? this; #endregion @@ -57,14 +70,20 @@ private sealed class IgnoreComponentOperation : IComponentOperation public void SetMaxCapacity(World world, int maxCapacity) { } + public void Set(World world, in StreamReaderWrapper reader) => Converter.Read(reader); + public void Set(in Entity entity, in StreamReaderWrapper reader) => Converter.Read(reader); public void SetSameAs(in Entity entity, in Entity reference) { } + public void SetSameAsWorld(in Entity entity) { } + public void SetDisabled(in Entity entity, in StreamReaderWrapper reader) => Set(entity, reader); public void SetDisabledSameAs(in Entity entity, in Entity reference) { } + public void SetDisabledSameAsWorld(in Entity entity) { } + public IComponentOperation ApplyContext(BinarySerializationContext context) => this; #endregion @@ -164,13 +183,24 @@ private ICollection Deserialize(Stream stream, ref World world) break; case EntryType.Component: - componentOperations[reader.Read()].Set(currentEntity, reader); + if (currentEntity == default) + { + componentOperations[reader.Read()].Set(world, reader); + } + else + { + componentOperations[reader.Read()].Set(currentEntity, reader); + } break; case EntryType.ComponentSameAs: componentOperations[reader.Read()].SetSameAs(currentEntity, entities[reader.Read()]); break; + case EntryType.ComponentSameAsWorld: + componentOperations[reader.Read()].SetSameAsWorld(currentEntity); + break; + case EntryType.DisabledEntity: currentEntity = world.CreateEntity(); currentEntity.Disable(); @@ -184,6 +214,10 @@ private ICollection Deserialize(Stream stream, ref World world) case EntryType.DisabledComponentSameAs: componentOperations[reader.Read()].SetDisabledSameAs(currentEntity, entities[reader.Read()]); break; + + case EntryType.DisabledComponentSameAsWorld: + componentOperations[reader.Read()].SetDisabledSameAsWorld(currentEntity); + break; } } @@ -281,7 +315,7 @@ public void Serialize(Stream stream, World world) Dictionary types = new(); - world.ReadAllComponentTypes(new ComponentTypeWriter(writer, types, world.MaxCapacity, _componentFilter)); + world.ReadAllComponentTypes(new ComponentTypeWriter(world, writer, types, world.MaxCapacity, _componentFilter)); new EntityWriter(writer, types, _componentFilter).Write(world); } diff --git a/source/DefaultEcs/Serialization/TextSerializationContext.cs b/source/DefaultEcs/Serialization/TextSerializationContext.cs index eff5dde0..07a6ae64 100644 --- a/source/DefaultEcs/Serialization/TextSerializationContext.cs +++ b/source/DefaultEcs/Serialization/TextSerializationContext.cs @@ -33,10 +33,14 @@ public MarshalComponentOperation(Func converter) public void SetMaxCapacity(World world, int maxCapacity) => world.SetMaxCapacity(maxCapacity); + public void Set(World world, StreamReaderWrapper reader) => world.Set(_converter(Converter.Read(reader))); + public void Set(in Entity entity, StreamReaderWrapper reader) => entity.Set(_converter(Converter.Read(reader))); public void SetSameAs(in Entity entity, in Entity reference) => entity.SetSameAs(reference); + public void SetSameAsWorld(in Entity entity) => entity.SetSameAsWorld(); + public void SetDisabled(in Entity entity, StreamReaderWrapper reader) { Set(entity, reader); @@ -49,6 +53,12 @@ public void SetDisabledSameAs(in Entity entity, in Entity reference) entity.Disable(); } + public void SetDisabledSameAsWorld(in Entity entity) + { + SetSameAsWorld(entity); + entity.Disable(); + } + public TextSerializer.IComponentOperation ApplyContext(TextSerializationContext context) => this; #endregion @@ -78,7 +88,7 @@ public TextSerializationContext() #region Methods - internal Action GetWorldWrite() => _id < SerializationContext.Actions.Length ? SerializationContext.Actions[_id].WorldWrite as Action : null; + internal Action GetWorldWrite() => _id < SerializationContext.Actions.Length ? SerializationContext.Actions[_id].WorldWrite as Action : null; internal Action GetEntityWrite() => _id < SerializationContext.Actions.Length ? SerializationContext.Actions[_id].EntityWrite as Action : null; @@ -105,7 +115,7 @@ public TextSerializationContext Marshal(Func converter) { SerializationContext.SetWriteActions( _id, - new Action((writer, maxCapacity) => writer.WriteComponent(maxCapacity)), + new Action((writer, maxCapacity, hasComponent) => writer.WriteComponent(maxCapacity, hasComponent, w => converter(w.Get()))), new Action((writer, value, owner, isEnabled) => writer.WriteComponent(converter(value), owner, isEnabled)), new WriteAction((StreamWriterWrapper writer, in TIn value) => { diff --git a/source/DefaultEcs/Serialization/TextSerializer.cs b/source/DefaultEcs/Serialization/TextSerializer.cs index 81e0275e..6b21b9ca 100644 --- a/source/DefaultEcs/Serialization/TextSerializer.cs +++ b/source/DefaultEcs/Serialization/TextSerializer.cs @@ -19,10 +19,13 @@ public sealed class TextSerializer : ISerializer internal interface IComponentOperation { void SetMaxCapacity(World world, int maxCapacity); + void Set(World world, StreamReaderWrapper reader); void Set(in Entity entity, StreamReaderWrapper reader); void SetSameAs(in Entity entity, in Entity reference); + void SetSameAsWorld(in Entity entity); void SetDisabled(in Entity entity, StreamReaderWrapper reader); void SetDisabledSameAs(in Entity entity, in Entity reference); + void SetDisabledSameAsWorld(in Entity entity); IComponentOperation ApplyContext(TextSerializationContext context); } @@ -32,10 +35,14 @@ private sealed class ComponentOperation : IComponentOperation public void SetMaxCapacity(World world, int maxCapacity) => world.SetMaxCapacity(maxCapacity); + public void Set(World world, StreamReaderWrapper reader) => world.Set(Converter.Read(reader)); + public void Set(in Entity entity, StreamReaderWrapper reader) => entity.Set(Converter.Read(reader)); public void SetSameAs(in Entity entity, in Entity reference) => entity.SetSameAs(reference); + public void SetSameAsWorld(in Entity entity) => entity.SetSameAsWorld(); + public void SetDisabled(in Entity entity, StreamReaderWrapper reader) { Set(entity, reader); @@ -48,6 +55,12 @@ public void SetDisabledSameAs(in Entity entity, in Entity reference) entity.Disable(); } + public void SetDisabledSameAsWorld(in Entity entity) + { + SetSameAsWorld(entity); + entity.Disable(); + } + public IComponentOperation ApplyContext(TextSerializationContext context) => context?.GetComponentOperation() ?? this; #endregion @@ -59,14 +72,20 @@ private sealed class IgnoreComponentOperation : IComponentOperation public void SetMaxCapacity(World world, int maxCapacity) { } + public void Set(World world, StreamReaderWrapper reader) => Converter.Read(reader); + public void Set(in Entity entity, StreamReaderWrapper reader) => Converter.Read(reader); public void SetSameAs(in Entity entity, in Entity reference) { } + public void SetSameAsWorld(in Entity entity) { } + public void SetDisabled(in Entity entity, StreamReaderWrapper reader) => Set(entity, reader); public void SetDisabledSameAs(in Entity entity, in Entity reference) { } + public void SetDisabledSameAsWorld(in Entity entity) { } + public IComponentOperation ApplyContext(TextSerializationContext context) => this; #endregion @@ -237,9 +256,18 @@ static int ReadInt(StreamReaderWrapper reader) break; case nameof(EntryType.Component): - if (currentEntity.Equals(default)) throw new ArgumentException($"Encountered a component before creation of an Entity on line {reader.LineNumber}"); + if (currentEntity == default) + { + if (!isNewWorld) throw new ArgumentException($"Encoutered {nameof(EntryType.ComponentMaxCapacity)} line"); + + world ??= new World(); - ReadComponentOperation(reader, componentOperations).Set(currentEntity, reader); + ReadComponentOperation(reader, componentOperations).Set(world, reader); + } + else + { + ReadComponentOperation(reader, componentOperations).Set(currentEntity, reader); + } break; case nameof(EntryType.ComponentSameAs): @@ -248,6 +276,12 @@ static int ReadInt(StreamReaderWrapper reader) ReadComponentOperation(reader, componentOperations).SetSameAs(currentEntity, ReadEntity(reader, entities)); break; + case nameof(EntryType.ComponentSameAsWorld): + if (currentEntity.Equals(default)) throw new ArgumentException($"Encountered a component before creation of an Entity on line {reader.LineNumber}"); + + ReadComponentOperation(reader, componentOperations).SetSameAsWorld(currentEntity); + break; + case nameof(EntryType.DisabledComponent): if (currentEntity.Equals(default)) throw new ArgumentException($"Encountered a component before creation of an Entity on line {reader.LineNumber}"); @@ -259,6 +293,12 @@ static int ReadInt(StreamReaderWrapper reader) ReadComponentOperation(reader, componentOperations).SetDisabledSameAs(currentEntity, ReadEntity(reader, entities)); break; + + case nameof(EntryType.DisabledComponentSameAsWorld): + if (currentEntity.Equals(default)) throw new ArgumentException($"Encountered a component before creation of an Entity on line {reader.LineNumber}"); + + ReadComponentOperation(reader, componentOperations).SetDisabledSameAsWorld(currentEntity); + break; } reader.EndLine(); @@ -363,7 +403,7 @@ public void Serialize(Stream stream, World world) writer.Stream.WriteLine(world.MaxCapacity); } - world.ReadAllComponentTypes(new ComponentTypeWriter(writer, types, world.MaxCapacity, _componentFilter)); + world.ReadAllComponentTypes(new ComponentTypeWriter(world, writer, types, world.MaxCapacity, _componentFilter)); new EntityWriter(writer, types, _componentFilter).Write(world); } diff --git a/source/DefaultEcs/Technical/Serialization/BinarySerializer/ComponentTypeWriter.cs b/source/DefaultEcs/Technical/Serialization/BinarySerializer/ComponentTypeWriter.cs index 5dfe579d..0ec9891f 100644 --- a/source/DefaultEcs/Technical/Serialization/BinarySerializer/ComponentTypeWriter.cs +++ b/source/DefaultEcs/Technical/Serialization/BinarySerializer/ComponentTypeWriter.cs @@ -8,6 +8,7 @@ internal sealed class ComponentTypeWriter : IComponentTypeReader { #region Fields + private readonly World _world; private readonly StreamWriterWrapper _writer; private readonly Dictionary _types; private readonly int _worldMaxCapacity; @@ -19,8 +20,9 @@ internal sealed class ComponentTypeWriter : IComponentTypeReader #region Initialisation - public ComponentTypeWriter(in StreamWriterWrapper writer, Dictionary types, int worldMaxCapacity, Predicate componentFilter) + public ComponentTypeWriter(World world, in StreamWriterWrapper writer, Dictionary types, int worldMaxCapacity, Predicate componentFilter) { + _world = world; _writer = writer; _types = types; _worldMaxCapacity = worldMaxCapacity; @@ -31,7 +33,7 @@ public ComponentTypeWriter(in StreamWriterWrapper writer, Dictionary(int maxCapacity) + public void WriteComponent(int maxCapacity, bool hasComponent, Func getter) { _types.Add(typeof(T), _currentType); @@ -46,6 +48,13 @@ public void WriteComponent(int maxCapacity) _writer.Write(maxCapacity); } + if (hasComponent) + { + _writer.WriteByte((byte)EntryType.Component); + _writer.Write(_currentType); + Converter.Write(_writer, getter(_world)); + } + ++_currentType; } @@ -57,14 +66,14 @@ void IComponentTypeReader.OnRead(int maxCapacity) { if (_componentFilter(typeof(T))) { - Action action = _writer.Context?.GetWorldWrite(); + Action action = _writer.Context?.GetWorldWrite(); if (action is null) { - WriteComponent(maxCapacity); + WriteComponent(maxCapacity, _world.Has(), w => w.Get()); } else { - action(this, maxCapacity); + action(this, maxCapacity, _world.Has()); } } } diff --git a/source/DefaultEcs/Technical/Serialization/BinarySerializer/EntityWriter.cs b/source/DefaultEcs/Technical/Serialization/BinarySerializer/EntityWriter.cs index 62c58ea6..bb6fb0bb 100644 --- a/source/DefaultEcs/Technical/Serialization/BinarySerializer/EntityWriter.cs +++ b/source/DefaultEcs/Technical/Serialization/BinarySerializer/EntityWriter.cs @@ -61,21 +61,29 @@ public void WriteComponent(in T component, in Entity componentOwner, bool isE _writer.WriteString(TypeNames.Get(typeof(T))); } - (Entity, Type) componentKey = (componentOwner, typeof(T)); - if (_components.TryGetValue(componentKey, out int key)) + if (componentOwner.IsAlive) { - _writer.WriteByte((byte)(isEnabled ? EntryType.ComponentSameAs : EntryType.DisabledComponentSameAs)); - _writer.Write(typeId); - _writer.Write(key); + (Entity, Type) componentKey = (componentOwner, typeof(T)); + if (_components.TryGetValue(componentKey, out int key)) + { + _writer.WriteByte((byte)(isEnabled ? EntryType.ComponentSameAs : EntryType.DisabledComponentSameAs)); + _writer.Write(typeId); + _writer.Write(key); + } + else + { + _components.Add(componentKey, _entityCount); + + _writer.WriteByte((byte)(isEnabled ? EntryType.Component : EntryType.DisabledComponent)); + _writer.Write(typeId); + + Converter.Write(_writer, component); + } } else { - _components.Add(componentKey, _entityCount); - - _writer.WriteByte((byte)(isEnabled ? EntryType.Component : EntryType.DisabledComponent)); + _writer.WriteByte((byte)(isEnabled ? EntryType.ComponentSameAsWorld : EntryType.DisabledComponentSameAsWorld)); _writer.Write(typeId); - - Converter.Write(_writer, component); } } diff --git a/source/DefaultEcs/Technical/Serialization/EntryType.cs b/source/DefaultEcs/Technical/Serialization/EntryType.cs index 9f9ac07f..e02efa7e 100644 --- a/source/DefaultEcs/Technical/Serialization/EntryType.cs +++ b/source/DefaultEcs/Technical/Serialization/EntryType.cs @@ -10,6 +10,8 @@ internal enum EntryType : byte ComponentSameAs = 5, DisabledEntity = 6, DisabledComponent = 7, - DisabledComponentSameAs = 8 + DisabledComponentSameAs = 8, + ComponentSameAsWorld = 9, + DisabledComponentSameAsWorld = 10 } } diff --git a/source/DefaultEcs/Technical/Serialization/TextSerializer/ComponentTypeWriter.cs b/source/DefaultEcs/Technical/Serialization/TextSerializer/ComponentTypeWriter.cs index 0a4c5a62..1bb1f252 100644 --- a/source/DefaultEcs/Technical/Serialization/TextSerializer/ComponentTypeWriter.cs +++ b/source/DefaultEcs/Technical/Serialization/TextSerializer/ComponentTypeWriter.cs @@ -10,6 +10,7 @@ internal sealed class ComponentTypeWriter : IComponentTypeReader { #region Fields + private readonly World _world; private readonly StreamWriterWrapper _writer; private readonly Dictionary _types; private readonly int _worldMaxCapacity; @@ -19,8 +20,9 @@ internal sealed class ComponentTypeWriter : IComponentTypeReader #region Initialisation - public ComponentTypeWriter(StreamWriterWrapper writer, Dictionary types, int worldMaxCapacity, Predicate componentFilter) + public ComponentTypeWriter(World world, StreamWriterWrapper writer, Dictionary types, int worldMaxCapacity, Predicate componentFilter) { + _world = world; _writer = writer; _types = types; _worldMaxCapacity = worldMaxCapacity; @@ -31,7 +33,7 @@ public ComponentTypeWriter(StreamWriterWrapper writer, Dictionary #region Methods - public void WriteComponent(int maxCapacity) + public void WriteComponent(int maxCapacity, bool hasComponent, Func getter) { string shortName = typeof(T).Name; @@ -48,6 +50,7 @@ public void WriteComponent(int maxCapacity) _writer.Write(shortName); _writer.WriteSpace(); _writer.WriteLine(TypeNames.Get(typeof(T))); + if (maxCapacity != _worldMaxCapacity && !typeof(T).GetTypeInfo().IsFlagType()) { _writer.Write(nameof(EntryType.ComponentMaxCapacity)); @@ -56,6 +59,15 @@ public void WriteComponent(int maxCapacity) _writer.WriteSpace(); _writer.Stream.WriteLine(maxCapacity); } + + if (hasComponent) + { + _writer.Write(nameof(EntryType.Component)); + _writer.WriteSpace(); + _writer.Write(shortName); + _writer.WriteSpace(); + Converter.Write(_writer, getter(_world)); + } } #endregion @@ -66,14 +78,14 @@ void IComponentTypeReader.OnRead(int maxCapacity) { if (_componentFilter(typeof(T))) { - Action action = _writer.Context?.GetWorldWrite(); + Action action = _writer.Context?.GetWorldWrite(); if (action is null) { - WriteComponent(maxCapacity); + WriteComponent(maxCapacity, _world.Has(), w => w.Get()); } else { - action(this, maxCapacity); + action(this, maxCapacity, _world.Has()); } } } diff --git a/source/DefaultEcs/Technical/Serialization/TextSerializer/EntityWriter.cs b/source/DefaultEcs/Technical/Serialization/TextSerializer/EntityWriter.cs index 060d1ec8..3758cf2f 100644 --- a/source/DefaultEcs/Technical/Serialization/TextSerializer/EntityWriter.cs +++ b/source/DefaultEcs/Technical/Serialization/TextSerializer/EntityWriter.cs @@ -69,27 +69,38 @@ public void WriteComponent(in T component, in Entity componentOwner, bool isE _writer.WriteLine(TypeNames.Get(typeof(T))); } - (Entity, Type) componentKey = (componentOwner, typeof(T)); - if (_components.TryGetValue(componentKey, out int key)) + if (componentOwner.IsAlive) { - string entry = isEnabled ? nameof(EntryType.ComponentSameAs) : nameof(EntryType.DisabledComponentSameAs); + (Entity, Type) componentKey = (componentOwner, typeof(T)); + if (_components.TryGetValue(componentKey, out int key)) + { + string entry = isEnabled ? nameof(EntryType.ComponentSameAs) : nameof(EntryType.DisabledComponentSameAs); - _writer.Write(entry); - _writer.WriteSpace(); - _writer.Write(_types[typeof(T)]); - _writer.WriteSpace(); - _writer.Stream.WriteLine(key); + _writer.Write(entry); + _writer.WriteSpace(); + _writer.Write(_types[typeof(T)]); + _writer.WriteSpace(); + _writer.Stream.WriteLine(key); + } + else + { + _components.Add(componentKey, _entityCount); + string entry = isEnabled ? nameof(EntryType.Component) : nameof(EntryType.DisabledComponent); + + _writer.Write(entry); + _writer.WriteSpace(); + _writer.Write(_types[typeof(T)]); + _writer.WriteSpace(); + Converter.Write(_writer, component); + } } else { - _components.Add(componentKey, _entityCount); - string entry = isEnabled ? nameof(EntryType.Component) : nameof(EntryType.DisabledComponent); + string entry = isEnabled ? nameof(EntryType.ComponentSameAsWorld) : nameof(EntryType.DisabledComponentSameAsWorld); _writer.Write(entry); _writer.WriteSpace(); - _writer.Write(_types[typeof(T)]); - _writer.WriteSpace(); - Converter.Write(_writer, component); + _writer.WriteLine(_types[typeof(T)]); } }