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 "CharacterCache.h"
20#include "Common.h"
21#include "Corpse.h"
22#include "DatabaseEnv.h"
23#include "DBCStores.h"
24#include "GameTime.h"
25#include "Log.h"
26#include "MapManager.h"
27#include "NPCHandler.h"
28#include "ObjectAccessor.h"
29#include "ObjectMgr.h"
30#include "Player.h"
31#include "QueryPackets.h"
32#include "Transport.h"
33#include "UpdateMask.h"
34#include "World.h"
35
37{
39 response.Player = guid;
40
41 if (CharacterCacheEntry const* characterInfo = sCharacterCache->GetCharacterCacheByGuid(guid))
42 {
43 response.Result = RESPONSE_SUCCESS; // name known
44
45 WorldPackets::Query::PlayerGuidLookupData& data = response.Data.emplace();
46 data.Name = characterInfo->Name;
47 data.Race = characterInfo->Race;
48 data.Sex = characterInfo->Sex;
49 data.ClassID = characterInfo->Class;
50
52 data.DeclinedNames = player->GetDeclinedNames();
53 }
54 else
55 response.Result = RESPONSE_FAILURE; // name unknown
56
57 SendPacket(response.Write());
58}
59
64
69
71{
74 data << uint32(sWorld->GetNextDailyQuestsResetTime() - GameTime::GetGameTime());
75 SendPacket(&data);
76}
77
80{
81 if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(query.CreatureID))
82 {
83 TC_LOG_DEBUG("network", "WORLD: CMSG_CREATURE_QUERY '{}' - Entry: {}.", ci->Name, query.CreatureID);
84 if (sWorld->getBoolConfig(CONFIG_CACHE_DATA_QUERIES))
85 SendPacket(&ci->QueryData[static_cast<uint32>(GetSessionDbLocaleIndex())]);
86 else
87 {
88 WorldPacket response = ci->BuildQueryData(GetSessionDbLocaleIndex());
89 SendPacket(&response);
90 }
91 TC_LOG_DEBUG("network", "WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE");
92 }
93 else
94 {
95 TC_LOG_DEBUG("network", "WORLD: CMSG_CREATURE_QUERY - NO CREATURE INFO! ({}, ENTRY: {})",
96 query.Guid.ToString(), query.CreatureID);
97
99 response.CreatureID = query.CreatureID;
100 SendPacket(response.Write());
101 TC_LOG_DEBUG("network", "WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE");
102 }
103}
104
107{
108 if (GameObjectTemplate const* info = sObjectMgr->GetGameObjectTemplate(query.GameObjectID))
109 {
110 if (sWorld->getBoolConfig(CONFIG_CACHE_DATA_QUERIES))
111 SendPacket(&info->QueryData[static_cast<uint32>(GetSessionDbLocaleIndex())]);
112 else
113 {
114 WorldPacket response = info->BuildQueryData(GetSessionDbLocaleIndex());
115 SendPacket(&response);
116 }
117 TC_LOG_DEBUG("network", "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE");
118 }
119 else
120 {
121 TC_LOG_DEBUG("network", "WORLD: CMSG_GAMEOBJECT_QUERY - Missing gameobject info for ({}, ENTRY: {})",
122 query.Guid.ToString(), query.GameObjectID);
123
125 response.GameObjectID = query.GameObjectID;
126 SendPacket(response.Write());
127 TC_LOG_DEBUG("network", "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE");
128 }
129}
130
132{
133 if (!_player->HasCorpse())
134 {
136 packet.Valid = false; // corpse not found
137 SendPacket(packet.Write());
138 return;
139 }
140
141 WorldLocation corpseLocation = _player->GetCorpseLocation();
142 uint32 corpseMapID = corpseLocation.GetMapId();
143 uint32 mapID = corpseLocation.GetMapId();
144 float x = corpseLocation.GetPositionX();
145 float y = corpseLocation.GetPositionY();
146 float z = corpseLocation.GetPositionZ();
147
148 // if corpse at different map
149 if (mapID != _player->GetMapId())
150 {
151 // search entrance map for proper show entrance
152 if (MapEntry const* corpseMapEntry = sMapStore.LookupEntry(mapID))
153 {
154 if (corpseMapEntry->IsDungeon() && corpseMapEntry->CorpseMapID >= 0)
155 {
156 // if corpse map have entrance
157 if (Map const* entranceMap = sMapMgr->CreateBaseMap(corpseMapEntry->CorpseMapID))
158 {
159 mapID = corpseMapEntry->CorpseMapID;
160 x = corpseMapEntry->Corpse.X;
161 y = corpseMapEntry->Corpse.Y;
162 z = entranceMap->GetHeight(GetPlayer()->GetPhaseMask(), x, y, MAX_HEIGHT);
163 }
164 }
165 }
166 }
167
169 packet.Valid = true;
170 packet.MapID = corpseMapID;
171 packet.ActualMapID = mapID;
172 packet.Position = Position(x, y, z);
173 packet.Transport = 0; // TODO: If corpse is on transport, send transport offsets and transport guid
174 SendPacket(packet.Write());
175}
176
178{
179 uint32 textID;
180 uint64 guid;
181
182 recvData >> textID;
183 TC_LOG_DEBUG("network", "WORLD: CMSG_NPC_TEXT_QUERY TextId: {}", textID);
184
185 recvData >> guid;
186
187 GossipText const* gossip = sObjectMgr->GetGossipText(textID);
188
189 WorldPacket data(SMSG_NPC_TEXT_UPDATE, 100); // guess size
190 data << textID;
191
192 if (!gossip)
193 {
194 for (uint8 i = 0; i < MAX_GOSSIP_TEXT_OPTIONS; ++i)
195 {
196 data << float(0);
197 data << "Greetings $N";
198 data << "Greetings $N";
199 data << uint32(0);
200 data << uint32(0);
201 data << uint32(0);
202 data << uint32(0);
203 data << uint32(0);
204 data << uint32(0);
205 data << uint32(0);
206 }
207 }
208 else
209 {
210 std::string text0[MAX_GOSSIP_TEXT_OPTIONS], text1[MAX_GOSSIP_TEXT_OPTIONS];
212
213 for (uint8 i = 0; i < MAX_GOSSIP_TEXT_OPTIONS; ++i)
214 {
215 BroadcastText const* bct = sObjectMgr->GetBroadcastText(gossip->Options[i].BroadcastTextID);
216 if (bct)
217 {
218 text0[i] = bct->GetText(locale, GENDER_MALE, true);
219 text1[i] = bct->GetText(locale, GENDER_FEMALE, true);
220 }
221 else
222 {
223 text0[i] = gossip->Options[i].Text_0;
224 text1[i] = gossip->Options[i].Text_1;
225 }
226
227 if (locale != DEFAULT_LOCALE && !bct)
228 {
229 if (NpcTextLocale const* npcTextLocale = sObjectMgr->GetNpcTextLocale(textID))
230 {
231 ObjectMgr::GetLocaleString(npcTextLocale->Text_0[i], locale, text0[i]);
232 ObjectMgr::GetLocaleString(npcTextLocale->Text_1[i], locale, text1[i]);
233 }
234 }
235
236 data << gossip->Options[i].Probability;
237
238 if (text0[i].empty())
239 data << text1[i];
240 else
241 data << text0[i];
242
243 if (text1[i].empty())
244 data << text0[i];
245 else
246 data << text1[i];
247
248 data << gossip->Options[i].Language;
249
250 for (uint8 j = 0; j < MAX_GOSSIP_TEXT_EMOTES; ++j)
251 {
252 data << gossip->Options[i].Emotes[j]._Delay;
253 data << gossip->Options[i].Emotes[j]._Emote;
254 }
255 }
256 }
257
258 SendPacket(&data);
259}
260
263{
264 TC_LOG_DEBUG("network", "WORLD: Received CMSG_PAGE_TEXT_QUERY");
265
266 uint32 pageID;
267 recvData >> pageID;
268 recvData.read_skip<uint64>(); // guid
269
270 while (pageID)
271 {
272 PageText const* pageText = sObjectMgr->GetPageText(pageID);
273 // guess size
275 data << pageID;
276
277 if (!pageText)
278 {
279 data << "Item page missing.";
280 data << uint32(0);
281 pageID = 0;
282 }
283 else
284 {
285 std::string Text = pageText->Text;
286
287 LocaleConstant localeConstant = GetSessionDbLocaleIndex();
288 if (localeConstant != LOCALE_enUS)
289 if (PageTextLocale const* pageTextLocale = sObjectMgr->GetPageTextLocale(pageID))
290 ObjectMgr::GetLocaleString(pageTextLocale->Text, localeConstant, Text);
291
292 data << Text;
293 data << uint32(pageText->NextPageID);
294 pageID = pageText->NextPageID;
295 }
296 SendPacket(&data);
297
298 TC_LOG_DEBUG("network", "WORLD: Sent SMSG_PAGE_TEXT_QUERY_RESPONSE");
299 }
300}
301
303{
305 if (Corpse const* corpse = _player->GetCorpse())
306 {
307 if (Transport const* transport = corpse->GetTransport())
308 {
309 if (transport->GetGUID().GetCounter() == queryCorpseTransport.Transport)
310 {
311 response.Position = transport->GetPosition();
312 response.Facing = transport->GetOrientation();
313 }
314 }
315 }
316
317 SendPacket(response.Write());
318}
319
321{
323 return;
324
325 // Read quest ids and add the in a unordered_set so we don't send POIs for the same quest multiple times
326 std::unordered_set<uint32> questIds;
327 for (uint32 i = 0; i < query.MissingQuestCount; ++i)
328 questIds.insert(query.MissingQuestPOIs[i]); // quest id
329
330 WorldPacket data(SMSG_QUEST_POI_QUERY_RESPONSE, 4 + (4 + 4 + 40) * questIds.size());
331 data << uint32(questIds.size()); // count
332
333 for (uint32 questId : questIds)
334 {
335 uint16 const questSlot = _player->FindQuestSlot(questId);
336 if (questSlot != MAX_QUEST_LOG_SIZE && _player->GetQuestSlotQuestId(questSlot) == questId)
337 {
338 if (QuestPOIWrapper const* poiWrapper = sObjectMgr->GetQuestPOIWrapper(questId))
339 {
340 if (sWorld->getBoolConfig(CONFIG_CACHE_DATA_QUERIES))
341 data.append(poiWrapper->QueryDataBuffer);
342 else
343 {
344 ByteBuffer POIByteBuffer = poiWrapper->BuildQueryData();
345 data.append(POIByteBuffer);
346 }
347 }
348 else
349 {
350 data << uint32(questId); // quest ID
351 data << uint32(0); // POI count
352 }
353 }
354 else
355 {
356 data << uint32(questId); // quest ID
357 data << uint32(0); // POI count
358 }
359 }
360
361 SendPacket(&data);
362}
#define sCharacterCache
LocaleConstant
Definition Common.h:48
@ LOCALE_enUS
Definition Common.h:49
#define DEFAULT_LOCALE
Definition Common.h:62
DBCStorage< MapEntry > sMapStore(MapEntryfmt)
uint8_t uint8
Definition Define.h:135
uint64_t uint64
Definition Define.h:132
uint16_t uint16
Definition Define.h:134
uint32_t uint32
Definition Define.h:133
#define TC_LOG_DEBUG(filterType__,...)
Definition Log.h:156
#define sMapMgr
Definition MapManager.h:211
#define MAX_HEIGHT
Definition Map.h:240
#define MAX_GOSSIP_TEXT_OPTIONS
Definition NPCHandler.h:39
#define MAX_GOSSIP_TEXT_EMOTES
Definition NPCHandler.h:27
#define sObjectMgr
Definition ObjectMgr.h:1721
#define MAX_QUEST_LOG_SIZE
Definition QuestDef.h:36
@ GENDER_MALE
@ GENDER_FEMALE
@ RESPONSE_FAILURE
@ RESPONSE_SUCCESS
void read_skip()
Definition ByteBuffer.h:330
void append(T value)
Definition ByteBuffer.h:129
Definition Map.h:281
std::string ToString() const
static std::string_view GetLocaleString(std::vector< std::string > const &data, size_t locale)
Definition ObjectMgr.h:1525
WorldLocation const & GetCorpseLocation() const
Definition Player.h:1758
uint16 FindQuestSlot(uint32 quest_id) const
Definition Player.cpp:15935
bool HasCorpse() const
Definition Player.h:1757
uint32 GetQuestSlotQuestId(uint16 slot) const
Definition Player.cpp:15944
Corpse * GetCorpse() const
Definition Player.cpp:4544
uint32 GetMapId() const
Definition Position.h:193
Transport * GetTransport() const
Definition Object.h:564
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
Optional< PlayerGuidLookupData > Data
uint32 MissingQuestPOIs[MAX_QUEST_LOG_SIZE]
void HandleQueryCorpseTransport(WorldPackets::Query::QueryCorpseTransport &packet)
void HandleQuestPOIQuery(WorldPackets::Query::QuestPOIQuery &query)
void SendPacket(WorldPacket const *packet)
Send a packet to the client.
LocaleConstant GetSessionDbLocaleIndex() const
void SendNameQueryOpcode(ObjectGuid guid)
void HandleQueryPageText(WorldPacket &recvPacket)
Only static data is sent in this packet !!!
Player * GetPlayer() const
void HandleNpcTextQueryOpcode(WorldPacket &recvPacket)
void HandleNameQueryOpcode(WorldPackets::Query::QueryPlayerName &queryPlayerName)
void HandleCreatureQueryOpcode(WorldPackets::Query::QueryCreature &query)
Only static data is sent in this packet !!!
Player * _player
void HandleQueryTimeOpcode(WorldPacket &recvPacket)
void HandleGameObjectQueryOpcode(WorldPackets::Query::QueryGameObject &query)
Only static data is sent in this packet !!!
void SendQueryTimeResponse()
void HandleQueryCorpseLocation(WorldPackets::Query::QueryCorpseLocationFromClient &packet)
@ SMSG_PAGE_TEXT_QUERY_RESPONSE
Definition Opcodes.h:120
@ SMSG_NPC_TEXT_UPDATE
Definition Opcodes.h:413
@ SMSG_QUERY_TIME_RESPONSE
Definition Opcodes.h:492
@ SMSG_QUEST_POI_QUERY_RESPONSE
Definition Opcodes.h:513
#define sWorld
Definition World.h:900
@ CONFIG_CACHE_DATA_QUERIES
Definition World.h:176
time_t GetGameTime()
Definition GameTime.cpp:42
TC_GAME_API Player * FindConnectedPlayer(ObjectGuid const &)
std::string const & GetText(LocaleConstant locale=DEFAULT_LOCALE, uint8 gender=GENDER_MALE, bool forceGender=false) const
Definition ObjectMgr.h:496
std::string Text_0
Definition NPCHandler.h:31
QEmote Emotes[MAX_GOSSIP_TEXT_EMOTES]
Definition NPCHandler.h:36
uint32 BroadcastTextID
Definition NPCHandler.h:33
std::string Text_1
Definition NPCHandler.h:32
GossipTextOption Options[MAX_GOSSIP_TEXT_OPTIONS]
Definition NPCHandler.h:43
std::string Text
Definition ObjectMgr.h:60
uint32 NextPageID
Definition ObjectMgr.h:61
float GetPositionZ() const
Definition Position.h:81
float GetPositionX() const
Definition Position.h:79
float GetPositionY() const
Definition Position.h:80
uint32 _Emote
Definition NPCHandler.h:23
uint32 _Delay
Definition NPCHandler.h:24