r2779 - in branches/nexuiz-2.0/data: . gfx qcsrc/server

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Wed Jul 4 08:45:56 EDT 2007


Author: div0
Date: 2007-07-04 08:45:56 -0400 (Wed, 04 Jul 2007)
New Revision: 2779

Added:
   branches/nexuiz-2.0/data/gfx/num_colon.tga
   branches/nexuiz-2.0/data/qcsrc/server/ipban.qc
   branches/nexuiz-2.0/data/qcsrc/server/ipban.qh
Modified:
   branches/nexuiz-2.0/data/default.cfg
   branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc
   branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc
   branches/nexuiz-2.0/data/qcsrc/server/defs.qh
   branches/nexuiz-2.0/data/qcsrc/server/extensions.qh
   branches/nexuiz-2.0/data/qcsrc/server/g_world.qc
   branches/nexuiz-2.0/data/qcsrc/server/gamecommand.qc
   branches/nexuiz-2.0/data/qcsrc/server/progs.src
Log:
IP banning!
Voting now displays who is going to be kicked/banned.
Voting now allows leaving out the space between # and the status number.


Modified: branches/nexuiz-2.0/data/default.cfg
===================================================================
--- branches/nexuiz-2.0/data/default.cfg	2007-06-30 21:20:08 UTC (rev 2778)
+++ branches/nexuiz-2.0/data/default.cfg	2007-07-04 12:45:56 UTC (rev 2779)
@@ -670,7 +670,7 @@
 
 con_chatwidth 0.6
 con_chat 5
-con_chatpos -7
+con_chatpos -8
 sbar_alpha_bg 0.4
 
 net_banlist ""
@@ -761,3 +761,11 @@
 
 // so it can be stuffcmd-ed still
 set cl_gravity 800 // but ignored anyway
+
+set g_ban_default_bantime 5400 // 90 minutes
+set g_ban_default_masksize 3   // whole 255.255.255.0 networks (set to 4 for single IPs)
+set g_banned_list ""           // format: 1 ip remainingtime ip remainingtime ...
+alias bans "sv_cmd bans $*"
+alias ban "sv_cmd ban $*"         // usage: ban address(maybe incomplete, like 1.2.3) bantime(seconds)
+alias kickban "sv_cmd kickban $*" // usage: kickban # playerno bantime(seconds) masksize(bytes)
+alias unban "sv_cmd unban $*"     // usage: unban 3 (number from bans)

Copied: branches/nexuiz-2.0/data/gfx/num_colon.tga (from rev 2773, trunk/data/gfx/num_colon.tga)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc	2007-06-30 21:20:08 UTC (rev 2778)
+++ branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc	2007-07-04 12:45:56 UTC (rev 2779)
@@ -605,6 +605,14 @@
 {
 	local string s;
 
+	if(Ban_IsClientBanned(self))
+	{
+		s = strcat("^1NOTE:^7 banned client ", self.netaddress, " just tried to enter\n");
+		dropclient(self);
+		bprint(s);
+		return;
+	}
+
 	self.classname = "player_joining";
 	self.flags = self.flags | FL_CLIENT;
 	self.version_nagtime = time + 10 + random() * 10;

Modified: branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc	2007-06-30 21:20:08 UTC (rev 2778)
+++ branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc	2007-07-04 12:45:56 UTC (rev 2779)
@@ -120,8 +120,47 @@
 	strunzone(msgstr);
 }
 
