about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/engine/server.h2
-rw-r--r--src/engine/server/server.cpp176
-rw-r--r--src/engine/server/server.h27
-rw-r--r--src/game/server/gamecontext.cpp65
-rw-r--r--src/game/server/gamecontext.h4
-rw-r--r--src/game/server/player.h3
6 files changed, 208 insertions, 69 deletions
diff --git a/src/engine/server.h b/src/engine/server.h
index deb36ef5..7896f911 100644
--- a/src/engine/server.h
+++ b/src/engine/server.h
@@ -1,5 +1,6 @@
 /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
 /* If you are missing that file, acquire a complete release at teeworlds.com.                */
+/* Modified by Teelevision for zCatch/TeeVi, see readme.txt and license.txt.                 */
 #ifndef ENGINE_SERVER_H
 #define ENGINE_SERVER_H
 #include "kernel.h"
@@ -32,6 +33,7 @@ public:
 	virtual bool ClientIngame(int ClientID) = 0;
 	virtual int GetClientInfo(int ClientID, CClientInfo *pInfo) = 0;
 	virtual void GetClientAddr(int ClientID, char *pAddrStr, int Size) = 0;
+	virtual int ClientVotebannedTime(int ClientID) = 0;
 
 	virtual int SendMsg(CMsgPacker *pMsg, int Flags, int ClientID) = 0;
 
diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp
index 4be9809b..766c4553 100644
--- a/src/engine/server/server.cpp
+++ b/src/engine/server/server.cpp
@@ -304,9 +304,22 @@ CServer::CServer() : m_DemoRecorder(&m_SnapshotDelta)
 	// when starting there are no admins
 	numLoggedInAdmins = 0;
 	
+	m_Votebans = NULL;
+	
 	Init();
 }
 
+CServer::~CServer()
+{
+	// delte votebans
+	while(m_Votebans != NULL)
+	{
+		CVoteban *tmp = m_Votebans->m_Next;
+		delete m_Votebans;
+		m_Votebans = tmp;
+	}
+}
+
 
 int CServer::TrySetClientName(int ClientID, const char *pName)
 {
@@ -445,6 +458,7 @@ int CServer::Init()
 		m_aClients[i].m_Snapshots.Init();
 	}
 
+	AdjustVotebanTime(m_CurrentGameTick);
 	m_CurrentGameTick = 0;
 
 	return 0;
@@ -1357,6 +1371,7 @@ int CServer::Run()
 					}
 
 					m_GameStartTime = time_get();
+					AdjustVotebanTime(m_CurrentGameTick);
 					m_CurrentGameTick = 0;
 					Kernel()->ReregisterInterface(GameServer());
 					GameServer()->OnInit();
@@ -1454,6 +1469,163 @@ int CServer::Run()
 	return 0;
 }
 
