Merge pull request #10701 from pchote/map-cleanup-part-4

Remove automatic map format upgrades and add versioned user map dirs
This commit is contained in:
Matthias Mailänder
2016-02-08 23:08:55 +01:00
11 changed files with 153 additions and 110 deletions

View File

@@ -362,8 +362,9 @@ all-dependencies: cli-dependencies windows-dependencies osx-dependencies
version: mods/ra/mod.yaml mods/cnc/mod.yaml mods/d2k/mod.yaml mods/ts/mod.yaml mods/modchooser/mod.yaml mods/all/mod.yaml
@for i in $? ; do \
awk '{sub("Version:.*$$","Version: $(VERSION)"); print $0}' $${i} > $${i}.tmp && \
awk '{sub("\tmodchooser:.*$$","\tmodchooser: $(VERSION)"); print $0}' $${i}.tmp > $${i} && \
rm $${i}.tmp ; \
awk '{sub("\tmodchooser:.*$$","\tmodchooser: $(VERSION)"); print $0}' $${i}.tmp > $${i}.tmp2 && \
awk '{sub("/[^/]*@User$$", "/$(VERSION)@User"); print $0}' $${i}.tmp2 > $${i} && \
rm $${i}.tmp $${i}.tmp2; \
done
docs: utility mods version

View File