+string GetKickVoteVictim_newcommand;
+entity GetKickVoteVictim(string vote, string cmd)
+{
+	float tokens;
+	float i, n;
+	string ns;
+	entity e;
+
+	tokens = tokenize(vote);
+	ns = "";
+
+	if(tokens == 2)
+		if(substring(argv(1), 0, 1) == "#")
+			ns = substring(argv(1), 1, 999);
+	
+	if(tokens == 3)
+		if(argv(1) == "#")
+			ns = argv(2);
+
+	if(ns != "")
+	{
+		n = stof(ns);
+		if(ns == ftos(n)) if(n >= 1) if(n <= maxclients)
+		{
+			for((e = world), (i = 0); i < n; ++i, (e = nextent(e)))
+				;
+			if(clienttype(e) == CLIENTTYPE_REAL)
+			{
+				GetKickVoteVictim_newcommand = strcat(argv(0), " # ", ns);
+				return e;
+			}
+		}
+	}
+
+	sprint(self, strcat("Usage: ", cmd, " ", argv(0), " #playernumber (as in \"status\")\n"));
+	return world;
+}
+
 void SV_ParseClientCommand(string s) {
 	local string cmd;
+	local entity e;
 
 	tokenize(s);
 
@@ -151,7 +190,7 @@
 			sprint(self, strcat("^3", cvar_string("sv_vote_commands"), "^7 and maybe further ^3arguments^7\n"));
 		} else if(argv(1) == "status") {
 			if(votecalled) {
-				sprint(self, strcat("^7Vote for \"^1", votecalledvote, "^7\" called by \"^7", votecaller.netname, "^7\".\n"));
+				sprint(self, strcat("^7Vote for ", votecalledvote_display, "^7 called by ^7", votecaller.netname, "^7.\n"));
 			} else {
 				sprint(self, "^1No vote called.\n");
 			}
@@ -169,18 +208,29 @@
 					} else if(VoteAllowed(strcat1(argv(2)))) { // strcat seems to be necessary
 						if(!ValidateMap(vote))
 							return;
+						// remap chmap to gotomap (forces intermission)
+						if(substring(vote, 0, 6) == "chmap ")
+							vote = strcat("gotomap ", substring(vote, 6, strlen(vote) - 6));
+						// make kick and kickban votes a bit nicer (and reject them if formatted badly)
+						if(substring(vote, 0, 5) == "kick " || substring(vote, 0, 8) == "kickban ")
+						{
+							if(!(e = GetKickVoteVictim(vote, "vcall")))
+								return;
+							votecalledvote_display = strzone(strcat("^1", vote, " (^7", e.netname, "^1)"));
+							vote = GetKickVoteVictim_newcommand;
+						}
+						else
+						{
+							votecalledvote_display = strzone(strcat("^1", vote));
+						}
+						votecalledvote = strzone(vote);
 						votecalled = TRUE;
 						votecalledmaster = FALSE;
-						// remap chmap to gotomap (forces intermission)
-						if(strlen(vote) >= 6)
-							if(substring(vote, 0, 6) == "chmap ")
-								vote = strcat("gotomap ", substring(vote, 6, strlen(vote) - 6));
-						votecalledvote = strzone(vote);
 						votecaller = self; // remember who called the vote
 						votefinished = time + cvar("sv_vote_timeout");
 						votecaller.vote_vote = 1; // of course you vote yes
 						votecaller.vote_next = time + cvar("sv_vote_wait");
-						bprint("\{1}^2* ^3", votecaller.netname, "^2 calls a vote for ^1", votecalledvote, "\n");
+						bprint("\{1}^2* ^3", votecaller.netname, "^2 calls a vote for ", votecalledvote_display, "\n");
 						VoteCount(); // needed if you are the only one
 					} else {
 						sprint(self, "^1This vote is not ok. See help for more info.\n");
@@ -194,6 +244,8 @@
 				sprint(self, "^1No vote called.\n");
 			} else if(self == votecaller) { // the votecaller can stop a vote
 				VoteStop(self);
+			} else if(self.vote_master) { // masters can, too
+				VoteStop(self);
 			} else {
 				sprint(self, "^1You are not allowed to stop that Vote.\n");
 			}
