From 17f75903b029bbf01217153dc98009d305137c8f Mon Sep 17 00:00:00 2001
From: James R <justsomejames2@gmail.com>
Date: Mon, 31 Aug 2020 20:08:22 -0700
Subject: [PATCH] Don't let players change their name more than five times per
 minute

---
 src/d_clisrv.c |  4 ++++
 src/d_clisrv.h |  4 ++++
 src/d_netcmd.c | 37 +++++++++++++++++++++++++++++++------
 src/g_game.c   |  7 +++++++
 src/g_game.h   |  1 +
 5 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index dd0c0e507..8b3e1abca 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -3024,6 +3024,8 @@ void CL_RemovePlayer(INT32 playernum, INT32 reason)
 	// Reset the name
 	sprintf(player_names[playernum], "Player %d", playernum+1);
 
+	player_name_changes[playernum] = 0;
+
 	if (IsPlayerAdmin(playernum))
 	{
 		RemoveAdminPlayer(playernum); // don't stay admin after you're gone
@@ -3692,6 +3694,8 @@ void SV_ResetServer(void)
 		adminplayers[i] = -1; // Populate the entire adminplayers array with -1.
 	}
 
+	memset(player_name_changes, 0, sizeof player_name_changes);
+
 	mynode = 0;
 	cl_packetmissed = false;
 
diff --git a/src/d_clisrv.h b/src/d_clisrv.h
index d750fb6cf..4bb795c9d 100644
--- a/src/d_clisrv.h
+++ b/src/d_clisrv.h
@@ -536,6 +536,10 @@ typedef enum
 
 } kickreason_t;
 
+/* the max number of name changes in some time period */
+#define MAXNAMECHANGES (5)
+#define NAMECHANGERATE (60*TICRATE)
+
 extern boolean server;
 extern boolean serverrunning;
 #define client (!server)
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index e524fb2c8..4a90de333 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -1218,6 +1218,8 @@ static void SetPlayerName(INT32 playernum, char *newname)
 			if (netgame)
 				HU_AddChatText(va("\x82*%s renamed to %s", player_names[playernum], newname), false);
 
+			player_name_changes[playernum]++;
+
 			strcpy(player_names[playernum], newname);
 			demo_extradata[playernum] |= DXD_NAME;
 		}
@@ -1399,7 +1401,12 @@ static void SendNameAndColor(void)
 	snacpending++;
 
 	// Don't change name if muted
-	if (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer)))
+	if (player_name_changes[consoleplayer] >= MAXNAMECHANGES)
+	{
+		CV_StealthSet(&cv_playername, player_names[consoleplayer]);
+		HU_AddChatText("\x85*You must wait to change your name again", false);
+	}
+	else if (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer)))
 		CV_StealthSet(&cv_playername, player_names[consoleplayer]);
 	else // Cleanup name if changing it
 		CleanupPlayerName(consoleplayer, cv_playername.zstring);
@@ -1523,7 +1530,12 @@ static void SendNameAndColor2(void)
 	snac2pending++;
 
 	// Don't change name if muted
-	if (cv_mute.value && !(server || IsPlayerAdmin(displayplayers[1])))
+	if (player_name_changes[displayplayers[1]] >= MAXNAMECHANGES)
+	{
+		CV_StealthSet(&cv_playername2, player_names[displayplayers[1]]);
+		HU_AddChatText("\x85*You must wait to change your name again", false);
+	}
+	else if (cv_mute.value && !(server || IsPlayerAdmin(displayplayers[1])))
 		CV_StealthSet(&cv_playername2, player_names[displayplayers[1]]);
 	else // Cleanup name if changing it
 		CleanupPlayerName(displayplayers[1], cv_playername2.zstring);
@@ -1638,7 +1650,12 @@ static void SendNameAndColor3(void)
 	snac3pending++;
 
 	// Don't change name if muted
-	if (cv_mute.value && !(server || IsPlayerAdmin(displayplayers[2])))
+	if (player_name_changes[displayplayers[2]] >= MAXNAMECHANGES)
+	{
+		CV_StealthSet(&cv_playername3, player_names[displayplayers[2]]);
+		HU_AddChatText("\x85*You must wait to change your name again", false);
+	}
+	else if (cv_mute.value && !(server || IsPlayerAdmin(displayplayers[2])))
 		CV_StealthSet(&cv_playername3, player_names[displayplayers[2]]);
 	else // Cleanup name if changing it
 		CleanupPlayerName(displayplayers[2], cv_playername3.zstring);
@@ -1761,7 +1778,12 @@ static void SendNameAndColor4(void)
 	snac4pending++;
 
 	// Don't change name if muted
-	if (cv_mute.value && !(server || IsPlayerAdmin(displayplayers[3])))
+	if (player_name_changes[displayplayers[3]] >= MAXNAMECHANGES)
+	{
+		CV_StealthSet(&cv_playername4, player_names[displayplayers[3]]);
+		HU_AddChatText("\x85*You must wait to change your name again", false);
+	}
+	else if (cv_mute.value && !(server || IsPlayerAdmin(displayplayers[3])))
 		CV_StealthSet(&cv_playername4, player_names[displayplayers[3]]);
 	else // Cleanup name if changing it
 		CleanupPlayerName(displayplayers[3], cv_playername4.zstring);
@@ -1816,8 +1838,11 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
 	skin = READUINT8(*cp);
 
 	// set name
-	if (strcasecmp(player_names[playernum], name) != 0)
-		SetPlayerName(playernum, name);
+	if (player_name_changes[playernum] < MAXNAMECHANGES)
+	{
+		if (strcasecmp(player_names[playernum], name) != 0)
+			SetPlayerName(playernum, name);
+	}
 
 	// set color
 	p->skincolor = color % MAXSKINCOLORS;
diff --git a/src/g_game.c b/src/g_game.c
index 43a270b77..86a949fd4 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -548,6 +548,8 @@ char player_names[MAXPLAYERS][MAXPLAYERNAME+1] =
 	"Player 16"
 }; // SRB2kart - removed Players 17 through 32
 
+int player_name_changes[MAXPLAYERS];
+
 INT16 rw_maximums[NUM_WEAPONS] =
 {
 	800, // MAX_INFINITY
@@ -2502,6 +2504,11 @@ void G_Ticker(boolean run)
 			spectatedelay3--;
 		if (spectatedelay4)
 			spectatedelay4--;
+
+		if (gametic % NAMECHANGERATE == 0)
+		{
+			memset(player_name_changes, 0, sizeof player_name_changes);
+		}
 	}
 }
 
diff --git a/src/g_game.h b/src/g_game.h
index 0edc13c74..293041e3a 100644
--- a/src/g_game.h
+++ b/src/g_game.h
@@ -27,6 +27,7 @@ extern char customversionstring[32];
 extern player_t *seenplayer;
 #endif
 extern char player_names[MAXPLAYERS][MAXPLAYERNAME+1];
+extern int  player_name_changes[MAXPLAYERS];
 
 extern player_t players[MAXPLAYERS];
 extern boolean playeringame[MAXPLAYERS];
-- 
GitLab