diff --git a/OpenRA.Game/MiniYaml.cs b/OpenRA.Game/MiniYaml.cs index 3c37d26e0a..260f7003bd 100644 --- a/OpenRA.Game/MiniYaml.cs +++ b/OpenRA.Game/MiniYaml.cs @@ -338,22 +338,24 @@ namespace OpenRA return ResolveInherits(nodes, tree, new Dictionary()); } - static void MergeIntoResolved(MiniYamlNode overrideNode, List existingNodes, + static void MergeIntoResolved(MiniYamlNode overrideNode, List existingNodes, HashSet existingNodeKeys, Dictionary tree, Dictionary inherited) { - var existingNode = existingNodes.Find(n => n.Key == overrideNode.Key); - if (existingNode != null) + if (existingNodeKeys.Add(overrideNode.Key)) { - existingNode.Value = MergePartial(existingNode.Value, overrideNode.Value); - existingNode.Value.Nodes = ResolveInherits(existingNode.Value, tree, inherited); - } - else existingNodes.Add(overrideNode.Clone()); + return; + } + + var existingNode = existingNodes.Find(n => n.Key == overrideNode.Key); + existingNode.Value = MergePartial(existingNode.Value, overrideNode.Value); + existingNode.Value.Nodes = ResolveInherits(existingNode.Value, tree, inherited); } static List ResolveInherits(MiniYaml node, Dictionary tree, Dictionary inherited) { var resolved = new List(node.Nodes.Count); + var resolvedKeys = new HashSet(node.Nodes.Count); // Inheritance is tracked from parent->child, but not from child->parentsiblings. inherited = new Dictionary(inherited); @@ -371,16 +373,17 @@ namespace OpenRA inherited.Add(n.Value.Value, n.Location); foreach (var r in ResolveInherits(parent, tree, inherited)) - MergeIntoResolved(r, resolved, tree, inherited); + MergeIntoResolved(r, resolved, resolvedKeys, tree, inherited); } else if (n.Key.StartsWith("-", StringComparison.Ordinal)) { var removed = n.Key[1..]; if (resolved.RemoveAll(r => r.Key == removed) == 0) throw new YamlException($"{n.Location}: There are no elements with key `{removed}` to remove"); + resolvedKeys.Remove(removed); } else - MergeIntoResolved(n, resolved, tree, inherited); + MergeIntoResolved(n, resolved, resolvedKeys, tree, inherited); } resolved.TrimExcess();