diff options
author | Shauren <shauren.trinity@gmail.com> | 2016-07-18 23:37:19 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2016-07-18 23:37:19 +0200 |
commit | fe4d11c65a512c61ccb924fbf3dc20c8cfc84dc7 (patch) | |
tree | 86888deb22268503d70ae7259bbf17add4dcdc1f | |
parent | a9a13d10f7c510bb392539608cb276435a78b688 (diff) |
Tools: Extractor updates
* VMAP extractor does not work due to a bug in CascLib
28 files changed, 1633 insertions, 1296 deletions
diff --git a/dep/CascLib/src/CascCommon.h b/dep/CascLib/src/CascCommon.h index 71855726d03..e7a9d6b5464 100644 --- a/dep/CascLib/src/CascCommon.h +++ b/dep/CascLib/src/CascCommon.h @@ -58,7 +58,7 @@ #define BLTE_HEADER_DELTA 0x1E // Distance of BLTE header from begin of the header area #define MAX_HEADER_AREA_SIZE 0x2A // Length of the file header area -// File header area in the data.xxx: +// File header area in the data.nnn: // BYTE HeaderHash[MD5_HASH_SIZE]; // MD5 of the frame array // DWORD dwFileSize; // Size of the file (see comment before CascGetFileSize for details) // BYTE SomeSize[4]; // Some size (big endian) @@ -205,6 +205,7 @@ typedef struct _TCascStorage QUERY_KEY ArchivesGroup; // Key array of the "archive-group" QUERY_KEY ArchivesKey; // Key array of the "archives" QUERY_KEY PatchArchivesKey; // Key array of the "patch-archives" + QUERY_KEY PatchArchivesGroup; // Key array of the "patch-archive-group" QUERY_KEY RootKey; QUERY_KEY PatchKey; QUERY_KEY DownloadKey; diff --git a/dep/CascLib/src/CascDecrypt.cpp b/dep/CascLib/src/CascDecrypt.cpp index 5f4dc77dfe8..21477b30e8d 100644 --- a/dep/CascLib/src/CascDecrypt.cpp +++ b/dep/CascLib/src/CascDecrypt.cpp @@ -255,7 +255,7 @@ int CascDecrypt(LPBYTE pbOutBuffer, PDWORD pcbOutBuffer, LPBYTE pbInBuffer, DWOR // Check if we know the key pbKey = FindCascKey(KeyName); if(pbKey == NULL) - return ERROR_UNKNOWN_FILE_KEY; + return ERROR_FILE_ENCRYPTED; // Shuffle the Vector with the block index // Note that there's no point to go beyond 32 bits, unless the file has diff --git a/dep/CascLib/src/CascFiles.cpp b/dep/CascLib/src/CascFiles.cpp index a32f411462f..0641b315a09 100644 --- a/dep/CascLib/src/CascFiles.cpp +++ b/dep/CascLib/src/CascFiles.cpp @@ -696,7 +696,7 @@ static int LoadCdnConfigFile(TCascStorage * hs, void * pvListFile) szVarBegin = CheckLineVariable(szLineBegin, szLineEnd, "patch-archive-group"); if(szVarBegin != NULL) { - LoadSingleBlob(&hs->PatchArchivesKey, szVarBegin, szLineEnd); + LoadSingleBlob(&hs->PatchArchivesGroup, szVarBegin, szLineEnd); continue; } diff --git a/dep/CascLib/src/CascLib.h b/dep/CascLib/src/CascLib.h index cc22738d63a..b6c68938d8e 100644 --- a/dep/CascLib/src/CascLib.h +++ b/dep/CascLib/src/CascLib.h @@ -32,35 +32,12 @@ extern "C" { #define CASCLIB_VERSION 0x0100 // Current version of CascLib (1.0) #define CASCLIB_VERSION_STRING "1.00" // String version of CascLib version -#define ERROR_UNKNOWN_FILE_KEY 10001 // Returned by encrypted stream when can't find file key -#define ERROR_FILE_INCOMPLETE 10006 // The required file part is missing - // Values for CascOpenStorage #define CASC_STOR_XXXXX 0x00000001 // Not used // Values for CascOpenFile #define CASC_OPEN_BY_ENCODING_KEY 0x00000001 // The name is just the encoding key; skip ROOT file processing -// Flags for file stream -#define BASE_PROVIDER_FILE 0x00000000 // Base data source is a file -#define BASE_PROVIDER_MAP 0x00000001 // Base data source is memory-mapped file -#define BASE_PROVIDER_HTTP 0x00000002 // Base data source is a file on web server -#define BASE_PROVIDER_MASK 0x0000000F // Mask for base provider value - -#define STREAM_PROVIDER_FLAT 0x00000000 // Stream is linear with no offset mapping -#define STREAM_PROVIDER_PARTIAL 0x00000010 // Stream is partial file (.part) -#define STREAM_PROVIDER_ENCRYPTED 0x00000020 // Stream is an encrypted archive -#define STREAM_PROVIDER_BLOCK4 0x00000030 // 0x4000 per block, text MD5 after each block, max 0x2000 blocks per file -#define STREAM_PROVIDER_MASK 0x000000F0 // Mask for stream provider value - -#define STREAM_FLAG_READ_ONLY 0x00000100 // Stream is read only -#define STREAM_FLAG_WRITE_SHARE 0x00000200 // Allow write sharing when open for write -#define STREAM_FLAG_USE_BITMAP 0x00000400 // If the file has a file bitmap, load it and use it -#define STREAM_OPTIONS_MASK 0x0000FF00 // Mask for stream options - -#define STREAM_PROVIDERS_MASK 0x000000FF // Mask to get stream providers -#define STREAM_FLAGS_MASK 0x0000FFFF // Mask for all stream flags (providers+options) - #define CASC_LOCALE_ALL 0xFFFFFFFF #define CASC_LOCALE_NONE 0x00000000 #define CASC_LOCALE_UNKNOWN1 0x00000001 diff --git a/dep/CascLib/src/CascOpenStorage.cpp b/dep/CascLib/src/CascOpenStorage.cpp index d8508da73bf..4883e83283e 100644 --- a/dep/CascLib/src/CascOpenStorage.cpp +++ b/dep/CascLib/src/CascOpenStorage.cpp @@ -507,7 +507,7 @@ static int LoadKeyMapping(PCASC_MAPPING_TABLE pKeyMapping, DWORD KeyIndex) { // Retrieve the file size FileStream_GetSize(pStream, &FileSize); - if(0 < FileSize && FileSize <= 0x100000) + if(0 < FileSize && FileSize <= 0x200000) { // WoW6 actually reads THE ENTIRE file to memory // Verified on Mac build (x64) @@ -991,6 +991,7 @@ static TCascStorage * FreeCascStorage(TCascStorage * hs) FreeCascBlob(&hs->ArchivesGroup); FreeCascBlob(&hs->ArchivesKey); FreeCascBlob(&hs->PatchArchivesKey); + FreeCascBlob(&hs->PatchArchivesGroup); FreeCascBlob(&hs->RootKey); FreeCascBlob(&hs->PatchKey); FreeCascBlob(&hs->DownloadKey); diff --git a/dep/CascLib/src/CascPort.h b/dep/CascLib/src/CascPort.h index 366aedcc89d..6a9aee2edce 100644 --- a/dep/CascLib/src/CascPort.h +++ b/dep/CascLib/src/CascPort.h @@ -216,6 +216,11 @@ #define ERROR_HANDLE_EOF 1002 // No such error code under Linux #define ERROR_CAN_NOT_COMPLETE 1003 // No such error code under Linux #define ERROR_FILE_CORRUPT 1004 // No such error code under Linux + #define ERROR_FILE_ENCRYPTED 1005 // Returned by encrypted stream when can't find file key +#endif + +#ifndef ERROR_FILE_INCOMPLETE +#define ERROR_FILE_INCOMPLETE 1006 // The required file part is missing #endif //----------------------------------------------------------------------------- diff --git a/dep/CascLib/src/CascRootFile_Diablo3.cpp b/dep/CascLib/src/CascRootFile_Diablo3.cpp index c515567af5f..6fa8309a2fe 100644 --- a/dep/CascLib/src/CascRootFile_Diablo3.cpp +++ b/dep/CascLib/src/CascRootFile_Diablo3.cpp @@ -231,7 +231,7 @@ static const DIABLO3_ASSET_INFO Assets[] = {"Accolade", "aco"}, // 0x42 }; -static const DIABLO3_ASSET_INFO UnknownAsset = {"Unknown", "xxx"}; +static const DIABLO3_ASSET_INFO UnknownAsset = {"Unknown", "unk"}; #define DIABLO3_ASSET_COUNT (sizeof(Assets) / sizeof(Assets[0])) @@ -327,7 +327,7 @@ static size_t CreateShortName( } } - // If we havent't found the package, we either use the default asset extension or "xxx" + // If we havent't found the package, we either use the default asset extension or "unk" if(szPackageName == NULL) { if(dwSubIndex == DIABLO3_INVALID_INDEX) @@ -337,7 +337,7 @@ static size_t CreateShortName( } else { - strcpy(szBuffer + nLength, "xxx"); + strcpy(szBuffer + nLength, "unk"); nLength += 3; } } @@ -887,7 +887,7 @@ static int ParseCoreTOC( // Find out the entry with the maximum index for(DWORD n = 0; n < pTocHeader->EntryCounts[i]; n++) { - if(pTocEntry->FileIndex > dwFileIndexes) + if(pTocEntry->FileIndex >= dwFileIndexes) dwFileIndexes = pTocEntry->FileIndex + 1; pTocEntry++; } diff --git a/dep/CascLib/src/CascRootFile_WoW6.cpp b/dep/CascLib/src/CascRootFile_WoW6.cpp index ee915986114..2e6a23610f3 100644 --- a/dep/CascLib/src/CascRootFile_WoW6.cpp +++ b/dep/CascLib/src/CascRootFile_WoW6.cpp @@ -381,7 +381,7 @@ static LPBYTE WowHandler_GetKey(TRootHandler_WoW6 * pRootHandler, const char * s BYTE FileDataIdLE[4]; // Open by FileDataId. The file name must be as following: - // File########.xxx, where '#' are hexa-decimal numbers (case insensitive). + // File########.unk, where '#' are hexa-decimal numbers (case insensitive). // Extension is ignored in that case if(IsFileDataIdName(szFileName)) { diff --git a/dep/CascLib/src/common/FileStream.cpp b/dep/CascLib/src/common/FileStream.cpp index ccd3a65318d..cb49f7f4ac1 100644 --- a/dep/CascLib/src/common/FileStream.cpp +++ b/dep/CascLib/src/common/FileStream.cpp @@ -1,7 +1,7 @@ /*****************************************************************************/ /* FileStream.cpp Copyright (c) Ladislav Zezula 2010 */ /*---------------------------------------------------------------------------*/ -/* File stream support for CascLib */ +/* File stream support */ /* */ /* Windows support: Written by Ladislav Zezula */ /* Mac support: Written by Sam Wilkins */ @@ -162,7 +162,7 @@ static bool BaseFile_Read( #ifdef PLATFORM_WINDOWS { - // Note: CascLib no longer supports Windows 9x. + // Note: We no longer support Windows 9x. // Thus, we can use the OVERLAPPED structure to specify // file offset to read from file. This allows us to skip // one system call to SetFilePointer @@ -233,7 +233,7 @@ static bool BaseFile_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const #ifdef PLATFORM_WINDOWS { - // Note: CascLib no longer supports Windows 9x. + // Note: We no longer support Windows 9x. // Thus, we can use the OVERLAPPED structure to specify // file offset to read from file. This allows us to skip // one system call to SetFilePointer @@ -2097,7 +2097,7 @@ static TFileStream * EncrStream_Open(const TCHAR * szFileName, DWORD dwStreamFla // Cleanup the stream and return FileStream_Close(pStream); - SetLastError(ERROR_UNKNOWN_FILE_KEY); + SetLastError(ERROR_FILE_ENCRYPTED); return NULL; } diff --git a/dep/CascLib/src/common/FileStream.h b/dep/CascLib/src/common/FileStream.h index 1e51acfc845..1c72619e393 100644 --- a/dep/CascLib/src/common/FileStream.h +++ b/dep/CascLib/src/common/FileStream.h @@ -12,6 +12,28 @@ #define __FILESTREAM_H__ //----------------------------------------------------------------------------- +// Flags for file stream + +#define BASE_PROVIDER_FILE 0x00000000 // Base data source is a file +#define BASE_PROVIDER_MAP 0x00000001 // Base data source is memory-mapped file +#define BASE_PROVIDER_HTTP 0x00000002 // Base data source is a file on web server +#define BASE_PROVIDER_MASK 0x0000000F // Mask for base provider value + +#define STREAM_PROVIDER_FLAT 0x00000000 // Stream is linear with no offset mapping +#define STREAM_PROVIDER_PARTIAL 0x00000010 // Stream is partial file (.part) +#define STREAM_PROVIDER_ENCRYPTED 0x00000020 // Stream is an encrypted archive +#define STREAM_PROVIDER_BLOCK4 0x00000030 // 0x4000 per block, text MD5 after each block, max 0x2000 blocks per file +#define STREAM_PROVIDER_MASK 0x000000F0 // Mask for stream provider value + +#define STREAM_FLAG_READ_ONLY 0x00000100 // Stream is read only +#define STREAM_FLAG_WRITE_SHARE 0x00000200 // Allow write sharing when open for write +#define STREAM_FLAG_USE_BITMAP 0x00000400 // If the file has a file bitmap, load it and use it +#define STREAM_OPTIONS_MASK 0x0000FF00 // Mask for stream options + +#define STREAM_PROVIDERS_MASK 0x000000FF // Mask to get stream providers +#define STREAM_FLAGS_MASK 0x0000FFFF // Mask for all stream flags (providers+options) + +//----------------------------------------------------------------------------- // Function prototypes typedef void (*STREAM_INIT)( diff --git a/dep/PackageList.txt b/dep/PackageList.txt index 5bf27dd5fe6..ebbe0a949b1 100644 --- a/dep/PackageList.txt +++ b/dep/PackageList.txt @@ -58,7 +58,7 @@ recastnavigation (Recast is state of the art navigation mesh construction toolse CascLib (An open-source implementation of library for reading CASC storage from Blizzard games since 2014) https://github.com/ladislav-zezula/CascLib - Version: d477d30f7c2b3a306fd07c92929950639335fb3f + Version: fe97d8cf7fd2deb08db7e8c14990a6420a3b47b4 rapidjson (A fast JSON parser/generator for C++ with both SAX/DOM style API http://rapidjson.org/) https://github.com/miloyip/rapidjson diff --git a/src/server/shared/DataStores/DB2Meta.cpp b/src/common/DataStores/DB2Meta.cpp index bf119b52150..bf119b52150 100644 --- a/src/server/shared/DataStores/DB2Meta.cpp +++ b/src/common/DataStores/DB2Meta.cpp diff --git a/src/server/shared/DataStores/DB2Meta.h b/src/common/DataStores/DB2Meta.h index 2c165b52d86..2c165b52d86 100644 --- a/src/server/shared/DataStores/DB2Meta.h +++ b/src/common/DataStores/DB2Meta.h diff --git a/src/tools/map_extractor/DB2.cpp b/src/tools/map_extractor/DB2.cpp new file mode 100644 index 00000000000..52d4a1544af --- /dev/null +++ b/src/tools/map_extractor/DB2.cpp @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * 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 "DB2.h" + +DB2FileLoader::DB2FileLoader() +{ + meta = nullptr; + + recordSize = 0; + recordCount = 0; + fieldCount = 0; + stringSize = 0; + tableHash = 0; + layoutHash = 0; + minIndex = 0; + maxIndex = 0; + localeMask = 0; + copyIdSize = 0; + + data = nullptr; + stringTable = nullptr; + idTable = nullptr; + idTableSize = 0; + copyTable = nullptr; + fields = nullptr; +} + +bool DB2FileLoader::Load(HANDLE db2Handle, DB2Meta const* meta) +{ + if (data) + { + delete[] data; + data = nullptr; + } + + DWORD bytesRead = 0; + this->meta = meta; + std::uint32_t header; + CascReadFile(db2Handle, &header, sizeof(header), &bytesRead); + if (bytesRead != sizeof(header)) // Signature + return false; + + EndianConvert(header); + + if (header != 0x35424457) + return false; //'WDB5' + + CascReadFile(db2Handle, &recordCount, sizeof(recordCount), &bytesRead); + if (bytesRead != sizeof(recordCount)) // Number of records + return false; + + EndianConvert(recordCount); + + CascReadFile(db2Handle, &fieldCount, sizeof(fieldCount), &bytesRead); + if (bytesRead != sizeof(fieldCount)) // Number of fields + return false; + + EndianConvert(fieldCount); + + CascReadFile(db2Handle, &recordSize, sizeof(recordSize), &bytesRead); + if (bytesRead != sizeof(recordSize)) // Size of a record + return false; + + EndianConvert(recordSize); + + CascReadFile(db2Handle, &stringSize, sizeof(stringSize), &bytesRead); + if (bytesRead != sizeof(stringSize)) // String size + return false; + + EndianConvert(stringSize); + + CascReadFile(db2Handle, &tableHash, sizeof(tableHash), &bytesRead); + if (bytesRead != sizeof(tableHash)) // Table hash + return false; + + EndianConvert(tableHash); + + CascReadFile(db2Handle, &layoutHash, sizeof(layoutHash), &bytesRead); + if (bytesRead != sizeof(layoutHash)) // Layout hash + return false; + + if (layoutHash != meta->LayoutHash) + return false; + + EndianConvert(layoutHash); + + CascReadFile(db2Handle, &minIndex, sizeof(minIndex), &bytesRead); + if (bytesRead != sizeof(minIndex)) // MinIndex WDB2 + return false; + + EndianConvert(minIndex); + + CascReadFile(db2Handle, &maxIndex, sizeof(maxIndex), &bytesRead); + if (bytesRead != sizeof(maxIndex)) // MaxIndex WDB2 + return false; + + EndianConvert(maxIndex); + + CascReadFile(db2Handle, &localeMask, sizeof(localeMask), &bytesRead); + if (bytesRead != sizeof(localeMask)) // Locales + return false; + + EndianConvert(localeMask); + + CascReadFile(db2Handle, ©IdSize, sizeof(copyIdSize), &bytesRead); + if (bytesRead != sizeof(copyIdSize)) + return false; + + EndianConvert(copyIdSize); + + CascReadFile(db2Handle, &metaFlags, sizeof(metaFlags), &bytesRead); + if (bytesRead != sizeof(metaFlags)) + return false; + + EndianConvert(metaFlags); + + ASSERT((metaFlags & 0x1) == 0); + ASSERT((meta->IndexField == -1) || (meta->IndexField == (metaFlags >> 16))); + + fields = new FieldEntry[fieldCount]; + CascReadFile(db2Handle, fields, fieldCount * sizeof(FieldEntry), &bytesRead); + if (bytesRead != fieldCount * sizeof(FieldEntry)) + return false; + + if (!meta->HasIndexFieldInData()) + idTableSize = recordCount * sizeof(std::uint32_t); + + data = new unsigned char[recordSize * recordCount + stringSize]; + stringTable = data + recordSize * recordCount; + + CascReadFile(db2Handle, data, recordSize * recordCount + stringSize, &bytesRead); + if (bytesRead != recordSize * recordCount + stringSize) + return false; + + if (idTableSize) + { + idTable = new unsigned char[idTableSize]; + CascReadFile(db2Handle, idTable, idTableSize, &bytesRead); + if (bytesRead != idTableSize) + return false; + } + + if (copyIdSize) + { + copyTable = new unsigned char[copyIdSize]; + CascReadFile(db2Handle, copyTable, copyIdSize, &bytesRead); + if (bytesRead != copyIdSize) + return false; + } + + return true; +} + +DB2FileLoader::~DB2FileLoader() +{ + delete[] data; + delete[] idTable; + delete[] copyTable; + delete[] fields; +} + +DB2FileLoader::Record DB2FileLoader::getRecord(size_t id) +{ + assert(data); + return Record(*this, data + id * recordSize); +} + +std::pair<std::uint32_t, std::uint32_t> DB2FileLoader::GetRowCopy(std::uint32_t i) const +{ + std::uint32_t* copyIds = (std::uint32_t*)copyTable; + std::uint32_t to = copyIds[i]; + std::uint32_t from = copyIds[i + 1]; + return{ from, to }; +} + +std::uint32_t DB2FileLoader::GetMaxId() const +{ + std::uint32_t j = maxIndex; + for (std::uint32_t i = 0; i < GetNumRowCopies(); ++i) + if (j < GetRowCopy(i).second) + j = GetRowCopy(i).second; + + return j; +} diff --git a/src/tools/map_extractor/DB2.h b/src/tools/map_extractor/DB2.h new file mode 100644 index 00000000000..0cb6c111941 --- /dev/null +++ b/src/tools/map_extractor/DB2.h @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * 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 MapExtractor_DB2_h__ +#define MapExtractor_DB2_h__ + +#include "DB2Meta.h" +#ifdef PLATFORM_WINDOWS +#undef PLATFORM_WINDOWS +#endif +#include "CascLib.h" +#include "Utilities/ByteConverter.h" +#include "Errors.h" + +class DB2FileLoader +{ + public: + DB2FileLoader(); + ~DB2FileLoader(); + + bool Load(HANDLE db2Handle, DB2Meta const* meta); + + class Record + { + public: + float getFloat(std::uint32_t field, std::uint32_t arrayIndex) const + { + ASSERT(field < file.fieldCount); + float val = *reinterpret_cast<float*>(offset + GetOffset(field) + arrayIndex * sizeof(float)); + EndianConvert(val); + return val; + } + + std::uint32_t getUInt(std::uint32_t field, std::uint32_t arrayIndex) const + { + ASSERT(field < file.fieldCount); + return GetVarInt(field, GetByteSize(field), arrayIndex); + } + + std::uint8_t getUInt8(std::uint32_t field, std::uint32_t arrayIndex) const + { + ASSERT(field < file.fieldCount); + ASSERT(GetByteSize(field) == 1); + return *reinterpret_cast<std::uint8_t*>(offset + GetOffset(field) + arrayIndex * sizeof(std::uint8_t)); + } + + std::uint16_t getUInt16(std::uint32_t field, std::uint32_t arrayIndex) const + { + ASSERT(field < file.fieldCount); + ASSERT(GetByteSize(field) == 2); + std::uint16_t val = *reinterpret_cast<std::uint16_t*>(offset + GetOffset(field) + arrayIndex * sizeof(std::uint16_t)); + EndianConvert(val); + return val; + } + + char const* getString(std::uint32_t field, std::uint32_t arrayIndex) const + { + ASSERT(field < file.fieldCount); + std::uint32_t stringOffset = *reinterpret_cast<std::uint32_t*>(offset + GetOffset(field) + arrayIndex * sizeof(std::uint32_t)); + EndianConvert(stringOffset); + ASSERT(stringOffset < file.stringSize); + return reinterpret_cast<char*>(file.stringTable + stringOffset); + } + + private: + std::uint16_t GetOffset(std::uint32_t field) const + { + ASSERT(field < file.fieldCount); + return file.fields[field].Offset; + } + + std::uint16_t GetByteSize(std::uint32_t field) const + { + ASSERT(field < file.fieldCount); + return 4 - file.fields[field].UnusedBits / 8; + } + + std::uint32_t GetVarInt(std::uint32_t field, std::uint16_t size, std::uint32_t arrayIndex) const + { + ASSERT(field < file.fieldCount); + switch (size) + { + case 1: + { + return *reinterpret_cast<std::uint8_t*>(offset + GetOffset(field) + arrayIndex * sizeof(std::uint8_t)); + } + case 2: + { + std::uint16_t val = *reinterpret_cast<std::uint16_t*>(offset + GetOffset(field) + arrayIndex * sizeof(std::uint16_t)); + EndianConvert(val); + return val; + } + case 3: + { +#pragma pack(push, 1) + struct dbcint24 { std::uint8_t v[3]; }; +#pragma pack(pop) + dbcint24 val = *reinterpret_cast<dbcint24*>(offset + GetOffset(field) + arrayIndex * sizeof(dbcint24)); + EndianConvert(val); + return std::uint32_t(val.v[0]) | (std::uint32_t(val.v[1]) << 8) | (std::uint32_t(val.v[2]) << 16); + } + case 4: + { + std::uint32_t val = *reinterpret_cast<std::uint32_t*>(offset + GetOffset(field) + arrayIndex * sizeof(std::uint32_t)); + EndianConvert(val); + return val; + } + default: + break; + } + + ASSERT(false, "GetByteSize(field) < 4"); + return 0; + } + + Record(DB2FileLoader &file_, unsigned char *offset_): offset(offset_), file(file_) {} + unsigned char *offset; + DB2FileLoader &file; + + friend class DB2FileLoader; + }; + + // Get record by id + Record getRecord(size_t id); + std::uint32_t getId(size_t row) { return ((std::uint32_t*)idTable)[row]; } + std::pair<std::uint32_t, std::uint32_t> GetRowCopy(std::uint32_t i) const; + + std::uint32_t GetNumRows() const { return recordCount; } + std::uint32_t GetNumRowCopies() const { return copyIdSize / 8; } + std::uint32_t GetMaxId() const; + +private: +#pragma pack(push, 1) + struct FieldEntry + { + std::uint16_t UnusedBits; + std::uint16_t Offset; + }; +#pragma pack(pop) + + DB2Meta const* meta; + + // WDB2 / WCH2 fields + std::uint32_t recordSize; + std::uint32_t recordCount; + std::uint32_t fieldCount; + std::uint32_t stringSize; + std::uint32_t tableHash; + std::uint32_t layoutHash; + std::uint32_t minIndex; + std::uint32_t maxIndex; + std::uint32_t localeMask; + std::uint32_t copyIdSize; + std::uint32_t metaFlags; + + unsigned char* data; + unsigned char* stringTable; + unsigned char* idTable; + std::uint32_t idTableSize; + unsigned char* copyTable; + FieldEntry* fields; +}; + +#endif // MapExtractor_DB2_h__ diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp index 91efa8ce287..9005a7ba936 100644 --- a/src/tools/map_extractor/System.cpp +++ b/src/tools/map_extractor/System.cpp @@ -34,7 +34,7 @@ #endif #include "DBFilesClientList.h" #include "CascLib.h" -#include "dbcfile.h" +#include "DB2.h" #include "Banner.h" #include "StringFormat.h" @@ -75,12 +75,34 @@ typedef struct uint32 id; } map_id; -map_id *map_ids; -uint16 *LiqType; +std::vector<map_id> map_ids; +std::vector<uint16> LiqType; #define MAX_PATH_LENGTH 128 char output_path[MAX_PATH_LENGTH]; char input_path[MAX_PATH_LENGTH]; +struct LiquidTypeMeta +{ + static DB2Meta const* Instance() + { + static char const* types = "sifffffSifihhbbbbbi"; + static uint8 const arraySizes[19] = { 1, 1, 1, 1, 1, 1, 1, 6, 2, 18, 4, 1, 1, 1, 1, 1, 1, 6, 1 }; + static DB2Meta instance(-1, 19, 0x28B44DCB, types, arraySizes); + return &instance; + } +}; + +struct MapMeta +{ + static DB2Meta const* Instance() + { + static char const* types = "siffssshhhhhhhbbbbb"; + static uint8 const arraySizes[19] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + static DB2Meta instance(-1, 19, 0xB32E648C, types, arraySizes); + return &instance; + } +}; + // ************************************************** // Extractor options // ************************************************** @@ -276,31 +298,34 @@ uint32 ReadBuild(int locale) return build; } -uint32 ReadMapDBC() +void ReadMapDBC() { printf("Read Map.dbc file... "); HANDLE dbcFile; - if (!CascOpenFile(CascStorage, "DBFilesClient\\Map.dbc", CASC_LOCALE_NONE, 0, &dbcFile)) + if (!CascOpenFile(CascStorage, "DBFilesClient\\Map.db2", CASC_LOCALE_NONE, 0, &dbcFile)) { printf("Fatal error: Cannot find Map.dbc in archive! %s\n", HumanReadableCASCError(GetLastError())); exit(1); } - DBCFile dbc(dbcFile); - if (!dbc.open()) + DB2FileLoader db2; + if (!db2.Load(dbcFile, MapMeta::Instance())) { - printf("Fatal error: Invalid Map.dbc file format!\n"); + printf("Fatal error: Invalid Map.db2 file format! %s\n", HumanReadableCASCError(GetLastError())); exit(1); } - size_t map_count = dbc.getRecordCount(); - map_ids = new map_id[map_count]; - for(uint32 x = 0; x < map_count; ++x) + map_ids.resize(db2.GetNumRows()); + std::unordered_map<uint32, uint32> idToIndex; + for (uint32 x = 0; x < db2.GetNumRows(); ++x) { - map_ids[x].id = dbc.getRecord(x).getUInt(0); + if (MapMeta::Instance()->HasIndexFieldInData()) + map_ids[x].id = db2.getRecord(x).getUInt(MapMeta::Instance()->GetIndexField(), 0); + else + map_ids[x].id = db2.getId(x); - const char* map_name = dbc.getRecord(x).getString(1); + const char* map_name = db2.getRecord(x).getString(0, 0); size_t max_map_name_length = sizeof(map_ids[x].name); if (strlen(map_name) >= max_map_name_length) { @@ -310,40 +335,62 @@ uint32 ReadMapDBC() strncpy(map_ids[x].name, map_name, max_map_name_length); map_ids[x].name[max_map_name_length - 1] = '\0'; + idToIndex[map_ids[x].id] = x; + } + + for (uint32 x = 0; x < db2.GetNumRowCopies(); ++x) + { + uint32 from = db2.GetRowCopy(x).first; + uint32 to = db2.GetRowCopy(x).second; + auto itr = idToIndex.find(from); + if (itr != idToIndex.end()) + { + map_id id; + id.id = to; + strcpy(id.name, map_ids[itr->second].name); + map_ids.push_back(id); + } } CascCloseFile(dbcFile); - printf("Done! (" SZFMTD " maps loaded)\n", map_count); - return map_count; + printf("Done! (" SZFMTD " maps loaded)\n", map_ids.size()); } void ReadLiquidTypeTableDBC() { printf("Read LiquidType.dbc file..."); HANDLE dbcFile; - if (!CascOpenFile(CascStorage, "DBFilesClient\\LiquidType.dbc", CASC_LOCALE_NONE, 0, &dbcFile)) + if (!CascOpenFile(CascStorage, "DBFilesClient\\LiquidType.db2", CASC_LOCALE_NONE, 0, &dbcFile)) { printf("Fatal error: Cannot find LiquidType.dbc in archive! %s\n", HumanReadableCASCError(GetLastError())); exit(1); } - DBCFile dbc(dbcFile); - if(!dbc.open()) + DB2FileLoader db2; + if (!db2.Load(dbcFile, LiquidTypeMeta::Instance())) { - printf("Fatal error: Invalid LiquidType.dbc file format!\n"); + printf("Fatal error: Invalid LiquidType.db2 file format!\n"); exit(1); } - size_t liqTypeCount = dbc.getRecordCount(); - size_t liqTypeMaxId = dbc.getMaxId(); - LiqType = new uint16[liqTypeMaxId + 1]; - memset(LiqType, 0xff, (liqTypeMaxId + 1) * sizeof(uint16)); + LiqType.resize(db2.GetMaxId(), 0xFFFF); + + for (uint32 x = 0; x < db2.GetNumRows(); ++x) + { + uint32 liquidTypeId; + if (LiquidTypeMeta::Instance()->HasIndexFieldInData()) + liquidTypeId = db2.getRecord(x).getUInt(LiquidTypeMeta::Instance()->GetIndexField(), 0); + else + liquidTypeId = db2.getId(x); + + LiqType[liquidTypeId] = db2.getRecord(x).getUInt8(13, 0); + } - for(uint32 x = 0; x < liqTypeCount; ++x) - LiqType[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3); + for (uint32 x = 0; x < db2.GetNumRowCopies(); ++x) + LiqType[db2.GetRowCopy(x).second] = LiqType[db2.GetRowCopy(x).first]; CascCloseFile(dbcFile); - printf("Done! (" SZFMTD " LiqTypes loaded)\n", liqTypeCount); + printf("Done! (" SZFMTD " LiqTypes loaded)\n", LiqType.size()); } // @@ -1034,7 +1081,7 @@ void ExtractMaps(uint32 build) printf("Extracting maps...\n"); - uint32 map_count = ReadMapDBC(); + ReadMapDBC(); ReadLiquidTypeTableDBC(); @@ -1045,9 +1092,9 @@ void ExtractMaps(uint32 build) std::set<std::string> wmoList; printf("Convert map files\n"); - for (uint32 z = 0; z < map_count; ++z) + for (std::size_t z = 0; z < map_ids.size(); ++z) { - printf("Extract %s (%d/%u) \n", map_ids[z].name, z+1, map_count); + printf("Extract %s (" SZFMTD "/" SZFMTD ") \n", map_ids[z].name, z+1, map_ids.size()); // Loadup map grid data storagePath = Trinity::StringFormat("World\\Maps\\%s\\%s.wdt", map_ids[z].name, map_ids[z].name); ChunkedFile wdt; @@ -1091,7 +1138,6 @@ void ExtractMaps(uint32 build) } printf("\n"); - delete[] map_ids; } bool ExtractFile(HANDLE fileInArchive, std::string filename) @@ -1138,8 +1184,7 @@ void ExtractDBFilesClient(int l) while (fileName) { std::string filename = fileName; - if (CascOpenFile(CascStorage, (filename = (filename + ".db2")).c_str(), WowLocaleToCascLocaleFlags[l], 0, &dbcFile) || - CascOpenFile(CascStorage, (filename = (filename.substr(0, filename.length() - 4) + ".dbc")).c_str(), WowLocaleToCascLocaleFlags[l], 0, &dbcFile)) + if (CascOpenFile(CascStorage, filename.c_str(), WowLocaleToCascLocaleFlags[l], 0, &dbcFile)) { filename = outputPath + filename.substr(filename.rfind('\\') + 1); diff --git a/src/tools/map_extractor/dbcfile.cpp b/src/tools/map_extractor/dbcfile.cpp deleted file mode 100644 index 2e05258cfbc..00000000000 --- a/src/tools/map_extractor/dbcfile.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/> - * - * 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/>. - */ - -#define _CRT_SECURE_NO_DEPRECATE - -#include "dbcfile.h" - -DBCFile::DBCFile(HANDLE file) : - _file(file), _recordSize(0), _recordCount(0), _fieldCount(0), - _stringSize(0), _data(NULL), _stringTable(NULL) -{ -} - -bool DBCFile::open() -{ - char header[4]; - unsigned int na, nb, es, ss; - - DWORD readBytes = 0; - CascReadFile(_file, header, 4, &readBytes); - if (readBytes != 4) // Number of records - return false; - - if (header[0] != 'W' || header[1] != 'D' || header[2] != 'B' || header[3] != 'C') - return false; - - CascReadFile(_file, &na, 4, &readBytes); - if (readBytes != 4) // Number of records - return false; - - CascReadFile(_file, &nb, 4, &readBytes); - if (readBytes != 4) // Number of fields - return false; - - CascReadFile(_file, &es, 4, &readBytes); - if (readBytes != 4) // Size of a record - return false; - - CascReadFile(_file, &ss, 4, &readBytes); - if (readBytes != 4) // String size - return false; - - _recordSize = es; - _recordCount = na; - _fieldCount = nb; - _stringSize = ss; - if (_fieldCount * 4 != _recordSize) - return false; - - _data = new unsigned char[_recordSize * _recordCount + _stringSize]; - _stringTable = _data + _recordSize*_recordCount; - - size_t data_size = _recordSize * _recordCount + _stringSize; - CascReadFile(_file, _data, data_size, &readBytes); - if (readBytes != data_size) - return false; - - return true; -} - -DBCFile::~DBCFile() -{ - delete [] _data; -} - -DBCFile::Record DBCFile::getRecord(size_t id) -{ - assert(_data); - return Record(*this, _data + id*_recordSize); -} - -size_t DBCFile::getMaxId() -{ - assert(_data); - - size_t maxId = 0; - for(size_t i = 0; i < getRecordCount(); ++i) - if (maxId < getRecord(i).getUInt(0)) - maxId = getRecord(i).getUInt(0); - - return maxId; -} - -DBCFile::Iterator DBCFile::begin() -{ - assert(_data); - return Iterator(*this, _data); -} - -DBCFile::Iterator DBCFile::end() -{ - assert(_data); - return Iterator(*this, _stringTable); -} diff --git a/src/tools/map_extractor/dbcfile.h b/src/tools/map_extractor/dbcfile.h deleted file mode 100644 index 6607c3e9c1e..00000000000 --- a/src/tools/map_extractor/dbcfile.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/> - * - * 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 DBCFILE_H -#define DBCFILE_H -#include <cassert> -#include <string> -#include "CascLib.h" - -class DBCFile -{ - public: - DBCFile(HANDLE file); - ~DBCFile(); - - // Open database. It must be openened before it can be used. - bool open(); - - // Database exceptions - class Exception - { - public: - Exception(const std::string &message) : message(message) { } - virtual ~Exception() { } - const std::string &getMessage() { return message; } - private: - std::string message; - }; - - class NotFound: public Exception - { - public: - NotFound(): Exception("Key was not found") { } - }; - - // Iteration over database - class Iterator; - class Record - { - public: - float getFloat(size_t field) const - { - assert(field < file._fieldCount); - return *reinterpret_cast<float*>(offset + field * 4); - } - - unsigned int getUInt(size_t field) const - { - assert(field < file._fieldCount); - return *reinterpret_cast<unsigned int*>(offset + field * 4); - } - - int getInt(size_t field) const - { - assert(field < file._fieldCount); - return *reinterpret_cast<int*>(offset + field * 4); - } - - char const* getString(size_t field) const - { - assert(field < file._fieldCount); - size_t stringOffset = getUInt(field); - assert(stringOffset < file._stringSize); - return reinterpret_cast<char*>(file._stringTable + stringOffset); - } - - private: - Record(DBCFile& file, unsigned char* offset): file(file), offset(offset) {} - DBCFile& file; - unsigned char* offset; - - friend class DBCFile; - friend class DBCFile::Iterator; - - Record& operator=(Record const& right); - }; - /** Iterator that iterates over records - */ - class Iterator - { - public: - Iterator(DBCFile &file, unsigned char* offset) : record(file, offset) { } - - /// Advance (prefix only) - Iterator& operator++() - { - record.offset += record.file._recordSize; - return *this; - } - - /// Return address of current instance - Record const& operator*() const { return record; } - Record const* operator->() const { return &record; } - - /// Comparison - bool operator==(Iterator const& b) const - { - return record.offset == b.record.offset; - } - - bool operator!=(Iterator const& b) const - { - return record.offset != b.record.offset; - } - - private: - Record record; - - Iterator& operator=(Iterator const& right); - }; - - // Get record by id - Record getRecord(size_t id); - /// Get begin iterator over records - Iterator begin(); - /// Get begin iterator over records - Iterator end(); - /// Trivial - size_t getRecordCount() const { return _recordCount; } - size_t getFieldCount() const { return _fieldCount; } - size_t getMaxId(); - - private: - HANDLE _file; - size_t _recordSize; - size_t _recordCount; - size_t _fieldCount; - size_t _stringSize; - unsigned char* _data; - unsigned char* _stringTable; -}; - -#endif diff --git a/src/tools/map_extractor/loadlib/DBFilesClientList.h b/src/tools/map_extractor/loadlib/DBFilesClientList.h index 080aea6a5bd..eec78cfa387 100644 --- a/src/tools/map_extractor/loadlib/DBFilesClientList.h +++ b/src/tools/map_extractor/loadlib/DBFilesClientList.h @@ -20,579 +20,575 @@ char const* DBFilesClientList[] = { - "DBFilesClient\\Achievement", - "DBFilesClient\\Achievement_Category", - "DBFilesClient\\AdventureJournal", - "DBFilesClient\\AnimKit", - "DBFilesClient\\AnimKitBoneSet", - "DBFilesClient\\AnimKitBoneSetAlias", - "DBFilesClient\\AnimKitConfig", - "DBFilesClient\\AnimKitConfigBoneSet", - "DBFilesClient\\AnimKitPriority", - "DBFilesClient\\AnimKitSegment", - "DBFilesClient\\AnimReplacement", - "DBFilesClient\\AnimReplacementSet", - "DBFilesClient\\AnimationData", - "DBFilesClient\\AreaGroup", - "DBFilesClient\\AreaGroupMember", - "DBFilesClient\\AreaPOI", - "DBFilesClient\\AreaPOIState", - "DBFilesClient\\AreaTable", - "DBFilesClient\\AreaTrigger", - "DBFilesClient\\AreaTriggerActionSet", - "DBFilesClient\\AreaTriggerBox", - "DBFilesClient\\AreaTriggerCylinder", - "DBFilesClient\\AreaTriggerSphere", - "DBFilesClient\\ArmorLocation", - "DBFilesClient\\AuctionHouse", - "DBFilesClient\\BankBagSlotPrices", - "DBFilesClient\\BannedAddOns", - "DBFilesClient\\BarberShopStyle", - "DBFilesClient\\BattlePetAbility", - "DBFilesClient\\BattlePetAbilityEffect", - "DBFilesClient\\BattlePetAbilityState", - "DBFilesClient\\BattlePetAbilityTurn", - "DBFilesClient\\BattlePetBreedQuality", - "DBFilesClient\\BattlePetBreedState", - "DBFilesClient\\BattlePetEffectProperties", - "DBFilesClient\\BattlePetNPCTeamMember", - "DBFilesClient\\BattlePetSpecies", - "DBFilesClient\\BattlePetSpeciesState", - "DBFilesClient\\BattlePetSpeciesXAbility", - "DBFilesClient\\BattlePetState", - "DBFilesClient\\BattlePetVisual", - "DBFilesClient\\BattlemasterList", - "DBFilesClient\\BroadcastText", - "DBFilesClient\\CameraMode", - "DBFilesClient\\CameraShakes", - "DBFilesClient\\CastableRaidBuffs", - "DBFilesClient\\Cfg_Categories", - "DBFilesClient\\Cfg_Configs", - "DBFilesClient\\Cfg_Regions", - "DBFilesClient\\CharBaseInfo", - "DBFilesClient\\CharBaseSection", - "DBFilesClient\\CharComponentTextureLayouts", - "DBFilesClient\\CharComponentTextureSections", - "DBFilesClient\\CharHairGeosets", - "DBFilesClient\\CharSections", - "DBFilesClient\\CharShipment", - "DBFilesClient\\CharShipmentContainer", - "DBFilesClient\\CharStartOutfit", - "DBFilesClient\\CharTitles", - "DBFilesClient\\CharacterFaceBoneSet", - "DBFilesClient\\CharacterFacialHairStyles", - "DBFilesClient\\CharacterLoadout", - "DBFilesClient\\CharacterLoadoutItem", - "DBFilesClient\\ChatChannels", - "DBFilesClient\\ChatProfanity", - "DBFilesClient\\ChrClasses", - "DBFilesClient\\ChrClassesXPowerTypes", - "DBFilesClient\\ChrRaces", - "DBFilesClient\\ChrSpecialization", - "DBFilesClient\\ChrUpgradeBucket", - "DBFilesClient\\ChrUpgradeBucketSpell", - "DBFilesClient\\ChrUpgradeTier", - "DBFilesClient\\CinematicCamera", - "DBFilesClient\\CinematicSequences", - "DBFilesClient\\CombatCondition", - "DBFilesClient\\Creature", - "DBFilesClient\\CreatureDifficulty", - "DBFilesClient\\CreatureDisplayInfo", - "DBFilesClient\\CreatureDisplayInfoExtra", - "DBFilesClient\\CreatureDisplayInfoTrn", - "DBFilesClient\\CreatureFamily", - "DBFilesClient\\CreatureImmunities", - "DBFilesClient\\CreatureModelData", - "DBFilesClient\\CreatureMovementInfo", - "DBFilesClient\\CreatureSoundData", - "DBFilesClient\\CreatureType", - "DBFilesClient\\Criteria", - "DBFilesClient\\CriteriaTree", - "DBFilesClient\\CriteriaTreeXEffect", - "DBFilesClient\\CurrencyCategory", - "DBFilesClient\\CurrencyTypes", - "DBFilesClient\\Curve", - "DBFilesClient\\CurvePoint", - "DBFilesClient\\DeathThudLookups", - "DBFilesClient\\DeclinedWord", - "DBFilesClient\\DeclinedWordCases", - "DBFilesClient\\DestructibleModelData", - "DBFilesClient\\DeviceBlacklist", - "DBFilesClient\\DeviceDefaultSettings", - "DBFilesClient\\Difficulty", - "DBFilesClient\\DriverBlacklist", - "DBFilesClient\\DungeonEncounter", - "DBFilesClient\\DungeonMap", - "DBFilesClient\\DungeonMapChunk", - "DBFilesClient\\DurabilityCosts", - "DBFilesClient\\DurabilityQuality", - "DBFilesClient\\Emotes", - "DBFilesClient\\EmotesText", - "DBFilesClient\\EmotesTextData", - "DBFilesClient\\EmotesTextSound", - "DBFilesClient\\EnvironmentalDamage", - "DBFilesClient\\Exhaustion", - "DBFilesClient\\Faction", - "DBFilesClient\\FactionGroup", - "DBFilesClient\\FactionTemplate", - "DBFilesClient\\FileData", - "DBFilesClient\\FileDataComplete", - "DBFilesClient\\FootprintTextures", - "DBFilesClient\\FootstepTerrainLookup", - "DBFilesClient\\FriendshipRepReaction", - "DBFilesClient\\FriendshipReputation", - "DBFilesClient\\GMSurveyAnswers", - "DBFilesClient\\GMSurveyCurrentSurvey", - "DBFilesClient\\GMSurveyQuestions", - "DBFilesClient\\GMSurveySurveys", - "DBFilesClient\\GMTicketCategory", - "DBFilesClient\\GameObjectArtKit", - "DBFilesClient\\GameObjectDiffAnimMap", - "DBFilesClient\\GameObjectDisplayInfo", - "DBFilesClient\\GameObjects", - "DBFilesClient\\GameTables", - "DBFilesClient\\GameTips", - "DBFilesClient\\GarrAbility", - "DBFilesClient\\GarrAbilityCategory", - "DBFilesClient\\GarrAbilityEffect", - "DBFilesClient\\GarrBuilding", - "DBFilesClient\\GarrBuildingDoodadSet", - "DBFilesClient\\GarrBuildingPlotInst", - "DBFilesClient\\GarrClassSpec", - "DBFilesClient\\GarrEncounter", - "DBFilesClient\\GarrEncounterXMechanic", - "DBFilesClient\\GarrFollItemSet", - "DBFilesClient\\GarrFollItemSetMember", - "DBFilesClient\\GarrFollower", - "DBFilesClient\\GarrFollowerLevelXP", - "DBFilesClient\\GarrFollowerQuality", - "DBFilesClient\\GarrFollowerType", - "DBFilesClient\\GarrFollowerXAbility", - "DBFilesClient\\GarrMechanic", - "DBFilesClient\\GarrMechanicType", - "DBFilesClient\\GarrMission", - "DBFilesClient\\GarrMissionReward", - "DBFilesClient\\GarrMissionTexture", - "DBFilesClient\\GarrMissionType", - "DBFilesClient\\GarrMissionXEncounter", - "DBFilesClient\\GarrMssnBonusAbility", - "DBFilesClient\\GarrPlot", - "DBFilesClient\\GarrPlotBuilding", - "DBFilesClient\\GarrPlotInstance", - "DBFilesClient\\GarrPlotUICategory", - "DBFilesClient\\GarrSiteLevel", - "DBFilesClient\\GarrSiteLevelPlotInst", - "DBFilesClient\\GarrSpecialization", - "DBFilesClient\\GarrUiAnimClassInfo", - "DBFilesClient\\GarrUiAnimRaceInfo", - "DBFilesClient\\GemProperties", - "DBFilesClient\\GlueScreenEmote", - "DBFilesClient\\GlyphExclusiveCategory", - "DBFilesClient\\GlyphProperties", - "DBFilesClient\\GlyphRequiredSpec", - "DBFilesClient\\GlyphSlot", - "DBFilesClient\\GroundEffectDoodad", - "DBFilesClient\\GroundEffectTexture", - "DBFilesClient\\GroupFinderActivity", - "DBFilesClient\\GroupFinderActivityGrp", - "DBFilesClient\\GroupFinderCategory", - "DBFilesClient\\GuildColorBackground", - "DBFilesClient\\GuildColorBorder", - "DBFilesClient\\GuildColorEmblem", - "DBFilesClient\\GuildPerkSpells", - "DBFilesClient\\Heirloom", - "DBFilesClient\\HelmetAnimScaling", - "DBFilesClient\\HelmetGeosetVisData", - "DBFilesClient\\HighlightColor", - "DBFilesClient\\HolidayDescriptions", - "DBFilesClient\\HolidayNames", - "DBFilesClient\\Holidays", - "DBFilesClient\\ImportPriceArmor", - "DBFilesClient\\ImportPriceQuality", - "DBFilesClient\\ImportPriceShield", - "DBFilesClient\\ImportPriceWeapon", - "DBFilesClient\\Item-sparse", - "DBFilesClient\\Item", - "DBFilesClient\\ItemAppearance", - "DBFilesClient\\ItemArmorQuality", - "DBFilesClient\\ItemArmorShield", - "DBFilesClient\\ItemArmorTotal", - "DBFilesClient\\ItemBagFamily", - "DBFilesClient\\ItemBonus", - "DBFilesClient\\ItemBonusTreeNode", - "DBFilesClient\\ItemClass", - "DBFilesClient\\ItemCurrencyCost", - "DBFilesClient\\ItemDamageAmmo", - "DBFilesClient\\ItemDamageOneHand", - "DBFilesClient\\ItemDamageOneHandCaster", - "DBFilesClient\\ItemDamageRanged", - "DBFilesClient\\ItemDamageThrown", - "DBFilesClient\\ItemDamageTwoHand", - "DBFilesClient\\ItemDamageTwoHandCaster", - "DBFilesClient\\ItemDamageWand", - "DBFilesClient\\ItemDisenchantLoot", - "DBFilesClient\\ItemDisplayInfo", - "DBFilesClient\\ItemEffect", - "DBFilesClient\\ItemExtendedCost", - "DBFilesClient\\ItemGroupSounds", - "DBFilesClient\\ItemLimitCategory", - "DBFilesClient\\ItemModifiedAppearance", - "DBFilesClient\\ItemNameDescription", - "DBFilesClient\\ItemPetFood", - "DBFilesClient\\ItemPriceBase", - "DBFilesClient\\ItemPurchaseGroup", - "DBFilesClient\\ItemRandomProperties", - "DBFilesClient\\ItemRandomSuffix", - "DBFilesClient\\ItemSet", - "DBFilesClient\\ItemSetSpell", - "DBFilesClient\\ItemSpec", - "DBFilesClient\\ItemSpecOverride", - "DBFilesClient\\ItemSubClass", - "DBFilesClient\\ItemSubClassMask", - "DBFilesClient\\ItemToBattlePetSpecies", - "DBFilesClient\\ItemToMountSpell", - "DBFilesClient\\ItemUpgrade", - "DBFilesClient\\ItemUpgradePath", - "DBFilesClient\\ItemVisualEffects", - "DBFilesClient\\ItemVisuals", - "DBFilesClient\\ItemXBonusTree", - "DBFilesClient\\JournalEncounter", - "DBFilesClient\\JournalEncounterCreature", - "DBFilesClient\\JournalEncounterItem", - "DBFilesClient\\JournalEncounterSection", - "DBFilesClient\\JournalEncounterXDifficulty", - "DBFilesClient\\JournalInstance", - "DBFilesClient\\JournalItemXDifficulty", - "DBFilesClient\\JournalSectionXDifficulty", - "DBFilesClient\\JournalTier", - "DBFilesClient\\JournalTierXInstance", - "DBFilesClient\\KeyChain", - "DBFilesClient\\LanguageWords", - "DBFilesClient\\Languages", - "DBFilesClient\\LfgDungeonExpansion", - "DBFilesClient\\LfgDungeonGroup", - "DBFilesClient\\LfgDungeons", - "DBFilesClient\\LfgDungeonsGroupingMap", - "DBFilesClient\\LfgRoleRequirement", - "DBFilesClient\\Light", - "DBFilesClient\\LightData", - "DBFilesClient\\LightParams", - "DBFilesClient\\LightSkybox", - "DBFilesClient\\LiquidMaterial", - "DBFilesClient\\LiquidObject", - "DBFilesClient\\LiquidType", - "DBFilesClient\\LoadingScreenTaxiSplines", - "DBFilesClient\\LoadingScreens", - "DBFilesClient\\Locale", - "DBFilesClient\\Location", - "DBFilesClient\\Lock", - "DBFilesClient\\LockType", - "DBFilesClient\\LookAtController", - "DBFilesClient\\MailTemplate", - "DBFilesClient\\ManifestInterfaceActionIcon", - "DBFilesClient\\ManifestInterfaceData", - "DBFilesClient\\ManifestInterfaceItemIcon", - "DBFilesClient\\ManifestInterfaceTOCData", - "DBFilesClient\\ManifestMP3", - "DBFilesClient\\Map", - "DBFilesClient\\MapChallengeMode", - "DBFilesClient\\MapDifficulty", - "DBFilesClient\\MarketingPromotionsXLocale", - "DBFilesClient\\Material", - "DBFilesClient\\MinorTalent", - "DBFilesClient\\ModelFileData", - "DBFilesClient\\ModelManifest", - "DBFilesClient\\ModelNameToManifest", - "DBFilesClient\\ModifierTree", - "DBFilesClient\\Mount", - "DBFilesClient\\MountCapability", - "DBFilesClient\\MountType", - "DBFilesClient\\MountTypeXCapability", - "DBFilesClient\\Movie", - "DBFilesClient\\MovieFileData", - "DBFilesClient\\MovieOverlays", - "DBFilesClient\\MovieVariation", - "DBFilesClient\\NPCSounds", - "DBFilesClient\\NameGen", - "DBFilesClient\\NamesProfanity", - "DBFilesClient\\NamesReserved", - "DBFilesClient\\NamesReservedLocale", - "DBFilesClient\\ObjectEffect", - "DBFilesClient\\ObjectEffectGroup", - "DBFilesClient\\ObjectEffectModifier", - "DBFilesClient\\ObjectEffectPackage", - "DBFilesClient\\ObjectEffectPackageElem", - "DBFilesClient\\OverrideSpellData", - "DBFilesClient\\PageTextMaterial", - "DBFilesClient\\PaperDollItemFrame", - "DBFilesClient\\ParticleColor", - "DBFilesClient\\Path", - "DBFilesClient\\PathNode", - "DBFilesClient\\PathNodeProperty", - "DBFilesClient\\PathProperty", - "DBFilesClient\\Phase", - "DBFilesClient\\PhaseShiftZoneSounds", - "DBFilesClient\\PhaseXPhaseGroup", - "DBFilesClient\\PlayerCondition", - "DBFilesClient\\PowerDisplay", - "DBFilesClient\\PvpDifficulty", - "DBFilesClient\\PvpItem", - "DBFilesClient\\QuestFactionReward", - "DBFilesClient\\QuestFeedbackEffect", - "DBFilesClient\\QuestInfo", - "DBFilesClient\\QuestLine", - "DBFilesClient\\QuestLineXQuest", - "DBFilesClient\\QuestMoneyReward", - "DBFilesClient\\QuestObjectiveCliTask", - "DBFilesClient\\QuestPOIBlob", - "DBFilesClient\\QuestPOIPoint", - "DBFilesClient\\QuestPOIPointCliTask", - "DBFilesClient\\QuestPackageItem", - "DBFilesClient\\QuestSort", - "DBFilesClient\\QuestV2", - "DBFilesClient\\QuestV2CliTask", - "DBFilesClient\\QuestXP", - "DBFilesClient\\RacialMounts", - "DBFilesClient\\RandPropPoints", - "DBFilesClient\\ResearchBranch", - "DBFilesClient\\ResearchField", - "DBFilesClient\\ResearchProject", - "DBFilesClient\\ResearchSite", - "DBFilesClient\\Resistances", - "DBFilesClient\\RulesetItemUpgrade", - "DBFilesClient\\RulesetRaidLootUpgrade", - "DBFilesClient\\RulesetRaidOverride", - "DBFilesClient\\ScalingStatDistribution", - "DBFilesClient\\Scenario", - "DBFilesClient\\ScenarioEventEntry", - "DBFilesClient\\ScenarioStep", - "DBFilesClient\\SceneScript", - "DBFilesClient\\SceneScriptPackage", - "DBFilesClient\\SceneScriptPackageMember", - "DBFilesClient\\ScreenEffect", - "DBFilesClient\\ScreenLocation", - "DBFilesClient\\ServerMessages", - "DBFilesClient\\SkillLine", - "DBFilesClient\\SkillLineAbility", - "DBFilesClient\\SkillLineAbilitySortedSpell", - "DBFilesClient\\SkillRaceClassInfo", - "DBFilesClient\\SoundAmbience", - "DBFilesClient\\SoundAmbienceFlavor", - "DBFilesClient\\SoundBus", - "DBFilesClient\\SoundBusName", - "DBFilesClient\\SoundEmitterPillPoints", - "DBFilesClient\\SoundEmitters", - "DBFilesClient\\SoundEntries", - "DBFilesClient\\SoundEntriesAdvanced", - "DBFilesClient\\SoundEntriesFallbacks", - "DBFilesClient\\SoundFilter", - "DBFilesClient\\SoundFilterElem", - "DBFilesClient\\SoundOverride", - "DBFilesClient\\SoundProviderPreferences", - "DBFilesClient\\SpamMessages", - "DBFilesClient\\SpecializationSpells", - "DBFilesClient\\Spell", - "DBFilesClient\\SpellActionBarPref", - "DBFilesClient\\SpellActivationOverlay", - "DBFilesClient\\SpellAuraOptions", - "DBFilesClient\\SpellAuraRestrictions", - "DBFilesClient\\SpellAuraRestrictionsDifficulty", - "DBFilesClient\\SpellAuraVisXChrSpec", - "DBFilesClient\\SpellAuraVisibility", - "DBFilesClient\\SpellCastTimes", - "DBFilesClient\\SpellCastingRequirements", - "DBFilesClient\\SpellCategories", - "DBFilesClient\\SpellCategory", - "DBFilesClient\\SpellChainEffects", - "DBFilesClient\\SpellClassOptions", - "DBFilesClient\\SpellCooldowns", - "DBFilesClient\\SpellDescriptionVariables", - "DBFilesClient\\SpellDispelType", - "DBFilesClient\\SpellDuration", - "DBFilesClient\\SpellEffect", - "DBFilesClient\\SpellEffectCameraShakes", - "DBFilesClient\\SpellEffectGroupSize", - "DBFilesClient\\SpellEffectScaling", - "DBFilesClient\\SpellEquippedItems", - "DBFilesClient\\SpellFlyout", - "DBFilesClient\\SpellFlyoutItem", - "DBFilesClient\\SpellFocusObject", - "DBFilesClient\\SpellIcon", - "DBFilesClient\\SpellInterrupts", - "DBFilesClient\\SpellItemEnchantment", - "DBFilesClient\\SpellItemEnchantmentCondition", - "DBFilesClient\\SpellKeyboundOverride", - "DBFilesClient\\SpellLearnSpell", - "DBFilesClient\\SpellLevels", - "DBFilesClient\\SpellMechanic", - "DBFilesClient\\SpellMisc", - "DBFilesClient\\SpellMiscDifficulty", - "DBFilesClient\\SpellMissile", - "DBFilesClient\\SpellMissileMotion", - "DBFilesClient\\SpellPower", - "DBFilesClient\\SpellPowerDifficulty", - "DBFilesClient\\SpellProcsPerMinute", - "DBFilesClient\\SpellProcsPerMinuteMod", - "DBFilesClient\\SpellRadius", - "DBFilesClient\\SpellRange", - "DBFilesClient\\SpellReagents", - "DBFilesClient\\SpellReagentsCurrency", - "DBFilesClient\\SpellRuneCost", - "DBFilesClient\\SpellScaling", - "DBFilesClient\\SpellShapeshift", - "DBFilesClient\\SpellShapeshiftForm", - "DBFilesClient\\SpellSpecialUnitEffect", - "DBFilesClient\\SpellTargetRestrictions", - "DBFilesClient\\SpellTotems", - "DBFilesClient\\SpellVisual", - "DBFilesClient\\SpellVisualColorEffect", - "DBFilesClient\\SpellVisualEffectName", - "DBFilesClient\\SpellVisualKit", - "DBFilesClient\\SpellVisualKitAreaModel", - "DBFilesClient\\SpellVisualKitModelAttach", - "DBFilesClient\\SpellVisualMissile", - "DBFilesClient\\SpellXSpellVisual", - "DBFilesClient\\Startup_Strings", - "DBFilesClient\\Stationery", - "DBFilesClient\\StringLookups", - "DBFilesClient\\SummonProperties", - "DBFilesClient\\Talent", - "DBFilesClient\\TaxiNodes", - "DBFilesClient\\TaxiPath", - "DBFilesClient\\TaxiPathNode", - "DBFilesClient\\TerrainMaterial", - "DBFilesClient\\TerrainType", - "DBFilesClient\\TerrainTypeSounds", - "DBFilesClient\\TextureFileData", - "DBFilesClient\\TotemCategory", - "DBFilesClient\\Toy", - "DBFilesClient\\TradeSkillCategory", - "DBFilesClient\\TransportAnimation", - "DBFilesClient\\TransportPhysics", - "DBFilesClient\\TransportRotation", - "DBFilesClient\\Trophy", - "DBFilesClient\\TrophyInstance", - "DBFilesClient\\TrophyType", - "DBFilesClient\\UiTextureAtlas", - "DBFilesClient\\UiTextureAtlasMember", - "DBFilesClient\\UiTextureKit", - "DBFilesClient\\UnitBlood", - "DBFilesClient\\UnitBloodLevels", - "DBFilesClient\\UnitCondition", - "DBFilesClient\\UnitPowerBar", - "DBFilesClient\\Vehicle", - "DBFilesClient\\VehicleSeat", - "DBFilesClient\\VehicleUIIndSeat", - "DBFilesClient\\VehicleUIIndicator", - "DBFilesClient\\VideoHardware", - "DBFilesClient\\Vignette", - "DBFilesClient\\VocalUISounds", - "DBFilesClient\\WMOAreaTable", - "DBFilesClient\\WbAccessControlList", - "DBFilesClient\\WbCertBlacklist", - "DBFilesClient\\WbCertWhitelist", - "DBFilesClient\\WbPermissions", - "DBFilesClient\\WeaponImpactSounds", - "DBFilesClient\\WeaponSwingSounds2", - "DBFilesClient\\WeaponTrail", - "DBFilesClient\\Weather", - "DBFilesClient\\WindSettings", - "DBFilesClient\\WorldBossLockout", - "DBFilesClient\\WorldChunkSounds", - "DBFilesClient\\WorldEffect", - "DBFilesClient\\WorldElapsedTimer", - "DBFilesClient\\WorldMapArea", - "DBFilesClient\\WorldMapContinent", - "DBFilesClient\\WorldMapOverlay", - "DBFilesClient\\WorldMapTransforms", - "DBFilesClient\\WorldSafeLocs", - "DBFilesClient\\WorldState", - "DBFilesClient\\WorldStateExpression", - "DBFilesClient\\WorldStateUI", - "DBFilesClient\\WorldStateZoneSounds", - "DBFilesClient\\World_PVP_Area", - "DBFilesClient\\ZoneIntroMusicTable", - "DBFilesClient\\ZoneLight", - "DBFilesClient\\ZoneLightPoint", - "DBFilesClient\\ZoneMusic", - "DBFilesClient\\gtArmorMitigationByLvl", - "DBFilesClient\\gtAttackPower", - "DBFilesClient\\gtAttackPowerRanged", - "DBFilesClient\\gtAvoidanceDim", - "DBFilesClient\\gtBarberShopCostBase", - "DBFilesClient\\gtBattlePetTypeDamageMod", - "DBFilesClient\\gtBattlePetXP", - "DBFilesClient\\gtChanceToDodgeBase", - "DBFilesClient\\gtChanceToMeleeCrit", - "DBFilesClient\\gtChanceToMeleeCritBase", - "DBFilesClient\\gtChanceToParryBase", - "DBFilesClient\\gtChanceToSpellCrit", - "DBFilesClient\\gtChanceToSpellCritBase", - "DBFilesClient\\gtCombatRatings", - "DBFilesClient\\gtItemLevelByLevel", - "DBFilesClient\\gtItemSocketCostPerLevel", - "DBFilesClient\\gtNPCExpectedResistPhysExp1", - "DBFilesClient\\gtNPCExpectedResistPhysExp2", - "DBFilesClient\\gtNPCExpectedResistPhysExp3", - "DBFilesClient\\gtNPCExpectedResistPhysExp4", - "DBFilesClient\\gtNPCExpectedResistPhysExp5", - "DBFilesClient\\gtNPCManaCostScaler", - "DBFilesClient\\gtNpcDamageByClass", - "DBFilesClient\\gtNpcDamageByClassExp1", - "DBFilesClient\\gtNpcDamageByClassExp2", - "DBFilesClient\\gtNpcDamageByClassExp3", - "DBFilesClient\\gtNpcDamageByClassExp4", - "DBFilesClient\\gtNpcDamageByClassExp5", - "DBFilesClient\\gtNpcGuildExperience", - "DBFilesClient\\gtNpcTotalHp", - "DBFilesClient\\gtNpcTotalHpExp1", - "DBFilesClient\\gtNpcTotalHpExp2", - "DBFilesClient\\gtNpcTotalHpExp3", - "DBFilesClient\\gtNpcTotalHpExp4", - "DBFilesClient\\gtNpcTotalHpExp5", - "DBFilesClient\\gtNpcTotalMp", - "DBFilesClient\\gtOCTBaseHPByClass", - "DBFilesClient\\gtOCTBaseMPByClass", - "DBFilesClient\\gtOCTChanceToDodge", - "DBFilesClient\\gtOCTChanceToParry", - "DBFilesClient\\gtOCTClassCombatRatingScalar", - "DBFilesClient\\gtOCTClassStats", - "DBFilesClient\\gtOCTHPFromItems", - "DBFilesClient\\gtOCTHpPerStamina", - "DBFilesClient\\gtOCTLevelExperience", - "DBFilesClient\\gtOCTMPFromItems", - "DBFilesClient\\gtOCTMPPerIntellect", - "DBFilesClient\\gtOCTNPCDpsScaler", - "DBFilesClient\\gtOCTNPCExpectedAgility", - "DBFilesClient\\gtOCTNPCExpectedIntellect", - "DBFilesClient\\gtOCTNPCExpectedResistPhysical", - "DBFilesClient\\gtOCTNPCExpectedSpirit", - "DBFilesClient\\gtOCTNPCExpectedStamina", - "DBFilesClient\\gtOCTNPCExpectedStrength", - "DBFilesClient\\gtOCTNPCHPScaler", - "DBFilesClient\\gtOCTRaceStats", - "DBFilesClient\\gtPCBaseAgility", - "DBFilesClient\\gtPCBaseIntellect", - "DBFilesClient\\gtPCBaseSpirit", - "DBFilesClient\\gtPCBaseStamina", - "DBFilesClient\\gtPCBaseStrength", - "DBFilesClient\\gtPCExpectedAgility", - "DBFilesClient\\gtPCExpectedIntellect", - "DBFilesClient\\gtPCExpectedSpirit", - "DBFilesClient\\gtPCExpectedStamina", - "DBFilesClient\\gtPCExpectedStrength", - "DBFilesClient\\gtPVPRanks", - "DBFilesClient\\gtRageGenScaler", - "DBFilesClient\\gtRegenMPPerSpt", - "DBFilesClient\\gtResilienceDR", - "DBFilesClient\\gtResistanceInnateFire", - "DBFilesClient\\gtResistanceInnateFrost", - "DBFilesClient\\gtResistanceInnateHoly", - "DBFilesClient\\gtResistanceInnateNature", - "DBFilesClient\\gtResistanceInnateShadow", - "DBFilesClient\\gtShieldBlockRegular", - "DBFilesClient\\gtSpellScaling", - "DBFilesClient\\gtXPGroupBonus", + "DBFilesClient\\Achievement.db2", + "DBFilesClient\\Achievement_Category.db2", + "DBFilesClient\\AdventureJournal.db2", + "DBFilesClient\\AdventureMapPOI.db2", + "DBFilesClient\\AnimKit.db2", + "DBFilesClient\\AnimKitBoneSet.db2", + "DBFilesClient\\AnimKitBoneSetAlias.db2", + "DBFilesClient\\AnimKitConfig.db2", + "DBFilesClient\\AnimKitConfigBoneSet.db2", + "DBFilesClient\\AnimKitPriority.db2", + "DBFilesClient\\AnimKitSegment.db2", + "DBFilesClient\\AnimReplacement.db2", + "DBFilesClient\\AnimReplacementSet.db2", + "DBFilesClient\\AnimationData.db2", + "DBFilesClient\\AreaGroupMember.db2", + "DBFilesClient\\AreaPOI.db2", + "DBFilesClient\\AreaPOIState.db2", + "DBFilesClient\\AreaTable.db2", + "DBFilesClient\\AreaTrigger.db2", + "DBFilesClient\\AreaTriggerActionSet.db2", + "DBFilesClient\\AreaTriggerBox.db2", + "DBFilesClient\\AreaTriggerCylinder.db2", + "DBFilesClient\\AreaTriggerSphere.db2", + "DBFilesClient\\ArmorLocation.db2", + "DBFilesClient\\Artifact.db2", + "DBFilesClient\\ArtifactAppearance.db2", + "DBFilesClient\\ArtifactAppearanceSet.db2", + "DBFilesClient\\ArtifactCategory.db2", + "DBFilesClient\\ArtifactPower.db2", + "DBFilesClient\\ArtifactPowerLink.db2", + "DBFilesClient\\ArtifactPowerRank.db2", + "DBFilesClient\\ArtifactQuestXP.db2", + "DBFilesClient\\ArtifactUnlock.db2", + "DBFilesClient\\AuctionHouse.db2", + "DBFilesClient\\BankBagSlotPrices.db2", + "DBFilesClient\\BannedAddOns.db2", + "DBFilesClient\\BarberShopStyle.db2", + "DBFilesClient\\BattlePetAbility.db2", + "DBFilesClient\\BattlePetAbilityEffect.db2", + "DBFilesClient\\BattlePetAbilityState.db2", + "DBFilesClient\\BattlePetAbilityTurn.db2", + "DBFilesClient\\BattlePetBreedQuality.db2", + "DBFilesClient\\BattlePetBreedState.db2", + "DBFilesClient\\BattlePetEffectProperties.db2", + "DBFilesClient\\BattlePetNPCTeamMember.db2", + "DBFilesClient\\BattlePetSpecies.db2", + "DBFilesClient\\BattlePetSpeciesState.db2", + "DBFilesClient\\BattlePetSpeciesXAbility.db2", + "DBFilesClient\\BattlePetState.db2", + "DBFilesClient\\BattlePetVisual.db2", + "DBFilesClient\\BattlemasterList.db2", + "DBFilesClient\\BoneWindModifierModel.db2", + "DBFilesClient\\BoneWindModifiers.db2", + "DBFilesClient\\Bounty.db2", + "DBFilesClient\\BountySet.db2", + "DBFilesClient\\BroadcastText.db2", + "DBFilesClient\\CameraEffect.db2", + "DBFilesClient\\CameraEffectEntry.db2", + "DBFilesClient\\CameraMode.db2", + "DBFilesClient\\CameraShakes.db2", + "DBFilesClient\\CastableRaidBuffs.db2", + "DBFilesClient\\Cfg_Categories.db2", + "DBFilesClient\\Cfg_Configs.db2", + "DBFilesClient\\Cfg_Regions.db2", + "DBFilesClient\\CharBaseInfo.db2", + "DBFilesClient\\CharBaseSection.db2", + "DBFilesClient\\CharComponentTextureLayouts.db2", + "DBFilesClient\\CharComponentTextureSections.db2", + "DBFilesClient\\CharHairGeosets.db2", + "DBFilesClient\\CharSections.db2", + "DBFilesClient\\CharShipment.db2", + "DBFilesClient\\CharShipmentContainer.db2", + "DBFilesClient\\CharStartOutfit.db2", + "DBFilesClient\\CharTitles.db2", + "DBFilesClient\\CharacterFaceBoneSet.db2", + "DBFilesClient\\CharacterFacialHairStyles.db2", + "DBFilesClient\\CharacterLoadout.db2", + "DBFilesClient\\CharacterLoadoutItem.db2", + "DBFilesClient\\ChatChannels.db2", + "DBFilesClient\\ChatProfanity.db2", + "DBFilesClient\\ChrClassRaceSex.db2", + "DBFilesClient\\ChrClassTitle.db2", + "DBFilesClient\\ChrClassUIDisplay.db2", + "DBFilesClient\\ChrClassVillain.db2", + "DBFilesClient\\ChrClasses.db2", + "DBFilesClient\\ChrClassesXPowerTypes.db2", + "DBFilesClient\\ChrRaces.db2", + "DBFilesClient\\ChrSpecialization.db2", + "DBFilesClient\\ChrUpgradeBucket.db2", + "DBFilesClient\\ChrUpgradeBucketSpell.db2", + "DBFilesClient\\ChrUpgradeTier.db2", + "DBFilesClient\\CinematicCamera.db2", + "DBFilesClient\\CinematicSequences.db2", + "DBFilesClient\\CloakDampening.db2", + "DBFilesClient\\CombatCondition.db2", + "DBFilesClient\\ComponentModelFileData.db2", + "DBFilesClient\\ComponentTextureFileData.db2", + "DBFilesClient\\ConversationLine.db2", + "DBFilesClient\\Creature.db2", + "DBFilesClient\\CreatureDifficulty.db2", + "DBFilesClient\\CreatureDispXUiCamera.db2", + "DBFilesClient\\CreatureDisplayInfo.db2", + "DBFilesClient\\CreatureDisplayInfoCond.db2", + "DBFilesClient\\CreatureDisplayInfoExtra.db2", + "DBFilesClient\\CreatureDisplayInfoTrn.db2", + "DBFilesClient\\CreatureFamily.db2", + "DBFilesClient\\CreatureImmunities.db2", + "DBFilesClient\\CreatureModelData.db2", + "DBFilesClient\\CreatureMovementInfo.db2", + "DBFilesClient\\CreatureSoundData.db2", + "DBFilesClient\\CreatureType.db2", + "DBFilesClient\\Criteria.db2", + "DBFilesClient\\CriteriaTree.db2", + "DBFilesClient\\CriteriaTreeXEffect.db2", + "DBFilesClient\\CurrencyCategory.db2", + "DBFilesClient\\CurrencyTypes.db2", + "DBFilesClient\\Curve.db2", + "DBFilesClient\\CurvePoint.db2", + "DBFilesClient\\DeathThudLookups.db2", + "DBFilesClient\\DecalProperties.db2", + "DBFilesClient\\DeclinedWord.db2", + "DBFilesClient\\DeclinedWordCases.db2", + "DBFilesClient\\DestructibleModelData.db2", + "DBFilesClient\\DeviceBlacklist.db2", + "DBFilesClient\\DeviceDefaultSettings.db2", + "DBFilesClient\\Difficulty.db2", + "DBFilesClient\\DissolveEffect.db2", + "DBFilesClient\\DriverBlacklist.db2", + "DBFilesClient\\DungeonEncounter.db2", + "DBFilesClient\\DungeonMap.db2", + "DBFilesClient\\DungeonMapChunk.db2", + "DBFilesClient\\DurabilityCosts.db2", + "DBFilesClient\\DurabilityQuality.db2", + "DBFilesClient\\EdgeGlowEffect.db2", + "DBFilesClient\\Emotes.db2", + "DBFilesClient\\EmotesText.db2", + "DBFilesClient\\EmotesTextData.db2", + "DBFilesClient\\EmotesTextSound.db2", + "DBFilesClient\\EnvironmentalDamage.db2", + "DBFilesClient\\Exhaustion.db2", + "DBFilesClient\\Faction.db2", + "DBFilesClient\\FactionGroup.db2", + "DBFilesClient\\FactionTemplate.db2", + "DBFilesClient\\FootprintTextures.db2", + "DBFilesClient\\FootstepTerrainLookup.db2", + "DBFilesClient\\FriendshipRepReaction.db2", + "DBFilesClient\\FriendshipReputation.db2", + "DBFilesClient\\FullScreenEffect.db2", + "DBFilesClient\\GMSurveyAnswers.db2", + "DBFilesClient\\GMSurveyCurrentSurvey.db2", + "DBFilesClient\\GMSurveyQuestions.db2", + "DBFilesClient\\GMSurveySurveys.db2", + "DBFilesClient\\GameObjectArtKit.db2", + "DBFilesClient\\GameObjectDiffAnimMap.db2", + "DBFilesClient\\GameObjectDisplayInfo.db2", + "DBFilesClient\\GameObjectDisplayInfoXSoundKit.db2", + "DBFilesClient\\GameObjects.db2", + "DBFilesClient\\GameTips.db2", + "DBFilesClient\\GarrAbility.db2", + "DBFilesClient\\GarrAbilityCategory.db2", + "DBFilesClient\\GarrAbilityEffect.db2", + "DBFilesClient\\GarrBuilding.db2", + "DBFilesClient\\GarrBuildingDoodadSet.db2", + "DBFilesClient\\GarrBuildingPlotInst.db2", + "DBFilesClient\\GarrClassSpec.db2", + "DBFilesClient\\GarrClassSpecPlayerCond.db2", + "DBFilesClient\\GarrEncounter.db2", + "DBFilesClient\\GarrEncounterSetXEncounter.db2", + "DBFilesClient\\GarrEncounterXMechanic.db2", + "DBFilesClient\\GarrFollItemSetMember.db2", + "DBFilesClient\\GarrFollSupportSpell.db2", + "DBFilesClient\\GarrFollower.db2", + "DBFilesClient\\GarrFollowerLevelXP.db2", + "DBFilesClient\\GarrFollowerQuality.db2", + "DBFilesClient\\GarrFollowerSetXFollower.db2", + "DBFilesClient\\GarrFollowerType.db2", + "DBFilesClient\\GarrFollowerUICreature.db2", + "DBFilesClient\\GarrFollowerXAbility.db2", + "DBFilesClient\\GarrMechanic.db2", + "DBFilesClient\\GarrMechanicSetXMechanic.db2", + "DBFilesClient\\GarrMechanicType.db2", + "DBFilesClient\\GarrMission.db2", + "DBFilesClient\\GarrMissionTexture.db2", + "DBFilesClient\\GarrMissionType.db2", + "DBFilesClient\\GarrMissionXEncounter.db2", + "DBFilesClient\\GarrMissionXFollower.db2", + "DBFilesClient\\GarrMssnBonusAbility.db2", + "DBFilesClient\\GarrPlot.db2", + "DBFilesClient\\GarrPlotBuilding.db2", + "DBFilesClient\\GarrPlotInstance.db2", + "DBFilesClient\\GarrPlotUICategory.db2", + "DBFilesClient\\GarrSiteLevel.db2", + "DBFilesClient\\GarrSiteLevelPlotInst.db2", + "DBFilesClient\\GarrSpecialization.db2", + "DBFilesClient\\GarrString.db2", + "DBFilesClient\\GarrTalent.db2", + "DBFilesClient\\GarrTalentTree.db2", + "DBFilesClient\\GarrType.db2", + "DBFilesClient\\GarrUiAnimClassInfo.db2", + "DBFilesClient\\GarrUiAnimRaceInfo.db2", + "DBFilesClient\\GemProperties.db2", + "DBFilesClient\\GlobalStrings.db2", + "DBFilesClient\\GlyphBindableSpell.db2", + "DBFilesClient\\GlyphExclusiveCategory.db2", + "DBFilesClient\\GlyphProperties.db2", + "DBFilesClient\\GlyphRequiredSpec.db2", + "DBFilesClient\\GroundEffectDoodad.db2", + "DBFilesClient\\GroundEffectTexture.db2", + "DBFilesClient\\GroupFinderActivity.db2", + "DBFilesClient\\GroupFinderActivityGrp.db2", + "DBFilesClient\\GroupFinderCategory.db2", + "DBFilesClient\\GuildColorBackground.db2", + "DBFilesClient\\GuildColorBorder.db2", + "DBFilesClient\\GuildColorEmblem.db2", + "DBFilesClient\\GuildPerkSpells.db2", + "DBFilesClient\\Heirloom.db2", + "DBFilesClient\\HelmetAnimScaling.db2", + "DBFilesClient\\HelmetGeosetVisData.db2", + "DBFilesClient\\HighlightColor.db2", + "DBFilesClient\\HolidayDescriptions.db2", + "DBFilesClient\\HolidayNames.db2", + "DBFilesClient\\Holidays.db2", + "DBFilesClient\\ImportPriceArmor.db2", + "DBFilesClient\\ImportPriceQuality.db2", + "DBFilesClient\\ImportPriceShield.db2", + "DBFilesClient\\ImportPriceWeapon.db2", + "DBFilesClient\\InvasionClientData.db2", + "DBFilesClient\\Item.db2", + "DBFilesClient\\ItemAppearance.db2", + "DBFilesClient\\ItemAppearanceXUiCamera.db2", + "DBFilesClient\\ItemArmorQuality.db2", + "DBFilesClient\\ItemArmorShield.db2", + "DBFilesClient\\ItemArmorTotal.db2", + "DBFilesClient\\ItemBagFamily.db2", + "DBFilesClient\\ItemBonus.db2", + "DBFilesClient\\ItemBonusListLevelDelta.db2", + "DBFilesClient\\ItemBonusTreeNode.db2", + "DBFilesClient\\ItemChildEquipment.db2", + "DBFilesClient\\ItemClass.db2", + "DBFilesClient\\ItemContextPickerEntry.db2", + "DBFilesClient\\ItemCurrencyCost.db2", + "DBFilesClient\\ItemDamageAmmo.db2", + "DBFilesClient\\ItemDamageOneHand.db2", + "DBFilesClient\\ItemDamageOneHandCaster.db2", + "DBFilesClient\\ItemDamageTwoHand.db2", + "DBFilesClient\\ItemDamageTwoHandCaster.db2", + "DBFilesClient\\ItemDisenchantLoot.db2", + "DBFilesClient\\ItemDisplayInfo.db2", + "DBFilesClient\\ItemDisplayInfoMaterialRes.db2", + "DBFilesClient\\ItemDisplayXUiCamera.db2", + "DBFilesClient\\ItemEffect.db2", + "DBFilesClient\\ItemExtendedCost.db2", + "DBFilesClient\\ItemGroupSounds.db2", + "DBFilesClient\\ItemLimitCategory.db2", + "DBFilesClient\\ItemLimitCategoryCondition.db2", + "DBFilesClient\\ItemModifiedAppearance.db2", + "DBFilesClient\\ItemModifiedAppearanceExtra.db2", + "DBFilesClient\\ItemNameDescription.db2", + "DBFilesClient\\ItemPetFood.db2", + "DBFilesClient\\ItemPriceBase.db2", + "DBFilesClient\\ItemRandomProperties.db2", + "DBFilesClient\\ItemRandomSuffix.db2", + "DBFilesClient\\ItemRangedDisplayInfo.db2", + "DBFilesClient\\ItemSearchName.db2", + "DBFilesClient\\ItemSet.db2", + "DBFilesClient\\ItemSetSpell.db2", + "DBFilesClient\\Item-sparse.db2", + "DBFilesClient\\ItemSpec.db2", + "DBFilesClient\\ItemSpecOverride.db2", + "DBFilesClient\\ItemSubClass.db2", + "DBFilesClient\\ItemSubClassMask.db2", + "DBFilesClient\\ItemUpgrade.db2", + "DBFilesClient\\ItemVisualEffects.db2", + "DBFilesClient\\ItemVisuals.db2", + "DBFilesClient\\ItemXBonusTree.db2", + "DBFilesClient\\JournalEncounter.db2", + "DBFilesClient\\JournalEncounterCreature.db2", + "DBFilesClient\\JournalEncounterItem.db2", + "DBFilesClient\\JournalEncounterSection.db2", + "DBFilesClient\\JournalEncounterXDifficulty.db2", + "DBFilesClient\\JournalInstance.db2", + "DBFilesClient\\JournalItemXDifficulty.db2", + "DBFilesClient\\JournalSectionXDifficulty.db2", + "DBFilesClient\\JournalTier.db2", + "DBFilesClient\\JournalTierXInstance.db2", + "DBFilesClient\\KeyChain.db2", + "DBFilesClient\\KeystoneAffix.db2", + "DBFilesClient\\LanguageWords.db2", + "DBFilesClient\\Languages.db2", + "DBFilesClient\\LfgDungeonExpansion.db2", + "DBFilesClient\\LfgDungeonGroup.db2", + "DBFilesClient\\LfgDungeons.db2", + "DBFilesClient\\LfgDungeonsGroupingMap.db2", + "DBFilesClient\\LfgRoleRequirement.db2", + "DBFilesClient\\Light.db2", + "DBFilesClient\\LightData.db2", + "DBFilesClient\\LightParams.db2", + "DBFilesClient\\LightSkybox.db2", + "DBFilesClient\\LiquidMaterial.db2", + "DBFilesClient\\LiquidObject.db2", + "DBFilesClient\\LiquidType.db2", + "DBFilesClient\\LoadingScreenTaxiSplines.db2", + "DBFilesClient\\LoadingScreens.db2", + "DBFilesClient\\Locale.db2", + "DBFilesClient\\Location.db2", + "DBFilesClient\\Lock.db2", + "DBFilesClient\\LockType.db2", + "DBFilesClient\\LookAtController.db2", + "DBFilesClient\\MailTemplate.db2", + "DBFilesClient\\ManifestInterfaceActionIcon.db2", + "DBFilesClient\\ManifestInterfaceData.db2", + "DBFilesClient\\ManifestInterfaceItemIcon.db2", + "DBFilesClient\\ManifestInterfaceTOCData.db2", + "DBFilesClient\\ManifestMP3.db2", + "DBFilesClient\\Map.db2", + "DBFilesClient\\MapChallengeMode.db2", + "DBFilesClient\\MapDifficulty.db2", + "DBFilesClient\\MapDifficultyXCondition.db2", + "DBFilesClient\\MarketingPromotionsXLocale.db2", + "DBFilesClient\\Material.db2", + "DBFilesClient\\MinorTalent.db2", + "DBFilesClient\\ModelAnimCloakDampening.db2", + "DBFilesClient\\ModelFileData.db2", + "DBFilesClient\\ModelRibbonQuality.db2", + "DBFilesClient\\ModifierTree.db2", + "DBFilesClient\\Mount.db2", + "DBFilesClient\\MountCapability.db2", + "DBFilesClient\\MountTypeXCapability.db2", + "DBFilesClient\\Movie.db2", + "DBFilesClient\\MovieFileData.db2", + "DBFilesClient\\MovieVariation.db2", + "DBFilesClient\\NPCSounds.db2", + "DBFilesClient\\NameGen.db2", + "DBFilesClient\\NamesProfanity.db2", + "DBFilesClient\\NamesReserved.db2", + "DBFilesClient\\NamesReservedLocale.db2", + "DBFilesClient\\NpcModelItemSlotDisplayInfo.db2", + "DBFilesClient\\ObjectEffect.db2", + "DBFilesClient\\ObjectEffectGroup.db2", + "DBFilesClient\\ObjectEffectModifier.db2", + "DBFilesClient\\ObjectEffectPackage.db2", + "DBFilesClient\\ObjectEffectPackageElem.db2", + "DBFilesClient\\OutlineEffect.db2", + "DBFilesClient\\OverrideSpellData.db2", + "DBFilesClient\\PageTextMaterial.db2", + "DBFilesClient\\PaperDollItemFrame.db2", + "DBFilesClient\\ParticleColor.db2", + "DBFilesClient\\Path.db2", + "DBFilesClient\\PathNode.db2", + "DBFilesClient\\PathNodeProperty.db2", + "DBFilesClient\\PathProperty.db2", + "DBFilesClient\\Phase.db2", + "DBFilesClient\\PhaseShiftZoneSounds.db2", + "DBFilesClient\\PhaseXPhaseGroup.db2", + "DBFilesClient\\PlayerCondition.db2", + "DBFilesClient\\Positioner.db2", + "DBFilesClient\\PositionerState.db2", + "DBFilesClient\\PositionerStateEntry.db2", + "DBFilesClient\\PowerDisplay.db2", + "DBFilesClient\\PowerType.db2", + "DBFilesClient\\PrestigeLevelInfo.db2", + "DBFilesClient\\PvpBracketTypes.db2", + "DBFilesClient\\PvpDifficulty.db2", + "DBFilesClient\\PvpItem.db2", + "DBFilesClient\\PvpReward.db2", + "DBFilesClient\\PvpTalent.db2", + "DBFilesClient\\PvpTalentUnlock.db2", + "DBFilesClient\\QuestFactionReward.db2", + "DBFilesClient\\QuestFeedbackEffect.db2", + "DBFilesClient\\QuestInfo.db2", + "DBFilesClient\\QuestLine.db2", + "DBFilesClient\\QuestLineXQuest.db2", + "DBFilesClient\\QuestMoneyReward.db2", + "DBFilesClient\\QuestObjective.db2", + "DBFilesClient\\QuestPOIBlob.db2", + "DBFilesClient\\QuestPOIPoint.db2", + "DBFilesClient\\QuestPOIPointCliTask.db2", + "DBFilesClient\\QuestPackageItem.db2", + "DBFilesClient\\QuestSort.db2", + "DBFilesClient\\QuestV2.db2", + "DBFilesClient\\QuestV2CliTask.db2", + "DBFilesClient\\QuestXP.db2", + "DBFilesClient\\RacialMounts.db2", + "DBFilesClient\\RandPropPoints.db2", + "DBFilesClient\\ResearchBranch.db2", + "DBFilesClient\\ResearchField.db2", + "DBFilesClient\\ResearchProject.db2", + "DBFilesClient\\ResearchSite.db2", + "DBFilesClient\\Resistances.db2", + "DBFilesClient\\RewardPack.db2", + "DBFilesClient\\RewardPackXCurrencyType.db2", + "DBFilesClient\\RewardPackXItem.db2", + "DBFilesClient\\RibbonQuality.db2", + "DBFilesClient\\RulesetItemUpgrade.db2", + "DBFilesClient\\ScalingStatDistribution.db2", + "DBFilesClient\\Scenario.db2", + "DBFilesClient\\ScenarioEventEntry.db2", + "DBFilesClient\\ScenarioStep.db2", + "DBFilesClient\\SceneScript.db2", + "DBFilesClient\\SceneScriptPackage.db2", + "DBFilesClient\\SceneScriptPackageMember.db2", + "DBFilesClient\\ScheduledInterval.db2", + "DBFilesClient\\ScheduledWorldState.db2", + "DBFilesClient\\ScheduledWorldStateGroup.db2", + "DBFilesClient\\ScheduledWorldStateXUniqCat.db2", + "DBFilesClient\\ScreenEffect.db2", + "DBFilesClient\\ScreenLocation.db2", + "DBFilesClient\\SeamlessSite.db2", + "DBFilesClient\\ServerMessages.db2", + "DBFilesClient\\ShadowyEffect.db2", + "DBFilesClient\\SkillLine.db2", + "DBFilesClient\\SkillLineAbility.db2", + "DBFilesClient\\SkillRaceClassInfo.db2", + "DBFilesClient\\SoundAmbience.db2", + "DBFilesClient\\SoundAmbienceFlavor.db2", + "DBFilesClient\\SoundBus.db2", + "DBFilesClient\\SoundEmitterPillPoints.db2", + "DBFilesClient\\SoundEmitters.db2", + "DBFilesClient\\SoundFilter.db2", + "DBFilesClient\\SoundFilterElem.db2", + "DBFilesClient\\SoundKit.db2", + "DBFilesClient\\SoundKitAdvanced.db2", + "DBFilesClient\\SoundKitChild.db2", + "DBFilesClient\\SoundKitEntry.db2", + "DBFilesClient\\SoundKitFallback.db2", + "DBFilesClient\\SoundOverride.db2", + "DBFilesClient\\SoundProviderPreferences.db2", + "DBFilesClient\\SourceInfo.db2", + "DBFilesClient\\SpamMessages.db2", + "DBFilesClient\\SpecializationSpells.db2", + "DBFilesClient\\Spell.db2", + "DBFilesClient\\SpellActionBarPref.db2", + "DBFilesClient\\SpellActivationOverlay.db2", + "DBFilesClient\\SpellAuraOptions.db2", + "DBFilesClient\\SpellAuraRestrictions.db2", + "DBFilesClient\\SpellAuraVisXChrSpec.db2", + "DBFilesClient\\SpellAuraVisibility.db2", + "DBFilesClient\\SpellCastTimes.db2", + "DBFilesClient\\SpellCastingRequirements.db2", + "DBFilesClient\\SpellCategories.db2", + "DBFilesClient\\SpellCategory.db2", + "DBFilesClient\\SpellChainEffects.db2", + "DBFilesClient\\SpellClassOptions.db2", + "DBFilesClient\\SpellCooldowns.db2", + "DBFilesClient\\SpellDescriptionVariables.db2", + "DBFilesClient\\SpellDispelType.db2", + "DBFilesClient\\SpellDuration.db2", + "DBFilesClient\\SpellEffect.db2", + "DBFilesClient\\SpellEffectCameraShakes.db2", + "DBFilesClient\\SpellEffectEmission.db2", + "DBFilesClient\\SpellEffectGroupSize.db2", + "DBFilesClient\\SpellEffectScaling.db2", + "DBFilesClient\\SpellEquippedItems.db2", + "DBFilesClient\\SpellFlyout.db2", + "DBFilesClient\\SpellFlyoutItem.db2", + "DBFilesClient\\SpellFocusObject.db2", + "DBFilesClient\\SpellIcon.db2", + "DBFilesClient\\SpellInterrupts.db2", + "DBFilesClient\\SpellItemEnchantment.db2", + "DBFilesClient\\SpellItemEnchantmentCondition.db2", + "DBFilesClient\\SpellKeyboundOverride.db2", + "DBFilesClient\\SpellLabel.db2", + "DBFilesClient\\SpellLearnSpell.db2", + "DBFilesClient\\SpellLevels.db2", + "DBFilesClient\\SpellMechanic.db2", + "DBFilesClient\\SpellMisc.db2", + "DBFilesClient\\SpellMiscDifficulty.db2", + "DBFilesClient\\SpellMissile.db2", + "DBFilesClient\\SpellMissileMotion.db2", + "DBFilesClient\\SpellPower.db2", + "DBFilesClient\\SpellPowerDifficulty.db2", + "DBFilesClient\\SpellProceduralEffect.db2", + "DBFilesClient\\SpellProcsPerMinute.db2", + "DBFilesClient\\SpellProcsPerMinuteMod.db2", + "DBFilesClient\\SpellRadius.db2", + "DBFilesClient\\SpellRange.db2", + "DBFilesClient\\SpellReagents.db2", + "DBFilesClient\\SpellReagentsCurrency.db2", + "DBFilesClient\\SpellScaling.db2", + "DBFilesClient\\SpellShapeshift.db2", + "DBFilesClient\\SpellShapeshiftForm.db2", + "DBFilesClient\\SpellSpecialUnitEffect.db2", + "DBFilesClient\\SpellTargetRestrictions.db2", + "DBFilesClient\\SpellTotems.db2", + "DBFilesClient\\SpellVisual.db2", + "DBFilesClient\\SpellVisualAnim.db2", + "DBFilesClient\\SpellVisualColorEffect.db2", + "DBFilesClient\\SpellVisualEffectName.db2", + "DBFilesClient\\SpellVisualKit.db2", + "DBFilesClient\\SpellVisualKitAreaModel.db2", + "DBFilesClient\\SpellVisualKitEffect.db2", + "DBFilesClient\\SpellVisualKitModelAttach.db2", + "DBFilesClient\\SpellVisualMissile.db2", + "DBFilesClient\\SpellXSpellVisual.db2", + "DBFilesClient\\Startup_Strings.db2", + "DBFilesClient\\Stationery.db2", + "DBFilesClient\\StringLookups.db2", + "DBFilesClient\\SummonProperties.db2", + "DBFilesClient\\TactKey.db2", + "DBFilesClient\\TactKeyLookup.db2", + "DBFilesClient\\Talent.db2", + "DBFilesClient\\TaxiNodes.db2", + "DBFilesClient\\TaxiPath.db2", + "DBFilesClient\\TaxiPathNode.db2", + "DBFilesClient\\TerrainMaterial.db2", + "DBFilesClient\\TerrainType.db2", + "DBFilesClient\\TerrainTypeSounds.db2", + "DBFilesClient\\TextureBlendSet.db2", + "DBFilesClient\\TextureFileData.db2", + "DBFilesClient\\TotemCategory.db2", + "DBFilesClient\\Toy.db2", + "DBFilesClient\\TradeSkillCategory.db2", + "DBFilesClient\\TradeSkillItem.db2", + "DBFilesClient\\TransformMatrix.db2", + "DBFilesClient\\TransmogSet.db2", + "DBFilesClient\\TransmogSetItem.db2", + "DBFilesClient\\TransportAnimation.db2", + "DBFilesClient\\TransportPhysics.db2", + "DBFilesClient\\TransportRotation.db2", + "DBFilesClient\\Trophy.db2", + "DBFilesClient\\UiCamFbackTransmogChrRace.db2", + "DBFilesClient\\UiCamFbackTransmogWeapon.db2", + "DBFilesClient\\UiCamera.db2", + "DBFilesClient\\UiCameraType.db2", + "DBFilesClient\\UiMapPOI.db2", + "DBFilesClient\\UiTextureAtlas.db2", + "DBFilesClient\\UiTextureAtlasMember.db2", + "DBFilesClient\\UiTextureKit.db2", + "DBFilesClient\\UnitBlood.db2", + "DBFilesClient\\UnitBloodLevels.db2", + "DBFilesClient\\UnitCondition.db2", + "DBFilesClient\\UnitPowerBar.db2", + "DBFilesClient\\Vehicle.db2", + "DBFilesClient\\VehicleSeat.db2", + "DBFilesClient\\VehicleUIIndSeat.db2", + "DBFilesClient\\VehicleUIIndicator.db2", + "DBFilesClient\\VideoHardware.db2", + "DBFilesClient\\Vignette.db2", + "DBFilesClient\\VocalUISounds.db2", + "DBFilesClient\\WMOAreaTable.db2", + "DBFilesClient\\WbAccessControlList.db2", + "DBFilesClient\\WbCertBlacklist.db2", + "DBFilesClient\\WbCertWhitelist.db2", + "DBFilesClient\\WbPermissions.db2", + "DBFilesClient\\WeaponImpactSounds.db2", + "DBFilesClient\\WeaponSwingSounds2.db2", + "DBFilesClient\\WeaponTrail.db2", + "DBFilesClient\\WeaponTrailModelDef.db2", + "DBFilesClient\\WeaponTrailParam.db2", + "DBFilesClient\\Weather.db2", + "DBFilesClient\\WindSettings.db2", + "DBFilesClient\\WmoMinimapTexture.db2", + "DBFilesClient\\WorldBossLockout.db2", + "DBFilesClient\\WorldChunkSounds.db2", + "DBFilesClient\\WorldEffect.db2", + "DBFilesClient\\WorldElapsedTimer.db2", + "DBFilesClient\\WorldMapArea.db2", + "DBFilesClient\\WorldMapContinent.db2", + "DBFilesClient\\WorldMapOverlay.db2", + "DBFilesClient\\WorldMapTransforms.db2", + "DBFilesClient\\WorldSafeLocs.db2", + "DBFilesClient\\WorldStateExpression.db2", + "DBFilesClient\\WorldStateUI.db2", + "DBFilesClient\\WorldStateZoneSounds.db2", + "DBFilesClient\\World_PVP_Area.db2", + "DBFilesClient\\ZoneIntroMusicTable.db2", + "DBFilesClient\\ZoneLight.db2", + "DBFilesClient\\ZoneLightPoint.db2", + "DBFilesClient\\ZoneMusic.db2", nullptr // terminator }; diff --git a/src/tools/vmap4_extractor/DB2.cpp b/src/tools/vmap4_extractor/DB2.cpp new file mode 100644 index 00000000000..52d4a1544af --- /dev/null +++ b/src/tools/vmap4_extractor/DB2.cpp @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * 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 "DB2.h" + +DB2FileLoader::DB2FileLoader() +{ + meta = nullptr; + + recordSize = 0; + recordCount = 0; + fieldCount = 0; + stringSize = 0; + tableHash = 0; + layoutHash = 0; + minIndex = 0; + maxIndex = 0; + localeMask = 0; + copyIdSize = 0; + + data = nullptr; + stringTable = nullptr; + idTable = nullptr; + idTableSize = 0; + copyTable = nullptr; + fields = nullptr; +} + +bool DB2FileLoader::Load(HANDLE db2Handle, DB2Meta const* meta) +{ + if (data) + { + delete[] data; + data = nullptr; + } + + DWORD bytesRead = 0; + this->meta = meta; + std::uint32_t header; + CascReadFile(db2Handle, &header, sizeof(header), &bytesRead); + if (bytesRead != sizeof(header)) // Signature + return false; + + EndianConvert(header); + + if (header != 0x35424457) + return false; //'WDB5' + + CascReadFile(db2Handle, &recordCount, sizeof(recordCount), &bytesRead); + if (bytesRead != sizeof(recordCount)) // Number of records + return false; + + EndianConvert(recordCount); + + CascReadFile(db2Handle, &fieldCount, sizeof(fieldCount), &bytesRead); + if (bytesRead != sizeof(fieldCount)) // Number of fields + return false; + + EndianConvert(fieldCount); + + CascReadFile(db2Handle, &recordSize, sizeof(recordSize), &bytesRead); + if (bytesRead != sizeof(recordSize)) // Size of a record + return false; + + EndianConvert(recordSize); + + CascReadFile(db2Handle, &stringSize, sizeof(stringSize), &bytesRead); + if (bytesRead != sizeof(stringSize)) // String size + return false; + + EndianConvert(stringSize); + + CascReadFile(db2Handle, &tableHash, sizeof(tableHash), &bytesRead); + if (bytesRead != sizeof(tableHash)) // Table hash + return false; + + EndianConvert(tableHash); + + CascReadFile(db2Handle, &layoutHash, sizeof(layoutHash), &bytesRead); + if (bytesRead != sizeof(layoutHash)) // Layout hash + return false; + + if (layoutHash != meta->LayoutHash) + return false; + + EndianConvert(layoutHash); + + CascReadFile(db2Handle, &minIndex, sizeof(minIndex), &bytesRead); + if (bytesRead != sizeof(minIndex)) // MinIndex WDB2 + return false; + + EndianConvert(minIndex); + + CascReadFile(db2Handle, &maxIndex, sizeof(maxIndex), &bytesRead); + if (bytesRead != sizeof(maxIndex)) // MaxIndex WDB2 + return false; + + EndianConvert(maxIndex); + + CascReadFile(db2Handle, &localeMask, sizeof(localeMask), &bytesRead); + if (bytesRead != sizeof(localeMask)) // Locales + return false; + + EndianConvert(localeMask); + + CascReadFile(db2Handle, ©IdSize, sizeof(copyIdSize), &bytesRead); + if (bytesRead != sizeof(copyIdSize)) + return false; + + EndianConvert(copyIdSize); + + CascReadFile(db2Handle, &metaFlags, sizeof(metaFlags), &bytesRead); + if (bytesRead != sizeof(metaFlags)) + return false; + + EndianConvert(metaFlags); + + ASSERT((metaFlags & 0x1) == 0); + ASSERT((meta->IndexField == -1) || (meta->IndexField == (metaFlags >> 16))); + + fields = new FieldEntry[fieldCount]; + CascReadFile(db2Handle, fields, fieldCount * sizeof(FieldEntry), &bytesRead); + if (bytesRead != fieldCount * sizeof(FieldEntry)) + return false; + + if (!meta->HasIndexFieldInData()) + idTableSize = recordCount * sizeof(std::uint32_t); + + data = new unsigned char[recordSize * recordCount + stringSize]; + stringTable = data + recordSize * recordCount; + + CascReadFile(db2Handle, data, recordSize * recordCount + stringSize, &bytesRead); + if (bytesRead != recordSize * recordCount + stringSize) + return false; + + if (idTableSize) + { + idTable = new unsigned char[idTableSize]; + CascReadFile(db2Handle, idTable, idTableSize, &bytesRead); + if (bytesRead != idTableSize) + return false; + } + + if (copyIdSize) + { + copyTable = new unsigned char[copyIdSize]; + CascReadFile(db2Handle, copyTable, copyIdSize, &bytesRead); + if (bytesRead != copyIdSize) + return false; + } + + return true; +} + +DB2FileLoader::~DB2FileLoader() +{ + delete[] data; + delete[] idTable; + delete[] copyTable; + delete[] fields; +} + +DB2FileLoader::Record DB2FileLoader::getRecord(size_t id) +{ + assert(data); + return Record(*this, data + id * recordSize); +} + +std::pair<std::uint32_t, std::uint32_t> DB2FileLoader::GetRowCopy(std::uint32_t i) const +{ + std::uint32_t* copyIds = (std::uint32_t*)copyTable; + std::uint32_t to = copyIds[i]; + std::uint32_t from = copyIds[i + 1]; + return{ from, to }; +} + +std::uint32_t DB2FileLoader::GetMaxId() const +{ + std::uint32_t j = maxIndex; + for (std::uint32_t i = 0; i < GetNumRowCopies(); ++i) + if (j < GetRowCopy(i).second) + j = GetRowCopy(i).second; + + return j; +} diff --git a/src/tools/vmap4_extractor/DB2.h b/src/tools/vmap4_extractor/DB2.h new file mode 100644 index 00000000000..0cb6c111941 --- /dev/null +++ b/src/tools/vmap4_extractor/DB2.h @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * 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 MapExtractor_DB2_h__ +#define MapExtractor_DB2_h__ + +#include "DB2Meta.h" +#ifdef PLATFORM_WINDOWS +#undef PLATFORM_WINDOWS +#endif +#include "CascLib.h" +#include "Utilities/ByteConverter.h" +#include "Errors.h" + +class DB2FileLoader +{ + public: + DB2FileLoader(); + ~DB2FileLoader(); + + bool Load(HANDLE db2Handle, DB2Meta const* meta); + + class Record + { + public: + float getFloat(std::uint32_t field, std::uint32_t arrayIndex) const + { + ASSERT(field < file.fieldCount); + float val = *reinterpret_cast<float*>(offset + GetOffset(field) + arrayIndex * sizeof(float)); + EndianConvert(val); + return val; + } + + std::uint32_t getUInt(std::uint32_t field, std::uint32_t arrayIndex) const + { + ASSERT(field < file.fieldCount); + return GetVarInt(field, GetByteSize(field), arrayIndex); + } + + std::uint8_t getUInt8(std::uint32_t field, std::uint32_t arrayIndex) const + { + ASSERT(field < file.fieldCount); + ASSERT(GetByteSize(field) == 1); + return *reinterpret_cast<std::uint8_t*>(offset + GetOffset(field) + arrayIndex * sizeof(std::uint8_t)); + } + + std::uint16_t getUInt16(std::uint32_t field, std::uint32_t arrayIndex) const + { + ASSERT(field < file.fieldCount); + ASSERT(GetByteSize(field) == 2); + std::uint16_t val = *reinterpret_cast<std::uint16_t*>(offset + GetOffset(field) + arrayIndex * sizeof(std::uint16_t)); + EndianConvert(val); + return val; + } + + char const* getString(std::uint32_t field, std::uint32_t arrayIndex) const + { + ASSERT(field < file.fieldCount); + std::uint32_t stringOffset = *reinterpret_cast<std::uint32_t*>(offset + GetOffset(field) + arrayIndex * sizeof(std::uint32_t)); + EndianConvert(stringOffset); + ASSERT(stringOffset < file.stringSize); + return reinterpret_cast<char*>(file.stringTable + stringOffset); + } + + private: + std::uint16_t GetOffset(std::uint32_t field) const + { + ASSERT(field < file.fieldCount); + return file.fields[field].Offset; + } + + std::uint16_t GetByteSize(std::uint32_t field) const + { + ASSERT(field < file.fieldCount); + return 4 - file.fields[field].UnusedBits / 8; + } + + std::uint32_t GetVarInt(std::uint32_t field, std::uint16_t size, std::uint32_t arrayIndex) const + { + ASSERT(field < file.fieldCount); + switch (size) + { + case 1: + { + return *reinterpret_cast<std::uint8_t*>(offset + GetOffset(field) + arrayIndex * sizeof(std::uint8_t)); + } + case 2: + { + std::uint16_t val = *reinterpret_cast<std::uint16_t*>(offset + GetOffset(field) + arrayIndex * sizeof(std::uint16_t)); + EndianConvert(val); + return val; + } + case 3: + { +#pragma pack(push, 1) + struct dbcint24 { std::uint8_t v[3]; }; +#pragma pack(pop) + dbcint24 val = *reinterpret_cast<dbcint24*>(offset + GetOffset(field) + arrayIndex * sizeof(dbcint24)); + EndianConvert(val); + return std::uint32_t(val.v[0]) | (std::uint32_t(val.v[1]) << 8) | (std::uint32_t(val.v[2]) << 16); + } + case 4: + { + std::uint32_t val = *reinterpret_cast<std::uint32_t*>(offset + GetOffset(field) + arrayIndex * sizeof(std::uint32_t)); + EndianConvert(val); + return val; + } + default: + break; + } + + ASSERT(false, "GetByteSize(field) < 4"); + return 0; + } + + Record(DB2FileLoader &file_, unsigned char *offset_): offset(offset_), file(file_) {} + unsigned char *offset; + DB2FileLoader &file; + + friend class DB2FileLoader; + }; + + // Get record by id + Record getRecord(size_t id); + std::uint32_t getId(size_t row) { return ((std::uint32_t*)idTable)[row]; } + std::pair<std::uint32_t, std::uint32_t> GetRowCopy(std::uint32_t i) const; + + std::uint32_t GetNumRows() const { return recordCount; } + std::uint32_t GetNumRowCopies() const { return copyIdSize / 8; } + std::uint32_t GetMaxId() const; + +private: +#pragma pack(push, 1) + struct FieldEntry + { + std::uint16_t UnusedBits; + std::uint16_t Offset; + }; +#pragma pack(pop) + + DB2Meta const* meta; + + // WDB2 / WCH2 fields + std::uint32_t recordSize; + std::uint32_t recordCount; + std::uint32_t fieldCount; + std::uint32_t stringSize; + std::uint32_t tableHash; + std::uint32_t layoutHash; + std::uint32_t minIndex; + std::uint32_t maxIndex; + std::uint32_t localeMask; + std::uint32_t copyIdSize; + std::uint32_t metaFlags; + + unsigned char* data; + unsigned char* stringTable; + unsigned char* idTable; + std::uint32_t idTableSize; + unsigned char* copyTable; + FieldEntry* fields; +}; + +#endif // MapExtractor_DB2_h__ diff --git a/src/tools/vmap4_extractor/dbcfile.cpp b/src/tools/vmap4_extractor/dbcfile.cpp deleted file mode 100644 index 920b08ed0e9..00000000000 --- a/src/tools/vmap4_extractor/dbcfile.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/> - * - * 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/>. - */ - -#define _CRT_SECURE_NO_DEPRECATE - -#include "dbcfile.h" - -DBCFile::DBCFile(HANDLE mpq, const char* filename) : - _mpq(mpq), _filename(filename), _file(NULL), _recordSize(0), _recordCount(0), - _fieldCount(0), _stringSize(0), _data(NULL), _stringTable(NULL) -{ -} - -bool DBCFile::open() -{ - if (!CascOpenFile(_mpq, _filename, CASC_LOCALE_NONE, 0, &_file)) - return false; - - char header[4]; - unsigned int na, nb, es, ss; - - DWORD readBytes = 0; - CascReadFile(_file, header, 4, &readBytes); - if (readBytes != 4) // Number of records - return false; - - if (header[0] != 'W' || header[1] != 'D' || header[2] != 'B' || header[3] != 'C') - return false; - - readBytes = 0; - CascReadFile(_file, &na, 4, &readBytes); - if (readBytes != 4) // Number of records - return false; - - readBytes = 0; - CascReadFile(_file, &nb, 4, &readBytes); - if (readBytes != 4) // Number of fields - return false; - - readBytes = 0; - CascReadFile(_file, &es, 4, &readBytes); - if (readBytes != 4) // Size of a record - return false; - - readBytes = 0; - CascReadFile(_file, &ss, 4, &readBytes); - if (readBytes != 4) // String size - return false; - - _recordSize = es; - _recordCount = na; - _fieldCount = nb; - _stringSize = ss; - if (_fieldCount * 4 != _recordSize) - return false; - - _data = new unsigned char[_recordSize * _recordCount + _stringSize]; - _stringTable = _data + _recordSize*_recordCount; - - size_t data_size = _recordSize * _recordCount + _stringSize; - readBytes = 0; - CascReadFile(_file, _data, data_size, &readBytes); - if (readBytes != data_size) - return false; - - return true; -} - -DBCFile::~DBCFile() -{ - delete [] _data; - if (_file != NULL) - CascCloseFile(_file); -} - -DBCFile::Record DBCFile::getRecord(size_t id) -{ - assert(_data); - return Record(*this, _data + id*_recordSize); -} - -size_t DBCFile::getMaxId() -{ - assert(_data); - - size_t maxId = 0; - for(size_t i = 0; i < getRecordCount(); ++i) - if (maxId < getRecord(i).getUInt(0)) - maxId = getRecord(i).getUInt(0); - - return maxId; -} - -DBCFile::Iterator DBCFile::begin() -{ - assert(_data); - return Iterator(*this, _data); -} - -DBCFile::Iterator DBCFile::end() -{ - assert(_data); - return Iterator(*this, _stringTable); -} - diff --git a/src/tools/vmap4_extractor/dbcfile.h b/src/tools/vmap4_extractor/dbcfile.h deleted file mode 100644 index 063ca0b70f0..00000000000 --- a/src/tools/vmap4_extractor/dbcfile.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/> - * - * 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 DBCFILE_H -#define DBCFILE_H -#include <cassert> -#include <string> -#include "CascLib.h" - -class DBCFile -{ - public: - DBCFile(HANDLE mpq, const char* filename); - ~DBCFile(); - - // Open database. It must be openened before it can be used. - bool open(); - - // Database exceptions - class Exception - { - public: - Exception(const std::string &message) : message(message) { } - virtual ~Exception() { } - const std::string &getMessage() { return message; } - private: - std::string message; - }; - - class NotFound: public Exception - { - public: - NotFound(): Exception("Key was not found") { } - }; - - // Iteration over database - class Iterator; - class Record - { - public: - float getFloat(size_t field) const - { - assert(field < file._fieldCount); - return *reinterpret_cast<float*>(offset + field * 4); - } - - unsigned int getUInt(size_t field) const - { - assert(field < file._fieldCount); - return *reinterpret_cast<unsigned int*>(offset + field * 4); - } - - int getInt(size_t field) const - { - assert(field < file._fieldCount); - return *reinterpret_cast<int*>(offset + field * 4); - } - - char const* getString(size_t field) const - { - assert(field < file._fieldCount); - size_t stringOffset = getUInt(field); - assert(stringOffset < file._stringSize); - return reinterpret_cast<char*>(file._stringTable + stringOffset); - } - - private: - Record(DBCFile& file, unsigned char* offset): file(file), offset(offset) {} - DBCFile& file; - unsigned char* offset; - - friend class DBCFile; - friend class DBCFile::Iterator; - - Record& operator=(Record const&); - Record(Record const& right) : file(right.file), offset(right.offset) - { - } - }; - /** Iterator that iterates over records - */ - class Iterator - { - public: - Iterator(DBCFile &file, unsigned char* offset) : record(file, offset) { } - - Iterator(Iterator const& right) : record(right.record) - { - } - - /// Advance (prefix only) - Iterator& operator++() - { - record.offset += record.file._recordSize; - return *this; - } - - /// Return address of current instance - Record const& operator*() const { return record; } - Record const* operator->() const { return &record; } - - /// Comparison - bool operator==(Iterator const& b) const - { - return record.offset == b.record.offset; - } - - bool operator!=(Iterator const& b) const - { - return record.offset != b.record.offset; - } - - Iterator& operator=(Iterator const& right) - { - record.offset = right.record.offset; - return *this; - } - private: - Record record; - - }; - - // Get record by id - Record getRecord(size_t id); - /// Get begin iterator over records - Iterator begin(); - /// Get begin iterator over records - Iterator end(); - /// Trivial - size_t getRecordCount() const { return _recordCount; } - size_t getFieldCount() const { return _fieldCount; } - size_t getMaxId(); - - private: - HANDLE _mpq; - const char* _filename; - HANDLE _file; - size_t _recordSize; - size_t _recordCount; - size_t _fieldCount; - size_t _stringSize; - unsigned char *_data; - unsigned char* _stringTable; -}; - -#endif diff --git a/src/tools/vmap4_extractor/gameobject_extract.cpp b/src/tools/vmap4_extractor/gameobject_extract.cpp index d8005b5ced9..8949111a5cd 100644 --- a/src/tools/vmap4_extractor/gameobject_extract.cpp +++ b/src/tools/vmap4_extractor/gameobject_extract.cpp @@ -16,28 +16,17 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "DB2.h" #include "model.h" -#include "dbcfile.h" #include "adtfile.h" #include "vmapexport.h" +#include "StringFormat.h" #include <algorithm> #include <stdio.h> -bool ExtractSingleModel(std::string& fname) +bool ExtractSingleModel(std::string& name) { - if (fname.substr(fname.length() - 4, 4) == ".mdx") - { - fname.erase(fname.length() - 2, 2); - fname.append("2"); - } - - std::string originalName = fname; - - char* name = GetPlainName((char*)fname.c_str()); - FixNameCase(name, strlen(name)); - FixNameSpaces(name, strlen(name)); - std::string output(szWorkDirWmo); output += "/"; output += name; @@ -45,7 +34,7 @@ bool ExtractSingleModel(std::string& fname) if (FileExists(output.c_str())) return true; - Model mdl(originalName); + Model mdl(name); if (!mdl.open()) return false; @@ -54,26 +43,64 @@ bool ExtractSingleModel(std::string& fname) extern HANDLE CascStorage; +struct GameObjectDisplayInfoMeta +{ + static DB2Meta const* Instance() + { + static char const* types = "ifffh"; + static uint8 const arraySizes[5] = { 1, 6, 1, 1, 1 }; + static DB2Meta instance(-1, 5, 0xDD4432B9, types, arraySizes); + return &instance; + } +}; + +struct CascFileHandleDeleter +{ + typedef HANDLE pointer; + void operator()(HANDLE handle) const { CascCloseFile(handle); } +}; + +enum ModelTypes : uint32 +{ + MODEL_MD20 = '02DM', + MODEL_MD21 = '12DM', + MODEL_WMO = 'REVM' +}; + +uint32 GetHeaderMagic(std::string const& fileName) +{ + HANDLE file; + if (!CascOpenFile(CascStorage, fileName.c_str(), CASC_LOCALE_ALL, 0, &file)) + return 0; + + std::unique_ptr<HANDLE, CascFileHandleDeleter> modelFile(file); + uint32 magic = 0; + DWORD bytesRead = 0; + if (!CascReadFile(file, &magic, 4, &bytesRead) || bytesRead != 4) + return 0; + + return magic; +} + void ExtractGameobjectModels() { printf("Extracting GameObject models..."); - DBCFile dbc(CascStorage, "DBFilesClient\\GameObjectDisplayInfo.dbc"); - if(!dbc.open()) + HANDLE dbcFile; + if (!CascOpenFile(CascStorage, "DBFilesClient\\GameObjectDisplayInfo.db2", CASC_LOCALE_NONE, 0, &dbcFile)) { - printf("Fatal error: Invalid GameObjectDisplayInfo.dbc file format!\n"); + printf("Fatal error: Cannot find GameObjectDisplayInfo.db2 in archive!\n"); exit(1); } - DBCFile fileData(CascStorage, "DBFilesClient\\FileData.dbc"); - if (!fileData.open()) + DB2FileLoader db2; + if (!db2.Load(dbcFile, GameObjectDisplayInfoMeta::Instance())) { - printf("Fatal error: Invalid FileData.dbc file format!\n"); + printf("Fatal error: Invalid GameObjectDisplayInfo.db2 file format!\n"); exit(1); } std::string basepath = szWorkDirWmo; basepath += "/"; - std::string path; std::string modelListPath = basepath + "temp_gameobject_models"; FILE* model_list = fopen(modelListPath.c_str(), "wb"); @@ -83,62 +110,30 @@ void ExtractGameobjectModels() return; } - size_t maxFileId = fileData.getMaxId() + 1; - uint32* fileDataIndex = new uint32[maxFileId]; - memset(fileDataIndex, 0, maxFileId * sizeof(uint32)); - size_t files = fileData.getRecordCount(); - for (uint32 i = 0; i < files; ++i) - fileDataIndex[fileData.getRecord(i).getUInt(0)] = i; - - for (DBCFile::Iterator it = dbc.begin(); it != dbc.end(); ++it) + for (uint32 rec = 0; rec < db2.GetNumRows(); ++rec) { - uint32 fileId = it->getUInt(1); + uint32 fileId = db2.getRecord(rec).getUInt(0, 0); if (!fileId) continue; - uint32 fileIndex = fileDataIndex[fileId]; - if (!fileIndex) - continue; - - std::string filename = fileData.getRecord(fileIndex).getString(1); - std::string filepath = fileData.getRecord(fileIndex).getString(2); - - path = filepath + filename; - - if (path.length() < 4) - continue; - - FixNameCase((char*)path.c_str(), path.size()); - char * name = GetPlainName((char*)path.c_str()); - FixNameSpaces(name, strlen(name)); - - char * ch_ext = GetExtension(name); - if (!ch_ext) - continue; - - strToLower(ch_ext); - + std::string fileName = Trinity::StringFormat("FILE%08X", fileId); bool result = false; - if (!strcmp(ch_ext, ".wmo")) - result = ExtractSingleWmo(path); - else if (!strcmp(ch_ext, ".mdl")) // TODO: extract .mdl files, if needed - continue; - else if (!strcmp(ch_ext, ".mdx") || !strcmp(ch_ext, ".m2")) - result = ExtractSingleModel(path); + if (GetHeaderMagic(fileName) == MODEL_WMO) + result = ExtractSingleWmo(fileName); + else + result = ExtractSingleModel(fileName); if (result) { - uint32 displayId = it->getUInt(0); - uint32 path_length = strlen(name); + uint32 displayId = db2.getId(rec); + uint32 path_length = fileName.length(); fwrite(&displayId, sizeof(uint32), 1, model_list); fwrite(&path_length, sizeof(uint32), 1, model_list); - fwrite(name, sizeof(char), path_length, model_list); + fwrite(fileName.c_str(), sizeof(char), path_length, model_list); } } fclose(model_list); - delete[] fileDataIndex; - printf("Done!\n"); } diff --git a/src/tools/vmap4_extractor/model.cpp b/src/tools/vmap4_extractor/model.cpp index bd2d6dc9b91..8ee7ec6202d 100644 --- a/src/tools/vmap4_extractor/model.cpp +++ b/src/tools/vmap4_extractor/model.cpp @@ -45,16 +45,24 @@ bool Model::open() _unload(); + int32 m2start = 0; + char const* ptr = f.getBuffer(); + while (m2start + 4 < f.getSize() && *reinterpret_cast<uint32 const*>(ptr) != '02DM') + { + ++m2start; + ++ptr; + } + memcpy(&header, f.getBuffer(), sizeof(ModelHeader)); if (header.nBoundingTriangles > 0) { - f.seek(0); + f.seek(m2start); f.seekRelative(header.ofsBoundingVertices); vertices = new Vec3D[header.nBoundingVertices]; f.read(vertices,header.nBoundingVertices*12); for (uint32 i=0; i<header.nBoundingVertices; i++) vertices[i] = fixCoordSystem(vertices[i]); - f.seek(0); + f.seek(m2start); f.seekRelative(header.ofsBoundingTriangles); indices = new uint16[header.nBoundingTriangles]; f.read(indices,header.nBoundingTriangles*2); diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp index e4177052751..66bad76d9f0 100644 --- a/src/tools/vmap4_extractor/vmapexport.cpp +++ b/src/tools/vmap4_extractor/vmapexport.cpp @@ -44,7 +44,7 @@ //From Extractor #include "adtfile.h" #include "wdtfile.h" -#include "dbcfile.h" +#include "DB2.h" #include "wmo.h" #include "mpqfile.h" @@ -68,13 +68,35 @@ typedef struct unsigned int id; }map_id; -map_id * map_ids; -uint16 *LiqType = 0; +std::vector<map_id> map_ids; +std::vector<uint16> LiqType; uint32 map_count; char output_path[128] = "."; char input_path[1024] = "."; bool preciseVectorData = false; +struct LiquidTypeMeta +{ + static DB2Meta const* Instance() + { + static char const* types = "sifffffSifihhbbbbbi"; + static uint8 const arraySizes[19] = { 1, 1, 1, 1, 1, 1, 1, 6, 2, 18, 4, 1, 1, 1, 1, 1, 1, 6, 1 }; + static DB2Meta instance(-1, 19, 0x28B44DCB, types, arraySizes); + return &instance; + } +}; + +struct MapMeta +{ + static DB2Meta const* Instance() + { + static char const* types = "siffssshhhhhhhbbbbb"; + static uint8 const arraySizes[19] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + static DB2Meta instance(-1, 19, 0xB32E648C, types, arraySizes); + return &instance; + } +}; + // Constants //static const char * szWorkDirMaps = ".\\Maps"; @@ -228,23 +250,38 @@ void strToLower(char* str) void ReadLiquidTypeTableDBC() { printf("Read LiquidType.dbc file..."); + HANDLE dbcFile; + if (!CascOpenFile(CascStorage, "DBFilesClient\\LiquidType.db2", CASC_LOCALE_NONE, 0, &dbcFile)) + { + printf("Fatal error: Cannot find LiquidType.dbc in archive! %s\n", HumanReadableCASCError(GetLastError())); + exit(1); + } - DBCFile dbc(CascStorage, "DBFilesClient\\LiquidType.dbc"); - if(!dbc.open()) + DB2FileLoader db2; + if (!db2.Load(dbcFile, LiquidTypeMeta::Instance())) { - printf("Fatal error: Invalid LiquidType.dbc file format!\n"); + printf("Fatal error: Invalid LiquidType.db2 file format!\n"); exit(1); } - size_t LiqType_count = dbc.getRecordCount(); - size_t LiqType_maxid = dbc.getRecord(LiqType_count - 1).getUInt(0); - LiqType = new uint16[LiqType_maxid + 1]; - memset(LiqType, 0xff, (LiqType_maxid + 1) * sizeof(uint16)); + LiqType.resize(db2.GetMaxId(), 0xFFFF); + + for (uint32 x = 0; x < db2.GetNumRows(); ++x) + { + uint32 liquidTypeId; + if (LiquidTypeMeta::Instance()->HasIndexFieldInData()) + liquidTypeId = db2.getRecord(x).getUInt(LiquidTypeMeta::Instance()->GetIndexField(), 0); + else + liquidTypeId = db2.getId(x); + + LiqType[liquidTypeId] = db2.getRecord(x).getUInt8(13, 0); + } - for(uint32 x = 0; x < LiqType_count; ++x) - LiqType[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3); + for (uint32 x = 0; x < db2.GetNumRowCopies(); ++x) + LiqType[db2.GetRowCopy(x).second] = LiqType[db2.GetRowCopy(x).first]; - printf("Done! (%u LiqTypes loaded)\n", (unsigned int)LiqType_count); + CascCloseFile(dbcFile); + printf("Done! (" SZFMTD " LiqTypes loaded)\n", LiqType.size()); } bool ExtractWmo() @@ -325,15 +362,12 @@ bool ExtractSingleWmo(std::string& fname) froot.ConvertToVMAPRootWmo(output); int Wmo_nVertices = 0; //printf("root has %d groups\n", froot->nGroups); - if (froot.nGroups !=0) + if (!froot.groupFileDataIDs.empty()) { - for (uint32 i = 0; i < froot.nGroups; ++i) + for (std::size_t i = 0; i < froot.groupFileDataIDs.size(); ++i) { - char temp[1024]; - strncpy(temp, fname.c_str(), 1024); - temp[fname.length()-4] = 0; char groupFileName[1024]; - sprintf(groupFileName, "%s_%03u.wmo", temp, i); + sprintf(groupFileName, "FILE%08X", froot.groupFileDataIDs[i]); //printf("Trying to open groupfile %s\n",groupFileName); std::string s = groupFileName; @@ -364,7 +398,7 @@ void ParsMapFiles() char fn[512]; //char id_filename[64]; char id[10]; - for (unsigned int i=0; i<map_count; ++i) + for (unsigned int i = 0; i < map_ids.size(); ++i) { sprintf(id, "%04u", map_ids[i].id); sprintf(fn,"World\\Maps\\%s\\%s.wdt", map_ids[i].name, map_ids[i].name); @@ -538,38 +572,61 @@ int main(int argc, char ** argv) //map.dbc if (success) { - DBCFile * dbc = new DBCFile(CascStorage, "DBFilesClient\\Map.dbc"); - if (!dbc->open()) + printf("Read Map.dbc file... "); + + HANDLE dbcFile; + if (!CascOpenFile(CascStorage, "DBFilesClient\\Map.db2", CASC_LOCALE_NONE, 0, &dbcFile)) { - delete dbc; - printf("FATAL ERROR: Map.dbc not found in data file.\n"); - return 1; + printf("Fatal error: Cannot find Map.dbc in archive! %s\n", HumanReadableCASCError(GetLastError())); + exit(1); } - map_count = dbc->getRecordCount(); - map_ids = new map_id[map_count]; - for (unsigned int x = 0; x < map_count; ++x) + DB2FileLoader db2; + if (!db2.Load(dbcFile, MapMeta::Instance())) { - map_ids[x].id = dbc->getRecord(x).getUInt(0); + printf("Fatal error: Invalid Map.db2 file format! %s\n", HumanReadableCASCError(GetLastError())); + exit(1); + } - const char* map_name = dbc->getRecord(x).getString(1); + map_ids.resize(db2.GetNumRows()); + std::unordered_map<uint32, uint32> idToIndex; + for (uint32 x = 0; x < db2.GetNumRows(); ++x) + { + if (MapMeta::Instance()->HasIndexFieldInData()) + map_ids[x].id = db2.getRecord(x).getUInt(MapMeta::Instance()->GetIndexField(), 0); + else + map_ids[x].id = db2.getId(x); + + const char* map_name = db2.getRecord(x).getString(0, 0); size_t max_map_name_length = sizeof(map_ids[x].name); if (strlen(map_name) >= max_map_name_length) { - delete dbc; - delete[] map_ids; - printf("FATAL ERROR: Map name too long.\n"); - return 1; + printf("Fatal error: Map name too long!\n"); + exit(1); } strncpy(map_ids[x].name, map_name, max_map_name_length); map_ids[x].name[max_map_name_length - 1] = '\0'; - printf("Map - %s\n", map_ids[x].name); + idToIndex[map_ids[x].id] = x; + } + + for (uint32 x = 0; x < db2.GetNumRowCopies(); ++x) + { + uint32 from = db2.GetRowCopy(x).first; + uint32 to = db2.GetRowCopy(x).second; + auto itr = idToIndex.find(from); + if (itr != idToIndex.end()) + { + map_id id; + id.id = to; + strcpy(id.name, map_ids[itr->second].name); + map_ids.push_back(id); + } } - delete dbc; + CascCloseFile(dbcFile); + printf("Done! (" SZFMTD " maps loaded)\n", map_ids.size()); ParsMapFiles(); - delete [] map_ids; } CascCloseStorage(CascStorage); @@ -582,6 +639,5 @@ int main(int argc, char ** argv) } printf("Extract %s. Work complete. No errors.\n", versionString); - delete [] LiqType; return 0; } diff --git a/src/tools/vmap4_extractor/wmo.cpp b/src/tools/vmap4_extractor/wmo.cpp index 31ae1cb3c40..4bceebc8f0c 100644 --- a/src/tools/vmap4_extractor/wmo.cpp +++ b/src/tools/vmap4_extractor/wmo.cpp @@ -29,11 +29,11 @@ #include "mpqfile.h" using namespace std; -extern uint16 *LiqType; +extern std::vector<uint16> LiqType; WMORoot::WMORoot(std::string &filename) - : filename(filename), col(0), nTextures(0), nGroups(0), nP(0), nLights(0), - nModels(0), nDoodads(0), nDoodadSets(0), RootWMOID(0), liquidType(0) + : filename(filename), color(0), nTextures(0), nGroups(0), nPortals(0), nLights(0), + nDoodadNames(0), nDoodadDefs(0), nDoodadSets(0), RootWMOID(0), flags(0) { memset(bbcorn1, 0, sizeof(bbcorn1)); memset(bbcorn2, 0, sizeof(bbcorn2)); @@ -67,18 +67,30 @@ bool WMORoot::open() { f.read(&nTextures, 4); f.read(&nGroups, 4); - f.read(&nP, 4); + f.read(&nPortals, 4); f.read(&nLights, 4); - f.read(&nModels, 4); - f.read(&nDoodads, 4); + f.read(&nDoodadNames, 4); + f.read(&nDoodadDefs, 4); f.read(&nDoodadSets, 4); - f.read(&col, 4); + f.read(&color, 4); f.read(&RootWMOID, 4); f.read(bbcorn1, 12); f.read(bbcorn2, 12); - f.read(&liquidType, 4); + f.read(&flags, 4); break; } + else if (!strcmp(fourcc, "GFID")) + { + for (uint32 gp = 0; gp < nGroups; ++gp) + { + uint32 fileDataId; + f.read(&fileDataId, 4); + groupFileDataIDs.push_back(fileDataId); + + if (flags & 16) // LOD related + f.seekRelative(8); + } + } /* else if (!strcmp(fourcc,"MOTX")) { @@ -409,7 +421,7 @@ int WMOGroup::ConvertToVMAPGroupWmo(FILE *output, WMORoot *rootWMO, bool precise // according to WoW.Dev Wiki: uint32 liquidEntry; - if (rootWMO->liquidType & 4) + if (rootWMO->flags & 4) liquidEntry = liquidType; else if (liquidType == 15) liquidEntry = 0; @@ -460,7 +472,7 @@ int WMOGroup::ConvertToVMAPGroupWmo(FILE *output, WMORoot *rootWMO, bool precise /* std::ofstream llog("Buildings/liquid.log", ios_base::out | ios_base::app); llog << filename; - llog << ":\nliquidEntry: " << liquidEntry << " type: " << hlq->type << " (root:" << rootWMO->liquidType << " group:" << liquidType << ")\n"; + llog << ":\nliquidEntry: " << liquidEntry << " type: " << hlq->type << " (root:" << rootWMO->flags << " group:" << flags << ")\n"; llog.close(); */ fwrite(hlq, sizeof(WMOLiquidHeader), 1, output); diff --git a/src/tools/vmap4_extractor/wmo.h b/src/tools/vmap4_extractor/wmo.h index 3bc5970f58f..4246dbe0e5a 100644 --- a/src/tools/vmap4_extractor/wmo.h +++ b/src/tools/vmap4_extractor/wmo.h @@ -23,6 +23,7 @@ #include <string> #include <set> +#include <vector> #include "vec3d.h" #include "mpqfile.h" @@ -47,11 +48,13 @@ class WMORoot private: std::string filename; public: - unsigned int col; - uint32 nTextures, nGroups, nP, nLights, nModels, nDoodads, nDoodadSets, RootWMOID, liquidType; + unsigned int color; + uint32 nTextures, nGroups, nPortals, nLights, nDoodadNames, nDoodadDefs, nDoodadSets, RootWMOID, flags; float bbcorn1[3]; float bbcorn2[3]; + std::vector<uint32> groupFileDataIDs; + WMORoot(std::string& filename); bool open(); |