diff --git a/src/server/game/Chat/Channels/Channel.cpp b/src/server/game/Chat/Channels/Channel.cpp index 11c8030b8..9a144281c 100644 --- a/src/server/game/Chat/Channels/Channel.cpp +++ b/src/server/game/Chat/Channels/Channel.cpp @@ -1258,3 +1258,54 @@ void Channel::RemoveWatching(Player* p) if (itr != playersWatchingStore.end()) playersWatchingStore.erase(itr); } + +void Channel::ToggleModeration(Player* player) +{ + uint64 guid = player->GetGUIDLow(); + + if (!IsOn(guid)) + { + WorldPacket data; + MakeNotMember(&data); + SendToOne(&data, guid); + return; + } + + const uint32 level = sWorld->getIntConfig(CONFIG_GM_LEVEL_CHANNEL_MODERATION); + const bool gm = (level && player->GetSession()->GetSecurity() >= level); + + if (!playersStore[guid].IsModerator() && !gm) + { + WorldPacket data; + MakeNotModerator(&data); + SendToOne(&data, guid); + return; + } + + // toggle channel moderation + _moderation = !_moderation; + + WorldPacket data; + if (_moderation) + { + MakeModerationOn(&data, guid); + } + else + { + MakeModerationOff(&data, guid); + } + + SendToAll(&data); +} + +void Channel::MakeModerationOn(WorldPacket* data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_MODERATION_ON_NOTICE); + *data << uint64(guid); +} + +void Channel::MakeModerationOff(WorldPacket* data, uint64 guid) +{ + MakeNotifyPacket(data, CHAT_MODERATION_OFF_NOTICE); + *data << uint64(guid); +} diff --git a/src/server/game/Chat/Channels/Channel.h b/src/server/game/Chat/Channels/Channel.h index 1e9dc30da..b55dec359 100644 --- a/src/server/game/Chat/Channels/Channel.h +++ b/src/server/game/Chat/Channels/Channel.h @@ -39,8 +39,8 @@ enum ChatNotify CHAT_MODE_CHANGE_NOTICE = 0x0C, //? CHAT_ANNOUNCEMENTS_ON_NOTICE = 0x0D, //+ "[%s] Channel announcements enabled by %s."; CHAT_ANNOUNCEMENTS_OFF_NOTICE = 0x0E, //+ "[%s] Channel announcements disabled by %s."; - // CHAT_MODERATION_ON_NOTICE = 0x0F, //+ "[%s] Channel moderation enabled by %s."; - // CHAT_MODERATION_OFF_NOTICE = 0x10, //+ "[%s] Channel moderation disabled by %s."; + CHAT_MODERATION_ON_NOTICE = 0x0F, //+ "[%s] Channel moderation enabled by %s."; + 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."; @@ -219,6 +219,7 @@ public: void LeaveNotify(Player* p); void FlagsNotify(Player* p); static void CleanOldChannelsInDB(); + void ToggleModeration(Player* p); // pussywizard: void AddWatching(Player* p); @@ -262,6 +263,8 @@ private: void MakeNotInLfg(WorldPacket* data); //? 0x21 void MakeVoiceOn(WorldPacket* data, uint64 guid); //+ 0x22 void MakeVoiceOff(WorldPacket* data, uint64 guid); //+ 0x23 + void MakeModerationOn(WorldPacket* data, uint64 guid); + void MakeModerationOff(WorldPacket* data, uint64 guid); void SendToAll(WorldPacket* data, uint64 guid = 0); void SendToAllButOne(WorldPacket* data, uint64 who); @@ -317,6 +320,7 @@ private: typedef std::unordered_set PlayersWatchingContainer; bool _announce; + bool _moderation; bool _ownership; bool _IsSaved; bool _isOwnerGM; diff --git a/src/server/game/Handlers/ChannelHandler.cpp b/src/server/game/Handlers/ChannelHandler.cpp index 19484cbc5..4c8f8d1fb 100644 --- a/src/server/game/Handlers/ChannelHandler.cpp +++ b/src/server/game/Handlers/ChannelHandler.cpp @@ -277,13 +277,28 @@ void WorldSession::HandleChannelAnnouncements(WorldPacket& recvPacket) #if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) sLog->outDebug(LOG_FILTER_CHATSYS, "CMSG_CHANNEL_ANNOUNCEMENTS %s Channel: %s", - GetPlayerInfo().c_str(), channelName.c_str()); + GetPlayerInfo().c_str(), channelName.c_str()); #endif if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeamId())) if (Channel* channel = cMgr->GetChannel(channelName, GetPlayer())) channel->Announce(GetPlayer()); } +void WorldSession::HandleChannelModerateOpcode(WorldPacket& recvPacket) +{ + std::string channelName; + recvPacket >> channelName; + +#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) + sLog->outDebug(LOG_FILTER_CHATSYS, "CMSG_CHANNEL_MODERATE %s Channel: %s", + GetPlayerInfo().c_str(), channelName.c_str()); +#endif + + if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeamId())) + if (Channel* chn = cMgr->GetChannel(channelName, GetPlayer())) + chn->ToggleModeration(GetPlayer()); +} + void WorldSession::HandleChannelDisplayListQuery(WorldPacket& recvPacket) { // this should be OK because the 2 function _were_ the same diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 3a1a250f9..20b10461e 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -182,7 +182,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*0x0A5*/ { "CMSG_CHANNEL_BAN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelBan }, /*0x0A6*/ { "CMSG_CHANNEL_UNBAN", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelUnban }, /*0x0A7*/ { "CMSG_CHANNEL_ANNOUNCEMENTS", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelAnnouncements }, - /*0x0A8*/ { "CMSG_CHANNEL_MODERATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL }, + /*0x0A8*/ { "CMSG_CHANNEL_MODERATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelModerateOpcode }, /*0x0A9*/ { "SMSG_UPDATE_OBJECT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, /*0x0AA*/ { "SMSG_DESTROY_OBJECT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, /*0x0AB*/ { "CMSG_USE_ITEM", STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleUseItemOpcode }, diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 4de5a2790..8823a0ebc 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -714,6 +714,7 @@ public: // opcodes handlers void HandleChannelBan(WorldPacket& recvPacket); void HandleChannelUnban(WorldPacket& recvPacket); void HandleChannelAnnouncements(WorldPacket& recvPacket); + void HandleChannelModerateOpcode(WorldPacket& recvPacket); void HandleChannelDeclineInvite(WorldPacket& recvPacket); void HandleChannelDisplayListQuery(WorldPacket& recvPacket); void HandleGetChannelMemberCount(WorldPacket& recvPacket); diff --git a/src/server/game/World/IWorld.h b/src/server/game/World/IWorld.h index 4c035569e..80988e9b2 100644 --- a/src/server/game/World/IWorld.h +++ b/src/server/game/World/IWorld.h @@ -368,6 +368,7 @@ enum WorldIntConfigs CONFIG_GUILD_BANK_TAB_COST_3, CONFIG_GUILD_BANK_TAB_COST_4, CONFIG_GUILD_BANK_TAB_COST_5, + CONFIG_GM_LEVEL_CHANNEL_MODERATION, INT_CONFIG_VALUE_COUNT }; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 7940b0302..721da95ef 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1407,6 +1407,8 @@ void World::LoadConfigSettings(bool reload) m_bool_configs[CONFIG_DEBUG_BATTLEGROUND] = sConfigMgr->GetBoolDefault("Debug.Battleground", false); m_bool_configs[CONFIG_DEBUG_ARENA] = sConfigMgr->GetBoolDefault("Debug.Arena", false); + m_int_configs[CONFIG_GM_LEVEL_CHANNEL_MODERATION] = sConfigMgr->GetIntDefault("Channel.ModerationGMLevel", 1); + // call ScriptMgr if we're reloading the configuration sScriptMgr->OnAfterConfigLoad(reload); } diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 2e223429a..f093ac6ad 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -2041,6 +2041,14 @@ Channel.RestrictedLfg = 1 Channel.SilentlyGMJoin = 0 +# Channel.ModerationGMLevel +# Min GM account security level required for executing moderator in-game commands in the channels +# This also bypasses password prompts on joining channels which require password +# 0 (in-game channel moderator privileges only) +# Default: 1 (enabled for moderators and above) + +Channel.ModerationGMLevel = 1 + # # ChatLevelReq.Channel # Description: Level requirement for characters to be able to write in chat channels.