Process shared map includes as part of the mod rules.
This ensures that they are only updated once instead of repeating the updates for every map that includes them.
This commit is contained in:
@@ -21,7 +21,10 @@ namespace OpenRA.Mods.Common.UpdateRules
|
||||
|
||||
public static class UpdateUtils
|
||||
{
|
||||
static YamlFileSet LoadYaml(ModData modData, IEnumerable<string> files)
|
||||
/// <summary>
|
||||
/// Loads a YamlFileSet from a list of mod files.
|
||||
/// </summary>
|
||||
static YamlFileSet LoadModYaml(ModData modData, IEnumerable<string> files)
|
||||
{
|
||||
var yaml = new YamlFileSet();
|
||||
foreach (var filename in files)
|
||||
@@ -40,7 +43,22 @@ namespace OpenRA.Mods.Common.UpdateRules
|
||||
return yaml;
|
||||
}
|
||||
|
||||
static YamlFileSet LoadMapYaml(ModData modData, IReadWritePackage mapPackage, MiniYaml yaml)
|
||||
/// <summary>
|
||||
/// Loads a YamlFileSet containing any external yaml definitions referenced by a map yaml block.
|
||||
/// </summary>
|
||||
static YamlFileSet LoadExternalMapYaml(ModData modData, MiniYaml yaml)
|
||||
{
|
||||
return FieldLoader.GetValue<string[]>("value", yaml.Value)
|
||||
.Where(f => f.Contains("|"))
|
||||
.SelectMany(f => LoadModYaml(modData, new[] { f }))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads a YamlFileSet containing any internal definitions yaml referenced by a map yaml block.
|
||||
/// External references or internal references to missing files are ignored.
|
||||
/// </summary>
|
||||
static YamlFileSet LoadInternalMapYaml(ModData modData, IReadWritePackage mapPackage, MiniYaml yaml, HashSet<string> externalFilenames)
|
||||
{
|
||||
var fileSet = new YamlFileSet()
|
||||
{
|
||||
@@ -50,20 +68,27 @@ namespace OpenRA.Mods.Common.UpdateRules
|
||||
var files = FieldLoader.GetValue<string[]>("value", yaml.Value);
|
||||
foreach (var filename in files)
|
||||
{
|
||||
// Ignore any files that aren't in the map bundle
|
||||
if (!filename.Contains("|") && mapPackage.Contains(filename))
|
||||
fileSet.Add(Tuple.Create(mapPackage, filename, MiniYaml.FromStream(mapPackage.GetStream(filename), filename)));
|
||||
else
|
||||
fileSet.AddRange(LoadYaml(modData, new[] { filename }));
|
||||
else if (modData.ModFiles.Exists(filename))
|
||||
externalFilenames.Add(filename);
|
||||
}
|
||||
|
||||
return fileSet;
|
||||
}
|
||||
|
||||
public static List<string> UpdateMap(ModData modData, IReadWritePackage mapPackage, UpdateRule rule, out YamlFileSet files)
|
||||
/// <summary>
|
||||
/// Run a given update rule on a map.
|
||||
/// The rule is only applied to internal files - external includes are assumed to be handled separately
|
||||
/// but are noted in the externalFilenames list for informational purposes.
|
||||
/// </summary>
|
||||
public static List<string> UpdateMap(ModData modData, IReadWritePackage mapPackage, UpdateRule rule, out YamlFileSet files, HashSet<string> externalFilenames)
|
||||
{
|
||||
var manualSteps = new List<string>();
|
||||
|
||||
var mapStream = mapPackage.GetStream("map.yaml");
|
||||
using (var mapStream = mapPackage.GetStream("map.yaml"))
|
||||
{
|
||||
if (mapStream == null)
|
||||
{
|
||||
// Not a valid map
|
||||
@@ -79,7 +104,7 @@ namespace OpenRA.Mods.Common.UpdateRules
|
||||
var mapRulesNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Rules");
|
||||
if (mapRulesNode != null)
|
||||
{
|
||||
var mapRules = LoadMapYaml(modData, mapPackage, mapRulesNode.Value);
|
||||
var mapRules = LoadInternalMapYaml(modData, mapPackage, mapRulesNode.Value, externalFilenames);
|
||||
manualSteps.AddRange(ApplyTopLevelTransform(modData, mapRules, rule.UpdateActorNode));
|
||||
files.AddRange(mapRules);
|
||||
}
|
||||
@@ -87,12 +112,13 @@ namespace OpenRA.Mods.Common.UpdateRules
|
||||
var mapWeaponsNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Weapons");
|
||||
if (mapWeaponsNode != null)
|
||||
{
|
||||
var mapWeapons = LoadMapYaml(modData, mapPackage, mapWeaponsNode.Value);
|
||||
var mapWeapons = LoadInternalMapYaml(modData, mapPackage, mapWeaponsNode.Value, externalFilenames);
|
||||
manualSteps.AddRange(ApplyTopLevelTransform(modData, mapWeapons, rule.UpdateWeaponNode));
|
||||
files.AddRange(mapWeapons);
|
||||
}
|
||||
|
||||
manualSteps.AddRange(rule.AfterUpdate(modData));
|
||||
}
|
||||
|
||||
return manualSteps;
|
||||
}
|
||||
@@ -100,10 +126,33 @@ namespace OpenRA.Mods.Common.UpdateRules
|
||||
public static List<string> UpdateMod(ModData modData, UpdateRule rule, out YamlFileSet files)
|
||||
{
|
||||
var manualSteps = new List<string>();
|
||||
var modRules = LoadYaml(modData, modData.Manifest.Rules);
|
||||
var modWeapons = LoadYaml(modData, modData.Manifest.Weapons);
|
||||
var modTilesets = LoadYaml(modData, modData.Manifest.TileSets);
|
||||
var modChromeLayout = LoadYaml(modData, modData.Manifest.ChromeLayout);
|
||||
var modRules = LoadModYaml(modData, modData.Manifest.Rules);
|
||||
var modWeapons = LoadModYaml(modData, modData.Manifest.Weapons);
|
||||
var modTilesets = LoadModYaml(modData, modData.Manifest.TileSets);
|
||||
var modChromeLayout = LoadModYaml(modData, modData.Manifest.ChromeLayout);
|
||||
|
||||
// Find and add shared map includes
|
||||
foreach (var package in modData.MapCache.EnumerateMapPackagesWithoutCaching())
|
||||
{
|
||||
using (var mapStream = package.GetStream("map.yaml"))
|
||||
{
|
||||
if (mapStream == null)
|
||||
continue;
|
||||
|
||||
var yaml = new MiniYaml(null, MiniYaml.FromStream(mapStream, package.Name));
|
||||
var mapRulesNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Rules");
|
||||
if (mapRulesNode != null)
|
||||
foreach (var f in LoadExternalMapYaml(modData, mapRulesNode.Value))
|
||||
if (!modRules.Any(m => m.Item1 == f.Item1 && m.Item2 == f.Item2))
|
||||
modRules.Add(f);
|
||||
|
||||
var mapWeaponsNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Weapons");
|
||||
if (mapWeaponsNode != null)
|
||||
foreach (var f in LoadExternalMapYaml(modData, mapWeaponsNode.Value))
|
||||
if (!modWeapons.Any(m => m.Item1 == f.Item1 && m.Item2 == f.Item2))
|
||||
modWeapons.Add(f);
|
||||
}
|
||||
}
|
||||
|
||||
manualSteps.AddRange(rule.BeforeUpdate(modData));
|
||||
manualSteps.AddRange(ApplyTopLevelTransform(modData, modRules, rule.UpdateActorNode));
|
||||
|
||||
@@ -82,9 +82,10 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
||||
|
||||
Console.Write(" Updating map... ");
|
||||
|
||||
var externalFilenames = new HashSet<string>();
|
||||
try
|
||||
{
|
||||
manualSteps = UpdateUtils.UpdateMap(modData, mapPackage, rule, out mapFiles);
|
||||
manualSteps = UpdateUtils.UpdateMap(modData, mapPackage, rule, out mapFiles, externalFilenames);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -104,6 +105,13 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
||||
mapFiles.Save();
|
||||
Console.WriteLine("COMPLETE");
|
||||
|
||||
if (externalFilenames.Any())
|
||||
{
|
||||
Console.WriteLine(" The following shared yaml files referenced by the map have been ignored:");
|
||||
Console.WriteLine(UpdateUtils.FormatMessageList(externalFilenames, 1));
|
||||
Console.WriteLine(" These files are assumed to have already been updated by the --update-mod command");
|
||||
}
|
||||
|
||||
if (manualSteps.Any())
|
||||
{
|
||||
Console.WriteLine(" Manual changes are required to complete this update:");
|
||||
|
||||
@@ -146,15 +146,17 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
||||
}
|
||||
|
||||
Console.Write(" Updating system maps... ");
|
||||
|
||||
if (!skipMaps)
|
||||
{
|
||||
var mapsFailed = false;
|
||||
var externalFilenames = new HashSet<string>();
|
||||
foreach (var package in modData.MapCache.EnumerateMapPackagesWithoutCaching())
|
||||
{
|
||||
try
|
||||
{
|
||||
YamlFileSet mapFiles;
|
||||
var mapSteps = UpdateUtils.UpdateMap(modData, package, rule, out mapFiles);
|
||||
var mapSteps = UpdateUtils.UpdateMap(modData, package, rule, out mapFiles, externalFilenames);
|
||||
allFiles.AddRange(mapFiles);
|
||||
|
||||
if (mapSteps.Any())
|
||||
|
||||
Reference in New Issue
Block a user