977: Active moderator mode r=heinrich5991 a=Ryozuki

This PR adds a RCON command called "moderate", which enables a active moderator mode for the caller, so this will happen if a vote kick/spec is made:

- Vote will last atleast x seconds defined by CGameContext::m_VoteCloseTime (35 seconds on ddnet, according to @heinrich5991) even if there is majority.
- If a active moderator votes, it will be a force vote.
- If the active moderator doesn't vote, it will pass normally
- This is only for kick and spec votes.

I also added `access_level moderate 1` to autoexec_server.cfg

If there are any spelling errors on the code tell me.

Maybe needs to be tested more.
This commit is contained in:
bors[bot] 2018-01-09 09:14:17 +00:00
commit 94e43509cc
7 changed files with 108 additions and 9 deletions

View file

@ -181,6 +181,7 @@ access_level bans 1
access_level bans_save 1
access_level kick 1
access_level force_vote 1
access_level moderate 1

View file

@ -47,6 +47,7 @@ CONSOLE_COMMAND("muteid", "v[id] i[seconds]", CFGFLAG_SERVER, ConMuteID, this, "
CONSOLE_COMMAND("muteip", "s[ip] i[seconds]", CFGFLAG_SERVER, ConMuteIP, this, "");
CONSOLE_COMMAND("unmute", "v[id]", CFGFLAG_SERVER, ConUnmute, this, "");
CONSOLE_COMMAND("mutes", "", CFGFLAG_SERVER, ConMutes, this, "");
CONSOLE_COMMAND("moderate", "", CFGFLAG_SERVER, ConModerate, this, "Enables/disables active moderator mode for the player")
CONSOLE_COMMAND("freezehammer", "v[id]", CFGFLAG_SERVER|CMDFLAG_TEST, ConFreezeHammer, this, "Gives a player Freeze Hammer")
CONSOLE_COMMAND("unfreezehammer", "v[id]", CFGFLAG_SERVER|CMDFLAG_TEST, ConUnFreezeHammer, this, "Removes Freeze Hammer from a player")

View file

@ -461,6 +461,34 @@ void CGameContext::ConMutes(IConsole::IResult *pResult, void *pUserData)
}
}
void CGameContext::ConModerate(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *)pUserData;
if (!CheckClientID(pResult->m_ClientID))
return;
bool HadModerator = pSelf->PlayerModerating();
CPlayer* player = pSelf->m_apPlayers[pResult->m_ClientID];
player->m_Moderating = !player->m_Moderating;
char aBuf[256];
if(!HadModerator && player->m_Moderating)
str_format(aBuf, sizeof(aBuf), "Server kick/spec votes will now be actively moderated.");
if (!pSelf->PlayerModerating())
str_format(aBuf, sizeof(aBuf), "Server kick/spec votes are no longer actively moderated.");
pSelf->SendChat(-1, CHAT_ALL, aBuf, 0);
if(player->m_Moderating)
pSelf->SendChatTarget(pResult->m_ClientID,
"Active moderator mode enabled for you.");
else
pSelf->SendChatTarget(pResult->m_ClientID, "Active moderator mode disabled for you.");
}
void CGameContext::ConList(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *)pUserData;

View file

