diff --git a/CMakeLists.txt b/CMakeLists.txt
index b5a2518..4f03f3f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,7 +4,9 @@ if (TARGET wzmaplib)
message(DEBUG "wzmaplib is already available - no need to use FetchContent")
else()
message(STATUS "maptools: wzmaplib must be fetched")
- set(_cmake_min_ver_supported 3.11) # CMake 3.11 is the minimum version for FetchContent
+ # CMake 3.11 is the minimum version for FetchContent
+ # CMake 3.14 is the minimum version for FetchContent_MakeAvailable, CMake 3.18 is required for "SOURCE_SUBDIR" to work with it, and CMake 3.28 is required for EXCLUDE_FROM_ALL to work with it
+ set(_cmake_min_ver_supported 3.11)
endif()
cmake_minimum_required(VERSION ${_cmake_min_ver_supported}...3.24)
@@ -47,16 +49,23 @@ if(NOT TARGET wzmaplib)
FetchContent_Declare(
warzone2100_repo
GIT_REPOSITORY https://github.com/Warzone2100/warzone2100.git
- GIT_TAG 85310b635635955e453901c308c343667b6f0a35
+ GIT_TAG 6847a6500248bffbbaaa786f1a9b122d22307a15
GIT_PROGRESS TRUE
USES_TERMINAL_DOWNLOAD TRUE
+ SOURCE_SUBDIR "lib/wzmaplib"
+ EXCLUDE_FROM_ALL
)
- FetchContent_GetProperties(warzone2100_repo)
- if(NOT warzone2100_repo_POPULATED)
- FetchContent_Populate(warzone2100_repo)
+ if(NOT CMAKE_VERSION VERSION_LESS 3.28)
+ FetchContent_MakeAvailable(warzone2100_repo)
+ message(STATUS "maptools: Added wzmaplib")
+ else()
+ FetchContent_GetProperties(warzone2100_repo)
+ if(NOT warzone2100_repo_POPULATED)
+ FetchContent_Populate(warzone2100_repo)
+ endif()
+ message(STATUS "maptools: Adding wzmaplib")
+ add_subdirectory("${warzone2100_repo_SOURCE_DIR}/lib/wzmaplib" "lib/wzmaplib" EXCLUDE_FROM_ALL)
endif()
- message(STATUS "maptools: Adding wzmaplib")
- add_subdirectory("${warzone2100_repo_SOURCE_DIR}/lib/wzmaplib" "lib/wzmaplib" EXCLUDE_FROM_ALL)
endif()
find_package(PNG 1.2 REQUIRED)
diff --git a/ChangeLog b/ChangeLog
index fd11878..4b081d5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2025-01-29: Version 1.3.1:
+ * Update wzmaplib to 1.3.1
+
+2025-01-28: Version 1.3.0:
+ * Update wzmaplib to 1.3.0
+ * Fix loading script-generated maps
+ * Add --map-seed option
+
2024-08-01: Version 1.2.7:
* Update wzmaplib to 1.2.7
* Add --layers option for genpreview command
diff --git a/README.md b/README.md
index 7fea57d..3b7c89b 100644
--- a/README.md
+++ b/README.md
@@ -54,6 +54,7 @@ Convert a map from one format to another
| `--preserve-mods` | Copy other files from the original map package (i.e. the extra files / modifications in a map-mod) | | |
| `--output-uncompressed` | Output uncompressed to a folder (not in a .wz file) | | |
| `--set-name` | Set / override the map name when converting | | |
+| `--map-seed` | Specify the script-generated map seed | uint32_t | DEFAULTS to `rand()` |
> Note: When converting a script-generated map:
> - If the output format is `jsonv2` (or later) the map script will be preserved
@@ -76,6 +77,8 @@ Generate a map preview PNG
| `-o`,`--output` | Output PNG filename (+ path) | TEXT:PATH | REQUIRED (may also be specified as positional parameter) |
| `-c`,`--playercolors` | Player colors | ENUM:value in {`simple`, `wz`} | DEFAULTS to `simple` |
| `--scavcolor` | Specify the scavengers hex color | RGB hex color code | DEFAULTS to `#800000` (maroon) |
+| `--layers` | Specify layers to draw | Either `all` or a comma-separated list of any of: {`terrain`, `structures`, `oil`} | DEFAULTS to `all` |
+| `--map-seed` | Specify the script-generated map seed | uint32_t | DEFAULTS to `rand()` |
## `maptools package info`
@@ -90,6 +93,7 @@ Extract info / stats from a map package to JSON
| `-h`,`--help` | Print help message and exit | | |
| `-i`,`--input` | Input map package (.wz package, or extracted package folder) | TEXT:PATH | REQUIRED (may also be specified as positional parameter) |
| `-o`,`--output` | Output filename (+ path) | TEXT:PATH | |
+| `--map-seed` | Specify the script-generated map seed | uint32_t | DEFAULTS to `rand()` |
> If `--output` is not specified, the JSON result is output to stdout
@@ -116,6 +120,7 @@ Both `inputmapdir` and `outputmapdir` must exist.
| `-f`,`--format` | [Output map format](#output-map-formats) | ENUM:value in { `bjo`, `json`, `jsonv2`, `latest`} | REQUIRED |
| `-i`,`--input` | Input map directory | TEXT:DIR | REQUIRED (may also be specified as positional parameter) |
| `-o`,`--output` | Output map directory | TEXT:DIR | REQUIRED (may also be specified as positional parameter) |
+| `--map-seed` | Specify the script-generated map seed | uint32_t | DEFAULTS to `rand()` |
## `maptools map genpreview`
@@ -133,6 +138,7 @@ Both `inputmapdir` and the parent directory for the output filename (`output`) m
| `-c`,`--playercolors` | Player colors | ENUM:value in {`simple`, `wz`} | DEFAULTS to `simple` |
| `--scavcolor` | Specify the scavengers hex color | RGB hex color code | DEFAULTS to `#800000` (maroon) |
| `--layers` | Specify layers to draw | Either `all` or a comma-separated list of any of: {`terrain`, `structures`, `oil`} | DEFAULTS to `all` |
+| `--map-seed` | Specify the script-generated map seed | uint32_t | DEFAULTS to `rand()` |
# Output Level Info Formats
| [format] | Description | flaME | WZ < 3.4 | WZ 3.4+ | WZ 4.1+ | WZ 4.3+ |
diff --git a/VERSION.in b/VERSION.in
index c04c650..3a3cd8c 100644
--- a/VERSION.in
+++ b/VERSION.in
@@ -1 +1 @@
-1.2.7
+1.3.1
diff --git a/src/maptools.cpp b/src/maptools.cpp
index a5507f5..50160c3 100644
--- a/src/maptools.cpp
+++ b/src/maptools.cpp
@@ -240,7 +240,7 @@ bool lexical_cast(const std::string &input, MapPreviewColorScheme::DrawOptions &
} // namespace WzMap
-static bool convertMapPackage(const std::string& mapPackageContentsPath, const std::string& outputPath, WzMap::LevelFormat levelFormat, WzMap::OutputFormat outputFormat, bool copyAdditionalFiles, bool verbose, bool exportUncompressed, bool fixedLastMod, optional override_map_name = nullopt, std::shared_ptr mapIO = std::shared_ptr(new WzMap::StdIOProvider()))
+static bool convertMapPackage(const std::string& mapPackageContentsPath, const std::string& outputPath, WzMap::LevelFormat levelFormat, WzMap::OutputFormat outputFormat, uint32_t mapSeed, bool copyAdditionalFiles, bool verbose, bool exportUncompressed, bool fixedLastMod, optional override_map_name = nullopt, std::shared_ptr mapIO = std::shared_ptr(new WzMap::StdIOProvider()))
{
auto logger = std::make_shared(new MapToolDebugLogger(verbose));
@@ -251,7 +251,7 @@ static bool convertMapPackage(const std::string& mapPackageContentsPath, const s
return false;
}
- auto wzMap = wzMapPackage->loadMap(rand(), logger);
+ auto wzMap = wzMapPackage->loadMap(mapSeed, logger);
if (!wzMap)
{
// Failed to load map
@@ -324,7 +324,7 @@ static bool convertMapPackage(const std::string& mapPackageContentsPath, const s
}
#if !defined(WZ_MAPTOOLS_DISABLE_ARCHIVE_SUPPORT)
-static bool convertMapPackage_FromArchive(const std::string& mapArchive, const std::string& outputPath, WzMap::LevelFormat levelFormat, WzMap::OutputFormat outputFormat, bool copyAdditionalFiles, bool verbose, bool outputUncompressed, bool fixedLastMod, optional override_map_name)
+static bool convertMapPackage_FromArchive(const std::string& mapArchive, const std::string& outputPath, WzMap::LevelFormat levelFormat, WzMap::OutputFormat outputFormat, uint32_t mapSeed, bool copyAdditionalFiles, bool verbose, bool outputUncompressed, bool fixedLastMod, optional override_map_name)
{
auto zipArchive = WzMapZipIO::openZipArchiveFS(mapArchive.c_str());
if (!zipArchive)
@@ -333,13 +333,13 @@ static bool convertMapPackage_FromArchive(const std::string& mapArchive, const s
return false;
}
- return convertMapPackage("", outputPath, levelFormat, outputFormat, copyAdditionalFiles, verbose, outputUncompressed, fixedLastMod, override_map_name, zipArchive);
+ return convertMapPackage("", outputPath, levelFormat, outputFormat, mapSeed, copyAdditionalFiles, verbose, outputUncompressed, fixedLastMod, override_map_name, zipArchive);
}
#endif // !defined(WZ_MAPTOOLS_DISABLE_ARCHIVE_SUPPORT)
-static bool convertMap(WzMap::MapType mapType, uint32_t mapMaxPlayers, const std::string& inputMapDirectory, const std::string& outputMapDirectory, WzMap::OutputFormat outputFormat, bool verbose)
+static bool convertMap(WzMap::MapType mapType, uint32_t mapMaxPlayers, const std::string& inputMapDirectory, const std::string& outputMapDirectory, WzMap::OutputFormat outputFormat, uint32_t mapSeed, bool verbose)
{
- auto wzMap = WzMap::Map::loadFromPath(inputMapDirectory, mapType, mapMaxPlayers, rand(), std::make_shared(new MapToolDebugLogger(verbose)));
+ auto wzMap = WzMap::Map::loadFromPath(inputMapDirectory, mapType, mapMaxPlayers, mapSeed, std::make_shared(new MapToolDebugLogger(verbose)));
if (!wzMap)
{
// Failed to load map
@@ -489,7 +489,7 @@ enum class MapToolsPreviewColorProvider
WZPlayerColors
};
-static bool generateMapPreviewPNG_FromMapObject(WzMap::Map& map, const std::string& outputPNGPath, MapToolsPreviewColorProvider playerColorProvider, WzMap::MapPreviewColor scavsColor, const WzMap::MapPreviewColorScheme::DrawOptions& drawOptions, const WzMap::LevelDetails &levelDetails)
+static std::unique_ptr generateMapPreview_FromMapObject_Impl(WzMap::Map& map, MapToolsPreviewColorProvider playerColorProvider, WzMap::MapPreviewColor scavsColor, const WzMap::MapPreviewColorScheme::DrawOptions& drawOptions, const WzMap::LevelDetails &levelDetails)
{
WzMap::MapPreviewColorScheme previewColorScheme;
previewColorScheme.hqColor = {255, 0, 255, 255};
@@ -518,12 +518,18 @@ static bool generateMapPreviewPNG_FromMapObject(WzMap::Map& map, const std::stri
}
previewColorScheme.drawOptions = drawOptions;
- auto previewResult = WzMap::generate2DMapPreview(map, previewColorScheme, WzMap::MapStatsConfiguration(levelDetails.type));
+ return WzMap::generate2DMapPreview(map, previewColorScheme, WzMap::MapStatsConfiguration(levelDetails.type));
+}
+
+static bool generateMapPreviewPNG_FromMapObject(WzMap::Map& map, const std::string& outputPNGPath, MapToolsPreviewColorProvider playerColorProvider, WzMap::MapPreviewColor scavsColor, const WzMap::MapPreviewColorScheme::DrawOptions& drawOptions, const WzMap::LevelDetails &levelDetails)
+{
+ auto previewResult = generateMapPreview_FromMapObject_Impl(map, playerColorProvider, scavsColor, drawOptions, levelDetails);
if (!previewResult)
{
std::cerr << "Failed to generate map preview" << std::endl;
return false;
}
+
if (!savePng(outputPNGPath.c_str(), previewResult->imageData.data(), static_cast(previewResult->width), static_cast(previewResult->height)))
{
std::cerr << "Failed to save preview PNG" << std::endl;
@@ -536,7 +542,7 @@ static bool generateMapPreviewPNG_FromMapObject(WzMap::Map& map, const std::stri
return true;
}
-static bool generateMapPreviewPNG_FromPackageContents(const std::string& mapPackageContentsPath, const std::string& outputPNGPath, MapToolsPreviewColorProvider playerColorProvider, WzMap::MapPreviewColor scavsColor, const WzMap::MapPreviewColorScheme::DrawOptions& drawOptions, bool verbose, std::shared_ptr mapIO = std::shared_ptr(new WzMap::StdIOProvider()))
+static bool generateMapPreviewPNG_FromPackageContents(const std::string& mapPackageContentsPath, const std::string& outputPNGPath, MapToolsPreviewColorProvider playerColorProvider, WzMap::MapPreviewColor scavsColor, const WzMap::MapPreviewColorScheme::DrawOptions& drawOptions, uint32_t mapSeed, bool verbose, std::shared_ptr mapIO = std::shared_ptr(new WzMap::StdIOProvider()))
{
auto logger = std::make_shared(new MapToolDebugLogger(verbose));
@@ -547,7 +553,7 @@ static bool generateMapPreviewPNG_FromPackageContents(const std::string& mapPack
return false;
}
- auto wzMap = wzMapPackage->loadMap(rand(), logger);
+ auto wzMap = wzMapPackage->loadMap(mapSeed, logger);
if (!wzMap)
{
// Failed to load map
@@ -559,7 +565,7 @@ static bool generateMapPreviewPNG_FromPackageContents(const std::string& mapPack
}
#if !defined(WZ_MAPTOOLS_DISABLE_ARCHIVE_SUPPORT)
-static bool generateMapPreviewPNG_FromArchive(const std::string& mapArchive, const std::string& outputPNGPath, MapToolsPreviewColorProvider playerColorProvider, WzMap::MapPreviewColor scavsColor, const WzMap::MapPreviewColorScheme::DrawOptions& drawOptions, bool verbose)
+static bool generateMapPreviewPNG_FromArchive(const std::string& mapArchive, const std::string& outputPNGPath, MapToolsPreviewColorProvider playerColorProvider, WzMap::MapPreviewColor scavsColor, const WzMap::MapPreviewColorScheme::DrawOptions& drawOptions, uint32_t mapSeed, bool verbose)
{
auto zipArchive = WzMapZipIO::openZipArchiveFS(mapArchive.c_str());
if (!zipArchive)
@@ -568,13 +574,13 @@ static bool generateMapPreviewPNG_FromArchive(const std::string& mapArchive, con
return false;
}
- return generateMapPreviewPNG_FromPackageContents("", outputPNGPath, playerColorProvider, scavsColor, drawOptions, verbose, zipArchive);
+ return generateMapPreviewPNG_FromPackageContents("", outputPNGPath, playerColorProvider, scavsColor, drawOptions, mapSeed, verbose, zipArchive);
}
#endif // !defined(WZ_MAPTOOLS_DISABLE_ARCHIVE_SUPPORT)
-static bool generateMapPreviewPNG_FromMapDirectory(WzMap::MapType mapType, uint32_t mapMaxPlayers, const std::string& inputMapDirectory, const std::string& outputPNGPath, MapToolsPreviewColorProvider playerColorProvider, WzMap::MapPreviewColor scavsColor, const WzMap::MapPreviewColorScheme::DrawOptions& drawOptions, bool verbose)
+static bool generateMapPreviewPNG_FromMapDirectory(WzMap::MapType mapType, uint32_t mapMaxPlayers, const std::string& inputMapDirectory, const std::string& outputPNGPath, MapToolsPreviewColorProvider playerColorProvider, WzMap::MapPreviewColor scavsColor, const WzMap::MapPreviewColorScheme::DrawOptions& drawOptions, uint32_t mapSeed, bool verbose)
{
- auto wzMap = WzMap::Map::loadFromPath(inputMapDirectory, mapType, mapMaxPlayers, rand(), std::make_shared(new MapToolDebugLogger(verbose)));
+ auto wzMap = WzMap::Map::loadFromPath(inputMapDirectory, mapType, mapMaxPlayers, mapSeed, std::make_shared(new MapToolDebugLogger(verbose)));
if (!wzMap)
{
// Failed to load map
@@ -803,7 +809,7 @@ static nlohmann::ordered_json generateMapInfoJSON_FromPackage(WzMap::MapPackage&
return output;
}
-static optional generateMapInfoJSON_FromPackageContents(const std::string& mapPackageContentsPath, std::shared_ptr logger, std::shared_ptr mapIO = std::shared_ptr(new WzMap::StdIOProvider()))
+static optional generateMapInfoJSON_FromPackageContents(const std::string& mapPackageContentsPath, uint32_t mapSeed, std::shared_ptr logger, std::shared_ptr mapIO = std::shared_ptr(new WzMap::StdIOProvider()))
{
auto wzMapPackage = WzMap::MapPackage::loadPackage(mapPackageContentsPath, logger, mapIO);
if (!wzMapPackage)
@@ -812,7 +818,7 @@ static optional generateMapInfoJSON_FromPackageContents(
return nullopt;
}
- auto mapStatsResult = wzMapPackage->calculateMapStats();
+ auto mapStatsResult = wzMapPackage->calculateMapStats(mapSeed);
if (!mapStatsResult.has_value())
{
std::cerr << "Failed to calculate map info / stats from: " << mapPackageContentsPath << std::endl;
@@ -823,7 +829,7 @@ static optional generateMapInfoJSON_FromPackageContents(
}
#if !defined(WZ_MAPTOOLS_DISABLE_ARCHIVE_SUPPORT)
-static optional generateMapInfoJSON_FromArchive(const std::string& mapArchive, std::shared_ptr logger)
+static optional generateMapInfoJSON_FromArchive(const std::string& mapArchive, uint32_t mapSeed, std::shared_ptr logger)
{
auto zipArchive = WzMapZipIO::openZipArchiveFS(mapArchive.c_str());
if (!zipArchive)
@@ -832,7 +838,7 @@ static optional generateMapInfoJSON_FromArchive(const st
return nullopt;
}
- return generateMapInfoJSON_FromPackageContents("", logger, zipArchive);
+ return generateMapInfoJSON_FromPackageContents("", mapSeed, logger, zipArchive);
}
#endif // !defined(WZ_MAPTOOLS_DISABLE_ARCHIVE_SUPPORT)
@@ -898,9 +904,77 @@ class AsHexColorValue : public CLI::Validator {
}
};
-static void addSubCommand_Package(CLI::App& app, int& retVal, bool& verbose)
+class WzMapToolsAppInstance : public CLI::App
+{
+protected:
+ explicit WzMapToolsAppInstance()
+ : CLI::App("WZ2100 Map Tools")
+ { }
+public:
+ static std::shared_ptr makeWzMapToolsAppInstance()
+ {
+ class make_shared_enabler: public WzMapToolsAppInstance {};
+ auto app = std::make_shared();
+
+ #if defined(MAPTOOLS_CLI_VERSION_MAJOR) && defined(MAPTOOLS_CLI_VERSION_MINOR) && defined(MAPTOOLS_CLI_VERSION_REV)
+ app->set_version_flag("--version", []() -> std::string {
+ return generateMapToolsVersionInfo();
+ });
+ #else
+ #error Missing maptools version defines
+ #endif
+
+ // Initialize rand()
+ srand((unsigned int)time(NULL));
+ (void)rand();
+ app->mapSeed = rand();
+
+ std::stringstream footerInfo;
+ footerInfo << "License: GPL-2.0-or-later" << std::endl;
+ footerInfo << "Source: https://github.com/Warzone2100/maptools-cli" << std::endl;
+ app->footer(footerInfo.str());
+
+ app->add_flag("-v,--verbose", app->verbose, "Verbose output");
+
+ WzMapToolsAppInstance::addSubCommand_Package(app);
+ WzMapToolsAppInstance::addSubCommand_Map(app);
+
+ return app;
+ }
+ int getRetVal() const { return retVal; }
+private:
+ static void addSubCommand_Package(const std::shared_ptr& app);
+ static void addSubCommand_Map(const std::shared_ptr& app);
+private:
+ int retVal = 0;
+ bool verbose = false;
+
+ std::string inputPath;
+ std::string outputPath;
+ uint32_t mapSeed;
+ WzMap::OutputFormat outputMapFormat = WzMap::LatestOutputFormat;
+
+ // package variables
+ WzMap::LevelFormat outputLevelFormat = WzMap::LevelFormat::JSON;
+ bool sub_convert_copyadditionalfiles = false;
+ bool sub_convert_fixed_last_mod = false;
+ bool sub_convert_uncompressed = false;
+ std::string override_map_name;
+
+ MapToolsPreviewColorProvider preview_PlayerColorProvider = MapToolsPreviewColorProvider::Simple;
+ WzMap::MapPreviewColor preview_scavsColor = ScavsColorDefault;
+ WzMap::MapPreviewColorScheme::DrawOptions preview_drawOptions;
+
+ // map commands variables
+ WzMap::MapType mapType = WzMap::MapType::SKIRMISH;
+ uint32_t mapMaxPlayers = 0;
+};
+
+void WzMapToolsAppInstance::addSubCommand_Package(const std::shared_ptr& app)
{
- CLI::App* sub_package = app.add_subcommand("package", "Manipulating a map package");
+ std::weak_ptr weakAppInstance = std::weak_ptr(app);
+
+ CLI::App* sub_package = app->add_subcommand("package", "Manipulating a map package");
sub_package->fallthrough();
std::string inputOptionDescription;
@@ -921,53 +995,52 @@ static void addSubCommand_Package(CLI::App& app, int& retVal, bool& verbose)
// [CONVERTING MAP PACKAGE]
CLI::App* sub_convert = sub_package->add_subcommand("convert", "Convert a map from one format to another");
sub_convert->fallthrough();
- static WzMap::LevelFormat outputLevelFormat = WzMap::LevelFormat::JSON;
- sub_convert->add_option("-l,--levelformat", outputLevelFormat, "Output level info format")
+ sub_convert->add_option("-l,--levelformat", app->outputLevelFormat, "Output level info format")
->transform(CLI::CheckedTransformer(levelformat_map, CLI::ignore_case).description("value in {\n\t\tlev -> LEV (flaME-compatible / old),\n\t\tjson -> JSON level file (WZ 4.3+),\n\t\tlatest -> " + CLI::detail::to_string(WzMap::LatestLevelFormat) + "}"))
->default_val("latest");
- static WzMap::OutputFormat outputMapFormat = WzMap::LatestOutputFormat;
- sub_convert->add_option("-f,--format", outputMapFormat, "Output map format")
+ sub_convert->add_option("-f,--format", app->outputMapFormat, "Output map format")
->required()
->transform(CLI::CheckedTransformer(outputformat_map, CLI::ignore_case).description("value in {\n\t\tbjo -> Binary .BJO (flaME-compatible / old),\n\t\tjson -> JSONv1 (WZ 3.4+),\n\t\tjsonv2 -> JSONv2 (WZ 4.1+),\n\t\tlatest -> " + CLI::detail::to_string(WzMap::LatestOutputFormat) + "}"));
- static std::string inputMapPackage;
- sub_convert->add_option("-i,--input,input", inputMapPackage, inputOptionDescription)
+ sub_convert->add_option("-i,--input,input", app->inputPath, inputOptionDescription)
->required()
->check(CLI::ExistingPath);
- static std::string outputPath;
- sub_convert->add_option("-o,--output,output", outputPath, "Output path")
+ sub_convert->add_option("-o,--output,output", app->outputPath, "Output path")
->required()
->check(CLI::NonexistentPath);
- static bool sub_convert_copyadditionalfiles = false;
- sub_convert->add_flag("--preserve-mods", sub_convert_copyadditionalfiles, "Copy other files from the original map package (i.e. the extra files / modifications in a map-mod)");
- static bool sub_convert_fixed_last_mod = false;
- sub_convert->add_flag("--fixed-lastmod", sub_convert_fixed_last_mod, "Fixed last modification date (if outputting to a .wz archive)");
- static bool sub_convert_uncompressed = false;
- sub_convert->add_flag("--output-uncompressed", sub_convert_uncompressed, "Output uncompressed to a folder (not in a .wz file)");
- static std::string override_map_name;
- sub_convert->add_option("--set-name", override_map_name, "Set / override the map name when converting");
- sub_convert->callback([&]() {
+ sub_convert->add_flag("--preserve-mods", app->sub_convert_copyadditionalfiles, "Copy other files from the original map package (i.e. the extra files / modifications in a map-mod)");
+ sub_convert->add_flag("--fixed-lastmod", app->sub_convert_fixed_last_mod, "Fixed last modification date (if outputting to a .wz archive)");
+ sub_convert->add_flag("--output-uncompressed", app->sub_convert_uncompressed, "Output uncompressed to a folder (not in a .wz file)");
+ sub_convert->add_option("--set-name", app->override_map_name, "Set / override the map name when converting");
+ sub_convert->add_option("--map-seed", app->mapSeed, "Specify the script-generated map seed");
+ sub_convert->callback([weakAppInstance, inputPathIsFile]() {
+ auto app = weakAppInstance.lock();
+ if (!app)
+ {
+ std::cerr << "ERROR: Invalid instance" << std::endl;
+ return;
+ }
optional override_map_name_opt = nullopt;
- if (!override_map_name.empty())
+ if (!app->override_map_name.empty())
{
- override_map_name_opt = override_map_name;
+ override_map_name_opt = app->override_map_name;
}
- if (inputPathIsFile(inputMapPackage))
+ if (inputPathIsFile(app->inputPath))
{
#if !defined(WZ_MAPTOOLS_DISABLE_ARCHIVE_SUPPORT)
- if (!convertMapPackage_FromArchive(inputMapPackage, outputPath, outputLevelFormat, outputMapFormat, sub_convert_copyadditionalfiles, verbose, sub_convert_uncompressed, sub_convert_fixed_last_mod, override_map_name_opt))
+ if (!convertMapPackage_FromArchive(app->inputPath, app->outputPath, app->outputLevelFormat, app->outputMapFormat, app->mapSeed, app->sub_convert_copyadditionalfiles, app->verbose, app->sub_convert_uncompressed, app->sub_convert_fixed_last_mod, override_map_name_opt))
{
- retVal = 1;
+ app->retVal = 1;
}
#else
- std::cerr << "ERROR: maptools was compiled without support for .wz archives, and cannot open: " << inputMapPackage << std::endl;
+ std::cerr << "ERROR: maptools was compiled without support for .wz archives, and cannot open: " << app->inputPath << std::endl;
retVal = 1;
#endif
}
else
{
- if (!convertMapPackage(inputMapPackage, outputPath, outputLevelFormat, outputMapFormat, sub_convert_copyadditionalfiles, verbose, sub_convert_uncompressed, sub_convert_fixed_last_mod, override_map_name_opt))
+ if (!convertMapPackage(app->inputPath, app->outputPath, app->outputLevelFormat, app->outputMapFormat, app->mapSeed, app->sub_convert_copyadditionalfiles, app->verbose, app->sub_convert_uncompressed, app->sub_convert_fixed_last_mod, override_map_name_opt))
{
- retVal = 1;
+ app->retVal = 1;
}
}
});
@@ -975,42 +1048,44 @@ static void addSubCommand_Package(CLI::App& app, int& retVal, bool& verbose)
// [GENERATING MAP PREVIEW PNG]
CLI::App* sub_preview = sub_package->add_subcommand("genpreview", "Generate a map preview PNG");
sub_preview->fallthrough();
- static std::string preview_inputMap;
- sub_preview->add_option("-i,--input,input", preview_inputMap, inputOptionDescription)
+ sub_preview->add_option("-i,--input,input", app->inputPath, inputOptionDescription)
->required()
->check(CLI::ExistingPath);
- static std::string preview_outputPNGFilename;
- sub_preview->add_option("-o,--output,output", preview_outputPNGFilename, "Output PNG filename (+ path)")
+ sub_preview->add_option("-o,--output,output", app->outputPath, "Output PNG filename (+ path)")
->required()
->check(FileExtensionValidator(".png"));
- static MapToolsPreviewColorProvider preview_PlayerColorProvider = MapToolsPreviewColorProvider::Simple;
- sub_preview->add_option("-c,--playercolors", preview_PlayerColorProvider, "Player colors")
+ sub_preview->add_option("-c,--playercolors", app->preview_PlayerColorProvider, "Player colors")
->transform(CLI::CheckedTransformer(previewcolors_map, CLI::ignore_case).description("value in {\n\t\tsimple -> use one color for scavs, one color for players,\n\t\twz -> use WZ colors for players (distinct)\n\t}"))
->default_val("simple");
- static WzMap::MapPreviewColor preview_scavsColor = ScavsColorDefault;
- sub_preview->add_option("--scavcolor", preview_scavsColor, "Specify the scavengers hex color")
+ sub_preview->add_option("--scavcolor", app->preview_scavsColor, "Specify the scavengers hex color")
->check(AsHexColorValue());
- static WzMap::MapPreviewColorScheme::DrawOptions preview_drawOptions;
- sub_preview->add_option("--layers", preview_drawOptions, "Specify layers to draw\n\t\teither \"all\" or a comma-separated list of any of:\n\t\t\"terrain\",\"structures\",\"oil\"")
+ sub_preview->add_option("--layers", app->preview_drawOptions, "Specify layers to draw\n\t\teither \"all\" or a comma-separated list of any of:\n\t\t\"terrain\",\"structures\",\"oil\"")
->default_val("all");
- sub_preview->callback([&]() {
- if (inputPathIsFile(preview_inputMap))
+ sub_preview->add_option("--map-seed", app->mapSeed, "Specify the script-generated map seed");
+ sub_preview->callback([weakAppInstance, inputPathIsFile]() {
+ auto app = weakAppInstance.lock();
+ if (!app)
+ {
+ std::cerr << "ERROR: Invalid instance" << std::endl;
+ return;
+ }
+ if (inputPathIsFile(app->inputPath))
{
#if !defined(WZ_MAPTOOLS_DISABLE_ARCHIVE_SUPPORT)
- if (!generateMapPreviewPNG_FromArchive(preview_inputMap, preview_outputPNGFilename, preview_PlayerColorProvider, preview_scavsColor, preview_drawOptions, verbose))
+ if (!generateMapPreviewPNG_FromArchive(app->inputPath, app->outputPath, app->preview_PlayerColorProvider, app->preview_scavsColor, app->preview_drawOptions, app->mapSeed, app->verbose))
{
- retVal = 1;
+ app->retVal = 1;
}
#else
- std::cerr << "ERROR: maptools was compiled without support for .wz archives, and cannot open: " << preview_inputMap << std::endl;
- retVal = 1;
+ std::cerr << "ERROR: maptools was compiled without support for .wz archives, and cannot open: " << app->inputPath << std::endl;
+ app->retVal = 1;
#endif
}
else
{
- if (!generateMapPreviewPNG_FromPackageContents(preview_inputMap, preview_outputPNGFilename, preview_PlayerColorProvider, preview_scavsColor, preview_drawOptions, verbose))
+ if (!generateMapPreviewPNG_FromPackageContents(app->inputPath, app->outputPath, app->preview_PlayerColorProvider, app->preview_scavsColor, app->preview_drawOptions, app->mapSeed, app->verbose))
{
- retVal = 1;
+ app->retVal = 1;
}
}
});
@@ -1018,52 +1093,57 @@ static void addSubCommand_Package(CLI::App& app, int& retVal, bool& verbose)
// [EXTRACTING INFORMATION FROM A MAP PACKAGE]
CLI::App* sub_info = sub_package->add_subcommand("info", "Extract info / stats from a map package");
sub_info->fallthrough();
- static std::string info_inputMap;
- sub_info->add_option("-i,--input,input", info_inputMap, inputOptionDescription)
+ sub_info->add_option("-i,--input,input", app->inputPath, inputOptionDescription)
->required()
->check(CLI::ExistingPath);
- static std::string info_outputFilename;
- sub_info->add_option("-o,--output", info_outputFilename, "Output filename (+ path)")
+ sub_info->add_option("-o,--output", app->outputPath, "Output filename (+ path)")
->check(FileExtensionValidator(".json"));
- sub_info->callback([&]() {
+ sub_info->add_option("--map-seed", app->mapSeed, "Specify the script-generated map seed");
+ sub_info->callback([weakAppInstance, inputPathIsFile]() {
+ auto app = weakAppInstance.lock();
+ if (!app)
+ {
+ std::cerr << "ERROR: Invalid instance" << std::endl;
+ return;
+ }
optional mapInfoJSON;
std::shared_ptr logger;
- if (!info_outputFilename.empty())
+ if (!app->outputPath.empty())
{
- logger = std::make_shared(new MapToolDebugLogger(verbose));
+ logger = std::make_shared(new MapToolDebugLogger(app->verbose));
}
- if (inputPathIsFile(info_inputMap))
+ if (inputPathIsFile(app->inputPath))
{
#if !defined(WZ_MAPTOOLS_DISABLE_ARCHIVE_SUPPORT)
- mapInfoJSON = generateMapInfoJSON_FromArchive(info_inputMap, logger);
+ mapInfoJSON = generateMapInfoJSON_FromArchive(app->inputPath, app->mapSeed, logger);
#else
- std::cerr << "ERROR: maptools was compiled without support for .wz archives, and cannot open: " << info_inputMap << std::endl;
- retVal = 1;
+ std::cerr << "ERROR: maptools was compiled without support for .wz archives, and cannot open: " << app->inputPath << std::endl;
+ app->retVal = 1;
#endif
}
else
{
- mapInfoJSON = generateMapInfoJSON_FromPackageContents(info_inputMap, logger);
+ mapInfoJSON = generateMapInfoJSON_FromPackageContents(app->inputPath, app->mapSeed, logger);
}
if (!mapInfoJSON.has_value())
{
- retVal = 1;
+ app->retVal = 1;
return;
}
std::string jsonStr = mapInfoJSON.value().dump(4, ' ', false, nlohmann::ordered_json::error_handler_t::ignore);
- if (!info_outputFilename.empty())
+ if (!app->outputPath.empty())
{
WzMap::StdIOProvider stdOutput;
- if (!stdOutput.writeFullFile(info_outputFilename, jsonStr.c_str(), static_cast(jsonStr.size())))
+ if (!stdOutput.writeFullFile(app->outputPath, jsonStr.c_str(), static_cast(jsonStr.size())))
{
- std::cerr << "Failed to output JSON to: " << info_outputFilename << std::endl;
- retVal = 1;
+ std::cerr << "Failed to output JSON to: " << app->outputPath << std::endl;
+ app->retVal = 1;
return;
}
- std::cout << "Wrote output JSON to: " << info_outputFilename << std::endl;
+ std::cout << "Wrote output JSON to: " << app->outputPath << std::endl;
}
else
{
@@ -1072,102 +1152,85 @@ static void addSubCommand_Package(CLI::App& app, int& retVal, bool& verbose)
});
}
-static void addSubCommand_Map(CLI::App& app, int& retVal, bool& verbose)
+void WzMapToolsAppInstance::addSubCommand_Map(const std::shared_ptr& app)
{
- CLI::App* sub_map = app.add_subcommand("map", "Manipulating a map folder");
+ std::weak_ptr weakAppInstance = std::weak_ptr(app);
+
+ CLI::App* sub_map = app->add_subcommand("map", "Manipulating a map folder");
sub_map->fallthrough();
// [CONVERTING MAP FORMAT]
CLI::App* sub_convert = sub_map->add_subcommand("convert", "Convert a map from one format to another");
sub_convert->fallthrough();
- static WzMap::MapType mapType = WzMap::MapType::SKIRMISH;
- sub_convert->add_option("-t,--maptype", mapType, "Map type")
+ sub_convert->add_option("-t,--maptype", app->mapType, "Map type")
->transform(CLI::CheckedTransformer(maptype_map, CLI::ignore_case))
->default_val(WzMap::MapType::SKIRMISH);
- static uint32_t mapMaxPlayers = 0;
- sub_convert->add_option("-p,--maxplayers", mapMaxPlayers, "Map max players")
+ sub_convert->add_option("-p,--maxplayers", app->mapMaxPlayers, "Map max players")
->required()
->check(CLI::Range(1, 10));
- static WzMap::OutputFormat outputFormat = WzMap::LatestOutputFormat;
- sub_convert->add_option("-f,--format", outputFormat, "Output map format")
+ sub_convert->add_option("-f,--format", app->outputMapFormat, "Output map format")
->required()
->transform(CLI::CheckedTransformer(outputformat_map, CLI::ignore_case).description("value in {\n\t\tbjo -> Binary .BJO (flaME-compatible / old),\n\t\tjson -> JSONv1 (WZ 3.4+),\n\t\tjsonv2 -> JSONv2 (WZ 4.1+),\n\t\tlatest -> " + CLI::detail::to_string(WzMap::LatestOutputFormat) + "}"));
- static std::string inputMapDirectory;
- sub_convert->add_option("-i,--input,inputmapdir", inputMapDirectory, "Input map directory")
+ sub_convert->add_option("-i,--input,inputmapdir", app->inputPath, "Input map directory")
->required()
->check(CLI::ExistingDirectory);
- static std::string outputMapDirectory;
- sub_convert->add_option("-o,--output,outputmapdir", outputMapDirectory, "Output map directory")
+ sub_convert->add_option("-o,--output,outputmapdir", app->outputPath, "Output map directory")
->required()
->check(CLI::ExistingDirectory);
- sub_convert->callback([&]() {
- if (!convertMap(mapType, mapMaxPlayers, inputMapDirectory, outputMapDirectory, outputFormat, verbose))
+ sub_convert->add_option("--map-seed", app->mapSeed, "Specify the script-generated map seed");
+ sub_convert->callback([weakAppInstance]() {
+ auto app = weakAppInstance.lock();
+ if (!app)
{
- retVal = 1;
+ std::cerr << "ERROR: Invalid instance" << std::endl;
+ return;
+ }
+ if (!convertMap(app->mapType, app->mapMaxPlayers, app->inputPath, app->outputPath, app->outputMapFormat, app->mapSeed, app->verbose))
+ {
+ app->retVal = 1;
}
});
// [GENERATING MAP PREVIEW PNG]
CLI::App* sub_preview = sub_map->add_subcommand("genpreview", "Generate a map preview PNG");
sub_preview->fallthrough();
- static WzMap::MapType preview_mapType = WzMap::MapType::SKIRMISH;
- sub_preview->add_option("-t,--maptype", preview_mapType, "Map type")
+ sub_preview->add_option("-t,--maptype", app->mapType, "Map type")
->transform(CLI::CheckedTransformer(maptype_map, CLI::ignore_case))
->default_val(WzMap::MapType::SKIRMISH);
- static uint32_t preview_mapMaxPlayers = 0;
- sub_preview->add_option("-p,--maxplayers", preview_mapMaxPlayers, "Map max players")
+ sub_preview->add_option("-p,--maxplayers", app->mapMaxPlayers, "Map max players")
->required()
->check(CLI::Range(1, 10));
- static std::string preview_inputMapDirectory;
- sub_preview->add_option("-i,--input,inputmapdir", preview_inputMapDirectory, "Input map directory")
+ sub_preview->add_option("-i,--input,inputmapdir", app->inputPath, "Input map directory")
->required()
->check(CLI::ExistingDirectory);
- static std::string preview_outputPNGFilename;
- sub_preview->add_option("-o,--output,output", preview_outputPNGFilename, "Output PNG filename (+ path)")
+ sub_preview->add_option("-o,--output,output", app->outputPath, "Output PNG filename (+ path)")
->required()
->check(FileExtensionValidator(".png"));
- static MapToolsPreviewColorProvider preview_PlayerColorProvider = MapToolsPreviewColorProvider::Simple;
- sub_preview->add_option("-c,--playercolors", preview_PlayerColorProvider, "Player colors")
+ sub_preview->add_option("-c,--playercolors", app->preview_PlayerColorProvider, "Player colors")
->transform(CLI::CheckedTransformer(previewcolors_map, CLI::ignore_case).description("value in {\n\t\tsimple -> use one color for scavs, one color for players,\n\t\twz -> use WZ colors for players (distinct)\n\t}"))
->default_val("simple");
- static WzMap::MapPreviewColor preview_scavsColor = ScavsColorDefault;
- sub_preview->add_option("--scavcolor", preview_scavsColor, "Specify the scavengers hex color")
+ sub_preview->add_option("--scavcolor", app->preview_scavsColor, "Specify the scavengers hex color")
->check(AsHexColorValue());
- static WzMap::MapPreviewColorScheme::DrawOptions preview_drawOptions;
- sub_preview->add_option("--layers", preview_drawOptions, "Specify layers to draw\n\t\teither \"all\" or a comma-separated list of any of:\n\t\t\"terrain\",\"structures\",\"oil\"")
+ sub_preview->add_option("--layers", app->preview_drawOptions, "Specify layers to draw\n\t\teither \"all\" or a comma-separated list of any of:\n\t\t\"terrain\",\"structures\",\"oil\"")
->default_val("all");
- sub_preview->callback([&]() {
- if (!generateMapPreviewPNG_FromMapDirectory(preview_mapType, preview_mapMaxPlayers, preview_inputMapDirectory, preview_outputPNGFilename, preview_PlayerColorProvider, preview_scavsColor, preview_drawOptions, verbose))
+ sub_preview->add_option("--map-seed", app->mapSeed, "Specify the script-generated map seed");
+ sub_preview->callback([weakAppInstance]() {
+ auto app = weakAppInstance.lock();
+ if (!app)
{
- retVal = 1;
+ std::cerr << "ERROR: Invalid instance" << std::endl;
+ return;
+ }
+ if (!generateMapPreviewPNG_FromMapDirectory(app->mapType, app->mapMaxPlayers, app->inputPath, app->outputPath, app->preview_PlayerColorProvider, app->preview_scavsColor, app->preview_drawOptions, app->mapSeed, app->verbose))
+ {
+ app->retVal = 1;
}
});
}
int main(int argc, char **argv)
{
- int retVal = 0;
- CLI::App app{"WZ2100 Map Tools"};
-
-#if defined(MAPTOOLS_CLI_VERSION_MAJOR) && defined(MAPTOOLS_CLI_VERSION_MINOR) && defined(MAPTOOLS_CLI_VERSION_REV)
- app.set_version_flag("--version", []() -> std::string {
- return generateMapToolsVersionInfo();
- });
-#else
- #error Missing maptools version defines
-#endif
-
- std::stringstream footerInfo;
- footerInfo << "License: GPL-2.0-or-later" << std::endl;
- footerInfo << "Source: https://github.com/Warzone2100/maptools-cli" << std::endl;
- app.footer(footerInfo.str());
-
- bool verbose = false;
- app.add_flag("-v,--verbose", verbose, "Verbose output");
-
- addSubCommand_Package(app, retVal, verbose);
- addSubCommand_Map(app, retVal, verbose);
-
- CLI11_PARSE(app, argc, argv);
- return retVal;
+ std::shared_ptr app = WzMapToolsAppInstance::makeWzMapToolsAppInstance();
+ CLI11_PARSE((*app), argc, argv);
+ return app->getRetVal();
}