From c05133f8fba0fbfd071721b2169833bcf650016e Mon Sep 17 00:00:00 2001 From: Yaki Khadafi Date: Thu, 9 Aug 2012 17:34:02 +0300 Subject: [PATCH] [0036] Fix chat handler. Author: @DDuarte Signed-off-by: Yaki Khadafi --- src/game/Chat.cpp | 17 ++- src/game/Chat.h | 2 +- src/game/ChatHandler.cpp | 309 ++++++++++++++++++++++++++++----------- src/game/Guild.cpp | 34 +++++ src/game/Guild.h | 2 + src/game/Object.cpp | 2 + src/game/Opcodes.cpp | 34 ++++- src/game/Opcodes.h | 32 +++- src/game/Player.cpp | 35 +++-- src/game/Player.h | 3 +- src/game/WorldSession.h | 1 + src/shared/revision_nr.h | 2 +- 12 files changed, 352 insertions(+), 121 deletions(-) diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 0e41ffe7d..8378e39db 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -2043,7 +2043,7 @@ bool ChatHandler::isValidChatMessage(const char* message) } // Note: target_guid used only in CHAT_MSG_WHISPER_INFORM mode (in this case channelName ignored) -void ChatHandler::FillMessageData(WorldPacket* data, WorldSession* session, uint8 type, uint32 language, const char* channelName, ObjectGuid targetGuid, const char* message, Unit* speaker) +void ChatHandler::FillMessageData(WorldPacket* data, WorldSession* session, uint8 type, uint32 language, const char* channelName, ObjectGuid targetGuid, const char* message, Unit* speaker, const char* addonPrefix /*= NULL*/) { uint32 messageLength = (message ? strlen(message) : 0) + 1; @@ -2097,6 +2097,12 @@ void ChatHandler::FillMessageData(WorldPacket* data, WorldSession* session, uint *data << uint32(messageLength); *data << message; *data << uint8(0); + + if (type == CHAT_MSG_RAID_BOSS_WHISPER || type == CHAT_MSG_RAID_BOSS_EMOTE) + { + *data << float(0.0f); // Added in 4.2.0, unk + *data << uint8(0); // Added in 4.2.0, unk + } return; } default: @@ -2112,9 +2118,16 @@ void ChatHandler::FillMessageData(WorldPacket* data, WorldSession* session, uint { MANGOS_ASSERT(channelName); *data << channelName; + *data << ObjectGuid(targetGuid); } + else if (type == CHAT_MSG_ADDON) + { + MANGOS_ASSERT(addonPrefix); + *data << addonPrefix; + } + else + *data << ObjectGuid(targetGuid); - *data << ObjectGuid(targetGuid); *data << uint32(messageLength); *data << message; if (session != 0 && type != CHAT_MSG_WHISPER_INFORM && type != CHAT_MSG_DND && type != CHAT_MSG_AFK) diff --git a/src/game/Chat.h b/src/game/Chat.h index 14b65d723..27134096c 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -69,7 +69,7 @@ class MANGOS_DLL_SPEC ChatHandler explicit ChatHandler(Player* player); ~ChatHandler(); - static void FillMessageData(WorldPacket* data, WorldSession* session, uint8 type, uint32 language, const char* channelName, ObjectGuid targetGuid, const char* message, Unit* speaker); + static void FillMessageData(WorldPacket* data, WorldSession* session, uint8 type, uint32 language, const char* channelName, ObjectGuid targetGuid, const char* message, Unit* speaker, const char* addonPrefix = NULL); static void FillMessageData(WorldPacket* data, WorldSession* session, uint8 type, uint32 language, ObjectGuid targetGuid, const char* message) { diff --git a/src/game/ChatHandler.cpp b/src/game/ChatHandler.cpp index b3ddd38cf..1c7373968 100644 --- a/src/game/ChatHandler.cpp +++ b/src/game/ChatHandler.cpp @@ -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)) diff --git a/src/game/Guild.cpp b/src/game/Guild.cpp index 6db99234c..ffc5409f5 100644 --- a/src/game/Guild.cpp +++ b/src/game/Guild.cpp @@ -575,6 +575,23 @@ void Guild::BroadcastToGuild(WorldSession* session, const std::string& msg, uint } } +void Guild::BroadcastAddonToGuild(WorldSession* session, const std::string& msg, const std::string& prefix) +{ + if (session && session->GetPlayer() && HasRankRight(session->GetPlayer()->GetRank(), GR_RIGHT_GCHATSPEAK)) + { + WorldPacket data; + ChatHandler::FillMessageData(&data, session,CHAT_MSG_GUILD, CHAT_MSG_ADDON, NULL, ObjectGuid(), msg.c_str(), NULL, prefix.c_str()); + + for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr) + { + Player* pl = ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER, itr->first)); + + if (pl && pl->GetSession() && HasRankRight(pl->GetRank(), GR_RIGHT_GCHATLISTEN) && !pl->GetSocial()->HasIgnore(session->GetPlayer()->GetObjectGuid())) + pl->GetSession()->SendPacket(&data); + } + } +} + void Guild::BroadcastToOfficers(WorldSession* session, const std::string& msg, uint32 language) { if (session && session->GetPlayer() && HasRankRight(session->GetPlayer()->GetRank(), GR_RIGHT_OFFCHATSPEAK)) @@ -592,6 +609,23 @@ void Guild::BroadcastToOfficers(WorldSession* session, const std::string& msg, u } } +void Guild::BroadcastAddonToOfficers(WorldSession* session, const std::string& msg, const std::string& prefix) +{ + if (session && session->GetPlayer() && HasRankRight(session->GetPlayer()->GetRank(), GR_RIGHT_OFFCHATSPEAK)) + { + for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr) + { + WorldPacket data; + ChatHandler::FillMessageData(&data, session, CHAT_MSG_OFFICER, CHAT_MSG_ADDON, NULL, ObjectGuid(), msg.c_str(), NULL, prefix.c_str()); + + Player* pl = ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER, itr->first)); + + if (pl && pl->GetSession() && HasRankRight(pl->GetRank(), GR_RIGHT_OFFCHATLISTEN) && !pl->GetSocial()->HasIgnore(session->GetPlayer()->GetObjectGuid())) + pl->GetSession()->SendPacket(&data); + } + } +} + void Guild::BroadcastPacket(WorldPacket* packet) { for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr) diff --git a/src/game/Guild.h b/src/game/Guild.h index b071a964a..728011df8 100644 --- a/src/game/Guild.h +++ b/src/game/Guild.h @@ -343,7 +343,9 @@ class Guild bool LoadMembersFromDB(QueryResult* guildMembersResult); void BroadcastToGuild(WorldSession* session, const std::string& msg, uint32 language = LANG_UNIVERSAL); + void BroadcastAddonToGuild(WorldSession* session, const std::string& msg, const std::string& prefix); void BroadcastToOfficers(WorldSession* session, const std::string& msg, uint32 language = LANG_UNIVERSAL); + void BroadcastAddonToOfficers(WorldSession* session, const std::string& msg, const std::string& prefix); void BroadcastPacketToRank(WorldPacket* packet, uint32 rankId); void BroadcastPacket(WorldPacket* packet); diff --git a/src/game/Object.cpp b/src/game/Object.cpp index 2b6effe8a..641724a33 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -1627,6 +1627,8 @@ void WorldObject::BuildMonsterChat(WorldPacket* data, ObjectGuid senderGuid, uin *data << uint32(strlen(text) + 1); *data << text; *data << uint8(0); // ChatTag + *data << float(0.0f); + *data << uint8(0); } void WorldObject::SendMessageToSet(WorldPacket* data, bool /*bToSelf*/) diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp index 16b1eb549..1a859fe06 100644 --- a/src/game/Opcodes.cpp +++ b/src/game/Opcodes.cpp @@ -194,8 +194,26 @@ void InitializeOpcodes() //OPCODE(SMSG_GUILD_EVENT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(SMSG_GUILD_COMMAND_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(UMSG_UPDATE_GUILD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //OPCODE(CMSG_MESSAGECHAT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode ); - //OPCODE(SMSG_MESSAGECHAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(CMSG_MESSAGECHAT_ADDON_BATTLEGROUND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonMessagechatOpcode ); + OPCODE(CMSG_MESSAGECHAT_ADDON_GUILD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonMessagechatOpcode ); + OPCODE(CMSG_MESSAGECHAT_ADDON_OFFICER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonMessagechatOpcode ); + OPCODE(CMSG_MESSAGECHAT_ADDON_PARTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonMessagechatOpcode ); + OPCODE(CMSG_MESSAGECHAT_ADDON_RAID, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonMessagechatOpcode ); + OPCODE(CMSG_MESSAGECHAT_ADDON_WHISPER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonMessagechatOpcode ); + OPCODE(CMSG_MESSAGECHAT_AFK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode ); + OPCODE(CMSG_MESSAGECHAT_BATTLEGROUND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode ); + OPCODE(CMSG_MESSAGECHAT_CHANNEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode ); + OPCODE(CMSG_MESSAGECHAT_DND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode ); + OPCODE(CMSG_MESSAGECHAT_EMOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode ); + OPCODE(CMSG_MESSAGECHAT_GUILD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode ); + OPCODE(CMSG_MESSAGECHAT_OFFICER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode ); + OPCODE(CMSG_MESSAGECHAT_PARTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode ); + OPCODE(CMSG_MESSAGECHAT_RAID, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode ); + OPCODE(CMSG_MESSAGECHAT_RAID_WARNING, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode ); + OPCODE(CMSG_MESSAGECHAT_SAY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode ); + OPCODE(CMSG_MESSAGECHAT_WHISPER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode ); + OPCODE(CMSG_MESSAGECHAT_YELL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMessagechatOpcode ); + OPCODE(SMSG_MESSAGECHAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(CMSG_JOIN_CHANNEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleJoinChannelOpcode ); //OPCODE(CMSG_LEAVE_CHANNEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLeaveChannelOpcode ); OPCODE(SMSG_CHANNEL_NOTIFY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); @@ -302,11 +320,11 @@ void InitializeOpcodes() //OPCODE(CMSG_TUTORIAL_FLAG, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTutorialFlagOpcode ); //OPCODE(CMSG_TUTORIAL_CLEAR, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTutorialClearOpcode ); //OPCODE(CMSG_TUTORIAL_RESET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTutorialResetOpcode ); - //OPCODE(CMSG_STANDSTATECHANGE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleStandStateChangeOpcode ); - //OPCODE(CMSG_EMOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEmoteOpcode ); - //OPCODE(SMSG_EMOTE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //OPCODE(CMSG_TEXT_EMOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTextEmoteOpcode ); - //OPCODE(SMSG_TEXT_EMOTE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(CMSG_STANDSTATECHANGE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleStandStateChangeOpcode ); + OPCODE(CMSG_EMOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEmoteOpcode ); + OPCODE(SMSG_EMOTE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(CMSG_TEXT_EMOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTextEmoteOpcode ); + OPCODE(SMSG_TEXT_EMOTE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(CMSG_AUTOEQUIP_GROUND_ITEM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //OPCODE(CMSG_AUTOSTORE_GROUND_ITEM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //OPCODE(CMSG_AUTOSTORE_LOOT_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAutostoreLootItemOpcode ); @@ -711,7 +729,7 @@ void InitializeOpcodes() //OPCODE(CMSG_GMTICKETSYSTEM_TOGGLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //OPCODE(CMSG_CANCEL_GROWTH_AURA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelGrowthAuraOpcode ); //OPCODE(SMSG_CANCEL_AUTO_REPEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //OPCODE(SMSG_STANDSTATE_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(SMSG_STANDSTATE_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(SMSG_LOOT_ALL_PASSED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(SMSG_LOOT_ROLL_WON, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(CMSG_LOOT_ROLL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLootRoll ); diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h index 9b65fb223..6377e43be 100644 --- a/src/game/Opcodes.h +++ b/src/game/Opcodes.h @@ -188,8 +188,26 @@ enum Opcodes SMSG_GUILD_EVENT = 0x1093, SMSG_GUILD_COMMAND_RESULT = 0x1094, UMSG_UPDATE_GUILD = 0x1095, + CMSG_MESSAGECHAT_ADDON_BATTLEGROUND = 0x0D46, // 4.3.4 15595 + CMSG_MESSAGECHAT_ADDON_GUILD = 0x0544, // 4.3.4 15595 + CMSG_MESSAGECHAT_ADDON_OFFICER = 0x3954, // 4.3.4 15595 + CMSG_MESSAGECHAT_ADDON_PARTY = 0x0546, // 4.3.4 15595 + CMSG_MESSAGECHAT_ADDON_RAID = 0x1D56, // 4.3.4 15595 + CMSG_MESSAGECHAT_ADDON_WHISPER = 0x2146, // 4.3.4 15595 + CMSG_MESSAGECHAT_AFK = 0x0D44, // 4.3.4 15595 + CMSG_MESSAGECHAT_BATTLEGROUND = 0x2156, // 4.3.4 15595 + CMSG_MESSAGECHAT_CHANNEL = 0x1D44, // 4.3.4 15595 + CMSG_MESSAGECHAT_DND = 0x2946, // 4.3.4 15595 + CMSG_MESSAGECHAT_EMOTE = 0x1156, // 4.3.4 15595 + CMSG_MESSAGECHAT_GUILD = 0x3956, // 4.3.4 15595 + CMSG_MESSAGECHAT_OFFICER = 0x1946, // 4.3.4 15595 + CMSG_MESSAGECHAT_PARTY = 0x1D46, // 4.3.4 15595 + CMSG_MESSAGECHAT_RAID = 0x2D44, // 4.3.4 15595 + CMSG_MESSAGECHAT_RAID_WARNING = 0x0944, // 4.3.4 15595 CMSG_MESSAGECHAT_SAY = 0x1154, // 4.3.4 15595 - SMSG_MESSAGECHAT = 0x1097, + CMSG_MESSAGECHAT_WHISPER = 0x0D56, // 4.3.4 15595 + CMSG_MESSAGECHAT_YELL = 0x3544, // 4.3.4 15595 + SMSG_MESSAGECHAT = 0x2026, // 4.3.4 15595 CMSG_JOIN_CHANNEL = 0x0156, // 4.3.4 15595 CMSG_LEAVE_CHANNEL = 0x1099, SMSG_CHANNEL_NOTIFY = 0x0825, // 4.3.4 15595 @@ -296,11 +314,11 @@ enum Opcodes CMSG_TUTORIAL_FLAG = 0x10FF, CMSG_TUTORIAL_CLEAR = 0x1100, CMSG_TUTORIAL_RESET = 0x1101, - CMSG_STANDSTATECHANGE = 0x1102, - CMSG_EMOTE = 0x1103, - SMSG_EMOTE = 0x1104, - CMSG_TEXT_EMOTE = 0x1105, - SMSG_TEXT_EMOTE = 0x1106, + CMSG_STANDSTATECHANGE = 0x0535, // 4.3.4 15595 + CMSG_EMOTE = 0x4C26, // 4.3.4 15595 + SMSG_EMOTE = 0x0A34, // 4.3.4 15595 + CMSG_TEXT_EMOTE = 0x2E24, // 4.3.4 15595 + SMSG_TEXT_EMOTE = 0x0B05, // 4.3.4 15595 CMSG_AUTOEQUIP_GROUND_ITEM = 0x1107, CMSG_AUTOSTORE_GROUND_ITEM = 0x1108, CMSG_AUTOSTORE_LOOT_ITEM = 0x1109, @@ -705,7 +723,7 @@ enum Opcodes CMSG_GMTICKETSYSTEM_TOGGLE = 0x129B, CMSG_CANCEL_GROWTH_AURA = 0x129C, SMSG_CANCEL_AUTO_REPEAT = 0x129D, - SMSG_STANDSTATE_UPDATE = 0x129E, + SMSG_STANDSTATE_UPDATE = 0x6F04, // 4.3.4 15595 SMSG_LOOT_ALL_PASSED = 0x129F, SMSG_LOOT_ROLL_WON = 0x12A0, CMSG_LOOT_ROLL = 0x12A1, diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 92357ae47..d02392b0c 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18572,13 +18572,16 @@ void Player::RemovePet(PetSaveMode mode) pet->Unsummon(mode, this); } -void Player::BuildPlayerChat(WorldPacket* data, uint8 msgtype, const std::string& text, uint32 language) const +void Player::BuildPlayerChat(WorldPacket* data, uint8 msgtype, const std::string& text, uint32 language, const char* addonPrefix) const { *data << uint8(msgtype); *data << uint32(language); - *data << ObjectGuid(GetObjectGuid()); - *data << uint32(language); // language 2.1.0 ? - *data << ObjectGuid(GetObjectGuid()); + *data << GetObjectGuid(); + *data << uint32(0); // constant unknown time 4.3.4 + if (addonPrefix) + *data << addonPrefix; + else + *data << GetObjectGuid(); *data << uint32(text.length() + 1); *data << text; *data << uint8(GetChatTag()); @@ -18607,22 +18610,15 @@ void Player::TextEmote(const std::string& text) void Player::Whisper(const std::string& text, uint32 language, ObjectGuid receiver) { - if (language != LANG_ADDON) // if not addon data - language = LANG_UNIVERSAL; // whispers should always be readable - Player* rPlayer = sObjectMgr.GetPlayer(receiver); WorldPacket data(SMSG_MESSAGECHAT, 200); BuildPlayerChat(&data, CHAT_MSG_WHISPER, text, language); rPlayer->GetSession()->SendPacket(&data); - // not send confirmation for addon messages - if (language != LANG_ADDON) - { - data.Initialize(SMSG_MESSAGECHAT, 200); - rPlayer->BuildPlayerChat(&data, CHAT_MSG_WHISPER_INFORM, text, language); - GetSession()->SendPacket(&data); - } + data.Initialize(SMSG_MESSAGECHAT, 200); + rPlayer->BuildPlayerChat(&data, CHAT_MSG_WHISPER_INFORM, text, language); + GetSession()->SendPacket(&data); if (!isAcceptWhispers()) { @@ -18637,6 +18633,17 @@ void Player::Whisper(const std::string& text, uint32 language, ObjectGuid receiv ChatHandler(this).PSendSysMessage(LANG_PLAYER_DND, rPlayer->GetName(), rPlayer->autoReplyMsg.c_str()); } +void Player::WhisperAddon(const std::string& text, const std::string& prefix, ObjectGuid receiver) +{ + Player* rPlayer = sObjectMgr.GetPlayer(receiver); + + std::string _text(text); + + WorldPacket data(SMSG_MESSAGECHAT, 200); + BuildPlayerChat(&data, CHAT_MSG_WHISPER, _text, LANG_UNIVERSAL, prefix.c_str()); + rPlayer->GetSession()->SendPacket(&data); +} + void Player::PetSpellInitialize() { Pet* pet = GetPet(); diff --git a/src/game/Player.h b/src/game/Player.h index 56b1f7e0f..a2eba49fb 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1159,7 +1159,8 @@ class MANGOS_DLL_SPEC Player : public Unit void Yell(const std::string& text, const uint32 language); void TextEmote(const std::string& text); void Whisper(const std::string& text, const uint32 language, ObjectGuid receiver); - void BuildPlayerChat(WorldPacket* data, uint8 msgtype, const std::string& text, uint32 language) const; + void WhisperAddon(const std::string& text, const std::string& prefix, ObjectGuid receiver); + void BuildPlayerChat(WorldPacket* data, uint8 msgtype, const std::string& text, uint32 language, const char* addonPrefix = NULL) const; /*********************************************************/ /*** STORAGE SYSTEM ***/ diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index 34cd91a87..6c7ff35a4 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -693,6 +693,7 @@ class MANGOS_DLL_SPEC WorldSession void SendWrongFactionNotice(); void SendChatRestrictedNotice(ChatRestrictionType restriction); void HandleMessagechatOpcode(WorldPacket& recvPacket); + void HandleAddonMessagechatOpcode(WorldPacket& recvPacket); void HandleTextEmoteOpcode(WorldPacket& recvPacket); void HandleChatIgnoredOpcode(WorldPacket& recvPacket); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 988c24efd..511476178 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "0035" + #define REVISION_NR "0036" #endif // __REVISION_NR_H__