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:
@@ -122,7 +122,7 @@ namespace OpenRA
|
||||
return;
|
||||
|
||||
var key = ExternalMod.MakeKey(mod);
|
||||
var yaml = new MiniYamlNode("Registration", new MiniYaml("", new List<MiniYamlNode>()
|
||||
var yaml = new MiniYamlNode("Registration", new MiniYaml("", new[]
|
||||
{
|
||||
new MiniYamlNode("Id", mod.Id),
|
||||
new MiniYamlNode("Version", mod.Metadata.Version),
|
||||
@@ -131,17 +131,21 @@ namespace OpenRA
|
||||
new MiniYamlNode("LaunchArgs", new[] { "Game.Mod=" + mod.Id }.Concat(launchArgs).JoinWith(", "))
|
||||
}));
|
||||
|
||||
var iconNodes = new List<MiniYamlNode>();
|
||||
|
||||
using (var stream = mod.Package.GetStream("icon.png"))
|
||||
if (stream != null)
|
||||
yaml.Value.Nodes.Add(new MiniYamlNode("Icon", Convert.ToBase64String(stream.ReadAllBytes())));
|
||||
iconNodes.Add(new MiniYamlNode("Icon", Convert.ToBase64String(stream.ReadAllBytes())));
|
||||
|
||||
using (var stream = mod.Package.GetStream("icon-2x.png"))
|
||||
if (stream != null)
|
||||
yaml.Value.Nodes.Add(new MiniYamlNode("Icon2x", Convert.ToBase64String(stream.ReadAllBytes())));
|
||||
iconNodes.Add(new MiniYamlNode("Icon2x", Convert.ToBase64String(stream.ReadAllBytes())));
|
||||
|
||||
using (var stream = mod.Package.GetStream("icon-3x.png"))
|
||||
if (stream != null)
|
||||
yaml.Value.Nodes.Add(new MiniYamlNode("Icon3x", Convert.ToBase64String(stream.ReadAllBytes())));
|
||||
iconNodes.Add(new MiniYamlNode("Icon3x", Convert.ToBase64String(stream.ReadAllBytes())));
|
||||
|
||||
yaml = yaml.WithValue(yaml.Value.WithNodesAppended(iconNodes));
|
||||
|
||||
var sources = new HashSet<string>();
|
||||
if (registration.HasFlag(ModRegistration.System))
|
||||
|
||||
@@ -500,7 +500,7 @@ namespace OpenRA
|
||||
if (yaml == null)
|
||||
return Activator.CreateInstance(fieldType);
|
||||
|
||||
var dict = Activator.CreateInstance(fieldType, yaml.Nodes.Count);
|
||||
var dict = Activator.CreateInstance(fieldType, yaml.Nodes.Length);
|
||||
var arguments = fieldType.GetGenericArguments();
|
||||
var addMethod = fieldType.GetMethod(nameof(Dictionary<object, object>.Add), arguments);
|
||||
var addArgs = new object[2];
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace OpenRA
|
||||
|
||||
return new MiniYaml(
|
||||
null,
|
||||
fields.Select(info => new MiniYamlNode(info.YamlName, FormatValue(o, info.Field))).ToList());
|
||||
fields.Select(info => new MiniYamlNode(info.YamlName, FormatValue(o, info.Field))));
|
||||
}
|
||||
|
||||
public static MiniYamlNode SaveField(object o, string field)
|
||||
|
||||
@@ -226,10 +226,10 @@ namespace OpenRA
|
||||
|
||||
static bool AnyCustomYaml(MiniYaml yaml)
|
||||
{
|
||||
return yaml != null && (yaml.Value != null || yaml.Nodes.Count > 0);
|
||||
return yaml != null && (yaml.Value != null || yaml.Nodes.Length > 0);
|
||||
}
|
||||
|
||||
static bool AnyFlaggedTraits(ModData modData, List<MiniYamlNode> actors)
|
||||
static bool AnyFlaggedTraits(ModData modData, IEnumerable<MiniYamlNode> actors)
|
||||
{
|
||||
foreach (var actorNode in actors)
|
||||
{
|
||||
|
||||
@@ -139,7 +139,7 @@ namespace OpenRA.GameRules
|
||||
{
|
||||
// Resolve any weapon-level yaml inheritance or removals
|
||||
// HACK: The "Defaults" sequence syntax prevents us from doing this generally during yaml parsing
|
||||
content.Nodes = MiniYaml.Merge(new[] { content.Nodes });
|
||||
content = content.WithNodes(MiniYaml.Merge(new IReadOnlyCollection<MiniYamlNode>[] { content.Nodes }));
|
||||
FieldLoader.Load(this, content);
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace OpenRA
|
||||
|
||||
public MiniYaml Save(Func<ActorInit, bool> initFilter = null)
|
||||
{
|
||||
var ret = new MiniYaml(Type);
|
||||
var nodes = new List<MiniYamlNode>();
|
||||
foreach (var o in initDict.Value)
|
||||
{
|
||||
if (o is not ActorInit init || o is ISuppressInitExport)
|
||||
@@ -98,10 +98,10 @@ namespace OpenRA
|
||||
if (!string.IsNullOrEmpty(init.InstanceName))
|
||||
initName += ActorInfo.TraitInstanceSeparator + init.InstanceName;
|
||||
|
||||
ret.Nodes.Add(new MiniYamlNode(initName, init.Save()));
|
||||
nodes.Add(new MiniYamlNode(initName, init.Save()));
|
||||
}
|
||||
|
||||
return ret;
|
||||
return new MiniYaml(Type, nodes);
|
||||
}
|
||||
|
||||
public IEnumerator<object> GetEnumerator() { return initDict.Value.GetEnumerator(); }
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
@@ -90,11 +91,11 @@ namespace OpenRA
|
||||
throw new InvalidOperationException("Map does not have a field/property " + fieldName);
|
||||
|
||||
var t = field != null ? field.FieldType : property.PropertyType;
|
||||
type = t == typeof(List<MiniYamlNode>) ? Type.NodeList :
|
||||
type = t == typeof(IReadOnlyCollection<MiniYamlNode>) ? Type.NodeList :
|
||||
t == typeof(MiniYaml) ? Type.MiniYaml : Type.Normal;
|
||||
}
|
||||
|
||||
public void Deserialize(Map map, List<MiniYamlNode> nodes)
|
||||
public void Deserialize(Map map, ImmutableArray<MiniYamlNode> nodes)
|
||||
{
|
||||
var node = nodes.FirstOrDefault(n => n.Key == key);
|
||||
if (node == null)
|
||||
@@ -130,14 +131,14 @@ namespace OpenRA
|
||||
var value = field != null ? field.GetValue(map) : property.GetValue(map, null);
|
||||
if (type == Type.NodeList)
|
||||
{
|
||||
var listValue = (List<MiniYamlNode>)value;
|
||||
var listValue = (IReadOnlyCollection<MiniYamlNode>)value;
|
||||
if (required || listValue.Count > 0)
|
||||
nodes.Add(new MiniYamlNode(key, null, listValue));
|
||||
}
|
||||
else if (type == Type.MiniYaml)
|
||||
{
|
||||
var yamlValue = (MiniYaml)value;
|
||||
if (required || (yamlValue != null && (yamlValue.Value != null || yamlValue.Nodes.Count > 0)))
|
||||
if (required || (yamlValue != null && (yamlValue.Value != null || yamlValue.Nodes.Length > 0)))
|
||||
nodes.Add(new MiniYamlNode(key, yamlValue));
|
||||
}
|
||||
else
|
||||
@@ -197,18 +198,18 @@ namespace OpenRA
|
||||
public int2 MapSize { get; private set; }
|
||||
|
||||
// Player and actor yaml. Public for access by the map importers and lint checks.
|
||||
public List<MiniYamlNode> PlayerDefinitions = new();
|
||||
public List<MiniYamlNode> ActorDefinitions = new();
|
||||
public IReadOnlyCollection<MiniYamlNode> PlayerDefinitions = ImmutableArray<MiniYamlNode>.Empty;
|
||||
public IReadOnlyCollection<MiniYamlNode> ActorDefinitions = ImmutableArray<MiniYamlNode>.Empty;
|
||||
|
||||
// Custom map yaml. Public for access by the map importers and lint checks
|
||||
public readonly MiniYaml RuleDefinitions;
|
||||
public readonly MiniYaml TranslationDefinitions;
|
||||
public readonly MiniYaml SequenceDefinitions;
|
||||
public readonly MiniYaml ModelSequenceDefinitions;
|
||||
public readonly MiniYaml WeaponDefinitions;
|
||||
public readonly MiniYaml VoiceDefinitions;
|
||||
public readonly MiniYaml MusicDefinitions;
|
||||
public readonly MiniYaml NotificationDefinitions;
|
||||
public MiniYaml RuleDefinitions;
|
||||
public MiniYaml TranslationDefinitions;
|
||||
public MiniYaml SequenceDefinitions;
|
||||
public MiniYaml ModelSequenceDefinitions;
|
||||
public MiniYaml WeaponDefinitions;
|
||||
public MiniYaml VoiceDefinitions;
|
||||
public MiniYaml MusicDefinitions;
|
||||
public MiniYaml NotificationDefinitions;
|
||||
|
||||
public readonly Dictionary<CPos, TerrainTile> ReplacedInvalidTerrainTiles = new();
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ namespace OpenRA
|
||||
var sources =
|
||||
modDataRules.Select(x => x.Where(IsLoadableRuleDefinition).ToList())
|
||||
.Concat(files.Select(s => MiniYaml.FromStream(fileSystem.Open(s), s).Where(IsLoadableRuleDefinition).ToList()));
|
||||
if (RuleDefinitions.Nodes.Count > 0)
|
||||
if (RuleDefinitions.Nodes.Length > 0)
|
||||
sources = sources.Append(RuleDefinitions.Nodes.Where(IsLoadableRuleDefinition).ToList());
|
||||
|
||||
var yamlNodes = MiniYaml.Merge(sources);
|
||||
|
||||
@@ -20,18 +20,36 @@ namespace OpenRA
|
||||
{
|
||||
public static class MiniYamlExts
|
||||
{
|
||||
public static void WriteToFile(this List<MiniYamlNode> y, string filename)
|
||||
public static void WriteToFile(this IEnumerable<MiniYamlNode> y, string filename)
|
||||
{
|
||||
File.WriteAllLines(filename, y.ToLines().Select(x => x.TrimEnd()).ToArray());
|
||||
}
|
||||
|
||||
public static string WriteToString(this List<MiniYamlNode> y)
|
||||
public static string WriteToString(this IEnumerable<MiniYamlNode> y)
|
||||
{
|
||||
// Remove all trailing newlines and restore the final EOF newline
|
||||
return y.ToLines().JoinWith("\n").TrimEnd('\n') + "\n";
|
||||
}
|
||||
|
||||
public static IEnumerable<string> ToLines(this List<MiniYamlNode> y)
|
||||
public static IEnumerable<string> ToLines(this IEnumerable<MiniYamlNode> y)
|
||||
{
|
||||
foreach (var kv in y)
|
||||
foreach (var line in kv.Value.ToLines(kv.Key, kv.Comment))
|
||||
yield return line;
|
||||
}
|
||||
|
||||
public static void WriteToFile(this IEnumerable<MiniYamlNodeBuilder> y, string filename)
|
||||
{
|
||||
File.WriteAllLines(filename, y.ToLines().Select(x => x.TrimEnd()).ToArray());
|
||||
}
|
||||
|
||||
public static string WriteToString(this IEnumerable<MiniYamlNodeBuilder> y)
|
||||
{
|
||||
// Remove all trailing newlines and restore the final EOF newline
|
||||
return y.ToLines().JoinWith("\n").TrimEnd('\n') + "\n";
|
||||
}
|
||||
|
||||
public static IEnumerable<string> ToLines(this IEnumerable<MiniYamlNodeBuilder> y)
|
||||
{
|
||||
foreach (var kv in y)
|
||||
foreach (var line in kv.Value.ToLines(kv.Key, kv.Comment))
|
||||
@@ -55,10 +73,17 @@ namespace OpenRA
|
||||
public override string ToString() { return $"{Filename}:{Line}"; }
|
||||
}
|
||||
|
||||
public SourceLocation Location;
|
||||
public string Key;
|
||||
public MiniYaml Value;
|
||||
public string Comment;
|
||||
public readonly SourceLocation Location;
|
||||
public readonly string Key;
|
||||
public readonly MiniYaml Value;
|
||||
public readonly string Comment;
|
||||
|
||||
public MiniYamlNode WithValue(MiniYaml value)
|
||||
{
|
||||
if (Value == value)
|
||||
return this;
|
||||
return new MiniYamlNode(Key, value, Comment, Location);
|
||||
}
|
||||
|
||||
public MiniYamlNode(string k, MiniYaml v, string c = null)
|
||||
{
|
||||
@@ -74,26 +99,15 @@ namespace OpenRA
|
||||
}
|
||||
|
||||
public MiniYamlNode(string k, string v, string c = null)
|
||||
: this(k, v, c, null) { }
|
||||
: this(k, new MiniYaml(v, Enumerable.Empty<MiniYamlNode>()), c) { }
|
||||
|
||||
public MiniYamlNode(string k, string v, List<MiniYamlNode> n)
|
||||
public MiniYamlNode(string k, string v, IEnumerable<MiniYamlNode> n)
|
||||
: this(k, new MiniYaml(v, n), null) { }
|
||||
|
||||
public MiniYamlNode(string k, string v, string c, List<MiniYamlNode> n)
|
||||
: this(k, new MiniYaml(v, n), c) { }
|
||||
|
||||
public MiniYamlNode(string k, string v, string c, List<MiniYamlNode> n, SourceLocation loc)
|
||||
: this(k, new MiniYaml(v, n), c, loc) { }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{{YamlNode: {Key} @ {Location}}}";
|
||||
}
|
||||
|
||||
public MiniYamlNode Clone()
|
||||
{
|
||||
return new MiniYamlNode(Key, Value.Clone(), Comment, Location);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MiniYaml
|
||||
@@ -101,15 +115,30 @@ namespace OpenRA
|
||||
const int SpacesPerLevel = 4;
|
||||
static readonly Func<string, string> StringIdentity = s => s;
|
||||
static readonly Func<MiniYaml, MiniYaml> MiniYamlIdentity = my => my;
|
||||
public string Value;
|
||||
public List<MiniYamlNode> Nodes;
|
||||
|
||||
public MiniYaml Clone()
|
||||
public readonly string Value;
|
||||
public readonly ImmutableArray<MiniYamlNode> Nodes;
|
||||
|
||||
public MiniYaml WithValue(string value)
|
||||
{
|
||||
var clonedNodes = new List<MiniYamlNode>(Nodes.Count);
|
||||
foreach (var node in Nodes)
|
||||
clonedNodes.Add(node.Clone());
|
||||
return new MiniYaml(Value, clonedNodes);
|
||||
if (Value == value)
|
||||
return this;
|
||||
return new MiniYaml(value, Nodes);
|
||||
}
|
||||
|
||||
public MiniYaml WithNodes(IEnumerable<MiniYamlNode> nodes)
|
||||
{
|
||||
if (nodes is ImmutableArray<MiniYamlNode> n && Nodes == n)
|
||||
return this;
|
||||
return new MiniYaml(Value, nodes);
|
||||
}
|
||||
|
||||
public MiniYaml WithNodesAppended(IEnumerable<MiniYamlNode> nodes)
|
||||
{
|
||||
var newNodes = Nodes.AddRange(nodes);
|
||||
if (Nodes == newNodes)
|
||||
return this;
|
||||
return new MiniYaml(Value, newNodes);
|
||||
}
|
||||
|
||||
public Dictionary<string, MiniYaml> ToDictionary()
|
||||
@@ -125,7 +154,7 @@ namespace OpenRA
|
||||
public Dictionary<TKey, TElement> ToDictionary<TKey, TElement>(
|
||||
Func<string, TKey> keySelector, Func<MiniYaml, TElement> elementSelector)
|
||||
{
|
||||
var ret = new Dictionary<TKey, TElement>(Nodes.Count);
|
||||
var ret = new Dictionary<TKey, TElement>(Nodes.Length);
|
||||
foreach (var y in Nodes)
|
||||
{
|
||||
var key = keySelector(y.Key);
|
||||
@@ -138,28 +167,28 @@ namespace OpenRA
|
||||
}
|
||||
|
||||
public MiniYaml(string value)
|
||||
: this(value, null) { }
|
||||
: this(value, Enumerable.Empty<MiniYamlNode>()) { }
|
||||
|
||||
public MiniYaml(string value, List<MiniYamlNode> nodes)
|
||||
public MiniYaml(string value, IEnumerable<MiniYamlNode> nodes)
|
||||
{
|
||||
Value = value;
|
||||
Nodes = nodes ?? new List<MiniYamlNode>();
|
||||
Nodes = ImmutableArray.CreateRange(nodes);
|
||||
}
|
||||
|
||||
public static List<MiniYamlNode> NodesOrEmpty(MiniYaml y, string s)
|
||||
public static ImmutableArray<MiniYamlNode> NodesOrEmpty(MiniYaml y, string s)
|
||||
{
|
||||
var nd = y.ToDictionary();
|
||||
return nd.TryGetValue(s, out var v) ? v.Nodes : new List<MiniYamlNode>();
|
||||
return y.Nodes.FirstOrDefault(n => n.Key == s)?.Value.Nodes ?? ImmutableArray<MiniYamlNode>.Empty;
|
||||
}
|
||||
|
||||
static List<MiniYamlNode> FromLines(IEnumerable<ReadOnlyMemory<char>> lines, string filename, bool discardCommentsAndWhitespace, Dictionary<string, string> stringPool)
|
||||
{
|
||||
stringPool ??= new Dictionary<string, string>();
|
||||
|
||||
var levels = new List<List<MiniYamlNode>>
|
||||
var result = new List<List<MiniYamlNode>>
|
||||
{
|
||||
new List<MiniYamlNode>()
|
||||
};
|
||||
var parsedLines = new List<(int Level, string Key, string Value, string Comment, MiniYamlNode.SourceLocation Location)>();
|
||||
|
||||
var lineNo = 0;
|
||||
foreach (var ll in lines)
|
||||
@@ -206,15 +235,9 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
if (levels.Count <= level)
|
||||
if (parsedLines.Count > 0 && parsedLines[^1].Level < level - 1)
|
||||
throw new YamlException($"Bad indent in miniyaml at {location}");
|
||||
|
||||
while (levels.Count > level + 1)
|
||||
{
|
||||
levels[^1].TrimExcess();
|
||||
levels.RemoveAt(levels.Count - 1);
|
||||
}
|
||||
|
||||
// Extract key, value, comment from line as `<key>: <value>#<comment>`
|
||||
// The # character is allowed in the value if escaped (\#).
|
||||
// Leading and trailing whitespace is always trimmed from keys.
|
||||
@@ -274,6 +297,9 @@ namespace OpenRA
|
||||
|
||||
if (!key.IsEmpty || !discardCommentsAndWhitespace)
|
||||
{
|
||||
while (parsedLines.Count > 0 && parsedLines[^1].Level > level)
|
||||
BuildCompletedSubNode(level);
|
||||
|
||||
var keyString = key.IsEmpty ? null : key.ToString();
|
||||
var valueString = value.IsEmpty ? null : value.ToString();
|
||||
|
||||
@@ -285,17 +311,46 @@ namespace OpenRA
|
||||
valueString = valueString == null ? null : stringPool.GetOrAdd(valueString, valueString);
|
||||
commentString = commentString == null ? null : stringPool.GetOrAdd(commentString, commentString);
|
||||
|
||||
var nodes = new List<MiniYamlNode>();
|
||||
levels[level].Add(new MiniYamlNode(keyString, valueString, commentString, nodes, location));
|
||||
|
||||
levels.Add(nodes);
|
||||
parsedLines.Add((level, keyString, valueString, commentString, location));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var nodes in levels)
|
||||
nodes.TrimExcess();
|
||||
if (parsedLines.Count > 0)
|
||||
BuildCompletedSubNode(0);
|
||||
|
||||
return levels[0];
|
||||
return result[0];
|
||||
|
||||
void BuildCompletedSubNode(int level)
|
||||
{
|
||||
var lastLevel = parsedLines[^1].Level;
|
||||
while (lastLevel >= result.Count)
|
||||
result.Add(new List<MiniYamlNode>());
|
||||
|
||||
while (parsedLines.Count > 0 && parsedLines[^1].Level >= level)
|
||||
{
|
||||
var parent = parsedLines[^1];
|
||||
var startOfRange = parsedLines.Count - 1;
|
||||
while (startOfRange > 0 && parsedLines[startOfRange - 1].Level == parent.Level)
|
||||
startOfRange--;
|
||||
|
||||
for (var i = startOfRange; i < parsedLines.Count - 1; i++)
|
||||
{
|
||||
var sibling = parsedLines[i];
|
||||
result[parent.Level].Add(
|
||||
new MiniYamlNode(sibling.Key, new MiniYaml(sibling.Value), sibling.Comment, sibling.Location));
|
||||
}
|
||||
|
||||
var childNodes = parent.Level + 1 < result.Count ? result[parent.Level + 1] : null;
|
||||
result[parent.Level].Add(new MiniYamlNode(
|
||||
parent.Key,
|
||||
new MiniYaml(parent.Value, childNodes ?? Enumerable.Empty<MiniYamlNode>()),
|
||||
parent.Comment,
|
||||
parent.Location));
|
||||
childNodes?.Clear();
|
||||
|
||||
parsedLines.RemoveRange(startOfRange, parsedLines.Count - startOfRange);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<MiniYamlNode> FromFile(string path, bool discardCommentsAndWhitespace = true, Dictionary<string, string> stringPool = null)
|
||||
@@ -313,7 +368,7 @@ namespace OpenRA
|
||||
return FromLines(text.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None).Select(s => s.AsMemory()), fileName, discardCommentsAndWhitespace, stringPool);
|
||||
}
|
||||
|
||||
public static List<MiniYamlNode> Merge(IEnumerable<List<MiniYamlNode>> sources)
|
||||
public static List<MiniYamlNode> Merge(IEnumerable<IReadOnlyCollection<MiniYamlNode>> sources)
|
||||
{
|
||||
var sourcesList = sources.ToList();
|
||||
if (sourcesList.Count == 0)
|
||||
@@ -336,7 +391,7 @@ namespace OpenRA
|
||||
}
|
||||
|
||||
// Resolve any top-level removals (e.g. removing whole actor blocks)
|
||||
var nodes = new MiniYaml("", resolved.Select(kv => new MiniYamlNode(kv.Key, kv.Value)).ToList());
|
||||
var nodes = new MiniYaml("", resolved.Select(kv => new MiniYamlNode(kv.Key, kv.Value)));
|
||||
return ResolveInherits(nodes, tree, ImmutableDictionary<string, MiniYamlNode.SourceLocation>.Empty);
|
||||
}
|
||||
|
||||
@@ -345,19 +400,23 @@ namespace OpenRA
|
||||
{
|
||||
if (existingNodeKeys.Add(overrideNode.Key))
|
||||
{
|
||||
existingNodes.Add(overrideNode.Clone());
|
||||
existingNodes.Add(overrideNode);
|
||||
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);
|
||||
var existingNodeIndex = IndexOfKey(existingNodes, overrideNode.Key);
|
||||
var existingNode = existingNodes[existingNodeIndex];
|
||||
var value = MergePartial(existingNode.Value, overrideNode.Value);
|
||||
var nodes = ResolveInherits(value, tree, inherited);
|
||||
if (!value.Nodes.SequenceEqual(nodes))
|
||||
value = value.WithNodes(nodes);
|
||||
existingNodes[existingNodeIndex] = existingNode.WithValue(value);
|
||||
}
|
||||
|
||||
static List<MiniYamlNode> ResolveInherits(MiniYaml node, Dictionary<string, MiniYaml> tree, ImmutableDictionary<string, MiniYamlNode.SourceLocation> inherited)
|
||||
{
|
||||
var resolved = new List<MiniYamlNode>(node.Nodes.Count);
|
||||
var resolvedKeys = new HashSet<string>(node.Nodes.Count);
|
||||
var resolved = new List<MiniYamlNode>(node.Nodes.Length);
|
||||
var resolvedKeys = new HashSet<string>(node.Nodes.Length);
|
||||
|
||||
foreach (var n in node.Nodes)
|
||||
{
|
||||
@@ -390,7 +449,6 @@ namespace OpenRA
|
||||
MergeIntoResolved(n, resolved, resolvedKeys, tree, inherited);
|
||||
}
|
||||
|
||||
resolved.TrimExcess();
|
||||
return resolved;
|
||||
}
|
||||
|
||||
@@ -398,7 +456,7 @@ namespace OpenRA
|
||||
/// Merges any duplicate keys that are defined within the same set of nodes.
|
||||
/// Does not resolve inheritance or node removals.
|
||||
/// </summary>
|
||||
static List<MiniYamlNode> MergeSelfPartial(List<MiniYamlNode> existingNodes)
|
||||
static IReadOnlyCollection<MiniYamlNode> MergeSelfPartial(IReadOnlyCollection<MiniYamlNode> existingNodes)
|
||||
{
|
||||
var keys = new HashSet<string>(existingNodes.Count);
|
||||
var ret = new List<MiniYamlNode>(existingNodes.Count);
|
||||
@@ -409,12 +467,12 @@ namespace OpenRA
|
||||
else
|
||||
{
|
||||
// Node with the same key has already been added: merge new node over the existing one
|
||||
var original = ret.First(r => r.Key == n.Key);
|
||||
original.Value = MergePartial(original.Value, n.Value);
|
||||
var originalIndex = IndexOfKey(ret, n.Key);
|
||||
var original = ret[originalIndex];
|
||||
ret[originalIndex] = original.WithValue(MergePartial(original.Value, n.Value));
|
||||
}
|
||||
}
|
||||
|
||||
ret.TrimExcess();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -432,7 +490,7 @@ namespace OpenRA
|
||||
return new MiniYaml(overrideNodes.Value ?? existingNodes.Value, MergePartial(existingNodes.Nodes, overrideNodes.Nodes));
|
||||
}
|
||||
|
||||
static List<MiniYamlNode> MergePartial(List<MiniYamlNode> existingNodes, List<MiniYamlNode> overrideNodes)
|
||||
static IReadOnlyCollection<MiniYamlNode> MergePartial(IReadOnlyCollection<MiniYamlNode> existingNodes, IReadOnlyCollection<MiniYamlNode> overrideNodes)
|
||||
{
|
||||
if (existingNodes.Count == 0)
|
||||
return overrideNodes;
|
||||
@@ -468,9 +526,8 @@ namespace OpenRA
|
||||
// A Removal node is closer than the previous node.
|
||||
// We should not merge the new node, as the data being merged will jump before the Removal.
|
||||
// Instead, append it so the previous node is applied, then removed, then the new node is applied.
|
||||
var removalKey = $"-{node.Key}";
|
||||
var previousNodeIndex = ret.FindLastIndex(n => n.Key == node.Key);
|
||||
var previousRemovalNodeIndex = ret.FindLastIndex(n => n.Key == removalKey);
|
||||
var previousNodeIndex = LastIndexOfKey(ret, node.Key);
|
||||
var previousRemovalNodeIndex = LastIndexOfKey(ret, $"-{node.Key}");
|
||||
if (previousRemovalNodeIndex != -1 && previousRemovalNodeIndex > previousNodeIndex)
|
||||
{
|
||||
ret.Add(node);
|
||||
@@ -479,13 +536,30 @@ namespace OpenRA
|
||||
|
||||
// A previous node is present with no intervening Removal.
|
||||
// We should merge the new one into it, in place.
|
||||
ret[previousNodeIndex] = new MiniYamlNode(node.Key, MergePartial(ret[previousNodeIndex].Value, node.Value), node.Comment, node.Location);
|
||||
ret[previousNodeIndex] = node.WithValue(MergePartial(ret[previousNodeIndex].Value, node.Value));
|
||||
}
|
||||
|
||||
ret.TrimExcess();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int IndexOfKey(List<MiniYamlNode> nodes, string key)
|
||||
{
|
||||
// PERF: Avoid LINQ.
|
||||
for (var i = 0; i < nodes.Count; i++)
|
||||
if (nodes[i].Key == key)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int LastIndexOfKey(List<MiniYamlNode> nodes, string key)
|
||||
{
|
||||
// PERF: Avoid LINQ.
|
||||
for (var i = nodes.Count - 1; i >= 0; i--)
|
||||
if (nodes[i].Key == key)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
public IEnumerable<string> ToLines(string key, string comment = null)
|
||||
{
|
||||
var hasKey = !string.IsNullOrEmpty(key);
|
||||
@@ -508,14 +582,94 @@ namespace OpenRA
|
||||
files = files.Append(mapFiles);
|
||||
}
|
||||
|
||||
var yaml = files.Select(s => FromStream(fileSystem.Open(s), s));
|
||||
if (mapRules != null && mapRules.Nodes.Count > 0)
|
||||
IEnumerable<IReadOnlyCollection<MiniYamlNode>> yaml = files.Select(s => FromStream(fileSystem.Open(s), s));
|
||||
if (mapRules != null && mapRules.Nodes.Length > 0)
|
||||
yaml = yaml.Append(mapRules.Nodes);
|
||||
|
||||
return Merge(yaml);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MiniYamlNodeBuilder
|
||||
{
|
||||
public MiniYamlNode.SourceLocation Location;
|
||||
public string Key;
|
||||
public MiniYamlBuilder Value;
|
||||
public string Comment;
|
||||
|
||||
public MiniYamlNodeBuilder(MiniYamlNode node)
|
||||
{
|
||||
Location = node.Location;
|
||||
Key = node.Key;
|
||||
Value = new MiniYamlBuilder(node.Value);
|
||||
Comment = node.Comment;
|
||||
}
|
||||
|
||||
public MiniYamlNodeBuilder(string k, MiniYamlBuilder v, string c = null)
|
||||
{
|
||||
Key = k;
|
||||
Value = v;
|
||||
Comment = c;
|
||||
}
|
||||
|
||||
public MiniYamlNodeBuilder(string k, MiniYamlBuilder v, string c, MiniYamlNode.SourceLocation loc)
|
||||
: this(k, v, c)
|
||||
{
|
||||
Location = loc;
|
||||
}
|
||||
|
||||
public MiniYamlNodeBuilder(string k, string v, string c = null)
|
||||
: this(k, new MiniYamlBuilder(v, null), c) { }
|
||||
|
||||
public MiniYamlNodeBuilder(string k, string v, List<MiniYamlNode> n)
|
||||
: this(k, new MiniYamlBuilder(v, n), null) { }
|
||||
|
||||
public MiniYamlNode Build()
|
||||
{
|
||||
return new MiniYamlNode(Key, Value.Build(), Comment, Location);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MiniYamlBuilder
|
||||
{
|
||||
public string Value;
|
||||
public List<MiniYamlNodeBuilder> Nodes;
|
||||
|
||||
public MiniYamlBuilder(MiniYaml yaml)
|
||||
{
|
||||
Value = yaml.Value;
|
||||
Nodes = yaml.Nodes.Select(n => new MiniYamlNodeBuilder(n)).ToList();
|
||||
}
|
||||
|
||||
public MiniYamlBuilder(string value)
|
||||
: this(value, null) { }
|
||||
|
||||
public MiniYamlBuilder(string value, List<MiniYamlNode> nodes)
|
||||
{
|
||||
Value = value;
|
||||
Nodes = nodes == null ? new List<MiniYamlNodeBuilder>() : nodes.Select(x => new MiniYamlNodeBuilder(x)).ToList();
|
||||
}
|
||||
|
||||
public MiniYaml Build()
|
||||
{
|
||||
return new MiniYaml(Value, Nodes.Select(n => n.Build()));
|
||||
}
|
||||
|
||||
public IEnumerable<string> ToLines(string key, string comment = null)
|
||||
{
|
||||
var hasKey = !string.IsNullOrEmpty(key);
|
||||
var hasValue = !string.IsNullOrEmpty(Value);
|
||||
var hasComment = comment != null;
|
||||
yield return (hasKey ? key + ":" : "")
|
||||
+ (hasValue ? " " + Value.Replace("#", "\\#") : "")
|
||||
+ (hasComment ? (hasKey || hasValue ? " " : "") + "#" + comment : "");
|
||||
|
||||
if (Nodes != null)
|
||||
foreach (var line in Nodes.ToLines())
|
||||
yield return "\t" + line;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class YamlException : Exception
|
||||
{
|
||||
|
||||
@@ -251,10 +251,8 @@ namespace OpenRA.Network
|
||||
root.Add(new MiniYamlNode("Mods", Mod + "@" + Version));
|
||||
}
|
||||
|
||||
var clientsNode = new MiniYaml("");
|
||||
var i = 0;
|
||||
foreach (var c in Clients)
|
||||
clientsNode.Nodes.Add(new MiniYamlNode("Client@" + i++.ToString(), FieldSaver.Save(c)));
|
||||
var clientsNode = new MiniYaml("", Clients.Select((c, i) =>
|
||||
new MiniYamlNode("Client@" + i, FieldSaver.Save(c))));
|
||||
|
||||
root.Add(new MiniYamlNode("Clients", clientsNode));
|
||||
return new MiniYaml("", root)
|
||||
|
||||
@@ -108,10 +108,9 @@ namespace OpenRA.Network
|
||||
|
||||
if (arguments != null)
|
||||
{
|
||||
var argumentsNode = new MiniYaml("");
|
||||
var i = 0;
|
||||
foreach (var argument in arguments.Select(a => new FluentArgument(a.Key, a.Value)))
|
||||
argumentsNode.Nodes.Add(new MiniYamlNode("Argument@" + i++, FieldSaver.Save(argument)));
|
||||
var argumentsNode = new MiniYaml("", arguments
|
||||
.Select(a => new FluentArgument(a.Key, a.Value))
|
||||
.Select((argument, i) => new MiniYamlNode("Argument@" + i, FieldSaver.Save(argument))));
|
||||
|
||||
root.Add(new MiniYamlNode("Arguments", argumentsNode));
|
||||
}
|
||||
|
||||
@@ -238,8 +238,9 @@ namespace OpenRA.Network
|
||||
public MiniYamlNode Serialize()
|
||||
{
|
||||
var data = new MiniYamlNode("GlobalSettings", FieldSaver.Save(this));
|
||||
var options = LobbyOptions.Select(kv => new MiniYamlNode(kv.Key, FieldSaver.Save(kv.Value))).ToList();
|
||||
data.Value.Nodes.Add(new MiniYamlNode("Options", new MiniYaml(null, options)));
|
||||
var options = LobbyOptions.Select(kv => new MiniYamlNode(kv.Key, FieldSaver.Save(kv.Value)));
|
||||
data = data.WithValue(data.Value.WithNodesAppended(
|
||||
new[] { new MiniYamlNode("Options", new MiniYaml(null, options)) }));
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
@@ -361,13 +361,14 @@ namespace OpenRA
|
||||
|
||||
public void Save()
|
||||
{
|
||||
var yamlCacheBuilder = yamlCache.Select(n => new MiniYamlNodeBuilder(n)).ToList();
|
||||
foreach (var kv in Sections)
|
||||
{
|
||||
var sectionYaml = yamlCache.FirstOrDefault(x => x.Key == kv.Key);
|
||||
var sectionYaml = yamlCacheBuilder.FirstOrDefault(x => x.Key == kv.Key);
|
||||
if (sectionYaml == null)
|
||||
{
|
||||
sectionYaml = new MiniYamlNode(kv.Key, new MiniYaml(""));
|
||||
yamlCache.Add(sectionYaml);
|
||||
sectionYaml = new MiniYamlNodeBuilder(kv.Key, new MiniYamlBuilder(""));
|
||||
yamlCacheBuilder.Add(sectionYaml);
|
||||
}
|
||||
|
||||
var defaultValues = Activator.CreateInstance(kv.Value.GetType());
|
||||
@@ -388,23 +389,25 @@ namespace OpenRA
|
||||
if (fieldYaml != null)
|
||||
fieldYaml.Value.Value = serialized;
|
||||
else
|
||||
sectionYaml.Value.Nodes.Add(new MiniYamlNode(fli.YamlName, new MiniYaml(serialized)));
|
||||
sectionYaml.Value.Nodes.Add(new MiniYamlNodeBuilder(fli.YamlName, new MiniYamlBuilder(serialized)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var keysYaml = yamlCache.FirstOrDefault(x => x.Key == "Keys");
|
||||
var keysYaml = yamlCacheBuilder.FirstOrDefault(x => x.Key == "Keys");
|
||||
if (keysYaml == null)
|
||||
{
|
||||
keysYaml = new MiniYamlNode("Keys", new MiniYaml(""));
|
||||
yamlCache.Add(keysYaml);
|
||||
keysYaml = new MiniYamlNodeBuilder("Keys", new MiniYamlBuilder(""));
|
||||
yamlCacheBuilder.Add(keysYaml);
|
||||
}
|
||||
|
||||
keysYaml.Value.Nodes.Clear();
|
||||
foreach (var kv in Keys)
|
||||
keysYaml.Value.Nodes.Add(new MiniYamlNode(kv.Key, FieldSaver.FormatValue(kv.Value)));
|
||||
keysYaml.Value.Nodes.Add(new MiniYamlNodeBuilder(kv.Key, FieldSaver.FormatValue(kv.Value)));
|
||||
|
||||
yamlCache.WriteToFile(settingsFile);
|
||||
yamlCacheBuilder.WriteToFile(settingsFile);
|
||||
yamlCache.Clear();
|
||||
yamlCache.AddRange(yamlCacheBuilder.Select(n => n.Build()));
|
||||
}
|
||||
|
||||
static string SanitizedName(string dirty)
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
@@ -349,7 +350,7 @@ namespace OpenRA.Traits
|
||||
public interface IGameSaveTraitData
|
||||
{
|
||||
List<MiniYamlNode> IssueTraitData(Actor self);
|
||||
void ResolveTraitData(Actor self, List<MiniYamlNode> data);
|
||||
void ResolveTraitData(Actor self, ImmutableArray<MiniYamlNode> data);
|
||||
}
|
||||
|
||||
[RequireExplicitImplementation]
|
||||
|
||||
@@ -128,6 +128,26 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
|
||||
public abstract void ValidateMapFormat(int format);
|
||||
|
||||
protected MiniYamlNodeBuilder GetWorldNodeBuilderFromRules()
|
||||
{
|
||||
var worldNode = Map.RuleDefinitions.Nodes.FirstOrDefault(n => n.Key == "World");
|
||||
var worldNodeBuilder = worldNode != null
|
||||
? new MiniYamlNodeBuilder(worldNode)
|
||||
: new MiniYamlNodeBuilder("World", new MiniYamlBuilder("", new List<MiniYamlNode>()));
|
||||
return worldNodeBuilder;
|
||||
}
|
||||
|
||||
protected void SaveUpdatedWorldNodeToRules(MiniYamlNodeBuilder worldNodeBuilder)
|
||||
{
|
||||
var nodes = Map.RuleDefinitions.Nodes.ToList();
|
||||
var worldNodeIndex = nodes.FindIndex(n => n.Key == "World");
|
||||
if (worldNodeIndex != -1)
|
||||
nodes[worldNodeIndex] = worldNodeBuilder.Build();
|
||||
else
|
||||
nodes.Add(worldNodeBuilder.Build());
|
||||
Map.RuleDefinitions = Map.RuleDefinitions.WithNodes(nodes);
|
||||
}
|
||||
|
||||
void LoadBriefing(IniFile file)
|
||||
{
|
||||
var briefingSection = file.GetSection("Briefing", true);
|
||||
@@ -144,21 +164,18 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
if (briefing.Length == 0)
|
||||
return;
|
||||
|
||||
var worldNode = Map.RuleDefinitions.Nodes.FirstOrDefault(n => n.Key == "World");
|
||||
if (worldNode == null)
|
||||
{
|
||||
worldNode = new MiniYamlNode("World", new MiniYaml("", new List<MiniYamlNode>()));
|
||||
Map.RuleDefinitions.Nodes.Add(worldNode);
|
||||
}
|
||||
var worldNodeBuilder = GetWorldNodeBuilderFromRules();
|
||||
|
||||
var missionData = worldNode.Value.Nodes.FirstOrDefault(n => n.Key == "MissionData");
|
||||
var missionData = worldNodeBuilder.Value.Nodes.FirstOrDefault(n => n.Key == "MissionData");
|
||||
if (missionData == null)
|
||||
{
|
||||
missionData = new MiniYamlNode("MissionData", new MiniYaml("", new List<MiniYamlNode>()));
|
||||
worldNode.Value.Nodes.Add(missionData);
|
||||
missionData = new MiniYamlNodeBuilder("MissionData", new MiniYamlBuilder("", new List<MiniYamlNode>()));
|
||||
worldNodeBuilder.Value.Nodes.Add(missionData);
|
||||
}
|
||||
|
||||
missionData.Value.Nodes.Add(new MiniYamlNode("Briefing", briefing.Replace("\n", " ").ToString()));
|
||||
missionData.Value.Nodes.Add(new MiniYamlNodeBuilder("Briefing", briefing.Replace("\n", " ").ToString()));
|
||||
|
||||
SaveUpdatedWorldNodeToRules(worldNodeBuilder);
|
||||
}
|
||||
|
||||
static void ReplaceInvalidTerrainTiles(Map map)
|
||||
@@ -190,7 +207,7 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
|
||||
void LoadVideos(IniFile file, string section)
|
||||
{
|
||||
var videos = new List<MiniYamlNode>();
|
||||
var videos = new List<MiniYamlNodeBuilder>();
|
||||
foreach (var s in file.GetSection(section))
|
||||
{
|
||||
if (s.Value != "x" && s.Value != "X" && s.Value != "<none>")
|
||||
@@ -198,19 +215,19 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
switch (s.Key)
|
||||
{
|
||||
case "Intro":
|
||||
videos.Add(new MiniYamlNode("BackgroundVideo", s.Value.ToLowerInvariant() + ".vqa"));
|
||||
videos.Add(new MiniYamlNodeBuilder("BackgroundVideo", s.Value.ToLowerInvariant() + ".vqa"));
|
||||
break;
|
||||
case "Brief":
|
||||
videos.Add(new MiniYamlNode("BriefingVideo", s.Value.ToLowerInvariant() + ".vqa"));
|
||||
videos.Add(new MiniYamlNodeBuilder("BriefingVideo", s.Value.ToLowerInvariant() + ".vqa"));
|
||||
break;
|
||||
case "Action":
|
||||
videos.Add(new MiniYamlNode("StartVideo", s.Value.ToLowerInvariant() + ".vqa"));
|
||||
videos.Add(new MiniYamlNodeBuilder("StartVideo", s.Value.ToLowerInvariant() + ".vqa"));
|
||||
break;
|
||||
case "Win":
|
||||
videos.Add(new MiniYamlNode("WinVideo", s.Value.ToLowerInvariant() + ".vqa"));
|
||||
videos.Add(new MiniYamlNodeBuilder("WinVideo", s.Value.ToLowerInvariant() + ".vqa"));
|
||||
break;
|
||||
case "Lose":
|
||||
videos.Add(new MiniYamlNode("LossVideo", s.Value.ToLowerInvariant() + ".vqa"));
|
||||
videos.Add(new MiniYamlNodeBuilder("LossVideo", s.Value.ToLowerInvariant() + ".vqa"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -218,21 +235,18 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
|
||||
if (videos.Count > 0)
|
||||
{
|
||||
var worldNode = Map.RuleDefinitions.Nodes.FirstOrDefault(n => n.Key == "World");
|
||||
if (worldNode == null)
|
||||
{
|
||||
worldNode = new MiniYamlNode("World", new MiniYaml("", new List<MiniYamlNode>()));
|
||||
Map.RuleDefinitions.Nodes.Add(worldNode);
|
||||
}
|
||||
var worldNodeBuilder = GetWorldNodeBuilderFromRules();
|
||||
|
||||
var missionData = worldNode.Value.Nodes.FirstOrDefault(n => n.Key == "MissionData");
|
||||
var missionData = worldNodeBuilder.Value.Nodes.FirstOrDefault(n => n.Key == "MissionData");
|
||||
if (missionData == null)
|
||||
{
|
||||
missionData = new MiniYamlNode("MissionData", new MiniYaml("", new List<MiniYamlNode>()));
|
||||
worldNode.Value.Nodes.Add(missionData);
|
||||
missionData = new MiniYamlNodeBuilder("MissionData", new MiniYamlBuilder("", new List<MiniYamlNode>()));
|
||||
worldNodeBuilder.Value.Nodes.Add(missionData);
|
||||
}
|
||||
|
||||
missionData.Value.Nodes.AddRange(videos);
|
||||
|
||||
SaveUpdatedWorldNodeToRules(worldNodeBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,13 +278,13 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
|
||||
void LoadWaypoints(IniSection waypointSection)
|
||||
{
|
||||
var actorCount = Map.ActorDefinitions.Count;
|
||||
var wps = waypointSection
|
||||
.Where(kv => Exts.ParseIntegerInvariant(kv.Value) > 0)
|
||||
.Select(kv => (WaypointNumber: Exts.ParseIntegerInvariant(kv.Key),
|
||||
Location: LocationFromMapOffset(Exts.ParseIntegerInvariant(kv.Value), MapSize)));
|
||||
|
||||
// Add waypoint actors skipping duplicate entries
|
||||
var nodes = new List<MiniYamlNode>();
|
||||
foreach (var (waypointNumber, location) in wps.DistinctBy(location => location.Location))
|
||||
{
|
||||
if (!singlePlayer && waypointNumber <= 7)
|
||||
@@ -281,7 +295,7 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
new OwnerInit("Neutral")
|
||||
};
|
||||
|
||||
Map.ActorDefinitions.Add(new MiniYamlNode("Actor" + actorCount++, ar.Save()));
|
||||
nodes.Add(new MiniYamlNode("Actor" + (Map.ActorDefinitions.Count + nodes.Count), ar.Save()));
|
||||
spawnCount++;
|
||||
}
|
||||
else
|
||||
@@ -292,15 +306,17 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
new OwnerInit("Neutral")
|
||||
};
|
||||
|
||||
SaveWaypoint(waypointNumber, ar);
|
||||
nodes.Add(SaveWaypoint(waypointNumber, ar));
|
||||
}
|
||||
}
|
||||
|
||||
Map.ActorDefinitions = Map.ActorDefinitions.Concat(nodes).ToArray();
|
||||
}
|
||||
|
||||
public virtual void SaveWaypoint(int waypointNumber, ActorReference waypointReference)
|
||||
public virtual MiniYamlNode SaveWaypoint(int waypointNumber, ActorReference waypointReference)
|
||||
{
|
||||
var waypointName = "waypoint" + waypointNumber;
|
||||
Map.ActorDefinitions.Add(new MiniYamlNode(waypointName, waypointReference.Save()));
|
||||
return new MiniYamlNode(waypointName, waypointReference.Save());
|
||||
}
|
||||
|
||||
void LoadSmudges(IniFile file, string section)
|
||||
@@ -322,25 +338,24 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
craters.Add(node);
|
||||
}
|
||||
|
||||
var worldNode = Map.RuleDefinitions.Nodes.FirstOrDefault(n => n.Key == "World");
|
||||
worldNode ??= new MiniYamlNode("World", new MiniYaml("", new List<MiniYamlNode>()));
|
||||
var worldNodeBuilder = GetWorldNodeBuilderFromRules();
|
||||
|
||||
if (scorches.Count > 0)
|
||||
{
|
||||
var initialScorches = new MiniYamlNode("InitialSmudges", new MiniYaml("", scorches));
|
||||
var smudgeLayer = new MiniYamlNode("SmudgeLayer@SCORCH", new MiniYaml("", new List<MiniYamlNode>() { initialScorches }));
|
||||
worldNode.Value.Nodes.Add(smudgeLayer);
|
||||
var smudgeLayer = new MiniYamlNodeBuilder("SmudgeLayer@SCORCH", new MiniYamlBuilder("", new List<MiniYamlNode>() { initialScorches }));
|
||||
worldNodeBuilder.Value.Nodes.Add(smudgeLayer);
|
||||
}
|
||||
|
||||
if (craters.Count > 0)
|
||||
{
|
||||
var initialCraters = new MiniYamlNode("InitialSmudges", new MiniYaml("", craters));
|
||||
var smudgeLayer = new MiniYamlNode("SmudgeLayer@CRATER", new MiniYaml("", new List<MiniYamlNode>() { initialCraters }));
|
||||
worldNode.Value.Nodes.Add(smudgeLayer);
|
||||
var smudgeLayer = new MiniYamlNodeBuilder("SmudgeLayer@CRATER", new MiniYamlBuilder("", new List<MiniYamlNode>() { initialCraters }));
|
||||
worldNodeBuilder.Value.Nodes.Add(smudgeLayer);
|
||||
}
|
||||
|
||||
if (worldNode.Value.Nodes.Count > 0 && !Map.RuleDefinitions.Nodes.Contains(worldNode))
|
||||
Map.RuleDefinitions.Nodes.Add(worldNode);
|
||||
if (worldNodeBuilder.Value.Nodes.Count > 0)
|
||||
SaveUpdatedWorldNodeToRules(worldNodeBuilder);
|
||||
}
|
||||
|
||||
// TODO: fix this -- will have bitrotted pretty badly.
|
||||
@@ -395,6 +410,7 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
|
||||
public void LoadActors(IniFile file, string section, List<string> players, Map map)
|
||||
{
|
||||
var nodes = new List<MiniYamlNode>();
|
||||
foreach (var s in file.GetSection(section, true))
|
||||
{
|
||||
// Structures: num=owner,type,health,location,turret-facing,trigger
|
||||
@@ -429,18 +445,18 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
if (section == "INFANTRY")
|
||||
actor.Add(new SubCellInit((SubCell)Exts.ParseByte(parts[4])));
|
||||
|
||||
var actorCount = map.ActorDefinitions.Count;
|
||||
|
||||
if (!map.Rules.Actors.ContainsKey(parts[1].ToLowerInvariant()))
|
||||
Console.WriteLine($"Ignoring unknown actor type: `{parts[1].ToLowerInvariant()}`");
|
||||
else
|
||||
map.ActorDefinitions.Add(new MiniYamlNode("Actor" + actorCount++, actor.Save()));
|
||||
nodes.Add(new MiniYamlNode("Actor" + (map.ActorDefinitions.Count + nodes.Count), actor.Save()));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Console.WriteLine($"Malformed actor definition: `{s}`");
|
||||
}
|
||||
}
|
||||
|
||||
map.ActorDefinitions = map.ActorDefinitions.Concat(nodes).ToArray();
|
||||
}
|
||||
|
||||
public abstract string ParseTreeActor(string input);
|
||||
@@ -451,6 +467,7 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
if (terrain == null)
|
||||
return;
|
||||
|
||||
var nodes = new List<MiniYamlNode>();
|
||||
foreach (var kv in terrain)
|
||||
{
|
||||
var loc = Exts.ParseIntegerInvariant(kv.Key);
|
||||
@@ -462,9 +479,10 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
new OwnerInit("Neutral")
|
||||
};
|
||||
|
||||
var actorCount = Map.ActorDefinitions.Count;
|
||||
Map.ActorDefinitions.Add(new MiniYamlNode("Actor" + actorCount++, ar.Save()));
|
||||
nodes.Add(new MiniYamlNode("Actor" + (Map.ActorDefinitions.Count + nodes.Count), ar.Save()));
|
||||
}
|
||||
|
||||
Map.ActorDefinitions = Map.ActorDefinitions.Concat(nodes).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -171,6 +171,7 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
}
|
||||
}
|
||||
|
||||
var nodes = new List<MiniYamlNode>();
|
||||
foreach (var cell in map.AllCells)
|
||||
{
|
||||
var overlayType = overlayPack[overlayIndex[cell]];
|
||||
@@ -180,7 +181,7 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
if (TryHandleOverlayToActorInner(cell, overlayPack, overlayIndex, overlayType, out var ar))
|
||||
{
|
||||
if (ar != null)
|
||||
map.ActorDefinitions.Add(new MiniYamlNode("Actor" + map.ActorDefinitions.Count, ar.Save()));
|
||||
nodes.Add(new MiniYamlNode("Actor" + (map.ActorDefinitions.Count + nodes.Count), ar.Save()));
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -196,10 +197,13 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
|
||||
Console.WriteLine($"Cell {cell}: unknown overlay {overlayType}");
|
||||
}
|
||||
|
||||
map.ActorDefinitions = map.ActorDefinitions.Concat(nodes).ToArray();
|
||||
}
|
||||
|
||||
protected virtual void ReadWaypoints(Map map, IniFile file, int2 fullSize)
|
||||
{
|
||||
var nodes = new List<MiniYamlNode>();
|
||||
var waypointsSection = file.GetSection("Waypoints", true);
|
||||
foreach (var kv in waypointsSection)
|
||||
{
|
||||
@@ -214,12 +218,15 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
new OwnerInit("Neutral")
|
||||
};
|
||||
|
||||
map.ActorDefinitions.Add(new MiniYamlNode("Actor" + map.ActorDefinitions.Count, ar.Save()));
|
||||
nodes.Add(new MiniYamlNode("Actor" + (map.ActorDefinitions.Count + nodes.Count), ar.Save()));
|
||||
}
|
||||
|
||||
map.ActorDefinitions = map.ActorDefinitions.Concat(nodes).ToArray();
|
||||
}
|
||||
|
||||
protected virtual void ReadTerrainActors(Map map, IniFile file, int2 fullSize)
|
||||
{
|
||||
var nodes = new List<MiniYamlNode>();
|
||||
var terrainSection = file.GetSection("Terrain", true);
|
||||
foreach (var kv in terrainSection)
|
||||
{
|
||||
@@ -238,12 +245,15 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
if (!map.Rules.Actors.ContainsKey(name))
|
||||
Console.WriteLine($"Ignoring unknown actor type: `{name}`");
|
||||
else
|
||||
map.ActorDefinitions.Add(new MiniYamlNode("Actor" + map.ActorDefinitions.Count, ar.Save()));
|
||||
nodes.Add(new MiniYamlNode("Actor" + (map.ActorDefinitions.Count + nodes.Count), ar.Save()));
|
||||
}
|
||||
|
||||
map.ActorDefinitions = map.ActorDefinitions.Concat(nodes).ToArray();
|
||||
}
|
||||
|
||||
protected virtual void ReadActors(Map map, IniFile file, string type, int2 fullSize)
|
||||
{
|
||||
var nodes = new List<MiniYamlNode>();
|
||||
var structuresSection = file.GetSection(type, true);
|
||||
foreach (var kv in structuresSection)
|
||||
{
|
||||
@@ -296,8 +306,10 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
if (!map.Rules.Actors.ContainsKey(name))
|
||||
Console.WriteLine($"Ignoring unknown actor type: `{name}`");
|
||||
else
|
||||
map.ActorDefinitions.Add(new MiniYamlNode("Actor" + map.ActorDefinitions.Count, ar.Save()));
|
||||
nodes.Add(new MiniYamlNode("Actor" + (map.ActorDefinitions.Count + nodes.Count), ar.Save()));
|
||||
}
|
||||
|
||||
map.ActorDefinitions = map.ActorDefinitions.Concat(nodes).ToArray();
|
||||
}
|
||||
|
||||
protected virtual void ReadLighting(Map map, IniFile file)
|
||||
@@ -340,10 +352,13 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
|
||||
if (lightingNodes.Count > 0)
|
||||
{
|
||||
map.RuleDefinitions.Nodes.Add(new MiniYamlNode("^BaseWorld", new MiniYaml("", new List<MiniYamlNode>()
|
||||
map.RuleDefinitions = map.RuleDefinitions.WithNodesAppended(new[]
|
||||
{
|
||||
new MiniYamlNode("TerrainLighting", new MiniYaml("", lightingNodes))
|
||||
})));
|
||||
new MiniYamlNode("^BaseWorld", new MiniYaml("", new[]
|
||||
{
|
||||
new MiniYamlNode("TerrainLighting", new MiniYaml("", lightingNodes))
|
||||
}))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,6 +372,7 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
{ "LightBlueTint", "BlueTint" },
|
||||
};
|
||||
|
||||
var nodes = new List<MiniYamlNode>();
|
||||
foreach (var lamp in LampActors)
|
||||
{
|
||||
var lightingSection = file.GetSection(lamp, true);
|
||||
@@ -380,12 +396,14 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
|
||||
if (lightingNodes.Count > 0)
|
||||
{
|
||||
map.RuleDefinitions.Nodes.Add(new MiniYamlNode(lamp, new MiniYaml("", new List<MiniYamlNode>()
|
||||
nodes.Add(new MiniYamlNode(lamp, new MiniYaml("", new[]
|
||||
{
|
||||
new MiniYamlNode("TerrainLightSource", new MiniYaml("", lightingNodes))
|
||||
})));
|
||||
}
|
||||
}
|
||||
|
||||
map.RuleDefinitions = map.RuleDefinitions.WithNodesAppended(nodes);
|
||||
}
|
||||
|
||||
protected virtual void SetInteractableBounds(Map map, int[] iniBounds)
|
||||
|
||||
@@ -94,6 +94,7 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
|
||||
void UnpackOverlayData(MemoryStream ms)
|
||||
{
|
||||
var nodes = new List<MiniYamlNode>();
|
||||
for (var j = 0; j < MapSize; j++)
|
||||
{
|
||||
for (var i = 0; i < MapSize; i++)
|
||||
@@ -115,11 +116,12 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
new OwnerInit("Neutral")
|
||||
};
|
||||
|
||||
var actorCount = Map.ActorDefinitions.Count;
|
||||
Map.ActorDefinitions.Add(new MiniYamlNode("Actor" + actorCount++, ar.Save()));
|
||||
nodes.Add(new MiniYamlNode("Actor" + (Map.ActorDefinitions.Count + nodes.Count), ar.Save()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map.ActorDefinitions = Map.ActorDefinitions.Concat(nodes).ToArray();
|
||||
}
|
||||
|
||||
public override string ParseTreeActor(string input)
|
||||
@@ -241,12 +243,12 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
LoadActors(file, "SHIPS", Players, Map);
|
||||
}
|
||||
|
||||
public override void SaveWaypoint(int waypointNumber, ActorReference waypointReference)
|
||||
public override MiniYamlNode SaveWaypoint(int waypointNumber, ActorReference waypointReference)
|
||||
{
|
||||
var waypointName = "waypoint" + waypointNumber;
|
||||
if (waypointNumber == 98)
|
||||
waypointName = "DefaultCameraPosition";
|
||||
Map.ActorDefinitions.Add(new MiniYamlNode(waypointName, waypointReference.Save()));
|
||||
return new MiniYamlNode(waypointName, waypointReference.Save());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
if (overlay == null)
|
||||
return;
|
||||
|
||||
var nodes = new List<MiniYamlNode>();
|
||||
foreach (var kv in overlay)
|
||||
{
|
||||
var loc = Exts.ParseIntegerInvariant(kv.Key);
|
||||
@@ -105,10 +106,11 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
new OwnerInit("Neutral")
|
||||
};
|
||||
|
||||
var actorCount = Map.ActorDefinitions.Count;
|
||||
Map.ActorDefinitions.Add(new MiniYamlNode("Actor" + actorCount++, ar.Save()));
|
||||
nodes.Add(new MiniYamlNode("Actor" + (Map.ActorDefinitions.Count + nodes.Count), ar.Save()));
|
||||
}
|
||||
}
|
||||
|
||||
Map.ActorDefinitions = Map.ActorDefinitions.Concat(nodes).ToArray();
|
||||
}
|
||||
|
||||
public override string ParseTreeActor(string input)
|
||||
@@ -170,7 +172,7 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
ReadOverlay(file);
|
||||
}
|
||||
|
||||
public override void SaveWaypoint(int waypointNumber, ActorReference waypointReference)
|
||||
public override MiniYamlNode SaveWaypoint(int waypointNumber, ActorReference waypointReference)
|
||||
{
|
||||
var waypointName = "waypoint" + waypointNumber;
|
||||
if (waypointNumber == 25)
|
||||
@@ -179,7 +181,7 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
|
||||
waypointName = "DefaultCameraPosition";
|
||||
else if (waypointNumber == 27)
|
||||
waypointName = "DefaultChinookTarget";
|
||||
Map.ActorDefinitions.Add(new MiniYamlNode(waypointName, waypointReference.Save()));
|
||||
return new MiniYamlNode(waypointName, waypointReference.Save());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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})";
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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"))
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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"))
|
||||
{
|
||||
|
||||
@@ -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"))
|
||||
{
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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"))
|
||||
{
|
||||
|
||||
@@ -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"))
|
||||
{
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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")
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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"))
|
||||
{
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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"))
|
||||
{
|
||||
|
||||
@@ -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"))
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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"))
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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("");
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"))
|
||||
{
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user