@@ -204,7 +256,8 @@
 				} else {
 					votecalled = TRUE;
 					votecalledmaster = TRUE;
-					votecalledvote = strzone("^3master");
+					votecalledvote = strzone("XXX");
+					votecalledvote_display = strzone("^3master");
 					votecaller = self; // remember who called the vote
 					votefinished = time + cvar("sv_vote_timeout");
 					votecaller.vote_vote = 1; // of course you vote yes
@@ -231,7 +284,7 @@
 				else
 					sprint(self, "^1You are NOT a master.\n");
 			} else if(self.vote_master) {
-				local string dovote;
+				local string dovote, dovote_display;
 				dovote = VoteParse();
 				if(dovote == "") {
 					sprint(self, "^1Your command was empty. See help for more info.\n");
@@ -241,8 +294,16 @@
 					// remap chmap to gotomap (forces intermission)
 					if(strlen(dovote) >= 6)
 						if(substring(dovote, 0, 6) == "chmap ")
-							vote = strcat("gotomap ", substring(dovote, 6, strlen(dovote) - 6));
-					bprint("\{1}^2* ^3", self.netname, "^2 used his ^3master^2 status to do \"^2", dovote, "^2\".\n");
+							dovote = strcat("gotomap ", substring(dovote, 6, strlen(dovote) - 6));
+					dovote_display = dovote;
+					if(substring(dovote, 0, 5) == "kick " || substring(dovote, 0, 8) == "kickban ")
+					{
+						if(!(e = GetKickVoteVictim(dovote, "vdo")))
+							return;
+						dovote_display = strzone(strcat("^1", dovote, " (^7", e.netname, "^1)"));
+						dovote = GetKickVoteVictim_newcommand;
+					}
+					bprint("\{1}^2* ^3", self.netname, "^2 used his ^3master^2 status to do \"^2", dovote_display, "^2\".\n");
 					localcmd(strcat(dovote, "\n"));
 				} else {
 					sprint(self, "^1This command is not ok. See help for more info.\n");
@@ -519,13 +580,19 @@
 		centerprint_expire(player, CENTERPRIO_VOTE);
 	}
 
+	if(votecalled)
+	{
+		strunzone(votecalledvote);
+		strunzone(votecalledvote_display);
+	}
+
 	votecalled = FALSE;
 	votecalledmaster = FALSE;
 	votefinished = 0;
 }
 
 void VoteAccept() {
-	bprint("\{1}^2* ^3", votecaller.netname, "^2's vote for ^1", votecalledvote, "^2 was accepted\n");
+	bprint("\{1}^2* ^3", votecaller.netname, "^2's vote for ^1", votecalledvote_display, "^2 was accepted\n");
 	if(votecalledmaster)
 	{
 		votecaller.vote_master = 1;
@@ -537,12 +604,12 @@
 }
 
 void VoteReject() {
-	bprint("\{1}^2* ^3", votecaller.netname, "^2's vote for ^1", votecalledvote, "^2 was rejected\n");
+	bprint("\{1}^2* ^3", votecaller.netname, "^2's vote for ", votecalledvote_display, "^2 was rejected\n");
 	VoteReset();
 }
 
 void VoteTimeout() {
-	bprint("\{1}^2* ^3", votecaller.netname, "^2's vote for ^1", votecalledvote, "^2 timed out\n");
+	bprint("\{1}^2* ^3", votecaller.netname, "^2's vote for ", votecalledvote_display, "^2 timed out\n");
 	VoteReset();
 }
 
@@ -558,7 +625,7 @@
 void VoteNag() {
 	if(votecalled)
 		if(self.vote_vote == 0)
-			centerprint_atprio(self, CENTERPRIO_VOTE, strcat("^7^3", votecaller.netname, "^2 called a vote for ^1", votecalledvote, "\n\n^2You have not voted yet!\n^2HINT: By default, F1 is yes and F2 is no."));
+			centerprint_atprio(self, CENTERPRIO_VOTE, strcat("^7^3", votecaller.netname, "^2 called a vote for ", votecalledvote_display, "\n\n^2You have not voted yet!\n^2HINT: By default, F1 is yes and F2 is no."));
 }
 
 void VoteCount() {

Modified: branches/nexuiz-2.0/data/qcsrc/server/defs.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/defs.qh	2007-06-30 21:20:08 UTC (rev 2778)
+++ branches/nexuiz-2.0/data/qcsrc/server/defs.qh	2007-07-04 12:45:56 UTC (rev 2779)
@@ -186,6 +186,7 @@
 // stahl's voting
 float votecalled;
 string votecalledvote;
+string votecalledvote_display;
 float votecalledmaster;
 entity votecaller;
 float votefinished;

Modified: branches/nexuiz-2.0/data/qcsrc/server/extensions.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/extensions.qh	2007-06-30 21:20:08 UTC (rev 2778)
+++ branches/nexuiz-2.0/data/qcsrc/server/extensions.qh	2007-07-04 12:45:56 UTC (rev 2779)
@@ -1455,3 +1455,5 @@
 //sv_stepheight (default 18)
 //description:
 //sv_jumpstep allows stepping up onto stairs while airborn, sv_stepheight controls how high a single step can be.
+
+.string netaddress; // TODO make this a full block

Modified: branches/nexuiz-2.0/data/qcsrc/server/g_world.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_world.qc	2007-06-30 21:20:08 UTC (rev 2778)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_world.qc	2007-07-04 12:45:56 UTC (rev 2779)
@@ -345,6 +345,8 @@
 	fteqcc_testbugs();
 
 	readlevelcvars();
+
+	Ban_LoadBans();
 }
 
 void light (void)
@@ -511,6 +513,8 @@
 		localcmd(strcat("exec \"", exit_cfg, "\"\n"));
 
 	localcmd("exec game_reset.cfg\n");
+
+	Ban_SaveBans();
 };
 
 void() Map_Goto =
