diff --git a/CMakeLists.txt b/CMakeLists.txt index 6af59e1..66927ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,8 @@ if(TARGET WarcraftXL) endif() if(TARGET WarcraftXLHost) + wxl_collect_sources(WXL_MOONWELL_HOST + "${CMAKE_CURRENT_SOURCE_DIR}/modules/moonwell/host/*.cpp") wxl_collect_sources(WXL_MODERN_ASSETS_HOST "${WXL_EXTERNAL_MODULES_DIR}/wxl-modern-assets/host/*.cpp" "${WXL_EXTERNAL_MODULES_DIR}/wxl-modern-assets/shared/*.cpp") @@ -53,6 +55,7 @@ if(TARGET WarcraftXLHost) "${WXL_EXTERNAL_MODULES_DIR}/wxl-modern-adt/shared/*.cpp") target_sources(WarcraftXLHost PRIVATE + ${WXL_MOONWELL_HOST} ${WXL_MODERN_ASSETS_HOST} ${WXL_MODERN_ADT_HOST}) endif() diff --git a/modules/moonwell/host/FileDataResolver.cpp b/modules/moonwell/host/FileDataResolver.cpp new file mode 100644 index 0000000..96d43e8 --- /dev/null +++ b/modules/moonwell/host/FileDataResolver.cpp @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// FileDataID resolver for selected retail assets shipped in MoonWell patches. + +#include "Host.hpp" +#include "core/Logger.hpp" +#include "mpq/MpqStore.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace moonwell::host +{ + namespace + { + constexpr std::string_view kFileDataMap = "WXLFileData.csv"; + + std::once_flag g_loadOnce; + std::unordered_map g_paths; + + std::string_view Trim(std::string_view value) + { + while (!value.empty() && (value.front() == ' ' || value.front() == '\t' || + value.front() == '\r' || value.front() == '\n')) + value.remove_prefix(1); + while (!value.empty() && (value.back() == ' ' || value.back() == '\t' || + value.back() == '\r' || value.back() == '\n')) + value.remove_suffix(1); + return value; + } + + void Load() + { + const std::string root = wxl::host::ClientRoot(); + wxl::host::mpq::MpqStore store; + std::vector bytes; + if (root.empty() || !store.Mount(root) || !store.ReadAll(kFileDataMap, bytes)) + { + WLOG_WARN("moonwell: FileDataID map '%.*s' was not found", + int(kFileDataMap.size()), kFileDataMap.data()); + return; + } + + const std::string_view text(reinterpret_cast(bytes.data()), bytes.size()); + size_t lineStart = 0; + while (lineStart < text.size()) + { + size_t lineEnd = text.find('\n', lineStart); + if (lineEnd == std::string_view::npos) lineEnd = text.size(); + std::string_view line = Trim(text.substr(lineStart, lineEnd - lineStart)); + lineStart = lineEnd + 1; + + if (line.empty() || line.front() == '#') continue; + const size_t comma = line.find(','); + if (comma == std::string_view::npos) continue; + + const std::string_view idText = Trim(line.substr(0, comma)); + std::string_view pathText = Trim(line.substr(comma + 1)); + uint32_t fileDataId = 0; + const auto parsed = std::from_chars(idText.data(), idText.data() + idText.size(), fileDataId); + if (parsed.ec != std::errc{} || parsed.ptr != idText.data() + idText.size() || + fileDataId == 0 || pathText.empty()) + continue; + + std::string path(pathText); + for (char& c : path) if (c == '/') c = '\\'; + g_paths[fileDataId] = std::move(path); + } + + WLOG_INFO("moonwell: loaded %zu FileDataID path(s) from %.*s", + g_paths.size(), int(kFileDataMap.size()), kFileDataMap.data()); + } + + bool Resolve(uint32_t fileDataId, std::string& outPath) + { + std::call_once(g_loadOnce, &Load); + const auto found = g_paths.find(fileDataId); + if (found == g_paths.end()) return false; + outPath = found->second; + return true; + } + + struct Registrar + { + Registrar() { wxl::host::RegisterResolver("moonwell-filedata", &Resolve); } + }; + + Registrar g_registrar; + } +} diff --git a/src/Data/patch-Z/Creature/Catslime/catslime.m2 b/src/Data/patch-Z/Creature/Catslime/catslime.m2 new file mode 100644 index 0000000..d1f5a25 Binary files /dev/null and b/src/Data/patch-Z/Creature/Catslime/catslime.m2 differ diff --git a/src/Data/patch-Z/Creature/Catslime/catslime00.skin b/src/Data/patch-Z/Creature/Catslime/catslime00.skin new file mode 100644 index 0000000..13b19fb Binary files /dev/null and b/src/Data/patch-Z/Creature/Catslime/catslime00.skin differ diff --git a/src/Data/patch-Z/Creature/Catslime/catslime0061-00.anim b/src/Data/patch-Z/Creature/Catslime/catslime0061-00.anim new file mode 100644 index 0000000..1fdd766 Binary files /dev/null and b/src/Data/patch-Z/Creature/Catslime/catslime0061-00.anim differ diff --git a/src/Data/patch-Z/Creature/Catslime/catslime0069-00.anim b/src/Data/patch-Z/Creature/Catslime/catslime0069-00.anim new file mode 100644 index 0000000..141c0f0 Binary files /dev/null and b/src/Data/patch-Z/Creature/Catslime/catslime0069-00.anim differ diff --git a/src/Data/patch-Z/Creature/Catslime/catslime0075-00.anim b/src/Data/patch-Z/Creature/Catslime/catslime0075-00.anim new file mode 100644 index 0000000..91f843a Binary files /dev/null and b/src/Data/patch-Z/Creature/Catslime/catslime0075-00.anim differ diff --git a/src/Data/patch-Z/Creature/Catslime/catslime0096-00.anim b/src/Data/patch-Z/Creature/Catslime/catslime0096-00.anim new file mode 100644 index 0000000..7efcc14 Binary files /dev/null and b/src/Data/patch-Z/Creature/Catslime/catslime0096-00.anim differ diff --git a/src/Data/patch-Z/Creature/Catslime/catslime0097-00.anim b/src/Data/patch-Z/Creature/Catslime/catslime0097-00.anim new file mode 100644 index 0000000..57613ed Binary files /dev/null and b/src/Data/patch-Z/Creature/Catslime/catslime0097-00.anim differ diff --git a/src/Data/patch-Z/Creature/Catslime/catslime0098-00.anim b/src/Data/patch-Z/Creature/Catslime/catslime0098-00.anim new file mode 100644 index 0000000..f4f0fad Binary files /dev/null and b/src/Data/patch-Z/Creature/Catslime/catslime0098-00.anim differ diff --git a/src/Data/patch-Z/Creature/Catslime/catslime0099-00.anim b/src/Data/patch-Z/Creature/Catslime/catslime0099-00.anim new file mode 100644 index 0000000..eefd193 Binary files /dev/null and b/src/Data/patch-Z/Creature/Catslime/catslime0099-00.anim differ diff --git a/src/Data/patch-Z/Creature/Catslime/catslime0100-00.anim b/src/Data/patch-Z/Creature/Catslime/catslime0100-00.anim new file mode 100644 index 0000000..0ac7fb3 Binary files /dev/null and b/src/Data/patch-Z/Creature/Catslime/catslime0100-00.anim differ diff --git a/src/Data/patch-Z/Creature/Catslime/catslime0101-00.anim b/src/Data/patch-Z/Creature/Catslime/catslime0101-00.anim new file mode 100644 index 0000000..6f7fb4e Binary files /dev/null and b/src/Data/patch-Z/Creature/Catslime/catslime0101-00.anim differ diff --git a/src/Data/patch-Z/Creature/Catslime/catslime0123-00.anim b/src/Data/patch-Z/Creature/Catslime/catslime0123-00.anim new file mode 100644 index 0000000..89d139f Binary files /dev/null and b/src/Data/patch-Z/Creature/Catslime/catslime0123-00.anim differ diff --git a/src/Data/patch-Z/Creature/Catslime/catslime_3732460.blp b/src/Data/patch-Z/Creature/Catslime/catslime_3732460.blp new file mode 100644 index 0000000..931c808 Binary files /dev/null and b/src/Data/patch-Z/Creature/Catslime/catslime_3732460.blp differ diff --git a/src/Data/patch-Z/Creature/Catslime/catslime_3732461.blp b/src/Data/patch-Z/Creature/Catslime/catslime_3732461.blp new file mode 100644 index 0000000..9dfb937 Binary files /dev/null and b/src/Data/patch-Z/Creature/Catslime/catslime_3732461.blp differ diff --git a/src/Data/patch-Z/Creature/Catslime/catslime_lod01.skin b/src/Data/patch-Z/Creature/Catslime/catslime_lod01.skin new file mode 100644 index 0000000..a2b1535 Binary files /dev/null and b/src/Data/patch-Z/Creature/Catslime/catslime_lod01.skin differ diff --git a/src/Data/patch-Z/Creature/Catslime/catslime_lod02.skin b/src/Data/patch-Z/Creature/Catslime/catslime_lod02.skin new file mode 100644 index 0000000..9d2a10e Binary files /dev/null and b/src/Data/patch-Z/Creature/Catslime/catslime_lod02.skin differ diff --git a/src/Data/patch-Z/Creature/Catslime/catslime_lod03.skin b/src/Data/patch-Z/Creature/Catslime/catslime_lod03.skin new file mode 100644 index 0000000..e94499f Binary files /dev/null and b/src/Data/patch-Z/Creature/Catslime/catslime_lod03.skin differ diff --git a/src/Data/patch-Z/WXLFileData.csv b/src/Data/patch-Z/WXLFileData.csv new file mode 100644 index 0000000..c35bcb0 --- /dev/null +++ b/src/Data/patch-Z/WXLFileData.csv @@ -0,0 +1,18 @@ +# FileDataID,archive path +3730958,Creature/Catslime/catslime.m2 +3732460,Creature/Catslime/catslime_3732460.blp +3732461,Creature/Catslime/catslime_3732461.blp +3732462,Creature/Catslime/catslime0097-00.anim +3732463,Creature/Catslime/catslime0096-00.anim +3732464,Creature/Catslime/catslime0098-00.anim +3732465,Creature/Catslime/catslime0100-00.anim +3732466,Creature/Catslime/catslime0099-00.anim +3732467,Creature/Catslime/catslime0101-00.anim +3732468,Creature/Catslime/catslime0069-00.anim +3732469,Creature/Catslime/catslime0123-00.anim +3732470,Creature/Catslime/catslime0061-00.anim +3732471,Creature/Catslime/catslime0075-00.anim +3732472,Creature/Catslime/catslime00.skin +3732473,Creature/Catslime/catslime_lod01.skin +3732474,Creature/Catslime/catslime_lod02.skin +3732475,Creature/Catslime/catslime_lod03.skin