TrinityCore
QueryHandler.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "WorldSession.h"
19#include "Common.h"
20#include "Corpse.h"
21#include "DatabaseEnv.h"
22#include "DB2Stores.h"
23#include "GameTime.h"
24#include "Item.h"
25#include "Log.h"
26#include "Map.h"
27#include "NPCHandler.h"
28#include "ObjectAccessor.h"
29#include "ObjectMgr.h"
30#include "Player.h"
31#include "QueryPackets.h"
32#include "RealmList.h"
33#include "TerrainMgr.h"
34#include "World.h"
35
37{
39
40 lookupData.Player = guid;
41
42 lookupData.Data.emplace();
43 if (lookupData.Data->Initialize(guid, player))
44 lookupData.Result = RESPONSE_SUCCESS; // name known
45 else
46 lookupData.Result = RESPONSE_FAILURE; // name unknown
47}
48
50{
52 for (ObjectGuid guid : queryPlayerNames.Players)
53 BuildNameQueryData(guid, response.Players.emplace_back());
54
55 SendPacket(response.Write());
56}
57
59{
61}
62
64{
66 queryTimeResponse.CurrentTime = GameTime::GetSystemTime();
67 SendPacket(queryTimeResponse.Write());
68}
69
72{
73 if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(packet.CreatureID))
74 {
75 TC_LOG_DEBUG("network", "WORLD: CMSG_QUERY_CREATURE '{}' - Entry: {}.", ci->Name, packet.CreatureID);
76
77 Difficulty difficulty = _player->GetMap()->GetDifficultyID();
78
79 // Cache only exists for difficulty base
80 if (sWorld->getBoolConfig(CONFIG_CACHE_DATA_QUERIES) && difficulty == DIFFICULTY_NONE)
81 SendPacket(&ci->QueryData[static_cast<uint32>(GetSessionDbLocaleIndex())]);
82 else
83 {
84 WorldPacket response = ci->BuildQueryData(GetSessionDbLocaleIndex(), difficulty);
85 SendPacket(&response);
86 }
87 TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUERY_CREATURE_RESPONSE");
88 }
89 else
90 {
91 TC_LOG_DEBUG("network", "WORLD: CMSG_QUERY_CREATURE - NO CREATURE INFO! (ENTRY: {})", packet.CreatureID);
92
94 response.CreatureID = packet.CreatureID;
95 SendPacket(response.Write());
96 TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUERY_CREATURE_RESPONSE");
97 }
98}
99
102{
103 if (GameObjectTemplate const* info = sObjectMgr->GetGameObjectTemplate(packet.GameObjectID))
104 {
105 if (sWorld->getBoolConfig(CONFIG_CACHE_DATA_QUERIES))
106 SendPacket(&info->QueryData[static_cast<uint32>(GetSessionDbLocaleIndex())]);
107 else
108 {
109 WorldPacket response = info->BuildQueryData(GetSessionDbLocaleIndex());
110 SendPacket(&response);
111 }
112 TC_LOG_DEBUG("network", "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE");
113 }
114 else
115 {
116 TC_LOG_DEBUG("network", "WORLD: CMSG_GAMEOBJECT_QUERY - Missing gameobject info for (ENTRY: {})", packet.GameObjectID);
117
119 response.GameObjectID = packet.GameObjectID;
120 response.Guid = packet.Guid;
121 SendPacket(response.Write());
122 TC_LOG_DEBUG("network", "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE");
123 }
124}
125
127{
128 Player* player = ObjectAccessor::FindConnectedPlayer(queryCorpseLocation.Player);
129 if (!player || !player->HasCorpse() || !_player->IsInSameRaidWith(player))
130 {
132 packet.Valid = false; // corpse not found
133 packet.Player = queryCorpseLocation.Player;
134 SendPacket(packet.Write());
135 return;
136 }
137
138 WorldLocation corpseLocation = player->GetCorpseLocation();
139 uint32 corpseMapID = corpseLocation.GetMapId();
140 uint32 mapID = corpseLocation.GetMapId();
141 float x = corpseLocation.GetPositionX();
142 float y = corpseLocation.GetPositionY();
143 float z = corpseLocation.GetPositionZ();
144
145 // if corpse at different map
146 if (mapID != player->GetMapId())
147 {
148 // search entrance map for proper show entrance
149 if (MapEntry const* corpseMapEntry = sMapStore.LookupEntry(mapID))
150 {
151 if (corpseMapEntry->IsDungeon() && corpseMapEntry->CorpseMapID >= 0)
152 {
153 // if corpse map have entrance
154 if (std::shared_ptr<TerrainInfo> entranceTerrain = sTerrainMgr.LoadTerrain(corpseMapEntry->CorpseMapID))
155 {
156 mapID = corpseMapEntry->CorpseMapID;
157 x = corpseMapEntry->Corpse.X;
158 y = corpseMapEntry->Corpse.Y;
159 z = entranceTerrain->GetStaticHeight(player->GetPhaseShift(), mapID, x, y, MAX_HEIGHT);
160 }
161 }
162 }
163 }
164
166 packet.Valid = true;
167 packet.Player = queryCorpseLocation.Player;
168 packet.MapID = corpseMapID;
169 packet.ActualMapID = mapID;
170 packet.Position = Position(x, y, z);
172 SendPacket(packet.Write());
173}
174
176{
177 TC_LOG_DEBUG("network", "WORLD: CMSG_NPC_TEXT_QUERY TextId: {}", packet.TextID);
178
179 NpcText const* npcText = sObjectMgr->GetNpcText(packet.TextID);
180
182 response.TextID = packet.TextID;
183
184 if (npcText)
185 {
186 for (uint8 i = 0; i < MAX_NPC_TEXT_OPTIONS; ++i)
187 {
188 response.Probabilities[i] = npcText->Data[i].Probability;
189 response.BroadcastTextID[i] = npcText->Data[i].BroadcastTextID;
190 if (!response.Allow && npcText->Data[i].BroadcastTextID)
191 response.Allow = true;
192 }
193 }
194
195 if (!response.Allow)
196 TC_LOG_ERROR("sql.sql", "HandleNpcTextQueryOpcode: no BroadcastTextID found for text {} in `npc_text table`", packet.TextID);
197
198 SendPacket(response.Write());
199}
200
203{
205 response.PageTextID = packet.PageTextID;
206
207 uint32 pageID = packet.PageTextID;
208 while (pageID)
209 {
210 PageText const* pageText = sObjectMgr->GetPageText(pageID);
211 if (!pageText)
212 break;
213
215 page.ID = pageID;
216 page.NextPageID = pageText->NextPageID;
217 page.Text = pageText->Text;
218 page.PlayerConditionID = pageText->PlayerConditionID;
219 page.Flags = pageText->Flags;
220
222 if (locale != LOCALE_enUS)
223 if (PageTextLocale const* pageTextLocale = sObjectMgr->GetPageTextLocale(pageID))
224 ObjectMgr::GetLocaleString(pageTextLocale->Text, locale, page.Text);
225
226 response.Pages.push_back(page);
227 pageID = pageText->NextPageID;
228 }
229
230 response.Allow = !response.Pages.empty();
231
232 SendPacket(response.Write());
233}
234
236{
238 response.Player = queryCorpseTransport.Player;
239 if (Player* player = ObjectAccessor::FindConnectedPlayer(queryCorpseTransport.Player))
240 {
241 Corpse* corpse = player->GetCorpse();
242 if (_player->IsInSameRaidWith(player) && corpse && !corpse->GetTransGUID().IsEmpty() && corpse->GetTransGUID() == queryCorpseTransport.Transport)
243 {
244 response.Position = corpse->GetTransOffset();
245 response.Facing = corpse->GetTransOffsetO();
246 }
247 }
248
249 SendPacket(response.Write());
250}
251
253{
255
256 for (int32& questID : queryQuestCompletionNPCs.QuestCompletionNPCs)
257 {
259
260 if (!sObjectMgr->GetQuestTemplate(questID))
261 {
262 TC_LOG_DEBUG("network", "WORLD: Unknown quest {} in CMSG_QUERY_QUEST_COMPLETION_NPCS by {}", questID, _player->GetGUID().ToString());
263 continue;
264 }
265
266 questCompletionNPC.QuestID = questID;
267
268 for (auto const& creatures : sObjectMgr->GetCreatureQuestInvolvedRelationReverseBounds(questID))
269 questCompletionNPC.NPCs.push_back(creatures.second);
270
271 for (auto const& gos : sObjectMgr->GetGOQuestInvolvedRelationReverseBounds(questID))
272 questCompletionNPC.NPCs.push_back(gos.second | 0x80000000); // GO mask
273
274 response.QuestCompletionNPCs.push_back(std::move(questCompletionNPC));
275 }
276
277 SendPacket(response.Write());
278}
279
281{
282 if (questPoiQuery.MissingQuestCount > MAX_QUEST_LOG_SIZE)
283 return;
284
285 // Read quest ids and add the in a unordered_set so we don't send POIs for the same quest multiple times
286 std::unordered_set<int32> questIds;
287 for (int32 i = 0; i < questPoiQuery.MissingQuestCount; ++i)
288 questIds.insert(questPoiQuery.MissingQuestPOIs[i]); // QuestID
289
291
292 for (uint32 questId : questIds)
294 if (QuestPOIData const* poiData = sObjectMgr->GetQuestPOIData(questId))
295 response.QuestPOIDataStats.push_back(poiData);
296
297 SendPacket(response.Write());
298}
299
306{
307 WorldPackets::Query::QueryItemTextResponse queryItemTextResponse;
308 queryItemTextResponse.Id = itemTextQuery.Id;
309
310 if (Item* item = _player->GetItemByGuid(itemTextQuery.Id))
311 {
312 queryItemTextResponse.Valid = true;
313 queryItemTextResponse.Item.Text = item->GetText();
314 }
315
316 SendPacket(queryItemTextResponse.Write());
317}
318
320{
322 realmQueryResponse.VirtualRealmAddress = queryRealmName.VirtualRealmAddress;
323
324 Battlenet::RealmHandle realmHandle(queryRealmName.VirtualRealmAddress);
325 if (sRealmList->GetRealmNames(realmHandle, &realmQueryResponse.NameInfo.RealmNameActual, &realmQueryResponse.NameInfo.RealmNameNormalized))
326 {
327 realmQueryResponse.LookupState = RESPONSE_SUCCESS;
328 realmQueryResponse.NameInfo.IsInternalRealm = false;
329 realmQueryResponse.NameInfo.IsLocal = queryRealmName.VirtualRealmAddress == GetVirtualRealmAddress();
330 }
331 else
332 realmQueryResponse.LookupState = RESPONSE_FAILURE;
333}
LocaleConstant
Definition: Common.h:48
@ LOCALE_enUS
Definition: Common.h:49
DB2Storage< MapEntry > sMapStore("Map.db2", &MapLoadInfo::Instance)
Difficulty
Definition: DBCEnums.h:873
@ DIFFICULTY_NONE
Definition: DBCEnums.h:874
uint8_t uint8
Definition: Define.h:144
int32_t int32
Definition: Define.h:138
uint32_t uint32
Definition: Define.h:142
#define MAX_HEIGHT
Definition: GridDefines.h:60
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
#define MAX_NPC_TEXT_OPTIONS
Definition: NPCHandler.h:27
#define sObjectMgr
Definition: ObjectMgr.h:1946
#define MAX_QUEST_LOG_SIZE
Definition: QuestDef.h:44
#define sRealmList
Definition: RealmList.h:96
@ RESPONSE_FAILURE
@ RESPONSE_SUCCESS
#define sTerrainMgr
Definition: TerrainMgr.h:165
Definition: Corpse.h:53
Definition: Item.h:170
Difficulty GetDifficultyID() const
Definition: Map.h:324
static ObjectGuid const Empty
Definition: ObjectGuid.h:274
bool IsEmpty() const
Definition: ObjectGuid.h:319
std::string ToString() const
Definition: ObjectGuid.cpp:554
static std::string_view GetLocaleString(std::vector< std::string > const &data, LocaleConstant locale)
Definition: ObjectMgr.h:1682
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
bool IsInSameRaidWith(Player const *p) const
Definition: Player.cpp:2160
uint16 FindQuestSlot(uint32 quest_id) const
Definition: Player.cpp:16432
bool HasCorpse() const
Definition: Player.h:2163
WorldLocation GetCorpseLocation() const
Definition: Player.h:2164
Item * GetItemByGuid(ObjectGuid guid) const
Definition: Player.cpp:9566
constexpr uint32 GetMapId() const
Definition: Position.h:201
Map * GetMap() const
Definition: Object.h:624
Position const & GetTransOffset() const
Definition: Object.h:755
PhaseShift & GetPhaseShift()
Definition: Object.h:523
virtual ObjectGuid GetTransGUID() const
Definition: Object.cpp:3748
float GetTransOffsetO() const
Definition: Object.h:754
WorldPacket const * Write() override
TaggedPosition<::Position::XYZ > Position
Definition: QueryPackets.h:275
TaggedPosition<::Position::XYZ > Position
Definition: QueryPackets.h:300
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
std::array< float, MAX_NPC_TEXT_OPTIONS > Probabilities
Definition: QueryPackets.h:214
std::array< uint32, MAX_NPC_TEXT_OPTIONS > BroadcastTextID
Definition: QueryPackets.h:215
std::vector< PageTextInfo > Pages
Definition: QueryPackets.h:191
WorldPacket const * Write() override
std::vector< NameCacheLookupResult > Players
Definition: QueryPackets.h:159
WorldPacket const * Write() override
Array< ObjectGuid, 50 > Players
Definition: QueryPackets.h:115
WorldPacket const * Write() override
std::vector< QuestCompletionNPC > QuestCompletionNPCs
Definition: QueryPackets.h:366
WorldPacket const * Write() override
std::vector< QuestPOIData const * > QuestPOIDataStats
Definition: QueryPackets.h:340
std::array< int32, 175 > MissingQuestPOIs
Definition: QueryPackets.h:330
WorldPackets::Auth::VirtualRealmNameInfo NameInfo
Definition: QueryPackets.h:441
void HandleQueryCorpseTransport(WorldPackets::Query::QueryCorpseTransport &packet)
void HandleCreatureQuery(WorldPackets::Query::QueryCreature &packet)
Only static data is sent in this packet !!!
void HandleQueryPageText(WorldPackets::Query::QueryPageText &packet)
Only static data is sent in this packet !!!
void HandleQueryQuestCompletionNPCs(WorldPackets::Query::QueryQuestCompletionNPCs &queryQuestCompletionNPCs)
LocaleConstant GetSessionDbLocaleIndex() const
void HandleItemTextQuery(WorldPackets::Query::ItemTextQuery &itemTextQuery)
void BuildNameQueryData(ObjectGuid guid, WorldPackets::Query::NameCacheLookupResult &lookupData)
void HandleGameObjectQueryOpcode(WorldPackets::Query::QueryGameObject &packet)
Only static data is sent in this packet !!!
void HandleNpcTextQueryOpcode(WorldPackets::Query::QueryNPCText &packet)
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
void HandleQueryPlayerNames(WorldPackets::Query::QueryPlayerNames &queryPlayerNames)
Player * _player
void HandleQueryRealmName(WorldPackets::Query::QueryRealmName &queryRealmName)
void HandleQuestPOIQuery(WorldPackets::Query::QuestPOIQuery &questPoiQuery)
void HandleQueryTimeOpcode(WorldPackets::Query::QueryTime &queryTime)
void SendQueryTimeResponse()
void HandleQueryCorpseLocation(WorldPackets::Query::QueryCorpseLocationFromClient &packet)
#define sWorld
Definition: World.h:931
uint32 GetVirtualRealmAddress()
Definition: World.cpp:3968
@ CONFIG_CACHE_DATA_QUERIES
Definition: World.h:191
SystemTimePoint GetSystemTime()
Current chrono system_clock time point.
Definition: GameTime.cpp:54
TC_GAME_API Player * FindConnectedPlayer(ObjectGuid const &)
float Probability
Definition: NPCHandler.h:23
uint32 BroadcastTextID
Definition: NPCHandler.h:24
NpcTextData Data[MAX_NPC_TEXT_OPTIONS]
Definition: NPCHandler.h:31
uint8 Flags
Definition: ObjectMgr.h:63
std::string Text
Definition: ObjectMgr.h:60
uint32 NextPageID
Definition: ObjectMgr.h:61
int32 PlayerConditionID
Definition: ObjectMgr.h:62
constexpr float GetPositionX() const
Definition: Position.h:76
constexpr float GetPositionY() const
Definition: Position.h:77
constexpr float GetPositionZ() const
Definition: Position.h:78
std::string RealmNameActual
the name of the realm
std::string RealmNameNormalized
the name of the realm without spaces
bool IsLocal
true if the realm is the same as the account's home realm
Optional< PlayerGuidLookupData > Data
Definition: QueryPackets.h:148