MiniYaml becomes an immutable data structure.

This changeset is motivated by a simple concept - get rid of the MiniYaml.Clone and MiniYamlNode.Clone methods to avoid deep copying yaml trees during merging. MiniYaml becoming immutable allows the merge function to reuse existing yaml trees rather than cloning them, saving on memory and improving merge performance. On initial loading the YAML for all maps is processed, so this provides a small reduction in initial loading time.

The rest of the changeset is dealing with the change in the exposed API surface. Some With* helper methods are introduced to allow creating new YAML from existing YAML. Areas of code that generated small amounts of YAML are able to transition directly to the immutable model without too much ceremony. Some use cases are far less ergonomic even with these helper methods and so a MiniYamlBuilder is introduced to retain mutable creation functionality. This allows those areas to continue to use the old mutable structures. The main users are the update rules and linting capabilities.
This commit is contained in:
RoosterDragon
2023-05-06 10:39:15 +01:00
committed by Gustas
parent b6a5d19871
commit 949ba589c0
104 changed files with 722 additions and 393 deletions

View File

@@ -49,7 +49,7 @@ namespace OpenRA.Mods.Common.Graphics
var sequences = new Dictionary<string, ISpriteSequence>();
var node = imageNode.Value.Nodes.SingleOrDefault(n => n.Key == "Defaults");
var defaults = node?.Value ?? NoData;
imageNode.Value.Nodes.Remove(node);
imageNode = imageNode.WithValue(imageNode.Value.WithNodes(imageNode.Value.Nodes.Remove(node)));
foreach (var sequenceNode in imageNode.Value.Nodes)
{
@@ -262,7 +262,7 @@ namespace OpenRA.Mods.Common.Graphics
protected static T LoadField<T>(string key, T fallback, MiniYaml data, MiniYaml defaults = null)
{
var node = data.Nodes.Find(n => n.Key == key) ?? defaults?.Nodes.Find(n => n.Key == key);
var node = data.Nodes.FirstOrDefault(n => n.Key == key) ?? defaults?.Nodes.FirstOrDefault(n => n.Key == key);
if (node == null)
return fallback;
@@ -276,7 +276,7 @@ namespace OpenRA.Mods.Common.Graphics
protected static T LoadField<T>(SpriteSequenceField<T> field, MiniYaml data, MiniYaml defaults, out MiniYamlNode.SourceLocation location)
{
var node = data.Nodes.Find(n => n.Key == field.Key) ?? defaults?.Nodes.Find(n => n.Key == field.Key);
var node = data.Nodes.FirstOrDefault(n => n.Key == field.Key) ?? defaults?.Nodes.FirstOrDefault(n => n.Key == field.Key);
if (node == null)
{
location = default;
@@ -414,10 +414,10 @@ namespace OpenRA.Mods.Common.Graphics
var offset = LoadField(Offset, data, defaults);
var blendMode = LoadField(BlendMode, data, defaults);
var combineNode = data.Nodes.Find(n => n.Key == Combine.Key);
var combineNode = data.Nodes.FirstOrDefault(n => n.Key == Combine.Key);
if (combineNode != null)
{
for (var i = 0; i < combineNode.Value.Nodes.Count; i++)
for (var i = 0; i < combineNode.Value.Nodes.Length; i++)
{
var subData = combineNode.Value.Nodes[i].Value;
var subOffset = LoadField(Offset, subData, NoData);

View File

@@ -11,6 +11,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using OpenRA.Widgets;
@@ -64,7 +65,7 @@ namespace OpenRA.Mods.Common.Lint
}
void CheckInner(ModData modData, string[] namedKeys, (string Widget, string Field)[] checkWidgetFields, Dictionary<string, List<string>> customLintMethods,
List<MiniYamlNode> nodes, string filename, MiniYamlNode parent, Action<string> emitError)
IEnumerable<MiniYamlNode> nodes, string filename, MiniYamlNode parent, Action<string> emitError)
{
foreach (var node in nodes)
{
@@ -94,7 +95,7 @@ namespace OpenRA.Mods.Common.Lint
}
// Logic classes can declare the data key names that specify hotkeys.
if (node.Key == "Logic" && node.Value.Nodes.Count > 0)
if (node.Key == "Logic" && node.Value.Nodes.Length > 0)
{
var typeNames = FieldLoader.GetValue<string[]>(node.Key, node.Value.Value);
var checkArgKeys = new List<string>();

View File

@@ -24,7 +24,7 @@ namespace OpenRA.Mods.Common.Lint
CheckInner(MiniYaml.FromStream(modData.DefaultFileSystem.Open(filename), filename), filename, emitError);
}
void CheckInner(List<MiniYamlNode> nodes, string filename, Action<string> emitError)
void CheckInner(IEnumerable<MiniYamlNode> nodes, string filename, Action<string> emitError)
{
var substitutions = new Dictionary<string, int>();
var readOnlySubstitutions = new ReadOnlyDictionary<string, int>(substitutions);

View File

@@ -23,7 +23,7 @@ namespace OpenRA.Mods.Common.Lint
CheckInner(MiniYaml.FromStream(modData.DefaultFileSystem.Open(filename), filename), filename, emitError);
}
void CheckInner(List<MiniYamlNode> nodes, string filename, Action<string> emitError)
void CheckInner(IEnumerable<MiniYamlNode> nodes, string filename, Action<string> emitError)
{
foreach (var node in nodes)
{

View File

@@ -52,7 +52,7 @@ namespace OpenRA.Mods.Common.Lint
// Removals can never define children or values.
if (t.Key.StartsWith("-", StringComparison.Ordinal))
{
if (t.Value.Nodes.Count > 0)
if (t.Value.Nodes.Length > 0)
emitError($"{t.Location} `{t.Key}` defines child nodes, which are not valid for removals.");
if (!string.IsNullOrEmpty(t.Value.Value))
@@ -66,7 +66,7 @@ namespace OpenRA.Mods.Common.Lint
// Inherits can never define children.
if (traitName == "Inherits")
{
if (t.Value.Nodes.Count > 0)
if (t.Value.Nodes.Length > 0)
emitError($"{t.Location} defines child nodes, which are not valid for Inherits.");
continue;
@@ -98,7 +98,7 @@ namespace OpenRA.Mods.Common.Lint
foreach (var f in mapFiles)
CheckActors(MiniYaml.FromStream(fileSystem.Open(f), f), emitError, modData);
if (ruleDefinitions.Nodes.Count > 0)
if (ruleDefinitions.Nodes.Length > 0)
CheckActors(ruleDefinitions.Nodes, emitError, modData);
}
}

View File

@@ -54,7 +54,7 @@ namespace OpenRA.Mods.Common.Lint
// Removals can never define children or values
if (field.Key.StartsWith("-", StringComparison.Ordinal))
{
if (field.Value.Nodes.Count > 0)
if (field.Value.Nodes.Length > 0)
emitError($"{field.Location} `{field.Key}` defines child nodes, which is not valid for removals.");
if (!string.IsNullOrEmpty(field.Value.Value))
@@ -119,7 +119,7 @@ namespace OpenRA.Mods.Common.Lint
foreach (var f in mapFiles)
CheckWeapons(MiniYaml.FromStream(fileSystem.Open(f), f), emitError, emitWarning, modData);
if (weaponDefinitions.Nodes.Count > 0)
if (weaponDefinitions.Nodes.Length > 0)
CheckWeapons(weaponDefinitions.Nodes, emitError, emitWarning, modData);
}
}

View File

@@ -66,7 +66,7 @@ namespace OpenRA.Mods.Common.Lint
foreach (var actorNode in nodes)
{
var inherits = inheritsMap.GetOrAdd(actorNode.Key, _ => new List<string>());
foreach (var inheritsNode in actorNode.ChildrenMatching("Inherits"))
foreach (var inheritsNode in new MiniYamlNodeBuilder(actorNode).ChildrenMatching("Inherits"))
inherits.Add(inheritsNode.Value.Value);
}

View File

@@ -11,6 +11,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
@@ -56,7 +57,7 @@ namespace OpenRA
public readonly MiniYaml IDFiles;
[FieldLoader.Ignore]
public readonly List<MiniYamlNode> Install;
public readonly ImmutableArray<MiniYamlNode> Install;
public readonly string TooltipText;

View File

@@ -55,7 +55,7 @@ namespace OpenRA.Mods.Common.Terrain
}
else
{
tileInfo = new TerrainTileInfo[nodes.Count];
tileInfo = new TerrainTileInfo[nodes.Length];
var i = 0;
foreach (var node in nodes)

View File

@@ -10,6 +10,7 @@
#endregion
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using OpenRA.Traits;
@@ -275,7 +276,7 @@ namespace OpenRA.Mods.Common.Traits
};
}
void IGameSaveTraitData.ResolveTraitData(Actor self, List<MiniYamlNode> data)
void IGameSaveTraitData.ResolveTraitData(Actor self, ImmutableArray<MiniYamlNode> data)
{
if (self.World.IsReplay)
return;

View File

@@ -10,6 +10,7 @@
#endregion
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using OpenRA.Traits;
@@ -211,7 +212,7 @@ namespace OpenRA.Mods.Common.Traits
};
}
void IGameSaveTraitData.ResolveTraitData(Actor self, List<MiniYamlNode> data)
void IGameSaveTraitData.ResolveTraitData(Actor self, ImmutableArray<MiniYamlNode> data)
{
if (self.World.IsReplay)
return;

View File

@@ -11,6 +11,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using OpenRA.Mods.Common.Traits.BotModules.Squads;
using OpenRA.Primitives;
@@ -407,7 +408,7 @@ namespace OpenRA.Mods.Common.Traits
};
}
void IGameSaveTraitData.ResolveTraitData(Actor self, List<MiniYamlNode> data)
void IGameSaveTraitData.ResolveTraitData(Actor self, ImmutableArray<MiniYamlNode> data)
{
if (self.World.IsReplay)
return;

View File

@@ -84,16 +84,15 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
public MiniYaml Serialize()
{
var nodes = new MiniYaml("", new List<MiniYamlNode>()
var nodes = new List<MiniYamlNode>()
{
new MiniYamlNode("Type", FieldSaver.FormatValue(Type)),
new MiniYamlNode("Units", FieldSaver.FormatValue(Units.Select(a => a.ActorID).ToArray())),
});
};
if (Target.Type == TargetType.Actor)
nodes.Nodes.Add(new MiniYamlNode("Target", FieldSaver.FormatValue(Target.Actor.ActorID)));
nodes.Add(new MiniYamlNode("Target", FieldSaver.FormatValue(Target.Actor.ActorID)));
return nodes;
return new MiniYaml("", nodes);
}
public static Squad Deserialize(IBot bot, SquadManagerBotModule squadManager, MiniYaml yaml)

View File

@@ -10,6 +10,7 @@
#endregion
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using OpenRA.Traits;
@@ -222,7 +223,7 @@ namespace OpenRA.Mods.Common.Traits
};
}
void IGameSaveTraitData.ResolveTraitData(Actor self, List<MiniYamlNode> data)
void IGameSaveTraitData.ResolveTraitData(Actor self, ImmutableArray<MiniYamlNode> data)
{
if (self.World.IsReplay)
return;

View File

@@ -10,6 +10,7 @@
#endregion
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using OpenRA.Traits;
@@ -221,7 +222,7 @@ namespace OpenRA.Mods.Common.Traits
};
}
void IGameSaveTraitData.ResolveTraitData(Actor self, List<MiniYamlNode> data)
void IGameSaveTraitData.ResolveTraitData(Actor self, ImmutableArray<MiniYamlNode> data)
{
if (self.World.IsReplay)
return;

View File

@@ -10,6 +10,7 @@
#endregion
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Traits;
@@ -49,7 +50,7 @@ namespace OpenRA.Mods.Common.Traits
return nodes;
}
void IGameSaveTraitData.ResolveTraitData(Actor self, List<MiniYamlNode> data)
void IGameSaveTraitData.ResolveTraitData(Actor self, ImmutableArray<MiniYamlNode> data)
{
var viewportNode = data.FirstOrDefault(n => n.Key == "Viewport");
if (viewportNode != null)

View File

@@ -10,6 +10,7 @@
#endregion
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using OpenRA.Traits;
@@ -132,7 +133,7 @@ namespace OpenRA.Mods.Common.Traits
};
}
void IGameSaveTraitData.ResolveTraitData(Actor self, List<MiniYamlNode> data)
void IGameSaveTraitData.ResolveTraitData(Actor self, ImmutableArray<MiniYamlNode> data)
{
var groupsNode = data.FirstOrDefault(n => n.Key == "Groups");
if (groupsNode != null)

View File

@@ -85,7 +85,7 @@ namespace OpenRA.Mods.Common.Traits
protected static object LoadSpeeds(MiniYaml y)
{
var speeds = y.ToDictionary()["TerrainSpeeds"].Nodes;
var ret = new Dictionary<string, TerrainInfo>(speeds.Count);
var ret = new Dictionary<string, TerrainInfo>(speeds.Length);
foreach (var t in speeds)
{
var speed = FieldLoader.GetValue<int>("speed", t.Value.Value);

View File

@@ -10,6 +10,7 @@
#endregion
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using OpenRA.Traits;
@@ -182,7 +183,7 @@ namespace OpenRA.Mods.Common.Traits
};
}
void IGameSaveTraitData.ResolveTraitData(Actor self, List<MiniYamlNode> data)
void IGameSaveTraitData.ResolveTraitData(Actor self, ImmutableArray<MiniYamlNode> data)
{
var selectionNode = data.FirstOrDefault(n => n.Key == "Selection");
if (selectionNode != null)

View File

@@ -72,9 +72,9 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
harvesterPipLocations.Clear();
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
var addNodes = new List<MiniYamlNode>();
var addNodes = new List<MiniYamlNodeBuilder>();
foreach (var selectionDecorations in actorNode.ChildrenMatching("SelectionDecorations"))
{
@@ -84,7 +84,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
foreach (var ammoPool in actorNode.ChildrenMatching("AmmoPool"))
{
var ammoPips = new MiniYamlNode("WithAmmoPipsDecoration", "");
var ammoPips = new MiniYamlNodeBuilder("WithAmmoPipsDecoration", "");
ammoPips.AddNode("Position", "BottomLeft");
ammoPips.AddNode("RequiresSelection", "true");
@@ -95,7 +95,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
var pipCount = pipCountNode.NodeValue<int>();
if (pipCount == 0)
{
addNodes.Add(new MiniYamlNode("-" + ammoPips.Key, ""));
addNodes.Add(new MiniYamlNodeBuilder("-" + ammoPips.Key, ""));
continue;
}
@@ -129,7 +129,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
foreach (var cargo in actorNode.ChildrenMatching("Cargo"))
{
var cargoPips = new MiniYamlNode("WithCargoPipsDecoration", "");
var cargoPips = new MiniYamlNodeBuilder("WithCargoPipsDecoration", "");
cargoPips.AddNode("Position", "BottomLeft");
cargoPips.AddNode("RequiresSelection", "true");
@@ -141,7 +141,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
var pipCount = pipCountNode.NodeValue<int>();
if (pipCount == 0)
{
addNodes.Add(new MiniYamlNode("-" + cargoPips.Key, ""));
addNodes.Add(new MiniYamlNodeBuilder("-" + cargoPips.Key, ""));
continue;
}
@@ -171,7 +171,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
foreach (var harvester in actorNode.ChildrenMatching("Harvester"))
{
var harvesterPips = new MiniYamlNode("WithHarvesterPipsDecoration", "");
var harvesterPips = new MiniYamlNodeBuilder("WithHarvesterPipsDecoration", "");
harvesterPips.AddNode("Position", "BottomLeft");
harvesterPips.AddNode("RequiresSelection", "true");
@@ -189,7 +189,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
var pipCount = pipCountNode.NodeValue<int>();
if (pipCount == 0)
{
addNodes.Add(new MiniYamlNode("-" + harvesterPips.Key, ""));
addNodes.Add(new MiniYamlNodeBuilder("-" + harvesterPips.Key, ""));
continue;
}
@@ -220,7 +220,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
foreach (var storesResources in actorNode.ChildrenMatching("StoresResources"))
{
var storagePips = new MiniYamlNode("WithResourceStoragePipsDecoration", "");
var storagePips = new MiniYamlNodeBuilder("WithResourceStoragePipsDecoration", "");
storagePips.AddNode("Position", "BottomLeft");
storagePips.AddNode("RequiresSelection", "true");
@@ -231,7 +231,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
var pipCount = pipCountNode.NodeValue<int>();
if (pipCount == 0)
{
addNodes.Add(new MiniYamlNode("-" + storagePips.Key, ""));
addNodes.Add(new MiniYamlNodeBuilder("-" + storagePips.Key, ""));
continue;
}

View File

@@ -21,7 +21,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
"Going forward, the value of the `Delay` attribute of the `DrawLineToTarget` trait will be\n" +
"interpreted as milliseconds instead of ticks.\n";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var dltt in actorNode.ChildrenMatching("DrawLineToTarget", includeRemovals: false))
{

View File

@@ -24,7 +24,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
static readonly string[] AffectedTraits = new string[] { "GrantExternalConditionPower", "ChronoshiftPower" };
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var at in AffectedTraits)
foreach (var trait in actorNode.ChildrenMatching(at))
@@ -33,7 +33,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
yield break;
}
void UpdatePower(MiniYamlNode power)
void UpdatePower(MiniYamlNodeBuilder power)
{
var range = 1;
var rangeNode = power.LastChildMatching("Range");
@@ -47,7 +47,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
}
var size = 2 * range + 1;
power.AddNode(new MiniYamlNode("Dimensions", size.ToString() + ", " + size.ToString()));
power.AddNode(new MiniYamlNodeBuilder("Dimensions", size.ToString() + ", " + size.ToString()));
var footprint = string.Empty;
@@ -79,7 +79,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
footprint += ' ';
}
power.AddNode(new MiniYamlNode("Footprint", footprint));
power.AddNode(new MiniYamlNodeBuilder("Footprint", footprint));
}
readonly List<string> locations = new();

View File

@@ -23,7 +23,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
readonly List<Tuple<string, string, string>> weaponsToUpdate = new();
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
var nukePowerTraits = actorNode.ChildrenMatching("NukePower");
foreach (var nukePowerTrait in nukePowerTraits)

View File

@@ -63,7 +63,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
locations.Clear();
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
var locationKey = $"{actorNode.Key} ({actorNode.Location.Filename})";

View File

@@ -36,7 +36,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
locations.Clear();
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var bo in actorNode.ChildrenMatching("BodyOrientation"))
{
@@ -58,7 +58,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
yield break;
}
public override IEnumerable<string> UpdateSequenceNode(ModData modData, MiniYamlNode sequenceNode)
public override IEnumerable<string> UpdateSequenceNode(ModData modData, MiniYamlNodeBuilder sequenceNode)
{
foreach (var sequence in sequenceNode.Value.Nodes)
{

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "ConditionManager trait has been removed. Its functionality has been integrated into the actor itself.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
actorNode.RemoveNodes("ConditionManager");
yield break;

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "'LaysTerrain' was removed.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
if (actorNode.RemoveNodes("LaysTerrain") > 0)
yield return $"'LaysTerrain' was removed from {actorNode.Key} ({actorNode.Location.Filename}) without replacement.\n";

View File

@@ -22,7 +22,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
"The same result can be created by using `Combine` in the sequence definitions to\n" +
"assemble the different facings sprites into a single sequence.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var a in actorNode.ChildrenMatching("Armament"))
{

View File

@@ -39,7 +39,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
turningAircraft.Clear();
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
var aircraft = actorNode.LastChildMatching("Aircraft");
if (aircraft != null)

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "RenderDetectionCircle and RenderShroudCircle ContrastColor have been renamed to BorderColor for consistency.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var rdc in actorNode.ChildrenMatching("RenderDetectionCircle"))
rdc.RenameChildrenMatching("ContrastColor", "BorderColor");

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "The 'HealUnitsCrateAction' has been renamed to 'HealActorsCrateAction'.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var huca in actorNode.ChildrenMatching("HealUnitsCrateAction"))
huca.RenameKey("HealActorsCrateAction");

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "The InfiltrateForCash Notification has been renamed to be in line with new notification properties added.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var rp in actorNode.ChildrenMatching("InfiltrateForCash"))
rp.RenameChildrenMatching("Notification", "InfiltratedNotification");

View File

@@ -21,7 +21,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
"SelfHealing was renamed to ChangesHealth\n" +
"HealIfBelow was renamed to StartIfBelow.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var sh in actorNode.ChildrenMatching("SelfHealing"))
{

View File

@@ -21,7 +21,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
"Renamed smoke-related properties on SmudgeLayer to be in line with comparable properties.\n" +
"Additionally, set the *Chance, *Image and *Sequences defaults to null.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var layer in actorNode.ChildrenMatching("SmudgeLayer"))
{

View File

@@ -77,7 +77,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
("TooltipDescription", "ValidStances", "ValidRelationships")
};
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var (traitName, oldName, newName) in traits)
foreach (var traitNode in actorNode.ChildrenMatching(traitName))
@@ -86,7 +86,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
yield break;
}
public override IEnumerable<string> UpdateWeaponNode(ModData modData, MiniYamlNode weaponNode)
public override IEnumerable<string> UpdateWeaponNode(ModData modData, MiniYamlNodeBuilder weaponNode)
{
foreach (var projectileNode in weaponNode.ChildrenMatching("Projectile"))
projectileNode.RenameChildrenMatching("ValidBounceBlockerStances", "ValidBounceBlockerRelationships");

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "`WithNukeLaunchAnimation` has been renamed to `WithSupportPowerActivationAnimation` and `WithNukeLaunchOverlay` to `WithSupportPowerActivationOverlay`.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
actorNode.RenameChildrenMatching("WithNukeLaunchAnimation", "WithSupportPowerActivationAnimation", true);
actorNode.RenameChildrenMatching("WithNukeLaunchOverlay", "WithSupportPowerActivationOverlay", true);

View File

@@ -19,9 +19,9 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "Burns can be replaced using WithIdleOverlay and ChangesHealth.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
var addNodes = new List<MiniYamlNode>();
var addNodes = new List<MiniYamlNodeBuilder>();
foreach (var burns in actorNode.ChildrenMatching("Burns"))
{
@@ -34,13 +34,13 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
var interval = burns.LastChildMatching("Interval");
var intervalValue = interval != null ? interval.NodeValue<int>() : 8;
var overlay = new MiniYamlNode("WithIdleOverlay@Burns", "");
var overlay = new MiniYamlNodeBuilder("WithIdleOverlay@Burns", "");
overlay.AddNode("Image", FieldSaver.FormatValue("fire"));
overlay.AddNode("Sequence", FieldSaver.FormatValue(animValue));
overlay.AddNode("IsDecoration", FieldSaver.FormatValue(true));
addNodes.Add(overlay);
var changesHealth = new MiniYamlNode("ChangesHealth", "");
var changesHealth = new MiniYamlNodeBuilder("ChangesHealth", "");
changesHealth.AddNode("Step", FieldSaver.FormatValue(-damageValue));
changesHealth.AddNode("StartIfBelow", FieldSaver.FormatValue(101));
changesHealth.AddNode("Delay", FieldSaver.FormatValue(intervalValue));

View File

@@ -70,7 +70,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
}
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var kv in TraitFields)
{
@@ -90,7 +90,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
yield break;
}
public override IEnumerable<string> UpdateWeaponNode(ModData modData, MiniYamlNode weaponNode)
public override IEnumerable<string> UpdateWeaponNode(ModData modData, MiniYamlNodeBuilder weaponNode)
{
foreach (var projectileNode in weaponNode.ChildrenMatching("Projectile"))
{

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "The 'EffectSequence' of 'SpawnActorPower' is unset by default.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var spawnActorPower in actorNode.ChildrenMatching("SpawnActorPower"))
{

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "'DamageThreshold' and 'StartOnThreshold' are no longer supported and removed from 'DamagedByTerrain'.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var damaged in actorNode.ChildrenMatching("DamagedByTerrain", includeRemovals: false))
{

View File

@@ -33,7 +33,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
}
}
public override IEnumerable<string> UpdateMapActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateMapActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
if (actorNode.RemoveNodes("Plugs") > 0)
yield return $"Initial plugs for actor {actorNode.Key} will need to be reconfigured using the map editor.";
@@ -48,7 +48,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
facing.ReplaceValue(FieldSaver.FormatValue(bodyFacing));
}
var removeNodes = new List<MiniYamlNode>();
var removeNodes = new List<MiniYamlNodeBuilder>();
foreach (var facing in actorNode.ChildrenMatching("TurretFacing"))
{
var turretFacing = WAngle.FromFacing(facing.NodeValue<int>()) - bodyFacing;
@@ -62,7 +62,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
actorNode.Value.Nodes.Remove(node);
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var turret in actorNode.ChildrenMatching("Turreted"))
turret.RemoveNodes("PreviewFacing");

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "The LeftColor and RightColor keys in tilesets have been renamed to MinColor and MaxColor to reflect their proper usage.";
public override IEnumerable<string> UpdateTilesetNode(ModData modData, MiniYamlNode tilesetNode)
public override IEnumerable<string> UpdateTilesetNode(ModData modData, MiniYamlNodeBuilder tilesetNode)
{
if (tilesetNode.Key == "Templates")
{

View File

@@ -20,11 +20,11 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "A new trait ControlGroups was added, splitting logic away from Selection.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
if (actorNode.ChildrenMatching("Selection").Any(x => !x.IsRemoval())
&& !actorNode.ChildrenMatching("ControlGroups").Any())
actorNode.AddNode(new MiniYamlNode("ControlGroups", ""));
actorNode.AddNode(new MiniYamlNodeBuilder("ControlGroups", ""));
yield break;
}

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "The tolerance for attack angle was defined twice on AttackBomber. This override has to be defined in the rules now.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var attackBomber in actorNode.ChildrenMatching("AttackBomber", includeRemovals: false))
{
@@ -27,7 +27,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
if (facingTolerance != null)
continue;
var facingToleranceNode = new MiniYamlNode("FacingTolerance", FieldSaver.FormatValue(new WAngle(8)));
var facingToleranceNode = new MiniYamlNodeBuilder("FacingTolerance", FieldSaver.FormatValue(new WAngle(8)));
attackBomber.AddNode(facingToleranceNode);
}

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "The tolerance for the attack angle was defined twice on AttackFrontal. This override has to be defined in the rules now.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var attackFrontal in actorNode.ChildrenMatching("AttackFrontal", includeRemovals: false))
{
@@ -27,7 +27,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
if (facingTolerance != null)
continue;
var facingToleranceNode = new MiniYamlNode("FacingTolerance", FieldSaver.FormatValue(WAngle.Zero));
var facingToleranceNode = new MiniYamlNodeBuilder("FacingTolerance", FieldSaver.FormatValue(WAngle.Zero));
attackFrontal.AddNode(facingToleranceNode);
}

View File

@@ -24,7 +24,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
readonly string[] traits = { "Interactable", "Selectable", "IsometricSelectable" };
readonly string[] fields = { "Bounds", "DecorationBounds" };
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
var grid = modData.Manifest.Get<MapGrid>();
var tileSize = grid.TileSize;

View File

@@ -19,12 +19,12 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "The DomainIndex trait was removed from World. Two overlay traits were added at the same time.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
if (actorNode.RemoveNodes("DomainIndex") > 0)
{
actorNode.AddNode(new MiniYamlNode("PathFinderOverlay", ""));
actorNode.AddNode(new MiniYamlNode("HierarchicalPathFinderOverlay", ""));
actorNode.AddNode(new MiniYamlNodeBuilder("PathFinderOverlay", ""));
actorNode.AddNode(new MiniYamlNodeBuilder("HierarchicalPathFinderOverlay", ""));
}
yield break;

View File

@@ -35,7 +35,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
locations.Clear();
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
var removed = 0;
foreach (var node in actorNode.ChildrenMatching("ActorPreviewPlaceBuildingPreview"))

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "PlayerHighlightPalette trait has been removed. Its functionality is now automatically provided by the engine.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
actorNode.RemoveNodes("PlayerHighlightPalette");
yield break;

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "The Scale option was removed from RenderSprites. Scale can now be defined on individual sequence definitions.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var renderSprites in actorNode.ChildrenMatching("RenderSprites"))
if (renderSprites.RemoveNodes("Scale") > 0)

View File

@@ -21,15 +21,15 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
"The ResourceType trait has been removed, and resource definitions moved to the\n" +
"ResourceLayer, EditorResourceLayer, ResourceRenderer, and PlayerResources traits.";
MiniYaml resourceLayer;
MiniYaml resourceRenderer;
MiniYaml values;
MiniYamlBuilder resourceLayer;
MiniYamlBuilder resourceRenderer;
MiniYamlBuilder values;
public override IEnumerable<string> BeforeUpdate(ModData modData)
{
resourceLayer = new MiniYaml("");
resourceRenderer = new MiniYaml("");
values = new MiniYaml("");
resourceLayer = new MiniYamlBuilder("");
resourceRenderer = new MiniYamlBuilder("");
values = new MiniYamlBuilder("");
yield break;
}
@@ -54,17 +54,17 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
"You must define a custom ResourceLayer subclass if you want to customize the default behaviour.";
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var resourceNode in actorNode.ChildrenMatching("ResourceType"))
{
var typeNode = resourceNode.LastChildMatching("Type");
if (typeNode != null)
{
var resourceLayerNode = new MiniYamlNode(typeNode.Value.Value, "");
var resourceLayerNode = new MiniYamlNodeBuilder(new MiniYamlNode(typeNode.Value.Value, ""));
resourceLayer.Nodes.Add(resourceLayerNode);
var resourceRendererNode = new MiniYamlNode(typeNode.Value.Value, "");
var resourceRendererNode = new MiniYamlNodeBuilder(new MiniYamlNode(typeNode.Value.Value, ""));
resourceRenderer.Nodes.Add(resourceRendererNode);
var indexNode = resourceNode.LastChildMatching("ResourceType");
@@ -88,7 +88,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
var valueNode = resourceNode.LastChildMatching("ValuePerUnit");
if (valueNode != null)
values.Nodes.Add(new MiniYamlNode(typeNode.Value.Value, valueNode.Value.Value));
values.Nodes.Add(new MiniYamlNodeBuilder(typeNode.Value.Value, valueNode.Value.Value));
var imageNode = resourceNode.LastChildMatching("Image");
if (imageNode != null)

View File

@@ -38,7 +38,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
locations.Clear();
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
var locationKey = $"{actorNode.Key} ({actorNode.Location.Filename})";
var anyConditionalSmokeTrail = false;
@@ -94,7 +94,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
if (anyConditionalSmokeTrail)
{
var grantCondition = new MiniYamlNode("GrantConditionOnDamageState@SmokeTrail", "");
var grantCondition = new MiniYamlNodeBuilder("GrantConditionOnDamageState@SmokeTrail", "");
grantCondition.AddNode("Condition", FieldSaver.FormatValue("enable-smoke"));
actorNode.AddNode(grantCondition);
}

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "Rename 'CloakTypes' to 'DetectionTypes' in order to make it clearer as well as make space for 'CloakType' in Cloak";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var traitNode in actorNode.ChildrenMatching("Cloak"))
traitNode.RenameChildrenMatching("CloakTypes", "DetectionTypes");

View File

@@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "Rename contrail color properties `Color` to `StartColor` and `UsePlayerColor` to `StartColorUsePlayerColor` in traits and weapons to account for added `EndColor` functionality";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var traitNode in actorNode.ChildrenMatching("Contrail"))
{
@@ -31,7 +31,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
yield break;
}
public override IEnumerable<string> UpdateWeaponNode(ModData modData, MiniYamlNode weaponNode)
public override IEnumerable<string> UpdateWeaponNode(ModData modData, MiniYamlNodeBuilder weaponNode)
{
foreach (var traitNode in weaponNode.ChildrenMatching("Projectile").Where(n => n.Value.Value == "Missile"))
{

View File

@@ -21,7 +21,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
"'SpawnMPUnits' was renamed to 'SpawnStartingUnits', 'MPStartUnits' to 'StartingUnits', 'MPStartLocations' to " +
"'MapStartingLocations', and 'CreateMPPlayers' to 'CreateMapPlayers'.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
actorNode.RenameChildrenMatching("SpawnMPUnits", "SpawnStartingUnits");
actorNode.RenameChildrenMatching("MPStartUnits", "StartingUnits");

View File

@@ -18,7 +18,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Name => "Support powers now use 'Name' and 'Description' fields like units.";
public override string Description => "'Description' was renamed to 'Name' and 'LongDesc' was renamed to 'Description'.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var traitNode in actorNode.ChildrenContaining("Power"))
{

View File

@@ -22,7 +22,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
"by multiplying with 25 internally. Converted to use ticks like everything else.\n" +
"Also renamed Lifetime to Duration and ScaredyCat.PanicLength to PanicDuration to match other places.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var crateNode in actorNode.ChildrenMatching("Crate"))
{

View File

@@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "The HarvesterResourceMultiplier trait has been removed, and the RefineryResourceMultiplier trait renamed to ResourceValueMultiplier.";
bool notified;
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
if (actorNode.RemoveNodes("HarvesterResourceModifier") > 0 && !notified)
{

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "The EmbeddedPalette sequence option was replaced with a boolean HasEmbeddedPalette.";
public override IEnumerable<string> UpdateSequenceNode(ModData modData, MiniYamlNode sequenceNode)
public override IEnumerable<string> UpdateSequenceNode(ModData modData, MiniYamlNodeBuilder sequenceNode)
{
foreach (var sequence in sequenceNode.Value.Nodes)
if (sequence.RemoveNodes("EmbeddedPalette") > 0)

View File

@@ -33,7 +33,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
locations.Clear();
}
public override IEnumerable<string> UpdateWeaponNode(ModData modData, MiniYamlNode weaponNode)
public override IEnumerable<string> UpdateWeaponNode(ModData modData, MiniYamlNodeBuilder weaponNode)
{
foreach (var projectileNode in weaponNode.ChildrenMatching("Projectile"))
if (projectileNode.RemoveNodes("ShadowPalette") > 0)
@@ -42,7 +42,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
yield break;
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var node in actorNode.ChildrenMatching("WithShadow"))
if (node.RemoveNodes("Palette") > 0)

View File

@@ -30,7 +30,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
locations.Clear();
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var node in actorNode.ChildrenMatching("WithColoredOverlay"))
if (node.RemoveNodes("Palette") > 0)

View File

@@ -22,7 +22,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
"NukePower used MissileWeapon field for as the name for missile image too.\n" +
"This function has been moved to its own MissileImage field.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var nukePowerNode in actorNode.ChildrenMatching("NukePower"))
{
@@ -30,7 +30,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
if (missileWeaponNode != null)
{
var weapon = missileWeaponNode.NodeValue<string>();
nukePowerNode.AddNode(new MiniYamlNode("MissileImage", weapon));
nukePowerNode.AddNode(new MiniYamlNodeBuilder("MissileImage", weapon));
}
}

View File

@@ -16,7 +16,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
{
public class UnhardcodeBaseBuilderBotModule : UpdateRule, IBeforeUpdateActors
{
MiniYamlNode defences;
MiniYamlNodeBuilder defences;
// Excludes AttackBomber and AttackTDGunboatTurreted as actors with these AttackBase traits aren't supposed to be controlled.
readonly string[] attackBase = { "AttackLeap", "AttackPopupTurreted", "AttackAircraft", "AttackTesla", "AttackCharges", "AttackFollow", "AttackTurreted", "AttackFrontal", "AttackGarrisoned", "AttackOmni", "AttackSwallow" };
@@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "DefenseTypes were added.";
public IEnumerable<string> BeforeUpdateActors(ModData modData, List<MiniYamlNode> resolvedActors)
public IEnumerable<string> BeforeUpdateActors(ModData modData, List<MiniYamlNodeBuilder> resolvedActors)
{
var defences = new List<string>();
@@ -70,7 +70,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
}
}
this.defences = new MiniYamlNode("DefenseTypes", FieldSaver.FormatValue(defences));
this.defences = new MiniYamlNodeBuilder("DefenseTypes", FieldSaver.FormatValue(defences));
yield break;
}
@@ -83,7 +83,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
anyAdded = false;
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var squadManager in actorNode.ChildrenMatching("BaseBuilderBotModule", includeRemovals: false))
{

View File

@@ -16,7 +16,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
{
public class UnhardcodeSquadManager : UpdateRule, IBeforeUpdateActors
{
readonly List<MiniYamlNode> addNodes = new();
readonly List<MiniYamlNodeBuilder> addNodes = new();
// Excludes AttackBomber and AttackTDGunboatTurreted as actors with these AttackBase traits aren't supposed to be controlled.
readonly string[] attackBase = { "AttackLeap", "AttackPopupTurreted", "AttackAircraft", "AttackTesla", "AttackCharges", "AttackFollow", "AttackTurreted", "AttackFrontal", "AttackGarrisoned", "AttackOmni", "AttackSwallow" };
@@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "AirUnitsTypes and ProtectionTypes were added.";
public IEnumerable<string> BeforeUpdateActors(ModData modData, List<MiniYamlNode> resolvedActors)
public IEnumerable<string> BeforeUpdateActors(ModData modData, List<MiniYamlNodeBuilder> resolvedActors)
{
var aircraft = new List<string>();
var vips = new List<string>();
@@ -106,15 +106,15 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
}
}
addNodes.Add(new MiniYamlNode("AirUnitsTypes", FieldSaver.FormatValue(aircraft)));
addNodes.Add(new MiniYamlNode("ProtectionTypes", FieldSaver.FormatValue(vips)));
addNodes.Add(new MiniYamlNodeBuilder("AirUnitsTypes", FieldSaver.FormatValue(aircraft)));
addNodes.Add(new MiniYamlNodeBuilder("ProtectionTypes", FieldSaver.FormatValue(vips)));
yield break;
}
bool anyAdded = false;
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var squadManager in actorNode.ChildrenMatching("SquadManagerBotModule", includeRemovals: false))
{

View File

@@ -32,12 +32,12 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
locations.Clear();
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var veteranProductionIconOverlay in actorNode.ChildrenMatching("VeteranProductionIconOverlay"))
{
veteranProductionIconOverlay.RenameKey("ProductionIconOverlayManager");
veteranProductionIconOverlay.AddNode(new MiniYamlNode("Type", "Veterancy"));
veteranProductionIconOverlay.AddNode(new MiniYamlNodeBuilder("Type", "Veterancy"));
}
foreach (var producibleWithLevel in actorNode.ChildrenMatching("ProducibleWithLevel"))

View File

@@ -23,7 +23,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
"PowerManager.AdviceInterval and PlayerResources.InsufficientFundsNotificationDelay were using ticks.\n" +
"Converted all of those to use real milliseconds instead.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var announce in actorNode.ChildrenMatching("AnnounceOnKill"))
{

View File

@@ -21,7 +21,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description =>
"Each preset color can now have their brightness specified. SimilarityThreshold range was changed.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
var manager = actorNode.LastChildMatching("ColorPickerManager");
if (manager == null)

View File

@@ -26,18 +26,18 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
"Tileset specific overrides can be defined as children of the TilesetFilenames field.";
string defaultSpriteExtension = ".shp";
List<MiniYamlNode> resolvedImagesNodes;
List<MiniYamlNodeBuilder> resolvedImagesNodes;
readonly Dictionary<string, string> tilesetExtensions = new();
readonly Dictionary<string, string> tilesetCodes = new();
bool parseModYaml = true;
bool reportModYamlChanges;
bool disabled;
public IEnumerable<string> BeforeUpdateSequences(ModData modData, List<MiniYamlNode> resolvedImagesNodes)
public IEnumerable<string> BeforeUpdateSequences(ModData modData, List<MiniYamlNodeBuilder> resolvedImagesNodes)
{
// Keep a resolved copy of the sequences so we can account for values imported through inheritance or Defaults.
// This will be modified during processing, so take a deep copy to avoid side-effects on other update rules.
this.resolvedImagesNodes = MiniYaml.FromString(resolvedImagesNodes.WriteToString());
this.resolvedImagesNodes = MiniYaml.FromString(resolvedImagesNodes.WriteToString()).Select(n => new MiniYamlNodeBuilder(n)).ToList();
var requiredMetadata = new HashSet<string>();
foreach (var imageNode in resolvedImagesNodes)
@@ -84,7 +84,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
yield break;
}
var spriteSequenceFormatNode = new MiniYamlNode("", spriteSequenceFormatYaml);
var spriteSequenceFormatNode = new MiniYamlNodeBuilder("", new MiniYamlBuilder(spriteSequenceFormatYaml));
var defaultSpriteExtensionNode = spriteSequenceFormatNode.LastChildMatching("DefaultSpriteExtension");
if (defaultSpriteExtensionNode != null)
{
@@ -121,7 +121,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
reportModYamlChanges = false;
}
public override IEnumerable<string> UpdateSequenceNode(ModData modData, MiniYamlNode imageNode)
public override IEnumerable<string> UpdateSequenceNode(ModData modData, MiniYamlNodeBuilder imageNode)
{
if (disabled)
yield break;
@@ -154,7 +154,11 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
if (resolvedSequenceNode == resolvedDefaultsNode)
continue;
resolvedSequenceNode.Value.Nodes = MiniYaml.Merge(new[] { resolvedDefaultsNode.Value.Nodes, resolvedSequenceNode.Value.Nodes });
resolvedSequenceNode.Value.Nodes = MiniYaml.Merge(new[]
{
resolvedDefaultsNode.Value.Nodes.Select(n => n.Build()).ToArray(),
resolvedSequenceNode.Value.Nodes.Select(n => n.Build()).ToArray()
}).Select(n => new MiniYamlNodeBuilder(n)).ToList();
resolvedSequenceNode.Value.Value ??= resolvedDefaultsNode.Value.Value;
}
}
@@ -180,8 +184,8 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
}
// Identify a suitable default for deduplication
MiniYamlNode defaultFilenameNode = null;
MiniYamlNode defaultTilesetFilenamesNode = null;
MiniYamlNodeBuilder defaultFilenameNode = null;
MiniYamlNodeBuilder defaultTilesetFilenamesNode = null;
foreach (var defaultsNode in imageNode.ChildrenMatching("Defaults"))
{
defaultFilenameNode = defaultsNode.LastChildMatching("Filename") ?? defaultFilenameNode;
@@ -222,12 +226,12 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
var defaultsNode = imageNode.LastChildMatching("Defaults");
if (defaultsNode == null)
{
defaultsNode = new MiniYamlNode("Defaults", "");
defaultsNode = new MiniYamlNodeBuilder("Defaults", "");
imageNode.Value.Nodes.Insert(inheritsNodeIndex, defaultsNode);
}
var nodes = MiniYaml.FromString(duplicateTilesetCount.First(kv => kv.Value == maxDuplicateTilesetCount).Key);
defaultTilesetFilenamesNode = new MiniYamlNode("TilesetFilenames", "", nodes);
defaultTilesetFilenamesNode = new MiniYamlNodeBuilder("TilesetFilenames", "", nodes);
defaultsNode.Value.Nodes.Insert(0, defaultTilesetFilenamesNode);
}
@@ -237,11 +241,11 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
var defaultsNode = imageNode.LastChildMatching("Defaults");
if (defaultsNode == null)
{
defaultsNode = new MiniYamlNode("Defaults", "");
defaultsNode = new MiniYamlNodeBuilder("Defaults", "");
imageNode.Value.Nodes.Insert(inheritsNodeIndex, defaultsNode);
}
defaultFilenameNode = new MiniYamlNode("Filename", duplicateCount.First(kv => kv.Value == maxDuplicateCount).Key);
defaultFilenameNode = new MiniYamlNodeBuilder("Filename", duplicateCount.First(kv => kv.Value == maxDuplicateCount).Key);
defaultsNode.Value.Nodes.Insert(0, defaultFilenameNode);
}
}
@@ -257,15 +261,15 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
var tilesetFilenamesNode = sequenceNode.LastChildMatching("TilesetFilenames");
if (defaultTilesetFilenamesNode != null && combineNode != null)
sequenceNode.Value.Nodes.Insert(0, new MiniYamlNode("TilesetFilenames", ""));
sequenceNode.Value.Nodes.Insert(0, new MiniYamlNodeBuilder("TilesetFilenames", ""));
if (defaultFilenameNode != null && combineNode != null)
sequenceNode.Value.Nodes.Insert(0, new MiniYamlNode("Filename", ""));
sequenceNode.Value.Nodes.Insert(0, new MiniYamlNodeBuilder("Filename", ""));
if (defaultTilesetFilenamesNode != null && tilesetFilenamesNode == null && filenameNode != null)
{
var index = sequenceNode.Value.Nodes.IndexOf(filenameNode) + 1;
sequenceNode.Value.Nodes.Insert(index, new MiniYamlNode("TilesetFilenames", ""));
sequenceNode.Value.Nodes.Insert(index, new MiniYamlNodeBuilder("TilesetFilenames", ""));
}
// Remove redundant overrides
@@ -334,7 +338,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
imageNode.RemoveNode(sequenceNode);
}
void ProcessNode(ModData modData, MiniYamlNode sequenceNode, MiniYamlNode resolvedSequenceNode, string imageName)
void ProcessNode(ModData modData, MiniYamlNodeBuilder sequenceNode, MiniYamlNodeBuilder resolvedSequenceNode, string imageName)
{
// "Filename" was introduced with this update rule, so that means this node was already processed and can be skipped
if (sequenceNode.LastChildMatching("Filename") != null)
@@ -390,7 +394,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
if (useTilesetExtension || useTilesetCode)
{
var tilesetFilenamesNode = new MiniYamlNode("TilesetFilenames", "");
var tilesetFilenamesNode = new MiniYamlNodeBuilder("TilesetFilenames", "");
var duplicateCount = new Dictionary<string, int>();
foreach (var tileset in modData.DefaultTerrainInfo.Keys)
{
@@ -415,7 +419,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
var maxDuplicateCount = duplicateCount.MaxByOrDefault(kv => kv.Value).Value;
if (maxDuplicateCount > 1)
{
var filenameNode = new MiniYamlNode("Filename", duplicateCount.First(kv => kv.Value == maxDuplicateCount).Key);
var filenameNode = new MiniYamlNodeBuilder("Filename", duplicateCount.First(kv => kv.Value == maxDuplicateCount).Key);
foreach (var overrideNode in tilesetFilenamesNode.Value.Nodes.ToList())
if (overrideNode.Value.Value == filenameNode.Value.Value)
tilesetFilenamesNode.Value.Nodes.Remove(overrideNode);
@@ -431,7 +435,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
if (addExtension)
filename += defaultSpriteExtension;
sequenceNode.Value.Nodes.Insert(0, new MiniYamlNode("Filename", filename));
sequenceNode.Value.Nodes.Insert(0, new MiniYamlNodeBuilder("Filename", filename));
}
sequenceNode.ReplaceValue("");

View File

@@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description =>
"Change the field name from Button to TabButton and add ArrowButton, if Button field was set.";
public override IEnumerable<string> UpdateChromeNode(ModData modData, MiniYamlNode chromeNode)
public override IEnumerable<string> UpdateChromeNode(ModData modData, MiniYamlNodeBuilder chromeNode)
{
if (!chromeNode.KeyMatches("ProductionTabs"))
yield break;
@@ -33,7 +33,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
}
if (buttonCollection != null)
chromeNode.AddNode(new MiniYamlNode("ArrowButton", buttonCollection));
chromeNode.AddNode(new MiniYamlNodeBuilder("ArrowButton", buttonCollection));
}
}
}

View File

@@ -32,7 +32,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
locations.Clear();
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
var removed = false;
foreach (var node in actorNode.ChildrenMatching("Infiltrates"))

View File

@@ -21,9 +21,9 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "Negative sequence length is no longer allowed, define individual frames in reverse instead.";
List<MiniYamlNode> resolvedImagesNodes;
List<MiniYamlNodeBuilder> resolvedImagesNodes;
public IEnumerable<string> BeforeUpdateSequences(ModData modData, List<MiniYamlNode> resolvedImagesNodes)
public IEnumerable<string> BeforeUpdateSequences(ModData modData, List<MiniYamlNodeBuilder> resolvedImagesNodes)
{
this.resolvedImagesNodes = resolvedImagesNodes;
yield break;
@@ -31,12 +31,12 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
readonly Queue<Action> actionQueue = new();
static MiniYamlNode GetNode(string key, MiniYamlNode node, MiniYamlNode defaultNode)
static MiniYamlNodeBuilder GetNode(string key, MiniYamlNodeBuilder node, MiniYamlNodeBuilder defaultNode)
{
return node.LastChildMatching(key, includeRemovals: false) ?? defaultNode?.LastChildMatching(key, includeRemovals: false);
}
public override IEnumerable<string> UpdateSequenceNode(ModData modData, MiniYamlNode sequenceNode)
public override IEnumerable<string> UpdateSequenceNode(ModData modData, MiniYamlNodeBuilder sequenceNode)
{
var defaultNode = sequenceNode.LastChildMatching("Defaults");
var defaultLengthNode = defaultNode == null ? null : GetNode("Length", defaultNode, null);

View File

@@ -33,7 +33,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
locations.Clear();
}
public override IEnumerable<string> UpdateSequenceNode(ModData modData, MiniYamlNode imageNode)
public override IEnumerable<string> UpdateSequenceNode(ModData modData, MiniYamlNodeBuilder imageNode)
{
foreach (var sequenceNode in imageNode.Value.Nodes)
sequenceNode.RemoveNodes("HasEmbeddedPalette");
@@ -41,7 +41,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
yield break;
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var traitNode in actorNode.ChildrenMatching("PaletteFromEmbeddedSpritePalette"))
{

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "TiberianSunRefinery was removed, use Refinery instead.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
actorNode.RenameChildrenMatching("TiberianSunRefinery", "Refinery");

View File

@@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "Rename contrail `TrailWidth` to `StartWidth` in traits and weapons to acount for added `EndWidth` functionality";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var traitNode in actorNode.ChildrenMatching("Contrail"))
traitNode.RenameChildrenMatching("TrailWidth", "StartWidth");
@@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
yield break;
}
public override IEnumerable<string> UpdateWeaponNode(ModData modData, MiniYamlNode weaponNode)
public override IEnumerable<string> UpdateWeaponNode(ModData modData, MiniYamlNodeBuilder weaponNode)
{
foreach (var traitNode in weaponNode.ChildrenMatching("Projectile").Where(n => n.Value.Value == "Missile"))
traitNode.RenameChildrenMatching("ContrailWidth", "ContrailStartWidth");

View File

@@ -21,7 +21,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
"'EngineerRepair' was renamed to 'InstantlyRepairs' " +
"and 'EngineerRepairable' to 'InstantlyRepairable'.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
actorNode.RenameChildrenMatching("EngineerRepair", "InstantlyRepairs");
actorNode.RenameChildrenMatching("EngineerRepairable", "InstantlyRepairable");

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description => "The 'GiveMcvCrateAction' has been renamed to 'GiveBaseBuilderCrateAction'.";
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
foreach (var node in actorNode.ChildrenMatching("GiveMcvCrateAction"))
node.RenameKey("GiveBaseBuilderCrateAction");

View File

@@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
public override string Description =>
"Change the field name from RemoveTime to DisplayDurationMs and convert the value from ticks to milliseconds";
public override IEnumerable<string> UpdateChromeNode(ModData modData, MiniYamlNode chromeNode)
public override IEnumerable<string> UpdateChromeNode(ModData modData, MiniYamlNodeBuilder chromeNode)
{
if (!chromeNode.KeyMatches("TextNotificationsDisplay"))
yield break;

View File

@@ -58,7 +58,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
yield break;
}
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode)
{
if (complete || actorNode.LastChildMatching("IsometricSelectable") != null)
yield break;
@@ -70,7 +70,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
if (height == 24)
yield break;
var selection = new MiniYamlNode("IsometricSelectable", "");
var selection = new MiniYamlNodeBuilder("IsometricSelectable", "");
selection.AddNode("Height", FieldSaver.FormatValue(height));
actorNode.AddNode(selection);

View File

@@ -20,19 +20,19 @@ namespace OpenRA.Mods.Common.UpdateRules
/// <summary>Defines a transformation that is run on each top-level node in a yaml file set.</summary>
/// <returns>An enumerable of manual steps to be run by the user.</returns>
public delegate IEnumerable<string> TopLevelNodeTransform(ModData modData, MiniYamlNode node);
public delegate IEnumerable<string> TopLevelNodeTransform(ModData modData, MiniYamlNodeBuilder node);
/// <summary>Defines a transformation that is run on each widget node in a chrome yaml file set.</summary>
/// <returns>An enumerable of manual steps to be run by the user.</returns>
public delegate IEnumerable<string> ChromeNodeTransform(ModData modData, MiniYamlNode widgetNode);
public delegate IEnumerable<string> ChromeNodeTransform(ModData modData, MiniYamlNodeBuilder widgetNode);
public virtual IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode) { yield break; }
public virtual IEnumerable<string> UpdateWeaponNode(ModData modData, MiniYamlNode weaponNode) { yield break; }
public virtual IEnumerable<string> UpdateSequenceNode(ModData modData, MiniYamlNode sequenceNode) { yield break; }
public virtual IEnumerable<string> UpdateChromeNode(ModData modData, MiniYamlNode chromeNode) { yield break; }
public virtual IEnumerable<string> UpdateTilesetNode(ModData modData, MiniYamlNode tilesetNode) { yield break; }
public virtual IEnumerable<string> UpdateChromeProviderNode(ModData modData, MiniYamlNode chromeProviderNode) { yield break; }
public virtual IEnumerable<string> UpdateMapActorNode(ModData modData, MiniYamlNode actorNode) { yield break; }
public virtual IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode) { yield break; }
public virtual IEnumerable<string> UpdateWeaponNode(ModData modData, MiniYamlNodeBuilder weaponNode) { yield break; }
public virtual IEnumerable<string> UpdateSequenceNode(ModData modData, MiniYamlNodeBuilder sequenceNode) { yield break; }
public virtual IEnumerable<string> UpdateChromeNode(ModData modData, MiniYamlNodeBuilder chromeNode) { yield break; }
public virtual IEnumerable<string> UpdateTilesetNode(ModData modData, MiniYamlNodeBuilder tilesetNode) { yield break; }
public virtual IEnumerable<string> UpdateChromeProviderNode(ModData modData, MiniYamlNodeBuilder chromeProviderNode) { yield break; }
public virtual IEnumerable<string> UpdateMapActorNode(ModData modData, MiniYamlNodeBuilder actorNode) { yield break; }
public virtual IEnumerable<string> BeforeUpdate(ModData modData) { yield break; }
public virtual IEnumerable<string> AfterUpdate(ModData modData) { yield break; }
@@ -41,16 +41,16 @@ namespace OpenRA.Mods.Common.UpdateRules
// These aren't part of the UpdateRule class as to avoid premature yaml merge crashes when updating maps.
public interface IBeforeUpdateActors
{
IEnumerable<string> BeforeUpdateActors(ModData modData, List<MiniYamlNode> resolvedActors) { yield break; }
IEnumerable<string> BeforeUpdateActors(ModData modData, List<MiniYamlNodeBuilder> resolvedActors) { yield break; }
}
public interface IBeforeUpdateWeapons
{
IEnumerable<string> BeforeUpdateWeapons(ModData modData, List<MiniYamlNode> resolvedWeapons) { yield break; }
IEnumerable<string> BeforeUpdateWeapons(ModData modData, List<MiniYamlNodeBuilder> resolvedWeapons) { yield break; }
}
public interface IBeforeUpdateSequences
{
IEnumerable<string> BeforeUpdateSequences(ModData modData, List<MiniYamlNode> resolvedImages) { yield break; }
IEnumerable<string> BeforeUpdateSequences(ModData modData, List<MiniYamlNodeBuilder> resolvedImages) { yield break; }
}
}

View File

@@ -17,7 +17,7 @@ using OpenRA.FileSystem;
namespace OpenRA.Mods.Common.UpdateRules
{
using YamlFileSet = List<(IReadWritePackage, string, List<MiniYamlNode>)>;
using YamlFileSet = List<(IReadWritePackage, string, List<MiniYamlNodeBuilder>)>;
public static class UpdateUtils
{
@@ -35,7 +35,7 @@ namespace OpenRA.Mods.Common.UpdateRules
continue;
}
yaml.Add(((IReadWritePackage)package, name, MiniYaml.FromStream(package.GetStream(name), name, false)));
yaml.Add(((IReadWritePackage)package, name, MiniYaml.FromStream(package.GetStream(name), name, false).Select(n => new MiniYamlNodeBuilder(n)).ToList()));
}
return yaml;
@@ -44,7 +44,7 @@ namespace OpenRA.Mods.Common.UpdateRules
/// <summary>
/// Loads a YamlFileSet containing any external yaml definitions referenced by a map yaml block.
/// </summary>
static YamlFileSet LoadExternalMapYaml(ModData modData, MiniYaml yaml, HashSet<string> externalFilenames)
static YamlFileSet LoadExternalMapYaml(ModData modData, MiniYamlBuilder yaml, HashSet<string> externalFilenames)
{
return FieldLoader.GetValue<string[]>("value", yaml.Value)
.Where(f => f.Contains('|'))
@@ -56,7 +56,7 @@ namespace OpenRA.Mods.Common.UpdateRules
/// Loads a YamlFileSet containing any internal definitions yaml referenced by a map yaml block.
/// External references or internal references to missing files are ignored.
/// </summary>
static YamlFileSet LoadInternalMapYaml(ModData modData, IReadWritePackage mapPackage, MiniYaml yaml, HashSet<string> externalFilenames)
static YamlFileSet LoadInternalMapYaml(ModData modData, IReadWritePackage mapPackage, MiniYamlBuilder yaml, HashSet<string> externalFilenames)
{
var fileSet = new YamlFileSet()
{
@@ -68,7 +68,7 @@ namespace OpenRA.Mods.Common.UpdateRules
{
// Ignore any files that aren't in the map bundle
if (!filename.Contains('|') && mapPackage.Contains(filename))
fileSet.Add((mapPackage, filename, MiniYaml.FromStream(mapPackage.GetStream(filename), filename, false)));
fileSet.Add((mapPackage, filename, MiniYaml.FromStream(mapPackage.GetStream(filename), filename, false).Select(n => new MiniYamlNodeBuilder(n)).ToList()));
else if (modData.ModFiles.Exists(filename))
externalFilenames.Add(filename);
}
@@ -94,7 +94,7 @@ namespace OpenRA.Mods.Common.UpdateRules
return manualSteps;
}
var yaml = new MiniYaml(null, MiniYaml.FromStream(mapStream, mapPackage.Name, false));
var yaml = new MiniYamlBuilder(null, MiniYaml.FromStream(mapStream, mapPackage.Name, false));
files = new YamlFileSet() { (mapPackage, "map.yaml", yaml.Nodes) };
manualSteps.AddRange(rule.BeforeUpdate(modData));
@@ -159,7 +159,7 @@ namespace OpenRA.Mods.Common.UpdateRules
return manualSteps;
}
public static List<MiniYamlNode> LoadMapYaml(IReadOnlyFileSystem fileSystem, IReadOnlyPackage mapPackage, IEnumerable<string> files, MiniYaml mapNode)
public static List<MiniYamlNodeBuilder> LoadMapYaml(IReadOnlyFileSystem fileSystem, IReadOnlyPackage mapPackage, IEnumerable<string> files, MiniYamlBuilder mapNode)
{
var yaml = files.Select(s => MiniYaml.FromStream(fileSystem.Open(s), s)).ToList();
@@ -177,9 +177,9 @@ namespace OpenRA.Mods.Common.UpdateRules
}
if (mapNode != null && mapNode.Nodes.Count > 0)
yaml.Add(mapNode.Nodes);
yaml.Add(mapNode.Nodes.Select(n => n.Build()).ToList());
return MiniYaml.Merge(yaml);
return MiniYaml.Merge(yaml).Select(n => new MiniYamlNodeBuilder(n)).ToList();
}
static IEnumerable<string> FilterExternalModFiles(ModData modData, IEnumerable<string> files, HashSet<string> externalFilenames)
@@ -215,7 +215,7 @@ namespace OpenRA.Mods.Common.UpdateRules
if (mapStream == null)
continue;
var yaml = new MiniYaml(null, MiniYaml.FromStream(mapStream, package.Name, false));
var yaml = new MiniYamlBuilder(new MiniYaml(null, MiniYaml.FromStream(mapStream, package.Name, false)));
var mapRulesNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Rules");
if (mapRulesNode != null)
foreach (var f in LoadExternalMapYaml(modData, mapRulesNode.Value, externalFilenames))
@@ -240,7 +240,8 @@ namespace OpenRA.Mods.Common.UpdateRules
if (rule is IBeforeUpdateActors beforeActors)
{
var resolvedActors = MiniYaml.Load(modData.DefaultFileSystem, modData.Manifest.Rules, null);
var resolvedActors = MiniYaml.Load(modData.DefaultFileSystem, modData.Manifest.Rules, null)
.Select(n => new MiniYamlNodeBuilder(n)).ToList();
manualSteps.AddRange(beforeActors.BeforeUpdateActors(modData, resolvedActors));
}
@@ -248,7 +249,8 @@ namespace OpenRA.Mods.Common.UpdateRules
if (rule is IBeforeUpdateWeapons beforeWeapons)
{
var resolvedWeapons = MiniYaml.Load(modData.DefaultFileSystem, modData.Manifest.Weapons, null);
var resolvedWeapons = MiniYaml.Load(modData.DefaultFileSystem, modData.Manifest.Weapons, null)
.Select(n => new MiniYamlNodeBuilder(n)).ToList();
manualSteps.AddRange(beforeWeapons.BeforeUpdateWeapons(modData, resolvedWeapons));
}
@@ -256,7 +258,8 @@ namespace OpenRA.Mods.Common.UpdateRules
if (rule is IBeforeUpdateSequences beforeSequences)
{
var resolvedImages = MiniYaml.Load(modData.DefaultFileSystem, modData.Manifest.Sequences, null);
var resolvedImages = MiniYaml.Load(modData.DefaultFileSystem, modData.Manifest.Sequences, null)
.Select(n => new MiniYamlNodeBuilder(n)).ToList();
manualSteps.AddRange(beforeSequences.BeforeUpdateSequences(modData, resolvedImages));
}
@@ -277,7 +280,7 @@ namespace OpenRA.Mods.Common.UpdateRules
return manualSteps;
}
static IEnumerable<string> ApplyChromeTransformInner(ModData modData, MiniYamlNode current, UpdateRule.ChromeNodeTransform transform)
static IEnumerable<string> ApplyChromeTransformInner(ModData modData, MiniYamlNodeBuilder current, UpdateRule.ChromeNodeTransform transform)
{
foreach (var manualStep in transform(modData, current))
yield return manualStep;
@@ -337,13 +340,13 @@ namespace OpenRA.Mods.Common.UpdateRules
}
/// <summary>Checks if node is a removal (has '-' prefix).</summary>
public static bool IsRemoval(this MiniYamlNode node)
public static bool IsRemoval(this MiniYamlNodeBuilder node)
{
return node.Key[0].ToString() == "-";
}
/// <summary>Renames a yaml key preserving any @suffix.</summary>
public static void RenameKey(this MiniYamlNode node, string newKey, bool preserveSuffix = true, bool includeRemovals = true)
public static void RenameKey(this MiniYamlNodeBuilder node, string newKey, bool preserveSuffix = true, bool includeRemovals = true)
{
var prefix = includeRemovals && node.IsRemoval() ? "-" : "";
var split = node.Key.IndexOf("@", StringComparison.Ordinal);
@@ -353,52 +356,52 @@ namespace OpenRA.Mods.Common.UpdateRules
node.Key = prefix + newKey;
}
public static T NodeValue<T>(this MiniYamlNode node)
public static T NodeValue<T>(this MiniYamlNodeBuilder node)
{
return FieldLoader.GetValue<T>(node.Key, node.Value.Value);
}
public static void ReplaceValue(this MiniYamlNode node, string value)
public static void ReplaceValue(this MiniYamlNodeBuilder node, string value)
{
node.Value.Value = value;
}
public static void AddNode(this MiniYamlNode node, string key, object value)
public static void AddNode(this MiniYamlNodeBuilder node, string key, object value)
{
node.Value.Nodes.Add(new MiniYamlNode(key, FieldSaver.FormatValue(value)));
node.Value.Nodes.Add(new MiniYamlNodeBuilder(key, FieldSaver.FormatValue(value)));
}
public static void AddNode(this MiniYamlNode node, MiniYamlNode toAdd)
public static void AddNode(this MiniYamlNodeBuilder node, MiniYamlNodeBuilder toAdd)
{
node.Value.Nodes.Add(toAdd);
}
public static void RemoveNode(this MiniYamlNode node, MiniYamlNode toRemove)
public static void RemoveNode(this MiniYamlNodeBuilder node, MiniYamlNodeBuilder toRemove)
{
node.Value.Nodes.Remove(toRemove);
}
public static void MoveNode(this MiniYamlNode node, MiniYamlNode fromNode, MiniYamlNode toNode)
public static void MoveNode(this MiniYamlNodeBuilder node, MiniYamlNodeBuilder fromNode, MiniYamlNodeBuilder toNode)
{
toNode.Value.Nodes.Add(node);
fromNode.Value.Nodes.Remove(node);
}
public static void MoveAndRenameNode(this MiniYamlNode node,
MiniYamlNode fromNode, MiniYamlNode toNode, string newKey, bool preserveSuffix = true, bool includeRemovals = true)
public static void MoveAndRenameNode(this MiniYamlNodeBuilder node,
MiniYamlNodeBuilder fromNode, MiniYamlNodeBuilder toNode, string newKey, bool preserveSuffix = true, bool includeRemovals = true)
{
node.RenameKey(newKey, preserveSuffix, includeRemovals);
node.MoveNode(fromNode, toNode);
}
/// <summary>Removes children with keys equal to [match] or [match]@[arbitrary suffix].</summary>
public static int RemoveNodes(this MiniYamlNode node, string match, bool ignoreSuffix = true, bool includeRemovals = true)
public static int RemoveNodes(this MiniYamlNodeBuilder node, string match, bool ignoreSuffix = true, bool includeRemovals = true)
{
return node.Value.Nodes.RemoveAll(n => n.KeyMatches(match, ignoreSuffix, includeRemovals));
}
/// <summary>Returns true if the node is of the form [match] or [match]@[arbitrary suffix].</summary>
public static bool KeyMatches(this MiniYamlNode node, string match, bool ignoreSuffix = true, bool includeRemovals = true)
public static bool KeyMatches(this MiniYamlNodeBuilder node, string match, bool ignoreSuffix = true, bool includeRemovals = true)
{
if (node.Key == null)
return false;
@@ -416,7 +419,7 @@ namespace OpenRA.Mods.Common.UpdateRules
}
/// <summary>Returns true if the node is of the form [match], [match]@[arbitrary suffix] or [arbitrary suffix]@[match].</summary>
public static bool KeyContains(this MiniYamlNode node, string match, bool ignoreSuffix = true, bool includeRemovals = true)
public static bool KeyContains(this MiniYamlNodeBuilder node, string match, bool ignoreSuffix = true, bool includeRemovals = true)
{
if (node.Key == null)
return false;
@@ -431,23 +434,23 @@ namespace OpenRA.Mods.Common.UpdateRules
}
/// <summary>Returns children with keys equal to [match] or [match]@[arbitrary suffix].</summary>
public static IEnumerable<MiniYamlNode> ChildrenMatching(this MiniYamlNode node, string match, bool ignoreSuffix = true, bool includeRemovals = true)
public static IEnumerable<MiniYamlNodeBuilder> ChildrenMatching(this MiniYamlNodeBuilder node, string match, bool ignoreSuffix = true, bool includeRemovals = true)
{
return node.Value.Nodes.Where(n => n.KeyMatches(match, ignoreSuffix, includeRemovals));
}
/// <summary>Returns children whose keys contain 'match' (optionally in the suffix).</summary>
public static IEnumerable<MiniYamlNode> ChildrenContaining(this MiniYamlNode node, string match, bool ignoreSuffix = true, bool includeRemovals = true)
public static IEnumerable<MiniYamlNodeBuilder> ChildrenContaining(this MiniYamlNodeBuilder node, string match, bool ignoreSuffix = true, bool includeRemovals = true)
{
return node.Value.Nodes.Where(n => n.KeyContains(match, ignoreSuffix, includeRemovals));
}
public static MiniYamlNode LastChildMatching(this MiniYamlNode node, string match, bool includeRemovals = true)
public static MiniYamlNodeBuilder LastChildMatching(this MiniYamlNodeBuilder node, string match, bool includeRemovals = true)
{
return node.ChildrenMatching(match, includeRemovals: includeRemovals).LastOrDefault();
}
public static void RenameChildrenMatching(this MiniYamlNode node, string match, string newKey, bool preserveSuffix = true, bool includeRemovals = true)
public static void RenameChildrenMatching(this MiniYamlNodeBuilder node, string match, string newKey, bool preserveSuffix = true, bool includeRemovals = true)
{
var matching = node.ChildrenMatching(match);
foreach (var m in matching)

View File

@@ -11,6 +11,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.FileSystem;
namespace OpenRA.Mods.Common.UtilityCommands
@@ -68,8 +69,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
}
}
foreach (var kv in forRemoval)
map.ActorDefinitions.Remove(kv);
map.ActorDefinitions = map.ActorDefinitions.Except(forRemoval).ToArray();
map.Save((IReadWritePackage)map.Package);
}

