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

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

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

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