diff --git a/OpenRA.Game/Map/Map.cs b/OpenRA.Game/Map/Map.cs
index 8d91489854..366f2b57a9 100644
--- a/OpenRA.Game/Map/Map.cs
+++ b/OpenRA.Game/Map/Map.cs
@@ -15,6 +15,7 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
+using System.Text.RegularExpressions;
using OpenRA.FileFormats;
using OpenRA.FileSystem;
using OpenRA.Graphics;
@@ -151,6 +152,7 @@ namespace OpenRA
public class Map : IReadOnlyFileSystem
{
public const int SupportedMapFormat = 11;
+ public const int CurrentMapFormat = 12;
const short InvalidCachedTerrainIndex = -1;
/// Defines the order of the fields in map.yaml
@@ -253,6 +255,11 @@ namespace OpenRA
internal Translation Translation;
public static string ComputeUID(IReadOnlyPackage package)
+ {
+ return ComputeUID(package, GetMapFormat(package));
+ }
+
+ static string ComputeUID(IReadOnlyPackage package, int format)
{
// UID is calculated by taking an SHA1 of the yaml and binary data
var requiredFiles = new[] { "map.yaml", "map.bin" };
@@ -265,7 +272,7 @@ namespace OpenRA
try
{
foreach (var filename in contents)
- if (filename.EndsWith(".yaml") || filename.EndsWith(".bin") || filename.EndsWith(".lua"))
+ if (filename.EndsWith(".yaml") || filename.EndsWith(".bin") || filename.EndsWith(".lua") || (format >= 12 && filename == "map.png"))
streams.Add(package.GetStream(filename));
// Take the SHA1
@@ -285,6 +292,19 @@ namespace OpenRA
}
}
+ static int GetMapFormat(IReadOnlyPackage p)
+ {
+ foreach (var line in p.GetStream("map.yaml").ReadAllLines())
+ {
+ // PERF This is a way to get MapFormat without expensive yaml parsing
+ var search = Regex.Match(line, "^MapFormat:\\s*(\\d*)\\s*$");
+ if (search.Success && search.Groups.Count > 0)
+ return FieldLoader.GetValue("MapFormat", search.Groups[1].Value);
+ }
+
+ throw new InvalidDataException($"MapFormat is not definedt\n File: {p.Name}");
+ }
+
///
/// Initializes a new map created by the editor or importer.
/// The map will not receive a valid UID until after it has been saved and reloaded.
@@ -332,7 +352,7 @@ namespace OpenRA
foreach (var field in YamlFields)
field.Deserialize(this, yaml.Nodes);
- if (MapFormat != SupportedMapFormat)
+ if (MapFormat < SupportedMapFormat)
throw new InvalidDataException($"Map format {MapFormat} is not supported.\n File: {package.Name}");
PlayerDefinitions = MiniYaml.NodesOrEmpty(yaml, "Players");
@@ -400,7 +420,7 @@ namespace OpenRA
PostInit();
- Uid = ComputeUID(Package);
+ Uid = ComputeUID(Package, MapFormat);
}
void PostInit()
@@ -600,7 +620,7 @@ namespace OpenRA
public void Save(IReadWritePackage toPackage)
{
- MapFormat = SupportedMapFormat;
+ MapFormat = CurrentMapFormat;
var root = new List();
foreach (var field in YamlFields)
@@ -625,7 +645,7 @@ namespace OpenRA
Package = toPackage;
// Update UID to match the newly saved data
- Uid = ComputeUID(toPackage);
+ Uid = ComputeUID(toPackage, MapFormat);
}
public byte[] SaveBinaryData()
diff --git a/OpenRA.Game/Map/MapPreview.cs b/OpenRA.Game/Map/MapPreview.cs
index 7dc47f0ca1..22f7197a14 100644
--- a/OpenRA.Game/Map/MapPreview.cs
+++ b/OpenRA.Game/Map/MapPreview.cs
@@ -320,7 +320,7 @@ namespace OpenRA
if (yaml.TryGetValue("MapFormat", out var temp))
{
var format = FieldLoader.GetValue("MapFormat", temp.Value);
- if (format != Map.SupportedMapFormat)
+ if (format < Map.SupportedMapFormat)
throw new InvalidDataException($"Map format {format} is not supported.");
}
diff --git a/OpenRA.Mods.Common/Lint/CheckMapMetadata.cs b/OpenRA.Mods.Common/Lint/CheckMapMetadata.cs
index 49119e97a2..869d9613f6 100644
--- a/OpenRA.Mods.Common/Lint/CheckMapMetadata.cs
+++ b/OpenRA.Mods.Common/Lint/CheckMapMetadata.cs
@@ -28,8 +28,8 @@ namespace OpenRA.Mods.Common.Lint
void Run(Action emitError, int mapFormat, string author, string title, string[] categories)
{
- if (mapFormat != Map.SupportedMapFormat)
- emitError($"Map format {mapFormat} does not match the supported version {Map.SupportedMapFormat}.");
+ if (mapFormat < Map.SupportedMapFormat)
+ emitError($"Map format {mapFormat} does not match the supported version {Map.CurrentMapFormat}.");
if (author == null)
emitError("Map does not define a valid author.");