mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-10 02:53:51 +00:00
feat(editor): add --rename-by-magic extension recovery flag
Reads the 4-byte magic of a file, looks it up in the shared format table, and renames the file to use the correct .w* extension. Useful when files have lost their extensions (downloaded as 'data.bin', extracted from a tarball with mangled metadata, or copied via a tool that strips suffixes). Safe by default — refuses to overwrite an existing target; pass --force to allow overwrite. --dry-run prints the planned move without touching the filesystem. Files that already have the correct extension are a no-op. Unrecognized magic exits 1 with the bytes printed for diagnostic context. Reuses cli_format_table.cpp so any future format addition is picked up automatically.
This commit is contained in:
parent
824a6c8cab
commit
4b928274b8
6 changed files with 118 additions and 1 deletions
|
|
@ -1420,6 +1420,7 @@ add_executable(wowee_editor
|
|||
tools/editor/cli_spell_visuals_catalog.cpp
|
||||
tools/editor/cli_format_table.cpp
|
||||
tools/editor/cli_summary_dir.cpp
|
||||
tools/editor/cli_rename_magic.cpp
|
||||
tools/editor/cli_quest_objective.cpp
|
||||
tools/editor/cli_quest_reward.cpp
|
||||
tools/editor/cli_clone.cpp
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ const char* const kArgRequired[] = {
|
|||
"--gen-liquids", "--gen-liquids-magical", "--gen-liquids-hazardous",
|
||||
"--info-wliq", "--validate-wliq",
|
||||
"--export-wliq-json", "--import-wliq-json",
|
||||
"--info-magic", "--summary-dir",
|
||||
"--info-magic", "--summary-dir", "--rename-by-magic",
|
||||
"--gen-animations", "--gen-animations-combat", "--gen-animations-movement",
|
||||
"--info-wani", "--validate-wani",
|
||||
"--export-wani-json", "--import-wani-json",
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@
|
|||
#include "cli_animations_catalog.hpp"
|
||||
#include "cli_spell_visuals_catalog.hpp"
|
||||
#include "cli_summary_dir.hpp"
|
||||
#include "cli_rename_magic.hpp"
|
||||
#include "cli_quest_objective.hpp"
|
||||
#include "cli_quest_reward.hpp"
|
||||
#include "cli_clone.hpp"
|
||||
|
|
@ -197,6 +198,7 @@ constexpr DispatchFn kDispatchTable[] = {
|
|||
handleAnimationsCatalog,
|
||||
handleSpellVisualsCatalog,
|
||||
handleSummaryDir,
|
||||
handleRenameMagic,
|
||||
handleQuestObjective,
|
||||
handleQuestReward,
|
||||
handleClone,
|
||||
|
|
|
|||
|
|
@ -1353,6 +1353,8 @@ void printUsage(const char* argv0) {
|
|||
std::printf(" Auto-detect any .w* file by 4-byte magic; report format / version / catalog name / entry count + suggest --info-* flag\n");
|
||||
std::printf(" --summary-dir <dir> [--json]\n");
|
||||
std::printf(" Recursively walk a directory; report per-format file count, total entries, and bytes for every Wowee open format found\n");
|
||||
std::printf(" --rename-by-magic <file> [--dry-run] [--force]\n");
|
||||
std::printf(" Recover the correct .w* extension on a file by reading its 4-byte magic. --dry-run prints the planned move; --force overwrites\n");
|
||||
std::printf(" --gen-animations <wani-base> [name]\n");
|
||||
std::printf(" Emit .wani starter: 5 essential animations (Stand / Walk / Run / Death / AttackUnarmed) with fallback chains\n");
|
||||
std::printf(" --gen-animations-combat <wani-base> [name]\n");
|
||||
|
|
|
|||
101
tools/editor/cli_rename_magic.cpp
Normal file
101
tools/editor/cli_rename_magic.cpp
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
#include "cli_rename_magic.hpp"
|
||||
#include "cli_arg_parse.hpp"
|
||||
#include "cli_format_table.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
namespace wowee {
|
||||
namespace editor {
|
||||
namespace cli {
|
||||
|
||||
namespace {
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
bool readMagic(const fs::path& path, char magic[4]) {
|
||||
std::ifstream is(path, std::ios::binary);
|
||||
if (!is) return false;
|
||||
is.read(magic, 4);
|
||||
return is.gcount() == 4;
|
||||
}
|
||||
|
||||
int handleRename(int& i, int argc, char** argv) {
|
||||
std::string filePath = argv[++i];
|
||||
bool dryRun = false;
|
||||
bool force = false;
|
||||
while (i + 1 < argc) {
|
||||
std::string a = argv[i + 1];
|
||||
if (a == "--dry-run") { dryRun = true; ++i; }
|
||||
else if (a == "--force") { force = true; ++i; }
|
||||
else break;
|
||||
}
|
||||
fs::path src = filePath;
|
||||
if (!fs::exists(src) || !fs::is_regular_file(src)) {
|
||||
std::fprintf(stderr,
|
||||
"rename-by-magic: not a file: %s\n", filePath.c_str());
|
||||
return 1;
|
||||
}
|
||||
char magic[4];
|
||||
if (!readMagic(src, magic)) {
|
||||
std::fprintf(stderr,
|
||||
"rename-by-magic: cannot read 4-byte magic: %s\n",
|
||||
filePath.c_str());
|
||||
return 1;
|
||||
}
|
||||
const FormatMagicEntry* fmt = findFormatByMagic(magic);
|
||||
if (!fmt) {
|
||||
char magicStr[5] = {magic[0], magic[1], magic[2], magic[3], 0};
|
||||
std::fprintf(stderr,
|
||||
"rename-by-magic: unrecognized magic '%s' in %s\n",
|
||||
magicStr, filePath.c_str());
|
||||
return 1;
|
||||
}
|
||||
fs::path dst = src;
|
||||
dst.replace_extension(fmt->extension);
|
||||
if (src == dst) {
|
||||
std::printf("rename-by-magic: %s already has correct "
|
||||
"extension (%s) — no change\n",
|
||||
filePath.c_str(), fmt->extension);
|
||||
return 0;
|
||||
}
|
||||
if (fs::exists(dst) && !force) {
|
||||
std::fprintf(stderr,
|
||||
"rename-by-magic: target %s already exists "
|
||||
"(pass --force to overwrite)\n", dst.string().c_str());
|
||||
return 1;
|
||||
}
|
||||
if (dryRun) {
|
||||
std::printf("rename-by-magic (dry-run): %s -> %s\n",
|
||||
filePath.c_str(), dst.string().c_str());
|
||||
return 0;
|
||||
}
|
||||
std::error_code ec;
|
||||
fs::rename(src, dst, ec);
|
||||
if (ec) {
|
||||
std::fprintf(stderr,
|
||||
"rename-by-magic: rename failed: %s\n",
|
||||
ec.message().c_str());
|
||||
return 1;
|
||||
}
|
||||
std::printf("rename-by-magic: %s -> %s\n",
|
||||
filePath.c_str(), dst.string().c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool handleRenameMagic(int& i, int argc, char** argv, int& outRc) {
|
||||
if (std::strcmp(argv[i], "--rename-by-magic") == 0 && i + 1 < argc) {
|
||||
outRc = handleRename(i, argc, argv); return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace cli
|
||||
} // namespace editor
|
||||
} // namespace wowee
|
||||
11
tools/editor/cli_rename_magic.hpp
Normal file
11
tools/editor/cli_rename_magic.hpp
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
namespace wowee {
|
||||
namespace editor {
|
||||
namespace cli {
|
||||
|
||||
bool handleRenameMagic(int& i, int argc, char** argv, int& outRc);
|
||||
|
||||
} // namespace cli
|
||||
} // namespace editor
|
||||
} // namespace wowee
|
||||
Loading…
Add table
Add a link
Reference in a new issue