From e717731ea315d5cb46c7274449f9693cc25dc069 Mon Sep 17 00:00:00 2001
From: Zwip-Zwap Zapony <ZwipZwapZapony@gmail.com>
Date: Tue, 2 Jan 2024 18:58:22 +0100
Subject: [PATCH] Update player->quittime when a server idles, again

---
 src/netcode/d_clisrv.c          | 29 ++++++++++++++++++++++++++---
 src/netcode/d_clisrv.h          |  2 +-
 src/netcode/server_connection.c |  2 +-
 src/p_tick.c                    | 16 +---------------
 4 files changed, 29 insertions(+), 20 deletions(-)

diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c
index d84759b423..f4251ef08a 100644
--- a/src/netcode/d_clisrv.c
+++ b/src/netcode/d_clisrv.c
@@ -1280,6 +1280,7 @@ static void UpdatePingTable(void)
 	}
 }
 
+// Handle idle and disconnected player timers
 static void IdleUpdate(void)
 {
 	INT32 i;
@@ -1302,7 +1303,26 @@ static void IdleUpdate(void)
 			}
 		}
 		else
+		{
 			players[i].lastinputtime = 0;
+
+			if (players[i].quittime && playeringame[i])
+			{
+				players[i].quittime++;
+
+				if (players[i].quittime == 30 * TICRATE && G_TagGametype())
+					P_CheckSurvivors();
+
+				if (server && players[i].quittime >= (tic_t)FixedMul(cv_rejointimeout.value, 60 * TICRATE)
+				&& !(players[i].quittime % TICRATE))
+				{
+					if (D_NumNodes(true) > 0)
+						SendKick(i, KICK_MSG_PLAYER_QUIT);
+					else // If the server is empty, don't send a NetXCmd - that would wake an idling dedicated server
+						CL_RemovePlayer(i, KICK_MSG_PLAYER_QUIT);
+				}
+			}
+		}
 	}
 }
 
@@ -1623,12 +1643,15 @@ INT32 D_NumPlayers(void)
 	return num;
 }
 
-/** Returns the number of nodes on the server.
+/** Returns the number of currently-connected nodes in a netgame.
+  * Not necessarily equivalent to D_NumPlayers() minus D_NumBots().
+  *
+  * \param skiphost Skip the server's own node.
   */
-INT32 D_NumNodes(void)
+INT32 D_NumNodes(boolean skiphost)
 {
 	INT32 num = 0;
-	for (INT32 ix = 0; ix < MAXNETNODES; ix++)
+	for (INT32 ix = skiphost ? 1 : 0; ix < MAXNETNODES; ix++)
 		if (netnodes[ix].ingame)
 			num++;
 	return num;
diff --git a/src/netcode/d_clisrv.h b/src/netcode/d_clisrv.h
index f9cbf88768..61823e65d2 100644
--- a/src/netcode/d_clisrv.h
+++ b/src/netcode/d_clisrv.h
@@ -121,7 +121,7 @@ extern char motd[254], server_context[8];
 extern UINT8 playernode[MAXPLAYERS];
 
 INT32 D_NumPlayers(void);
-INT32 D_NumNodes(void);
+INT32 D_NumNodes(boolean skiphost);
 INT32 D_NumBots(void);
 
 tic_t GetLag(INT32 node);
diff --git a/src/netcode/server_connection.c b/src/netcode/server_connection.c
index bfbe30a08e..376700f0db 100644
--- a/src/netcode/server_connection.c
+++ b/src/netcode/server_connection.c
@@ -109,7 +109,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
 	netbuffer->u.serverinfo.leveltime = (tic_t)LONG(leveltime);
 
 	// Exclude bots from both counts
-	netbuffer->u.serverinfo.numberofplayer = (UINT8)(D_NumNodes() - (dedicated ? 1 : 0));
+	netbuffer->u.serverinfo.numberofplayer = (UINT8)D_NumNodes(dedicated);
 	netbuffer->u.serverinfo.maxplayer = (UINT8)(cv_maxplayers.value - D_NumBots());
 
 	netbuffer->u.serverinfo.refusereason = GetRefuseReason(node);
diff --git a/src/p_tick.c b/src/p_tick.c
index 143fa7e368..4ab388486d 100644
--- a/src/p_tick.c
+++ b/src/p_tick.c
@@ -701,25 +701,11 @@ void P_Ticker(boolean run)
 {
 	INT32 i;
 
-	// Increment jointime and quittime even if paused
+	// Increment jointime even if paused
 	for (i = 0; i < MAXPLAYERS; i++)
 		if (playeringame[i])
-		{
 			players[i].jointime++;
 
-			if (players[i].quittime)
-			{
-				players[i].quittime++;
-
-				if (players[i].quittime == 30 * TICRATE && G_TagGametype())
-					P_CheckSurvivors();
-
-				if (server && players[i].quittime >= (tic_t)FixedMul(cv_rejointimeout.value, 60 * TICRATE)
-				&& !(players[i].quittime % TICRATE))
-					SendKick(i, KICK_MSG_PLAYER_QUIT);
-			}
-		}
-
 	if (objectplacing)
 	{
 		if (OP_FreezeObjectplace())
-- 
GitLab