rewritten mutes

This commit is contained in:
heinrich5991 2011-02-23 22:39:53 +01:00 committed by GreYFoX
parent 90d93ba7b2
commit 3d0aab503f
6 changed files with 152 additions and 118 deletions

View file

@ -29,6 +29,7 @@ public:
virtual bool ClientIngame(int ClientID) = 0;
virtual int GetClientInfo(int ClientID, CClientInfo *pInfo) = 0;
virtual void GetClientIP(int ClientID, char *pIPString, int Size) = 0;
virtual void GetClientAddr(int ClientID, NETADDR *pAddr) = 0;
virtual int *LatestInput(int ClientID, int *pSize) = 0;
virtual void SetRconLevel(int ClientID, int Level) = 0;

View file

@ -348,7 +348,12 @@ void CServer::GetClientIP(int ClientID, char *pIPString, int Size)
}
}
void CServer::GetClientAddr(int ClientID, NETADDR *pAddr)
{
if(ClientID >= 0 && ClientID < MAX_CLIENTS && m_aClients[ClientID].m_State == CClient::STATE_INGAME)
*pAddr = m_NetServer.ClientAddr(ClientID);
}
int *CServer::LatestInput(int ClientID, int *size)
{
if(ClientID < 0 || ClientID >= MAX_CLIENTS || m_aClients[ClientID].m_State < CServer::CClient::STATE_READY)

View file

@ -158,6 +158,7 @@ public:
int IsAuthed(int ClientID);
int GetClientInfo(int ClientID, CClientInfo *pInfo);
void GetClientAddr(int ClientID, NETADDR *pAddr);
void GetClientIP(int ClientID, char *pIPString, int Size);
const char *ClientName(int ClientID);
bool ClientIngame(int ClientID);

View file

@ -1277,41 +1277,51 @@ void CGameContext::ConToggleStrict(IConsole::IResult *pResult, void *pUserData,
return;
}
void CGameContext::Mute(const char *pIP, int Secs, const char *pDisplayName)
void CGameContext::Mute(NETADDR *Addr, int Secs, const char *pDisplayName)
{
char aBuf[128];
// purge expired mutes first
for(int z = 0; z < MAX_MUTES; ++z)
if (m_aMutes[z].m_IP[0] && m_aMutes[z].m_Expire <= Server()->Tick())
m_aMutes[z].m_IP[0] = 0;
int FoundInd = -1;
for(int i = 0; i < m_NumMutes; i++)
{
if(m_aMutes[i].m_Expire <= Server()->Tick())
{
m_NumMutes--;
m_aMutes[i] = m_aMutes[m_NumMutes];
}
}
int Found = 0;
// find a matching mute for this ip, update expiration time if found
for(int z = 0; z < MAX_MUTES; ++z)
if (m_aMutes[z].m_IP[0] && str_comp(m_aMutes[z].m_IP, pIP) == 0)
m_aMutes[FoundInd = z].m_Expire = Server()->Tick() + Secs * Server()->TickSpeed();
for(int i = 0; i < m_NumMutes; i++)
{
if(net_addr_comp(&m_aMutes[i].m_Addr, Addr) == 0)
{
m_aMutes[i].m_Expire = Server()->Tick() + Secs * Server()->TickSpeed();
Found = 1;
}
}
if (FoundInd == -1) // nothing found so far, find a free slot..
for(int z = 0; z < MAX_MUTES; ++z) //..in order to add a new mute
if (!m_aMutes[z].m_IP[0])
{
str_copy(m_aMutes[z].m_IP, pIP, str_length(pIP)+1);
m_aMutes[FoundInd = z].m_Expire = Server()->Tick() + Secs * Server()->TickSpeed();
break;
}
if (FoundInd != -1)
if(!Found) // nothing found so far, find a free slot..
{
if(m_NumMutes < MAX_MUTES)
{
m_aMutes[m_NumMutes].m_Addr = *Addr;
m_aMutes[m_NumMutes].m_Expire = Server()->Tick() + Secs * Server()->TickSpeed();
Found = 1;
}
}
if(Found)
{
str_format(aBuf, sizeof aBuf, "'%s' has been muted for %d seconds.", pDisplayName, Secs);
SendChat(-1, CHAT_ALL, aBuf);
}
else // no free slot found
Console()->PrintResponse(IConsole::OUTPUT_LEVEL_STANDARD, "server", "mute array is full");
Console()->PrintResponse(IConsole::OUTPUT_LEVEL_STANDARD, "mutes", "mute array is full");
}
void CGameContext::ConMute(IConsole::IResult *pResult, void *pUserData, int ClientID)
{
((CGameContext *)pUserData)->Console()->PrintResponse(IConsole::OUTPUT_LEVEL_STANDARD, "server", "Use either 'muteid <client_id> <seconds>' or 'muteip <ip> <seconds>'");
((CGameContext *)pUserData)->Console()->PrintResponse(IConsole::OUTPUT_LEVEL_STANDARD, "mutes", "Use either 'muteid <client_id> <seconds>' or 'muteip <ip> <seconds>'");
}
// mute through client id
@ -1319,54 +1329,56 @@ void CGameContext::ConMuteID(IConsole::IResult *pResult, void *pUserData, int Cl
{
CGameContext *pSelf = (CGameContext *)pUserData;
int Victim = pResult->GetVictim();
if (Victim < 0 || Victim >= MAX_CLIENTS || !pSelf->m_apPlayers[Victim])
return;
char aIP[16];
pSelf->Server()->GetClientIP(Victim, aIP, sizeof aIP);
NETADDR Addr;
pSelf->Server()->GetClientAddr(Victim, &Addr);
pSelf->Mute(aIP, clamp(pResult->GetInteger(0), 1, 60*60*24*365), pSelf->Server()->ClientName(Victim));
pSelf->Mute(&Addr, clamp(pResult->GetInteger(0), 1, 86400), pSelf->Server()->ClientName(Victim));
}
// mute through ip, arguments reversed to workaround parsing
void CGameContext::ConMuteIP(IConsole::IResult *pResult, void *pUserData, int ClientID)
{
CGameContext *pSelf = (CGameContext *)pUserData;
pSelf->Mute(pResult->GetString(0), clamp(pResult->GetInteger(1), 1, 60*60*24*365), pResult->GetString(0));
NETADDR Addr;
if(net_addr_from_str(&Addr, pResult->GetString(0)))
{
pSelf->Console()->PrintResponse(IConsole::OUTPUT_LEVEL_STANDARD, "mutes", "Invalid network address to mute");
}
pSelf->Mute(&Addr, clamp(pResult->GetInteger(1), 1, 86400), pResult->GetString(0));
}
// unmute by mute list index
void CGameContext::ConUnmute(IConsole::IResult *pResult, void *pUserData, int ClientID)
{
char aBuf[32];
CGameContext *pSelf = (CGameContext *)pUserData;
int Ind = pResult->GetInteger(0);
char aIpBuf[64];
char aBuf[64];
int Index = pResult->GetInteger(0);
if (Ind < 0 || Ind >= MAX_MUTES || !m_aMutes[Ind].m_IP[0])
if(Index < 0 || Index >= pSelf->m_NumMutes)
return;
pSelf->m_NumMutes--;
pSelf->m_aMutes[Index] = pSelf->m_aMutes[pSelf->m_NumMutes];
str_format(aBuf, sizeof aBuf, "Unmuted %s" , m_aMutes[Ind].m_IP);
pSelf->Console()->PrintResponse(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
m_aMutes[Ind].m_IP[0] = 0;
net_addr_str(&pSelf->m_aMutes[Index].m_Addr, aIpBuf, sizeof(aIpBuf));
str_format(aBuf, sizeof(aBuf), "Unmuted %s" , aIpBuf);
pSelf->Console()->PrintResponse(IConsole::OUTPUT_LEVEL_STANDARD, "mutes", aBuf);
}
// list mutes
void CGameContext::ConMutes(IConsole::IResult *pResult, void *pUserData, int ClientID)
{
char aBuf[128];
CGameContext *pSelf = (CGameContext *)pUserData;
pSelf->Console()->PrintResponse(IConsole::OUTPUT_LEVEL_STANDARD, "server", "Active mutes:");
for(int z = 0; z < MAX_MUTES; ++z)
if (m_aMutes[z].m_IP[0])
{
int Exp = (m_aMutes[z].m_Expire - pSelf->Server()->Tick()) / pSelf->Server()->TickSpeed();
if (Exp > 0)
str_format(aBuf, sizeof aBuf, "%d: \"%s\", %d seconds left", z, m_aMutes[z].m_IP, Exp);
else
str_format(aBuf, sizeof aBuf, "%d: \"%s\", expired (pending)", z, m_aMutes[z].m_IP);
pSelf->Console()->PrintResponse(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
}
char aIpBuf[64];
char aBuf[128];
pSelf->Console()->PrintResponse(IConsole::OUTPUT_LEVEL_STANDARD, "mutes", "Active mutes:");
for(int i = 0; i < pSelf->m_NumMutes; i++)
{
net_addr_str(&pSelf->m_aMutes[i].m_Addr, aIpBuf, sizeof(aIpBuf));
str_format(aBuf, sizeof aBuf, "%d: \"%s\", %d seconds left", i, aIpBuf, (pSelf->m_aMutes[i].m_Expire - pSelf->Server()->Tick()) / pSelf->Server()->TickSpeed());
pSelf->Console()->PrintResponse(IConsole::OUTPUT_LEVEL_STANDARD, "mutes", aBuf);
}
}

View file

@ -27,8 +27,6 @@
#include "score/sql_score.h"
#endif
struct CMute CGameContext::m_aMutes[MAX_MUTES];
enum
{
RESET,
@ -51,9 +49,8 @@ void CGameContext::Construct(int Resetting)
if(Resetting==NO_RESET)
{
m_pVoteOptionHeap = new CHeap();
m_pScore = 0;
for(int z = 0; z < MAX_MUTES; ++z)
m_aMutes[z].m_IP[0] = 0;
m_pScore = 0;
m_NumMutes = 0;
}
}
@ -242,15 +239,48 @@ void CGameContext::SendChatTarget(int To, const char *pText)
}
int CGameContext::ProcessSpamProtection(int ClientID)
{
if(g_Config.m_SvSpamprotection && m_apPlayers[ClientID]->m_Last_Chat
&& m_apPlayers[ClientID]->m_Last_Chat + Server()->TickSpeed() + g_Config.m_SvChatDelay > Server()->Tick())
return 1;
else
m_apPlayers[ClientID]->m_Last_Chat = Server()->Tick();
NETADDR Addr;
Server()->GetClientAddr(ClientID, &Addr);
int Muted = 0;
for(int i = 0; i < m_NumMutes && !Muted; i++)
{
if(!net_addr_comp(&Addr, &m_aMutes[i].m_Addr))
Muted = (m_aMutes[i].m_Expire - Server()->Tick()) / Server()->TickSpeed();
}
if (Muted > 0)
{
char aBuf[128];
str_format(aBuf, sizeof aBuf, "You are not permitted to talk for the next %d seconds.", Muted);
SendChatTarget(ClientID, aBuf);
return 1;
}
if ((m_apPlayers[ClientID]->m_ChatScore += g_Config.m_SvChatPenalty) > g_Config.m_SvChatThreshold)
{
Mute(&Addr, g_Config.m_SvSpamMuteDuration, Server()->ClientName(ClientID));
m_apPlayers[ClientID]->m_ChatScore = 0;
return 1;
}
return 0;
}
void CGameContext::SendChat(int ChatterClientID, int Team, const char *pText, int SpamProtectionClientID)
{
if(SpamProtectionClientID >= 0 && SpamProtectionClientID < MAX_CLIENTS)
{
if(g_Config.m_SvSpamprotection && m_apPlayers[SpamProtectionClientID]->m_Last_Chat
&& m_apPlayers[SpamProtectionClientID]->m_Last_Chat + Server()->TickSpeed() + g_Config.m_SvChatDelay > Server()->Tick())
if(ProcessSpamProtection(SpamProtectionClientID))
return;
else
m_apPlayers[SpamProtectionClientID]->m_Last_Chat = Server()->Tick();
}
char aBuf[256], aText[256];
@ -545,34 +575,42 @@ void CGameContext::OnTick()
}
}
if(Server()->Tick() % (g_Config.m_SvAnnouncementInterval * Server()->TickSpeed() * 60) == 0)
{
char *Line = ((CServer *) Server())->GetAnnouncementLine(g_Config.m_SvAnnouncementFileName);
if(Line)
SendChat(-1, CGameContext::CHAT_ALL, Line);
}
if(Collision()->m_NumSwitchers > 0)
for (int i = 0; i < Collision()->m_NumSwitchers+1; ++i)
for(int i = 0; i < m_NumMutes; i++)
{
for (int j = 0; j < 16; ++j)
if(m_aMutes[i].m_Expire <= Server()->Tick())
{
if(Collision()->m_pSwitchers[i].m_EndTick[j] <= Server()->Tick() && Collision()->m_pSwitchers[i].m_Type[j] == TILE_SWITCHTIMEDOPEN)
{
Collision()->m_pSwitchers[i].m_Status[j] = false;
Collision()->m_pSwitchers[i].m_EndTick[j] = 0;
Collision()->m_pSwitchers[i].m_Type[j] = TILE_SWITCHCLOSE;
}
else if(Collision()->m_pSwitchers[i].m_EndTick[j] <= Server()->Tick() && Collision()->m_pSwitchers[i].m_Type[j] == TILE_SWITCHTIMEDCLOSE)
{
Collision()->m_pSwitchers[i].m_Status[j] = true;
Collision()->m_pSwitchers[i].m_EndTick[j] = 0;
Collision()->m_pSwitchers[i].m_Type[j] = TILE_SWITCHOPEN;
}
m_NumMutes--;
m_aMutes[i] = m_aMutes[m_NumMutes];
}
}
if(Server()->Tick() % (g_Config.m_SvAnnouncementInterval * Server()->TickSpeed() * 60) == 0)
{
char *Line = ((CServer *) Server())->GetAnnouncementLine(g_Config.m_SvAnnouncementFileName);
if(Line)
SendChat(-1, CGameContext::CHAT_ALL, Line);
}
if(Collision()->m_NumSwitchers > 0)
for (int i = 0; i < Collision()->m_NumSwitchers+1; ++i)
{
for (int j = 0; j < 16; ++j)
{
if(Collision()->m_pSwitchers[i].m_EndTick[j] <= Server()->Tick() && Collision()->m_pSwitchers[i].m_Type[j] == TILE_SWITCHTIMEDOPEN)
{
Collision()->m_pSwitchers[i].m_Status[j] = false;
Collision()->m_pSwitchers[i].m_EndTick[j] = 0;
Collision()->m_pSwitchers[i].m_Type[j] = TILE_SWITCHCLOSE;
}
else if(Collision()->m_pSwitchers[i].m_EndTick[j] <= Server()->Tick() && Collision()->m_pSwitchers[i].m_Type[j] == TILE_SWITCHTIMEDCLOSE)
{
Collision()->m_pSwitchers[i].m_Status[j] = true;
Collision()->m_pSwitchers[i].m_EndTick[j] = 0;
Collision()->m_pSwitchers[i].m_Type[j] = TILE_SWITCHOPEN;
}
}
}
#ifdef CONF_DEBUG
if(g_Config.m_DbgDummies)
{
@ -711,35 +749,6 @@ void CGameContext::OnMessage(int MsgId, CUnpacker *pUnpacker, int ClientID)
return;
}
char aIP[16];
int MuteTicks = 0;
Server()->GetClientIP(ClientID, aIP, sizeof aIP);
for(int z = 0; z < MAX_MUTES && MuteTicks <= 0; ++z) //find a mute, remove it, if expired.
if (m_aMutes[z].m_IP[0] && str_comp(aIP, m_aMutes[z].m_IP) == 0 && (MuteTicks = m_aMutes[z].m_Expire - Server()->Tick()) <= 0)
m_aMutes[z].m_IP[0] = 0;
if(pMsg->m_pMessage[0]!='/')
{
if (MuteTicks > 0)
{
char aBuf[128];
str_format(aBuf, sizeof aBuf, "You are not permitted to talk for the next %d seconds.", MuteTicks / Server()->TickSpeed());
SendChatTarget(ClientID, aBuf);
return;
}
if ((p->m_ChatScore += g_Config.m_SvChatPenalty) > g_Config.m_SvChatThreshold)
{
char aIP[16];
Server()->GetClientIP(ClientID, aIP, sizeof aIP);
Mute(aIP, g_Config.m_SvSpamMuteDuration, Server()->ClientName(ClientID));
p->m_ChatScore = 0;
return;
}
}
// check for invalid chars
unsigned char *pMessage = (unsigned char *)pMsg->m_pMessage;
while (*pMessage)

View file

@ -15,8 +15,6 @@
#include "player.h"
#include "score.h"
#define MAX_MUTES 32
/*
Tick
Game Context (CGameContext::tick)
@ -141,6 +139,7 @@ public:
void SendEmoticon(int ClientID, int Emoticon);
void SendWeaponPickup(int ClientID, int Weapon);
void SendBroadcast(const char *pText, int ClientID);
int ProcessSpamProtection(int ClientID);
//
@ -254,8 +253,20 @@ private:
static void ConUnmute(IConsole::IResult *pResult, void *pUserData, int ClientID);
static void ConMutes(IConsole::IResult *pResult, void *pUserData, int ClientID);
static struct CMute m_aMutes[MAX_MUTES];
void Mute(const char *pIP, int Secs, const char *pDisplayName);
enum
{
MAX_MUTES=32,
};
struct CMute
{
NETADDR m_Addr;
int m_Expire;
};
CMute m_aMutes[MAX_MUTES];
int m_NumMutes;
void Mute(NETADDR *Addr, int Secs, const char *pDisplayName);
public:
CLayers *Layers() { return &m_Layers; }
class IScore *Score() { return m_pScore; }
@ -278,11 +289,6 @@ public:
virtual bool PlayerHooking();
};
struct CMute {
char m_IP[16];// TODO ipv6
int m_Expire;
};
inline int CmaskAll() { return -1; }
inline int CmaskOne(int ClientID) { return 1<<ClientID; }
inline int CmaskAllExceptOne(int ClientID) { return 0x7fffffff^CmaskOne(ClientID); }