+// returns the time in seconds that the client is votebanned or 0 if he isn't
+int CServer::ClientVotebannedTime(int ClientID)
+{
+	CVoteban **v = IsVotebannedAddr(m_NetServer.ClientAddr(ClientID));
+	if(v != NULL && (*v)->m_Expire > Tick())
+		return ((*v)->m_Expire - Tick()) / TickSpeed();
+	return 0;
+}
+
+// decreases the time of all votebans by the given offset of ticks
+void CServer::AdjustVotebanTime(int offset)
+{
+	CleanVotebans();
+	CVoteban *v = m_Votebans;
+	while(v != NULL)
+	{
+		v->m_Expire -= offset;
+		v = v->m_Next;
+	}
+}
+
+// adds a new voteban for a specific address
+void CServer::AddVotebanAddr(const NETADDR *addr, int expire)
+{
+	CVoteban **v = IsVotebannedAddr(addr);
+	// create new
+	if(!v)
+	{
+		CVoteban *v = new CVoteban;
+		v->m_Addr = *addr;
+		v->m_Expire = expire;
+		// insert front
+		v->m_Next = m_Votebans;
+		m_Votebans = v;
+	}
+	// update existing entry
+	else
+		(*v)->m_Expire = expire;
+}
+
+// adds a new voteban for a client's address
+void CServer::AddVoteban(int ClientID, int time)
+{
+	int expire = Tick() + time * TickSpeed();
+	AddVotebanAddr(m_NetServer.ClientAddr(ClientID), expire);
+}
+
+// removes a voteban from a client's address
+void CServer::RemoveVoteban(int ClientID)
+{
+	RemoveVotebanAddr(m_NetServer.ClientAddr(ClientID));
+}
+
+// removes a voteban on an address
+void CServer::RemoveVotebanAddr(const NETADDR *addr)
+{
+	CVoteban **v = IsVotebannedAddr(addr);
+	if(*v != NULL)
+	{
+		CVoteban *next = (*v)->m_Next;
+		delete *v;
+		*v = next;
+	}
+}
+
+// returns the voteban with the given address if it exists
+CServer::CVoteban **CServer::IsVotebannedAddr(const NETADDR *addr)
+{
+	CVoteban **v = &m_Votebans;
+	while(*v != NULL)
+	{
+		// only check ip-type and ip, not port
+		if((*v)->m_Addr.type == addr->type && !mem_comp(&(*v)->m_Addr.ip, &addr->ip, sizeof(unsigned char[16])))
+			return v;
+		v = &(*v)->m_Next;
+	}
+	return NULL;
+}
+
+// removes expired votebans
+void CServer::CleanVotebans()
+{
+	CVoteban **v = &m_Votebans;
+	while(*v != NULL)
+	{
+		if((*v)->m_Expire <= Tick())
+		{
+			CVoteban *next = (*v)->m_Next;
+			delete *v;
+			*v = next;
+		}
+		else
+			v = &(*v)->m_Next;
+	}
+}
+
+void CServer::ConVoteban(IConsole::IResult *pResult, void *pUser)
+{
+	CServer* pThis = static_cast<CServer *>(pUser);
+	int ClientID = pResult->GetInteger(0);
+	if(ClientID < 0 || ClientID >= MAX_CLIENTS || pThis->m_aClients[ClientID].m_State == CServer::CClient::STATE_EMPTY)
+	{
+		pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", "Invalid ClientID");
+		return;
+	}
+	int time = (pResult->NumArguments() > 1) ? pResult->GetInteger(1) : 300;
+	pThis->AddVoteban(ClientID, time);
+	// message to console and chat
+	char aBuf[128];
+	str_format(aBuf, sizeof(aBuf), "%s has been votebanned for %d:%02d min.", pThis->ClientName(ClientID), time/60, time%60);
+	pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf);
+	// pSelf->SendChatTarget(-1, aBuf);
+}
+
+void CServer::ConUnvoteban(IConsole::IResult *pResult, void *pUser)
+{
+	CServer* pThis = static_cast<CServer *>(pUser);
+	int ClientID = pResult->GetInteger(0);
+	if(ClientID < 0 || ClientID >= MAX_CLIENTS || pThis->m_aClients[ClientID].m_State == CServer::CClient::STATE_EMPTY)
+	{
+		pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", "Invalid ClientID");
+		return;
+	}
+	pThis->RemoveVoteban(ClientID);
+	// message to console
+	char aBuf[128];
+	str_format(aBuf, sizeof(aBuf), "%s has been un-votebanned.", pThis->ClientName(ClientID));
+	pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf);
+}
+
+void CServer::ConVotebans(IConsole::IResult *pResult, void *pUser)
+{
+	CServer* pThis = static_cast<CServer *>(pUser);
+	char aBuf[128];
+	char aAddrStr[NETADDR_MAXSTRSIZE];
+	int time;
+	int count = 0;
+	
+	pThis->CleanVotebans();
+	CVoteban *v = pThis->m_Votebans;
+	NETADDR addr;
+	while(v != NULL)
+	{
+		addr.type = v->m_Addr.type;
+		mem_copy(addr.ip, v->m_Addr.ip, sizeof(unsigned char[16]));
+		net_addr_str(&addr, aAddrStr, sizeof(aAddrStr), false);
+		time = (v->m_Expire - pThis->Tick()) / pThis->TickSpeed();
+		str_format(aBuf, sizeof(aBuf), "addr=%s time=%d:%02d min", aAddrStr, time/60, time%60);
+		pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf);
+		count++;
+		v = v->m_Next;
+	}
+	
+	str_format(aBuf, sizeof(aBuf), "%d votebanned ip(s)", count);
+	pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf);
+}
+
 void CServer::ConKick(IConsole::IResult *pResult, void *pUser)
 {
 	if(pResult->NumArguments() > 1)
@@ -1652,6 +1824,10 @@ void CServer::RegisterCommands()
 	Console()->Chain("sv_max_clients_per_ip", ConchainMaxclientsperipUpdate, this);
 	Console()->Chain("mod_command", ConchainModCommandUpdate, this);
 	Console()->Chain("console_output_level", ConchainConsoleOutputLevelUpdate, this);
+	
+	Console()->Register("voteban", "i?i", CFGFLAG_SERVER, ConVoteban, this, "Voteban a player by id");
+	Console()->Register("unvoteban", "i", CFGFLAG_SERVER, ConUnvoteban, this, "Remove voteban on player by id");
+	Console()->Register("votebans", "", CFGFLAG_SERVER, ConVotebans, this, "Show all votebans");
 
 	// register console commands in sub parts
 	m_ServerBan.InitServerBan(Console(), Storage(), this);
diff --git a/src/engine/server/server.h b/src/engine/server/server.h
index 0d14d53e..3fb3bfb3 100644
--- a/src/engine/server/server.h
+++ b/src/engine/server/server.h
@@ -170,6 +170,7 @@ public:
 	CMapChecker m_MapChecker;
 
 	CServer();
+	~CServer();
 
 	int TrySetClientName(int ClientID, const char *pName);
 
@@ -251,6 +252,32 @@ public:
 	
 	//zCatch
 	virtual void MapReload();
+	
+	// voteban system
+	// struct CVotebanAddr
+	// {
+		// unsigned char ip[16];
+		// unsigned int type;
+	// };
+	struct CVoteban
+	{
+		// CVotebanAddr m_Addr;
+		NETADDR m_Addr;
+		int m_Expire;
+		CVoteban *m_Next;
+	};
+	CVoteban *m_Votebans;
+	int ClientVotebannedTime(int ClientID);
+	void AdjustVotebanTime(int offset);
+	void AddVotebanAddr(const NETADDR *addr, int expire);
+	void AddVoteban(int ClientID, int time);
+	void RemoveVoteban(int ClientID);
+	void RemoveVotebanAddr(const NETADDR *addr);
+	CVoteban **IsVotebannedAddr(const NETADDR *addr);
+	void CleanVotebans();
+	static void ConVoteban(IConsole::IResult *pResult, void *pUser);
+	static void ConUnvoteban(IConsole::IResult *pResult, void *pUser);
+	static void ConVotebans(IConsole::IResult *pResult, void *pUser);
 };
 
 #endif
diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp
index 226f9133..1160d56e 100644
--- a/src/game/server/gamecontext.cpp
+++ b/src/game/server/gamecontext.cpp
@@ -775,10 +775,10 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
 		char aChatmsg[512];
 		
 		// check voteban
-		if(pPlayer->m_VoteBannedUntilTick > Server()->Tick())
+		int left = Server()->ClientVotebannedTime(ClientID);
+		if(left)
 		{
-			int left = (pPlayer->m_VoteBannedUntilTick - Server()->Tick()) / Server()->TickSpeed();
-			str_format(aChatmsg, sizeof(aChatmsg), "You must wait %d:%02d min until you are allowed to vote again.", left/60, left%60);
+			str_format(aChatmsg, sizeof(aChatmsg), "You are not allowed to vote for the next %d:%02d min.", left/60, left%60);
 			SendChatTarget(ClientID, aChatmsg);
 			return;
 		}
@@ -1695,61 +1695,6 @@ void CGameContext::ConUnmuteIP(IConsole::IResult *pResult, void *pUserData)
 	}
 }
 
-void CGameContext::ConVoteban(IConsole::IResult *pResult, void *pUserData)
-{
-	CGameContext *pSelf = (CGameContext *)pUserData;
-	char aBuf[128];
-	int CID = pResult->GetInteger(0);
-	if(CID < 0 || CID >= MAX_CLIENTS || !pSelf->m_apPlayers[CID])
-	{
-		pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", "Invalid ClientID");
-		return;
-	}
-	int time = (pResult->NumArguments() > 1) ? pResult->GetInteger(1) : 300;
-	pSelf->m_apPlayers[CID]->m_VoteBannedUntilTick = pSelf->Server()->Tick() + time * pSelf->Server()->TickSpeed();
-	str_format(aBuf, sizeof(aBuf), "%s has been votebanned for %d:%02d min.", pSelf->Server()->ClientName(CID), time/60, time%60);
-	pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf);
-	pSelf->SendChatTarget(-1, aBuf);
-}
-
-void CGameContext::ConUnvoteban(IConsole::IResult *pResult, void *pUserData)
-{
-	CGameContext *pSelf = (CGameContext *)pUserData;
-	char aBuf[128];
-	int CID = pResult->GetInteger(0);
-	if(CID < 0 || CID >= MAX_CLIENTS || !pSelf->m_apPlayers[CID])
-	{
-		pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", "Invalid ClientID");
-		return;
-	}
-	pSelf->m_apPlayers[CID]->m_VoteBannedUntilTick = 0;
-	str_format(aBuf, sizeof(aBuf), "%s has been un-votebanned.", pSelf->Server()->ClientName(CID));
-	pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf);
-}
-
-void CGameContext::ConVotebans(IConsole::IResult *pResult, void *pUserData)
-{
-	CGameContext *pSelf = (CGameContext *)pUserData;
-	char aBuf[128];
-	char aAddrStr[NETADDR_MAXSTRSIZE];
-	int time;
-	int count = 0;
-	
-	for(int i = 0; i < MAX_CLIENTS; i++)
-	{
-		if(pSelf->m_apPlayers[i] && pSelf->m_apPlayers[i]->m_VoteBannedUntilTick > pSelf->Server()->Tick())
-		{
-			pSelf->Server()->GetClientAddr(i, aAddrStr, sizeof(aAddrStr));
-			time = (pSelf->m_apPlayers[i]->m_VoteBannedUntilTick - pSelf->Server()->Tick()) / pSelf->Server()->TickSpeed();
-			str_format(aBuf, sizeof(aBuf), "id=%d addr=%s name='%s' time=%d:%02d min", i, aAddrStr, pSelf->Server()->ClientName(i), time/60, time%60);
-			pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf);
-			count++;
-		}
-	}
-	str_format(aBuf, sizeof(aBuf), "%d voteban(s)", count);
-	pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf);
-}
-
 void CGameContext::OnConsoleInit()
 {
 	m_pServer = Kernel()->RequestInterface<IServer>();
@@ -1781,10 +1726,6 @@ void CGameContext::OnConsoleInit()
 	Console()->Register("unmuteid", "i", CFGFLAG_SERVER, ConUnmuteID, this, "Unmutes a player by its client id");
 	Console()->Register("unmuteip", "i", CFGFLAG_SERVER, ConUnmuteIP, this, "Removes a mute by its index");
 	Console()->Register("mutes", "", CFGFLAG_SERVER, ConMutes, this, "Show all mutes");
-	
-	Console()->Register("voteban", "i?i", CFGFLAG_SERVER, ConVoteban, this, "Voteban a player by id");
-	Console()->Register("unvoteban", "i", CFGFLAG_SERVER, ConUnvoteban, this, "Remove voteban on player by id");
-	Console()->Register("votebans", "", CFGFLAG_SERVER, ConVotebans, this, "Show all votebans");
 		
 	Console()->Chain("sv_motd", ConchainSpecialMotdupdate, this);
 }
diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h
index 6a0fd8f9..5d340613 100644
--- a/src/game/server/gamecontext.h
+++ b/src/game/server/gamecontext.h
@@ -72,10 +72,6 @@ class CGameContext : public IGameServer
 	static void ConUnmuteID(IConsole::IResult *pResult, void *pUserData);
 	static void ConUnmuteIP(IConsole::IResult *pResult, void *pUserData);
 	static void ConMutes(IConsole::IResult *pResult, void *pUserData);
-	
-	static void ConVoteban(IConsole::IResult *pResult, void *pUserData);
-	static void ConUnvoteban(IConsole::IResult *pResult, void *pUserData);
-	static void ConVotebans(IConsole::IResult *pResult, void *pUserData);
 
 	CGameContext(int Resetting);
 	void Construct(int Resetting);
diff --git a/src/game/server/player.h b/src/game/server/player.h
index b7b863d6..a19209a8 100644
--- a/src/game/server/player.h
+++ b/src/game/server/player.h
@@ -114,9 +114,6 @@ public:
 	int m_CampTick;
 	vec2 m_CampPos;
 	
-	// voteban system
-	int m_VoteBannedUntilTick;
-	
 private:
 	CCharacter *m_pCharacter;
 	CGameContext *m_pGameServer;