wip: Serialization Game Manager

This commit is contained in:
Syntriax 2024-02-10 20:02:38 +03:00
parent 2f6fecdd78
commit 4c04e3d02f
6 changed files with 162 additions and 9 deletions

View File

@ -0,0 +1,8 @@
using System.Collections.Generic;
namespace Engine.Serialization.DTOs;
internal record struct GameManagerDTO(
string ClassType,
List<GameObjectDTO> GameObjects
);

View File

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using Engine.Serialization.DTOs;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Serialization;
namespace Engine.Serialization;
internal class GameManagerYamlConverter : IYamlTypeConverter
{
public bool Accepts(Type type) => type == typeof(GameManagerDTO);
public object ReadYaml(IParser parser, Type type)
{
if (parser.Current is not MappingStart)
throw new InvalidOperationException("Expected MappingStart");
parser.MoveNext();
var gameManager = new GameManagerDTO();
while (parser.Current != null && parser.Current is not MappingEnd)
{
var propertyName = ((Scalar)parser.Current).Value;
parser.MoveNext();
switch (propertyName)
{
case nameof(GameManagerDTO.ClassType):
gameManager.ClassType = ((Scalar)parser.Current).Value;
break;
case nameof(GameManagerDTO.GameObjects):
gameManager.GameObjects = (List<GameObjectDTO>)new GameObjectDTOListConverter().ReadYaml(parser, typeof(List<GameObjectDTO>));
break;
}
parser.MoveNext();
}
return gameManager;
}
public void WriteYaml(IEmitter emitter, object? value, Type type)
{
var gameManager = (GameManagerDTO)(value ?? throw new Exception());
GameObjectDTOListConverter gameObjectDTOListConverter = new();
emitter.Emit(new MappingStart());
emitter.Emit(new Scalar(nameof(GameManagerDTO.ClassType)));
emitter.Emit(new Scalar(gameManager.ClassType));
emitter.Emit(new Scalar(nameof(GameManagerDTO.GameObjects)));
gameObjectDTOListConverter.WriteYaml(emitter, gameManager.GameObjects, typeof(List<GameObjectDTO>));
emitter.Emit(new MappingEnd());
}
}

View File

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using Engine.Serialization.DTOs;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Serialization;
namespace Engine.Serialization;
public class GameObjectDTOListConverter : IYamlTypeConverter
{
public bool Accepts(Type type)
{
return type == typeof(List<GameObjectDTO>);
}
public object ReadYaml(IParser parser, Type type)
{
var gameObjects = new List<GameObjectDTO>();
if (parser.Current is SequenceStart)
{
parser.MoveNext();
while (parser.Current != null && !(parser.Current is SequenceEnd))
{
gameObjects.Add((GameObjectDTO)new GameObjectYamlConverter().ReadYaml(parser, typeof(GameObjectDTO)));
parser.MoveNext();
}
}
return gameObjects;
}
public void WriteYaml(IEmitter emitter, object? value, Type type)
{
var gameObjects = (List<GameObjectDTO>)(value ?? throw new Exception());
emitter.Emit(new SequenceStart(null, null, false, SequenceStyle.Block));
foreach (var gameObject in gameObjects)
new GameObjectYamlConverter().WriteYaml(emitter, gameObject, typeof(BehaviourDTO));
emitter.Emit(new SequenceEnd());
}
}

View File