@@ -109,7 +109,7 @@ namespace OpenRA
public class Map
{
public const int MinimumSupportedMapFormat = 6;
public const int SupportedMapFormat = 8;
public const int MaxTilesInCircleRange = 50;
public readonly MapGrid Grid;
@@ -167,6 +167,34 @@ namespace OpenRA
return videos;
}
public static string ComputeUID(IReadOnlyPackage package)
{
// UID is calculated by taking an SHA1 of the yaml and binary data
using (var ms = new MemoryStream())
{
// Read the relevant data into the buffer
using (var s = package.GetStream("map.yaml"))
{
if (s == null)
throw new FileNotFoundException("Required file map.yaml not present in this map");
s.CopyTo(ms);
}
using (var s = package.GetStream("map.bin"))
{
if (s == null)
throw new FileNotFoundException("Required file map.bin not present in this map");
s.CopyTo(ms);
}
// Take the SHA1
ms.Seek(0, SeekOrigin.Begin);
using (var csp = SHA1.Create())
return new string(csp.ComputeHash(ms).SelectMany(a => a.ToString("x2")).ToArray());
}
}
public Rectangle Bounds;
/// <summary>
@@ -284,73 +312,9 @@ namespace OpenRA
var yaml = new MiniYaml(null, MiniYaml.FromStream(Container.GetStream("map.yaml"), path));
FieldLoader.Load(this, yaml);
// Support for formats 1-3 dropped 2011-02-11.
// Use release-20110207 to convert older maps to format 4
// Use release-20110511 to convert older maps to format 5
// Use release-20141029 to convert older maps to format 6
if (MapFormat < MinimumSupportedMapFormat)
if (MapFormat != SupportedMapFormat)
throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(MapFormat, path));
var nd = yaml.ToDictionary();
// Format 6 -> 7 combined the Selectable and UseAsShellmap flags into the Class enum
if (MapFormat < 7)
{
MiniYaml useAsShellmap;
if (nd.TryGetValue("UseAsShellmap", out useAsShellmap) && bool.Parse(useAsShellmap.Value))
Visibility = MapVisibility.Shellmap;
else if (Type == "Mission" || Type == "Campaign")
Visibility = MapVisibility.MissionSelector;
}
// Format 7 -> 8 replaced normalized HSL triples with rgb(a) hex colors
if (MapFormat < 8)
{
var players = yaml.Nodes.FirstOrDefault(n => n.Key == "Players");
if (players != null)
{
bool noteHexColors = false;
bool noteColorRamp = false;
foreach (var player in players.Value.Nodes)
{
var colorRampNode = player.Value.Nodes.FirstOrDefault(n => n.Key == "ColorRamp");
if (colorRampNode != null)
{
Color dummy;
var parts = colorRampNode.Value.Value.Split(',');
if (parts.Length == 3 || parts.Length == 4)
{
// Try to convert old normalized HSL value to a rgb hex color
try
{
HSLColor color = new HSLColor(
(byte)Exts.ParseIntegerInvariant(parts[0].Trim()).Clamp(0, 255),
(byte)Exts.ParseIntegerInvariant(parts[1].Trim()).Clamp(0, 255),
(byte)Exts.ParseIntegerInvariant(parts[2].Trim()).Clamp(0, 255));
colorRampNode.Value.Value = FieldSaver.FormatValue(color);
noteHexColors = true;
}
catch (Exception)
{
throw new InvalidDataException("Invalid ColorRamp value.\n File: " + path);
}
}
else if (parts.Length != 1 || !HSLColor.TryParseRGB(parts[0], out dummy))
throw new InvalidDataException("Invalid ColorRamp value.\n File: " + path);
colorRampNode.Key = "Color";
noteColorRamp = true;
}
}
Console.WriteLine("Converted " + path + " to MapFormat 8.");
if (noteHexColors)
Console.WriteLine("ColorRamp is now called Color and uses rgb(a) hex value - rrggbb[aa].");
else if (noteColorRamp)
Console.WriteLine("ColorRamp is now called Color.");
}
}
SpawnPoints = Exts.Lazy(() =>
{
var spawns = new List<CPos>();
@@ -399,7 +363,7 @@ namespace OpenRA
if (MapFormat < 8)
Save(path);
Uid = ComputeHash();
Uid = ComputeUID(Container);
}
void PostInit()
@@ -604,7 +568,7 @@ namespace OpenRA
Container.Write(entries);
// Update UID to match the newly saved data
Uid = ComputeHash();
Uid = ComputeUID(Container);
}
public CellLayer<TerrainTile> LoadMapTiles()
@@ -915,24 +879,6 @@ namespace OpenRA
ProjectedCellBounds = new ProjectedCellRegion(this, tl, br);
}
string ComputeHash()
{
// UID is calculated by taking an SHA1 of the yaml and binary data
using (var ms = new MemoryStream())
{
// Read the relevant data into the buffer
using (var s = Container.GetStream("map.yaml"))
s.CopyTo(ms);
using (var s = Container.GetStream("map.bin"))
s.CopyTo(ms);
// Take the SHA1
ms.Seek(0, SeekOrigin.Begin);
using (var csp = SHA1.Create())
return new string(csp.ComputeHash(ms).SelectMany(a => a.ToString("x2")).ToArray());
}
}
public void FixOpenAreas(Ruleset rules)
{
var r = new Random();

View File

@@ -17,9 +17,9 @@ namespace OpenRA.Mods.Common.Lint
{
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
{
if (map.MapFormat < Map.MinimumSupportedMapFormat)
emitError("Map format {0} is older than the minimum supported version {1}."
.F(map.MapFormat, Map.MinimumSupportedMapFormat));
if (map.MapFormat != Map.SupportedMapFormat)
emitError("Map format {0} does not match the supported version {1}."
.F(map.MapFormat, Map.SupportedMapFormat));
if (map.Author == null)
emitError("Map does not define a valid author.");

View File

@@ -24,9 +24,8 @@ namespace OpenRA.Mods.Common.UtilityCommands
[Desc("MAPFILE", "Generate hash of specified oramap file.")]
public void Run(ModData modData, string[] args)
{
Game.ModData = modData;
var result = new Map(args[1]).Uid;
Console.WriteLine(result);
using (var package = modData.ModFiles.OpenPackage(args[1]))
Console.WriteLine(Map.ComputeUID(package));
}
}
}

View File

@@ -25,9 +25,10 @@ namespace OpenRA.Mods.Common.UtilityCommands
// HACK: The engine code assumes that Game.modData is set.
Game.ModData = modData;
UpgradeRules.UpgradeMapFormat(modData, args[1]);
var map = new Map(args[1]);
var engineDate = Exts.ParseIntegerInvariant(args[2]);
UpgradeRules.UpgradeWeaponRules(engineDate, ref map.WeaponDefinitions, null, 0);
UpgradeRules.UpgradeActorRules(engineDate, ref map.RuleDefinitions, null, 0);
UpgradeRules.UpgradePlayers(engineDate, ref map.PlayerDefinitions, null, 0);

View File

@@ -28,12 +28,12 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
// HACK: The engine code assumes that Game.modData is set.
Game.ModData = modData;
Game.ModData.MapCache.LoadMaps();
modData.MapCache.LoadMaps();
var engineDate = Exts.ParseIntegerInvariant(args[1]);
Console.WriteLine("Processing Rules:");
foreach (var filename in Game.ModData.Manifest.Rules)
foreach (var filename in modData.Manifest.Rules)
{
Console.WriteLine("\t" + filename);
var yaml = MiniYaml.FromFile(filename);
@@ -44,7 +44,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
}
Console.WriteLine("Processing Weapons:");
foreach (var filename in Game.ModData.Manifest.Weapons)
foreach (var filename in modData.Manifest.Weapons)
{
Console.WriteLine("\t" + filename);
var yaml = MiniYaml.FromFile(filename);
@@ -55,7 +55,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
}
Console.WriteLine("Processing Tilesets:");
foreach (var filename in Game.ModData.Manifest.TileSets)
foreach (var filename in modData.Manifest.TileSets)
{
Console.WriteLine("\t" + filename);
var yaml = MiniYaml.FromFile(filename);
@@ -66,7 +66,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
}
Console.WriteLine("Processing Cursors:");
foreach (var filename in Game.ModData.Manifest.Cursors)
foreach (var filename in modData.Manifest.Cursors)
{
Console.WriteLine("\t" + filename);
var yaml = MiniYaml.FromFile(filename);
@@ -77,7 +77,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
}
Console.WriteLine("Processing Chrome Metrics:");
foreach (var filename in Game.ModData.Manifest.ChromeMetrics)
foreach (var filename in modData.Manifest.ChromeMetrics)
{
Console.WriteLine("\t" + filename);
var yaml = MiniYaml.FromFile(filename);
@@ -88,7 +88,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
}
Console.WriteLine("Processing Chrome Layout:");
foreach (var filename in Game.ModData.Manifest.ChromeLayout)
foreach (var filename in modData.Manifest.ChromeLayout)
{
Console.WriteLine("\t" + filename);
var yaml = MiniYaml.FromFile(filename);
@@ -99,13 +99,16 @@ namespace OpenRA.Mods.Common.UtilityCommands
}
Console.WriteLine("Processing Maps:");
var maps = Game.ModData.MapCache
var mapPaths = modData.MapCache
.Where(m => m.Status == MapStatus.Available)
.Select(m => new Map(m.Path));
.Select(m => m.Path);
foreach (var map in maps)
foreach (var path in mapPaths)
{
Console.WriteLine("\t" + map.Path);
Console.WriteLine("\t" + path);
UpgradeRules.UpgradeMapFormat(modData, path);
var map = new Map(path);
UpgradeRules.UpgradeActorRules(engineDate, ref map.RuleDefinitions, null, 0);
UpgradeRules.UpgradeWeaponRules(engineDate, ref map.WeaponDefinitions, null, 0);
UpgradeRules.UpgradePlayers(engineDate, ref map.PlayerDefinitions, null, 0);

View File

@@ -12,7 +12,9 @@ using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using OpenRA.Graphics;
using OpenRA.Traits;
@@ -3598,5 +3600,96 @@ namespace OpenRA.Mods.Common.UtilityCommands
UpgradeActors(engineVersion, ref node.Value.Nodes, node, depth + 1);
}
}
internal static void UpgradeMapFormat(ModData modData, string path)
{
using (var package = modData.ModFiles.OpenWritablePackage(path))
{
if (package == null)
return;
var yamlStream = package.GetStream("map.yaml");
if (yamlStream == null)
return;
var yaml = new MiniYaml(null, MiniYaml.FromStream(yamlStream, path));
var nd = yaml.ToDictionary();
var mapFormat = FieldLoader.GetValue<int>("MapFormat", nd["MapFormat"].Value);
if (mapFormat < 6)
throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(mapFormat, path));
// Nothing to do
if (mapFormat >= 8)
return;
// Format 6 -> 7 combined the Selectable and UseAsShellmap flags into the Class enum
if (mapFormat < 7)
{
MiniYaml useAsShellmap;
if (nd.TryGetValue("UseAsShellmap", out useAsShellmap) && bool.Parse(useAsShellmap.Value))
yaml.Nodes.Add(new MiniYamlNode("Visibility", new MiniYaml("Shellmap")));
else if (nd["Type"].Value == "Mission" || nd["Type"].Value == "Campaign")
yaml.Nodes.Add(new MiniYamlNode("Visibility", new MiniYaml("MissionSelector")));
}
// Format 7 -> 8 replaced normalized HSL triples with rgb(a) hex colors
if (mapFormat < 8)
{
var players = yaml.Nodes.FirstOrDefault(n => n.Key == "Players");
if (players != null)
{
bool noteHexColors = false;
bool noteColorRamp = false;
foreach (var player in players.Value.Nodes)
{
var colorRampNode = player.Value.Nodes.FirstOrDefault(n => n.Key == "ColorRamp");
if (colorRampNode != null)
{
Color dummy;
var parts = colorRampNode.Value.Value.Split(',');
if (parts.Length == 3 || parts.Length == 4)
{
// Try to convert old normalized HSL value to a rgb hex color
try
{
HSLColor color = new HSLColor(
(byte)Exts.ParseIntegerInvariant(parts[0].Trim()).Clamp(0, 255),
(byte)Exts.ParseIntegerInvariant(parts[1].Trim()).Clamp(0, 255),
(byte)Exts.ParseIntegerInvariant(parts[2].Trim()).Clamp(0, 255));
colorRampNode.Value.Value = FieldSaver.FormatValue(color);
noteHexColors = true;
}
catch (Exception)
{
throw new InvalidDataException("Invalid ColorRamp value.\n File: " + path);
}
}
else if (parts.Length != 1 || !HSLColor.TryParseRGB(parts[0], out dummy))
throw new InvalidDataException("Invalid ColorRamp value.\n File: " + path);
colorRampNode.Key = "Color";
noteColorRamp = true;
}
}
Console.WriteLine("Converted " + path + " to MapFormat 8.");
if (noteHexColors)
Console.WriteLine("ColorRamp is now called Color and uses rgb(a) hex value - rrggbb[aa].");
else if (noteColorRamp)
Console.WriteLine("ColorRamp is now called Color.");
}
}
var entries = new Dictionary<string, byte[]>();
entries.Add("map.yaml", Encoding.UTF8.GetBytes(yaml.Nodes.WriteToString()));
foreach (var file in package.Contents)
{
if (file == "map.yaml")
continue;
entries.Add(file, package.GetStream(file).ReadAllBytes());
}
}
}
}
}

View File

@@ -33,7 +33,7 @@ Packages:
MapFolders:
./mods/cnc/maps@System
~^maps/cnc@User
~^maps/cnc/{DEV_VERSION}@User
Rules:
./mods/cnc/rules/misc.yaml

View File

@@ -22,7 +22,7 @@ Packages:
MapFolders:
d2k:maps@System
~^maps/d2k@User
~^maps/d2k/{DEV_VERSION}@User
Rules:
d2k:rules/misc.yaml

View File

@@ -32,7 +32,7 @@ Packages:
MapFolders:
./mods/ra/maps@System
~^maps/ra@User
~^maps/ra/{DEV_VERSION}@User
Rules:
./mods/ra/rules/misc.yaml

View File

@@ -55,7 +55,7 @@ Packages:
MapFolders:
./mods/ts/maps@System
~^maps/ts@User
~^maps/ts/{DEV_VERSION}@User
Rules:
./mods/ts/rules/ai.yaml