void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data) { uint32 type; uint32 lang; recv_data >> type; recv_data >> lang; if (type >= MAX_CHAT_MSG_TYPE) { sLog.outError("CHAT: Wrong message type received: %u", type); return; } DEBUG_LOG("CHAT: packet received. type %u, lang %u", type, lang); // prevent talking at unknown language (cheating) LanguageDesc const* langDesc = GetLanguageDescByID(lang); if (!langDesc) { SendNotification(LANG_UNKNOWN_LANGUAGE); return; } if (langDesc->skill_id != 0 && !_player->HasSkill(langDesc->skill_id)) { // also check SPELL_AURA_COMPREHEND_LANGUAGE (client offers option to speak in that language) Unit::AuraList const& langAuras = _player->GetAurasByType(SPELL_AURA_COMPREHEND_LANGUAGE); bool foundAura = false; for (Unit::AuraList::const_iterator i = langAuras.begin(); i != langAuras.end(); ++i) { if ((*i)->GetModifier()->m_miscvalue == int32(lang)) { foundAura = true; break; } } if (!foundAura) { SendNotification(LANG_NOT_LEARNED_LANGUAGE); return; } } if (lang == LANG_ADDON) { // Disabled addon channel? if (!sWorld.getConfig(CONFIG_BOOL_ADDON_CHANNEL)) return; } // LANG_ADDON should not be changed nor be affected by flood control else { // send in universal language if player in .gmon mode (ignore spell effects) if (_player->isGameMaster()) lang = LANG_UNIVERSAL; else { // send in universal language in two side iteration allowed mode if (sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_CHAT)) lang = LANG_UNIVERSAL; else { switch (type) { case CHAT_MSG_PARTY: case CHAT_MSG_RAID: case CHAT_MSG_RAID_LEADER: case CHAT_MSG_RAID_WARNING: // allow two side chat at group channel if two side group allowed if (sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_GROUP)) lang = LANG_UNIVERSAL; break; case CHAT_MSG_GUILD: case CHAT_MSG_OFFICER: // allow two side chat at guild channel if two side guild allowed if (sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_GUILD)) lang = LANG_UNIVERSAL; break; } } // but overwrite it by SPELL_AURA_MOD_LANGUAGE auras (only single case used) Unit::AuraList const& ModLangAuras = _player->GetAurasByType(SPELL_AURA_MOD_LANGUAGE); if (!ModLangAuras.empty()) lang = ModLangAuras.front()->GetModifier()->m_miscvalue; } if (type != CHAT_MSG_AFK && type != CHAT_MSG_DND) { if (!_player->CanSpeak()) { std::string timeStr = secsToTimeString(m_muteTime - time(NULL)); SendNotification(GetMangosString(LANG_WAIT_BEFORE_SPEAKING), timeStr.c_str()); return; } GetPlayer()->UpdateSpeakTime(); } } switch (type) { case CHAT_MSG_SAY: case CHAT_MSG_EMOTE: case CHAT_MSG_YELL: { std::string msg; recv_data >> msg; if (msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str())) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; if (type == CHAT_MSG_SAY) GetPlayer()->Say(msg, lang); else if (type == CHAT_MSG_EMOTE) GetPlayer()->TextEmote(msg); else if (type == CHAT_MSG_YELL) GetPlayer()->Yell(msg, lang); } break; case CHAT_MSG_WHISPER: { std::string to, msg; recv_data >> to; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; if (!normalizePlayerName(to)) { SendPlayerNotFoundNotice(to); break; } Player* player = sObjectMgr.GetPlayer(to.c_str()); uint32 tSecurity = GetSecurity(); uint32 pSecurity = player ? player->GetSession()->GetSecurity() : SEC_PLAYER; if (!player || (tSecurity == SEC_PLAYER && pSecurity > SEC_PLAYER && !player->isAcceptWhispers())) { SendPlayerNotFoundNotice(to); return; } if (!sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_CHAT) && tSecurity == SEC_PLAYER && pSecurity == SEC_PLAYER) { if (GetPlayer()->GetTeam() != player->GetTeam()) { SendWrongFactionNotice(); return; } } // Playerbot mod: handle whispered command to bot if (player->GetPlayerbotAI()) { player->GetPlayerbotAI()->HandleCommand(msg, *GetPlayer()); GetPlayer()->m_speakTime = 0; GetPlayer()->m_speakCount = 0; } else GetPlayer()->Whisper(msg, lang, player->GetObjectGuid()); } break; case CHAT_MSG_PARTY: { std::string msg; recv_data >> msg; if (msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str())) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; // if player is in battleground, he cannot say to battleground members by /p Group* group = GetPlayer()->GetOriginalGroup(); if (!group) { group = _player->GetGroup(); if (!group || group->isBGGroup()) return; } // Playerbot mod: broadcast message to bot members for(GroupReference* itr = group->GetFirstMember(); itr != NULL; itr=itr->next()) { Player* player = itr->getSource(); if (player && player->GetPlayerbotAI()) { player->GetPlayerbotAI()->HandleCommand(msg, *GetPlayer()); GetPlayer()->m_speakTime = 0; GetPlayer()->m_speakCount = 0; } } // END Playerbot mod WorldPacket data; ChatHandler::FillMessageData(&data, this, type, lang, msg.c_str()); group->BroadcastPacket(&data, false, group->GetMemberGroup(GetPlayer()->GetObjectGuid())); break; } case CHAT_MSG_GUILD: { std::string msg; recv_data >> msg; if (msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str())) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; if (GetPlayer()->GetGuildId()) if (Guild* guild = sGuildMgr.GetGuildById(GetPlayer()->GetGuildId())) guild->BroadcastToGuild(this, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL); break; } case CHAT_MSG_OFFICER: { std::string msg; recv_data >> msg; if (msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str())) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; if (GetPlayer()->GetGuildId()) if (Guild* guild = sGuildMgr.GetGuildById(GetPlayer()->GetGuildId())) guild->BroadcastToOfficers(this, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL); break; } case CHAT_MSG_RAID: { std::string msg; recv_data >> msg; if (msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str())) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; // if player is in battleground, he cannot say to battleground members by /ra Group* group = GetPlayer()->GetOriginalGroup(); if (!group) { group = GetPlayer()->GetGroup(); if (!group || group->isBGGroup() || !group->isRaidGroup()) return; } WorldPacket data; ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID, lang, msg.c_str()); group->BroadcastPacket(&data, false); } break; case CHAT_MSG_RAID_LEADER: { std::string msg; recv_data >> msg; if (msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str())) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; // if player is in battleground, he cannot say to battleground members by /ra Group* group = GetPlayer()->GetOriginalGroup(); if (!group) { group = GetPlayer()->GetGroup(); if (!group || group->isBGGroup() || !group->isRaidGroup() || !group->IsLeader(_player->GetObjectGuid())) return; } WorldPacket data; ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_LEADER, lang, msg.c_str()); group->BroadcastPacket(&data, false); } break; case CHAT_MSG_RAID_WARNING: { std::string msg; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; Group* group = GetPlayer()->GetGroup(); if (!group || !group->isRaidGroup() || !(group->IsLeader(GetPlayer()->GetObjectGuid()) || group->IsAssistant(GetPlayer()->GetObjectGuid()))) return; WorldPacket data; // in battleground, raid warning is sent only to players in battleground - code is ok ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_WARNING, lang, msg.c_str()); group->BroadcastPacket(&data, false); } break; case CHAT_MSG_BATTLEGROUND: { std::string msg; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; // battleground raid is always in Player->GetGroup(), never in GetOriginalGroup() Group* group = GetPlayer()->GetGroup(); if (!group || !group->isBGGroup()) return; WorldPacket data; ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND, lang, msg.c_str()); group->BroadcastPacket(&data, false); } break; case CHAT_MSG_BATTLEGROUND_LEADER: { std::string msg; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; // battleground raid is always in Player->GetGroup(), never in GetOriginalGroup() Group* group = GetPlayer()->GetGroup(); if (!group || !group->isBGGroup() || !group->IsLeader(GetPlayer()->GetObjectGuid())) return; WorldPacket data; ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND_LEADER, lang, msg.c_str()); group->BroadcastPacket(&data, false); } break; case CHAT_MSG_CHANNEL: { std::string channel, msg; recv_data >> channel; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if (msg.empty()) break; if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) if (Channel* chn = cMgr->GetChannel(channel, _player)) chn->Say(_player->GetObjectGuid(), msg.c_str(), lang); } break; case CHAT_MSG_AFK: { std::string msg; recv_data >> msg; if (!_player->isInCombat()) { if (_player->isAFK()) // Already AFK { if (msg.empty()) _player->ToggleAFK(); // Remove AFK else _player->autoReplyMsg = msg; // Update message } else // New AFK mode { _player->autoReplyMsg = msg.empty() ? GetMangosString(LANG_PLAYER_AFK_DEFAULT) : msg; if (_player->isDND()) _player->ToggleDND(); _player->ToggleAFK(); } } break; } case CHAT_MSG_DND: { std::string msg; recv_data >> msg; if (_player->isDND()) // Already DND { if (msg.empty()) _player->ToggleDND(); // Remove DND else _player->autoReplyMsg = msg; // Update message } else // New DND mode { _player->autoReplyMsg = msg.empty() ? GetMangosString(LANG_PLAYER_DND_DEFAULT) : msg; if (_player->isAFK()) _player->ToggleAFK(); _player->ToggleDND(); } break; } default: sLog.outError("CHAT: unknown message type %u, lang: %u", type, lang); break; } }
void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) { uint32 type; uint32 lang; recv_data >> type; recv_data >> lang; if(type >= MAX_CHAT_MSG_TYPE) { sLog.outError("CHAT: Wrong message type received: %u", type); return; } //sLog.outDebug("CHAT: packet received. type %u, lang %u", type, lang ); // prevent talking at unknown language (cheating) LanguageDesc const* langDesc = GetLanguageDescByID(lang); if(!langDesc) { SendNotification(LANG_UNKNOWN_LANGUAGE); return; } if(langDesc->skill_id != 0 && !_player->HasSkill(langDesc->skill_id)) { // also check SPELL_AURA_COMPREHEND_LANGUAGE (client offers option to speak in that language) Unit::AuraList const& langAuras = _player->GetAurasByType(SPELL_AURA_COMPREHEND_LANGUAGE); bool foundAura = false; for(Unit::AuraList::const_iterator i = langAuras.begin();i != langAuras.end(); ++i) { if((*i)->GetModifier()->m_miscvalue == int32(lang)) { foundAura = true; break; } } if(!foundAura) { SendNotification(LANG_NOT_LEARNED_LANGUAGE); return; } } if(lang == LANG_ADDON) { // Disabled addon channel? if(!sWorld.getConfig(CONFIG_ADDON_CHANNEL)) return; } // LANG_ADDON should not be changed nor be affected by flood control else { // send in universal language if player in .gmon mode (ignore spell effects) if (_player->isGameMaster()) lang = LANG_UNIVERSAL; else { // send in universal language in two side iteration allowed mode if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT)) lang = LANG_UNIVERSAL; else { switch(type) { case CHAT_MSG_PARTY: case CHAT_MSG_RAID: case CHAT_MSG_RAID_LEADER: case CHAT_MSG_RAID_WARNING: // allow two side chat at group channel if two side group allowed if(sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP)) lang = LANG_UNIVERSAL; break; case CHAT_MSG_GUILD: case CHAT_MSG_OFFICER: // allow two side chat at guild channel if two side guild allowed if(sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD)) lang = LANG_UNIVERSAL; break; } } // but overwrite it by SPELL_AURA_MOD_LANGUAGE auras (only single case used) Unit::AuraList const& ModLangAuras = _player->GetAurasByType(SPELL_AURA_MOD_LANGUAGE); if(!ModLangAuras.empty()) lang = ModLangAuras.front()->GetModifier()->m_miscvalue; } if (!_player->CanSpeak()) { std::string timeStr = secsToTimeString(m_muteTime - time(NULL)); SendNotification(GetMangosString(LANG_WAIT_BEFORE_SPEAKING),timeStr.c_str()); return; } if (type != CHAT_MSG_AFK && type != CHAT_MSG_DND) GetPlayer()->UpdateSpeakTime(); } switch(type) { case CHAT_MSG_SAY: case CHAT_MSG_EMOTE: case CHAT_MSG_YELL: { std::string msg = ""; recv_data >> msg; if(msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if(msg.empty()) break; if(type == CHAT_MSG_SAY) { //sChatLog.ChatMsg(GetPlayer(), msg, type); GetPlayer()->Say(msg, lang); } else if(type == CHAT_MSG_EMOTE) { //sChatLog.ChatMsg(GetPlayer(), msg, type); GetPlayer()->TextEmote(msg); } else if(type == CHAT_MSG_YELL) { //sChatLog.ChatMsg(GetPlayer(), msg, type); GetPlayer()->Yell(msg, lang); } } break; case CHAT_MSG_WHISPER: { std::string to, msg; recv_data >> to; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if(msg.empty()) break; //sChatLog.WhisperMsg(GetPlayer(), to, msg); if(!normalizePlayerName(to)) { WorldPacket data(SMSG_CHAT_PLAYER_NOT_FOUND, (to.size()+1)); data<<to; SendPacket(&data); break; } Player *player = sObjectMgr.GetPlayer(to.c_str()); uint32 tSecurity = GetSecurity(); uint32 pSecurity = player ? player->GetSession()->GetSecurity() : SEC_PLAYER; if (!player || (tSecurity == SEC_PLAYER && pSecurity > SEC_PLAYER && !player->isAcceptWhispers())) { WorldPacket data(SMSG_CHAT_PLAYER_NOT_FOUND, (to.size()+1)); data<<to; SendPacket(&data); return; } if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT) && tSecurity == SEC_PLAYER && pSecurity == SEC_PLAYER ) { uint32 sidea = GetPlayer()->GetTeam(); uint32 sideb = player->GetTeam(); if( sidea != sideb ) { WorldPacket data(SMSG_CHAT_PLAYER_NOT_FOUND, (to.size()+1)); data<<to; SendPacket(&data); return; } } GetPlayer()->Whisper(msg, lang,player->GetGUID()); } break; case CHAT_MSG_PARTY: { std::string msg = ""; recv_data >> msg; if(msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if(msg.empty()) break; //sChatLog.PartyMsg(GetPlayer(), msg); Group *group = GetPlayer()->GetGroup(); if(!group) return; WorldPacket data; ChatHandler::FillMessageData(&data, this, CHAT_MSG_PARTY, lang, NULL, 0, msg.c_str(),NULL); group->BroadcastPacket(&data, group->GetMemberGroup(GetPlayer()->GetGUID())); } break; case CHAT_MSG_GUILD: { std::string msg = ""; recv_data >> msg; if(msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if(msg.empty()) break; //sChatLog.GuildMsg(GetPlayer(), msg, false); //sChatLog.GuildMsg(GetPlayer(), msg, true); if (GetPlayer()->GetGuildId()) { Guild *guild = sObjectMgr.GetGuildById(GetPlayer()->GetGuildId()); if (guild) guild->BroadcastToGuild(this, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL); } break; } case CHAT_MSG_OFFICER: { std::string msg = ""; recv_data >> msg; if(msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if(msg.empty()) break; if (GetPlayer()->GetGuildId()) { Guild *guild = sObjectMgr.GetGuildById(GetPlayer()->GetGuildId()); if (guild) guild->BroadcastToOfficers(this, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL); } break; } case CHAT_MSG_RAID: { std::string msg=""; recv_data >> msg; if(msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if(msg.empty()) break; //sChatLog.RaidMsg(GetPlayer(), msg, type); Group *group = GetPlayer()->GetGroup(); if(!group || !group->isRaidGroup()) return; WorldPacket data; ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID, lang, "", 0, msg.c_str(),NULL); group->BroadcastPacket(&data); } break; case CHAT_MSG_RAID_LEADER: { std::string msg=""; recv_data >> msg; if(msg.empty()) break; if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) break; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if(msg.empty()) break; //sChatLog.RaidMsg(GetPlayer(), msg, type); Group *group = GetPlayer()->GetGroup(); if(!group || !group->isRaidGroup() || !group->IsLeader(GetPlayer()->GetGUID())) return; WorldPacket data; ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_LEADER, lang, "", 0, msg.c_str(),NULL); group->BroadcastPacket(&data); } break; case CHAT_MSG_RAID_WARNING: { std::string msg=""; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if(msg.empty()) break; //sChatLog.RaidMsg(GetPlayer(), msg, type); Group *group = GetPlayer()->GetGroup(); if(!group || !group->isRaidGroup() || !(group->IsLeader(GetPlayer()->GetGUID()) || group->IsAssistant(GetPlayer()->GetGUID()))) return; WorldPacket data; ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_WARNING, lang, "", 0, msg.c_str(),NULL); group->BroadcastPacket(&data); } break; case CHAT_MSG_BATTLEGROUND: { std::string msg=""; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if(msg.empty()) break; //sChatLog.BattleGroundMsg(GetPlayer(), msg, type); Group *group = GetPlayer()->GetGroup(); if(!group || !group->isRaidGroup()) return; WorldPacket data; ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND, lang, "", 0, msg.c_str(),NULL); group->BroadcastPacket(&data); } break; case CHAT_MSG_BATTLEGROUND_LEADER: { std::string msg=""; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if(msg.empty()) break; //sChatLog.BattleGroundMsg(GetPlayer(), msg, type); Group *group = GetPlayer()->GetGroup(); if(!group || !group->isRaidGroup() || !group->IsLeader(GetPlayer()->GetGUID())) return; WorldPacket data; ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND_LEADER, lang, "", 0, msg.c_str(),NULL); group->BroadcastPacket(&data); } break; case CHAT_MSG_CHANNEL: { std::string channel = "", msg = ""; recv_data >> channel; recv_data >> msg; if (!processChatmessageFurtherAfterSecurityChecks(msg, lang)) return; if(msg.empty()) break; //sChatLog.ChannelMsg(GetPlayer(), channel, msg); if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) { if(Channel *chn = cMgr->GetChannel(channel,_player)) chn->Say(_player->GetGUID(),msg.c_str(),lang); } } break; case CHAT_MSG_AFK: { std::string msg; recv_data >> msg; if((msg.empty() || !_player->isAFK()) && !_player->isInCombat() ) { if(!_player->isAFK()) { if(msg.empty()) msg = GetMangosString(LANG_PLAYER_AFK_DEFAULT); _player->afkMsg = msg; } _player->ToggleAFK(); if(_player->isAFK() && _player->isDND()) _player->ToggleDND(); } } break; case CHAT_MSG_DND: { std::string msg; recv_data >> msg; if(msg.empty() || !_player->isDND()) { if(!_player->isDND()) { if(msg.empty()) msg = GetMangosString(LANG_PLAYER_DND_DEFAULT); _player->dndMsg = msg; } _player->ToggleDND(); if(_player->isDND() && _player->isAFK()) _player->ToggleAFK(); } } break; default: sLog.outError("CHAT: unknown message type %u, lang: %u", type, lang); break; } }