aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2025-05-26 12:50:38 +0200
committerShauren <shauren.trinity@gmail.com>2025-05-26 12:50:38 +0200
commitbc57ce984bd8ac7e066e86a18b8cfd95616f86dd (patch)
tree53eee77330140f340615fff7619c4bd85fdc264b /src
parent1a5af00760e8ba96a01c0e9049cca9de30ded567 (diff)
Tools/Extractors: Load the same MPQ file set as the client does (including custom patches)
Diffstat (limited to 'src')
-rw-r--r--src/tools/CMakeLists.txt1
-rw-r--r--src/tools/extractor_common/CMakeLists.txt30
-rw-r--r--src/tools/extractor_common/mpq_libmpq.cpp241
-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.txt3
-rw-r--r--src/tools/map_extractor/System.cpp131
-rw-r--r--src/tools/map_extractor/dbcfile.cpp4
-rw-r--r--src/tools/map_extractor/loadlib.cpp2
-rw-r--r--src/tools/map_extractor/mpq_libmpq.cpp128
-rw-r--r--src/tools/vmap4_extractor/CMakeLists.txt3
-rw-r--r--src/tools/vmap4_extractor/adtfile.h2
-rw-r--r--src/tools/vmap4_extractor/dbcfile.cpp2
-rw-r--r--src/tools/vmap4_extractor/model.cpp2
-rw-r--r--src/tools/vmap4_extractor/mpq_libmpq.cpp134
-rw-r--r--src/tools/vmap4_extractor/mpq_libmpq04.h102
-rw-r--r--src/tools/vmap4_extractor/vmapexport.cpp166
-rw-r--r--src/tools/vmap4_extractor/wdtfile.h2
-rw-r--r--src/tools/vmap4_extractor/wmo.cpp2
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"