mirror of
https://github.com/mangosfour/server.git
synced 2025-12-21 10:37:06 +00:00
[0036] Fix chat handler. Author: @DDuarte
Signed-off-by: Yaki Khadafi <elsoldollo@gmail.com>
This commit is contained in:
parent
27f2d4ce1c
commit
c05133f8fb
12 changed files with 352 additions and 121 deletions
|
|
@ -63,100 +63,121 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
uint32 type;
|
||||
uint32 lang;
|
||||
|
||||
recv_data >> type;
|
||||
recv_data >> lang;
|
||||
|
||||
if (type >= MAX_CHAT_MSG_TYPE)
|
||||
switch (recv_data.GetOpcode())
|
||||
{
|
||||
sLog.outError("CHAT: Wrong message type received: %u", type);
|
||||
return;
|
||||
case CMSG_MESSAGECHAT_SAY: type = CHAT_MSG_SAY; break;
|
||||
case CMSG_MESSAGECHAT_YELL: type = CHAT_MSG_YELL; break;
|
||||
case CMSG_MESSAGECHAT_CHANNEL: type = CHAT_MSG_CHANNEL; break;
|
||||
case CMSG_MESSAGECHAT_WHISPER: type = CHAT_MSG_WHISPER; break;
|
||||
case CMSG_MESSAGECHAT_GUILD: type = CHAT_MSG_GUILD; break;
|
||||
case CMSG_MESSAGECHAT_OFFICER: type = CHAT_MSG_OFFICER; break;
|
||||
case CMSG_MESSAGECHAT_AFK: type = CHAT_MSG_AFK; break;
|
||||
case CMSG_MESSAGECHAT_DND: type = CHAT_MSG_DND; break;
|
||||
case CMSG_MESSAGECHAT_EMOTE: type = CHAT_MSG_EMOTE; break;
|
||||
case CMSG_MESSAGECHAT_PARTY: type = CHAT_MSG_PARTY; break;
|
||||
case CMSG_MESSAGECHAT_RAID: type = CHAT_MSG_RAID; break;
|
||||
case CMSG_MESSAGECHAT_BATTLEGROUND: type = CHAT_MSG_BATTLEGROUND; break;
|
||||
case CMSG_MESSAGECHAT_RAID_WARNING: type = CHAT_MSG_RAID_WARNING; break;
|
||||
default:
|
||||
sLog.outError("HandleMessagechatOpcode : Unknown chat opcode (0x%X)", recv_data.GetOpcode());
|
||||
recv_data.rfinish();
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_LOG("CHAT: packet received. type %u, lang %u", type, lang);
|
||||
// no language sent with emote packet.
|
||||
if (type != CHAT_MSG_EMOTE && type != CHAT_MSG_AFK && type != CHAT_MSG_DND)
|
||||
{
|
||||
recv_data >> 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)
|
||||
// prevent talking at unknown language (cheating)
|
||||
LanguageDesc const* langDesc = GetLanguageDescByID(lang);
|
||||
if (!langDesc)
|
||||
{
|
||||
if ((*i)->GetModifier()->m_miscvalue == int32(lang))
|
||||
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)
|
||||
{
|
||||
foundAura = true;
|
||||
break;
|
||||
if ((*i)->GetModifier()->m_miscvalue == int32(lang))
|
||||
{
|
||||
foundAura = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundAura)
|
||||
{
|
||||
SendNotification(LANG_NOT_LEARNED_LANGUAGE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
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;
|
||||
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 in two side iteration allowed mode
|
||||
if (sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_CHAT))
|
||||
// send in universal language if player in .gmon mode (ignore spell effects)
|
||||
if (_player->isGameMaster())
|
||||
lang = LANG_UNIVERSAL;
|
||||
else
|
||||
{
|
||||
switch (type)
|
||||
// send in universal language in two side iteration allowed mode
|
||||
if (sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_CHAT))
|
||||
lang = LANG_UNIVERSAL;
|
||||
else
|
||||
{
|
||||
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;
|
||||
switch (type)
|
||||
{
|
||||
case CHAT_MSG_PARTY:
|
||||
case CHAT_MSG_PARTY_LEADER:
|
||||
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;
|
||||
}
|
||||
|
||||
// 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())
|
||||
if (type != CHAT_MSG_AFK && type != CHAT_MSG_DND)
|
||||
{
|
||||
std::string timeStr = secsToTimeString(m_muteTime - time(NULL));
|
||||
SendNotification(GetMangosString(LANG_WAIT_BEFORE_SPEAKING), timeStr.c_str());
|
||||
return;
|
||||
}
|
||||
if (!_player->CanSpeak())
|
||||
{
|
||||
std::string timeStr = secsToTimeString(m_muteTime - time(NULL));
|
||||
SendNotification(GetMangosString(LANG_WAIT_BEFORE_SPEAKING), timeStr.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
GetPlayer()->UpdateSpeakTime();
|
||||
GetPlayer()->UpdateSpeakTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
lang = LANG_UNIVERSAL;
|
||||
|
||||
DEBUG_LOG("CHAT: packet received. type %u lang %u", type, lang);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
|
|
@ -165,7 +186,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
case CHAT_MSG_YELL:
|
||||
{
|
||||
std::string msg;
|
||||
recv_data >> msg;
|
||||
msg = recv_data.ReadString(recv_data.ReadBits(9));
|
||||
|
||||
if (msg.empty())
|
||||
break;
|
||||
|
|
@ -190,8 +211,10 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
case CHAT_MSG_WHISPER:
|
||||
{
|
||||
std::string to, msg;
|
||||
recv_data >> to;
|
||||
recv_data >> msg;
|
||||
uint32 toLength = recv_data.ReadBits(10);
|
||||
uint32 msgLength = recv_data.ReadBits(9);
|
||||
to = recv_data.ReadString(toLength);
|
||||
msg = recv_data.ReadString(msgLength);
|
||||
|
||||
if (!processChatmessageFurtherAfterSecurityChecks(msg, lang))
|
||||
return;
|
||||
|
|
@ -230,7 +253,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
case CHAT_MSG_PARTY_LEADER:
|
||||
{
|
||||
std::string msg;
|
||||
recv_data >> msg;
|
||||
msg = recv_data.ReadString(recv_data.ReadBits(9));
|
||||
|
||||
if (msg.empty())
|
||||
break;
|
||||
|
|
@ -265,7 +288,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
case CHAT_MSG_GUILD:
|
||||
{
|
||||
std::string msg;
|
||||
recv_data >> msg;
|
||||
msg = recv_data.ReadString(recv_data.ReadBits(9));
|
||||
|
||||
if (msg.empty())
|
||||
break;
|
||||
|
|
@ -288,7 +311,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
case CHAT_MSG_OFFICER:
|
||||
{
|
||||
std::string msg;
|
||||
recv_data >> msg;
|
||||
msg = recv_data.ReadString(recv_data.ReadBits(9));
|
||||
|
||||
if (msg.empty())
|
||||
break;
|
||||
|
|
@ -311,7 +334,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
case CHAT_MSG_RAID:
|
||||
{
|
||||
std::string msg;
|
||||
recv_data >> msg;
|
||||
msg = recv_data.ReadString(recv_data.ReadBits(9));
|
||||
|
||||
if (msg.empty())
|
||||
break;
|
||||
|
|
@ -341,7 +364,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
case CHAT_MSG_RAID_LEADER:
|
||||
{
|
||||
std::string msg;
|
||||
recv_data >> msg;
|
||||
msg = recv_data.ReadString(recv_data.ReadBits(9));
|
||||
|
||||
if (msg.empty())
|
||||
break;
|
||||
|
|
@ -372,7 +395,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
case CHAT_MSG_RAID_WARNING:
|
||||
{
|
||||
std::string msg;
|
||||
recv_data >> msg;
|
||||
msg = recv_data.ReadString(recv_data.ReadBits(9));
|
||||
|
||||
if (!processChatmessageFurtherAfterSecurityChecks(msg, lang))
|
||||
return;
|
||||
|
|
@ -394,7 +417,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
case CHAT_MSG_BATTLEGROUND:
|
||||
{
|
||||
std::string msg;
|
||||
recv_data >> msg;
|
||||
msg = recv_data.ReadString(recv_data.ReadBits(9));
|
||||
|
||||
if (!processChatmessageFurtherAfterSecurityChecks(msg, lang))
|
||||
return;
|
||||
|
|
@ -415,7 +438,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
case CHAT_MSG_BATTLEGROUND_LEADER:
|
||||
{
|
||||
std::string msg;
|
||||
recv_data >> msg;
|
||||
msg = recv_data.ReadString(recv_data.ReadBits(9));
|
||||
|
||||
if (!processChatmessageFurtherAfterSecurityChecks(msg, lang))
|
||||
return;
|
||||
|
|
@ -436,8 +459,10 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
case CHAT_MSG_CHANNEL:
|
||||
{
|
||||
std::string channel, msg;
|
||||
recv_data >> channel;
|
||||
recv_data >> msg;
|
||||
uint32 channelLength = recv_data.ReadBits(10);
|
||||
uint32 msgLength = recv_data.ReadBits(9);
|
||||
msg = recv_data.ReadString(msgLength);
|
||||
channel = recv_data.ReadString(channelLength);
|
||||
|
||||
if (!processChatmessageFurtherAfterSecurityChecks(msg, lang))
|
||||
return;
|
||||
|
|
@ -453,7 +478,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
case CHAT_MSG_AFK:
|
||||
{
|
||||
std::string msg;
|
||||
recv_data >> msg;
|
||||
msg = recv_data.ReadString(recv_data.ReadBits(9));
|
||||
|
||||
if (!_player->isInCombat())
|
||||
{
|
||||
|
|
@ -479,7 +504,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
case CHAT_MSG_DND:
|
||||
{
|
||||
std::string msg;
|
||||
recv_data >> msg;
|
||||
msg = recv_data.ReadString(recv_data.ReadBits(9));
|
||||
|
||||
if (_player->isDND()) // Already DND
|
||||
{
|
||||
|
|
@ -506,6 +531,116 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleAddonMessagechatOpcode(WorldPacket& recv_data)
|
||||
{
|
||||
uint32 type;
|
||||
|
||||
switch (recv_data.GetOpcode())
|
||||
{
|
||||
case CMSG_MESSAGECHAT_ADDON_BATTLEGROUND: type = CHAT_MSG_BATTLEGROUND; break;
|
||||
case CMSG_MESSAGECHAT_ADDON_GUILD: type = CHAT_MSG_GUILD; break;
|
||||
case CMSG_MESSAGECHAT_ADDON_OFFICER: type = CHAT_MSG_OFFICER; break;
|
||||
case CMSG_MESSAGECHAT_ADDON_PARTY: type = CHAT_MSG_PARTY; break;
|
||||
case CMSG_MESSAGECHAT_ADDON_RAID: type = CHAT_MSG_RAID; break;
|
||||
case CMSG_MESSAGECHAT_ADDON_WHISPER: type = CHAT_MSG_WHISPER; break;
|
||||
default:
|
||||
sLog.outError("HandleAddonMessagechatOpcode: Unknown addon chat opcode (0x%X)", recv_data.GetOpcode());
|
||||
recv_data.rfinish();
|
||||
return;
|
||||
}
|
||||
|
||||
// Disabled addon channel?
|
||||
if (!sWorld.getConfig(CONFIG_BOOL_ADDON_CHANNEL))
|
||||
return;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case CHAT_MSG_BATTLEGROUND:
|
||||
{
|
||||
uint32 msgLen = recv_data.ReadBits(9);
|
||||
uint32 prefixLen = recv_data.ReadBits(5);
|
||||
std::string msg = recv_data.ReadString(msgLen);
|
||||
std::string prefix = recv_data.ReadString(prefixLen);
|
||||
|
||||
Group* group = _player->GetGroup();
|
||||
if (!group || !group->isBGGroup())
|
||||
return;
|
||||
|
||||
WorldPacket data;
|
||||
ChatHandler::FillMessageData(&data, this, type, LANG_ADDON, "", ObjectGuid(), msg.c_str(), NULL);
|
||||
group->BroadcastPacket(&data, false);
|
||||
break;
|
||||
}
|
||||
case CHAT_MSG_GUILD:
|
||||
{
|
||||
uint32 msgLen = recv_data.ReadBits(9);
|
||||
uint32 prefixLen = recv_data.ReadBits(5);
|
||||
std::string msg = recv_data.ReadString(msgLen);
|
||||
std::string prefix = recv_data.ReadString(prefixLen);
|
||||
|
||||
if (_player->GetGuildId())
|
||||
if (Guild* guild = sGuildMgr.GetGuildById(_player->GetGuildId()))
|
||||
guild->BroadcastAddonToGuild(this, msg, prefix);
|
||||
|
||||
break;
|
||||
}
|
||||
case CHAT_MSG_OFFICER:
|
||||
{
|
||||
uint32 prefixLen = recv_data.ReadBits(5);
|
||||
uint32 msgLen = recv_data.ReadBits(9);
|
||||
std::string prefix = recv_data.ReadString(prefixLen);
|
||||
std::string msg = recv_data.ReadString(msgLen);
|
||||
|
||||
if (_player->GetGuildId())
|
||||
if (Guild* guild = sGuildMgr.GetGuildById(_player->GetGuildId()))
|
||||
guild->BroadcastAddonToOfficers(this, msg, prefix);
|
||||
break;
|
||||
}
|
||||
case CHAT_MSG_WHISPER:
|
||||
{
|
||||
uint32 msgLen = recv_data.ReadBits(9);
|
||||
uint32 prefixLen = recv_data.ReadBits(5);
|
||||
uint32 targetLen = recv_data.ReadBits(10);
|
||||
std::string msg = recv_data.ReadString(msgLen);
|
||||
std::string prefix = recv_data.ReadString(prefixLen);
|
||||
std::string targetName = recv_data.ReadString(targetLen);
|
||||
|
||||
if (!normalizePlayerName(targetName))
|
||||
break;
|
||||
|
||||
Player* receiver = sObjectMgr.GetPlayer(targetName.c_str());
|
||||
if (!receiver)
|
||||
break;
|
||||
|
||||
_player->WhisperAddon(msg, prefix, receiver->GetObjectGuid());
|
||||
break;
|
||||
}
|
||||
// Messages sent to "RAID" while in a party will get delivered to "PARTY"
|
||||
case CHAT_MSG_PARTY:
|
||||
case CHAT_MSG_RAID:
|
||||
{
|
||||
uint32 prefixLen = recv_data.ReadBits(5);
|
||||
uint32 msgLen = recv_data.ReadBits(9);
|
||||
std::string prefix = recv_data.ReadString(prefixLen);
|
||||
std::string msg = recv_data.ReadString(msgLen);
|
||||
|
||||
Group* group = _player->GetGroup();
|
||||
if (!group || group->isBGGroup())
|
||||
break;
|
||||
|
||||
WorldPacket data;
|
||||
ChatHandler::FillMessageData(&data, this, type, LANG_ADDON, "", ObjectGuid(), msg.c_str(), NULL, prefix.c_str());
|
||||
group->BroadcastPacket(&data, false, group->GetMemberGroup(_player->GetObjectGuid()));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
sLog.outError("HandleAddonMessagechatOpcode: unknown addon message type %u", type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleEmoteOpcode(WorldPacket& recv_data)
|
||||
{
|
||||
if (!GetPlayer()->isAlive() || GetPlayer()->hasUnitState(UNIT_STAT_DIED))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue