Add purgeExtractedAssets() to clear all extracted asset data from disk
Some checks failed
Build / Build (arm64) (push) Has been cancelled
Build / Build (x86-64) (push) Has been cancelled
Build / Build (macOS arm64) (push) Has been cancelled
Build / Build (windows-arm64) (push) Has been cancelled
Build / Build (windows-x86-64) (push) Has been cancelled
Security / CodeQL (C/C++) (push) Has been cancelled
Security / Semgrep (push) Has been cancelled
Security / Sanitizer Build (ASan/UBSan) (push) Has been cancelled

This commit is contained in:
Kelsi 2026-02-28 09:07:47 -08:00
parent 543535a892
commit 19652ae521
2 changed files with 137 additions and 0 deletions

View file

@ -117,6 +117,15 @@ public:
*/
void clearDBCCache();
/**
* Delete all extracted asset files from the data directory on disk.
* Removes extracted subdirectories (db, character, creature, terrain, etc.),
* manifest.json, override dir, and expansion-specific extracted assets.
* After calling this, initialize() will fail until assets are re-extracted.
* @return Number of entries removed
*/
size_t purgeExtractedAssets();
private:
bool initialized = false;
std::string dataPath;

View file

@ -393,6 +393,134 @@ void AssetManager::clearCache() {
LOG_INFO("Cleared asset cache (DBC + file cache)");
}
size_t AssetManager::purgeExtractedAssets() {
clearCache();
if (dataPath.empty()) {
LOG_WARNING("Cannot purge: no data path set");
return 0;
}
size_t removed = 0;
namespace fs = std::filesystem;
// Extracted MPQ content directories
const char* extractedDirs[] = {
"db", "character", "creature", "terrain", "world",
"interface", "item", "sound", "spell", "environment",
"misc", "enUS",
// Case variants (Windows-extracted assets)
"Character", "Creature", "World"
};
for (const auto& dir : extractedDirs) {
fs::path p = fs::path(dataPath) / dir;
if (fs::exists(p)) {
std::error_code ec;
auto count = fs::remove_all(p, ec);
if (!ec) {
LOG_INFO("Purged: ", p.string(), " (", count, " entries)");
removed += count;
} else {
LOG_WARNING("Failed to remove ", p.string(), ": ", ec.message());
}
}
}
// Root manifest
fs::path manifestPath = fs::path(dataPath) / "manifest.json";
if (fs::exists(manifestPath)) {
std::error_code ec;
fs::remove(manifestPath, ec);
if (!ec) {
LOG_INFO("Purged: ", manifestPath.string());
++removed;
}
}
// Override directory
if (!overridePath_.empty() && fs::exists(overridePath_)) {
std::error_code ec;
auto count = fs::remove_all(overridePath_, ec);
if (!ec) {
LOG_INFO("Purged: ", overridePath_, " (", count, " entries)");
removed += count;
}
}
// HD texture packs
fs::path hdPath = fs::path(dataPath) / "hd";
if (fs::exists(hdPath)) {
std::error_code ec;
auto count = fs::remove_all(hdPath, ec);
if (!ec) {
LOG_INFO("Purged: ", hdPath.string(), " (", count, " entries)");
removed += count;
}
}
// Per-expansion extracted assets, manifests, and overlays
fs::path expansionsDir = fs::path(dataPath) / "expansions";
if (fs::is_directory(expansionsDir)) {
for (auto& expEntry : fs::directory_iterator(expansionsDir)) {
if (!expEntry.is_directory()) continue;
fs::path expDir = expEntry.path();
// Extracted assets
fs::path assetsDir = expDir / "assets";
if (fs::exists(assetsDir)) {
std::error_code ec;
auto count = fs::remove_all(assetsDir, ec);
if (!ec) {
LOG_INFO("Purged: ", assetsDir.string(), " (", count, " entries)");
removed += count;
}
}
// Expansion manifest
fs::path expManifest = expDir / "manifest.json";
if (fs::exists(expManifest)) {
std::error_code ec;
fs::remove(expManifest, ec);
if (!ec) {
LOG_INFO("Purged: ", expManifest.string());
++removed;
}
}
// Overlay
fs::path overlayDir = expDir / "overlay";
if (fs::exists(overlayDir)) {
std::error_code ec;
auto count = fs::remove_all(overlayDir, ec);
if (!ec) {
LOG_INFO("Purged: ", overlayDir.string(), " (", count, " entries)");
removed += count;
}
}
// Generated CSVs
fs::path dbDir = expDir / "db";
if (fs::is_directory(dbDir)) {
for (auto& f : fs::directory_iterator(dbDir)) {
if (f.path().extension() == ".csv") {
std::error_code ec;
fs::remove(f.path(), ec);
if (!ec) ++removed;
}
}
}
}
}
// Reset manifest state so initialize() knows it needs re-extraction
manifest_ = AssetManifest();
initialized = false;
LOG_INFO("Purge complete: ", removed, " entries removed from ", dataPath);
return removed;
}
std::string AssetManager::normalizePath(const std::string& path) const {
std::string normalized = path;
std::replace(normalized.begin(), normalized.end(), '/', '\\');