TrinityCore
Loading...
Searching...
No Matches
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 "Transport.h"
35#include "World.h"
36
38{
40
41 lookupData.Player = guid;
42
43 lookupData.Data.emplace();
44 if (lookupData.Data->Initialize(guid, player))
45 lookupData.Result = RESPONSE_SUCCESS; // name known
46 else
47 lookupData.Result = RESPONSE_FAILURE; // name unknown
48}
49
51{
53 for (ObjectGuid guid : queryPlayerNames.Players)
54 BuildNameQueryData(guid, response.Players.emplace_back());
55
56 SendPacket(response.Write());
57}
58
63
65{
67 queryTimeResponse.CurrentTime = GameTime::GetSystemTime();
68 SendPacket(queryTimeResponse.Write());
69}
70
73{
74 if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(packet.CreatureID))
75 {
76 TC_LOG_DEBUG("network", "WORLD: CMSG_QUERY_CREATURE '{}' - Entry: {}.", ci->Name, packet.CreatureID);
77
78 Difficulty difficulty = _player->GetMap()->GetDifficultyID();
79
80 // Cache only exists for difficulty base
81 if (ci->QueryData && difficulty == DIFFICULTY_NONE)
82 SendPacket(&ci->QueryData[static_cast<uint32>(GetSessionDbLocaleIndex())]);
83 else
84 {
85 WorldPacket response = ci->BuildQueryData(GetSessionDbLocaleIndex(), difficulty);
86 SendPacket(&response);
87 }
88 TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUERY_CREATURE_RESPONSE");
89 }
90 else
91 {
92 TC_LOG_DEBUG("network", "WORLD: CMSG_QUERY_CREATURE - NO CREATURE INFO! (ENTRY: {})", packet.CreatureID);
93
95 response.CreatureID = packet.CreatureID;
96 SendPacket(response.Write());
97 TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUERY_CREATURE_RESPONSE");
98 }
99}
100
103{
104 if (GameObjectTemplate const* info = sObjectMgr->GetGameObjectTemplate(packet.GameObjectID))
105 {
106 if (info->QueryData)
107 SendPacket(&info->QueryData[static_cast<uint32>(GetSessionDbLocaleIndex())]);
108 else
109 {
110 WorldPacket response = info->BuildQueryData(GetSessionDbLocaleIndex());
111 SendPacket(&response);
112 }
113 TC_LOG_DEBUG("network", "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE");
114 }
115 else
116 {
117 TC_LOG_DEBUG("network", "WORLD: CMSG_GAMEOBJECT_QUERY - Missing gameobject info for (ENTRY: {})", packet.GameObjectID);
118
120 response.GameObjectID = packet.GameObjectID;
121 response.Guid = packet.Guid;
122 SendPacket(response.Write());
123 TC_LOG_DEBUG("network", "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE");
124 }
125}
126
128{
129 Player* player = ObjectAccessor::FindConnectedPlayer(queryCorpseLocation.Player);
130 if (!player || !player->HasCorpse() || !_player->IsInSameRaidWith(player))
131 {
133 packet.Valid = false; // corpse not found
134 packet.Player = queryCorpseLocation.Player;
135 SendPacket(packet.Write());
136 return;
137 }
138
139 WorldLocation corpseLocation = player->GetCorpseLocation();
140 uint32 corpseMapID = corpseLocation.GetMapId();
141 uint32 mapID = corpseLocation.GetMapId();
142 float x = corpseLocation.GetPositionX();
143 float y = corpseLocation.GetPositionY();
144 float z = corpseLocation.GetPositionZ();
145
146 // if corpse at different map
147 if (mapID != player->GetMapId())
148 {
149 // search entrance map for proper show entrance
150 if (MapEntry const* corpseMapEntry = sMapStore.LookupEntry(mapID))
151 {
152 if (corpseMapEntry->IsDungeon() && corpseMapEntry->CorpseMapID >= 0)
153 {
154 // if corpse map have entrance
155 if (std::shared_ptr<TerrainInfo> entranceTerrain = sTerrainMgr.LoadTerrain(corpseMapEntry->CorpseMapID))
156 {
157 mapID = corpseMapEntry->CorpseMapID;
158 x = corpseMapEntry->Corpse.X;
159 y = corpseMapEntry->Corpse.Y;
160 z = entranceTerrain->GetStaticHeight(player->GetPhaseShift(), mapID, x, y, MAX_HEIGHT);
161 }
162 }
163 }
164 }
165
167 packet.Valid = true;
168 packet.Player = queryCorpseLocation.Player;
169 packet.MapID = corpseMapID;
170 packet.ActualMapID = mapID;
171 packet.Position = Position(x, y, z);
172 packet.Transport = ObjectGuid::Empty; // TODO: If corpse is on transport, send transport offsets and transport guid
173 SendPacket(packet.Write());
174}
175
177{
178 TC_LOG_DEBUG("network", "WORLD: CMSG_NPC_TEXT_QUERY TextId: {}", packet.TextID);
179
180 NpcText const* npcText = sObjectMgr->GetNpcText(packet.TextID);
181
183 response.TextID = packet.TextID;
184
185 if (npcText)
186 {
187 for (uint8 i = 0; i < MAX_NPC_TEXT_OPTIONS; ++i)
188 {
189 response.Probabilities[i] = npcText->Data[i].Probability;
190 response.BroadcastTextID[i] = npcText->Data[i].BroadcastTextID;
191 if (!response.Allow && npcText->Data[i].BroadcastTextID)
192 response.Allow = true;
193 }
194 }
195
196 if (!response.Allow)
197 TC_LOG_ERROR("sql.sql", "HandleNpcTextQueryOpcode: no BroadcastTextID found for text {} in `npc_text table`", packet.TextID);
198
199 SendPacket(response.Write());
200}
201
204{
206 response.PageTextID = packet.PageTextID;
207
208 uint32 pageID = packet.PageTextID;
209 while (pageID)
210 {
211 PageText const* pageText = sObjectMgr->GetPageText(pageID);
212 if (!pageText)
213 break;
214
216 page.ID = pageID;
217 page.NextPageID = pageText->NextPageID;
218 page.Text = pageText->Text;
219 page.PlayerConditionID = pageText->PlayerConditionID;
220 page.Flags = pageText->Flags;
221
223 if (locale != LOCALE_enUS)
224 if (PageTextLocale const* pageTextLocale = sObjectMgr->GetPageTextLocale(pageID))
225 ObjectMgr::GetLocaleString(pageTextLocale->Text, locale, page.Text);
226
227 response.Pages.push_back(page);
228 pageID = pageText->NextPageID;
229 }
230
231 response.Allow = !response.Pages.empty();
232
233 SendPacket(response.Write());
234}
235
237{
239 response.Player = queryCorpseTransport.Player;
240 if (Player* player = ObjectAccessor::FindConnectedPlayer(queryCorpseTransport.Player); player && _player->IsInSameRaidWith(player))
241 {
242 if (Corpse const* corpse = _player->GetCorpse())
243 {
244 if (Transport const* transport = dynamic_cast<Transport const*>(corpse->GetTransport()))
245 {
246 if (transport->GetGUID() == queryCorpseTransport.Transport)
247 {
248 response.Position = transport->GetPosition();
249 response.Facing = transport->GetOrientation();
250 }
251 }
252 }
253 }
254
255 SendPacket(response.Write());
256}
257
259{
261
262 for (int32& questID : queryQuestCompletionNPCs.QuestCompletionNPCs)
263 {
265
266 if (!sObjectMgr->GetQuestTemplate(questID))
267 {
268 TC_LOG_DEBUG("network", "WORLD: Unknown quest {} in CMSG_QUERY_QUEST_COMPLETION_NPCS by {}", questID, _player->GetGUID().ToString());
269 continue;
270 }
271
272 questCompletionNPC.QuestID = questID;
273
274 for (auto const& creatures : sObjectMgr->GetCreatureQuestInvolvedRelationReverseBounds(questID))
275 questCompletionNPC.NPCs.push_back(creatures.second);
276
277 for (auto const& gos : sObjectMgr->GetGOQuestInvolvedRelationReverseBounds(questID))
278 questCompletionNPC.NPCs.push_back(gos.second | 0x80000000); // GO mask
279
280 response.QuestCompletionNPCs.push_back(std::move(questCompletionNPC));
281 }
282
283 SendPacket(response.Write());
284}
285
287{
288 if (questPoiQuery.MissingQuestCount > MAX_QUEST_LOG_SIZE)
289 return;
290
291 // Read quest ids and add the in a unordered_set so we don't send POIs for the same quest multiple times
292 std::unordered_set<int32> questIds;
293 for (int32 i = 0; i < questPoiQuery.MissingQuestCount; ++i)
294 questIds.insert(questPoiQuery.MissingQuestPOIs[i]); // QuestID
295
297
298 for (uint32 questId : questIds)
300 if (QuestPOIData const* poiData = sObjectMgr->GetQuestPOIData(questId))
301 response.QuestPOIDataStats.push_back(poiData);
302
303 SendPacket(response.Write());
304}
305
312{
313 WorldPackets::Query::QueryItemTextResponse queryItemTextResponse;
314 queryItemTextResponse.Id = itemTextQuery.Id;
315
316 if (Item* item = _player->GetItemByGuid(itemTextQuery.Id))
317 {
318 queryItemTextResponse.Valid = true;
319 queryItemTextResponse.Item.Text = item->GetText();
320 }
321
322 SendPacket(queryItemTextResponse.Write());
323}
324
326{
328 realmQueryResponse.VirtualRealmAddress = queryRealmName.VirtualRealmAddress;
329
330 if (std::shared_ptr<Realm const> realm = sRealmList->GetRealm(queryRealmName.VirtualRealmAddress))
331 {
332 realmQueryResponse.LookupState = RESPONSE_SUCCESS;
333 realmQueryResponse.NameInfo.IsInternalRealm = false;
334 realmQueryResponse.NameInfo.IsLocal = queryRealmName.VirtualRealmAddress == GetVirtualRealmAddress();
335 realmQueryResponse.NameInfo.RealmNameActual = realm->Name;
336 realmQueryResponse.NameInfo.RealmNameNormalized = realm->NormalizedName;
337 }
338 else
339 realmQueryResponse.LookupState = RESPONSE_FAILURE;
340
341 SendPacket(realmQueryResponse.Write());
342}
343
345{
346 Quest const* questInfo = sObjectMgr->GetQuestTemplate(queryTreasurePicker.QuestID);
347 if (!questInfo)
348 return;
349
350 WorldPackets::Query::TreasurePickerResponse treasurePickerResponse;
351 treasurePickerResponse.QuestID = queryTreasurePicker.QuestID;
352 treasurePickerResponse.TreasurePickerID = queryTreasurePicker.TreasurePickerID;
353
354 // TODO: Missing treasure picker implementation
355
356 SendPacket(treasurePickerResponse.Write());
357}
LocaleConstant
Definition Common.h:51
@ LOCALE_enUS
Definition Common.h:52
DB2Storage< MapEntry > sMapStore("Map.db2", &MapLoadInfo::Instance)
Difficulty
Definition DBCEnums.h:932
@ DIFFICULTY_NONE
Definition DBCEnums.h:933
uint8_t uint8
Definition Define.h:156
int32_t int32
Definition Define.h:150
uint32_t uint32
Definition Define.h:154
#define MAX_HEIGHT
Definition GridDefines.h:60
#define TC_LOG_DEBUG(filterType__, message__,...)
Definition Log.h:181
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:190
#define MAX_NPC_TEXT_OPTIONS
Definition NPCHandler.h:27
#define sObjectMgr
Definition ObjectMgr.h:1885
#define MAX_QUEST_LOG_SIZE
Definition QuestDef.h:46
#define sRealmList
Definition RealmList.h:93
@ RESPONSE_FAILURE
@ RESPONSE_SUCCESS
#define sTerrainMgr
Definition TerrainMgr.h:167
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
Definition Item.h:179
Difficulty GetDifficultyID() const
Definition Map.h:360
static ObjectGuid const Empty
Definition ObjectGuid.h:314
std::string ToString() const
static std::string_view GetLocaleString(std::vector< std::string > const &data, LocaleConstant locale)
Definition ObjectMgr.h:1611
WorldLocation const & GetCorpseLocation() const
Definition Player.h:2338
bool IsInSameRaidWith(Player const *p) const
Definition Player.cpp:2149
uint16 FindQuestSlot(uint32 quest_id) const
Definition Player.cpp:16383
bool HasCorpse() const
Definition Player.h:2337
Corpse * GetCorpse() const
Definition Player.cpp:4562
Item * GetItemByGuid(ObjectGuid guid) const
Definition Player.cpp:9614
constexpr uint32 GetMapId() const
Definition Position.h:216
Map * GetMap() const
Definition Object.h:411
PhaseShift & GetPhaseShift()
Definition Object.h:310
WorldPacket const * Write() override
TaggedPosition<::Position::XYZ > Position
TaggedPosition<::Position::XYZ > Position
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
std::array< float, MAX_NPC_TEXT_OPTIONS > Probabilities
std::array< uint32, MAX_NPC_TEXT_OPTIONS > BroadcastTextID
WorldPacket const * Write() override
std::vector< NameCacheLookupResult > Players
WorldPacket const * Write() override
std::vector< QuestCompletionNPC > QuestCompletionNPCs
WorldPacket const * Write() override
std::vector< QuestPOIData const * > QuestPOIDataStats
std::array< int32, 175 > MissingQuestPOIs
WorldPackets::Auth::VirtualRealmNameInfo NameInfo
WorldPacket const * Write() override
WorldPacket const * Write() override
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 HandleQueryTreasurePicker(WorldPackets::Query::QueryTreasurePicker const &queryTreasurePicker)
void HandleQueryCorpseLocation(WorldPackets::Query::QueryCorpseLocationFromClient &packet)
uint32 GetVirtualRealmAddress()
Definition World.cpp:3526
SystemTimePoint GetSystemTime()
Current chrono system_clock time point.
Definition GameTime.cpp:62
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:67
std::string Text
Definition ObjectMgr.h:64
uint32 NextPageID
Definition ObjectMgr.h:65
int32 PlayerConditionID
Definition ObjectMgr.h:66
constexpr float GetPositionX() const
Definition Position.h:87
constexpr float GetPositionY() const
Definition Position.h:88
constexpr float GetPositionZ() const
Definition Position.h:89
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