aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorariel- <ariel-@users.noreply.github.com>2016-10-03 06:06:33 -0300
committerariel- <ariel-@users.noreply.github.com>2016-10-07 01:09:28 -0300
commit59a9bc5ca0ae81ef58107f9b24b1a92b11478fd8 (patch)
tree0ca9878358731b10a38577cf95a41220051155f6
parent4b5e5bbd72bd12683b9fc792d9c291cad1e52c0e (diff)
Core/Channels: Revamp of channel system
* Core/Chat: general cleanup and revamping: (#17576) (fbbb03212e93591a77a1169a30fb01867cd3c0e9) * Core/Channel: restore accidentally deleted line, fixes channels not honoring ownership setting (7c714179930c8c369f124d8d1404656fff0a1199) * Channel Followup: avoid setting an invisible gm as Channel owner (#17597) (8a8362ef153eca50be0bcb5670e615b9685607fc) * Core/Channel: change the way channels are stored and sent to client, fixes multiple channels per zone when using different locales (#17980)
-rw-r--r--src/server/database/Database/Implementation/CharacterDatabase.cpp2
-rw-r--r--src/server/game/Chat/Channels/Channel.cpp1013
-rw-r--r--src/server/game/Chat/Channels/Channel.h130
-rw-r--r--src/server/game/Chat/Channels/ChannelAppenders.h473
-rw-r--r--src/server/game/Chat/Channels/ChannelMgr.cpp148
-rw-r--r--src/server/game/Chat/Channels/ChannelMgr.h22
-rw-r--r--src/server/game/Chat/Chat.cpp86
-rw-r--r--src/server/game/Chat/Chat.h14
-rw-r--r--src/server/game/Chat/ChatLink.cpp22
-rw-r--r--src/server/game/Entities/Player/Player.cpp99
-rw-r--r--src/server/game/Entities/Player/Player.h4
-rw-r--r--src/server/game/Handlers/ChannelHandler.cpp46
-rw-r--r--src/server/game/Handlers/ChatHandler.cpp15
-rw-r--r--src/server/scripts/Commands/cs_message.cpp45
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, &param1_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);