aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp43
-rw-r--r--src/server/game/DataStores/DB2Stores.h18
-rw-r--r--src/server/game/Handlers/HotfixHandler.cpp93
-rw-r--r--src/server/game/Handlers/QueryHandler.cpp31
-rw-r--r--src/server/game/Server/Packets/AllPackets.h1
-rw-r--r--src/server/game/Server/Packets/HotfixPackets.cpp101
-rw-r--r--src/server/game/Server/Packets/HotfixPackets.h108
-rw-r--r--src/server/game/Server/Packets/QueryPackets.cpp26
-rw-r--r--src/server/game/Server/Packets/QueryPackets.h31
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp6
-rw-r--r--src/server/game/Server/WorldSession.cpp1
-rw-r--r--src/server/game/Server/WorldSession.h13
-rw-r--r--src/server/game/Server/WorldSocket.h2
-rw-r--r--src/server/game/World/World.cpp16
-rw-r--r--src/server/game/World/World.h1
-rw-r--r--src/server/shared/Packets/ByteBuffer.h4
-rw-r--r--src/server/worldserver/worldserver.conf.dist8
17 files changed, 373 insertions, 130 deletions
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp
index d37ec2ee846..66ee56c21ca 100644
--- a/src/server/game/DataStores/DB2Stores.cpp
+++ b/src/server/game/DataStores/DB2Stores.cpp
@@ -963,50 +963,45 @@ void DB2Manager::LoadHotfixData()
{
uint32 oldMSTime = getMSTime();
- QueryResult result = HotfixDatabase.Query("SELECT TableHash, RecordID, `Timestamp`, Deleted FROM hotfix_data");
+ QueryResult result = HotfixDatabase.Query("SELECT Id, TableHash, RecordId, Deleted FROM hotfix_data ORDER BY Id");
if (!result)
{
- TC_LOG_INFO("misc", ">> Loaded 0 hotfix info entries.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 hotfix info entries.");
return;
}
uint32 count = 0;
- _hotfixData.reserve(result->GetRowCount());
+ std::map<std::pair<uint32, int32>, bool> deletedRecords;
do
{
Field* fields = result->Fetch();
- HotfixNotify info;
- info.TableHash = fields[0].GetUInt32();
- info.Entry = fields[1].GetUInt32();
- info.Timestamp = fields[2].GetUInt32();
- _hotfixData.push_back(info);
-
- if (fields[3].GetBool())
+ int32 id = fields[0].GetInt32();
+ uint32 tableHash = fields[1].GetUInt32();
+ int32 recordId = fields[2].GetInt32();
+ bool deleted = fields[3].GetBool();
+ if (_stores.find(tableHash) == _stores.end())
{
- auto itr = _stores.find(info.TableHash);
- if (itr != _stores.end())
- itr->second->EraseRecord(info.Entry);
+ TC_LOG_ERROR("sql.sql", "Table `hotfix_data` references unknown DB2 store by hash 0x%X in hotfix id %d", tableHash, id);
+ continue;
}
+ HotfixData& data = _hotfixData[id];
+ data.Id = id;
+ data.Records.emplace_back(tableHash, recordId);
+ deletedRecords[std::make_pair(tableHash, recordId)] = deleted;
++count;
} while (result->NextRow());
- TC_LOG_INFO("misc", ">> Loaded %u hotfix info entries in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
-}
-
-time_t DB2Manager::GetHotfixDate(uint32 entry, uint32 type) const
-{
- time_t ret = 0;
- for (HotfixNotify const& hotfix : _hotfixData)
- if (hotfix.Entry == entry && hotfix.TableHash == type)
- if (time_t(hotfix.Timestamp) > ret)
- ret = time_t(hotfix.Timestamp);
+ for (auto itr = deletedRecords.begin(); itr != deletedRecords.end(); ++itr)
+ if (itr->second)
+ if (DB2StorageBase* store = Trinity::Containers::MapGetValuePtr(_stores, itr->first.first))
+ store->EraseRecord(itr->first.second);
- return ret ? ret : time(nullptr);
+ TC_LOG_INFO("server.loading", ">> Loaded %u hotfix records in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
std::vector<uint32> DB2Manager::GetAreasForGroup(uint32 areaGroupId) const
diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h
index 2c284ddcc04..d161ac438cb 100644
--- a/src/server/game/DataStores/DB2Stores.h
+++ b/src/server/game/DataStores/DB2Stores.h
@@ -209,14 +209,19 @@ TC_GAME_API extern TaxiMask sAllianceTax
TC_GAME_API extern TaxiPathSetBySource sTaxiPathSetBySource;
TC_GAME_API extern TaxiPathNodesByPath sTaxiPathNodesByPath;
-struct HotfixNotify
+struct HotfixRecord
{
+ HotfixRecord(uint32 tableHash, int32 recordId) : TableHash(tableHash), RecordId(recordId) { }
+
uint32 TableHash;
- uint32 Timestamp;
- uint32 Entry;
+ int32 RecordId;
};
-typedef std::vector<HotfixNotify> HotfixData;
+struct HotfixData
+{
+ int32 Id;
+ std::vector<HotfixRecord> Records;
+};
#define DEFINE_DB2_SET_COMPARATOR(structure) \
struct structure ## Comparator \
@@ -285,8 +290,7 @@ public:
DB2StorageBase const* GetStorage(uint32 type) const;
void LoadHotfixData();
- HotfixData const* GetHotfixData() const { return &_hotfixData; }
- time_t GetHotfixDate(uint32 entry, uint32 type) const;
+ std::map<int32, HotfixData> const& GetHotfixData() const { return _hotfixData; }
std::vector<uint32> GetAreasForGroup(uint32 areaGroupId) const;
std::vector<ArtifactPowerEntry const*> GetArtifactPowers(uint8 artifactId) const;
@@ -354,7 +358,7 @@ public:
private:
StorageMap _stores;
- HotfixData _hotfixData;
+ std::map<int32, HotfixData> _hotfixData;
AreaGroupMemberContainer _areaGroupMembers;
ArtifactPowersContainer _artifactPowers;
diff --git a/src/server/game/Handlers/HotfixHandler.cpp b/src/server/game/Handlers/HotfixHandler.cpp
new file mode 100644
index 00000000000..656afb6858f
--- /dev/null
+++ b/src/server/game/Handlers/HotfixHandler.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "WorldSession.h"
+#include "Containers.h"
+#include "DB2Stores.h"
+#include "HotfixPackets.h"
+#include "Log.h"
+
+void WorldSession::HandleDBQueryBulk(WorldPackets::Hotfix::DBQueryBulk& dbQuery)
+{
+ DB2StorageBase const* store = sDB2Manager.GetStorage(dbQuery.TableHash);
+ if (!store)
+ {
+ TC_LOG_ERROR("network", "CMSG_DB_QUERY_BULK: %s requested unsupported unknown hotfix type: %u", GetPlayerInfo().c_str(), dbQuery.TableHash);
+ return;
+ }
+
+ for (WorldPackets::Hotfix::DBQueryBulk::DBQueryRecord const& record : dbQuery.Queries)
+ {
+ WorldPackets::Hotfix::DBReply dbReply;
+ dbReply.TableHash = dbQuery.TableHash;
+ dbReply.RecordID = record.RecordID;
+
+ if (store->HasRecord(record.RecordID))
+ {
+ dbReply.Allow = true;
+ dbReply.Timestamp = sWorld->GetGameTime();
+ store->WriteRecord(record.RecordID, GetSessionDbcLocale(), dbReply.Data);
+ }
+ else
+ {
+ TC_LOG_TRACE("network", "CMSG_DB_QUERY_BULK: %s requested non-existing entry %u in datastore: %u", GetPlayerInfo().c_str(), record.RecordID, dbQuery.TableHash);
+ dbReply.Timestamp = time(NULL);
+ }
+
+ SendPacket(dbReply.Write());
+ }
+}
+
+void WorldSession::SendHotfixList(int32 version)
+{
+ SendPacket(WorldPackets::Hotfix::HotfixList(version, sDB2Manager.GetHotfixData()).Write());
+}
+
+void WorldSession::HandleHotfixQuery(WorldPackets::Hotfix::HotfixQuery& hotfixQuery)
+{
+ std::map<int32, HotfixData> const& hotfixes = sDB2Manager.GetHotfixData();
+ WorldPackets::Hotfix::HotfixQueryResponse hotfixQueryResponse;
+ hotfixQueryResponse.Hotfixes.reserve(hotfixQuery.Hotfixes.size());
+ for (int32 hotfixId : hotfixQuery.Hotfixes)
+ {
+ if (HotfixData const* hotfix = Trinity::Containers::MapGetValuePtr(hotfixes, hotfixId))
+ {
+ WorldPackets::Hotfix::HotfixQueryResponse::HotfixData hotfixData;
+ hotfixData.ID = hotfix->Id;
+
+ for (HotfixRecord const& hotfixRecord : hotfix->Records)
+ {
+ DB2StorageBase const* storage = sDB2Manager.GetStorage(hotfixRecord.TableHash);
+
+ WorldPackets::Hotfix::HotfixQueryResponse::HotfixRecord record;
+ record.TableHash = hotfixRecord.TableHash;
+ record.RecordID = hotfixRecord.RecordId;
+ if (storage->HasRecord(hotfixRecord.RecordId))
+ {
+ record.HotfixData = boost::in_place();
+ storage->WriteRecord(hotfixRecord.RecordId, GetSessionDbcLocale(), *record.HotfixData);
+ }
+
+ hotfixData.Records.emplace_back(std::move(record));
+ }
+
+ hotfixQueryResponse.Hotfixes.emplace_back(std::move(hotfixData));
+ }
+ }
+
+ SendPacket(hotfixQueryResponse.Write());
+}
diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp
index a934f05cd67..6006f66772c 100644
--- a/src/server/game/Handlers/QueryHandler.cpp
+++ b/src/server/game/Handlers/QueryHandler.cpp
@@ -393,37 +393,6 @@ void WorldSession::HandleQuestPOIQuery(WorldPackets::Query::QuestPOIQuery& quest
SendPacket(response.Write());
}
-void WorldSession::HandleDBQueryBulk(WorldPackets::Query::DBQueryBulk& packet)
-{
- DB2StorageBase const* store = sDB2Manager.GetStorage(packet.TableHash);
- if (!store)
- {
- TC_LOG_ERROR("network", "CMSG_DB_QUERY_BULK: %s requested unsupported unknown hotfix type: %u", GetPlayerInfo().c_str(), packet.TableHash);
- return;
- }
-
- for (WorldPackets::Query::DBQueryBulk::DBQueryRecord const& rec : packet.Queries)
- {
- WorldPackets::Query::DBReply response;
- response.TableHash = packet.TableHash;
- response.RecordID = rec.RecordID;
-
- if (store->HasRecord(rec.RecordID))
- {
- response.Allow = true;
- response.Timestamp = sDB2Manager.GetHotfixDate(rec.RecordID, packet.TableHash);
- store->WriteRecord(rec.RecordID, GetSessionDbcLocale(), response.Data);
- }
- else
- {
- TC_LOG_TRACE("network", "CMSG_DB_QUERY_BULK: %s requested non-existing entry %u in datastore: %u", GetPlayerInfo().c_str(), rec.RecordID, packet.TableHash);
- response.Timestamp = time(NULL);
- }
-
- SendPacket(response.Write());
- }
-}
-
/**
* Handles the packet sent by the client when requesting information about item text.
*
diff --git a/src/server/game/Server/Packets/AllPackets.h b/src/server/game/Server/Packets/AllPackets.h
index e1fe1860388..98370db4073 100644
--- a/src/server/game/Server/Packets/AllPackets.h
+++ b/src/server/game/Server/Packets/AllPackets.h
@@ -44,6 +44,7 @@
#include "GarrisonPackets.h"
#include "GuildFinderPackets.h"
#include "GuildPackets.h"
+#include "HotfixPackets.h"
#include "InspectPackets.h"
#include "InstancePackets.h"
#include "ItemPackets.h"
diff --git a/src/server/game/Server/Packets/HotfixPackets.cpp b/src/server/game/Server/Packets/HotfixPackets.cpp
new file mode 100644
index 00000000000..fa1fabf3bf4
--- /dev/null
+++ b/src/server/game/Server/Packets/HotfixPackets.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "HotfixPackets.h"
+#include "PacketUtilities.h"
+
+void WorldPackets::Hotfix::DBQueryBulk::Read()
+{
+ _worldPacket >> TableHash;
+
+ uint32 count = _worldPacket.ReadBits(13);
+
+ Queries.resize(count);
+ for (uint32 i = 0; i < count; ++i)
+ {
+ _worldPacket >> Queries[i].GUID;
+ _worldPacket >> Queries[i].RecordID;
+ }
+}
+
+WorldPacket const* WorldPackets::Hotfix::DBReply::Write()
+{
+ _worldPacket << uint32(TableHash);
+ _worldPacket << uint32(RecordID);
+ _worldPacket << uint32(Timestamp);
+ _worldPacket.WriteBit(Allow);
+ _worldPacket << uint32(Data.size());
+ _worldPacket.append(Data);
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Hotfix::HotfixList::Write()
+{
+ _worldPacket << int32(HotfixCacheVersion);
+ _worldPacket << uint32(Hotfixes.size());
+ for (auto const& hotfixEntry : Hotfixes)
+ _worldPacket << int32(hotfixEntry.first);
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Hotfix::HotfixQuery::Read()
+{
+ uint32 hotfixCount = _worldPacket.read<uint32>();
+ if (hotfixCount > sDB2Manager.GetHotfixData().size())
+ throw PacketArrayMaxCapacityException(hotfixCount, sDB2Manager.GetHotfixData().size());
+
+ Hotfixes.resize(hotfixCount);
+ for (int32& hotfixId : Hotfixes)
+ _worldPacket >> hotfixId;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Hotfix::HotfixQueryResponse::HotfixRecord const& hotfixRecord)
+{
+ data << uint32(hotfixRecord.TableHash);
+ data << int32(hotfixRecord.RecordID);
+ data.WriteBit(hotfixRecord.HotfixData.is_initialized());
+ if (hotfixRecord.HotfixData)
+ {
+ data << uint32(hotfixRecord.HotfixData->size());
+ data.append(*hotfixRecord.HotfixData);
+ }
+ else
+ data << uint32(0);
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Hotfix::HotfixQueryResponse::HotfixData const& hotfixData)
+{
+ data << int32(hotfixData.ID);
+ data << uint32(hotfixData.Records.size());
+ for (WorldPackets::Hotfix::HotfixQueryResponse::HotfixRecord const& hotfixRecord : hotfixData.Records)
+ data << hotfixRecord;
+
+ return data;
+}
+
+WorldPacket const* WorldPackets::Hotfix::HotfixQueryResponse::Write()
+{
+ _worldPacket << uint32(Hotfixes.size());
+ for (HotfixData const& hotfix : Hotfixes)
+ _worldPacket << hotfix;
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/HotfixPackets.h b/src/server/game/Server/Packets/HotfixPackets.h
new file mode 100644
index 00000000000..eb87ddba1e6
--- /dev/null
+++ b/src/server/game/Server/Packets/HotfixPackets.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HotfixPackets_h__
+#define HotfixPackets_h__
+
+#include "Packet.h"
+#include "Common.h"
+#include "DB2Stores.h"
+#include "ObjectGuid.h"
+
+namespace WorldPackets
+{
+ namespace Hotfix
+ {
+ class DBQueryBulk final : public ClientPacket
+ {
+ public:
+ struct DBQueryRecord
+ {
+ ObjectGuid GUID;
+ uint32 RecordID = 0;
+ };
+
+ DBQueryBulk(WorldPacket&& packet) : ClientPacket(CMSG_DB_QUERY_BULK, std::move(packet)) { }
+
+ void Read() override;
+
+ uint32 TableHash = 0;
+ std::vector<DBQueryRecord> Queries;
+ };
+
+ class DBReply final : public ServerPacket
+ {
+ public:
+ DBReply() : ServerPacket(SMSG_DB_REPLY, 12) { }
+
+ WorldPacket const* Write() override;
+
+ uint32 TableHash = 0;
+ uint32 Timestamp = 0;
+ uint32 RecordID = 0;
+ bool Allow = false;
+ ByteBuffer Data;
+ };
+
+ class HotfixList final : public ServerPacket
+ {
+ public:
+ HotfixList(int32 hotfixCacheVersion, std::map<int32, HotfixData> const& hotfixes)
+ : ServerPacket(SMSG_HOTFIX_LIST), HotfixCacheVersion(hotfixCacheVersion), Hotfixes(hotfixes) { }
+
+ WorldPacket const* Write() override;
+
+ int32 HotfixCacheVersion;
+ std::map<int32, HotfixData> const& Hotfixes;
+ };
+
+ class HotfixQuery final : public ClientPacket
+ {
+ public:
+ HotfixQuery(WorldPacket&& packet) : ClientPacket(CMSG_HOTFIX_QUERY, std::move(packet)) { }
+
+ void Read() override;
+
+ std::vector<int32> Hotfixes;
+ };
+
+ class HotfixQueryResponse final : public ServerPacket
+ {
+ public:
+ struct HotfixRecord
+ {
+ uint32 TableHash = 0;
+ int32 RecordID = 0;
+ Optional<ByteBuffer> HotfixData;
+ };
+
+ struct HotfixData
+ {
+ int32 ID = 0;
+ std::vector<HotfixRecord> Records;
+ };
+
+ HotfixQueryResponse() : ServerPacket(SMSG_HOTFIX_QUERY_RESPONSE) { }
+
+ WorldPacket const* Write() override;
+
+ std::vector<HotfixData> Hotfixes;
+ };
+ }
+}
+
+#endif // HotfixPackets_h__
diff --git a/src/server/game/Server/Packets/QueryPackets.cpp b/src/server/game/Server/Packets/QueryPackets.cpp
index f2627203cce..84cdb5e1e47 100644
--- a/src/server/game/Server/Packets/QueryPackets.cpp
+++ b/src/server/game/Server/Packets/QueryPackets.cpp
@@ -254,32 +254,6 @@ WorldPacket const* WorldPackets::Query::QueryNPCTextResponse::Write()
return &_worldPacket;
}
-void WorldPackets::Query::DBQueryBulk::Read()
-{
- _worldPacket >> TableHash;
-
- uint32 count = _worldPacket.ReadBits(13);
-
- Queries.resize(count);
- for (uint32 i = 0; i < count; ++i)
- {
- _worldPacket >> Queries[i].GUID;
- _worldPacket >> Queries[i].RecordID;
- }
-}
-
-WorldPacket const* WorldPackets::Query::DBReply::Write()
-{
- _worldPacket << uint32(TableHash);
- _worldPacket << uint32(RecordID);
- _worldPacket << uint32(Timestamp);
- _worldPacket.WriteBit(Allow);
- _worldPacket << uint32(Data.size());
- _worldPacket.append(Data);
-
- return &_worldPacket;
-}
-
void WorldPackets::Query::QueryGameObject::Read()
{
_worldPacket >> GameObjectID;
diff --git a/src/server/game/Server/Packets/QueryPackets.h b/src/server/game/Server/Packets/QueryPackets.h
index 0d669e6ff31..a5f95a9dc49 100644
--- a/src/server/game/Server/Packets/QueryPackets.h
+++ b/src/server/game/Server/Packets/QueryPackets.h
@@ -176,37 +176,6 @@ namespace WorldPackets
uint32 BroadcastTextID[MAX_NPC_TEXT_OPTIONS];
};
- class DBQueryBulk final : public ClientPacket
- {
- public:
- struct DBQueryRecord
- {
- ObjectGuid GUID;
- uint32 RecordID = 0;
- };
-
- DBQueryBulk(WorldPacket&& packet) : ClientPacket(CMSG_DB_QUERY_BULK, std::move(packet)) { }
-
- void Read() override;
-
- uint32 TableHash = 0;
- std::vector<DBQueryRecord> Queries;
- };
-
- class DBReply final : public ServerPacket
- {
- public:
- DBReply() : ServerPacket(SMSG_DB_REPLY, 12) { }
-
- WorldPacket const* Write() override;
-
- uint32 TableHash = 0;
- uint32 Timestamp = 0;
- uint32 RecordID = 0;
- bool Allow = false;
- ByteBuffer Data;
- };
-
class QueryGameObject final : public ClientPacket
{
public:
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index fd6769cb16b..809a2d2c36b 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -445,7 +445,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_GUILD_UPDATE_INFO_TEXT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildUpdateInfoText);
DEFINE_HANDLER(CMSG_GUILD_UPDATE_MOTD_TEXT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildUpdateMotdText);
DEFINE_HANDLER(CMSG_HEARTH_AND_RESURRECT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleHearthAndResurrect);
- DEFINE_HANDLER(CMSG_HOTFIX_QUERY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
+ DEFINE_HANDLER(CMSG_HOTFIX_QUERY, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleHotfixQuery);
DEFINE_HANDLER(CMSG_IGNORE_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleIgnoreTradeOpcode);
DEFINE_HANDLER(CMSG_INITIATE_ROLE_POLL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInitiateRolePoll);
DEFINE_HANDLER(CMSG_INITIATE_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInitiateTradeOpcode);
@@ -1257,8 +1257,8 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HEALTH_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HIGHEST_THREAT_UPDATE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOTFIXES, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOTFIX_LIST, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOTFIX_QUERY_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOTFIX_LIST, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOTFIX_QUERY_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INITIALIZE_FACTIONS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INITIAL_SETUP, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INIT_WORLD_STATES, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index c9daf2a274f..62e83ce253e 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -1047,6 +1047,7 @@ void WorldSession::InitializeSessionCallback(SQLQueryHolder* realmHolder, SQLQue
SendSetTimeZoneInformation();
SendFeatureSystemStatusGlueScreen();
SendClientCacheVersion(sWorld->getIntConfig(CONFIG_CLIENTCACHE_VERSION));
+ SendHotfixList(int32(sWorld->getIntConfig(CONFIG_HOTFIX_CACHE_VERSION)));
SendTutorialsData();
if (PreparedQueryResult characterCountsResult = holder->GetPreparedResult(AccountInfoQueryHolder::GLOBAL_REALM_CHARACTER_COUNTS))
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 2438bb2a426..3703cdcf513 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -351,6 +351,12 @@ namespace WorldPackets
class LFGuildSetGuildPost;
}
+ namespace Hotfix
+ {
+ class DBQueryBulk;
+ class HotfixQuery;
+ }
+
namespace Inspect
{
class Inspect;
@@ -545,7 +551,6 @@ namespace WorldPackets
class QueryPlayerName;
class QueryPageText;
class QueryNPCText;
- class DBQueryBulk;
class QueryGameObject;
class QueryCorpseLocationFromClient;
class QueryCorpseTransport;
@@ -933,6 +938,7 @@ class TC_GAME_API WorldSession
void SendAuthResponse(uint32 code, bool queued, uint32 queuePos = 0);
void SendClientCacheVersion(uint32 version);
+ void SendHotfixList(int32 version);
void InitializeSession();
void InitializeSessionCallback(SQLQueryHolder* realmHolder, SQLQueryHolder* holder);
@@ -1251,10 +1257,11 @@ class TC_GAME_API WorldSession
void HandleNameQueryOpcode(WorldPackets::Query::QueryPlayerName& packet);
void HandleQueryTimeOpcode(WorldPackets::Query::QueryTime& queryTime);
void HandleCreatureQuery(WorldPackets::Query::QueryCreature& packet);
- void HandleDBQueryBulk(WorldPackets::Query::DBQueryBulk& packet);
-
void HandleGameObjectQueryOpcode(WorldPackets::Query::QueryGameObject& packet);
+ void HandleDBQueryBulk(WorldPackets::Hotfix::DBQueryBulk& dbQuery);
+ void HandleHotfixQuery(WorldPackets::Hotfix::HotfixQuery& hotfixQuery);
+
void HandleMoveWorldportAckOpcode(WorldPackets::Movement::WorldPortResponse& packet);
void HandleMoveWorldportAck(); // for server-side calls
void HandleSuspendTokenResponse(WorldPackets::Movement::SuspendTokenResponse& suspendTokenResponse);
diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h
index 1a3e4e71b25..14ce250d622 100644
--- a/src/server/game/Server/WorldSocket.h
+++ b/src/server/game/Server/WorldSocket.h
@@ -53,7 +53,7 @@ struct PacketHeader
uint32 Size;
uint16 Command;
- bool IsValidSize() { return Size < 10240; }
+ bool IsValidSize() { return Size < 0x10000; }
bool IsValidOpcode() { return Command < NUM_OPCODE_HANDLERS; }
};
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 6560f3c1d92..08ea6e57195 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1206,6 +1206,18 @@ void World::LoadConfigSettings(bool reload)
TC_LOG_ERROR("server.loading", "ClientCacheVersion can't be negative %d, ignored.", clientCacheId);
}
+ if (int32 hotfixCacheId = sConfigMgr->GetIntDefault("HotfixCacheVersion", 0))
+ {
+ // overwrite DB/old value
+ if (hotfixCacheId > 0)
+ {
+ m_int_configs[CONFIG_HOTFIX_CACHE_VERSION] = hotfixCacheId;
+ TC_LOG_INFO("server.loading", "Hotfix cache version set to: %u", hotfixCacheId);
+ }
+ else
+ TC_LOG_ERROR("server.loading", "HotfixCacheVersion can't be negative %d, ignored.", hotfixCacheId);
+ }
+
m_int_configs[CONFIG_GUILD_NEWS_LOG_COUNT] = sConfigMgr->GetIntDefault("Guild.NewsLogRecordsCount", GUILD_NEWSLOG_MAX_RECORDS);
if (m_int_configs[CONFIG_GUILD_NEWS_LOG_COUNT] > GUILD_NEWSLOG_MAX_RECORDS)
m_int_configs[CONFIG_GUILD_NEWS_LOG_COUNT] = GUILD_NEWSLOG_MAX_RECORDS;
@@ -3380,14 +3392,14 @@ void World::UpdateMaxSessionCounters()
void World::LoadDBVersion()
{
- QueryResult result = WorldDatabase.Query("SELECT db_version, cache_id FROM version LIMIT 1");
- if (result)
+ if (QueryResult result = WorldDatabase.Query("SELECT db_version, cache_id, hotfix_cache_id FROM version LIMIT 1"))
{
Field* fields = result->Fetch();
m_DBVersion = fields[0].GetString();
// will be overwrite by config values if different and non-0
m_int_configs[CONFIG_CLIENTCACHE_VERSION] = fields[1].GetUInt32();
+ m_int_configs[CONFIG_HOTFIX_CACHE_VERSION] = fields[2].GetUInt32();
}
if (m_DBVersion.empty())
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index c6fbe7e47ab..4bab6c0fb3b 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -341,6 +341,7 @@ enum WorldIntConfigs
CONFIG_LOGDB_CLEARINTERVAL,
CONFIG_LOGDB_CLEARTIME,
CONFIG_CLIENTCACHE_VERSION,
+ CONFIG_HOTFIX_CACHE_VERSION,
CONFIG_GUILD_NEWS_LOG_COUNT,
CONFIG_GUILD_EVENT_LOG_COUNT,
CONFIG_GUILD_BANK_EVENT_LOG_COUNT,
diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h
index 49c77735605..df1e32ace59 100644
--- a/src/server/shared/Packets/ByteBuffer.h
+++ b/src/server/shared/Packets/ByteBuffer.h
@@ -67,7 +67,7 @@ class TC_SHARED_API ByteBuffer
_storage.reserve(reserve);
}
- ByteBuffer(ByteBuffer&& buf) : _rpos(buf._rpos), _wpos(buf._wpos),
+ ByteBuffer(ByteBuffer&& buf) noexcept : _rpos(buf._rpos), _wpos(buf._wpos),
_bitpos(buf._bitpos), _curbitval(buf._curbitval), _storage(buf.Move()) { }
ByteBuffer(ByteBuffer const& right) : _rpos(right._rpos), _wpos(right._wpos),
@@ -75,7 +75,7 @@ class TC_SHARED_API ByteBuffer
ByteBuffer(MessageBuffer&& buffer);
- std::vector<uint8>&& Move()
+ std::vector<uint8>&& Move() noexcept
{
_rpos = 0;
_wpos = 0;
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index 7f662a5c954..37af5263fe6 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -1165,6 +1165,14 @@ OffhandCheckAtSpellUnlearn = 1
ClientCacheVersion = 0
#
+# HotfixCacheVersion
+# Description: Hotfix cache version for hotfix cache data reset. Use any value different
+# from DB and not recently been used to trigger client side cache reset.
+# Default: 0 - (Use DB value from world DB version.hotfix_id field)
+
+HotfixCacheVersion = 0
+
+#
# Event.Announce
# Description: Announce events.
# Default: 0 - (Disabled)