diff --git a/MapConverter/MapConverter.cs b/MapConverter/MapConverter.cs index c705cf4279..4dc2f95208 100644 --- a/MapConverter/MapConverter.cs +++ b/MapConverter/MapConverter.cs @@ -395,8 +395,9 @@ namespace MapConverter public void Save(string filepath) { Directory.CreateDirectory(filepath); + + Map.Package = new Folder(filepath); SavePreviewImage(Path.Combine(filepath,"preview.png")); - Map.UpdateUid(); Map.Save(filepath); } } diff --git a/OpenRA.FileFormats/Map/Map.cs b/OpenRA.FileFormats/Map/Map.cs index 5824adce52..ca6e223ff8 100644 --- a/OpenRA.FileFormats/Map/Map.cs +++ b/OpenRA.FileFormats/Map/Map.cs @@ -23,6 +23,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; +using System.Security.Cryptography; namespace OpenRA.FileFormats { @@ -30,7 +31,7 @@ namespace OpenRA.FileFormats { public IFolder Package; public string Uid; - + // Yaml map data public int MapFormat = 1; public string Title; @@ -64,7 +65,7 @@ namespace OpenRA.FileFormats public IEnumerable SpawnPoints {get {return Waypoints.Select(kv => kv.Value);}} static List SimpleFields = new List() { - "Uid", "MapFormat", "Title", "Description", "Author", "PlayerCount", "Tileset", "MapSize", "TopLeft", "BottomRight" + "MapFormat", "Title", "Description", "Author", "PlayerCount", "Tileset", "MapSize", "TopLeft", "BottomRight" }; public Map() {} @@ -83,9 +84,7 @@ namespace OpenRA.FileFormats string[] loc = wp.Value.Value.Split(','); Waypoints.Add(wp.Key, new int2(int.Parse(loc[0]),int.Parse(loc[1]))); } - - // TODO: Players - + // Actors foreach (var kv in yaml["Actors"].Nodes) { @@ -106,17 +105,10 @@ namespace OpenRA.FileFormats // Rules Rules = yaml["Rules"].Nodes; + LoadUid(); LoadBinaryData(); } - public void UpdateUid() - { - // TODO: Do this properly. - // Use a hash of the important data - Random foo = new Random(); - Uid = foo.Next().ToString(); - } - public void Save(string filepath) { Dictionary root = new Dictionary(); @@ -126,14 +118,15 @@ namespace OpenRA.FileFormats FieldInfo f = this.GetType().GetField(field); if (f.GetValue(this) == null) continue; root.Add(field,new MiniYaml(FieldSaver.FormatValue(this,f),null)); - } + } + root.Add("Actors",MiniYaml.FromDictionary(Actors)); root.Add("Waypoints",MiniYaml.FromDictionary(Waypoints)); root.Add("Smudges",MiniYaml.FromList(Smudges)); - // TODO: Players root.Add("Rules",new MiniYaml(null,Rules)); SaveBinaryData(Path.Combine(filepath,"map.bin")); root.WriteToFile(Path.Combine(filepath,"map.yaml")); + SaveUid(Path.Combine(filepath,"map.uid")); } static byte ReadByte( Stream s ) @@ -216,6 +209,34 @@ namespace OpenRA.FileFormats File.Move(filepath+".tmp",filepath); } + public void LoadUid() + { + StreamReader uidStream = new StreamReader(Package.GetContent("map.uid")); + Uid = uidStream.ReadLine(); + uidStream.Close(); + } + + public void SaveUid(string filename) + { + // UID is calculated by taking an SHA1 of the yaml and binary data + // Read the relevant data into a buffer + var yamlStream = Package.GetContent("map.yaml"); + var binaryStream = Package.GetContent("map.bin"); + var data = new byte[yamlStream.Length+binaryStream.Length]; + + yamlStream.Read(data,0,(int)yamlStream.Length); + binaryStream.Read(data,(int)yamlStream.Length,(int)binaryStream.Length); + + // Take the SHA1 + using (var csp = SHA1.Create()) + Uid = new string(csp.ComputeHash(data).SelectMany(a => a.ToString("x2")).ToArray()); + + // Save to file + StreamWriter file = new System.IO.StreamWriter(filename); + file.WriteLine(Uid); + file.Close(); + } + public bool IsInMap(int2 xy) { return IsInMap(xy.X,xy.Y); diff --git a/OpenRA.FileFormats/Map/MapStub.cs b/OpenRA.FileFormats/Map/MapStub.cs index b49488dbc5..89149727f9 100644 --- a/OpenRA.FileFormats/Map/MapStub.cs +++ b/OpenRA.FileFormats/Map/MapStub.cs @@ -20,6 +20,7 @@ using System.Collections.Generic; using System.Drawing; +using System.IO; using System; namespace OpenRA.FileFormats @@ -43,7 +44,7 @@ namespace OpenRA.FileFormats public Lazy Preview; static List Fields = new List() { - "Uid", "Title", "Description", "Author", "PlayerCount", "Tileset", "TopLeft", "BottomRight" + "Title", "Description", "Author", "PlayerCount", "Tileset", "TopLeft", "BottomRight" }; public MapStub() {} @@ -57,6 +58,10 @@ namespace OpenRA.FileFormats Preview = Lazy.New( () => {return new Bitmap(Package.GetContent("preview.png"));} ); + + StreamReader uidStream = new StreamReader(Package.GetContent("map.uid")); + Uid = uidStream.ReadLine(); + uidStream.Close(); } public Rectangle PreviewBounds(Rectangle container) diff --git a/mods/cnc/maps/scm01ea/map.uid b/mods/cnc/maps/scm01ea/map.uid new file mode 100644 index 0000000000..0ec0e01fef --- /dev/null +++ b/mods/cnc/maps/scm01ea/map.uid @@ -0,0 +1 @@ +a00d9720b29238ced3e3a442f0d6b99901f2fc02 diff --git a/mods/cnc/maps/scm01ea/map.yaml b/mods/cnc/maps/scm01ea/map.yaml index ed477fab4b..f4f0329043 100644 --- a/mods/cnc/maps/scm01ea/map.yaml +++ b/mods/cnc/maps/scm01ea/map.yaml @@ -1,5 +1,3 @@ -Uid: 97516324 - MapFormat: 1 Title: GREEN ACRES diff --git a/mods/cnc/maps/scm02ea/map.uid b/mods/cnc/maps/scm02ea/map.uid new file mode 100644 index 0000000000..17aabb3859 --- /dev/null +++ b/mods/cnc/maps/scm02ea/map.uid @@ -0,0 +1 @@ +0694d1ad31535697679194fc0beca8d57ead5a1c diff --git a/mods/cnc/maps/scm02ea/map.yaml b/mods/cnc/maps/scm02ea/map.yaml index a37a0acd38..50c5346495 100644 --- a/mods/cnc/maps/scm02ea/map.yaml +++ b/mods/cnc/maps/scm02ea/map.yaml @@ -1,5 +1,3 @@ -Uid: 119926504 - MapFormat: 1 Title: Sand Trap diff --git a/mods/cnc/maps/scm03ea/map.uid b/mods/cnc/maps/scm03ea/map.uid new file mode 100644 index 0000000000..1daf9fa06d --- /dev/null +++ b/mods/cnc/maps/scm03ea/map.uid @@ -0,0 +1 @@ +e1a198be05a4fe4487e5441f60259693dcf7a00f diff --git a/mods/cnc/maps/scm03ea/map.yaml b/mods/cnc/maps/scm03ea/map.yaml index e2dc69ecff..c03ce0c327 100644 --- a/mods/cnc/maps/scm03ea/map.yaml +++ b/mods/cnc/maps/scm03ea/map.yaml @@ -1,5 +1,3 @@ -Uid: 708244922 - MapFormat: 1 Title: Lost Arena diff --git a/mods/cnc/mod.yaml b/mods/cnc/mod.yaml index 8be602691d..7f9b29ecf2 100644 --- a/mods/cnc/mod.yaml +++ b/mods/cnc/mod.yaml @@ -52,4 +52,4 @@ Voices: Terrain: mods/cnc/terrain.yaml -ShellmapUid:119926504 +ShellmapUid:a00d9720b29238ced3e3a442f0d6b99901f2fc02 diff --git a/mods/ra/maps/scm01ea/map.uid b/mods/ra/maps/scm01ea/map.uid new file mode 100644 index 0000000000..f807902a63 --- /dev/null +++ b/mods/ra/maps/scm01ea/map.uid @@ -0,0 +1 @@ +d2d0811ce6cd64e836317039547ce777b5a199d3 diff --git a/mods/ra/maps/scm01ea/map.yaml b/mods/ra/maps/scm01ea/map.yaml index 84ceb64593..b9e297e76a 100644 --- a/mods/ra/maps/scm01ea/map.yaml +++ b/mods/ra/maps/scm01ea/map.yaml @@ -1,5 +1,3 @@ -Uid: 45646351 - MapFormat: 1 Title: Coastal Influence (4-6) diff --git a/mods/ra/maps/scm02ea/map.uid b/mods/ra/maps/scm02ea/map.uid new file mode 100644 index 0000000000..405e35e947 --- /dev/null +++ b/mods/ra/maps/scm02ea/map.uid @@ -0,0 +1 @@ +b3e0dbb967bc20a3e7da64e7383d2d90094684f0 diff --git a/mods/ra/maps/scm02ea/map.yaml b/mods/ra/maps/scm02ea/map.yaml index e5906ba082..368a43f277 100644 --- a/mods/ra/maps/scm02ea/map.yaml +++ b/mods/ra/maps/scm02ea/map.yaml @@ -1,5 +1,3 @@ -Uid: 1134734410 - MapFormat: 1 Title: Middle Mayhem (2) diff --git a/mods/ra/maps/scm03ea/map.uid b/mods/ra/maps/scm03ea/map.uid new file mode 100644 index 0000000000..3cf7e1ffe8 --- /dev/null +++ b/mods/ra/maps/scm03ea/map.uid @@ -0,0 +1 @@ +580c39f9606d773ea8daa2bf9603aa9687736be1 diff --git a/mods/ra/maps/scm03ea/map.yaml b/mods/ra/maps/scm03ea/map.yaml index aae7f356e7..f77077a234 100644 --- a/mods/ra/maps/scm03ea/map.yaml +++ b/mods/ra/maps/scm03ea/map.yaml @@ -1,5 +1,3 @@ -Uid: 846202401 - MapFormat: 1 Title: Equal Opportunity (2) diff --git a/mods/ra/mod.yaml b/mods/ra/mod.yaml index 3a7cb9e5de..6ab2985a57 100644 --- a/mods/ra/mod.yaml +++ b/mods/ra/mod.yaml @@ -50,4 +50,4 @@ Voices: Terrain: mods/ra/terrain.yaml -ShellmapUid:1134734410 +ShellmapUid:d2d0811ce6cd64e836317039547ce777b5a199d3