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{
73 queryTimeResponse.CurrentTime = GameTime::GetGameTime();
74 queryTimeResponse.TimeOutRequest = sWorld->GetNextDailyQuestsResetTime() - queryTimeResponse.CurrentTime;
75 SendPacket(queryTimeResponse.Write());
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 TC_LOG_DEBUG("network", "WORLD: CMSG_NPC_TEXT_QUERY TextId: {}", packet.TextID);
180
181 GossipText const* npcText = sObjectMgr->GetGossipText(packet.TextID);
182
184 response.TextID = packet.TextID;
185 response.Allow = true;
186
187 if (npcText)
188 {
190
191 for (uint8 i = 0; i < MAX_GOSSIP_TEXT_OPTIONS; ++i)
192 {
193 response.Options[i].Probability = npcText->Options[i].Probability;
194 if (BroadcastTextEntry const* bct = sObjectMgr->GetBroadcastText(npcText->Options[i].BroadcastTextID))
195 {
196 response.Options[i].Text = bct->GetText(locale, GENDER_MALE, true);
197 response.Options[i].Text1 = bct->GetText(locale, GENDER_FEMALE, true);
198 }
199 else
200 {
201 response.Options[i].Text = npcText->Options[i].Text_0;
202 response.Options[i].Text1 = npcText->Options[i].Text_1;
203
204 if (locale != DEFAULT_LOCALE)
205 {
206 if (NpcTextLocale const* npcTextLocale = sObjectMgr->GetNpcTextLocale(packet.TextID))
207 {
208 ObjectMgr::GetLocaleString(npcTextLocale->Text_0[i], locale, response.Options[i].Text);
209 ObjectMgr::GetLocaleString(npcTextLocale->Text_1[i], locale, response.Options[i].Text1);
210 }
211 }
212 }
213
214 if (response.Options[i].Text.empty())
215 response.Options[i].Text = response.Options[i].Text1;
216
217 if (response.Options[i].Text1.empty())
218 response.Options[i].Text1 = response.Options[i].Text;
219
220 response.Options[i].LanguageID = npcText->Options[i].Language;
221
222 for (uint8 j = 0; j < MAX_GOSSIP_TEXT_EMOTES; ++j)
223 {
224 response.Options[i].EmoteDelay[j] = npcText->Options[i].Emotes[j]._Delay;
225 response.Options[i].EmoteID[j] = npcText->Options[i].Emotes[j]._Emote;
226 }
227 }
228 }
229 else
230 {
231 for (uint8 i = 0; i < MAX_GOSSIP_TEXT_OPTIONS; ++i)
232 {
233 response.Options[i].Text = "Greetings $N";
234 response.Options[i].Text1 = "Greetings $N";
235 }
236 }
237
238 SendPacket(response.Write());
239}
240
243{
244 uint32 pageID = packet.PageTextID;
245 while (pageID)
246 {
248 response.PageTextID = pageID;
249 if (PageText const* pageText = sObjectMgr->GetPageText(pageID))
250 {
251 response.Allow = true;
252
254 page.NextPageID = pageText->NextPageID;
255 page.Text = pageText->Text;
256
257 LocaleConstant localeConstant = GetSessionDbLocaleIndex();
258 if (localeConstant != LOCALE_enUS)
259 if (PageTextLocale const* pageTextLocale = sObjectMgr->GetPageTextLocale(pageID))
260 ObjectMgr::GetLocaleString(pageTextLocale->Text, localeConstant, page.Text);
261
262 pageID = pageText->NextPageID;
263 }
264 else
265 pageID = 0;
266
267 SendPacket(response.Write());
268 }
269}
270
272{
274 if (Corpse const* corpse = _player->GetCorpse())
275 {
276 if (Transport const* transport = corpse->GetTransport())
277 {
278 if (transport->GetGUID().GetCounter() == queryCorpseTransport.Transport)
279 {
280 response.Position = transport->GetPosition();
281 response.Facing = transport->GetOrientation();
282 }
283 }
284 }
285
286 SendPacket(response.Write());
287}
288
290{
292 return;
293
294 // Read quest ids and add the in a unordered_set so we don't send POIs for the same quest multiple times
295 std::unordered_set<uint32> questIds;
296 for (uint32 i = 0; i < query.MissingQuestCount; ++i)
297 questIds.insert(query.MissingQuestPOIs[i]); // quest id
298
299 WorldPacket data(SMSG_QUEST_POI_QUERY_RESPONSE, 4 + (4 + 4 + 40) * questIds.size());
300 data << uint32(questIds.size()); // count
301
302 for (uint32 questId : questIds)
303 {
304 uint16 const questSlot = _player->FindQuestSlot(questId);
305 if (questSlot != MAX_QUEST_LOG_SIZE && _player->GetQuestSlotQuestId(questSlot) == questId)
306 {
307 if (QuestPOIWrapper const* poiWrapper = sObjectMgr->GetQuestPOIWrapper(questId))
308 {
309 if (sWorld->getBoolConfig(CONFIG_CACHE_DATA_QUERIES))
310 data.append(poiWrapper->QueryDataBuffer);
311 else
312 {
313 ByteBuffer POIByteBuffer = poiWrapper->BuildQueryData();
314 data.append(POIByteBuffer);
315 }
316 }
317 else
318 {
319 data << uint32(questId); // quest ID
320 data << uint32(0); // POI count
321 }
322 }
323 else
324 {
325 data << uint32(questId); // quest ID
326 data << uint32(0); // POI count
327 }
328 }
329
330 SendPacket(&data);
331}
#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
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:261
#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 append(T value)
Definition ByteBuffer.h:133
Definition Map.h:302
std::string ToString() const
static std::string_view GetLocaleString(std::vector< std::string > const &data, LocaleConstant locale)
Definition ObjectMgr.h:1519
WorldLocation const & GetCorpseLocation() const
Definition Player.h:1744
uint16 FindQuestSlot(uint32 quest_id) const
Definition Player.cpp:15948
bool HasCorpse() const
Definition Player.h:1743
uint32 GetQuestSlotQuestId(uint16 slot) const
Definition Player.cpp:15957
Corpse * GetCorpse() const
Definition Player.cpp:4563
uint32 GetMapId() const
Definition Position.h:193
Transport * GetTransport() const
Definition Object.h:566
WorldPacket const * Write() override
TaggedPosition<::Position::XYZ > Position
TaggedPosition<::Position::XYZ > Position
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
std::array< NPCText, MAX_GOSSIP_TEXT_OPTIONS > Options
WorldPacket const * Write() override
WorldPacket const * Write() override
Optional< PlayerGuidLookupData > Data
WorldPacket const * Write() override
uint32 MissingQuestPOIs[MAX_QUEST_LOG_SIZE]
void HandleQueryCorpseTransport(WorldPackets::Query::QueryCorpseTransport &packet)
void HandleQuestPOIQuery(WorldPackets::Query::QuestPOIQuery &query)
void HandleQueryPageText(WorldPackets::Query::QueryPageText &packet)
Only static data is sent in this packet !!!
void SendPacket(WorldPacket const *packet)
Send a packet to the client.
LocaleConstant GetSessionDbLocaleIndex() const
void SendNameQueryOpcode(ObjectGuid guid)
Player * GetPlayer() const
void HandleNpcTextQueryOpcode(WorldPackets::Query::QueryNPCText &packet)
void HandleNameQueryOpcode(WorldPackets::Query::QueryPlayerName &queryPlayerName)
void HandleCreatureQueryOpcode(WorldPackets::Query::QueryCreature &query)
Only static data is sent in this packet !!!
Player * _player
void HandleQueryTimeOpcode(WorldPackets::Query::QueryTime &queryTime)
void HandleGameObjectQueryOpcode(WorldPackets::Query::QueryGameObject &query)
Only static data is sent in this packet !!!
void SendQueryTimeResponse()
void HandleQueryCorpseLocation(WorldPackets::Query::QueryCorpseLocationFromClient &packet)
@ SMSG_QUEST_POI_QUERY_RESPONSE
Definition Opcodes.h:513
#define sWorld
Definition World.h:901
@ CONFIG_CACHE_DATA_QUERIES
Definition World.h:176
time_t GetGameTime()
Definition GameTime.cpp:42
TC_GAME_API Player * FindConnectedPlayer(ObjectGuid const &)
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
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