From 48514ee88d54a5d36a92c2af0fdd1feb587acf2d Mon Sep 17 00:00:00 2001 From: CobaltBW Date: Thu, 15 Jul 2021 15:04:24 -0700 Subject: [PATCH] Fixed G_RemovePlayer crash in players.iterate This was done by storing flag-for-removal status as a boolean inside the player struct. Bot players are instead removed at the start of G_Ticker, rather than being removed immediately by G_RemovePlayer. --- src/d_player.h | 1 + src/g_game.c | 22 +++++++++++++++++++++- src/lua_baselib.c | 14 ++------------ src/p_saveg.c | 2 ++ 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 89776fe5e..a0db1402d 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -559,6 +559,7 @@ typedef struct player_s boolean spectator; boolean outofcoop; + boolean removing; UINT8 bot; struct player_s *botleader; UINT16 lastbuttons; diff --git a/src/g_game.c b/src/g_game.c index 0643350b6..4d501f526 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1545,7 +1545,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) cmd->forwardmove = (SINT8)(cmd->forwardmove + forward); cmd->sidemove = (SINT8)(cmd->sidemove + side); - //Note: Majority of botstuffs are handled in G_Ticker now. + // Note: Majority of botstuffs are handled in G_Ticker now. if (player->bot == BOT_2PHUMAN) //Player-controlled bot { G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1); // empty, or external driver @@ -2198,6 +2198,23 @@ void G_Ticker(boolean run) UINT32 i; INT32 buf; + // Bot players queued for removal + for (i = MAXPLAYERS-1; i != UINT32_MAX; i--) + { + if (playeringame[i] && players[i].removing) + { + CL_RemovePlayer(i, i); + if (netgame) + { + char kickmsg[256]; + + strcpy(kickmsg, M_GetText("\x82*Bot %s has been removed")); + strcpy(kickmsg, va(kickmsg, player_names[i], i)); + HU_AddChatText(kickmsg, false); + } + } + } + // see also SCR_DisplayMarathonInfo if ((marathonmode & (MA_INIT|MA_INGAME)) == MA_INGAME && gamestate == GS_LEVEL) marathontime++; @@ -2520,6 +2537,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) tic_t quittime; boolean spectator; boolean outofcoop; + boolean removing; INT16 bot; SINT8 pity; INT16 rings; @@ -2536,6 +2554,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) quittime = players[player].quittime; spectator = players[player].spectator; outofcoop = players[player].outofcoop; + removing = players[player].removing; pflags = (players[player].pflags & (PF_FLIPCAM|PF_ANALOGMODE|PF_DIRECTIONCHAR|PF_AUTOBRAKE|PF_TAGIT|PF_GAMETYPEOVER)); playerangleturn = players[player].angleturn; oldrelangleturn = players[player].oldrelangleturn; @@ -2612,6 +2631,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->quittime = quittime; p->spectator = spectator; p->outofcoop = outofcoop; + p->removing = removing; p->angleturn = playerangleturn; p->oldrelangleturn = oldrelangleturn; diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 9946a9fd3..9e01a98c0 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3482,24 +3482,14 @@ static int lib_gAddPlayer(lua_State *L) static int lib_gRemovePlayer(lua_State *L) { UINT8 pnum = -1; - //const char *kickreason = luaL_checkstring(L, 2); if (!lua_isnoneornil(L, 1)) pnum = luaL_checkinteger(L, 1); if (&players[pnum]) { - if (players[pnum].bot != BOT_NONE) + if (players[pnum].bot != BOT_NONE && players[pnum].removing == false) { -// CL_RemovePlayer(pnum, *kickreason); - CL_RemovePlayer(pnum, pnum); - if (netgame) - { - char kickmsg[256]; - - strcpy(kickmsg, M_GetText("\x82*Bot %s has been removed")); - strcpy(kickmsg, va(kickmsg, player_names[pnum], pnum)); - HU_AddChatText(kickmsg, false); - } + players[pnum].removing = true; // This function can be run in players.iterate(), which isn't equipped to deal with players being removed mid-process. Instead we'll remove the player at the beginning of the next ticframe. lua_pushboolean(L, true); return 1; } diff --git a/src/p_saveg.c b/src/p_saveg.c index 7e9d7b6d4..1270064c0 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -201,6 +201,7 @@ static void P_NetArchivePlayers(void) WRITEUINT8(save_p, players[i].botmem.lastBlocked); WRITEUINT8(save_p, players[i].botmem.catchup_tics); WRITEUINT8(save_p, players[i].botmem.thinkstate); + WRITEUINT8(save_p, players[i].removing); WRITEUINT8(save_p, players[i].blocked); WRITEUINT16(save_p, players[i].lastbuttons); @@ -428,6 +429,7 @@ static void P_NetUnArchivePlayers(void) players[i].botmem.lastBlocked = READUINT8(save_p); players[i].botmem.catchup_tics = READUINT8(save_p); players[i].botmem.thinkstate = READUINT8(save_p); + players[i].removing = READUINT8(save_p); players[i].blocked = READUINT8(save_p); players[i].lastbuttons = READUINT16(save_p);