From c7249e6fa68e2dec80ca76b82152ba5b9b7b3533 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 10 May 2015 16:07:11 +0100 Subject: [PATCH] Move yaml removals to the end of the merge. --- OpenRA.Game/GameRules/ActorInfo.cs | 15 +-- OpenRA.Game/GameRules/RulesetCache.cs | 6 +- OpenRA.Game/Graphics/ChromeProvider.cs | 6 +- OpenRA.Game/Graphics/CursorProvider.cs | 6 +- OpenRA.Game/Graphics/SequenceProvider.cs | 3 +- OpenRA.Game/Graphics/VoxelProvider.cs | 3 +- OpenRA.Game/MiniYaml.cs | 93 +++++++++---------- OpenRA.Game/ModData.cs | 7 +- OpenRA.Game/Widgets/ChromeMetrics.cs | 4 +- OpenRA.Mods.Common/Lint/CheckSequences.cs | 6 +- .../UtilityCommands/CheckSequenceSprites.cs | 3 +- .../Widgets/Logic/MissionBrowserLogic.cs | 5 +- 12 files changed, 83 insertions(+), 74 deletions(-) diff --git a/OpenRA.Game/GameRules/ActorInfo.cs b/OpenRA.Game/GameRules/ActorInfo.cs index a951c6b8f5..1c0e74c42b 100644 --- a/OpenRA.Game/GameRules/ActorInfo.cs +++ b/OpenRA.Game/GameRules/ActorInfo.cs @@ -35,20 +35,16 @@ namespace OpenRA { try { + Name = name; + var allParents = new HashSet(); var abstractActorType = name.StartsWith("^"); // Guard against circular inheritance allParents.Add(name); - var mergedNode = MergeWithParents(node, allUnits, allParents).ToDictionary(); - - Name = name; - - foreach (var t in mergedNode) - { - if (t.Key[0] == '-') - throw new YamlException("Bogus trait removal: " + t.Key); + var partial = MergeWithParents(node, allUnits, allParents); + foreach (var t in MiniYaml.ApplyRemovals(partial.Nodes)) if (t.Key != "Inherits" && !t.Key.StartsWith("Inherits@")) try { @@ -59,7 +55,6 @@ namespace OpenRA if (!abstractActorType) throw new YamlException(e.Message); } - } } catch (YamlException e) { @@ -98,7 +93,7 @@ namespace OpenRA throw new YamlException( "Bogus inheritance -- duplicate inheritance of {0}.".F(kv.Key)); - node = MiniYaml.Merge(node, MergeWithParents(kv.Value, allUnits, allParents)); + node = MiniYaml.MergePartial(node, MergeWithParents(kv.Value, allUnits, allParents)); } return node; diff --git a/OpenRA.Game/GameRules/RulesetCache.cs b/OpenRA.Game/GameRules/RulesetCache.cs index ae57659ed4..b5d53936c0 100644 --- a/OpenRA.Game/GameRules/RulesetCache.cs +++ b/OpenRA.Game/GameRules/RulesetCache.cs @@ -99,7 +99,7 @@ namespace OpenRA var inputKey = string.Concat(string.Join("|", files), "|", nodes.WriteToString()); - var mergedNodes = files + var partial = files .Select(s => MiniYaml.FromFile(s)) .Aggregate(nodes, MiniYaml.MergePartial); @@ -117,8 +117,8 @@ namespace OpenRA return t; }; - var yy = mergedNodes.ToDictionary(x => x.Key, x => x.Value); - var itemSet = mergedNodes.ToDictionaryWithConflictLog(kv => kv.Key.ToLowerInvariant(), kv => wrap(kv, yy), "LoadYamlRules", null, null); + var yy = partial.ToDictionary(x => x.Key, x => x.Value); + var itemSet = partial.ToDictionaryWithConflictLog(kv => kv.Key.ToLowerInvariant(), kv => wrap(kv, yy), "LoadYamlRules", null, null); RaiseProgress(); return itemSet; diff --git a/OpenRA.Game/Graphics/ChromeProvider.cs b/OpenRA.Game/Graphics/ChromeProvider.cs index d02ad988d9..89148a3b28 100644 --- a/OpenRA.Game/Graphics/ChromeProvider.cs +++ b/OpenRA.Game/Graphics/ChromeProvider.cs @@ -33,7 +33,11 @@ namespace OpenRA.Graphics cachedSheets = new Dictionary(); cachedSprites = new Dictionary>(); - var chrome = chromeFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergePartial); + var partial = chromeFiles + .Select(s => MiniYaml.FromFile(s)) + .Aggregate(MiniYaml.MergePartial); + + var chrome = MiniYaml.ApplyRemovals(partial); foreach (var c in chrome) LoadCollection(c.Key, c.Value); diff --git a/OpenRA.Game/Graphics/CursorProvider.cs b/OpenRA.Game/Graphics/CursorProvider.cs index e90fb1ee91..2267d70170 100644 --- a/OpenRA.Game/Graphics/CursorProvider.cs +++ b/OpenRA.Game/Graphics/CursorProvider.cs @@ -25,7 +25,11 @@ namespace OpenRA.Graphics public CursorProvider(ModData modData) { var sequenceFiles = modData.Manifest.Cursors; - var sequences = new MiniYaml(null, sequenceFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergePartial)); + var partial = sequenceFiles + .Select(s => MiniYaml.FromFile(s)) + .Aggregate(MiniYaml.MergePartial); + + var sequences = new MiniYaml(null, MiniYaml.ApplyRemovals(partial)); var shadowIndex = new int[] { }; var nodesDict = sequences.ToDictionary(); diff --git a/OpenRA.Game/Graphics/SequenceProvider.cs b/OpenRA.Game/Graphics/SequenceProvider.cs index f1f2cf20cf..ba041076d4 100644 --- a/OpenRA.Game/Graphics/SequenceProvider.cs +++ b/OpenRA.Game/Graphics/SequenceProvider.cs @@ -127,10 +127,11 @@ namespace OpenRA.Graphics { var sequenceFiles = modData.Manifest.Sequences; - var nodes = sequenceFiles + var partial = sequenceFiles .Select(s => MiniYaml.FromFile(s)) .Aggregate(sequenceNodes, MiniYaml.MergePartial); + var nodes = MiniYaml.ApplyRemovals(partial); var items = new Dictionary(); foreach (var n in nodes) { diff --git a/OpenRA.Game/Graphics/VoxelProvider.cs b/OpenRA.Game/Graphics/VoxelProvider.cs index 90ab867f9c..da5ef4e534 100644 --- a/OpenRA.Game/Graphics/VoxelProvider.cs +++ b/OpenRA.Game/Graphics/VoxelProvider.cs @@ -23,10 +23,11 @@ namespace OpenRA.Graphics { units = new Dictionary>(); - var sequences = voxelFiles + var partial = voxelFiles .Select(s => MiniYaml.FromFile(s)) .Aggregate(voxelNodes, MiniYaml.MergePartial); + var sequences = MiniYaml.ApplyRemovals(partial); foreach (var s in sequences) LoadVoxelsForUnit(s.Key, s.Value); diff --git a/OpenRA.Game/MiniYaml.cs b/OpenRA.Game/MiniYaml.cs index bf465cfd79..4fbaf94feb 100644 --- a/OpenRA.Game/MiniYaml.cs +++ b/OpenRA.Game/MiniYaml.cs @@ -264,15 +264,10 @@ namespace OpenRA public static List Merge(List a, List b) { - return Merge(a, b, false); + return ApplyRemovals(MergePartial(a, b)); } public static List MergePartial(List a, List b) - { - return Merge(a, b, true); - } - - static List Merge(List a, List b, bool allowUnresolvedRemoves = false) { if (a.Count == 0) return b; @@ -286,58 +281,49 @@ namespace OpenRA var dictB = b.ToDictionaryWithConflictLog(x => x.Key, "MiniYaml.Merge", null, x => "{0} (at {1})".F(x.Key, x.Location)); var allKeys = dictA.Keys.Union(dictB.Keys); - var keys = allKeys.Where(x => x.Length == 0 || x[0] != '-').ToList(); - var removeKeys = allKeys.Where(x => x.Length > 0 && x[0] == '-') - .Select(k => k.Substring(1)).ToHashSet(); - - foreach (var key in keys) + foreach (var key in allKeys) { MiniYamlNode aa, bb; dictA.TryGetValue(key, out aa); dictB.TryGetValue(key, out bb); - if (removeKeys.Contains(key)) - removeKeys.Remove(key); - else - { - var loc = aa == null ? default(MiniYamlNode.SourceLocation) : aa.Location; - var merged = (aa == null || bb == null) ? aa ?? bb : new MiniYamlNode(key, Merge(aa.Value, bb.Value, allowUnresolvedRemoves), loc); - ret.Add(merged); - } - } - - if (removeKeys.Any()) - { - if (allowUnresolvedRemoves) - { - // Add the removal nodes back for the next pass to deal with - foreach (var k in removeKeys) - { - var key = "-" + k; - MiniYamlNode rem; - if (!dictA.TryGetValue(key, out rem)) - rem = dictB[key]; - ret.Add(rem); - } - } - else - throw new YamlException("Bogus yaml removals: {0}".F(removeKeys.JoinWith(", "))); + var loc = aa == null ? default(MiniYamlNode.SourceLocation) : aa.Location; + var merged = (aa == null || bb == null) ? aa ?? bb : new MiniYamlNode(key, MergePartial(aa.Value, bb.Value), loc); + ret.Add(merged); } return ret; } + public static List ApplyRemovals(List a) + { + var removeKeys = a.Select(x => x.Key) + .Where(x => x.Length > 0 && x[0] == '-') + .Select(k => k.Substring(1)) + .ToHashSet(); + + var ret = new List(); + foreach (var x in a) + { + if (x.Key[0] == '-') + continue; + + if (removeKeys.Contains(x.Key)) + removeKeys.Remove(x.Key); + else + { + x.Value.Nodes = ApplyRemovals(x.Value.Nodes); + ret.Add(x); + } + } + + if (removeKeys.Any()) + throw new YamlException("Bogus yaml removals: {0}".F(removeKeys.JoinWith(", "))); + + return ret; + } + public static MiniYaml MergePartial(MiniYaml a, MiniYaml b) - { - return Merge(a, b, true); - } - - public static MiniYaml Merge(MiniYaml a, MiniYaml b) - { - return Merge(a, b, false); - } - - static MiniYaml Merge(MiniYaml a, MiniYaml b, bool allowUnresolvedRemoves) { if (a == null) return b; @@ -345,7 +331,18 @@ namespace OpenRA if (b == null) return a; - return new MiniYaml(a.Value ?? b.Value, Merge(a.Nodes, b.Nodes, allowUnresolvedRemoves)); + return new MiniYaml(a.Value ?? b.Value, MergePartial(a.Nodes, b.Nodes)); + } + + public static MiniYaml Merge(MiniYaml a, MiniYaml b) + { + if (a == null) + return b; + + if (b == null) + return a; + + return new MiniYaml(a.Value ?? b.Value, Merge(a.Nodes, b.Nodes)); } public IEnumerable ToLines(string name) diff --git a/OpenRA.Game/ModData.cs b/OpenRA.Game/ModData.cs index 04128b4992..3bca6729ec 100644 --- a/OpenRA.Game/ModData.cs +++ b/OpenRA.Game/ModData.cs @@ -119,11 +119,10 @@ namespace OpenRA return; } - var yaml = Manifest.Translations.Select(MiniYaml.FromFile).Aggregate(MiniYaml.MergePartial); - Languages = yaml.Select(t => t.Key).ToArray(); - - yaml = MiniYaml.MergePartial(map.TranslationDefinitions, yaml); + var partial = Manifest.Translations.Select(MiniYaml.FromFile).Aggregate(MiniYaml.MergePartial); + Languages = partial.Select(t => t.Key).ToArray(); + var yaml = MiniYaml.Merge(map.TranslationDefinitions, partial); foreach (var y in yaml) { if (y.Key == Game.Settings.Graphics.Language) diff --git a/OpenRA.Game/Widgets/ChromeMetrics.cs b/OpenRA.Game/Widgets/ChromeMetrics.cs index fb7b848eb3..f283de0e45 100644 --- a/OpenRA.Game/Widgets/ChromeMetrics.cs +++ b/OpenRA.Game/Widgets/ChromeMetrics.cs @@ -20,9 +20,11 @@ namespace OpenRA.Widgets public static void Initialize(IEnumerable yaml) { data = new Dictionary(); - var metrics = yaml.Select(y => MiniYaml.FromFile(y)) + var partial = yaml + .Select(y => MiniYaml.FromFile(y)) .Aggregate(MiniYaml.MergePartial); + var metrics = MiniYaml.ApplyRemovals(partial); foreach (var m in metrics) foreach (var n in m.Value.Nodes) data[n.Key] = n.Value.Value; diff --git a/OpenRA.Mods.Common/Lint/CheckSequences.cs b/OpenRA.Mods.Common/Lint/CheckSequences.cs index 262afc462f..dc7e3386f5 100644 --- a/OpenRA.Mods.Common/Lint/CheckSequences.cs +++ b/OpenRA.Mods.Common/Lint/CheckSequences.cs @@ -32,8 +32,10 @@ namespace OpenRA.Mods.Common.Lint this.emitError = emitError; var sequenceSource = map != null ? map.SequenceDefinitions : new List(); - sequenceDefinitions = MiniYaml.MergePartial(sequenceSource, - Game.ModData.Manifest.Sequences.Select(MiniYaml.FromFile).Aggregate(MiniYaml.MergePartial)); + var partial = Game.ModData.Manifest.Sequences + .Select(MiniYaml.FromFile) + .Aggregate(MiniYaml.MergePartial); + sequenceDefinitions = MiniYaml.Merge(sequenceSource, partial); var rules = map == null ? Game.ModData.DefaultRules : map.Rules; var factions = rules.Actors["world"].TraitInfos().Select(f => f.InternalName).ToArray(); diff --git a/OpenRA.Mods.Common/UtilityCommands/CheckSequenceSprites.cs b/OpenRA.Mods.Common/UtilityCommands/CheckSequenceSprites.cs index c6607b6132..11671cd10f 100644 --- a/OpenRA.Mods.Common/UtilityCommands/CheckSequenceSprites.cs +++ b/OpenRA.Mods.Common/UtilityCommands/CheckSequenceSprites.cs @@ -39,10 +39,11 @@ namespace OpenRA.Mods.Common.UtilityCommands var sc = new SpriteCache(modData.SpriteLoaders, new SheetBuilder(SheetType.Indexed)); var sequenceFiles = modData.Manifest.Sequences; - var nodes = sequenceFiles + var partial = sequenceFiles .Select(s => MiniYaml.FromFile(s)) .Aggregate(MiniYaml.MergePartial); + var nodes = MiniYaml.ApplyRemovals(partial); foreach (var n in nodes) Game.ModData.SpriteSequenceLoader.ParseSequences(Game.ModData, ts, sc, n); } diff --git a/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs index 6c264500b6..ec1fba73ee 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs @@ -97,8 +97,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic // Add a group for each campaign if (Game.ModData.Manifest.Missions.Any()) { - var yaml = Game.ModData.Manifest.Missions.Select(MiniYaml.FromFile).Aggregate(MiniYaml.MergePartial); + var partial = Game.ModData.Manifest.Missions + .Select(MiniYaml.FromFile) + .Aggregate(MiniYaml.MergePartial); + var yaml = MiniYaml.ApplyRemovals(partial); foreach (var kv in yaml) { var missionMapPaths = kv.Value.Nodes.Select(n => Path.GetFullPath(n.Key));