diff options
author | Shauren <shauren.trinity@gmail.com> | 2025-05-26 12:50:38 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2025-05-26 12:50:38 +0200 |
commit | bc57ce984bd8ac7e066e86a18b8cfd95616f86dd (patch) | |
tree | 53eee77330140f340615fff7619c4bd85fdc264b | |
parent | 1a5af00760e8ba96a01c0e9049cca9de30ded567 (diff) |
Tools/Extractors: Load the same MPQ file set as the client does (including custom patches)
-rw-r--r-- | src/tools/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/tools/extractor_common/CMakeLists.txt | 30 | ||||
-rw-r--r-- | src/tools/extractor_common/mpq_libmpq.cpp | 241 | ||||
-rw-r--r-- | src/tools/extractor_common/mpq_libmpq.h (renamed from src/tools/map_extractor/mpq_libmpq04.h) | 27 | ||||
-rw-r--r-- | src/tools/map_extractor/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/tools/map_extractor/System.cpp | 131 | ||||
-rw-r--r-- | src/tools/map_extractor/dbcfile.cpp | 4 | ||||
-rw-r--r-- | src/tools/map_extractor/loadlib.cpp | 2 | ||||
-rw-r--r-- | src/tools/map_extractor/mpq_libmpq.cpp | 128 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/adtfile.h | 2 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/dbcfile.cpp | 2 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/model.cpp | 2 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/mpq_libmpq.cpp | 134 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/mpq_libmpq04.h | 102 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/vmapexport.cpp | 166 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/wdtfile.h | 2 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/wmo.cpp | 2 |
18 files changed, 347 insertions, 635 deletions
diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt index 66f75253ec2..db2cefd7709 100644 --- a/src/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -8,6 +8,7 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +add_subdirectory(extractor_common) add_subdirectory(map_extractor) add_subdirectory(vmap4_assembler) add_subdirectory(vmap4_extractor) diff --git a/src/tools/extractor_common/CMakeLists.txt b/src/tools/extractor_common/CMakeLists.txt new file mode 100644 index 00000000000..400f92c83b3 --- /dev/null +++ b/src/tools/extractor_common/CMakeLists.txt @@ -0,0 +1,30 @@ +# This file is part of the TrinityCore Project. See AUTHORS file for Copyright information +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +CollectSourceFiles( + ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE_SOURCES) + +add_library(extractor_common STATIC ${PRIVATE_SOURCES}) + +target_link_libraries(extractor_common + PRIVATE + trinity-core-interface + PUBLIC + mpq + common) + +target_include_directories(extractor_common + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}) + +set_target_properties(extractor_common + PROPERTIES + FOLDER "tools") diff --git a/src/tools/extractor_common/mpq_libmpq.cpp b/src/tools/extractor_common/mpq_libmpq.cpp new file mode 100644 index 00000000000..59052cd3ea6 --- /dev/null +++ b/src/tools/extractor_common/mpq_libmpq.cpp @@ -0,0 +1,241 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "mpq_libmpq.h" +#include "StringFormat.h" +#include "Util.h" +#include <boost/filesystem/directory.hpp> +#include <boost/filesystem/operations.hpp> +#include <boost/filesystem/path.hpp> +#include <algorithm> +#include <array> +#include <stdexcept> +#include <cstdio> + +ArchiveSet gOpenArchives; + +MPQArchive::MPQArchive(char const* filename) +{ + int result = libmpq__archive_open(&mpq_a, filename, -1); + printf("Opening %s\n", filename); + switch(result) + { + case LIBMPQ_ERROR_OPEN: + throw std::runtime_error(Trinity::StringFormat("Error opening archive '{}': Does file really exist?", filename)); + case LIBMPQ_ERROR_FORMAT: + throw std::runtime_error(Trinity::StringFormat("Error opening archive '{}': Bad file format", filename)); + case LIBMPQ_ERROR_SEEK: + throw std::runtime_error(Trinity::StringFormat("Error opening archive '{}': Seeking in file failed", filename)); + case LIBMPQ_ERROR_READ: + throw std::runtime_error(Trinity::StringFormat("Error opening archive '{}': Read error in archive", filename)); + case LIBMPQ_ERROR_MALLOC: + throw std::runtime_error(Trinity::StringFormat("Error opening archive '{}': Maybe not enough memory", filename)); + default: + throw std::runtime_error(Trinity::StringFormat("Error opening archive '{}': Unknown error", filename)); + case 0: + // success + break; + } +} + +void MPQArchive::close() +{ + if (mpq_a) + { + libmpq__archive_close(mpq_a); + mpq_a = nullptr; + } +} + +MPQFile::MPQFile(char const* filename): + eof(false), + buffer(nullptr), + pointer(0), + size(0) +{ + for (ArchiveSet::iterator i = gOpenArchives.begin(); i != gOpenArchives.end(); ++i) + { + mpq_archive *mpq_a = i->mpq_a; + if (!mpq_a) + continue; + + uint32_t filenum; + if(libmpq__file_number(mpq_a, filename, &filenum)) continue; + libmpq__off_t transferred; + libmpq__file_size_unpacked(mpq_a, filenum, &size); + + // HACK: in patch.mpq some files don't want to open and give 1 for filesize + if (size<=1) { +// printf("warning: file %s has size %d; cannot read.\n", filename, size); + eof = true; + buffer = 0; + return; + } + buffer = new char[size]; + + //libmpq_file_getdata + libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred); + /*libmpq_file_getdata(&mpq_a, hash, fileno, (unsigned char*)buffer);*/ + return; + + } + eof = true; + buffer = nullptr; +} + +size_t MPQFile::read(void* dest, size_t bytes) +{ + if (eof) return 0; + + size_t rpos = pointer + bytes; + if (rpos > size_t(size)) { + bytes = size - pointer; + eof = true; + } + + memcpy(dest, &(buffer[pointer]), bytes); + + pointer = rpos; + + return bytes; +} + +void MPQFile::seek(int offset) +{ + pointer = offset; + eof = (pointer >= size); +} + +void MPQFile::seekRelative(int offset) +{ + pointer += offset; + eof = (pointer >= size); +} + +void MPQFile::close() +{ + delete[] buffer; + buffer = nullptr; + eof = true; +} + +namespace MPQ +{ +struct ArchiveData +{ + std::string_view NamePattern; + bool Required; +}; + +constexpr std::array<ArchiveData, 11> Archives = +{{ + { .NamePattern = "{installDir}/Data/patch-?.MPQ", .Required = true }, + { .NamePattern = "{installDir}/Data/{locale}/patch-{locale}-?.MPQ", .Required = true }, + { .NamePattern = "{installDir}/Data/patch.MPQ", .Required = true }, + { .NamePattern = "{installDir}/Data/{locale}/patch-{locale}.MPQ", .Required = true }, + { .NamePattern = "{installDir}/Data/expansion.MPQ", .Required = true }, + { .NamePattern = "{installDir}/Data/lichking.MPQ", .Required = true }, + { .NamePattern = "{installDir}/Data/common.MPQ", .Required = true }, + { .NamePattern = "{installDir}/Data/common-2.MPQ", .Required = true }, + { .NamePattern = "{installDir}/Data/{locale}/locale-{locale}.MPQ", .Required = true }, + //{ .NamePattern = "{installDir}/Data/{locale}/speech-{locale}.MPQ", .Required = false }, + { .NamePattern = "{installDir}/Data/{locale}/expansion-locale-{locale}.MPQ", .Required = true }, + { .NamePattern = "{installDir}/Data/{locale}/lichking-locale-{locale}.MPQ", .Required = true }, + //{ .NamePattern = "{installDir}/Data/{locale}/expansion-speech-{locale}.MPQ", .Required = false }, + //{ .NamePattern = "{installDir}/Data/{locale}/lichking-speech-{locale}.MPQ", .Required = false }, +}}; + +bool FileNameMatchesArchivePattern(std::string_view const& fileName, std::string_view const& pattern) +{ + return std::ranges::equal(fileName, pattern, [](char fileChar, char patternChar) + { + return patternChar == '?' || charToLower(fileChar) == charToLower(patternChar); + }); +} + +std::vector<boost::filesystem::path> ResolveArchiveFileList(std::string_view inputPath, std::string_view localeName, std::string_view namePattern) +{ + boost::filesystem::path path = Trinity::StringFormat(fmt::runtime(namePattern), fmt::arg("installDir", inputPath), fmt::arg("locale", localeName)); + std::vector<boost::filesystem::path> absolutePaths; + + std::string fileNamePattern = path.filename().string(); + if (fileNamePattern.find('?') != std::string::npos) + { + // scan directory + boost::system::error_code ec; + for (boost::filesystem::directory_entry const& dirEntry : boost::filesystem::directory_iterator(path.parent_path(), ec)) + { + if (!FileNameMatchesArchivePattern(dirEntry.path().filename().string(), fileNamePattern)) + continue; + + absolutePaths.push_back(dirEntry.path().lexically_normal().make_preferred()); + } + + std::ranges::sort(absolutePaths, [](boost::filesystem::path const& left, boost::filesystem::path const& right) + { + return std::ranges::lexicographical_compare(left.string(), right.string(), std::ranges::greater(), charToLower, charToLower); + }); + } + else + absolutePaths.push_back(path.lexically_normal().make_preferred()); + + return absolutePaths; +} + +bool OpenArchive(std::string_view inputPath, std::string_view localeName, ArchiveData const& archive) +{ + std::vector<boost::filesystem::path> fileNames = ResolveArchiveFileList(inputPath, localeName, archive.NamePattern); + for (boost::filesystem::path const& fileName : fileNames) + { + if (!exists(fileName)) + { + if (archive.Required) + return false; + + continue; + } + + try + { + gOpenArchives.emplace_back(fileName.string().c_str()); + } + catch (std::exception const& e) + { + printf("%s\n", e.what()); + if (archive.Required) + return false; + } + } + + return true; +} + +bool OpenArchives(std::string_view inputPath, std::string_view localeName) +{ + for (ArchiveData const& archive : Archives) + if (!OpenArchive(inputPath, localeName, archive)) + if (archive.Required) + return false; + + return true; +} + +void CloseArchives() +{ + gOpenArchives.clear(); +} +} diff --git a/src/tools/map_extractor/mpq_libmpq04.h b/src/tools/extractor_common/mpq_libmpq.h index f1763069c1a..9de8ffc496e 100644 --- a/src/tools/map_extractor/mpq_libmpq04.h +++ b/src/tools/extractor_common/mpq_libmpq.h @@ -18,27 +18,29 @@ #ifndef MPQ_H #define MPQ_H -#include "loadlib/loadlib.h" -#include "libmpq/mpq.h" -#include <string.h> -#include <ctype.h> +#include "Define.h" +#include <libmpq/mpq.h> +#include <string> +#include <utility> #include <vector> -#include <iostream> -#include <deque> +#include <cstring> class MPQArchive { - public: mpq_archive_s *mpq_a; MPQArchive(char const* filename); + MPQArchive(MPQArchive const&) = delete; + MPQArchive(MPQArchive&& other) noexcept : mpq_a(std::exchange(other.mpq_a, nullptr)) { } + MPQArchive& operator=(MPQArchive const&) = delete; + MPQArchive& operator=(MPQArchive&& other) noexcept { if (this != &other) mpq_a = std::exchange(other.mpq_a, nullptr); return *this; } ~MPQArchive() { close(); } void close(); void GetFileListTo(std::vector<std::string>& filelist) { uint32_t filenum; - if(libmpq__file_number(mpq_a, "(listfile)", &filenum)) return; + if(!mpq_a || libmpq__file_number(mpq_a, "(listfile)", &filenum)) return; libmpq__off_t size, transferred; libmpq__file_size_unpacked(mpq_a, filenum, &size); @@ -64,7 +66,8 @@ public: delete[] buffer; } }; -typedef std::deque<MPQArchive*> ArchiveSet; +typedef std::vector<MPQArchive> ArchiveSet; +extern ArchiveSet gOpenArchives; class MPQFile { @@ -102,4 +105,10 @@ inline void flipcc(char *fcc) fcc[2]=t; } +namespace MPQ +{ +bool OpenArchives(std::string_view inputPath, std::string_view localeName); +void CloseArchives(); +} + #endif diff --git a/src/tools/map_extractor/CMakeLists.txt b/src/tools/map_extractor/CMakeLists.txt index e80c9d9a939..0613d0a7d4f 100644 --- a/src/tools/map_extractor/CMakeLists.txt +++ b/src/tools/map_extractor/CMakeLists.txt @@ -27,8 +27,7 @@ target_link_libraries(mapextractor PRIVATE trinity-core-interface PUBLIC - common - mpq) + extractor_common) CollectIncludeDirectories( ${CMAKE_CURRENT_SOURCE_DIR} diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp index 9e8b0dbb3b2..c1830e57253 100644 --- a/src/tools/map_extractor/System.cpp +++ b/src/tools/map_extractor/System.cpp @@ -18,7 +18,7 @@ #include "dbcfile.h" #include "Banner.h" #include "Locales.h" -#include "mpq_libmpq04.h" +#include "mpq_libmpq.h" #include "StringFormat.h" #include "Util.h" @@ -38,8 +38,6 @@ #include <G3D/Plane.h> #include <boost/filesystem.hpp> -extern ArchiveSet gOpenArchives; - typedef struct { char name[64]; @@ -80,21 +78,7 @@ float CONF_float_to_int16_limit = 2048.0f; // Max accuracy = val/65536 float CONF_flat_height_delta_limit = 0.005f; // If max - min less this value - surface is flat float CONF_flat_liquid_delta_limit = 0.001f; // If max - min less this value - liquid surface is flat -// List MPQ for extract from -const char *CONF_mpq_list[]={ - "common.MPQ", - "common-2.MPQ", - "lichking.MPQ", - "expansion.MPQ", - "patch.MPQ", - "patch-2.MPQ", - "patch-3.MPQ", - "patch-4.MPQ", - "patch-5.MPQ", -}; - -static char const* const langs[] = {"enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU" }; -#define LANG_COUNT 12 +static constexpr std::array<std::string_view, 12> MpqLocaleNames = { "enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU" }; void CreateDir(boost::filesystem::path const& path) { @@ -174,7 +158,7 @@ void HandleArgs(int argc, char * arg[]) uint32 ReadBuild(int locale) { // include build info file also - std::string filename = Trinity::StringFormat("component.wow-{}.txt", langs[locale]); + std::string filename = Trinity::StringFormat("component.wow-{}.txt", MpqLocaleNames[locale]); //printf("Read %s file... ", filename.c_str()); MPQFile m(filename.c_str()); @@ -995,7 +979,7 @@ void ExtractDBCFiles(int locale, bool basicLocale) for(ArchiveSet::iterator i = gOpenArchives.begin(); i != gOpenArchives.end();++i) { std::vector<std::string> files; - (*i)->GetFileListTo(files); + i->GetFileListTo(files); for (std::vector<std::string>::iterator iter = files.begin(); iter != files.end(); ++iter) if (iter->rfind(".dbc") == iter->length() - strlen(".dbc")) dbcfiles.insert(*iter); @@ -1006,14 +990,14 @@ void ExtractDBCFiles(int locale, bool basicLocale) CreateDir(path); if(!basicLocale) { - path += langs[locale]; + path += MpqLocaleNames[locale]; path += "/"; CreateDir(path); } // extract Build info file { - std::string mpq_name = std::string("component.wow-") + langs[locale] + ".txt"; + std::string mpq_name = Trinity::StringFormat("component.wow-{}.txt", MpqLocaleNames[locale]); std::string filename = path + mpq_name; ExtractFile(mpq_name.c_str(), filename); @@ -1064,7 +1048,7 @@ void ExtractCameraFiles(int locale, bool basicLocale) CreateDir(path); if (!basicLocale) { - path += langs[locale]; + path += MpqLocaleNames[locale]; path += "/"; CreateDir(path); } @@ -1085,42 +1069,6 @@ void ExtractCameraFiles(int locale, bool basicLocale) printf("Extracted %u camera files\n", count); } -void LoadLocaleMPQFiles(int const locale) -{ - std::string fileName = Trinity::StringFormat("{}/Data/{}/locale-{}.MPQ", input_path, langs[locale], langs[locale]); - - new MPQArchive(fileName.c_str()); - - for(int i = 1; i < 5; ++i) - { - std::string ext; - if (i > 1) - ext = Trinity::StringFormat("-{}", i); - - fileName = Trinity::StringFormat("{}/Data/{}/patch-{}{}.MPQ", input_path, langs[locale], langs[locale], ext); - if (boost::filesystem::exists(fileName)) - new MPQArchive(fileName.c_str()); - } -} - -void LoadCommonMPQFiles() -{ - std::string fileName; - int count = sizeof(CONF_mpq_list)/sizeof(char*); - for(int i = 0; i < count; ++i) - { - fileName = Trinity::StringFormat("{}/Data/{}", input_path, CONF_mpq_list[i]); - if (boost::filesystem::exists(fileName)) - new MPQArchive(fileName.c_str()); - } -} - -inline void CloseMPQFiles() -{ - for(ArchiveSet::iterator j = gOpenArchives.begin(); j != gOpenArchives.end();++j) (*j)->close(); - gOpenArchives.clear(); -} - int main(int argc, char * arg[]) { Trinity::VerifyOsVersion(); @@ -1134,38 +1082,35 @@ int main(int argc, char * arg[]) int FirstLocale = -1; uint32 build = 0; - for (int i = 0; i < LANG_COUNT; i++) + for (std::size_t i = 0; i < MpqLocaleNames.size(); i++) { - std::string filename = Trinity::StringFormat("{}/Data/{}/locale-{}.MPQ", input_path, langs[i], langs[i]); - if (boost::filesystem::exists(filename)) - { - printf("Detected locale: %s\n", langs[i]); - - //Open MPQs - LoadLocaleMPQFiles(i); + //Open MPQs + if (!MPQ::OpenArchives(input_path, MpqLocaleNames[i])) + continue; - if((CONF_extract & EXTRACT_DBC) == 0) - { - FirstLocale = i; - build = ReadBuild(FirstLocale); - printf("Detected client build: %u\n", build); - break; - } + printf("Detected locale: " STRING_VIEW_FMT "\n", STRING_VIEW_FMT_ARG(MpqLocaleNames[i])); - //Extract DBC files - if(FirstLocale < 0) - { - FirstLocale = i; - build = ReadBuild(FirstLocale); - printf("Detected client build: %u\n", build); - ExtractDBCFiles(i, true); - } - else - ExtractDBCFiles(i, false); + if((CONF_extract & EXTRACT_DBC) == 0) + { + FirstLocale = i; + build = ReadBuild(FirstLocale); + printf("Detected client build: %u\n", build); + break; + } - //Close MPQs - CloseMPQFiles(); + //Extract DBC files + if(FirstLocale < 0) + { + FirstLocale = i; + build = ReadBuild(FirstLocale); + printf("Detected client build: %u\n", build); + ExtractDBCFiles(i, true); } + else + ExtractDBCFiles(i, false); + + //Close MPQs + MPQ::CloseArchives(); } if(FirstLocale < 0) @@ -1176,30 +1121,28 @@ int main(int argc, char * arg[]) if (CONF_extract & EXTRACT_CAMERA) { - printf("Using locale: %s\n", langs[FirstLocale]); + printf("Using locale: " STRING_VIEW_FMT "\n", STRING_VIEW_FMT_ARG(MpqLocaleNames[FirstLocale])); // Open MPQs - LoadLocaleMPQFiles(FirstLocale); - LoadCommonMPQFiles(); + MPQ::OpenArchives(input_path, MpqLocaleNames[FirstLocale]); ExtractCameraFiles(FirstLocale, true); // Close MPQs - CloseMPQFiles(); + MPQ::CloseArchives(); } if (CONF_extract & EXTRACT_MAP) { - printf("Using locale: %s\n", langs[FirstLocale]); + printf("Using locale: " STRING_VIEW_FMT "\n", STRING_VIEW_FMT_ARG(MpqLocaleNames[FirstLocale])); // Open MPQs - LoadLocaleMPQFiles(FirstLocale); - LoadCommonMPQFiles(); + MPQ::OpenArchives(input_path, MpqLocaleNames[FirstLocale]); // Extract maps ExtractMapsFromMpq(build); // Close MPQs - CloseMPQFiles(); + MPQ::CloseArchives(); } return 0; diff --git a/src/tools/map_extractor/dbcfile.cpp b/src/tools/map_extractor/dbcfile.cpp index fa61fee22a1..66caf752992 100644 --- a/src/tools/map_extractor/dbcfile.cpp +++ b/src/tools/map_extractor/dbcfile.cpp @@ -15,10 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#define _CRT_SECURE_NO_DEPRECATE - #include "dbcfile.h" -#include "mpq_libmpq04.h" +#include "mpq_libmpq.h" DBCFile::DBCFile(const std::string& filename): filename(filename), recordSize(0), recordCount(0), fieldCount(0), stringSize(0), data(nullptr), stringTable(nullptr) diff --git a/src/tools/map_extractor/loadlib.cpp b/src/tools/map_extractor/loadlib.cpp index 72c6b73e38c..67cdfba1664 100644 --- a/src/tools/map_extractor/loadlib.cpp +++ b/src/tools/map_extractor/loadlib.cpp @@ -18,7 +18,7 @@ #define _CRT_SECURE_NO_DEPRECATE #include "loadlib.h" -#include "mpq_libmpq04.h" +#include "mpq_libmpq.h" #include <cstdio> class MPQFile; diff --git a/src/tools/map_extractor/mpq_libmpq.cpp b/src/tools/map_extractor/mpq_libmpq.cpp deleted file mode 100644 index d4766b27a58..00000000000 --- a/src/tools/map_extractor/mpq_libmpq.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "mpq_libmpq04.h" -#include <deque> -#include <cstdio> - -ArchiveSet gOpenArchives; - -MPQArchive::MPQArchive(char const* filename) -{ - int result = libmpq__archive_open(&mpq_a, filename, -1); - printf("Opening %s\n", filename); - if(result) { - switch(result) { - case LIBMPQ_ERROR_OPEN : - printf("Error opening archive '%s': Does file really exist?\n", filename); - break; - case LIBMPQ_ERROR_FORMAT : /* bad file format */ - printf("Error opening archive '%s': Bad file format\n", filename); - break; - case LIBMPQ_ERROR_SEEK : /* seeking in file failed */ - printf("Error opening archive '%s': Seeking in file failed\n", filename); - break; - case LIBMPQ_ERROR_READ : /* Read error in archive */ - printf("Error opening archive '%s': Read error in archive\n", filename); - break; - case LIBMPQ_ERROR_MALLOC : /* maybe not enough memory? :) */ - printf("Error opening archive '%s': Maybe not enough memory\n", filename); - break; - default: - printf("Error opening archive '%s': Unknown error\n", filename); - break; - } - return; - } - gOpenArchives.push_front(this); -} - -void MPQArchive::close() -{ - //gOpenArchives.erase(erase(&mpq_a); - libmpq__archive_close(mpq_a); -} - -MPQFile::MPQFile(char const* filename): - eof(false), - buffer(0), - pointer(0), - size(0) -{ - for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end();++i) - { - mpq_archive *mpq_a = (*i)->mpq_a; - - uint32_t filenum; - if(libmpq__file_number(mpq_a, filename, &filenum)) continue; - libmpq__off_t transferred; - libmpq__file_size_unpacked(mpq_a, filenum, &size); - - // HACK: in patch.mpq some files don't want to open and give 1 for filesize - if (size<=1) { -// printf("warning: file %s has size %d; cannot read.\n", filename, size); - eof = true; - buffer = 0; - return; - } - buffer = new char[size]; - - //libmpq_file_getdata - libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred); - /*libmpq_file_getdata(&mpq_a, hash, fileno, (unsigned char*)buffer);*/ - return; - - } - eof = true; - buffer = 0; -} - -size_t MPQFile::read(void* dest, size_t bytes) -{ - if (eof) return 0; - - size_t rpos = pointer + bytes; - if (rpos > size_t(size)) { - bytes = size - pointer; - eof = true; - } - - memcpy(dest, &(buffer[pointer]), bytes); - - pointer = rpos; - - return bytes; -} - -void MPQFile::seek(int offset) -{ - pointer = offset; - eof = (pointer >= size); -} - -void MPQFile::seekRelative(int offset) -{ - pointer += offset; - eof = (pointer >= size); -} - -void MPQFile::close() -{ - delete[] buffer; - buffer = 0; - eof = true; -} diff --git a/src/tools/vmap4_extractor/CMakeLists.txt b/src/tools/vmap4_extractor/CMakeLists.txt index 3bde87bff52..9d997b16296 100644 --- a/src/tools/vmap4_extractor/CMakeLists.txt +++ b/src/tools/vmap4_extractor/CMakeLists.txt @@ -20,8 +20,7 @@ target_link_libraries(vmap4extractor PRIVATE trinity-core-interface PUBLIC - common - mpq) + extractor_common) set_target_properties(vmap4extractor PROPERTIES diff --git a/src/tools/vmap4_extractor/adtfile.h b/src/tools/vmap4_extractor/adtfile.h index 7290aba8c5d..d762e8aebe5 100644 --- a/src/tools/vmap4_extractor/adtfile.h +++ b/src/tools/vmap4_extractor/adtfile.h @@ -18,7 +18,7 @@ #ifndef ADT_H #define ADT_H -#include "mpq_libmpq04.h" +#include "mpq_libmpq.h" #include "wmo.h" #include "model.h" diff --git a/src/tools/vmap4_extractor/dbcfile.cpp b/src/tools/vmap4_extractor/dbcfile.cpp index a5b98455c0d..02098f35398 100644 --- a/src/tools/vmap4_extractor/dbcfile.cpp +++ b/src/tools/vmap4_extractor/dbcfile.cpp @@ -16,7 +16,7 @@ */ #include "dbcfile.h" -#include "mpq_libmpq04.h" +#include "mpq_libmpq.h" #undef min #undef max diff --git a/src/tools/vmap4_extractor/model.cpp b/src/tools/vmap4_extractor/model.cpp index 05e0d09df8f..c1271b1c76d 100644 --- a/src/tools/vmap4_extractor/model.cpp +++ b/src/tools/vmap4_extractor/model.cpp @@ -20,7 +20,7 @@ #include "model.h" #include "wmo.h" #include "adtfile.h" -#include "mpq_libmpq04.h" +#include "mpq_libmpq.h" #include "VMapDefinitions.h" #include <G3D/Quat.h> #include <algorithm> diff --git a/src/tools/vmap4_extractor/mpq_libmpq.cpp b/src/tools/vmap4_extractor/mpq_libmpq.cpp deleted file mode 100644 index 16a866a15f2..00000000000 --- a/src/tools/vmap4_extractor/mpq_libmpq.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "mpq_libmpq04.h" -#include <deque> -#include <cstdio> -#include <algorithm> - -ArchiveSet gOpenArchives; - -MPQArchive::MPQArchive(char const* filename) -{ - int result = libmpq__archive_open(&mpq_a, filename, -1); - printf("Opening %s\n", filename); - if(result) { - switch(result) { - case LIBMPQ_ERROR_OPEN : - printf("Error opening archive '%s': Does file really exist?\n", filename); - break; - case LIBMPQ_ERROR_FORMAT : /* bad file format */ - printf("Error opening archive '%s': Bad file format\n", filename); - break; - case LIBMPQ_ERROR_SEEK : /* seeking in file failed */ - printf("Error opening archive '%s': Seeking in file failed\n", filename); - break; - case LIBMPQ_ERROR_READ : /* Read error in archive */ - printf("Error opening archive '%s': Read error in archive\n", filename); - break; - case LIBMPQ_ERROR_MALLOC : /* maybe not enough memory? :) */ - printf("Error opening archive '%s': Maybe not enough memory\n", filename); - break; - default: - printf("Error opening archive '%s': Unknown error\n", filename); - break; - } - return; - } - gOpenArchives.push_front(this); -} - -bool MPQArchive::isOpened() const -{ - return std::find(gOpenArchives.begin(), gOpenArchives.end(), this) != gOpenArchives.end(); -} - -void MPQArchive::close() -{ - //gOpenArchives.erase(erase(&mpq_a); - libmpq__archive_close(mpq_a); -} - -MPQFile::MPQFile(char const* filename): - eof(false), - buffer(0), - pointer(0), - size(0) -{ - for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end();++i) - { - mpq_archive *mpq_a = (*i)->mpq_a; - - uint32 filenum; - if(libmpq__file_number(mpq_a, filename, &filenum)) continue; - libmpq__off_t transferred; - libmpq__file_size_unpacked(mpq_a, filenum, &size); - - // HACK: in patch.mpq some files don't want to open and give 1 for filesize - if (size<=1) { - // printf("info: file %s has size %d; considered dummy file.\n", filename, size); - eof = true; - buffer = 0; - return; - } - buffer = new char[size]; - - //libmpq_file_getdata - libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred); - /*libmpq_file_getdata(&mpq_a, hash, fileno, (unsigned char*)buffer);*/ - return; - - } - eof = true; - buffer = 0; -} - -size_t MPQFile::read(void* dest, size_t bytes) -{ - if (eof) return 0; - - size_t rpos = pointer + bytes; - if (rpos > size_t(size)) { - bytes = size - pointer; - eof = true; - } - - memcpy(dest, &(buffer[pointer]), bytes); - - pointer = rpos; - - return bytes; -} - -void MPQFile::seek(int offset) -{ - pointer = offset; - eof = (pointer >= size); -} - -void MPQFile::seekRelative(int offset) -{ - pointer += offset; - eof = (pointer >= size); -} - -void MPQFile::close() -{ - delete[] buffer; - buffer = 0; - eof = true; -} diff --git a/src/tools/vmap4_extractor/mpq_libmpq04.h b/src/tools/vmap4_extractor/mpq_libmpq04.h deleted file mode 100644 index 1cd9403a4cf..00000000000 --- a/src/tools/vmap4_extractor/mpq_libmpq04.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef MPQ_H -#define MPQ_H - -#include "loadlib/loadlib.h" -#include "libmpq/mpq.h" - -#include <string.h> -#include <string> -#include <vector> -#include <deque> - -class MPQArchive -{ - -public: - mpq_archive_s *mpq_a; - - MPQArchive(char const* filename); - ~MPQArchive() { if (isOpened()) close(); } - - void GetFileListTo(std::vector<std::string>& filelist) { - uint32_t filenum; - if(libmpq__file_number(mpq_a, "(listfile)", &filenum)) return; - libmpq__off_t size, transferred; - libmpq__file_size_unpacked(mpq_a, filenum, &size); - - char *buffer = new char[size + 1]; - buffer[size] = '\0'; - - libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred); - - char seps[] = "\n"; - char *token; - - token = strtok( buffer, seps ); - uint32 counter = 0; - while ((token != nullptr) && (counter < size)) { - //cout << token << endl; - token[strlen(token) - 1] = 0; - std::string s = token; - filelist.push_back(s); - counter += strlen(token) + 2; - token = strtok(nullptr, seps); - } - - delete[] buffer; - } - -private: - void close(); - bool isOpened() const; -}; -typedef std::deque<MPQArchive*> ArchiveSet; - -class MPQFile -{ - //MPQHANDLE handle; - bool eof; - char *buffer; - libmpq__off_t pointer,size; - - MPQFile(MPQFile const& /*f*/) = delete; - void operator=(MPQFile const& /*f*/) = delete; - -public: - MPQFile(char const* filename); // filenames are not case sensitive - ~MPQFile() { close(); } - size_t read(void* dest, size_t bytes); - size_t getSize() { return size; } - size_t getPos() { return pointer; } - char* getBuffer() { return buffer; } - char* getPointer() { return buffer + pointer; } - bool isEof() { return eof; } - void seek(int offset); - void seekRelative(int offset); - void close(); -}; - -inline void flipcc(char *fcc) -{ - std::swap(fcc[0], fcc[3]); - std::swap(fcc[1], fcc[2]); -} - -#endif diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp index 462ae88d2ab..e5a3c04b839 100644 --- a/src/tools/vmap4_extractor/vmapexport.cpp +++ b/src/tools/vmap4_extractor/vmapexport.cpp @@ -24,33 +24,17 @@ #include "Util.h" #include "wdtfile.h" #include "wmo.h" -#include "mpq_libmpq04.h" +#include "mpq_libmpq.h" #include <boost/filesystem/directory.hpp> #include <boost/filesystem/operations.hpp> -#include <fstream> -#include <iostream> #include <list> #include <map> #include <unordered_map> #include <vector> #include <cstdio> -#include <cerrno> -#include <sys/stat.h> - -#ifdef _WIN32 - #include <direct.h> - #define mkdir _mkdir -#endif - -//------------------------------------------------------------------------------ -// Defines - -#define MPQ_BLOCK_SIZE 0x1000 //----------------------------------------------------------------------------- -extern ArchiveSet gOpenArchives; - typedef struct { char name[64]; @@ -66,6 +50,7 @@ bool preciseVectorData = false; std::unordered_map<std::string, WMODoodadData> WmoDoodads; // Constants +static constexpr std::array<std::string_view, 12> MpqLocaleNames = { "enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU" }; char const* szWorkDirWmo = "./Buildings"; @@ -226,123 +211,6 @@ void ParsMapFiles() } } -void getGamePath() -{ -#ifdef _WIN32 - strcpy(input_path,"Data\\"); -#else - strcpy(input_path,"Data/"); -#endif -} - -bool scan_patches(char const* scanmatch, std::vector<std::string>& pArchiveNames) -{ - int i; - char path[512]; - - for (i = 1; i <= 99; i++) - { - if (i != 1) - { - sprintf(path, "%s-%d.MPQ", scanmatch, i); - } - else - { - sprintf(path, "%s.MPQ", scanmatch); - } -#ifdef __linux__ - if(FILE* h = fopen64(path, "rb")) -#else - if(FILE* h = fopen(path, "rb")) -#endif - { - fclose(h); - //matches.push_back(path); - pArchiveNames.push_back(path); - } - } - - return(true); -} - -bool fillArchiveNameVector(std::vector<std::string>& pArchiveNames) -{ - if(!hasInputPathParam) - getGamePath(); - - printf("\nGame path: %s\n", input_path); - - std::string in_path(input_path); - std::vector<std::string> locales, searchLocales; - - searchLocales.push_back("enGB"); - searchLocales.push_back("enUS"); - searchLocales.push_back("deDE"); - searchLocales.push_back("esES"); - searchLocales.push_back("frFR"); - searchLocales.push_back("koKR"); - searchLocales.push_back("zhCN"); - searchLocales.push_back("zhTW"); - searchLocales.push_back("enCN"); - searchLocales.push_back("enTW"); - searchLocales.push_back("esMX"); - searchLocales.push_back("ruRU"); - - for (std::vector<std::string>::iterator i = searchLocales.begin(); i != searchLocales.end(); ++i) - { - std::string localePath = in_path + *i; - // check if locale exists: - struct stat status; - if (stat(localePath.c_str(), &status)) - continue; - if ((status.st_mode & S_IFDIR) == 0) - continue; - printf("Found locale '%s'\n", i->c_str()); - locales.push_back(*i); - } - printf("\n"); - - // open locale expansion and common files - printf("Adding data files from locale directories.\n"); - for (std::vector<std::string>::iterator i = locales.begin(); i != locales.end(); ++i) - { - pArchiveNames.push_back(in_path + *i + "/locale-" + *i + ".MPQ"); - pArchiveNames.push_back(in_path + *i + "/expansion-locale-" + *i + ".MPQ"); - pArchiveNames.push_back(in_path + *i + "/lichking-locale-" + *i + ".MPQ"); - } - - // open expansion and common files - pArchiveNames.push_back(input_path + std::string("common.MPQ")); - pArchiveNames.push_back(input_path + std::string("common-2.MPQ")); - pArchiveNames.push_back(input_path + std::string("expansion.MPQ")); - pArchiveNames.push_back(input_path + std::string("lichking.MPQ")); - - // now, scan for the patch levels in the core dir - printf("Scanning patch levels from data directory.\n"); - if (!scan_patches(Trinity::StringFormat("{}patch", input_path).c_str(), pArchiveNames)) - return(false); - - // now, scan for the patch levels in locale dirs - printf("Scanning patch levels from locale directories.\n"); - bool foundOne = false; - for (std::string const& locale : locales) - { - printf("Locale: %s\n", locale.c_str()); - if(scan_patches(Trinity::StringFormat("{}{}/patch-{}", input_path, locale, locale).c_str(), pArchiveNames)) - foundOne = true; - } - - printf("\n"); - - if(!foundOne) - { - printf("no locale found\n"); - return false; - } - - return true; -} - bool processArgv(int argc, char ** argv, const char *versionString) { bool result = true; @@ -423,12 +291,10 @@ int main(int argc, char ** argv) return 1; // some simple check if working dir is dirty - else + boost::filesystem::path sdir_bin = boost::filesystem::path(szWorkDirWmo) / "dir_bin"; { - std::string sdir = std::string(szWorkDirWmo) + "/dir"; - std::string sdir_bin = std::string(szWorkDirWmo) + "/dir_bin"; - struct stat status; - if (!stat(sdir.c_str(), &status) || !stat(sdir_bin.c_str(), &status)) + boost::system::error_code ec; + if (boost::filesystem::exists(sdir_bin, ec)) { printf("Your output directory seems to be polluted, please use an empty directory!\n"); printf("<press return to exit>"); @@ -440,24 +306,14 @@ int main(int argc, char ** argv) printf("Extract %s. Beginning work ....\n", versionString); //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // Create the working directory - if (mkdir(szWorkDirWmo -#if defined(__linux__) || defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) - , 0711 -#endif - )) - success = (errno == EEXIST); - - // prepare archive name list - std::vector<std::string> archiveNames; - fillArchiveNameVector(archiveNames); - for (size_t i = 0; i < archiveNames.size(); ++i) + success = boost::filesystem::create_directories(szWorkDirWmo) || boost::filesystem::is_directory(szWorkDirWmo); + + auto foundLocale = std::ranges::find_if(MpqLocaleNames, [](std::string_view localeName) { - MPQArchive *archive = new MPQArchive(archiveNames[i].c_str()); - if (gOpenArchives.empty() || gOpenArchives.front() != archive) - delete archive; - } + return MPQ::OpenArchives(input_path, localeName); + }); - if (gOpenArchives.empty()) + if (foundLocale == MpqLocaleNames.end()) { printf("FATAL ERROR: None MPQ archive found by path '%s'. Use -d option with proper path.\n", input_path); return 1; diff --git a/src/tools/vmap4_extractor/wdtfile.h b/src/tools/vmap4_extractor/wdtfile.h index ccb23db3b13..c74adf62e6d 100644 --- a/src/tools/vmap4_extractor/wdtfile.h +++ b/src/tools/vmap4_extractor/wdtfile.h @@ -18,7 +18,7 @@ #ifndef WDTFILE_H #define WDTFILE_H -#include "mpq_libmpq04.h" +#include "mpq_libmpq.h" #include <string> class ADTFile; diff --git a/src/tools/vmap4_extractor/wmo.cpp b/src/tools/vmap4_extractor/wmo.cpp index 0442240249b..5146f674a35 100644 --- a/src/tools/vmap4_extractor/wmo.cpp +++ b/src/tools/vmap4_extractor/wmo.cpp @@ -18,7 +18,7 @@ #include "vmapexport.h" #include "adtfile.h" #include "vec3d.h" -#include "mpq_libmpq04.h" +#include "mpq_libmpq.h" #include "VMapDefinitions.h" #include "wmo.h" |