Support multiple inheritance for actor rules.

This commit is contained in:
Paul Chote
2015-04-22 19:27:26 +12:00
parent 8de497925d
commit 2cbe269c1e

View File

@@ -33,11 +33,22 @@ namespace OpenRA
{ {
try try
{ {
var mergedNode = MergeWithParent(node, allUnits).ToDictionary(); var allParents = new HashSet<string>();
// Guard against circular inheritance
allParents.Add(name);
var mergedNode = MergeWithParents(node, allUnits, allParents).ToDictionary();
Name = name; Name = name;
foreach (var t in mergedNode) foreach (var t in mergedNode)
Traits.Add(LoadTraitInfo(t.Key.Split('@')[0], t.Value)); {
if (t.Key[0] == '-')
throw new YamlException("Bogus trait removal: " + t.Key);
if (t.Key != "Inherits" && !t.Key.StartsWith("Inherits@"))
Traits.Add(LoadTraitInfo(t.Key.Split('@')[0], t.Value));
}
} }
catch (YamlException e) catch (YamlException e)
{ {
@@ -45,31 +56,31 @@ namespace OpenRA
} }
} }
static MiniYaml GetParent(MiniYaml node, Dictionary<string, MiniYaml> allUnits) static Dictionary<string, MiniYaml> GetParents(MiniYaml node, Dictionary<string, MiniYaml> allUnits)
{ {
MiniYaml inherits; return node.Nodes.Where(n => n.Key == "Inherits" || n.Key.StartsWith("Inherits@"))
node.ToDictionary().TryGetValue("Inherits", out inherits); .ToDictionary(n => n.Value.Value, n =>
if (inherits == null || string.IsNullOrEmpty(inherits.Value)) {
return null; MiniYaml i;
if (!allUnits.TryGetValue(n.Value.Value, out i))
throw new YamlException(
"Bogus inheritance -- parent type {0} does not exist".F(n.Value.Value));
MiniYaml parent; return i;
allUnits.TryGetValue(inherits.Value, out parent); });
if (parent == null)
throw new InvalidOperationException(
"Bogus inheritance -- actor type {0} does not exist".F(inherits.Value));
return parent;
} }
static MiniYaml MergeWithParent(MiniYaml node, Dictionary<string, MiniYaml> allUnits) static MiniYaml MergeWithParents(MiniYaml node, Dictionary<string, MiniYaml> allUnits, HashSet<string> allParents)
{ {
var parent = GetParent(node, allUnits); var parents = GetParents(node, allUnits);
if (parent != null)
{
var result = MiniYaml.MergeStrict(node, MergeWithParent(parent, allUnits));
result.Nodes.RemoveAll(a => a.Key == "Inherits"); foreach (var kv in parents)
return result; {
if (!allParents.Add(kv.Key))
throw new YamlException(
"Bogus inheritance -- duplicate inheritance of {0}.".F(kv.Key));
node = MiniYaml.MergeStrict(node, MergeWithParents(kv.Value, allUnits, allParents));
} }
return node; return node;