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.
This commit is contained in:
Kelsi 2026-05-06 10:23:32 -07:00
parent 9e801f93b6
commit 5ed2008621
6 changed files with 212 additions and 0 deletions

View file

@ -1,6 +1,7 @@
#include "extractor.hpp"
#include "path_mapper.hpp"
#include "manifest_writer.hpp"
#include "open_format_emitter.hpp"
#include <StormLib.h>
@ -975,6 +976,25 @@ bool Extractor::run(const Options& opts) {
}
}
// Open-format emission: walk the extracted tree and write
// wowee-format side-files (PNG / JSON DBC) next to each .blp/.dbc.
// Originals are left untouched so private servers continue to work.
if (opts.emitPng || opts.emitJsonDbc) {
std::cout << "Emitting wowee open-format side-files...\n";
OpenFormatStats ofs;
emitOpenFormats(effectiveOutputDir, opts.emitPng, opts.emitJsonDbc, ofs);
if (opts.emitPng) {
std::cout << " PNG (BLP→PNG) : " << ofs.pngOk << " ok";
if (ofs.pngFail) std::cout << ", " << ofs.pngFail << " failed";
std::cout << "\n";
}
if (opts.emitJsonDbc) {
std::cout << " JSON (DBC→JSON) : " << ofs.jsonDbcOk << " ok";
if (ofs.jsonDbcFail) std::cout << ", " << ofs.jsonDbcFail << " failed";
std::cout << "\n";
}
}
// Cache WoW.exe for Warden MEM_CHECK responses
{
const char* exeNames[] = { "WoW.exe", "TurtleWoW.exe", "Wow.exe" };