diff --git a/MapConverter/Main.cs b/MapConverter/Main.cs index e6311aa4e8..dccd026cb9 100644 --- a/MapConverter/Main.cs +++ b/MapConverter/Main.cs @@ -19,11 +19,9 @@ namespace MapConverter foreach (var folder in manifest.Folders) FileSystem.Mount(folder); foreach (var pkg in manifest.Packages) FileSystem.Mount(pkg); - var map = new NewMap(args[2]); - map.DebugContents(); - - //var map = new IniMap(args[1]); - //map.Save(args[2]); + var converter = new MapConverter(args[1]); + converter.Map.DebugContents(); + converter.Save(args[2]); } } } diff --git a/MapConverter/IniMap.cs b/MapConverter/MapConverter.cs similarity index 54% rename from MapConverter/IniMap.cs rename to MapConverter/MapConverter.cs index 83a2189cff..18f31c559b 100644 --- a/MapConverter/IniMap.cs +++ b/MapConverter/MapConverter.cs @@ -28,141 +28,62 @@ using OpenRA.FileFormats; namespace MapConverter { - public class MapData + public class MapConverter { - // General info - public int MapFormat; - public string Title; - public string Description; - public string Author; - public int Players; - - // 'Simple' map data - public string Tileset; - public int2 Size; - public int[] Bounds; - - // 'Complex' map data - public string TileData; - public string ResourceData; - public string[] Waypoints; - public string[] Actors; - } - - public class IniMap - { - public readonly string Title; - public readonly string Theater; public readonly int INIFormat; public readonly int MapSize; public readonly int XOffset; public readonly int YOffset; - public int2 Offset { get { return new int2( XOffset, YOffset ); } } public readonly int Width; public readonly int Height; - public int2 Size { get { return new int2(Width, Height); } } - - public readonly TileReference[ , ] MapTiles; - public readonly List Actors = new List(); - - public readonly IEnumerable SpawnPoints; + public NewMap Map = new NewMap(); static string Truncate( string s, int maxLength ) { return s.Length <= maxLength ? s : s.Substring(0,maxLength ); } - public void Save(string filename) + + static string[] raOverlayNames = { - Dictionary< string, Pair > resourceMapping = new Dictionary>() { - { "gold01", new Pair(1,0) }, - { "gold02", new Pair(1,1) }, - { "gold03", new Pair(1,2) }, - { "gold04", new Pair(1,3) }, - - { "gem01", new Pair(2,0) }, - { "gem02", new Pair(2,1) }, - { "gem03", new Pair(2,2) }, - { "gem04", new Pair(2,3) }, - }; + "sbag", "cycl", "brik", "fenc", "wood", + "gold01", "gold02", "gold03", "gold04", + "gem01", "gem02", "gem03", "gem04", + "v12", "v13", "v14", "v15", "v16", "v17", "v18", + "fpls", "wcrate", "scrate", "barb", "sbag", + }; + + Dictionary< string, Pair > resourceMapping = new Dictionary>() { + { "gold01", new Pair(1,0) }, + { "gold02", new Pair(1,1) }, + { "gold03", new Pair(1,2) }, + { "gold04", new Pair(1,3) }, - // Metadata - var data = new MapData(); - data.MapFormat = 1; - data.Title = Title; - data.Players = SpawnPoints.Count(); - data.Author = "Westwood Studios"; - data.Description = ""; - data.Tileset = Theater; - data.Bounds = new int[] {XOffset, YOffset, Width, Height}; - data.Size = new int2(MapSize,MapSize); + { "gem01", new Pair(2,0) }, + { "gem02", new Pair(2,1) }, + { "gem03", new Pair(2,2) }, + { "gem04", new Pair(2,3) }, + // TODO Add cnc tiberium + }; + + + public MapConverter(string filename) + { + Map.Author = "Westwood Studios"; - // Tile data is stored as a base-64 encoded stream of - // {(2-byte) tile index, (1-byte) image index} pairs - MemoryStream tiles = new MemoryStream(); - BinaryWriter writer = new BinaryWriter( tiles ); - - for( int i = 0 ; i < MapSize ; i++ ) - for( int j = 0 ; j < MapSize ; j++ ) - { - writer.Write( MapTiles[j,i].tile ); - // Semi-hack: Convert clear and water tiles to "pick an image for me" magic number - byte image = (MapTiles[ j, i ].tile == 0xff || MapTiles[ j, i ].tile == 0xffff) ? byte.MaxValue : MapTiles[j,i].image; - writer.Write(image); - } - writer.Flush(); - data.TileData = Convert.ToBase64String(tiles.ToArray()); - - // Resource data is stored as a base-64 encoded stream of - // {(1-byte) resource index, (1-byte) image index} pairs - MemoryStream resources = new MemoryStream(); - writer = new BinaryWriter( resources ); - - for( int i = 0 ; i < MapSize ; i++ ) - for( int j = 0 ; j < MapSize ; j++ ) - { - byte type = 0; - byte image = 0; - if (MapTiles[j,i].overlay != null) - { - var res = resourceMapping[MapTiles[j,i].overlay]; - type = res.First; - image = res.Second; - } - - writer.Write(type); - writer.Write(image); - } - writer.Flush(); - data.ResourceData = Convert.ToBase64String(resources.ToArray()); - - // Spawn points - int s = 0; - data.Waypoints = SpawnPoints.Select(t => "spawn{0}={1}|{2}".F(s++,t.X,t.Y)).ToArray(); - - // Actors - s = 0; - data.Actors = Actors.Select(t=>"actor{0}={1}|{2}|{3}".F(s++,t.Name,t.Location.X,t.Location.Y)).ToArray(); - - Dictionary Nodes = new Dictionary(); - Nodes.Add("MAP",FieldSaver.Save(data)); - Nodes.WriteToFile(filename); - - } - - public IniMap(string filename) - { IniFile file = new IniFile(FileSystem.Open(filename)); IniSection basic = file.GetSection("Basic"); - Title = basic.GetValue("Name", "(null)"); + Map.Title = basic.GetValue("Name", "(null)"); + + INIFormat = int.Parse(basic.GetValue("NewINIFormat", "0")); IniSection map = file.GetSection("Map"); - Theater = Truncate(map.GetValue("Theater", "TEMPERAT"), 8); + Map.Tileset = Truncate(map.GetValue("Theater", "TEMPERAT"), 8); XOffset = int.Parse(map.GetValue("X", "0")); YOffset = int.Parse(map.GetValue("Y", "0")); @@ -171,11 +92,9 @@ namespace MapConverter Height = int.Parse(map.GetValue("Height", "0")); MapSize = (INIFormat == 3) ? 128 : 64; - MapTiles = new TileReference[ MapSize, MapSize ]; - for (int j = 0; j < MapSize; j++) - for (int i = 0; i < MapSize; i++) - MapTiles[i, j] = new TileReference(); - + Map.Size.X = MapSize; + Map.Size.Y = MapSize; + Map.Bounds = new int[] {XOffset, YOffset, Width, Height}; if (INIFormat == 3) // RA map { @@ -193,13 +112,17 @@ namespace MapConverter LoadActors(file, "STRUCTURES"); LoadActors(file, "UNITS"); LoadActors(file, "INFANTRY"); - - SpawnPoints = file.GetSection("Waypoints") + + var wp = file.GetSection("Waypoints") .Where(kv => int.Parse(kv.Value) > 0) .Select(kv => Pair.New(int.Parse(kv.Key), new int2(int.Parse(kv.Value) % MapSize, int.Parse(kv.Value) / MapSize))) .Where(a => a.First < 8) - .Select(a => a.Second) .ToArray(); + + Map.PlayerCount = wp.Count(); + + foreach (var kv in wp) + Map.Waypoints.Add("spawn"+kv.First, kv.Second); } static MemoryStream ReadPackedSection(IniSection mapPackSection) @@ -260,35 +183,37 @@ namespace MapConverter void UnpackRATileData( MemoryStream ms ) { + Map.MapTiles = new NewTileReference[ MapSize, MapSize ]; for( int i = 0 ; i < MapSize ; i++ ) for( int j = 0 ; j < MapSize ; j++ ) - MapTiles[j, i].tile = ReadWord(ms); + Map.MapTiles[j, i] = new NewTileReference(); + + for( int i = 0 ; i < MapSize ; i++ ) + for( int j = 0 ; j < MapSize ; j++ ) + Map.MapTiles[j, i].type = ReadWord(ms); for( int i = 0 ; i < MapSize ; i++ ) for( int j = 0 ; j < MapSize ; j++ ) { - MapTiles[j, i].image = (byte)ms.ReadByte(); - if( MapTiles[ j, i ].tile == 0xff || MapTiles[ j, i ].tile == 0xffff ) - MapTiles[ j, i ].image = (byte)( i % 4 + ( j % 4 ) * 4 ); + Map.MapTiles[j, i].index = (byte)ms.ReadByte(); + if( Map.MapTiles[ j, i ].type == 0xff || Map.MapTiles[ j, i ].type == 0xffff ) + Map.MapTiles[ j, i ].index = byte.MaxValue; } } - - static string[] raOverlayNames = - { - "sbag", "cycl", "brik", "fenc", "wood", - "gold01", "gold02", "gold03", "gold04", - "gem01", "gem02", "gem03", "gem04", - "v12", "v13", "v14", "v15", "v16", "v17", "v18", - "fpls", "wcrate", "scrate", "barb", "sbag", - }; void UnpackRAOverlayData( MemoryStream ms ) { + Map.MapResources = new NewTileReference[ MapSize, MapSize ]; for( int i = 0 ; i < MapSize ; i++ ) for( int j = 0 ; j < MapSize ; j++ ) { byte o = ReadByte( ms ); - MapTiles[ j, i ].overlay = (o == 255) ? null : raOverlayNames[o]; + var res = Pair.New((byte)0,(byte)0); + + if (o != 255 && resourceMapping.ContainsKey(raOverlayNames[o])) + res = resourceMapping[raOverlayNames[o]]; + + Map.MapResources[j, i] = new NewTileReference(res.First, res.Second); } } @@ -297,17 +222,17 @@ namespace MapConverter IniSection terrain = file.GetSection( "TERRAIN", true ); if( terrain == null ) return; - + int a = 0; foreach( KeyValuePair kv in terrain ) { var loc = int.Parse( kv.Key ); - Actors.Add( new ActorReference(kv.Value, new int2(loc % MapSize, loc / MapSize), null ) ); + Map.Actors.Add("Actor"+a++, new ActorReference(kv.Value, new int2(loc % MapSize, loc / MapSize), null ) ); } } void UnpackCncTileData( Stream ms ) { - for( int i = 0 ; i < MapSize ; i++ ) + /*for( int i = 0 ; i < MapSize ; i++ ) for( int j = 0 ; j < MapSize ; j++ ) { MapTiles[j, i].tile = (byte)ms.ReadByte(); @@ -315,12 +240,12 @@ namespace MapConverter if( MapTiles[ j, i ].tile == 0xff ) MapTiles[ j, i ].image = (byte)( i % 4 + ( j % 4 ) * 4 ); - } + }*/ } void ReadCncOverlay( IniFile file ) { - IniSection overlay = file.GetSection( "OVERLAY", true ); + /*IniSection overlay = file.GetSection( "OVERLAY", true ); if( overlay == null ) return; @@ -329,7 +254,7 @@ namespace MapConverter var loc = int.Parse( kv.Key ); int2 cell = new int2(loc % MapSize, loc / MapSize); MapTiles[ cell.X, cell.Y ].overlay = kv.Value.ToLower(); - } + }*/ } @@ -338,33 +263,31 @@ namespace MapConverter IniSection terrain = file.GetSection( "TERRAIN", true ); if( terrain == null ) return; - + + int a = 0; foreach( KeyValuePair kv in terrain ) { var loc = int.Parse( kv.Key ); - Actors.Add( new ActorReference( kv.Value.Split(',')[0], new int2(loc % MapSize, loc / MapSize),null)); + Map.Actors.Add("Actor"+a++, new ActorReference( kv.Value.Split(',')[0], new int2(loc % MapSize, loc / MapSize),null)); } } void LoadActors(IniFile file, string section) { + int a = 0; foreach (var s in file.GetSection(section, true)) { //num=owner,type,health,location,facing,... var parts = s.Value.Split( ',' ); var loc = int.Parse(parts[3]); - Actors.Add( new ActorReference( parts[1].ToLowerInvariant(), new int2(loc % MapSize, loc / MapSize), parts[0])); + Map.Actors.Add("Actor"+a++, new ActorReference( parts[1].ToLowerInvariant(), new int2(loc % MapSize, loc / MapSize), parts[0])); } } - public bool IsInMap(int2 xy) + public void Save(string filepath) { - return IsInMap(xy.X,xy.Y); - } - - public bool IsInMap(int x, int y) - { - return (x >= XOffset && y >= YOffset && x < XOffset + Width && y < YOffset + Height); + Map.Tiledata = filepath+".bin"; + Map.Save(filepath+".yaml"); } } } diff --git a/MapConverter/MapConverter.csproj b/MapConverter/MapConverter.csproj index a62e0c9f4b..bb5a683def 100644 --- a/MapConverter/MapConverter.csproj +++ b/MapConverter/MapConverter.csproj @@ -1,5 +1,4 @@ - - + Debug AnyCPU @@ -36,7 +35,7 @@ - + diff --git a/OpenRA.FileFormats/Map/NewMap.cs b/OpenRA.FileFormats/Map/NewMap.cs index 5204c60c1d..c5761e37d1 100644 --- a/OpenRA.FileFormats/Map/NewMap.cs +++ b/OpenRA.FileFormats/Map/NewMap.cs @@ -28,31 +28,34 @@ namespace OpenRA.FileFormats { public class NewMap { - // General info - public byte MapFormat = 1; + // Yaml map data + public int MapFormat = 1; public string Title; public string Description; public string Author; public int PlayerCount; public string Preview; - - // 'Simple' map data - public string Tiledata; - public byte TileFormat = 1; - public string Tileset; - public int2 Size; public int[] Bounds; - - // 'Complex' map data - public TileReference[ , ] MapTiles; + public string Tileset; + public Dictionary Actors = new Dictionary(); public Dictionary Waypoints = new Dictionary(); public Dictionary Rules = new Dictionary(); + // Binary map data + public string Tiledata; + public byte TileFormat = 1; + public int2 Size; + public NewTileReference[ , ] MapTiles; + public NewTileReference[ , ] MapResources; + + List SimpleFields = new List() { - "MapFormat", "Title", "Description", "Author", "PlayerCount", "Tileset", "Size", "Tiledata", "Preview", "Bounds" + "MapFormat", "Title", "Description", "Author", "PlayerCount", "Tileset", "Tiledata", "Preview", "Bounds" }; + public NewMap() {} + public NewMap(string filename) { var yaml = MiniYaml.FromFile(filename); @@ -84,12 +87,61 @@ namespace OpenRA.FileFormats // Rules Rules = yaml["Rules"].Nodes; + + LoadBinaryData(Tiledata); } + public void Save(string filepath) + { + // Do stuff + + SaveBinaryData(Tiledata); + } + + static byte ReadByte( Stream s ) + { + int ret = s.ReadByte(); + if( ret == -1 ) + throw new NotImplementedException(); + return (byte)ret; + } + + static ushort ReadWord(Stream s) + { + ushort ret = ReadByte(s); + ret |= (ushort)(ReadByte(s) << 8); + + return ret; + } + + public void LoadBinaryData(string filename) + { + Console.Write("path: {0}",filename); + + Stream dataStream = FileSystem.Open(filename); + + // Load header info + byte version = ReadByte(dataStream); + Size.X = ReadWord(dataStream); + Size.Y = ReadWord(dataStream); + + MapTiles = new NewTileReference[ Size.X, Size.Y ]; + MapResources = new NewTileReference[ Size.X, Size.Y ]; + + // Load tile data + for( int i = 0 ; i < Size.X ; i++ ) + for( int j = 0 ; j < Size.Y ; j++ ) + MapTiles[i, j] = new NewTileReference(ReadWord(dataStream),ReadByte(dataStream)); + + // Load resource data + for( int i = 0 ; i < Size.X ; i++ ) + for( int j = 0 ; j < Size.Y ; j++ ) + MapResources[i, j] = new NewTileReference(ReadByte(dataStream),ReadByte(dataStream)); + } + public void SaveBinaryData(string filepath) { - FileStream dataStream = new FileStream(filepath+".tmp", FileMode.Create, FileAccess.Write); BinaryWriter writer = new BinaryWriter( dataStream ); writer.BaseStream.Seek(0, SeekOrigin.Begin); @@ -99,39 +151,24 @@ namespace OpenRA.FileFormats writer.Write((ushort)Size.X); writer.Write((ushort)Size.Y); - // Tile data is stored as a base-64 encoded stream of - // {(2-byte) tile index, (1-byte) image index} pairs + // Tile data for( int i = 0 ; i < Size.X ; i++ ) for( int j = 0 ; j < Size.Y ; j++ ) { - writer.Write( MapTiles[j,i].tile ); - // Semi-hack: Convert clear and water tiles to "pick an image for me" magic number - byte image = (MapTiles[ j, i ].tile == 0xff || MapTiles[ j, i ].tile == 0xffff) ? byte.MaxValue : MapTiles[j,i].image; - writer.Write(image); + writer.Write( MapTiles[j,i].type ); + writer.Write( MapTiles[ j, i ].index ); } - - - // TODO: Need a proper resources array to write - /* - // Resource data is stored as a base-64 encoded stream of - // {(1-byte) resource index, (1-byte) image index} pairs + + // Resource data for( int i = 0 ; i < Size.X ; i++ ) for( int j = 0 ; j < Size.Y ; j++ ) - { - byte type = 0; - byte image = 0; - if (MapTiles[j,i].overlay != null) - { - var res = resourceMapping[MapTiles[j,i].overlay]; - type = res.First; - image = res.Second; - } - - writer.Write(type); - writer.Write(image); + { + writer.Write( MapResources[j,i].type ); + writer.Write( MapResources[j,i].index ); } - */ + writer.Flush(); + writer.Close(); } public void DebugContents() diff --git a/OpenRA.FileFormats/Map/NewTileReference.cs b/OpenRA.FileFormats/Map/NewTileReference.cs new file mode 100644 index 0000000000..8f7f42a073 --- /dev/null +++ b/OpenRA.FileFormats/Map/NewTileReference.cs @@ -0,0 +1,36 @@ +#region Copyright & License Information +/* + * Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford. + * This file is part of OpenRA. + * + * OpenRA is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OpenRA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OpenRA. If not, see . + */ +#endregion + +namespace OpenRA.FileFormats +{ + public struct NewTileReference + { + public T type; + public U index; + + public NewTileReference(T t, U i) + { + type = t; + index = i; + } + + public override int GetHashCode() { return type.GetHashCode() ^ index.GetHashCode(); } + } +} diff --git a/OpenRA.FileFormats/OpenRA.FileFormats.csproj b/OpenRA.FileFormats/OpenRA.FileFormats.csproj index 7b7456337b..64d1f2114a 100644 --- a/OpenRA.FileFormats/OpenRA.FileFormats.csproj +++ b/OpenRA.FileFormats/OpenRA.FileFormats.csproj @@ -102,6 +102,7 @@ +