@ -12,6 +12,15 @@ internal static class InternalExtensions
public static GameObjectDTO ToDTO(this IGameObject gameObject) public static GameObjectDTO ToDTO(this IGameObject gameObject)
=> new(gameObject.GetType().FullName ?? throw new System.Exception(), gameObject.Id, gameObject.Name, gameObject.Transform.ToDTO(), gameObject.BehaviourController.ToDTO(), gameObject.StateEnable.ToDTO()); => new(gameObject.GetType().FullName ?? throw new System.Exception(), gameObject.Id, gameObject.Name, gameObject.Transform.ToDTO(), gameObject.BehaviourController.ToDTO(), gameObject.StateEnable.ToDTO());
public static GameManagerDTO ToDTO(this IGameManager gameManager)
{
List<GameObjectDTO> dtos = [];
foreach (var gameObject in gameManager)
dtos.Add(gameObject.ToDTO());
return new(gameManager.GetType().FullName ?? throw new System.Exception(), dtos);
}
public static StateEnableDTO ToDTO(this IStateEnable stateEnable) public static StateEnableDTO ToDTO(this IStateEnable stateEnable)
=> new(stateEnable.GetType().FullName ?? throw new System.Exception(), stateEnable.Enabled); => new(stateEnable.GetType().FullName ?? throw new System.Exception(), stateEnable.Enabled);

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using Engine.Serialization.DTOs; using Engine.Serialization.DTOs;
using Syntriax.Engine.Core; using Syntriax.Engine.Core;
using Syntriax.Engine.Core.Abstract; using Syntriax.Engine.Core.Abstract;
@ -14,11 +15,44 @@ public static class Serialization
public static T DeserializeGameObject<T>(string serializedString) where T : class, IGameObject public static T DeserializeGameObject<T>(string serializedString) where T : class, IGameObject
{ {
GameObjectDTO gameObjectDTO = Deserialize<GameObjectDTO>(serializedString, defaultSerializer); GameObjectDTO gameObjectDTO = Deserialize<GameObjectDTO>(serializedString, defaultSerializer);
return CreateGameObject<T>(gameObjectDTO);
}
private static T CreateGameObject<T>(GameObjectDTO gameObjectDTO) where T : class, IGameObject
{
Type gameObjectType = (gameObjectDTO.ClassType is not null) ? TypeFactory.Get(gameObjectDTO.ClassType) : typeof(GameObject); Type gameObjectType = (gameObjectDTO.ClassType is not null) ? TypeFactory.Get(gameObjectDTO.ClassType) : typeof(GameObject);
T t = new GameObjectFactory().Instantiate<T>(gameObjectType); Type stateEnableType = (gameObjectDTO.StateEnable.ClassType is not null) ? TypeFactory.Get(gameObjectDTO.StateEnable.ClassType) : typeof(Transform);
Type transformType = (gameObjectDTO.Transform.ClassType is not null) ? TypeFactory.Get(gameObjectDTO.Transform.ClassType) : typeof(Transform);
Type behaviourControllerType = (gameObjectDTO.BehaviourController.ClassType is not null) ? TypeFactory.Get(gameObjectDTO.BehaviourController.ClassType) : typeof(Transform);
ITransform transform = TypeFactory.Get<ITransform>(transformType);
IStateEnable stateEnable = TypeFactory.Get<IStateEnable>(stateEnableType);
IBehaviourController behaviourController = TypeFactory.Get<IBehaviourController>(behaviourControllerType);
T t = new GameObjectFactory().Instantiate<T>(transform, behaviourController, stateEnable, gameObjectType);
foreach (var behaviourDto in gameObjectDTO.BehaviourController.Behaviours)
{
IBehaviour behaviour = TypeFactory.Get<IBehaviour>(behaviourDto.ClassType);
behaviourController.AddBehaviour(behaviour);
}
return t; return t;
} }
public static string SerializeGameManager(IGameManager gameManager) => Serialize(gameManager.ToDTO(), defaultSerializer);
public static T DeserializeGameManager<T>(string serializedString) where T : class, IGameManager
{
GameManagerDTO gameManagerDto = Deserialize<GameManagerDTO>(serializedString, defaultSerializer);
Type gameManagerType = (gameManagerDto.ClassType is not null) ? TypeFactory.Get(gameManagerDto.ClassType) : typeof(GameManager);
T gameManager = TypeFactory.Get<T>(gameManagerType);
foreach (var gameObjectDto in gameManagerDto.GameObjects)
gameManager.RegisterGameObject(CreateGameObject<IGameObject>(gameObjectDto));
return gameManager;
}
public static string Serialize<T>(T @object) => Serialize(@object, defaultSerializer); public static string Serialize<T>(T @object) => Serialize(@object, defaultSerializer);
public static string Serialize<T>(T @object, ISerializer serializer) => serializer.Serialize(@object); public static string Serialize<T>(T @object, ISerializer serializer) => serializer.Serialize(@object);

View File

@ -7,19 +7,27 @@ public class YamlSerializer : ISerializer
{ {
private readonly YamlDotNet.Serialization.ISerializer serializer = new SerializerBuilder() private readonly YamlDotNet.Serialization.ISerializer serializer = new SerializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance) .WithNamingConvention(CamelCaseNamingConvention.Instance)
// .WithTypeConverter(new BehaviourYamlConverter())
// .WithTypeConverter(new BehaviourControllerYamlConverter())
// .WithTypeConverter(new BehaviourDTOListConverter())
// .WithTypeConverter(new GameManagerYamlConverter())
// .WithTypeConverter(new GameObjectYamlConverter())
// .WithTypeConverter(new GameObjectDTOListConverter())
// .WithTypeConverter(new StateEnableYamlConverter())
// .WithTypeConverter(new TransformYamlConverter())
.WithTypeConverter(new Vector2DYamlConverter()) .WithTypeConverter(new Vector2DYamlConverter())
.WithTypeConverter(new TransformYamlConverter())
.WithTypeConverter(new BehaviourYamlConverter())
.WithTypeConverter(new GameObjectYamlConverter())
.WithTypeConverter(new StateEnableYamlConverter())
.Build(); .Build();
private readonly YamlDotNet.Serialization.IDeserializer deserializer = new DeserializerBuilder() private readonly YamlDotNet.Serialization.IDeserializer deserializer = new DeserializerBuilder()
.WithNamingConvention(UnderscoredNamingConvention.Instance) .WithNamingConvention(UnderscoredNamingConvention.Instance)
// .WithTypeConverter(new BehaviourYamlConverter())
// .WithTypeConverter(new BehaviourControllerYamlConverter())
// .WithTypeConverter(new BehaviourDTOListConverter())
// .WithTypeConverter(new GameManagerYamlConverter())
// .WithTypeConverter(new GameObjectYamlConverter())
// .WithTypeConverter(new GameObjectDTOListConverter())
// .WithTypeConverter(new StateEnableYamlConverter())
// .WithTypeConverter(new TransformYamlConverter())
.WithTypeConverter(new Vector2DYamlConverter()) .WithTypeConverter(new Vector2DYamlConverter())
.WithTypeConverter(new TransformYamlConverter())
.WithTypeConverter(new BehaviourYamlConverter())
.WithTypeConverter(new GameObjectYamlConverter())
.WithTypeConverter(new StateEnableYamlConverter())
.Build(); .Build();
public string Serialize<T>(T @object) => serializer.Serialize(@object); public string Serialize<T>(T @object) => serializer.Serialize(@object);