Commit graph

169 commits

Author SHA1 Message Date
Kelsi
a25961e2dd refactor(editor): extract --info-{zone,project}-water into cli_info_water.cpp
Moves the two water-layer audit handlers (--info-zone-water,
--info-project-water) out of main.cpp into a new
cli_info_water.{hpp,cpp} module. Both aggregate liquid data
(water/ocean/magma/slime) across MH2O chunks; the project
variant rolls per-zone counts into a project-wide total with
height range and per-type histogram.

main.cpp shrinks by 209 lines (7,463 to 7,254). Both --json
output modes preserved for capacity-planning pipelines.
2026-05-09 07:28:15 -07:00
Kelsi
c005396040 refactor(editor): extract --info-{zone,project}-extents into cli_info_extents.cpp
Moves the two spatial-bounds info handlers (--info-zone-extents,
--info-project-extents) out of main.cpp into a new
cli_info_extents.{hpp,cpp} module. Both compute world-space XYZ
bounding boxes from manifest tile coords + per-chunk height
samples; the project variant unions every zone's box into one.

main.cpp shrinks by 232 lines (7,695 to 7,463). Both --json
output modes preserved for camera-framing pipelines.
2026-05-09 07:22:06 -07:00
Kelsi
3009f406f8 refactor(editor): extract --info-{zone,project}-bytes into cli_info_bytes.cpp
Moves the two disk-byte audit handlers (--info-zone-bytes,
--info-project-bytes) out of main.cpp into a new
cli_info_bytes.{hpp,cpp} module. Both categorize files by
extension into open / proprietary / derived buckets — the
project-wide variant is the headline metric for tracking
the open-format migration's progress against the .m2/.wmo/
.blp/.dbc baseline.

main.cpp shrinks by 244 lines (7,939 to 7,695). Both --json
output modes preserved for machine-readable reports.
2026-05-09 07:16:27 -07:00
Kelsi
7950648943 refactor(editor): extract --info-{zone,project}-tree into cli_info_tree.cpp
Moves the two tree-style content browser handlers
(--info-zone-tree, --info-project-tree) out of main.cpp into
a new cli_info_tree.{hpp,cpp} module. Both render
Unix-`tree`-style hierarchical views — one drilling into a
single zone (manifest, tiles, creatures, objects, quests,
files) and one giving a bird's-eye view of every zone in a
project with bake/viewer status.

main.cpp shrinks by 201 lines (8,140 to 7,939). The remaining
info-zone/-project-* pairs (bytes, extents, water, density,
audio) form the next natural extraction batch.
2026-05-09 07:10:12 -07:00
Kelsi
e128d91d66 refactor(editor): extract WOB/WHM/WOC IO into cli_world_io.cpp
Moves all six world-asset interchange handlers (--export-wob-glb,
--export-wob-obj, --import-wob-obj, --export-whm-glb,
--export-whm-obj, --export-woc-obj) out of main.cpp into a new
cli_world_io.{hpp,cpp} module. WOB / WHM / WOC are our open
replacements for proprietary WMO / ADT-heightmap / ADT-collision
data; these are the bridge that lets the open formats round-trip
through Blender, MeshLab, Three.js, and the rest of the standard
3D toolchain.

main.cpp shrinks by 858 lines (8,997 to 8,140). The single-mesh
--import-obj handler stays inline for now -- it shadow-mirrors
cli_wom_io's --import-stl semantics and will move there next.
2026-05-09 07:03:14 -07:00
Kelsi
b59c310742 refactor(editor): extract WOM <-> OBJ/GLB/STL into cli_wom_io.cpp
Moves the four WOM interchange-format handlers (--export-obj,
--export-glb, --export-stl, --import-stl) out of main.cpp into
a new cli_wom_io.{hpp,cpp} module. WOM is our open M2
replacement; these are the bridge that lets it round-trip
through every external 3D tool — Blender, Three.js, slicers,
CAD packages — so the open format is actually useful.

main.cpp shrinks by 467 lines (9,464 to 8,997). The five WOB
and WHM exporters (--export-wob-glb, --export-whm-glb, etc.)
remain inline for a follow-up extraction.
2026-05-09 06:55:00 -07:00
Kelsi
9362623297 refactor(editor): extract GLB inspectors into cli_glb_inspect.cpp
Moves all 4 GLB introspection handlers (--validate-glb /
--info-glb shared, --info-glb-tree, --info-glb-bytes,
--check-glb-bounds) out of main.cpp into a new
cli_glb_inspect.{hpp,cpp} module. GLB is our open replacement
for proprietary M2/WMO bake outputs, so these belong with the
other open-format tooling.

