root/trunk/src/game/QueryHandler.cpp @ 217

Revision 207, 14.3 kB (checked in by yumileroy, 17 years ago)

[svn] * Improve some arena team related DB access
* Cache GM tickets on server startup.
* Remove unused src/game/HateMatrix.h and references.
* Better check client inventory pos data received in some client packets to
skip invalid cases

Original author: KingPin?
Date: 2008-11-10 09:04:23-06:00

Line 
1/*
2 * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
3 *
4 * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "Common.h"
22#include "Language.h"
23#include "Database/DatabaseEnv.h"
24#include "Database/DatabaseImpl.h"
25#include "WorldPacket.h"
26#include "WorldSession.h"
27#include "Opcodes.h"
28#include "Log.h"
29#include "World.h"
30#include "ObjectMgr.h"
31#include "Player.h"
32#include "UpdateMask.h"
33#include "NPCHandler.h"
34#include "ObjectAccessor.h"
35#include "Pet.h"
36
37void WorldSession::SendNameQueryOpcode(Player *p)
38{
39    if(!p)
40        return;
41
42                                                            // guess size
43    WorldPacket data( SMSG_NAME_QUERY_RESPONSE, (8+1+4+4+4+10) );
44    data << p->GetGUID();
45    data << p->GetName();
46    data << uint8(0);                                       // realm name for cross realm BG usage
47    data << uint32(p->getRace());
48    data << uint32(p->getGender());
49    data << uint32(p->getClass());
50    if(DeclinedName const* names = p->GetDeclinedNames())
51    {
52        data << uint8(1);                                   // is declined
53        for(int i = 0; i < MAX_DECLINED_NAME_CASES; ++i)
54            data << names->name[i];
55    }
56    else
57        data << uint8(0);                                   // is not declined
58
59    SendPacket(&data);
60}
61
62void WorldSession::SendNameQueryOpcodeFromDB(uint64 guid)
63{
64    CharacterDatabase.AsyncPQuery(&WorldSession::SendNameQueryOpcodeFromDBCallBack, GetAccountId(),
65        !sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) ?
66    //   ------- Query Without Declined Names --------
67    //          0                1     2
68        "SELECT guid, name, SUBSTRING(data, LENGTH(SUBSTRING_INDEX(data, ' ', '%u'))+2, LENGTH(SUBSTRING_INDEX(data, ' ', '%u')) - LENGTH(SUBSTRING_INDEX(data, ' ', '%u'))-1) "
69        "FROM characters WHERE guid = '%u'"
70        :
71    //   --------- Query With Declined Names ---------
72    //          0                1     2
73        "SELECT characters.guid, name, SUBSTRING(data, LENGTH(SUBSTRING_INDEX(data, ' ', '%u'))+2, LENGTH(SUBSTRING_INDEX(data, ' ', '%u')) - LENGTH(SUBSTRING_INDEX(data, ' ', '%u'))-1), "
74    //   3         4       5           6             7
75        "genitive, dative, accusative, instrumental, prepositional "
76        "FROM characters LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid WHERE characters.guid = '%u'",
77        UNIT_FIELD_BYTES_0, UNIT_FIELD_BYTES_0+1, UNIT_FIELD_BYTES_0, GUID_LOPART(guid));
78}
79
80void WorldSession::SendNameQueryOpcodeFromDBCallBack(QueryResult *result, uint32 accountId)
81{
82    if(!result)
83        return;
84
85    WorldSession * session = sWorld.FindSession(accountId);
86    if(!session)
87    {
88        delete result;
89        return;
90    }
91
92    Field *fields = result->Fetch();
93    uint32 guid      = fields[0].GetUInt32();
94    std::string name = fields[1].GetCppString();
95    uint32 field     = 0;
96    if(name == "")
97        name         = session->GetTrinityString(LANG_NON_EXIST_CHARACTER);
98    else
99        field        = fields[2].GetUInt32();
100
101                                                        // guess size
102    WorldPacket data( SMSG_NAME_QUERY_RESPONSE, (8+1+4+4+4+10) );
103    data << MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER);
104    data << name;
105    data << (uint8)0;
106    data << (uint32)(field & 0xFF);
107    data << (uint32)((field >> 16) & 0xFF);
108    data << (uint32)((field >> 8) & 0xFF);
109
110    // if the first declined name field (3) is empty, the rest must be too
111    if(sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) && fields[3].GetCppString() != "")
112    {
113        data << (uint8)1;                                   // is declined
114        for(int i = 3; i < MAX_DECLINED_NAME_CASES+3; ++i)
115            data << fields[i].GetCppString();
116    }
117    else
118        data << (uint8)0;                                   // is declined
119
120    session->SendPacket( &data );
121    delete result;
122}
123
124void WorldSession::HandleNameQueryOpcode( WorldPacket & recv_data )
125{
126    CHECK_PACKET_SIZE(recv_data,8);
127
128    uint64 guid;
129
130    recv_data >> guid;
131
132    Player *pChar = objmgr.GetPlayer(guid);
133
134    if (pChar)
135        SendNameQueryOpcode(pChar);
136    else
137        SendNameQueryOpcodeFromDB(guid);
138}
139
140void WorldSession::HandleQueryTimeOpcode( WorldPacket & /*recv_data*/ )
141{
142    WorldPacket data( SMSG_QUERY_TIME_RESPONSE, 4+4 );
143    data << (uint32)time(NULL);
144    data << (uint32)0;
145    SendPacket( &data );
146}
147
148/// Only _static_ data send in this packet !!!
149void WorldSession::HandleCreatureQueryOpcode( WorldPacket & recv_data )
150{
151    CHECK_PACKET_SIZE(recv_data,4+8);
152
153    uint32 entry;
154    recv_data >> entry;
155
156    CreatureInfo const *ci = objmgr.GetCreatureTemplate(entry);
157    if (ci)
158    {
159
160        std::string Name, SubName;
161        Name = ci->Name;
162        SubName = ci->SubName;
163
164        int loc_idx = GetSessionDbLocaleIndex();
165        if (loc_idx >= 0)
166        {
167            CreatureLocale const *cl = objmgr.GetCreatureLocale(entry);
168            if (cl)
169            {
170                if (cl->Name.size() > loc_idx && !cl->Name[loc_idx].empty())
171                    Name = cl->Name[loc_idx];
172                if (cl->SubName.size() > loc_idx && !cl->SubName[loc_idx].empty())
173                    SubName = cl->SubName[loc_idx];
174            }
175        }
176        sLog.outDetail("WORLD: CMSG_CREATURE_QUERY '%s' - Entry: %u.", ci->Name, entry);
177                                                            // guess size
178        WorldPacket data( SMSG_CREATURE_QUERY_RESPONSE, 100 );
179        data << (uint32)entry;                              // creature entry
180        data << Name;
181        data << uint8(0) << uint8(0) << uint8(0);           // name2, name3, name4, always empty
182        data << SubName;
183        data << ci->IconName;                               // "Directions" for guard, string for Icons 2.3.0
184        data << (uint32)ci->type_flags;                          // flags          wdbFeild7=wad flags1
185        data << (uint32)ci->type;
186        data << (uint32)ci->family;                         // family         wdbFeild9
187        data << (uint32)ci->rank;                           // rank           wdbFeild10
188        data << (uint32)0;                                  // unknown        wdbFeild11
189        data << (uint32)ci->PetSpellDataId;                 // Id from CreatureSpellData.dbc    wdbField12
190        data << (uint32)ci->Modelid1;                       // Modelid1
191        data << (uint32)ci->Modelid2;                       // Modelid2
192        data << (uint32)ci->Modelid3;                       // Modelid3
193        data << (uint32)ci->Modelid4;                       // Modelid4
194        data << (float)1.0f;                                // unk
195        data << (float)1.0f;                                // unk
196        data << (uint8)ci->RacialLeader;
197        SendPacket( &data );
198        sLog.outDebug(  "WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE " );
199    }
200    else
201    {
202        uint64 guid;
203        recv_data >> guid;
204
205        sLog.outDebug("WORLD: CMSG_CREATURE_QUERY - NO CREATURE INFO! (GUID: %u, ENTRY: %u)",
206            GUID_LOPART(guid), entry);
207        WorldPacket data( SMSG_CREATURE_QUERY_RESPONSE, 4 );
208        data << uint32(entry | 0x80000000);
209        SendPacket( &data );
210        sLog.outDebug(  "WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE " );
211    }
212}
213
214/// Only _static_ data send in this packet !!!
215void WorldSession::HandleGameObjectQueryOpcode( WorldPacket & recv_data )
216{
217    CHECK_PACKET_SIZE(recv_data,4+8);
218
219    uint32 entryID;
220    recv_data >> entryID;
221
222    const GameObjectInfo *info = objmgr.GetGameObjectInfo(entryID);
223    if(info)
224    {
225
226        std::string Name;
227        std::string CastBarCaption;
228
229        Name = info->name;
230        CastBarCaption = info->castBarCaption;
231
232        int loc_idx = GetSessionDbLocaleIndex();
233        if (loc_idx >= 0)
234        {
235            GameObjectLocale const *gl = objmgr.GetGameObjectLocale(entryID);
236            if (gl)
237            {
238                if (gl->Name.size() > loc_idx && !gl->Name[loc_idx].empty())
239                    Name = gl->Name[loc_idx];
240                if (gl->CastBarCaption.size() > loc_idx && !gl->CastBarCaption[loc_idx].empty())
241                    CastBarCaption = gl->CastBarCaption[loc_idx];
242            }
243        }
244        sLog.outDetail("WORLD: CMSG_GAMEOBJECT_QUERY '%s' - Entry: %u. ", info->name, entryID);
245        WorldPacket data ( SMSG_GAMEOBJECT_QUERY_RESPONSE, 150 );
246        data << entryID;
247        data << (uint32)info->type;
248        data << (uint32)info->displayId;
249        data << Name;
250        data << uint8(0) << uint8(0) << uint8(0);           // name2, name3, name4
251        data << uint8(0);                                   // 2.0.3, string
252        data << CastBarCaption;                             // 2.0.3, string. Text will appear in Cast Bar when using GO (ex: "Collecting")
253        data << uint8(0);                                   // 2.0.3, probably string
254        data.append(info->raw.data,24);
255        SendPacket( &data );
256        sLog.outDebug(  "WORLD: Sent CMSG_GAMEOBJECT_QUERY " );
257    }
258    else
259    {
260
261        uint64 guid;
262        recv_data >> guid;
263
264        sLog.outDebug(  "WORLD: CMSG_GAMEOBJECT_QUERY - Missing gameobject info for (GUID: %u, ENTRY: %u)",
265            GUID_LOPART(guid), entryID );
266        WorldPacket data ( SMSG_GAMEOBJECT_QUERY_RESPONSE, 4 );
267        data << uint32(entryID | 0x80000000);
268        SendPacket( &data );
269        sLog.outDebug(  "WORLD: Sent CMSG_GAMEOBJECT_QUERY " );
270    }
271}
272
273void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recv_data*/)
274{
275    sLog.outDetail("WORLD: Received MSG_CORPSE_QUERY");
276
277    Corpse *corpse = GetPlayer()->GetCorpse();
278
279    uint8 found = 1;
280    if(!corpse)
281        found = 0;
282
283    WorldPacket data(MSG_CORPSE_QUERY, (1+found*(5*4)));
284    data << uint8(found);
285    if(found)
286    {
287        data << corpse->GetMapId();
288        data << corpse->GetPositionX();
289        data << corpse->GetPositionY();
290        data << corpse->GetPositionZ();
291        data << _player->GetMapId();
292    }
293    SendPacket(&data);
294}
295
296void WorldSession::HandleNpcTextQueryOpcode( WorldPacket & recv_data )
297{
298    CHECK_PACKET_SIZE(recv_data,4+8);
299
300    uint32 textID;
301    uint64 guid;
302    GossipText *pGossip;
303    std::string GossipStr;
304
305    recv_data >> textID;
306    sLog.outDetail("WORLD: CMSG_NPC_TEXT_QUERY ID '%u'", textID);
307
308    recv_data >> guid;
309    GetPlayer()->SetUInt64Value(UNIT_FIELD_TARGET, guid);
310
311    pGossip = objmgr.GetGossipText(textID);
312
313    WorldPacket data( SMSG_NPC_TEXT_UPDATE, 100 );          // guess size
314    data << textID;
315
316    if (!pGossip)
317    {
318        for(uint32 i = 0; i < 8; ++i)
319        {
320            data << float(0);
321            data << "Greetings $N";
322            data << "Greetings $N";
323            data << uint32(0);
324            data << uint32(0);
325            data << uint32(0);
326            data << uint32(0);
327            data << uint32(0);
328            data << uint32(0);
329            data << uint32(0);
330        }
331    }
332    else
333    {
334        std::string Text_0[8], Text_1[8];
335        for (int i=0;i<8;i++)
336        {
337            Text_0[i]=pGossip->Options[i].Text_0;
338            Text_1[i]=pGossip->Options[i].Text_1;
339        }
340
341        int loc_idx = GetSessionDbLocaleIndex();
342        if (loc_idx >= 0)
343        {
344            NpcTextLocale const *nl = objmgr.GetNpcTextLocale(textID);
345            if (nl)
346            {
347                for (int i=0;i<8;i++)
348                {
349                    if (nl->Text_0[i].size() > loc_idx && !nl->Text_0[i][loc_idx].empty())
350                        Text_0[i]=nl->Text_0[i][loc_idx];
351                    if (nl->Text_1[i].size() > loc_idx && !nl->Text_1[i][loc_idx].empty())
352                        Text_1[i]=nl->Text_1[i][loc_idx];
353                }
354            }
355        }
356
357        for (int i=0; i<8; i++)
358        {
359            data << pGossip->Options[i].Probability;
360
361            if ( Text_0[i].empty() )
362                data << Text_1[i];
363            else
364                data << Text_0[i];
365
366            if ( Text_1[i].empty() )
367                data << Text_0[i];
368            else
369                data << Text_1[i];
370
371            data << pGossip->Options[i].Language;
372
373            data << pGossip->Options[i].Emotes[0]._Delay;
374            data << pGossip->Options[i].Emotes[0]._Emote;
375
376            data << pGossip->Options[i].Emotes[1]._Delay;
377            data << pGossip->Options[i].Emotes[1]._Emote;
378
379            data << pGossip->Options[i].Emotes[2]._Delay;
380            data << pGossip->Options[i].Emotes[2]._Emote;
381        }
382    }
383
384    SendPacket( &data );
385
386    sLog.outDebug(  "WORLD: Sent SMSG_NPC_TEXT_UPDATE " );
387}
388
389void WorldSession::HandlePageQueryOpcode( WorldPacket & recv_data )
390{
391    CHECK_PACKET_SIZE(recv_data,4);
392
393    uint32 pageID;
394
395    recv_data >> pageID;
396    sLog.outDetail("WORLD: Received CMSG_PAGE_TEXT_QUERY for pageID '%u'", pageID);
397
398    while (pageID)
399    {
400        PageText const *pPage = sPageTextStore.LookupEntry<PageText>( pageID );
401                                                            // guess size
402        WorldPacket data( SMSG_PAGE_TEXT_QUERY_RESPONSE, 50 );
403        data << pageID;
404
405        if (!pPage)
406        {
407            data << "Item page missing.";
408            data << uint32(0);
409            pageID = 0;
410        }
411        else
412        {
413            std::string Text = pPage->Text;
414
415            int loc_idx = GetSessionDbLocaleIndex();
416            if (loc_idx >= 0)
417            {
418                PageTextLocale const *pl = objmgr.GetPageTextLocale(pageID);
419                if (pl)
420                {
421                    if (pl->Text.size() > loc_idx && !pl->Text[loc_idx].empty())
422                        Text = pl->Text[loc_idx];
423                }
424            }
425
426            data << Text;
427            data << uint32(pPage->Next_Page);
428            pageID = pPage->Next_Page;
429        }
430        SendPacket( &data );
431
432        sLog.outDebug(  "WORLD: Sent SMSG_PAGE_TEXT_QUERY_RESPONSE " );
433    }
434}
Note: See TracBrowser for help on using the browser.