Changed MiniYaml.NodesDict property into a method.

Method is now called ToDictionary.
- Cached a few invocations into locals which should prevent some redundant evaluation.
- Added ToDictionary overloads that take projection functions for the keys and elements, since several callsites were doing a subsequent Linq.ToDictionary call to get this.
This commit is contained in:
RoosterDragon
2014-05-21 05:14:16 +01:00
parent 334a210231
commit 2e992a7310
21 changed files with 104 additions and 74 deletions

View File

@@ -88,7 +88,11 @@ namespace OpenRA.Editor
foreach (var init in Program.Rules.Actors[kv.Value.Type].GetInitKeys())
apd.AddRow(init.First,
apd.MakeEditorControl(init.Second,
() => objSaved.NodesDict.ContainsKey(init.First) ? objSaved.NodesDict[init.First].Value : null,
() =>
{
var nodesDict = objSaved.ToDictionary();
return nodesDict.ContainsKey(init.First) ? nodesDict[init.First].Value : null;
},
_ => { }));
apd.ShowDialog();

View File

@@ -33,7 +33,7 @@ namespace OpenRA
{
try
{
var mergedNode = MergeWithParent(node, allUnits).NodesDict;
var mergedNode = MergeWithParent(node, allUnits).ToDictionary();
Name = name;
foreach (var t in mergedNode)
@@ -49,7 +49,7 @@ namespace OpenRA
static MiniYaml GetParent( MiniYaml node, Dictionary<string, MiniYaml> allUnits )
{
MiniYaml inherits;
node.NodesDict.TryGetValue( "Inherits", out inherits );
node.ToDictionary().TryGetValue( "Inherits", out inherits );
if( inherits == null || string.IsNullOrEmpty( inherits.Value ) )
return null;

View File

@@ -24,7 +24,7 @@ namespace OpenRA.GameRules
{
Title = value.Value;
var nd = value.NodesDict;
var nd = value.ToDictionary();
var ext = nd.ContainsKey("Extension") ? nd["Extension"].Value : "aud";
Filename = (nd.ContainsKey("Filename") ? nd["Filename"].Value : key)+"."+ext;
if (!GlobalFileSystem.Exists(Filename))

View File

@@ -28,10 +28,9 @@ namespace OpenRA.GameRules
static Dictionary<string, string[]> Load(MiniYaml y, string name)
{
return y.NodesDict.ContainsKey(name)
? y.NodesDict[name].NodesDict.ToDictionary(
a => a.Key,
a => FieldLoader.GetValue<string[]>("(value)", a.Value.Value))
var nd = y.ToDictionary();
return nd.ContainsKey(name)
? nd[name].ToDictionary(my => FieldLoader.GetValue<string[]>("(value)", my.Value))
: new Dictionary<string, string[]>();
}

View File

@@ -73,10 +73,9 @@ namespace OpenRA.GameRules
static object LoadVersus(MiniYaml y)
{
return y.NodesDict.ContainsKey("Versus")
? y.NodesDict["Versus"].NodesDict.ToDictionary(
a => a.Key,
a => FieldLoader.GetValue<float>("(value)", a.Value.Value))
var nd = y.ToDictionary();
return nd.ContainsKey("Versus")
? nd["Versus"].ToDictionary(my => FieldLoader.GetValue<float>("(value)", my.Value))
: new Dictionary<string, float>();
}
}
@@ -126,7 +125,7 @@ namespace OpenRA.GameRules
static object LoadProjectile(MiniYaml yaml)
{
MiniYaml proj;
if (!yaml.NodesDict.TryGetValue("Projectile", out proj))
if (!yaml.ToDictionary().TryGetValue("Projectile", out proj))
return null;
var ret = Game.CreateObject<IProjectileInfo>(proj.Value + "Info");
FieldLoader.Load(ret, proj);

View File

@@ -31,20 +31,20 @@ namespace OpenRA.Graphics
var sequences = new MiniYaml(null, sequenceFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergeLiberal));
var shadowIndex = new int[] { };
if (sequences.NodesDict.ContainsKey("ShadowIndex"))
var nodesDict = sequences.ToDictionary();
if (nodesDict.ContainsKey("ShadowIndex"))
{
Array.Resize(ref shadowIndex, shadowIndex.Length + 1);
Exts.TryParseIntegerInvariant(sequences.NodesDict["ShadowIndex"].Value,
Exts.TryParseIntegerInvariant(nodesDict["ShadowIndex"].Value,
out shadowIndex[shadowIndex.Length - 1]);
}
palette = new HardwarePalette();
foreach (var p in sequences.NodesDict["Palettes"].Nodes)
foreach (var p in nodesDict["Palettes"].Nodes)
palette.AddPalette(p.Key, new Palette(GlobalFileSystem.Open(p.Value.Value), shadowIndex), false);
var spriteLoader = new SpriteLoader(new string[0], new SheetBuilder(SheetType.Indexed));
foreach (var s in sequences.NodesDict["Cursors"].Nodes)
foreach (var s in nodesDict["Cursors"].Nodes)
LoadSequencesForCursor(spriteLoader, s.Key, s.Value);
palette.Initialize();

View File

@@ -28,7 +28,7 @@ namespace OpenRA.Graphics
public CursorSequence(SpriteLoader loader, string cursorSrc, string palette, MiniYaml info)
{
sprites = loader.LoadAllSprites(cursorSrc);
var d = info.NodesDict;
var d = info.ToDictionary();
start = Exts.ParseIntegerInvariant(d["start"].Value);
this.palette = palette;

View File

@@ -33,7 +33,7 @@ namespace OpenRA.Graphics
{
var srcOverride = info.Value;
Name = name;
var d = info.NodesDict;
var d = info.ToDictionary();
var offset = float2.Zero;
var blendMode = BlendMode.Alpha;

View File

@@ -118,7 +118,7 @@ namespace OpenRA.Graphics
else
{
t = Exts.Lazy(() => (IReadOnlyDictionary<string, Sequence>)new ReadOnlyDictionary<string, Sequence>(
node.Value.NodesDict.ToDictionary(x => x.Key, x =>
node.Value.ToDictionary().ToDictionary(x => x.Key, x =>
{
using (new Support.PerfTimer("new Sequence(\"{0}\")".F(node.Key), 20))
return new Sequence(spriteLoader.Value, node.Key, x.Key, x.Value);

View File

@@ -33,7 +33,7 @@ namespace OpenRA.Graphics
Game.modData.VoxelLoader.RefreshBuffer();
}
static Voxel LoadVoxel(string unit, string name, MiniYaml info)
static Voxel LoadVoxel(string unit, MiniYaml info)
{
var vxl = unit;
var hva = unit;
@@ -55,7 +55,7 @@ namespace OpenRA.Graphics
Game.modData.LoadScreen.Display();
try
{
var seq = sequences.NodesDict.ToDictionary(x => x.Key, x => LoadVoxel(unit,x.Key,x.Value));
var seq = sequences.ToDictionary(my => LoadVoxel(unit, my));
units.Add(unit, seq);
}
catch (FileNotFoundException) {} // Do nothing; we can crash later if we actually wanted art

View File

@@ -37,7 +37,7 @@ namespace OpenRA
public Manifest(string mod)
{
var path = new[] { "mods", mod, "mod.yaml" }.Aggregate(Path.Combine);
var yaml = new MiniYaml(null, MiniYaml.FromFile(path)).NodesDict;
var yaml = new MiniYaml(null, MiniYaml.FromFile(path)).ToDictionary();
Mod = FieldLoader.Load<ModMetadata>(yaml["Metadata"]);
Mod.Id = mod;
@@ -68,9 +68,11 @@ namespace OpenRA
LoadScreen = yaml["LoadScreen"];
LobbyDefaults = yaml["LobbyDefaults"];
Fonts = yaml["Fonts"].NodesDict.ToDictionary(x => x.Key,
x => Pair.New(x.Value.NodesDict["Font"].Value,
Exts.ParseIntegerInvariant(x.Value.NodesDict["Size"].Value)));
Fonts = yaml["Fonts"].ToDictionary(my =>
{
var nd = my.ToDictionary();
return Pair.New(nd["Font"].Value, Exts.ParseIntegerInvariant(nd["Size"].Value));
});
if (yaml.ContainsKey("TileSize"))
TileSize = FieldLoader.GetValue<Size>("TileSize", yaml["TileSize"].Value);
@@ -94,7 +96,7 @@ namespace OpenRA
if (!yaml.ContainsKey(key))
return new string[] { };
return yaml[key].NodesDict.Keys.ToArray();
return yaml[key].ToDictionary().Keys.ToArray();
}
static IReadOnlyDictionary<string, string> YamlDictionary(Dictionary<string, MiniYaml> yaml, string key)
@@ -102,7 +104,7 @@ namespace OpenRA
if (!yaml.ContainsKey(key))
return new ReadOnlyDictionary<string, string>();
var inner = yaml[key].NodesDict.ToDictionary(x => x.Key, x => x.Value.Value);
var inner = yaml[key].ToDictionary(my => my.Value);
return new ReadOnlyDictionary<string, string>(inner);
}
}

View File

@@ -80,8 +80,9 @@ namespace OpenRA
static object LoadOptions(MiniYaml y)
{
var options = new MapOptions();
if (y.NodesDict.ContainsKey("Options"))
FieldLoader.Load(options, y.NodesDict["Options"]);
var nodesDict = y.ToDictionary();
if (nodesDict.ContainsKey("Options"))
FieldLoader.Load(options, nodesDict["Options"]);
return options;
}
@@ -185,18 +186,20 @@ namespace OpenRA
RequiresMod = upgradeForMod;
}
var nd = yaml.ToDictionary();
// Load players
foreach (var kv in yaml.NodesDict["Players"].NodesDict)
foreach (var my in nd["Players"].ToDictionary().Values)
{
var player = new PlayerReference(kv.Value);
var player = new PlayerReference(my);
Players.Add(player.Name, player);
}
Actors = Exts.Lazy(() =>
{
var ret = new Dictionary<string, ActorReference>();
foreach (var kv in yaml.NodesDict["Actors"].NodesDict)
ret.Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.NodesDict));
foreach (var kv in nd["Actors"].ToDictionary())
ret.Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.ToDictionary()));
return ret;
});
@@ -204,9 +207,9 @@ namespace OpenRA
Smudges = Exts.Lazy(() =>
{
var ret = new List<SmudgeReference>();
foreach (var kv in yaml.NodesDict["Smudges"].NodesDict)
foreach (var name in nd["Smudges"].ToDictionary().Keys)
{
var vals = kv.Key.Split(' ');
var vals = name.Split(' ');
var loc = vals[1].Split(',');
ret.Add(new SmudgeReference(vals[0], new int2(
Exts.ParseIntegerInvariant(loc[0]),

View File

@@ -56,9 +56,9 @@ namespace OpenRA
static object LoadTiles(MiniYaml y)
{
return y.NodesDict["Tiles"].NodesDict.ToDictionary(
t => byte.Parse(t.Key),
t => t.Value.Value);
return y.ToDictionary()["Tiles"].ToDictionary(
name => byte.Parse(name),
my => my.Value);
}
static readonly string[] Fields = { "Id", "Image", "Frames", "Size", "PickAny" };
@@ -105,11 +105,11 @@ namespace OpenRA
FieldLoader.Load(this, yaml["General"]);
// TerrainTypes
Terrain = yaml["Terrain"].NodesDict.Values
Terrain = yaml["Terrain"].ToDictionary().Values
.Select(y => new TerrainTypeInfo(y)).ToDictionary(t => t.Type);
// Templates
Templates = yaml["Templates"].NodesDict.Values
Templates = yaml["Templates"].ToDictionary().Values
.Select(y => new TileTemplate(y)).ToDictionary(t => t.Id);
}

View File

@@ -83,23 +83,39 @@ namespace OpenRA
public class MiniYaml
{
static Func<string, string> StringIdentity = s => s;
static Func<MiniYaml, MiniYaml> MiniYamlIdentity = my => my;
public string Value;
public List<MiniYamlNode> Nodes;
public Dictionary<string, MiniYaml> NodesDict
public Dictionary<string, MiniYaml> ToDictionary()
{
get
{
var ret = new Dictionary<string, MiniYaml>();
foreach (var y in Nodes)
{
if (ret.ContainsKey(y.Key))
throw new InvalidDataException("Duplicate key `{0}' in {1}".F(y.Key, y.Location));
ret.Add(y.Key, y.Value);
}
return ToDictionary(MiniYamlIdentity);
}
return ret;
public Dictionary<string, TElement> ToDictionary<TElement>(Func<MiniYaml, TElement> elementSelector)
{
return ToDictionary(StringIdentity, elementSelector);
}
public Dictionary<TKey, TElement> ToDictionary<TKey, TElement>(
Func<string, TKey> keySelector, Func<MiniYaml, TElement> elementSelector)
{
var ret = new Dictionary<TKey, TElement>();
foreach (var y in Nodes)
{
var key = keySelector(y.Key);
var element = elementSelector(y.Value);
try
{
ret.Add(key, element);
}
catch (ArgumentException ex)
{
throw new InvalidDataException("Duplicate key `{0}' in {1}".F(y.Key, y.Location), ex);
}
}
return ret;
}
public MiniYaml(string value) : this(value, null) { }
@@ -122,7 +138,8 @@ namespace OpenRA
public static List<MiniYamlNode> NodesOrEmpty(MiniYaml y, string s)
{
return y.NodesDict.ContainsKey(s) ? y.NodesDict[s].Nodes : new List<MiniYamlNode>();
var nd = y.ToDictionary();
return nd.ContainsKey(s) ? nd[s].Nodes : new List<MiniYamlNode>();
}
static List<MiniYamlNode> FromLines(string[] lines, string filename)

View File

@@ -38,7 +38,7 @@ namespace OpenRA
Manifest = new Manifest(mod);
ObjectCreator = new ObjectCreator(Manifest);
LoadScreen = ObjectCreator.CreateObject<ILoadScreen>(Manifest.LoadScreen.Value);
LoadScreen.Init(Manifest, Manifest.LoadScreen.NodesDict.ToDictionary(x => x.Key, x => x.Value.Value));
LoadScreen.Init(Manifest, Manifest.LoadScreen.ToDictionary(my => my.Value));
LoadScreen.Display();
WidgetLoader = new WidgetLoader(this);
RulesetCache = new RulesetCache(this);
@@ -96,9 +96,9 @@ namespace OpenRA
foreach (var y in yaml)
{
if (y.Key == Game.Settings.Graphics.Language)
selectedTranslations = y.Value.NodesDict.ToDictionary(x => x.Key, x => x.Value.Value ?? "");
if (y.Key == Game.Settings.Graphics.DefaultLanguage)
defaultTranslations = y.Value.NodesDict.ToDictionary(x => x.Key, x => x.Value.Value ?? "");
selectedTranslations = y.Value.ToDictionary(my => my.Value ?? "");
else if (y.Key == Game.Settings.Graphics.DefaultLanguage)
defaultTranslations = y.Value.ToDictionary(my => my.Value ?? "");
}
var translations = new Dictionary<string, string>();

View File

@@ -34,10 +34,11 @@ namespace OpenRA
continue;
var yaml = new MiniYaml(null, MiniYaml.FromFile(yamlPath));
if (!yaml.NodesDict.ContainsKey("Metadata"))
var nd = yaml.ToDictionary();
if (!nd.ContainsKey("Metadata"))
continue;
var mod = FieldLoader.Load<ModMetadata>(yaml.NodesDict["Metadata"]);
var mod = FieldLoader.Load<ModMetadata>(nd["Metadata"]);
mod.Id = m;
ret.Add(m, mod);

View File

@@ -68,10 +68,9 @@ namespace OpenRA.Mods.RA.AI
static object LoadList<T>(MiniYaml y, string field)
{
return y.NodesDict.ContainsKey(field)
? y.NodesDict[field].NodesDict.ToDictionary(
a => a.Key,
a => FieldLoader.GetValue<T>(field, a.Value.Value))
var nd = y.ToDictionary();
return nd.ContainsKey(field)
? nd[field].ToDictionary(my => FieldLoader.GetValue<T>(field, my.Value))
: new Dictionary<string, T>();
}

View File

@@ -41,11 +41,12 @@ namespace OpenRA.Mods.RA.Move
static object LoadSpeeds(MiniYaml y)
{
Dictionary<string, TerrainInfo> ret = new Dictionary<string, TerrainInfo>();
foreach (var t in y.NodesDict["TerrainSpeeds"].Nodes)
foreach (var t in y.ToDictionary()["TerrainSpeeds"].Nodes)
{
var speed = FieldLoader.GetValue<decimal>("speed", t.Value.Value);
var cost = t.Value.NodesDict.ContainsKey("PathingCost")
? FieldLoader.GetValue<int>("cost", t.Value.NodesDict["PathingCost"].Value)
var nodesDict = t.Value.ToDictionary();
var cost = nodesDict.ContainsKey("PathingCost")
? FieldLoader.GetValue<int>("cost", nodesDict["PathingCost"].Value)
: (int)(10000 / speed);
ret.Add(t.Key, new TerrainInfo { Speed = speed, Cost = cost });
}

View File

@@ -193,12 +193,17 @@ namespace OpenRA.Mods.RA.Widgets.Logic
static IEnumerable<NewsItem> ReadNews(byte[] bytes)
{
var str = Encoding.UTF8.GetString(bytes);
return MiniYaml.FromString(str).Select(node => new NewsItem
return MiniYaml.FromString(str).Select(node =>
{
Title = node.Value.NodesDict["Title"].Value,
Author = node.Value.NodesDict["Author"].Value,
DateTime = FieldLoader.GetValue<DateTime>("DateTime", node.Key),
Content = node.Value.NodesDict["Content"].Value
var nodesDict = node.Value.ToDictionary();
return new NewsItem
{
Title = nodesDict["Title"].Value,
Author = nodesDict["Author"].Value,
DateTime = FieldLoader.GetValue<DateTime>("DateTime", node.Key),
Content = nodesDict["Content"].Value
};
});
}

View File

@@ -45,7 +45,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
description = widget.Get<LabelWidget>("MISSION_DESCRIPTION");
descriptionFont = Game.Renderer.Fonts[description.Font];
var yaml = new MiniYaml(null, Game.modData.Manifest.Missions.Select(MiniYaml.FromFile).Aggregate(MiniYaml.MergeLiberal)).NodesDict;
var yaml = new MiniYaml(null, Game.modData.Manifest.Missions.Select(MiniYaml.FromFile).Aggregate(MiniYaml.MergeLiberal)).ToDictionary();
var missionMapPaths = yaml["Missions"].Nodes.Select(n => Path.GetFullPath(n.Key));

View File

@@ -82,7 +82,7 @@ namespace OpenRA.TilesetBuilder
int size = int.Parse(tsize);
var yaml = MiniYaml.DictFromFile("OpenRA.TilesetBuilder/defaults.yaml");
terrainDefinition = yaml["Terrain"].NodesDict.Values.Select(y => new TerrainTypeInfo(y)).ToDictionary(t => t.Type);
terrainDefinition = yaml["Terrain"].ToDictionary().Values.Select(y => new TerrainTypeInfo(y)).ToDictionary(t => t.Type);
int i = 0;
surface1.Icon = new Bitmap[terrainDefinition.Keys.Count];
TerrainType = new TerrainTypeInfo[terrainDefinition.Keys.Count];