From fb16f94cf6337ed0303ef3d9e6701d065c44d166 Mon Sep 17 00:00:00 2001 From: Ray Koopa Date: Wed, 26 Apr 2017 14:56:54 +0200 Subject: [PATCH] Add support for LEV files. --- src/Syroot.Worms.Test/Program.cs | 5 +- .../Gen2/Armageddon/GeneratedMapTests.cs | 25 +++ .../Gen2/Armageddon/GeneratedMap.cs | 99 +++++++++++ src/Syroot.Worms/Gen2/Armageddon/LandData.cs | 2 +- .../Gen2/Armageddon/MapGeneratorSettings.cs | 159 ++++++++++++++++++ src/Syroot.Worms/Gen2/WorldParty/LandData.cs | 2 +- src/Syroot.Worms/Gen2/Worms2/LandData.cs | 2 +- 7 files changed, 288 insertions(+), 6 deletions(-) create mode 100644 src/Syroot.Worms.UnitTest/Gen2/Armageddon/GeneratedMapTests.cs create mode 100644 src/Syroot.Worms/Gen2/Armageddon/GeneratedMap.cs create mode 100644 src/Syroot.Worms/Gen2/Armageddon/MapGeneratorSettings.cs diff --git a/src/Syroot.Worms.Test/Program.cs b/src/Syroot.Worms.Test/Program.cs index 294af48..a618a4e 100644 --- a/src/Syroot.Worms.Test/Program.cs +++ b/src/Syroot.Worms.Test/Program.cs @@ -3,6 +3,7 @@ using System.IO; using System.Collections.Generic; using Syroot.Worms.Gen2; using Syroot.Worms.Gen2.WorldParty; +using Syroot.Worms.Gen2.Armageddon; namespace Syroot.Worms.Test { @@ -19,9 +20,7 @@ namespace Syroot.Worms.Test private static void Main(string[] args) { - Image image = new Image(@"D:\Archive\Games\Worms\Worms Armageddon\3.7.2.1\custom.img"); - image.Save(@"D:\Pictures\test.img"); - image.Load(@"D:\Pictures\test.img"); + GeneratedMap genMap = new GeneratedMap(@"D:\Archive\Games\Worms\Worms Armageddon\3.7.2.1\User\SavedLevels\test.LEV"); Console.WriteLine("Done."); Console.ReadLine(); diff --git a/src/Syroot.Worms.UnitTest/Gen2/Armageddon/GeneratedMapTests.cs b/src/Syroot.Worms.UnitTest/Gen2/Armageddon/GeneratedMapTests.cs new file mode 100644 index 0000000..a93dabb --- /dev/null +++ b/src/Syroot.Worms.UnitTest/Gen2/Armageddon/GeneratedMapTests.cs @@ -0,0 +1,25 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Syroot.Worms.Gen2.Armageddon; +using Syroot.Worms.UnitTest.Common; + +namespace Syroot.Worms.UnitTest.Gen2.Armageddon +{ + /// + /// Represents a collection of tests for the class. + /// + [TestCategory("GeneratedMap")] + [TestClass] + public class GeneratedMapTests + { + // ---- METHODS (PUBLIC) --------------------------------------------------------------------------------------- + + /// + /// Loads all files found in any game directories. + /// + [TestMethod] + public void LoadGeneratedMaps() + { + TestHelpers.LoadFiles(Game.Armageddon, "*.lev"); + } + } +} diff --git a/src/Syroot.Worms/Gen2/Armageddon/GeneratedMap.cs b/src/Syroot.Worms/Gen2/Armageddon/GeneratedMap.cs new file mode 100644 index 0000000..a28e892 --- /dev/null +++ b/src/Syroot.Worms/Gen2/Armageddon/GeneratedMap.cs @@ -0,0 +1,99 @@ +using System.IO; +using System.Text; +using Syroot.IO; +using Syroot.Worms.Core; + +namespace Syroot.Worms.Gen2.Armageddon +{ + /// + /// Represents stored in a LEV file. + /// Used by WA and WWP. S. https://worms2d.info/Monochrome_map_(.bit,_.lev). + /// + public class GeneratedMap : ILoadableFile, ISaveableFile + { + // ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------ + + /// + /// Initializes a new instance of the class. + /// + public GeneratedMap() + { + } + + /// + /// Initializes a new instance of the class, loading the data from the given + /// . + /// + /// The to load the data from. + public GeneratedMap(Stream stream) + { + Load(stream); + } + + /// + /// Initializes a new instance of the class, loading the data from the given file. + /// + /// The name of the file to load the data from. + public GeneratedMap(string fileName) + { + Load(fileName); + } + + // ---- PROPERTIES --------------------------------------------------------------------------------------------- + + /// + /// Gets or sets the . + /// + public MapGeneratorSettings Settings { get; set; } + + // ---- METHODS (PUBLIC) --------------------------------------------------------------------------------------- + + /// + /// Loads the data from the given . + /// + /// The to load the data from. + public void Load(Stream stream) + { + using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true)) + { + Settings = reader.ReadStruct(); + } + } + + /// + /// Loads the data from the given file. + /// + /// The name of the file to load the data from. + public void Load(string fileName) + { + using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + Load(stream); + } + } + + /// + /// Saves the data into the given . + /// + /// The to save the data to. + public void Save(Stream stream) + { + using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII)) + { + writer.Write(Settings); + } + } + + /// + /// Saves the data in the given file. + /// + /// The name of the file to save the data in. + public void Save(string fileName) + { + using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) + { + Save(stream); + } + } + } +} diff --git a/src/Syroot.Worms/Gen2/Armageddon/LandData.cs b/src/Syroot.Worms/Gen2/Armageddon/LandData.cs index d39bf62..5ab0da2 100644 --- a/src/Syroot.Worms/Gen2/Armageddon/LandData.cs +++ b/src/Syroot.Worms/Gen2/Armageddon/LandData.cs @@ -8,7 +8,7 @@ namespace Syroot.Worms.Gen2.Armageddon { /// /// Represents map configuration stored by the land generator in LAND.DAT files. - /// Used by WA and WWP. S. https://worms2d.info/Land_Data_file. + /// Used by WA. S. https://worms2d.info/Land_Data_file. /// public class LandData : ILoadableFile, ISaveableFile { diff --git a/src/Syroot.Worms/Gen2/Armageddon/MapGeneratorSettings.cs b/src/Syroot.Worms/Gen2/Armageddon/MapGeneratorSettings.cs new file mode 100644 index 0000000..4d2a9b5 --- /dev/null +++ b/src/Syroot.Worms/Gen2/Armageddon/MapGeneratorSettings.cs @@ -0,0 +1,159 @@ +using System.Runtime.InteropServices; + +namespace Syroot.Worms.Gen2.Armageddon +{ + /// + /// Represents the required configuration for the land generator to create a map. This structure appears in LEV + /// files (being their only content), in BIT files (being the header) and in PNG maps stored by WA (being the data + /// of the w2lv or waLV chunks). + /// + [StructLayout(LayoutKind.Sequential)] + public struct MapGeneratorSettings + { + // ---- MEMBERS ------------------------------------------------------------------------------------------------ + + /// + /// The random seed to generate the land shape (no effect in BIT files). + /// + public int LandSeed; + + /// + /// The random seed to generate object placements. + /// + public int ObjectSeed; + + /// + /// true treats the generated map as a cavern, otherwise as an island, depending on . + /// + [MarshalAs(UnmanagedType.Bool)] + public bool Cavern; + + /// + /// The style of the land generated, dependending on + /// + public MapGeneratorStyle Style; + + /// + /// true to disable an indestructible border being placed around the map. + /// + [MarshalAs(UnmanagedType.Bool)] + public bool NoIndestructibleBorders; + + /// + /// The probability percentage of map objects to appear on the land, from 0-100. + /// + public int ObjectPercentage; + + /// + /// The probability percentage of bridges to appear on the land, from 0-100. + /// + public int BridgePercentage; + + /// + /// The height of the water in percent, from 0-99. + /// + public int WaterLevel; + + /// + /// The version of the structure, determining the available values in Worms + /// Armageddon. + /// + public MapGeneratorVersion Version; + + /// + /// Represents the texture index determining the style of the generated map. + /// + public MapGeneratorSoil SoilTextureIndex; + + /// + /// Represents the water color used for the map (deprecated, used only in Worms Armageddon 1.0). + /// + public int WaterColor; + } + + /// + /// Represents the possible land styles. + /// + public enum MapGeneratorStyle : int + { + /// + /// Represents a single island or a cavern. + /// + OneIslandOrCavern, + + /// + /// Represents two islands or a double-layer cavern. + /// + TwoIslandsOrCaverns, + + /// + /// Represents one flat island or a cavern open at the bottom. + /// + OneFlatIslandOrCavernOpenBottom, + + /// + /// Represents two flat islands or a cavern open at the left or right. + /// + TwoFlatIslandsOrCavernOpenLeftRight + } + + /// + /// Represents the possible versions which can be stored in the field. + /// + public enum MapGeneratorVersion : short + { + /// + /// Game version 3.0. Special soil texture indices are 26 = Tribal, 27 = Tribal, 28 = Urban. Additionally, + /// floor and ceiling trimming is more severe. + /// + Version_3_0_0_0 = -1, + + /// + /// Game version 3.5. Special soil texture indices are 27 = Urban, 28 = undefined. + /// + Version_3_5_0_0 = 0, + + /// + /// Game version 3.6.26.4. Special soil texture indices are 26 = Tools, 27 = Tribal, Urban = 28 (same as in + /// WWP). + /// + Version_3_6_26_4 = 1 + } + + /// + /// Represents the possible soil styles. In case of Worms Armageddon, this list matches + /// . + /// + public enum MapGeneratorSoil : short + { + ClassicBeach, + ClassicDesert, + ClassicFarm, + ClassicForest, + ClassicHell, + Art, + Cheese, + Construction, + Desert, + Dungeon, + Easter, + Forest, + Fruit, + Gulf, + Hell, + Hospital, + Jungle, + Manhattan, + Medieval, + Music, + Pirate, + Snow, + Space, + Sports, + Tentacle, + Time, + Tools, + Tribal, + Urban + } +} diff --git a/src/Syroot.Worms/Gen2/WorldParty/LandData.cs b/src/Syroot.Worms/Gen2/WorldParty/LandData.cs index 3b378b1..8a0574e 100644 --- a/src/Syroot.Worms/Gen2/WorldParty/LandData.cs +++ b/src/Syroot.Worms/Gen2/WorldParty/LandData.cs @@ -107,7 +107,7 @@ namespace Syroot.Worms.Gen2.WorldParty { throw new InvalidDataException("Invalid LND file signature."); } - int fileLength = reader.ReadInt32(); + int fileSize = reader.ReadInt32(); // Read the data. Size = reader.ReadStruct(); diff --git a/src/Syroot.Worms/Gen2/Worms2/LandData.cs b/src/Syroot.Worms/Gen2/Worms2/LandData.cs index 783c931..bb48deb 100644 --- a/src/Syroot.Worms/Gen2/Worms2/LandData.cs +++ b/src/Syroot.Worms/Gen2/Worms2/LandData.cs @@ -111,7 +111,7 @@ namespace Syroot.Worms.Gen2.Worms2 { throw new InvalidDataException("Invalid LND file signature."); } - int fileLength = reader.ReadInt32(); + int fileSize = reader.ReadInt32(); // Read the data. Size = reader.ReadStruct();