View File

@@ -18,7 +18,7 @@ using OpenRA.Mods.Common.UpdateRules;
namespace OpenRA.Mods.Common.UtilityCommands
{
using YamlFileSet = List<(IReadWritePackage, string, List<MiniYamlNode>)>;
using YamlFileSet = List<(IReadWritePackage, string, List<MiniYamlNodeBuilder>)>;
sealed class UpdateModCommand : IUtilityCommand
{

View File

@@ -78,7 +78,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
[ObjectCreator.UseCtor]
public SaveMapLogic(Widget widget, ModData modData, Map map, Action<string> onSave, Action onExit,
World world, List<MiniYamlNode> playerDefinitions, List<MiniYamlNode> actorDefinitions)
World world, IReadOnlyCollection<MiniYamlNode> playerDefinitions, IReadOnlyCollection<MiniYamlNode> actorDefinitions)
{
var title = widget.Get<TextFieldWidget>("TITLE");
title.Text = map.Title;

View File

@@ -486,7 +486,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (string.IsNullOrEmpty(bl.Data))
continue;
var game = MiniYaml.FromString(bl.Data)[0].Value;
var game = new MiniYamlBuilder(MiniYaml.FromString(bl.Data)[0].Value);
var idNode = game.Nodes.FirstOrDefault(n => n.Key == "Id");
// Skip beacons created by this instance and replace Id by expected int value
@@ -499,9 +499,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (addressNode != null)
addressNode.Value.Value = bl.Address.ToString().Split(':')[0] + ":" + addressNode.Value.Value.Split(':')[1];
game.Nodes.Add(new MiniYamlNode("Location", "Local Network"));
game.Nodes.Add(new MiniYamlNodeBuilder("Location", "Local Network"));
lanGames.Add(new GameServer(game));
lanGames.Add(new GameServer(game.Build()));
}
}
catch