mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-10 02:53:51 +00:00
Adds cli_dispatch.{hpp,cpp} containing a static table of every
extracted handler family's dispatch function. The table-walker
tryDispatchAll() iterates the table once per argv token, calling
each handler in turn. handleConvertSingle stays as a special-
case call in main.cpp because it threads dataPath through.
main.cpp shrinks from 486 to 236 lines (-250). Adding a new
handler module now requires touching only cli_dispatch.cpp's
include list + table — no main.cpp edits, no growing
if-else chain. The 60+ #include lines for individual cli_*
modules collapse to one #include for cli_dispatch.hpp.
246 lines
9.2 KiB
C++
246 lines
9.2 KiB
C++
#include "editor_app.hpp"
|
|
#include "cli_dispatch.hpp"
|
|
#include "cli_convert_single.hpp"
|
|
#include "cli_arg_required.hpp"
|
|
#include "content_pack.hpp"
|
|
#include "npc_spawner.hpp"
|
|
#include "object_placer.hpp"
|
|
#include "quest_editor.hpp"
|
|
#include "wowee_terrain.hpp"
|
|
#include "zone_manifest.hpp"
|
|
#include "terrain_editor.hpp"
|
|
#include "terrain_biomes.hpp"
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
#include <iomanip>
|
|
#include <sstream>
|
|
#include "pipeline/wowee_model.hpp"
|
|
#include "pipeline/wowee_building.hpp"
|
|
#include "pipeline/wowee_collision.hpp"
|
|
#include "pipeline/wowee_terrain_loader.hpp"
|
|
#include "pipeline/wmo_loader.hpp"
|
|
#include "pipeline/m2_loader.hpp"
|
|
#include "pipeline/adt_loader.hpp"
|
|
#include "pipeline/asset_manager.hpp"
|
|
#include "pipeline/custom_zone_discovery.hpp"
|
|
#include "core/logger.hpp"
|
|
#include <string>
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
#include <unordered_map>
|
|
#include <unordered_set>
|
|
#include <map>
|
|
#include <set>
|
|
#include <cctype>
|
|
#include <cstdio>
|
|
#include <chrono>
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <algorithm>
|
|
#include <nlohmann/json.hpp>
|
|
#include "stb_image_write.h"
|
|
#include "stb_image.h" // implementation in stb_image_impl.cpp
|
|
|
|
// ─── Open-format consistency checks ─────────────────────────────
|
|
// Both validators are called from the per-file CLI commands AND
|
|
// from --validate-all which walks a zone dir. Returning a vector
|
|
// of error strings (empty == passed) keeps callers simple.
|
|
// Minimal SHA-256 implementation (FIPS 180-4) used by --export-zone-checksum
|
|
// to produce hashes that interoperate with `sha256sum -c`. Not exposed beyond
|
|
// this file — about 90 LoC, no external deps. See RFC 6234 for the algorithm.
|
|
|
|
|
|
|
|
int main(int argc, char* argv[]) {
|
|
std::string dataPath;
|
|
std::string adtMap;
|
|
int adtX = -1, adtY = -1;
|
|
|
|
// Detect non-GUI options that are missing their argument and bail out
|
|
// with a helpful message instead of silently dropping into the GUI.
|
|
for (int i = 1; i < argc; i++) {
|
|
for (std::size_t k = 0; k < wowee::editor::cli::kArgRequiredSize; ++k) {
|
|
const char* opt = wowee::editor::cli::kArgRequired[k];
|
|
if (std::strcmp(argv[i], opt) == 0 && i + 1 >= argc) {
|
|
std::fprintf(stderr, "%s requires an argument\n", opt);
|
|
return 1;
|
|
}
|
|
}
|
|
if (std::strcmp(argv[i], "--adt") == 0 && i + 3 >= argc) {
|
|
std::fprintf(stderr, "--adt requires <map> <x> <y>\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--diff-zone") == 0 && i + 2 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--diff-zone requires <zoneA> <zoneB>\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--diff-glb") == 0 && i + 2 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--diff-glb requires <a.glb> <b.glb>\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--diff-wom") == 0 && i + 2 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--diff-wom requires <a-base> <b-base>\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--diff-wob") == 0 && i + 2 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--diff-wob requires <a-base> <b-base>\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--diff-whm") == 0 && i + 2 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--diff-whm requires <a-base> <b-base>\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--diff-woc") == 0 && i + 2 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--diff-woc requires <a.woc> <b.woc>\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--diff-jsondbc") == 0 && i + 2 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--diff-jsondbc requires <a.json> <b.json>\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--diff-extract") == 0 && i + 2 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--diff-extract requires <dirA> <dirB>\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--diff-checksum") == 0 && i + 2 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--diff-checksum requires <a.sha256> <b.sha256>\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--diff-wcp") == 0 && i + 2 >= argc) {
|
|
std::fprintf(stderr, "--diff-wcp requires two paths\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--add-creature") == 0 && i + 5 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--add-creature requires <zoneDir> <name> <x> <y> <z>\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--add-object") == 0 && i + 6 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--add-object requires <zoneDir> <m2|wmo> <gamePath> <x> <y> <z>\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--add-quest") == 0 && i + 2 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--add-quest requires <zoneDir> <title>\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--add-quest-objective") == 0 && i + 4 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--add-quest-objective requires <zoneDir> <questIdx> <type> <targetName>\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--remove-quest-objective") == 0 && i + 3 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--remove-quest-objective requires <zoneDir> <questIdx> <objIdx>\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--clone-quest") == 0 && i + 2 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--clone-quest requires <zoneDir> <questIdx>\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--clone-creature") == 0 && i + 2 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--clone-creature requires <zoneDir> <idx>\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--clone-object") == 0 && i + 2 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--clone-object requires <zoneDir> <idx>\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--add-quest-reward-item") == 0 && i + 3 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--add-quest-reward-item requires <zoneDir> <questIdx> <itemPath>\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--set-quest-reward") == 0 && i + 2 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--set-quest-reward requires <zoneDir> <questIdx> [--xp N] [--gold N] [--silver N] [--copper N]\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--add-tile") == 0 && i + 3 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--add-tile requires <zoneDir> <tx> <ty>\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--remove-tile") == 0 && i + 3 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--remove-tile requires <zoneDir> <tx> <ty>\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--copy-zone") == 0 && i + 2 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--copy-zone requires <srcDir> <newName>\n");
|
|
return 1;
|
|
}
|
|
if (std::strcmp(argv[i], "--rename-zone") == 0 && i + 2 >= argc) {
|
|
std::fprintf(stderr,
|
|
"--rename-zone requires <srcDir> <newName>\n");
|
|
return 1;
|
|
}
|
|
for (const char* opt : {"--remove-creature", "--remove-object",
|
|
"--remove-quest"}) {
|
|
if (std::strcmp(argv[i], opt) == 0 && i + 2 >= argc) {
|
|
std::fprintf(stderr, "%s requires <zoneDir> <index>\n", opt);
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int i = 1; i < argc; i++) {
|
|
// CLI handlers live in cli_dispatch.cpp's table-driven
|
|
// dispatcher. handleConvertSingle is the one outlier
|
|
// because it needs dataPath threaded in; everything else
|
|
// goes through tryDispatchAll. Either return path captures
|
|
// the handler's exit code via outRc.
|
|
int outRc = 0;
|
|
if (wowee::editor::cli::handleConvertSingle(i, argc, argv,
|
|
dataPath, outRc)) {
|
|
return outRc;
|
|
}
|
|
if (wowee::editor::cli::tryDispatchAll(i, argc, argv, outRc)) {
|
|
return outRc;
|
|
}
|
|
// GUI-state args don't return — they're absorbed and
|
|
// applied to the EditorApp after argv parsing finishes.
|
|
if (std::strcmp(argv[i], "--data") == 0 && i + 1 < argc) {
|
|
dataPath = argv[++i];
|
|
} else if (std::strcmp(argv[i], "--adt") == 0 && i + 3 < argc) {
|
|
adtMap = argv[++i];
|
|
adtX = std::atoi(argv[++i]);
|
|
adtY = std::atoi(argv[++i]);
|
|
}
|
|
}
|
|
|
|
|
|
if (dataPath.empty()) {
|
|
dataPath = "Data";
|
|
LOG_INFO("No --data path specified, using default: ", dataPath);
|
|
}
|
|
|
|
wowee::editor::EditorApp app;
|
|
if (!app.initialize(dataPath)) {
|
|
LOG_ERROR("Failed to initialize editor");
|
|
return 1;
|
|
}
|
|
|
|
if (!adtMap.empty()) {
|
|
app.loadADT(adtMap, adtX, adtY);
|
|
}
|
|
|
|
app.run();
|
|
app.shutdown();
|
|
|
|
return 0;
|
|
}
|