From 2f01d7899f109e286c24cf541d6da4da0a6fa5b3 Mon Sep 17 00:00:00 2001 From: 20kdc Date: Sat, 6 Feb 2021 22:56:40 +0000 Subject: [PATCH] Mapping merge driver: continued (#2803) Co-authored-by: DrSmugleaf Co-authored-by: Pieter-Jan Briers --- .gitattributes | 1 + .gitignore | 4 + Content.Tools/Content.Tools.csproj | 16 ++ Content.Tools/Map.cs | 83 +++++++ Content.Tools/MappingMergeDriver.cs | 38 +++ Content.Tools/Merger.cs | 356 ++++++++++++++++++++++++++++ Content.Tools/TypeTagPreserver.cs | 25 ++ Content.Tools/YamlTools.cs | 199 ++++++++++++++++ Content.Tools/test/0A.yml | 95 ++++++++ Content.Tools/test/0B.yml | 86 +++++++ Content.Tools/test/0C.yml | 105 ++++++++ Content.Tools/test/run.sh | 3 + SpaceStation14.sln | 6 + Tools/mapping-merge-driver.sh | 9 + 14 files changed, 1026 insertions(+) create mode 100644 Content.Tools/Content.Tools.csproj create mode 100644 Content.Tools/Map.cs create mode 100644 Content.Tools/MappingMergeDriver.cs create mode 100644 Content.Tools/Merger.cs create mode 100644 Content.Tools/TypeTagPreserver.cs create mode 100644 Content.Tools/YamlTools.cs create mode 100644 Content.Tools/test/0A.yml create mode 100644 Content.Tools/test/0B.yml create mode 100644 Content.Tools/test/0C.yml create mode 100755 Content.Tools/test/run.sh create mode 100755 Tools/mapping-merge-driver.sh diff --git a/.gitattributes b/.gitattributes index 0630300756a..6292d191fab 100644 --- a/.gitattributes +++ b/.gitattributes @@ -34,6 +34,7 @@ #*.modelproj merge=binary #*.sqlproj merge=binary #*.wwaproj merge=binary +Resources/Maps/**.yml merge=mapping-merge-driver ############################################################################### # behavior for image files diff --git a/.gitignore b/.gitignore index 05b654564fa..98164b71c99 100644 --- a/.gitignore +++ b/.gitignore @@ -284,3 +284,7 @@ BuildFiles/Windows/Godot/* # Windows image file caches Thumbs.db ehthumbs.db + +# Merge driver stuff +Content.Tools/test/out.yml + diff --git a/Content.Tools/Content.Tools.csproj b/Content.Tools/Content.Tools.csproj new file mode 100644 index 00000000000..e3a5e3bca9a --- /dev/null +++ b/Content.Tools/Content.Tools.csproj @@ -0,0 +1,16 @@ + + + + Exe + net5.0 + + + + + + + + + + + diff --git a/Content.Tools/Map.cs b/Content.Tools/Map.cs new file mode 100644 index 00000000000..6e6ed592976 --- /dev/null +++ b/Content.Tools/Map.cs @@ -0,0 +1,83 @@ +using System.IO; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using YamlDotNet.Core; +using Robust.Shared.Utility; +using YamlDotNet.RepresentationModel; + +namespace Content.Tools +{ + public class Map + { + public Map(string path) + { + Path = path; + + using var reader = new StreamReader(path); + var stream = new YamlStream(); + + stream.Load(reader); + + Root = stream.Documents[0].RootNode; + TilemapNode = (YamlMappingNode) Root["tilemap"]; + GridsNode = (YamlSequenceNode) Root["grids"]; + _entitiesNode = (YamlSequenceNode) Root["entities"]; + + foreach (var entity in _entitiesNode) + { + var uid = uint.Parse(entity["uid"].AsString()); + if (uid >= NextAvailableEntityId) + NextAvailableEntityId = uid + 1; + Entities[uid] = (YamlMappingNode) entity; + } + } + + // Core + + public string Path { get; } + + public YamlNode Root { get; } + + // Useful + + public YamlMappingNode TilemapNode { get; } + + public YamlSequenceNode GridsNode { get; } + + // Entities lookup + + private YamlSequenceNode _entitiesNode { get; } + + public Dictionary Entities { get; } = new Dictionary(); + + public uint MaxId => Entities.Max(entry => entry.Key); + + public uint NextAvailableEntityId { get; set; } + + // ---- + + public void Save(string fileName) + { + // Update entities node + _entitiesNode.Children.Clear(); + foreach (var kvp in Entities) + _entitiesNode.Add(kvp.Value); + + using var writer = new StreamWriter(fileName); + var document = new YamlDocument(Root); + var stream = new YamlStream(document); + var emitter = new Emitter(writer); + var fixer = new TypeTagPreserver(emitter); + + stream.Save(fixer, false); + + writer.Flush(); + } + + public void Save() + { + Save(Path); + } + } +} diff --git a/Content.Tools/MappingMergeDriver.cs b/Content.Tools/MappingMergeDriver.cs new file mode 100644 index 00000000000..f069a7a5bbe --- /dev/null +++ b/Content.Tools/MappingMergeDriver.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using YamlDotNet.Core; +using YamlDotNet.RepresentationModel; + +namespace Content.Tools +{ + internal static class MappingMergeDriver + { + /// %A: Our file + /// %O: Origin (common, base) file + /// %B: Other file + /// %P: Actual filename of the resulting file + public static void Main(string[] args) + { + var ours = new Map(args[0]); + var based = new Map(args[1]); // On what? + var other = new Map(args[2]); + + if ((ours.GridsNode.Children.Count != 1) || (based.GridsNode.Children.Count != 1) || (other.GridsNode.Children.Count != 1)) + { + Console.WriteLine("one or more files had an amount of grids not equal to 1"); + Environment.Exit(1); + } + + if (!(new Merger(ours, based, other).Merge())) + { + Console.WriteLine("unable to merge!"); + Environment.Exit(1); + } + + ours.Save(); + Environment.Exit(0); + } + } +} diff --git a/Content.Tools/Merger.cs b/Content.Tools/Merger.cs new file mode 100644 index 00000000000..1b5aaa4fe3c --- /dev/null +++ b/Content.Tools/Merger.cs @@ -0,0 +1,356 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using YamlDotNet.Core; +using YamlDotNet.RepresentationModel; + +namespace Content.Tools +{ + public class Merger + { + public Map MapOurs { get; } + public Map MapBased { get; } + public Map MapOther { get; } + + public Dictionary TileMapFromOtherToOurs { get; } = new Dictionary(); + public Dictionary TileMapFromBasedToOurs { get; } = new Dictionary(); + public Dictionary EntityMapFromOtherToOurs { get; } = new Dictionary(); + public List EntityListDirectMerge { get; } = new List(); + + private const int ExpectedChunkSize = 16 * 16 * 4; + + public Merger(Map ours, Map based, Map other) + { + MapOurs = ours; + MapBased = based; + MapOther = other; + } + + public bool Merge() + { + PlanTileMapping(TileMapFromOtherToOurs, MapOther); + PlanTileMapping(TileMapFromBasedToOurs, MapBased); + MergeTiles(); + PlanEntityMapping(); + return MergeEntities(); + } + + // -- Tiles -- + + public void PlanTileMapping(Dictionary relativeOtherToOurs, Map relativeOther) + { + var mapping = new Dictionary(); + uint nextAvailable = 0; + foreach (var kvp in MapOurs.TilemapNode) + { + var k = uint.Parse(kvp.Key.ToString()); + var v = kvp.Value.ToString(); + mapping[v] = k; + if (k >= nextAvailable) + nextAvailable = k + 1; + } + foreach (var kvp in relativeOther.TilemapNode) + { + var k = uint.Parse(kvp.Key.ToString()); + var v = kvp.Value.ToString(); + if (mapping.ContainsKey(v)) + { + relativeOtherToOurs[k] = mapping[v]; + } + else + { + MapOurs.TilemapNode.Add(nextAvailable.ToString(CultureInfo.InvariantCulture), v); + relativeOtherToOurs[k] = nextAvailable++; + } + } + } + + public void MergeTiles() + { + var a = MapOurs.GridsNode.Children[0]; + var b = MapBased.GridsNode.Children[0]; + var c = MapOther.GridsNode.Children[0]; + var aChunks = a["chunks"]; + var bChunks = b["chunks"]; + var cChunks = c["chunks"]; + MergeTileChunks((YamlSequenceNode) aChunks, (YamlSequenceNode) bChunks, (YamlSequenceNode) cChunks); + } + + public void MergeTileChunks(YamlSequenceNode aChunks, YamlSequenceNode bChunks, YamlSequenceNode cChunks) + { + var aMap = ConvertTileChunks(aChunks); + var bMap = ConvertTileChunks(bChunks); + var cMap = ConvertTileChunks(cChunks); + + var xMap = new HashSet(); + foreach (var kvp in aMap) + xMap.Add(kvp.Key); + // don't include b because that would mess with chunk deletion + foreach (var kvp in cMap) + xMap.Add(kvp.Key); + + foreach (var ind in xMap) + { + using var a = new MemoryStream(GetChunkBytes(aMap, ind)); + using var b = new MemoryStream(GetChunkBytes(bMap, ind)); + using var c = new MemoryStream(GetChunkBytes(cMap, ind)); + using var aR = new BinaryReader(a); + using var bR = new BinaryReader(b); + using var cR = new BinaryReader(c); + + var outB = new byte[ExpectedChunkSize]; + + { + using (var outS = new MemoryStream(outB)) + using (var outW = new BinaryWriter(outS)) + + for (var i = 0; i < ExpectedChunkSize; i += 4) + { + var aI = aR.ReadUInt32(); + var bI = MapTileId(bR.ReadUInt32(), TileMapFromBasedToOurs); + var cI = MapTileId(cR.ReadUInt32(), TileMapFromOtherToOurs); + // cI needs translation. + + uint result = aI; + if (aI == bI) + { + // If aI == bI then aI did not change anything, so cI always wins + result = cI; + } + else if (bI != cI) + { + // If bI != cI then cI definitely changed something (conflict, but overrides aI) + result = cI; + Console.WriteLine("WARNING: Tile (" + ind + ")[" + i + "] was changed by both branches."); + } + outW.Write(result); + } + } + + // Actually output chunk + if (!aMap.ContainsKey(ind)) + { + var res = new YamlMappingNode(); + res.Children["ind"] = ind; + aMap[ind] = res; + } + aMap[ind].Children["tiles"] = Convert.ToBase64String(outB); + } + } + + public uint MapTileId(uint src, Dictionary mapping) + { + return (src & 0xFFFF0000) | mapping[src & 0xFFFF]; + } + + public Dictionary ConvertTileChunks(YamlSequenceNode chunks) + { + var map = new Dictionary(); + foreach (var chunk in chunks) + map[chunk["ind"].ToString()] = (YamlMappingNode) chunk; + return map; + } + + public byte[] GetChunkBytes(Dictionary chunks, string ind) + { + if (!chunks.ContainsKey(ind)) + return new byte[ExpectedChunkSize]; + return Convert.FromBase64String(chunks[ind]["tiles"].ToString()); + } + + // -- Entities -- + + public void PlanEntityMapping() + { + // Ok, so here's how it works: + // 1. Entities that do not exist in "based" are additions. + // 2. Entities that exist in "based" but do not exist in the one map or the other are removals. + + // Find modifications and deletions + foreach (var kvp in MapBased.Entities) + { + var deletedByOurs = !MapOurs.Entities.ContainsKey(kvp.Key); + var deletedByOther = !MapOther.Entities.ContainsKey(kvp.Key); + if (deletedByOther && !deletedByOurs) + { + // Delete + MapOurs.Entities.Remove(kvp.Key); + } + else if (!(deletedByOurs || deletedByOther)) + { + // Modify + EntityMapFromOtherToOurs[kvp.Key] = kvp.Key; + } + } + + // Find additions + foreach (var kvp in MapOther.Entities) + { + if (!MapBased.Entities.ContainsKey(kvp.Key)) + { + // New + var newId = MapOurs.NextAvailableEntityId++; + EntityMapFromOtherToOurs[kvp.Key] = newId; + } + } + } + + public bool MergeEntities() + { + bool success = true; + foreach (var kvp in EntityMapFromOtherToOurs) + { + // For debug use. + // Console.WriteLine("Entity C/" + kvp.Key + " -> A/" + kvp.Value); + YamlMappingNode oursEnt; + if (MapOurs.Entities.ContainsKey(kvp.Value)) + { + oursEnt = MapOurs.Entities[kvp.Value]; + if (!MapBased.Entities.TryGetValue(kvp.Value, out var basedEnt)) + { + basedEnt = oursEnt; + } + + if (!MergeEntityNodes(oursEnt, basedEnt, MapOther.Entities[kvp.Key])) + { + Console.WriteLine("Unable to successfully merge entity C/" + kvp.Key); + success = false; + } + } + else + { + oursEnt = (YamlMappingNode) YamlTools.CopyYamlNodes(MapOther.Entities[kvp.Key]); + if (!MapEntity(oursEnt)) { + Console.WriteLine("Unable to successfully import entity C/" + kvp.Key); + success = false; + } else { + MapOurs.Entities[kvp.Value] = oursEnt; + } + } + oursEnt.Children["uid"] = kvp.Value.ToString(CultureInfo.InvariantCulture); + } + return success; + } + + public bool MergeEntityNodes(YamlMappingNode ours, YamlMappingNode based, YamlMappingNode other) + { + // Copy to intermediate + var otherMapped = (YamlMappingNode) YamlTools.CopyYamlNodes(other); + if (!MapEntity(otherMapped)) + return false; + // Merge stuff that isn't components + var path = "Entity" + (other["uid"].ToString()); + YamlTools.MergeYamlMappings(ours, based, otherMapped, path, new string[] {"components"}); + // Components are special + var ourComponents = new Dictionary(); + var basedComponents = new Dictionary(); + var ourComponentsNode = (YamlSequenceNode) ours["components"]; + var basedComponentsNode = (YamlSequenceNode) based["components"]; + var otherComponentsNode = (YamlSequenceNode) otherMapped["components"]; + foreach (var component in ourComponentsNode) + { + var name = component["type"].ToString(); + ourComponents[name] = (YamlMappingNode) component; + } + foreach (var component in basedComponentsNode) + { + var name = component["type"].ToString(); + basedComponents[name] = (YamlMappingNode) component; + } + foreach (var otherComponent in otherComponentsNode) + { + var name = otherComponent["type"].ToString(); + if (ourComponents.ContainsKey(name)) + { + var ourComponent = ourComponents[name]; + if (!basedComponents.TryGetValue(name, out var basedComponent)) + basedComponent = new YamlMappingNode(); + + YamlTools.MergeYamlNodes(ourComponent, basedComponent, otherComponent, path + "/components/" + name); + } + else + { + ourComponentsNode.Add(otherComponent); + } + } + return true; + } + + public bool MapEntity(YamlMappingNode other) + { + var path = "Entity" + (other["uid"].ToString()); + if (other.Children.ContainsKey("components")) + { + var components = (YamlSequenceNode) other["components"]; + foreach (var component in components) + { + var type = component["type"].ToString(); + if (type == "Transform") + { + if (!MapEntityProperty((YamlMappingNode) component, "parent", path)) + return false; + } + else if (type == "ContainerContainer") + { + MapEntityRecursiveAndBadly(component, path); + } + } + } + return true; + } + + public bool MapEntityProperty(YamlMappingNode node, string property, string path) + { + if (node.Children.ContainsKey(property)) { + var prop = node[property]; + if (prop is YamlScalarNode) + return MapEntityProperty((YamlScalarNode) prop, path + "/" + property); + } + return true; + } + + public bool MapEntityProperty(YamlScalarNode node, string path) + { + if (uint.TryParse(node.ToString(), out var uid)) + { + if (EntityMapFromOtherToOurs.ContainsKey(uid)) + { + node.Value = EntityMapFromOtherToOurs[uid].ToString(CultureInfo.InvariantCulture); + } + else + { + Console.WriteLine($"Error finding UID in MapEntityRecursiveAndBadly {path}. To fix this, the merge driver needs to be improved."); + return false; + } + } + return true; + } + + public bool MapEntityRecursiveAndBadly(YamlNode node, string path) + { + switch (node) + { + case YamlSequenceNode subSequence: + var idx = 0; + foreach (var val in subSequence) + if (!MapEntityRecursiveAndBadly(val, path + "/" + (idx++))) + return false; + return true; + case YamlMappingNode subMapping: + foreach (var kvp in subMapping) + if (!MapEntityRecursiveAndBadly(kvp.Key, path)) + return false; + foreach (var kvp in subMapping) + if (!MapEntityRecursiveAndBadly(kvp.Value, path + "/" + kvp.Key.ToString())) + return false; + return true; + case YamlScalarNode subScalar: + return MapEntityProperty(subScalar, path); + default: + throw new ArgumentException($"Unrecognized YAML node type: {node.GetType()} at {path}"); + } + } + } +} diff --git a/Content.Tools/TypeTagPreserver.cs b/Content.Tools/TypeTagPreserver.cs new file mode 100644 index 00000000000..94996767d3e --- /dev/null +++ b/Content.Tools/TypeTagPreserver.cs @@ -0,0 +1,25 @@ +using YamlDotNet.Core; +using YamlDotNet.Core.Events; + +namespace Content.Tools +{ + public class TypeTagPreserver : IEmitter + { + public TypeTagPreserver(IEmitter emitter) + { + Emitter = emitter; + } + + private IEmitter Emitter { get; } + + public void Emit(ParsingEvent @event) + { + if (@event is MappingStart mapping) + { + @event = new MappingStart(mapping.Anchor, mapping.Tag, false, mapping.Style, mapping.Start, mapping.End); + } + + Emitter.Emit(@event); + } + } +} diff --git a/Content.Tools/YamlTools.cs b/Content.Tools/YamlTools.cs new file mode 100644 index 00000000000..ec1f4322846 --- /dev/null +++ b/Content.Tools/YamlTools.cs @@ -0,0 +1,199 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using YamlDotNet.Core; +using YamlDotNet.RepresentationModel; + +namespace Content.Tools +{ + public static class YamlTools + { + public static YamlNode CopyYamlNodes(YamlNode other) + { + switch (other) + { + case YamlSequenceNode subSequence: + YamlSequenceNode tmp1 = new YamlSequenceNode(); + MergeYamlSequences((YamlSequenceNode) tmp1, new YamlSequenceNode(), (YamlSequenceNode) other, ""); + return tmp1; + case YamlMappingNode subMapping: + YamlMappingNode tmp2 = new YamlMappingNode(); + MergeYamlMappings((YamlMappingNode) tmp2, new YamlMappingNode(), (YamlMappingNode) other, "", new string[] {}); + return tmp2; + case YamlScalarNode subScalar: + YamlScalarNode tmp3 = new YamlScalarNode(); + CopyYamlScalar(tmp3, subScalar); + return tmp3; + default: + throw new ArgumentException($"Unrecognized YAML node type for copy: {other.GetType()}", nameof(other)); + } + } + + public static bool TriTypeMatch(YamlNode ours, YamlNode based, YamlNode other) + { + var refType = other.GetType(); + if (refType != based.GetType()) + return false; + if (refType != ours.GetType()) + return false; + return true; + } + + public static void MergeYamlNodes(YamlNode ours, YamlNode based, YamlNode other, string path) + { + if (!TriTypeMatch(ours, based, other)) + throw new ArgumentException($"Node type mismatch at {path}"); + switch (other) + { + case YamlSequenceNode subSequence: + MergeYamlSequences((YamlSequenceNode) ours, (YamlSequenceNode) based, (YamlSequenceNode) other, path); + break; + case YamlMappingNode subMapping: + MergeYamlMappings((YamlMappingNode) ours, (YamlMappingNode) based, (YamlMappingNode) other, path, new string[] {}); + break; + case YamlScalarNode subScalar: + // Console.WriteLine(path + " - " + ours + " || " + based + " || " + other); + var scalarA = (YamlScalarNode) ours; + var scalarB = (YamlScalarNode) based; + var scalarC = (YamlScalarNode) other; + var aeb = (scalarA.Value == scalarB.Value); + var cneb = (scalarC.Value != scalarB.Value); + if (aeb || cneb) + CopyYamlScalar(scalarA, scalarC); + // Console.WriteLine(path + " . " + ours + " || " + based + " || " + other); + break; + default: + throw new ArgumentException($"Unrecognized YAML node type at {path}: {other.GetType()}", nameof(other)); + } + } + + public static void MergeYamlSequences(YamlSequenceNode ours, YamlSequenceNode based, YamlSequenceNode other, string path) + { + if ((ours.Children.Count == based.Children.Count) && (other.Children.Count == ours.Children.Count)) + { + // this is terrible and doesn't do proper rearrange detection + // but it looks as if vectors might be arrays + // so rearrange detection might break more stuff... + // nope, they aren't, but still good to have + for (var i = 0; i < ours.Children.Count; i++) + MergeYamlNodes(ours.Children[i], based.Children[i], other.Children[i], path + "/" + i); + return; + } + // for now, just copy other -> ours + // I am aware this is terrible + ours.Children.Clear(); + foreach (var c in other.Children) + ours.Add(CopyYamlNodes(c)); + } + + public static void MergeYamlMappings(YamlMappingNode ours, YamlMappingNode based, YamlMappingNode other, string path, string[] ignoreThese) + { + // Deletions/modifications + foreach (var kvp in based) + { + if (ignoreThese.Contains(kvp.Key.ToString())) + continue; + + var localPath = path + "/" + kvp.Key.ToString(); + var deletedByOurs = !ours.Children.ContainsKey(kvp.Key); + var deletedByOther = !other.Children.ContainsKey(kvp.Key); + if (deletedByOther && (!deletedByOurs)) + { + // Delete + ours.Children.Remove(kvp.Key); + } + else if (!(deletedByOurs || deletedByOther)) + { + // Modify + var a = ours[kvp.Key]; + var b = kvp.Value; // based[kvp.Key] + var c = other[kvp.Key]; + if (!TriTypeMatch(a, b, c)) + { + Console.WriteLine("Warning: Type mismatch (defaulting to value C) at " + localPath); + ours.Children[kvp.Key] = CopyYamlNodes(c); + } + else + { + MergeYamlNodes(a, b, c, localPath); + } + } + } + // Additions + foreach (var kvp in other) + { + if (ignoreThese.Contains(kvp.Key.ToString())) + continue; + + var localPath = path + "/" + kvp.Key.ToString(); + if (!based.Children.ContainsKey(kvp.Key)) + { + if (ours.Children.ContainsKey(kvp.Key)) + { + // Both sides added the same key. Try to merge. + var a = ours[kvp.Key]; + var b = based[kvp.Key]; + var c = kvp.Value; // other[kvp.Key] + if (!TriTypeMatch(a, b, c)) + { + Console.WriteLine("Warning: Type mismatch (defaulting to value C) at " + localPath); + ours.Children[kvp.Key] = CopyYamlNodes(c); + } + else + { + MergeYamlNodes(a, b, c, localPath); + } + } + else + { + // Well that was easy + ours.Children[kvp.Key] = CopyYamlNodes(kvp.Value); + } + } + } + } + + // NOTE: This is a heuristic ONLY! And is also not used at the moment because sequence matching isn't in place. + // It could also be massively improved. + public static float YamlNodesHeuristic(YamlNode a, YamlNode b) + { + if (a.GetType() != b.GetType()) + return 0.0f; + switch (a) + { + case YamlSequenceNode x: + return YamlSequencesHeuristic((YamlSequenceNode) a, (YamlSequenceNode) b); + case YamlMappingNode y: + return YamlMappingsHeuristic((YamlMappingNode) a, (YamlMappingNode) b); + case YamlScalarNode z: + return (((YamlScalarNode) a).Value == ((YamlScalarNode) b).Value) ? 1.0f : 0.0f; + default: + throw new ArgumentException($"Unrecognized YAML node type: {a.GetType()}", nameof(a)); + } + } + + public static float YamlSequencesHeuristic(YamlSequenceNode a, YamlSequenceNode b) + { + if (a.Children.Count != b.Children.Count) + return 0.0f; + if (a.Children.Count == 0) + return 1.0f; + var total = 0.0f; + for (var i = 0; i < a.Children.Count; i++) + total += YamlNodesHeuristic(a.Children[i], b.Children[i]); + return total / a.Children.Count; + } + + public static float YamlMappingsHeuristic(YamlMappingNode a, YamlMappingNode b) + { + return (a == b) ? 1.0f : 0.0f; + } + + public static void CopyYamlScalar(YamlScalarNode dst, YamlScalarNode src) + { + dst.Value = src.Value; + dst.Style = src.Style; + } + } +} diff --git a/Content.Tools/test/0A.yml b/Content.Tools/test/0A.yml new file mode 100644 index 00000000000..d977df527ae --- /dev/null +++ b/Content.Tools/test/0A.yml @@ -0,0 +1,95 @@ +meta: + format: 2 + name: DemoStation + author: Space-Wizards + postmapinit: false +tilemap: + 0: space + 7: floor_dark + 8: floor_elevator_shaft + 9: floor_freezer + 10: floor_gold + 11: floor_green_circuit + 12: floor_hydro + 13: floor_lino + 14: floor_mono + 15: floor_reinforced + 16: floor_rock_vault + 17: floor_showroom + 18: floor_snow + 19: floor_steel + 20: floor_steel_dirty + 21: floor_techmaint + 22: floor_white + 23: floor_wood + 24: lattice + 25: plating + 26: underplating +grids: +- settings: + chunksize: 16 + tilesize: 1 + snapsize: 1 + chunks: + - ind: "-2,-2" + comment: "Ew in A | FQ in B | Fg in C | Fg in Out - SHOULD CAUSE CONFLICT WARNING" + tiles: EwAAABMAAAATAAAAEwAAABMAAAATAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABcAAAAaAAAAEwAAABMAAAATAAAAGgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAaAAAAFgAAABYAAAAaAAAAGgAAABMAAAATAAAAEwAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABoAAAATAAAAEwAAABMAAAAaAAAAGgAAABMAAAAaAAAAEwAAABoAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAAaAAAAEwAAABoAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAAaAAAAGgAAABoAAAAVAAAAGgAAABoAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAGgAAABkAAAAZAAAAGQAAABkAAAAZAAAAGgAAABoAAAAaAAAAGgAAABoAAAATAAAAGgAAABMAAAATAAAAEwAAABUAAAAZAAAAFQAAABUAAAAVAAAAGQAAABkAAAAZAAAAFQAAABUAAAAVAAAAGgAAABoAAAATAAAAEwAAABMAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGQAAABUAAAAaAAAAFQAAAA== + - ind: "-1,-1" + tiles: EwAAABYAAAAWAAAAFgAAABYAAAATAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABoAAAAWAAAAFgAAABYAAAAWAAAAEwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAEwAAABMAAAAaAAAAEwAAABMAAAAaAAAAGgAAABoAAAAaAAAAGgAAABkAAAAaAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAGgAAABMAAAAZAAAAGgAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABoAAAATAAAAGQAAABoAAAATAAAAEwAAABMAAAAaAAAAEwAAABoAAAAaAAAAEwAAABMAAAAaAAAAGgAAABMAAAAaAAAAGgAAABkAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAAZAAAAFQAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAGgAAABoAAAAaAAAAGgAAAA== + - ind: "-1,0" + tiles: EwAAABYAAAAWAAAAFgAAABYAAAATAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABoAAAAWAAAAFgAAABYAAAAWAAAAEwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAEwAAABMAAAAaAAAAEwAAABMAAAAaAAAAGgAAABoAAAAaAAAAGgAAABkAAAAaAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAGgAAABMAAAAZAAAAGgAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABoAAAATAAAAGQAAABoAAAATAAAAEwAAABMAAAAaAAAAEwAAABoAAAAaAAAAEwAAABMAAAAaAAAAGgAAABMAAAAaAAAAGgAAABkAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAAZAAAAFQAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAGgAAABoAAAAaAAAAGgAAAA== + - ind: "0,0" + tiles: FwAAABMAAAATAAAAEwAAABMAAAATAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABcAAAAaAAAAEwAAABMAAAATAAAAGgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAaAAAAFgAAABYAAAAaAAAAGgAAABMAAAATAAAAEwAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABoAAAATAAAAEwAAABMAAAAaAAAAGgAAABMAAAAaAAAAEwAAABoAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAAaAAAAEwAAABoAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAAaAAAAGgAAABoAAAAVAAAAGgAAABoAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAGgAAABkAAAAZAAAAGQAAABkAAAAZAAAAGgAAABoAAAAaAAAAGgAAABoAAAATAAAAGgAAABMAAAATAAAAEwAAABUAAAAZAAAAFQAAABUAAAAVAAAAGQAAABkAAAAZAAAAFQAAABUAAAAVAAAAGgAAABoAAAATAAAAEwAAABMAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGQAAABUAAAAaAAAAFQAAAA== +entities: +- uid: 0 + type: FakeTestDummy + components: + - parent: 855 + pos: -5.5,-1.5 + rot: -1.5707963267948966 rad + type: Transform + - type: ContainerContainer + typeChange: + - 0 + - 1 + - 2 + example: + - 0 + - 1 + - 2 + - 3 + - 855 + - "contributionA" +- uid: 1 + type: FakeTestDummy + components: + - parent: 0 + pos: -15.5,-14.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 2 + type: FakeTestDummy + components: + - parent: 1 + pos: -15.5,-14.5 + rot: -1.5707963267948966 rad + type: Transform + - type: ThereShouldBeTwoOfTheseInOutputOfMergeTestAAA +- uid: 3 + type: AnnoyingPlaceholderOnPurpose + components: + - parent: 0 + type: Transform +- uid: 855 + components: + - name: Saltern Station + type: MetaData + - parent: null + type: Transform + - index: 0 + type: MapGrid + - shapes: + - !type:PhysShapeGrid + grid: 0 + type: Physics + diff --git a/Content.Tools/test/0B.yml b/Content.Tools/test/0B.yml new file mode 100644 index 00000000000..27430439da5 --- /dev/null +++ b/Content.Tools/test/0B.yml @@ -0,0 +1,86 @@ +meta: + format: 2 + name: DemoStation + author: Space-Wizards + postmapinit: false +tilemap: + 0: space + 7: floor_dark + 8: floor_elevator_shaft + 9: floor_freezer + 10: floor_gold + 11: floor_green_circuit + 12: floor_hydro + 13: floor_lino + 14: floor_mono + 15: floor_reinforced + 16: floor_rock_vault + 17: floor_showroom + 18: floor_snow + 19: floor_steel + 20: floor_steel_dirty + 21: floor_techmaint + 22: floor_white + 23: floor_wood + 24: lattice + 25: plating + 26: underplating +grids: +- settings: + chunksize: 16 + tilesize: 1 + snapsize: 1 + chunks: + - ind: "-2,-2" + comment: "Ew in A | FQ in B | Fg in C | Fg in Out - SHOULD CAUSE CONFLICT WARNING" + tiles: FQAAABMAAAATAAAAEwAAABMAAAATAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABcAAAAaAAAAEwAAABMAAAATAAAAGgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAaAAAAFgAAABYAAAAaAAAAGgAAABMAAAATAAAAEwAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABoAAAATAAAAEwAAABMAAAAaAAAAGgAAABMAAAAaAAAAEwAAABoAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAAaAAAAEwAAABoAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAAaAAAAGgAAABoAAAAVAAAAGgAAABoAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAGgAAABkAAAAZAAAAGQAAABkAAAAZAAAAGgAAABoAAAAaAAAAGgAAABoAAAATAAAAGgAAABMAAAATAAAAEwAAABUAAAAZAAAAFQAAABUAAAAVAAAAGQAAABkAAAAZAAAAFQAAABUAAAAVAAAAGgAAABoAAAATAAAAEwAAABMAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGQAAABUAAAAaAAAAFQAAAA== + - ind: "-1,-1" + tiles: FQAAABUAAAAVAAAAFQAAABUAAAAVAAAAFQAAABUAAAAVAAAAGgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABkAAAAZAAAAGQAAABkAAAAZAAAAGQAAABkAAAAVAAAAFQAAABoAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAaAAAAGgAAABUAAAAaAAAAGgAAABoAAAAZAAAAFQAAABUAAAAaAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFQAAABUAAAAVAAAAFQAAABUAAAAaAAAAGQAAABUAAAAVAAAAGgAAABYAAAAWAAAAFgAAABoAAAAaAAAAGgAAABUAAAAVAAAAFQAAABUAAAAVAAAAGgAAABkAAAAVAAAAFQAAABoAAAAaAAAAFgAAABoAAAAaAAAAGQAAABkAAAAVAAAAFQAAABUAAAAVAAAAFQAAABoAAAAZAAAAGQAAABkAAAAZAAAAGQAAABkAAAAZAAAAGQAAABkAAAAZAAAAFQAAABUAAAAVAAAAFQAAABUAAAAaAAAAGQAAABUAAAAVAAAAFQAAABUAAAAVAAAAFQAAABUAAAAVAAAAFQAAABoAAAAaAAAAGgAAABUAAAAaAAAAGgAAABkAAAAZAAAAGQAAABkAAAAZAAAAGQAAABkAAAAZAAAAFQAAABUAAAAVAAAAFQAAABUAAAAVAAAAFQAAABUAAAAZAAAAFQAAAA0AAAANAAAADQAAAA0AAAANAAAAGgAAABUAAAAVAAAAGQAAABkAAAAZAAAAGQAAABkAAAAZAAAAGQAAABkAAAANAAAADQAAAA0AAAANAAAADQAAABoAAAAVAAAAFQAAABkAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAADQAAAA0AAAANAAAADQAAAA0AAAAaAAAAGgAAABoAAAAZAAAAEwAAAAkAAAAJAAAACQAAAAkAAAAJAAAAGgAAAA0AAAANAAAADQAAAA0AAAANAAAAFwAAABcAAAAXAAAAGgAAABoAAAAJAAAACQAAAAkAAAAJAAAACQAAABoAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABoAAAAaAAAAGgAAABMAAAAaAAAAGgAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAaAAAAFgAAABYAAAAWAAAAFgAAABYAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAGgAAABYAAAAWAAAAFgAAABYAAAATAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAAA== + - ind: "-1,0" + tiles: EwAAABYAAAAWAAAAFgAAABYAAAATAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABoAAAAWAAAAFgAAABYAAAAWAAAAEwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAEwAAABMAAAAaAAAAEwAAABMAAAAaAAAAGgAAABoAAAAaAAAAGgAAABkAAAAaAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAGgAAABMAAAAZAAAAGgAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABoAAAATAAAAGQAAABoAAAATAAAAEwAAABMAAAAaAAAAEwAAABoAAAAaAAAAEwAAABMAAAAaAAAAGgAAABMAAAAaAAAAGgAAABkAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAAZAAAAFQAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAGgAAABoAAAAaAAAAGgAAAA== + - ind: "0,-1" + tiles: FgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABYAAAAWAAAAFgAAABYAAAAaAAAAFgAAABYAAAAWAAAAFgAAABYAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAAWAAAAFgAAABYAAAAWAAAAGgAAABYAAAAWAAAAFgAAABYAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAFgAAABYAAAAWAAAAFgAAABoAAAAWAAAAFgAAABYAAAAWAAAAGgAAABoAAAATAAAAEwAAABMAAAAaAAAAGgAAABoAAAAWAAAAGgAAABoAAAAaAAAAFgAAABYAAAAWAAAAGgAAABkAAAAaAAAAEwAAABMAAAATAAAAGgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAZAAAAGgAAABMAAAATAAAAEwAAABoAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAGQAAABoAAAATAAAAEwAAABMAAAAaAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABkAAAAaAAAAEwAAABMAAAATAAAAGgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAZAAAAFQAAABMAAAATAAAAEwAAABoAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFQAAABoAAAATAAAAEwAAABMAAAAaAAAAGgAAABYAAAAaAAAAGgAAABYAAAAWAAAAGgAAABoAAAAWAAAAFgAAABoAAAAaAAAAEwAAABMAAAATAAAAGgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAaAAAAFgAAABYAAAAXAAAAGgAAABMAAAATAAAAEwAAABoAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAGgAAABYAAAAWAAAAFwAAABoAAAATAAAAEwAAABMAAAAaAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABoAAAAaAAAAFgAAABcAAAATAAAAEwAAABMAAAATAAAAEwAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAaAAAAFgAAABYAAAAXAAAAEwAAABMAAAATAAAAEwAAABMAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAGgAAABYAAAAWAAAAFwAAABMAAAATAAAAEwAAABMAAAATAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABoAAAAWAAAAFgAAAA== + - ind: "0,0" + tiles: FwAAABMAAAATAAAAEwAAABMAAAATAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABcAAAAaAAAAEwAAABMAAAATAAAAGgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAaAAAAFgAAABYAAAAaAAAAGgAAABMAAAATAAAAEwAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABoAAAATAAAAEwAAABMAAAAaAAAAGgAAABMAAAAaAAAAEwAAABoAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAAaAAAAEwAAABoAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAAaAAAAGgAAABoAAAAVAAAAGgAAABoAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAGgAAABkAAAAZAAAAGQAAABkAAAAZAAAAGgAAABoAAAAaAAAAGgAAABoAAAATAAAAGgAAABMAAAATAAAAEwAAABUAAAAZAAAAFQAAABUAAAAVAAAAGQAAABkAAAAZAAAAFQAAABUAAAAVAAAAGgAAABoAAAATAAAAEwAAABMAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGQAAABUAAAAaAAAAFQAAAA== +entities: +- uid: 0 + type: FakeTestDummy + components: + - parent: 855 + pos: -15.5,-11.5 + rot: -1.5707963267948966 rad + type: Transform + - type: ContainerContainer + typeChange: + - 0 + - 1 + example: + - 0 + - 1 + - 3 + - 855 +- uid: 1 + type: FakeTestDummy + components: + - parent: 0 + pos: -15.5,-14.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3 + type: AnnoyingPlaceholderOnPurpose + components: + - parent: 0 + type: Transform +- uid: 855 + components: + - name: Saltern Station + type: MetaData + - parent: null + type: Transform + - index: 0 + type: MapGrid + - shapes: + - !type:PhysShapeGrid + grid: 0 + type: Physics + diff --git a/Content.Tools/test/0C.yml b/Content.Tools/test/0C.yml new file mode 100644 index 00000000000..9d1634c44f4 --- /dev/null +++ b/Content.Tools/test/0C.yml @@ -0,0 +1,105 @@ +meta: + format: 2 + name: DemoStation + author: Space-Wizards + postmapinit: false +tilemap: + 0: space + 1: floor_asteroid_coarse_sand0 + 2: floor_asteroid_coarse_sand1 + 3: floor_asteroid_coarse_sand2 + 4: floor_asteroid_coarse_sand_dug + 5: floor_asteroid_sand + 6: floor_asteroid_tile + 7: floor_dark + 8: floor_elevator_shaft + 9: floor_freezer + 10: floor_gold + 11: floor_green_circuit + 12: floor_hydro + 13: floor_lino + 14: floor_mono + 15: floor_reinforced + 16: floor_rock_vault + 17: floor_showroom + 18: floor_snow + 19: floor_steel + 20: floor_steel_dirty + 21: floor_techmaint + 22: floor_white + 23: floor_wood + 24: lattice + 25: plating + 26: underplating +grids: +- settings: + chunksize: 16 + tilesize: 1 + snapsize: 1 + chunks: + - ind: "-2,-2" + comment: "Ew in A | FQ in B | Fg in C | Fg in Out - SHOULD CAUSE CONFLICT WARNING" + tiles: FgAAABMAAAATAAAAEwAAABMAAAATAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABcAAAAaAAAAEwAAABMAAAATAAAAGgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAaAAAAFgAAABYAAAAaAAAAGgAAABMAAAATAAAAEwAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABoAAAATAAAAEwAAABMAAAAaAAAAGgAAABMAAAAaAAAAEwAAABoAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAAaAAAAEwAAABoAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAAaAAAAGgAAABoAAAAVAAAAGgAAABoAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAGgAAABkAAAAZAAAAGQAAABkAAAAZAAAAGgAAABoAAAAaAAAAGgAAABoAAAATAAAAGgAAABMAAAATAAAAEwAAABUAAAAZAAAAFQAAABUAAAAVAAAAGQAAABkAAAAZAAAAFQAAABUAAAAVAAAAGgAAABoAAAATAAAAEwAAABMAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGQAAABUAAAAaAAAAFQAAAA== + - ind: "-1,-1" + tiles: FQAAABUAAAAVAAAAFQAAABUAAAAVAAAAFQAAABUAAAAVAAAAGgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABkAAAAZAAAAGQAAABkAAAAZAAAAGQAAABkAAAAVAAAAFQAAABoAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAaAAAAGgAAABUAAAAaAAAAGgAAABoAAAAZAAAAFQAAABUAAAAaAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFQAAABUAAAAVAAAAFQAAABUAAAAaAAAAGQAAABUAAAAVAAAAGgAAABYAAAAWAAAAFgAAABoAAAAaAAAAGgAAABUAAAAVAAAAFQAAABUAAAAVAAAAGgAAABkAAAAVAAAAFQAAABoAAAAaAAAAFgAAABoAAAAaAAAAGQAAABkAAAAVAAAAFQAAABUAAAAVAAAAFQAAABoAAAAZAAAAGQAAABkAAAAZAAAAGQAAABkAAAAZAAAAGQAAABkAAAAZAAAAFQAAABUAAAAVAAAAFQAAABUAAAAaAAAAGQAAABUAAAAVAAAAFQAAABUAAAAVAAAAFQAAABUAAAAVAAAAFQAAABoAAAAaAAAAGgAAABUAAAAaAAAAGgAAABkAAAAZAAAAGQAAABkAAAAZAAAAGQAAABkAAAAZAAAAFQAAABUAAAAVAAAAFQAAABUAAAAVAAAAFQAAABUAAAAZAAAAFQAAAA0AAAANAAAADQAAAA0AAAANAAAAGgAAABUAAAAVAAAAGQAAABkAAAAZAAAAGQAAABkAAAAZAAAAGQAAABkAAAANAAAADQAAAA0AAAANAAAADQAAABoAAAAVAAAAFQAAABkAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAADQAAAA0AAAANAAAADQAAAA0AAAAaAAAAGgAAABoAAAAZAAAAEwAAAAkAAAAJAAAACQAAAAkAAAAJAAAAGgAAAA0AAAANAAAADQAAAA0AAAANAAAAFwAAABcAAAAXAAAAGgAAABoAAAAJAAAACQAAAAkAAAAJAAAACQAAABoAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABoAAAAaAAAAGgAAABMAAAAaAAAAGgAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAaAAAAFgAAABYAAAAWAAAAFgAAABYAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAGgAAABYAAAAWAAAAFgAAABYAAAATAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAAA== + - ind: "-1,0" + tiles: EwAAABYAAAAWAAAAFgAAABYAAAATAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABoAAAAWAAAAFgAAABYAAAAWAAAAEwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAEwAAABMAAAAaAAAAEwAAABMAAAAaAAAAGgAAABoAAAAaAAAAGgAAABkAAAAaAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAGgAAABMAAAAZAAAAGgAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABoAAAATAAAAGQAAABoAAAATAAAAEwAAABMAAAAaAAAAEwAAABoAAAAaAAAAEwAAABMAAAAaAAAAGgAAABMAAAAaAAAAGgAAABkAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAAZAAAAFQAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAEwAAABMAAAATAAAAEwAAABoAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAGgAAABoAAAAaAAAAGgAAAA== + - ind: "0,-1" + tiles: FgAAABMAAAATAAAAEwAAABMAAAATAAAAGgAAABYAAAAWAAAAFgAAABYAAAAaAAAAFgAAABYAAAAWAAAAFgAAABYAAAATAAAAEwAAABMAAAATAAAAEwAAABoAAAAWAAAAFgAAABYAAAAWAAAAGgAAABYAAAAWAAAAFgAAABYAAAAaAAAAEwAAABMAAAATAAAAEwAAABMAAAAaAAAAFgAAABYAAAAWAAAAFgAAABoAAAAWAAAAFgAAABYAAAAWAAAAGgAAABoAAAATAAAAEwAAABMAAAAaAAAAGgAAABoAAAAWAAAAGgAAABoAAAAaAAAAFgAAABYAAAAWAAAAGgAAABkAAAAaAAAAEwAAABMAAAATAAAAGgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAZAAAAGgAAABMAAAATAAAAEwAAABoAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAGQAAABoAAAATAAAAEwAAABMAAAAaAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABkAAAAaAAAAEwAAABMAAAATAAAAGgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAZAAAAFQAAABMAAAATAAAAEwAAABoAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFQAAABoAAAATAAAAEwAAABMAAAAaAAAAGgAAABYAAAAaAAAAGgAAABYAAAAWAAAAGgAAABoAAAAWAAAAFgAAABoAAAAaAAAAEwAAABMAAAATAAAAGgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAaAAAAFgAAABYAAAAXAAAAGgAAABMAAAATAAAAEwAAABoAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAGgAAABYAAAAWAAAAFwAAABoAAAATAAAAEwAAABMAAAAaAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABoAAAAaAAAAFgAAABcAAAATAAAAEwAAABMAAAATAAAAEwAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAaAAAAFgAAABYAAAAXAAAAEwAAABMAAAATAAAAEwAAABMAAAAWAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAGgAAABYAAAAWAAAAFwAAABMAAAATAAAAEwAAABMAAAATAAAAFgAAABYAAAAWAAAAFgAAABYAAAAWAAAAFgAAABoAAAAWAAAAFgAAAA== +entities: +- uid: 0 + type: FakeTestDummy + components: + - parent: 855 + pos: -15.5,-11.5 + rot: -1.5707963267948966 rad + type: Transform + - type: ContainerContainer + typeChange: + something: true + example: + - 0 + - 1 + - 2 + - 3 + - 4 + - 855 + - "contributionC" +- uid: 1 + type: FakeTestDummy + components: + - parent: 0 + pos: -5.5,-4.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 2 + type: FakeTestDummy + components: + - parent: 1 + pos: -15.5,-14.5 + rot: -1.5707963267948966 rad + type: Transform + - type: ThereShouldBeTwoOfTheseInOutputOfMergeTestBBB +- uid: 3 + type: AnnoyingPlaceholderOnPurpose + components: + - parent: 0 + type: Transform +- uid: 4 + type: ThisShouldHaveParentChangedToFollowUID + components: + - parent: 2 + type: Transform +- uid: 855 + components: + - name: Saltern Station + type: MetaData + - parent: null + type: Transform + - index: 0 + type: MapGrid + - shapes: + - !type:PhysShapeGrid + grid: 0 + type: Physics + diff --git a/Content.Tools/test/run.sh b/Content.Tools/test/run.sh new file mode 100755 index 00000000000..7809b4dc92a --- /dev/null +++ b/Content.Tools/test/run.sh @@ -0,0 +1,3 @@ +#!/bin/sh +cp 0A.yml out.yml +../bin/Debug/net5.0/Content.Tools out.yml 0B.yml 0C.yml diff --git a/SpaceStation14.sln b/SpaceStation14.sln index 9736962bea9..2ed361745fb 100644 --- a/SpaceStation14.sln +++ b/SpaceStation14.sln @@ -89,6 +89,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XamlX", "RobustToolbox\Xaml EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XamlX.Runtime", "RobustToolbox\XamlX\src\XamlX.Runtime\XamlX.Runtime.csproj", "{440426C1-8DCA-43F6-967F-94439B8DAF47}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Content.Tools", "Content.Tools\Content.Tools.csproj", "{75AB8F8D-9E56-4B12-85E3-E03A852B31CC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -193,6 +195,10 @@ Global {440426C1-8DCA-43F6-967F-94439B8DAF47}.Debug|Any CPU.Build.0 = Debug|Any CPU {440426C1-8DCA-43F6-967F-94439B8DAF47}.Release|Any CPU.ActiveCfg = Release|Any CPU {440426C1-8DCA-43F6-967F-94439B8DAF47}.Release|Any CPU.Build.0 = Release|Any CPU + {75AB8F8D-9E56-4B12-85E3-E03A852B31CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {75AB8F8D-9E56-4B12-85E3-E03A852B31CC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {75AB8F8D-9E56-4B12-85E3-E03A852B31CC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {75AB8F8D-9E56-4B12-85E3-E03A852B31CC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Tools/mapping-merge-driver.sh b/Tools/mapping-merge-driver.sh new file mode 100755 index 00000000000..0421278f311 --- /dev/null +++ b/Tools/mapping-merge-driver.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +# Add this to .git/config: +# [merge "mapping-merge-driver"] +# name = Merge driver for maps +# driver = Tools/mapping-merge-driver.sh %A %O %B + +dotnet run --project ./Content.Tools "$@" +