Rewrite yaml merger.

This commit is contained in:
Paul Chote
2016-01-30 03:04:34 +00:00
parent 1581ba951f
commit ab921682c4
15 changed files with 253 additions and 305 deletions

View File

@@ -31,30 +31,25 @@ namespace OpenRA
readonly TypeDictionary traits = new TypeDictionary();
List<ITraitInfo> constructOrderCache = null;
public ActorInfo(ObjectCreator creator, string name, MiniYaml node, Dictionary<string, MiniYaml> allUnits)
public ActorInfo(ObjectCreator creator, string name, MiniYaml node)
{
try
{
Name = name;
var allParents = new HashSet<string>();
var abstractActorType = name.StartsWith("^");
// Guard against circular inheritance
allParents.Add(name);
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(creator, t.Key.Split('@')[0], t.Value));
}
catch (FieldLoader.MissingFieldsException e)
{
if (!abstractActorType)
throw new YamlException(e.Message);
}
foreach (var t in node.Nodes)
{
try
{
traits.Add(LoadTraitInfo(creator, t.Key.Split('@')[0], t.Value));
}
catch (FieldLoader.MissingFieldsException e)
{
if (!abstractActorType)
throw new YamlException(e.Message);
}
}
}
catch (YamlException e)
{
@@ -69,36 +64,6 @@ namespace OpenRA
traits.Add(t);
}
static Dictionary<string, MiniYaml> GetParents(MiniYaml node, Dictionary<string, MiniYaml> allUnits)
{
return node.Nodes.Where(n => n.Key == "Inherits" || n.Key.StartsWith("Inherits@"))
.ToDictionary(n => n.Value.Value, n =>
{
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));
return i;
});
}
static MiniYaml MergeWithParents(MiniYaml node, Dictionary<string, MiniYaml> allUnits, HashSet<string> allParents)
{
var parents = GetParents(node, allUnits);
foreach (var kv in parents)
{
if (!allParents.Add(kv.Key))
throw new YamlException(
"Bogus inheritance -- duplicate inheritance of {0}.".F(kv.Key));
node = MiniYaml.MergePartial(node, MergeWithParents(kv.Value, allUnits, allParents));
}
return node;
}
static ITraitInfo LoadTraitInfo(ObjectCreator creator, string traitName, MiniYaml my)
{
if (!string.IsNullOrEmpty(my.Value))

View File

@@ -61,27 +61,27 @@ namespace OpenRA
using (new PerfTimer("Actors"))
actors = LoadYamlRules(actorCache, m.Rules,
map != null ? map.RuleDefinitions : NoMapRules,
(k, y) => new ActorInfo(Game.ModData.ObjectCreator, k.Key.ToLowerInvariant(), k.Value, y));
k => new ActorInfo(Game.ModData.ObjectCreator, k.Key.ToLowerInvariant(), k.Value));
using (new PerfTimer("Weapons"))
weapons = LoadYamlRules(weaponCache, m.Weapons,
map != null ? map.WeaponDefinitions : NoMapRules,
(k, _) => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value));
k => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value));
using (new PerfTimer("Voices"))
voices = LoadYamlRules(voiceCache, m.Voices,
map != null ? map.VoiceDefinitions : NoMapRules,
(k, _) => new SoundInfo(k.Value));
k => new SoundInfo(k.Value));
using (new PerfTimer("Notifications"))
notifications = LoadYamlRules(notificationCache, m.Notifications,
map != null ? map.NotificationDefinitions : NoMapRules,
(k, _) => new SoundInfo(k.Value));
k => new SoundInfo(k.Value));
using (new PerfTimer("Music"))
music = LoadYamlRules(musicCache, m.Music,
map != null ? map.MusicDefinitions : NoMapRules,
(k, _) => new MusicInfo(k.Key, k.Value));
k => new MusicInfo(k.Key, k.Value));
using (new PerfTimer("TileSets"))
tileSets = LoadTileSets(tileSetCache, sequenceCaches, m.TileSets);
@@ -93,33 +93,30 @@ namespace OpenRA
Dictionary<string, T> LoadYamlRules<T>(
Dictionary<string, T> itemCache,
string[] files, List<MiniYamlNode> nodes,
Func<MiniYamlNode, Dictionary<string, MiniYaml>, T> f)
Func<MiniYamlNode, T> f)
{
RaiseProgress();
var inputKey = string.Concat(string.Join("|", files), "|", nodes.WriteToString());
var partial = files
.Select(s => MiniYaml.FromFile(s))
.Aggregate(nodes, MiniYaml.MergePartial);
Func<MiniYamlNode, Dictionary<string, MiniYaml>, T> wrap = (wkv, wyy) =>
Func<MiniYamlNode, T> wrap = wkv =>
{
var key = inputKey + wkv.Value.ToLines(wkv.Key).JoinWith("|");
T t;
if (itemCache.TryGetValue(key, out t))
return t;
t = f(wkv, wyy);
t = f(wkv);
itemCache.Add(key, t);
RaiseProgress();
return t;
};
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);
var tree = MiniYaml.Merge(files.Select(MiniYaml.FromFile).Append(nodes))
.ToDictionaryWithConflictLog(n => n.Key, n => n.Value, "LoadYamlRules", null, null);
RaiseProgress();
var itemSet = tree.ToDictionary(kv => kv.Key.ToLowerInvariant(), kv => wrap(new MiniYamlNode(kv.Key, kv.Value)));
RaiseProgress();
return itemSet;
}