From a8fe500d0e22beb37e7c734d74cfa2632199bbdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Tue, 19 Sep 2023 19:05:43 +0200 Subject: [PATCH 1/3] Add auto-kick for inactive players --- src/netcode/d_clisrv.c | 35 +++++++++++++++++++++++++++++++++++ src/netcode/d_clisrv.h | 4 ++-- src/netcode/d_net.h | 1 + src/netcode/d_netcmd.c | 1 + src/netcode/protocol.h | 1 + 5 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index f06192f2c..efa251ff7 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -113,6 +113,7 @@ consvar_t cv_blamecfail = CVAR_INIT ("blamecfail", "Off", CV_SAVE|CV_NETVAR, CV_ static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, NULL}}; 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_dedicatedidletime = CVAR_INIT ("dedicatedidletime", "10", CV_SAVE, CV_Unsigned, NULL); void ResetNode(INT32 node) @@ -492,6 +493,10 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) HU_AddChatText(va("\x82*%s has been banned (%s)", player_names[pnum], reason), false); kickreason = KR_BAN; break; + case KICK_MSG_IDLE: + HU_AddChatText(va("\x82*%s has left the game (Inactive for too long)", player_names[pnum]), false); + kickreason = KR_TIMEOUT; + break; } if (pnum == consoleplayer) @@ -507,6 +512,8 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) M_StartMessage(M_GetText("Server closed connection\n(synch failure)\nPress ESC\n"), NULL, MM_NOTHING); else if (msg == KICK_MSG_PING_HIGH) M_StartMessage(M_GetText("Server closed connection\n(Broke ping limit)\nPress ESC\n"), NULL, MM_NOTHING); + else if (msg == KICK_MSG_IDLE) + M_StartMessage(M_GetText("Server closed connection\n(Inactive for too long)\nPress ESC\n"), NULL, MM_NOTHING); else if (msg == KICK_MSG_BANNED) M_StartMessage(M_GetText("You have been banned by the server\n\nPress ESC\n"), NULL, MM_NOTHING); else if (msg == KICK_MSG_CUSTOM_KICK) @@ -1267,6 +1274,30 @@ static void UpdatePingTable(void) } } +static void IdleUpdate(void) +{ + INT32 i; + if (!server || !netgame) + return; + + for (i = 1; i < MAXPLAYERS; i++) + { + if (cv_idletime.value && playeringame[i] && playernode[i] != UINT8_MAX && !players[i].quittime && !players[i].spectator && i != serverplayer) + { + if (players[i].cmd.forwardmove || players[i].cmd.sidemove || players[i].cmd.buttons) + netnodes[i].lastinput = gametime; + + if (gametime - netnodes[i].lastinput > cv_idletime.value * TICRATE) + { + netnodes[i].lastinput = gametime; + SendKick(i, KICK_MSG_IDLE | KICK_MSG_KEEP_BODY); + } + } + else + netnodes[i].lastinput = gametime; + } +} + // Handle timeouts to prevent definitive freezes from happenning static void HandleNodeTimeouts(void) { @@ -1299,6 +1330,8 @@ void NetKeepAlive(void) GetPackets(); + IdleUpdate(); + #ifdef MASTERSERVER MasterClient_Ticker(); #endif @@ -1419,6 +1452,8 @@ void NetUpdate(void) GetPackets(); // get packet from client or from server + IdleUpdate(); + // The client sends the command after receiving from the server // The server sends it before because this is better in single player diff --git a/src/netcode/d_clisrv.h b/src/netcode/d_clisrv.h index d87ead9ec..db9a780cd 100644 --- a/src/netcode/d_clisrv.h +++ b/src/netcode/d_clisrv.h @@ -48,7 +48,7 @@ typedef enum KR_TIMEOUT = 4, //Connection Timeout KR_BAN = 5, //Banned by server KR_LEAVE = 6, //Quit the game - + KR_IDLE = 7, //Remained still for too long } kickreason_t; /* the max number of name changes in some time period */ @@ -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_dedicatedidletime; +extern consvar_t cv_netticbuffer, cv_resynchattempts, cv_blamecfail, cv_playbackspeed, cv_idletime, cv_dedicatedidletime; // Used in d_net, the only dependence void D_ClientServerInit(void); diff --git a/src/netcode/d_net.h b/src/netcode/d_net.h index 549f2b93c..e8e3b5895 100644 --- a/src/netcode/d_net.h +++ b/src/netcode/d_net.h @@ -43,6 +43,7 @@ typedef struct netnode_s { boolean ingame; // set false as nodes leave game tic_t freezetimeout; // Until when can this node freeze the server before getting a timeout? + tic_t lastinput; // the last tic the player has made any input SINT8 player; SINT8 player2; // say the numplayer for this node if any (splitscreen) diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c index 5afa95561..0cceac112 100644 --- a/src/netcode/d_netcmd.c +++ b/src/netcode/d_netcmd.c @@ -601,6 +601,7 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_showjoinaddress); CV_RegisterVar(&cv_blamecfail); CV_RegisterVar(&cv_dedicatedidletime); + CV_RegisterVar(&cv_idletime); COM_AddCommand("ping", Command_Ping_f, COM_LUA); CV_RegisterVar(&cv_nettimeout); diff --git a/src/netcode/protocol.h b/src/netcode/protocol.h index a992e3b69..c084d920c 100644 --- a/src/netcode/protocol.h +++ b/src/netcode/protocol.h @@ -331,6 +331,7 @@ typedef struct #define KICK_MSG_PING_HIGH 6 #define KICK_MSG_CUSTOM_KICK 7 #define KICK_MSG_CUSTOM_BAN 8 +#define KICK_MSG_IDLE 9 #define KICK_MSG_KEEP_BODY 0x80 #endif From 436de2180831aec6b14de01e1aa61ba894c5c1ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Sat, 7 Oct 2023 00:07:56 +0200 Subject: [PATCH 2/3] Refactor code after review comments --- src/d_player.h | 1 + src/netcode/d_clisrv.c | 10 +++++----- src/netcode/d_net.h | 1 - 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 7ad5b9f81..ca700d4e1 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -607,6 +607,7 @@ typedef struct player_s tic_t jointime; // Timer when player joins game to change skin/color tic_t quittime; // Time elapsed since user disconnected, zero if connected + tic_t lastinputtime; // the last tic the player has made any input #ifdef HWRENDER fixed_t fovadd; // adjust FOV for hw rendering #endif diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index efa251ff7..4571930f8 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -1282,19 +1282,19 @@ static void IdleUpdate(void) for (i = 1; i < MAXPLAYERS; i++) { - if (cv_idletime.value && playeringame[i] && playernode[i] != UINT8_MAX && !players[i].quittime && !players[i].spectator && i != serverplayer) + if (cv_idletime.value && playeringame[i] && playernode[i] != UINT8_MAX && !players[i].quittime && !players[i].spectator && !IsPlayerAdmin(i)) { if (players[i].cmd.forwardmove || players[i].cmd.sidemove || players[i].cmd.buttons) - netnodes[i].lastinput = gametime; + players[i].lastinputtime = gametime; - if (gametime - netnodes[i].lastinput > cv_idletime.value * TICRATE) + if (gametime - players[i].lastinputtime > (tic_t)cv_idletime.value * TICRATE * 60) { - netnodes[i].lastinput = gametime; + players[i].lastinputtime = gametime; SendKick(i, KICK_MSG_IDLE | KICK_MSG_KEEP_BODY); } } else - netnodes[i].lastinput = gametime; + players[i].lastinputtime = gametime; } } diff --git a/src/netcode/d_net.h b/src/netcode/d_net.h index e8e3b5895..549f2b93c 100644 --- a/src/netcode/d_net.h +++ b/src/netcode/d_net.h @@ -43,7 +43,6 @@ typedef struct netnode_s { boolean ingame; // set false as nodes leave game tic_t freezetimeout; // Until when can this node freeze the server before getting a timeout? - tic_t lastinput; // the last tic the player has made any input SINT8 player; SINT8 player2; // say the numplayer for this node if any (splitscreen) From 80e386b16f66079fcef80bcfb116135b8524efe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Sat, 14 Oct 2023 21:50:59 +0200 Subject: [PATCH 3/3] Expose lastinputtime to Lua --- src/lua_baselib.c | 1 + src/lua_playerlib.c | 8 ++++++++ src/netcode/d_clisrv.c | 13 ++++++++----- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 8cb6d185d..d1fa8f368 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3572,6 +3572,7 @@ static int lib_gAddPlayer(lua_State *L) newplayer->jointime = 0; newplayer->quittime = 0; + newplayer->lastinputtime = 0; // Read the skin argument (defaults to Sonic) if (!lua_isnoneornil(L, 1)) diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 827e5a405..d0858e044 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -223,6 +223,7 @@ enum player_e player_blocked, player_jointime, player_quittime, + player_lastinputtime, player_ping, #ifdef HWRENDER player_fovadd, @@ -371,6 +372,7 @@ static const char *const player_opt[] = { "blocked", "jointime", "quittime", + "lastinputtime", "ping", #ifdef HWRENDER "fovadd", @@ -826,6 +828,9 @@ static int player_get(lua_State *L) case player_quittime: lua_pushinteger(L, plr->quittime); break; + case player_lastinputtime: + lua_pushinteger(L, plr->lastinputtime); + break; case player_ping: lua_pushinteger(L, playerpingtable[plr - players]); break; @@ -1349,6 +1354,9 @@ static int player_set(lua_State *L) case player_quittime: plr->quittime = (tic_t)luaL_checkinteger(L, 3); break; + case player_lastinputtime: + plr->lastinputtime = (tic_t)luaL_checkinteger(L, 3); + break; #ifdef HWRENDER case player_fovadd: plr->fovadd = luaL_checkfixed(L, 3); diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index 4571930f8..7804b068f 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -227,6 +227,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) newplayer->jointime = 0; newplayer->quittime = 0; + newplayer->lastinputtime = 0; READSTRINGN(*p, player_names[newplayernum], MAXPLAYERNAME); @@ -1282,19 +1283,21 @@ static void IdleUpdate(void) for (i = 1; i < MAXPLAYERS; i++) { - if (cv_idletime.value && playeringame[i] && playernode[i] != UINT8_MAX && !players[i].quittime && !players[i].spectator && !IsPlayerAdmin(i)) + if (cv_idletime.value && playeringame[i] && playernode[i] != UINT8_MAX && !players[i].quittime && !players[i].spectator && !players[i].bot && !IsPlayerAdmin(i) && i != serverplayer) { if (players[i].cmd.forwardmove || players[i].cmd.sidemove || players[i].cmd.buttons) - players[i].lastinputtime = gametime; + players[i].lastinputtime = 0; + else + players[i].lastinputtime++; - if (gametime - players[i].lastinputtime > (tic_t)cv_idletime.value * TICRATE * 60) + if (players[i].lastinputtime > (tic_t)cv_idletime.value * TICRATE * 60) { - players[i].lastinputtime = gametime; + players[i].lastinputtime = 0; SendKick(i, KICK_MSG_IDLE | KICK_MSG_KEEP_BODY); } } else - players[i].lastinputtime = gametime; + players[i].lastinputtime = 0; } }