diff options
author | ariel- <ariel-@users.noreply.github.com> | 2016-10-07 00:59:56 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-10-07 00:59:56 -0300 |
commit | 66688a7855a8862666a39b9a958073aaa2489447 (patch) | |
tree | e9efaffe69a0299dc596c254a669ab6d39674688 /src | |
parent | ce45e1bf95a03be6b1f42c785e4c01dd55999d33 (diff) |
Core/Channel: revamp channel system (#17980)
* Core/Channel: change the way channels are stored and sent to client.
- Fixes multiple channels per zone when using different locales
- Connected clients will receive locally the name of the channel for their apropiate locale (if available)
- In other cases default locale name will be sent, so as to prevent breaking channel chat for those players
Closes #8411
Diffstat (limited to 'src')
-rw-r--r-- | src/server/database/Database/Implementation/CharacterDatabase.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Chat/Channels/Channel.cpp | 782 | ||||
-rw-r--r-- | src/server/game/Chat/Channels/Channel.h | 95 | ||||
-rw-r--r-- | src/server/game/Chat/Channels/ChannelAppenders.h | 476 | ||||
-rw-r--r-- | src/server/game/Chat/Channels/ChannelMgr.cpp | 162 | ||||
-rw-r--r-- | src/server/game/Chat/Channels/ChannelMgr.h | 28 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 29 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 4 | ||||
-rw-r--r-- | src/server/game/Handlers/ChannelHandler.cpp | 132 | ||||
-rw-r--r-- | src/server/game/Handlers/ChatHandler.cpp | 10 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_message.cpp | 43 |
11 files changed, 1090 insertions, 673 deletions
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index 658827662ec..bbf03248ec2 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp @@ -226,7 +226,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_SEL_CHAR_DATA_FOR_GUILD, "SELECT name, level, class, zone, account FROM characters WHERE guid = ?", CONNECTION_SYNCH); // Chat channel handling - PrepareStatement(CHAR_SEL_CHANNEL, "SELECT announce, ownership, password, bannedList FROM channels WHERE name = ? AND team = ?", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_CHANNEL, "SELECT name, announce, ownership, password, bannedList FROM channels WHERE name = ? AND team = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_INS_CHANNEL, "INSERT INTO channels(name, team, lastUsed) VALUES (?, ?, UNIX_TIMESTAMP())", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_CHANNEL, "UPDATE channels SET announce = ?, ownership = ?, password = ?, bannedList = ?, lastUsed = UNIX_TIMESTAMP() WHERE name = ? AND team = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_CHANNEL_USAGE, "UPDATE channels SET lastUsed = UNIX_TIMESTAMP() WHERE name = ? AND team = ?", CONNECTION_ASYNC); diff --git a/src/server/game/Chat/Channels/Channel.cpp b/src/server/game/Chat/Channels/Channel.cpp index 22601b711d1..85d03ef6b1f 100644 --- a/src/server/game/Chat/Channels/Channel.cpp +++ b/src/server/game/Chat/Channels/Channel.cpp @@ -17,93 +17,125 @@ */ #include "Channel.h" +#include "ChannelAppenders.h" #include "Chat.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" #include "ObjectMgr.h" +#include "Language.h" #include "SocialMgr.h" #include "World.h" #include "DatabaseEnv.h" #include "AccountMgr.h" #include "Player.h" -Channel::Channel(std::string const& name, uint32 channelId, uint32 team /*= 0*/): - _announceEnabled(true), - _ownershipEnabled(true), +Channel::Channel(uint32 channelId, uint32 team /*= 0*/, AreaTableEntry const* zoneEntry /*= nullptr*/) : + _announceEnabled(false), // no join/leave announces + _ownershipEnabled(false), // no ownership handout _persistentChannel(false), _isOwnerInvisible(false), - _channelFlags(0), + _channelFlags(CHANNEL_FLAG_GENERAL), // for all built-in channels _channelId(channelId), _channelTeam(team), _ownerGuid(), - _channelName(name), - _channelPassword() + _channelName(), + _channelPassword(), + _zoneEntry(zoneEntry) { - // set special flags if built-in channel - if (ChatChannelsEntry const* ch = sChatChannelsStore.LookupEntry(channelId)) // check whether it's a built-in channel - { - _announceEnabled = false; // no join/leave announces - _ownershipEnabled = false; // no ownership handout + ChatChannelsEntry const* channelEntry = sChatChannelsStore.AssertEntry(channelId); + if (channelEntry->flags & CHANNEL_DBC_FLAG_TRADE) // for trade channel + _channelFlags |= CHANNEL_FLAG_TRADE; - _channelFlags |= CHANNEL_FLAG_GENERAL; // for all built-in channels + if (channelEntry->flags & CHANNEL_DBC_FLAG_CITY_ONLY2) // for city only channels + _channelFlags |= CHANNEL_FLAG_CITY; - if (ch->flags & CHANNEL_DBC_FLAG_TRADE) // for trade channel - _channelFlags |= CHANNEL_FLAG_TRADE; + if (channelEntry->flags & CHANNEL_DBC_FLAG_LFG) // for LFG channel + _channelFlags |= CHANNEL_FLAG_LFG; + else // for all other channels + _channelFlags |= CHANNEL_FLAG_NOT_LFG; +} - if (ch->flags & CHANNEL_DBC_FLAG_CITY_ONLY2) // for city only channels - _channelFlags |= CHANNEL_FLAG_CITY; - if (ch->flags & CHANNEL_DBC_FLAG_LFG) // for LFG channel - _channelFlags |= CHANNEL_FLAG_LFG; - else // for all other channels - _channelFlags |= CHANNEL_FLAG_NOT_LFG; - } - else // it's custom channel +Channel::Channel(std::string const& name, uint32 team /*= 0*/) : + _announceEnabled(true), + _ownershipEnabled(true), + _persistentChannel(false), + _isOwnerInvisible(false), + _channelFlags(CHANNEL_FLAG_CUSTOM), + _channelId(0), + _channelTeam(team), + _ownerGuid(), + _channelName(name), + _channelPassword(), + _zoneEntry(nullptr) +{ + // If storing custom channels in the db is enabled either load or save the channel + if (sWorld->getBoolConfig(CONFIG_PRESERVE_CUSTOM_CHANNELS)) { - _channelFlags |= CHANNEL_FLAG_CUSTOM; - - // If storing custom channels in the db is enabled either load or save the channel - if (sWorld->getBoolConfig(CONFIG_PRESERVE_CUSTOM_CHANNELS)) + PreparedStatement *stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHANNEL); + stmt->setString(0, name); + stmt->setUInt32(1, _channelTeam); + if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) // load { - PreparedStatement *stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHANNEL); - stmt->setString(0, name); - stmt->setUInt32(1, _channelTeam); - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (result) //load + Field* fields = result->Fetch(); + _channelName = fields[0].GetString(); // re-get channel name. MySQL table collation is case insensitive + _announceEnabled = fields[1].GetBool(); + _ownershipEnabled = fields[2].GetBool(); + _channelPassword = fields[3].GetString(); + std::string db_BannedList = fields[4].GetString(); + + if (!db_BannedList.empty()) { - Field* fields = result->Fetch(); - _announceEnabled = fields[0].GetBool(); - _ownershipEnabled = fields[1].GetBool(); - _channelPassword = fields[2].GetString(); - char const* db_BannedList = fields[3].GetCString(); - - if (db_BannedList) + Tokenizer tokens(db_BannedList, ' '); + for (auto const& token : tokens) { - Tokenizer tokens(db_BannedList, ' '); - for (Tokenizer::const_iterator i = tokens.begin(); i != tokens.end(); ++i) + ObjectGuid banned_guid(uint64(atoull(token))); + if (banned_guid) { - ObjectGuid banned_guid(uint64(atoull(*i))); - if (banned_guid) - { - TC_LOG_DEBUG("chat.system", "Channel(%s) loaded bannedStore %s", name.c_str(), banned_guid.ToString().c_str()); - _bannedStore.insert(banned_guid); - } + TC_LOG_DEBUG("chat.system", "Channel(%s) loaded player %s into bannedStore", name.c_str(), banned_guid.ToString().c_str()); + _bannedStore.insert(banned_guid); } } } - else // save - { - stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHANNEL); - stmt->setString(0, name); - stmt->setUInt32(1, _channelTeam); - CharacterDatabase.Execute(stmt); - TC_LOG_DEBUG("chat.system", "Channel(%s) saved in database", name.c_str()); - } + } + else // save + { + stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHANNEL); + stmt->setString(0, name); + stmt->setUInt32(1, _channelTeam); + CharacterDatabase.Execute(stmt); + TC_LOG_DEBUG("chat.system", "Channel(%s) saved in database", name.c_str()); + } + + _persistentChannel = true; + } +} - _persistentChannel = true; +void Channel::GetChannelName(std::string& channelName, uint32 channelId, LocaleConstant locale, AreaTableEntry const* zoneEntry) +{ + if (channelId) + { + ChatChannelsEntry const* channelEntry = sChatChannelsStore.AssertEntry(channelId); + if (!(channelEntry->flags & CHANNEL_DBC_FLAG_GLOBAL)) + { + if (channelEntry->flags & CHANNEL_DBC_FLAG_CITY_ONLY) + channelName = Trinity::StringFormat(channelEntry->pattern[locale], sObjectMgr->GetTrinityString(LANG_CHANNEL_CITY, locale)); + else + channelName = Trinity::StringFormat(channelEntry->pattern[locale], ASSERT_NOTNULL(zoneEntry)->area_name[locale]); } + else + channelName = channelEntry->pattern[locale]; } } +std::string Channel::GetName(LocaleConstant locale /*= DEFAULT_LOCALE*/) const +{ + std::string result = _channelName; + Channel::GetChannelName(result, _channelId, locale, _zoneEntry); + + return result; +} + void Channel::UpdateChannelInDB() const { if (_persistentChannel) @@ -155,26 +187,26 @@ void Channel::JoinChannel(Player* player, std::string const& pass) // Do not send error message for built-in channels if (!IsConstant()) { - WorldPacket data; - MakePlayerAlreadyMember(&data, guid); - SendToOne(&data, guid); + PlayerAlreadyMemberAppend appender(guid); + ChannelNameBuilder<PlayerAlreadyMemberAppend> builder(this, appender); + SendToOne(builder, guid); } return; } if (IsBanned(guid)) { - WorldPacket data; - MakeBanned(&data); - SendToOne(&data, guid); + BannedAppend appender; + ChannelNameBuilder<BannedAppend> builder(this, appender); + SendToOne(builder, guid); return; } if (!_channelPassword.empty() && pass != _channelPassword) { - WorldPacket data; - MakeWrongPassword(&data); - SendToOne(&data, guid); + WrongPasswordAppend appender; + ChannelNameBuilder<WrongPasswordAppend> builder(this, appender); + SendToOne(builder, guid); return; } @@ -183,9 +215,9 @@ void Channel::JoinChannel(Player* player, std::string const& pass) AccountMgr::IsPlayerAccount(player->GetSession()->GetSecurity()) && //FIXME: Move to RBAC player->GetGroup()) { - WorldPacket data; - MakeNotInLfg(&data); - SendToOne(&data, guid); + NotInLFGAppend appender; + ChannelNameBuilder<NotInLFGAppend> builder(this, appender); + SendToOne(builder, guid); return; } @@ -193,9 +225,9 @@ void Channel::JoinChannel(Player* player, std::string const& pass) if (_announceEnabled && !player->GetSession()->HasPermission(rbac::RBAC_PERM_SILENTLY_JOIN_CHANNEL)) { - WorldPacket data; - MakeJoined(&data, guid); - SendToAll(&data); + JoinedAppend appender(guid); + ChannelNameBuilder<JoinedAppend> builder(this, appender); + SendToAll(builder); } bool newChannel = _playersStore.empty(); @@ -204,9 +236,9 @@ void Channel::JoinChannel(Player* player, std::string const& pass) pinfo.flags = MEMBER_FLAG_NONE; pinfo.invisible = !player->isGMVisible(); - WorldPacket data; - MakeYouJoined(&data); - SendToOne(&data, guid); + YouJoinedAppend appender(this); + ChannelNameBuilder<YouJoinedAppend> builder(this, appender); + SendToOne(builder, guid); JoinNotify(guid); @@ -236,20 +268,20 @@ void Channel::LeaveChannel(Player* player, bool send) { if (send) { - WorldPacket data; - MakeNotMember(&data); - SendToOne(&data, guid); + NotMemberAppend appender; + ChannelNameBuilder<NotMemberAppend> builder(this, appender); + SendToOne(builder, guid); } return; } if (send) { - WorldPacket data; - MakeYouLeft(&data); - SendToOne(&data, guid); + YouLeftAppend appender(this); + ChannelNameBuilder<YouLeftAppend> builder(this, appender); + SendToOne(builder, guid); + player->LeftChannel(this); - data.clear(); } PlayerInfo& info = _playersStore.at(guid); @@ -258,9 +290,9 @@ void Channel::LeaveChannel(Player* player, bool send) if (_announceEnabled && !player->GetSession()->HasPermission(rbac::RBAC_PERM_SILENTLY_JOIN_CHANNEL)) { - WorldPacket data; - MakeLeft(&data, guid); - SendToAll(&data); + LeftAppend appender(guid); + ChannelNameBuilder<LeftAppend> builder(this, appender); + SendToAll(builder); } LeaveNotify(guid); @@ -302,18 +334,18 @@ void Channel::KickOrBan(Player const* player, std::string const& badname, bool b if (!IsOn(good)) { - WorldPacket data; - MakeNotMember(&data); - SendToOne(&data, good); + NotMemberAppend appender; + ChannelNameBuilder<NotMemberAppend> builder(this, appender); + SendToOne(builder, good); return; } PlayerInfo& info = _playersStore.at(good); if (!info.IsModerator() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) { - WorldPacket data; - MakeNotModerator(&data); - SendToOne(&data, good); + NotModeratorAppend appender; + ChannelNameBuilder<NotModeratorAppend> builder(this, appender); + SendToOne(builder, good); return; } @@ -321,9 +353,9 @@ void Channel::KickOrBan(Player const* player, std::string const& badname, bool b ObjectGuid victim = bad ? bad->GetGUID() : ObjectGuid::Empty; if (!victim || !IsOn(victim)) { - WorldPacket data; - MakePlayerNotFound(&data, badname); - SendToOne(&data, good); + PlayerNotFoundAppend appender(badname); + ChannelNameBuilder<PlayerNotFoundAppend> builder(this, appender); + SendToOne(builder, good); return; } @@ -331,9 +363,9 @@ void Channel::KickOrBan(Player const* player, std::string const& badname, bool b if (!player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR) && changeowner && good != _ownerGuid) { - WorldPacket data; - MakeNotOwner(&data); - SendToOne(&data, good); + NotOwnerAppend appender; + ChannelNameBuilder<NotOwnerAppend> builder(this, appender); + SendToOne(builder, good); return; } @@ -344,16 +376,16 @@ void Channel::KickOrBan(Player const* player, std::string const& badname, bool b if (!player->GetSession()->HasPermission(rbac::RBAC_PERM_SILENTLY_JOIN_CHANNEL)) { - WorldPacket data; - MakePlayerBanned(&data, victim, good); - SendToAll(&data); + PlayerBannedAppend appender(good, victim); + ChannelNameBuilder<PlayerBannedAppend> builder(this, appender); + SendToAll(builder); } } else if (!player->GetSession()->HasPermission(rbac::RBAC_PERM_SILENTLY_JOIN_CHANNEL)) { - WorldPacket data; - MakePlayerKicked(&data, victim, good); - SendToAll(&data); + PlayerKickedAppend appender(good, victim); + ChannelNameBuilder<PlayerKickedAppend> builder(this, appender); + SendToAll(builder); } _playersStore.erase(victim); @@ -373,18 +405,18 @@ void Channel::UnBan(Player const* player, std::string const& badname) if (!IsOn(good)) { - WorldPacket data; - MakeNotMember(&data); - SendToOne(&data, good); + NotMemberAppend appender; + ChannelNameBuilder<NotMemberAppend> builder(this, appender); + SendToOne(builder, good); return; } PlayerInfo& info = _playersStore.at(good); if (!info.IsModerator() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) { - WorldPacket data; - MakeNotModerator(&data); - SendToOne(&data, good); + NotModeratorAppend appender; + ChannelNameBuilder<NotModeratorAppend> builder(this, appender); + SendToOne(builder, good); return; } @@ -393,17 +425,17 @@ void Channel::UnBan(Player const* player, std::string const& badname) if (!victim || !IsBanned(victim)) { - WorldPacket data; - MakePlayerNotFound(&data, badname); - SendToOne(&data, good); + PlayerNotFoundAppend appender(badname); + ChannelNameBuilder<PlayerNotFoundAppend> builder(this, appender); + SendToOne(builder, good); return; } _bannedStore.erase(victim); - WorldPacket data; - MakePlayerUnbanned(&data, victim, good); - SendToAll(&data); + PlayerUnbannedAppend appender(good, victim); + ChannelNameBuilder<PlayerUnbannedAppend> builder(this, appender); + SendToAll(builder); UpdateChannelInDB(); } @@ -415,26 +447,26 @@ void Channel::Password(Player const* player, std::string const& pass) ChatHandler chat(player->GetSession()); if (!IsOn(guid)) { - WorldPacket data; - MakeNotMember(&data); - SendToOne(&data, guid); + NotMemberAppend appender; + ChannelNameBuilder<NotMemberAppend> builder(this, appender); + SendToOne(builder, guid); return; } PlayerInfo& info = _playersStore.at(guid); if (!info.IsModerator() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) { - WorldPacket data; - MakeNotModerator(&data); - SendToOne(&data, guid); + NotModeratorAppend appender; + ChannelNameBuilder<NotModeratorAppend> builder(this, appender); + SendToOne(builder, guid); return; } _channelPassword = pass; - WorldPacket data; - MakePasswordChanged(&data, guid); - SendToAll(&data); + PasswordChangedAppend appender(guid); + ChannelNameBuilder<PasswordChangedAppend> builder(this, appender); + SendToAll(builder); UpdateChannelInDB(); } @@ -445,18 +477,18 @@ void Channel::SetMode(Player const* player, std::string const& p2n, bool mod, bo if (!IsOn(guid)) { - WorldPacket data; - MakeNotMember(&data); - SendToOne(&data, guid); + NotMemberAppend appender; + ChannelNameBuilder<NotMemberAppend> builder(this, appender); + SendToOne(builder, guid); return; } PlayerInfo& info = _playersStore.at(guid); if (!info.IsModerator() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) { - WorldPacket data; - MakeNotModerator(&data); - SendToOne(&data, guid); + NotModeratorAppend appender; + ChannelNameBuilder<NotModeratorAppend> builder(this, appender); + SendToOne(builder, guid); return; } @@ -471,17 +503,17 @@ void Channel::SetMode(Player const* player, std::string const& p2n, bool mod, bo (!player->GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_CHANNEL) || !newp->GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_CHANNEL)))) { - WorldPacket data; - MakePlayerNotFound(&data, p2n); - SendToOne(&data, guid); + PlayerNotFoundAppend appender(p2n); + ChannelNameBuilder<PlayerNotFoundAppend> builder(this, appender); + SendToOne(builder, guid); return; } if (_ownerGuid == victim && _ownerGuid != guid) { - WorldPacket data; - MakeNotOwner(&data); - SendToOne(&data, guid); + NotOwnerAppend appender; + ChannelNameBuilder<NotOwnerAppend> builder(this, appender); + SendToOne(builder, guid); return; } @@ -504,23 +536,57 @@ void Channel::SetInvisible(Player const* player, bool on) _isOwnerInvisible = on; } +void Channel::SetModerator(ObjectGuid guid, bool set) +{ + if (!IsOn(guid)) + return; + + PlayerInfo& playerInfo = _playersStore.at(guid); + if (playerInfo.IsModerator() != set) + { + uint8 oldFlag = GetPlayerFlags(guid); + playerInfo.SetModerator(set); + + ModeChangeAppend appender(guid, oldFlag, GetPlayerFlags(guid)); + ChannelNameBuilder<ModeChangeAppend> builder(this, appender); + SendToAll(builder); + } +} + +void Channel::SetMute(ObjectGuid guid, bool set) +{ + if (!IsOn(guid)) + return; + + PlayerInfo& playerInfo = _playersStore.at(guid); + if (playerInfo.IsMuted() != set) + { + uint8 oldFlag = GetPlayerFlags(guid); + playerInfo.SetMuted(set); + + ModeChangeAppend appender(guid, oldFlag, GetPlayerFlags(guid)); + ChannelNameBuilder<ModeChangeAppend> builder(this, appender); + SendToAll(builder); + } +} + void Channel::SetOwner(Player const* player, std::string const& newname) { ObjectGuid guid = player->GetGUID(); if (!IsOn(guid)) { - WorldPacket data; - MakeNotMember(&data); - SendToOne(&data, guid); + NotMemberAppend appender; + ChannelNameBuilder<NotMemberAppend> builder(this, appender); + SendToOne(builder, guid); return; } if (!player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR) && guid != _ownerGuid) { - WorldPacket data; - MakeNotOwner(&data); - SendToOne(&data, guid); + NotOwnerAppend appender; + ChannelNameBuilder<NotOwnerAppend> builder(this, appender); + SendToOne(builder, guid); return; } @@ -532,9 +598,9 @@ void Channel::SetOwner(Player const* player, std::string const& newname) (!player->GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_CHANNEL) || !newp->GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_CHANNEL)))) { - WorldPacket data; - MakePlayerNotFound(&data, newname); - SendToOne(&data, guid); + PlayerNotFoundAppend appender(newname); + ChannelNameBuilder<PlayerNotFoundAppend> builder(this, appender); + SendToOne(builder, guid); return; } @@ -545,12 +611,18 @@ void Channel::SetOwner(Player const* player, std::string const& newname) void Channel::SendWhoOwner(ObjectGuid guid) { - WorldPacket data; if (IsOn(guid)) - MakeChannelOwner(&data); + { + ChannelOwnerAppend appender(this, _ownerGuid); + ChannelNameBuilder<ChannelOwnerAppend> builder(this, appender); + SendToOne(builder, guid); + } else - MakeNotMember(&data); - SendToOne(&data, guid); + { + NotMemberAppend appender; + ChannelNameBuilder<NotMemberAppend> builder(this, appender); + SendToOne(builder, guid); + } } void Channel::List(Player const* player) const @@ -559,18 +631,19 @@ void Channel::List(Player const* player) const if (!IsOn(guid)) { - WorldPacket data; - MakeNotMember(&data); - SendToOne(&data, guid); + NotMemberAppend appender; + ChannelNameBuilder<NotMemberAppend> builder(this, appender); + SendToOne(builder, guid); return; } + std::string channelName = GetName(player->GetSession()->GetSessionDbcLocale()); TC_LOG_DEBUG("chat.system", "SMSG_CHANNEL_LIST %s Channel: %s", - player->GetSession()->GetPlayerInfo().c_str(), GetName().c_str()); + player->GetSession()->GetPlayerInfo().c_str(), channelName.c_str()); - WorldPacket data(SMSG_CHANNEL_LIST, 1+(GetName().size()+1)+1+4+_playersStore.size()*(8+1)); + WorldPacket data(SMSG_CHANNEL_LIST, 1 + (channelName.size() + 1) + 1 + 4 + _playersStore.size() * (8 + 1)); data << uint8(1); // channel type? - data << GetName(); // channel name + data << channelName; // channel name data << uint8(GetFlags()); // channel flags? size_t pos = data.wpos(); @@ -597,8 +670,7 @@ void Channel::List(Player const* player) const } data.put<uint32>(pos, count); - - SendToOne(&data, guid); + player->SendDirectMessage(&data); } void Channel::Announce(Player const* player) @@ -607,29 +679,35 @@ void Channel::Announce(Player const* player) if (!IsOn(guid)) { - WorldPacket data; - MakeNotMember(&data); - SendToOne(&data, guid); + NotMemberAppend appender; + ChannelNameBuilder<NotMemberAppend> builder(this, appender); + SendToOne(builder, guid); return; } PlayerInfo& info = _playersStore.at(guid); if (!info.IsModerator() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) { - WorldPacket data; - MakeNotModerator(&data); - SendToOne(&data, guid); + NotModeratorAppend appender; + ChannelNameBuilder<NotModeratorAppend> builder(this, appender); + SendToOne(builder, guid); return; } _announceEnabled = !_announceEnabled; - WorldPacket data; if (_announceEnabled) - MakeAnnouncementsOn(&data, guid); + { + AnnouncementsOnAppend appender(guid); + ChannelNameBuilder<AnnouncementsOnAppend> builder(this, appender); + SendToAll(builder); + } else - MakeAnnouncementsOff(&data, guid); - SendToAll(&data); + { + AnnouncementsOffAppend appender(guid); + ChannelNameBuilder<AnnouncementsOffAppend> builder(this, appender); + SendToAll(builder); + } UpdateChannelInDB(); } @@ -645,28 +723,33 @@ void Channel::Say(ObjectGuid guid, std::string const& what, uint32 lang) const if (!IsOn(guid)) { - WorldPacket data; - MakeNotMember(&data); - SendToOne(&data, guid); + NotMemberAppend appender; + ChannelNameBuilder<NotMemberAppend> builder(this, appender); + SendToOne(builder, guid); return; } PlayerInfo const& info = _playersStore.at(guid); if (info.IsMuted()) { - WorldPacket data; - MakeMuted(&data); - SendToOne(&data, guid); + MutedAppend appender; + ChannelNameBuilder<MutedAppend> builder(this, appender); + SendToOne(builder, guid); return; } - WorldPacket data; - if (Player* player = ObjectAccessor::FindConnectedPlayer(guid)) - ChatHandler::BuildChatPacket(data, CHAT_MSG_CHANNEL, Language(lang), player, player, what, 0, _channelName); - else - ChatHandler::BuildChatPacket(data, CHAT_MSG_CHANNEL, Language(lang), guid, guid, what, 0, "", "", 0, false, _channelName); + auto builder = [&](WorldPacket& data, LocaleConstant locale) + { + LocaleConstant localeIdx = sWorld->GetAvailableDbcLocale(locale); + + if (Player* player = ObjectAccessor::FindConnectedPlayer(guid)) + ChatHandler::BuildChatPacket(data, CHAT_MSG_CHANNEL, Language(lang), player, player, what, 0, GetName(localeIdx)); + else + ChatHandler::BuildChatPacket(data, CHAT_MSG_CHANNEL, Language(lang), guid, guid, what, 0, "", "", 0, false, GetName(localeIdx)); + }; + + SendToAll(builder, !info.IsModerator() ? guid : ObjectGuid::Empty); - SendToAll(&data, !info.IsModerator() ? guid : ObjectGuid::Empty); } void Channel::Invite(Player const* player, std::string const& newname) @@ -675,26 +758,26 @@ void Channel::Invite(Player const* player, std::string const& newname) if (!IsOn(guid)) { - WorldPacket data; - MakeNotMember(&data); - SendToOne(&data, guid); + NotMemberAppend appender; + ChannelNameBuilder<NotMemberAppend> builder(this, appender); + SendToOne(builder, guid); return; } Player* newp = ObjectAccessor::FindConnectedPlayerByName(newname); if (!newp || !newp->isGMVisible()) { - WorldPacket data; - MakePlayerNotFound(&data, newname); - SendToOne(&data, guid); + PlayerNotFoundAppend appender(newname); + ChannelNameBuilder<PlayerNotFoundAppend> builder(this, appender); + SendToOne(builder, guid); return; } if (IsBanned(newp->GetGUID())) { - WorldPacket data; - MakePlayerInviteBanned(&data, newname); - SendToOne(&data, guid); + PlayerInviteBannedAppend appender(newname); + ChannelNameBuilder<PlayerInviteBannedAppend> builder(this, appender); + SendToOne(builder, guid); return; } @@ -702,31 +785,30 @@ void Channel::Invite(Player const* player, std::string const& newname) (!player->GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_CHANNEL) || !newp->GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_CHANNEL))) { - WorldPacket data; - MakeInviteWrongFaction(&data); - SendToOne(&data, guid); + InviteWrongFactionAppend appender; + ChannelNameBuilder<InviteWrongFactionAppend> builder(this, appender); + SendToOne(builder, guid); return; } if (IsOn(newp->GetGUID())) { - WorldPacket data; - MakePlayerAlreadyMember(&data, newp->GetGUID()); - SendToOne(&data, guid); + PlayerAlreadyMemberAppend appender(newp->GetGUID()); + ChannelNameBuilder<PlayerAlreadyMemberAppend> builder(this, appender); + SendToOne(builder, guid); return; } if (!newp->GetSocial()->HasIgnore(guid.GetCounter())) { - WorldPacket data; - MakeInvite(&data, guid); - SendToOne(&data, newp->GetGUID()); - data.clear(); + InviteAppend appender(guid); + ChannelNameBuilder<InviteAppend> builder(this, appender); + SendToOne(builder, newp->GetGUID()); } - WorldPacket data; - MakePlayerInvited(&data, newp->GetName()); - SendToOne(&data, guid); + PlayerInvitedAppend appender(newp->GetName()); + ChannelNameBuilder<PlayerInvitedAppend> builder(this, appender); + SendToOne(builder, guid); } void Channel::SetOwner(ObjectGuid guid, bool exclaim) @@ -749,42 +831,21 @@ void Channel::SetOwner(ObjectGuid guid, bool exclaim) itr->second.SetModerator(true); itr->second.SetOwner(true); - WorldPacket data; - MakeModeChange(&data, _ownerGuid, oldFlag); - SendToAll(&data); + ModeChangeAppend appender(_ownerGuid, oldFlag, GetPlayerFlags(_ownerGuid)); + ChannelNameBuilder<ModeChangeAppend> builder(this, appender); + SendToAll(builder); if (exclaim) { - MakeOwnerChanged(&data, _ownerGuid); - SendToAll(&data); + OwnerChangedAppend appender(_ownerGuid); + ChannelNameBuilder<OwnerChangedAppend> builder(this, appender); + SendToAll(builder); } UpdateChannelInDB(); } } -void Channel::SendToAll(WorldPacket* data, ObjectGuid guid) const -{ - for (PlayerContainer::const_iterator i = _playersStore.begin(); i != _playersStore.end(); ++i) - if (Player* player = ObjectAccessor::FindConnectedPlayer(i->first)) - if (!guid || !player->GetSocial()->HasIgnore(guid.GetCounter())) - player->GetSession()->SendPacket(data); -} - -void Channel::SendToAllButOne(WorldPacket* data, ObjectGuid who) const -{ - for (PlayerContainer::const_iterator i = _playersStore.begin(); i != _playersStore.end(); ++i) - if (i->first != who) - if (Player* player = ObjectAccessor::FindConnectedPlayer(i->first)) - player->GetSession()->SendPacket(data); -} - -void Channel::SendToOne(WorldPacket* data, ObjectGuid who) const -{ - if (Player* player = ObjectAccessor::FindConnectedPlayer(who)) - player->GetSession()->SendPacket(data); -} - void Channel::Voice(ObjectGuid /*guid1*/, ObjectGuid /*guid2*/) const { @@ -795,245 +856,72 @@ void Channel::DeVoice(ObjectGuid /*guid1*/, ObjectGuid /*guid2*/) const } -void Channel::MakeNotifyPacket(WorldPacket* data, uint8 notify_type) const -{ - data->Initialize(SMSG_CHANNEL_NOTIFY, 1 + _channelName.size()); - *data << uint8(notify_type); - *data << _channelName; -} - -void Channel::MakeJoined(WorldPacket* data, ObjectGuid guid) const -{ - MakeNotifyPacket(data, CHAT_JOINED_NOTICE); - *data << uint64(guid); -} - -void Channel::MakeLeft(WorldPacket* data, ObjectGuid guid) const -{ - MakeNotifyPacket(data, CHAT_LEFT_NOTICE); - *data << uint64(guid); -} - -void Channel::MakeYouJoined(WorldPacket* data) const -{ - MakeNotifyPacket(data, CHAT_YOU_JOINED_NOTICE); - *data << uint8(GetFlags()); - *data << uint32(GetChannelId()); - *data << uint32(0); -} - -void Channel::MakeYouLeft(WorldPacket* data) const -{ - MakeNotifyPacket(data, CHAT_YOU_LEFT_NOTICE); - *data << uint32(GetChannelId()); - *data << uint8(IsConstant()); -} - -void Channel::MakeWrongPassword(WorldPacket* data) const -{ - MakeNotifyPacket(data, CHAT_WRONG_PASSWORD_NOTICE); -} - -void Channel::MakeNotMember(WorldPacket* data) const -{ - MakeNotifyPacket(data, CHAT_NOT_MEMBER_NOTICE); -} - -void Channel::MakeNotModerator(WorldPacket* data) const -{ - MakeNotifyPacket(data, CHAT_NOT_MODERATOR_NOTICE); -} - -void Channel::MakePasswordChanged(WorldPacket* data, ObjectGuid guid) const -{ - MakeNotifyPacket(data, CHAT_PASSWORD_CHANGED_NOTICE); - *data << uint64(guid); -} - -void Channel::MakeOwnerChanged(WorldPacket* data, ObjectGuid guid) const -{ - MakeNotifyPacket(data, CHAT_OWNER_CHANGED_NOTICE); - *data << uint64(guid); -} - -void Channel::MakePlayerNotFound(WorldPacket* data, std::string const& name) const -{ - MakeNotifyPacket(data, CHAT_PLAYER_NOT_FOUND_NOTICE); - *data << name; -} - -void Channel::MakeNotOwner(WorldPacket* data) const +void Channel::JoinNotify(ObjectGuid guid) const { - MakeNotifyPacket(data, CHAT_NOT_OWNER_NOTICE); -} + auto builder = [&](WorldPacket& data, LocaleConstant locale) + { + LocaleConstant localeIdx = sWorld->GetAvailableDbcLocale(locale); -void Channel::MakeChannelOwner(WorldPacket* data) const -{ - std::string name; + data.Initialize(IsConstant() ? SMSG_USERLIST_ADD : SMSG_USERLIST_UPDATE, 8 + 1 + 1 + 4 + 30 /*channelName buffer*/); + data << uint64(guid); + data << uint8(GetPlayerFlags(guid)); + data << uint8(GetFlags()); + data << uint32(GetNumPlayers()); + data << GetName(localeIdx); + }; - CharacterInfo const* cInfo = sWorld->GetCharacterInfo(_ownerGuid); - if (!cInfo || cInfo->Name.empty()) - name = "PLAYER_NOT_FOUND"; + if (IsConstant()) + SendToAllButOne(builder, guid); else - name = cInfo->Name; - - MakeNotifyPacket(data, CHAT_CHANNEL_OWNER_NOTICE); - *data << ((IsConstant() || !_ownerGuid) ? "Nobody" : name); -} - -void Channel::MakeModeChange(WorldPacket* data, ObjectGuid guid, uint8 oldflags) const -{ - MakeNotifyPacket(data, CHAT_MODE_CHANGE_NOTICE); - *data << uint64(guid); - *data << uint8(oldflags); - *data << uint8(GetPlayerFlags(guid)); -} - -void Channel::MakeAnnouncementsOn(WorldPacket* data, ObjectGuid guid) const -{ - MakeNotifyPacket(data, CHAT_ANNOUNCEMENTS_ON_NOTICE); - *data << uint64(guid); -} - -void Channel::MakeAnnouncementsOff(WorldPacket* data, ObjectGuid guid) const -{ - MakeNotifyPacket(data, CHAT_ANNOUNCEMENTS_OFF_NOTICE); - *data << uint64(guid); -} - -void Channel::MakeMuted(WorldPacket* data) const -{ - MakeNotifyPacket(data, CHAT_MUTED_NOTICE); -} - -void Channel::MakePlayerKicked(WorldPacket* data, ObjectGuid bad, ObjectGuid good) const -{ - MakeNotifyPacket(data, CHAT_PLAYER_KICKED_NOTICE); - *data << uint64(bad); - *data << uint64(good); -} - -void Channel::MakeBanned(WorldPacket* data) const -{ - MakeNotifyPacket(data, CHAT_BANNED_NOTICE); -} - -void Channel::MakePlayerBanned(WorldPacket* data, ObjectGuid bad, ObjectGuid good) const -{ - MakeNotifyPacket(data, CHAT_PLAYER_BANNED_NOTICE); - *data << uint64(bad); - *data << uint64(good); -} - -void Channel::MakePlayerUnbanned(WorldPacket* data, ObjectGuid bad, ObjectGuid good) const -{ - MakeNotifyPacket(data, CHAT_PLAYER_UNBANNED_NOTICE); - *data << uint64(bad); - *data << uint64(good); -} - -void Channel::MakePlayerNotBanned(WorldPacket* data, const std::string &name) const -{ - MakeNotifyPacket(data, CHAT_PLAYER_NOT_BANNED_NOTICE); - *data << name; + SendToAll(builder); } -void Channel::MakePlayerAlreadyMember(WorldPacket* data, ObjectGuid guid) const -{ - MakeNotifyPacket(data, CHAT_PLAYER_ALREADY_MEMBER_NOTICE); - *data << uint64(guid); -} - -void Channel::MakeInvite(WorldPacket* data, ObjectGuid guid) const -{ - MakeNotifyPacket(data, CHAT_INVITE_NOTICE); - *data << uint64(guid); -} - -void Channel::MakeInviteWrongFaction(WorldPacket* data) const -{ - MakeNotifyPacket(data, CHAT_INVITE_WRONG_FACTION_NOTICE); -} - -void Channel::MakeWrongFaction(WorldPacket* data) const -{ - MakeNotifyPacket(data, CHAT_WRONG_FACTION_NOTICE); -} - -void Channel::MakeInvalidName(WorldPacket* data) const -{ - MakeNotifyPacket(data, CHAT_INVALID_NAME_NOTICE); -} - -void Channel::MakeNotModerated(WorldPacket* data) const -{ - MakeNotifyPacket(data, CHAT_NOT_MODERATED_NOTICE); -} - -void Channel::MakePlayerInvited(WorldPacket* data, std::string const& name) const -{ - MakeNotifyPacket(data, CHAT_PLAYER_INVITED_NOTICE); - *data << name; -} - -void Channel::MakePlayerInviteBanned(WorldPacket* data, std::string const& name) const -{ - MakeNotifyPacket(data, CHAT_PLAYER_INVITE_BANNED_NOTICE); - *data << name; -} - -void Channel::MakeThrottled(WorldPacket* data) const +void Channel::LeaveNotify(ObjectGuid guid) const { - MakeNotifyPacket(data, CHAT_THROTTLED_NOTICE); -} + auto builder = [&](WorldPacket& data, LocaleConstant locale) + { + LocaleConstant localeIdx = sWorld->GetAvailableDbcLocale(locale); -void Channel::MakeNotInArea(WorldPacket* data) const -{ - MakeNotifyPacket(data, CHAT_NOT_IN_AREA_NOTICE); -} + data.Initialize(SMSG_USERLIST_REMOVE, 8 + 1 + 4 + 30 /*channelName buffer*/); + data << uint64(guid); + data << uint8(GetFlags()); + data << uint32(GetNumPlayers()); + data << GetName(localeIdx); + }; -void Channel::MakeNotInLfg(WorldPacket* data) const -{ - MakeNotifyPacket(data, CHAT_NOT_IN_LFG_NOTICE); + if (IsConstant()) + SendToAllButOne(builder, guid); + else + SendToAll(builder); } -void Channel::MakeVoiceOn(WorldPacket* data, ObjectGuid guid) const +template<class Builder> +void Channel::SendToAll(Builder& builder, ObjectGuid guid /*= ObjectGuid::Empty*/) const { - MakeNotifyPacket(data, CHAT_VOICE_ON_NOTICE); - *data << uint64(guid); -} + Trinity::LocalizedPacketDo<Builder> localizer(builder); -void Channel::MakeVoiceOff(WorldPacket* data, ObjectGuid guid) const -{ - MakeNotifyPacket(data, CHAT_VOICE_OFF_NOTICE); - *data << uint64(guid); + for (PlayerContainer::const_iterator i = _playersStore.begin(); i != _playersStore.end(); ++i) + if (Player* player = ObjectAccessor::FindConnectedPlayer(i->first)) + if (!guid || !player->GetSocial()->HasIgnore(guid.GetCounter())) + localizer(player); } -void Channel::JoinNotify(ObjectGuid guid) const +template<class Builder> +void Channel::SendToAllButOne(Builder& builder, ObjectGuid who) const { - WorldPacket data(IsConstant() ? SMSG_USERLIST_ADD : SMSG_USERLIST_UPDATE, 8 + 1 + 1 + 4 + GetName().size()); - data << uint64(guid); - data << uint8(GetPlayerFlags(guid)); - data << uint8(GetFlags()); - data << uint32(GetNumPlayers()); - data << GetName(); + Trinity::LocalizedPacketDo<Builder> localizer(builder); - if (IsConstant()) - SendToAllButOne(&data, guid); - else - SendToAll(&data); + for (PlayerContainer::const_iterator i = _playersStore.begin(); i != _playersStore.end(); ++i) + if (i->first != who) + if (Player* player = ObjectAccessor::FindConnectedPlayer(i->first)) + localizer(player); } -void Channel::LeaveNotify(ObjectGuid guid) const +template<class Builder> +void Channel::SendToOne(Builder& builder, ObjectGuid who) const { - WorldPacket data(SMSG_USERLIST_REMOVE, 8 + 1 + 4 + GetName().size()); - data << uint64(guid); - data << uint8(GetFlags()); - data << uint32(GetNumPlayers()); - data << GetName(); + Trinity::LocalizedPacketDo<Builder> localizer(builder); - if (IsConstant()) - SendToAllButOne(&data, guid); - else - SendToAll(&data); + if (Player* player = ObjectAccessor::FindConnectedPlayer(who)) + localizer(player); } diff --git a/src/server/game/Chat/Channels/Channel.h b/src/server/game/Chat/Channels/Channel.h index 4859a984967..8c01a474854 100644 --- a/src/server/game/Chat/Channels/Channel.h +++ b/src/server/game/Chat/Channels/Channel.h @@ -150,9 +150,11 @@ class TC_GAME_API Channel }; public: - Channel(std::string const& name, uint32 channel_id, uint32 team = 0); + Channel(uint32 channelId, uint32 team = 0, AreaTableEntry const* zoneEntry = nullptr); // built-in channel ctor + Channel(std::string const& name, uint32 team = 0); // custom player channel ctor - std::string const& GetName() const { return _channelName; } + static void GetChannelName(std::string& channelName, uint32 channelId, LocaleConstant locale, AreaTableEntry const* zoneEntry); + std::string GetName(LocaleConstant locale = DEFAULT_LOCALE) const; uint32 GetChannelId() const { return _channelId; } bool IsConstant() const { return _channelId != 0; } @@ -169,6 +171,8 @@ class TC_GAME_API Channel uint8 GetFlags() const { return _channelFlags; } bool HasFlag(uint8 flag) const { return (_channelFlags & flag) != 0; } + AreaTableEntry const* GetZoneEntry() const { return _zoneEntry; } + void JoinChannel(Player* player, std::string const& pass); void LeaveChannel(Player* player, bool send = true); @@ -203,47 +207,15 @@ class TC_GAME_API Channel static void CleanOldChannelsInDB(); private: - // initial packet data (notify type and channel name) - void MakeNotifyPacket(WorldPacket* data, uint8 notify_type) const; - // type specific packet data - void MakeJoined(WorldPacket* data, ObjectGuid guid) const; //+ 0x00 - void MakeLeft(WorldPacket* data, ObjectGuid guid) const; //+ 0x01 - void MakeYouJoined(WorldPacket* data) const; //+ 0x02 - void MakeYouLeft(WorldPacket* data) const; //+ 0x03 - void MakeWrongPassword(WorldPacket* data) const; //? 0x04 - void MakeNotMember(WorldPacket* data) const; //? 0x05 - void MakeNotModerator(WorldPacket* data) const; //? 0x06 - void MakePasswordChanged(WorldPacket* data, ObjectGuid guid) const; //+ 0x07 - void MakeOwnerChanged(WorldPacket* data, ObjectGuid guid) const; //? 0x08 - void MakePlayerNotFound(WorldPacket* data, std::string const& name) const; //+ 0x09 - void MakeNotOwner(WorldPacket* data) const; //? 0x0A - void MakeChannelOwner(WorldPacket* data) const; //? 0x0B - void MakeModeChange(WorldPacket* data, ObjectGuid guid, uint8 oldflags) const; //+ 0x0C - void MakeAnnouncementsOn(WorldPacket* data, ObjectGuid guid) const; //+ 0x0D - void MakeAnnouncementsOff(WorldPacket* data, ObjectGuid guid) const; //+ 0x0E - void MakeMuted(WorldPacket* data) const; //? 0x11 - void MakePlayerKicked(WorldPacket* data, ObjectGuid bad, ObjectGuid good) const; //? 0x12 - void MakeBanned(WorldPacket* data) const; //? 0x13 - void MakePlayerBanned(WorldPacket* data, ObjectGuid bad, ObjectGuid good) const; //? 0x14 - void MakePlayerUnbanned(WorldPacket* data, ObjectGuid bad, ObjectGuid good) const; //? 0x15 - void MakePlayerNotBanned(WorldPacket* data, std::string const& name) const; //? 0x16 - void MakePlayerAlreadyMember(WorldPacket* data, ObjectGuid guid) const; //+ 0x17 - void MakeInvite(WorldPacket* data, ObjectGuid guid) const; //? 0x18 - void MakeInviteWrongFaction(WorldPacket* data) const; //? 0x19 - void MakeWrongFaction(WorldPacket* data) const; //? 0x1A - void MakeInvalidName(WorldPacket* data) const; //? 0x1B - void MakeNotModerated(WorldPacket* data) const; //? 0x1C - void MakePlayerInvited(WorldPacket* data, std::string const& name) const; //+ 0x1D - void MakePlayerInviteBanned(WorldPacket* data, std::string const& name) const; //? 0x1E - void MakeThrottled(WorldPacket* data) const; //? 0x1F - void MakeNotInArea(WorldPacket* data) const; //? 0x20 - void MakeNotInLfg(WorldPacket* data) const; //? 0x21 - void MakeVoiceOn(WorldPacket* data, ObjectGuid guid) const; //+ 0x22 - void MakeVoiceOff(WorldPacket* data, ObjectGuid guid) const; //+ 0x23 - - void SendToAll(WorldPacket* data, ObjectGuid guid = ObjectGuid::Empty) const; - void SendToAllButOne(WorldPacket* data, ObjectGuid who) const; - void SendToOne(WorldPacket* data, ObjectGuid who) const; + + template<class Builder> + void SendToAll(Builder&, ObjectGuid guid = ObjectGuid::Empty) const; + + template<class Builder> + void SendToAllButOne(Builder& builder, ObjectGuid who) const; + + template<class Builder> + void SendToOne(Builder& builder, ObjectGuid who) const; bool IsOn(ObjectGuid who) const { return _playersStore.count(who) != 0; } bool IsBanned(ObjectGuid guid) const { return _bannedStore.count(guid) != 0; } @@ -257,39 +229,8 @@ class TC_GAME_API Channel return itr != _playersStore.end() ? itr->second.flags : 0; } - void SetModerator(ObjectGuid guid, bool set) - { - if (!IsOn(guid)) - return; - - PlayerInfo& playerInfo = _playersStore.at(guid); - if (playerInfo.IsModerator() != set) - { - uint8 oldFlag = GetPlayerFlags(guid); - playerInfo.SetModerator(set); - - WorldPacket data; - MakeModeChange(&data, guid, oldFlag); - SendToAll(&data); - } - } - - void SetMute(ObjectGuid guid, bool set) - { - if (!IsOn(guid)) - return; - - PlayerInfo& playerInfo = _playersStore.at(guid); - if (playerInfo.IsMuted() != set) - { - uint8 oldFlag = GetPlayerFlags(guid); - playerInfo.SetMuted(set); - - WorldPacket data; - MakeModeChange(&data, guid, oldFlag); - SendToAll(&data); - } - } + void SetModerator(ObjectGuid guid, bool set); + void SetMute(ObjectGuid guid, bool set); typedef std::map<ObjectGuid, PlayerInfo> PlayerContainer; typedef GuidUnorderedSet BannedContainer; @@ -307,6 +248,8 @@ class TC_GAME_API Channel std::string _channelPassword; PlayerContainer _playersStore; BannedContainer _bannedStore; + + AreaTableEntry const* _zoneEntry; }; #endif diff --git a/src/server/game/Chat/Channels/ChannelAppenders.h b/src/server/game/Chat/Channels/ChannelAppenders.h new file mode 100644 index 00000000000..3dfdc3f32cf --- /dev/null +++ b/src/server/game/Chat/Channels/ChannelAppenders.h @@ -0,0 +1,476 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _CHANNELAPPENDERS_H +#define _CHANNELAPPENDERS_H + +#include "Channel.h" + +// initial packet data (notify type and channel name) +template<class PacketModifier> +class ChannelNameBuilder +{ + public: + ChannelNameBuilder(Channel const* source, PacketModifier const& modifier) + : _source(source), _modifier(modifier){ } + + void operator()(WorldPacket& data, LocaleConstant locale) const + { + // LocalizedPacketDo sends client DBC locale, we need to get available to server locale + LocaleConstant localeIdx = sWorld->GetAvailableDbcLocale(locale); + + data.Initialize(SMSG_CHANNEL_NOTIFY, 60); // guess size + data << uint8(_modifier.NotificationType); + data << _source->GetName(localeIdx); + _modifier.Append(data); + } + + private: + Channel const* _source; + PacketModifier _modifier; +}; + +struct JoinedAppend +{ + explicit JoinedAppend(ObjectGuid const& guid) : _guid(guid) { } + + static uint8 const NotificationType = CHAT_JOINED_NOTICE; + + void Append(WorldPacket& data) const + { + data << uint64(_guid); + } + +private: + ObjectGuid _guid; +}; + +struct LeftAppend +{ + explicit LeftAppend(ObjectGuid const& guid) : _guid(guid) { } + + static uint8 const NotificationType = CHAT_LEFT_NOTICE; + + void Append(WorldPacket& data) const + { + data << uint64(_guid); + } + +private: + ObjectGuid _guid; +}; + +struct YouJoinedAppend +{ + explicit YouJoinedAppend(Channel const* channel) : _channel(channel) { } + + static uint8 const NotificationType = CHAT_YOU_JOINED_NOTICE; + + void Append(WorldPacket& data) const + { + data << uint8(_channel->GetFlags()); + data << uint32(_channel->GetChannelId()); + data << uint32(0); + } + +private: + Channel const* _channel; +}; + +struct YouLeftAppend +{ + explicit YouLeftAppend(Channel const* channel) : _channel(channel) { } + + static uint8 const NotificationType = CHAT_YOU_LEFT_NOTICE; + + void Append(WorldPacket& data) const + { + data << uint32(_channel->GetChannelId()); + data << uint8(_channel->IsConstant()); + } + +private: + Channel const* _channel; +}; + +struct WrongPasswordAppend +{ + static uint8 const NotificationType = CHAT_WRONG_PASSWORD_NOTICE; + + void Append(WorldPacket& /*data*/) const { } +}; + +struct NotMemberAppend +{ + static uint8 const NotificationType = CHAT_NOT_MEMBER_NOTICE; + + void Append(WorldPacket& /*data*/) const { } +}; + +struct NotModeratorAppend +{ + static uint8 const NotificationType = CHAT_NOT_MODERATOR_NOTICE; + + void Append(WorldPacket& /*data*/) const { } +}; + +struct PasswordChangedAppend +{ + explicit PasswordChangedAppend(ObjectGuid const& guid) : _guid(guid) { } + + static uint8 const NotificationType = CHAT_PASSWORD_CHANGED_NOTICE; + + void Append(WorldPacket& data) const + { + data << uint64(_guid); + } + +private: + ObjectGuid _guid; +}; + +struct OwnerChangedAppend +{ + explicit OwnerChangedAppend(ObjectGuid const& guid) : _guid(guid) { } + + static uint8 const NotificationType = CHAT_OWNER_CHANGED_NOTICE; + + void Append(WorldPacket& data) const + { + data << uint64(_guid); + } + +private: + ObjectGuid _guid; +}; + +struct PlayerNotFoundAppend +{ + explicit PlayerNotFoundAppend(std::string const& playerName) : _playerName(playerName) { } + + static uint8 const NotificationType = CHAT_PLAYER_NOT_FOUND_NOTICE; + + void Append(WorldPacket& data) const + { + data << _playerName; + } + +private: + std::string _playerName; +}; + +struct NotOwnerAppend +{ + static uint8 const NotificationType = CHAT_NOT_OWNER_NOTICE; + + void Append(WorldPacket& /*data*/) const { } +}; + +struct ChannelOwnerAppend +{ + explicit ChannelOwnerAppend(Channel const* channel, ObjectGuid const& ownerGuid) : _channel(channel), _ownerGuid(ownerGuid) + { + CharacterInfo const* cInfo = sWorld->GetCharacterInfo(_ownerGuid); + if (!cInfo || cInfo->Name.empty()) + _ownerName = "PLAYER_NOT_FOUND"; + else + _ownerName = cInfo->Name; + } + + static uint8 const NotificationType = CHAT_CHANNEL_OWNER_NOTICE; + + void Append(WorldPacket& data) const + { + data << ((_channel->IsConstant() || !_ownerGuid) ? "Nobody" : _ownerName); + } + +private: + Channel const* _channel; + ObjectGuid _ownerGuid; + + std::string _ownerName; +}; + +struct ModeChangeAppend +{ + explicit ModeChangeAppend(ObjectGuid const& guid, uint8 oldFlags, uint8 newFlags) : _guid(guid), _oldFlags(oldFlags), _newFlags(newFlags) { } + + static uint8 const NotificationType = CHAT_MODE_CHANGE_NOTICE; + + void Append(WorldPacket& data) const + { + data << uint64(_guid); + data << uint8(_oldFlags); + data << uint8(_newFlags); + } + +private: + ObjectGuid _guid; + uint8 _oldFlags; + uint8 _newFlags; +}; + +struct AnnouncementsOnAppend +{ + explicit AnnouncementsOnAppend(ObjectGuid const& guid) : _guid(guid) { } + + static uint8 const NotificationType = CHAT_ANNOUNCEMENTS_ON_NOTICE; + + void Append(WorldPacket& data) const + { + data << uint64(_guid); + } + +private: + ObjectGuid _guid; +}; + +struct AnnouncementsOffAppend +{ + explicit AnnouncementsOffAppend(ObjectGuid const& guid) : _guid(guid) { } + + static uint8 const NotificationType = CHAT_ANNOUNCEMENTS_OFF_NOTICE; + + void Append(WorldPacket& data) const + { + data << uint64(_guid); + } + +private: + ObjectGuid _guid; +}; + +struct MutedAppend +{ + static uint8 const NotificationType = CHAT_MUTED_NOTICE; + + void Append(WorldPacket& /*data*/) const { } +}; + +struct PlayerKickedAppend +{ + explicit PlayerKickedAppend(ObjectGuid const& kicker, ObjectGuid const& kickee) : _kicker(kicker), _kickee(kickee) { } + + static uint8 const NotificationType = CHAT_PLAYER_KICKED_NOTICE; + + void Append(WorldPacket& data) const + { + data << uint64(_kickee); + data << uint64(_kicker); + } + +private: + ObjectGuid _kicker; + ObjectGuid _kickee; +}; + +struct BannedAppend +{ + static uint8 const NotificationType = CHAT_BANNED_NOTICE; + + void Append(WorldPacket& /*data*/) const { } +}; + +struct PlayerBannedAppend +{ + explicit PlayerBannedAppend(ObjectGuid const& moderator, ObjectGuid const& banned) : _moderator(moderator), _banned(banned) { } + + static uint8 const NotificationType = CHAT_PLAYER_BANNED_NOTICE; + + void Append(WorldPacket& data) const + { + data << uint64(_banned); + data << uint64(_moderator); + } + +private: + ObjectGuid _moderator; + ObjectGuid _banned; +}; + +struct PlayerUnbannedAppend +{ + explicit PlayerUnbannedAppend(ObjectGuid const& moderator, ObjectGuid const& unbanned) : _moderator(moderator), _unbanned(unbanned) { } + + static uint8 const NotificationType = CHAT_PLAYER_UNBANNED_NOTICE; + + void Append(WorldPacket& data) const + { + data << uint64(_unbanned); + data << uint64(_moderator); + } + +private: + ObjectGuid _moderator; + ObjectGuid _unbanned; +}; + +struct PlayerNotBannedAppend +{ + explicit PlayerNotBannedAppend(std::string const& playerName) : _playerName(playerName) { } + + static uint8 const NotificationType = CHAT_PLAYER_NOT_BANNED_NOTICE; + + void Append(WorldPacket& data) const + { + data << _playerName; + } + +private: + std::string _playerName; +}; + +struct PlayerAlreadyMemberAppend +{ + explicit PlayerAlreadyMemberAppend(ObjectGuid const& guid) : _guid(guid) { } + + static uint8 const NotificationType = CHAT_PLAYER_ALREADY_MEMBER_NOTICE; + + void Append(WorldPacket& data) const + { + data << uint64(_guid); + } + +private: + ObjectGuid _guid; +}; + +struct InviteAppend +{ + explicit InviteAppend(ObjectGuid const& guid) : _guid(guid) { } + + static uint8 const NotificationType = CHAT_INVITE_NOTICE; + + void Append(WorldPacket& data) const + { + data << uint64(_guid); + } + +private: + ObjectGuid _guid; +}; + +struct InviteWrongFactionAppend +{ + static uint8 const NotificationType = CHAT_INVITE_WRONG_FACTION_NOTICE; + + void Append(WorldPacket& /*data*/) const { } +}; + +struct WrongFactionAppend +{ + static uint8 const NotificationType = CHAT_WRONG_FACTION_NOTICE; + + void Append(WorldPacket& /*data*/) const { } +}; + +struct InvalidNameAppend +{ + static uint8 const NotificationType = CHAT_INVALID_NAME_NOTICE; + + void Append(WorldPacket& /*data*/) const { } +}; + +struct NotModeratedAppend +{ + static uint8 const NotificationType = CHAT_NOT_MODERATED_NOTICE; + + void Append(WorldPacket& /*data*/) const { } +}; + +struct PlayerInvitedAppend +{ + explicit PlayerInvitedAppend(std::string const& playerName) : _playerName(playerName) { } + + static uint8 const NotificationType = CHAT_PLAYER_INVITED_NOTICE; + + void Append(WorldPacket& data) const + { + data << _playerName; + } + +private: + std::string _playerName; +}; + +struct PlayerInviteBannedAppend +{ + explicit PlayerInviteBannedAppend(std::string const& playerName) : _playerName(playerName) { } + + static uint8 const NotificationType = CHAT_PLAYER_INVITE_BANNED_NOTICE; + + void Append(WorldPacket& data) const + { + data << _playerName; + } + +private: + std::string _playerName; +}; + +struct ThrottledAppend +{ + static uint8 const NotificationType = CHAT_THROTTLED_NOTICE; + + void Append(WorldPacket& /*data*/) const { } +}; + +struct NotInAreaAppend +{ + static uint8 const NotificationType = CHAT_NOT_IN_AREA_NOTICE; + + void Append(WorldPacket& /*data*/) const { } +}; + +struct NotInLFGAppend +{ + static uint8 const NotificationType = CHAT_NOT_IN_LFG_NOTICE; + + void Append(WorldPacket& /*data*/) const { } +}; + +struct VoiceOnAppend +{ + explicit VoiceOnAppend(ObjectGuid const& guid) : _guid(guid) { } + + static uint8 const NotificationType = CHAT_VOICE_ON_NOTICE; + + void Append(WorldPacket& data) const + { + data << uint64(_guid); + } + +private: + ObjectGuid _guid; +}; + +struct VoiceOffAppend +{ + explicit VoiceOffAppend(ObjectGuid const& guid) : _guid(guid) { } + + static uint8 const NotificationType = CHAT_VOICE_OFF_NOTICE; + + void Append(WorldPacket& data) const + { + data << uint64(_guid); + } + +private: + ObjectGuid _guid; +}; + +#endif // _CHANNELAPPENDERS_H diff --git a/src/server/game/Chat/Channels/ChannelMgr.cpp b/src/server/game/Chat/Channels/ChannelMgr.cpp index 043d4bdc2bc..ee1f463aae2 100644 --- a/src/server/game/Chat/Channels/ChannelMgr.cpp +++ b/src/server/game/Chat/Channels/ChannelMgr.cpp @@ -16,20 +16,25 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "Channel.h" #include "ChannelMgr.h" #include "Player.h" #include "World.h" ChannelMgr::~ChannelMgr() { - for (ChannelMap::iterator itr = channels.begin(); itr != channels.end(); ++itr) + for (auto itr = _channels.begin(); itr != _channels.end(); ++itr) + delete itr->second; + + for (auto itr = _customChannels.begin(); itr != _customChannels.end(); ++itr) delete itr->second; } ChannelMgr* ChannelMgr::forTeam(uint32 team) { - static ChannelMgr allianceChannelMgr; - static ChannelMgr hordeChannelMgr; + static ChannelMgr allianceChannelMgr(ALLIANCE); + static ChannelMgr hordeChannelMgr(HORDE); + if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) return &allianceChannelMgr; // cross-faction @@ -42,69 +47,148 @@ ChannelMgr* ChannelMgr::forTeam(uint32 team) return nullptr; } -Channel* ChannelMgr::GetJoinChannel(std::string const& name, uint32 channelId) +Channel* ChannelMgr::GetChannelForPlayerByNamePart(std::string const& namePart, Player* playerSearcher) { - std::wstring wname; - if (!Utf8toWStr(name, wname)) + std::wstring channelNamePart; + if (!Utf8toWStr(namePart, channelNamePart)) return nullptr; - wstrToLower(wname); + wstrToLower(channelNamePart); + for (Channel* channel : playerSearcher->GetJoinedChannels()) + { + std::string chanName = channel->GetName(playerSearcher->GetSession()->GetSessionDbcLocale()); - ChannelMap::const_iterator i = channels.find(wname); + std::wstring channelNameW; + if (!Utf8toWStr(chanName, channelNameW)) + continue; - if (i == channels.end()) - { - Channel* nchan = new Channel(name, channelId, team); - channels[wname] = nchan; - return nchan; + wstrToLower(channelNameW); + if (!channelNameW.compare(0, channelNamePart.size(), channelNamePart)) + return channel; } - return i->second; + return nullptr; } -Channel* ChannelMgr::GetChannel(std::string const& name, Player* player, bool pkt) +Channel* ChannelMgr::GetJoinChannel(uint32 channelId, std::string const& name, AreaTableEntry const* zoneEntry /*= nullptr*/) { - std::wstring wname; - if (!Utf8toWStr(name, wname)) - return nullptr; + if (channelId) // builtin + { + ChatChannelsEntry const* channelEntry = sChatChannelsStore.AssertEntry(channelId); + uint32 zoneId = zoneEntry ? zoneEntry->ID : 0; + if (channelEntry->flags & (CHANNEL_DBC_FLAG_GLOBAL | CHANNEL_DBC_FLAG_CITY_ONLY)) + zoneId = 0; - wstrToLower(wname); + std::pair<uint32, uint32> key = std::make_pair(channelId, zoneId); - ChannelMap::const_iterator i = channels.find(wname); + auto itr = _channels.find(key); + if (itr != _channels.end()) + return itr->second; - if (i == channels.end()) + Channel* newChannel = new Channel(channelId, _team, zoneEntry); + _channels[key] = newChannel; + return newChannel; + } + else // custom { - if (pkt) - { - WorldPacket data; - MakeNotOnPacket(&data, name); - player->GetSession()->SendPacket(&data); - } + std::wstring channelName; + if (!Utf8toWStr(name, channelName)) + return nullptr; + + wstrToLower(channelName); + auto itr = _customChannels.find(channelName); + if (itr != _customChannels.end()) + return itr->second; + + Channel* newChannel = new Channel(name, _team); + _customChannels[channelName] = newChannel; + return newChannel; + } +} - return nullptr; +Channel* ChannelMgr::GetChannel(uint32 channelId, std::string const& name, Player* player, bool pkt /*= true*/, AreaTableEntry const* zoneEntry /*= nullptr*/) const +{ + Channel* ret = nullptr; + bool send = false; + + if (channelId) // builtin + { + ChatChannelsEntry const* channelEntry = sChatChannelsStore.AssertEntry(channelId); + uint32 zoneId = zoneEntry ? zoneEntry->ID : 0; + if (channelEntry->flags & (CHANNEL_DBC_FLAG_GLOBAL | CHANNEL_DBC_FLAG_CITY_ONLY)) + zoneId = 0; + + std::pair<uint32, uint32> key = std::make_pair(channelId, zoneId); + + auto itr = _channels.find(key); + if (itr != _channels.end()) + ret = itr->second; + else + send = true; } + else // custom + { + std::wstring channelName; + if (!Utf8toWStr(name, channelName)) + return nullptr; + + wstrToLower(channelName); + auto itr = _customChannels.find(channelName); + if (itr != _customChannels.end()) + ret = itr->second; + else + send = true; + } + + if (send && pkt) + { + std::string channelName = name; + Channel::GetChannelName(channelName, channelId, player->GetSession()->GetSessionDbcLocale(), zoneEntry); - return i->second; + WorldPacket data; + ChannelMgr::MakeNotOnPacket(&data, channelName); + player->SendDirectMessage(&data); + } + + return ret; } void ChannelMgr::LeftChannel(std::string const& name) { - std::wstring wname; - if (!Utf8toWStr(name, wname)) + std::wstring channelName; + if (!Utf8toWStr(name, channelName)) return; - wstrToLower(wname); + wstrToLower(channelName); + auto itr = _customChannels.find(channelName); + if (itr == _customChannels.end()) + return; - ChannelMap::const_iterator i = channels.find(wname); + Channel* channel = itr->second; + if (!channel->GetNumPlayers()) + { + _customChannels.erase(itr); + delete channel; + } +} - if (i == channels.end()) - return; +void ChannelMgr::LeftChannel(uint32 channelId, AreaTableEntry const* zoneEntry) +{ + ChatChannelsEntry const* channelEntry = sChatChannelsStore.AssertEntry(channelId); + uint32 zoneId = zoneEntry ? zoneEntry->ID : 0; + if (channelEntry->flags & (CHANNEL_DBC_FLAG_GLOBAL | CHANNEL_DBC_FLAG_CITY_ONLY)) + zoneId = 0; + + std::pair<uint32, uint32> key = std::make_pair(channelId, zoneId); - Channel* channel = i->second; + auto itr = _channels.find(key); + if (itr == _channels.end()) + return; - if (!channel->GetNumPlayers() && !channel->IsConstant()) + Channel* channel = itr->second; + if (!channel->GetNumPlayers()) { - channels.erase(wname); + _channels.erase(itr); delete channel; } } @@ -112,5 +196,5 @@ void ChannelMgr::LeftChannel(std::string const& name) void ChannelMgr::MakeNotOnPacket(WorldPacket* data, std::string const& name) { data->Initialize(SMSG_CHANNEL_NOTIFY, 1 + name.size()); - (*data) << uint8(5) << name; + (*data) << uint8(CHAT_NOT_MEMBER_NOTICE) << name; } diff --git a/src/server/game/Chat/Channels/ChannelMgr.h b/src/server/game/Chat/Channels/ChannelMgr.h index abe45690997..c9d85a99812 100644 --- a/src/server/game/Chat/Channels/ChannelMgr.h +++ b/src/server/game/Chat/Channels/ChannelMgr.h @@ -19,36 +19,34 @@ #define __TRINITY_CHANNELMGR_H #include "Common.h" -#include "Channel.h" -#include <map> -#include <string> - -#include "World.h" - -#define MAX_CHANNEL_PASS_STR 31 +class Channel; class TC_GAME_API ChannelMgr { - typedef std::map<std::wstring, Channel*> ChannelMap; + typedef std::unordered_map<std::wstring, Channel*> CustomChannelContainer; // custom channels only differ in name + typedef std::unordered_map<std::pair<uint32 /*channelId*/, uint32 /*zoneId*/>, Channel*> BuiltinChannelContainer; //identify builtin (DBC) channels by zoneId instead, since name changes by client locale protected: - ChannelMgr() : team(0) { } + explicit ChannelMgr(uint32 team) : _team(team) { } ~ChannelMgr(); public: static ChannelMgr* forTeam(uint32 team); - void setTeam(uint32 newTeam) { team = newTeam; } + static Channel* GetChannelForPlayerByNamePart(std::string const& namePart, Player* playerSearcher); - Channel* GetJoinChannel(std::string const& name, uint32 channel_id); - Channel* GetChannel(std::string const& name, Player* p, bool pkt = true); + Channel* GetJoinChannel(uint32 channelId, std::string const& name, AreaTableEntry const* zoneEntry = nullptr); + Channel* GetChannel(uint32 channelId, std::string const& name, Player* player, bool pkt = true, AreaTableEntry const* zoneEntry = nullptr) const; void LeftChannel(std::string const& name); + void LeftChannel(uint32 channelId, AreaTableEntry const* zoneEntry); private: - ChannelMap channels; - uint32 team; + CustomChannelContainer _customChannels; + BuiltinChannelContainer _channels; + uint32 const _team; - void MakeNotOnPacket(WorldPacket* data, std::string const& name); + static void MakeNotOnPacket(WorldPacket* data, std::string const& name); + ChannelMgr() = delete; }; #endif diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index dff6f8c0478..e6681f27e51 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -5172,8 +5172,15 @@ void Player::CleanupChannels() Channel* ch = *m_channels.begin(); m_channels.erase(m_channels.begin()); // remove from player's channel list ch->LeaveChannel(this, false); // not send to client, not remove from player's channel list + + // delete channel if empty if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetTeam())) - cMgr->LeftChannel(ch->GetName()); // deleted channel if empty + { + if (ch->IsConstant()) + cMgr->LeftChannel(ch->GetChannelId(), ch->GetZoneEntry()); + else + cMgr->LeftChannel(ch->GetName()); + } } TC_LOG_DEBUG("chat.system", "Player::CleanupChannels: Channels of player '%s' (%s) cleaned up.", GetName().c_str(), GetGUID().ToString().c_str()); } @@ -5191,7 +5198,6 @@ void Player::UpdateLocalChannels(uint32 newZone) if (!cMgr) return; - std::string current_zone_name = current_zone->area_name[GetSession()->GetSessionDbcLocale()]; for (uint32 i = 0; i < sChatChannelsStore.GetNumRows(); ++i) { ChatChannelsEntry const* channelEntry = sChatChannelsStore.LookupEntry(i); @@ -5219,14 +5225,7 @@ void Player::UpdateLocalChannels(uint32 newZone) if (channelEntry->flags & CHANNEL_DBC_FLAG_CITY_ONLY && usedChannel) continue; // Already on the channel, as city channel names are not changing - std::string currentNameExt; - if (channelEntry->flags & CHANNEL_DBC_FLAG_CITY_ONLY) - currentNameExt = sObjectMgr->GetTrinityStringForDBCLocale(LANG_CHANNEL_CITY); - else - currentNameExt = current_zone_name; - - std::string newChannelName = Trinity::StringFormat(channelEntry->pattern[m_session->GetSessionDbcLocale()], currentNameExt.c_str()); - joinChannel = cMgr->GetJoinChannel(newChannelName, channelEntry->ChannelID); + joinChannel = cMgr->GetJoinChannel(channelEntry->ChannelID, std::string(), current_zone); if (usedChannel) { if (joinChannel != usedChannel) @@ -5239,7 +5238,7 @@ void Player::UpdateLocalChannels(uint32 newZone) } } else - joinChannel = cMgr->GetJoinChannel(channelEntry->pattern[m_session->GetSessionDbcLocale()], channelEntry->ChannelID); + joinChannel = cMgr->GetJoinChannel(channelEntry->ChannelID, std::string()); } else removeChannel = usedChannel; @@ -5249,10 +5248,10 @@ void Player::UpdateLocalChannels(uint32 newZone) if (removeChannel) { - removeChannel->LeaveChannel(this, sendRemove); // Leave old channel - std::string name = removeChannel->GetName(); // Store name, (*i)erase in LeftChannel - LeftChannel(removeChannel); // Remove from player's channel list - cMgr->LeftChannel(name); // Delete if empty + removeChannel->LeaveChannel(this, sendRemove); // Leave old channel + + LeftChannel(removeChannel); // Remove from player's channel list + cMgr->LeftChannel(removeChannel->GetChannelId(), removeChannel->GetZoneEntry()); // Delete if empty } } } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 2f580908e2b..7c4bf2f9471 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1847,6 +1847,9 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void UpdateLocalChannels(uint32 newZone); void LeaveLFGChannel(); + typedef std::list<Channel*> JoinedChannelsList; + JoinedChannelsList const& GetJoinedChannels() const { return m_channels; } + void UpdateDefense(); void UpdateWeaponSkill (WeaponAttackType attType); void UpdateCombatSkills(Unit* victim, WeaponAttackType attType, bool defense); @@ -2454,7 +2457,6 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> WorldSession* m_session; - typedef std::list<Channel*> JoinedChannelsList; JoinedChannelsList m_channels; uint8 m_cinematic; diff --git a/src/server/game/Handlers/ChannelHandler.cpp b/src/server/game/Handlers/ChannelHandler.cpp index 9285f4247b2..71cdddcebf5 100644 --- a/src/server/game/Handlers/ChannelHandler.cpp +++ b/src/server/game/Handlers/ChannelHandler.cpp @@ -17,11 +17,15 @@ */ #include "ObjectMgr.h" // for normalizePlayerName +#include "Channel.h" #include "ChannelMgr.h" #include "Player.h" +#include "WorldSession.h" #include <cctype> +static size_t const MAX_CHANNEL_PASS_STR = 31; + void WorldSession::HandleJoinChannel(WorldPacket& recvPacket) { uint32 channelId; @@ -33,13 +37,13 @@ void WorldSession::HandleJoinChannel(WorldPacket& recvPacket) TC_LOG_DEBUG("chat.system", "CMSG_JOIN_CHANNEL %s Channel: %u, unk1: %u, unk2: %u, channel: %s, password: %s", GetPlayerInfo().c_str(), channelId, unknown1, unknown2, channelName.c_str(), password.c_str()); + AreaTableEntry const* zone = sAreaTableStore.LookupEntry(GetPlayer()->GetZoneId()); if (channelId) { ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(channelId); if (!channel) return; - AreaTableEntry const* zone = sAreaTableStore.LookupEntry(GetPlayer()->GetZoneId()); if (!zone || !GetPlayer()->CanJoinConstantChannelInZone(channel, zone)) return; } @@ -51,30 +55,42 @@ void WorldSession::HandleJoinChannel(WorldPacket& recvPacket) return; if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeam())) - { - cMgr->setTeam(GetPlayer()->GetTeam()); - if (Channel* channel = cMgr->GetJoinChannel(channelName, channelId)) + if (Channel* channel = cMgr->GetJoinChannel(channelId, channelName, zone)) channel->JoinChannel(GetPlayer(), password); - } } void WorldSession::HandleLeaveChannel(WorldPacket& recvPacket) { - uint32 unk; + uint32 channelId; std::string channelName; - recvPacket >> unk >> channelName; + recvPacket >> channelId >> channelName; - TC_LOG_DEBUG("chat.system", "CMSG_LEAVE_CHANNEL %s Channel: %s, unk1: %u", - GetPlayerInfo().c_str(), channelName.c_str(), unk); + TC_LOG_DEBUG("chat.system", "CMSG_LEAVE_CHANNEL %s Channel: %s, channelId: %u", + GetPlayerInfo().c_str(), channelName.c_str(), channelId); - if (channelName.empty()) + if (channelName.empty() && !channelId) return; + AreaTableEntry const* zone = sAreaTableStore.LookupEntry(GetPlayer()->GetZoneId()); + if (channelId) + { + ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(channelId); + if (!channel) + return; + + if (!zone || !GetPlayer()->CanJoinConstantChannelInZone(channel, zone)) + return; + } + if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeam())) { - if (Channel* channel = cMgr->GetChannel(channelName, GetPlayer())) + if (Channel* channel = cMgr->GetChannel(channelId, channelName, GetPlayer(), true, zone)) channel->LeaveChannel(GetPlayer(), true); - cMgr->LeftChannel(channelName); + + if (channelId) + cMgr->LeftChannel(channelId, zone); + else + cMgr->LeftChannel(channelName); } } @@ -87,9 +103,8 @@ void WorldSession::HandleChannelList(WorldPacket& recvPacket) recvPacket.GetOpcode() == CMSG_CHANNEL_DISPLAY_LIST ? "CMSG_CHANNEL_DISPLAY_LIST" : "CMSG_CHANNEL_LIST", GetPlayerInfo().c_str(), channelName.c_str()); - if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeam())) - if (Channel* channel = cMgr->GetChannel(channelName, GetPlayer())) - channel->List(GetPlayer()); + if (Channel* channel = ChannelMgr::GetChannelForPlayerByNamePart(channelName, GetPlayer())) + channel->List(GetPlayer()); } void WorldSession::HandleChannelPassword(WorldPacket& recvPacket) @@ -103,9 +118,8 @@ void WorldSession::HandleChannelPassword(WorldPacket& recvPacket) if (password.length() > MAX_CHANNEL_PASS_STR) return; - if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeam())) - if (Channel* channel = cMgr->GetChannel(channelName, GetPlayer())) - channel->Password(GetPlayer(), password); + if (Channel* channel = ChannelMgr::GetChannelForPlayerByNamePart(channelName, GetPlayer())) + channel->Password(GetPlayer(), password); } void WorldSession::HandleChannelSetOwner(WorldPacket& recvPacket) @@ -119,9 +133,8 @@ void WorldSession::HandleChannelSetOwner(WorldPacket& recvPacket) if (!normalizePlayerName(targetName)) return; - if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeam())) - if (Channel* channel = cMgr->GetChannel(channelName, GetPlayer())) - channel->SetOwner(GetPlayer(), targetName); + if (Channel* channel = ChannelMgr::GetChannelForPlayerByNamePart(channelName, GetPlayer())) + channel->SetOwner(GetPlayer(), targetName); } void WorldSession::HandleChannelOwner(WorldPacket& recvPacket) @@ -132,9 +145,8 @@ void WorldSession::HandleChannelOwner(WorldPacket& recvPacket) TC_LOG_DEBUG("chat.system", "CMSG_CHANNEL_OWNER %s Channel: %s", GetPlayerInfo().c_str(), channelName.c_str()); - if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeam())) - if (Channel* channel = cMgr->GetChannel(channelName, GetPlayer())) - channel->SendWhoOwner(GetPlayer()->GetGUID()); + if (Channel* channel = ChannelMgr::GetChannelForPlayerByNamePart(channelName, GetPlayer())) + channel->SendWhoOwner(GetPlayer()->GetGUID()); } void WorldSession::HandleChannelModerator(WorldPacket& recvPacket) @@ -148,9 +160,8 @@ void WorldSession::HandleChannelModerator(WorldPacket& recvPacket) if (!normalizePlayerName(targetName)) return; - if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeam())) - if (Channel* channel = cMgr->GetChannel(channelName, GetPlayer())) - channel->SetModerator(GetPlayer(), targetName); + if (Channel* channel = ChannelMgr::GetChannelForPlayerByNamePart(channelName, GetPlayer())) + channel->SetModerator(GetPlayer(), targetName); } void WorldSession::HandleChannelUnmoderator(WorldPacket& recvPacket) @@ -164,9 +175,8 @@ void WorldSession::HandleChannelUnmoderator(WorldPacket& recvPacket) if (!normalizePlayerName(targetName)) return; - if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeam())) - if (Channel* channel = cMgr->GetChannel(channelName, GetPlayer())) - channel->UnsetModerator(GetPlayer(), targetName); + if (Channel* channel = ChannelMgr::GetChannelForPlayerByNamePart(channelName, GetPlayer())) + channel->UnsetModerator(GetPlayer(), targetName); } void WorldSession::HandleChannelMute(WorldPacket& recvPacket) @@ -180,9 +190,8 @@ void WorldSession::HandleChannelMute(WorldPacket& recvPacket) if (!normalizePlayerName(targetName)) return; - if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeam())) - if (Channel* channel = cMgr->GetChannel(channelName, GetPlayer())) - channel->SetMute(GetPlayer(), targetName); + if (Channel* channel = ChannelMgr::GetChannelForPlayerByNamePart(channelName, GetPlayer())) + channel->SetMute(GetPlayer(), targetName); } void WorldSession::HandleChannelUnmute(WorldPacket& recvPacket) @@ -196,9 +205,8 @@ void WorldSession::HandleChannelUnmute(WorldPacket& recvPacket) if (!normalizePlayerName(targetName)) return; - if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeam())) - if (Channel* channel = cMgr->GetChannel(channelName, GetPlayer())) - channel->UnsetMute(GetPlayer(), targetName); + if (Channel* channel = ChannelMgr::GetChannelForPlayerByNamePart(channelName, GetPlayer())) + channel->UnsetMute(GetPlayer(), targetName); } void WorldSession::HandleChannelInvite(WorldPacket& recvPacket) @@ -212,9 +220,8 @@ void WorldSession::HandleChannelInvite(WorldPacket& recvPacket) if (!normalizePlayerName(targetName)) return; - if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeam())) - if (Channel* channel = cMgr->GetChannel(channelName, GetPlayer())) - channel->Invite(GetPlayer(), targetName); + if (Channel* channel = ChannelMgr::GetChannelForPlayerByNamePart(channelName, GetPlayer())) + channel->Invite(GetPlayer(), targetName); } void WorldSession::HandleChannelKick(WorldPacket& recvPacket) @@ -228,9 +235,8 @@ void WorldSession::HandleChannelKick(WorldPacket& recvPacket) if (!normalizePlayerName(targetName)) return; - if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeam())) - if (Channel* channel = cMgr->GetChannel(channelName, GetPlayer())) - channel->Kick(GetPlayer(), targetName); + if (Channel* channel = ChannelMgr::GetChannelForPlayerByNamePart(channelName, GetPlayer())) + channel->Kick(GetPlayer(), targetName); } void WorldSession::HandleChannelBan(WorldPacket& recvPacket) @@ -244,9 +250,8 @@ void WorldSession::HandleChannelBan(WorldPacket& recvPacket) if (!normalizePlayerName(targetName)) return; - if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeam())) - if (Channel* channel = cMgr->GetChannel(channelName, GetPlayer())) - channel->Ban(GetPlayer(), targetName); + if (Channel* channel = ChannelMgr::GetChannelForPlayerByNamePart(channelName, GetPlayer())) + channel->Ban(GetPlayer(), targetName); } void WorldSession::HandleChannelUnban(WorldPacket& recvPacket) @@ -260,9 +265,8 @@ void WorldSession::HandleChannelUnban(WorldPacket& recvPacket) if (!normalizePlayerName(targetName)) return; - if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeam())) - if (Channel* channel = cMgr->GetChannel(channelName, GetPlayer())) - channel->UnBan(GetPlayer(), targetName); + if (Channel* channel = ChannelMgr::GetChannelForPlayerByNamePart(channelName, GetPlayer())) + channel->UnBan(GetPlayer(), targetName); } void WorldSession::HandleChannelAnnouncements(WorldPacket& recvPacket) @@ -273,9 +277,8 @@ void WorldSession::HandleChannelAnnouncements(WorldPacket& recvPacket) TC_LOG_DEBUG("chat.system", "CMSG_CHANNEL_ANNOUNCEMENTS %s Channel: %s", GetPlayerInfo().c_str(), channelName.c_str()); - if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeam())) - if (Channel* channel = cMgr->GetChannel(channelName, GetPlayer())) - channel->Announce(GetPlayer()); + if (Channel* channel = ChannelMgr::GetChannelForPlayerByNamePart(channelName, GetPlayer())) + channel->Announce(GetPlayer()); } void WorldSession::HandleChannelDisplayListQuery(WorldPacket &recvPacket) @@ -292,19 +295,17 @@ void WorldSession::HandleGetChannelMemberCount(WorldPacket &recvPacket) TC_LOG_DEBUG("chat.system", "CMSG_GET_CHANNEL_MEMBER_COUNT %s Channel: %s", GetPlayerInfo().c_str(), channelName.c_str()); - if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeam())) + if (Channel* channel = ChannelMgr::GetChannelForPlayerByNamePart(channelName, GetPlayer())) { - if (Channel* channel = cMgr->GetChannel(channelName, GetPlayer())) - { - TC_LOG_DEBUG("chat.system", "SMSG_CHANNEL_MEMBER_COUNT %s Channel: %s Count: %u", - GetPlayerInfo().c_str(), channelName.c_str(), channel->GetNumPlayers()); - - WorldPacket data(SMSG_CHANNEL_MEMBER_COUNT, channel->GetName().size() + 1 + 4); - data << channel->GetName(); - data << uint8(channel->GetFlags()); - data << uint32(channel->GetNumPlayers()); - SendPacket(&data); - } + TC_LOG_DEBUG("chat.system", "SMSG_CHANNEL_MEMBER_COUNT %s Channel: %s Count: %u", + GetPlayerInfo().c_str(), channelName.c_str(), channel->GetNumPlayers()); + + std::string name = channel->GetName(GetSessionDbcLocale()); + WorldPacket data(SMSG_CHANNEL_MEMBER_COUNT, name.size() + 1 + 4); + data << name; + data << uint8(channel->GetFlags()); + data << uint32(channel->GetNumPlayers()); + SendPacket(&data); } } @@ -317,8 +318,7 @@ void WorldSession::HandleSetChannelWatch(WorldPacket &recvPacket) GetPlayerInfo().c_str(), channelName.c_str()); /* - if (ChannelMgr* cMgr = channelMgr(GetPlayer()->GetTeam())) - if (Channel* channel = cMgr->GetChannel(channelName, GetPlayer())) - channel->JoinNotify(GetPlayer()); + if (Channel* channel = ChannelMgr::GetChannelForPlayerByNamePart(channelName, GetPlayer())) + channel->JoinNotify(GetPlayer()); */ } diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp index 2b1660fef2b..ba5164f9be5 100644 --- a/src/server/game/Handlers/ChatHandler.cpp +++ b/src/server/game/Handlers/ChatHandler.cpp @@ -26,6 +26,7 @@ #include "DatabaseEnv.h" #include "CellImpl.h" #include "Chat.h" +#include "Channel.h" #include "ChannelMgr.h" #include "GridNotifiersImpl.h" #include "Group.h" @@ -461,13 +462,10 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) } } - if (ChannelMgr* cMgr = ChannelMgr::forTeam(sender->GetTeam())) + if (Channel* chn = ChannelMgr::GetChannelForPlayerByNamePart(channel, sender)) { - if (Channel* chn = cMgr->GetChannel(channel, sender)) - { - sScriptMgr->OnPlayerChat(sender, type, lang, msg, chn); - chn->Say(sender->GetGUID(), msg.c_str(), lang); - } + sScriptMgr->OnPlayerChat(sender, type, lang, msg, chn); + chn->Say(sender->GetGUID(), msg.c_str(), lang); } break; } diff --git a/src/server/scripts/Commands/cs_message.cpp b/src/server/scripts/Commands/cs_message.cpp index 69ff04ffb46..4b3caae686b 100644 --- a/src/server/scripts/Commands/cs_message.cpp +++ b/src/server/scripts/Commands/cs_message.cpp @@ -24,6 +24,7 @@ EndScriptData */ #include "ScriptMgr.h" #include "Chat.h" +#include "Channel.h" #include "ChannelMgr.h" #include "Language.h" #include "Player.h" @@ -63,21 +64,49 @@ public: if (!*args) return false; char const* channelStr = strtok((char*)args, " "); - char const* argStr = strtok(NULL, ""); + char const* argStr = strtok(nullptr, ""); if (!channelStr || !argStr) return false; + uint32 channelId = 0; + for (uint32 i = 0; i < sChatChannelsStore.GetNumRows(); ++i) + { + ChatChannelsEntry const* entry = sChatChannelsStore.LookupEntry(i); + if (!entry) + continue; + + if (strstr(entry->pattern[handler->GetSessionDbcLocale()], channelStr)) + { + channelId = i; + break; + } + } + + AreaTableEntry const* zoneEntry = nullptr; + for (uint32 i = 0; i < sAreaTableStore.GetNumRows(); ++i) + { + AreaTableEntry const* entry = sAreaTableStore.LookupEntry(i); + if (!entry) + continue; + + if (strstr(entry->area_name[handler->GetSessionDbcLocale()], channelStr)) + { + zoneEntry = entry; + break; + } + } + Player* player = handler->GetSession()->GetPlayer(); - Channel* channcel = NULL; + Channel* channel = nullptr; if (ChannelMgr* cMgr = ChannelMgr::forTeam(player->GetTeam())) - channcel = cMgr->GetChannel(channelStr, player); + channel = cMgr->GetChannel(channelId, channelStr, player, false, zoneEntry); if (strcmp(argStr, "on") == 0) { - if (channcel) - channcel->SetOwnership(true); + if (channel) + channel->SetOwnership(true); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHANNEL_OWNERSHIP); stmt->setUInt8 (0, 1); stmt->setString(1, channelStr); @@ -86,8 +115,8 @@ public: } else if (strcmp(argStr, "off") == 0) { - if (channcel) - channcel->SetOwnership(false); + if (channel) + channel->SetOwnership(false); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHANNEL_OWNERSHIP); stmt->setUInt8 (0, 0); stmt->setString(1, channelStr); |