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

Revision 102, 14.4 kB (checked in by yumileroy, 17 years ago)

[svn] Fixed copyright notices to comply with GPL.

Original author: w12x
Date: 2008-10-23 03:29:52-05: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->flag1;                          // 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->DisplayID_A;                    // modelid_male1
191        data << (uint32)ci->DisplayID_H;                    // modelid_female1 ?
192        data << (uint32)ci->DisplayID_A2;                   // modelid_male2 ?
193        data << (uint32)ci->DisplayID_H2;                   // modelid_femmale2 ?
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 - (%u) NO CREATURE INFO! (GUID: %u, ENTRY: %u)", uint32(GUID_LOPART(guid)), guid, entry );
206        WorldPacket data( SMSG_CREATURE_QUERY_RESPONSE, 4 );
207        data << uint32(entry | 0x80000000);
208        SendPacket( &data );
209        sLog.outDebug(  "WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE " );
210    }
211}
212
213/// Only _static_ data send in this packet !!!
214void WorldSession::HandleGameObjectQueryOpcode( WorldPacket & recv_data )
215{
216    CHECK_PACKET_SIZE(recv_data,4+8);
217
218    uint32 entryID;
219    recv_data >> entryID;
220
221    const GameObjectInfo *info = objmgr.GetGameObjectInfo(entryID);
222    if(info)
223    {
224
225        std::string Name;
226        std::string CastBarCaption;
227
228        Name = info->name;
229        CastBarCaption = info->castBarCaption;
230
231        int loc_idx = GetSessionDbLocaleIndex();
232        if (loc_idx >= 0)
233        {
234            GameObjectLocale const *gl = objmgr.GetGameObjectLocale(entryID);
235            if (gl)
236            {
237                if (gl->Name.size() > loc_idx && !gl->Name[loc_idx].empty())
238                    Name = gl->Name[loc_idx];
239                if (gl->CastBarCaption.size() > loc_idx && !gl->CastBarCaption[loc_idx].empty())
240                    CastBarCaption = gl->CastBarCaption[loc_idx];
241            }
242        }
243        sLog.outDetail("WORLD: CMSG_GAMEOBJECT_QUERY '%s' - Entry: %u. ", info->name, entryID);
244        WorldPacket data ( SMSG_GAMEOBJECT_QUERY_RESPONSE, 150 );
245        data << entryID;
246        data << (uint32)info->type;
247        data << (uint32)info->displayId;
248        data << Name;
249        data << uint8(0) << uint8(0) << uint8(0);           // name2, name3, name4
250        data << uint8(0);                                   // 2.0.3, string
251        data << CastBarCaption;                             // 2.0.3, string. Text will appear in Cast Bar when using GO (ex: "Collecting")
252        data << uint8(0);                                   // 2.0.3, probably string
253        data.append(info->raw.data,24);
254        SendPacket( &data );
255        sLog.outDebug(  "WORLD: Sent CMSG_GAMEOBJECT_QUERY " );
256    }
257    else
258    {
259
260        uint64 guid;
261        recv_data >> guid;
262
263        sLog.outDebug(  "WORLD: CMSG_GAMEOBJECT_QUERY - (%u) Missing gameobject info for (GUID: %u, ENTRY: %u)", uint32(GUID_LOPART(guid)), guid, entryID );
264        WorldPacket data ( SMSG_GAMEOBJECT_QUERY_RESPONSE, 4 );
265        data << uint32(entryID | 0x80000000);
266        SendPacket( &data );
267        sLog.outDebug(  "WORLD: Sent CMSG_GAMEOBJECT_QUERY " );
268    }
269}
270
271void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recv_data*/)
272{
273    sLog.outDetail("WORLD: Received MSG_CORPSE_QUERY");
274
275    Corpse *corpse = GetPlayer()->GetCorpse();
276
277    uint8 found = 1;
278    if(!corpse)
279        found = 0;
280
281    WorldPacket data(MSG_CORPSE_QUERY, (1+found*(5*4)));
282    data << uint8(found);
283    if(found)
284    {
285        data << corpse->GetMapId();
286        data << corpse->GetPositionX();
287        data << corpse->GetPositionY();
288        data << corpse->GetPositionZ();
289        data << _player->GetMapId();
290    }
291    SendPacket(&data);
292}
293
294void WorldSession::HandleNpcTextQueryOpcode( WorldPacket & recv_data )
295{
296    CHECK_PACKET_SIZE(recv_data,4+8);
297
298    uint32 textID;
299    uint64 guid;
300    GossipText *pGossip;
301    std::string GossipStr;
302
303    recv_data >> textID;
304    sLog.outDetail("WORLD: CMSG_NPC_TEXT_QUERY ID '%u'", textID);
305
306    recv_data >> guid;
307    GetPlayer()->SetUInt64Value(UNIT_FIELD_TARGET, guid);
308
309    pGossip = objmgr.GetGossipText(textID);
310
311    WorldPacket data( SMSG_NPC_TEXT_UPDATE, 100 );          // guess size
312    data << textID;
313
314    if (!pGossip)
315    {
316        for(uint32 i = 0; i < 8; ++i)
317        {
318            data << float(0);
319            data << "Greetings $N";
320            data << "Greetings $N";
321            data << uint32(0);
322            data << uint32(0);
323            data << uint32(0);
324            data << uint32(0);
325            data << uint32(0);
326            data << uint32(0);
327            data << uint32(0);
328        }
329    }
330    else
331    {
332        std::string Text_0[8], Text_1[8];
333        for (int i=0;i<8;i++)
334        {
335            Text_0[i]=pGossip->Options[i].Text_0;
336            Text_1[i]=pGossip->Options[i].Text_1;
337        }
338
339        int loc_idx = GetSessionDbLocaleIndex();
340        if (loc_idx >= 0)
341        {
342            NpcTextLocale const *nl = objmgr.GetNpcTextLocale(textID);
343            if (nl)
344            {
345                for (int i=0;i<8;i++)
346                {
347                    if (nl->Text_0[i].size() > loc_idx && !nl->Text_0[i][loc_idx].empty())
348                        Text_0[i]=nl->Text_0[i][loc_idx];
349                    if (nl->Text_1[i].size() > loc_idx && !nl->Text_1[i][loc_idx].empty())
350                        Text_1[i]=nl->Text_1[i][loc_idx];
351                }
352            }
353        }
354
355        for (int i=0; i<8; i++)
356        {
357            data << pGossip->Options[i].Probability;
358
359            if ( Text_0[i].empty() )
360                data << Text_1[i];
361            else
362                data << Text_0[i];
363
364            if ( Text_1[i].empty() )
365                data << Text_0[i];
366            else
367                data << Text_1[i];
368
369            data << pGossip->Options[i].Language;
370
371            data << pGossip->Options[i].Emotes[0]._Delay;
372            data << pGossip->Options[i].Emotes[0]._Emote;
373
374            data << pGossip->Options[i].Emotes[1]._Delay;
375            data << pGossip->Options[i].Emotes[1]._Emote;
376
377            data << pGossip->Options[i].Emotes[2]._Delay;
378            data << pGossip->Options[i].Emotes[2]._Emote;
379        }
380    }
381
382    SendPacket( &data );
383
384    sLog.outDebug(  "WORLD: Sent SMSG_NPC_TEXT_UPDATE " );
385}
386
387void WorldSession::HandlePageQueryOpcode( WorldPacket & recv_data )
388{
389    CHECK_PACKET_SIZE(recv_data,4);
390
391    uint32 pageID;
392
393    recv_data >> pageID;
394    sLog.outDetail("WORLD: Received CMSG_PAGE_TEXT_QUERY for pageID '%u'", pageID);
395
396    while (pageID)
397    {
398        PageText const *pPage = sPageTextStore.LookupEntry<PageText>( pageID );
399                                                            // guess size
400        WorldPacket data( SMSG_PAGE_TEXT_QUERY_RESPONSE, 50 );
401        data << pageID;
402
403        if (!pPage)
404        {
405            data << "Item page missing.";
406            data << uint32(0);
407            pageID = 0;
408        }
409        else
410        {
411            std::string Text = pPage->Text;
412
413            int loc_idx = GetSessionDbLocaleIndex();
414            if (loc_idx >= 0)
415            {
416                PageTextLocale const *pl = objmgr.GetPageTextLocale(pageID);
417                if (pl)
418                {
419                    if (pl->Text.size() > loc_idx && !pl->Text[loc_idx].empty())
420                        Text = pl->Text[loc_idx];
421                }
422            }
423
424            data << Text;
425            data << uint32(pPage->Next_Page);
426            pageID = pPage->Next_Page;
427        }
428        SendPacket( &data );
429
430        sLog.outDebug(  "WORLD: Sent SMSG_PAGE_TEXT_QUERY_RESPONSE " );
431    }
432}
Note: See TracBrowser for help on using the browser.