Files
zfxaction26_1/src/SideScrollerGame.Sim/Serialization/SimulationStateSerializer.cs

98 lines
3.5 KiB
C#

using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using SideScrollerGame.Sim.Math;
using SideScrollerGame.Sim.Runtime;
namespace SideScrollerGame.Sim.Serialization;
[ExcludeFromCodeCoverage]
internal static class SimulationStateSerializer
{
[ExcludeFromCodeCoverage]
private sealed record SimulationStateDocument
{
public int Version { get; init; }
public int Tick { get; init; }
public int Seed { get; init; }
public ulong RandomState { get; init; }
public ulong LastRandomValue { get; init; }
public ImmutableArray<PlayerStateDocument> Players { get; init; }
public ImmutableArray<string> ActivatedTriggerIds { get; init; }
}
[ExcludeFromCodeCoverage]
private sealed record PlayerStateDocument
{
public int PlayerId { get; init; }
public int PositionX { get; init; }
public int PositionY { get; init; }
public sbyte MoveAxisX { get; init; }
public sbyte MoveAxisY { get; init; }
public short AimAxisX { get; init; }
public short AimAxisY { get; init; }
public int SelectedWeaponSlot { get; init; }
public int ButtonMask { get; init; }
public int Health { get; init; }
}
public static byte[] Serialize(SimulationState state)
{
List<PlayerStateDocument> players = new(state.Players.Length);
foreach (var player in state.Players)
{
players.Add(new()
{
PlayerId = player.PlayerId.Value,
PositionX = player.Position.m_X.m_Value,
PositionY = player.Position.m_Y.m_Value,
MoveAxisX = player.MoveAxisX,
MoveAxisY = player.MoveAxisY,
AimAxisX = player.AimAxisX,
AimAxisY = player.AimAxisY,
SelectedWeaponSlot = player.SelectedWeaponSlot,
ButtonMask = player.ButtonMask,
Health = player.Health
});
}
return JsonSerializer.SerializeToUtf8Bytes(new SimulationStateDocument
{
Version = SimulationDefaults.StateFormatVersion,
Tick = state.Tick,
Seed = state.Seed,
RandomState = state.RandomState,
LastRandomValue = state.LastRandomValue,
Players = players.ToImmutableArray(),
ActivatedTriggerIds = state.ActivatedTriggerIds.Order(StringComparer.Ordinal).ToImmutableArray()
});
}
public static SimulationState Deserialize(byte[] data)
{
var document = JsonSerializer.Deserialize<SimulationStateDocument>(data) ?? throw new InvalidOperationException("Simulation state payload was empty.");
if (document.Version != SimulationDefaults.StateFormatVersion)
throw new NotSupportedException($"Unsupported simulation state version {document.Version}.");
var players = ImmutableArray.CreateBuilder<PlayerState>(document.Players.Length);
foreach (var player in document.Players)
players.Add(new(new(player.PlayerId), new(new() { m_Value = player.PositionX }, new FixPoint16 { m_Value = player.PositionY }), player.MoveAxisX, player.MoveAxisY, player.AimAxisX, player.AimAxisY, player.SelectedWeaponSlot, player.ButtonMask, player.Health));
return new(document.Tick, document.Seed, document.RandomState, document.LastRandomValue, players.MoveToImmutable(), document.ActivatedTriggerIds.ToImmutableHashSet(StringComparer.Ordinal));
}
}