| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- using System.Globalization;
- using Content.Shared.Atmos;
- using Robust.Shared.Serialization;
- using Robust.Shared.Serialization.Manager;
- using Robust.Shared.Serialization.Markdown;
- using Robust.Shared.Serialization.Markdown.Mapping;
- using Robust.Shared.Serialization.Markdown.Validation;
- using Robust.Shared.Serialization.Markdown.Value;
- using Robust.Shared.Serialization.TypeSerializers.Implementations.Generic;
- using Robust.Shared.Serialization.TypeSerializers.Interfaces;
- using Robust.Shared.Utility;
- namespace Content.Server.Atmos.Serialization;
- public sealed partial class TileAtmosCollectionSerializer : ITypeSerializer<Dictionary<Vector2i, TileAtmosphere>, MappingDataNode>, ITypeCopier<Dictionary<Vector2i, TileAtmosphere>>
- {
- public ValidationNode Validate(ISerializationManager serializationManager, MappingDataNode node,
- IDependencyCollection dependencies, ISerializationContext? context = null)
- {
- return serializationManager.ValidateNode<TileAtmosData>(node, context);
- }
- public Dictionary<Vector2i, TileAtmosphere> Read(ISerializationManager serializationManager, MappingDataNode node,
- IDependencyCollection dependencies,
- SerializationHookContext hookCtx, ISerializationContext? context = null,
- ISerializationManager.InstantiationDelegate<Dictionary<Vector2i, TileAtmosphere>>? instanceProvider = null)
- {
- node.TryGetValue(new ValueDataNode("version"), out var versionNode);
- var version = ((ValueDataNode?) versionNode)?.AsInt() ?? 1;
- Dictionary<Vector2i, TileAtmosphere> tiles = new();
- // Backwards compatability
- if (version == 1)
- {
- var tile2 = node["tiles"];
- var mixies = serializationManager.Read<Dictionary<Vector2i, int>?>(tile2, hookCtx, context);
- var unique = serializationManager.Read<List<GasMixture>?>(node["uniqueMixes"], hookCtx, context);
- if (unique != null && mixies != null)
- {
- foreach (var (indices, mix) in mixies)
- {
- try
- {
- tiles.Add(indices, new TileAtmosphere(EntityUid.Invalid, indices,
- unique[mix].Clone()));
- }
- catch (ArgumentOutOfRangeException)
- {
- Logger.Error(
- $"Error during atmos serialization! Tile at {indices} points to an unique mix ({mix}) out of range!");
- }
- }
- }
- }
- else
- {
- var dataNode = (MappingDataNode) node["data"];
- var chunkSize = serializationManager.Read<int>(dataNode["chunkSize"], hookCtx, context);
- dataNode.TryGetValue(new ValueDataNode("uniqueMixes"), out var mixNode);
- var unique = mixNode == null ? null : serializationManager.Read<List<GasMixture>?>(mixNode, hookCtx, context);
- if (unique != null)
- {
- var tileNode = (MappingDataNode) dataNode["tiles"];
- foreach (var (chunkNode, valueNode) in tileNode)
- {
- var chunkOrigin = serializationManager.Read<Vector2i>(chunkNode, hookCtx, context);
- var chunk = serializationManager.Read<TileAtmosChunk>(valueNode, hookCtx, context);
- foreach (var (mix, data) in chunk.Data)
- {
- for (var x = 0; x < chunkSize; x++)
- {
- for (var y = 0; y < chunkSize; y++)
- {
- var flag = data & (uint) (1 << (x + y * chunkSize));
- if (flag == 0)
- continue;
- var indices = new Vector2i(x + chunkOrigin.X * chunkSize,
- y + chunkOrigin.Y * chunkSize);
- try
- {
- tiles.Add(indices, new TileAtmosphere(EntityUid.Invalid, indices,
- unique[mix].Clone()));
- }
- catch (ArgumentOutOfRangeException)
- {
- Logger.Error(
- $"Error during atmos serialization! Tile at {indices} points to an unique mix ({mix}) out of range!");
- }
- }
- }
- }
- }
- }
- }
- return tiles;
- }
- public DataNode Write(ISerializationManager serializationManager, Dictionary<Vector2i, TileAtmosphere> value, IDependencyCollection dependencies,
- bool alwaysWrite = false, ISerializationContext? context = null)
- {
- var uniqueMixes = new List<GasMixture>();
- var tileChunks = new Dictionary<Vector2i, TileAtmosChunk>();
- var chunkSize = 4;
- foreach (var (gridIndices, tile) in value)
- {
- if (tile.Air == null) continue;
- var mixIndex = uniqueMixes.IndexOf(tile.Air);
- if (mixIndex == -1)
- {
- mixIndex = uniqueMixes.Count;
- uniqueMixes.Add(tile.Air);
- }
- var chunkOrigin = SharedMapSystem.GetChunkIndices(gridIndices, chunkSize);
- var tileChunk = tileChunks.GetOrNew(chunkOrigin);
- var indices = SharedMapSystem.GetChunkRelative(gridIndices, chunkSize);
- var mixFlag = tileChunk.Data.GetOrNew(mixIndex);
- mixFlag |= (uint) 1 << (indices.X + indices.Y * chunkSize);
- tileChunk.Data[mixIndex] = mixFlag;
- }
- if (uniqueMixes.Count == 0)
- uniqueMixes = null;
- if (tileChunks.Count == 0)
- tileChunks = null;
- var map = new MappingDataNode
- {
- { "version", 2.ToString(CultureInfo.InvariantCulture) },
- {
- "data", serializationManager.WriteValue(new TileAtmosData
- {
- ChunkSize = chunkSize,
- UniqueMixes = uniqueMixes,
- TilesUniqueMixes = tileChunks,
- }, alwaysWrite, context)
- }
- };
- return map;
- }
- [DataDefinition]
- private partial struct TileAtmosData
- {
- [DataField("chunkSize")] public int ChunkSize;
- [DataField("uniqueMixes")] public List<GasMixture>? UniqueMixes;
- [DataField("tiles")] public Dictionary<Vector2i, TileAtmosChunk>? TilesUniqueMixes;
- }
- [DataDefinition]
- private partial record struct TileAtmosChunk()
- {
- /// <summary>
- /// Key is unique mix and value is bitflag of the affected tiles.
- /// </summary>
- [IncludeDataField(customTypeSerializer: typeof(DictionarySerializer<int, uint>))]
- public Dictionary<int, uint> Data = new();
- }
- public void CopyTo(ISerializationManager serializationManager, Dictionary<Vector2i, TileAtmosphere> source, ref Dictionary<Vector2i, TileAtmosphere> target,
- IDependencyCollection dependencies,
- SerializationHookContext hookCtx,
- ISerializationContext? context = null)
- {
- target.Clear();
- foreach (var (key, val) in source)
- {
- target.Add(key, new TileAtmosphere(val));
- }
- }
- }
|