root/trunk/src/game/ChatHandler.cpp @ 37

Revision 37, 18.0 kB (checked in by yumileroy, 17 years ago)

[svn] * svn:eol-style native set on all files that need it

Original author: Neo2003
Date: 2008-10-11 14:16:25-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 "Log.h"
21#include "WorldPacket.h"
22#include "WorldSession.h"
23#include "World.h"
24#include "Opcodes.h"
25#include "ObjectMgr.h"
26#include "Chat.h"
27#include "Database/DatabaseEnv.h"
28#include "ChannelMgr.h"
29#include "Group.h"
30#include "Guild.h"
31#include "MapManager.h"
32#include "ObjectAccessor.h"
33#include "ScriptCalls.h"
34#include "Player.h"
35#include "SpellAuras.h"
36#include "Language.h"
37#include "Util.h"
38
39void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
40{
41    CHECK_PACKET_SIZE(recv_data,4+4+1);
42
43    uint32 type;
44    uint32 lang;
45
46    recv_data >> type;
47    recv_data >> lang;
48
49    if(type >= MAX_CHAT_MSG_TYPE)
50    {
51        sLog.outError("CHAT: Wrong message type received: %u", type);
52        return;
53    }
54
55    //sLog.outDebug("CHAT: packet received. type %u, lang %u", type, lang );
56
57    // prevent talking at unknown language (cheating)
58    LanguageDesc const* langDesc = GetLanguageDescByID(lang);
59    if(!langDesc)
60    {
61        SendNotification(LANG_UNKNOWN_LANGUAGE);
62        return;
63    }
64    if(langDesc->skill_id != 0 && !_player->HasSkill(langDesc->skill_id))
65    {
66        // also check SPELL_AURA_COMPREHEND_LANGUAGE (client offers option to speak in that language)
67        Unit::AuraList const& langAuras = _player->GetAurasByType(SPELL_AURA_COMPREHEND_LANGUAGE);
68        bool foundAura = false;
69        for(Unit::AuraList::const_iterator i = langAuras.begin();i != langAuras.end(); ++i)
70        {
71            if((*i)->GetModifier()->m_miscvalue == lang)
72            {
73                foundAura = true;
74                break;
75            }
76        }
77        if(!foundAura)
78        {
79            SendNotification(LANG_NOT_LEARNED_LANGUAGE);
80            return;
81        }
82    }
83
84    if(lang == LANG_ADDON)
85    {
86        // Disabled addon channel?
87        if(!sWorld.getConfig(CONFIG_ADDON_CHANNEL))
88            return;
89    }
90    // LANG_ADDON should not be changed nor be affected by flood control
91    else
92    {
93        // send in universal language if player in .gmon mode (ignore spell effects)
94        if (_player->isGameMaster())
95            lang = LANG_UNIVERSAL;
96        else
97        {
98            // send in universal language in two side iteration allowed mode
99            if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT))
100                lang = LANG_UNIVERSAL;
101            else
102            {
103                switch(type)
104                {
105                    case CHAT_MSG_PARTY:
106                    case CHAT_MSG_RAID:
107                    case CHAT_MSG_RAID_LEADER:
108                    case CHAT_MSG_RAID_WARNING:
109                        // allow two side chat at group channel if two side group allowed
110                        if(sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
111                            lang = LANG_UNIVERSAL;
112                        break;
113                    case CHAT_MSG_GUILD:
114                    case CHAT_MSG_OFFICER:
115                        // allow two side chat at guild channel if two side guild allowed
116                        if(sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD))
117                            lang = LANG_UNIVERSAL;
118                        break;
119                }
120            }
121
122            // but overwrite it by SPELL_AURA_MOD_LANGUAGE auras (only single case used)
123            Unit::AuraList const& ModLangAuras = _player->GetAurasByType(SPELL_AURA_MOD_LANGUAGE);
124            if(!ModLangAuras.empty())
125                lang = ModLangAuras.front()->GetModifier()->m_miscvalue;
126        }
127
128        if (!_player->CanSpeak())
129        {
130            std::string timeStr = secsToTimeString(m_muteTime - time(NULL));
131            SendNotification(GetMangosString(LANG_WAIT_BEFORE_SPEAKING),timeStr.c_str());
132            return;
133        }
134
135        if (type != CHAT_MSG_AFK && type != CHAT_MSG_DND)
136            GetPlayer()->UpdateSpeakTime();
137    }
138
139    switch(type)
140    {
141        case CHAT_MSG_SAY:
142        case CHAT_MSG_EMOTE:
143        case CHAT_MSG_YELL:
144        {
145            std::string msg = "";
146            recv_data >> msg;
147
148            if(msg.empty())
149                break;
150
151            if (ChatHandler(this).ParseCommands(msg.c_str()) > 0)
152                break;
153
154            // strip invisible characters for non-addon messages
155            if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING))
156                stripLineInvisibleChars(msg);
157
158            if(msg.empty())
159                break;
160
161            if(type == CHAT_MSG_SAY)
162                GetPlayer()->Say(msg, lang);
163            else if(type == CHAT_MSG_EMOTE)
164                GetPlayer()->TextEmote(msg);
165            else if(type == CHAT_MSG_YELL)
166                GetPlayer()->Yell(msg, lang);
167        } break;
168
169        case CHAT_MSG_WHISPER:
170        {
171            std::string to, msg;
172            recv_data >> to;
173            CHECK_PACKET_SIZE(recv_data,4+4+(to.size()+1)+1);
174            recv_data >> msg;
175
176            // strip invisible characters for non-addon messages
177            if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING))
178                stripLineInvisibleChars(msg);
179
180            if(msg.empty())
181                break;
182
183            if(!normalizePlayerName(to))
184            {
185                WorldPacket data(SMSG_CHAT_PLAYER_NOT_FOUND, (to.size()+1));
186                data<<to;
187                SendPacket(&data);
188                break;
189            }
190
191            Player *player = objmgr.GetPlayer(to.c_str());
192            uint32 tSecurity = GetSecurity();
193            uint32 pSecurity = player ? player->GetSession()->GetSecurity() : 0;
194            if(!player || tSecurity == SEC_PLAYER && pSecurity > SEC_PLAYER && !player->isAcceptWhispers())
195            {
196                WorldPacket data(SMSG_CHAT_PLAYER_NOT_FOUND, (to.size()+1));
197                data<<to;
198                SendPacket(&data);
199                return;
200            }
201
202            if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT) && tSecurity == SEC_PLAYER && pSecurity == SEC_PLAYER )
203            {
204                uint32 sidea = GetPlayer()->GetTeam();
205                uint32 sideb = player->GetTeam();
206                if( sidea != sideb )
207                {
208                    WorldPacket data(SMSG_CHAT_PLAYER_NOT_FOUND, (to.size()+1));
209                    data<<to;
210                    SendPacket(&data);
211                    return;
212                }
213            }
214
215            GetPlayer()->Whisper(msg, lang,player->GetGUID());
216        } break;
217
218        case CHAT_MSG_PARTY:
219        {
220            std::string msg = "";
221            recv_data >> msg;
222
223            if(msg.empty())
224                break;
225
226            if (ChatHandler(this).ParseCommands(msg.c_str()) > 0)
227                break;
228
229            // strip invisible characters for non-addon messages
230            if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING))
231                stripLineInvisibleChars(msg);
232
233            if(msg.empty())
234                break;
235
236            Group *group = GetPlayer()->GetGroup();
237            if(!group)
238                return;
239
240            WorldPacket data;
241            ChatHandler::FillMessageData(&data, this, CHAT_MSG_PARTY, lang, NULL, 0, msg.c_str(),NULL);
242            group->BroadcastPacket(&data, group->GetMemberGroup(GetPlayer()->GetGUID()));
243        }
244        break;
245        case CHAT_MSG_GUILD:
246        {
247            std::string msg = "";
248            recv_data >> msg;
249
250            if(msg.empty())
251                break;
252
253            if (ChatHandler(this).ParseCommands(msg.c_str()) > 0)
254                break;
255
256            // strip invisible characters for non-addon messages
257            if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING))
258                stripLineInvisibleChars(msg);
259
260            if(msg.empty())
261                break;
262
263            if (GetPlayer()->GetGuildId())
264            {
265                Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId());
266                if (guild)
267                    guild->BroadcastToGuild(this, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL);
268            }
269
270            break;
271        }
272        case CHAT_MSG_OFFICER:
273        {
274            std::string msg = "";
275            recv_data >> msg;
276
277            if(msg.empty())
278                break;
279
280            if (ChatHandler(this).ParseCommands(msg.c_str()) > 0)
281                break;
282
283            // strip invisible characters for non-addon messages
284            if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING))
285                stripLineInvisibleChars(msg);
286
287            if(msg.empty())
288                break;
289
290            if (GetPlayer()->GetGuildId())
291            {
292                Guild *guild = objmgr.GetGuildById(GetPlayer()->GetGuildId());
293                if (guild)
294                    guild->BroadcastToOfficers(this, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL);
295            }
296            break;
297        }
298        case CHAT_MSG_RAID:
299        {
300            std::string msg="";
301            recv_data >> msg;
302
303            if(msg.empty())
304                break;
305
306            if (ChatHandler(this).ParseCommands(msg.c_str()) > 0)
307                break;
308
309            // strip invisible characters for non-addon messages
310            if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING))
311                stripLineInvisibleChars(msg);
312
313            if(msg.empty())
314                break;
315
316            Group *group = GetPlayer()->GetGroup();
317            if(!group || !group->isRaidGroup())
318                return;
319
320            WorldPacket data;
321            ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID, lang, "", 0, msg.c_str(),NULL);
322            group->BroadcastPacket(&data);
323        } break;
324        case CHAT_MSG_RAID_LEADER:
325        {
326            std::string msg="";
327            recv_data >> msg;
328
329            if(msg.empty())
330                break;
331
332            if (ChatHandler(this).ParseCommands(msg.c_str()) > 0)
333                break;
334
335            // strip invisible characters for non-addon messages
336            if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING))
337                stripLineInvisibleChars(msg);
338
339            if(msg.empty())
340                break;
341
342            Group *group = GetPlayer()->GetGroup();
343            if(!group || !group->isRaidGroup() || !group->IsLeader(GetPlayer()->GetGUID()))
344                return;
345
346            WorldPacket data;
347            ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_LEADER, lang, "", 0, msg.c_str(),NULL);
348            group->BroadcastPacket(&data);
349        } break;
350        case CHAT_MSG_RAID_WARNING:
351        {
352            std::string msg="";
353            recv_data >> msg;
354
355            // strip invisible characters for non-addon messages
356            if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING))
357                stripLineInvisibleChars(msg);
358
359            if(msg.empty())
360                break;
361
362            Group *group = GetPlayer()->GetGroup();
363            if(!group || !group->isRaidGroup() || !(group->IsLeader(GetPlayer()->GetGUID()) || group->IsAssistant(GetPlayer()->GetGUID())))
364                return;
365
366            WorldPacket data;
367            ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_WARNING, lang, "", 0, msg.c_str(),NULL);
368            group->BroadcastPacket(&data);
369        } break;
370
371        case CHAT_MSG_BATTLEGROUND:
372        {
373            std::string msg="";
374            recv_data >> msg;
375
376            // strip invisible characters for non-addon messages
377            if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING))
378                stripLineInvisibleChars(msg);
379
380            if(msg.empty())
381                break;
382
383            Group *group = GetPlayer()->GetGroup();
384            if(!group || !group->isRaidGroup())
385                return;
386
387            WorldPacket data;
388            ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND, lang, "", 0, msg.c_str(),NULL);
389            group->BroadcastPacket(&data);
390        } break;
391
392        case CHAT_MSG_BATTLEGROUND_LEADER:
393        {
394            std::string msg="";
395            recv_data >> msg;
396
397            // strip invisible characters for non-addon messages
398            if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING))
399                stripLineInvisibleChars(msg);
400
401            if(msg.empty())
402                break;
403
404            Group *group = GetPlayer()->GetGroup();
405            if(!group || !group->isRaidGroup() || !group->IsLeader(GetPlayer()->GetGUID()))
406                return;
407
408            WorldPacket data;
409            ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND_LEADER, lang, "", 0, msg.c_str(),NULL);
410            group->BroadcastPacket(&data);
411        } break;
412
413        case CHAT_MSG_CHANNEL:
414        {
415            std::string channel = "", msg = "";
416            recv_data >> channel;
417
418            // recheck
419            CHECK_PACKET_SIZE(recv_data,4+4+(channel.size()+1)+1);
420
421            recv_data >> msg;
422
423            // strip invisible characters for non-addon messages
424            if (lang != LANG_ADDON && sWorld.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING))
425                stripLineInvisibleChars(msg);
426
427            if(msg.empty())
428                break;
429
430            if(ChannelMgr* cMgr = channelMgr(_player->GetTeam()))
431            {
432                if(Channel *chn = cMgr->GetChannel(channel,_player))
433                    chn->Say(_player->GetGUID(),msg.c_str(),lang);
434            }
435        } break;
436
437        case CHAT_MSG_AFK:
438        {
439            std::string msg;
440            recv_data >> msg;
441
442            if((msg.empty() || !_player->isAFK()) && !_player->isInCombat() )
443            {
444                if(!_player->isAFK())
445                {
446                    if(msg.empty())
447                        msg  = GetMangosString(LANG_PLAYER_AFK_DEFAULT);
448                    _player->afkMsg = msg;
449                }
450                _player->ToggleAFK();
451                if(_player->isAFK() && _player->isDND())
452                    _player->ToggleDND();
453            }
454        } break;
455
456        case CHAT_MSG_DND:
457        {
458            std::string msg;
459            recv_data >> msg;
460
461            if(msg.empty() || !_player->isDND())
462            {
463                if(!_player->isDND())
464                {
465                    if(msg.empty())
466                        msg  = GetMangosString(LANG_PLAYER_DND_DEFAULT);
467                    _player->dndMsg = msg;
468                }
469                _player->ToggleDND();
470                if(_player->isDND() && _player->isAFK())
471                    _player->ToggleAFK();
472            }
473        } break;
474
475        default:
476            sLog.outError("CHAT: unknown message type %u, lang: %u", type, lang);
477            break;
478    }
479}
480
481void WorldSession::HandleEmoteOpcode( WorldPacket & recv_data )
482{
483    if(!GetPlayer()->isAlive())
484        return;
485    CHECK_PACKET_SIZE(recv_data,4);
486
487    uint32 emote;
488    recv_data >> emote;
489    GetPlayer()->HandleEmoteCommand(emote);
490}
491
492void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data )
493{
494    if(!GetPlayer()->isAlive())
495        return;
496
497    if (!GetPlayer()->CanSpeak())
498    {
499        std::string timeStr = secsToTimeString(m_muteTime - time(NULL));
500        SendNotification(GetMangosString(LANG_WAIT_BEFORE_SPEAKING),timeStr.c_str());
501        return;
502    }
503
504    CHECK_PACKET_SIZE(recv_data,4+4+8);
505
506    uint32 text_emote, emoteNum;
507    uint64 guid;
508
509    recv_data >> text_emote;
510    recv_data >> emoteNum;
511    recv_data >> guid;
512
513    const char *nam = 0;
514    uint32 namlen = 1;
515
516    Unit* unit = ObjectAccessor::GetUnit(*_player, guid);
517    Creature *pCreature = dynamic_cast<Creature *>(unit);
518    if(unit)
519    {
520        nam = unit->GetName();
521        namlen = (nam ? strlen(nam) : 0) + 1;
522    }
523
524    EmotesTextEntry const *em = sEmotesTextStore.LookupEntry(text_emote);
525    if (em)
526    {
527        uint32 emote_anim = em->textid;
528
529        WorldPacket data;
530
531        switch(emote_anim)
532        {
533            case EMOTE_STATE_SLEEP:
534            case EMOTE_STATE_SIT:
535            case EMOTE_STATE_KNEEL:
536            case EMOTE_ONESHOT_NONE:
537                break;
538            default:
539                GetPlayer()->HandleEmoteCommand(emote_anim);
540                break;
541        }
542
543        data.Initialize(SMSG_TEXT_EMOTE, (20+namlen));
544        data << GetPlayer()->GetGUID();
545        data << (uint32)text_emote;
546        data << emoteNum;
547        data << (uint32)namlen;
548        if( namlen > 1 )
549        {
550            data.append(nam, namlen);
551        }
552        else
553        {
554            data << (uint8)0x00;
555        }
556
557        GetPlayer()->SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true);
558
559        //Send scripted event call
560        if (pCreature && Script)
561            Script->ReceiveEmote(GetPlayer(),pCreature,text_emote);
562    }
563}
564
565void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data )
566{
567    CHECK_PACKET_SIZE(recv_data, 8+1);
568
569    uint64 iguid;
570    uint8 unk;
571    //sLog.outDebug("WORLD: Received CMSG_CHAT_IGNORED");
572
573    recv_data >> iguid;
574    recv_data >> unk;                                       // probably related to spam reporting
575
576    Player *player = objmgr.GetPlayer(iguid);
577    if(!player || !player->GetSession())
578        return;
579
580    WorldPacket data;
581    ChatHandler::FillMessageData(&data, this, CHAT_MSG_IGNORED, LANG_UNIVERSAL, NULL, GetPlayer()->GetGUID(), GetPlayer()->GetName(),NULL);
582    player->GetSession()->SendPacket(&data);
583}
Note: See TracBrowser for help on using the browser.