@ -740,6 +740,26 @@ void CGameContext::OnTick()
else if(ActVote < 0)
VetoStop = true;
}
// Check if a active moderator has voted.
if (m_apPlayers[i] && m_apPlayers[i]->m_Vote != 0 && m_apPlayers[i]->m_Moderating)
{
if (m_apPlayers[i]->m_Vote == 1)
{
Server()->SetRconCID(IServer::RCON_CID_VOTE);
Console()->ExecuteLine(m_aVoteCommand);
Server()->SetRconCID(IServer::RCON_CID_SERV);
EndVote();
SendChat(-1, CGameContext::CHAT_ALL, "Vote passed enforced by server moderator");
return;
}
else if (m_apPlayers[i]->m_Vote == -1)
{
EndVote();
SendChat(-1, CGameContext::CHAT_ALL, "Vote failed enforced by server moderator");
return;
}
}
}
if(g_Config.m_SvVoteMaxTotal && Total > g_Config.m_SvVoteMaxTotal &&
@ -762,14 +782,32 @@ void CGameContext::OnTick()
if(m_VoteEnforce == VOTE_ENFORCE_YES)
{
Server()->SetRconCID(IServer::RCON_CID_VOTE);
Console()->ExecuteLine(m_aVoteCommand);
Server()->SetRconCID(IServer::RCON_CID_SERV);
EndVote();
SendChat(-1, CGameContext::CHAT_ALL, "Vote passed");
if (PlayerModerating() && (m_VoteKick || m_VoteSpec))
{
// Ensure minimum time for vote to end when moderating.
if (time_get() > m_VoteCloseTime)
{
Server()->SetRconCID(IServer::RCON_CID_VOTE);
Console()->ExecuteLine(m_aVoteCommand);
Server()->SetRconCID(IServer::RCON_CID_SERV);
EndVote();
SendChat(-1, CGameContext::CHAT_ALL, "Vote passed");
if(m_apPlayers[m_VoteCreator] && !m_VoteKick && !m_VoteSpec)
m_apPlayers[m_VoteCreator]->m_LastVoteCall = 0;
if (m_apPlayers[m_VoteCreator] && !m_VoteKick && !m_VoteSpec)
m_apPlayers[m_VoteCreator]->m_LastVoteCall = 0;
}
}
else
{
Server()->SetRconCID(IServer::RCON_CID_VOTE);
Console()->ExecuteLine(m_aVoteCommand);
Server()->SetRconCID(IServer::RCON_CID_SERV);
EndVote();
SendChat(-1, CGameContext::CHAT_ALL, "Vote passed");
if (m_apPlayers[m_VoteCreator] && !m_VoteKick && !m_VoteSpec)
m_apPlayers[m_VoteCreator]->m_LastVoteCall = 0;
}
}
else if(m_VoteEnforce == VOTE_ENFORCE_YES_ADMIN)
{
@ -3345,3 +3383,13 @@ void CGameContext::SetClientVersion(int ClientID, int Version) {
}
m_apPlayers[ClientID]->m_ClientVersion = Version;
}
bool CGameContext::PlayerModerating()
{
for (int i = 0; i < MAX_CLIENTS; i++)
{
if (m_apPlayers[i] && m_apPlayers[i]->m_Moderating)
return true;
}
return false;
}

View file

@ -245,6 +245,8 @@ public:
int GetClientVersion(int ClientID);
void SetClientVersion(int ClientID, int Version);
bool PlayerExists(int ClientID) { return m_apPlayers[ClientID]; };
// Returns true if someone is actively moderating.
bool PlayerModerating();
private:
@ -335,13 +337,12 @@ private:
static void ConRescue(IConsole::IResult *pResult, void *pUserData);
static void ConProtectedKill(IConsole::IResult *pResult, void *pUserData);
static void ConMute(IConsole::IResult *pResult, void *pUserData);
static void ConMuteID(IConsole::IResult *pResult, void *pUserData);
static void ConMuteIP(IConsole::IResult *pResult, void *pUserData);
static void ConUnmute(IConsole::IResult *pResult, void *pUserData);
static void ConMutes(IConsole::IResult *pResult, void *pUserData);
static void ConModerate(IConsole::IResult *pResult, void *pUserData);
static void ConList(IConsole::IResult *pResult, void *pUserData);
static void ConSetDDRTeam(IConsole::IResult *pResult, void *pUserData);

View file

@ -62,6 +62,7 @@ void CPlayer::Reset()
m_Sent1stAfkWarning = 0;
m_Sent2ndAfkWarning = 0;
m_ChatScore = 0;
m_Moderating = false;
m_EyeEmote = true;
m_TimerType = (g_Config.m_SvDefaultTimerType == CPlayer::TIMERTYPE_GAMETIMER || g_Config.m_SvDefaultTimerType == CPlayer::TIMERTYPE_GAMETIMER_AND_BROADCAST) ? CPlayer::TIMERTYPE_BROADCAST : g_Config.m_SvDefaultTimerType;
m_DefEmote = EMOTE_NORMAL;
@ -153,6 +154,15 @@ void CPlayer::Tick()
Server()->SetClientScore(m_ClientID, m_Score);
if (m_Moderating && m_Afk)
{
m_Moderating = false;
GameServer()->SendChatTarget(m_ClientID, "Active moderator mode disabled because you are afk.");
if (!GameServer()->PlayerModerating())
GameServer()->SendChat(-1, CGameContext::CHAT_ALL, "Server kick/spec votes are no longer actively moderated.");
}
// do latency stuff
{
IServer::CClientInfo Info;
@ -374,6 +384,14 @@ void CPlayer::OnDisconnect(const char *pReason)
str_format(aBuf, sizeof(aBuf), "leave player='%d:%s'", m_ClientID, Server()->ClientName(m_ClientID));
GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "game", aBuf);
bool WasModerator = m_Moderating;
// Set this to false, otherwise PlayerModerating() will return true.
m_Moderating = false;
if (!GameServer()->PlayerModerating() && WasModerator)
GameServer()->SendChat(-1, CGameContext::CHAT_ALL, "Server kick/spec votes are no longer actively moderated.");
}
CGameControllerDDRace* Controller = (CGameControllerDDRace*)GameServer()->m_pController;

View file

@ -176,6 +176,8 @@ public:
int m_ChatScore;
bool m_Moderating;
bool AfkTimer(int new_target_x, int new_target_y); //returns true if kicked
void AfkVoteTimer(CNetObj_PlayerInput *NewTarget);
int64 m_LastPlaytime;