@@ -653,6 +657,8 @@
 
 float() DoNextMapOverride =
 {
+	Ban_SaveBans();
+
 	if(cvar("g_campaign"))
 	{
 		CampaignPostIntermission();

Modified: branches/nexuiz-2.0/data/qcsrc/server/gamecommand.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/gamecommand.qc	2007-06-30 21:20:08 UTC (rev 2778)
+++ branches/nexuiz-2.0/data/qcsrc/server/gamecommand.qc	2007-07-04 12:45:56 UTC (rev 2779)
@@ -9,10 +9,14 @@
 		print("  adminmsg clientnumber \"message\"\n");
 		print("  teamstatus\n");
 		print("  printstats\n");
+		GameCommand_Ban("help");
 		GameCommand_Generic("help");
 		return;
 	}
 
+	if(GameCommand_Ban(command))
+		return;
+
 	if(GameCommand_Generic(command))
 		return;
 

Copied: branches/nexuiz-2.0/data/qcsrc/server/ipban.qc (from rev 2774, trunk/data/qcsrc/server/ipban.qc)
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/ipban.qc	                        (rev 0)
+++ branches/nexuiz-2.0/data/qcsrc/server/ipban.qc	2007-07-04 12:45:56 UTC (rev 2779)
@@ -0,0 +1,257 @@
+#define BAN_MAX 64
+float ban_loaded;
+string ban_ip[BAN_MAX];
+float ban_expire[BAN_MAX];
+float ban_count;
+
+string ban_ip1;
+string ban_ip2;
+string ban_ip3;
+string ban_ip4;
+
+void Ban_SaveBans()
+{
+	string out;
+	float i;
+
+	if(!ban_loaded)
+		return;
+
+	// version of list
+	out = "1";
+	for(i = 0; i < ban_count; ++i)
+	{
+		if(time > ban_expire[i])
+			continue;
+		out = strcat(out, " ", ban_ip[i]);
+		out = strcat(out, " ", ftos(ban_expire[i] - time));
+	}
+	if(strlen(out) <= 1) // no real entries
+		cvar_set("g_banned_list", "");
+	else
+		cvar_set("g_banned_list", out);
+}
+
+float Ban_Delete(float i)
+{
+	if(i < 0)
+		return FALSE;
+	if(i >= ban_count)
+		return FALSE;
+	if(ban_expire[i] == 0)
+		return FALSE;
+	if(ban_expire[i] > 0)
+		strunzone(ban_ip[i]);
+	ban_expire[i] = 0;
+	ban_ip[i] = "";
+	Ban_SaveBans();
+	return TRUE;
+}
+
+void Ban_LoadBans()
+{
+	float i, n;
+	for(i = 0; i < ban_count; ++i)
+		Ban_Delete(i);
+	ban_count = 0;
+	ban_loaded = TRUE;
+	n = tokenize(cvar_string("g_banned_list"));
+	if(stof(argv(0)) == 1)
+	{
+		ban_count = (n - 1) / 2;
+		for(i = 0; i < ban_count; ++i)
+		{
+			ban_ip[i] = strzone(argv(2*i+1));
+			ban_expire[i] = time + stof(argv(2*i+2));
+		}
+	}
+}
+
+void Ban_View()
+{
+	float i;
+	string msg;
+	for(i = 0; i < ban_count; ++i)
+	{
+		if(time > ban_expire[i])
+			continue;
+		msg = strcat("#", ftos(i), ": ");
+		msg = strcat(msg, ban_ip[i], " is still banned for ");
+		msg = strcat(msg, ftos(ban_expire[i] - time), " seconds");
+		ServerConsoleEcho(msg, FALSE);
+	}
+}
+
+float Ban_GetClientIP(entity client)
+{
+	float n;
+	n = tokenizebyseparator(client.netaddress, ".");
+	if(n != 4)
+		return FALSE;
+	ban_ip1 = strcat1(argv(0));
+	ban_ip2 = strcat(ban_ip1, ".", argv(1));
+	ban_ip3 = strcat(ban_ip2, ".", argv(2));
+	ban_ip4 = strcat(ban_ip3, ".", argv(3));
+	return TRUE;
+}
+
+float Ban_IsClientBanned(entity client)
+{
+	float i;
+	if(!ban_loaded)
+		Ban_LoadBans();
+	if(!Ban_GetClientIP(client))
+		return FALSE;
+	for(i = 0; i < ban_count; ++i)
+	{
+		string s;
+		if(time > ban_expire[i])
+			continue;
+		s = ban_ip[i];
+		if(ban_ip1 == s) return TRUE;
+		if(ban_ip2 == s) return TRUE;
+		if(ban_ip3 == s) return TRUE;
+		if(ban_ip4 == s) return TRUE;
+	}
+	return FALSE;
+}
+
+float Ban_Insert(string ip, float bantime)
+{
+	float i;
+	float j;
+	float bestscore;
+	// already banned?
+	for(i = 0; i < ban_count; ++i)
+		if(ban_ip[i] == ip)
+			return FALSE;
+	// do we have a free slot?
+	for(i = 0; i < ban_count; ++i)
+		if(time > ban_expire[i])
+			break;
+	// no free slot? Then look for the one who would get unbanned next
+	if(i >= BAN_MAX)
+	{
+		i = 0;
+		bestscore = ban_expire[i];
+		for(j = 1; j < ban_count; ++j)
+		{
+			if(ban_expire[j] < bestscore)
+			{
+				i = j;
+				bestscore = ban_expire[i];
+			}
+		}
+	}
+	// if we replace someone, will we be banned longer than him (so long-term
+	// bans never get overridden by short-term bans)
+	if(ban_expire[i] > time + bantime)
+		return FALSE;
+	// okay, insert our new victim as i
+	Ban_Delete(i);
+	ServerConsoleEcho(strcat(ip, " has been banned for ", ftos(bantime), " seconds"), FALSE);
+	ban_expire[i] = time + bantime;
+	ban_ip[i] = strzone(ip);
+	ban_count = max(ban_count, i + 1);
+
+	Ban_SaveBans();
+
+	return TRUE;
+}
+
+void Ban_KickBanClient(entity client, float bantime, float masksize)
+{
+	if(!Ban_GetClientIP(client))
+	{
+		dropclient(client);
+		return;
+	}
+	// now ban him
+	switch(masksize)
+	{
+		case 1:
+			Ban_Insert(ban_ip1, bantime);
+			break;
+		case 2:
+			Ban_Insert(ban_ip2, bantime);
+			break;
+		case 3:
+			Ban_Insert(ban_ip3, bantime);
+			break;
+		default:
+			Ban_Insert(ban_ip4, bantime);
+			break;
+	}
+	// and kick him
+	dropclient(client);
+}
+
+float GameCommand_Ban(string command)
+{
+	float argc;
+	float bantime;
+	entity client;
+	float entno;
+	float masksize;
+
+	argc = tokenize(command);
+	if(argv(0) == "help")
+	{
+		print("  kickban # n m p - kickban player n for m seconds, using mask size p (1 to 4)\n");
+		print("  ban ip m - ban an IP or range (incomplete IP, like 1.2.3) for m seconds\n");
+		print("  bans - list all existing bans\n");
+		print("  unban n - delete the entry #n from the bans list\n");
+		return TRUE;
+	}
+	if(argv(0) == "kickban")
+	{
+		if(argc >= 3)
+		{
+			entno = stof(argv(2));
+			if(entno > maxclients || entno < 1)
+				return TRUE;
+			for(client = world; entno > 0; --entno, client = nextent(client))
+				;
+			if(argc >= 4)
+				bantime = stof(argv(3));
+			else
+				bantime = cvar("g_ban_default_bantime");
+			if(argc >= 5)
+				masksize = stof(argv(4));
+			else
+				masksize = cvar("g_ban_default_masksize");
+			Ban_KickBanClient(client, bantime, masksize);
+			return TRUE;
+		}
+	}
+	else if(argv(0) == "ban")
+	{
+		if(argc >= 2)
+		{
+			string ip;
+			ip = argv(1);
+			if(argc >= 3)
+				bantime = stof(argv(2));
+			else
+				bantime = cvar("g_ban_default_bantime");
+			Ban_Insert(ip, bantime);
+			return TRUE;
+		}
+	}
+	else if(argv(0) == "bans")
+	{
+		Ban_View();
+		return TRUE;
+	}
+	else if(argv(0) == "unban")
+	{
+		if(argc >= 2)
+		{
+			float who;
+			who = stof(argv(1));
+			Ban_Delete(who);
+			return TRUE;
+		}
+	}
+	return FALSE;
+}

Copied: branches/nexuiz-2.0/data/qcsrc/server/ipban.qh (from rev 2774, trunk/data/qcsrc/server/ipban.qh)
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/ipban.qh	                        (rev 0)
+++ branches/nexuiz-2.0/data/qcsrc/server/ipban.qh	2007-07-04 12:45:56 UTC (rev 2779)
@@ -0,0 +1,4 @@
+void Ban_SaveBans();
+void Ban_LoadBans();
+float Ban_IsClientBanned(entity client);
+float GameCommand_Ban(string command);

Modified: branches/nexuiz-2.0/data/qcsrc/server/progs.src
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/progs.src	2007-06-30 21:20:08 UTC (rev 2778)
+++ branches/nexuiz-2.0/data/qcsrc/server/progs.src	2007-07-04 12:45:56 UTC (rev 2779)
@@ -12,6 +12,8 @@
 ../common/util.qh
 ../common/util.qc
 
+ipban.qh
+
 keyhunt.qh
 
 miscfunctions.qc
@@ -88,3 +90,5 @@
 gamecommand.qc
 
 keyhunt.qc
+
+ipban.qc




More information about the nexuiz-commits mailing list