diff options
author | Shauren <shauren.trinity@gmail.com> | 2017-03-08 18:10:02 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2017-03-08 18:10:02 +0100 |
commit | 7b235ce6e4da0e9c19fa9c6306bc7a71c7fb905d (patch) | |
tree | 28611e02e44e55d28f60a9b1b3433831ed6772b8 /src | |
parent | f585c831248f24c93697b0c314dd015897febe39 (diff) |
Core/DataStores: Refactor DB2 loaders to be reusable by extractors
Diffstat (limited to 'src')
31 files changed, 2874 insertions, 3001 deletions
diff --git a/src/common/DataStores/DB2FileLoader.cpp b/src/common/DataStores/DB2FileLoader.cpp new file mode 100644 index 00000000000..6ec065aef27 --- /dev/null +++ b/src/common/DataStores/DB2FileLoader.cpp @@ -0,0 +1,1156 @@ +/* + * Copyright (C) 2008-2017 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 "DB2FileLoader.h" +#include "ByteConverter.h" +#include "Common.h" +#include "DB2Meta.h" +#include "Errors.h" +#include "Log.h" + +DB2FileLoadInfo::DB2FileLoadInfo() : Fields(nullptr), FieldCount(0), Meta(nullptr) +{ +} + +DB2FileLoadInfo::DB2FileLoadInfo(DB2FieldMeta const* fields, std::size_t fieldCount, DB2Meta const* meta) + : Fields(fields), FieldCount(fieldCount), Meta(meta) +{ + TypesString.reserve(FieldCount); + for (std::size_t i = 0; i < FieldCount; ++i) + TypesString += char(Fields[i].Type); +} + +uint32 DB2FileLoadInfo::GetStringFieldCount(bool localizedOnly) const +{ + uint32 stringFields = 0; + for (std::size_t i = 0; i < TypesString.length(); ++i) + if (TypesString[i] == FT_STRING || (TypesString[i] == FT_STRING_NOT_LOCALIZED && !localizedOnly)) + ++stringFields; + + return stringFields; +} + +DB2FileSource::~DB2FileSource() +{ +} + +class DB2FileLoaderImpl +{ +public: + virtual ~DB2FileLoaderImpl() { } + virtual bool Load(DB2FileSource* source, DB2FileLoadInfo const* loadInfo, DB2Header const* header) = 0; + virtual char* AutoProduceData(uint32& count, char**& indexTable, std::vector<char*>& stringPool) = 0; + virtual char* AutoProduceStrings(char* dataTable, uint32 locale) = 0; + virtual void AutoProduceRecordCopies(uint32 records, char** indexTable, char* dataTable) = 0; + virtual DB2Record GetRecord(uint32 recordNumber) const = 0; + virtual DB2RecordCopy GetRecordCopy(uint32 copyNumber) const = 0; + virtual uint32 GetRecordCount() const = 0; + virtual uint32 GetRecordCopyCount() const = 0; + virtual uint32 GetMaxId() const = 0; + +private: + friend class DB2Record; + virtual unsigned char const* GetRawRecordData(uint32 recordNumber) const = 0; + virtual uint32 RecordGetId(unsigned char const* record, uint32 recordIndex) const = 0; + virtual uint8 RecordGetUInt8(unsigned char const* record, uint32 field, uint32 arrayIndex) const = 0; + virtual uint16 RecordGetUInt16(unsigned char const* record, uint32 field, uint32 arrayIndex) const = 0; + virtual uint32 RecordGetUInt32(unsigned char const* record, uint32 field, uint32 arrayIndex) const = 0; + virtual int32 RecordGetInt32(unsigned char const* record, uint32 field, uint32 arrayIndex) const = 0; + virtual float RecordGetFloat(unsigned char const* record, uint32 field, uint32 arrayIndex) const = 0; + virtual char const* RecordGetString(unsigned char const* record, uint32 field, uint32 arrayIndex) const = 0; + virtual std::size_t* RecordCreateDetachedFieldOffsets(std::size_t* oldOffsets) const = 0; + virtual void RecordDestroyFieldOffsets(std::size_t*& fieldOffsets) const = 0; +}; + +class DB2FileLoaderRegularImpl final : public DB2FileLoaderImpl +{ +public: + DB2FileLoaderRegularImpl(); + ~DB2FileLoaderRegularImpl(); + + bool Load(DB2FileSource* source, DB2FileLoadInfo const* loadInfo, DB2Header const* header) override; + char* AutoProduceData(uint32& count, char**& indexTable, std::vector<char*>& stringPool) override; + char* AutoProduceStrings(char* dataTable, uint32 locale) override; + void AutoProduceRecordCopies(uint32 records, char** indexTable, char* dataTable) override; + DB2Record GetRecord(uint32 recordNumber) const override; + DB2RecordCopy GetRecordCopy(uint32 copyNumber) const override; + uint32 GetRecordCount() const override; + uint32 GetRecordCopyCount() const override; + uint32 GetMaxId() const override; + +private: + unsigned char const* GetRawRecordData(uint32 recordNumber) const override; + uint32 RecordGetId(unsigned char const* record, uint32 recordIndex) const override; + uint8 RecordGetUInt8(unsigned char const* record, uint32 field, uint32 arrayIndex) const override; + uint16 RecordGetUInt16(unsigned char const* record, uint32 field, uint32 arrayIndex) const override; + uint32 RecordGetUInt32(unsigned char const* record, uint32 field, uint32 arrayIndex) const override; + int32 RecordGetInt32(unsigned char const* record, uint32 field, uint32 arrayIndex) const override; + float RecordGetFloat(unsigned char const* record, uint32 field, uint32 arrayIndex) const override; + char const* RecordGetString(unsigned char const* record, uint32 field, uint32 arrayIndex) const override; + uint32 RecordGetVarInt(unsigned char const* record, uint32 field, uint32 arrayIndex, bool isSigned) const; + uint16 GetFieldOffset(uint32 field) const; + uint16 GetFieldSize(uint32 field) const; + std::size_t* RecordCreateDetachedFieldOffsets(std::size_t* oldOffsets) const override; + void RecordDestroyFieldOffsets(std::size_t*& fieldOffsets) const override; + +#pragma pack(push, 1) + struct FieldEntry + { + uint16 UnusedBits; + uint16 Offset; + }; +#pragma pack(pop) + + char const* fileName; + DB2FileLoadInfo const* _loadInfo; + + DB2Header const* _header; + + unsigned char* data; + unsigned char* stringTable; + unsigned char* idTable; + uint32 idTableSize; + DB2RecordCopy* copyTable; + FieldEntry* fields; +}; + +class DB2FileLoaderSparseImpl final : public DB2FileLoaderImpl +{ +public: + DB2FileLoaderSparseImpl(); + ~DB2FileLoaderSparseImpl(); + + bool Load(DB2FileSource* source, DB2FileLoadInfo const* loadInfo, DB2Header const* header) override; + char* AutoProduceData(uint32& records, char**& indexTable, std::vector<char*>& stringPool) override; + char* AutoProduceStrings(char* dataTable, uint32 locale) override; + void AutoProduceRecordCopies(uint32 /*records*/, char** /*indexTable*/, char* /*dataTable*/) override { } + DB2Record GetRecord(uint32 recordNumber) const override; + DB2RecordCopy GetRecordCopy(uint32 copyNumber) const override; + uint32 GetRecordCount() const override; + uint32 GetRecordCopyCount() const override; + uint32 GetMaxId() const override; + +private: + unsigned char const* GetRawRecordData(uint32 recordNumber) const override; + uint32 RecordGetId(unsigned char const* record, uint32 recordIndex) const override; + uint8 RecordGetUInt8(unsigned char const* record, uint32 field, uint32 arrayIndex) const override; + uint16 RecordGetUInt16(unsigned char const* record, uint32 field, uint32 arrayIndex) const override; + uint32 RecordGetUInt32(unsigned char const* record, uint32 field, uint32 arrayIndex) const override; + int32 RecordGetInt32(unsigned char const* record, uint32 field, uint32 arrayIndex) const override; + float RecordGetFloat(unsigned char const* record, uint32 field, uint32 arrayIndex) const override; + char const* RecordGetString(unsigned char const* record, uint32 field, uint32 arrayIndex) const override; + uint32 RecordGetVarInt(unsigned char const* record, uint32 field, uint32 arrayIndex, bool isSigned) const; + uint16 GetFieldOffset(uint32 field, uint32 arrayIndex) const; + uint16 GetFieldSize(uint32 field) const; + std::size_t* RecordCreateDetachedFieldOffsets(std::size_t* oldOffsets) const override; + void RecordDestroyFieldOffsets(std::size_t*& fieldOffsets) const override; + void CalculateAndStoreFieldOffsets(unsigned char const* rawRecord) const; + +#pragma pack(push, 1) + struct OffsetTableEntry + { + uint32 FileOffset; + uint16 RecordSize; + }; + struct FieldEntry + { + uint16 UnusedBits; + uint16 Offset; + }; +#pragma pack(pop) + + char const* fileName; + DB2FileLoadInfo const* _loadInfo; + std::size_t* _fieldAndArrayOffsets; + + DB2Header const* _header; + FieldEntry* fields; + + std::size_t dataStart; + unsigned char* data; + OffsetTableEntry* offsets; +}; + +DB2FileLoaderRegularImpl::DB2FileLoaderRegularImpl() +{ + fileName = nullptr; + _loadInfo = nullptr; + _header = nullptr; + data = nullptr; + stringTable = nullptr; + idTable = nullptr; + idTableSize = 0; + copyTable = nullptr; + fields = nullptr; +} + +bool DB2FileLoaderRegularImpl::Load(DB2FileSource* source, DB2FileLoadInfo const* loadInfo, DB2Header const* header) +{ + _loadInfo = loadInfo; + _header = header; + ASSERT(_loadInfo->Meta->IndexField == -1 || _loadInfo->Meta->IndexField == int32(header->IndexField)); + + fileName = source->GetFileName(); + fields = new FieldEntry[header->FieldCount]; + if (!source->Read(fields, header->FieldCount * sizeof(FieldEntry))) + return false; + + if (!_loadInfo->Meta->HasIndexFieldInData()) + idTableSize = header->RecordCount * sizeof(uint32); + + data = new unsigned char[header->RecordSize * header->RecordCount + header->StringTableSize]; + stringTable = data + header->RecordSize * header->RecordCount; + + if (!source->Read(data, header->RecordSize * header->RecordCount + header->StringTableSize)) + return false; + + if (idTableSize) + { + idTable = new unsigned char[idTableSize]; + if (!source->Read(idTable, idTableSize)) + return false; + } + + if (header->CopyTableSize) + { + copyTable = new DB2RecordCopy[header->CopyTableSize / sizeof(DB2RecordCopy)]; + if (!source->Read(copyTable, header->CopyTableSize)) + return false; + } + + return true; +} + +DB2FileLoaderRegularImpl::~DB2FileLoaderRegularImpl() +{ + delete[] data; + delete[] idTable; + delete[] copyTable; + delete[] fields; +} + +static char const* const nullStr = ""; + +char* DB2FileLoaderRegularImpl::AutoProduceData(uint32& records, char**& indexTable, std::vector<char*>& stringPool) +{ + if (_loadInfo->Meta->FieldCount != _header->FieldCount) + return nullptr; + + //get struct size and index pos + uint32 recordsize = _loadInfo->Meta->GetRecordSize(); + + uint32 maxi = GetMaxId() + 1; + + using index_entry_t = char*; + + records = maxi; + indexTable = new index_entry_t[maxi]; + memset(indexTable, 0, maxi * sizeof(index_entry_t)); + + char* dataTable = new char[(_header->RecordCount + (_header->CopyTableSize / 8)) * recordsize]; + + // we store flat holders pool as single memory block + std::size_t stringFields = _loadInfo->GetStringFieldCount(false); + std::size_t localizedStringFields = _loadInfo->GetStringFieldCount(true); + + // each string field at load have array of string for each locale + std::size_t stringHoldersRecordPoolSize = localizedStringFields * sizeof(LocalizedString) + (stringFields - localizedStringFields) * sizeof(char*); + char* stringHoldersPool = nullptr; + if (stringFields) + { + std::size_t stringHoldersPoolSize = stringHoldersRecordPoolSize * _header->RecordCount; + + stringHoldersPool = new char[stringHoldersPoolSize]; + stringPool.push_back(stringHoldersPool); + + // DB2 strings expected to have at least empty string + for (std::size_t i = 0; i < stringHoldersPoolSize / sizeof(char*); ++i) + ((char const**)stringHoldersPool)[i] = nullStr; + } + + uint32 offset = 0; + + for (uint32 y = 0; y < _header->RecordCount; y++) + { + unsigned char const* rawRecord = GetRawRecordData(y); + if (!rawRecord) + continue; + + uint32 indexVal = RecordGetId(rawRecord, y); + + indexTable[indexVal] = &dataTable[offset]; + + uint32 fieldIndex = 0; + if (!_loadInfo->Meta->HasIndexFieldInData()) + { + *((uint32*)(&dataTable[offset])) = indexVal; + offset += 4; + ++fieldIndex; + } + + uint32 stringFieldOffset = 0; + + for (uint32 x = 0; x < _header->FieldCount; ++x) + { + for (uint32 z = 0; z < _loadInfo->Meta->ArraySizes[x]; ++z) + { + switch (_loadInfo->TypesString[fieldIndex]) + { + case FT_FLOAT: + *((float*)(&dataTable[offset])) = RecordGetFloat(rawRecord, x, z); + offset += 4; + break; + case FT_INT: + *((uint32*)(&dataTable[offset])) = RecordGetVarInt(rawRecord, x, z, _loadInfo->Fields[fieldIndex].IsSigned); + offset += 4; + break; + case FT_BYTE: + *((uint8*)(&dataTable[offset])) = RecordGetUInt8(rawRecord, x, z); + offset += 1; + break; + case FT_SHORT: + *((uint16*)(&dataTable[offset])) = RecordGetUInt16(rawRecord, x, z); + offset += 2; + break; + case FT_STRING: + case FT_STRING_NOT_LOCALIZED: + { + // init db2 string field slots by pointers to string holders + char const*** slot = (char const***)(&dataTable[offset]); + *slot = (char const**)(&stringHoldersPool[stringHoldersRecordPoolSize * y + stringFieldOffset]); + if (_loadInfo->TypesString[fieldIndex] == FT_STRING) + stringFieldOffset += sizeof(LocalizedString); + else + stringFieldOffset += sizeof(char*); + + offset += sizeof(char*); + break; + } + default: + ASSERT(false, "Unknown format character '%c' found in %s meta", _loadInfo->TypesString[x], fileName); + break; + } + ++fieldIndex; + } + } + } + + return dataTable; +} + +char* DB2FileLoaderRegularImpl::AutoProduceStrings(char* dataTable, uint32 locale) +{ + if (_loadInfo->Meta->FieldCount != _header->FieldCount) + return nullptr; + + if (!(_header->Locale & (1 << locale))) + { + char const* sep = ""; + std::ostringstream str; + for (uint32 i = 0; i < TOTAL_LOCALES; ++i) + { + if (_header->Locale & (1 << i)) + { + str << sep << localeNames[i]; + sep = ", "; + } + } + + TC_LOG_ERROR("", "Attempted to load %s which has locales %s as %s. Check if you placed your localized db2 files in correct directory.", fileName, str.str().c_str(), localeNames[locale]); + return nullptr; + } + + char* stringPool = new char[_header->StringTableSize]; + memcpy(stringPool, stringTable, _header->StringTableSize); + + uint32 offset = 0; + + for (uint32 y = 0; y < _header->RecordCount; y++) + { + unsigned char const* rawRecord = GetRawRecordData(y); + uint32 fieldIndex = 0; + if (!_loadInfo->Meta->HasIndexFieldInData()) + { + offset += 4; + ++fieldIndex; + } + + for (uint32 x = 0; x < _header->FieldCount; ++x) + { + for (uint32 z = 0; z < _loadInfo->Meta->ArraySizes[x]; ++z) + { + switch (_loadInfo->TypesString[fieldIndex]) + { + case FT_FLOAT: + case FT_INT: + offset += 4; + break; + case FT_BYTE: + offset += 1; + break; + case FT_SHORT: + offset += 2; + break; + case FT_STRING: + { + // fill only not filled entries + LocalizedString* db2str = *(LocalizedString**)(&dataTable[offset]); + if (db2str->Str[locale] == nullStr) + { + char const* st = RecordGetString(rawRecord, x, z); + db2str->Str[locale] = stringPool + (st - (char const*)stringTable); + } + + offset += sizeof(char*); + break; + } + case FT_STRING_NOT_LOCALIZED: + { + char** db2str = (char**)(&dataTable[offset]); + char const* st = RecordGetString(rawRecord, x, z); + *db2str = stringPool + (st - (char const*)stringTable); + offset += sizeof(char*); + break; + } + default: + ASSERT(false, "Unknown format character '%c' found in %s meta", _loadInfo->TypesString[x], fileName); + break; + } + ++fieldIndex; + } + } + } + + return stringPool; +} + +void DB2FileLoaderRegularImpl::AutoProduceRecordCopies(uint32 records, char** indexTable, char* dataTable) +{ + uint32 recordsize = _loadInfo->Meta->GetRecordSize(); + uint32 offset = _header->RecordCount * recordsize; + for (uint32 c = 0; c < GetRecordCopyCount(); ++c) + { + DB2RecordCopy copy = GetRecordCopy(c); + if (copy.SourceRowId && copy.SourceRowId < records && copy.NewRowId < records && indexTable[copy.SourceRowId]) + { + indexTable[copy.NewRowId] = &dataTable[offset]; + memcpy(indexTable[copy.NewRowId], indexTable[copy.SourceRowId], recordsize); + + if (_loadInfo->Meta->HasIndexFieldInData()) + *((uint32*)(&dataTable[offset + GetFieldOffset(_loadInfo->Meta->GetIndexField())])) = copy.NewRowId; + else + *((uint32*)(&dataTable[offset])) = copy.NewRowId; + + offset += recordsize; + } + } +} + +DB2Record DB2FileLoaderRegularImpl::GetRecord(uint32 recordNumber) const +{ + return DB2Record(*this, recordNumber, nullptr); +} + +DB2RecordCopy DB2FileLoaderRegularImpl::GetRecordCopy(uint32 copyNumber) const +{ + if (copyNumber >= GetRecordCopyCount()) + return DB2RecordCopy{}; + + return copyTable[copyNumber]; +} + +uint32 DB2FileLoaderRegularImpl::GetRecordCount() const +{ + return _header->RecordCount; +} + +uint32 DB2FileLoaderRegularImpl::GetRecordCopyCount() const +{ + return _header->CopyTableSize / sizeof(DB2RecordCopy); +} + +unsigned char const* DB2FileLoaderRegularImpl::GetRawRecordData(uint32 recordNumber) const +{ + if (recordNumber >= _header->RecordCount) + return nullptr; + + return data + recordNumber * _header->RecordSize; +} + +uint32 DB2FileLoaderRegularImpl::RecordGetId(unsigned char const* record, uint32 recordIndex) const +{ + if (_loadInfo->Meta->HasIndexFieldInData()) + return RecordGetVarInt(record, _loadInfo->Meta->GetIndexField(), 0, false); + + return (reinterpret_cast<uint32 const*>(idTable))[recordIndex]; +} + +uint8 DB2FileLoaderRegularImpl::RecordGetUInt8(unsigned char const* record, uint32 field, uint32 arrayIndex) const +{ + ASSERT(field < _header->FieldCount); + ASSERT(GetFieldSize(field) == 1); + return *reinterpret_cast<uint8 const*>(record + GetFieldOffset(field) + arrayIndex * sizeof(uint8)); +} + +uint16 DB2FileLoaderRegularImpl::RecordGetUInt16(unsigned char const* record, uint32 field, uint32 arrayIndex) const +{ + ASSERT(field < _header->FieldCount); + ASSERT(GetFieldSize(field) == 2); + uint16 val = *reinterpret_cast<uint16 const*>(record + GetFieldOffset(field) + arrayIndex * sizeof(uint16)); + EndianConvert(val); + return val; +} + +uint32 DB2FileLoaderRegularImpl::RecordGetUInt32(unsigned char const* record, uint32 field, uint32 arrayIndex) const +{ + return RecordGetVarInt(record, field, arrayIndex, false); +} + +int32 DB2FileLoaderRegularImpl::RecordGetInt32(unsigned char const* record, uint32 field, uint32 arrayIndex) const +{ + return int32(RecordGetVarInt(record, field, arrayIndex, true)); +} + +float DB2FileLoaderRegularImpl::RecordGetFloat(unsigned char const* record, uint32 field, uint32 arrayIndex) const +{ + ASSERT(field < _header->FieldCount); + float val = *reinterpret_cast<float const*>(record + GetFieldOffset(field) + arrayIndex * sizeof(float)); + EndianConvert(val); + return val; +} + +char const* DB2FileLoaderRegularImpl::RecordGetString(unsigned char const* record, uint32 field, uint32 arrayIndex) const +{ + ASSERT(field < _header->FieldCount); + uint32 stringOffset = *reinterpret_cast<uint32 const*>(record + GetFieldOffset(field) + arrayIndex * sizeof(uint32)); + EndianConvert(stringOffset); + ASSERT(stringOffset < _header->StringTableSize); + return reinterpret_cast<char*>(stringTable + stringOffset); +} + +uint32 DB2FileLoaderRegularImpl::RecordGetVarInt(unsigned char const* record, uint32 field, uint32 arrayIndex, bool isSigned) const +{ + ASSERT(field < _header->FieldCount); + uint32 val = *reinterpret_cast<uint32 const*>(record + GetFieldOffset(field) + arrayIndex * (4 - fields[field].UnusedBits / 8)); + EndianConvert(val); + if (isSigned) + return int32(val) << fields[field].UnusedBits >> fields[field].UnusedBits; + + return val << fields[field].UnusedBits >> fields[field].UnusedBits; +} + +uint16 DB2FileLoaderRegularImpl::GetFieldOffset(uint32 field) const +{ + ASSERT(field < _header->FieldCount); + return fields[field].Offset; +} + +uint16 DB2FileLoaderRegularImpl::GetFieldSize(uint32 field) const +{ + ASSERT(field < _header->FieldCount); + return 4 - fields[field].UnusedBits / 8; +} + +std::size_t* DB2FileLoaderRegularImpl::RecordCreateDetachedFieldOffsets(std::size_t* /*oldOffsets*/) const +{ + return nullptr; +} + +void DB2FileLoaderRegularImpl::RecordDestroyFieldOffsets(std::size_t*& /*fieldOffsets*/) const +{ +} + +uint32 DB2FileLoaderRegularImpl::GetMaxId() const +{ + uint32 maxId = 0; + for (uint32 row = 0; row < _header->RecordCount; ++row) + { + uint32 id = RecordGetId(GetRawRecordData(row), row); + if (id > maxId) + maxId = id; + } + + for (uint32 copy = 0; copy < GetRecordCopyCount(); ++copy) + { + uint32 id = GetRecordCopy(copy).NewRowId; + if (id > maxId) + maxId = id; + } + + return maxId; +} + +DB2FileLoaderSparseImpl::DB2FileLoaderSparseImpl() +{ + fileName = nullptr; + _loadInfo = nullptr; + _fieldAndArrayOffsets = nullptr; + _header = nullptr; + fields = nullptr; + dataStart = 0; + data = nullptr; + offsets = nullptr; +} + +DB2FileLoaderSparseImpl::~DB2FileLoaderSparseImpl() +{ + delete[] _fieldAndArrayOffsets; + delete[] data; + delete[] offsets; + delete[] fields; +} + +bool DB2FileLoaderSparseImpl::Load(DB2FileSource* source, DB2FileLoadInfo const* loadInfo, DB2Header const* header) +{ + _loadInfo = loadInfo; + _header = header; + fileName = source->GetFileName(); + + fields = new FieldEntry[header->FieldCount]; + if (!source->Read(fields, header->FieldCount * sizeof(FieldEntry))) + return false; + + dataStart = source->GetPosition(); + + data = new unsigned char[header->StringTableSize - dataStart]; + + if (!source->Read(data, header->StringTableSize - dataStart)) + return false; + + offsets = new OffsetTableEntry[header->MaxId - header->MinId + 1]; + if (!source->Read(offsets, (header->MaxId - header->MinId + 1) * 6)) + return false; + + _fieldAndArrayOffsets = new std::size_t[_loadInfo->Meta->FieldCount + _loadInfo->FieldCount - (!_loadInfo->Meta->HasIndexFieldInData() ? 1 : 0)]; + return true; +} + +char* DB2FileLoaderSparseImpl::AutoProduceData(uint32& maxId, char**& indexTable, std::vector<char*>& stringPool) +{ + if (_loadInfo->Meta->FieldCount != _header->FieldCount) + return NULL; + + //get struct size and index pos + uint32 recordsize = _loadInfo->Meta->GetRecordSize(); + + uint32 offsetCount = _header->MaxId - _header->MinId + 1; + uint32 records = 0; + uint32 expandedDataSize = 0; + for (uint32 i = 0; i < offsetCount; ++i) + { + if (offsets[i].FileOffset && offsets[i].RecordSize) + { + ++records; + expandedDataSize += offsets[i].RecordSize; + } + } + + using index_entry_t = char*; + + maxId = _header->MaxId + 1; + indexTable = new index_entry_t[maxId]; + memset(indexTable, 0, maxId * sizeof(index_entry_t)); + + char* dataTable = new char[records * recordsize]; + + // we store flat holders pool as single memory block + std::size_t stringFields = _loadInfo->GetStringFieldCount(false); + std::size_t localizedStringFields = _loadInfo->GetStringFieldCount(true); + + // each string field at load have array of string for each locale + std::size_t stringHoldersRecordPoolSize = localizedStringFields * sizeof(LocalizedString) + (stringFields - localizedStringFields) * sizeof(char*); + std::size_t stringHoldersPoolSize = stringHoldersRecordPoolSize * records; + + char* stringHoldersPool = new char[stringHoldersPoolSize]; + stringPool.push_back(stringHoldersPool); + + // DB2 strings expected to have at least empty string + for (std::size_t i = 0; i < stringHoldersPoolSize / sizeof(char*); ++i) + ((char const**)stringHoldersPool)[i] = nullStr; + + char* stringTable = new char[expandedDataSize - records * ((recordsize - (!_loadInfo->Meta->HasIndexFieldInData() ? 4 : 0)) - stringFields * sizeof(char*))]; + memset(stringTable, 0, expandedDataSize - records * ((recordsize - (!_loadInfo->Meta->HasIndexFieldInData() ? 4 : 0)) - stringFields * sizeof(char*))); + stringPool.push_back(stringTable); + char* stringPtr = stringTable; + + uint32 offset = 0; + uint32 recordNum = 0; + for (uint32 y = 0; y < offsetCount; ++y) + { + unsigned char const* rawRecord = GetRawRecordData(y); + if (!rawRecord) + continue; + + uint32 indexVal = RecordGetId(rawRecord, y); + indexTable[indexVal] = &dataTable[offset]; + + uint32 fieldIndex = 0; + if (!_loadInfo->Meta->HasIndexFieldInData()) + { + *((uint32*)(&dataTable[offset])) = indexVal; + offset += 4; + ++fieldIndex; + } + + uint32 stringFieldOffset = 0; + for (uint32 x = 0; x < _header->FieldCount; ++x) + { + for (uint32 z = 0; z < _loadInfo->Meta->ArraySizes[x]; ++z) + { + switch (_loadInfo->TypesString[fieldIndex]) + { + case FT_FLOAT: + *((float*)(&dataTable[offset])) = RecordGetFloat(rawRecord, x, z); + offset += 4; + break; + case FT_INT: + *((uint32*)(&dataTable[offset])) = RecordGetVarInt(rawRecord, x, z, _loadInfo->Fields[fieldIndex].IsSigned); + offset += 4; + break; + case FT_BYTE: + *((uint8*)(&dataTable[offset])) = RecordGetUInt8(rawRecord, x, z); + offset += 1; + break; + case FT_SHORT: + *((uint16*)(&dataTable[offset])) = RecordGetUInt16(rawRecord, x, z); + offset += 2; + break; + case FT_STRING: + { + LocalizedString** slot = (LocalizedString**)(&dataTable[offset]); + *slot = (LocalizedString*)(&stringHoldersPool[stringHoldersRecordPoolSize * recordNum + stringFieldOffset]); + for (uint32 locale = 0; locale < TOTAL_LOCALES; ++locale) + if (_header->Locale & (1 << locale)) + (*slot)->Str[locale] = stringPtr; + strcpy(stringPtr, RecordGetString(rawRecord, x, z)); + stringPtr += strlen(stringPtr) + 1; + stringFieldOffset += sizeof(LocalizedString); + offset += sizeof(LocalizedString*); + break; + } + case FT_STRING_NOT_LOCALIZED: + { + char const*** slot = (char const***)(&dataTable[offset]); + *slot = (char const**)(&stringHoldersPool[stringHoldersRecordPoolSize * recordNum + stringFieldOffset]); + **slot = stringPtr; + strcpy(stringPtr, RecordGetString(rawRecord, x, z)); + stringPtr += strlen(stringPtr) + 1; + stringFieldOffset += sizeof(char*); + offset += sizeof(char*); + break; + } + default: + ASSERT(false, "Unknown format character '%c' found in %s meta", _loadInfo->TypesString[x], fileName); + break; + } + ++fieldIndex; + } + } + + ++recordNum; + } + + return dataTable; +} + +char* DB2FileLoaderSparseImpl::AutoProduceStrings(char* dataTable, uint32 locale) +{ + if (_loadInfo->Meta->FieldCount != _header->FieldCount) + return nullptr; + + if (!(_header->Locale & (1 << locale))) + { + char const* sep = ""; + std::ostringstream str; + for (uint32 i = 0; i < TOTAL_LOCALES; ++i) + { + if (_header->Locale & (1 << i)) + { + str << sep << localeNames[i]; + sep = ", "; + } + } + + TC_LOG_ERROR("", "Attempted to load %s which has locales %s as %s. Check if you placed your localized db2 files in correct directory.", fileName, str.str().c_str(), localeNames[locale]); + return nullptr; + } + + uint32 offsetCount = _header->MaxId - _header->MinId + 1; + uint32 records = 0; + for (uint32 i = 0; i < offsetCount; ++i) + if (offsets[i].FileOffset && offsets[i].RecordSize) + ++records; + + uint32 recordsize = _loadInfo->Meta->GetRecordSize(); + std::size_t stringFields = _loadInfo->GetStringFieldCount(true); + char* stringTable = new char[_header->StringTableSize - dataStart - records * ((recordsize - (!_loadInfo->Meta->HasIndexFieldInData() ? 4 : 0)) - stringFields * sizeof(char*))]; + memset(stringTable, 0, _header->StringTableSize - dataStart - records * ((recordsize - (!_loadInfo->Meta->HasIndexFieldInData() ? 4 : 0)) - stringFields * sizeof(char*))); + char* stringPtr = stringTable; + + uint32 offset = 0; + + for (uint32 y = 0; y < offsetCount; y++) + { + unsigned char const* rawRecord = GetRawRecordData(y); + if (!rawRecord) + continue; + + uint32 fieldIndex = 0; + if (!_loadInfo->Meta->HasIndexFieldInData()) + { + offset += 4; + ++fieldIndex; + } + + for (uint32 x = 0; x < _header->FieldCount; ++x) + { + for (uint32 z = 0; z < _loadInfo->Meta->ArraySizes[x]; ++z) + { + switch (_loadInfo->TypesString[fieldIndex]) + { + case FT_FLOAT: + offset += 4; + break; + case FT_INT: + offset += 4; + break; + case FT_BYTE: + offset += 1; + break; + case FT_SHORT: + offset += 2; + break; + case FT_STRING: + { + LocalizedString* db2str = *(LocalizedString**)(&dataTable[offset]); + db2str->Str[locale] = stringPtr; + strcpy(stringPtr, RecordGetString(rawRecord, x, z)); + stringPtr += strlen(stringPtr) + 1; + offset += sizeof(char*); + break; + } + case FT_STRING_NOT_LOCALIZED: + offset += sizeof(char*); + break; + default: + ASSERT(false, "Unknown format character '%c' found in %s meta", _loadInfo->TypesString[x], fileName); + break; + } + ++fieldIndex; + } + } + } + + return stringTable; +} + +DB2Record DB2FileLoaderSparseImpl::GetRecord(uint32 recordNumber) const +{ + return DB2Record(*this, recordNumber, _fieldAndArrayOffsets); +} + +DB2RecordCopy DB2FileLoaderSparseImpl::GetRecordCopy(uint32 /*recordId*/) const +{ + return DB2RecordCopy{}; +} + +uint32 DB2FileLoaderSparseImpl::GetRecordCount() const +{ + return _header->MaxId - _header->MinId + 1; +} + +uint32 DB2FileLoaderSparseImpl::GetRecordCopyCount() const +{ + return 0; +} + +unsigned char const* DB2FileLoaderSparseImpl::GetRawRecordData(uint32 recordNumber) const +{ + if (recordNumber > (_header->MaxId - _header->MinId) || !offsets[recordNumber].FileOffset || !offsets[recordNumber].RecordSize) + return nullptr; + + unsigned char const* rawRecord = &data[offsets[recordNumber].FileOffset - dataStart]; + CalculateAndStoreFieldOffsets(rawRecord); + return rawRecord; +} + +uint32 DB2FileLoaderSparseImpl::RecordGetId(unsigned char const* record, uint32 recordIndex) const +{ + if (_loadInfo->Meta->HasIndexFieldInData()) + return RecordGetVarInt(record, _loadInfo->Meta->GetIndexField(), 0, false); + + return _header->MinId + recordIndex; +} + +uint8 DB2FileLoaderSparseImpl::RecordGetUInt8(unsigned char const* record, uint32 field, uint32 arrayIndex) const +{ + ASSERT(field < _header->FieldCount); + ASSERT(GetFieldSize(field) == 1); + return *reinterpret_cast<uint8 const*>(record + GetFieldOffset(field, arrayIndex)); +} + +uint16 DB2FileLoaderSparseImpl::RecordGetUInt16(unsigned char const* record, uint32 field, uint32 arrayIndex) const +{ + ASSERT(field < _header->FieldCount); + ASSERT(GetFieldSize(field) == 2); + uint16 val = *reinterpret_cast<uint16 const*>(record + GetFieldOffset(field, arrayIndex)); + EndianConvert(val); + return val; +} + +uint32 DB2FileLoaderSparseImpl::RecordGetUInt32(unsigned char const* record, uint32 field, uint32 arrayIndex) const +{ + return RecordGetVarInt(record, field, arrayIndex, false); +} + +int32 DB2FileLoaderSparseImpl::RecordGetInt32(unsigned char const* record, uint32 field, uint32 arrayIndex) const +{ + return int32(RecordGetVarInt(record, field, arrayIndex, true)); +} + +float DB2FileLoaderSparseImpl::RecordGetFloat(unsigned char const* record, uint32 field, uint32 arrayIndex) const +{ + ASSERT(field < _header->FieldCount); + float val = *reinterpret_cast<float const*>(record + GetFieldOffset(field, arrayIndex)); + EndianConvert(val); + return val; +} + +char const* DB2FileLoaderSparseImpl::RecordGetString(unsigned char const* record, uint32 field, uint32 arrayIndex) const +{ + ASSERT(field < _header->FieldCount); + return reinterpret_cast<char const*>(record + GetFieldOffset(field, arrayIndex)); +} + +uint32 DB2FileLoaderSparseImpl::RecordGetVarInt(unsigned char const* record, uint32 field, uint32 arrayIndex, bool isSigned) const +{ + ASSERT(field < _header->FieldCount); + uint32 val = *reinterpret_cast<uint32 const*>(record + GetFieldOffset(field, arrayIndex)); + EndianConvert(val); + if (isSigned) + return int32(val) << fields[field].UnusedBits >> fields[field].UnusedBits; + + return val << fields[field].UnusedBits >> fields[field].UnusedBits; +} + +uint16 DB2FileLoaderSparseImpl::GetFieldOffset(uint32 field, uint32 arrayIndex) const +{ + return _fieldAndArrayOffsets[_fieldAndArrayOffsets[field] + arrayIndex]; +} + +uint16 DB2FileLoaderSparseImpl::GetFieldSize(uint32 field) const +{ + ASSERT(field < _header->FieldCount); + return 4 - fields[field].UnusedBits / 8; +} + +std::size_t* DB2FileLoaderSparseImpl::RecordCreateDetachedFieldOffsets(std::size_t* oldOffsets) const +{ + if (oldOffsets != _fieldAndArrayOffsets) + return oldOffsets; + + uint32 size = _loadInfo->Meta->FieldCount + _loadInfo->FieldCount - (!_loadInfo->Meta->HasIndexFieldInData() ? 1 : 0); + std::size_t* newOffsets = new std::size_t[size]; + memcpy(newOffsets, _fieldAndArrayOffsets, size * sizeof(std::size_t)); + return newOffsets; +} + +void DB2FileLoaderSparseImpl::RecordDestroyFieldOffsets(std::size_t*& fieldOffsets) const +{ + if (fieldOffsets == _fieldAndArrayOffsets) + return; + + delete[] fieldOffsets; + fieldOffsets = nullptr; +} + +void DB2FileLoaderSparseImpl::CalculateAndStoreFieldOffsets(unsigned char const* rawRecord) const +{ + std::size_t offset = 0; + uint32 combinedField = _loadInfo->Meta->FieldCount; + for (uint32 field = 0; field < _loadInfo->Meta->FieldCount; ++field) + { + _fieldAndArrayOffsets[field] = combinedField; + for (uint32 arr = 0; arr < _loadInfo->Meta->ArraySizes[field]; ++arr) + { + _fieldAndArrayOffsets[combinedField] = offset; + switch (_loadInfo->Meta->Types[field]) + { + case FT_BYTE: + case FT_SHORT: + case FT_INT: + offset += GetFieldSize(field); + break; + case FT_FLOAT: + offset += sizeof(float); + break; + case FT_STRING: + offset += strlen(reinterpret_cast<char const*>(rawRecord) + offset) + 1; + break; + default: + ASSERT(false, "Unknown format character '%c' found in %s meta", _loadInfo->Meta->Types[field], fileName); + break; + } + ++combinedField; + } + } +} + +uint32 DB2FileLoaderSparseImpl::GetMaxId() const +{ + return _header->MaxId; +} + +DB2Record::DB2Record(DB2FileLoaderImpl const& db2, uint32 recordIndex, std::size_t* fieldOffsets) + : _db2(db2), _recordIndex(recordIndex), _recordData(db2.GetRawRecordData(recordIndex)), _fieldOffsets(fieldOffsets) +{ +} + +DB2Record::~DB2Record() +{ + _db2.RecordDestroyFieldOffsets(_fieldOffsets); +} + +DB2Record::operator bool() +{ + return _recordData != nullptr; +} + +uint32 DB2Record::GetId() const +{ + return _db2.RecordGetId(_recordData, _recordIndex); +} + +uint8 DB2Record::GetUInt8(uint32 field, uint32 arrayIndex) const +{ + return _db2.RecordGetUInt8(_recordData, field, arrayIndex); +} + +uint16 DB2Record::GetUInt16(uint32 field, uint32 arrayIndex) const +{ + return _db2.RecordGetUInt16(_recordData, field, arrayIndex); +} + +uint32 DB2Record::GetUInt32(uint32 field, uint32 arrayIndex) const +{ + return _db2.RecordGetUInt32(_recordData, field, arrayIndex); +} + +int32 DB2Record::GetInt32(uint32 field, uint32 arrayIndex) const +{ + return _db2.RecordGetInt32(_recordData, field, arrayIndex); +} + +float DB2Record::GetFloat(uint32 field, uint32 arrayIndex) const +{ + return _db2.RecordGetFloat(_recordData, field, arrayIndex); +} + +char const* DB2Record::GetString(uint32 field, uint32 arrayIndex) const +{ + return _db2.RecordGetString(_recordData, field, arrayIndex); +} + +void DB2Record::MakePersistent() +{ + _fieldOffsets = _db2.RecordCreateDetachedFieldOffsets(_fieldOffsets); +} + +DB2FileLoader::DB2FileLoader() : _impl(nullptr) +{ +} + +DB2FileLoader::~DB2FileLoader() +{ + delete _impl; +} + +bool DB2FileLoader::Load(DB2FileSource* source, DB2FileLoadInfo const* loadInfo) +{ + if (!source->IsOpen()) + return false; + + if (!source->Read(&_header, sizeof(DB2Header))) + return false; + + EndianConvert(_header.Signature); + EndianConvert(_header.RecordCount); + EndianConvert(_header.FieldCount); + EndianConvert(_header.RecordSize); + EndianConvert(_header.StringTableSize); + EndianConvert(_header.TableHash); + EndianConvert(_header.LayoutHash); + EndianConvert(_header.MinId); + EndianConvert(_header.MaxId); + EndianConvert(_header.Locale); + EndianConvert(_header.CopyTableSize); + EndianConvert(_header.Flags); + EndianConvert(_header.IndexField); + + if (_header.Signature != 0x35424457) //'WDB5' + return false; + + if (_header.LayoutHash != loadInfo->Meta->LayoutHash) + return false; + + if (!(_header.Flags & 0x1)) + _impl = new DB2FileLoaderRegularImpl(); + else + _impl = new DB2FileLoaderSparseImpl(); + + return _impl->Load(source, loadInfo, &_header); +} + +char* DB2FileLoader::AutoProduceData(uint32& count, char**& indexTable, std::vector<char*>& stringPool) +{ + return _impl->AutoProduceData(count, indexTable, stringPool); +} + +char* DB2FileLoader::AutoProduceStrings(char* dataTable, uint32 locale) +{ + return _impl->AutoProduceStrings(dataTable, locale); +} + +void DB2FileLoader::AutoProduceRecordCopies(uint32 records, char** indexTable, char* dataTable) +{ + _impl->AutoProduceRecordCopies(records, indexTable, dataTable); +} + +uint32 DB2FileLoader::GetRecordCount() const +{ + return _impl->GetRecordCount(); +} + +uint32 DB2FileLoader::GetRecordCopyCount() const +{ + return _impl->GetRecordCopyCount(); +} + +uint32 DB2FileLoader::GetMaxId() const +{ + return _impl->GetMaxId(); +} + +DB2Record DB2FileLoader::GetRecord(uint32 recordNumber) const +{ + return _impl->GetRecord(recordNumber); +} + +DB2RecordCopy DB2FileLoader::GetRecordCopy(uint32 copyNumber) const +{ + return _impl->GetRecordCopy(copyNumber); +} diff --git a/src/common/DataStores/DB2FileLoader.h b/src/common/DataStores/DB2FileLoader.h new file mode 100644 index 00000000000..a8dd7d27e41 --- /dev/null +++ b/src/common/DataStores/DB2FileLoader.h @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2008-2017 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 DB2_FILE_LOADER_H +#define DB2_FILE_LOADER_H + +#include "Define.h" +#include <string> +#include <vector> + +class DB2FileLoaderImpl; +struct DB2FieldMeta; +struct DB2Meta; + +#pragma pack(push, 1) +struct DB2Header +{ + uint32 Signature; + uint32 RecordCount; + uint32 FieldCount; + uint32 RecordSize; + uint32 StringTableSize; + uint32 TableHash; + uint32 LayoutHash; + uint32 MinId; + uint32 MaxId; + uint32 Locale; + uint32 CopyTableSize; + uint16 Flags; + int16 IndexField; +}; +#pragma pack(pop) + +struct TC_COMMON_API DB2FileLoadInfo +{ + DB2FileLoadInfo(); + DB2FileLoadInfo(DB2FieldMeta const* fields, std::size_t fieldCount, DB2Meta const* meta); + + uint32 GetStringFieldCount(bool localizedOnly) const; + + DB2FieldMeta const* Fields; + std::size_t FieldCount; + DB2Meta const* Meta; + std::string TypesString; +}; + +struct TC_COMMON_API DB2FileSource +{ + virtual ~DB2FileSource(); + + /// + /** + * Returns true when the source is open for reading + */ + virtual bool IsOpen() const = 0; + + // Reads numBytes bytes from source and places them into buffer + // Retu + virtual bool Read(void* buffer, std::size_t numBytes) = 0; + virtual std::size_t GetPosition() const = 0; + virtual char const* GetFileName() const = 0; +}; + +class TC_COMMON_API DB2Record +{ +public: + DB2Record(DB2FileLoaderImpl const& db2, uint32 recordIndex, std::size_t* fieldOffsets); + ~DB2Record(); + + operator bool(); + + uint32 GetId() const; + + uint8 GetUInt8(uint32 field, uint32 arrayIndex) const; + uint16 GetUInt16(uint32 field, uint32 arrayIndex) const; + uint32 GetUInt32(uint32 field, uint32 arrayIndex) const; + int32 GetInt32(uint32 field, uint32 arrayIndex) const; + float GetFloat(uint32 field, uint32 arrayIndex) const; + char const* GetString(uint32 field, uint32 arrayIndex) const; + + // Creates its own heap allocated copy of _fieldOffsets + // by default _fieldOffets point to a shared array inside Loader to avoid heap allocations + // meaning that only one instance of DB2Record has valid offsets if the file is sparse + void MakePersistent(); + +private: + DB2FileLoaderImpl const& _db2; + uint32 _recordIndex; + unsigned char const* _recordData; + std::size_t* _fieldOffsets; +}; + +#pragma pack(push, 1) +struct DB2RecordCopy +{ + uint32 NewRowId = 0; + uint32 SourceRowId = 0; +}; +#pragma pack(pop) + +class TC_COMMON_API DB2FileLoader +{ +public: + DB2FileLoader(); + ~DB2FileLoader(); + + bool Load(DB2FileSource* source, DB2FileLoadInfo const* loadInfo); + char* AutoProduceData(uint32& count, char**& indexTable, std::vector<char*>& stringPool); + char* AutoProduceStrings(char* dataTable, uint32 locale); + void AutoProduceRecordCopies(uint32 records, char** indexTable, char* dataTable); + + uint32 GetCols() const { return _header.FieldCount; } + uint32 GetRecordCount() const; + uint32 GetRecordCopyCount() const; + uint32 GetTableHash() const { return _header.TableHash; } + uint32 GetLayoutHash() const { return _header.LayoutHash; } + uint32 GetMaxId() const; + + DB2Record GetRecord(uint32 recordNumber) const; + DB2RecordCopy GetRecordCopy(uint32 copyNumber) const; + +private: + DB2FileLoaderImpl* _impl; + DB2Header _header; +}; + +#endif diff --git a/src/server/game/DataStores/DB2LoadInfo.h b/src/server/game/DataStores/DB2LoadInfo.h index e8e93a0d87e..f17ce912a9b 100644 --- a/src/server/game/DataStores/DB2LoadInfo.h +++ b/src/server/game/DataStores/DB2LoadInfo.h @@ -21,12 +21,12 @@ #ifndef DB2LoadInfo_h__ #define DB2LoadInfo_h__ -#include "DB2StorageLoader.h" +#include "DB2DatabaseLoader.h" #include "DB2Metadata.h" struct AchievementLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -46,13 +46,14 @@ struct AchievementLoadInfo { false, FT_BYTE, "MinimumCriteria" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, AchievementMeta::Instance(), HOTFIX_SEL_ACHIEVEMENT }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, AchievementMeta::Instance(), HOTFIX_SEL_ACHIEVEMENT); + return &loadInfo; } }; struct AnimKitLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -61,13 +62,14 @@ struct AnimKitLoadInfo { false, FT_SHORT, "OneShotStopAnimKitID" }, { false, FT_SHORT, "LowDefAnimKitID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, AnimKitMeta::Instance(), HOTFIX_SEL_ANIM_KIT }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, AnimKitMeta::Instance(), HOTFIX_SEL_ANIM_KIT); + return &loadInfo; } }; struct AreaGroupMemberLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -75,13 +77,14 @@ struct AreaGroupMemberLoadInfo { false, FT_SHORT, "AreaGroupID" }, { false, FT_SHORT, "AreaID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, AreaGroupMemberMeta::Instance(), HOTFIX_SEL_AREA_GROUP_MEMBER }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, AreaGroupMemberMeta::Instance(), HOTFIX_SEL_AREA_GROUP_MEMBER); + return &loadInfo; } }; struct AreaTableLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -114,13 +117,14 @@ struct AreaTableLoadInfo { false, FT_BYTE, "WindSettingsID" }, { false, FT_INT, "UWIntroSound" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, AreaTableMeta::Instance(), HOTFIX_SEL_AREA_TABLE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, AreaTableMeta::Instance(), HOTFIX_SEL_AREA_TABLE); + return &loadInfo; } }; struct AreaTriggerLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -142,13 +146,14 @@ struct AreaTriggerLoadInfo { false, FT_BYTE, "Flag" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, AreaTriggerMeta::Instance(), HOTFIX_SEL_AREA_TRIGGER }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, AreaTriggerMeta::Instance(), HOTFIX_SEL_AREA_TRIGGER); + return &loadInfo; } }; struct ArmorLocationLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -159,13 +164,14 @@ struct ArmorLocationLoadInfo { false, FT_FLOAT, "Modifier4" }, { false, FT_FLOAT, "Modifier5" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ArmorLocationMeta::Instance(), HOTFIX_SEL_ARMOR_LOCATION }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ArmorLocationMeta::Instance(), HOTFIX_SEL_ARMOR_LOCATION); + return &loadInfo; } }; struct ArtifactLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -179,13 +185,14 @@ struct ArtifactLoadInfo { false, FT_BYTE, "ArtifactCategoryID" }, { false, FT_BYTE, "Flags" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ArtifactMeta::Instance(), HOTFIX_SEL_ARTIFACT }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ArtifactMeta::Instance(), HOTFIX_SEL_ARTIFACT); + return &loadInfo; } }; struct ArtifactAppearanceLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -205,13 +212,14 @@ struct ArtifactAppearanceLoadInfo { false, FT_INT, "ItemAppearanceID" }, { false, FT_INT, "AltItemAppearanceID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ArtifactAppearanceMeta::Instance(), HOTFIX_SEL_ARTIFACT_APPEARANCE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ArtifactAppearanceMeta::Instance(), HOTFIX_SEL_ARTIFACT_APPEARANCE); + return &loadInfo; } }; struct ArtifactAppearanceSetLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -225,13 +233,14 @@ struct ArtifactAppearanceSetLoadInfo { false, FT_BYTE, "Flags" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ArtifactAppearanceSetMeta::Instance(), HOTFIX_SEL_ARTIFACT_APPEARANCE_SET }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ArtifactAppearanceSetMeta::Instance(), HOTFIX_SEL_ARTIFACT_APPEARANCE_SET); + return &loadInfo; } }; struct ArtifactCategoryLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -239,13 +248,14 @@ struct ArtifactCategoryLoadInfo { false, FT_SHORT, "ArtifactKnowledgeCurrencyID" }, { false, FT_SHORT, "ArtifactKnowledgeMultiplierCurveID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ArtifactCategoryMeta::Instance(), HOTFIX_SEL_ARTIFACT_CATEGORY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ArtifactCategoryMeta::Instance(), HOTFIX_SEL_ARTIFACT_CATEGORY); + return &loadInfo; } }; struct ArtifactPowerLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -257,13 +267,14 @@ struct ArtifactPowerLoadInfo { false, FT_INT, "ID" }, { true, FT_INT, "RelicType" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ArtifactPowerMeta::Instance(), HOTFIX_SEL_ARTIFACT_POWER }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ArtifactPowerMeta::Instance(), HOTFIX_SEL_ARTIFACT_POWER); + return &loadInfo; } }; struct ArtifactPowerLinkLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -271,13 +282,14 @@ struct ArtifactPowerLinkLoadInfo { false, FT_SHORT, "FromArtifactPowerID" }, { false, FT_SHORT, "ToArtifactPowerID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ArtifactPowerLinkMeta::Instance(), HOTFIX_SEL_ARTIFACT_POWER_LINK }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ArtifactPowerLinkMeta::Instance(), HOTFIX_SEL_ARTIFACT_POWER_LINK); + return &loadInfo; } }; struct ArtifactPowerRankLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -288,13 +300,14 @@ struct ArtifactPowerRankLoadInfo { false, FT_SHORT, "Unknown" }, { false, FT_BYTE, "Rank" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ArtifactPowerRankMeta::Instance(), HOTFIX_SEL_ARTIFACT_POWER_RANK }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ArtifactPowerRankMeta::Instance(), HOTFIX_SEL_ARTIFACT_POWER_RANK); + return &loadInfo; } }; struct ArtifactQuestXpLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -310,13 +323,14 @@ struct ArtifactQuestXpLoadInfo { false, FT_INT, "Exp9" }, { false, FT_INT, "Exp10" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ArtifactQuestXPMeta::Instance(), HOTFIX_SEL_ARTIFACT_QUEST_XP }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ArtifactQuestXPMeta::Instance(), HOTFIX_SEL_ARTIFACT_QUEST_XP); + return &loadInfo; } }; struct AuctionHouseLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -326,26 +340,28 @@ struct AuctionHouseLoadInfo { false, FT_BYTE, "DepositRate" }, { false, FT_BYTE, "ConsignmentRate" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, AuctionHouseMeta::Instance(), HOTFIX_SEL_AUCTION_HOUSE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, AuctionHouseMeta::Instance(), HOTFIX_SEL_AUCTION_HOUSE); + return &loadInfo; } }; struct BankBagSlotPricesLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { { false, FT_INT, "ID" }, { false, FT_INT, "Cost" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, BankBagSlotPricesMeta::Instance(), HOTFIX_SEL_BANK_BAG_SLOT_PRICES }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, BankBagSlotPricesMeta::Instance(), HOTFIX_SEL_BANK_BAG_SLOT_PRICES); + return &loadInfo; } }; struct BannedAddonsLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -354,13 +370,14 @@ struct BannedAddonsLoadInfo { false, FT_STRING_NOT_LOCALIZED, "Version" }, { false, FT_BYTE, "Flags" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, BannedAddOnsMeta::Instance(), HOTFIX_SEL_BANNED_ADDONS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, BannedAddOnsMeta::Instance(), HOTFIX_SEL_BANNED_ADDONS); + return &loadInfo; } }; struct BarberShopStyleLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -373,13 +390,14 @@ struct BarberShopStyleLoadInfo { false, FT_BYTE, "Data" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, BarberShopStyleMeta::Instance(), HOTFIX_SEL_BARBER_SHOP_STYLE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, BarberShopStyleMeta::Instance(), HOTFIX_SEL_BARBER_SHOP_STYLE); + return &loadInfo; } }; struct BattlePetBreedQualityLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -387,13 +405,14 @@ struct BattlePetBreedQualityLoadInfo { false, FT_FLOAT, "Modifier" }, { false, FT_BYTE, "Quality" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, BattlePetBreedQualityMeta::Instance(), HOTFIX_SEL_BATTLE_PET_BREED_QUALITY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, BattlePetBreedQualityMeta::Instance(), HOTFIX_SEL_BATTLE_PET_BREED_QUALITY); + return &loadInfo; } }; struct BattlePetBreedStateLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -402,13 +421,14 @@ struct BattlePetBreedStateLoadInfo { false, FT_BYTE, "BreedID" }, { false, FT_BYTE, "State" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, BattlePetBreedStateMeta::Instance(), HOTFIX_SEL_BATTLE_PET_BREED_STATE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, BattlePetBreedStateMeta::Instance(), HOTFIX_SEL_BATTLE_PET_BREED_STATE); + return &loadInfo; } }; struct BattlePetSpeciesLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -422,13 +442,14 @@ struct BattlePetSpeciesLoadInfo { true, FT_BYTE, "Source" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, BattlePetSpeciesMeta::Instance(), HOTFIX_SEL_BATTLE_PET_SPECIES }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, BattlePetSpeciesMeta::Instance(), HOTFIX_SEL_BATTLE_PET_SPECIES); + return &loadInfo; } }; struct BattlePetSpeciesStateLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -437,13 +458,14 @@ struct BattlePetSpeciesStateLoadInfo { false, FT_SHORT, "SpeciesID" }, { false, FT_BYTE, "State" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, BattlePetSpeciesStateMeta::Instance(), HOTFIX_SEL_BATTLE_PET_SPECIES_STATE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, BattlePetSpeciesStateMeta::Instance(), HOTFIX_SEL_BATTLE_PET_SPECIES_STATE); + return &loadInfo; } }; struct BattlemasterListLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -479,13 +501,14 @@ struct BattlemasterListLoadInfo { false, FT_BYTE, "MaxPlayers" }, { false, FT_BYTE, "Flags" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, BattlemasterListMeta::Instance(), HOTFIX_SEL_BATTLEMASTER_LIST }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, BattlemasterListMeta::Instance(), HOTFIX_SEL_BATTLEMASTER_LIST); + return &loadInfo; } }; struct BroadcastTextLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -505,13 +528,14 @@ struct BroadcastTextLoadInfo { false, FT_INT, "SoundID2" }, { false, FT_INT, "PlayerConditionID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, BroadcastTextMeta::Instance(), HOTFIX_SEL_BROADCAST_TEXT }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, BroadcastTextMeta::Instance(), HOTFIX_SEL_BROADCAST_TEXT); + return &loadInfo; } }; struct CharSectionsLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -526,13 +550,14 @@ struct CharSectionsLoadInfo { false, FT_BYTE, "Type" }, { false, FT_BYTE, "Color" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, CharSectionsMeta::Instance(), HOTFIX_SEL_CHAR_SECTIONS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CharSectionsMeta::Instance(), HOTFIX_SEL_CHAR_SECTIONS); + return &loadInfo; } }; struct CharStartOutfitLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -568,13 +593,14 @@ struct CharStartOutfitLoadInfo { false, FT_BYTE, "OutfitID" }, { false, FT_BYTE, "PetFamilyID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, CharStartOutfitMeta::Instance(), HOTFIX_SEL_CHAR_START_OUTFIT }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CharStartOutfitMeta::Instance(), HOTFIX_SEL_CHAR_START_OUTFIT); + return &loadInfo; } }; struct CharTitlesLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -584,13 +610,14 @@ struct CharTitlesLoadInfo { false, FT_SHORT, "MaskID" }, { false, FT_BYTE, "Flags" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, CharTitlesMeta::Instance(), HOTFIX_SEL_CHAR_TITLES }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CharTitlesMeta::Instance(), HOTFIX_SEL_CHAR_TITLES); + return &loadInfo; } }; struct ChatChannelsLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -600,13 +627,14 @@ struct ChatChannelsLoadInfo { false, FT_STRING, "Shortcut" }, { false, FT_BYTE, "FactionGroup" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ChatChannelsMeta::Instance(), HOTFIX_SEL_CHAT_CHANNELS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ChatChannelsMeta::Instance(), HOTFIX_SEL_CHAT_CHANNELS); + return &loadInfo; } }; struct ChrClassesLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -630,13 +658,14 @@ struct ChrClassesLoadInfo { false, FT_BYTE, "Unk1" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ChrClassesMeta::Instance(), HOTFIX_SEL_CHR_CLASSES }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ChrClassesMeta::Instance(), HOTFIX_SEL_CHR_CLASSES); + return &loadInfo; } }; struct ChrClassesXPowerTypesLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -644,13 +673,14 @@ struct ChrClassesXPowerTypesLoadInfo { false, FT_BYTE, "ClassID" }, { false, FT_BYTE, "PowerType" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ChrClassesXPowerTypesMeta::Instance(), HOTFIX_SEL_CHR_CLASSES_X_POWER_TYPES }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ChrClassesXPowerTypesMeta::Instance(), HOTFIX_SEL_CHR_CLASSES_X_POWER_TYPES); + return &loadInfo; } }; struct ChrRacesLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -698,13 +728,14 @@ struct ChrRacesLoadInfo { false, FT_INT, "Unk2" }, { false, FT_INT, "Unk3" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ChrRacesMeta::Instance(), HOTFIX_SEL_CHR_RACES }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ChrRacesMeta::Instance(), HOTFIX_SEL_CHR_RACES); + return &loadInfo; } }; struct ChrSpecializationLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -723,13 +754,14 @@ struct ChrSpecializationLoadInfo { false, FT_INT, "Flags" }, { false, FT_INT, "AnimReplacementSetID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ChrSpecializationMeta::Instance(), HOTFIX_SEL_CHR_SPECIALIZATION }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ChrSpecializationMeta::Instance(), HOTFIX_SEL_CHR_SPECIALIZATION); + return &loadInfo; } }; struct CinematicCameraLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -741,13 +773,14 @@ struct CinematicCameraLoadInfo { false, FT_FLOAT, "OriginFacing" }, { false, FT_SHORT, "SoundID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, CinematicCameraMeta::Instance(), HOTFIX_SEL_CINEMATIC_CAMERA }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CinematicCameraMeta::Instance(), HOTFIX_SEL_CINEMATIC_CAMERA); + return &loadInfo; } }; struct CinematicSequencesLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -762,13 +795,14 @@ struct CinematicSequencesLoadInfo { false, FT_SHORT, "Camera7" }, { false, FT_SHORT, "Camera8" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, CinematicSequencesMeta::Instance(), HOTFIX_SEL_CINEMATIC_SEQUENCES }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CinematicSequencesMeta::Instance(), HOTFIX_SEL_CINEMATIC_SEQUENCES); + return &loadInfo; } }; struct CreatureDisplayInfoLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -797,13 +831,14 @@ struct CreatureDisplayInfoLoadInfo { true, FT_BYTE, "Gender" }, { true, FT_BYTE, "Unk700" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, CreatureDisplayInfoMeta::Instance(), HOTFIX_SEL_CREATURE_DISPLAY_INFO }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CreatureDisplayInfoMeta::Instance(), HOTFIX_SEL_CREATURE_DISPLAY_INFO); + return &loadInfo; } }; struct CreatureDisplayInfoExtraLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -823,13 +858,14 @@ struct CreatureDisplayInfoExtraLoadInfo { false, FT_BYTE, "CustomDisplayOption3" }, { false, FT_BYTE, "Flags" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, CreatureDisplayInfoExtraMeta::Instance(), HOTFIX_SEL_CREATURE_DISPLAY_INFO_EXTRA }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CreatureDisplayInfoExtraMeta::Instance(), HOTFIX_SEL_CREATURE_DISPLAY_INFO_EXTRA); + return &loadInfo; } }; struct CreatureFamilyLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -845,13 +881,14 @@ struct CreatureFamilyLoadInfo { false, FT_BYTE, "MaxScaleLevel" }, { false, FT_BYTE, "PetTalentType" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, CreatureFamilyMeta::Instance(), HOTFIX_SEL_CREATURE_FAMILY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CreatureFamilyMeta::Instance(), HOTFIX_SEL_CREATURE_FAMILY); + return &loadInfo; } }; struct CreatureModelDataLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -890,13 +927,14 @@ struct CreatureModelDataLoadInfo { false, FT_INT, "SoundID" }, { false, FT_INT, "CreatureGeosetDataID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, CreatureModelDataMeta::Instance(), HOTFIX_SEL_CREATURE_MODEL_DATA }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CreatureModelDataMeta::Instance(), HOTFIX_SEL_CREATURE_MODEL_DATA); + return &loadInfo; } }; struct CreatureTypeLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -904,13 +942,14 @@ struct CreatureTypeLoadInfo { false, FT_STRING, "Name" }, { false, FT_BYTE, "Flags" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, CreatureTypeMeta::Instance(), HOTFIX_SEL_CREATURE_TYPE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CreatureTypeMeta::Instance(), HOTFIX_SEL_CREATURE_TYPE); + return &loadInfo; } }; struct CriteriaLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -927,13 +966,14 @@ struct CriteriaLoadInfo { false, FT_BYTE, "Flags" }, { false, FT_BYTE, "EligibilityWorldStateValue" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, CriteriaMeta::Instance(), HOTFIX_SEL_CRITERIA }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CriteriaMeta::Instance(), HOTFIX_SEL_CRITERIA); + return &loadInfo; } }; struct CriteriaTreeLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -946,13 +986,14 @@ struct CriteriaTreeLoadInfo { false, FT_BYTE, "Operator" }, { true, FT_INT, "OrderIndex" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, CriteriaTreeMeta::Instance(), HOTFIX_SEL_CRITERIA_TREE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CriteriaTreeMeta::Instance(), HOTFIX_SEL_CRITERIA_TREE); + return &loadInfo; } }; struct CurrencyTypesLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -969,13 +1010,14 @@ struct CurrencyTypesLoadInfo { false, FT_BYTE, "Quality" }, { false, FT_INT, "SpellWeight" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, CurrencyTypesMeta::Instance(), HOTFIX_SEL_CURRENCY_TYPES }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CurrencyTypesMeta::Instance(), HOTFIX_SEL_CURRENCY_TYPES); + return &loadInfo; } }; struct CurveLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -983,13 +1025,14 @@ struct CurveLoadInfo { false, FT_BYTE, "Type" }, { false, FT_BYTE, "Unused" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, CurveMeta::Instance(), HOTFIX_SEL_CURVE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CurveMeta::Instance(), HOTFIX_SEL_CURVE); + return &loadInfo; } }; struct CurvePointLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -999,13 +1042,14 @@ struct CurvePointLoadInfo { false, FT_SHORT, "CurveID" }, { false, FT_BYTE, "Index" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, CurvePointMeta::Instance(), HOTFIX_SEL_CURVE_POINT }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CurvePointMeta::Instance(), HOTFIX_SEL_CURVE_POINT); + return &loadInfo; } }; struct DestructibleModelDataLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1033,13 +1077,14 @@ struct DestructibleModelDataLoadInfo { false, FT_BYTE, "DoNotHighlight" }, { false, FT_BYTE, "HealEffect" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, DestructibleModelDataMeta::Instance(), HOTFIX_SEL_DESTRUCTIBLE_MODEL_DATA }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, DestructibleModelDataMeta::Instance(), HOTFIX_SEL_DESTRUCTIBLE_MODEL_DATA); + return &loadInfo; } }; struct DifficultyLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1058,13 +1103,14 @@ struct DifficultyLoadInfo { false, FT_BYTE, "ItemBonusTreeModID" }, { false, FT_BYTE, "OrderIndex" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, DifficultyMeta::Instance(), HOTFIX_SEL_DIFFICULTY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, DifficultyMeta::Instance(), HOTFIX_SEL_DIFFICULTY); + return &loadInfo; } }; struct DungeonEncounterLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1078,13 +1124,14 @@ struct DungeonEncounterLoadInfo { false, FT_BYTE, "Flags" }, { true, FT_INT, "OrderIndex" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, DungeonEncounterMeta::Instance(), HOTFIX_SEL_DUNGEON_ENCOUNTER }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, DungeonEncounterMeta::Instance(), HOTFIX_SEL_DUNGEON_ENCOUNTER); + return &loadInfo; } }; struct DurabilityCostsLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1119,26 +1166,28 @@ struct DurabilityCostsLoadInfo { false, FT_SHORT, "ArmorSubClassCost7" }, { false, FT_SHORT, "ArmorSubClassCost8" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, DurabilityCostsMeta::Instance(), HOTFIX_SEL_DURABILITY_COSTS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, DurabilityCostsMeta::Instance(), HOTFIX_SEL_DURABILITY_COSTS); + return &loadInfo; } }; struct DurabilityQualityLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { { false, FT_INT, "ID" }, { false, FT_FLOAT, "QualityMod" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, DurabilityQualityMeta::Instance(), HOTFIX_SEL_DURABILITY_QUALITY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, DurabilityQualityMeta::Instance(), HOTFIX_SEL_DURABILITY_QUALITY); + return &loadInfo; } }; struct EmotesLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1153,13 +1202,14 @@ struct EmotesLoadInfo { true, FT_INT, "ClassMask" }, { true, FT_INT, "RaceMask" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, EmotesMeta::Instance(), HOTFIX_SEL_EMOTES }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, EmotesMeta::Instance(), HOTFIX_SEL_EMOTES); + return &loadInfo; } }; struct EmotesTextLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1167,13 +1217,14 @@ struct EmotesTextLoadInfo { false, FT_STRING, "Name" }, { false, FT_SHORT, "EmoteID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, EmotesTextMeta::Instance(), HOTFIX_SEL_EMOTES_TEXT }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, EmotesTextMeta::Instance(), HOTFIX_SEL_EMOTES_TEXT); + return &loadInfo; } }; struct EmotesTextSoundLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1184,13 +1235,14 @@ struct EmotesTextSoundLoadInfo { false, FT_BYTE, "ClassId" }, { false, FT_INT, "SoundId" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, EmotesTextSoundMeta::Instance(), HOTFIX_SEL_EMOTES_TEXT_SOUND }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, EmotesTextSoundMeta::Instance(), HOTFIX_SEL_EMOTES_TEXT_SOUND); + return &loadInfo; } }; struct FactionLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1227,13 +1279,14 @@ struct FactionLoadInfo { false, FT_BYTE, "Flags" }, { false, FT_BYTE, "FriendshipRepID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, FactionMeta::Instance(), HOTFIX_SEL_FACTION }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, FactionMeta::Instance(), HOTFIX_SEL_FACTION); + return &loadInfo; } }; struct FactionTemplateLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1252,13 +1305,14 @@ struct FactionTemplateLoadInfo { false, FT_BYTE, "FriendMask" }, { false, FT_BYTE, "EnemyMask" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, FactionTemplateMeta::Instance(), HOTFIX_SEL_FACTION_TEMPLATE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, FactionTemplateMeta::Instance(), HOTFIX_SEL_FACTION_TEMPLATE); + return &loadInfo; } }; struct GameobjectsLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1287,13 +1341,14 @@ struct GameobjectsLoadInfo { false, FT_BYTE, "Type" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, GameObjectsMeta::Instance(), HOTFIX_SEL_GAMEOBJECTS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GameObjectsMeta::Instance(), HOTFIX_SEL_GAMEOBJECTS); + return &loadInfo; } }; struct GameobjectDisplayInfoLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1309,13 +1364,14 @@ struct GameobjectDisplayInfoLoadInfo { false, FT_FLOAT, "OverrideNameScale" }, { false, FT_SHORT, "ObjectEffectPackageID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, GameObjectDisplayInfoMeta::Instance(), HOTFIX_SEL_GAMEOBJECT_DISPLAY_INFO }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GameObjectDisplayInfoMeta::Instance(), HOTFIX_SEL_GAMEOBJECT_DISPLAY_INFO); + return &loadInfo; } }; struct GarrAbilityLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1328,13 +1384,14 @@ struct GarrAbilityLoadInfo { false, FT_BYTE, "FollowerTypeID" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, GarrAbilityMeta::Instance(), HOTFIX_SEL_GARR_ABILITY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GarrAbilityMeta::Instance(), HOTFIX_SEL_GARR_ABILITY); + return &loadInfo; } }; struct GarrBuildingLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1364,13 +1421,14 @@ struct GarrBuildingLoadInfo { true, FT_INT, "CostCurrencyAmount" }, { true, FT_INT, "BonusAmount" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, GarrBuildingMeta::Instance(), HOTFIX_SEL_GARR_BUILDING }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GarrBuildingMeta::Instance(), HOTFIX_SEL_GARR_BUILDING); + return &loadInfo; } }; struct GarrBuildingPlotInstLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1381,13 +1439,14 @@ struct GarrBuildingPlotInstLoadInfo { false, FT_BYTE, "GarrBuildingID" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, GarrBuildingPlotInstMeta::Instance(), HOTFIX_SEL_GARR_BUILDING_PLOT_INST }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GarrBuildingPlotInstMeta::Instance(), HOTFIX_SEL_GARR_BUILDING_PLOT_INST); + return &loadInfo; } }; struct GarrClassSpecLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1400,13 +1459,14 @@ struct GarrClassSpecLoadInfo { false, FT_BYTE, "Flags" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, GarrClassSpecMeta::Instance(), HOTFIX_SEL_GARR_CLASS_SPEC }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GarrClassSpecMeta::Instance(), HOTFIX_SEL_GARR_CLASS_SPEC); + return &loadInfo; } }; struct GarrFollowerLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1442,13 +1502,14 @@ struct GarrFollowerLoadInfo { false, FT_BYTE, "AllianceFlavorTextGarrStringID" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, GarrFollowerMeta::Instance(), HOTFIX_SEL_GARR_FOLLOWER }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GarrFollowerMeta::Instance(), HOTFIX_SEL_GARR_FOLLOWER); + return &loadInfo; } }; struct GarrFollowerXAbilityLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1457,13 +1518,14 @@ struct GarrFollowerXAbilityLoadInfo { false, FT_SHORT, "GarrAbilityID" }, { false, FT_BYTE, "FactionIndex" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, GarrFollowerXAbilityMeta::Instance(), HOTFIX_SEL_GARR_FOLLOWER_X_ABILITY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GarrFollowerXAbilityMeta::Instance(), HOTFIX_SEL_GARR_FOLLOWER_X_ABILITY); + return &loadInfo; } }; struct GarrPlotLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1477,13 +1539,14 @@ struct GarrPlotLoadInfo { false, FT_INT, "MinCount" }, { false, FT_INT, "MaxCount" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, GarrPlotMeta::Instance(), HOTFIX_SEL_GARR_PLOT }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GarrPlotMeta::Instance(), HOTFIX_SEL_GARR_PLOT); + return &loadInfo; } }; struct GarrPlotBuildingLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1491,13 +1554,14 @@ struct GarrPlotBuildingLoadInfo { false, FT_BYTE, "GarrPlotID" }, { false, FT_BYTE, "GarrBuildingID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, GarrPlotBuildingMeta::Instance(), HOTFIX_SEL_GARR_PLOT_BUILDING }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GarrPlotBuildingMeta::Instance(), HOTFIX_SEL_GARR_PLOT_BUILDING); + return &loadInfo; } }; struct GarrPlotInstanceLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1505,13 +1569,14 @@ struct GarrPlotInstanceLoadInfo { false, FT_STRING, "Name" }, { false, FT_BYTE, "GarrPlotID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, GarrPlotInstanceMeta::Instance(), HOTFIX_SEL_GARR_PLOT_INSTANCE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GarrPlotInstanceMeta::Instance(), HOTFIX_SEL_GARR_PLOT_INSTANCE); + return &loadInfo; } }; struct GarrSiteLevelLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1527,13 +1592,14 @@ struct GarrSiteLevelLoadInfo { false, FT_BYTE, "MovieID" }, { false, FT_BYTE, "Level2" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, GarrSiteLevelMeta::Instance(), HOTFIX_SEL_GARR_SITE_LEVEL }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GarrSiteLevelMeta::Instance(), HOTFIX_SEL_GARR_SITE_LEVEL); + return &loadInfo; } }; struct GarrSiteLevelPlotInstLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1544,13 +1610,14 @@ struct GarrSiteLevelPlotInstLoadInfo { false, FT_BYTE, "GarrPlotInstanceID" }, { false, FT_BYTE, "Unknown" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, GarrSiteLevelPlotInstMeta::Instance(), HOTFIX_SEL_GARR_SITE_LEVEL_PLOT_INST }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GarrSiteLevelPlotInstMeta::Instance(), HOTFIX_SEL_GARR_SITE_LEVEL_PLOT_INST); + return &loadInfo; } }; struct GemPropertiesLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1559,13 +1626,14 @@ struct GemPropertiesLoadInfo { false, FT_SHORT, "EnchantID" }, { false, FT_SHORT, "MinItemLevel" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, GemPropertiesMeta::Instance(), HOTFIX_SEL_GEM_PROPERTIES }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GemPropertiesMeta::Instance(), HOTFIX_SEL_GEM_PROPERTIES); + return &loadInfo; } }; struct GlyphBindableSpellLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1573,13 +1641,14 @@ struct GlyphBindableSpellLoadInfo { false, FT_INT, "SpellID" }, { false, FT_SHORT, "GlyphPropertiesID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, GlyphBindableSpellMeta::Instance(), HOTFIX_SEL_GLYPH_BINDABLE_SPELL }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GlyphBindableSpellMeta::Instance(), HOTFIX_SEL_GLYPH_BINDABLE_SPELL); + return &loadInfo; } }; struct GlyphPropertiesLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1589,13 +1658,14 @@ struct GlyphPropertiesLoadInfo { false, FT_BYTE, "Type" }, { false, FT_BYTE, "GlyphExclusiveCategoryID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, GlyphPropertiesMeta::Instance(), HOTFIX_SEL_GLYPH_PROPERTIES }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GlyphPropertiesMeta::Instance(), HOTFIX_SEL_GLYPH_PROPERTIES); + return &loadInfo; } }; struct GlyphRequiredSpecLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1603,13 +1673,14 @@ struct GlyphRequiredSpecLoadInfo { false, FT_SHORT, "GlyphPropertiesID" }, { false, FT_SHORT, "ChrSpecializationID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, GlyphRequiredSpecMeta::Instance(), HOTFIX_SEL_GLYPH_REQUIRED_SPEC }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GlyphRequiredSpecMeta::Instance(), HOTFIX_SEL_GLYPH_REQUIRED_SPEC); + return &loadInfo; } }; struct GuildColorBackgroundLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1618,13 +1689,14 @@ struct GuildColorBackgroundLoadInfo { false, FT_BYTE, "Green" }, { false, FT_BYTE, "Blue" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, GuildColorBackgroundMeta::Instance(), HOTFIX_SEL_GUILD_COLOR_BACKGROUND }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GuildColorBackgroundMeta::Instance(), HOTFIX_SEL_GUILD_COLOR_BACKGROUND); + return &loadInfo; } }; struct GuildColorBorderLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1633,13 +1705,14 @@ struct GuildColorBorderLoadInfo { false, FT_BYTE, "Green" }, { false, FT_BYTE, "Blue" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, GuildColorBorderMeta::Instance(), HOTFIX_SEL_GUILD_COLOR_BORDER }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GuildColorBorderMeta::Instance(), HOTFIX_SEL_GUILD_COLOR_BORDER); + return &loadInfo; } }; struct GuildColorEmblemLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1648,26 +1721,28 @@ struct GuildColorEmblemLoadInfo { false, FT_BYTE, "Green" }, { false, FT_BYTE, "Blue" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, GuildColorEmblemMeta::Instance(), HOTFIX_SEL_GUILD_COLOR_EMBLEM }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GuildColorEmblemMeta::Instance(), HOTFIX_SEL_GUILD_COLOR_EMBLEM); + return &loadInfo; } }; struct GuildPerkSpellsLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { { false, FT_INT, "ID" }, { false, FT_INT, "SpellID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, GuildPerkSpellsMeta::Instance(), HOTFIX_SEL_GUILD_PERK_SPELLS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GuildPerkSpellsMeta::Instance(), HOTFIX_SEL_GUILD_PERK_SPELLS); + return &loadInfo; } }; struct HeirloomLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1684,13 +1759,14 @@ struct HeirloomLoadInfo { false, FT_BYTE, "Source" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, HeirloomMeta::Instance(), HOTFIX_SEL_HEIRLOOM }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, HeirloomMeta::Instance(), HOTFIX_SEL_HEIRLOOM); + return &loadInfo; } }; struct HolidaysLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1740,13 +1816,14 @@ struct HolidaysLoadInfo { true, FT_BYTE, "CalendarFilterType" }, { false, FT_BYTE, "Flags" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, HolidaysMeta::Instance(), HOTFIX_SEL_HOLIDAYS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, HolidaysMeta::Instance(), HOTFIX_SEL_HOLIDAYS); + return &loadInfo; } }; struct ImportPriceArmorLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1756,52 +1833,56 @@ struct ImportPriceArmorLoadInfo { false, FT_FLOAT, "MailFactor" }, { false, FT_FLOAT, "PlateFactor" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ImportPriceArmorMeta::Instance(), HOTFIX_SEL_IMPORT_PRICE_ARMOR }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ImportPriceArmorMeta::Instance(), HOTFIX_SEL_IMPORT_PRICE_ARMOR); + return &loadInfo; } }; struct ImportPriceQualityLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { { false, FT_INT, "ID" }, { false, FT_FLOAT, "Factor" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ImportPriceQualityMeta::Instance(), HOTFIX_SEL_IMPORT_PRICE_QUALITY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ImportPriceQualityMeta::Instance(), HOTFIX_SEL_IMPORT_PRICE_QUALITY); + return &loadInfo; } }; struct ImportPriceShieldLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { { false, FT_INT, "ID" }, { false, FT_FLOAT, "Factor" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ImportPriceShieldMeta::Instance(), HOTFIX_SEL_IMPORT_PRICE_SHIELD }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ImportPriceShieldMeta::Instance(), HOTFIX_SEL_IMPORT_PRICE_SHIELD); + return &loadInfo; } }; struct ImportPriceWeaponLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { { false, FT_INT, "ID" }, { false, FT_FLOAT, "Factor" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ImportPriceWeaponMeta::Instance(), HOTFIX_SEL_IMPORT_PRICE_WEAPON }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ImportPriceWeaponMeta::Instance(), HOTFIX_SEL_IMPORT_PRICE_WEAPON); + return &loadInfo; } }; struct ItemLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1815,13 +1896,14 @@ struct ItemLoadInfo { false, FT_BYTE, "Sheath" }, { false, FT_BYTE, "GroupSoundsID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemMeta::Instance(), HOTFIX_SEL_ITEM }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemMeta::Instance(), HOTFIX_SEL_ITEM); + return &loadInfo; } }; struct ItemAppearanceLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1831,13 +1913,14 @@ struct ItemAppearanceLoadInfo { false, FT_INT, "UIOrder" }, { false, FT_BYTE, "ObjectComponentSlot" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemAppearanceMeta::Instance(), HOTFIX_SEL_ITEM_APPEARANCE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemAppearanceMeta::Instance(), HOTFIX_SEL_ITEM_APPEARANCE); + return &loadInfo; } }; struct ItemArmorQualityLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1851,13 +1934,14 @@ struct ItemArmorQualityLoadInfo { false, FT_FLOAT, "QualityMod7" }, { false, FT_SHORT, "ItemLevel" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemArmorQualityMeta::Instance(), HOTFIX_SEL_ITEM_ARMOR_QUALITY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemArmorQualityMeta::Instance(), HOTFIX_SEL_ITEM_ARMOR_QUALITY); + return &loadInfo; } }; struct ItemArmorShieldLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1871,13 +1955,14 @@ struct ItemArmorShieldLoadInfo { false, FT_FLOAT, "Quality7" }, { false, FT_SHORT, "ItemLevel" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemArmorShieldMeta::Instance(), HOTFIX_SEL_ITEM_ARMOR_SHIELD }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemArmorShieldMeta::Instance(), HOTFIX_SEL_ITEM_ARMOR_SHIELD); + return &loadInfo; } }; struct ItemArmorTotalLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1888,26 +1973,28 @@ struct ItemArmorTotalLoadInfo { false, FT_FLOAT, "Value4" }, { false, FT_SHORT, "ItemLevel" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemArmorTotalMeta::Instance(), HOTFIX_SEL_ITEM_ARMOR_TOTAL }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemArmorTotalMeta::Instance(), HOTFIX_SEL_ITEM_ARMOR_TOTAL); + return &loadInfo; } }; struct ItemBagFamilyLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { { false, FT_INT, "ID" }, { false, FT_STRING, "Name" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemBagFamilyMeta::Instance(), HOTFIX_SEL_ITEM_BAG_FAMILY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemBagFamilyMeta::Instance(), HOTFIX_SEL_ITEM_BAG_FAMILY); + return &loadInfo; } }; struct ItemBonusLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1918,26 +2005,28 @@ struct ItemBonusLoadInfo { false, FT_BYTE, "Type" }, { false, FT_BYTE, "Index" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemBonusMeta::Instance(), HOTFIX_SEL_ITEM_BONUS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemBonusMeta::Instance(), HOTFIX_SEL_ITEM_BONUS); + return &loadInfo; } }; struct ItemBonusListLevelDeltaLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { { true, FT_SHORT, "Delta" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemBonusListLevelDeltaMeta::Instance(), HOTFIX_SEL_ITEM_BONUS_LIST_LEVEL_DELTA }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemBonusListLevelDeltaMeta::Instance(), HOTFIX_SEL_ITEM_BONUS_LIST_LEVEL_DELTA); + return &loadInfo; } }; struct ItemBonusTreeNodeLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1947,13 +2036,14 @@ struct ItemBonusTreeNodeLoadInfo { false, FT_SHORT, "BonusListID" }, { false, FT_BYTE, "BonusTreeModID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemBonusTreeNodeMeta::Instance(), HOTFIX_SEL_ITEM_BONUS_TREE_NODE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemBonusTreeNodeMeta::Instance(), HOTFIX_SEL_ITEM_BONUS_TREE_NODE); + return &loadInfo; } }; struct ItemChildEquipmentLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1962,13 +2052,14 @@ struct ItemChildEquipmentLoadInfo { false, FT_INT, "AltItemID" }, { false, FT_BYTE, "AltEquipmentSlot" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemChildEquipmentMeta::Instance(), HOTFIX_SEL_ITEM_CHILD_EQUIPMENT }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemChildEquipmentMeta::Instance(), HOTFIX_SEL_ITEM_CHILD_EQUIPMENT); + return &loadInfo; } }; struct ItemClassLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -1978,26 +2069,28 @@ struct ItemClassLoadInfo { false, FT_BYTE, "OldEnumValue" }, { false, FT_BYTE, "Flags" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemClassMeta::Instance(), HOTFIX_SEL_ITEM_CLASS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemClassMeta::Instance(), HOTFIX_SEL_ITEM_CLASS); + return &loadInfo; } }; struct ItemCurrencyCostLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { { false, FT_INT, "ID" }, { false, FT_INT, "ItemId" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemCurrencyCostMeta::Instance(), HOTFIX_SEL_ITEM_CURRENCY_COST }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemCurrencyCostMeta::Instance(), HOTFIX_SEL_ITEM_CURRENCY_COST); + return &loadInfo; } }; struct ItemDamageAmmoLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2011,13 +2104,14 @@ struct ItemDamageAmmoLoadInfo { false, FT_FLOAT, "DPS7" }, { false, FT_SHORT, "ItemLevel" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemDamageAmmoMeta::Instance(), HOTFIX_SEL_ITEM_DAMAGE_AMMO }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemDamageAmmoMeta::Instance(), HOTFIX_SEL_ITEM_DAMAGE_AMMO); + return &loadInfo; } }; struct ItemDamageOneHandLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2031,13 +2125,14 @@ struct ItemDamageOneHandLoadInfo { false, FT_FLOAT, "DPS7" }, { false, FT_SHORT, "ItemLevel" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemDamageOneHandMeta::Instance(), HOTFIX_SEL_ITEM_DAMAGE_ONE_HAND }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemDamageOneHandMeta::Instance(), HOTFIX_SEL_ITEM_DAMAGE_ONE_HAND); + return &loadInfo; } }; struct ItemDamageOneHandCasterLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2051,13 +2146,14 @@ struct ItemDamageOneHandCasterLoadInfo { false, FT_FLOAT, "DPS7" }, { false, FT_SHORT, "ItemLevel" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemDamageOneHandCasterMeta::Instance(), HOTFIX_SEL_ITEM_DAMAGE_ONE_HAND_CASTER }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemDamageOneHandCasterMeta::Instance(), HOTFIX_SEL_ITEM_DAMAGE_ONE_HAND_CASTER); + return &loadInfo; } }; struct ItemDamageTwoHandLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2071,13 +2167,14 @@ struct ItemDamageTwoHandLoadInfo { false, FT_FLOAT, "DPS7" }, { false, FT_SHORT, "ItemLevel" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemDamageTwoHandMeta::Instance(), HOTFIX_SEL_ITEM_DAMAGE_TWO_HAND }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemDamageTwoHandMeta::Instance(), HOTFIX_SEL_ITEM_DAMAGE_TWO_HAND); + return &loadInfo; } }; struct ItemDamageTwoHandCasterLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2091,13 +2188,14 @@ struct ItemDamageTwoHandCasterLoadInfo { false, FT_FLOAT, "DPS7" }, { false, FT_SHORT, "ItemLevel" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemDamageTwoHandCasterMeta::Instance(), HOTFIX_SEL_ITEM_DAMAGE_TWO_HAND_CASTER }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemDamageTwoHandCasterMeta::Instance(), HOTFIX_SEL_ITEM_DAMAGE_TWO_HAND_CASTER); + return &loadInfo; } }; struct ItemDisenchantLootLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2109,13 +2207,14 @@ struct ItemDisenchantLootLoadInfo { true, FT_BYTE, "ItemSubClass" }, { false, FT_BYTE, "ItemQuality" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemDisenchantLootMeta::Instance(), HOTFIX_SEL_ITEM_DISENCHANT_LOOT }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemDisenchantLootMeta::Instance(), HOTFIX_SEL_ITEM_DISENCHANT_LOOT); + return &loadInfo; } }; struct ItemEffectLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2130,13 +2229,14 @@ struct ItemEffectLoadInfo { false, FT_BYTE, "OrderIndex" }, { false, FT_BYTE, "Trigger" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemEffectMeta::Instance(), HOTFIX_SEL_ITEM_EFFECT }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemEffectMeta::Instance(), HOTFIX_SEL_ITEM_EFFECT); + return &loadInfo; } }; struct ItemExtendedCostLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2168,13 +2268,14 @@ struct ItemExtendedCostLoadInfo { false, FT_BYTE, "RequirementFlags" }, { false, FT_BYTE, "RequiredAchievement" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemExtendedCostMeta::Instance(), HOTFIX_SEL_ITEM_EXTENDED_COST }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemExtendedCostMeta::Instance(), HOTFIX_SEL_ITEM_EXTENDED_COST); + return &loadInfo; } }; struct ItemLimitCategoryLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2183,13 +2284,14 @@ struct ItemLimitCategoryLoadInfo { false, FT_BYTE, "Quantity" }, { false, FT_BYTE, "Flags" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemLimitCategoryMeta::Instance(), HOTFIX_SEL_ITEM_LIMIT_CATEGORY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemLimitCategoryMeta::Instance(), HOTFIX_SEL_ITEM_LIMIT_CATEGORY); + return &loadInfo; } }; struct ItemModifiedAppearanceLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2200,13 +2302,14 @@ struct ItemModifiedAppearanceLoadInfo { false, FT_BYTE, "SourceType" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemModifiedAppearanceMeta::Instance(), HOTFIX_SEL_ITEM_MODIFIED_APPEARANCE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemModifiedAppearanceMeta::Instance(), HOTFIX_SEL_ITEM_MODIFIED_APPEARANCE); + return &loadInfo; } }; struct ItemPriceBaseLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2215,13 +2318,14 @@ struct ItemPriceBaseLoadInfo { false, FT_FLOAT, "WeaponFactor" }, { false, FT_SHORT, "ItemLevel" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemPriceBaseMeta::Instance(), HOTFIX_SEL_ITEM_PRICE_BASE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemPriceBaseMeta::Instance(), HOTFIX_SEL_ITEM_PRICE_BASE); + return &loadInfo; } }; struct ItemRandomPropertiesLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2233,13 +2337,14 @@ struct ItemRandomPropertiesLoadInfo { false, FT_SHORT, "Enchantment4" }, { false, FT_SHORT, "Enchantment5" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemRandomPropertiesMeta::Instance(), HOTFIX_SEL_ITEM_RANDOM_PROPERTIES }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemRandomPropertiesMeta::Instance(), HOTFIX_SEL_ITEM_RANDOM_PROPERTIES); + return &loadInfo; } }; struct ItemRandomSuffixLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2256,13 +2361,14 @@ struct ItemRandomSuffixLoadInfo { false, FT_SHORT, "AllocationPct4" }, { false, FT_SHORT, "AllocationPct5" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemRandomSuffixMeta::Instance(), HOTFIX_SEL_ITEM_RANDOM_SUFFIX }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemRandomSuffixMeta::Instance(), HOTFIX_SEL_ITEM_RANDOM_SUFFIX); + return &loadInfo; } }; struct ItemSearchNameLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2283,13 +2389,14 @@ struct ItemSearchNameLoadInfo { false, FT_BYTE, "RequiredLevel" }, { true, FT_INT, "AllowableClass" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemSearchNameMeta::Instance(), HOTFIX_SEL_ITEM_SEARCH_NAME }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemSearchNameMeta::Instance(), HOTFIX_SEL_ITEM_SEARCH_NAME); + return &loadInfo; } }; struct ItemSetLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2316,13 +2423,14 @@ struct ItemSetLoadInfo { false, FT_INT, "RequiredSkill" }, { false, FT_INT, "Flags" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemSetMeta::Instance(), HOTFIX_SEL_ITEM_SET }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemSetMeta::Instance(), HOTFIX_SEL_ITEM_SET); + return &loadInfo; } }; struct ItemSetSpellLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2332,13 +2440,14 @@ struct ItemSetSpellLoadInfo { false, FT_SHORT, "ChrSpecID" }, { false, FT_BYTE, "Threshold" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemSetSpellMeta::Instance(), HOTFIX_SEL_ITEM_SET_SPELL }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemSetSpellMeta::Instance(), HOTFIX_SEL_ITEM_SET_SPELL); + return &loadInfo; } }; struct ItemSparseLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2447,13 +2556,14 @@ struct ItemSparseLoadInfo { false, FT_BYTE, "ArtifactID" }, { false, FT_BYTE, "RequiredExpansion" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemSparseMeta::Instance(), HOTFIX_SEL_ITEM_SPARSE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemSparseMeta::Instance(), HOTFIX_SEL_ITEM_SPARSE); + return &loadInfo; } }; struct ItemSpecLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2465,13 +2575,14 @@ struct ItemSpecLoadInfo { false, FT_BYTE, "PrimaryStat" }, { false, FT_BYTE, "SecondaryStat" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemSpecMeta::Instance(), HOTFIX_SEL_ITEM_SPEC }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemSpecMeta::Instance(), HOTFIX_SEL_ITEM_SPEC); + return &loadInfo; } }; struct ItemSpecOverrideLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2479,13 +2590,14 @@ struct ItemSpecOverrideLoadInfo { false, FT_INT, "ItemID" }, { false, FT_SHORT, "SpecID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemSpecOverrideMeta::Instance(), HOTFIX_SEL_ITEM_SPEC_OVERRIDE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemSpecOverrideMeta::Instance(), HOTFIX_SEL_ITEM_SPEC_OVERRIDE); + return &loadInfo; } }; struct ItemUpgradeLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2496,13 +2608,14 @@ struct ItemUpgradeLoadInfo { false, FT_BYTE, "ItemUpgradePathID" }, { false, FT_BYTE, "ItemLevelBonus" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemUpgradeMeta::Instance(), HOTFIX_SEL_ITEM_UPGRADE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemUpgradeMeta::Instance(), HOTFIX_SEL_ITEM_UPGRADE); + return &loadInfo; } }; struct ItemXBonusTreeLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2510,13 +2623,14 @@ struct ItemXBonusTreeLoadInfo { false, FT_INT, "ItemID" }, { false, FT_SHORT, "BonusTreeID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ItemXBonusTreeMeta::Instance(), HOTFIX_SEL_ITEM_X_BONUS_TREE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ItemXBonusTreeMeta::Instance(), HOTFIX_SEL_ITEM_X_BONUS_TREE); + return &loadInfo; } }; struct KeyChainLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2554,13 +2668,14 @@ struct KeyChainLoadInfo { false, FT_BYTE, "Key31" }, { false, FT_BYTE, "Key32" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, KeyChainMeta::Instance(), HOTFIX_SEL_KEY_CHAIN }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, KeyChainMeta::Instance(), HOTFIX_SEL_KEY_CHAIN); + return &loadInfo; } }; struct LfgDungeonsLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2597,13 +2712,14 @@ struct LfgDungeonsLoadInfo { false, FT_BYTE, "MentorCharLevel" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, LfgDungeonsMeta::Instance(), HOTFIX_SEL_LFG_DUNGEONS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, LfgDungeonsMeta::Instance(), HOTFIX_SEL_LFG_DUNGEONS); + return &loadInfo; } }; struct LightLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2623,13 +2739,14 @@ struct LightLoadInfo { false, FT_SHORT, "LightParamsID7" }, { false, FT_SHORT, "LightParamsID8" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, LightMeta::Instance(), HOTFIX_SEL_LIGHT }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, LightMeta::Instance(), HOTFIX_SEL_LIGHT); + return &loadInfo; } }; struct LiquidTypeLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2685,13 +2802,14 @@ struct LiquidTypeLoadInfo { false, FT_BYTE, "DepthTexCount6" }, { false, FT_INT, "SoundID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, LiquidTypeMeta::Instance(), HOTFIX_SEL_LIQUID_TYPE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, LiquidTypeMeta::Instance(), HOTFIX_SEL_LIQUID_TYPE); + return &loadInfo; } }; struct LockLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2729,26 +2847,28 @@ struct LockLoadInfo { false, FT_BYTE, "Action7" }, { false, FT_BYTE, "Action8" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, LockMeta::Instance(), HOTFIX_SEL_LOCK }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, LockMeta::Instance(), HOTFIX_SEL_LOCK); + return &loadInfo; } }; struct MailTemplateLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { { false, FT_INT, "ID" }, { false, FT_STRING, "Body" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, MailTemplateMeta::Instance(), HOTFIX_SEL_MAIL_TEMPLATE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, MailTemplateMeta::Instance(), HOTFIX_SEL_MAIL_TEMPLATE); + return &loadInfo; } }; struct MapLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2775,13 +2895,14 @@ struct MapLoadInfo { false, FT_BYTE, "MaxPlayers" }, { false, FT_BYTE, "TimeOffset" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, MapMeta::Instance(), HOTFIX_SEL_MAP }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, MapMeta::Instance(), HOTFIX_SEL_MAP); + return &loadInfo; } }; struct MapDifficultyLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2795,13 +2916,14 @@ struct MapDifficultyLoadInfo { false, FT_BYTE, "ItemBonusTreeModID" }, { false, FT_INT, "Context" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, MapDifficultyMeta::Instance(), HOTFIX_SEL_MAP_DIFFICULTY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, MapDifficultyMeta::Instance(), HOTFIX_SEL_MAP_DIFFICULTY); + return &loadInfo; } }; struct ModifierTreeLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2814,13 +2936,14 @@ struct ModifierTreeLoadInfo { false, FT_BYTE, "Operator" }, { false, FT_BYTE, "Amount" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ModifierTreeMeta::Instance(), HOTFIX_SEL_MODIFIER_TREE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ModifierTreeMeta::Instance(), HOTFIX_SEL_MODIFIER_TREE); + return &loadInfo; } }; struct MountLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2836,13 +2959,14 @@ struct MountLoadInfo { false, FT_BYTE, "Source" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, MountMeta::Instance(), HOTFIX_SEL_MOUNT }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, MountMeta::Instance(), HOTFIX_SEL_MOUNT); + return &loadInfo; } }; struct MountCapabilityLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2855,13 +2979,14 @@ struct MountCapabilityLoadInfo { false, FT_INT, "ID" }, { false, FT_INT, "RequiredAura" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, MountCapabilityMeta::Instance(), HOTFIX_SEL_MOUNT_CAPABILITY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, MountCapabilityMeta::Instance(), HOTFIX_SEL_MOUNT_CAPABILITY); + return &loadInfo; } }; struct MountTypeXCapabilityLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2870,13 +2995,14 @@ struct MountTypeXCapabilityLoadInfo { false, FT_SHORT, "MountCapabilityID" }, { false, FT_BYTE, "OrderIndex" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, MountTypeXCapabilityMeta::Instance(), HOTFIX_SEL_MOUNT_TYPE_X_CAPABILITY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, MountTypeXCapabilityMeta::Instance(), HOTFIX_SEL_MOUNT_TYPE_X_CAPABILITY); + return &loadInfo; } }; struct MovieLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2886,13 +3012,14 @@ struct MovieLoadInfo { false, FT_BYTE, "Volume" }, { false, FT_BYTE, "KeyID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, MovieMeta::Instance(), HOTFIX_SEL_MOVIE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, MovieMeta::Instance(), HOTFIX_SEL_MOVIE); + return &loadInfo; } }; struct NameGenLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2901,13 +3028,14 @@ struct NameGenLoadInfo { false, FT_BYTE, "Race" }, { false, FT_BYTE, "Sex" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, NameGenMeta::Instance(), HOTFIX_SEL_NAME_GEN }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, NameGenMeta::Instance(), HOTFIX_SEL_NAME_GEN); + return &loadInfo; } }; struct NamesProfanityLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2915,26 +3043,28 @@ struct NamesProfanityLoadInfo { false, FT_STRING_NOT_LOCALIZED, "Name" }, { true, FT_BYTE, "Language" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, NamesProfanityMeta::Instance(), HOTFIX_SEL_NAMES_PROFANITY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, NamesProfanityMeta::Instance(), HOTFIX_SEL_NAMES_PROFANITY); + return &loadInfo; } }; struct NamesReservedLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { { false, FT_INT, "ID" }, { false, FT_STRING_NOT_LOCALIZED, "Name" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, NamesReservedMeta::Instance(), HOTFIX_SEL_NAMES_RESERVED }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, NamesReservedMeta::Instance(), HOTFIX_SEL_NAMES_RESERVED); + return &loadInfo; } }; struct NamesReservedLocaleLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2942,13 +3072,14 @@ struct NamesReservedLocaleLoadInfo { false, FT_STRING_NOT_LOCALIZED, "Name" }, { false, FT_BYTE, "LocaleMask" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, NamesReservedLocaleMeta::Instance(), HOTFIX_SEL_NAMES_RESERVED }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, NamesReservedLocaleMeta::Instance(), HOTFIX_SEL_NAMES_RESERVED); + return &loadInfo; } }; struct OverrideSpellDataLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2966,26 +3097,28 @@ struct OverrideSpellDataLoadInfo { false, FT_INT, "PlayerActionbarFileDataID" }, { false, FT_BYTE, "Flags" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, OverrideSpellDataMeta::Instance(), HOTFIX_SEL_OVERRIDE_SPELL_DATA }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, OverrideSpellDataMeta::Instance(), HOTFIX_SEL_OVERRIDE_SPELL_DATA); + return &loadInfo; } }; struct PhaseLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { { false, FT_INT, "ID" }, { false, FT_SHORT, "Flags" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, PhaseMeta::Instance(), HOTFIX_SEL_PHASE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, PhaseMeta::Instance(), HOTFIX_SEL_PHASE); + return &loadInfo; } }; struct PhaseXPhaseGroupLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -2993,13 +3126,14 @@ struct PhaseXPhaseGroupLoadInfo { false, FT_SHORT, "PhaseID" }, { false, FT_SHORT, "PhaseGroupID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, PhaseXPhaseGroupMeta::Instance(), HOTFIX_SEL_PHASE_X_PHASE_GROUP }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, PhaseXPhaseGroupMeta::Instance(), HOTFIX_SEL_PHASE_X_PHASE_GROUP); + return &loadInfo; } }; struct PlayerConditionLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3150,13 +3284,14 @@ struct PlayerConditionLoadInfo { true, FT_INT, "Unknown7001" }, { true, FT_INT, "Unknown7002" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, PlayerConditionMeta::Instance(), HOTFIX_SEL_PLAYER_CONDITION }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, PlayerConditionMeta::Instance(), HOTFIX_SEL_PLAYER_CONDITION); + return &loadInfo; } }; struct PowerDisplayLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3167,13 +3302,14 @@ struct PowerDisplayLoadInfo { false, FT_BYTE, "Green" }, { false, FT_BYTE, "Blue" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, PowerDisplayMeta::Instance(), HOTFIX_SEL_POWER_DISPLAY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, PowerDisplayMeta::Instance(), HOTFIX_SEL_POWER_DISPLAY); + return &loadInfo; } }; struct PowerTypeLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3191,13 +3327,14 @@ struct PowerTypeLoadInfo { true, FT_BYTE, "RegenerationMax" }, { false, FT_BYTE, "UIModifier" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, PowerTypeMeta::Instance(), HOTFIX_SEL_POWER_TYPE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, PowerTypeMeta::Instance(), HOTFIX_SEL_POWER_TYPE); + return &loadInfo; } }; struct PvpDifficultyLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3207,13 +3344,14 @@ struct PvpDifficultyLoadInfo { false, FT_BYTE, "MinLevel" }, { false, FT_BYTE, "MaxLevel" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, PvpDifficultyMeta::Instance(), HOTFIX_SEL_PVP_DIFFICULTY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, PvpDifficultyMeta::Instance(), HOTFIX_SEL_PVP_DIFFICULTY); + return &loadInfo; } }; struct QuestFactionRewardLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3229,13 +3367,14 @@ struct QuestFactionRewardLoadInfo { true, FT_SHORT, "QuestRewFactionValue9" }, { true, FT_SHORT, "QuestRewFactionValue10" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, QuestFactionRewardMeta::Instance(), HOTFIX_SEL_QUEST_FACTION_REWARD }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, QuestFactionRewardMeta::Instance(), HOTFIX_SEL_QUEST_FACTION_REWARD); + return &loadInfo; } }; struct QuestMoneyRewardLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3251,13 +3390,14 @@ struct QuestMoneyRewardLoadInfo { false, FT_INT, "Money9" }, { false, FT_INT, "Money10" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, QuestMoneyRewardMeta::Instance(), HOTFIX_SEL_QUEST_MONEY_REWARD }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, QuestMoneyRewardMeta::Instance(), HOTFIX_SEL_QUEST_MONEY_REWARD); + return &loadInfo; } }; struct QuestPackageItemLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3267,13 +3407,14 @@ struct QuestPackageItemLoadInfo { false, FT_BYTE, "ItemCount" }, { false, FT_BYTE, "FilterType" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, QuestPackageItemMeta::Instance(), HOTFIX_SEL_QUEST_PACKAGE_ITEM }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, QuestPackageItemMeta::Instance(), HOTFIX_SEL_QUEST_PACKAGE_ITEM); + return &loadInfo; } }; struct QuestSortLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3281,26 +3422,28 @@ struct QuestSortLoadInfo { false, FT_STRING, "SortName" }, { false, FT_BYTE, "SortOrder" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, QuestSortMeta::Instance(), HOTFIX_SEL_QUEST_SORT }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, QuestSortMeta::Instance(), HOTFIX_SEL_QUEST_SORT); + return &loadInfo; } }; struct QuestV2LoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { { false, FT_INT, "ID" }, { false, FT_SHORT, "UniqueBitFlag" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, QuestV2Meta::Instance(), HOTFIX_SEL_QUEST_V2 }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, QuestV2Meta::Instance(), HOTFIX_SEL_QUEST_V2); + return &loadInfo; } }; struct QuestXpLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3316,13 +3459,14 @@ struct QuestXpLoadInfo { false, FT_SHORT, "Exp9" }, { false, FT_SHORT, "Exp10" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, QuestXPMeta::Instance(), HOTFIX_SEL_QUEST_XP }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, QuestXPMeta::Instance(), HOTFIX_SEL_QUEST_XP); + return &loadInfo; } }; struct RandPropPointsLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3343,13 +3487,14 @@ struct RandPropPointsLoadInfo { false, FT_INT, "UncommonPropertiesPoints4" }, { false, FT_INT, "UncommonPropertiesPoints5" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, RandPropPointsMeta::Instance(), HOTFIX_SEL_RAND_PROP_POINTS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, RandPropPointsMeta::Instance(), HOTFIX_SEL_RAND_PROP_POINTS); + return &loadInfo; } }; struct RulesetItemUpgradeLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3357,13 +3502,14 @@ struct RulesetItemUpgradeLoadInfo { false, FT_INT, "ItemID" }, { false, FT_SHORT, "ItemUpgradeID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, RulesetItemUpgradeMeta::Instance(), HOTFIX_SEL_RULESET_ITEM_UPGRADE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, RulesetItemUpgradeMeta::Instance(), HOTFIX_SEL_RULESET_ITEM_UPGRADE); + return &loadInfo; } }; struct ScalingStatDistributionLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3372,13 +3518,14 @@ struct ScalingStatDistributionLoadInfo { false, FT_INT, "MinLevel" }, { false, FT_INT, "MaxLevel" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ScalingStatDistributionMeta::Instance(), HOTFIX_SEL_SCALING_STAT_DISTRIBUTION }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ScalingStatDistributionMeta::Instance(), HOTFIX_SEL_SCALING_STAT_DISTRIBUTION); + return &loadInfo; } }; struct ScenarioLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3388,13 +3535,14 @@ struct ScenarioLoadInfo { false, FT_BYTE, "Flags" }, { false, FT_BYTE, "Type" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ScenarioMeta::Instance(), HOTFIX_SEL_SCENARIO }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ScenarioMeta::Instance(), HOTFIX_SEL_SCENARIO); + return &loadInfo; } }; struct ScenarioStepLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3409,13 +3557,14 @@ struct ScenarioStepLoadInfo { false, FT_BYTE, "Flags" }, { false, FT_INT, "BonusRequiredStepID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ScenarioStepMeta::Instance(), HOTFIX_SEL_SCENARIO_STEP }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ScenarioStepMeta::Instance(), HOTFIX_SEL_SCENARIO_STEP); + return &loadInfo; } }; struct SceneScriptLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3425,26 +3574,28 @@ struct SceneScriptLoadInfo { false, FT_SHORT, "PrevScriptId" }, { false, FT_SHORT, "NextScriptId" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SceneScriptMeta::Instance(), HOTFIX_SEL_SCENE_SCRIPT }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SceneScriptMeta::Instance(), HOTFIX_SEL_SCENE_SCRIPT); + return &loadInfo; } }; struct SceneScriptPackageLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { { false, FT_INT, "ID" }, { false, FT_STRING_NOT_LOCALIZED, "Name" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SceneScriptPackageMeta::Instance(), HOTFIX_SEL_SCENE_SCRIPT_PACKAGE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SceneScriptPackageMeta::Instance(), HOTFIX_SEL_SCENE_SCRIPT_PACKAGE); + return &loadInfo; } }; struct SkillLineLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3458,13 +3609,14 @@ struct SkillLineLoadInfo { false, FT_BYTE, "CanLink" }, { false, FT_INT, "ParentSkillLineID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SkillLineMeta::Instance(), HOTFIX_SEL_SKILL_LINE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SkillLineMeta::Instance(), HOTFIX_SEL_SKILL_LINE); + return &loadInfo; } }; struct SkillLineAbilityLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3483,13 +3635,14 @@ struct SkillLineAbilityLoadInfo { false, FT_BYTE, "NumSkillUps" }, { true, FT_INT, "ClassMask" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SkillLineAbilityMeta::Instance(), HOTFIX_SEL_SKILL_LINE_ABILITY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SkillLineAbilityMeta::Instance(), HOTFIX_SEL_SKILL_LINE_ABILITY); + return &loadInfo; } }; struct SkillRaceClassInfoLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3502,13 +3655,14 @@ struct SkillRaceClassInfoLoadInfo { false, FT_BYTE, "MinLevel" }, { true, FT_INT, "ClassMask" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SkillRaceClassInfoMeta::Instance(), HOTFIX_SEL_SKILL_RACE_CLASS_INFO }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SkillRaceClassInfoMeta::Instance(), HOTFIX_SEL_SKILL_RACE_CLASS_INFO); + return &loadInfo; } }; struct SoundKitLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3530,13 +3684,14 @@ struct SoundKitLoadInfo { false, FT_BYTE, "Unk700" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SoundKitMeta::Instance(), HOTFIX_SEL_SOUND_KIT }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SoundKitMeta::Instance(), HOTFIX_SEL_SOUND_KIT); + return &loadInfo; } }; struct SpecializationSpellsLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3547,13 +3702,14 @@ struct SpecializationSpellsLoadInfo { false, FT_BYTE, "OrderIndex" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpecializationSpellsMeta::Instance(), HOTFIX_SEL_SPECIALIZATION_SPELLS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpecializationSpellsMeta::Instance(), HOTFIX_SEL_SPECIALIZATION_SPELLS); + return &loadInfo; } }; struct SpellLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3565,13 +3721,14 @@ struct SpellLoadInfo { false, FT_INT, "ID" }, { false, FT_INT, "DescriptionVariablesID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellMeta::Instance(), HOTFIX_SEL_SPELL }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellMeta::Instance(), HOTFIX_SEL_SPELL); + return &loadInfo; } }; struct SpellAuraOptionsLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3585,13 +3742,14 @@ struct SpellAuraOptionsLoadInfo { false, FT_BYTE, "ProcChance" }, { false, FT_BYTE, "SpellProcsPerMinuteID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellAuraOptionsMeta::Instance(), HOTFIX_SEL_SPELL_AURA_OPTIONS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellAuraOptionsMeta::Instance(), HOTFIX_SEL_SPELL_AURA_OPTIONS); + return &loadInfo; } }; struct SpellAuraRestrictionsLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3607,13 +3765,14 @@ struct SpellAuraRestrictionsLoadInfo { false, FT_BYTE, "ExcludeCasterAuraState" }, { false, FT_BYTE, "ExcludeTargetAuraState" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellAuraRestrictionsMeta::Instance(), HOTFIX_SEL_SPELL_AURA_RESTRICTIONS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellAuraRestrictionsMeta::Instance(), HOTFIX_SEL_SPELL_AURA_RESTRICTIONS); + return &loadInfo; } }; struct SpellCastTimesLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3622,13 +3781,14 @@ struct SpellCastTimesLoadInfo { true, FT_INT, "MinCastTime" }, { true, FT_SHORT, "CastTimePerLevel" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellCastTimesMeta::Instance(), HOTFIX_SEL_SPELL_CAST_TIMES }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellCastTimesMeta::Instance(), HOTFIX_SEL_SPELL_CAST_TIMES); + return &loadInfo; } }; struct SpellCastingRequirementsLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3641,13 +3801,14 @@ struct SpellCastingRequirementsLoadInfo { false, FT_BYTE, "MinReputation" }, { false, FT_BYTE, "RequiredAuraVision" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellCastingRequirementsMeta::Instance(), HOTFIX_SEL_SPELL_CASTING_REQUIREMENTS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellCastingRequirementsMeta::Instance(), HOTFIX_SEL_SPELL_CASTING_REQUIREMENTS); + return &loadInfo; } }; struct SpellCategoriesLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3662,13 +3823,14 @@ struct SpellCategoriesLoadInfo { false, FT_BYTE, "Mechanic" }, { false, FT_BYTE, "PreventionType" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellCategoriesMeta::Instance(), HOTFIX_SEL_SPELL_CATEGORIES }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellCategoriesMeta::Instance(), HOTFIX_SEL_SPELL_CATEGORIES); + return &loadInfo; } }; struct SpellCategoryLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3680,13 +3842,14 @@ struct SpellCategoryLoadInfo { false, FT_BYTE, "MaxCharges" }, { false, FT_INT, "ChargeCategoryType" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellCategoryMeta::Instance(), HOTFIX_SEL_SPELL_CATEGORY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellCategoryMeta::Instance(), HOTFIX_SEL_SPELL_CATEGORY); + return &loadInfo; } }; struct SpellClassOptionsLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3699,13 +3862,14 @@ struct SpellClassOptionsLoadInfo { false, FT_BYTE, "SpellClassSet" }, { false, FT_INT, "ModalNextSpell" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellClassOptionsMeta::Instance(), HOTFIX_SEL_SPELL_CLASS_OPTIONS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellClassOptionsMeta::Instance(), HOTFIX_SEL_SPELL_CLASS_OPTIONS); + return &loadInfo; } }; struct SpellCooldownsLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3716,13 +3880,14 @@ struct SpellCooldownsLoadInfo { false, FT_INT, "StartRecoveryTime" }, { false, FT_BYTE, "DifficultyID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellCooldownsMeta::Instance(), HOTFIX_SEL_SPELL_COOLDOWNS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellCooldownsMeta::Instance(), HOTFIX_SEL_SPELL_COOLDOWNS); + return &loadInfo; } }; struct SpellDurationLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3731,13 +3896,14 @@ struct SpellDurationLoadInfo { true, FT_INT, "MaxDuration" }, { true, FT_SHORT, "DurationPerLevel" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellDurationMeta::Instance(), HOTFIX_SEL_SPELL_DURATION }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellDurationMeta::Instance(), HOTFIX_SEL_SPELL_DURATION); + return &loadInfo; } }; struct SpellEffectLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3773,13 +3939,14 @@ struct SpellEffectLoadInfo { false, FT_INT, "EffectIndex" }, { false, FT_INT, "EffectAttributes" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellEffectMeta::Instance(), HOTFIX_SEL_SPELL_EFFECT }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellEffectMeta::Instance(), HOTFIX_SEL_SPELL_EFFECT); + return &loadInfo; } }; struct SpellEffectScalingLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3789,13 +3956,14 @@ struct SpellEffectScalingLoadInfo { false, FT_FLOAT, "ResourceCoefficient" }, { false, FT_INT, "SpellEffectID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellEffectScalingMeta::Instance(), HOTFIX_SEL_SPELL_EFFECT_SCALING }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellEffectScalingMeta::Instance(), HOTFIX_SEL_SPELL_EFFECT_SCALING); + return &loadInfo; } }; struct SpellEquippedItemsLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3805,26 +3973,28 @@ struct SpellEquippedItemsLoadInfo { true, FT_INT, "EquippedItemSubClassMask" }, { true, FT_BYTE, "EquippedItemClass" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellEquippedItemsMeta::Instance(), HOTFIX_SEL_SPELL_EQUIPPED_ITEMS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellEquippedItemsMeta::Instance(), HOTFIX_SEL_SPELL_EQUIPPED_ITEMS); + return &loadInfo; } }; struct SpellFocusObjectLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { { false, FT_INT, "ID" }, { false, FT_STRING, "Name" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellFocusObjectMeta::Instance(), HOTFIX_SEL_SPELL_FOCUS_OBJECT }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellFocusObjectMeta::Instance(), HOTFIX_SEL_SPELL_FOCUS_OBJECT); + return &loadInfo; } }; struct SpellInterruptsLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3837,13 +4007,14 @@ struct SpellInterruptsLoadInfo { false, FT_SHORT, "InterruptFlags" }, { false, FT_BYTE, "DifficultyID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellInterruptsMeta::Instance(), HOTFIX_SEL_SPELL_INTERRUPTS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellInterruptsMeta::Instance(), HOTFIX_SEL_SPELL_INTERRUPTS); + return &loadInfo; } }; struct SpellItemEnchantmentLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3876,13 +4047,14 @@ struct SpellItemEnchantmentLoadInfo { true, FT_BYTE, "ScalingClassRestricted" }, { false, FT_INT, "PlayerConditionID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellItemEnchantmentMeta::Instance(), HOTFIX_SEL_SPELL_ITEM_ENCHANTMENT }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellItemEnchantmentMeta::Instance(), HOTFIX_SEL_SPELL_ITEM_ENCHANTMENT); + return &loadInfo; } }; struct SpellItemEnchantmentConditionLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3918,13 +4090,14 @@ struct SpellItemEnchantmentConditionLoadInfo { false, FT_INT, "LTOperand4" }, { false, FT_INT, "LTOperand5" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellItemEnchantmentConditionMeta::Instance(), HOTFIX_SEL_SPELL_ITEM_ENCHANTMENT_CONDITION }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellItemEnchantmentConditionMeta::Instance(), HOTFIX_SEL_SPELL_ITEM_ENCHANTMENT_CONDITION); + return &loadInfo; } }; struct SpellLearnSpellLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3933,13 +4106,14 @@ struct SpellLearnSpellLoadInfo { false, FT_INT, "SpellID" }, { false, FT_INT, "OverridesSpellID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellLearnSpellMeta::Instance(), HOTFIX_SEL_SPELL_LEARN_SPELL }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellLearnSpellMeta::Instance(), HOTFIX_SEL_SPELL_LEARN_SPELL); + return &loadInfo; } }; struct SpellLevelsLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3951,13 +4125,14 @@ struct SpellLevelsLoadInfo { false, FT_BYTE, "DifficultyID" }, { false, FT_BYTE, "MaxUsableLevel" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellLevelsMeta::Instance(), HOTFIX_SEL_SPELL_LEVELS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellLevelsMeta::Instance(), HOTFIX_SEL_SPELL_LEVELS); + return &loadInfo; } }; struct SpellMiscLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -3985,13 +4160,14 @@ struct SpellMiscLoadInfo { false, FT_SHORT, "ActiveIconID" }, { false, FT_BYTE, "SchoolMask" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellMiscMeta::Instance(), HOTFIX_SEL_SPELL_MISC }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellMiscMeta::Instance(), HOTFIX_SEL_SPELL_MISC); + return &loadInfo; } }; struct SpellPowerLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4010,13 +4186,14 @@ struct SpellPowerLoadInfo { false, FT_INT, "PowerDisplayID" }, { false, FT_INT, "UnitPowerBarID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellPowerMeta::Instance(), HOTFIX_SEL_SPELL_POWER }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellPowerMeta::Instance(), HOTFIX_SEL_SPELL_POWER); + return &loadInfo; } }; struct SpellPowerDifficultyLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4024,13 +4201,14 @@ struct SpellPowerDifficultyLoadInfo { false, FT_BYTE, "PowerIndex" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellPowerDifficultyMeta::Instance(), HOTFIX_SEL_SPELL_POWER_DIFFICULTY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellPowerDifficultyMeta::Instance(), HOTFIX_SEL_SPELL_POWER_DIFFICULTY); + return &loadInfo; } }; struct SpellProcsPerMinuteLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4038,13 +4216,14 @@ struct SpellProcsPerMinuteLoadInfo { false, FT_FLOAT, "BaseProcRate" }, { false, FT_BYTE, "Flags" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellProcsPerMinuteMeta::Instance(), HOTFIX_SEL_SPELL_PROCS_PER_MINUTE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellProcsPerMinuteMeta::Instance(), HOTFIX_SEL_SPELL_PROCS_PER_MINUTE); + return &loadInfo; } }; struct SpellProcsPerMinuteModLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4054,13 +4233,14 @@ struct SpellProcsPerMinuteModLoadInfo { false, FT_BYTE, "Type" }, { false, FT_BYTE, "SpellProcsPerMinuteID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellProcsPerMinuteModMeta::Instance(), HOTFIX_SEL_SPELL_PROCS_PER_MINUTE_MOD }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellProcsPerMinuteModMeta::Instance(), HOTFIX_SEL_SPELL_PROCS_PER_MINUTE_MOD); + return &loadInfo; } }; struct SpellRadiusLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4070,13 +4250,14 @@ struct SpellRadiusLoadInfo { false, FT_FLOAT, "RadiusMin" }, { false, FT_FLOAT, "RadiusMax" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellRadiusMeta::Instance(), HOTFIX_SEL_SPELL_RADIUS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellRadiusMeta::Instance(), HOTFIX_SEL_SPELL_RADIUS); + return &loadInfo; } }; struct SpellRangeLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4089,13 +4270,14 @@ struct SpellRangeLoadInfo { false, FT_STRING, "DisplayNameShort" }, { false, FT_BYTE, "Flags" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellRangeMeta::Instance(), HOTFIX_SEL_SPELL_RANGE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellRangeMeta::Instance(), HOTFIX_SEL_SPELL_RANGE); + return &loadInfo; } }; struct SpellReagentsLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4118,13 +4300,14 @@ struct SpellReagentsLoadInfo { false, FT_SHORT, "ReagentCount7" }, { false, FT_SHORT, "ReagentCount8" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellReagentsMeta::Instance(), HOTFIX_SEL_SPELL_REAGENTS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellReagentsMeta::Instance(), HOTFIX_SEL_SPELL_REAGENTS); + return &loadInfo; } }; struct SpellScalingLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4135,13 +4318,14 @@ struct SpellScalingLoadInfo { false, FT_INT, "MinScalingLevel" }, { false, FT_INT, "MaxScalingLevel" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellScalingMeta::Instance(), HOTFIX_SEL_SPELL_SCALING }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellScalingMeta::Instance(), HOTFIX_SEL_SPELL_SCALING); + return &loadInfo; } }; struct SpellShapeshiftLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4153,13 +4337,14 @@ struct SpellShapeshiftLoadInfo { false, FT_INT, "ShapeshiftMask2" }, { false, FT_BYTE, "StanceBarOrder" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellShapeshiftMeta::Instance(), HOTFIX_SEL_SPELL_SHAPESHIFT }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellShapeshiftMeta::Instance(), HOTFIX_SEL_SPELL_SHAPESHIFT); + return &loadInfo; } }; struct SpellShapeshiftFormLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4185,13 +4370,14 @@ struct SpellShapeshiftFormLoadInfo { true, FT_BYTE, "CreatureType" }, { false, FT_BYTE, "BonusActionBar" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellShapeshiftFormMeta::Instance(), HOTFIX_SEL_SPELL_SHAPESHIFT_FORM }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellShapeshiftFormMeta::Instance(), HOTFIX_SEL_SPELL_SHAPESHIFT_FORM); + return &loadInfo; } }; struct SpellTargetRestrictionsLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4205,13 +4391,14 @@ struct SpellTargetRestrictionsLoadInfo { false, FT_BYTE, "MaxAffectedTargets" }, { false, FT_INT, "MaxTargetLevel" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellTargetRestrictionsMeta::Instance(), HOTFIX_SEL_SPELL_TARGET_RESTRICTIONS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellTargetRestrictionsMeta::Instance(), HOTFIX_SEL_SPELL_TARGET_RESTRICTIONS); + return &loadInfo; } }; struct SpellTotemsLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4222,13 +4409,14 @@ struct SpellTotemsLoadInfo { false, FT_SHORT, "RequiredTotemCategoryID1" }, { false, FT_SHORT, "RequiredTotemCategoryID2" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellTotemsMeta::Instance(), HOTFIX_SEL_SPELL_TOTEMS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellTotemsMeta::Instance(), HOTFIX_SEL_SPELL_TOTEMS); + return &loadInfo; } }; struct SpellXSpellVisualLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4243,13 +4431,14 @@ struct SpellXSpellVisualLoadInfo { false, FT_BYTE, "Priority" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SpellXSpellVisualMeta::Instance(), HOTFIX_SEL_SPELL_X_SPELL_VISUAL }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SpellXSpellVisualMeta::Instance(), HOTFIX_SEL_SPELL_X_SPELL_VISUAL); + return &loadInfo; } }; struct SummonPropertiesLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4260,13 +4449,14 @@ struct SummonPropertiesLoadInfo { true, FT_INT, "Type" }, { true, FT_INT, "Slot" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, SummonPropertiesMeta::Instance(), HOTFIX_SEL_SUMMON_PROPERTIES }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, SummonPropertiesMeta::Instance(), HOTFIX_SEL_SUMMON_PROPERTIES); + return &loadInfo; } }; struct TactKeyLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4288,13 +4478,14 @@ struct TactKeyLoadInfo { false, FT_BYTE, "Key15" }, { false, FT_BYTE, "Key16" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, TactKeyMeta::Instance(), HOTFIX_SEL_TACT_KEY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, TactKeyMeta::Instance(), HOTFIX_SEL_TACT_KEY); + return &loadInfo; } }; struct TalentLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4310,13 +4501,14 @@ struct TalentLoadInfo { false, FT_BYTE, "CategoryMask2" }, { false, FT_BYTE, "ClassID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, TalentMeta::Instance(), HOTFIX_SEL_TALENT }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, TalentMeta::Instance(), HOTFIX_SEL_TALENT); + return &loadInfo; } }; struct TaxiNodesLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4334,13 +4526,14 @@ struct TaxiNodesLoadInfo { false, FT_BYTE, "Flags" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, TaxiNodesMeta::Instance(), HOTFIX_SEL_TAXI_NODES }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, TaxiNodesMeta::Instance(), HOTFIX_SEL_TAXI_NODES); + return &loadInfo; } }; struct TaxiPathLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4349,13 +4542,14 @@ struct TaxiPathLoadInfo { false, FT_INT, "ID" }, { false, FT_INT, "Cost" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, TaxiPathMeta::Instance(), HOTFIX_SEL_TAXI_PATH }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, TaxiPathMeta::Instance(), HOTFIX_SEL_TAXI_PATH); + return &loadInfo; } }; struct TaxiPathNodeLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4371,13 +4565,14 @@ struct TaxiPathNodeLoadInfo { false, FT_BYTE, "Flags" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, TaxiPathNodeMeta::Instance(), HOTFIX_SEL_TAXI_PATH_NODE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, TaxiPathNodeMeta::Instance(), HOTFIX_SEL_TAXI_PATH_NODE); + return &loadInfo; } }; struct TotemCategoryLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4386,13 +4581,14 @@ struct TotemCategoryLoadInfo { false, FT_INT, "CategoryMask" }, { false, FT_BYTE, "CategoryType" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, TotemCategoryMeta::Instance(), HOTFIX_SEL_TOTEM_CATEGORY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, TotemCategoryMeta::Instance(), HOTFIX_SEL_TOTEM_CATEGORY); + return &loadInfo; } }; struct ToyLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4402,13 +4598,14 @@ struct ToyLoadInfo { false, FT_BYTE, "CategoryFilter" }, { false, FT_INT, "ID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, ToyMeta::Instance(), HOTFIX_SEL_TOY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, ToyMeta::Instance(), HOTFIX_SEL_TOY); + return &loadInfo; } }; struct TransportAnimationLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4420,13 +4617,14 @@ struct TransportAnimationLoadInfo { false, FT_FLOAT, "PosZ" }, { false, FT_BYTE, "SequenceID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, TransportAnimationMeta::Instance(), HOTFIX_SEL_TRANSPORT_ANIMATION }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, TransportAnimationMeta::Instance(), HOTFIX_SEL_TRANSPORT_ANIMATION); + return &loadInfo; } }; struct TransportRotationLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4438,13 +4636,14 @@ struct TransportRotationLoadInfo { false, FT_FLOAT, "Z" }, { false, FT_FLOAT, "W" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, TransportRotationMeta::Instance(), HOTFIX_SEL_TRANSPORT_ROTATION }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, TransportRotationMeta::Instance(), HOTFIX_SEL_TRANSPORT_ROTATION); + return &loadInfo; } }; struct UnitPowerBarLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4476,13 +4675,14 @@ struct UnitPowerBarLoadInfo { false, FT_INT, "MinPower" }, { false, FT_INT, "MaxPower" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, UnitPowerBarMeta::Instance(), HOTFIX_SEL_UNIT_POWER_BAR }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, UnitPowerBarMeta::Instance(), HOTFIX_SEL_UNIT_POWER_BAR); + return &loadInfo; } }; struct VehicleLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4528,13 +4728,14 @@ struct VehicleLoadInfo { false, FT_BYTE, "FlagsB" }, { false, FT_BYTE, "UILocomotionType" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, VehicleMeta::Instance(), HOTFIX_SEL_VEHICLE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, VehicleMeta::Instance(), HOTFIX_SEL_VEHICLE); + return &loadInfo; } }; struct VehicleSeatLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4605,13 +4806,14 @@ struct VehicleSeatLoadInfo { false, FT_INT, "EnterUISoundID" }, { false, FT_INT, "ExitUISoundID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, VehicleSeatMeta::Instance(), HOTFIX_SEL_VEHICLE_SEAT }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, VehicleSeatMeta::Instance(), HOTFIX_SEL_VEHICLE_SEAT); + return &loadInfo; } }; struct WmoAreaTableLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4631,13 +4833,14 @@ struct WmoAreaTableLoadInfo { false, FT_INT, "ID" }, { false, FT_INT, "UWZoneMusic" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, WMOAreaTableMeta::Instance(), HOTFIX_SEL_WMO_AREA_TABLE }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, WMOAreaTableMeta::Instance(), HOTFIX_SEL_WMO_AREA_TABLE); + return &loadInfo; } }; struct WorldMapAreaLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4659,13 +4862,14 @@ struct WorldMapAreaLoadInfo { false, FT_INT, "ID" }, { false, FT_INT, "PlayerConditionID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, WorldMapAreaMeta::Instance(), HOTFIX_SEL_WORLD_MAP_AREA }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, WorldMapAreaMeta::Instance(), HOTFIX_SEL_WORLD_MAP_AREA); + return &loadInfo; } }; struct WorldMapOverlayLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4687,13 +4891,14 @@ struct WorldMapOverlayLoadInfo { false, FT_INT, "PlayerConditionID" }, { false, FT_INT, "Flags" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, WorldMapOverlayMeta::Instance(), HOTFIX_SEL_WORLD_MAP_OVERLAY }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, WorldMapOverlayMeta::Instance(), HOTFIX_SEL_WORLD_MAP_OVERLAY); + return &loadInfo; } }; struct WorldMapTransformsLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4714,13 +4919,14 @@ struct WorldMapTransformsLoadInfo { false, FT_SHORT, "NewAreaID" }, { false, FT_BYTE, "Flags" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, WorldMapTransformsMeta::Instance(), HOTFIX_SEL_WORLD_MAP_TRANSFORMS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, WorldMapTransformsMeta::Instance(), HOTFIX_SEL_WORLD_MAP_TRANSFORMS); + return &loadInfo; } }; struct WorldSafeLocsLoadInfo { - static DB2LoadInfo Instance() + static DB2LoadInfo const* Instance() { static DB2FieldMeta const fields[] = { @@ -4732,7 +4938,8 @@ struct WorldSafeLocsLoadInfo { false, FT_STRING, "AreaName" }, { false, FT_SHORT, "MapID" }, }; - return { &fields[0], std::extent<decltype(fields)>::value, WorldSafeLocsMeta::Instance(), HOTFIX_SEL_WORLD_SAFE_LOCS }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, WorldSafeLocsMeta::Instance(), HOTFIX_SEL_WORLD_SAFE_LOCS); + return &loadInfo; } }; diff --git a/src/server/shared/DataStores/DB2DatabaseLoader.cpp b/src/server/shared/DataStores/DB2DatabaseLoader.cpp new file mode 100644 index 00000000000..a19b8a5b389 --- /dev/null +++ b/src/server/shared/DataStores/DB2DatabaseLoader.cpp @@ -0,0 +1,301 @@ +/* + * Copyright (C) 2008-2017 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 "DB2DatabaseLoader.h" +#include "Database/DatabaseEnv.h" +#include "DB2Meta.h" + +DB2LoadInfo::DB2LoadInfo() : DB2FileLoadInfo() +{ +} + +DB2LoadInfo::DB2LoadInfo(DB2FieldMeta const* fields, std::size_t fieldCount, DB2Meta const* meta, HotfixDatabaseStatements statement) + : DB2FileLoadInfo(fields, fieldCount, meta), Statement(statement) +{ +} + +static char const* nullStr = ""; + +char* DB2DatabaseLoader::Load(uint32& records, char**& indexTable, char*& stringHolders, std::vector<char*>& stringPool) +{ + // Even though this query is executed only once, prepared statement is used to send data from mysql server in binary format + PreparedQueryResult result = HotfixDatabase.Query(HotfixDatabase.GetPreparedStatement(_loadInfo->Statement)); + if (!result) + return nullptr; + + if (_loadInfo->Meta->GetDbFieldCount() != result->GetFieldCount()) + return nullptr; + + // get struct size and index pos + uint32 indexField = _loadInfo->Meta->GetDbIndexField(); + uint32 recordSize = _loadInfo->Meta->GetRecordSize(); + + // we store flat holders pool as single memory block + std::size_t stringFields = _loadInfo->GetStringFieldCount(false); + std::size_t localizedStringFields = _loadInfo->GetStringFieldCount(true); + + // each string field at load have array of string for each locale + std::size_t stringHoldersRecordPoolSize = localizedStringFields * sizeof(LocalizedString) + (stringFields - localizedStringFields) * sizeof(char*); + + if (stringFields) + { + std::size_t stringHoldersPoolSize = stringHoldersRecordPoolSize * result->GetRowCount(); + stringHolders = new char[stringHoldersPoolSize]; + + // DB2 strings expected to have at least empty string + for (std::size_t i = 0; i < stringHoldersPoolSize / sizeof(char*); ++i) + ((char const**)stringHolders)[i] = nullStr; + } + else + stringHolders = nullptr; + + // Resize index table + // database query *MUST* contain ORDER BY `index_field` DESC clause + uint32 indexTableSize = (*result)[indexField].GetUInt32() + 1; + if (indexTableSize < records) + indexTableSize = records; + + if (indexTableSize > records) + { + char** tmpIdxTable = new char*[indexTableSize]; + memset(tmpIdxTable, 0, indexTableSize * sizeof(char*)); + memcpy(tmpIdxTable, indexTable, records * sizeof(char*)); + delete[] indexTable; + indexTable = tmpIdxTable; + } + + char* tempDataTable = new char[result->GetRowCount() * recordSize]; + uint32* newIndexes = new uint32[result->GetRowCount()]; + uint32 rec = 0; + uint32 newRecords = 0; + + do + { + Field* fields = result->Fetch(); + uint32 offset = 0; + uint32 stringFieldOffset = 0; + + uint32 indexValue = fields[indexField].GetUInt32(); + + // Attempt to overwrite existing data + char* dataValue = indexTable[indexValue]; + if (!dataValue) + { + newIndexes[newRecords] = indexValue; + dataValue = &tempDataTable[newRecords++ * recordSize]; + } + + uint32 f = 0; + if (!_loadInfo->Meta->HasIndexFieldInData()) + { + *((uint32*)(&dataValue[offset])) = indexValue; + offset += 4; + ++f; + } + + for (uint32 x = 0; x < _loadInfo->Meta->FieldCount; ++x) + { + for (uint32 z = 0; z < _loadInfo->Meta->ArraySizes[x]; ++z) + { + switch (_loadInfo->TypesString[f]) + { + case FT_FLOAT: + *((float*)(&dataValue[offset])) = fields[f].GetFloat(); + offset += 4; + break; + case FT_INT: + *((int32*)(&dataValue[offset])) = fields[f].GetInt32(); + offset += 4; + break; + case FT_BYTE: + *((int8*)(&dataValue[offset])) = fields[f].GetInt8(); + offset += 1; + break; + case FT_SHORT: + *((int16*)(&dataValue[offset])) = fields[f].GetInt16(); + offset += 2; + break; + case FT_STRING: + { + LocalizedString** slot = (LocalizedString**)(&dataValue[offset]); + *slot = (LocalizedString*)(&stringHolders[stringHoldersRecordPoolSize * rec + stringFieldOffset]); + ASSERT(*slot); + + // Value in database in main table field must be for enUS locale + if (char* str = AddString(&(*slot)->Str[LOCALE_enUS], fields[f].GetString())) + stringPool.push_back(str); + + stringFieldOffset += sizeof(LocalizedString); + offset += sizeof(char*); + break; + } + case FT_STRING_NOT_LOCALIZED: + { + char const** slot = (char const**)(&dataValue[offset]); + *slot = (char*)(&stringHolders[stringHoldersRecordPoolSize * rec + stringFieldOffset]); + ASSERT(*slot); + + // Value in database in main table field must be for enUS locale + if (char* str = AddString(slot, fields[f].GetString())) + stringPool.push_back(str); + + stringFieldOffset += sizeof(char*); + offset += sizeof(char*); + break; + } + default: + ASSERT(false, "Unknown format character '%c' found in %s meta", _loadInfo->TypesString[x], _storageName.c_str()); + break; + } + ++f; + } + } + + ASSERT(offset == recordSize); + ++rec; + } while (result->NextRow()); + + if (!newRecords) + { + delete[] tempDataTable; + delete[] newIndexes; + return nullptr; + } + + // Compact new data table to only contain new records not previously loaded from file + char* dataTable = new char[newRecords * recordSize]; + memcpy(dataTable, tempDataTable, newRecords * recordSize); + + // insert new records to index table + for (uint32 i = 0; i < newRecords; ++i) + indexTable[newIndexes[i]] = &dataTable[i * recordSize]; + + delete[] tempDataTable; + delete[] newIndexes; + + records = indexTableSize; + + return dataTable; +} + +void DB2DatabaseLoader::LoadStrings(uint32 locale, uint32 records, char** indexTable, std::vector<char*>& stringPool) +{ + PreparedStatement* stmt = HotfixDatabase.GetPreparedStatement(HotfixDatabaseStatements(_loadInfo->Statement + 1)); + stmt->setString(0, localeNames[locale]); + PreparedQueryResult result = HotfixDatabase.Query(stmt); + if (!result) + return; + + std::size_t stringFields = _loadInfo->GetStringFieldCount(true); + if (result->GetFieldCount() != stringFields + 1 /*ID*/) + return; + + uint32 fieldCount = _loadInfo->Meta->FieldCount; + uint32 recordSize = _loadInfo->Meta->GetRecordSize(); + + do + { + Field* fields = result->Fetch(); + uint32 offset = 0; + uint32 stringFieldNumInRecord = 0; + uint32 indexValue = fields[0].GetUInt32(); + + if (indexValue >= records) + continue; + + // Attempt to overwrite existing data + if (char* dataValue = indexTable[indexValue]) + { + uint32 fieldIndex = 0; + if (!_loadInfo->Meta->HasIndexFieldInData()) + { + offset += 4; + ++fieldIndex; + } + + for (uint32 x = 0; x < fieldCount; ++x) + { + for (uint32 z = 0; z < _loadInfo->Meta->ArraySizes[x]; ++z) + { + switch (_loadInfo->TypesString[fieldIndex]) + { + case FT_FLOAT: + case FT_INT: + offset += 4; + break; + case FT_BYTE: + offset += 1; + break; + case FT_SHORT: + offset += 2; + break; + case FT_STRING: + { + // fill only not filled entries + LocalizedString* db2str = *(LocalizedString**)(&dataValue[offset]); + if (db2str->Str[locale] == nullStr) + if (char* str = AddString(&db2str->Str[locale], fields[1 + stringFieldNumInRecord].GetString())) + stringPool.push_back(str); + + ++stringFieldNumInRecord; + offset += sizeof(LocalizedString*); + break; + } + case FT_STRING_NOT_LOCALIZED: + offset += sizeof(char*); + break; + default: + ASSERT(false, "Unknown format character '%c' found in %s meta", _loadInfo->TypesString[x], _storageName.c_str()); + break; + } + ++fieldIndex; + } + } + + ASSERT(offset == recordSize); + } + else + TC_LOG_ERROR("sql.sql", "Hotfix locale table for storage %s references row that does not exist %u locale %s!", _storageName.c_str(), indexValue, localeNames[locale]); + + } while (result->NextRow()); + + return; +} + +char* DB2DatabaseLoader::AddString(char const** holder, std::string const& value) +{ + if (!value.empty()) + { + std::size_t existingLength = strlen(*holder); + if (existingLength >= value.length()) + { + // Reuse existing storage if there is enough space + char* str = const_cast<char*>(*holder); + memcpy(str, value.c_str(), value.length()); + str[value.length()] = '\0'; + return nullptr; + } + + char* str = new char[value.length() + 1]; + memcpy(str, value.c_str(), value.length()); + str[value.length()] = '\0'; + *holder = str; + return str; + } + + return nullptr; +} diff --git a/src/server/shared/DataStores/DB2StorageLoader.h b/src/server/shared/DataStores/DB2DatabaseLoader.h index 62361edcedd..f288b46859b 100644 --- a/src/server/shared/DataStores/DB2StorageLoader.h +++ b/src/server/shared/DataStores/DB2DatabaseLoader.h @@ -15,67 +15,18 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef DB2_FILE_LOADER_H -#define DB2_FILE_LOADER_H +#ifndef DB2_DATABASE_LOADER_H +#define DB2_DATABASE_LOADER_H -#include "Define.h" +#include "DB2FileLoader.h" #include "Implementation/HotfixDatabase.h" -class DB2FileLoaderImpl; -struct DB2Meta; -struct DB2FieldMeta; - -#pragma pack(push, 1) -struct DB2Header -{ - uint32 Signature; - uint32 RecordCount; - uint32 FieldCount; - uint32 RecordSize; - uint32 StringTableSize; - uint32 TableHash; - uint32 LayoutHash; - uint32 MinId; - uint32 MaxId; - uint32 Locale; - uint32 CopyTableSize; - uint16 Flags; - int16 IndexField; -}; -#pragma pack(pop) - -struct TC_SHARED_API DB2LoadInfo +struct TC_SHARED_API DB2LoadInfo : public DB2FileLoadInfo { DB2LoadInfo(); DB2LoadInfo(DB2FieldMeta const* fields, std::size_t fieldCount, DB2Meta const* meta, HotfixDatabaseStatements statement); - uint32 GetStringFieldCount(bool localizedOnly) const; - - DB2FieldMeta const* Fields; - std::size_t FieldCount; - DB2Meta const* Meta; HotfixDatabaseStatements Statement; - std::string TypesString; -}; - -class TC_SHARED_API DB2FileLoader -{ -public: - DB2FileLoader(); - ~DB2FileLoader(); - - bool Load(char const* filename, DB2LoadInfo const* loadInfo); - char* AutoProduceData(uint32& count, char**& indexTable, std::vector<char*>& stringPool); - char* AutoProduceStrings(char* dataTable, uint32 locale); - void AutoProduceRecordCopies(uint32 records, char** indexTable, char* dataTable); - - uint32 GetCols() const { return _header.FieldCount; } - uint32 GetTableHash() const { return _header.TableHash; } - uint32 GetLayoutHash() const { return _header.LayoutHash; } - -private: - DB2FileLoaderImpl* _impl; - DB2Header _header; }; class TC_SHARED_API DB2DatabaseLoader diff --git a/src/server/shared/DataStores/DB2StorageLoader.cpp b/src/server/shared/DataStores/DB2StorageLoader.cpp deleted file mode 100644 index 11caca97afb..00000000000 --- a/src/server/shared/DataStores/DB2StorageLoader.cpp +++ /dev/null @@ -1,1257 +0,0 @@ -/* - * Copyright (C) 2008-2017 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 "DB2StorageLoader.h" -#include "Database/DatabaseEnv.h" -#include "DB2Meta.h" -#include "Utilities/ByteConverter.h" - -DB2LoadInfo::DB2LoadInfo() : Fields(nullptr), FieldCount(0), Meta(nullptr), Statement(MAX_HOTFIXDATABASE_STATEMENTS) -{ -} - -DB2LoadInfo::DB2LoadInfo(DB2FieldMeta const* fields, std::size_t fieldCount, DB2Meta const* meta, HotfixDatabaseStatements statement) - : Fields(fields), FieldCount(fieldCount), Meta(meta), Statement(statement) -{ - TypesString.reserve(FieldCount); - for (std::size_t i = 0; i < FieldCount; ++i) - TypesString += char(Fields[i].Type); -} - -uint32 DB2LoadInfo::GetStringFieldCount(bool localizedOnly) const -{ - uint32 stringFields = 0; - for (std::size_t i = 0; i < TypesString.length(); ++i) - if (TypesString[i] == FT_STRING || (TypesString[i] == FT_STRING_NOT_LOCALIZED && !localizedOnly)) - ++stringFields; - - return stringFields; -} - -class DB2FileLoaderImpl -{ -public: - virtual ~DB2FileLoaderImpl() { } - virtual bool Load(char const* filename, FILE* file, DB2LoadInfo const* loadInfo, DB2Header const* header) = 0; - virtual char* AutoProduceData(uint32& count, char**& indexTable, std::vector<char*>& stringPool) = 0; - virtual char* AutoProduceStrings(char* dataTable, uint32 locale) = 0; - virtual void AutoProduceRecordCopies(uint32 records, char** indexTable, char* dataTable) = 0; -}; - -class DB2FileLoaderRegularImpl : public DB2FileLoaderImpl -{ -public: - DB2FileLoaderRegularImpl(); - ~DB2FileLoaderRegularImpl(); - - bool Load(char const* filename, FILE* file, DB2LoadInfo const* loadInfo, DB2Header const* header) override; - char* AutoProduceData(uint32& count, char**& indexTable, std::vector<char*>& stringPool) override; - char* AutoProduceStrings(char* dataTable, uint32 locale) override; - void AutoProduceRecordCopies(uint32 records, char** indexTable, char* dataTable) override; - -private: - class Record - { - public: - float getFloat(uint32 field, uint32 arrayIndex) const; - uint32 getUInt(uint32 field, uint32 arrayIndex, bool isSigned) const; - uint8 getUInt8(uint32 field, uint32 arrayIndex) const; - uint16 getUInt16(uint32 field, uint32 arrayIndex) const; - char const* getString(uint32 field, uint32 arrayIndex) const; - - private: - uint16 GetOffset(uint32 field) const; - uint16 GetByteSize(uint32 field) const; - uint32 GetVarInt(uint32 field, uint32 arrayIndex, bool isSigned) const; - - Record(DB2FileLoaderRegularImpl &file_, unsigned char *offset_); - unsigned char *offset; - DB2FileLoaderRegularImpl &file; - - friend class DB2FileLoaderRegularImpl; - }; - - // Get record by id - Record getRecord(size_t id); - -#pragma pack(push, 1) - struct FieldEntry - { - uint16 UnusedBits; - uint16 Offset; - }; -#pragma pack(pop) - - char const* fileName; - DB2LoadInfo const* _loadInfo; - DB2Header const* _header; - - unsigned char* data; - unsigned char* stringTable; - unsigned char* idTable; - uint32 idTableSize; - unsigned char* copyTable; - FieldEntry* fields; -}; - -class DB2FileLoaderSparseImpl : public DB2FileLoaderImpl -{ -public: - DB2FileLoaderSparseImpl(); - ~DB2FileLoaderSparseImpl(); - - bool Load(char const* filename, FILE* file, DB2LoadInfo const* loadInfo, DB2Header const* header) override; - char* AutoProduceData(uint32& records, char**& indexTable, std::vector<char*>& stringPool) override; - char* AutoProduceStrings(char* dataTable, uint32 locale) override; - void AutoProduceRecordCopies(uint32 /*records*/, char** /*indexTable*/, char* /*dataTable*/) override { } - -private: -#pragma pack(push, 1) - struct OffsetTableEntry - { - uint32 FileOffset; - uint16 RecordSize; - }; - struct FieldEntry - { - uint16 UnusedBits; - uint16 Offset; - }; -#pragma pack(pop) - - char const* fileName; - DB2LoadInfo const* _loadInfo; - DB2Header const* _header; - FieldEntry* fields; - - uint32 dataStart; - unsigned char* data; - OffsetTableEntry* offsets; -}; - -float DB2FileLoaderRegularImpl::Record::getFloat(uint32 field, uint32 arrayIndex) const -{ - ASSERT(field < file._header->FieldCount); - float val = *reinterpret_cast<float*>(offset + GetOffset(field) + arrayIndex * sizeof(float)); - EndianConvert(val); - return val; -} - -uint32 DB2FileLoaderRegularImpl::Record::getUInt(uint32 field, uint32 arrayIndex, bool isSigned) const -{ - ASSERT(field < file._header->FieldCount); - return GetVarInt(field, arrayIndex, isSigned); -} - -uint8 DB2FileLoaderRegularImpl::Record::getUInt8(uint32 field, uint32 arrayIndex) const -{ - ASSERT(field < file._header->FieldCount); - ASSERT(GetByteSize(field) == 1); - return *reinterpret_cast<uint8*>(offset + GetOffset(field) + arrayIndex * sizeof(uint8)); -} - -uint16 DB2FileLoaderRegularImpl::Record::getUInt16(uint32 field, uint32 arrayIndex) const -{ - ASSERT(field < file._header->FieldCount); - ASSERT(GetByteSize(field) == 2); - uint16 val = *reinterpret_cast<uint16*>(offset + GetOffset(field) + arrayIndex * sizeof(uint16)); - EndianConvert(val); - return val; -} - -char const* DB2FileLoaderRegularImpl::Record::getString(uint32 field, uint32 arrayIndex) const -{ - ASSERT(field < file._header->FieldCount); - uint32 stringOffset = *reinterpret_cast<uint32*>(offset + GetOffset(field) + arrayIndex * sizeof(uint32)); - EndianConvert(stringOffset); - ASSERT(stringOffset < file._header->StringTableSize); - return reinterpret_cast<char*>(file.stringTable + stringOffset); -} - -uint16 DB2FileLoaderRegularImpl::Record::GetOffset(uint32 field) const -{ - ASSERT(field < file._header->FieldCount); - return file.fields[field].Offset; -} - -uint16 DB2FileLoaderRegularImpl::Record::GetByteSize(uint32 field) const -{ - ASSERT(field < file._header->FieldCount); - return 4 - file.fields[field].UnusedBits / 8; -} - -uint32 DB2FileLoaderRegularImpl::Record::GetVarInt(uint32 field, uint32 arrayIndex, bool isSigned) const -{ - ASSERT(field < file._header->FieldCount); - uint32 val = *reinterpret_cast<uint32*>(offset + GetOffset(field) + arrayIndex * (4 - file.fields[field].UnusedBits / 8)); - EndianConvert(val); - if (isSigned) - return int32(val) << file.fields[field].UnusedBits >> file.fields[field].UnusedBits; - - return val << file.fields[field].UnusedBits >> file.fields[field].UnusedBits; -} - -DB2FileLoaderRegularImpl::Record::Record(DB2FileLoaderRegularImpl &file_, unsigned char *offset_) : offset(offset_), file(file_) -{ -} - -DB2FileLoaderRegularImpl::DB2FileLoaderRegularImpl() -{ - fileName = nullptr; - _loadInfo = nullptr; - _header = nullptr; - data = nullptr; - stringTable = nullptr; - idTable = nullptr; - idTableSize = 0; - copyTable = nullptr; - fields = nullptr; -} - -bool DB2FileLoaderRegularImpl::Load(char const* filename, FILE* file, DB2LoadInfo const* loadInfo, DB2Header const* header) -{ - _loadInfo = loadInfo; - _header = header; - ASSERT(_loadInfo->Meta->IndexField == -1 || _loadInfo->Meta->IndexField == int32(header->IndexField)); - - fileName = filename; - fields = new FieldEntry[header->FieldCount]; - if (fread(fields, header->FieldCount * sizeof(FieldEntry), 1, file) != 1) - return false; - - if (!_loadInfo->Meta->HasIndexFieldInData()) - idTableSize = header->RecordCount * sizeof(uint32); - - data = new unsigned char[header->RecordSize * header->RecordCount + header->StringTableSize]; - stringTable = data + header->RecordSize * header->RecordCount; - - if (fread(data, header->RecordSize * header->RecordCount + header->StringTableSize, 1, file) != 1) - return false; - - if (idTableSize) - { - idTable = new unsigned char[idTableSize]; - if (fread(idTable, idTableSize, 1, file) != 1) - return false; - } - - if (header->CopyTableSize) - { - copyTable = new unsigned char[header->CopyTableSize]; - if (fread(copyTable, header->CopyTableSize, 1, file) != 1) - return false; - } - - return true; -} - -DB2FileLoaderRegularImpl::~DB2FileLoaderRegularImpl() -{ - delete[] data; - delete[] idTable; - delete[] copyTable; - delete[] fields; -} - -DB2FileLoaderRegularImpl::Record DB2FileLoaderRegularImpl::getRecord(size_t id) -{ - assert(data); - return Record(*this, data + id * _header->RecordSize); -} - -static char const* const nullStr = ""; - -char* DB2FileLoaderRegularImpl::AutoProduceData(uint32& records, char**& indexTable, std::vector<char*>& stringPool) -{ - if (_loadInfo->Meta->FieldCount != _header->FieldCount) - return nullptr; - - //get struct size and index pos - uint32 indexField = _loadInfo->Meta->GetIndexField(); - uint32 recordsize = _loadInfo->Meta->GetRecordSize(); - - uint32 maxi = 0; - //find max index - if (!idTableSize) - { - for (uint32 y = 0; y < _header->RecordCount; ++y) - { - uint32 ind = getRecord(y).getUInt(indexField, 0, false); - if (ind > maxi) - maxi = ind; - } - } - else - { - for (uint32 y = 0; y < _header->RecordCount; ++y) - { - uint32 ind = ((uint32*)idTable)[y]; - if (ind > maxi) - maxi = ind; - } - } - - for (uint32 y = 0; y < _header->CopyTableSize; y += 8) - { - uint32 ind = *((uint32*)(copyTable + y)); - if (ind > maxi) - maxi = ind; - } - - using index_entry_t = char*; - - ++maxi; - records = maxi; - indexTable = new index_entry_t[maxi]; - memset(indexTable, 0, maxi * sizeof(index_entry_t)); - - char* dataTable = new char[(_header->RecordCount + (_header->CopyTableSize / 8)) * recordsize]; - - // we store flat holders pool as single memory block - std::size_t stringFields = _loadInfo->GetStringFieldCount(false); - std::size_t localizedStringFields = _loadInfo->GetStringFieldCount(true); - - // each string field at load have array of string for each locale - std::size_t stringHoldersRecordPoolSize = localizedStringFields * sizeof(LocalizedString) + (stringFields - localizedStringFields) * sizeof(char*); - char* stringHoldersPool = nullptr; - if (stringFields) - { - std::size_t stringHoldersPoolSize = stringHoldersRecordPoolSize * _header->RecordCount; - - stringHoldersPool = new char[stringHoldersPoolSize]; - stringPool.push_back(stringHoldersPool); - - // DB2 strings expected to have at least empty string - for (std::size_t i = 0; i < stringHoldersPoolSize / sizeof(char*); ++i) - ((char const**)stringHoldersPool)[i] = nullStr; - } - - uint32 offset = 0; - - for (uint32 y = 0; y < _header->RecordCount; y++) - { - Record rec = getRecord(y); - uint32 indexVal = _loadInfo->Meta->HasIndexFieldInData() ? rec.getUInt(indexField, 0, false) : ((uint32*)idTable)[y]; - - indexTable[indexVal] = &dataTable[offset]; - - uint32 fieldIndex = 0; - if (!_loadInfo->Meta->HasIndexFieldInData()) - { - *((uint32*)(&dataTable[offset])) = indexVal; - offset += 4; - ++fieldIndex; - } - - uint32 stringFieldOffset = 0; - - for (uint32 x = 0; x < _header->FieldCount; ++x) - { - for (uint32 z = 0; z < _loadInfo->Meta->ArraySizes[x]; ++z) - { - switch (_loadInfo->TypesString[fieldIndex]) - { - case FT_FLOAT: - *((float*)(&dataTable[offset])) = rec.getFloat(x, z); - offset += 4; - break; - case FT_INT: - *((uint32*)(&dataTable[offset])) = rec.getUInt(x, z, _loadInfo->Fields[fieldIndex].IsSigned); - offset += 4; - break; - case FT_BYTE: - *((uint8*)(&dataTable[offset])) = rec.getUInt8(x, z); - offset += 1; - break; - case FT_SHORT: - *((uint16*)(&dataTable[offset])) = rec.getUInt16(x, z); - offset += 2; - break; - case FT_STRING: - case FT_STRING_NOT_LOCALIZED: - { - // init db2 string field slots by pointers to string holders - char const*** slot = (char const***)(&dataTable[offset]); - *slot = (char const**)(&stringHoldersPool[stringHoldersRecordPoolSize * y + stringFieldOffset]); - if (_loadInfo->TypesString[fieldIndex] == FT_STRING) - stringFieldOffset += sizeof(LocalizedString); - else - stringFieldOffset += sizeof(char*); - - offset += sizeof(char*); - break; - } - default: - ASSERT(false, "Unknown format character '%c' found in %s meta", _loadInfo->TypesString[x], fileName); - break; - } - ++fieldIndex; - } - } - } - - return dataTable; -} - -char* DB2FileLoaderRegularImpl::AutoProduceStrings(char* dataTable, uint32 locale) -{ - if (_loadInfo->Meta->FieldCount != _header->FieldCount) - return nullptr; - - if (!(_header->Locale & (1 << locale))) - { - char const* sep = ""; - std::ostringstream str; - for (uint32 i = 0; i < TOTAL_LOCALES; ++i) - { - if (_header->Locale & (1 << i)) - { - str << sep << localeNames[i]; - sep = ", "; - } - } - - TC_LOG_ERROR("", "Attempted to load %s which has locales %s as %s. Check if you placed your localized db2 files in correct directory.", fileName, str.str().c_str(), localeNames[locale]); - return nullptr; - } - - char* stringPool = new char[_header->StringTableSize]; - memcpy(stringPool, stringTable, _header->StringTableSize); - - uint32 offset = 0; - - for (uint32 y = 0; y < _header->RecordCount; y++) - { - uint32 fieldIndex = 0; - if (!_loadInfo->Meta->HasIndexFieldInData()) - { - offset += 4; - ++fieldIndex; - } - - for (uint32 x = 0; x < _header->FieldCount; ++x) - { - for (uint32 z = 0; z < _loadInfo->Meta->ArraySizes[x]; ++z) - { - switch (_loadInfo->TypesString[fieldIndex]) - { - case FT_FLOAT: - case FT_INT: - offset += 4; - break; - case FT_BYTE: - offset += 1; - break; - case FT_SHORT: - offset += 2; - break; - case FT_STRING: - { - // fill only not filled entries - LocalizedString* db2str = *(LocalizedString**)(&dataTable[offset]); - if (db2str->Str[locale] == nullStr) - { - char const* st = getRecord(y).getString(x, z); - db2str->Str[locale] = stringPool + (st - (char const*)stringTable); - } - - offset += sizeof(char*); - break; - } - case FT_STRING_NOT_LOCALIZED: - { - char** db2str = (char**)(&dataTable[offset]); - char const* st = getRecord(y).getString(x, z); - *db2str = stringPool + (st - (char const*)stringTable); - offset += sizeof(char*); - break; - } - default: - ASSERT(false, "Unknown format character '%c' found in %s meta", _loadInfo->TypesString[x], fileName); - break; - } - ++fieldIndex; - } - } - } - - return stringPool; -} - -void DB2FileLoaderRegularImpl::AutoProduceRecordCopies(uint32 records, char** indexTable, char* dataTable) -{ - uint32 recordsize = _loadInfo->Meta->GetRecordSize(); - uint32 offset = _header->RecordCount * recordsize; - uint32* copyIds = (uint32*)copyTable; - for (uint32 c = 0; c < _header->CopyTableSize / 4; c += 2) - { - uint32 to = copyIds[c]; - uint32 from = copyIds[c + 1]; - - if (from && from < records && to < records && indexTable[from]) - { - indexTable[to] = &dataTable[offset]; - memcpy(indexTable[to], indexTable[from], recordsize); - - if (_loadInfo->Meta->HasIndexFieldInData()) - *((uint32*)(&dataTable[offset + fields[_loadInfo->Meta->GetIndexField()].Offset])) = to; - else - *((uint32*)(&dataTable[offset])) = to; - - offset += recordsize; - } - } -} - -DB2FileLoaderSparseImpl::DB2FileLoaderSparseImpl() -{ - fileName = nullptr; - _loadInfo = nullptr; - _header = nullptr; - fields = nullptr; - dataStart = 0; - data = nullptr; - offsets = nullptr; -} - -bool DB2FileLoaderSparseImpl::Load(char const* filename, FILE* file, DB2LoadInfo const* loadInfo, DB2Header const* header) -{ - _loadInfo = loadInfo; - _header = header; - fileName = filename; - - fields = new FieldEntry[header->FieldCount]; - if (fread(fields, header->FieldCount * sizeof(FieldEntry), 1, file) != 1) - return false; - - dataStart = ftell(file); - - data = new unsigned char[header->StringTableSize - dataStart]; - - if (fread(data, header->StringTableSize - dataStart, 1, file) != 1) - return false; - - offsets = new OffsetTableEntry[header->MaxId - header->MinId + 1]; - if (fread(offsets, (header->MaxId - header->MinId + 1) * 6, 1, file) != 1) - return false; - - return true; -} - -DB2FileLoaderSparseImpl::~DB2FileLoaderSparseImpl() -{ - delete[] data; - delete[] offsets; - delete[] fields; -} - -char* DB2FileLoaderSparseImpl::AutoProduceData(uint32& maxId, char**& indexTable, std::vector<char*>& stringPool) -{ - if (_loadInfo->Meta->FieldCount != _header->FieldCount) - return NULL; - - //get struct size and index pos - uint32 recordsize = _loadInfo->Meta->GetRecordSize(); - - uint32 offsetCount = _header->MaxId - _header->MinId + 1; - uint32 records = 0; - uint32 expandedDataSize = 0; - for (uint32 i = 0; i < offsetCount; ++i) - { - if (offsets[i].FileOffset && offsets[i].RecordSize) - { - ++records; - expandedDataSize += offsets[i].RecordSize; - } - } - - using index_entry_t = char*; - - maxId = _header->MaxId + 1; - indexTable = new index_entry_t[maxId]; - memset(indexTable, 0, maxId * sizeof(index_entry_t)); - - char* dataTable = new char[records * recordsize]; - - // we store flat holders pool as single memory block - std::size_t stringFields = _loadInfo->GetStringFieldCount(false); - std::size_t localizedStringFields = _loadInfo->GetStringFieldCount(true); - - // each string field at load have array of string for each locale - std::size_t stringHoldersRecordPoolSize = localizedStringFields * sizeof(LocalizedString) + (stringFields - localizedStringFields) * sizeof(char*); - std::size_t stringHoldersPoolSize = stringHoldersRecordPoolSize * records; - - char* stringHoldersPool = new char[stringHoldersPoolSize]; - stringPool.push_back(stringHoldersPool); - - // DB2 strings expected to have at least empty string - for (std::size_t i = 0; i < stringHoldersPoolSize / sizeof(char*); ++i) - ((char const**)stringHoldersPool)[i] = nullStr; - - char* stringTable = new char[expandedDataSize - records * ((recordsize - (!_loadInfo->Meta->HasIndexFieldInData() ? 4 : 0)) - stringFields * sizeof(char*))]; - memset(stringTable, 0, expandedDataSize - records * ((recordsize - (!_loadInfo->Meta->HasIndexFieldInData() ? 4 : 0)) - stringFields * sizeof(char*))); - stringPool.push_back(stringTable); - char* stringPtr = stringTable; - - uint32 offset = 0; - uint32 recordNum = 0; - for (uint32 y = 0; y < offsetCount; ++y) - { - if (!offsets[y].FileOffset || !offsets[y].RecordSize) - continue; - - indexTable[y + _header->MinId] = &dataTable[offset]; - ASSERT(indexTable[y + _header->MinId]); - std::size_t fieldOffset = 0; - uint32 stringFieldOffset = 0; - - uint32 fieldIndex = 0; - if (!_loadInfo->Meta->HasIndexFieldInData()) - { - *((uint32*)(&dataTable[offset])) = y + _header->MinId; - offset += 4; - ++fieldIndex; - } - - for (uint32 x = 0; x < _header->FieldCount; ++x) - { - uint16 fieldBytes = 4 - fields[x].UnusedBits / 8; - for (uint32 z = 0; z < _loadInfo->Meta->ArraySizes[x]; ++z) - { - switch (_loadInfo->TypesString[fieldIndex]) - { - case FT_FLOAT: - { - float val = *reinterpret_cast<float*>(&data[offsets[y].FileOffset - dataStart + fieldOffset]); - EndianConvert(val); - *((float*)(&dataTable[offset])) = val; - offset += 4; - fieldOffset += 4; - break; - } - case FT_INT: - { - ASSERT(fieldBytes && fieldBytes <= 4); - uint32 val = 0; - switch (fieldBytes) - { - case 1: - val = *reinterpret_cast<uint8*>(&data[offsets[y].FileOffset - dataStart + fieldOffset]); - break; - case 2: - { - uint16 val16 = *reinterpret_cast<uint16*>(&data[offsets[y].FileOffset - dataStart + fieldOffset]); - EndianConvert(val16); - val = val16; - break; - } - case 3: - { -#pragma pack(push, 1) - struct dbcint24 { uint8 v[3]; }; -#pragma pack(pop) - dbcint24 i24v = *reinterpret_cast<dbcint24*>(&data[offsets[y].FileOffset - dataStart + fieldOffset]); - EndianConvert(i24v); - val = uint32(i24v.v[0]) | (uint32(i24v.v[1]) << 8) | (uint32(i24v.v[2]) << 16); - break; - } - case 4: - val = *reinterpret_cast<uint32*>(&data[offsets[y].FileOffset - dataStart + fieldOffset]); - EndianConvert(val); - break; - default: - break; - } - *((uint32*)(&dataTable[offset])) = val; - offset += 4; - fieldOffset += fieldBytes; - break; - } - case FT_BYTE: - { - ASSERT(fieldBytes == 1); - *((uint8*)(&dataTable[offset])) = *reinterpret_cast<uint8*>(&data[offsets[y].FileOffset - dataStart + fieldOffset]); - offset += 1; - fieldOffset += 1; - break; - } - case FT_SHORT: - { - ASSERT(fieldBytes == 2); - uint16 val = *reinterpret_cast<uint16*>(&data[offsets[y].FileOffset - dataStart + fieldOffset]); - EndianConvert(val); - *((uint16*)(&dataTable[offset])) = val; - offset += 2; - fieldOffset += 2; - break; - } - case FT_STRING: - { - LocalizedString** slot = (LocalizedString**)(&dataTable[offset]); - *slot = (LocalizedString*)(&stringHoldersPool[stringHoldersRecordPoolSize * recordNum + stringFieldOffset]); - for (uint32 locale = 0; locale < TOTAL_LOCALES; ++locale) - if (_header->Locale & (1 << locale)) - (*slot)->Str[locale] = stringPtr; - strcpy(stringPtr, (char*)&data[offsets[y].FileOffset - dataStart + fieldOffset]); - fieldOffset += strlen(stringPtr) + 1; - stringPtr += strlen(stringPtr) + 1; - stringFieldOffset += sizeof(LocalizedString); - offset += sizeof(LocalizedString*); - break; - } - case FT_STRING_NOT_LOCALIZED: - { - char const*** slot = (char const***)(&dataTable[offset]); - *slot = (char const**)(&stringHoldersPool[stringHoldersRecordPoolSize * recordNum + stringFieldOffset]); - **slot = stringPtr; - strcpy(stringPtr, (char*)&data[offsets[y].FileOffset - dataStart + fieldOffset]); - fieldOffset += strlen(stringPtr) + 1; - stringPtr += strlen(stringPtr) + 1; - stringFieldOffset += sizeof(char*); - offset += sizeof(char*); - break; - } - default: - ASSERT(false, "Unknown format character '%c' found in %s meta", _loadInfo->TypesString[x], fileName); - break; - } - ++fieldIndex; - } - } - - ++recordNum; - } - - return dataTable; -} - -char* DB2FileLoaderSparseImpl::AutoProduceStrings(char* dataTable, uint32 locale) -{ - if (_loadInfo->Meta->FieldCount != _header->FieldCount) - return nullptr; - - if (!(_header->Locale & (1 << locale))) - { - char const* sep = ""; - std::ostringstream str; - for (uint32 i = 0; i < TOTAL_LOCALES; ++i) - { - if (_header->Locale & (1 << i)) - { - str << sep << localeNames[i]; - sep = ", "; - } - } - - TC_LOG_ERROR("", "Attempted to load %s which has locales %s as %s. Check if you placed your localized db2 files in correct directory.", fileName, str.str().c_str(), localeNames[locale]); - return nullptr; - } - - uint32 offsetCount = _header->MaxId - _header->MinId + 1; - uint32 records = 0; - for (uint32 i = 0; i < offsetCount; ++i) - if (offsets[i].FileOffset && offsets[i].RecordSize) - ++records; - - uint32 recordsize = _loadInfo->Meta->GetRecordSize(); - std::size_t stringFields = _loadInfo->GetStringFieldCount(true); - char* stringTable = new char[_header->StringTableSize - dataStart - records * ((recordsize - (!_loadInfo->Meta->HasIndexFieldInData() ? 4 : 0)) - stringFields * sizeof(char*))]; - memset(stringTable, 0, _header->StringTableSize - dataStart - records * ((recordsize - (!_loadInfo->Meta->HasIndexFieldInData() ? 4 : 0)) - stringFields * sizeof(char*))); - char* stringPtr = stringTable; - - uint32 offset = 0; - - for (uint32 y = 0; y < offsetCount; y++) - { - if (!offsets[y].FileOffset || !offsets[y].RecordSize) - continue; - - uint32 fieldIndex = 0; - if (!_loadInfo->Meta->HasIndexFieldInData()) - { - offset += 4; - ++fieldIndex; - } - - std::size_t fieldOffset = 0; - for (uint32 x = 0; x < _header->FieldCount; ++x) - { - for (uint32 z = 0; z < _loadInfo->Meta->ArraySizes[x]; ++z) - { - switch (_loadInfo->TypesString[fieldIndex]) - { - case FT_FLOAT: - offset += 4; - fieldOffset += 4; - break; - case FT_INT: - offset += 4; - fieldOffset += 4 - fields[x].UnusedBits / 8; - break; - case FT_BYTE: - offset += 1; - fieldOffset += 1; - break; - case FT_SHORT: - offset += 2; - fieldOffset += 2; - break; - case FT_STRING: - { - LocalizedString* db2str = *(LocalizedString**)(&dataTable[offset]); - db2str->Str[locale] = stringPtr; - strcpy(stringPtr, (char*)&data[offsets[y].FileOffset - dataStart + fieldOffset]); - fieldOffset += strlen(stringPtr) + 1; - stringPtr += strlen(stringPtr) + 1; - offset += sizeof(char*); - break; - } - case FT_STRING_NOT_LOCALIZED: - { - fieldOffset += strlen((char*)&data[offsets[y].FileOffset - dataStart + fieldOffset]) + 1; - offset += sizeof(char*); - break; - } - default: - ASSERT(false, "Unknown format character '%c' found in %s meta", _loadInfo->TypesString[x], fileName); - break; - } - ++fieldIndex; - } - } - } - - return stringTable; -} - -char* DB2DatabaseLoader::Load(uint32& records, char**& indexTable, char*& stringHolders, std::vector<char*>& stringPool) -{ - // Even though this query is executed only once, prepared statement is used to send data from mysql server in binary format - PreparedQueryResult result = HotfixDatabase.Query(HotfixDatabase.GetPreparedStatement(_loadInfo->Statement)); - if (!result) - return nullptr; - - if (_loadInfo->Meta->GetDbFieldCount() != result->GetFieldCount()) - return nullptr; - - // get struct size and index pos - uint32 indexField = _loadInfo->Meta->GetDbIndexField(); - uint32 recordSize = _loadInfo->Meta->GetRecordSize(); - - // we store flat holders pool as single memory block - std::size_t stringFields = _loadInfo->GetStringFieldCount(false); - std::size_t localizedStringFields = _loadInfo->GetStringFieldCount(true); - - // each string field at load have array of string for each locale - std::size_t stringHoldersRecordPoolSize = localizedStringFields * sizeof(LocalizedString) + (stringFields - localizedStringFields) * sizeof(char*); - - if (stringFields) - { - std::size_t stringHoldersPoolSize = stringHoldersRecordPoolSize * result->GetRowCount(); - stringHolders = new char[stringHoldersPoolSize]; - - // DB2 strings expected to have at least empty string - for (std::size_t i = 0; i < stringHoldersPoolSize / sizeof(char*); ++i) - ((char const**)stringHolders)[i] = nullStr; - } - else - stringHolders = nullptr; - - // Resize index table - // database query *MUST* contain ORDER BY `index_field` DESC clause - uint32 indexTableSize = (*result)[indexField].GetUInt32() + 1; - if (indexTableSize < records) - indexTableSize = records; - - if (indexTableSize > records) - { - char** tmpIdxTable = new char*[indexTableSize]; - memset(tmpIdxTable, 0, indexTableSize * sizeof(char*)); - memcpy(tmpIdxTable, indexTable, records * sizeof(char*)); - delete[] indexTable; - indexTable = tmpIdxTable; - } - - char* tempDataTable = new char[result->GetRowCount() * recordSize]; - uint32* newIndexes = new uint32[result->GetRowCount()]; - uint32 rec = 0; - uint32 newRecords = 0; - - do - { - Field* fields = result->Fetch(); - uint32 offset = 0; - uint32 stringFieldOffset = 0; - - uint32 indexValue = fields[indexField].GetUInt32(); - - // Attempt to overwrite existing data - char* dataValue = indexTable[indexValue]; - if (!dataValue) - { - newIndexes[newRecords] = indexValue; - dataValue = &tempDataTable[newRecords++ * recordSize]; - } - - uint32 f = 0; - if (!_loadInfo->Meta->HasIndexFieldInData()) - { - *((uint32*)(&dataValue[offset])) = indexValue; - offset += 4; - ++f; - } - - for (uint32 x = 0; x < _loadInfo->Meta->FieldCount; ++x) - { - for (uint32 z = 0; z < _loadInfo->Meta->ArraySizes[x]; ++z) - { - switch (_loadInfo->TypesString[f]) - { - case FT_FLOAT: - *((float*)(&dataValue[offset])) = fields[f].GetFloat(); - offset += 4; - break; - case FT_INT: - *((int32*)(&dataValue[offset])) = fields[f].GetInt32(); - offset += 4; - break; - case FT_BYTE: - *((int8*)(&dataValue[offset])) = fields[f].GetInt8(); - offset += 1; - break; - case FT_SHORT: - *((int16*)(&dataValue[offset])) = fields[f].GetInt16(); - offset += 2; - break; - case FT_STRING: - { - LocalizedString** slot = (LocalizedString**)(&dataValue[offset]); - *slot = (LocalizedString*)(&stringHolders[stringHoldersRecordPoolSize * rec + stringFieldOffset]); - ASSERT(*slot); - - // Value in database in main table field must be for enUS locale - if (char* str = AddString(&(*slot)->Str[LOCALE_enUS], fields[f].GetString())) - stringPool.push_back(str); - - stringFieldOffset += sizeof(LocalizedString); - offset += sizeof(char*); - break; - } - case FT_STRING_NOT_LOCALIZED: - { - char const** slot = (char const**)(&dataValue[offset]); - *slot = (char*)(&stringHolders[stringHoldersRecordPoolSize * rec + stringFieldOffset]); - ASSERT(*slot); - - // Value in database in main table field must be for enUS locale - if (char* str = AddString(slot, fields[f].GetString())) - stringPool.push_back(str); - - stringFieldOffset += sizeof(char*); - offset += sizeof(char*); - break; - } - default: - ASSERT(false, "Unknown format character '%c' found in %s meta", _loadInfo->TypesString[x], _storageName.c_str()); - break; - } - ++f; - } - } - - ASSERT(offset == recordSize); - ++rec; - } while (result->NextRow()); - - if (!newRecords) - { - delete[] tempDataTable; - delete[] newIndexes; - return nullptr; - } - - // Compact new data table to only contain new records not previously loaded from file - char* dataTable = new char[newRecords * recordSize]; - memcpy(dataTable, tempDataTable, newRecords * recordSize); - - // insert new records to index table - for (uint32 i = 0; i < newRecords; ++i) - indexTable[newIndexes[i]] = &dataTable[i * recordSize]; - - delete[] tempDataTable; - delete[] newIndexes; - - records = indexTableSize; - - return dataTable; -} - -void DB2DatabaseLoader::LoadStrings(uint32 locale, uint32 records, char** indexTable, std::vector<char*>& stringPool) -{ - PreparedStatement* stmt = HotfixDatabase.GetPreparedStatement(HotfixDatabaseStatements(_loadInfo->Statement + 1)); - stmt->setString(0, localeNames[locale]); - PreparedQueryResult result = HotfixDatabase.Query(stmt); - if (!result) - return; - - std::size_t stringFields = _loadInfo->GetStringFieldCount(true); - if (result->GetFieldCount() != stringFields + 1 /*ID*/) - return; - - uint32 fieldCount = _loadInfo->Meta->FieldCount; - uint32 recordSize = _loadInfo->Meta->GetRecordSize(); - - do - { - Field* fields = result->Fetch(); - uint32 offset = 0; - uint32 stringFieldNumInRecord = 0; - uint32 indexValue = fields[0].GetUInt32(); - - if (indexValue >= records) - continue; - - // Attempt to overwrite existing data - if (char* dataValue = indexTable[indexValue]) - { - uint32 fieldIndex = 0; - if (!_loadInfo->Meta->HasIndexFieldInData()) - { - offset += 4; - ++fieldIndex; - } - - for (uint32 x = 0; x < fieldCount; ++x) - { - for (uint32 z = 0; z < _loadInfo->Meta->ArraySizes[x]; ++z) - { - switch (_loadInfo->TypesString[fieldIndex]) - { - case FT_FLOAT: - case FT_INT: - offset += 4; - break; - case FT_BYTE: - offset += 1; - break; - case FT_SHORT: - offset += 2; - break; - case FT_STRING: - { - // fill only not filled entries - LocalizedString* db2str = *(LocalizedString**)(&dataValue[offset]); - if (db2str->Str[locale] == nullStr) - if (char* str = AddString(&db2str->Str[locale], fields[1 + stringFieldNumInRecord].GetString())) - stringPool.push_back(str); - - ++stringFieldNumInRecord; - offset += sizeof(LocalizedString*); - break; - } - case FT_STRING_NOT_LOCALIZED: - offset += sizeof(char*); - break; - default: - ASSERT(false, "Unknown format character '%c' found in %s meta", _loadInfo->TypesString[x], _storageName.c_str()); - break; - } - ++fieldIndex; - } - } - - ASSERT(offset == recordSize); - } - else - TC_LOG_ERROR("sql.sql", "Hotfix locale table for storage %s references row that does not exist %u locale %s!", _storageName.c_str(), indexValue, localeNames[locale]); - - } while (result->NextRow()); - - return; -} - -char* DB2DatabaseLoader::AddString(char const** holder, std::string const& value) -{ - if (!value.empty()) - { - std::size_t existingLength = strlen(*holder); - if (existingLength >= value.length()) - { - // Reuse existing storage if there is enough space - char* str = const_cast<char*>(*holder); - memcpy(str, value.c_str(), value.length()); - str[value.length()] = '\0'; - return nullptr; - } - - char* str = new char[value.length() + 1]; - memcpy(str, value.c_str(), value.length()); - str[value.length()] = '\0'; - *holder = str; - return str; - } - - return nullptr; -} - -DB2FileLoader::DB2FileLoader() : _impl(nullptr) -{ -} - -DB2FileLoader::~DB2FileLoader() -{ - delete _impl; -} - -bool DB2FileLoader::Load(char const* filename, DB2LoadInfo const* loadInfo) -{ - FILE* f = fopen(filename, "rb"); - if (!f) - return false; - - if (fread(&_header.Signature, 4, 1, f) != 1) // Signature - { - fclose(f); - return false; - } - - EndianConvert(_header.Signature); - - if (_header.Signature != 0x35424457) - { - fclose(f); - return false; //'WDB5' - } - - if (fread(&_header.RecordCount, 4, 1, f) != 1) // Number of records - { - fclose(f); - return false; - } - - EndianConvert(_header.RecordCount); - - if (fread(&_header.FieldCount, 4, 1, f) != 1) // Number of fields - { - fclose(f); - return false; - } - - EndianConvert(_header.FieldCount); - - if (fread(&_header.RecordSize, 4, 1, f) != 1) // Size of a record - { - fclose(f); - return false; - } - - EndianConvert(_header.RecordSize); - - if (fread(&_header.StringTableSize, 4, 1, f) != 1) // String size - { - fclose(f); - return false; - } - - EndianConvert(_header.StringTableSize); - - if (fread(&_header.TableHash, 4, 1, f) != 1) // Table hash - { - fclose(f); - return false; - } - - EndianConvert(_header.TableHash); - - if (fread(&_header.LayoutHash, 4, 1, f) != 1) // Layout hash - { - fclose(f); - return false; - } - - EndianConvert(_header.LayoutHash); - - if (_header.LayoutHash != loadInfo->Meta->LayoutHash) - { - fclose(f); - return false; - } - - if (fread(&_header.MinId, 4, 1, f) != 1) // MinIndex WDB2 - { - fclose(f); - return false; - } - - EndianConvert(_header.MinId); - - if (fread(&_header.MaxId, 4, 1, f) != 1) // MaxIndex WDB2 - { - fclose(f); - return false; - } - - EndianConvert(_header.MaxId); - - if (fread(&_header.Locale, 4, 1, f) != 1) // Locales - { - fclose(f); - return false; - } - - EndianConvert(_header.Locale); - - if (fread(&_header.CopyTableSize, 4, 1, f) != 1) - { - fclose(f); - return false; - } - - EndianConvert(_header.CopyTableSize); - - if (fread(&_header.Flags, 4, 1, f) != 1) - { - fclose(f); - return false; - } - - EndianConvert(_header.Flags); - - if (!(_header.Flags & 0x1)) - _impl = new DB2FileLoaderRegularImpl(); - else - _impl = new DB2FileLoaderSparseImpl(); - - bool result = _impl->Load(filename, f, loadInfo, &_header); - fclose(f); - return result; -} - -char* DB2FileLoader::AutoProduceData(uint32& count, char**& indexTable, std::vector<char*>& stringPool) -{ - return _impl->AutoProduceData(count, indexTable, stringPool); -} - -char* DB2FileLoader::AutoProduceStrings(char* dataTable, uint32 locale) -{ - return _impl->AutoProduceStrings(dataTable, locale); -} - -void DB2FileLoader::AutoProduceRecordCopies(uint32 records, char** indexTable, char* dataTable) -{ - _impl->AutoProduceRecordCopies(records, indexTable, dataTable); -} diff --git a/src/server/shared/DataStores/DB2Store.cpp b/src/server/shared/DataStores/DB2Store.cpp new file mode 100644 index 00000000000..bb36ed6b61b --- /dev/null +++ b/src/server/shared/DataStores/DB2Store.cpp @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2008-2017 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 "DB2Store.h" +#include "ByteBuffer.h" +#include "DB2DatabaseLoader.h" +#include "DB2Meta.h" + +struct DB2FileSystemSource : public DB2FileSource +{ + DB2FileSystemSource(std::string const& fileName) + { + _fileName = fileName; + _file = fopen(_fileName.c_str(), "rb"); + } + + ~DB2FileSystemSource() + { + if (_file) + fclose(_file); + } + + bool IsOpen() const override + { + return _file != nullptr; + } + + bool Read(void* buffer, std::size_t numBytes) override + { + return fread(buffer, numBytes, 1, _file) == 1; + } + + std::size_t GetPosition() const override + { + return ftell(_file); + } + + char const* GetFileName() const override + { + return _fileName.c_str(); + } + +private: + std::string _fileName; + FILE* _file; +}; + +DB2StorageBase::DB2StorageBase(char const* fileName, DB2LoadInfo const* loadInfo) + : _tableHash(0), _layoutHash(0), _fileName(fileName), _fieldCount(0), _loadInfo(loadInfo), _dataTable(nullptr), _dataTableEx(nullptr), _indexTableSize(0) +{ +} + +DB2StorageBase::~DB2StorageBase() +{ + delete[] _dataTable; + delete[] _dataTableEx; + for (char* strings : _stringPool) + delete[] strings; +} + +void DB2StorageBase::WriteRecordData(char const* entry, uint32 locale, ByteBuffer& buffer) const +{ + std::size_t i = 0; + if (!_loadInfo->Meta->HasIndexFieldInData()) + { + entry += 4; + ++i; + } + + for (; i < _loadInfo->FieldCount; ++i) + { + switch (_loadInfo->TypesString[i]) + { + case FT_INT: + buffer << *(uint32*)entry; + entry += 4; + break; + case FT_FLOAT: + buffer << *(float*)entry; + entry += 4; + break; + case FT_BYTE: + buffer << *(uint8*)entry; + entry += 1; + break; + case FT_SHORT: + buffer << *(uint16*)entry; + entry += 2; + break; + case FT_STRING: + { + LocalizedString* locStr = *(LocalizedString**)entry; + if (locStr->Str[locale][0] == '\0') + locale = 0; + + buffer << locStr->Str[locale]; + entry += sizeof(LocalizedString*); + break; + } + case FT_STRING_NOT_LOCALIZED: + { + buffer << *(char const**)entry; + entry += sizeof(char const*); + break; + } + } + } +} + +bool DB2StorageBase::Load(std::string const& path, uint32 locale, char**& indexTable) +{ + indexTable = nullptr; + DB2FileLoader db2; + { + DB2FileSystemSource source(path + _fileName); + // Check if load was successful, only then continue + if (!db2.Load(&source, _loadInfo)) + return false; + } + + _fieldCount = db2.GetCols(); + _tableHash = db2.GetTableHash(); + _layoutHash = db2.GetLayoutHash(); + + // load raw non-string data + _dataTable = db2.AutoProduceData(_indexTableSize, indexTable, _stringPool); + + // load strings from db2 data + if (!_stringPool.empty()) + if (char* stringBlock = db2.AutoProduceStrings(_dataTable, locale)) + _stringPool.push_back(stringBlock); + + db2.AutoProduceRecordCopies(_indexTableSize, indexTable, _dataTable); + + // error in db2 file at loading if NULL + return indexTable != nullptr; +} + +bool DB2StorageBase::LoadStringsFrom(std::string const& path, uint32 locale, char** indexTable) +{ + // DB2 must be already loaded using Load + if (!indexTable) + return false; + + DB2FileLoader db2; + { + DB2FileSystemSource source(path + _fileName); + // Check if load was successful, only then continue + if (!db2.Load(&source, _loadInfo)) + return false; + } + + // load strings from another locale db2 data + if (_loadInfo->GetStringFieldCount(true)) + if (char* stringBlock = db2.AutoProduceStrings(_dataTable, locale)) + _stringPool.push_back(stringBlock); + + return true; +} + +void DB2StorageBase::LoadFromDB(char**& indexTable) +{ + char* extraStringHolders = nullptr; + _dataTableEx = DB2DatabaseLoader(_fileName, _loadInfo).Load(_indexTableSize, indexTable, extraStringHolders, _stringPool); + if (extraStringHolders) + _stringPool.push_back(extraStringHolders); +} + +void DB2StorageBase::LoadStringsFromDB(uint32 locale, char** indexTable) +{ + if (!_loadInfo->GetStringFieldCount(true)) + return; + + DB2DatabaseLoader(_fileName, _loadInfo).LoadStrings(locale, _indexTableSize, indexTable, _stringPool); +} diff --git a/src/server/shared/DataStores/DB2Store.h b/src/server/shared/DataStores/DB2Store.h index 7011a3b6e61..68cd888cd05 100644 --- a/src/server/shared/DataStores/DB2Store.h +++ b/src/server/shared/DataStores/DB2Store.h @@ -19,41 +19,29 @@ #define DB2STORE_H #include "Common.h" -#include "DB2Meta.h" -#include "DB2StorageLoader.h" #include "DBStorageIterator.h" -#include "ByteBuffer.h" +#include <vector> + +class ByteBuffer; +struct DB2LoadInfo; /// Interface class for common access -class DB2StorageBase +class TC_SHARED_API DB2StorageBase { public: - DB2StorageBase(char const* fileName, DB2LoadInfo&& loadInfo) - : _tableHash(0), _layoutHash(0), _fileName(fileName), _fieldCount(0), _loadInfo(std::move(loadInfo)), _dataTable(nullptr), _dataTableEx(nullptr) { } - - virtual ~DB2StorageBase() - { - delete[] _dataTable; - delete[] _dataTableEx; - for (char* strings : _stringPool) - delete[] strings; - } + DB2StorageBase(char const* fileName, DB2LoadInfo const* loadInfo); + virtual ~DB2StorageBase(); uint32 GetTableHash() const { return _tableHash; } - uint32 GetLayoutHash() const { return _layoutHash; } virtual bool HasRecord(uint32 id) const = 0; - virtual void WriteRecord(uint32 id, uint32 locale, ByteBuffer& buffer) const = 0; - virtual void EraseRecord(uint32 id) = 0; std::string const& GetFileName() const { return _fileName; } - uint32 GetFieldCount() const { return _fieldCount; } - - DB2LoadInfo const* GetLoadInfo() const { return &_loadInfo; } + DB2LoadInfo const* GetLoadInfo() const { return _loadInfo; } virtual bool Load(std::string const& path, uint32 locale) = 0; virtual bool LoadStringsFrom(std::string const& path, uint32 locale) = 0; @@ -61,63 +49,21 @@ public: virtual void LoadStringsFromDB(uint32 locale) = 0; protected: - void WriteRecordData(char const* entry, uint32 locale, ByteBuffer& buffer) const - { - std::size_t i = 0; - if (!_loadInfo.Meta->HasIndexFieldInData()) - { - entry += 4; - ++i; - } - - for (; i < _loadInfo.FieldCount; ++i) - { - switch (_loadInfo.TypesString[i]) - { - case FT_INT: - buffer << *(uint32*)entry; - entry += 4; - break; - case FT_FLOAT: - buffer << *(float*)entry; - entry += 4; - break; - case FT_BYTE: - buffer << *(uint8*)entry; - entry += 1; - break; - case FT_SHORT: - buffer << *(uint16*)entry; - entry += 2; - break; - case FT_STRING: - { - LocalizedString* locStr = *(LocalizedString**)entry; - if (locStr->Str[locale][0] == '\0') - locale = 0; - - buffer << locStr->Str[locale]; - entry += sizeof(LocalizedString*); - break; - } - case FT_STRING_NOT_LOCALIZED: - { - buffer << *(char const**)entry; - entry += sizeof(char const*); - break; - } - } - } - } + void WriteRecordData(char const* entry, uint32 locale, ByteBuffer& buffer) const; + bool Load(std::string const& path, uint32 locale, char**& indexTable); + bool LoadStringsFrom(std::string const& path, uint32 locale, char** indexTable); + void LoadFromDB(char**& indexTable); + void LoadStringsFromDB(uint32 locale, char** indexTable); uint32 _tableHash; uint32 _layoutHash; std::string _fileName; uint32 _fieldCount; - DB2LoadInfo _loadInfo; + DB2LoadInfo const* _loadInfo; char* _dataTable; char* _dataTableEx; std::vector<char*> _stringPool; + uint32 _indexTableSize; }; template<class T> @@ -128,10 +74,9 @@ class DB2Storage : public DB2StorageBase public: typedef DBStorageIterator<T> iterator; - DB2Storage(char const* fileName, DB2LoadInfo&& loadInfo) : DB2StorageBase(fileName, std::move(loadInfo)), - _indexTableSize(0) + DB2Storage(char const* fileName, DB2LoadInfo const* loadInfo) : DB2StorageBase(fileName, loadInfo) { - _indexTable.AsT = NULL; + _indexTable.AsT = nullptr; } ~DB2Storage() @@ -153,61 +98,22 @@ public: uint32 GetNumRows() const { return _indexTableSize; } bool Load(std::string const& path, uint32 locale) override { - DB2FileLoader db2; - // Check if load was successful, only then continue - if (!db2.Load((path + _fileName).c_str(), &_loadInfo)) - return false; - - _fieldCount = db2.GetCols(); - _tableHash = db2.GetTableHash(); - _layoutHash = db2.GetLayoutHash(); - - // load raw non-string data - _dataTable = db2.AutoProduceData(_indexTableSize, _indexTable.AsChar, _stringPool); - - // load strings from db2 data - if (!_stringPool.empty()) - if (char* stringBlock = db2.AutoProduceStrings(_dataTable, locale)) - _stringPool.push_back(stringBlock); - - db2.AutoProduceRecordCopies(_indexTableSize, _indexTable.AsChar, _dataTable); - - // error in db2 file at loading if NULL - return _indexTable.AsT != NULL; + return DB2StorageBase::Load(path, locale, _indexTable.AsChar); } bool LoadStringsFrom(std::string const& path, uint32 locale) override { - // DB2 must be already loaded using Load - if (!_indexTable.AsT) - return false; - - DB2FileLoader db2; - // Check if load was successful, only then continue - if (!db2.Load((path + _fileName).c_str(), &_loadInfo)) - return false; - - // load strings from another locale db2 data - if (_loadInfo.GetStringFieldCount(true)) - if (char* stringBlock = db2.AutoProduceStrings(_dataTable, locale)) - _stringPool.push_back(stringBlock); - return true; + return DB2StorageBase::LoadStringsFrom(path, locale, _indexTable.AsChar); } void LoadFromDB() override { - char* extraStringHolders = nullptr; - _dataTableEx = DB2DatabaseLoader(_fileName, &_loadInfo).Load(_indexTableSize, _indexTable.AsChar, extraStringHolders, _stringPool); - if (extraStringHolders) - _stringPool.push_back(extraStringHolders); + DB2StorageBase::LoadFromDB(_indexTable.AsChar); } void LoadStringsFromDB(uint32 locale) override { - if (!_loadInfo.GetStringFieldCount(true)) - return; - - DB2DatabaseLoader(_fileName, &_loadInfo).LoadStrings(locale, _indexTableSize, _indexTable.AsChar, _stringPool); + DB2StorageBase::LoadStringsFromDB(locale, _indexTable.AsChar); } iterator begin() { return iterator(_indexTable.AsT, _indexTableSize); } @@ -219,7 +125,6 @@ private: T** AsT; char** AsChar; } _indexTable; - uint32 _indexTableSize; }; #endif diff --git a/src/tools/extractor_common/CMakeLists.txt b/src/tools/extractor_common/CMakeLists.txt index 50cc20c9682..a982ce6ad1b 100644 --- a/src/tools/extractor_common/CMakeLists.txt +++ b/src/tools/extractor_common/CMakeLists.txt @@ -14,7 +14,10 @@ CollectSourceFiles( add_library(extractor_common STATIC ${PRIVATE_SOURCES}) -target_link_libraries(extractor_common boost casc) +target_link_libraries(extractor_common + PUBLIC + casc + common) target_include_directories(extractor_common PUBLIC diff --git a/src/tools/extractor_common/CascHandles.cpp b/src/tools/extractor_common/CascHandles.cpp index 9624a1ca149..46f90d8233f 100644 --- a/src/tools/extractor_common/CascHandles.cpp +++ b/src/tools/extractor_common/CascHandles.cpp @@ -16,32 +16,29 @@ */ #include "CascHandles.h" -#include "CascLib.h" +#include <CascLib.h> #include <boost/filesystem/operations.hpp> -namespace +char const* CASC::HumanReadableCASCError(DWORD error) { - const char* HumanReadableCASCError(int error) + switch (error) { - switch (error) - { - case ERROR_SUCCESS: return "SUCCESS"; - case ERROR_FILE_CORRUPT: return "FILE_CORRUPT"; - case ERROR_CAN_NOT_COMPLETE: return "CAN_NOT_COMPLETE"; - case ERROR_HANDLE_EOF: return "HANDLE_EOF"; - case ERROR_NO_MORE_FILES: return "NO_MORE_FILES"; - case ERROR_BAD_FORMAT: return "BAD_FORMAT"; - case ERROR_INSUFFICIENT_BUFFER: return "INSUFFICIENT_BUFFER"; - case ERROR_ALREADY_EXISTS: return "ALREADY_EXISTS"; - case ERROR_DISK_FULL: return "DISK_FULL"; - case ERROR_INVALID_PARAMETER: return "INVALID_PARAMETER"; - case ERROR_NOT_SUPPORTED: return "NOT_SUPPORTED"; - case ERROR_NOT_ENOUGH_MEMORY: return "NOT_ENOUGH_MEMORY"; - case ERROR_INVALID_HANDLE: return "INVALID_HANDLE"; - case ERROR_ACCESS_DENIED: return "ACCESS_DENIED"; - case ERROR_FILE_NOT_FOUND: return "FILE_NOT_FOUND"; - default: return "UNKNOWN"; - } + case ERROR_SUCCESS: return "SUCCESS"; + case ERROR_FILE_CORRUPT: return "FILE_CORRUPT"; + case ERROR_CAN_NOT_COMPLETE: return "CAN_NOT_COMPLETE"; + case ERROR_HANDLE_EOF: return "HANDLE_EOF"; + case ERROR_NO_MORE_FILES: return "NO_MORE_FILES"; + case ERROR_BAD_FORMAT: return "BAD_FORMAT"; + case ERROR_INSUFFICIENT_BUFFER: return "INSUFFICIENT_BUFFER"; + case ERROR_ALREADY_EXISTS: return "ALREADY_EXISTS"; + case ERROR_DISK_FULL: return "DISK_FULL"; + case ERROR_INVALID_PARAMETER: return "INVALID_PARAMETER"; + case ERROR_NOT_SUPPORTED: return "NOT_SUPPORTED"; + case ERROR_NOT_ENOUGH_MEMORY: return "NOT_ENOUGH_MEMORY"; + case ERROR_INVALID_HANDLE: return "INVALID_HANDLE"; + case ERROR_ACCESS_DENIED: return "ACCESS_DENIED"; + case ERROR_FILE_NOT_FOUND: return "FILE_NOT_FOUND"; + default: return "UNKNOWN"; } } @@ -95,6 +92,11 @@ DWORD CASC::GetFileSize(FileHandle const& file, PDWORD fileSizeHigh) return ::CascGetFileSize(file.get(), fileSizeHigh); } +DWORD CASC::GetFilePointer(FileHandle const& file) +{ + return ::CascSetFilePointer(file.get(), 0, nullptr, FILE_CURRENT); +} + bool CASC::ReadFile(FileHandle const& file, void* buffer, DWORD bytes, PDWORD bytesRead) { return ::CascReadFile(file.get(), buffer, bytes, bytesRead); diff --git a/src/tools/extractor_common/CascHandles.h b/src/tools/extractor_common/CascHandles.h index 455306ad5e0..ebfd04466ab 100644 --- a/src/tools/extractor_common/CascHandles.h +++ b/src/tools/extractor_common/CascHandles.h @@ -18,7 +18,7 @@ #ifndef CascHandles_h__ #define CascHandles_h__ -#include "CascPort.h" +#include <CascPort.h> #include <memory> namespace boost @@ -46,10 +46,13 @@ namespace CASC typedef std::unique_ptr<HANDLE, StorageDeleter> StorageHandle; typedef std::unique_ptr<HANDLE, FileDeleter> FileHandle; + char const* HumanReadableCASCError(DWORD error); + StorageHandle OpenStorage(boost::filesystem::path const& path, DWORD localeMask); FileHandle OpenFile(StorageHandle const& storage, char const* fileName, DWORD localeMask, bool printErrors = false); DWORD GetFileSize(FileHandle const& file, PDWORD fileSizeHigh); + DWORD GetFilePointer(FileHandle const& file); bool ReadFile(FileHandle const& file, void* buffer, DWORD bytes, PDWORD bytesRead); } diff --git a/src/tools/extractor_common/DB2CascFileSource.cpp b/src/tools/extractor_common/DB2CascFileSource.cpp new file mode 100644 index 00000000000..24bf47491dd --- /dev/null +++ b/src/tools/extractor_common/DB2CascFileSource.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2008-2017 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 "DB2CascFileSource.h" +#include <CascLib.h> + +DB2CascFileSource::DB2CascFileSource(CASC::StorageHandle const& storage, std::string fileName) +{ + _fileHandle = CASC::OpenFile(storage, fileName.c_str(), CASC_LOCALE_NONE, true); + _fileName = std::move(fileName); +} + +bool DB2CascFileSource::IsOpen() const +{ + return _fileHandle != nullptr; +} + +bool DB2CascFileSource::Read(void* buffer, std::size_t numBytes) +{ + DWORD bytesRead = 0; + return CASC::ReadFile(_fileHandle, buffer, numBytes, &bytesRead) && numBytes == bytesRead; +} + +std::size_t DB2CascFileSource::GetPosition() const +{ + return CASC::GetFilePointer(_fileHandle); +} + +char const* DB2CascFileSource::GetFileName() const +{ + return _fileName.c_str(); +} diff --git a/src/tools/extractor_common/DB2CascFileSource.h b/src/tools/extractor_common/DB2CascFileSource.h new file mode 100644 index 00000000000..b8876fdcdd1 --- /dev/null +++ b/src/tools/extractor_common/DB2CascFileSource.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2008-2017 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 DB2CascFileSource_h__ +#define DB2CascFileSource_h__ + +#include "DB2FileLoader.h" +#include "CascHandles.h" +#include <string> + +struct DB2CascFileSource : public DB2FileSource +{ + DB2CascFileSource(CASC::StorageHandle const& storage, std::string fileName); + bool IsOpen() const override; + bool Read(void* buffer, std::size_t numBytes) override; + std::size_t GetPosition() const override; + char const* GetFileName() const override; + +private: + CASC::FileHandle _fileHandle; + std::string _fileName; +}; + +#endif // DB2CascFile_h__ diff --git a/src/tools/map_extractor/CMakeLists.txt b/src/tools/map_extractor/CMakeLists.txt index 3cf7dab9ea0..6347d3bc807 100644 --- a/src/tools/map_extractor/CMakeLists.txt +++ b/src/tools/map_extractor/CMakeLists.txt @@ -28,7 +28,6 @@ target_include_directories(mapextractor target_link_libraries(mapextractor PUBLIC - common extractor_common) CollectIncludeDirectories( diff --git a/src/tools/map_extractor/DB2.cpp b/src/tools/map_extractor/DB2.cpp deleted file mode 100644 index fca95476edb..00000000000 --- a/src/tools/map_extractor/DB2.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2008-2017 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" -#include <cassert> - -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(CASC::FileHandle const& db2Handle, DB2Meta const* meta_) -{ - if (data) - { - delete[] data; - data = nullptr; - } - - DWORD bytesRead = 0; - meta = meta_; - std::uint32_t header; - CASC::ReadFile(db2Handle, &header, sizeof(header), &bytesRead); - if (bytesRead != sizeof(header)) // Signature - return false; - - EndianConvert(header); - - if (header != 0x35424457) - return false; //'WDB5' - - CASC::ReadFile(db2Handle, &recordCount, sizeof(recordCount), &bytesRead); - if (bytesRead != sizeof(recordCount)) // Number of records - return false; - - EndianConvert(recordCount); - - CASC::ReadFile(db2Handle, &fieldCount, sizeof(fieldCount), &bytesRead); - if (bytesRead != sizeof(fieldCount)) // Number of fields - return false; - - EndianConvert(fieldCount); - - CASC::ReadFile(db2Handle, &recordSize, sizeof(recordSize), &bytesRead); - if (bytesRead != sizeof(recordSize)) // Size of a record - return false; - - EndianConvert(recordSize); - - CASC::ReadFile(db2Handle, &stringSize, sizeof(stringSize), &bytesRead); - if (bytesRead != sizeof(stringSize)) // String size - return false; - - EndianConvert(stringSize); - - CASC::ReadFile(db2Handle, &tableHash, sizeof(tableHash), &bytesRead); - if (bytesRead != sizeof(tableHash)) // Table hash - return false; - - EndianConvert(tableHash); - - CASC::ReadFile(db2Handle, &layoutHash, sizeof(layoutHash), &bytesRead); - if (bytesRead != sizeof(layoutHash)) // Layout hash - return false; - - if (layoutHash != meta->LayoutHash) - return false; - - EndianConvert(layoutHash); - - CASC::ReadFile(db2Handle, &minIndex, sizeof(minIndex), &bytesRead); - if (bytesRead != sizeof(minIndex)) // MinIndex WDB2 - return false; - - EndianConvert(minIndex); - - CASC::ReadFile(db2Handle, &maxIndex, sizeof(maxIndex), &bytesRead); - if (bytesRead != sizeof(maxIndex)) // MaxIndex WDB2 - return false; - - EndianConvert(maxIndex); - - CASC::ReadFile(db2Handle, &localeMask, sizeof(localeMask), &bytesRead); - if (bytesRead != sizeof(localeMask)) // Locales - return false; - - EndianConvert(localeMask); - - CASC::ReadFile(db2Handle, ©IdSize, sizeof(copyIdSize), &bytesRead); - if (bytesRead != sizeof(copyIdSize)) - return false; - - EndianConvert(copyIdSize); - - CASC::ReadFile(db2Handle, &metaFlags, sizeof(metaFlags), &bytesRead); - if (bytesRead != sizeof(metaFlags)) - return false; - - EndianConvert(metaFlags); - - ASSERT((metaFlags & 0x1) == 0); - ASSERT((meta->IndexField == -1) || (meta->IndexField == int32((metaFlags >> 16)))); - - fields = new FieldEntry[fieldCount]; - CASC::ReadFile(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; - - CASC::ReadFile(db2Handle, data, recordSize * recordCount + stringSize, &bytesRead); - if (bytesRead != recordSize * recordCount + stringSize) - return false; - - if (idTableSize) - { - idTable = new unsigned char[idTableSize]; - CASC::ReadFile(db2Handle, idTable, idTableSize, &bytesRead); - if (bytesRead != idTableSize) - return false; - } - - if (copyIdSize) - { - copyTable = new unsigned char[copyIdSize]; - CASC::ReadFile(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 deleted file mode 100644 index f28aeb0e05f..00000000000 --- a/src/tools/map_extractor/DB2.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2008-2017 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" -#include "CascHandles.h" -#include "CascLib.h" -#include "Utilities/ByteConverter.h" -#include "Errors.h" - -class DB2FileLoader -{ - public: - DB2FileLoader(); - ~DB2FileLoader(); - - bool Load(CASC::FileHandle const& 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 4b0dc6fb74f..e1a5d860946 100644 --- a/src/tools/map_extractor/System.cpp +++ b/src/tools/map_extractor/System.cpp @@ -17,7 +17,20 @@ */ #define _CRT_SECURE_NO_DEPRECATE +#define WIN32_LEAN_AND_MEAN +#include "Banner.h" +#include "CascHandles.h" +#include "Common.h" +#include "DB2CascFileSource.h" +#include "DB2Meta.h" +#include "DBFilesClientList.h" +#include "StringFormat.h" +#include "adt.h" +#include "wdt.h" +#include <CascLib.h> +#include <boost/filesystem/path.hpp> +#include <boost/filesystem/operations.hpp> #include <cstdio> #include <deque> #include <fstream> @@ -25,46 +38,6 @@ #include <cstdlib> #include <cstring> -#include <boost/filesystem/path.hpp> -#include <boost/filesystem/operations.hpp> - -#include "Common.h" -#include "DBFilesClientList.h" -#include "CascLib.h" -#include "CascHandles.h" -#include "DB2.h" -#include "Banner.h" -#include "StringFormat.h" - -#include "adt.h" -#include "wdt.h" - -namespace -{ - const char* HumanReadableCASCError(int error) - { - switch (error) - { - case ERROR_SUCCESS: return "SUCCESS"; - case ERROR_FILE_CORRUPT: return "FILE_CORRUPT"; - case ERROR_CAN_NOT_COMPLETE: return "CAN_NOT_COMPLETE"; - case ERROR_HANDLE_EOF: return "HANDLE_EOF"; - case ERROR_NO_MORE_FILES: return "NO_MORE_FILES"; - case ERROR_BAD_FORMAT: return "BAD_FORMAT"; - case ERROR_INSUFFICIENT_BUFFER: return "INSUFFICIENT_BUFFER"; - case ERROR_ALREADY_EXISTS: return "ALREADY_EXISTS"; - case ERROR_DISK_FULL: return "DISK_FULL"; - case ERROR_INVALID_PARAMETER: return "INVALID_PARAMETER"; - case ERROR_NOT_SUPPORTED: return "NOT_SUPPORTED"; - case ERROR_NOT_ENOUGH_MEMORY: return "NOT_ENOUGH_MEMORY"; - case ERROR_INVALID_HANDLE: return "INVALID_HANDLE"; - case ERROR_ACCESS_DENIED: return "ACCESS_DENIED"; - case ERROR_FILE_NOT_FOUND: return "FILE_NOT_FOUND"; - default: return "UNKNOWN"; - } - } -} - CASC::StorageHandle CascStorage; typedef struct @@ -79,36 +52,128 @@ std::set<std::string> CameraFileNames; boost::filesystem::path input_path; boost::filesystem::path output_path; -struct CinematicCameraMeta +struct CinematicCameraLoadInfo { - static DB2Meta const* Instance() + static DB2FileLoadInfo const* Instance() { + static DB2FieldMeta const fields[] = + { + { false, FT_INT, "ID" }, + { false, FT_STRING_NOT_LOCALIZED, "Model" }, + { false, FT_FLOAT, "OriginX" }, + { false, FT_FLOAT, "OriginY" }, + { false, FT_FLOAT, "OriginZ" }, + { false, FT_FLOAT, "OriginFacing" }, + { false, FT_SHORT, "SoundID" }, + }; static char const* types = "sffh"; static uint8 const arraySizes[4] = { 1, 3, 1, 1 }; - static DB2Meta instance(-1, 4, 0xA7B95349, types, arraySizes); - return &instance; + static DB2Meta const meta(-1, 4, 0xA7B95349, types, arraySizes); + static DB2FileLoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, &meta); + return &loadInfo; } }; -struct LiquidTypeMeta +struct LiquidTypeLoadInfo { - static DB2Meta const* Instance() + static DB2FileLoadInfo const* Instance() { + static DB2FieldMeta const fields[] = + { + { false, FT_INT, "ID" }, + { false, FT_STRING, "Name" }, + { false, FT_INT, "SpellID" }, + { false, FT_FLOAT, "MaxDarkenDepth" }, + { false, FT_FLOAT, "FogDarkenIntensity" }, + { false, FT_FLOAT, "AmbDarkenIntensity" }, + { false, FT_FLOAT, "DirDarkenIntensity" }, + { false, FT_FLOAT, "ParticleScale" }, + { false, FT_STRING_NOT_LOCALIZED, "Texture1" }, + { false, FT_STRING_NOT_LOCALIZED, "Texture2" }, + { false, FT_STRING_NOT_LOCALIZED, "Texture3" }, + { false, FT_STRING_NOT_LOCALIZED, "Texture4" }, + { false, FT_STRING_NOT_LOCALIZED, "Texture5" }, + { false, FT_STRING_NOT_LOCALIZED, "Texture6" }, + { false, FT_INT, "Color1" }, + { false, FT_INT, "Color2" }, + { false, FT_FLOAT, "Float1" }, + { false, FT_FLOAT, "Float2" }, + { false, FT_FLOAT, "Float3" }, + { false, FT_FLOAT, "Float4" }, + { false, FT_FLOAT, "Float5" }, + { false, FT_FLOAT, "Float6" }, + { false, FT_FLOAT, "Float7" }, + { false, FT_FLOAT, "Float8" }, + { false, FT_FLOAT, "Float9" }, + { false, FT_FLOAT, "Float10" }, + { false, FT_FLOAT, "Float11" }, + { false, FT_FLOAT, "Float12" }, + { false, FT_FLOAT, "Float13" }, + { false, FT_FLOAT, "Float14" }, + { false, FT_FLOAT, "Float15" }, + { false, FT_FLOAT, "Float16" }, + { false, FT_FLOAT, "Float17" }, + { false, FT_FLOAT, "Float18" }, + { false, FT_INT, "Int1" }, + { false, FT_INT, "Int2" }, + { false, FT_INT, "Int3" }, + { false, FT_INT, "Int4" }, + { false, FT_SHORT, "Flags" }, + { false, FT_SHORT, "LightID" }, + { false, FT_BYTE, "Type" }, + { false, FT_BYTE, "ParticleMovement" }, + { false, FT_BYTE, "ParticleTexSlots" }, + { false, FT_BYTE, "MaterialID" }, + { false, FT_BYTE, "DepthTexCount1" }, + { false, FT_BYTE, "DepthTexCount2" }, + { false, FT_BYTE, "DepthTexCount3" }, + { false, FT_BYTE, "DepthTexCount4" }, + { false, FT_BYTE, "DepthTexCount5" }, + { false, FT_BYTE, "DepthTexCount6" }, + { false, FT_INT, "SoundID" }, + }; 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, 0x99FC34E5, types, arraySizes); - return &instance; + static DB2Meta const meta(-1, 19, 0x99FC34E5, types, arraySizes); + static DB2FileLoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, &meta); + return &loadInfo; } }; -struct MapMeta +struct MapLoadInfo { - static DB2Meta const* Instance() + static DB2FileLoadInfo const* Instance() { + static DB2FieldMeta const fields[] = + { + { false, FT_INT, "ID" }, + { false, FT_STRING_NOT_LOCALIZED, "Directory" }, + { false, FT_INT, "Flags1" }, + { false, FT_INT, "Flags2" }, + { false, FT_FLOAT, "MinimapIconScale" }, + { false, FT_FLOAT, "CorpsePosX" }, + { false, FT_FLOAT, "CorpsePosY" }, + { false, FT_STRING, "MapName" }, + { false, FT_STRING, "MapDescription0" }, + { false, FT_STRING, "MapDescription1" }, + { false, FT_SHORT, "AreaTableID" }, + { false, FT_SHORT, "LoadingScreenID" }, + { true, FT_SHORT, "CorpseMapID" }, + { false, FT_SHORT, "TimeOfDayOverride" }, + { true, FT_SHORT, "ParentMapID" }, + { true, FT_SHORT, "CosmeticParentMapID" }, + { false, FT_SHORT, "WindSettingsID" }, + { false, FT_BYTE, "InstanceType" }, + { false, FT_BYTE, "unk5" }, + { false, FT_BYTE, "ExpansionID" }, + { false, FT_BYTE, "MaxPlayers" }, + { false, FT_BYTE, "TimeOffset" }, + }; 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, 0xF7CF2DA2, types, arraySizes); - return &instance; + static DB2Meta const meta(-1, 19, 0xF7CF2DA2, types, arraySizes); + static DB2FileLoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, &meta); + return &loadInfo; } }; @@ -306,29 +371,22 @@ void ReadMapDBC() { printf("Read Map.db2 file...\n"); - CASC::FileHandle dbcFile = CASC::OpenFile(CascStorage, "DBFilesClient\\Map.db2", CASC_LOCALE_NONE, true); - if (!dbcFile) - { - exit(1); - } - + DB2CascFileSource source(CascStorage, "DBFilesClient\\Map.db2"); DB2FileLoader db2; - if (!db2.Load(dbcFile, MapMeta::Instance())) + if (!db2.Load(&source, MapLoadInfo::Instance())) { - printf("Fatal error: Invalid Map.db2 file format! %s\n", HumanReadableCASCError(GetLastError())); + printf("Fatal error: Invalid Map.db2 file format! %s\n", CASC::HumanReadableCASCError(GetLastError())); exit(1); } - map_ids.resize(db2.GetNumRows()); + map_ids.resize(db2.GetRecordCount()); std::unordered_map<uint32, uint32> idToIndex; - for (uint32 x = 0; x < db2.GetNumRows(); ++x) + for (uint32 x = 0; x < db2.GetRecordCount(); ++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); + DB2Record record = db2.GetRecord(x); + map_ids[x].id = record.GetId(); - const char* map_name = db2.getRecord(x).getString(0, 0); + const char* map_name = record.GetString(0, 0); size_t max_map_name_length = sizeof(map_ids[x].name); if (strlen(map_name) >= max_map_name_length) { @@ -341,15 +399,14 @@ void ReadMapDBC() idToIndex[map_ids[x].id] = x; } - for (uint32 x = 0; x < db2.GetNumRowCopies(); ++x) + for (uint32 x = 0; x < db2.GetRecordCopyCount(); ++x) { - uint32 from = db2.GetRowCopy(x).first; - uint32 to = db2.GetRowCopy(x).second; - auto itr = idToIndex.find(from); + DB2RecordCopy copy = db2.GetRecordCopy(x); + auto itr = idToIndex.find(copy.SourceRowId); if (itr != idToIndex.end()) { map_id id; - id.id = to; + id.id = copy.NewRowId; strcpy(id.name, map_ids[itr->second].name); map_ids.push_back(id); } @@ -361,14 +418,10 @@ void ReadMapDBC() void ReadLiquidTypeTableDBC() { printf("Read LiquidType.db2 file...\n"); - CASC::FileHandle dbcFile = CASC::OpenFile(CascStorage, "DBFilesClient\\LiquidType.db2", CASC_LOCALE_NONE, true); - if (!dbcFile) - { - exit(1); - } + DB2CascFileSource source(CascStorage, "DBFilesClient\\LiquidType.db2"); DB2FileLoader db2; - if (!db2.Load(dbcFile, LiquidTypeMeta::Instance())) + if (!db2.Load(&source, LiquidTypeLoadInfo::Instance())) { printf("Fatal error: Invalid LiquidType.db2 file format!\n"); exit(1); @@ -376,19 +429,14 @@ void ReadLiquidTypeTableDBC() LiqType.resize(db2.GetMaxId() + 1, 0xFFFF); - for (uint32 x = 0; x < db2.GetNumRows(); ++x) + for (uint32 x = 0; x < db2.GetRecordCount(); ++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); + DB2Record record = db2.GetRecord(x); + LiqType[record.GetId()] = record.GetUInt8(13, 0); } - for (uint32 x = 0; x < db2.GetNumRowCopies(); ++x) - LiqType[db2.GetRowCopy(x).second] = LiqType[db2.GetRowCopy(x).first]; + for (uint32 x = 0; x < db2.GetRecordCopyCount(); ++x) + LiqType[db2.GetRecordCopy(x).NewRowId] = LiqType[db2.GetRecordCopy(x).SourceRowId]; printf("Done! (" SZFMTD " LiqTypes loaded)\n", LiqType.size()); } @@ -397,24 +445,19 @@ bool ReadCinematicCameraDBC() { printf("Read CinematicCamera.db2 file...\n"); - CASC::FileHandle dbcFile = CASC::OpenFile(CascStorage, "DBFilesClient\\CinematicCamera.db2", CASC_LOCALE_NONE, true); - if (!dbcFile) - { - printf("Unable to open CinematicCamera.db2. Camera extract aborted.\n"); - return false; - } - + DB2CascFileSource source(CascStorage, "DBFilesClient\\CinematicCamera.db2"); DB2FileLoader db2; - if (!db2.Load(dbcFile, CinematicCameraMeta::Instance())) + if (!db2.Load(&source, CinematicCameraLoadInfo::Instance())) { - printf("Invalid CinematicCamera.db2 file format. Camera extract aborted. %s\n", HumanReadableCASCError(GetLastError())); + printf("Invalid CinematicCamera.db2 file format. Camera extract aborted. %s\n", CASC::HumanReadableCASCError(GetLastError())); return false; } // get camera file list from DB2 - for (size_t i = 0; i < db2.GetNumRows(); ++i) + for (size_t i = 0; i < db2.GetRecordCount(); ++i) { - std::string camFile(db2.getRecord(i).getString(0, 0)); + DB2Record record = db2.GetRecord(i); + std::string camFile(record.GetString(0, 0)); size_t loc = camFile.find(".mdx"); if (loc != std::string::npos) camFile.replace(loc, 4, ".m2"); @@ -1089,23 +1132,6 @@ bool ConvertADT(std::string const& inputPath, std::string const& outputPath, int return true; } -void ExtractWmos(ChunkedFile& file, std::set<std::string>& wmoList) -{ - if (FileChunk* chunk = file.GetChunk("MWMO")) - { - file_MWMO* wmo = chunk->As<file_MWMO>(); - if (wmo->size) - { - char* fileName = wmo->FileList; - while (fileName < wmo->FileList + wmo->size) - { - wmoList.insert(fileName); - fileName += strlen(fileName) + 1; - } - } - } -} - void ExtractMaps(uint32 build) { std::string storagePath; @@ -1119,8 +1145,6 @@ void ExtractMaps(uint32 build) CreateDir(output_path / "maps"); - std::set<std::string> wmoList; - printf("Convert map files\n"); for (std::size_t z = 0; z < map_ids.size(); ++z) { @@ -1131,8 +1155,6 @@ void ExtractMaps(uint32 build) if (!wdt.loadFile(CascStorage, storagePath, false)) continue; - ExtractWmos(wdt, wmoList); - FileChunk* chunk = wdt.GetChunk("MAIN"); for (uint32 y = 0; y < WDT_MAP_SIZE; ++y) { @@ -1144,11 +1166,6 @@ void ExtractMaps(uint32 build) storagePath = Trinity::StringFormat("World\\Maps\\%s\\%s_%u_%u.adt", map_ids[z].name, map_ids[z].name, x, y); outputFileName = Trinity::StringFormat("%s/maps/%04u_%02u_%02u.map", output_path.string().c_str(), map_ids[z].id, y, x); ConvertADT(storagePath, outputFileName, y, x, build); - - storagePath = Trinity::StringFormat("World\\Maps\\%s\\%s_%u_%u_obj0.adt", map_ids[z].name, map_ids[z].name, x, y); - ChunkedFile adtObj; - if (adtObj.loadFile(CascStorage, storagePath, false)) - ExtractWmos(adtObj, wmoList); } // draw progress bar @@ -1156,17 +1173,6 @@ void ExtractMaps(uint32 build) } } - if (!wmoList.empty()) - { - if (FILE* wmoListFile = fopen("wmo_list.txt", "w")) - { - for (std::string const& wmo : wmoList) - fprintf(wmoListFile, "%s\n", wmo.c_str()); - - fclose(wmoListFile); - } - } - printf("\n"); } @@ -1226,7 +1232,7 @@ void ExtractDBFilesClient(int l) ++count; } else - printf("Unable to open file %s in the archive for locale %s: %s\n", fileName, localeNames[l], HumanReadableCASCError(GetLastError())); + printf("Unable to open file %s in the archive for locale %s: %s\n", fileName, localeNames[l], CASC::HumanReadableCASCError(GetLastError())); fileName = DBFilesClientList[++index]; } @@ -1260,7 +1266,7 @@ void ExtractCameraFiles() ++count; } else - printf("Unable to open file %s in the archive: %s\n", cameraFileName.c_str(), HumanReadableCASCError(GetLastError())); + printf("Unable to open file %s in the archive: %s\n", cameraFileName.c_str(), CASC::HumanReadableCASCError(GetLastError())); } printf("Extracted %u camera files\n", count); @@ -1326,7 +1332,7 @@ void ExtractGameTables() ++count; } else - printf("Unable to open file %s in the archive: %s\n", fileName, HumanReadableCASCError(GetLastError())); + printf("Unable to open file %s in the archive: %s\n", fileName, CASC::HumanReadableCASCError(GetLastError())); fileName = GameTables[++index]; } diff --git a/src/tools/map_extractor/loadlib.cpp b/src/tools/map_extractor/loadlib.cpp index cb195f6b714..6f21c92ce5e 100644 --- a/src/tools/map_extractor/loadlib.cpp +++ b/src/tools/map_extractor/loadlib.cpp @@ -19,6 +19,7 @@ #define _CRT_SECURE_NO_DEPRECATE #include "loadlib.h" +#include <CascLib.h> u_map_fcc MverMagic = { { 'R','E','V','M' } }; @@ -40,9 +41,16 @@ bool ChunkedFile::loadFile(CASC::StorageHandle const& mpq, std::string const& fi if (!file) return false; - data_size = CASC::GetFileSize(file, nullptr); + DWORD fileSize = CASC::GetFileSize(file, nullptr); + if (fileSize == CASC_INVALID_SIZE) + return false; + + data_size = fileSize; data = new uint8[data_size]; - CASC::ReadFile(file, data, data_size, nullptr/*bytesRead*/); + DWORD bytesRead = 0; + if (!CASC::ReadFile(file, data, data_size, &bytesRead) || bytesRead != data_size) + return false; + parseChunks(); if (prepareLoadedData()) return true; diff --git a/src/tools/map_extractor/loadlib/loadlib.h b/src/tools/map_extractor/loadlib/loadlib.h index 3267d944955..d6a8b9015c3 100644 --- a/src/tools/map_extractor/loadlib/loadlib.h +++ b/src/tools/map_extractor/loadlib/loadlib.h @@ -21,7 +21,6 @@ #include "Define.h" #include "CascHandles.h" -#include "CascLib.h" #include <map> #include <string> diff --git a/src/tools/vmap4_extractor/CMakeLists.txt b/src/tools/vmap4_extractor/CMakeLists.txt index 8ef299295f8..8af68c8e8ed 100644 --- a/src/tools/vmap4_extractor/CMakeLists.txt +++ b/src/tools/vmap4_extractor/CMakeLists.txt @@ -21,8 +21,6 @@ add_executable(vmap4extractor ${PRIVATE_SOURCES}) target_link_libraries(vmap4extractor PUBLIC - common - casc bzip2 extractor_common) diff --git a/src/tools/vmap4_extractor/DB2.cpp b/src/tools/vmap4_extractor/DB2.cpp deleted file mode 100644 index fca95476edb..00000000000 --- a/src/tools/vmap4_extractor/DB2.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2008-2017 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" -#include <cassert> - -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(CASC::FileHandle const& db2Handle, DB2Meta const* meta_) -{ - if (data) - { - delete[] data; - data = nullptr; - } - - DWORD bytesRead = 0; - meta = meta_; - std::uint32_t header; - CASC::ReadFile(db2Handle, &header, sizeof(header), &bytesRead); - if (bytesRead != sizeof(header)) // Signature - return false; - - EndianConvert(header); - - if (header != 0x35424457) - return false; //'WDB5' - - CASC::ReadFile(db2Handle, &recordCount, sizeof(recordCount), &bytesRead); - if (bytesRead != sizeof(recordCount)) // Number of records - return false; - - EndianConvert(recordCount); - - CASC::ReadFile(db2Handle, &fieldCount, sizeof(fieldCount), &bytesRead); - if (bytesRead != sizeof(fieldCount)) // Number of fields - return false; - - EndianConvert(fieldCount); - - CASC::ReadFile(db2Handle, &recordSize, sizeof(recordSize), &bytesRead); - if (bytesRead != sizeof(recordSize)) // Size of a record - return false; - - EndianConvert(recordSize); - - CASC::ReadFile(db2Handle, &stringSize, sizeof(stringSize), &bytesRead); - if (bytesRead != sizeof(stringSize)) // String size - return false; - - EndianConvert(stringSize); - - CASC::ReadFile(db2Handle, &tableHash, sizeof(tableHash), &bytesRead); - if (bytesRead != sizeof(tableHash)) // Table hash - return false; - - EndianConvert(tableHash); - - CASC::ReadFile(db2Handle, &layoutHash, sizeof(layoutHash), &bytesRead); - if (bytesRead != sizeof(layoutHash)) // Layout hash - return false; - - if (layoutHash != meta->LayoutHash) - return false; - - EndianConvert(layoutHash); - - CASC::ReadFile(db2Handle, &minIndex, sizeof(minIndex), &bytesRead); - if (bytesRead != sizeof(minIndex)) // MinIndex WDB2 - return false; - - EndianConvert(minIndex); - - CASC::ReadFile(db2Handle, &maxIndex, sizeof(maxIndex), &bytesRead); - if (bytesRead != sizeof(maxIndex)) // MaxIndex WDB2 - return false; - - EndianConvert(maxIndex); - - CASC::ReadFile(db2Handle, &localeMask, sizeof(localeMask), &bytesRead); - if (bytesRead != sizeof(localeMask)) // Locales - return false; - - EndianConvert(localeMask); - - CASC::ReadFile(db2Handle, ©IdSize, sizeof(copyIdSize), &bytesRead); - if (bytesRead != sizeof(copyIdSize)) - return false; - - EndianConvert(copyIdSize); - - CASC::ReadFile(db2Handle, &metaFlags, sizeof(metaFlags), &bytesRead); - if (bytesRead != sizeof(metaFlags)) - return false; - - EndianConvert(metaFlags); - - ASSERT((metaFlags & 0x1) == 0); - ASSERT((meta->IndexField == -1) || (meta->IndexField == int32((metaFlags >> 16)))); - - fields = new FieldEntry[fieldCount]; - CASC::ReadFile(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; - - CASC::ReadFile(db2Handle, data, recordSize * recordCount + stringSize, &bytesRead); - if (bytesRead != recordSize * recordCount + stringSize) - return false; - - if (idTableSize) - { - idTable = new unsigned char[idTableSize]; - CASC::ReadFile(db2Handle, idTable, idTableSize, &bytesRead); - if (bytesRead != idTableSize) - return false; - } - - if (copyIdSize) - { - copyTable = new unsigned char[copyIdSize]; - CASC::ReadFile(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 deleted file mode 100644 index f28aeb0e05f..00000000000 --- a/src/tools/vmap4_extractor/DB2.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2008-2017 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" -#include "CascHandles.h" -#include "CascLib.h" -#include "Utilities/ByteConverter.h" -#include "Errors.h" - -class DB2FileLoader -{ - public: - DB2FileLoader(); - ~DB2FileLoader(); - - bool Load(CASC::FileHandle const& 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/adtfile.cpp b/src/tools/vmap4_extractor/adtfile.cpp index f4cb5b686da..e97469c0918 100644 --- a/src/tools/vmap4_extractor/adtfile.cpp +++ b/src/tools/vmap4_extractor/adtfile.cpp @@ -148,12 +148,16 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY) char* p = buf; while (p < buf + size) { + std::string path(p); + char* s = GetPlainName(p); FixNameCase(s, strlen(s)); FixNameSpaces(s, strlen(s)); WmoInstanceNames.push_back(s); + ExtractSingleWmo(path); + p += strlen(p) + 1; } delete[] buf; diff --git a/src/tools/vmap4_extractor/cascfile.cpp b/src/tools/vmap4_extractor/cascfile.cpp index b9074d8696e..2a54e5ba27b 100644 --- a/src/tools/vmap4_extractor/cascfile.cpp +++ b/src/tools/vmap4_extractor/cascfile.cpp @@ -1,5 +1,22 @@ +/* + * Copyright (C) 2008-2017 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 "cascfile.h" -#include <deque> +#include <CascLib.h> #include <cstdio> CASCFile::CASCFile(CASC::StorageHandle const& casc, const char* filename, bool warnNoExist /*= true*/) : @@ -12,33 +29,34 @@ CASCFile::CASCFile(CASC::StorageHandle const& casc, const char* filename, bool w if (!file) { if (warnNoExist || GetLastError() != ERROR_FILE_NOT_FOUND) - fprintf(stderr, "Can't open %s, err=%u!\n", filename, GetLastError()); + fprintf(stderr, "Can't open %s: %s\n", filename, CASC::HumanReadableCASCError(GetLastError())); eof = true; return; } - DWORD hi = 0; - size = CASC::GetFileSize(file, &hi); - - if (hi) + DWORD fileSizeHigh = 0; + DWORD fileSize = CASC::GetFileSize(file, &fileSizeHigh); + if (fileSize == CASC_INVALID_SIZE) { - fprintf(stderr, "Can't open %s, size[hi] = %u!\n", filename, uint32(hi)); + fprintf(stderr, "Can't open %s, failed to get size: %s!\n", filename, CASC::HumanReadableCASCError(GetLastError())); eof = true; return; } - if (size <= 1) + if (fileSizeHigh) { - fprintf(stderr, "Can't open %s, size = %u!\n", filename, uint32(size)); + fprintf(stderr, "Can't open %s, file larger than 2GB", filename); eof = true; return; } + size = fileSize; + DWORD read = 0; buffer = new char[size]; if (!CASC::ReadFile(file, buffer, size, &read) || size != read) { - fprintf(stderr, "Can't read %s, size=%u read=%u!\n", filename, uint32(size), uint32(read)); + fprintf(stderr, "Can't read %s, size=%u read=%u: %s\n", filename, uint32(size), uint32(read), CASC::HumanReadableCASCError(GetLastError())); eof = true; return; } @@ -46,10 +64,12 @@ CASCFile::CASCFile(CASC::StorageHandle const& casc, const char* filename, bool w size_t CASCFile::read(void* dest, size_t bytes) { - if (eof) return 0; + if (eof) + return 0; size_t rpos = pointer + bytes; - if (rpos > size) { + if (rpos > size) + { bytes = size - pointer; eof = true; } @@ -75,7 +95,7 @@ void CASCFile::seekRelative(int offset) void CASCFile::close() { - if (buffer) delete[] buffer; + delete[] buffer; buffer = 0; eof = true; } diff --git a/src/tools/vmap4_extractor/cascfile.h b/src/tools/vmap4_extractor/cascfile.h index 882ec116ca5..fd97fb6e008 100644 --- a/src/tools/vmap4_extractor/cascfile.h +++ b/src/tools/vmap4_extractor/cascfile.h @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2008-2017 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/>. + */ + #define _CRT_SECURE_NO_DEPRECATE #ifndef _CRT_SECURE_NO_WARNINGS // fuck the police^Wwarnings #define _CRT_SECURE_NO_WARNINGS @@ -6,33 +23,12 @@ #ifndef MPQ_H #define MPQ_H -#include <string.h> -#include <ctype.h> -#include <vector> -#include <iostream> -#include <deque> -#include <cstdint> +#include "Define.h" #include "CascHandles.h" -#include "CascLib.h" - -typedef int64_t int64; -typedef int32_t int32; -typedef int16_t int16; -typedef int8_t int8; -typedef uint64_t uint64; -typedef uint32_t uint32; -typedef uint16_t uint16; -typedef uint8_t uint8; - -#ifdef _WIN32 -#include <Windows.h> // mainly only HANDLE definition is required -#else -int GetLastError(); -#endif +#include <utility> class CASCFile { - //MPQHANDLE handle; bool eof; char *buffer; size_t pointer,size; @@ -57,13 +53,8 @@ public: inline void flipcc(char *fcc) { - char t; - t=fcc[0]; - fcc[0]=fcc[3]; - fcc[3]=t; - t=fcc[1]; - fcc[1]=fcc[2]; - fcc[2]=t; + std::swap(fcc[0], fcc[3]); + std::swap(fcc[1], fcc[2]); } #endif diff --git a/src/tools/vmap4_extractor/gameobject_extract.cpp b/src/tools/vmap4_extractor/gameobject_extract.cpp index 08777315470..73fa7130f24 100644 --- a/src/tools/vmap4_extractor/gameobject_extract.cpp +++ b/src/tools/vmap4_extractor/gameobject_extract.cpp @@ -16,14 +16,16 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "DB2.h" -#include "model.h" #include "adtfile.h" -#include "vmapexport.h" +#include "DB2CascFileSource.h" +#include "DB2Meta.h" +#include "Errors.h" +#include "model.h" #include "StringFormat.h" - +#include "vmapexport.h" +#include <CascLib.h> #include <algorithm> -#include <stdio.h> +#include <cstdio> bool ExtractSingleModel(std::string& fname) { @@ -55,14 +57,29 @@ bool ExtractSingleModel(std::string& fname) extern CASC::StorageHandle CascStorage; -struct GameObjectDisplayInfoMeta +struct GameobjectDisplayInfoLoadInfo { - static DB2Meta const* Instance() + static DB2FileLoadInfo const* Instance() { + static DB2FieldMeta const fields[] = + { + { false, FT_INT, "ID" }, + { false, FT_INT, "FileDataID" }, + { false, FT_FLOAT, "GeoBoxMinX" }, + { false, FT_FLOAT, "GeoBoxMinY" }, + { false, FT_FLOAT, "GeoBoxMinZ" }, + { false, FT_FLOAT, "GeoBoxMaxX" }, + { false, FT_FLOAT, "GeoBoxMaxY" }, + { false, FT_FLOAT, "GeoBoxMaxZ" }, + { false, FT_FLOAT, "OverrideLootEffectScale" }, + { false, FT_FLOAT, "OverrideNameScale" }, + { false, FT_SHORT, "ObjectEffectPackageID" }, + }; static char const* types = "ifffh"; static uint8 const arraySizes[5] = { 1, 6, 1, 1, 1 }; - static DB2Meta instance(-1, 5, 0xE2D6FAB7, types, arraySizes); - return &instance; + static DB2Meta const meta(-1, 5, 0xE2D6FAB7, types, arraySizes); + static DB2FileLoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, &meta); + return &loadInfo; } }; @@ -89,15 +106,11 @@ bool GetHeaderMagic(std::string const& fileName, uint32* magic) void ExtractGameobjectModels() { - printf("Extracting GameObject models..."); - CASC::FileHandle dbcFile = CASC::OpenFile(CascStorage, "DBFilesClient\\GameObjectDisplayInfo.db2", CASC_LOCALE_NONE, true); - if (!dbcFile) - { - exit(1); - } + printf("Extracting GameObject models...\n"); + DB2CascFileSource source(CascStorage, "DBFilesClient\\GameObjectDisplayInfo.db2"); DB2FileLoader db2; - if (!db2.Load(dbcFile, GameObjectDisplayInfoMeta::Instance())) + if (!db2.Load(&source, GameobjectDisplayInfoLoadInfo::Instance())) { printf("Fatal error: Invalid GameObjectDisplayInfo.db2 file format!\n"); exit(1); @@ -114,9 +127,10 @@ void ExtractGameobjectModels() return; } - for (uint32 rec = 0; rec < db2.GetNumRows(); ++rec) + for (uint32 rec = 0; rec < db2.GetRecordCount(); ++rec) { - uint32 fileId = db2.getRecord(rec).getUInt(0, 0); + DB2Record record = db2.GetRecord(rec); + uint32 fileId = record.GetUInt32(0, 0); if (!fileId) continue; @@ -135,7 +149,7 @@ void ExtractGameobjectModels() if (result) { - uint32 displayId = db2.getId(rec); + uint32 displayId = record.GetId(); uint32 path_length = fileName.length(); fwrite(&displayId, sizeof(uint32), 1, model_list); fwrite(&path_length, sizeof(uint32), 1, model_list); diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp index 571b8655646..02d0df202de 100644 --- a/src/tools/vmap4_extractor/vmapexport.cpp +++ b/src/tools/vmap4_extractor/vmapexport.cpp @@ -17,14 +17,29 @@ */ #define _CRT_SECURE_NO_DEPRECATE -#include <cstdio> +#define WIN32_LEAN_AND_MEAN + +#include "adtfile.h" +#include "Banner.h" +#include "Common.h" +#include "cascfile.h" +#include "DB2CascFileSource.h" +#include "DB2Meta.h" +#include "StringFormat.h" +#include "vmapexport.h" +#include "wdtfile.h" +#include "wmo.h" +#include <CascLib.h> +#include <boost/filesystem/operations.hpp> +#include <fstream> #include <iostream> -#include <vector> #include <list> -#include <errno.h> +#include <map> +#include <vector> +#include <cstdio> +#include <cerrno> #ifdef WIN32 - #define WIN32_LEAN_AND_MEAN #include <Windows.h> #include <sys/stat.h> #include <direct.h> @@ -34,22 +49,6 @@ #define ERROR_PATH_NOT_FOUND ERROR_FILE_NOT_FOUND #endif -#include <map> -#include <fstream> - -#include "Common.h" -//From Extractor -#include "adtfile.h" -#include "wdtfile.h" -#include "DB2.h" -#include "wmo.h" -#include "cascfile.h" - -#include "vmapexport.h" -#include "Banner.h" -#include <boost/filesystem/path.hpp> -#include <boost/filesystem/operations.hpp> - //------------------------------------------------------------------------------ // Defines @@ -66,30 +65,44 @@ typedef struct }map_id; std::vector<map_id> map_ids; -std::vector<uint16> LiqType; uint32 map_count; boost::filesystem::path input_path; 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, 0x99FC34E5, types, arraySizes); - return &instance; - } -}; - -struct MapMeta +struct MapLoadInfo { - static DB2Meta const* Instance() + static DB2FileLoadInfo const* Instance() { + static DB2FieldMeta const fields[] = + { + { false, FT_INT, "ID" }, + { false, FT_STRING_NOT_LOCALIZED, "Directory" }, + { false, FT_INT, "Flags1" }, + { false, FT_INT, "Flags2" }, + { false, FT_FLOAT, "MinimapIconScale" }, + { false, FT_FLOAT, "CorpsePosX" }, + { false, FT_FLOAT, "CorpsePosY" }, + { false, FT_STRING, "MapName" }, + { false, FT_STRING, "MapDescription0" }, + { false, FT_STRING, "MapDescription1" }, + { false, FT_SHORT, "AreaTableID" }, + { false, FT_SHORT, "LoadingScreenID" }, + { true, FT_SHORT, "CorpseMapID" }, + { false, FT_SHORT, "TimeOfDayOverride" }, + { true, FT_SHORT, "ParentMapID" }, + { true, FT_SHORT, "CosmeticParentMapID" }, + { false, FT_SHORT, "WindSettingsID" }, + { false, FT_BYTE, "InstanceType" }, + { false, FT_BYTE, "unk5" }, + { false, FT_BYTE, "ExpansionID" }, + { false, FT_BYTE, "MaxPlayers" }, + { false, FT_BYTE, "TimeOffset" }, + }; 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, 0xF7CF2DA2, types, arraySizes); - return &instance; + static DB2Meta const meta(-1, 19, 0xF7CF2DA2, types, arraySizes); + static DB2FileLoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, &meta); + return &loadInfo; } }; @@ -129,32 +142,6 @@ uint32 WowLocaleToCascLocaleFlags[12] = CASC_LOCALE_ITIT, }; -namespace -{ - const char* HumanReadableCASCError(int error) - { - switch (error) - { - case ERROR_SUCCESS: return "SUCCESS"; - case ERROR_FILE_CORRUPT: return "FILE_CORRUPT"; - case ERROR_CAN_NOT_COMPLETE: return "CAN_NOT_COMPLETE"; - case ERROR_HANDLE_EOF: return "HANDLE_EOF"; - case ERROR_NO_MORE_FILES: return "NO_MORE_FILES"; - case ERROR_BAD_FORMAT: return "BAD_FORMAT"; - case ERROR_INSUFFICIENT_BUFFER: return "INSUFFICIENT_BUFFER"; - case ERROR_ALREADY_EXISTS: return "ALREADY_EXISTS"; - case ERROR_DISK_FULL: return "DISK_FULL"; - case ERROR_INVALID_PARAMETER: return "INVALID_PARAMETER"; - case ERROR_NOT_SUPPORTED: return "NOT_SUPPORTED"; - case ERROR_NOT_ENOUGH_MEMORY: return "NOT_ENOUGH_MEMORY"; - case ERROR_INVALID_HANDLE: return "INVALID_HANDLE"; - case ERROR_ACCESS_DENIED: return "ACCESS_DENIED"; - case ERROR_FILE_NOT_FOUND: return "FILE_NOT_FOUND"; - default: return "UNKNOWN"; - } - } -} - uint32 ReadBuild(int locale) { // include build info file also @@ -241,73 +228,6 @@ void strToLower(char* str) } } -// copied from src\tools\map_extractor\System.cpp -void ReadLiquidTypeTableDBC() -{ - printf("Read LiquidType.dbc file..."); - CASC::FileHandle dbcFile = CASC::OpenFile(CascStorage, "DBFilesClient\\LiquidType.db2", CASC_LOCALE_NONE, true); - if (!dbcFile) - { - exit(1); - } - - DB2FileLoader db2; - if (!db2.Load(dbcFile, LiquidTypeMeta::Instance())) - { - printf("Fatal error: Invalid LiquidType.db2 file format!\n"); - exit(1); - } - - LiqType.resize(db2.GetMaxId() + 1, 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 < db2.GetNumRowCopies(); ++x) - LiqType[db2.GetRowCopy(x).second] = LiqType[db2.GetRowCopy(x).first]; - - printf("Done! (" SZFMTD " LiqTypes loaded)\n", LiqType.size()); -} - -bool ExtractWmo() -{ - bool success = true; - - std::ifstream wmoList("wmo_list.txt"); - if (!wmoList) - { - printf("\nUnable to open wmo_list.txt! Nothing extracted.\n"); - return false; - } - - std::set<std::string> wmos; - for (;;) - { - std::string str; - std::getline(wmoList, str); - if (str.empty()) - break; - - wmos.insert(std::move(str)); - } - - for (std::string str : wmos) - success &= ExtractSingleWmo(str); - - if (success) - printf("\nExtract wmo complete (No (fatal) errors)\n"); - - return success; -} - bool ExtractSingleWmo(std::string& fname) { // Copy files from archive @@ -315,7 +235,8 @@ bool ExtractSingleWmo(std::string& fname) char szLocalFile[1024]; const char * plain_name = GetPlainName(fname.c_str()); sprintf(szLocalFile, "%s/%s", szWorkDirWmo, plain_name); - FixNameCase(szLocalFile,strlen(szLocalFile)); + FixNameCase(szLocalFile, strlen(szLocalFile)); + FixNameSpaces(szLocalFile, strlen(szLocalFile)); if (FileExists(szLocalFile)) return true; @@ -339,7 +260,7 @@ bool ExtractSingleWmo(std::string& fname) return true; bool file_ok = true; - std::cout << "Extracting " << fname << std::endl; + printf("Extracting %s\n", fname.c_str()); WMORoot froot(fname); if(!froot.open()) { @@ -355,25 +276,18 @@ bool ExtractSingleWmo(std::string& fname) froot.ConvertToVMAPRootWmo(output); int Wmo_nVertices = 0; //printf("root has %d groups\n", froot->nGroups); - if (!froot.groupFileDataIDs.empty()) + for (std::size_t i = 0; i < froot.groupFileDataIDs.size(); ++i) { - for (std::size_t i = 0; i < froot.groupFileDataIDs.size(); ++i) + std::string s = Trinity::StringFormat("FILE%08X.xxx", froot.groupFileDataIDs[i]); + WMOGroup fgroup(s); + if(!fgroup.open()) { - char groupFileName[1024]; - sprintf(groupFileName, "FILE%08X", froot.groupFileDataIDs[i]); - //printf("Trying to open groupfile %s\n",groupFileName); - - std::string s = groupFileName; - WMOGroup fgroup(s); - if(!fgroup.open()) - { - printf("Could not open all Group file for: %s\n", plain_name); - file_ok = false; - break; - } - - Wmo_nVertices += fgroup.ConvertToVMAPGroupWmo(output, &froot, preciseVectorData); + printf("Could not open all Group file for: %s\n", plain_name); + file_ok = false; + break; } + + Wmo_nVertices += fgroup.ConvertToVMAPGroupWmo(output, &froot, preciseVectorData); } fseek(output, 8, SEEK_SET); // store the correct no of vertices @@ -544,41 +458,28 @@ int main(int argc, char ** argv) // Extract models, listed in GameObjectDisplayInfo.dbc ExtractGameobjectModels(); - ReadLiquidTypeTableDBC(); - - // extract data - if (success) - success = ExtractWmo(); - //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx //map.dbc if (success) { printf("Read Map.dbc file... "); - CASC::FileHandle dbcFile = CASC::OpenFile(CascStorage, "DBFilesClient\\Map.db2", CASC_LOCALE_NONE, true); - if (!dbcFile) - { - exit(1); - } - + DB2CascFileSource source(CascStorage, "DBFilesClient\\Map.db2"); DB2FileLoader db2; - if (!db2.Load(dbcFile, MapMeta::Instance())) + if (!db2.Load(&source, MapLoadInfo::Instance())) { - printf("Fatal error: Invalid Map.db2 file format! %s\n", HumanReadableCASCError(GetLastError())); + printf("Fatal error: Invalid Map.db2 file format! %s\n", CASC::HumanReadableCASCError(GetLastError())); exit(1); } - map_ids.resize(db2.GetNumRows()); + map_ids.resize(db2.GetRecordCount()); std::unordered_map<uint32, uint32> idToIndex; - for (uint32 x = 0; x < db2.GetNumRows(); ++x) + for (uint32 x = 0; x < db2.GetRecordCount(); ++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); + DB2Record record = db2.GetRecord(x); + map_ids[x].id = record.GetId(); - const char* map_name = db2.getRecord(x).getString(0, 0); + const char* map_name = record.GetString(0, 0); size_t max_map_name_length = sizeof(map_ids[x].name); if (strlen(map_name) >= max_map_name_length) { @@ -591,15 +492,14 @@ int main(int argc, char ** argv) idToIndex[map_ids[x].id] = x; } - for (uint32 x = 0; x < db2.GetNumRowCopies(); ++x) + for (uint32 x = 0; x < db2.GetRecordCopyCount(); ++x) { - uint32 from = db2.GetRowCopy(x).first; - uint32 to = db2.GetRowCopy(x).second; - auto itr = idToIndex.find(from); + DB2RecordCopy copy = db2.GetRecordCopy(x); + auto itr = idToIndex.find(copy.SourceRowId); if (itr != idToIndex.end()) { map_id id; - id.id = to; + id.id = copy.NewRowId; strcpy(id.name, map_ids[itr->second].name); map_ids.push_back(id); } diff --git a/src/tools/vmap4_extractor/wdtfile.cpp b/src/tools/vmap4_extractor/wdtfile.cpp index ce2e98886bf..318d16ad3bc 100644 --- a/src/tools/vmap4_extractor/wdtfile.cpp +++ b/src/tools/vmap4_extractor/wdtfile.cpp @@ -80,10 +80,15 @@ bool WDTFile::init(char* /*map_id*/, unsigned int mapID) char *p = buf; while (p < buf + size) { + std::string path(p); + char* s = wdtGetPlainName(p); FixNameCase(s, strlen(s)); + FixNameSpaces(s, strlen(s)); p = p + strlen(p) + 1; gWmoInstansName.push_back(s); + + ExtractSingleWmo(path); } delete[] buf; } diff --git a/src/tools/vmap4_extractor/wdtfile.h b/src/tools/vmap4_extractor/wdtfile.h index 2a7d7df797c..07fc20bd9a8 100644 --- a/src/tools/vmap4_extractor/wdtfile.h +++ b/src/tools/vmap4_extractor/wdtfile.h @@ -23,7 +23,6 @@ #include "wmo.h" #include <string> #include <vector> -#include <cstdlib> class ADTFile; diff --git a/src/tools/vmap4_extractor/wmo.cpp b/src/tools/vmap4_extractor/wmo.cpp index b538da01d0e..03e32658337 100644 --- a/src/tools/vmap4_extractor/wmo.cpp +++ b/src/tools/vmap4_extractor/wmo.cpp @@ -29,7 +29,6 @@ #include "cascfile.h" using namespace std; -extern std::vector<uint16> LiqType; WMORoot::WMORoot(std::string &filename) : filename(filename), color(0), nTextures(0), nGroups(0), nPortals(0), nLights(0), diff --git a/src/tools/vmap4_extractor/wmo.h b/src/tools/vmap4_extractor/wmo.h index 05bc940042a..adb84e022c5 100644 --- a/src/tools/vmap4_extractor/wmo.h +++ b/src/tools/vmap4_extractor/wmo.h @@ -135,8 +135,6 @@ public: uint32 indx, id, d2, d3; WMOInstance(CASCFile&f , char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile); - - static void reset(); }; #endif |