Better caching for Rules and Sequences
Refactored the Rules and SequenceProvider classes to be parts of ModData and maintain a cache of the instances used in the mod. The caching reduced the load times a lot, especially after the first load. Some lazy loading in sequences also helped lower the startup time.. Note: The static classes were left behind to redirect the existing code's calls.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
@@ -13,45 +13,79 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Primitives;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public static class SequenceProvider
|
||||
{
|
||||
static Dictionary<string, Dictionary<string, Sequence>> units;
|
||||
|
||||
public static void Initialize(string[] sequenceFiles, List<MiniYamlNode> sequenceNodes)
|
||||
public static Sequence GetSequence(string unitName, string sequenceName)
|
||||
{
|
||||
units = new Dictionary<string, Dictionary<string, Sequence>>();
|
||||
return Game.modData.SequenceProvider.GetSequence(unitName, sequenceName);
|
||||
}
|
||||
|
||||
var sequences = sequenceFiles
|
||||
public static bool HasSequence(string unitName, string sequenceName)
|
||||
{
|
||||
return Game.modData.SequenceProvider.HasSequence(unitName, sequenceName);
|
||||
}
|
||||
|
||||
public static IEnumerable<string> Sequences(string unitName)
|
||||
{
|
||||
return Game.modData.SequenceProvider.Sequences(unitName);
|
||||
}
|
||||
}
|
||||
|
||||
public class ModSequenceProvider
|
||||
{
|
||||
readonly ModData modData;
|
||||
|
||||
readonly Dictionary<string, Lazy<Dictionary<string, Sequence>>> sequenceCache = new Dictionary<string, Lazy<Dictionary<string, Sequence>>>();
|
||||
Dictionary<string, Lazy<Dictionary<string, Sequence>>> sequences;
|
||||
|
||||
public ModSequenceProvider(ModData modData)
|
||||
{
|
||||
this.modData = modData;
|
||||
}
|
||||
|
||||
public void ActivateMap(Map map)
|
||||
{
|
||||
sequences = Load(modData.Manifest.Sequences, map.Sequences);
|
||||
}
|
||||
|
||||
public Dictionary<string, Lazy<Dictionary<string, Sequence>>> Load(string[] sequenceFiles, List<MiniYamlNode> sequenceNodes)
|
||||
{
|
||||
Game.modData.LoadScreen.Display();
|
||||
|
||||
var nodes = sequenceFiles
|
||||
.Select(s => MiniYaml.FromFile(s))
|
||||
.Aggregate(sequenceNodes, MiniYaml.MergeLiberal);
|
||||
|
||||
foreach (var s in sequences)
|
||||
LoadSequencesForUnit(s.Key, s.Value);
|
||||
}
|
||||
|
||||
static void LoadSequencesForUnit(string unit, MiniYaml sequences)
|
||||
{
|
||||
Game.modData.LoadScreen.Display();
|
||||
try
|
||||
var items = new Dictionary<string, Lazy<Dictionary<string, Sequence>>>();
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
var seq = sequences.NodesDict.ToDictionary(x => x.Key, x => new Sequence(unit,x.Key,x.Value));
|
||||
units.Add(unit, seq);
|
||||
var key = node.Value.ToLines(node.Key).JoinWith("|");
|
||||
Lazy<Dictionary<string, Sequence>> t;
|
||||
if (sequenceCache.TryGetValue(key, out t))
|
||||
{
|
||||
items.Add(node.Key, t);
|
||||
}
|
||||
else
|
||||
{
|
||||
t = Exts.Lazy(() => node.Value.NodesDict.ToDictionary(x => x.Key, x => new Sequence(node.Key, x.Key, x.Value)));
|
||||
sequenceCache.Add(key, t);
|
||||
items.Add(node.Key, t);
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
// Do nothing; we can crash later if we actually wanted art
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
public static Sequence GetSequence(string unitName, string sequenceName)
|
||||
public Sequence GetSequence(string unitName, string sequenceName)
|
||||
{
|
||||
try { return units[unitName][sequenceName]; }
|
||||
try { return sequences[unitName].Value[sequenceName]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
if (units.ContainsKey(unitName))
|
||||
if (sequences.ContainsKey(unitName))
|
||||
throw new InvalidOperationException(
|
||||
"Unit `{0}` does not have a sequence `{1}`".F(unitName, sequenceName));
|
||||
else
|
||||
@@ -60,22 +94,22 @@ namespace OpenRA.Graphics
|
||||
}
|
||||
}
|
||||
|
||||
public static bool HasSequence(string unit, string seq)
|
||||
public bool HasSequence(string unitName, string sequenceName)
|
||||
{
|
||||
if (!units.ContainsKey(unit))
|
||||
if (!sequences.ContainsKey(unitName))
|
||||
throw new InvalidOperationException(
|
||||
"Unit `{0}` does not have sequence `{1}` defined.".F(unit, seq));
|
||||
"Unit `{0}` does not have sequence `{1}` defined.".F(unitName, sequenceName));
|
||||
|
||||
return units[unit].ContainsKey(seq);
|
||||
return sequences[unitName].Value.ContainsKey(sequenceName);
|
||||
}
|
||||
|
||||
public static IEnumerable<string> Sequences(string unit)
|
||||
public IEnumerable<string> Sequences(string unitName)
|
||||
{
|
||||
if (!units.ContainsKey(unit))
|
||||
if (!sequences.ContainsKey(unitName))
|
||||
throw new InvalidOperationException(
|
||||
"Unit `{0}` does not have all sequences defined.".F(unit));
|
||||
"Unit `{0}` does not have all sequences defined.".F(unitName));
|
||||
|
||||
return units[unit].Keys;
|
||||
return sequences[unitName].Value.Keys;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user