mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-09 18:43:51 +00:00
refactor(editor): extract zone-pack orchestrators into cli_zone_packs.cpp
Continues the modularization started in 6c9ab6fa. Moves the four
pack-orchestrator handlers (--gen-zone-texture-pack, -mesh-pack,
-starter-pack, --gen-project-starter-pack) into their own file
following the same handle<Family> pattern.
Side cleanup:
- Consolidated the duplicated --seed flag parser into a single
parseSeedFlag helper
- Consolidated the std::system + > /dev/null wrap into runSilently
main.cpp drops 28,329 → 28,070 lines (-259). Pack family is fully
self-contained (~260 lines), behavior unchanged (verified by
re-running gen-zone-starter-pack and confirming 6 PNGs + 5 WOMs).
This commit is contained in:
parent
6c9ab6faed
commit
774dab9330
4 changed files with 302 additions and 263 deletions
|
|
@ -1,5 +1,6 @@
|
|||
#include "editor_app.hpp"
|
||||
#include "cli_gen_audio.hpp"
|
||||
#include "cli_zone_packs.hpp"
|
||||
#include "content_pack.hpp"
|
||||
#include "npc_spawner.hpp"
|
||||
#include "object_placer.hpp"
|
||||
|
|
@ -1365,6 +1366,9 @@ int main(int argc, char* argv[]) {
|
|||
if (wowee::editor::cli::handleGenAudio(i, argc, argv, outRc)) {
|
||||
return outRc;
|
||||
}
|
||||
if (wowee::editor::cli::handleZonePacks(i, argc, argv, outRc)) {
|
||||
return outRc;
|
||||
}
|
||||
}
|
||||
if (std::strcmp(argv[i], "--data") == 0 && i + 1 < argc) {
|
||||
dataPath = argv[++i];
|
||||
|
|
@ -14397,269 +14401,6 @@ int main(int argc, char* argv[]) {
|
|||
std::printf(" objects : %d\n", objects);
|
||||
std::printf(" items : %d\n", items);
|
||||
return 0;
|
||||
} else if (std::strcmp(argv[i], "--gen-zone-texture-pack") == 0 && i + 1 < argc) {
|
||||
// Drop a starter PNG texture pack into <zoneDir>/textures/
|
||||
// by fanning out to the procedural --gen-texture-* commands.
|
||||
// Saves the user from sourcing proprietary art when bringing
|
||||
// up a new zone — six themed textures (grass, dirt, stone,
|
||||
// brick, wood, water) cover most outdoor & dungeon needs.
|
||||
std::string zoneDir = argv[++i];
|
||||
uint32_t seed = 1;
|
||||
for (int k = i + 1; k < argc; ++k) {
|
||||
std::string flag = argv[k];
|
||||
if (flag == "--seed" && k + 1 < argc) {
|
||||
try { seed = static_cast<uint32_t>(std::stoul(argv[++k])); } catch (...) {}
|
||||
i = k;
|
||||
} else if (flag.rfind("--", 0) == 0) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-texture-pack: unknown flag '%s'\n", flag.c_str());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
std::filesystem::path zp(zoneDir);
|
||||
if (!std::filesystem::exists(zp / "zone.json")) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-texture-pack: %s has no zone.json\n",
|
||||
zoneDir.c_str());
|
||||
return 1;
|
||||
}
|
||||
std::filesystem::path texDir = zp / "textures";
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(texDir, ec);
|
||||
if (ec) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-texture-pack: cannot create %s: %s\n",
|
||||
texDir.string().c_str(), ec.message().c_str());
|
||||
return 1;
|
||||
}
|
||||
std::string self = (argc > 0) ? argv[0] : "wowee_editor";
|
||||
// Each row: {flag, fileName, args...}. Using std::string so
|
||||
// we can interpolate the per-pack seed without sprintf
|
||||
// gymnastics; subprocess invocation handles quoting.
|
||||
struct Cmd {
|
||||
std::string flag;
|
||||
std::string outName;
|
||||
std::vector<std::string> args;
|
||||
};
|
||||
std::vector<Cmd> jobs = {
|
||||
{"--gen-texture-noise", "grass.png", {"4A7C2E", "5C9B3A", "256", "256"}},
|
||||
{"--gen-texture-noise", "dirt.png", {"6B4A2A", "8B5E3A", "256", "256"}},
|
||||
{"--gen-texture-checker", "stone.png", {"7A7A7A", "5A5A5A", "32", "256", "256"}},
|
||||
{"--gen-texture-brick", "brick.png", {"8B4513", "D3D3D3", "64", "24", "4", "256", "256"}},
|
||||
{"--gen-texture-wood", "wood.png", {"8B5A2B", "4A3216", "12", std::to_string(seed), "256", "256"}},
|
||||
{"--gen-texture-radial", "water.png", {"3A6FA0", "1E4A78", "256", "256"}},
|
||||
};
|
||||
int written = 0;
|
||||
for (const auto& job : jobs) {
|
||||
std::filesystem::path out = texDir / job.outName;
|
||||
std::string cmd = "\"" + self + "\" " + job.flag + " \"" + out.string() + "\"";
|
||||
for (const auto& a : job.args) cmd += " " + a;
|
||||
cmd += " > /dev/null 2>&1";
|
||||
int rc = std::system(cmd.c_str());
|
||||
if (rc != 0) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-texture-pack: %s failed (rc=%d)\n",
|
||||
job.flag.c_str(), rc);
|
||||
} else {
|
||||
++written;
|
||||
}
|
||||
}
|
||||
std::printf("gen-zone-texture-pack: wrote %d of %zu textures to %s\n",
|
||||
written, jobs.size(), texDir.string().c_str());
|
||||
return written == static_cast<int>(jobs.size()) ? 0 : 1;
|
||||
} else if (std::strcmp(argv[i], "--gen-zone-mesh-pack") == 0 && i + 1 < argc) {
|
||||
// Companion to --gen-zone-texture-pack: drops a starter
|
||||
// WOM mesh pack into <zoneDir>/meshes/. Bootstraps the
|
||||
// mesh side of the open-format pipeline so a fresh zone
|
||||
// has placeholders for outdoor decoration without any
|
||||
// proprietary M2 imports. Each rock variant uses a
|
||||
// different seed so they read as distinct boulders.
|
||||
std::string zoneDir = argv[++i];
|
||||
uint32_t seed = 1;
|
||||
for (int k = i + 1; k < argc; ++k) {
|
||||
std::string flag = argv[k];
|
||||
if (flag == "--seed" && k + 1 < argc) {
|
||||
try { seed = static_cast<uint32_t>(std::stoul(argv[++k])); } catch (...) {}
|
||||
i = k;
|
||||
} else if (flag.rfind("--", 0) == 0) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-mesh-pack: unknown flag '%s'\n", flag.c_str());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
std::filesystem::path zp(zoneDir);
|
||||
if (!std::filesystem::exists(zp / "zone.json")) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-mesh-pack: %s has no zone.json\n",
|
||||
zoneDir.c_str());
|
||||
return 1;
|
||||
}
|
||||
std::filesystem::path meshDir = zp / "meshes";
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(meshDir, ec);
|
||||
if (ec) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-mesh-pack: cannot create %s: %s\n",
|
||||
meshDir.string().c_str(), ec.message().c_str());
|
||||
return 1;
|
||||
}
|
||||
std::string self = (argc > 0) ? argv[0] : "wowee_editor";
|
||||
struct MeshJob {
|
||||
std::string flag;
|
||||
std::string outBase; // no .wom extension
|
||||
std::vector<std::string> args;
|
||||
};
|
||||
std::string s0 = std::to_string(seed);
|
||||
std::string s1 = std::to_string(seed + 17);
|
||||
std::string s2 = std::to_string(seed + 41);
|
||||
std::vector<MeshJob> jobs = {
|
||||
// 3 rock variants with distinct seeds for variety
|
||||
{"--gen-mesh-rock", "rock_small", {"0.6", "0.30", "2", s0}},
|
||||
{"--gen-mesh-rock", "rock_medium", {"1.2", "0.25", "2", s1}},
|
||||
{"--gen-mesh-rock", "rock_large", {"2.4", "0.35", "3", s2}},
|
||||
// Tree placeholder, fence segment for boundaries
|
||||
{"--gen-mesh-tree", "tree", {"0.15", "3.0", "1.0"}},
|
||||
{"--gen-mesh-fence", "fence", {"5", "1.2", "1.4", "0.06"}},
|
||||
};
|
||||
int written = 0;
|
||||
for (const auto& job : jobs) {
|
||||
std::filesystem::path out = meshDir / job.outBase;
|
||||
std::string cmd = "\"" + self + "\" " + job.flag + " \"" + out.string() + "\"";
|
||||
for (const auto& a : job.args) cmd += " " + a;
|
||||
cmd += " > /dev/null 2>&1";
|
||||
int rc = std::system(cmd.c_str());
|
||||
if (rc != 0) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-mesh-pack: %s failed (rc=%d)\n",
|
||||
job.flag.c_str(), rc);
|
||||
} else {
|
||||
++written;
|
||||
}
|
||||
}
|
||||
std::printf("gen-zone-mesh-pack: wrote %d of %zu meshes to %s\n",
|
||||
written, jobs.size(), meshDir.string().c_str());
|
||||
return written == static_cast<int>(jobs.size()) ? 0 : 1;
|
||||
} else if (std::strcmp(argv[i], "--gen-zone-starter-pack") == 0 && i + 1 < argc) {
|
||||
// Convenience entry point: run --gen-zone-texture-pack
|
||||
// and --gen-zone-mesh-pack in sequence so a fresh zone
|
||||
// gets a full open-format asset bootstrap from a single
|
||||
// command. The seed propagates to both children so a
|
||||
// user can reliably reproduce the same starter pack.
|
||||
std::string zoneDir = argv[++i];
|
||||
uint32_t seed = 1;
|
||||
for (int k = i + 1; k < argc; ++k) {
|
||||
std::string flag = argv[k];
|
||||
if (flag == "--seed" && k + 1 < argc) {
|
||||
try { seed = static_cast<uint32_t>(std::stoul(argv[++k])); } catch (...) {}
|
||||
i = k;
|
||||
} else if (flag.rfind("--", 0) == 0) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-starter-pack: unknown flag '%s'\n", flag.c_str());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!std::filesystem::exists(std::filesystem::path(zoneDir) / "zone.json")) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-starter-pack: %s has no zone.json\n",
|
||||
zoneDir.c_str());
|
||||
return 1;
|
||||
}
|
||||
std::string self = (argc > 0) ? argv[0] : "wowee_editor";
|
||||
std::string seedStr = std::to_string(seed);
|
||||
std::printf("gen-zone-starter-pack: %s (seed %u)\n",
|
||||
zoneDir.c_str(), seed);
|
||||
std::printf(" step 1/2: textures\n");
|
||||
std::string cmd1 = "\"" + self + "\" --gen-zone-texture-pack \"" +
|
||||
zoneDir + "\" --seed " + seedStr;
|
||||
int rc1 = std::system(cmd1.c_str());
|
||||
if (rc1 != 0) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-starter-pack: texture step failed (rc=%d)\n", rc1);
|
||||
return 1;
|
||||
}
|
||||
std::printf(" step 2/2: meshes\n");
|
||||
std::string cmd2 = "\"" + self + "\" --gen-zone-mesh-pack \"" +
|
||||
zoneDir + "\" --seed " + seedStr;
|
||||
int rc2 = std::system(cmd2.c_str());
|
||||
if (rc2 != 0) {
|
||||
std::fprintf(stderr,
|
||||
"gen-zone-starter-pack: mesh step failed (rc=%d)\n", rc2);
|
||||
return 1;
|
||||
}
|
||||
std::printf("\ngen-zone-starter-pack: complete\n");
|
||||
std::printf(" zone dir : %s\n", zoneDir.c_str());
|
||||
std::printf(" textures : 6 PNGs in textures/\n");
|
||||
std::printf(" meshes : 5 WOMs in meshes/\n");
|
||||
return 0;
|
||||
} else if (std::strcmp(argv[i], "--gen-project-starter-pack") == 0 && i + 1 < argc) {
|
||||
// Project-wide bootstrap. For every zone in <projectDir>,
|
||||
// run --gen-zone-starter-pack (textures + meshes) and
|
||||
// --gen-zone-audio-pack (audio). Each zone gets a unique
|
||||
// sub-seed offset from the base seed so per-zone content
|
||||
// looks distinct (e.g. rocks differ, wood grain differs).
|
||||
//
|
||||
// Pairs with --validate-project-packs as the inverse —
|
||||
// bootstrap, then audit, then ship.
|
||||
std::string projectDir = argv[++i];
|
||||
uint32_t seed = 1;
|
||||
for (int k = i + 1; k < argc; ++k) {
|
||||
std::string flag = argv[k];
|
||||
if (flag == "--seed" && k + 1 < argc) {
|
||||
try { seed = static_cast<uint32_t>(std::stoul(argv[++k])); } catch (...) {}
|
||||
i = k;
|
||||
} else if (flag.rfind("--", 0) == 0) {
|
||||
std::fprintf(stderr,
|
||||
"gen-project-starter-pack: unknown flag '%s'\n", flag.c_str());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
namespace fs = std::filesystem;
|
||||
if (!fs::exists(projectDir) || !fs::is_directory(projectDir)) {
|
||||
std::fprintf(stderr,
|
||||
"gen-project-starter-pack: %s is not a directory\n",
|
||||
projectDir.c_str());
|
||||
return 1;
|
||||
}
|
||||
std::vector<std::string> zones;
|
||||
for (const auto& entry : fs::directory_iterator(projectDir)) {
|
||||
if (!entry.is_directory()) continue;
|
||||
if (!fs::exists(entry.path() / "zone.json")) continue;
|
||||
zones.push_back(entry.path().string());
|
||||
}
|
||||
std::sort(zones.begin(), zones.end());
|
||||
if (zones.empty()) {
|
||||
std::fprintf(stderr,
|
||||
"gen-project-starter-pack: %s contains no zones\n",
|
||||
projectDir.c_str());
|
||||
return 1;
|
||||
}
|
||||
std::string self = (argc > 0) ? argv[0] : "wowee_editor";
|
||||
std::printf("gen-project-starter-pack: %s (base seed %u)\n",
|
||||
projectDir.c_str(), seed);
|
||||
std::printf(" zones: %zu\n\n", zones.size());
|
||||
int passed = 0, failed = 0;
|
||||
for (size_t z = 0; z < zones.size(); ++z) {
|
||||
std::string zoneSeed = std::to_string(seed + z * 17);
|
||||
std::string name = fs::path(zones[z]).filename().string();
|
||||
std::printf(" [%zu/%zu] %s (seed %s)\n",
|
||||
z + 1, zones.size(), name.c_str(), zoneSeed.c_str());
|
||||
std::string c1 = "\"" + self + "\" --gen-zone-starter-pack \"" +
|
||||
zones[z] + "\" --seed " + zoneSeed +
|
||||
" > /dev/null 2>&1";
|
||||
int rc1 = std::system(c1.c_str());
|
||||
std::string c2 = "\"" + self + "\" --gen-zone-audio-pack \"" +
|
||||
zones[z] + "\" > /dev/null 2>&1";
|
||||
int rc2 = std::system(c2.c_str());
|
||||
if (rc1 == 0 && rc2 == 0) {
|
||||
++passed;
|
||||
std::printf(" OK textures + meshes + audio\n");
|
||||
} else {
|
||||
++failed;
|
||||
std::printf(" FAIL starter rc=%d, audio rc=%d\n", rc1, rc2);
|
||||
}
|
||||
}
|
||||
std::printf("\n Total: %d passed, %d failed\n", passed, failed);
|
||||
return failed == 0 ? 0 : 1;
|
||||
} else if (std::strcmp(argv[i], "--info-zone-summary") == 0 && i + 1 < argc) {
|
||||
// One-glance health digest for a zone. Combines the per-
|
||||
// category counts/bytes from the inventory commands with
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue