diff options
Diffstat (limited to 'src/server/shared')
| -rw-r--r-- | src/server/shared/DataStores/DB2FileLoader.cpp | 408 | ||||
| -rw-r--r-- | src/server/shared/DataStores/DB2FileLoader.h | 106 | ||||
| -rw-r--r-- | src/server/shared/DataStores/DB2Store.h | 141 | ||||
| -rwxr-xr-x | src/server/shared/DataStores/DBCFileLoader.h | 4 | ||||
| -rwxr-xr-x[-rw-r--r--] | src/server/shared/Database/Implementation/CharacterDatabase.cpp | 21 | ||||
| -rwxr-xr-x[-rw-r--r--] | src/server/shared/Database/Implementation/CharacterDatabase.h | 2 | ||||
| -rwxr-xr-x | src/server/shared/Define.h | 14 | ||||
| -rwxr-xr-x | src/server/shared/Logging/Log.cpp | 7 | ||||
| -rwxr-xr-x | src/server/shared/Logging/Log.h | 2 | ||||
| -rw-r--r-- | src/server/shared/Packets/ByteBuffer.cpp | 85 | ||||
| -rwxr-xr-x | src/server/shared/Packets/ByteBuffer.h | 251 | ||||
| -rwxr-xr-x | src/server/shared/Packets/WorldPacket.h | 52 |
12 files changed, 1021 insertions, 72 deletions
diff --git a/src/server/shared/DataStores/DB2FileLoader.cpp b/src/server/shared/DataStores/DB2FileLoader.cpp new file mode 100644 index 00000000000..14170845211 --- /dev/null +++ b/src/server/shared/DataStores/DB2FileLoader.cpp @@ -0,0 +1,408 @@ +/* + * Copyright (C) 2011 TrintiyCore <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 "Common.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "DB2FileLoader.h" + +DB2FileLoader::DB2FileLoader() +{ + data = NULL; + fieldsOffset = NULL; +} + +bool DB2FileLoader::Load(const char *filename, const char *fmt) +{ + uint32 header = 48; + if (data) + { + delete [] data; + data=NULL; + } + + FILE * f = fopen(filename, "rb"); + if (!f) + return false; + + if (fread(&header, 4, 1, f) != 1) // Signature + { + fclose(f); + return false; + } + + EndianConvert(header); + + if (header != 0x32424457) + { + fclose(f); + return false; //'WDB2' + } + + if (fread(&recordCount, 4, 1, f) != 1) // Number of records + { + fclose(f); + return false; + } + + EndianConvert(recordCount); + + if (fread(&fieldCount, 4, 1, f) != 1) // Number of fields + { + fclose(f); + return false; + } + + EndianConvert(fieldCount); + + if (fread(&recordSize, 4, 1, f) != 1) // Size of a record + { + fclose(f); + return false; + } + + EndianConvert(recordSize); + + if (fread(&stringSize, 4, 1, f) != 1) // String size + { + fclose(f); + return false; + } + + EndianConvert(stringSize); + + /* NEW WDB2 FIELDS*/ + if (fread(&tableHash, 4, 1, f) != 1) // Table hash + { + fclose(f); + return false; + } + + EndianConvert(tableHash); + + if (fread(&build, 4, 1, f) != 1) // Build + { + fclose(f); + return false; + } + + EndianConvert(build); + + if (fread(&unk1, 4, 1, f) != 1) // Unknown WDB2 + { + fclose(f); + return false; + } + + EndianConvert(unk1); + + if (build > 12880) + { + if (fread(&unk2, 4, 1, f) != 1) // Unknown WDB2 + { + fclose(f); + return false; + } + EndianConvert(unk2); + + if (fread(&maxIndex, 4, 1, f) != 1) // MaxIndex WDB2 + { + fclose(f); + return false; + } + EndianConvert(maxIndex); + + if (fread(&locale, 4, 1, f) != 1) // Locales + { + fclose(f); + return false; + } + EndianConvert(locale); + + if (fread(&unk5, 4, 1, f) != 1) // Unknown WDB2 + { + fclose(f); + return false; + } + EndianConvert(unk5); + } + + if (maxIndex != 0) + { + int32 diff = maxIndex - unk2 + 1; + fseek(f, diff * 4 + diff * 2, SEEK_CUR); // diff * 4: an index for rows, diff * 2: a memory allocation bank + } + + fieldsOffset = new uint32[fieldCount]; + fieldsOffset[0] = 0; + for (uint32 i = 1; i < fieldCount; i++) + { + fieldsOffset[i] = fieldsOffset[i - 1]; + if (fmt[i - 1] == 'b' || fmt[i - 1] == 'X') + fieldsOffset[i] += 1; + else + fieldsOffset[i] += 4; + } + + data = new unsigned char[recordSize*recordCount+stringSize]; + stringTable = data + recordSize*recordCount; + + if (fread(data, recordSize * recordCount + stringSize, 1, f) != 1) + { + fclose(f); + return false; + } + + fclose(f); + return true; +} + +DB2FileLoader::~DB2FileLoader() +{ + if (data) + delete [] data; + if (fieldsOffset) + delete [] fieldsOffset; +} + +DB2FileLoader::Record DB2FileLoader::getRecord(size_t id) +{ + assert(data); + return Record(*this, data + id*recordSize); +} + +uint32 DB2FileLoader::GetFormatRecordSize(const char * format, int32* index_pos) +{ + uint32 recordsize = 0; + int32 i = -1; + for (uint32 x=0; format[x]; ++x) + { + switch(format[x]) + { + case FT_FLOAT: + case FT_INT: + recordsize += 4; + break; + case FT_STRING: + recordsize += sizeof(char*); + break; + case FT_SORT: + i = x; + break; + case FT_IND: + i = x; + recordsize += 4; + break; + case FT_BYTE: + recordsize += 1; + break; + } + } + + if (index_pos) + *index_pos = i; + + return recordsize; +} + +uint32 DB2FileLoader::GetFormatStringsFields(const char * format) +{ + uint32 stringfields = 0; + for (uint32 x=0; format[x]; ++x) + if (format[x] == FT_STRING) + ++stringfields; + + return stringfields; +} + +char* DB2FileLoader::AutoProduceData(const char* format, uint32& records, char**& indexTable) +{ + + typedef char * ptr; + if (strlen(format) != fieldCount) + return NULL; + + //get struct size and index pos + int32 i; + uint32 recordsize=GetFormatRecordSize(format, &i); + + if (i >= 0) + { + uint32 maxi = 0; + //find max index + for (uint32 y = 0; y < recordCount; y++) + { + uint32 ind=getRecord(y).getUInt(i); + if (ind>maxi) + maxi = ind; + } + + ++maxi; + records = maxi; + indexTable = new ptr[maxi]; + memset(indexTable, 0, maxi * sizeof(ptr)); + } + else + { + records = recordCount; + indexTable = new ptr[recordCount]; + } + + char* dataTable = new char[recordCount * recordsize]; + + uint32 offset=0; + + for (uint32 y =0; y < recordCount; y++) + { + if (i>=0) + { + indexTable[getRecord(y).getUInt(i)] = &dataTable[offset]; + } + else + indexTable[y] = &dataTable[offset]; + + for (uint32 x = 0; x < fieldCount; x++) + { + switch(format[x]) + { + case FT_FLOAT: + *((float*)(&dataTable[offset])) = getRecord(y).getFloat(x); + offset += 4; + break; + case FT_IND: + case FT_INT: + *((uint32*)(&dataTable[offset])) = getRecord(y).getUInt(x); + offset += 4; + break; + case FT_BYTE: + *((uint8*)(&dataTable[offset])) = getRecord(y).getUInt8(x); + offset += 1; + break; + case FT_STRING: + *((char**)(&dataTable[offset])) = NULL; // will be replaces non-empty or "" strings in AutoProduceStrings + offset += sizeof(char*); + break; + } + } + } + + return dataTable; +} + +static char const* const nullStr = ""; + +char* DB2FileLoader::AutoProduceStringsArrayHolders(const char* format, char* dataTable) +{ + if (strlen(format) != fieldCount) + return NULL; + + // we store flat holders pool as single memory block + size_t stringFields = GetFormatStringsFields(format); + // each string field at load have array of string for each locale + size_t stringHolderSize = sizeof(char*) * TOTAL_LOCALES; + size_t stringHoldersRecordPoolSize = stringFields * stringHolderSize; + size_t stringHoldersPoolSize = stringHoldersRecordPoolSize * recordCount; + + char* stringHoldersPool = new char[stringHoldersPoolSize]; + + // DB2 strings expected to have at least empty string + for (size_t i = 0; i < stringHoldersPoolSize / sizeof(char*); ++i) + ((char const**)stringHoldersPool)[i] = nullStr; + + uint32 offset=0; + + // assign string holders to string field slots + for (uint32 y = 0; y < recordCount; y++) + { + uint32 stringFieldNum = 0; + + for(uint32 x = 0; x < fieldCount; x++) + switch(format[x]) + { + case FT_FLOAT: + case FT_IND: + case FT_INT: + offset += 4; + break; + case FT_BYTE: + offset += 1; + break; + case FT_STRING: + { + // init db2 string field slots by pointers to string holders + char const*** slot = (char const***)(&dataTable[offset]); + *slot = (char const**)(&stringHoldersPool[stringHoldersRecordPoolSize * y + stringHolderSize*stringFieldNum]); + ++stringFieldNum; + offset += sizeof(char*); + break; + } + case FT_NA: + case FT_NA_BYTE: + case FT_SORT: + break; + default: + assert(false && "unknown format character"); + } + } + + //send as char* for store in char* pool list for free at unload + return stringHoldersPool; +} + +char* DB2FileLoader::AutoProduceStrings(const char* format, char* dataTable) +{ + if (strlen(format) != fieldCount) + return NULL; + + char* stringPool= new char[stringSize]; + memcpy(stringPool, stringTable, stringSize); + + uint32 offset = 0; + + for (uint32 y =0; y < recordCount; y++) + { + for (uint32 x = 0; x < fieldCount; x++) + switch(format[x]) + { + case FT_FLOAT: + case FT_IND: + case FT_INT: + offset += 4; + break; + case FT_BYTE: + offset += 1; + break; + case FT_STRING: + { + // fill only not filled entries + char** slot = (char**)(&dataTable[offset]); + if (**((char***)slot) == nullStr) + { + const char * st = getRecord(y).getString(x); + *slot=stringPool + (st-(const char*)stringTable); + } + + offset+=sizeof(char*); + break; + } + } + } + + return stringPool; +} diff --git a/src/server/shared/DataStores/DB2FileLoader.h b/src/server/shared/DataStores/DB2FileLoader.h new file mode 100644 index 00000000000..c30e33c29f6 --- /dev/null +++ b/src/server/shared/DataStores/DB2FileLoader.h @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2011 TrintiyCore <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 "Utilities/ByteConverter.h" +#include <cassert> + +class DB2FileLoader +{ + public: + DB2FileLoader(); + ~DB2FileLoader(); + + bool Load(const char *filename, const char *fmt); + + class Record + { + public: + float getFloat(size_t field) const + { + assert(field < file.fieldCount); + float val = *reinterpret_cast<float*>(offset+file.GetOffset(field)); + EndianConvert(val); + return val; + } + uint32 getUInt(size_t field) const + { + assert(field < file.fieldCount); + uint32 val = *reinterpret_cast<uint32*>(offset+file.GetOffset(field)); + EndianConvert(val); + return val; + } + uint8 getUInt8(size_t field) const + { + assert(field < file.fieldCount); + return *reinterpret_cast<uint8*>(offset+file.GetOffset(field)); + } + + const char *getString(size_t field) const + { + assert(field < file.fieldCount); + size_t stringOffset = getUInt(field); + assert(stringOffset < file.stringSize); + return reinterpret_cast<char*>(file.stringTable + stringOffset); + } + + private: + Record(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); + /// Get begin iterator over records + + uint32 GetNumRows() const { return recordCount;} + uint32 GetCols() const { return fieldCount; } + uint32 GetOffset(size_t id) const { return (fieldsOffset != NULL && id < fieldCount) ? fieldsOffset[id] : 0; } + bool IsLoaded() const { return (data != NULL); } + char* AutoProduceData(const char* fmt, uint32& count, char**& indexTable); + char* AutoProduceStringsArrayHolders(const char* fmt, char* dataTable); + char* AutoProduceStrings(const char* fmt, char* dataTable); + static uint32 GetFormatRecordSize(const char * format, int32 * index_pos = NULL); + static uint32 GetFormatStringsFields(const char * format); +private: + + uint32 recordSize; + uint32 recordCount; + uint32 fieldCount; + uint32 stringSize; + uint32 *fieldsOffset; + unsigned char *data; + unsigned char *stringTable; + + // WDB2 / WCH2 fields + uint32 tableHash; // WDB2 + uint32 build; // WDB2 + + int unk1; // WDB2 (Unix time in WCH2) + int unk2; // WDB2 + int maxIndex; // WDB2 (index table) + int locale; // WDB2 + int unk5; // WDB2 +}; + +#endif
\ No newline at end of file diff --git a/src/server/shared/DataStores/DB2Store.h b/src/server/shared/DataStores/DB2Store.h new file mode 100644 index 00000000000..d1fbc5f36a3 --- /dev/null +++ b/src/server/shared/DataStores/DB2Store.h @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2011 TrintiyCore <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 DB2STORE_H +#define DB2STORE_H + +#include "DB2FileLoader.h" +#include "DB2fmt.h" +#include "Logging/Log.h" +#include "Field.h" +#include "DatabaseWorkerPool.h" +#include "Implementation/WorldDatabase.h" +#include "DatabaseEnv.h" + +#include <vector> + +template<class T> +class DB2Storage +{ + typedef std::list<char*> StringPoolList; + typedef std::vector<T*> DataTableEx; +public: + explicit DB2Storage(const char *f) : nCount(0), fieldCount(0), fmt(f), indexTable(NULL), m_dataTable(NULL) { } + ~DB2Storage() { Clear(); } + + T const* LookupEntry(uint32 id) const { return (id>=nCount)?NULL:indexTable[id]; } + uint32 GetNumRows() const { return nCount; } + char const* GetFormat() const { return fmt; } + uint32 GetFieldCount() const { return fieldCount; } + + /// Copies the provided entry and stores it. + void AddEntry(uint32 id, const T* entry) + { + if (LookupEntry(id)) + return; + + if (id >= nCount) + { + // reallocate index table + char** tmpIdxTable = new char*[id+1]; + memset(tmpIdxTable, 0, (id+1) * sizeof(char*)); + memcpy(tmpIdxTable, (char*)indexTable, nCount * sizeof(char*)); + delete[] ((char*)indexTable); + nCount = id + 1; + indexTable = (T**)tmpIdxTable; + } + + T* entryDst = new T; + memcpy((char*)entryDst, (char*)entry, sizeof(T)); + m_dataTableEx.push_back(entryDst); + indexTable[id] = entryDst; + } + + bool Load(char const* fn) + { + DB2FileLoader db2; + // Check if load was sucessful, only then continue + if (!db2.Load(fn, fmt)) + return false; + + fieldCount = db2.GetCols(); + + // load raw non-string data + m_dataTable = (T*)db2.AutoProduceData(fmt, nCount, (char**&)indexTable); + + // create string holders for loaded string fields + m_stringPoolList.push_back(db2.AutoProduceStringsArrayHolders(fmt, (char*)m_dataTable)); + + // load strings from dbc data + m_stringPoolList.push_back(db2.AutoProduceStrings(fmt, (char*)m_dataTable)); + + // error in dbc file at loading if NULL + return indexTable!=NULL; + } + + bool LoadStringsFrom(char const* fn) + { + // DBC must be already loaded using Load + if (!indexTable) + return false; + + DB2FileLoader db2; + // Check if load was successful, only then continue + if (!db2.Load(fn, fmt)) + return false; + + // load strings from another locale dbc data + m_stringPoolList.push_back(db2.AutoProduceStrings(fmt, (char*)m_dataTable)); + + return true; + } + + void Clear() + { + if (!indexTable) + return; + + delete[] ((char*)indexTable); + indexTable = NULL; + delete[] ((char*)m_dataTable); + m_dataTable = NULL; + for (typename DataTableEx::const_iterator itr = m_dataTableEx.begin(); itr != m_dataTableEx.end(); ++itr) + delete *itr; + m_dataTableEx.clear(); + + while (!m_stringPoolList.empty()) + { + delete[] m_stringPoolList.front(); + m_stringPoolList.pop_front(); + } + nCount = 0; + } + + void EraseEntry(uint32 id) { indexTable[id] = NULL; } + +private: + uint32 nCount; + uint32 fieldCount; + uint32 recordSize; + char const* fmt; + T** indexTable; + T* m_dataTable; + DataTableEx m_dataTableEx; + StringPoolList m_stringPoolList; +}; + +#endif
\ No newline at end of file diff --git a/src/server/shared/DataStores/DBCFileLoader.h b/src/server/shared/DataStores/DBCFileLoader.h index a43807a3b59..184186d28ee 100755 --- a/src/server/shared/DataStores/DBCFileLoader.h +++ b/src/server/shared/DataStores/DBCFileLoader.h @@ -22,7 +22,7 @@ #include "Utilities/ByteConverter.h" #include <cassert> -enum +/*enum { FT_NA='x', //not used or unknown, 4 byte size FT_NA_BYTE='X', //not used or unknown, byte @@ -35,7 +35,7 @@ enum FT_LOGIC='l', //Logical (boolean) FT_SQL_PRESENT='p', //Used in sql format to mark column present in sql dbc FT_SQL_ABSENT='a' //Used in sql format to mark column absent in sql dbc -}; +};*/ class DBCFileLoader { diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index a24f17a8b76..6b331740aa6 100644..100755 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -57,8 +57,8 @@ void CharacterDatabaseConnection::DoPrepareStatements() PREPARE_STATEMENT(CHAR_SEL_CHARACTER, "SELECT guid, account, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags, " "position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, " "resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, instance_mode_mask, " - "arenaPoints, totalHonorPoints, todayHonorPoints, yesterdayHonorPoints, totalKills, todayKills, yesterdayKills, chosenTitle, knownCurrencies, watchedFaction, drunk, " - "health, power1, power2, power3, power4, power5, power6, power7, instance_id, speccount, activespec, exploredZones, equipmentCache, ammoId, knownTitles, actionBars, grantableLevels FROM characters WHERE guid = ?", CONNECTION_ASYNC) + "conquestPoints, totalHonorPoints, totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, " + "health, power1, power2, power3, power4, power5, instance_id, speccount, activespec, exploredZones, equipmentCache, knownTitles, actionBars, grantableLevels, guildId FROM characters WHERE guid = ?", CONNECTION_ASYNC) PREPARE_STATEMENT(CHAR_SEL_GROUP_MEMBER, "SELECT guid FROM group_member WHERE memberGuid = ?", CONNECTION_ASYNC) PREPARE_STATEMENT(CHAR_SEL_CHARACTER_INSTANCE, "SELECT id, permanent, map, difficulty, resettime FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = ?", CONNECTION_ASYNC) PREPARE_STATEMENT(CHAR_SEL_CHARACTER_AURAS, "SELECT caster_guid, spell, effect_mask, recalculate_mask, stackcount, amount0, amount1, amount2, " @@ -140,6 +140,9 @@ void CharacterDatabaseConnection::DoPrepareStatements() // 0: uint32, 1: string, 2: uint32, 3: string, 4: string, 5: uint64, 6-10: uint32, 11: uint64 PREPARE_STATEMENT(CHAR_INS_GUILD, "INSERT INTO guild (guildid, name, leaderguid, info, motd, createdate, EmblemStyle, EmblemColor, BorderStyle, BorderColor, BackgroundColor, BankMoney) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC) PREPARE_STATEMENT(CHAR_DEL_GUILD, "DELETE FROM guild WHERE guildid = ?", CONNECTION_ASYNC) // 0: uint32 + // 0: uint32 + PREPARE_STATEMENT(CHAR_SET_GUILD_ID, "UPDATE characters SET guildId = ? WHERE guid = ?", CONNECTION_ASYNC) + PREPARE_STATEMENT(CHAR_GET_GUILD_ID, "SELECT guildId FROM characters WHERE guid = ?", CONNECTION_SYNCH) // 0: uint32, 1: uint32, 2: uint8, 4: string, 5: string PREPARE_STATEMENT(CHAR_INS_GUILD_MEMBER, "INSERT INTO guild_member (guildid, guid, rank, pnote, offnote) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC) PREPARE_STATEMENT(CHAR_DEL_GUILD_MEMBER, "DELETE FROM guild_member WHERE guid = ?", CONNECTION_ASYNC) // 0: uint32 @@ -332,16 +335,16 @@ void CharacterDatabaseConnection::DoPrepareStatements() "taximask, cinematic, " "totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, " "extra_flags, stable_slots, at_login, zone, " - "death_expire_time, taxi_path, arenaPoints, totalHonorPoints, todayHonorPoints, yesterdayHonorPoints, totalKills, " - "todayKills, yesterdayKills, chosenTitle, knownCurrencies, watchedFaction, drunk, health, power1, power2, power3, " - "power4, power5, power6, power7, latency, speccount, activespec, exploredZones, equipmentCache, ammoId, knownTitles, actionBars, grantableLevels) VALUES " - "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", CONNECTION_ASYNC); + "death_expire_time, taxi_path, conquestPoints, totalHonorPoints, totalKills, " + "todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, health, power1, power2, power3, " + "power4, power5, latency, speccount, activespec, exploredZones, equipmentCache, knownTitles, actionBars, grantableLevels) VALUES " + "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", CONNECTION_ASYNC); PREPARE_STATEMENT(CHAR_UPD_CHARACTER, "UPDATE characters SET name=?,race=?,class=?,gender=?,level=?,xp=?,money=?,playerBytes=?,playerBytes2=?,playerFlags=?," "map=?,instance_id=?,instance_mode_mask=?,position_x=?,position_y=?,position_z=?,orientation=?,taximask=?,cinematic=?,totaltime=?,leveltime=?,rest_bonus=?," "logout_time=?,is_logout_resting=?,resettalents_cost=?,resettalents_time=?,extra_flags=?,stable_slots=?,at_login=?,zone=?,death_expire_time=?,taxi_path=?," - "arenaPoints=?,totalHonorPoints=?,todayHonorPoints=?,yesterdayHonorPoints=?,totalKills=?,todayKills=?,yesterdayKills=?,chosenTitle=?,knownCurrencies=?," - "watchedFaction=?,drunk=?,health=?,power1=?,power2=?,power3=?,power4=?,power5=?,power6=?,power7=?,latency=?,speccount=?,activespec=?,exploredZones=?," - "equipmentCache=?,ammoId=?,knownTitles=?,actionBars=?,grantableLevels=?,online=? WHERE guid=?", CONNECTION_ASYNC); + "conquestPoints=?,totalHonorPoints=?,totalKills=?,todayKills=?,yesterdayKills=?,chosenTitle=?," + "watchedFaction=?,drunk=?,health=?,power1=?,power2=?,power3=?,power4=?,power5=?,latency=?,speccount=?,activespec=?,exploredZones=?," + "equipmentCache=?,knownTitles=?,actionBars=?,grantableLevels=?,online=? WHERE guid=?", CONNECTION_ASYNC); PREPARE_STATEMENT(CHAR_UPD_ADD_AT_LOGIN_FLAG, "UPDATE characters SET at_login = at_login | ? WHERE guid = ?", CONNECTION_ASYNC); PREPARE_STATEMENT(CHAR_UPD_REM_AT_LOGIN_FLAG, "UPDATE characters set at_login = at_login & ~ ? WHERE guid = ?", CONNECTION_ASYNC); diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h index a239e274a54..0ea1549eff2 100644..100755 --- a/src/server/shared/Database/Implementation/CharacterDatabase.h +++ b/src/server/shared/Database/Implementation/CharacterDatabase.h @@ -147,6 +147,8 @@ enum CharacterDatabaseStatements CHAR_INS_GUILD, CHAR_DEL_GUILD, + CHAR_SET_GUILD_ID, + CHAR_GET_GUILD_ID, CHAR_INS_GUILD_MEMBER, CHAR_DEL_GUILD_MEMBER, CHAR_DEL_GUILD_MEMBERS, diff --git a/src/server/shared/Define.h b/src/server/shared/Define.h index bb3bab75e87..8c1b42af36f 100755 --- a/src/server/shared/Define.h +++ b/src/server/shared/Define.h @@ -79,4 +79,18 @@ typedef ACE_UINT32 uint32; typedef ACE_UINT16 uint16; typedef ACE_UINT8 uint8; +enum DBCFormer +{ + FT_NA='x', //not used or unknown, 4 byte size + FT_NA_BYTE='X', //not used or unknown, byte + FT_STRING='s', //char* + FT_FLOAT='f', //float + FT_INT='i', //uint32 + FT_BYTE='b', //uint8 + FT_SORT='d', //sorted by this field, field is not included + FT_IND='n', //the same, but parsed to data + FT_LOGIC='l', //Logical (boolean) + FT_SQL_PRESENT='p', //Used in sql format to mark column present in sql dbc + FT_SQL_ABSENT='a' //Used in sql format to mark column absent in sql dbc +}; #endif //TRINITY_DEFINE_H diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp index abdeace4d97..e04225a94e1 100755 --- a/src/server/shared/Logging/Log.cpp +++ b/src/server/shared/Logging/Log.cpp @@ -990,6 +990,13 @@ void Log::outCharDump(const char * str, uint32 account_id, uint32 guid, const ch } } +void Log::outOpCode(uint32 op, const char * name, bool smsg) +{ + if (!(m_DebugLogMask & LOG_FILTER_OPCODES)) + return; + outString("%s: %s 0x%.4X (%u)", smsg ? "S->C" : "C->S", name, op, op); +} + void Log::outRemote(const char * str, ...) { if (!str) diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h index 2381d91d98d..0489b84f7fe 100755 --- a/src/server/shared/Logging/Log.h +++ b/src/server/shared/Logging/Log.h @@ -50,6 +50,7 @@ enum DebugLogFilters LOG_FILTER_LOOT = 0x00100000, // Loot related LOG_FILTER_GUILD = 0x00200000, // Guild related LOG_FILTER_TRANSPORTS = 0x00400000, // Transport related + LOG_FILTER_OPCODES = 0x00800000, // OpCodes }; enum LogTypes @@ -137,6 +138,7 @@ class Log void outArena( const char * str, ... ) ATTR_PRINTF(2, 3); void outSQLDriver( const char* str, ... ) ATTR_PRINTF(2, 3); void outCharDump( const char * str, uint32 account_id, uint32 guid, const char * name ); + void outOpCode(uint32 op, const char * name, bool smsg = true); static void outTimestamp(FILE* file); static std::string GetTimestampStr(); diff --git a/src/server/shared/Packets/ByteBuffer.cpp b/src/server/shared/Packets/ByteBuffer.cpp new file mode 100644 index 00000000000..adb58936c75 --- /dev/null +++ b/src/server/shared/Packets/ByteBuffer.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2008-2011 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 "ByteBuffer.h" + +void BitStream::Clear() +{ + _data.clear(); + _rpos = _wpos = 0; +} + +uint8 BitStream::GetBit(uint32 bit) +{ + ASSERT(_data.size() > bit); + return _data[bit]; +} + +uint8 BitStream::ReadBit() +{ + ASSERT(_data.size() < _rpos); + uint8 b = _data[_rpos]; + ++_rpos; + return b; +} + +void BitStream::WriteBit(uint32 bit) +{ + _data.push_back(bit ? uint8(1) : uint8(0)); + ++_wpos; +} + +template <typename T> void BitStream::WriteBits(T value, size_t bits) +{ + for (int32 i = bits-1; i >= 0; --i) + WriteBit((value >> i) & 1); +} + +bool BitStream::Empty() +{ + return _data.empty(); +} + +void BitStream::Reverse() +{ + uint32 len = GetLength(); + std::vector<uint8> b = _data; + Clear(); + + for(uint32 i = len; i > 0; --i) + WriteBit(b[i-1]); +} + +void BitStream::Print() +{ + if (!sLog->IsOutDebug()) + return; + std::stringstream ss; + ss << "BitStream: "; + for (uint32 i = 0; i < GetLength(); ++i) + ss << uint32(GetBit(i)) << " "; + + sLog->outDebug(LOG_FILTER_NETWORKIO, "%s", ss.str().c_str()); +} + +ByteBuffer::ByteBuffer(size_t res, bool init): _rpos(0), _wpos(0), _bitpos(8), _curbitval(0) +{ + if (init) + _storage.resize(res, 0); + else + _storage.reserve(res); +} diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h index 6b99b79625d..16f06563630 100755 --- a/src/server/shared/Packets/ByteBuffer.h +++ b/src/server/shared/Packets/ByteBuffer.h @@ -24,6 +24,8 @@ #include "Logging/Log.h" #include "Utilities/ByteConverter.h" + + class ByteBufferException { public: @@ -45,25 +47,66 @@ class ByteBufferException size_t size; }; +class BitStream +{ + public: + BitStream(): _rpos(0), _wpos(0) {} + + BitStream(uint32 val, size_t len): _rpos(0), _wpos(0) + { + WriteBits(val, len); + } + + BitStream(BitStream const& bs) : _data(bs._data), _rpos(bs._rpos), _wpos(bs._wpos) {} + + void Clear(); + uint8 GetBit(uint32 bit); + uint8 ReadBit(); + void WriteBit(uint32 bit); + template <typename T> void WriteBits(T value, size_t bits); + bool Empty(); + void Reverse(); + void Print(); + + size_t GetLength() { return _data.size(); } + uint32 GetReadPosition() { return _rpos; } + uint32 GetWritePosition() { return _wpos; } + void SetReadPos(uint32 pos) { _rpos = pos; } + + uint8 const& operator[](uint32 const pos) const + { + return _data[pos]; + } + + uint8& operator[] (uint32 const pos) + { + return _data[pos]; + } + + private: + std::vector<uint8> _data; + uint32 _rpos, _wpos; +}; + class ByteBuffer { public: const static size_t DEFAULT_SIZE = 0x1000; // constructor - ByteBuffer(): _rpos(0), _wpos(0) + ByteBuffer(): _rpos(0), _wpos(0), _bitpos(8), _curbitval(0) { _storage.reserve(DEFAULT_SIZE); } // constructor - ByteBuffer(size_t res): _rpos(0), _wpos(0) - { - _storage.reserve(res); - } + ByteBuffer(size_t res, bool init = false); // copy constructor - ByteBuffer(const ByteBuffer &buf): _rpos(buf._rpos), _wpos(buf._wpos), _storage(buf._storage) { } + ByteBuffer(const ByteBuffer &buf) : _rpos(buf._rpos), _wpos(buf._wpos), + _bitpos(buf._bitpos), _curbitval(buf._curbitval), _storage(buf._storage) + { + } void clear() { @@ -73,10 +116,73 @@ class ByteBuffer template <typename T> void append(T value) { + FlushBits(); EndianConvert(value); append((uint8 *)&value, sizeof(value)); } + void FlushBits() + { + if (_bitpos == 8) + return; + + append((uint8 *)&_curbitval, sizeof(uint8)); + _curbitval = 0; + _bitpos = 8; + } + + bool WriteBit(uint32 bit) + { + --_bitpos; + if (bit) + _curbitval |= (1 << (_bitpos)); + + if (_bitpos == 0) + { + _bitpos = 8; + append((uint8 *)&_curbitval, sizeof(_curbitval)); + _curbitval = 0; + } + + return (bit != 0); + } + + bool ReadBit() + { + ++_bitpos; + if (_bitpos > 7) + { + _bitpos = 0; + _curbitval = read<uint8>(); + } + + return ((_curbitval >> (7-_bitpos)) & 1) != 0; + } + + template <typename T> void WriteBits(T value, size_t bits) + { + for (int32 i = bits-1; i >= 0; --i) + WriteBit((value >> i) & 1); + } + + uint32 ReadBits(size_t bits) + { + uint32 value = 0; + for (int32 i = bits-1; i >= 0; --i) + if (ReadBit()) + value |= (1 << (_bitpos)); + + return value; + } + + BitStream ReadBitStream(uint32 len) + { + BitStream b; + for (uint32 i = 0; i < len; ++i) + b.WriteBit(ReadBit()); + return b; + } + template <typename T> void put(size_t pos, T value) { EndianConvert(value); @@ -239,9 +345,18 @@ class ByteBuffer return *this; } - uint8 operator[](size_t pos) const + uint8& operator[](size_t const pos) { - return read<uint8>(pos); + if (pos >= size()) + throw ByteBufferException(false, pos, 1, size()); + return _storage[pos]; + } + + uint8 const& operator[](size_t const pos) const + { + if (pos >= size()) + throw ByteBufferException(false, pos, 1, size()); + return _storage[pos]; } size_t rpos() const { return _rpos; } @@ -323,6 +438,83 @@ class ByteBuffer } } + uint8 ReadUInt8() + { + uint8 u = 0; + (*this) >> u; + return u; + } + + uint16 ReadUInt16() + { + uint16 u = 0; + (*this) >> u; + return u; + } + + uint32 ReadUInt32() + { + uint32 u = 0; + (*this) >> u; + return u; + } + + uint64 ReadUInt64() + { + uint64 u = 0; + (*this) >> u; + return u; + } + + int8 ReadInt8() + { + int8 u = 0; + (*this) >> u; + return u; + } + + int16 ReadInt16() + { + int16 u = 0; + (*this) >> u; + return u; + } + + int32 ReadInt32() + { + uint32 u = 0; + (*this) >> u; + return u; + } + + int64 ReadInt64() + { + int64 u = 0; + (*this) >> u; + return u; + } + + std::string ReadString() + { + std::string s = 0; + (*this) >> s; + return s; + } + + bool ReadBoolean() + { + uint8 b = 0; + (*this) >> b; + return b > 0 ? true : false; + } + + float ReadSingle() + { + float f = 0; + (*this) >> f; + return f; + } + const uint8 *contents() const { return &_storage[0]; } size_t size() const { return _storage.size(); } @@ -489,7 +681,8 @@ class ByteBuffer } protected: - size_t _rpos, _wpos; + size_t _rpos, _wpos, _bitpos; + uint8 _curbitval; std::vector<uint8> _storage; }; @@ -598,5 +791,45 @@ inline void ByteBuffer::read_skip<std::string>() { read_skip<char*>(); } + +class BitConverter +{ + public: + static uint8 ToUInt8(ByteBuffer const& buff, size_t start = 0) + { + return buff.read<uint8>(start); + } + + static uint16 ToUInt16(ByteBuffer const& buff, size_t start = 0) + { + return buff.read<uint16>(start); + } + + static uint32 ToUInt32(ByteBuffer const& buff, size_t start = 0) + { + return buff.read<uint32>(start); + } + + static uint64 ToUInt64(ByteBuffer const& buff, size_t start = 0) + { + return buff.read<uint64>(start); + } + + static int16 ToInt16(ByteBuffer const& buff, size_t start = 0) + { + return buff.read<int16>(start); + } + + static int32 ToInt32(ByteBuffer const& buff, size_t start = 0) + { + return buff.read<int32>(start); + } + + static int64 ToInt64(ByteBuffer const& buff, size_t start = 0) + { + return buff.read<int64>(start); + } +}; + #endif diff --git a/src/server/shared/Packets/WorldPacket.h b/src/server/shared/Packets/WorldPacket.h deleted file mode 100755 index 7ab95bc496d..00000000000 --- a/src/server/shared/Packets/WorldPacket.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef TRINITYCORE_WORLDPACKET_H -#define TRINITYCORE_WORLDPACKET_H - -#include "Common.h" -#include "ByteBuffer.h" - -class WorldPacket : public ByteBuffer -{ - public: - // just container for later use - WorldPacket() : ByteBuffer(0), m_opcode(0) - { - } - explicit WorldPacket(uint16 opcode, size_t res=200) : ByteBuffer(res), m_opcode(opcode) { } - // copy constructor - WorldPacket(const WorldPacket &packet) : ByteBuffer(packet), m_opcode(packet.m_opcode) - { - } - - void Initialize(uint16 opcode, size_t newres=200) - { - clear(); - _storage.reserve(newres); - m_opcode = opcode; - } - - uint16 GetOpcode() const { return m_opcode; } - void SetOpcode(uint16 opcode) { m_opcode = opcode; } - - protected: - uint16 m_opcode; -}; -#endif - |
