diff --git a/src/game/ddracecommands.h b/src/game/ddracecommands.h index 31c69ba77..3a61fb7c4 100644 --- a/src/game/ddracecommands.h +++ b/src/game/ddracecommands.h @@ -42,6 +42,7 @@ CONSOLE_COMMAND("showall", "?i['0'|'1']", CFGFLAG_CHAT, ConShowAll, this, "Wheth CONSOLE_COMMAND("list", "?s[filter]", CFGFLAG_CHAT, ConList, this, "List connected players with optional case-insensitive substring matching filter") CONSOLE_COMMAND("set_team_ddr", "v[id] ?i[team]", CFGFLAG_SERVER, ConSetDDRTeam, this, "Set ddrace team of a player") +CONSOLE_COMMAND("vote_mute", "v[id] i[seconds]", CFGFLAG_SERVER, ConVoteMute, this, "Remove v's right to vote for i seconds") CONSOLE_COMMAND("mute", "", CFGFLAG_SERVER, ConMute, this, "") CONSOLE_COMMAND("muteid", "v[id] i[seconds]", CFGFLAG_SERVER, ConMuteID, this, "") CONSOLE_COMMAND("muteip", "s[ip] i[seconds]", CFGFLAG_SERVER, ConMuteIP, this, "") diff --git a/src/game/server/ddracecommands.cpp b/src/game/server/ddracecommands.cpp index 65f11ada1..ecf652074 100644 --- a/src/game/server/ddracecommands.cpp +++ b/src/game/server/ddracecommands.cpp @@ -345,6 +345,50 @@ void CGameContext::ConForcePause(IConsole::IResult *pResult, void *pUserData) pPlayer->ForcePause(Seconds); } +void CGameContext::VoteMute(IConsole::IResult *pResult, NETADDR *pAddr, int Secs, + const char *pDisplayName, int AuthedID) +{ + char aBuf[128]; + bool Found = 0; + + pAddr->port = 0; // ignore port number for vote mutes + + // find a matching vote mute for this ip, update expiration time if found + for(int i = 0; i < m_NumVoteMutes; i++) + { + if(net_addr_comp(&m_aVoteMutes[i].m_Addr, pAddr) == 0) + { + m_aVoteMutes[i].m_Expire = Server()->Tick() + + Secs * Server()->TickSpeed(); + Found = 1; + break; + } + } + + if(!Found) // nothing found so far, find a free slot.. + { + if(m_NumVoteMutes < MAX_VOTE_BANS) + { + m_aVoteMutes[m_NumVoteMutes].m_Addr = *pAddr; + m_aVoteMutes[m_NumVoteMutes].m_Expire = Server()->Tick() + + Secs * Server()->TickSpeed(); + m_NumVoteMutes++; + Found = 1; + } + } + if(Found) + { + if(pDisplayName) + { + str_format(aBuf, sizeof aBuf, "'%s' banned '%s' for %d seconds from voting.", + Server()->ClientName(AuthedID), pDisplayName, Secs); + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "votemute", aBuf); + } + } + else // no free slot found + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "votemute", "vote mute array is full"); +} + void CGameContext::Mute(IConsole::IResult *pResult, NETADDR *Addr, int Secs, const char *pDisplayName) { @@ -388,6 +432,24 @@ void CGameContext::Mute(IConsole::IResult *pResult, NETADDR *Addr, int Secs, Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "mutes", "mute array is full"); } +void CGameContext::ConVoteMute(IConsole::IResult *pResult, void *pUserData) +{ + CGameContext *pSelf = (CGameContext *)pUserData; + int Victim = pResult->GetVictim(); + + if(Victim < 0 || Victim > MAX_CLIENTS || !pSelf->m_apPlayers[Victim]) + { + pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "votemute", "Client ID not found"); + return; + } + + NETADDR Addr; + pSelf->Server()->GetClientAddr(Victim, &Addr); + + pSelf->VoteMute(pResult, &Addr, clamp(pResult->GetInteger(1), 1, 86400), + pSelf->Server()->ClientName(Victim), pResult->m_ClientID); +} + void CGameContext::ConMute(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *) pUserData; diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 8650b32fc..b6c6ba82d 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -53,6 +53,7 @@ void CGameContext::Construct(int Resetting) m_pVoteOptionHeap = new CHeap(); m_pScore = 0; m_NumMutes = 0; + m_NumVoteMutes = 0; } m_ChatResponseTargetID = -1; m_aDeleteTempfile[0] = 0; @@ -736,7 +737,7 @@ void CGameContext::OnTick() continue; // don't count votes by blacklisted clients - if (g_Config.m_SvDnsblVote && !m_pServer->DnsblWhite(i)) + if(g_Config.m_SvDnsblVote && !m_pServer->DnsblWhite(i)) continue; int ActVote = m_apPlayers[i]->m_Vote; @@ -1351,6 +1352,21 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) return; } + NETADDR Addr; + Server()->GetClientAddr(ClientID, &Addr); + Addr.port = 0; // ignore port number + int VoteMuted = 0; + for(int i = 0; i < m_NumVoteMutes && !VoteMuted; i++) + if(!net_addr_comp(&Addr, &m_aVoteMutes[i].m_Addr)) + VoteMuted = (m_aVoteMutes[i].m_Expire - Server()->Tick()) / Server()->TickSpeed(); + if(VoteMuted > 0) + { + char aChatmsg[64]; + str_format(aChatmsg, sizeof(aChatmsg), "You are not permitted to vote for the next %d seconds.", VoteMuted); + SendChatTarget(ClientID, aChatmsg); + return; + } + char aChatmsg[512] = {0}; char aDesc[VOTE_DESC_LENGTH] = {0}; char aCmd[VOTE_CMD_LENGTH] = {0}; diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index 9f9202ad7..abefbfc59 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -342,6 +342,7 @@ private: static void ConRescue(IConsole::IResult *pResult, void *pUserData); static void ConProtectedKill(IConsole::IResult *pResult, void *pUserData); + static void ConVoteMute(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); @@ -358,16 +359,25 @@ private: enum { MAX_MUTES=32, + MAX_VOTE_BANS=32, }; struct CMute { NETADDR m_Addr; int m_Expire; }; + struct CVoteMute + { + NETADDR m_Addr; + int m_Expire; + }; CMute m_aMutes[MAX_MUTES]; int m_NumMutes; + CVoteMute m_aVoteMutes[MAX_VOTE_BANS]; + int m_NumVoteMutes; void Mute(IConsole::IResult *pResult, NETADDR *Addr, int Secs, const char *pDisplayName); + void VoteMute(IConsole::IResult *pResult, NETADDR *pAddr, int Secs, const char *pDisplayName, int AuthedID); void Whisper(int ClientID, char *pStr); void WhisperID(int ClientID, int VictimID, char *pMessage); void Converse(int ClientID, char *pStr);