main.cpp shrinks by 657 lines (10,121 to 9,464). Every
handler preserves its --json output mode for machine-readable
reports.
2026-05-09 06:46:02 -07:00
Kelsi
06a4fdb60f refactor(editor): extract interop --validate-* into cli_validate_interop.cpp
Moves the four structural validators for INTEROP file formats
(--validate-stl, --validate-png, --validate-blp, --validate-jsondbc)
out of main.cpp into a new cli_validate_interop.{hpp,cpp} module.
These check files coming in/out of wowee from third-party tools,
distinct from cli_format_validate.cpp which validates the native
open formats (WOM, WOB, WOC, WHM).

main.cpp shrinks by 524 lines (10,644 to 10,121). Each validator
preserves its --json output mode for machine-readable reports.
2026-05-09 06:36:02 -07:00
Kelsi
0d2312ec8d refactor(editor): extract single-file --convert-* into cli_convert_single.cpp
Moves the five single-file format converters (--convert-m2,
--convert-wmo, --convert-dbc-json, --convert-json-dbc,
--convert-blp-png) out of two dedicated post-loop blocks in
main.cpp into a new cli_convert_single.{hpp,cpp} module. The
batch wrappers in cli_convert.cpp keep working — they shell
out to wowee_editor with these flags.

main.cpp shrinks by ~335 lines (10,979 → 10,644). The two
trailing for-loops were dead code after wiring the dispatcher
into the main loop, so they're gone too.
2026-05-09 06:25:04 -07:00
Kelsi
f0bbc228ef refactor(editor): extract --migrate-* handlers into cli_migrate.cpp
Moves the four schema-migration handlers (--migrate-wom,
--migrate-zone, --migrate-project, --migrate-jsondbc) out of
main.cpp into a new cli_migrate.{hpp,cpp} module. Same
behavior — they're idempotent in-place upgraders for older
WOM revisions and JSON DBC sidecar schemas. main.cpp shrinks
by 282 lines (11,261 → 10,979).
2026-05-09 06:13:41 -07:00
Kelsi
d03c2dad1f refactor(editor): extract zone/project mesh-bake handlers into cli_bake.cpp
Moves the 3D-export bake handlers out of main.cpp:
  --bake-zone-glb     --bake-zone-stl     --bake-zone-obj
  --bake-project-obj  --bake-project-stl  --bake-project-glb

The STL + GLB project bakes share a combined dispatcher (one
function with internal STL-vs-GLB branching) since they walk
the same per-zone asset list and only differ in the output
emission code.

main.cpp drops 12,119 → 11,261 lines (-858). The combined-OR
opener spanning multiple lines created a parse-error fragment
in the extraction; caught + manually fixed before commit
(same pattern as the WOM info attachments/particles/sequences
extraction).
2026-05-09 05:57:25 -07:00
Kelsi
a4d282b588 refactor(editor): extract 9 export handlers + sha256 helper into cli_export.cpp
Moves the report-export handlers (md / csv / html / sha256 /
graphviz) for zone & project audits out of main.cpp:
  --export-zone-summary-md       --export-zone-csv
  --export-zone-checksum         --export-project-checksum
  --validate-project-checksum    --export-zone-html
  --export-project-html          --export-project-md
  --export-quest-graph

Also moves the file-scope wowee_sha256 namespace (the SHA-256
implementation that the checksum exporters use) into the new
module's anonymous namespace — it had no other callers in
main.cpp so no cross-TU coupling needed.

main.cpp drops 13,120 → 12,119 lines (-1,001). Build error
during extraction (missing #include <unordered_set>) caught
and fixed.
2026-05-09 05:45:00 -07:00
Kelsi
c9831b38ff refactor(editor): extract data-tree inspection into cli_extract_info.cpp
Moves the four extracted-Data-tree audit handlers out of main:
  --info-extract           (per-extension counts + bytes)
  --info-extract-tree      (per-directory rollup)
  --info-extract-budget    (proprietary share + open-format gap)
  --list-missing-sidecars  (find unconverted .m2/.wmo/.blp/.dbc)

All four operate on a Blizzard-format extracted Data tree —
they audit what's there and what's missing in the migration
from proprietary formats to open ones.

main.cpp drops 13,485 → 13,120 lines (-365). Behavior verified
by re-running --info-extract on a test zone (same output).
2026-05-09 05:32:27 -07:00
Kelsi
59ae675b78 refactor(editor): extract 5 item read-only handlers into cli_items.cpp
Moves the items.json read-only inspection handlers out of
main.cpp:
  --list-items            --info-item
  --validate-items        --validate-project-items
  --info-project-items

Item editing handlers (--add-item, --set-item, --remove-item,
--add-quest-reward-item) stay in main.cpp since they share
state with quest reward editing logic and would need a
broader extraction.

main.cpp drops 13,887 → 13,485 lines (-402). Behavior
verified by re-running --list-items on a non-items zone
(same error message).
2026-05-09 05:19:04 -07:00
Kelsi
83c7fd9bee refactor(editor): extract 8 spawn/snap handlers into cli_spawn_audit.cpp
Moves the NPC spawn / object placer audit + ground-snap
handlers out of main.cpp:
  --snap-zone-to-ground       --snap-project-to-ground
  --audit-zone-spawns         --audit-project-spawns
  --list-zone-spawns          --list-project-spawns
  --diff-zone-spawns          --info-spawn

All operate on creatures.json + objects.json sidecars and
the WHM terrain heightfield via WoweeTerrainLoader.

main.cpp drops 14,628 → 13,887 lines (-741). Behavior verified
by re-running --audit-zone-spawns on a test zone (PASSED with
0 issues, same as before).
2026-05-09 05:05:22 -07:00
Kelsi
3967c8de57 refactor(editor): extract 10 diff handlers into cli_diff.cpp
Moves the file-comparison handlers out of main.cpp into their
own translation unit:
  --diff-wcp        --diff-zone
  --diff-glb        --diff-wom
  --diff-wob        --diff-whm
  --diff-woc        --diff-jsondbc
  --diff-extract    --diff-checksum

main.cpp drops 15,653 → 14,732 lines (-921). One build error
during extraction (missing #include for NpcSpawner /
ObjectPlacer / QuestEditor used by --diff-zone) caught by
build and fixed.
2026-05-09 04:35:08 -07:00
Kelsi
5f37221179 refactor(editor): extract data-tree audit/migration into cli_data_tree.cpp
Moves the seven proprietary-data-tree handlers out of main.cpp:
  --migrate-data-tree         --bench-migrate-data-tree
  --list-data-tree-largest    --export-data-tree-md
  --info-data-tree            --strip-data-tree
  --audit-data-tree

All operate on a Blizzard-format extracted Data tree (the .m2/
.skin/.wmo/.blp/.dbc files) — they audit, migrate, or strip
proprietary-format files in support of the open-format
migration story.

Original placement spanned two sub-blocks (12546-12892 and
13093-13417 in main.cpp) interrupted by --gen-texture and
--add-texture-to-zone in the middle. Extraction collapses
both sub-blocks into one cohesive translation unit.

main.cpp drops 16,321 → 15,653 lines (-668). Behavior verified
by re-running --info-data-tree against a missing directory.
2026-05-09 04:14:32 -07:00
Kelsi
67ede85f7f refactor(editor): extract zone/project metadata info into cli_zone_info.cpp
Moves the three zone & project metadata inspection handlers
out of main.cpp:
  --info-zone              (single zone.json print)
  --info-zone-overview     (high-level zone digest)
  --info-project-overview  (per-zone summary table for a project)

All three load zone.json via wowee::editor::ZoneManifest.

main.cpp drops 16,564 → 16,321 lines (-243). Behavior verified
by re-running --info-zone + --info-project-overview against
existing test zones.
2026-05-09 03:52:44 -07:00
Kelsi
c519ee3e99 refactor(editor): extract creature/object/quest info into cli_content_info.cpp
Some checks are pending
Build / Build (arm64) (push) Waiting to run
Build / Build (x86-64) (push) Waiting to run
Build / Build (macOS arm64) (push) Waiting to run
Build / Build (windows-arm64) (push) Waiting to run
Build / Build (windows-x86-64) (push) Waiting to run
Security / CodeQL (C/C++) (push) Waiting to run
Security / Semgrep (push) Waiting to run
Security / Sanitizer Build (ASan/UBSan) (push) Waiting to run
Moves 16 contiguous content-inspection handlers out of main.cpp:

  --info-creatures              --info-creatures-by-faction
  --info-creatures-by-level     --info-objects-by-path
  --info-objects-by-type        --info-quests-by-level
  --info-quests-by-xp           --list-creatures
  --list-objects                --list-quests
  --list-quest-objectives       --list-quest-rewards
  --info-quest-graph-stats      --info-creature
  --info-quest                  --info-object

All read JSON sidecars (creatures.json, objects.json, quests.json)
via wowee::editor::{NpcSpawner, ObjectPlacer, QuestEditor} loaders.

main.cpp drops 17,505 → 16,564 lines (-941). Behavior verified
by running --info-creatures (correctly fails with same parse-
error message on a non-zone path).
2026-05-09 03:33:40 -07:00
Kelsi
f283ab2ce7 refactor(editor): extract WCP pack handlers into cli_pack.cpp
Moves the six WoWee Content Pack (.wcp) handlers out of
main.cpp:
  --list-wcp           --info-wcp
  --info-pack-budget   --info-pack-tree
  --pack-wcp           --unpack-wcp

All six defer to wowee::editor::ContentPacker for actual pack
I/O; the handlers just parse args and format output, so the
extraction has no behavioral impact on the pack format itself.

main.cpp drops 17,766 → 17,505 lines (-261). Behavior verified
by re-running --info-wcp on a missing file (same error message).
2026-05-09 03:12:09 -07:00
Kelsi
08e7d9c689 refactor(editor): extract format inspection handlers into cli_format_info.cpp
Moves the proprietary-format inspection commands out of main.cpp
into their own translation unit. Each reads a Blizzard-format
file and prints its structure:

  --info-png        --info-blp
  --info-m2         --info-wmo
  --info-adt        --info-jsondbc

main.cpp drops 18,198 → 17,766 lines (-432). Behavior verified
by re-running --info-png on a generated noise texture.
2026-05-09 02:48:58 -07:00
Kelsi
98c7621e1d refactor(editor): extract batch convert handlers into cli_convert.cpp
Moves the four bulk format-conversion handlers out of main.cpp:
  --convert-m2-batch    (M2 → WOM)
  --convert-wmo-batch   (WMO → WOB)
  --convert-blp-batch   (BLP → PNG)
  --convert-dbc-batch   (DBC → JSON)

These all share the same pattern: walk srcDir recursively for
files of the input extension and fan out to the single-file
--convert-* counterpart via subprocess (preserving the existing
per-file logic as the source of truth, no duplication).

Single-file converters (--convert-m2, --convert-wmo, etc.) and
the --migrate-* meta-commands still live in main.cpp; they're
in dedicated argv-rescan loops that need a different extraction
approach.

main.cpp drops 18,396 → 18,198 lines (-198). Behavior verified
by re-running --convert-blp-batch with a missing directory and
confirming the same error message.
2026-05-09 02:25:05 -07:00
Kelsi
b87ece2d5b refactor(editor): extract format validation into cli_format_validate.cpp
Moves the open-format validation + project-audit handlers out
of main.cpp:

  --validate                    --validate-wom
  --validate-wob                --validate-woc
  --validate-whm                --validate-all
  --validate-project            --validate-project-open-only
  --audit-project               --bench-audit-project
  --bench-validate-project

Also moves the four shared validate*Errors helpers (validateWom/
Wob/Woc/WhmErrors, ~365 lines) into the same module's anonymous
namespace — they were file-scope helpers in main.cpp used only
by these handlers, so co-locating eliminates the cross-TU
coupling.

main.cpp drops 19,446 → 18,396 lines (-1,050). Two build errors
caught during extraction (wrong include path for the WHM loader
header; missing #include for ContentPacker / std::set / std::map);
all fixed before commit.
2026-05-09 01:57:37 -07:00
Kelsi
efe0a91335 refactor(editor): extract WOM info handlers into cli_wom_info.cpp
Moves the WOM model inspection commands out of main.cpp:

  --info               (bare WOM summary)
  --info-batches       (per-batch material info)
  --info-textures      (texture path list)
  --info-doodads       (WOB doodad set / instance list)
  --info-attachments   ⎫ combined handler with same M2 load +
  --info-particles     ⎬ skin merge but different sub-array
  --info-sequences     ⎭ iteration
  --info-bones         (bone hierarchy)
  --export-bones-dot   (Graphviz DOT output)

main.cpp drops 20,005 → 19,446 lines (-559). Behavior verified
by running --info, --info-batches, --info-textures on a fresh
WOM. Build error during extraction (combined-or handler header
spanned 4 lines, the transform script only stripped the first;
also missing #include for WoweeBuildingLoader) caught by build
and fixed before commit.
2026-05-09 01:18:09 -07:00
Kelsi
3da5e5517f refactor(editor): extract 10 mesh edit ops into cli_mesh_edit.cpp
Moves the WOM mesh editing/transform handlers out of main.cpp:

  --add-texture-to-mesh   --scale-mesh
  --translate-mesh        --strip-mesh
  --rotate-mesh           --center-mesh
  --flip-mesh-normals     --mirror-mesh
  --smooth-mesh-normals   --merge-meshes

These are the post-generation manipulators (load → mutate → save)
distinct from the geometry generators in cli_gen_mesh.cpp and
the heightmap I/O in cli_mesh_io.cpp.

main.cpp drops 20,741 → 20,005 lines (-736). Behavior verified
by piping a fresh cube through scale → translate → center.
2026-05-09 00:36:51 -07:00
Kelsi
3d5a786ca9 refactor(editor): extract mesh ⇄ heightmap I/O into cli_mesh_io.cpp
Moves the three mesh-PNG bridge handlers (--displace-mesh,
--gen-mesh-from-heightmap, --export-mesh-heightmap) out of
main.cpp into their own translation unit. These three are
distinct from the gen-mesh-* primitive generators in that
they read or write external image files rather than synthesize
geometry from parameters alone.

main.cpp drops 21,061 → 20,741 lines (-320). Behavior verified
by re-running gen-mesh-from-heightmap → validate-wom → and
displace-mesh on a fresh plane.
2026-05-09 00:04:27 -07:00
Kelsi
0075494109 refactor(editor): extract 12 composite mesh primitives into cli_gen_mesh.cpp
Moves the recently-added composite-prop mesh handlers (rock,
pillar, bridge, tower, house, fountain, statue, altar, portal,
archway, barrel, chest) into their own translation unit. These
12 handlers were the most contiguous block of similar-shaped
mesh code in main.cpp.

Other mesh handlers (--gen-mesh dispatcher, fence, tree, grid,
stairs, disc, tube, capsule, arch, pyramid, from-heightmap,
textured) still live in main.cpp and may be migrated in
subsequent batches.

main.cpp drops 24,270 → 22,681 lines (-1,589). Behavior
verified by re-running rock/chest/archway/fountain.
2026-05-08 22:19:41 -07:00
Kelsi
6ea2dfcf8c refactor(editor): extract 7 newer texture generators into cli_gen_texture.cpp
Moves the Worley/cellular-noise-based texture handlers
(--gen-texture-cobble, -marble, -metal, -leather, -sand,
-snow, -lava) into their own translation unit. Each handler
previously had its own ~33-line copy of the parseHex lambda;
all 7 copies are replaced with a single shared parseHex
helper at file scope.

Older simpler generators (gradient/noise/radial/stripes/dots/
rings/checker/brick/wood/grass/fabric) still live in main.cpp
and will be migrated in subsequent batches.

main.cpp drops 26,286 → 25,494 lines (-792). Behavior
unchanged across all 7 handlers (re-verified).
2026-05-08 20:59:02 -07:00
Kelsi
68bded4f20 refactor(editor): extract printUsage into cli_help.cpp
Pulls the 597-line block of printf calls that emits the --help
text out of main.cpp into its own translation unit. printUsage
is the longest single function in main.cpp by far and was pure
boilerplate (no logic, just a flat list of help lines).

Function moved verbatim to wowee::editor::cli::printUsage; all
6 in-tree callers (--list-commands, --info-cli-stats,
--info-cli-categories, --info-cli-help, --validate-cli-help,
and the bare --help/-h handler) updated to the namespaced name.
The CLI-meta commands continue to capture printUsage's stdout
the same way, so behavior is identical (verified by re-running
--validate-cli-help, --info-cli-stats, --list-commands).

main.cpp drops 26,650 → 26,286 lines (-364 net; -597 from the
removal, +233 from the include and namespace-prefixing the
six call sites... wait, no, +6). Actually main.cpp net delta
matches the body extraction.
2026-05-08 20:12:15 -07:00
Kelsi
a773654be5 refactor(editor): extract project inventory into cli_project_inventory.cpp
Pairs with the per-zone inventory module from c0f2ab75. Moves
the five project-wide inventory handlers into their own file:

  --list-project-meshes        (per-zone WOM aggregate)
  --list-project-meshes-detail (per-mesh sorted listing)
  --list-project-audio         (per-zone WAV aggregate)
  --list-project-textures      (per-zone + global texture refs)
  --info-project-summary       (BOOTSTRAPPED/PARTIAL/EMPTY rollup)

All five enumerate zones the same way; consolidated that into
a shared enumerateZones() helper at file scope.

main.cpp drops 27,200 → 26,650 lines (-550). Behavior unchanged
across all 5 commands (verified against /tmp/proj_starter).
2026-05-08 18:47:06 -07:00
Kelsi
c0f2ab7515 refactor(editor): extract per-zone inventory into cli_zone_inventory.cpp
Continues the modularization. Moves the four per-zone inventory
handlers into their own file:

  --list-zone-meshes    (WOM stats)
  --list-zone-audio     (WAV header parse)
  --list-zone-textures  (texture-ref histogram)
  --info-zone-summary   (BOOTSTRAPPED/PARTIAL/EMPTY status)

Each consumes a trailing --json flag the same way; consolidated
that check into a consumeJsonFlag helper at the top.

main.cpp drops 27,445 → 27,200 lines (-245). Per-zone inventory
behavior unchanged (re-verified all 4 commands).

A pre-existing duplicate --list-zone-meshes handler (the older
detailed per-mesh listing, similar to the --list-project-meshes
collision fixed in 976549fe) is now dead code in the in-line
chain since the extracted module dispatches first. Will rename
or remove that duplicate in a follow-up cleanup.
2026-05-08 18:24:01 -07:00
Kelsi
a39f4e9b43 refactor(editor): extract README generators into cli_readmes.cpp
Continues the modularization. Moves --gen-zone-readme and
--gen-project-readme into their own translation unit using the
established handle<Family> dispatch pattern. Consolidated the
trailing --out flag parser into a single parseOutFlag helper
(was duplicated between the two handlers).

main.cpp drops 27,736 → 27,445 lines (-291). Behavior unchanged
(verified by re-generating README and PROJECT.md, contents
identical to pre-refactor output).
2026-05-08 17:36:10 -07:00
Kelsi
ac17d04f8c refactor(editor): extract audit family into cli_audits.cpp
Continues the modularization. Moves the four audit handlers
(--validate-zone-pack, --validate-project-packs, --info-zone-deps,
--info-project-deps) into their own file using the same
handle<Family>(int& i, int argc, char** argv, int& outRc) pattern.

Side-cleanup: the two project-scope audits had identical
subprocess-fanout structure (enumerate zones → run per-zone
command → tally PASS/FAIL → print summary). Consolidated that
into a shared runPerZoneAudit helper. Saves ~80 lines of
duplicated dispatch code.

main.cpp drops 28,070 → 27,736 lines (-334). Audit family is
fully self-contained (~330 lines), behavior unchanged
(verified all 4 commands against existing test zones).
2026-05-08 17:12:10 -07:00
Kelsi
774dab9330 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).
2026-05-08 16:46:14 -07:00
Kelsi
6c9ab6faed refactor(editor): extract gen-audio-* handlers into cli_gen_audio.cpp
main.cpp had grown past 28k lines, with each new procedural-
generation command adding 100-200 lines to the inline if/else
dispatch chain. This commit starts breaking that up by moving
the four audio-related handlers (--gen-audio-tone, -noise,
-sweep, --gen-zone-audio-pack) into their own translation unit.

Pattern established here for future family extractions:

- Family lives in cli_<family>.{hpp,cpp}
- Single dispatch entry point: bool handle<Family>(int& i, int argc,
  char** argv, int& outRc) — true if matched (writes outRc), false
  to fall through.
- main.cpp's argv loop calls each family's dispatcher first and
  returns its outRc on match, before the legacy in-line chain.

Side-benefit: consolidated the duplicated 25-line WAV header
writer + 5ms attack/release envelope into shared helpers
(writeWavMono16, applyEdgeEnvelope) at the top of the new file.

main.cpp drops from 28,943 → 28,329 lines (-614). Audio family
is fully self-contained (~440 lines), behavior unchanged
(verified by re-running tone/noise/sweep + zone-audio-pack).
2026-05-08 16:19:30 -07:00
Kelsi
d4c69a2b46 feat(extract): emit WHM+WOT+WOC for ADT terrain tiles
Final piece of the open-format emit pipeline:
  --emit-terrain  foo.adt → foo.whm + foo.wot + foo.woc

With this, --emit-open now produces a fully open-format zone
alongside every Blizzard MPQ extraction:
  BLP  → PNG       (textures)
  DBC  → JSON      (data tables)
  M2   → WOM       (models, with skin merge)
  WMO  → WOB       (buildings, with group merge)
  ADT  → WHM/WOT   (terrain heights + metadata)
       → WOC       (collision mesh derived from heights)

Originals stay on disk and indexed by manifest.json so private
servers continue to load proprietary formats; wowee runtime/editor
read the open formats directly. One extraction now feeds both
audiences with no separate conversion pass.

Implementation:
- Inline WHM+WOT writer in open_format_emitter.cpp (mirrors the
  editor's WoweeTerrain::exportOpen but without the PNG-preview /
  normal-map deps so the extractor stays editor-independent).
- Tile coords (x,y) parsed from <map>_<x>_<y>.adt filename.
- Collision mesh derived via WoweeCollisionBuilder::fromTerrain
  (terrain triangles only — WMO collision overlays would need
  asset manager and aren't worth the extractor complexity).
2026-05-06 10:36:14 -07:00
Kelsi
e6ace7cce5 feat(extract): emit WOM and WOB side-files (M2/WMO → open formats)
Extends asset_extract with two more open-format emitters:
  --emit-wom  foo.m2 (+ foo00.skin) → foo.wom
  --emit-wob  foo.wmo (+ foo_NNN.wmo groups) → foo.wob
  --emit-open now also turns these on

Originals are preserved so private servers still load .m2/.wmo
through the manifest path; the wowee runtime/editor pick up the
.wom/.wob next to them via the existing open-format search rules.

Implementation:
- New WoweeModelLoader::fromM2Bytes(m2Data, skinData) shares the
  conversion body with fromM2(path, am) via a static helper
  (convertM2ToWom). Lets the extractor convert without standing
  up an AssetManager.
- fromM2(path, am) moved to a separate translation unit
  (wowee_model_fromm2.cpp) so asset_extract doesn't have to
  link the AssetManager dependency.
- WoweeBuildingLoader::fromWMO already takes a WMOModel directly,
  so emitWobFromWmo just needs to read root + group files and
  call save().
- Group sub-files (<base>_NNN.wmo) are skipped during the walk
  since they're merged into the root WMO.
2026-05-06 10:32:17 -07:00
Kelsi
5ed2008621 feat(extract): emit open-format side-files (BLP→PNG, DBC→JSON)
The asset_extract tool now optionally writes wowee open-format
copies next to each extracted proprietary file:
  --emit-png      foo.blp → foo.png
  --emit-json-dbc foo.dbc → foo.json
  --emit-open     shortcut for both

Originals are left untouched, so private servers (AzerothCore,
TrinityCore) that load from the manifest's .blp/.dbc paths
continue to work unchanged. The wowee runtime / editor can now
consume the open formats directly without an extra conversion pass.

Implementation:
- New tools/asset_extract/open_format_emitter.{hpp,cpp} encapsulates
  the post-extract walk + per-file conversion.
- BLP→PNG uses BLPLoader::load + stbi_write_png with the same
  dimension/buffer-size sanity guards the editor's texture exporter
  applies.
- DBC→JSON mirrors the editor's DBCExporter::exportAsJson schema
  (string/float/uint heuristic) so the runtime DBC overlay loader
  can consume the output drop-in.
2026-05-06 10:23:32 -07:00
Kelsi
fdd527b373 fix(build): asset_extract tool needs extern/ in include path for nlohmann/json
asset_extract pulls in src/pipeline/dbc_loader.cpp which #includes
<nlohmann/json.hpp>, but the tool's include directories didn't list
extern/ where the header lives. Build succeeded if asset_extract was
disabled (no StormLib) but failed otherwise. Added the extern/ system
include so the tool builds wherever StormLib is found.
2026-05-06 02:30:04 -07:00
Kelsi
cceff622b4 feat(editor): AzerothCore server module generator
One-click generation of a complete AzerothCore/TrinityCore server module
from editor zone data. File > Generate Server Module creates:

- sql/01_map.sql: map_dbc + area_table_dbc registration
- sql/02_spawns.sql: creature_template + creature + waypoint_data + quests
- sql/03_teleport.sql: game_tele entry for .tele command
- sql/04_zone_flags.sql: sanctuary/PvP area flags
- conf/mod_wowee.conf.dist: worldserver.conf snippet with zone settings
- README.md: step-by-step server admin installation guide
- module.json: machine-readable module manifest

Server admins can import the SQL files, add the config snippet, and
restart their server to have the custom zone fully operational with
NPC spawns, patrol paths, quests, teleport commands, and zone flags.
2026-05-05 16:31:13 -07:00
Kelsi
b19627d82c feat(editor): SQL spawn export for AzerothCore/TrinityCore
Private server integration: export creature spawns, patrol waypoints,
and quest definitions as ready-to-import SQL for AzerothCore/TrinityCore.

- creature_template: name, level, health, mana, damage, armor, faction,
  npcflag (questgiver/vendor/flightmaster/innkeeper), displayId, scale
- creature: spawn position, orientation, respawn time, wander distance,
  movement type (stationary/wander/patrol)
- creature_addon + waypoint_data: patrol path waypoints with delays
- quest_template: title, description, completion text, level, XP, money
- All use ON DUPLICATE KEY UPDATE for safe re-imports
- Auto-exported as spawns.sql alongside other assets on zone save
- File > Export Server SQL menu item for standalone export
- Map ID from zone metadata panel used in spawn table
2026-05-05 16:06:34 -07:00
Kelsi
4d5eef480e feat: WOC collision mesh format — 7th novel open format
New format: WOC (Wowee Open Collision) — binary collision mesh for
custom zone walkability. Magic WOC1 (0x31434F57).

- WoweeCollisionBuilder::fromTerrain() generates collision triangles
  from terrain heightmap with slope classification (50 deg threshold)
- Per-triangle flags: walkable (0x01), water (0x02), steep (0x04)
- Respects terrain holes (skips triangles in hole regions)
- Binary save/load with bounds, tile coords, triangle data
- Auto-exported on zone save alongside WOT/WHM/WOM/WOB
- Added to content pack validation (score now 0-7)
- FORMAT_SPEC.md v1.1 updated with WOC binary layout
- 19 new test assertions: flat terrain generation (32k tris all
  walkable), save/load round-trip, hole skipping
- 328 total assertions across 84 test cases
2026-05-05 15:23:58 -07:00
Kelsi
90142cb0df docs: CHANGELOG, README editor section, fix dbc_to_csv build
- CHANGELOG: add World Editor section (12.5k+ lines, 6 modes, 30+ tools)
  and Novel Open Formats section (6/6 replacements, 309 test assertions)
- README: add World Editor section with build/run/CLI examples, format
  summary, and reference to FORMAT_SPEC.md
- Fix dbc_to_csv build: add extern/ to include path for nlohmann/json
  (broke when dbc_loader.cpp gained JSON DBC loading support)
2026-05-05 15:12:19 -07:00
Kelsi
71c3eb0fe6 feat: Wowee Open Building format (.wob) — novel WMO replacement
ALL 6 BLIZZARD FORMATS NOW HAVE OPEN REPLACEMENTS.

WOB format: binary building file with groups, portals, and doodads.
- WOB1 magic header
- Groups: vertices (pos+normal+uv+color), indices, texture paths,
  bounding box, indoor/outdoor flag
- Portals: connect groups with polygon boundaries
- Doodad placements: reference .wom models with transform

WoweeBuildingLoader: load/save/exists for .wob files.

Complete format replacement table:
- ADT → WOT/WHM (terrain heightmaps + metadata)
- WDT → zone.json (map definition)
- BLP → PNG (textures)
- DBC → JSON (data tables)
- M2 → WOM (static models)
- WMO → WOB (buildings with groups/portals/doodads)

The wowee project now has a complete suite of novel, open file
formats for creating and distributing custom WoW content without
any dependency on Blizzard proprietary file formats.
2026-05-05 10:28:24 -07:00
Kelsi
b4cb833108 feat: Wowee Open Model format (.wom) — novel M2 replacement
WOM format: binary model file with no Blizzard structures.
- WOM1 magic header + vertex/index counts + bounding box
- Vertices: position(vec3) + normal(vec3) + texCoord(vec2) = 32 bytes
- Indices: uint32 triangle list
- Texture paths: PNG references (not BLP)

WoweeModelLoader:
- load(): reads .wom binary back to WoweeModel struct
- save(): writes WoweeModel to .wom binary
- fromM2(): converts existing M2 models to WOM (static geometry,
  strips bone/animation data, converts BLP paths to PNG)
- exists(): checks for .wom file

Format replacement progress — 5 out of 6 done:
- DONE: ADT → WOT/WHM (terrain)
- DONE: WDT → zone.json (map definition)
- DONE: BLP → PNG (textures)
- DONE: DBC → JSON (data tables)
- DONE: M2 → WOM (static models)
- TODO: WMO → open building format
2026-05-05 10:24:46 -07:00
Kelsi
176115f279 feat(editor): DBC→JSON export for open format zone data tables
- DBCExporter: converts Blizzard DBC binary data tables to JSON
- Exports zone-relevant DBCs: AreaTable, Map, Light, LightParams,
  ZoneMusic, SoundAmbience, GroundEffectTexture/Doodad, LiquidType
- Auto-detects string vs numeric vs float fields
- Zone export now includes data/ directory with JSON DBCs
- Client can load these via existing CSV/JSON fallback paths

Format replacement progress:
- DONE: ADT → WOT/WHM (terrain)
- DONE: WDT → zone.json (map definition)
- DONE: BLP → PNG (textures)
- DONE: DBC → JSON (data tables)
- TODO: M2 → open model format
- TODO: WMO → open building format
2026-05-05 10:21:14 -07:00
Kelsi
cb3de59b5c feat(editor): BLP→PNG texture export for open format zones
- TextureExporter: converts Blizzard BLP textures to standard PNG
  for fully open redistribution of custom zones
- collectUsedTextures(): finds all texture paths referenced by terrain
- exportTexturesAsPng(): loads BLP via asset manager, writes RGBA PNG
  using stb_image_write to output/MapName/textures/
- Zone export now automatically converts all used textures to PNG
- Client's PNG override system already loads these automatically
  (checks for .png alongside .blp before loading)

Format replacement progress:
- DONE: ADT→WOT/WHM (terrain)
- DONE: WDT→zone.json (map definition)
- DONE: BLP→PNG (textures — auto-exported on zone save)
- TODO: DBC→JSON, M2→open model, WMO→open building
2026-05-05 10:17:03 -07:00
Kelsi
c05c15f6c9 feat(editor): Load Custom Zone menu discovers and loads WOT/WHM zones
- File > Load Custom Zone scans output/ and custom_zones/ for zone.json
- Lists all discovered custom zones with name and quest indicator [Q]
- Tooltip shows description and author on hover
- Click to load the zone's WOT/WHM terrain into the editor
- Parses tile coords from WOT filename for correct positioning
- Full round-trip: export → discover → reload for iterative editing
2026-05-05 10:04:45 -07:00
Kelsi
d10d962e31 feat: custom zone discovery system for client auto-detection
- CustomZoneDiscovery scans directories for zone.json manifest files
- Discovers custom zones in custom_zones/ and output/ directories
- Reports: name, author, description, creature/quest availability
- Client can list all available custom expansions at startup
- Foundation for a zone selection menu in the client UI
2026-05-05 10:01:05 -07:00
Kelsi
954894460e feat: integrate Wowee Open Terrain loader into client terrain pipeline
The wowee client can now load custom zones exported from the editor
using the novel WOT/WHM format — no Blizzard files needed.

Loading priority in TerrainManager::prepareTile():
1. Check custom_zones/{mapName}/{mapName}_{x}_{y}.wot/.whm
2. Check output/{mapName}/{mapName}_{x}_{y}.wot/.whm (editor output)
3. Fall back to World\Maps\...\*.adt (standard extracted data)

Pipeline:
- WoweeTerrainLoader in src/pipeline/ (shared between client + editor)
- Loads .whm binary heightmap (WHM1 magic, 256 chunks × 145 floats)
- Loads .wot JSON metadata (textures, layers, holes, water)
- Populates the same ADTTerrain struct the mesh generator uses
- obj0 merge only runs for ADT-loaded tiles (custom zones have no obj0)

To use: export zone from editor → files appear in output/ → client
loads them automatically on next terrain request for that map name.
2026-05-05 09:56:24 -07:00