diff options
-rw-r--r-- | src/server/database/Database/Implementation/CharacterDatabase.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Chat/Channels/Channel.cpp | 1013 | ||||
-rw-r--r-- | src/server/game/Chat/Channels/Channel.h | 130 | ||||
-rw-r--r-- | src/server/game/Chat/Channels/ChannelAppenders.h | 473 | ||||
-rw-r--r-- | src/server/game/Chat/Channels/ChannelMgr.cpp | 148 | ||||
-rw-r--r-- | src/server/game/Chat/Channels/ChannelMgr.h | 22 | ||||
-rw-r--r-- | src/server/game/Chat/Chat.cpp | 86 | ||||
-rw-r--r-- | src/server/game/Chat/Chat.h | 14 | ||||
-rw-r--r-- | src/server/game/Chat/ChatLink.cpp | 22 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 99 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 4 | ||||
-rw-r--r-- | src/server/game/Handlers/ChannelHandler.cpp | 46 | ||||
-rw-r--r-- | src/server/game/Handlers/ChatHandler.cpp | 15 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_message.cpp | 45 |
14 files changed, 1323 insertions, 796 deletions
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index 007a7a07ee7..e5ca505cd38 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp @@ -271,7 +271,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() " ON DUPLICATE KEY UPDATE LogGuid = VALUES (LogGuid), EventType = VALUES (EventType), PlayerGuid = VALUES (PlayerGuid), Flags = VALUES (Flags), Value = VALUES (Value), Timestamp = VALUES (Timestamp)", CONNECTION_ASYNC); // 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 e2fee9c2faf..6a6a6ff3e2d 100644 --- a/src/server/game/Chat/Channels/Channel.cpp +++ b/src/server/game/Chat/Channels/Channel.cpp @@ -17,119 +17,147 @@ */ #include "Channel.h" +#include "ChannelAppenders.h" #include "AccountMgr.h" -#include "ChannelPackets.h" #include "Chat.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" #include "DatabaseEnv.h" #include "ObjectMgr.h" +#include "Language.h" #include "Player.h" #include "SocialMgr.h" #include "World.h" -Channel::Channel(std::string const& name, uint32 channelId, uint32 team): - _announce(true), - _ownership(true), - _IsSaved(false), - _flags(0), +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(CHANNEL_FLAG_GENERAL), // for all built-in channels _channelId(channelId), - _team(team), - _name(name) -{ - // set special flags if built-in channel - if (ChatChannelsEntry const* ch = sChatChannelsStore.LookupEntry(channelId)) // check whether it's a built-in channel - { - _announce = false; // no join/leave announces - _ownership = false; // no ownership handout - - _flags |= CHANNEL_FLAG_GENERAL; // for all built-in channels - - if (ch->Flags & CHANNEL_DBC_FLAG_TRADE) // for trade channel - _flags |= CHANNEL_FLAG_TRADE; - - if (ch->Flags & CHANNEL_DBC_FLAG_CITY_ONLY2) // for city only channels - _flags |= CHANNEL_FLAG_CITY; - - if (ch->Flags & CHANNEL_DBC_FLAG_LFG) // for LFG channel - _flags |= CHANNEL_FLAG_LFG; - else // for all other channels - _flags |= CHANNEL_FLAG_NOT_LFG; - } - else // it's custom channel - { - _flags |= 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)) + _channelTeam(team), + _zoneEntry(zoneEntry) +{ + ChatChannelsEntry const* channelEntry = sChatChannelsStore.AssertEntry(channelId); + if (channelEntry->Flags & CHANNEL_DBC_FLAG_TRADE) // for trade channel + _channelFlags |= CHANNEL_FLAG_TRADE; + + if (channelEntry->Flags & CHANNEL_DBC_FLAG_CITY_ONLY2) // for city only channels + _channelFlags |= CHANNEL_FLAG_CITY; + + if (channelEntry->Flags & CHANNEL_DBC_FLAG_LFG) // for LFG channel + _channelFlags |= CHANNEL_FLAG_LFG; + else // for all other channels + _channelFlags |= CHANNEL_FLAG_NOT_LFG; +} + +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), + _channelName(name), + _zoneEntry(nullptr) +{ + // 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, _channelName); + 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, _team); - 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 bannedList = fields[4].GetString(); + + if (!bannedList.empty()) { - Field* fields = result->Fetch(); - _announce = fields[0].GetBool(); - _ownership = fields[1].GetBool(); - _password = fields[2].GetString(); - std::string bannedList = fields[3].GetString(); - - if (!bannedList.empty()) + Tokenizer tokens(bannedList, ' '); + for (auto const& token : tokens) { - Tokenizer tokens(bannedList, ' '); - for (Tokenizer::const_iterator i = tokens.begin(); i != tokens.end(); ++i) + std::string bannedGuidStr(token); + ObjectGuid bannedGuid; + bannedGuid.SetRawValue(uint64(strtoull(bannedGuidStr.substr(0, 16).c_str(), nullptr, 16)), uint64(strtoull(bannedGuidStr.substr(16).c_str(), nullptr, 16))); + if (!bannedGuid.IsEmpty()) { - std::string bannedGuidStr(*i); - ObjectGuid bannedGuid; - bannedGuid.SetRawValue(uint64(strtoull(bannedGuidStr.substr(0, 16).c_str(), nullptr, 16)), uint64(strtoull(bannedGuidStr.substr(16).c_str(), nullptr, 16))); - if (!bannedGuid.IsEmpty()) - { - TC_LOG_DEBUG("chat.system", "Channel (%s) loaded bannedStore %s", _name.c_str(), bannedGuid.ToString().c_str()); - _bannedStore.insert(bannedGuid); - } + TC_LOG_DEBUG("chat.system", "Channel (%s) loaded player %s into bannedStore", _channelName.c_str(), bannedGuid.ToString().c_str()); + _bannedStore.insert(bannedGuid); } } } - else // save - { - stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHANNEL); - stmt->setString(0, _name); - stmt->setUInt32(1, _team); - 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, _channelName); + stmt->setUInt32(1, _channelTeam); + CharacterDatabase.Execute(stmt); + TC_LOG_DEBUG("chat.system", "Channel (%s) saved in database", _channelName.c_str()); + } - _IsSaved = 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->Name->Str[locale], sObjectMgr->GetTrinityString(LANG_CHANNEL_CITY, locale)); + else + channelName = Trinity::StringFormat(channelEntry->Name->Str[locale], ASSERT_NOTNULL(zoneEntry)->AreaName->Str[locale]); } + else + channelName = channelEntry->Name->Str[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 (_IsSaved) + if (_persistentChannel) { std::ostringstream banlist; for (ObjectGuid const& guid : _bannedStore) banlist << guid << ' '; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHANNEL); - stmt->setBool(0, _announce); - stmt->setBool(1, _ownership); - stmt->setString(2, _password); + stmt->setBool(0, _announceEnabled); + stmt->setBool(1, _ownershipEnabled); + stmt->setString(2, _channelPassword); stmt->setString(3, banlist.str()); - stmt->setString(4, _name); - stmt->setUInt32(5, _team); + stmt->setString(4, _channelName); + stmt->setUInt32(5, _channelTeam); CharacterDatabase.Execute(stmt); - TC_LOG_DEBUG("chat.system", "Channel (%s) updated in database", _name.c_str()); + TC_LOG_DEBUG("chat.system", "Channel (%s) updated in database", _channelName.c_str()); } } void Channel::UpdateChannelUseageInDB() const { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHANNEL_USAGE); - stmt->setString(0, _name); - stmt->setUInt32(1, _team); + stmt->setString(0, _channelName); + stmt->setUInt32(1, _channelTeam); CharacterDatabase.Execute(stmt); } @@ -153,26 +181,26 @@ void Channel::JoinChannel(Player* player, std::string const& pass) // Do not send error message for built-in channels if (!IsConstant()) { - WorldPackets::Channel::ChannelNotify notify; - MakePlayerAlreadyMember(notify, guid); - player->SendDirectMessage(notify.Write()); + PlayerAlreadyMemberAppend appender(guid); + ChannelNameBuilder<PlayerAlreadyMemberAppend> builder(this, appender); + SendToOne(builder, guid); } return; } if (IsBanned(guid)) { - WorldPackets::Channel::ChannelNotify notify; - MakeBanned(notify); - player->SendDirectMessage(notify.Write()); + BannedAppend appender; + ChannelNameBuilder<BannedAppend> builder(this, appender); + SendToOne(builder, guid); return; } - if (!_password.empty() && pass != _password) + if (!_channelPassword.empty() && pass != _channelPassword) { - WorldPackets::Channel::ChannelNotify notify; - MakeWrongPassword(notify); - player->SendDirectMessage(notify.Write()); + WrongPasswordAppend appender; + ChannelNameBuilder<WrongPasswordAppend> builder(this, appender); + SendToOne(builder, guid); return; } @@ -181,38 +209,44 @@ void Channel::JoinChannel(Player* player, std::string const& pass) AccountMgr::IsPlayerAccount(player->GetSession()->GetSecurity()) && //FIXME: Move to RBAC player->GetGroup()) { - WorldPackets::Channel::ChannelNotify notify; - MakeNotInLfg(notify); - player->SendDirectMessage(notify.Write()); + NotInLFGAppend appender; + ChannelNameBuilder<NotInLFGAppend> builder(this, appender); + SendToOne(builder, guid); return; } player->JoinedChannel(this); - if (_announce && !player->GetSession()->HasPermission(rbac::RBAC_PERM_SILENTLY_JOIN_CHANNEL)) + if (_announceEnabled && !player->GetSession()->HasPermission(rbac::RBAC_PERM_SILENTLY_JOIN_CHANNEL)) { - WorldPackets::Channel::ChannelNotify notify; - MakeJoined(notify, guid); - SendToAll(notify.Write()); + JoinedAppend appender(guid); + ChannelNameBuilder<JoinedAppend> builder(this, appender); + SendToAll(builder); } - PlayerInfo playerInfo; - playerInfo.PlayerGuid = guid; - _playersStore[guid] = playerInfo; + bool newChannel = _playersStore.empty(); + + PlayerInfo& playerInfo = _playersStore[guid]; + playerInfo.SetInvisible(!player->isGMVisible()); /* - WorldPackets::Channel::ChannelNotify notify; - MakeYouJoined(notify); - player->SendDirectMessage(notify.Write()); + YouJoinedAppend appender; + ChannelNameBuilder<YouJoinedAppend> builder(this, appender); + SendToOne(builder, guid); */ - WorldPackets::Channel::ChannelNotifyJoined notify; - //notify.ChannelWelcomeMsg = ""; - notify.ChatChannelID = _channelId; - //notify.InstanceID = 0; - notify._ChannelFlags = _flags; - notify._Channel = _name; - player->SendDirectMessage(notify.Write()); + auto builder = [&](LocaleConstant /*locale*/) + { + WorldPackets::Channel::ChannelNotifyJoined* notify = new WorldPackets::Channel::ChannelNotifyJoined(); + //notify->ChannelWelcomeMsg = ""; + notify->ChatChannelID = _channelId; + //notify->InstanceID = 0; + notify->_ChannelFlags = _channelFlags; + notify->_Channel = _channelName; + return notify; + }; + + SendToOne(builder, guid); JoinNotify(player); @@ -224,10 +258,14 @@ void Channel::JoinChannel(Player* player, std::string const& pass) UpdateChannelUseageInDB(); // If the channel has no owner yet and ownership is allowed, set the new owner. - if (_ownerGUID.IsEmpty() && _ownership) + // or if the owner was a GM with .gm visible off + // don't do this if the new player is, too, an invis GM, unless the channel was empty + if (_ownershipEnabled && (newChannel || !playerInfo.IsInvisible()) && (_ownerGuid.IsEmpty() || _isOwnerInvisible)) { - SetOwner(guid, _playersStore.size() > 1); - _playersStore[guid].SetModerator(true); + _isOwnerInvisible = playerInfo.IsInvisible(); + + SetOwner(guid, !newChannel && !_isOwnerInvisible); + playerInfo.SetModerator(true); } } } @@ -239,9 +277,9 @@ void Channel::LeaveChannel(Player* player, bool send) { if (send) { - WorldPackets::Channel::ChannelNotify notify; - MakeNotMember(notify); - player->SendDirectMessage(notify.Write()); + NotMemberAppend appender; + ChannelNameBuilder<NotMemberAppend> builder(this, appender); + SendToOne(builder, guid); } return; } @@ -251,27 +289,34 @@ void Channel::LeaveChannel(Player* player, bool send) if (send) { /* - WorldPackets::Channel::ChannelNotify notify; - MakeYouLeft(notify); - player->SendDirectMessage(notify.Write()); + YouLeftAppend appender; + ChannelNameBuilder<YouLeftAppend> builder(this, appender); + SendToOne(builder, guid); */ - WorldPackets::Channel::ChannelNotifyLeft notify; - notify.Channel = _name; - notify.ChatChannelID = 0; - //notify.Suspended = false; - player->SendDirectMessage(notify.Write()); - } + auto builder = [&](LocaleConstant locale) + { + LocaleConstant localeIdx = sWorld->GetAvailableDbcLocale(locale); + + WorldPackets::Channel::ChannelNotifyLeft* notify = new WorldPackets::Channel::ChannelNotifyLeft(); + notify->Channel = GetName(localeIdx); + notify->ChatChannelID = 0; + //notify->Suspended = false; + return notify; + }; - bool changeowner = _playersStore[guid].IsOwner(); + SendToOne(builder, guid); + } + PlayerInfo& info = _playersStore.at(guid); + bool changeowner = info.IsOwner(); _playersStore.erase(guid); - if (_announce && !player->GetSession()->HasPermission(rbac::RBAC_PERM_SILENTLY_JOIN_CHANNEL)) + if (_announceEnabled && !player->GetSession()->HasPermission(rbac::RBAC_PERM_SILENTLY_JOIN_CHANNEL)) { - WorldPackets::Channel::ChannelNotify notify; - MakeLeft(notify, guid); - SendToAll(notify.Write()); + LeftAppend appender(guid); + ChannelNameBuilder<LeftAppend> builder(this, appender); + SendToAll(builder); } LeaveNotify(player); @@ -282,11 +327,27 @@ void Channel::LeaveChannel(Player* player, bool send) UpdateChannelUseageInDB(); // If the channel owner left and there are still playersStore inside, pick a new owner - if (changeowner && _ownership && !_playersStore.empty()) + // do not pick invisible gm owner unless there are only invisible gms in that channel (rare) + if (changeowner && _ownershipEnabled && !_playersStore.empty()) { - ObjectGuid const& newowner = _playersStore.begin()->second.PlayerGuid; - _playersStore[newowner].SetModerator(true); + PlayerContainer::iterator itr; + for (itr = _playersStore.begin(); itr != _playersStore.end(); ++itr) + { + if (!itr->second.IsInvisible()) + break; + } + + if (itr == _playersStore.end()) + itr = _playersStore.begin(); + + ObjectGuid const& newowner = itr->first; + itr->second.SetModerator(true); + SetOwner(newowner); + + // if the new owner is invisible gm, set flag to automatically choose a new owner + if (itr->second.IsInvisible()) + _isOwnerInvisible = true; } } } @@ -297,37 +358,38 @@ void Channel::KickOrBan(Player const* player, std::string const& badname, bool b if (!IsOn(good)) { - WorldPackets::Channel::ChannelNotify notify; - MakeNotMember(notify); - player->SendDirectMessage(notify.Write()); + NotMemberAppend appender; + ChannelNameBuilder<NotMemberAppend> builder(this, appender); + SendToOne(builder, good); return; } - if (!_playersStore[good].IsModerator() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) + PlayerInfo& info = _playersStore.at(good); + if (!info.IsModerator() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) { - WorldPackets::Channel::ChannelNotify notify; - MakeNotModerator(notify); - player->SendDirectMessage(notify.Write()); + NotModeratorAppend appender; + ChannelNameBuilder<NotModeratorAppend> builder(this, appender); + SendToOne(builder, good); return; } Player* bad = ObjectAccessor::FindConnectedPlayerByName(badname); - ObjectGuid victim = bad ? bad->GetGUID() : ObjectGuid::Empty; + ObjectGuid const& victim = bad ? bad->GetGUID() : ObjectGuid::Empty; if (!victim || !IsOn(victim)) { - WorldPackets::Channel::ChannelNotify notify; - MakePlayerNotFound(notify, badname); - player->SendDirectMessage(notify.Write()); + PlayerNotFoundAppend appender(badname); + ChannelNameBuilder<PlayerNotFoundAppend> builder(this, appender); + SendToOne(builder, good); return; } - bool changeowner = _ownerGUID == victim; + bool changeowner = _ownerGuid == victim; - if (!player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR) && changeowner && good != _ownerGUID) + if (!player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR) && changeowner && good != _ownerGuid) { - WorldPackets::Channel::ChannelNotify notify; - MakeNotOwner(notify); - player->SendDirectMessage(notify.Write()); + NotOwnerAppend appender; + ChannelNameBuilder<NotOwnerAppend> builder(this, appender); + SendToOne(builder, good); return; } @@ -338,24 +400,24 @@ void Channel::KickOrBan(Player const* player, std::string const& badname, bool b if (!player->GetSession()->HasPermission(rbac::RBAC_PERM_SILENTLY_JOIN_CHANNEL)) { - WorldPackets::Channel::ChannelNotify notify; - MakePlayerBanned(notify, victim, good); - SendToAll(notify.Write()); + PlayerBannedAppend appender(good, victim); + ChannelNameBuilder<PlayerBannedAppend> builder(this, appender); + SendToAll(builder); } } else if (!player->GetSession()->HasPermission(rbac::RBAC_PERM_SILENTLY_JOIN_CHANNEL)) { - WorldPackets::Channel::ChannelNotify notify; - MakePlayerKicked(notify, victim, good); - SendToAll(notify.Write()); + PlayerKickedAppend appender(good, victim); + ChannelNameBuilder<PlayerKickedAppend> builder(this, appender); + SendToAll(builder); } _playersStore.erase(victim); bad->LeftChannel(this); - if (changeowner && _ownership && !_playersStore.empty()) + if (changeowner && _ownershipEnabled && !_playersStore.empty()) { - _playersStore[good].SetModerator(true); + info.SetModerator(true); SetOwner(good); } } @@ -366,17 +428,18 @@ void Channel::UnBan(Player const* player, std::string const& badname) if (!IsOn(good)) { - WorldPackets::Channel::ChannelNotify notify; - MakeNotMember(notify); - player->SendDirectMessage(notify.Write()); + NotMemberAppend appender; + ChannelNameBuilder<NotMemberAppend> builder(this, appender); + SendToOne(builder, good); return; } - if (!_playersStore[good].IsModerator() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) + PlayerInfo& info = _playersStore.at(good); + if (!info.IsModerator() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) { - WorldPackets::Channel::ChannelNotify notify; - MakeNotModerator(notify); - player->SendDirectMessage(notify.Write()); + NotModeratorAppend appender; + ChannelNameBuilder<NotModeratorAppend> builder(this, appender); + SendToOne(builder, good); return; } @@ -385,17 +448,17 @@ void Channel::UnBan(Player const* player, std::string const& badname) if (victim.IsEmpty() || !IsBanned(victim)) { - WorldPackets::Channel::ChannelNotify notify; - MakePlayerNotFound(notify, badname); - player->SendDirectMessage(notify.Write()); + PlayerNotFoundAppend appender(badname); + ChannelNameBuilder<PlayerNotFoundAppend> builder(this, appender); + SendToOne(builder, good); return; } _bannedStore.erase(victim); - WorldPackets::Channel::ChannelNotify notify; - MakePlayerUnbanned(notify, victim, good); - SendToAll(notify.Write()); + PlayerUnbannedAppend appender(good, victim); + ChannelNameBuilder<PlayerUnbannedAppend> builder(this, appender); + SendToAll(builder); UpdateChannelInDB(); } @@ -406,25 +469,26 @@ void Channel::Password(Player const* player, std::string const& pass) if (!IsOn(guid)) { - WorldPackets::Channel::ChannelNotify notify; - MakeNotMember(notify); - player->SendDirectMessage(notify.Write()); + NotMemberAppend appender; + ChannelNameBuilder<NotMemberAppend> builder(this, appender); + SendToOne(builder, guid); return; } - if (!_playersStore[guid].IsModerator() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) + PlayerInfo& info = _playersStore.at(guid); + if (!info.IsModerator() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) { - WorldPackets::Channel::ChannelNotify notify; - MakeNotModerator(notify); - player->SendDirectMessage(notify.Write()); + NotModeratorAppend appender; + ChannelNameBuilder<NotModeratorAppend> builder(this, appender); + SendToOne(builder, guid); return; } - _password = pass; + _channelPassword = pass; - WorldPackets::Channel::ChannelNotify notify; - MakePasswordChanged(notify, guid); - SendToAll(notify.Write()); + PasswordChangedAppend appender(guid); + ChannelNameBuilder<PasswordChangedAppend> builder(this, appender); + SendToAll(builder); UpdateChannelInDB(); } @@ -435,21 +499,22 @@ void Channel::SetMode(Player const* player, std::string const& p2n, bool mod, bo if (!IsOn(guid)) { - WorldPackets::Channel::ChannelNotify notify; - MakeNotMember(notify); - player->SendDirectMessage(notify.Write()); + NotMemberAppend appender; + ChannelNameBuilder<NotMemberAppend> builder(this, appender); + SendToOne(builder, guid); return; } - if (!_playersStore[guid].IsModerator() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) + PlayerInfo& info = _playersStore.at(guid); + if (!info.IsModerator() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) { - WorldPackets::Channel::ChannelNotify notify; - MakeNotModerator(notify); - player->SendDirectMessage(notify.Write()); + NotModeratorAppend appender; + ChannelNameBuilder<NotModeratorAppend> builder(this, appender); + SendToOne(builder, guid); return; } - if (guid == _ownerGUID && p2n == player->GetName() && mod) + if (guid == _ownerGuid && p2n == player->GetName() && mod) return; Player* newp = ObjectAccessor::FindConnectedPlayerByName(p2n); @@ -460,17 +525,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)))) { - WorldPackets::Channel::ChannelNotify notify; - MakePlayerNotFound(notify, p2n); - player->SendDirectMessage(notify.Write()); + PlayerNotFoundAppend appender(p2n); + ChannelNameBuilder<PlayerNotFoundAppend> builder(this, appender); + SendToOne(builder, guid); return; } - if (_ownerGUID == victim && _ownerGUID != guid) + if (_ownerGuid == victim && _ownerGuid != guid) { - WorldPackets::Channel::ChannelNotify notify; - MakeNotOwner(notify); - player->SendDirectMessage(notify.Write()); + NotOwnerAppend appender; + ChannelNameBuilder<NotOwnerAppend> builder(this, appender); + SendToOne(builder, guid); return; } @@ -480,23 +545,36 @@ void Channel::SetMode(Player const* player, std::string const& p2n, bool mod, bo SetMute(newp->GetGUID(), set); } +void Channel::SetInvisible(Player const* player, bool on) +{ + auto itr = _playersStore.find(player->GetGUID()); + if (itr == _playersStore.end()) + return; + + itr->second.SetInvisible(on); + + // we happen to be owner too, update flag + if (_ownerGuid == player->GetGUID()) + _isOwnerInvisible = on; +} + void Channel::SetOwner(Player const* player, std::string const& newname) { ObjectGuid const& guid = player->GetGUID(); if (!IsOn(guid)) { - WorldPackets::Channel::ChannelNotify notify; - MakeNotMember(notify); - player->SendDirectMessage(notify.Write()); + NotMemberAppend appender; + ChannelNameBuilder<NotMemberAppend> builder(this, appender); + SendToOne(builder, guid); return; } - if (!player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR) && guid != _ownerGUID) + if (!player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR) && guid != _ownerGuid) { - WorldPackets::Channel::ChannelNotify notify; - MakeNotOwner(notify); - player->SendDirectMessage(notify.Write()); + NotOwnerAppend appender; + ChannelNameBuilder<NotOwnerAppend> builder(this, appender); + SendToOne(builder, guid); return; } @@ -508,42 +586,52 @@ 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)))) { - WorldPackets::Channel::ChannelNotify notify; - MakePlayerNotFound(notify, newname); - player->SendDirectMessage(notify.Write()); + PlayerNotFoundAppend appender(newname); + ChannelNameBuilder<PlayerNotFoundAppend> builder(this, appender); + SendToOne(builder, guid); return; } - _playersStore[victim].SetModerator(true); + PlayerInfo& info = _playersStore.at(victim); + info.SetModerator(true); SetOwner(victim); } void Channel::SendWhoOwner(Player const* player) { - WorldPackets::Channel::ChannelNotify notify; - if (IsOn(player->GetGUID())) - MakeChannelOwner(notify); + ObjectGuid const& guid = player->GetGUID(); + if (IsOn(guid)) + { + ChannelOwnerAppend appender(this, _ownerGuid); + ChannelNameBuilder<ChannelOwnerAppend> builder(this, appender); + SendToOne(builder, guid); + } else - MakeNotMember(notify); - player->SendDirectMessage(notify.Write()); + { + NotMemberAppend appender; + ChannelNameBuilder<NotMemberAppend> builder(this, appender); + SendToOne(builder, guid); + } } void Channel::List(Player const* player) { - if (!IsOn(player->GetGUID())) + ObjectGuid const& guid = player->GetGUID(); + if (!IsOn(guid)) { - WorldPackets::Channel::ChannelNotify notify; - MakeNotMember(notify); - player->SendDirectMessage(notify.Write()); + 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()); WorldPackets::Channel::ChannelListResponse list; list._Display = true; /// always true? - list._Channel = GetName(); + list._Channel = channelName; list._ChannelFlags = GetFlags(); uint32 gmLevelInWhoList = sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST); @@ -560,7 +648,7 @@ void Channel::List(Player const* player) member->GetSession()->GetSecurity() <= AccountTypes(gmLevelInWhoList)) && member->IsVisibleGloballyFor(player)) { - list._Members.emplace_back(i.second.PlayerGuid, GetVirtualRealmAddress(), i.second.GetFlags()); + list._Members.emplace_back(i.first, GetVirtualRealmAddress(), i.second.GetFlags()); } } @@ -573,33 +661,41 @@ void Channel::Announce(Player const* player) if (!IsOn(guid)) { - WorldPackets::Channel::ChannelNotify notify; - MakeNotMember(notify); - player->SendDirectMessage(notify.Write()); + NotMemberAppend appender; + ChannelNameBuilder<NotMemberAppend> builder(this, appender); + SendToOne(builder, guid); return; } - if (!_playersStore[guid].IsModerator() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) + PlayerInfo const& playerInfo = _playersStore.at(guid); + if (!playerInfo.IsModerator() && !player->GetSession()->HasPermission(rbac::RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR)) { - WorldPackets::Channel::ChannelNotify notify; - MakeNotModerator(notify); - player->SendDirectMessage(notify.Write()); + NotModeratorAppend appender; + ChannelNameBuilder<NotModeratorAppend> builder(this, appender); + SendToOne(builder, guid); return; } - _announce = !_announce; + _announceEnabled = !_announceEnabled; WorldPackets::Channel::ChannelNotify notify; - if (_announce) - MakeAnnouncementsOn(notify, guid); + if (_announceEnabled) + { + AnnouncementsOnAppend appender(guid); + ChannelNameBuilder<AnnouncementsOnAppend> builder(this, appender); + SendToAll(builder); + } else - MakeAnnouncementsOff(notify, guid); - SendToAll(notify.Write()); + { + AnnouncementsOffAppend appender(guid); + ChannelNameBuilder<AnnouncementsOffAppend> builder(this, appender); + SendToAll(builder); + } UpdateChannelInDB(); } -void Channel::Say(ObjectGuid const& guid, std::string const& what, uint32 lang) +void Channel::Say(ObjectGuid const& guid, std::string const& what, uint32 lang) const { if (what.empty()) return; @@ -610,31 +706,39 @@ void Channel::Say(ObjectGuid const& guid, std::string const& what, uint32 lang) if (!IsOn(guid)) { - WorldPackets::Channel::ChannelNotify notify; - MakeNotMember(notify); - SendToOne(notify.Write(), guid); + NotMemberAppend appender; + ChannelNameBuilder<NotMemberAppend> builder(this, appender); + SendToOne(builder, guid); return; } - if (_playersStore[guid].IsMuted()) + PlayerInfo const& playerInfo = _playersStore.at(guid); + if (playerInfo.IsMuted()) { - WorldPackets::Channel::ChannelNotify notify; - MakeMuted(notify); - SendToOne(notify.Write(), guid); + MutedAppend appender; + ChannelNameBuilder<MutedAppend> builder(this, appender); + SendToOne(builder, guid); return; } - WorldPackets::Chat::Chat packet; - if (Player* player = ObjectAccessor::FindConnectedPlayer(guid)) - packet.Initialize(CHAT_MSG_CHANNEL, Language(lang), player, player, what, 0, _name); - else + auto builder = [&](LocaleConstant locale) { - packet.Initialize(CHAT_MSG_CHANNEL, Language(lang), nullptr, nullptr, what, 0, _name); - packet.SenderGUID = guid; - packet.TargetGUID = guid; - } + LocaleConstant localeIdx = sWorld->GetAvailableDbcLocale(locale); - SendToAll(packet.Write(), !_playersStore[guid].IsModerator() ? guid : ObjectGuid::Empty); + WorldPackets::Chat::Chat* packet = new WorldPackets::Chat::Chat(); + if (Player* player = ObjectAccessor::FindConnectedPlayer(guid)) + packet->Initialize(CHAT_MSG_CHANNEL, Language(lang), player, player, what, 0, GetName(localeIdx)); + else + { + packet->Initialize(CHAT_MSG_CHANNEL, Language(lang), nullptr, nullptr, what, 0, GetName(localeIdx)); + packet->SenderGUID = guid; + packet->TargetGUID = guid; + } + + return packet; + }; + + SendToAll(builder, !playerInfo.IsModerator() ? guid : ObjectGuid::Empty); } void Channel::Invite(Player const* player, std::string const& newname) @@ -643,26 +747,26 @@ void Channel::Invite(Player const* player, std::string const& newname) if (!IsOn(guid)) { - WorldPackets::Channel::ChannelNotify notify; - MakeNotMember(notify); - player->SendDirectMessage(notify.Write()); + NotMemberAppend appender; + ChannelNameBuilder<NotMemberAppend> builder(this, appender); + SendToOne(builder, guid); return; } Player* newp = ObjectAccessor::FindConnectedPlayerByName(newname); if (!newp || !newp->isGMVisible()) { - WorldPackets::Channel::ChannelNotify notify; - MakePlayerNotFound(notify, newname); - player->SendDirectMessage(notify.Write()); + PlayerNotFoundAppend appender(newname); + ChannelNameBuilder<PlayerNotFoundAppend> builder(this, appender); + SendToOne(builder, guid); return; } if (IsBanned(newp->GetGUID())) { - WorldPackets::Channel::ChannelNotify notify; - MakePlayerInviteBanned(notify, newname); - player->SendDirectMessage(notify.Write()); + PlayerInviteBannedAppend appender(newname); + ChannelNameBuilder<PlayerInviteBannedAppend> builder(this, appender); + SendToOne(builder, guid); return; } @@ -670,57 +774,62 @@ 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))) { - WorldPackets::Channel::ChannelNotify notify; - MakeInviteWrongFaction(notify); - player->SendDirectMessage(notify.Write()); + InviteWrongFactionAppend appender; + ChannelNameBuilder<InviteWrongFactionAppend> builder(this, appender); + SendToOne(builder, guid); return; } if (IsOn(newp->GetGUID())) { - WorldPackets::Channel::ChannelNotify notify; - MakePlayerAlreadyMember(notify, newp->GetGUID()); - player->SendDirectMessage(notify.Write()); + PlayerAlreadyMemberAppend appender(newp->GetGUID()); + ChannelNameBuilder<PlayerAlreadyMemberAppend> builder(this, appender); + SendToOne(builder, guid); return; } if (!newp->GetSocial()->HasIgnore(guid)) { - WorldPackets::Channel::ChannelNotify notify; - MakeInvite(notify, guid); - newp->SendDirectMessage(notify.Write()); + InviteAppend appender(guid); + ChannelNameBuilder<InviteAppend> builder(this, appender); + SendToOne(builder, newp->GetGUID()); } - WorldPackets::Channel::ChannelNotify notify; - MakePlayerInvited(notify, newp->GetName()); - player->SendDirectMessage(notify.Write()); + PlayerInvitedAppend appender(newp->GetName()); + ChannelNameBuilder<PlayerInvitedAppend> builder(this, appender); + SendToOne(builder, guid); } void Channel::SetOwner(ObjectGuid const& guid, bool exclaim) { - if (!_ownerGUID.IsEmpty()) + if (!_ownerGuid.IsEmpty()) { // [] will re-add player after it possible removed - PlayerContainer::iterator itr = _playersStore.find(_ownerGUID); + auto itr = _playersStore.find(_ownerGuid); if (itr != _playersStore.end()) itr->second.SetOwner(false); } - _ownerGUID = guid; - if (!_ownerGUID.IsEmpty()) + _ownerGuid = guid; + if (!_ownerGuid.IsEmpty()) { - uint8 oldFlag = _playersStore[_ownerGUID].GetFlags(); - _playersStore[_ownerGUID].SetModerator(true); - _playersStore[_ownerGUID].SetOwner(true); + uint8 oldFlag = GetPlayerFlags(_ownerGuid); + auto itr = _playersStore.find(_ownerGuid); + if (itr == _playersStore.end()) + return; - WorldPackets::Channel::ChannelNotify notify; - MakeModeChange(notify, _ownerGUID, oldFlag, _playersStore[_ownerGUID].GetFlags()); - SendToAll(notify.Write()); + itr->second.SetModerator(true); + itr->second.SetOwner(true); + + ModeChangeAppend appender(_ownerGuid, oldFlag, GetPlayerFlags(_ownerGuid)); + ChannelNameBuilder<ModeChangeAppend> builder(this, appender); + SendToAll(builder); if (exclaim) { - MakeOwnerChanged(notify, _ownerGUID); - SendToAll(notify.Write()); + OwnerChangedAppend appender(_ownerGuid); + ChannelNameBuilder<OwnerChangedAppend> builder(this, appender); + SendToAll(builder); } UpdateChannelInDB(); @@ -755,301 +864,129 @@ void Channel::DeVoice(Player const* /*player*/) { } -void Channel::SendToAll(WorldPacket const* data, ObjectGuid const& guid) -{ - for (PlayerContainer::value_type const& i : _playersStore) - if (Player* player = ObjectAccessor::FindConnectedPlayer(i.first)) - if (guid.IsEmpty() || !player->GetSocial()->HasIgnore(guid)) - player->SendDirectMessage(data); -} - -void Channel::SendToAllButOne(WorldPacket const* data, ObjectGuid const& who) -{ - for (PlayerContainer::value_type const& i : _playersStore) - if (i.first != who) - if (Player* player = ObjectAccessor::FindConnectedPlayer(i.first)) - player->SendDirectMessage(data); -} - -void Channel::SendToOne(WorldPacket const* data, ObjectGuid const& who) -{ - if (Player* player = ObjectAccessor::FindConnectedPlayer(who)) - player->SendDirectMessage(data); -} - -void Channel::MakeNotifyPacket(WorldPackets::Channel::ChannelNotify& data, uint8 notifyType) -{ - data.Type = notifyType; - data._Channel = _name; -} - -void Channel::MakeJoined(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& guid) -{ - MakeNotifyPacket(data, CHAT_JOINED_NOTICE); - data.SenderGuid = guid; -} - -void Channel::MakeLeft(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& guid) -{ - MakeNotifyPacket(data, CHAT_LEFT_NOTICE); - data.SenderGuid = guid; -} - -void Channel::MakeYouJoined(WorldPackets::Channel::ChannelNotify& data) -{ - MakeNotifyPacket(data, CHAT_YOU_JOINED_NOTICE); - //*data << uint8(GetFlags()); - data.ChatChannelID = GetChannelId(); - //*data << uint32(0); -} - -void Channel::MakeYouLeft(WorldPackets::Channel::ChannelNotify& data) -{ - MakeNotifyPacket(data, CHAT_YOU_LEFT_NOTICE); - data.ChatChannelID = GetChannelId(); - //*data << uint8(IsConstant()); -} - -void Channel::MakeWrongPassword(WorldPackets::Channel::ChannelNotify& data) -{ - MakeNotifyPacket(data, CHAT_WRONG_PASSWORD_NOTICE); -} - -void Channel::MakeNotMember(WorldPackets::Channel::ChannelNotify& data) -{ - MakeNotifyPacket(data, CHAT_NOT_MEMBER_NOTICE); -} - -void Channel::MakeNotModerator(WorldPackets::Channel::ChannelNotify& data) -{ - MakeNotifyPacket(data, CHAT_NOT_MODERATOR_NOTICE); -} - -void Channel::MakePasswordChanged(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& guid) -{ - MakeNotifyPacket(data, CHAT_PASSWORD_CHANGED_NOTICE); - data.SenderGuid = guid; -} - -void Channel::MakeOwnerChanged(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& guid) -{ - MakeNotifyPacket(data, CHAT_OWNER_CHANGED_NOTICE); - data.SenderGuid = guid; -} - -void Channel::MakePlayerNotFound(WorldPackets::Channel::ChannelNotify& data, std::string const& name) -{ - MakeNotifyPacket(data, CHAT_PLAYER_NOT_FOUND_NOTICE); - data.Sender = name; -} - -void Channel::MakeNotOwner(WorldPackets::Channel::ChannelNotify& data) -{ - MakeNotifyPacket(data, CHAT_NOT_OWNER_NOTICE); -} - -void Channel::MakeChannelOwner(WorldPackets::Channel::ChannelNotify& data) -{ - std::string name; - - if (!ObjectMgr::GetPlayerNameByGUID(_ownerGUID, name) || name.empty()) - name = "PLAYER_NOT_FOUND"; - - MakeNotifyPacket(data, CHAT_CHANNEL_OWNER_NOTICE); - data.Sender = ((IsConstant() || !_ownerGUID) ? "Nobody" : name); -} - -void Channel::MakeModeChange(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& guid, uint8 oldFlags, uint8 newFlags) -{ - MakeNotifyPacket(data, CHAT_MODE_CHANGE_NOTICE); - data.SenderGuid = guid; - data.OldFlags = oldFlags; - data.NewFlags = newFlags; -} - -void Channel::MakeAnnouncementsOn(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& guid) -{ - MakeNotifyPacket(data, CHAT_ANNOUNCEMENTS_ON_NOTICE); - data.SenderGuid = guid; -} - -void Channel::MakeAnnouncementsOff(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& guid) -{ - MakeNotifyPacket(data, CHAT_ANNOUNCEMENTS_OFF_NOTICE); - data.SenderGuid = guid; -} - -void Channel::MakeMuted(WorldPackets::Channel::ChannelNotify& data) -{ - MakeNotifyPacket(data, CHAT_MUTED_NOTICE); -} - -void Channel::MakePlayerKicked(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& bad, ObjectGuid const& good) -{ - MakeNotifyPacket(data, CHAT_PLAYER_KICKED_NOTICE); - data.SenderGuid = good; - data.TargetGuid = bad; -} - -void Channel::MakeBanned(WorldPackets::Channel::ChannelNotify& data) -{ - MakeNotifyPacket(data, CHAT_BANNED_NOTICE); -} - -void Channel::MakePlayerBanned(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& bad, ObjectGuid const& good) -{ - MakeNotifyPacket(data, CHAT_PLAYER_BANNED_NOTICE); - data.SenderGuid = good; - data.TargetGuid = bad; -} - -void Channel::MakePlayerUnbanned(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& bad, ObjectGuid const& good) -{ - MakeNotifyPacket(data, CHAT_PLAYER_UNBANNED_NOTICE); - data.SenderGuid = good; - data.TargetGuid = bad; -} - -void Channel::MakePlayerNotBanned(WorldPackets::Channel::ChannelNotify& data, std::string const& name) -{ - MakeNotifyPacket(data, CHAT_PLAYER_NOT_BANNED_NOTICE); - data.Sender = name; -} - -void Channel::MakePlayerAlreadyMember(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& guid) +void Channel::JoinNotify(Player const* player) { - MakeNotifyPacket(data, CHAT_PLAYER_ALREADY_MEMBER_NOTICE); - data.SenderGuid = guid; -} + ObjectGuid const& guid = player->GetGUID(); -void Channel::MakeInvite(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& guid) -{ - MakeNotifyPacket(data, CHAT_INVITE_NOTICE); - data.SenderGuid = guid; -} + if (IsConstant()) + { + auto builder = [&](LocaleConstant locale) + { + LocaleConstant localeIdx = sWorld->GetAvailableDbcLocale(locale); -void Channel::MakeInviteWrongFaction(WorldPackets::Channel::ChannelNotify& data) -{ - MakeNotifyPacket(data, CHAT_INVITE_WRONG_FACTION_NOTICE); -} + WorldPackets::Channel::UserlistAdd* userlistAdd = new WorldPackets::Channel::UserlistAdd(); + userlistAdd->AddedUserGUID = guid; + userlistAdd->_ChannelFlags = GetFlags(); + userlistAdd->UserFlags = GetPlayerFlags(guid); + userlistAdd->ChannelID = GetChannelId(); + userlistAdd->ChannelName = GetName(localeIdx); + return userlistAdd; + }; -void Channel::MakeWrongFaction(WorldPackets::Channel::ChannelNotify& data) -{ - MakeNotifyPacket(data, CHAT_WRONG_FACTION_NOTICE); -} + SendToAllButOne(builder, guid); + } + else + { + auto builder = [&](LocaleConstant locale) + { + LocaleConstant localeIdx = sWorld->GetAvailableDbcLocale(locale); -void Channel::MakeInvalidName(WorldPackets::Channel::ChannelNotify& data) -{ - MakeNotifyPacket(data, CHAT_INVALID_NAME_NOTICE); -} + WorldPackets::Channel::UserlistUpdate* userlistUpdate = new WorldPackets::Channel::UserlistUpdate(); + userlistUpdate->UpdatedUserGUID = guid; + userlistUpdate->_ChannelFlags = GetFlags(); + userlistUpdate->UserFlags = GetPlayerFlags(guid); + userlistUpdate->ChannelID = GetChannelId(); + userlistUpdate->ChannelName = GetName(localeIdx); + return userlistUpdate; + }; -void Channel::MakeNotModerated(WorldPackets::Channel::ChannelNotify& data) -{ - MakeNotifyPacket(data, CHAT_NOT_MODERATED_NOTICE); + SendToAll(builder); + } } -void Channel::MakePlayerInvited(WorldPackets::Channel::ChannelNotify& data, std::string const& name) +void Channel::LeaveNotify(Player const* player) { - MakeNotifyPacket(data, CHAT_PLAYER_INVITED_NOTICE); - data.Sender = name; -} + ObjectGuid const& guid = player->GetGUID(); -void Channel::MakePlayerInviteBanned(WorldPackets::Channel::ChannelNotify& data, std::string const& name) -{ - MakeNotifyPacket(data, CHAT_PLAYER_INVITE_BANNED_NOTICE); - data.Sender = name; -} + auto builder = [&](LocaleConstant locale) + { + LocaleConstant localeIdx = sWorld->GetAvailableDbcLocale(locale); -void Channel::MakeThrottled(WorldPackets::Channel::ChannelNotify& data) -{ - MakeNotifyPacket(data, CHAT_THROTTLED_NOTICE); -} + WorldPackets::Channel::UserlistRemove* userlistRemove = new WorldPackets::Channel::UserlistRemove(); + userlistRemove->RemovedUserGUID = guid; + userlistRemove->_ChannelFlags = GetFlags(); + userlistRemove->ChannelID = GetChannelId(); + userlistRemove->ChannelName = GetName(localeIdx); + return userlistRemove; + }; -void Channel::MakeNotInArea(WorldPackets::Channel::ChannelNotify& data) -{ - MakeNotifyPacket(data, CHAT_NOT_IN_AREA_NOTICE); + if (IsConstant()) + SendToAllButOne(builder, guid); + else + SendToAll(builder); } -void Channel::MakeNotInLfg(WorldPackets::Channel::ChannelNotify& data) +void Channel::SetModerator(ObjectGuid const& guid, bool set) { - MakeNotifyPacket(data, CHAT_NOT_IN_LFG_NOTICE); -} + if (!IsOn(guid)) + return; -void Channel::MakeVoiceOn(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& guid) -{ - MakeNotifyPacket(data, CHAT_VOICE_ON_NOTICE); - data.SenderGuid = guid; -} + PlayerInfo& playerInfo = _playersStore.at(guid); + if (playerInfo.IsModerator() != set) + { + uint8 oldFlag = playerInfo.GetFlags(); + playerInfo.SetModerator(set); -void Channel::MakeVoiceOff(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& guid) -{ - MakeNotifyPacket(data, CHAT_VOICE_OFF_NOTICE); - data.SenderGuid = guid; + ModeChangeAppend appender(guid, oldFlag, playerInfo.GetFlags()); + ChannelNameBuilder<ModeChangeAppend> builder(this, appender); + SendToAll(builder); + } } -void Channel::JoinNotify(Player const* player) +void Channel::SetMute(ObjectGuid const& guid, bool set) { - ObjectGuid const& guid = player->GetGUID(); + if (!IsOn(guid)) + return; - if (IsConstant()) - { - WorldPackets::Channel::UserlistAdd userlistAdd; - userlistAdd.AddedUserGUID = guid; - userlistAdd._ChannelFlags = GetFlags(); - userlistAdd.UserFlags = GetPlayerFlags(guid); - userlistAdd.ChannelID = GetChannelId(); - userlistAdd.ChannelName = GetName(); - SendToAllButOne(userlistAdd.Write(), guid); - } - else + PlayerInfo& playerInfo = _playersStore.at(guid); + if (playerInfo.IsMuted() != set) { - WorldPackets::Channel::UserlistUpdate userlistUpdate; - userlistUpdate.UpdatedUserGUID = guid; - userlistUpdate._ChannelFlags = GetFlags(); - userlistUpdate.UserFlags = GetPlayerFlags(guid); - userlistUpdate.ChannelID = GetChannelId(); - userlistUpdate.ChannelName = GetName(); - SendToAll(userlistUpdate.Write()); + uint8 oldFlag = playerInfo.GetFlags(); + playerInfo.SetMuted(set); + + ModeChangeAppend appender(guid, oldFlag, playerInfo.GetFlags()); + ChannelNameBuilder<ModeChangeAppend> builder(this, appender); + SendToAll(builder); } } -void Channel::LeaveNotify(Player const* player) +template <class Builder> +void Channel::SendToAll(Builder& builder, ObjectGuid const& guid) const { - ObjectGuid const& guid = player->GetGUID(); - WorldPackets::Channel::UserlistRemove userlistRemove; - userlistRemove.RemovedUserGUID = guid; - userlistRemove._ChannelFlags = GetFlags(); - userlistRemove.ChannelID = GetChannelId(); - userlistRemove.ChannelName = GetName(); + Trinity::LocalizedPacketDo<Builder> localizer(builder); - if (IsConstant()) - SendToAllButOne(userlistRemove.Write(), guid); - else - SendToAll(userlistRemove.Write()); + for (PlayerContainer::value_type const& i : _playersStore) + if (Player* player = ObjectAccessor::FindConnectedPlayer(i.first)) + if (guid.IsEmpty() || !player->GetSocial()->HasIgnore(guid)) + localizer(player); } -void Channel::SetModerator(ObjectGuid const& guid, bool set) +template <class Builder> +void Channel::SendToAllButOne(Builder& builder, ObjectGuid const& who) const { - if (_playersStore[guid].IsModerator() != set) - { - uint8 oldFlag = _playersStore[guid].GetFlags(); - _playersStore[guid].SetModerator(set); + Trinity::LocalizedPacketDo<Builder> localizer(builder); - WorldPackets::Channel::ChannelNotify data; - MakeModeChange(data, guid, oldFlag, _playersStore[guid].GetFlags()); - SendToAll(data.Write()); - } + for (PlayerContainer::value_type const& i : _playersStore) + if (i.first != who) + if (Player* player = ObjectAccessor::FindConnectedPlayer(i.first)) + localizer(player); } -void Channel::SetMute(ObjectGuid const& guid, bool set) +template <class Builder> +void Channel::SendToOne(Builder& builder, ObjectGuid const& who) const { - if (_playersStore[guid].IsMuted() != set) - { - uint8 oldFlag = _playersStore[guid].GetFlags(); - _playersStore[guid].SetMuted(set); + Trinity::LocalizedPacketDo<Builder> localizer(builder); - WorldPackets::Channel::ChannelNotify data; - MakeModeChange(data, guid, oldFlag, _playersStore[guid].GetFlags()); - SendToAll(data.Write()); - } + 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 f309f3c7936..b8c5e5d080d 100644 --- a/src/server/game/Chat/Channels/Channel.h +++ b/src/server/game/Chat/Channels/Channel.h @@ -56,10 +56,10 @@ enum ChatNotify CHAT_MODERATION_OFF_NOTICE = 0x10, //+ "[%s] Channel moderation disabled by %s."; CHAT_MUTED_NOTICE = 0x11, //+ "[%s] You do not have permission to speak."; CHAT_PLAYER_KICKED_NOTICE = 0x12, //? "[%s] Player %s kicked by %s."; - CHAT_BANNED_NOTICE = 0x13, //+ "[%s] You are bannedStore from that channel."; - CHAT_PLAYER_BANNED_NOTICE = 0x14, //? "[%s] Player %s bannedStore by %s."; + CHAT_BANNED_NOTICE = 0x13, //+ "[%s] You are banned from that channel."; + CHAT_PLAYER_BANNED_NOTICE = 0x14, //? "[%s] Player %s banned by %s."; CHAT_PLAYER_UNBANNED_NOTICE = 0x15, //? "[%s] Player %s unbanned by %s."; - CHAT_PLAYER_NOT_BANNED_NOTICE = 0x16, //+ "[%s] Player %s is not bannedStore."; + CHAT_PLAYER_NOT_BANNED_NOTICE = 0x16, //+ "[%s] Player %s is not banned."; CHAT_PLAYER_ALREADY_MEMBER_NOTICE = 0x17, //+ "[%s] Player %s is already on the channel."; CHAT_INVITE_NOTICE = 0x18, //+ "%2$s has invited you to join the channel '%1$s'."; CHAT_INVITE_WRONG_FACTION_NOTICE = 0x19, //+ "Target is in the wrong alliance for %s."; @@ -67,7 +67,7 @@ enum ChatNotify CHAT_INVALID_NAME_NOTICE = 0x1B, //+ "Invalid channel name"; CHAT_NOT_MODERATED_NOTICE = 0x1C, //+ "%s is not moderated"; CHAT_PLAYER_INVITED_NOTICE = 0x1D, //+ "[%s] You invited %s to join the channel"; - CHAT_PLAYER_INVITE_BANNED_NOTICE = 0x1E, //+ "[%s] %s has been bannedStore."; + CHAT_PLAYER_INVITE_BANNED_NOTICE = 0x1E, //+ "[%s] %s has been banned."; CHAT_THROTTLED_NOTICE = 0x1F, //+ "[%s] The number of messages that can be sent to this channel is limited, please wait to send another message."; CHAT_NOT_IN_AREA_NOTICE = 0x20, //+ "[%s] You are not in the correct area for this channel."; -- The user is trying to send a chat to a zone specific channel, and they're not physically in that zone. CHAT_NOT_IN_LFG_NOTICE = 0x21, //+ "[%s] You must be queued in looking for group before joining this channel."; -- The user must be in the looking for group system to join LFG chat channels. @@ -90,7 +90,7 @@ enum ChannelFlags CHANNEL_FLAG_VOICE = 0x80 // General 0x18 = 0x10 | 0x08 // Trade 0x3C = 0x20 | 0x10 | 0x08 | 0x04 - // LocalDefence 0x18 = 0x10 | 0x08 + // LocalDefense 0x18 = 0x10 | 0x08 // GuildRecruitment 0x38 = 0x20 | 0x10 | 0x08 // LookingForGroup 0x50 = 0x40 | 0x10 }; @@ -127,9 +127,11 @@ class TC_GAME_API Channel { struct PlayerInfo { - ObjectGuid PlayerGuid; - uint8 GetFlags() const { return _flags; } + + bool IsInvisible() const { return _invisible; } + void SetInvisible(bool on) { _invisible = on; } + inline bool HasFlag(uint8 flag) const { return (_flags & flag) != 0; } inline void SetFlag(uint8 flag) { _flags |= flag; } inline void RemoveFlag(uint8 flag) { _flags &= ~flag; } @@ -163,34 +165,51 @@ class TC_GAME_API Channel private: uint8 _flags = MEMBER_FLAG_NONE; + bool _invisible = false; }; 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 + + static void GetChannelName(std::string& channelName, uint32 channelId, LocaleConstant locale, AreaTableEntry const* zoneEntry); + std::string GetName(LocaleConstant locale = DEFAULT_LOCALE) const; - std::string const& GetName() const { return _name; } uint32 GetChannelId() const { return _channelId; } bool IsConstant() const { return _channelId != 0; } - bool IsAnnounce() const { return _announce; } + bool IsLFG() const { return (GetFlags() & CHANNEL_FLAG_LFG) != 0; } - std::string const& GetPassword() const { return _password; } - void SetPassword(std::string const& npassword) { _password = npassword; } - void SetAnnounce(bool nannounce) { _announce = nannounce; } + + bool IsAnnounce() const { return _announceEnabled; } + void SetAnnounce(bool nannounce) { _announceEnabled = nannounce; } + + std::string const& GetPassword() const { return _channelPassword; } + void SetPassword(std::string const& npassword) { _channelPassword = npassword; } + uint32 GetNumPlayers() const { return uint32(_playersStore.size()); } - uint8 GetFlags() const { return _flags; } - bool HasFlag(uint8 flag) const { return (_flags & flag) != 0; } + + 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); + void KickOrBan(Player const* player, std::string const& badname, bool ban); void Kick(Player const* player, std::string const& badname) { KickOrBan(player, badname, false); } void Ban(Player const* player, std::string const& badname) { KickOrBan(player, badname, true); } + void UnBan(Player const* player, std::string const& badname); void Password(Player const* player, std::string const& pass); void SetMode(Player const* player, std::string const& p2n, bool mod, bool set); + + void SetInvisible(Player const* player, bool on); + void SetOwner(ObjectGuid const& guid, bool exclaim = true); void SetOwner(Player const* player, std::string const& name); void SendWhoOwner(Player const* player); + void SetModerator(Player const* player, std::string const& newname) { SetMode(player, newname, true, true); } void UnsetModerator(Player const* player, std::string const& newname) { SetMode(player, newname, true, false); } void SetMute(Player const* player, std::string const& newname) { SetMode(player, newname, false, true); } @@ -201,61 +220,28 @@ class TC_GAME_API Channel void UnsilenceVoice(Player const* player, std::string const& name); void List(Player const* player); void Announce(Player const* player); - void Say(ObjectGuid const& guid, std::string const& what, uint32 lang); + void Say(ObjectGuid const& guid, std::string const& what, uint32 lang) const; void DeclineInvite(Player const* player); void Invite(Player const* player, std::string const& newp); void Voice(Player const* player); void DeVoice(Player const* player); void JoinNotify(Player const* player); void LeaveNotify(Player const* player); - void SetOwnership(bool ownership) { _ownership = ownership; } + void SetOwnership(bool ownership) { _ownershipEnabled = ownership; } static void CleanOldChannelsInDB(); private: - // initial packet data (notify type and channel name) - void MakeNotifyPacket(WorldPackets::Channel::ChannelNotify& data, uint8 notifyType); - // type specific packet data - void MakeJoined(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& guid); //+ 0x00 - void MakeLeft(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& guid); //+ 0x01 - void MakeYouJoined(WorldPackets::Channel::ChannelNotify& data); //+ 0x02 - void MakeYouLeft(WorldPackets::Channel::ChannelNotify& data); //+ 0x03 - void MakeWrongPassword(WorldPackets::Channel::ChannelNotify& data); //? 0x04 - void MakeNotMember(WorldPackets::Channel::ChannelNotify& data); //? 0x05 - void MakeNotModerator(WorldPackets::Channel::ChannelNotify& data); //? 0x06 - void MakePasswordChanged(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& guid); //+ 0x07 - void MakeOwnerChanged(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& guid); //? 0x08 - void MakePlayerNotFound(WorldPackets::Channel::ChannelNotify& data, std::string const& name); //+ 0x09 - void MakeNotOwner(WorldPackets::Channel::ChannelNotify& data); //? 0x0A - void MakeChannelOwner(WorldPackets::Channel::ChannelNotify& data); //? 0x0B - void MakeModeChange(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& guid, uint8 oldFlags, uint8 newFlags); //+ 0x0C - void MakeAnnouncementsOn(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& guid); //+ 0x0D - void MakeAnnouncementsOff(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& guid); //+ 0x0E - void MakeMuted(WorldPackets::Channel::ChannelNotify& data); //? 0x11 - void MakePlayerKicked(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& bad, ObjectGuid const& good); //? 0x12 - void MakeBanned(WorldPackets::Channel::ChannelNotify& data); //? 0x13 - void MakePlayerBanned(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& bad, ObjectGuid const& good); //? 0x14 - void MakePlayerUnbanned(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& bad, ObjectGuid const& good); //? 0x15 - void MakePlayerNotBanned(WorldPackets::Channel::ChannelNotify& data, std::string const& name); //? 0x16 - void MakePlayerAlreadyMember(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& guid); //+ 0x17 - void MakeInvite(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& guid); //? 0x18 - void MakeInviteWrongFaction(WorldPackets::Channel::ChannelNotify& data); //? 0x19 - void MakeWrongFaction(WorldPackets::Channel::ChannelNotify& data); //? 0x1A - void MakeInvalidName(WorldPackets::Channel::ChannelNotify& data); //? 0x1B - void MakeNotModerated(WorldPackets::Channel::ChannelNotify& data); //? 0x1C - void MakePlayerInvited(WorldPackets::Channel::ChannelNotify& data, std::string const& name); //+ 0x1D - void MakePlayerInviteBanned(WorldPackets::Channel::ChannelNotify& data, std::string const& name); //? 0x1E - void MakeThrottled(WorldPackets::Channel::ChannelNotify& data); //? 0x1F - void MakeNotInArea(WorldPackets::Channel::ChannelNotify& data); //? 0x20 - void MakeNotInLfg(WorldPackets::Channel::ChannelNotify& data); //? 0x21 - void MakeVoiceOn(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& guid); //+ 0x22 - void MakeVoiceOff(WorldPackets::Channel::ChannelNotify& data, ObjectGuid const& guid); //+ 0x23 - - void SendToAll(WorldPacket const* data, ObjectGuid const& guid = ObjectGuid::Empty); - void SendToAllButOne(WorldPacket const* data, ObjectGuid const& who); - void SendToOne(WorldPacket const* data, ObjectGuid const& who); - - bool IsOn(ObjectGuid const& who) const { return _playersStore.find(who) != _playersStore.end(); } - bool IsBanned(ObjectGuid const& guid) const { return _bannedStore.find(guid) != _bannedStore.end(); } + template <class Builder> + void SendToAll(Builder& builder, ObjectGuid const& guid = ObjectGuid::Empty) const; + + template <class Builder> + void SendToAllButOne(Builder& builder, ObjectGuid const& who) const; + + template <class Builder> + void SendToOne(Builder& builder, ObjectGuid const& who) const; + + bool IsOn(ObjectGuid const& who) const { return _playersStore.count(who) != 0; } + bool IsBanned(ObjectGuid const& guid) const { return _bannedStore.count(guid) != 0; } void UpdateChannelInDB() const; void UpdateChannelUseageInDB() const; @@ -270,19 +256,23 @@ class TC_GAME_API Channel void SetMute(ObjectGuid const& guid, bool set); typedef std::map<ObjectGuid, PlayerInfo> PlayerContainer; - typedef GuidSet BannedContainer; + typedef GuidUnorderedSet BannedContainer; - bool _announce; - bool _ownership; - bool _IsSaved; - uint8 _flags; + bool _announceEnabled; //< Whether we should broadcast a packet whenever a player joins/exits the channel + bool _ownershipEnabled; //< Whether the channel has to maintain an owner + bool _persistentChannel; //< Whether the channel is saved to DB + bool _isOwnerInvisible; //< Whether the channel is owned by invisible GM, ownership should change to first player that joins channel + + uint8 _channelFlags; uint32 _channelId; - uint32 _team; - ObjectGuid _ownerGUID; - std::string _name; - std::string _password; + uint32 _channelTeam; + ObjectGuid _ownerGuid; + std::string _channelName; + 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..490eadc4021 --- /dev/null +++ b/src/server/game/Chat/Channels/ChannelAppenders.h @@ -0,0 +1,473 @@ +/* + * 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" +#include "ChannelPackets.h" +#include "World.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){ } + + WorldPackets::Packet* operator()(LocaleConstant locale) const + { + // LocalizedPacketDo sends client DBC locale, we need to get available to server locale + LocaleConstant localeIdx = sWorld->GetAvailableDbcLocale(locale); + + WorldPackets::Channel::ChannelNotify* data = new WorldPackets::Channel::ChannelNotify(); + data->Type = _modifier.NotificationType; + data->_Channel = _source->GetName(localeIdx); + _modifier.Append(*data); + return 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(WorldPackets::Channel::ChannelNotify& data) const + { + data.SenderGuid = _guid; + } + +private: + ObjectGuid _guid; +}; + +struct LeftAppend +{ + explicit LeftAppend(ObjectGuid const& guid) : _guid(guid) { } + + static uint8 const NotificationType = CHAT_LEFT_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& data) const + { + data.SenderGuid = _guid; + } + +private: + ObjectGuid _guid; +}; + +struct YouJoinedAppend +{ + explicit YouJoinedAppend(Channel const* channel) : _channel(channel) { } + + static uint8 const NotificationType = CHAT_YOU_JOINED_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& data) const + { + data.ChatChannelID = _channel->GetChannelId(); + } + +private: + Channel const* _channel; +}; + +struct YouLeftAppend +{ + explicit YouLeftAppend(Channel const* channel) : _channel(channel) { } + + static uint8 const NotificationType = CHAT_YOU_LEFT_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& data) const + { + data.ChatChannelID = _channel->GetChannelId(); + } + +private: + Channel const* _channel; +}; + +struct WrongPasswordAppend +{ + static uint8 const NotificationType = CHAT_WRONG_PASSWORD_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& /*data*/) const { } +}; + +struct NotMemberAppend +{ + static uint8 const NotificationType = CHAT_NOT_MEMBER_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& /*data*/) const { } +}; + +struct NotModeratorAppend +{ + static uint8 const NotificationType = CHAT_NOT_MODERATOR_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& /*data*/) const { } +}; + +struct PasswordChangedAppend +{ + explicit PasswordChangedAppend(ObjectGuid const& guid) : _guid(guid) { } + + static uint8 const NotificationType = CHAT_PASSWORD_CHANGED_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& data) const + { + data.SenderGuid = _guid; + } + +private: + ObjectGuid _guid; +}; + +struct OwnerChangedAppend +{ + explicit OwnerChangedAppend(ObjectGuid const& guid) : _guid(guid) { } + + static uint8 const NotificationType = CHAT_OWNER_CHANGED_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& data) const + { + data.SenderGuid = _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(WorldPackets::Channel::ChannelNotify& data) const + { + data.Sender = _playerName; + } + +private: + std::string _playerName; +}; + +struct NotOwnerAppend +{ + static uint8 const NotificationType = CHAT_NOT_OWNER_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& /*data*/) const { } +}; + +struct ChannelOwnerAppend +{ + explicit ChannelOwnerAppend(Channel const* channel, ObjectGuid const& ownerGuid) : _channel(channel), _ownerGuid(ownerGuid) + { + if (!ObjectMgr::GetPlayerNameByGUID(_ownerGuid, _ownerName)) + _ownerName = "PLAYER_NOT_FOUND"; + } + + static uint8 const NotificationType = CHAT_CHANNEL_OWNER_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& data) const + { + data.Sender = ((_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(WorldPackets::Channel::ChannelNotify& data) const + { + data.SenderGuid = _guid; + data.OldFlags = _oldFlags; + data.NewFlags = _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(WorldPackets::Channel::ChannelNotify& data) const + { + data.SenderGuid = _guid; + } + +private: + ObjectGuid _guid; +}; + +struct AnnouncementsOffAppend +{ + explicit AnnouncementsOffAppend(ObjectGuid const& guid) : _guid(guid) { } + + static uint8 const NotificationType = CHAT_ANNOUNCEMENTS_OFF_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& data) const + { + data.SenderGuid = _guid; + } + +private: + ObjectGuid _guid; +}; + +struct MutedAppend +{ + static uint8 const NotificationType = CHAT_MUTED_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& /*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(WorldPackets::Channel::ChannelNotify& data) const + { + data.SenderGuid = _kicker; + data.TargetGuid = _kickee; + } + +private: + ObjectGuid _kicker; + ObjectGuid _kickee; +}; + +struct BannedAppend +{ + static uint8 const NotificationType = CHAT_BANNED_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& /*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(WorldPackets::Channel::ChannelNotify& data) const + { + data.SenderGuid = _moderator; + data.TargetGuid = _banned; + } + +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(WorldPackets::Channel::ChannelNotify& data) const + { + data.SenderGuid = _moderator; + data.TargetGuid = _unbanned; + } + +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(WorldPackets::Channel::ChannelNotify& data) const + { + data.Sender = _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(WorldPackets::Channel::ChannelNotify& data) const + { + data.SenderGuid = _guid; + } + +private: + ObjectGuid _guid; +}; + +struct InviteAppend +{ + explicit InviteAppend(ObjectGuid const& guid) : _guid(guid) { } + + static uint8 const NotificationType = CHAT_INVITE_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& data) const + { + data.SenderGuid = _guid; + } + +private: + ObjectGuid _guid; +}; + +struct InviteWrongFactionAppend +{ + static uint8 const NotificationType = CHAT_INVITE_WRONG_FACTION_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& /*data*/) const { } +}; + +struct WrongFactionAppend +{ + static uint8 const NotificationType = CHAT_WRONG_FACTION_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& /*data*/) const { } +}; + +struct InvalidNameAppend +{ + static uint8 const NotificationType = CHAT_INVALID_NAME_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& /*data*/) const { } +}; + +struct NotModeratedAppend +{ + static uint8 const NotificationType = CHAT_NOT_MODERATED_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& /*data*/) const { } +}; + +struct PlayerInvitedAppend +{ + explicit PlayerInvitedAppend(std::string const& playerName) : _playerName(playerName) { } + + static uint8 const NotificationType = CHAT_PLAYER_INVITED_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& data) const + { + data.Sender = _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(WorldPackets::Channel::ChannelNotify& data) const + { + data.Sender = _playerName; + } + +private: + std::string _playerName; +}; + +struct ThrottledAppend +{ + static uint8 const NotificationType = CHAT_THROTTLED_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& /*data*/) const { } +}; + +struct NotInAreaAppend +{ + static uint8 const NotificationType = CHAT_NOT_IN_AREA_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& /*data*/) const { } +}; + +struct NotInLFGAppend +{ + static uint8 const NotificationType = CHAT_NOT_IN_LFG_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& /*data*/) const { } +}; + +struct VoiceOnAppend +{ + explicit VoiceOnAppend(ObjectGuid const& guid) : _guid(guid) { } + + static uint8 const NotificationType = CHAT_VOICE_ON_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& data) const + { + data.SenderGuid = _guid; + } + +private: + ObjectGuid _guid; +}; + +struct VoiceOffAppend +{ + explicit VoiceOffAppend(ObjectGuid const& guid) : _guid(guid) { } + + static uint8 const NotificationType = CHAT_VOICE_OFF_NOTICE; + + void Append(WorldPackets::Channel::ChannelNotify& data) const + { + data.SenderGuid = _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 ecf45ec5d5e..90d022df196 100644 --- a/src/server/game/Chat/Channels/ChannelMgr.cpp +++ b/src/server/game/Chat/Channels/ChannelMgr.cpp @@ -16,6 +16,7 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "Channel.h" #include "ChannelMgr.h" #include "ChannelPackets.h" #include "Player.h" @@ -23,14 +24,18 @@ 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 @@ -43,62 +48,139 @@ 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()); + + std::wstring channelNameW; + if (!Utf8toWStr(chanName, channelNameW)) + continue; + + wstrToLower(channelNameW); + if (!channelNameW.compare(0, channelNamePart.size(), channelNamePart)) + return channel; + } - ChannelMap::const_iterator i = _channels.find(wname); - if (i == _channels.end()) + return nullptr; +} + +Channel* ChannelMgr::GetJoinChannel(uint32 channelId, std::string const& name, AreaTableEntry const* zoneEntry /*= nullptr*/) +{ + if (channelId) // builtin { - Channel* nchan = new Channel(name, channelId, _team); - _channels[wname] = nchan; - return nchan; + 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()) + return itr->second; + + Channel* newChannel = new Channel(channelId, _team, zoneEntry); + _channels[key] = newChannel; + return newChannel; } + else // custom + { + std::wstring channelName; + if (!Utf8toWStr(name, channelName)) + return nullptr; - return i->second; + 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; + } } -Channel* ChannelMgr::GetChannel(std::string const& name, Player* player, bool notify /*= true*/) +Channel* ChannelMgr::GetChannel(uint32 channelId, std::string const& name, Player* player, bool notify /*= true*/, AreaTableEntry const* zoneEntry /*= nullptr*/) const { - std::wstring wname; - if (!Utf8toWStr(name, wname)) - return nullptr; + Channel* result = 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; + + std::pair<uint32, uint32> key = std::make_pair(channelId, zoneId); + auto itr = _channels.find(key); + if (itr != _channels.end()) + result = itr->second; + } + else // custom + { + std::wstring channelName; + if (!Utf8toWStr(name, channelName)) + return nullptr; - wstrToLower(wname); + wstrToLower(channelName); - ChannelMap::const_iterator i = _channels.find(wname); - if (i == _channels.end()) + auto itr = _customChannels.find(channelName); + if (itr != _customChannels.end()) + result = itr->second; + } + + if (!result && notify) { - if (notify) - SendNotOnChannelNotify(player, name); + std::string channelName = name; + Channel::GetChannelName(channelName, channelId, player->GetSession()->GetSessionDbcLocale(), zoneEntry); - return nullptr; + SendNotOnChannelNotify(player, channelName); } - return i->second; + return result; } void ChannelMgr::LeftChannel(std::string const& name) { - std::wstring wname; - if (!Utf8toWStr(name, wname)) + std::wstring channelName; + if (!Utf8toWStr(name, channelName)) return; - wstrToLower(wname); - - ChannelMap::const_iterator i = _channels.find(wname); - if (i == _channels.end()) + wstrToLower(channelName); + auto itr = _customChannels.find(channelName); + if (itr == _customChannels.end()) return; - Channel* channel = i->second; + Channel* channel = itr->second; + if (!channel->GetNumPlayers()) + { + _customChannels.erase(itr); + delete channel; + } +} + +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); + auto itr = _channels.find(key); + if (itr == _channels.end()) + return; - if (!channel->GetNumPlayers() && !channel->IsConstant()) + Channel* channel = itr->second; + if (!channel->GetNumPlayers()) { - _channels.erase(i); + _channels.erase(itr); delete channel; } } diff --git a/src/server/game/Chat/Channels/ChannelMgr.h b/src/server/game/Chat/Channels/ChannelMgr.h index cdaf6b8565c..53454c4361d 100644 --- a/src/server/game/Chat/Channels/ChannelMgr.h +++ b/src/server/game/Chat/Channels/ChannelMgr.h @@ -19,32 +19,34 @@ #define __TRINITY_CHANNELMGR_H #include "Common.h" -#include "Channel.h" -#define MAX_CHANNEL_NAME_STR 0x31 -#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 channelId); - Channel* GetChannel(std::string const& name, Player* player, bool notify = true); + Channel* GetJoinChannel(uint32 channelId, std::string const& name, AreaTableEntry const* zoneEntry = nullptr); + Channel* GetChannel(uint32 channelId, std::string const& name, Player* player, bool notify = 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; static void SendNotOnChannelNotify(Player const* player, std::string const& name); + ChannelMgr() = delete; }; #endif diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index 85d803a6948..37a6b7c0dc2 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -82,7 +82,7 @@ bool ChatHandler::isAvailable(ChatCommand const& cmd) const bool ChatHandler::HasLowerSecurity(Player* target, ObjectGuid guid, bool strong) { - WorldSession* target_session = NULL; + WorldSession* target_session = nullptr; uint32 target_account = 0; if (target) @@ -117,7 +117,7 @@ bool ChatHandler::HasLowerSecurityAccount(WorldSession* target, uint32 target_ac else if (target_account) target_sec = AccountMgr::GetSecurity(target_account, realm.Id.Realm); else - return true; // caller must report error for (target == NULL && target_account == 0) + return true; // caller must report error for (target == nullptr && target_account == 0) AccountTypes target_ac_sec = AccountTypes(target_sec); if (m_session->GetSecurity() < target_ac_sec || (strong && m_session->GetSecurity() <= target_ac_sec)) @@ -540,7 +540,7 @@ bool ChatHandler::ShowHelpForCommand(std::vector<ChatCommand> const& table, cons continue; // have subcommand - char const* subcmd = (*cmd) ? strtok(NULL, " ") : ""; + char const* subcmd = (*cmd) ? strtok(nullptr, " ") : ""; if (!table[i].ChildCommands.empty() && subcmd && *subcmd) { @@ -586,7 +586,7 @@ bool ChatHandler::ShowHelpForCommand(std::vector<ChatCommand> const& table, cons Player* ChatHandler::getSelectedPlayer() { if (!m_session) - return NULL; + return nullptr; ObjectGuid selected = m_session->GetPlayer()->GetTarget(); if (!selected) @@ -598,7 +598,7 @@ Player* ChatHandler::getSelectedPlayer() Unit* ChatHandler::getSelectedUnit() { if (!m_session) - return NULL; + return nullptr; if (Unit* selected = m_session->GetPlayer()->GetSelectedUnit()) return selected; @@ -609,7 +609,7 @@ Unit* ChatHandler::getSelectedUnit() WorldObject* ChatHandler::getSelectedObject() { if (!m_session) - return NULL; + return nullptr; ObjectGuid guid = m_session->GetPlayer()->GetTarget(); @@ -622,7 +622,7 @@ WorldObject* ChatHandler::getSelectedObject() Creature* ChatHandler::getSelectedCreature() { if (!m_session) - return NULL; + return nullptr; return ObjectAccessor::GetCreatureOrPetOrVehicle(*m_session->GetPlayer(), m_session->GetPlayer()->GetTarget()); } @@ -630,7 +630,7 @@ Creature* ChatHandler::getSelectedCreature() Player* ChatHandler::getSelectedPlayerOrSelf() { if (!m_session) - return NULL; + return nullptr; ObjectGuid selected = m_session->GetPlayer()->GetTarget(); if (!selected) @@ -649,14 +649,14 @@ char* ChatHandler::extractKeyFromLink(char* text, char const* linkType, char** s { // skip empty if (!text) - return NULL; + return nullptr; // skip spaces while (*text == ' '||*text == '\t'||*text == '\b') ++text; if (!*text) - return NULL; + return nullptr; // return non link case if (text[0] != '|') @@ -668,28 +668,28 @@ char* ChatHandler::extractKeyFromLink(char* text, char const* linkType, char** s char* check = strtok(text, "|"); // skip color if (!check) - return NULL; // end of data + return nullptr; // end of data - char* cLinkType = strtok(NULL, ":"); // linktype + char* cLinkType = strtok(nullptr, ":"); // linktype if (!cLinkType) - return NULL; // end of data + return nullptr; // end of data if (strcmp(cLinkType, linkType) != 0) { - strtok(NULL, " "); // skip link tail (to allow continue strtok(NULL, s) use after retturn from function + strtok(nullptr, " "); // skip link tail (to allow continue strtok(nullptr, s) use after retturn from function SendSysMessage(LANG_WRONG_LINK_TYPE); - return NULL; + return nullptr; } - char* cKeys = strtok(NULL, "|"); // extract keys and values - char* cKeysTail = strtok(NULL, ""); + char* cKeys = strtok(nullptr, "|"); // extract keys and values + char* cKeysTail = strtok(nullptr, ""); char* cKey = strtok(cKeys, ":|"); // extract key if (something1) - *something1 = strtok(NULL, ":|"); // extract something + *something1 = strtok(nullptr, ":|"); // extract something strtok(cKeysTail, "]"); // restart scan tail and skip name with possible spaces - strtok(NULL, " "); // skip link tail (to allow continue strtok(NULL, s) use after return from function + strtok(nullptr, " "); // skip link tail (to allow continue strtok(nullptr, s) use after return from function return cKey; } @@ -697,14 +697,14 @@ char* ChatHandler::extractKeyFromLink(char* text, char const* const* linkTypes, { // skip empty if (!text) - return NULL; + return nullptr; // skip spaces while (*text == ' '||*text == '\t'||*text == '\b') ++text; if (!*text) - return NULL; + return nullptr; // return non link case if (text[0] != '|') @@ -722,48 +722,48 @@ char* ChatHandler::extractKeyFromLink(char* text, char const* const* linkTypes, { char* check = strtok(text, "|"); // skip color if (!check) - return NULL; // end of data + return nullptr; // end of data - tail = strtok(NULL, ""); // tail + tail = strtok(nullptr, ""); // tail } else tail = text+1; // skip first | char* cLinkType = strtok(tail, ":"); // linktype if (!cLinkType) - return NULL; // end of data + return nullptr; // end of data for (int i = 0; linkTypes[i]; ++i) { if (strcmp(cLinkType, linkTypes[i]) == 0) { - char* cKeys = strtok(NULL, "|"); // extract keys and values - char* cKeysTail = strtok(NULL, ""); + char* cKeys = strtok(nullptr, "|"); // extract keys and values + char* cKeysTail = strtok(nullptr, ""); char* cKey = strtok(cKeys, ":|"); // extract key if (something1) - *something1 = strtok(NULL, ":|"); // extract something + *something1 = strtok(nullptr, ":|"); // extract something strtok(cKeysTail, "]"); // restart scan tail and skip name with possible spaces - strtok(NULL, " "); // skip link tail (to allow continue strtok(NULL, s) use after return from function + strtok(nullptr, " "); // skip link tail (to allow continue strtok(nullptr, s) use after return from function if (found_idx) *found_idx = i; return cKey; } } - strtok(NULL, " "); // skip link tail (to allow continue strtok(NULL, s) use after return from function + strtok(nullptr, " "); // skip link tail (to allow continue strtok(nullptr, s) use after return from function SendSysMessage(LANG_WRONG_LINK_TYPE); - return NULL; + return nullptr; } GameObject* ChatHandler::GetNearbyGameObject() { if (!m_session) - return NULL; + return nullptr; Player* pl = m_session->GetPlayer(); - GameObject* obj = NULL; + GameObject* obj = nullptr; Trinity::NearestGameObjectCheck check(*pl); Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectCheck> searcher(pl, obj, check); pl->VisitNearbyGridObject(SIZE_OF_GRIDS, searcher); @@ -773,7 +773,7 @@ GameObject* ChatHandler::GetNearbyGameObject() GameObject* ChatHandler::GetObjectGlobalyWithGuidOrNearWithDbGuid(ObjectGuid::LowType lowguid, uint32 entry) { if (!m_session) - return NULL; + return nullptr; Player* pl = m_session->GetPlayer(); @@ -818,7 +818,7 @@ uint32 ChatHandler::extractSpellIdFromLink(char* text) // number or [name] Shift-click form |color|Htalent:talent_id, rank|h[name]|h|r // number or [name] Shift-click form |color|Htrade:spell_id, skill_id, max_value, cur_value|h[name]|h|r int type = 0; - char* param1_str = NULL; + char* param1_str = nullptr; char* idS = extractKeyFromLink(text, spellKeys, &type, ¶m1_str); if (!idS) return 0; @@ -862,7 +862,7 @@ GameTele const* ChatHandler::extractGameTeleFromLink(char* text) // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r char* cId = extractKeyFromLink(text, "Htele"); if (!cId) - return NULL; + return nullptr; // id case (explicit or from shift link) if (cId[0] >= '0' || cId[0] >= '9') @@ -949,7 +949,7 @@ std::string ChatHandler::extractPlayerNameFromLink(char* text) return name; } -bool ChatHandler::extractPlayerTarget(char* args, Player** player, ObjectGuid* player_guid /*=NULL*/, std::string* player_name /*= NULL*/) +bool ChatHandler::extractPlayerTarget(char* args, Player** player, ObjectGuid* player_guid /*= nullptr*/, std::string* player_name /*= nullptr*/) { if (args && *args) { @@ -1005,12 +1005,12 @@ bool ChatHandler::extractPlayerTarget(char* args, Player** player, ObjectGuid* p void ChatHandler::extractOptFirstArg(char* args, char** arg1, char** arg2) { char* p1 = strtok(args, " "); - char* p2 = strtok(NULL, " "); + char* p2 = strtok(nullptr, " "); if (!p2) { p2 = p1; - p1 = NULL; + p1 = nullptr; } if (arg1) @@ -1023,7 +1023,7 @@ void ChatHandler::extractOptFirstArg(char* args, char** arg1, char** arg2) char* ChatHandler::extractQuotedArg(char* args) { if (!args || !*args) - return NULL; + return nullptr; if (*args == '"') return strtok(args+1, "\""); @@ -1036,9 +1036,9 @@ char* ChatHandler::extractQuotedArg(char* args) continue; } - // return NULL if we reached the end of the string + // return nullptr if we reached the end of the string if (!*args) - return NULL; + return nullptr; // since we skipped all spaces, we expect another token now if (*args == '"') @@ -1056,7 +1056,7 @@ char* ChatHandler::extractQuotedArg(char* args) return strtok(args + 1, "\""); } else - return NULL; + return nullptr; } } @@ -1110,7 +1110,7 @@ bool CliHandler::needReportToTarget(Player* /*chr*/) const bool ChatHandler::GetPlayerGroupAndGUIDByName(const char* cname, Player*& player, Group*& group, ObjectGuid& guid, bool offline) { - player = NULL; + player = nullptr; guid.Clear(); if (cname) diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h index 04d040d7508..6a7bd2962dc 100644 --- a/src/server/game/Chat/Chat.h +++ b/src/server/game/Chat/Chat.h @@ -60,7 +60,7 @@ class TC_GAME_API ChatHandler explicit ChatHandler(WorldSession* session) : m_session(session), sentErrorMessage(false) { } virtual ~ChatHandler() { } - static char* LineFromMessage(char*& pos) { char* start = strtok(pos, "\n"); pos = NULL; return start; } + static char* LineFromMessage(char*& pos) { char* start = strtok(pos, "\n"); pos = nullptr; return start; } // function with different implementation for chat/console virtual char const* GetTrinityString(uint32 entry) const; @@ -115,10 +115,10 @@ class TC_GAME_API ChatHandler // Returns either the selected player or self if there is no selected player Player* getSelectedPlayerOrSelf(); - char* extractKeyFromLink(char* text, char const* linkType, char** something1 = NULL); - char* extractKeyFromLink(char* text, char const* const* linkTypes, int* found_idx, char** something1 = NULL); + char* extractKeyFromLink(char* text, char const* linkType, char** something1 = nullptr); + char* extractKeyFromLink(char* text, char const* const* linkTypes, int* found_idx, char** something1 = nullptr); - // if args have single value then it return in arg2 and arg1 == NULL + // if args have single value then it return in arg2 and arg1 == nullptr void extractOptFirstArg(char* args, char** arg1, char** arg2); char* extractQuotedArg(char* args); @@ -128,7 +128,7 @@ class TC_GAME_API ChatHandler bool GetPlayerGroupAndGUIDByName(const char* cname, Player*& player, Group*& group, ObjectGuid& guid, bool offline = false); std::string extractPlayerNameFromLink(char* text); // select by arg (name/link) or in-game selection online/offline player or self if a creature is selected - bool extractPlayerTarget(char* args, Player** player, ObjectGuid* player_guid = NULL, std::string* player_name = NULL); + bool extractPlayerTarget(char* args, Player** player, ObjectGuid* player_guid = nullptr, std::string* player_name = nullptr); std::string playerLink(std::string const& name) const { return m_session ? "|cffffffff|Hplayer:"+name+"|h["+name+"]|h|r" : name; } std::string GetNameLink(Player* chr) const; @@ -140,13 +140,13 @@ class TC_GAME_API ChatHandler bool ShowHelpForCommand(std::vector<ChatCommand> const& table, const char* cmd); protected: - explicit ChatHandler() : m_session(NULL), sentErrorMessage(false) { } // for CLI subclass + explicit ChatHandler() : m_session(nullptr), sentErrorMessage(false) { } // for CLI subclass static bool SetDataForCommandInTable(std::vector<ChatCommand>& table, const char* text, uint32 permission, std::string const& help, std::string const& fullcommand); bool ExecuteCommandInTable(std::vector<ChatCommand> const& table, const char* text, std::string const& fullcmd); bool ShowHelpForSubCommands(std::vector<ChatCommand> const& table, char const* cmd, char const* subcmd); private: - WorldSession* m_session; // != NULL for chat command call and NULL for CLI command + WorldSession* m_session; // != nullptr for chat command call and nullptr for CLI command // common global flag bool sentErrorMessage; diff --git a/src/server/game/Chat/ChatLink.cpp b/src/server/game/Chat/ChatLink.cpp index 1a78b716682..1abb14a1669 100644 --- a/src/server/game/Chat/ChatLink.cpp +++ b/src/server/game/Chat/ChatLink.cpp @@ -70,7 +70,7 @@ inline std::string ReadSkip(std::istringstream& iss, char term) return res; } -inline bool CheckDelimiter(std::istringstream& iss, char delimiter, const char* context) +inline bool CheckDelimiter(std::istringstream& iss, char delimiter, char const* context) { char c = iss.peek(); if (c != delimiter) @@ -95,7 +95,7 @@ inline bool ReadHex(std::istringstream& iss, uint32& res, uint32 length) #define DELIMITER ':' #define PIPE_CHAR '|' -bool ChatLink::ValidateName(char* buffer, const char* /*context*/) +bool ChatLink::ValidateName(char* buffer, char const* /*context*/) { _name = buffer; return true; @@ -218,11 +218,11 @@ std::string ItemChatLink::FormatName(uint8 index, LocalizedString* suffixStrings return ss.str(); } -bool ItemChatLink::ValidateName(char* buffer, const char* context) +bool ItemChatLink::ValidateName(char* buffer, char const* context) { ChatLink::ValidateName(buffer, context); - LocalizedString* suffixStrings = _suffix ? _suffix->Name : (_property ? _property->Name : NULL); + LocalizedString* suffixStrings = _suffix ? _suffix->Name : (_property ? _property->Name : nullptr); bool res = (FormatName(LOCALE_enUS, suffixStrings) == buffer); if (!res) @@ -280,7 +280,7 @@ bool QuestChatLink::Initialize(std::istringstream& iss) return true; } -bool QuestChatLink::ValidateName(char* buffer, const char* context) +bool QuestChatLink::ValidateName(char* buffer, char const* context) { ChatLink::ValidateName(buffer, context); @@ -321,7 +321,7 @@ bool SpellChatLink::Initialize(std::istringstream& iss) return true; } -bool SpellChatLink::ValidateName(char* buffer, const char* context) +bool SpellChatLink::ValidateName(char* buffer, char const* context) { ChatLink::ValidateName(buffer, context); @@ -414,7 +414,7 @@ bool AchievementChatLink::Initialize(std::istringstream& iss) return true; } -bool AchievementChatLink::ValidateName(char* buffer, const char* context) +bool AchievementChatLink::ValidateName(char* buffer, char const* context) { ChatLink::ValidateName(buffer, context); @@ -583,7 +583,7 @@ bool GlyphChatLink::Initialize(std::istringstream& iss) return true; } -LinkExtractor::LinkExtractor(const char* msg) : _iss(msg) { } +LinkExtractor::LinkExtractor(char const* msg) : _iss(msg) { } LinkExtractor::~LinkExtractor() { @@ -595,19 +595,19 @@ LinkExtractor::~LinkExtractor() bool LinkExtractor::IsValidMessage() { const char validSequence[6] = "cHhhr"; - const char* validSequenceIterator = validSequence; + char const* validSequenceIterator = validSequence; char buffer[256]; std::istringstream::pos_type startPos = 0; uint32 color = 0; - ChatLink* link = NULL; + ChatLink* link = nullptr; while (!_iss.eof()) { if (validSequence == validSequenceIterator) { - link = NULL; + link = nullptr; _iss.ignore(255, PIPE_CHAR); startPos = _iss.tellg() - std::istringstream::pos_type(1); } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 73b48b2370a..c829c9998c3 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -34,6 +34,7 @@ #include "CharacterDatabaseCleaner.h" #include "CharacterPackets.h" #include "Chat.h" +#include "Channel.h" #include "ChatPackets.h" #include "CombatLogPackets.h" #include "CombatPackets.h" @@ -2247,6 +2248,9 @@ void Player::SetGMVisible(bool on) m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GM, GetSession()->GetSecurity()); } + + for (Channel* channel : m_channels) + channel->SetInvisible(this, !on); } bool Player::IsGroupVisibleFor(Player const* p) const @@ -4699,8 +4703,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()); } @@ -4720,68 +4731,58 @@ void Player::UpdateLocalChannels(uint32 newZone) for (uint32 i = 0; i < sChatChannelsStore.GetNumRows(); ++i) { - if (ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(i)) - { - Channel* usedChannel = nullptr; + ChatChannelsEntry const* channelEntry = sChatChannelsStore.LookupEntry(i); + if (!channelEntry) + continue; - for (JoinedChannelsList::iterator itr = m_channels.begin(); itr != m_channels.end(); ++itr) + Channel* usedChannel = nullptr; + for (Channel* channel : m_channels) + { + if (channel->GetChannelId() == i) { - if ((*itr)->GetChannelId() == i) - { - usedChannel = *itr; - break; - } + usedChannel = channel; + break; } + } - Channel* removeChannel = nullptr; - Channel* joinChannel = nullptr; - bool sendRemove = true; + Channel* removeChannel = nullptr; + Channel* joinChannel = nullptr; + bool sendRemove = true; - if (CanJoinConstantChannelInZone(channel, current_zone)) + if (CanJoinConstantChannelInZone(channelEntry, current_zone)) + { + if (!(channelEntry->Flags & CHANNEL_DBC_FLAG_GLOBAL)) { - if (!(channel->Flags & CHANNEL_DBC_FLAG_GLOBAL)) - { - if (channel->Flags & CHANNEL_DBC_FLAG_CITY_ONLY && usedChannel) - continue; // Already on the channel, as city channel names are not changing - - char new_channel_name_buf[100]; - char const* currentNameExt; + if (channelEntry->Flags & CHANNEL_DBC_FLAG_CITY_ONLY && usedChannel) + continue; // Already on the channel, as city channel names are not changing - if (channel->Flags & CHANNEL_DBC_FLAG_CITY_ONLY) - currentNameExt = sObjectMgr->GetTrinityStringForDBCLocale(LANG_CHANNEL_CITY); - else - currentNameExt = current_zone->AreaName->Str[GetSession()->GetSessionDbcLocale()]; - - snprintf(new_channel_name_buf, 100, channel->Name->Str[m_session->GetSessionDbcLocale()], currentNameExt); - - joinChannel = cMgr->GetJoinChannel(new_channel_name_buf, i); - if (usedChannel) + joinChannel = cMgr->GetJoinChannel(channelEntry->ID, std::string(), current_zone); + if (usedChannel) + { + if (joinChannel != usedChannel) { - if (joinChannel != usedChannel) - { - removeChannel = usedChannel; - sendRemove = false; // Do not send leave channel, it already replaced at client - } - else - joinChannel = nullptr; + removeChannel = usedChannel; + sendRemove = false; // Do not send leave channel, it already replaced at client } + else + joinChannel = nullptr; } - else - joinChannel = cMgr->GetJoinChannel(channel->Name->Str[m_session->GetSessionDbcLocale()], i); } else - removeChannel = usedChannel; + joinChannel = cMgr->GetJoinChannel(channelEntry->ID, std::string()); + } + else + removeChannel = usedChannel; - if (joinChannel) - joinChannel->JoinChannel(this, ""); // Changed Channel: ... or Joined Channel: ... + if (joinChannel) + joinChannel->JoinChannel(this, ""); // Changed Channel: ... or Joined Channel: ... - 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 - } + if (removeChannel) + { + 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 d9cd1fca30d..0977225bee2 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2042,6 +2042,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 SetSkill(uint16 id, uint16 step, uint16 newVal, uint16 maxVal); uint16 GetMaxSkillValue(uint32 skill) const; // max + perm. bonus + temp bonus uint16 GetPureMaxSkillValue(uint32 skill) const; // max @@ -2678,7 +2681,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 344592580cf..4099dab80bd 100644 --- a/src/server/game/Handlers/ChannelHandler.cpp +++ b/src/server/game/Handlers/ChannelHandler.cpp @@ -24,18 +24,21 @@ #include <cctype> +static size_t const MAX_CHANNEL_NAME_STR = 0x31; +static size_t const MAX_CHANNEL_PASS_STR = 31; + void WorldSession::HandleJoinChannel(WorldPackets::Channel::JoinChannel& packet) { TC_LOG_DEBUG("chat.system", "CMSG_JOIN_CHANNEL %s ChatChannelId: %u, CreateVoiceSession: %u, Internal: %u, ChannelName: %s, Password: %s", GetPlayerInfo().c_str(), packet.ChatChannelId, packet.CreateVoiceSession, packet.Internal, packet.ChannelName.c_str(), packet.Password.c_str()); + AreaTableEntry const* zone = sAreaTableStore.LookupEntry(GetPlayer()->GetZoneId()); if (packet.ChatChannelId) { ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(packet.ChatChannelId); if (!channel) return; - AreaTableEntry const* zone = sAreaTableStore.LookupEntry(GetPlayer()->GetZoneId()); if (!zone || !GetPlayer()->CanJoinConstantChannelInZone(channel, zone)) return; } @@ -47,11 +50,8 @@ void WorldSession::HandleJoinChannel(WorldPackets::Channel::JoinChannel& packet) return; if (ChannelMgr* cMgr = ChannelMgr::ForTeam(GetPlayer()->GetTeam())) - { - cMgr->SetTeam(GetPlayer()->GetTeam()); - if (Channel* channel = cMgr->GetJoinChannel(packet.ChannelName, packet.ChatChannelId)) + if (Channel* channel = cMgr->GetJoinChannel(packet.ChatChannelId, packet.ChannelName, zone)) channel->JoinChannel(GetPlayer(), packet.Password); - } } void WorldSession::HandleLeaveChannel(WorldPackets::Channel::LeaveChannel& packet) @@ -59,14 +59,29 @@ void WorldSession::HandleLeaveChannel(WorldPackets::Channel::LeaveChannel& packe TC_LOG_DEBUG("chat.system", "CMSG_LEAVE_CHANNEL %s ChannelName: %s, ZoneChannelID: %u", GetPlayerInfo().c_str(), packet.ChannelName.c_str(), packet.ZoneChannelID); - if (packet.ChannelName.empty()) + if (packet.ChannelName.empty() && !packet.ZoneChannelID) return; + AreaTableEntry const* zone = sAreaTableStore.LookupEntry(GetPlayer()->GetZoneId()); + if (packet.ZoneChannelID) + { + ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(packet.ZoneChannelID); + if (!channel) + return; + + if (!zone || !GetPlayer()->CanJoinConstantChannelInZone(channel, zone)) + return; + } + if (ChannelMgr* cMgr = ChannelMgr::ForTeam(GetPlayer()->GetTeam())) { - if (Channel* channel = cMgr->GetChannel(packet.ChannelName, GetPlayer())) + if (Channel* channel = cMgr->GetChannel(packet.ZoneChannelID, packet.ChannelName, GetPlayer(), true, zone)) channel->LeaveChannel(GetPlayer(), true); - cMgr->LeftChannel(packet.ChannelName); + + if (packet.ZoneChannelID) + cMgr->LeftChannel(packet.ZoneChannelID, zone); + else + cMgr->LeftChannel(packet.ChannelName); } } @@ -76,9 +91,8 @@ void WorldSession::HandleChannelCommand(WorldPackets::Channel::ChannelPlayerComm TC_LOG_DEBUG("chat.system", "%s %s ChannelName: %s", GetOpcodeNameForLogging(packet.GetOpcode()).c_str(), GetPlayerInfo().c_str(), packet.ChannelName.c_str()); - if (ChannelMgr* cMgr = ChannelMgr::ForTeam(GetPlayer()->GetTeam())) - if (Channel* channel = cMgr->GetChannel(packet.ChannelName, GetPlayer())) - (channel->*CommandFunction)(GetPlayer()); + if (Channel* channel = ChannelMgr::GetChannelForPlayerByNamePart(packet.ChannelName, GetPlayer())) + (channel->*CommandFunction)(GetPlayer()); } template<void(Channel::*CommandFunction)(Player const*, std::string const&)> @@ -97,9 +111,8 @@ void WorldSession::HandleChannelPlayerCommand(WorldPackets::Channel::ChannelPlay if (!normalizePlayerName(packet.Name)) return; - if (ChannelMgr* cMgr = ChannelMgr::ForTeam(GetPlayer()->GetTeam())) - if (Channel* channel = cMgr->GetChannel(packet.ChannelName, GetPlayer())) - (channel->*CommandFunction)(GetPlayer(), packet.Name); + if (Channel* channel = ChannelMgr::GetChannelForPlayerByNamePart(packet.ChannelName, GetPlayer())) + (channel->*CommandFunction)(GetPlayer(), packet.Name); } template<> @@ -115,9 +128,8 @@ void WorldSession::HandleChannelPlayerCommand<&Channel::Password>(WorldPackets:: TC_LOG_DEBUG("chat.system", "%s %s ChannelName: %s, Password: %s", GetOpcodeNameForLogging(packet.GetOpcode()).c_str(), GetPlayerInfo().c_str(), packet.ChannelName.c_str(), packet.Name.c_str()); - if (ChannelMgr* cMgr = ChannelMgr::ForTeam(GetPlayer()->GetTeam())) - if (Channel* channel = cMgr->GetChannel(packet.ChannelName, GetPlayer())) - channel->Password(GetPlayer(), packet.Name); + if (Channel* channel = ChannelMgr::GetChannelForPlayerByNamePart(packet.ChannelName, GetPlayer())) + channel->Password(GetPlayer(), packet.Name); } template void WorldSession::HandleChannelCommand<&Channel::Announce>(WorldPackets::Channel::ChannelPlayerCommand&); diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp index 2d5099fa341..444da486a2d 100644 --- a/src/server/game/Handlers/ChatHandler.cpp +++ b/src/server/game/Handlers/ChatHandler.cpp @@ -25,6 +25,7 @@ #include "WorldSession.h" #include "DatabaseEnv.h" #include "Chat.h" +#include "Channel.h" #include "ChannelMgr.h" #include "GridNotifiersImpl.h" #include "Group.h" @@ -357,13 +358,10 @@ void WorldSession::HandleChatMessage(ChatMsg type, uint32 lang, std::string msg, } } - if (ChannelMgr* cMgr = ChannelMgr::ForTeam(sender->GetTeam())) + if (Channel* chn = ChannelMgr::GetChannelForPlayerByNamePart(target, sender)) { - if (Channel* chn = cMgr->GetChannel(target, 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; } @@ -488,9 +486,8 @@ void WorldSession::HandleChatAddonMessage(ChatMsg type, std::string prefix, std: } case CHAT_MSG_CHANNEL: { - if (ChannelMgr* cMgr = ChannelMgr::ForTeam(sender->GetTeam())) - if (Channel* chn = cMgr->GetChannel(target, sender, false)) - chn->Say(sender->GetGUID(), text.c_str(), uint32(LANG_ADDON)); + if (Channel* chn = ChannelMgr::GetChannelForPlayerByNamePart(target, sender)) + chn->Say(sender->GetGUID(), text.c_str(), uint32(LANG_ADDON)); break; } default: diff --git a/src/server/scripts/Commands/cs_message.cpp b/src/server/scripts/Commands/cs_message.cpp index 8522b4e47dd..7a44cc23172 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,50 @@ 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* channelEntry = sChatChannelsStore.LookupEntry(i); + if (!channelEntry) + continue; + + if (strstr(channelEntry->Name->Str[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->AreaName->Str[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 +116,9 @@ 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); |