From f874b74b7f5dd7bf77c3ad0af279a2d36f734a92 Mon Sep 17 00:00:00 2001
From: Hanicef <gustaf@hanicef.me>
Date: Sun, 25 Feb 2024 19:05:16 +0100
Subject: [PATCH] Add variable to move idle players to spectators

---
 src/netcode/d_clisrv.c | 17 ++++++++++++++++-
 src/netcode/d_clisrv.h |  2 +-
 src/netcode/d_netcmd.c |  1 +
 3 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c
index d735e81321..251ca1873b 100644
--- a/src/netcode/d_clisrv.c
+++ b/src/netcode/d_clisrv.c
@@ -114,6 +114,7 @@ static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0,
 consvar_t cv_playbackspeed = CVAR_INIT ("playbackspeed", "1", 0, playbackspeed_cons_t, NULL);
 
 consvar_t cv_idletime = CVAR_INIT ("idletime", "0", CV_SAVE, CV_Unsigned, NULL);
+consvar_t cv_idlespectate = CVAR_INIT ("idlespectate", "On", CV_SAVE, CV_OnOff, NULL);
 consvar_t cv_dedicatedidletime = CVAR_INIT ("dedicatedidletime", "10", CV_SAVE, CV_Unsigned, NULL);
 
 consvar_t cv_httpsource = CVAR_INIT ("http_source", "", CV_SAVE, NULL, NULL);
@@ -1372,7 +1373,21 @@ static void IdleUpdate(void)
 			if (players[i].lastinputtime > (tic_t)cv_idletime.value * TICRATE * 60)
 			{
 				players[i].lastinputtime = 0;
-				SendKick(i, KICK_MSG_IDLE | KICK_MSG_KEEP_BODY);
+				if (cv_idlespectate.value && G_GametypeHasSpectators())
+				{
+					changeteam_union NetPacket;
+					UINT16 usvalue;
+					NetPacket.value.l = NetPacket.value.b = 0;
+					NetPacket.packet.newteam = 0;
+					NetPacket.packet.playernum = i;
+					NetPacket.packet.verification = true; // This signals that it's a server change
+					usvalue = SHORT(NetPacket.value.l|NetPacket.value.b);
+					SendNetXCmd(XD_TEAMCHANGE, &usvalue, sizeof(usvalue));
+				}
+				else
+				{
+					SendKick(i, KICK_MSG_IDLE | KICK_MSG_KEEP_BODY);
+				}
 			}
 		}
 		else
diff --git a/src/netcode/d_clisrv.h b/src/netcode/d_clisrv.h
index 5aac4693d2..342173dff5 100644
--- a/src/netcode/d_clisrv.h
+++ b/src/netcode/d_clisrv.h
@@ -73,7 +73,7 @@ extern UINT32 realpingtable[MAXPLAYERS];
 extern UINT32 playerpingtable[MAXPLAYERS];
 extern tic_t servermaxping;
 
-extern consvar_t cv_netticbuffer, cv_resynchattempts, cv_blamecfail, cv_playbackspeed, cv_idletime, cv_dedicatedidletime;
+extern consvar_t cv_netticbuffer, cv_resynchattempts, cv_blamecfail, cv_playbackspeed, cv_idletime, cv_idlespectate, cv_dedicatedidletime;
 extern consvar_t cv_httpsource;
 
 // Used in d_net, the only dependence
diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c
index ebb284d7b3..100b4ca22a 100644
--- a/src/netcode/d_netcmd.c
+++ b/src/netcode/d_netcmd.c
@@ -612,6 +612,7 @@ void D_RegisterServerCommands(void)
 	CV_RegisterVar(&cv_blamecfail);
 	CV_RegisterVar(&cv_dedicatedidletime);
 	CV_RegisterVar(&cv_idletime);
+	CV_RegisterVar(&cv_idlespectate);
 	CV_RegisterVar(&cv_httpsource);
 
 	COM_AddCommand("ping", Command_Ping_f, COM_LUA);
-- 
GitLab