aboutsummaryrefslogtreecommitdiff
path: root/src/server/shared
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/shared')
-rw-r--r--src/server/shared/Common.h17
-rw-r--r--src/server/shared/DataStores/DB2FileLoader.cpp408
-rw-r--r--src/server/shared/DataStores/DB2FileLoader.h107
-rw-r--r--src/server/shared/DataStores/DB2Store.h233
-rw-r--r--src/server/shared/DataStores/DBCFileLoader.cpp9
-rw-r--r--src/server/shared/DataStores/DBCFileLoader.h15
-rw-r--r--src/server/shared/DataStores/DBCStore.h2
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.cpp96
-rwxr-xr-x[-rw-r--r--]src/server/shared/Database/Implementation/CharacterDatabase.h35
-rw-r--r--src/server/shared/Database/Implementation/WorldDatabase.cpp8
-rw-r--r--src/server/shared/Define.h14
-rw-r--r--src/server/shared/Packets/ByteBuffer.h137
-rw-r--r--src/server/shared/Packets/WorldPacket.h52
-rw-r--r--src/server/shared/Utilities/Util.cpp6
-rw-r--r--src/server/shared/Utilities/Util.h2
15 files changed, 1016 insertions, 125 deletions
diff --git a/src/server/shared/Common.h b/src/server/shared/Common.h
index e3074ef45b9..6a15d12e02a 100644
--- a/src/server/shared/Common.h
+++ b/src/server/shared/Common.h
@@ -182,6 +182,23 @@ LocaleConstant GetLocaleByName(const std::string& name);
typedef std::vector<std::string> StringVector;
+#if defined(__GNUC__)
+#pragma pack(1)
+#else
+#pragma pack(push, 1)
+#endif
+
+struct LocalizedString
+{
+ char const* Str[TOTAL_LOCALES];
+};
+
+#if defined(__GNUC__)
+#pragma pack()
+#else
+#pragma pack(pop)
+#endif
+
// we always use stdlibc++ std::max/std::min, undefine some not C++ standard defines (Win API and some other platforms)
#ifdef max
#undef max
diff --git a/src/server/shared/DataStores/DB2FileLoader.cpp b/src/server/shared/DataStores/DB2FileLoader.cpp
new file mode 100644
index 00000000000..7a27072dd20
--- /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)
+{
+ if (data)
+ {
+ delete [] data;
+ data = NULL;
+ }
+
+ FILE* f = fopen(filename, "rb");
+ if (!f)
+ return false;
+
+ uint32 header;
+ 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(&minIndex, 4, 1, f) != 1) // MinIndex WDB2
+ {
+ fclose(f);
+ return false;
+ }
+ EndianConvert(minIndex);
+
+ 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 - minIndex + 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, uint32 locale)
+{
+ 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
+ LocalizedString* db2str = *(LocalizedString**)(&dataTable[offset]);
+ if (db2str->Str[locale] == nullStr)
+ {
+ const char * st = getRecord(y).getString(x);
+ db2str->Str[locale] = 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..86350ebf1d6
--- /dev/null
+++ b/src/server/shared/DataStores/DB2FileLoader.h
@@ -0,0 +1,107 @@
+/*
+ * 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; }
+ uint32 GetHash() const { return tableHash; }
+ 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, uint32 locale);
+ 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 minIndex; // 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..77d6c4144e5
--- /dev/null
+++ b/src/server/shared/DataStores/DB2Store.h
@@ -0,0 +1,233 @@
+/*
+ * 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 "Common.h"
+#include "ByteBuffer.h"
+#include <vector>
+
+/// Interface class for common access
+class DB2StorageBase
+{
+public:
+ virtual ~DB2StorageBase() { }
+
+ uint32 GetHash() const { return tableHash; }
+
+ virtual bool HasRecord(uint32 id) const = 0;
+
+ virtual void WriteRecord(uint32 id, uint32 locale, ByteBuffer& buffer) const = 0;
+
+protected:
+ uint32 tableHash;
+};
+
+template<class T>
+class DB2Storage;
+
+template<class T>
+bool DB2StorageHasEntry(DB2Storage<T> const& store, uint32 id)
+{
+ return store.LookupEntry(id) != NULL;
+}
+
+template<class T>
+void WriteDB2RecordToPacket(DB2Storage<T> const& store, uint32 id, uint32 locale, ByteBuffer& buffer)
+{
+ uint8 const* entry = (uint8 const*)store.LookupEntry(id);
+ ASSERT(entry);
+
+ std::string format = store.GetFormat();
+ for (uint32 i = 0; i < format.length(); ++i)
+ {
+ switch (format[i])
+ {
+ case FT_IND:
+ 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_STRING:
+ {
+ LocalizedString* locStr = *(LocalizedString**)entry;
+ if (locStr->Str[locale][0] == '\0')
+ locale = 0;
+
+ char const* str = locStr->Str[locale];
+ size_t len = strlen(str);
+ buffer << uint16(len);
+ if (len)
+ buffer << str;
+ entry += sizeof(char*);
+ break;
+ }
+ case FT_NA:
+ case FT_SORT:
+ buffer << uint32(0);
+ break;
+ case FT_NA_BYTE:
+ buffer << uint8(0);
+ break;
+ }
+ }
+}
+
+template<class T>
+class DB2Storage : public DB2StorageBase
+{
+ typedef std::list<char*> StringPoolList;
+ typedef std::vector<T*> DataTableEx;
+ typedef bool(*EntryChecker)(DB2Storage<T> const&, uint32);
+ typedef void(*PacketWriter)(DB2Storage<T> const&, uint32, uint32, ByteBuffer&);
+public:
+ DB2Storage(char const* f, EntryChecker checkEntry = NULL, PacketWriter writePacket = NULL) :
+ nCount(0), fieldCount(0), fmt(f), m_dataTable(NULL)
+ {
+ indexTable.asT = NULL;
+ CheckEntry = checkEntry ? checkEntry : (EntryChecker)&DB2StorageHasEntry<T>;
+ WritePacket = writePacket ? writePacket : (PacketWriter)&WriteDB2RecordToPacket<T>;
+ }
+
+ ~DB2Storage() { Clear(); }
+
+ bool HasRecord(uint32 id) const { return CheckEntry(*this, id); }
+ T const* LookupEntry(uint32 id) const { return (id >= nCount) ? NULL : indexTable.asT[id]; }
+ uint32 GetNumRows() const { return nCount; }
+ char const* GetFormat() const { return fmt; }
+ uint32 GetFieldCount() const { return fieldCount; }
+ void WriteRecord(uint32 id, uint32 locale, ByteBuffer& buffer) const
+ {
+ WritePacket(*this, id, locale, buffer);
+ }
+
+ T* CreateEntry(uint32 id, bool evenIfExists = false)
+ {
+ if (evenIfExists && LookupEntry(id))
+ return NULL;
+
+ if (id >= nCount)
+ {
+ // reallocate index table
+ char** tmpIdxTable = new char*[id + 1];
+ memset(tmpIdxTable, 0, (id + 1) * sizeof(char*));
+ memcpy(tmpIdxTable, indexTable.asChar, nCount * sizeof(char*));
+ delete[] reinterpret_cast<char*>(indexTable.asT);
+ nCount = id + 1;
+ indexTable.asChar = tmpIdxTable;
+ }
+
+ T* entryDst = new T;
+ m_dataTableEx.push_back(entryDst);
+ indexTable.asT[id] = entryDst;
+ return entryDst;
+ }
+
+ void EraseEntry(uint32 id) { indexTable.asT[id] = NULL; }
+
+ bool Load(char const* fn, uint32 locale)
+ {
+ DB2FileLoader db2;
+ // Check if load was sucessful, only then continue
+ if (!db2.Load(fn, fmt))
+ return false;
+
+ fieldCount = db2.GetCols();
+ tableHash = db2.GetHash();
+
+ // load raw non-string data
+ m_dataTable = reinterpret_cast<T*>(db2.AutoProduceData(fmt, nCount, indexTable.asChar));
+
+ // 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, locale));
+
+ // error in dbc file at loading if NULL
+ return indexTable.asT != NULL;
+ }
+
+ bool LoadStringsFrom(char const* fn, uint32 locale)
+ {
+ // DBC must be already loaded using Load
+ if (!indexTable.asT)
+ 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, locale));
+
+ return true;
+ }
+
+ void Clear()
+ {
+ if (!indexTable.asT)
+ return;
+
+ delete[] reinterpret_cast<char*>(indexTable.asT);
+ indexTable.asT = NULL;
+
+ delete[] reinterpret_cast<char*>(m_dataTable);
+ m_dataTable = NULL;
+
+ for (typename DataTableEx::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;
+ }
+
+ EntryChecker CheckEntry;
+ PacketWriter WritePacket;
+
+private:
+ uint32 nCount;
+ uint32 fieldCount;
+ char const* fmt;
+ union
+ {
+ T** asT;
+ char** asChar;
+ } indexTable;
+ T* m_dataTable;
+ DataTableEx m_dataTableEx;
+ StringPoolList m_stringPoolList;
+};
+
+#endif
diff --git a/src/server/shared/DataStores/DBCFileLoader.cpp b/src/server/shared/DataStores/DBCFileLoader.cpp
index 3c02d5f533d..f9c6574ba43 100644
--- a/src/server/shared/DataStores/DBCFileLoader.cpp
+++ b/src/server/shared/DataStores/DBCFileLoader.cpp
@@ -155,9 +155,6 @@ uint32 DBCFileLoader::GetFormatRecordSize(const char* format, int32* index_pos)
case FT_NA:
case FT_NA_BYTE:
break;
- case FT_LOGIC:
- ASSERT(false && "Attempted to load DBC files that do not have field types that match what is in the core. Check DBCfmt.h or your DBC files.");
- break;
default:
ASSERT(false && "Unknown field format character in DBCfmt.h");
break;
@@ -249,9 +246,6 @@ char* DBCFileLoader::AutoProduceData(const char* format, uint32& records, char**
*((char**)(&dataTable[offset])) = NULL; // will replace non-empty or "" strings in AutoProduceStrings
offset += sizeof(char*);
break;
- case FT_LOGIC:
- ASSERT(false && "Attempted to load DBC files that do not have field types that match what is in the core. Check DBCfmt.h or your DBC files.");
- break;
case FT_NA:
case FT_NA_BYTE:
case FT_SORT:
@@ -306,9 +300,6 @@ char* DBCFileLoader::AutoProduceStrings(const char* format, char* dataTable)
offset += sizeof(char*);
break;
}
- case FT_LOGIC:
- ASSERT(false && "Attempted to load DBC files that does not have field types that match what is in the core. Check DBCfmt.h or your DBC files.");
- break;
case FT_NA:
case FT_NA_BYTE:
case FT_SORT:
diff --git a/src/server/shared/DataStores/DBCFileLoader.h b/src/server/shared/DataStores/DBCFileLoader.h
index 1f8768e5da4..5eeaffe659e 100644
--- a/src/server/shared/DataStores/DBCFileLoader.h
+++ b/src/server/shared/DataStores/DBCFileLoader.h
@@ -22,21 +22,6 @@
#include "Utilities/ByteConverter.h"
#include <cassert>
-enum DbcFieldFormat
-{
- 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
-};
-
class DBCFileLoader
{
public:
diff --git a/src/server/shared/DataStores/DBCStore.h b/src/server/shared/DataStores/DBCStore.h
index ad13b2a02af..bf373433844 100644
--- a/src/server/shared/DataStores/DBCStore.h
+++ b/src/server/shared/DataStores/DBCStore.h
@@ -20,7 +20,7 @@
#define DBCSTORE_H
#include "DBCFileLoader.h"
-#include "Logging/Log.h"
+#include "Log.h"
#include "Field.h"
#include "DatabaseWorkerPool.h"
#include "Implementation/WorldDatabase.h"
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index da99d6c3537..e7b4c9fae97 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -43,14 +43,14 @@ void CharacterDatabaseConnection::DoPrepareStatements()
"subject, deliver_time, expire_time, money, has_items FROM mail WHERE receiver = ? ", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_MAIL_LIST_ITEMS, "SELECT itemEntry,count FROM item_instance WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_ENUM, "SELECT c.guid, c.name, c.race, c.class, c.gender, c.playerBytes, c.playerBytes2, c.level, c.zone, c.map, c.position_x, c.position_y, c.position_z, "
- "gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, cb.guid "
+ "gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, cb.guid, c.slot "
"FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? LEFT JOIN guild_member AS gm ON c.guid = gm.guid "
- "LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.account = ? AND c.deleteInfos_Name IS NULL ORDER BY c.guid", CONNECTION_ASYNC);
+ "LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.account = ? AND c.deleteInfos_Name IS NULL", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_ENUM_DECLINED_NAME, "SELECT c.guid, c.name, c.race, c.class, c.gender, c.playerBytes, c.playerBytes2, c.level, c.zone, c.map, "
"c.position_x, c.position_y, c.position_z, gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, "
- "cb.guid, cd.genitive FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? "
+ "cb.guid, c.slot, cd.genitive FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? "
"LEFT JOIN character_declinedname AS cd ON c.guid = cd.guid LEFT JOIN guild_member AS gm ON c.guid = gm.guid "
- "LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.account = ? AND c.deleteInfos_Name IS NULL ORDER BY c.guid", CONNECTION_ASYNC);
+ "LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.account = ? AND c.deleteInfos_Name IS NULL", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_FREE_NAME, "SELECT guid, name FROM characters WHERE guid = ? AND account = ? AND (at_login & ?) = ? AND NOT EXISTS (SELECT NULL FROM characters WHERE name = ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_GUID_RACE_ACC_BY_NAME, "SELECT guid, race, account FROM characters WHERE name = ?", CONNECTION_BOTH);
PrepareStatement(CHAR_SEL_CHAR_RACE, "SELECT race FROM characters WHERE guid = ?", CONNECTION_SYNCH);
@@ -73,9 +73,9 @@ void CharacterDatabaseConnection::DoPrepareStatements()
// Start LoginQueryHolder content
PrepareStatement(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 "
+ "resettalents_time, talentTree, 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, "
+ "totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, "
+ "health, power1, power2, power3, power4, power5, instance_id, speccount, activespec, exploredZones, equipmentCache, knownTitles, actionBars, grantableLevels "
"FROM characters WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_GROUP_MEMBER, "SELECT guid FROM group_member WHERE memberGuid = ?", CONNECTION_BOTH);
@@ -113,7 +113,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_CHARACTER_EQUIPMENTSETS, "SELECT setguid, setindex, name, iconname, ignore_mask, item0, item1, item2, item3, item4, item5, item6, item7, item8, "
"item9, item10, item11, item12, item13, item14, item15, item16, item17, item18 FROM character_equipmentsets WHERE guid = ? ORDER BY setindex", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_BGDATA, "SELECT instanceId, team, joinX, joinY, joinZ, joinO, joinMapId, taxiStart, taxiEnd, mountSpell FROM character_battleground_data WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_SEL_CHARACTER_GLYPHS, "SELECT spec, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6 FROM character_glyphs WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHARACTER_GLYPHS, "SELECT spec, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6, glyph7, glyph8, glyph9 FROM character_glyphs WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_TALENTS, "SELECT spell, spec FROM character_talent WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_SKILLS, "SELECT skill, value, max FROM character_skills WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_RANDOMBG, "SELECT guid FROM character_battleground_random WHERE guid = ?", CONNECTION_ASYNC);
@@ -181,7 +181,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
// 0: uint32, 1: uint8, 3: string, 4: uint32, 5: uint32
PrepareStatement(CHAR_INS_GUILD_RANK, "INSERT INTO guild_rank (guildid, rid, rname, rights, BankMoneyPerDay) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_GUILD_RANKS, "DELETE FROM guild_rank WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32
- PrepareStatement(CHAR_DEL_GUILD_LOWEST_RANK, "DELETE FROM guild_rank WHERE guildid = ? AND rid >= ?", CONNECTION_ASYNC); // 0: uint32, 1: uint8
+ PrepareStatement(CHAR_DEL_GUILD_RANK, "DELETE FROM guild_rank WHERE guildid = ? AND rid = ?", CONNECTION_ASYNC); // 0: uint32, 1: uint8
PrepareStatement(CHAR_INS_GUILD_BANK_TAB, "INSERT INTO guild_bank_tab (guildid, TabId) VALUES (?, ?)", CONNECTION_ASYNC); // 0: uint32, 1: uint8
PrepareStatement(CHAR_DEL_GUILD_BANK_TAB, "DELETE FROM guild_bank_tab WHERE guildid = ? AND TabId = ?", CONNECTION_ASYNC); // 0: uint32, 1: uint8
PrepareStatement(CHAR_DEL_GUILD_BANK_TABS, "DELETE FROM guild_bank_tab WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32
@@ -221,12 +221,24 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_UPD_GUILD_BANK_TAB_TEXT, "UPDATE guild_bank_tab SET TabText = ? WHERE guildid = ? AND TabId = ?", CONNECTION_ASYNC); // 0: string, 1: uint32, 2: uint8
PrepareStatement(CHAR_INS_GUILD_MEMBER_WITHDRAW,
- "INSERT INTO guild_member_withdraw (guid, tab0, tab1, tab2, tab3, tab4, tab5, money) VALUES (?, ?, ?, ?, ?, ?, ?, ?) "
- "ON DUPLICATE KEY UPDATE tab0 = VALUES (tab0), tab1 = VALUES (tab1), tab2 = VALUES (tab2), tab3 = VALUES (tab3), tab4 = VALUES (tab4), tab5 = VALUES (tab5)", CONNECTION_ASYNC);
+ "INSERT INTO guild_member_withdraw (guid, tab0, tab1, tab2, tab3, tab4, tab5, tab6, tab7, money) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "
+ "ON DUPLICATE KEY UPDATE tab0 = VALUES (tab0), tab1 = VALUES (tab1), tab2 = VALUES (tab2), tab3 = VALUES (tab3), tab4 = VALUES (tab4), tab5 = VALUES (tab5), tab6 = VALUES (tab6), tab7 = VALUES (tab7), money = VALUES (money)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_GUILD_MEMBER_WITHDRAW, "TRUNCATE guild_member_withdraw", CONNECTION_ASYNC);
// 0: uint32, 1: uint32, 2: uint32
PrepareStatement(CHAR_SEL_CHAR_DATA_FOR_GUILD, "SELECT name, level, class, zone, account FROM characters WHERE guid = ?", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_DEL_GUILD_ACHIEVEMENT, "DELETE FROM guild_achievement WHERE guildId = ? AND achievement = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_GUILD_ACHIEVEMENT, "INSERT INTO guild_achievement (guildId, achievement, date, guids) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_GUILD_ACHIEVEMENT_CRITERIA, "DELETE FROM guild_achievement_progress WHERE guildId = ? AND criteria = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_GUILD_ACHIEVEMENT_CRITERIA, "INSERT INTO guild_achievement_progress (guildId, criteria, counter, date, completedGuid) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_ALL_GUILD_ACHIEVEMENTS, "DELETE FROM guild_achievement WHERE guildId = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_ALL_GUILD_ACHIEVEMENT_CRITERIA, "DELETE FROM guild_achievement_progress WHERE guildId = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_GUILD_ACHIEVEMENT, "SELECT achievement, date, guids FROM guild_achievement WHERE guildId = ?", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_SEL_GUILD_ACHIEVEMENT_CRITERIA, "SELECT criteria, counter, date, completedGuid FROM guild_achievement_progress WHERE guildId = ?", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_UPD_GUILD_EXPERIENCE, "UPDATE guild SET level = ?, experience = ?, todayExperience = ? WHERE guildId = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_UPD_GUILD_RESET_TODAY_EXPERIENCE, "UPDATE guild SET todayExperience = 0", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_GUILD_NEWS, "INSERT INTO guild_newslog (guildid, LogGuid, EventType, PlayerGuid, Flags, Value, Timestamp) VALUES (?, ?, ?, ?, ?, ?, ?)"
+ " ON DUPLICATE KEY UPDATE LogGuid = VALUES (LogGuid), EventType = VALUES (EventType), PlayerGuid = VALUES (PlayerGuid), Flags = VALUES (Flags), Value = VALUES (Value), Timestamp = VALUES (Timestamp)", CONNECTION_ASYNC);
// Chat channel handling
PrepareStatement(CHAR_SEL_CHANNEL, "SELECT announce, ownership, password, bannedList FROM channels WHERE name = ? AND team = ?", CONNECTION_SYNCH);
@@ -249,6 +261,11 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_INS_AURA, "INSERT INTO character_aura (guid, caster_guid, item_guid, spell, effect_mask, recalculate_mask, stackcount, amount0, amount1, amount2, base_amount0, base_amount1, base_amount2, maxduration, remaintime, remaincharges) "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ // Currency
+ PrepareStatement(CHAR_SEL_PLAYER_CURRENCY, "SELECT currency, week_count, total_count FROM character_currency WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_UPD_PLAYER_CURRENCY, "UPDATE character_currency SET week_count = ?, total_count = ? WHERE guid = ? AND currency = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_REP_PLAYER_CURRENCY, "REPLACE INTO character_currency (guid, currency, week_count, total_count) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
+
// Account data
PrepareStatement(CHAR_SEL_ACCOUNT_DATA, "SELECT type, time, data FROM account_data WHERE accountId = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_REP_ACCOUNT_DATA, "REPLACE INTO account_data (accountId, type, time, data) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
@@ -314,8 +331,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_PLAYER_HOMEBIND, "DELETE FROM character_homebind WHERE guid = ?", CONNECTION_ASYNC);
// Corpse
- PrepareStatement(CHAR_SEL_CORPSES, "SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, guildId, flags, dynFlags, time, corpseType, instanceId, phaseMask, corpseGuid, guid FROM corpse WHERE corpseType <> 0", CONNECTION_SYNCH);
- PrepareStatement(CHAR_INS_CORPSE, "INSERT INTO corpse (corpseGuid, guid, posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, guildId, flags, dynFlags, time, corpseType, instanceId, phaseMask) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CORPSES, "SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, phaseMask, corpseGuid, guid FROM corpse WHERE corpseType <> 0", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_INS_CORPSE, "INSERT INTO corpse (corpseGuid, guid, posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, phaseMask) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CORPSE, "DELETE FROM corpse WHERE corpseGuid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_PLAYER_CORPSES, "DELETE FROM corpse WHERE guid = ? AND corpseType <> 0", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_OLD_CORPSES, "DELETE FROM corpse WHERE corpseType = 0 OR time < (UNIX_TIMESTAMP(NOW()) - ?)", CONNECTION_ASYNC);
@@ -355,18 +372,18 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_INS_CHARACTER, "INSERT INTO characters (guid, account, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags, "
"map, instance_id, instance_mode_mask, position_x, position_y, position_z, orientation, trans_x, trans_y, trans_z, trans_o, transguid, "
"taximask, cinematic, "
- "totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, "
+ "totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, talentTree, "
"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, totalKills, "
+ "todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, health, power1, power2, power3, "
+ "power4, power5, latency, speccount, activespec, exploredZones, equipmentCache, knownTitles, actionBars, grantableLevels) VALUES "
+ "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", CONNECTION_ASYNC);
PrepareStatement(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=?,trans_x=?,trans_y=?,trans_z=?,trans_o=?,transguid=?,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);
+ "logout_time=?,is_logout_resting=?,resettalents_cost=?,resettalents_time=?,talentTree=?,extra_flags=?,stable_slots=?,at_login=?,zone=?,death_expire_time=?,taxi_path=?,"
+ "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);
PrepareStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG, "UPDATE characters SET at_login = at_login | ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_REM_AT_LOGIN_FLAG, "UPDATE characters set at_login = at_login & ~ ? WHERE guid = ?", CONNECTION_ASYNC);
@@ -393,6 +410,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_UPD_ZONE, "UPDATE characters SET zone = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_LEVEL, "UPDATE characters SET level = ?, xp = 0 WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA, "DELETE FROM character_achievement_progress WHERE criteria = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA_GUILD, "DELETE FROM guild_achievement_progress WHERE criteria = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_INVALID_ACHIEVMENT, "DELETE FROM character_achievement WHERE achievement = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_ADDON, "INSERT INTO addons (name, crc) VALUES (?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_INVALID_PET_SPELL, "DELETE FROM pet_spell WHERE spell = ?", CONNECTION_ASYNC);
@@ -463,7 +481,6 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_INS_CHAR_ACHIEVEMENT_PROGRESS, "INSERT INTO character_achievement_progress (guid, criteria, counter, date) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_REPUTATION_BY_FACTION, "DELETE FROM character_reputation WHERE guid = ? AND faction = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_REPUTATION_BY_FACTION, "INSERT INTO character_reputation (guid, faction, standing, flags) VALUES (?, ?, ? , ?)", CONNECTION_ASYNC);
- PrepareStatement(CHAR_UPD_CHAR_ARENA_POINTS, "UPDATE characters SET arenaPoints = (arenaPoints + ?) WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_ITEM_REFUND_INSTANCE, "DELETE FROM item_refund_instance WHERE item_guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_ITEM_REFUND_INSTANCE, "INSERT INTO item_refund_instance (item_guid, player_guid, paidMoney, paidExtendedCost) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_GROUP, "DELETE FROM groups WHERE guid = ?", CONNECTION_ASYNC);
@@ -518,8 +535,6 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_DAILY, "DELETE FROM character_queststatus_daily WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_TALENT, "DELETE FROM character_talent WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_SKILLS, "DELETE FROM character_skills WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_UDP_CHAR_HONOR_POINTS, "UPDATE characters SET totalHonorPoints = ? WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_UDP_CHAR_ARENA_POINTS, "UPDATE characters SET arenaPoints = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UDP_CHAR_MONEY, "UPDATE characters SET money = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_ACTION, "INSERT INTO character_action (guid, spec, button, action, type) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_ACTION, "UPDATE character_action SET action = ?, type = ? WHERE guid = ? AND button = ? AND spec = ?", CONNECTION_ASYNC);
@@ -539,17 +554,34 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_UDP_CHAR_SKILLS, "UPDATE character_skills SET value = ?, max = ? WHERE guid = ? AND skill = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_SPELL, "INSERT INTO character_spell (guid, spell, active, disabled) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_STATS, "DELETE FROM character_stats WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_INS_CHAR_STATS, "INSERT INTO character_stats (guid, maxhealth, maxpower1, maxpower2, maxpower3, maxpower4, maxpower5, maxpower6, maxpower7, strength, agility, stamina, intellect, spirit, "
+ PrepareStatement(CHAR_INS_CHAR_STATS, "INSERT INTO character_stats (guid, maxhealth, maxpower1, maxpower2, maxpower3, maxpower4, maxpower5, strength, agility, stamina, intellect, spirit, "
"armor, resHoly, resFire, resNature, resFrost, resShadow, resArcane, blockPct, dodgePct, parryPct, critPct, rangedCritPct, spellCritPct, attackPower, rangedAttackPower, "
- "spellPower, resilience) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ "spellPower, resilience) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_PETITION_BY_OWNER, "DELETE FROM petition WHERE ownerguid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_PETITION_SIGNATURE_BY_OWNER, "DELETE FROM petition_sign WHERE ownerguid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_PETITION_BY_OWNER_AND_TYPE, "DELETE FROM petition WHERE ownerguid = ? AND type = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_PETITION_SIGNATURE_BY_OWNER_AND_TYPE, "DELETE FROM petition_sign WHERE ownerguid = ? AND type = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_INS_CHAR_GLYPHS, "INSERT INTO character_glyphs VALUES(?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_CHAR_GLYPHS, "INSERT INTO character_glyphs (guid, spec, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6, glyph7, glyph8, glyph9) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_TALENT_BY_SPELL_SPEC, "DELETE FROM character_talent WHERE guid = ? and spell = ? and spec = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_TALENT, "INSERT INTO character_talent (guid, spell, spec) VALUES (?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_ACTION_EXCEPT_SPEC, "DELETE FROM character_action WHERE spec<>? AND guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_UPD_CHAR_LIST_SLOT, "UPDATE characters SET slot = ? WHERE guid = ?", CONNECTION_ASYNC);
+
+ // Void Storage
+ PrepareStatement(CHAR_SEL_CHAR_VOID_STORAGE, "SELECT itemId, itemEntry, slot, creatorGuid, randomProperty, suffixFactor FROM character_void_storage WHERE playerGuid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_REP_CHAR_VOID_STORAGE_ITEM, "REPLACE INTO character_void_storage (itemId, playerGuid, itemEntry, slot, creatorGuid, randomProperty, suffixFactor) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHAR_VOID_STORAGE_ITEM_BY_SLOT, "DELETE FROM character_void_storage WHERE slot = ? AND playerGuid = ?", CONNECTION_ASYNC);
+
+ // CompactUnitFrame profiles
+ PrepareStatement(CHAR_SEL_CHAR_CUF_PROFILES, "SELECT id, name, frameHeight, frameWidth, sortBy, healthText, boolOptions, unk146, unk147, unk148, unk150, unk152, unk154 FROM character_cuf_profiles WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_REP_CHAR_CUF_PROFILES, "REPLACE INTO character_cuf_profiles (guid, id, name, frameHeight, frameWidth, sortBy, healthText, boolOptions, unk146, unk147, unk148, unk150, unk152, unk154) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHAR_CUF_PROFILES, "DELETE FROM character_cuf_profiles WHERE guid = ? and id = ?", CONNECTION_ASYNC);
+
+ // Guild Finder
+ PrepareStatement(CHAR_REP_GUILD_FINDER_APPLICANT, "REPLACE INTO guild_finder_applicant (guildId, playerGuid, availability, classRole, interests, comment, submitTime) VALUES(?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_GUILD_FINDER_APPLICANT, "DELETE FROM guild_finder_applicant WHERE guildId = ? AND playerGuid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_REP_GUILD_FINDER_GUILD_SETTINGS, "REPLACE INTO guild_finder_guild_settings (guildId, availability, classRoles, interests, level, listed, comment) VALUES(?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_GUILD_FINDER_GUILD_SETTINGS, "DELETE FROM guild_finder_guild_settings WHERE guildId = ?", CONNECTION_ASYNC);
// Items that hold loot or money
PrepareStatement(CHAR_SEL_ITEMCONTAINER_ITEMS, "SELECT item_id, item_count, follow_rules, ffa, blocked, counted, under_threshold, needs_quest, rnd_prop, rnd_suffix FROM item_loot_items WHERE container_id = ?", CONNECTION_SYNCH);
@@ -589,10 +621,10 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_INS_PET_SPELL, "INSERT INTO pet_spell (guid, spell, active) VALUES (?, ?, ?)", CONNECTION_BOTH);
PrepareStatement(CHAR_INS_PET_AURA, "INSERT INTO pet_aura (guid, caster_guid, spell, effect_mask, recalculate_mask, stackcount, amount0, amount1, amount2, "
"base_amount0, base_amount1, base_amount2, maxduration, remaintime, remaincharges) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_BOTH);
- PrepareStatement(CHAR_SEL_CHAR_PET_BY_ENTRY, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND id = ?", CONNECTION_SYNCH);
- PrepareStatement(CHAR_SEL_CHAR_PET_BY_ENTRY_AND_SLOT_2, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND entry = ? AND (slot = ? OR slot > ?)", CONNECTION_SYNCH);
- PrepareStatement(CHAR_SEL_CHAR_PET_BY_SLOT, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND (slot = ? OR slot > ?) ", CONNECTION_SYNCH);
- PrepareStatement(CHAR_SEL_CHAR_PET_BY_ENTRY_AND_SLOT, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND slot = ?", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_SEL_CHAR_PET_BY_ENTRY, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND id = ?", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_SEL_CHAR_PET_BY_ENTRY_AND_SLOT_2, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND entry = ? AND (slot = ? OR slot > ?)", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_SEL_CHAR_PET_BY_SLOT, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND (slot = ? OR slot > ?) ", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_SEL_CHAR_PET_BY_ENTRY_AND_SLOT, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND slot = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_DEL_CHAR_PET_BY_OWNER, "DELETE FROM character_pet WHERE owner = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_PET_NAME, "UPDATE character_pet SET name = ?, renamed = 1 WHERE owner = ? AND id = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UDP_CHAR_PET_SLOT_BY_SLOT_EXCLUDE_ID, "UPDATE character_pet SET slot = ? WHERE owner = ? AND slot = ? AND id <> ?", CONNECTION_ASYNC);
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h
index aa47fb53097..ccbacc56c92 100644..100755
--- a/src/server/shared/Database/Implementation/CharacterDatabase.h
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.h
@@ -173,7 +173,7 @@ enum CharacterDatabaseStatements
CHAR_DEL_GUILD_MEMBERS,
CHAR_INS_GUILD_RANK,
CHAR_DEL_GUILD_RANKS,
- CHAR_DEL_GUILD_LOWEST_RANK,
+ CHAR_DEL_GUILD_RANK,
CHAR_INS_GUILD_BANK_TAB,
CHAR_DEL_GUILD_BANK_TAB,
CHAR_DEL_GUILD_BANK_TABS,
@@ -206,6 +206,17 @@ enum CharacterDatabaseStatements
CHAR_INS_GUILD_MEMBER_WITHDRAW,
CHAR_DEL_GUILD_MEMBER_WITHDRAW,
CHAR_SEL_CHAR_DATA_FOR_GUILD,
+ CHAR_DEL_GUILD_ACHIEVEMENT,
+ CHAR_INS_GUILD_ACHIEVEMENT,
+ CHAR_DEL_GUILD_ACHIEVEMENT_CRITERIA,
+ CHAR_INS_GUILD_ACHIEVEMENT_CRITERIA,
+ CHAR_DEL_ALL_GUILD_ACHIEVEMENTS,
+ CHAR_DEL_ALL_GUILD_ACHIEVEMENT_CRITERIA,
+ CHAR_SEL_GUILD_ACHIEVEMENT,
+ CHAR_SEL_GUILD_ACHIEVEMENT_CRITERIA,
+ CHAR_UPD_GUILD_EXPERIENCE,
+ CHAR_UPD_GUILD_RESET_TODAY_EXPERIENCE,
+ CHAR_INS_GUILD_NEWS,
CHAR_SEL_CHANNEL,
CHAR_INS_CHANNEL,
@@ -220,6 +231,10 @@ enum CharacterDatabaseStatements
CHAR_INS_AURA,
+ CHAR_SEL_PLAYER_CURRENCY,
+ CHAR_UPD_PLAYER_CURRENCY,
+ CHAR_REP_PLAYER_CURRENCY,
+
CHAR_SEL_ACCOUNT_DATA,
CHAR_REP_ACCOUNT_DATA,
CHAR_DEL_ACCOUNT_DATA,
@@ -330,6 +345,7 @@ enum CharacterDatabaseStatements
CHAR_UPD_ZONE,
CHAR_UPD_LEVEL,
CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA,
+ CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA_GUILD,
CHAR_DEL_INVALID_ACHIEVMENT,
CHAR_INS_ADDON,
CHAR_DEL_INVALID_PET_SPELL,
@@ -399,7 +415,6 @@ enum CharacterDatabaseStatements
CHAR_INS_CHAR_ACHIEVEMENT_PROGRESS,
CHAR_DEL_CHAR_REPUTATION_BY_FACTION,
CHAR_INS_CHAR_REPUTATION_BY_FACTION,
- CHAR_UPD_CHAR_ARENA_POINTS,
CHAR_DEL_ITEM_REFUND_INSTANCE,
CHAR_INS_ITEM_REFUND_INSTANCE,
CHAR_DEL_GROUP,
@@ -454,8 +469,6 @@ enum CharacterDatabaseStatements
CHAR_DEL_CHAR_QUESTSTATUS_DAILY,
CHAR_DEL_CHAR_TALENT,
CHAR_DEL_CHAR_SKILLS,
- CHAR_UDP_CHAR_HONOR_POINTS,
- CHAR_UDP_CHAR_ARENA_POINTS,
CHAR_UDP_CHAR_MONEY,
CHAR_INS_CHAR_ACTION,
CHAR_UPD_CHAR_ACTION,
@@ -484,6 +497,20 @@ enum CharacterDatabaseStatements
CHAR_DEL_CHAR_TALENT_BY_SPELL_SPEC,
CHAR_INS_CHAR_TALENT,
CHAR_DEL_CHAR_ACTION_EXCEPT_SPEC,
+ CHAR_UPD_CHAR_LIST_SLOT,
+
+ CHAR_SEL_CHAR_VOID_STORAGE,
+ CHAR_REP_CHAR_VOID_STORAGE_ITEM,
+ CHAR_DEL_CHAR_VOID_STORAGE_ITEM_BY_SLOT,
+
+ CHAR_SEL_CHAR_CUF_PROFILES,
+ CHAR_REP_CHAR_CUF_PROFILES,
+ CHAR_DEL_CHAR_CUF_PROFILES,
+
+ CHAR_REP_GUILD_FINDER_APPLICANT,
+ CHAR_DEL_GUILD_FINDER_APPLICANT,
+ CHAR_REP_GUILD_FINDER_GUILD_SETTINGS,
+ CHAR_DEL_GUILD_FINDER_GUILD_SETTINGS,
CHAR_REP_CALENDAR_EVENT,
CHAR_DEL_CALENDAR_EVENT,
diff --git a/src/server/shared/Database/Implementation/WorldDatabase.cpp b/src/server/shared/Database/Implementation/WorldDatabase.cpp
index f27ee2b72e0..8a00de8c20b 100644
--- a/src/server/shared/Database/Implementation/WorldDatabase.cpp
+++ b/src/server/shared/Database/Implementation/WorldDatabase.cpp
@@ -34,9 +34,9 @@ void WorldDatabaseConnection::DoPrepareStatements()
PrepareStatement(WORLD_DEL_GRAVEYARD_ZONE, "DELETE FROM game_graveyard_zone WHERE id = ? AND ghost_zone = ? AND faction = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_INS_GAME_TELE, "INSERT INTO game_tele (id, position_x, position_y, position_z, orientation, map, name) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(WORLD_DEL_GAME_TELE, "DELETE FROM game_tele WHERE name = ?", CONNECTION_ASYNC);
- PrepareStatement(WORLD_INS_NPC_VENDOR, "INSERT INTO npc_vendor (entry, item, maxcount, incrtime, extendedcost) VALUES(?, ?, ?, ?, ?)", CONNECTION_ASYNC);
- PrepareStatement(WORLD_DEL_NPC_VENDOR, "DELETE FROM npc_vendor WHERE entry = ? AND item = ?", CONNECTION_ASYNC);
- PrepareStatement(WORLD_SEL_NPC_VENDOR_REF, "SELECT item, maxcount, incrtime, ExtendedCost FROM npc_vendor WHERE entry = ? ORDER BY slot ASC", CONNECTION_SYNCH);
+ PrepareStatement(WORLD_INS_NPC_VENDOR, "INSERT INTO npc_vendor (entry, item, maxcount, incrtime, extendedcost, type) VALUES(?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(WORLD_DEL_NPC_VENDOR, "DELETE FROM npc_vendor WHERE entry = ? AND item = ? AND type = ?", CONNECTION_ASYNC);
+ PrepareStatement(WORLD_SEL_NPC_VENDOR_REF, "SELECT item, maxcount, incrtime, ExtendedCost, type FROM npc_vendor WHERE entry = ? AND type = ? ORDER BY slot ASC", CONNECTION_SYNCH);
PrepareStatement(WORLD_UPD_CREATURE_MOVEMENT_TYPE, "UPDATE creature SET MovementType = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_UPD_CREATURE_FACTION, "UPDATE creature_template SET faction_A = ?, faction_H = ? WHERE entry = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_UPD_CREATURE_NPCFLAG, "UPDATE creature_template SET npcflag = ? WHERE entry = ?", CONNECTION_ASYNC);
@@ -76,7 +76,7 @@ void WorldDatabaseConnection::DoPrepareStatements()
PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_ID_BY_GUID, "SELECT id FROM waypoint_scripts WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_DEL_CREATURE, "DELETE FROM creature WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_SEL_COMMANDS, "SELECT name, permission, help FROM command", CONNECTION_SYNCH);
- PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction_A, faction_H, npcflag, speed_walk, speed_run, scale, rank, mindmg, maxdmg, dmgschool, attackpower, dmg_multiplier, baseattacktime, rangeattacktime, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_type, trainer_spell, trainer_class, trainer_race, minrangedmg, maxrangedmg, rangedattackpower, type, type_flags, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, Health_mod, Mana_mod, Armor_mod, RacialLeader, questItem1, questItem2, questItem3, questItem4, questItem5, questItem6, movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template WHERE entry = ?", CONNECTION_SYNCH);
+ PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, exp_unk, faction_A, faction_H, npcflag, speed_walk, speed_run, scale, rank, mindmg, maxdmg, dmgschool, attackpower, dmg_multiplier, baseattacktime, rangeattacktime, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_type, trainer_class, trainer_race, minrangedmg, maxrangedmg, rangedattackpower, type, type_flags, type_flags2, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, Health_mod, Mana_mod, Mana_mod_extra, Armor_mod, RacialLeader, questItem1, questItem2, questItem3, questItem4, questItem5, questItem6, movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template WHERE entry = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_BY_ID, "SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_ITEM_TEMPLATE_BY_NAME, "SELECT entry FROM item_template WHERE name = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_CREATURE_BY_ID, "SELECT guid FROM creature WHERE id = ?", CONNECTION_SYNCH);
diff --git a/src/server/shared/Define.h b/src/server/shared/Define.h
index d18f160aeaf..57e63a49790 100644
--- a/src/server/shared/Define.h
+++ b/src/server/shared/Define.h
@@ -95,4 +95,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_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/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h
index d2677538805..c30dfff2f40 100644
--- a/src/server/shared/Packets/ByteBuffer.h
+++ b/src/server/shared/Packets/ByteBuffer.h
@@ -69,19 +69,19 @@ class ByteBuffer
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);
}
- ByteBuffer(size_t reserve) : _rpos(0), _wpos(0)
+ ByteBuffer(size_t reserve) : _rpos(0), _wpos(0), _bitpos(8), _curbitval(0)
{
_storage.reserve(reserve);
}
// copy constructor
ByteBuffer(const ByteBuffer &buf) : _rpos(buf._rpos), _wpos(buf._wpos),
- _storage(buf._storage)
+ _bitpos(buf._bitpos), _curbitval(buf._curbitval), _storage(buf._storage)
{
}
@@ -93,16 +93,115 @@ 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 << (i));
+
+ return value;
+ }
+
+ // Reads a byte (if needed) in-place
+ void ReadByteSeq(uint8& b)
+ {
+ if (b != 0)
+ b ^= read<uint8>();
+ }
+
+ void WriteByteSeq(uint8 b)
+ {
+ if (b != 0)
+ append<uint8>(b ^ 1);
+ }
+
template <typename T> void put(size_t pos, T value)
{
EndianConvert(value);
put(pos, (uint8 *)&value, sizeof(value));
}
+ /**
+ * @name PutBits
+ * @brief Places specified amount of bits of value at specified position in packet.
+ * To ensure all bits are correctly written, only call this method after
+ * bit flush has been performed
+
+ * @param pos Position to place the value at, in bits. The entire value must fit in the packet
+ * It is advised to obtain the position using bitwpos() function.
+
+ * @param value Data to write.
+ * @param bitCount Number of bits to store the value on.
+ */
+ template <typename T> void PutBits(size_t pos, T value, uint32 bitCount)
+ {
+ if (!bitCount)
+ throw ByteBufferSourceException((pos + bitCount) / 8, size(), 0);
+
+ if (pos + bitCount > size() * 8)
+ throw ByteBufferPositionException(false, (pos + bitCount) / 8, size(), (bitCount - 1) / 8 + 1);
+
+ for (uint32 i = 0; i < bitCount; ++i)
+ {
+ size_t wp = (pos + i) / 8;
+ size_t bit = (pos + i) % 8;
+ if ((value >> (bitCount - i - 1)) & 1)
+ _storage[wp] |= 1 << (7 - bit);
+ else
+ _storage[wp] &= ~(1 << (7 - bit));
+ }
+ }
+
ByteBuffer &operator<<(uint8 value)
{
append<uint8>(value);
@@ -296,6 +395,16 @@ class ByteBuffer
return _wpos;
}
+ /// Returns position of last written bit
+ size_t bitwpos() const { return _wpos * 8 + 8 - _bitpos; }
+
+ size_t bitwpos(size_t newPos)
+ {
+ _wpos = newPos / 8;
+ _bitpos = 8 - (newPos % 8);
+ return _wpos * 8 + 8 - _bitpos;
+ }
+
template<typename T>
void read_skip() { read_skip(sizeof(T)); }
@@ -354,6 +463,25 @@ class ByteBuffer
}
}
+ std::string ReadString(uint32 length)
+ {
+ if (!length)
+ return std::string();
+ char* buffer = new char[length + 1]();
+ read((uint8*)buffer, length);
+ std::string retval = buffer;
+ delete[] buffer;
+ return retval;
+ }
+
+ //! Method for writing strings that have their length sent separately in packet
+ //! without null-terminating the string
+ void WriteString(std::string const& str)
+ {
+ if (size_t len = str.length())
+ append(str.c_str(), len);
+ }
+
uint32 ReadPackedTime()
{
uint32 packedDate = read<uint32>();
@@ -481,7 +609,8 @@ class ByteBuffer
void hexlike() const;
protected:
- size_t _rpos, _wpos;
+ size_t _rpos, _wpos, _bitpos;
+ uint8 _curbitval;
std::vector<uint8> _storage;
};
diff --git a/src/server/shared/Packets/WorldPacket.h b/src/server/shared/Packets/WorldPacket.h
deleted file mode 100644
index 7ec2b5d1e1e..00000000000
--- a/src/server/shared/Packets/WorldPacket.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2008-2013 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
-
diff --git a/src/server/shared/Utilities/Util.cpp b/src/server/shared/Utilities/Util.cpp
index 48012b6eea8..e53f0c9b839 100644
--- a/src/server/shared/Utilities/Util.cpp
+++ b/src/server/shared/Utilities/Util.cpp
@@ -150,9 +150,9 @@ std::string secsToTimeString(uint64 timeInSecs, bool shortText, bool hoursOnly)
return ss.str();
}
-int32 MoneyStringToMoney(const std::string& moneyString)
+int64 MoneyStringToMoney(const std::string& moneyString)
{
- int32 money = 0;
+ int64 money = 0;
if (!(std::count(moneyString.begin(), moneyString.end(), 'g') == 1 ||
std::count(moneyString.begin(), moneyString.end(), 's') == 1 ||
@@ -169,7 +169,7 @@ int32 MoneyStringToMoney(const std::string& moneyString)
if (gCount + sCount + cCount != 1)
return 0;
- uint32 amount = atoi(*itr);
+ uint64 amount = atol(*itr);
if (gCount == 1)
money += amount * 100 * 100;
else if (sCount == 1)
diff --git a/src/server/shared/Utilities/Util.h b/src/server/shared/Utilities/Util.h
index 30a6b27f186..d814c5b59e7 100644
--- a/src/server/shared/Utilities/Util.h
+++ b/src/server/shared/Utilities/Util.h
@@ -68,7 +68,7 @@ private:
void stripLineInvisibleChars(std::string &src);
-int32 MoneyStringToMoney(const std::string& moneyString);
+int64 MoneyStringToMoney(const std::string& moneyString);
std::string secsToTimeString(uint64 timeInSecs, bool shortText = false, bool hoursOnly = false);
uint32 TimeStringToSecs(const std::string& timestring);