Merge pull request #9710 from obrakmann/yaml-removals

Fix yaml removals
This commit is contained in:
Matthias Mailänder
2015-12-06 17:04:47 +01:00
16 changed files with 170 additions and 104 deletions

View File

@@ -31,35 +31,30 @@ namespace OpenRA
readonly TypeDictionary traits = new TypeDictionary();
List<ITraitInfo> constructOrderCache = null;
public ActorInfo(string name, MiniYaml node, Dictionary<string, MiniYaml> allUnits)
public ActorInfo(ObjectCreator creator, string name, MiniYaml node, Dictionary<string, MiniYaml> allUnits)
{
try
{
Name = name;
var allParents = new HashSet<string>();
var abstractActorType = name.StartsWith("^");
// Guard against circular inheritance
allParents.Add(name);
var mergedNode = MergeWithParents(node, allUnits, allParents).ToDictionary();
Name = name;
foreach (var t in mergedNode)
{
if (t.Key[0] == '-')
throw new YamlException("Bogus trait removal: " + t.Key);
var partial = MergeWithParents(node, allUnits, allParents);
foreach (var t in MiniYaml.ApplyRemovals(partial.Nodes))
if (t.Key != "Inherits" && !t.Key.StartsWith("Inherits@"))
try
{
traits.Add(LoadTraitInfo(t.Key.Split('@')[0], t.Value));
traits.Add(LoadTraitInfo(creator, t.Key.Split('@')[0], t.Value));
}
catch (FieldLoader.MissingFieldsException e)
{
if (!abstractActorType)
throw new YamlException(e.Message);
}
}
}
catch (YamlException e)
{
@@ -98,18 +93,18 @@ namespace OpenRA
throw new YamlException(
"Bogus inheritance -- duplicate inheritance of {0}.".F(kv.Key));
node = MiniYaml.MergeStrict(node, MergeWithParents(kv.Value, allUnits, allParents));
node = MiniYaml.MergePartial(node, MergeWithParents(kv.Value, allUnits, allParents));
}
return node;
}
static ITraitInfo LoadTraitInfo(string traitName, MiniYaml my)
static ITraitInfo LoadTraitInfo(ObjectCreator creator, string traitName, MiniYaml my)
{
if (!string.IsNullOrEmpty(my.Value))
throw new YamlException("Junk value `{0}` on trait node {1}"
.F(my.Value, traitName));
var info = Game.CreateObject<ITraitInfo>(traitName + "Info");
var info = creator.CreateObject<ITraitInfo>(traitName + "Info");
try
{
FieldLoader.Load(info, my);

View File

@@ -61,7 +61,7 @@ namespace OpenRA
using (new PerfTimer("Actors"))
actors = LoadYamlRules(actorCache, m.Rules,
map != null ? map.RuleDefinitions : NoMapRules,
(k, y) => new ActorInfo(k.Key.ToLowerInvariant(), k.Value, y));
(k, y) => new ActorInfo(Game.ModData.ObjectCreator, k.Key.ToLowerInvariant(), k.Value, y));
using (new PerfTimer("Weapons"))
weapons = LoadYamlRules(weaponCache, m.Weapons,
@@ -99,9 +99,9 @@ namespace OpenRA
var inputKey = string.Concat(string.Join("|", files), "|", nodes.WriteToString());
var mergedNodes = files
var partial = files
.Select(s => MiniYaml.FromFile(s))
.Aggregate(nodes, MiniYaml.MergeLiberal);
.Aggregate(nodes, MiniYaml.MergePartial);
Func<MiniYamlNode, Dictionary<string, MiniYaml>, T> wrap = (wkv, wyy) =>
{
@@ -117,8 +117,8 @@ namespace OpenRA
return t;
};
var yy = mergedNodes.ToDictionary(x => x.Key, x => x.Value);
var itemSet = mergedNodes.ToDictionaryWithConflictLog(kv => kv.Key.ToLowerInvariant(), kv => wrap(kv, yy), "LoadYamlRules", null, null);
var yy = partial.ToDictionary(x => x.Key, x => x.Value);
var itemSet = partial.ToDictionaryWithConflictLog(kv => kv.Key.ToLowerInvariant(), kv => wrap(kv, yy), "LoadYamlRules", null, null);
RaiseProgress();
return itemSet;

View File

@@ -33,7 +33,11 @@ namespace OpenRA.Graphics
cachedSheets = new Dictionary<string, Sheet>();
cachedSprites = new Dictionary<string, Dictionary<string, Sprite>>();
var chrome = chromeFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergeLiberal);
var partial = chromeFiles
.Select(s => MiniYaml.FromFile(s))
.Aggregate(MiniYaml.MergePartial);
var chrome = MiniYaml.ApplyRemovals(partial);
foreach (var c in chrome)
LoadCollection(c.Key, c.Value);

View File

@@ -25,7 +25,11 @@ namespace OpenRA.Graphics
public CursorProvider(ModData modData)
{
var sequenceFiles = modData.Manifest.Cursors;
var sequences = new MiniYaml(null, sequenceFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergeLiberal));
var partial = sequenceFiles
.Select(s => MiniYaml.FromFile(s))
.Aggregate(MiniYaml.MergePartial);
var sequences = new MiniYaml(null, MiniYaml.ApplyRemovals(partial));
var shadowIndex = new int[] { };
var nodesDict = sequences.ToDictionary();

View File

@@ -127,10 +127,11 @@ namespace OpenRA.Graphics
{
var sequenceFiles = modData.Manifest.Sequences;
var nodes = sequenceFiles
var partial = sequenceFiles
.Select(s => MiniYaml.FromFile(s))
.Aggregate(sequenceNodes, MiniYaml.MergeLiberal);
.Aggregate(sequenceNodes, MiniYaml.MergePartial);
var nodes = MiniYaml.ApplyRemovals(partial);
var items = new Dictionary<string, UnitSequences>();
foreach (var n in nodes)
{

View File

@@ -23,10 +23,11 @@ namespace OpenRA.Graphics
{
units = new Dictionary<string, Dictionary<string, Voxel>>();
var sequences = voxelFiles
var partial = voxelFiles
.Select(s => MiniYaml.FromFile(s))
.Aggregate(voxelNodes, MiniYaml.MergeLiberal);
.Aggregate(voxelNodes, MiniYaml.MergePartial);
var sequences = MiniYaml.ApplyRemovals(partial);
foreach (var s in sequences)
LoadVoxelsForUnit(s.Key, s.Value);

View File

@@ -262,17 +262,12 @@ namespace OpenRA
return FromLines(text.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries), fileName);
}
public static List<MiniYamlNode> MergeStrict(List<MiniYamlNode> a, List<MiniYamlNode> b)
public static List<MiniYamlNode> Merge(List<MiniYamlNode> a, List<MiniYamlNode> b)
{
return Merge(a, b, false);
return ApplyRemovals(MergePartial(a, b));
}
public static List<MiniYamlNode> MergeLiberal(List<MiniYamlNode> a, List<MiniYamlNode> b)
{
return Merge(a, b, true);
}
static List<MiniYamlNode> Merge(List<MiniYamlNode> a, List<MiniYamlNode> b, bool allowUnresolvedRemoves = false)
public static List<MiniYamlNode> MergePartial(List<MiniYamlNode> a, List<MiniYamlNode> b)
{
if (a.Count == 0)
return b;
@@ -286,58 +281,49 @@ namespace OpenRA
var dictB = b.ToDictionaryWithConflictLog(x => x.Key, "MiniYaml.Merge", null, x => "{0} (at {1})".F(x.Key, x.Location));
var allKeys = dictA.Keys.Union(dictB.Keys);
var keys = allKeys.Where(x => x.Length == 0 || x[0] != '-').ToList();
var removeKeys = allKeys.Where(x => x.Length > 0 && x[0] == '-')
.Select(k => k.Substring(1)).ToHashSet();
foreach (var key in keys)
foreach (var key in allKeys)
{
MiniYamlNode aa, bb;
dictA.TryGetValue(key, out aa);
dictB.TryGetValue(key, out bb);
if (removeKeys.Contains(key))
removeKeys.Remove(key);
else
{
var loc = aa == null ? default(MiniYamlNode.SourceLocation) : aa.Location;
var merged = (aa == null || bb == null) ? aa ?? bb : new MiniYamlNode(key, Merge(aa.Value, bb.Value, allowUnresolvedRemoves), loc);
ret.Add(merged);
}
}
if (removeKeys.Any())
{
if (allowUnresolvedRemoves)
{
// Add the removal nodes back for the next pass to deal with
foreach (var k in removeKeys)
{
var key = "-" + k;
MiniYamlNode rem;
if (!dictA.TryGetValue(key, out rem))
rem = dictB[key];
ret.Add(rem);
}
}
else
throw new YamlException("Bogus yaml removals: {0}".F(removeKeys.JoinWith(", ")));
var loc = aa == null ? default(MiniYamlNode.SourceLocation) : aa.Location;
var merged = (aa == null || bb == null) ? aa ?? bb : new MiniYamlNode(key, MergePartial(aa.Value, bb.Value), loc);
ret.Add(merged);
}
return ret;
}
public static MiniYaml MergeLiberal(MiniYaml a, MiniYaml b)
public static List<MiniYamlNode> ApplyRemovals(List<MiniYamlNode> a)
{
return Merge(a, b, true);
var removeKeys = a.Select(x => x.Key)
.Where(x => x.Length > 0 && x[0] == '-')
.Select(k => k.Substring(1))
.ToHashSet();
var ret = new List<MiniYamlNode>();
foreach (var x in a)
{
if (x.Key[0] == '-')
continue;
if (removeKeys.Contains(x.Key))
removeKeys.Remove(x.Key);
else
{
x.Value.Nodes = ApplyRemovals(x.Value.Nodes);
ret.Add(x);
}
}
if (removeKeys.Any())
throw new YamlException("Bogus yaml removals: {0}".F(removeKeys.JoinWith(", ")));
return ret;
}
public static MiniYaml MergeStrict(MiniYaml a, MiniYaml b)
{
return Merge(a, b, false);
}
static MiniYaml Merge(MiniYaml a, MiniYaml b, bool allowUnresolvedRemoves)
public static MiniYaml MergePartial(MiniYaml a, MiniYaml b)
{
if (a == null)
return b;
@@ -345,7 +331,18 @@ namespace OpenRA
if (b == null)
return a;
return new MiniYaml(a.Value ?? b.Value, Merge(a.Nodes, b.Nodes, allowUnresolvedRemoves));
return new MiniYaml(a.Value ?? b.Value, MergePartial(a.Nodes, b.Nodes));
}
public static MiniYaml Merge(MiniYaml a, MiniYaml b)
{
if (a == null)
return b;
if (b == null)
return a;
return new MiniYaml(a.Value ?? b.Value, Merge(a.Nodes, b.Nodes));
}
public IEnumerable<string> ToLines(string name)

View File

@@ -12,6 +12,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using OpenRA.FileSystem;
using OpenRA.Graphics;
using OpenRA.Widgets;
@@ -38,7 +39,12 @@ namespace OpenRA
{
Languages = new string[0];
Manifest = new Manifest(mod);
ObjectCreator = new ObjectCreator(Manifest);
// Allow mods to load types from the core Game assembly, and any additional assemblies they specify.
var assemblies =
new[] { typeof(Game).Assembly }.Concat(
Manifest.Assemblies.Select(path => Assembly.LoadFrom(Platform.ResolvePath(path))));
ObjectCreator = new ObjectCreator(assemblies);
Manifest.LoadCustomData(ObjectCreator);
if (useLoadScreen)
@@ -119,11 +125,10 @@ namespace OpenRA
return;
}
var yaml = Manifest.Translations.Select(MiniYaml.FromFile).Aggregate(MiniYaml.MergeLiberal);
Languages = yaml.Select(t => t.Key).ToArray();
yaml = MiniYaml.MergeLiberal(map.TranslationDefinitions, yaml);
var partial = Manifest.Translations.Select(MiniYaml.FromFile).Aggregate(MiniYaml.MergePartial);
Languages = partial.Select(t => t.Key).ToArray();
var yaml = MiniYaml.Merge(map.TranslationDefinitions, partial);
foreach (var y in yaml)
{
if (y.Key == Game.Settings.Graphics.Language)

View File

@@ -22,24 +22,11 @@ namespace OpenRA
readonly Cache<Type, ConstructorInfo> ctorCache;
readonly Pair<Assembly, string>[] assemblies;
public ObjectCreator(Manifest manifest)
public ObjectCreator(IEnumerable<Assembly> sourceAssemblies)
{
typeCache = new Cache<string, Type>(FindType);
ctorCache = new Cache<Type, ConstructorInfo>(GetCtor);
// All the core namespaces
var asms = typeof(Game).Assembly.GetNamespaces() // Game
.Select(c => Pair.New(typeof(Game).Assembly, c))
.ToList();
// Namespaces from each mod assembly
foreach (var a in manifest.Assemblies)
{
var asm = Assembly.LoadFile(Platform.ResolvePath(a));
asms.AddRange(asm.GetNamespaces().Select(ns => Pair.New(asm, ns)));
}
assemblies = asms.ToArray();
assemblies = sourceAssemblies.SelectMany(asm => asm.GetNamespaces().Select(ns => Pair.New(asm, ns))).ToArray();
}
public static Action<string> MissingTypeAction =

View File

@@ -20,9 +20,11 @@ namespace OpenRA.Widgets
public static void Initialize(IEnumerable<string> yaml)
{
data = new Dictionary<string, string>();
var metrics = yaml.Select(y => MiniYaml.FromFile(y))
.Aggregate(MiniYaml.MergeLiberal);
var partial = yaml
.Select(y => MiniYaml.FromFile(y))
.Aggregate(MiniYaml.MergePartial);
var metrics = MiniYaml.ApplyRemovals(partial);
foreach (var m in metrics)
foreach (var n in m.Value.Nodes)
data[n.Key] = n.Value.Value;