| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- using System.Globalization;
- using System.Linq;
- using System.Numerics;
- using Robust.Shared.Map;
- 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.Sequence;
- using Robust.Shared.Serialization.Markdown.Validation;
- using Robust.Shared.Serialization.Markdown.Value;
- using Robust.Shared.Serialization.TypeSerializers.Interfaces;
- using Robust.Shared.Utility;
- using static Content.Shared.Decals.DecalGridComponent;
- namespace Content.Shared.Decals
- {
- [TypeSerializer]
- public sealed partial class DecalGridChunkCollectionTypeSerializer : ITypeSerializer<DecalGridChunkCollection, MappingDataNode>
- {
- public ValidationNode Validate(ISerializationManager serializationManager, MappingDataNode node,
- IDependencyCollection dependencies, ISerializationContext? context = null)
- {
- return serializationManager.ValidateNode<Dictionary<Vector2i, Dictionary<uint, Decal>>>(node, context);
- }
- public DecalGridChunkCollection Read(ISerializationManager serializationManager,
- MappingDataNode node,
- IDependencyCollection dependencies, SerializationHookContext hookCtx, ISerializationContext? context = null,
- ISerializationManager.InstantiationDelegate<DecalGridChunkCollection>? _ = default)
- {
- node.TryGetValue(new ValueDataNode("version"), out var versionNode);
- var version = ((ValueDataNode?) versionNode)?.AsInt() ?? 1;
- Dictionary<Vector2i, DecalChunk> dictionary;
- uint nextIndex = 0;
- var ids = new HashSet<uint>();
- // TODO: Dump this when we don't need support anymore.
- if (version > 1)
- {
- var nodes = (SequenceDataNode) node["nodes"];
- dictionary = new Dictionary<Vector2i, DecalChunk>();
- foreach (var dNode in nodes)
- {
- var aNode = (MappingDataNode) dNode;
- var data = serializationManager.Read<DecalData>(aNode["node"], hookCtx, context);
- var deckNodes = (MappingDataNode) aNode["decals"];
- foreach (var (decalUidNode, decalData) in deckNodes)
- {
- var dUid = serializationManager.Read<uint>(decalUidNode, hookCtx, context);
- var coords = serializationManager.Read<Vector2>(decalData, hookCtx, context);
- var chunkOrigin = SharedMapSystem.GetChunkIndices(coords, SharedDecalSystem.ChunkSize);
- var chunk = dictionary.GetOrNew(chunkOrigin);
- var decal = new Decal(coords, data.Id, data.Color, data.Angle, data.ZIndex, data.Cleanable);
- nextIndex = Math.Max(nextIndex, dUid);
- // Re-used ID somehow
- // This will bump all IDs by up to 1 but will ensure the map is still readable.
- if (!ids.Add(dUid))
- {
- dUid = nextIndex++;
- ids.Add(dUid);
- }
- chunk.Decals[dUid] = decal;
- }
- }
- }
- else
- {
- dictionary = serializationManager.Read<Dictionary<Vector2i, DecalChunk>>(node, hookCtx, context, notNullableOverride: true);
- foreach (var decals in dictionary.Values)
- {
- foreach (var uid in decals.Decals.Keys)
- {
- nextIndex = Math.Max(uid, nextIndex);
- }
- }
- }
- nextIndex++;
- return new DecalGridChunkCollection(dictionary) { NextDecalId = nextIndex };
- }
- public DataNode Write(ISerializationManager serializationManager,
- DecalGridChunkCollection value, IDependencyCollection dependencies,
- bool alwaysWrite = false,
- ISerializationContext? context = null)
- {
- var lookup = new Dictionary<DecalData, List<uint>>();
- var decalLookup = new Dictionary<uint, Decal>();
- var allData = new MappingDataNode();
- // Want consistent chunk + decal ordering so diffs aren't mangled
- var nodes = new SequenceDataNode();
- // Assuming decal indices stay consistent:
- // We'll write decals by
- // - decaldata
- // - decal uid
- // - additional decal data
- // Build all of the decal lookups first.
- foreach (var chunk in value.ChunkCollection.Values)
- {
- foreach (var (uid, decal) in chunk.Decals)
- {
- var data = new DecalData(decal);
- var existing = lookup.GetOrNew(data);
- existing.Add(uid);
- decalLookup[uid] = decal;
- }
- }
- var lookupNodes = lookup.Keys.ToList();
- lookupNodes.Sort();
- foreach (var data in lookupNodes)
- {
- var uids = lookup[data];
- var lookupNode = new MappingDataNode { { "node", serializationManager.WriteValue(data, alwaysWrite, context) } };
- var decks = new MappingDataNode();
- uids.Sort();
- foreach (var uid in uids)
- {
- var decal = decalLookup[uid];
- // Inline coordinates
- decks.Add(serializationManager.WriteValue(uid, alwaysWrite, context), serializationManager.WriteValue(decal.Coordinates, alwaysWrite, context));
- }
- lookupNode.Add("decals", decks);
- nodes.Add(lookupNode);
- }
- allData.Add("version", 2.ToString(CultureInfo.InvariantCulture));
- allData.Add("nodes", nodes);
- return allData;
- }
- [DataDefinition]
- private readonly partial struct DecalData : IEquatable<DecalData>, IComparable<DecalData>
- {
- [DataField("id")]
- public string Id { get; init; } = string.Empty;
- [DataField("color")]
- public Color? Color { get; init; }
- [DataField("angle")]
- public Angle Angle { get; init; } = Angle.Zero;
- [DataField("zIndex")]
- public int ZIndex { get; init; }
- [DataField("cleanable")]
- public bool Cleanable { get; init; }
- public DecalData(string id, Color? color, Angle angle, int zIndex, bool cleanable)
- {
- Id = id;
- Color = color;
- Angle = angle;
- ZIndex = zIndex;
- Cleanable = cleanable;
- }
- public DecalData(Decal decal)
- {
- Id = decal.Id;
- Color = decal.Color;
- Angle = decal.Angle;
- ZIndex = decal.ZIndex;
- Cleanable = decal.Cleanable;
- }
- public bool Equals(DecalData other)
- {
- return Id == other.Id &&
- Nullable.Equals(Color, other.Color) &&
- Angle.Equals(other.Angle) &&
- ZIndex == other.ZIndex &&
- Cleanable == other.Cleanable;
- }
- public override bool Equals(object? obj)
- {
- return obj is DecalData other && Equals(other);
- }
- public override int GetHashCode()
- {
- return HashCode.Combine(Id, Color, Angle, ZIndex, Cleanable);
- }
- public int CompareTo(DecalData other)
- {
- var idComparison = string.Compare(Id, other.Id, StringComparison.Ordinal);
- if (idComparison != 0)
- return idComparison;
- var colorComparison = string.Compare(Color?.ToHex(), other.Color?.ToHex(), StringComparison.Ordinal);
- if (colorComparison != 0)
- return colorComparison;
- var angleComparison = Angle.Theta.CompareTo(other.Angle.Theta);
- if (angleComparison != 0)
- return angleComparison;
- var zIndexComparison = ZIndex.CompareTo(other.ZIndex);
- if (zIndexComparison != 0)
- return zIndexComparison;
- return Cleanable.CompareTo(other.Cleanable);
- }
- }
- }
- }
|