From e5be5e80baa31bcb1e1a8b2d490f20457647c9cf Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 1 Feb 2019 00:44:35 -0600 Subject: [PATCH] Make joins/quits/enters/spectates sync in replays I'm not 100% sure on joins. That P_RandomByte() call looks ugly. It'll probably be a source of trouble. --- src/d_clisrv.c | 4 +++- src/d_clisrv.h | 1 + src/d_netcmd.c | 2 ++ src/g_game.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 5369ff2c..3c8865d6 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2479,13 +2479,15 @@ void CL_ClearPlayer(INT32 playernum) // // Removes a player from the current game // -static void CL_RemovePlayer(INT32 playernum, INT32 reason) +void CL_RemovePlayer(INT32 playernum, INT32 reason) { // Sanity check: exceptional cases (i.e. c-fails) can cause multiple // kick commands to be issued for the same player. if (!playeringame[playernum]) return; + demo_extradata[playernum] |= DXD_PLAYSTATE; + if (server && !demoplayback) { INT32 node = playernode[playernum]; diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 39cb8c4d..e59e4419 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -549,6 +549,7 @@ void CL_AddSplitscreenPlayer(void); void CL_RemoveSplitscreenPlayer(UINT8 p); void CL_Reset(void); void CL_ClearPlayer(INT32 playernum); +void CL_RemovePlayer(INT32 playernum, INT32 reason); void CL_UpdateServerList(boolean internetsearch, INT32 room); // Is there a game running boolean Playing(void); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 982b75d4..7b3925e9 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3362,6 +3362,8 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) if (gamestate != GS_LEVEL) return; + demo_extradata[playernum] |= DXD_PLAYSTATE; + // Clear player score and rings if a spectator. if (players[playernum].spectator) { diff --git a/src/g_game.c b/src/g_game.c index ab4a6b8e..25a70b3e 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -14,6 +14,7 @@ #include "doomdef.h" #include "console.h" #include "d_main.h" +#include "d_clisrv.h" #include "d_player.h" #include "f_finale.h" #include "p_setup.h" @@ -3032,6 +3033,8 @@ void G_AddPlayer(INT32 playernum) p->jointime = 0; p->playerstate = PST_REBORN; + + demo_extradata[playernum] |= DXD_PLAYSTATE|DXD_COLOR|DXD_NAME|DXD_SKIN; // Set everything } void G_ExitLevel(void) @@ -3118,7 +3121,7 @@ boolean G_GametypeHasSpectators(void) #if 0 return (gametype != GT_COOP && gametype != GT_COMPETITION && gametype != GT_RACE); #else - return (netgame); //true + return (netgame || (multiplayer && demoplayback)); //true #endif } @@ -4607,6 +4610,43 @@ void G_ReadDemoExtraData(void) extradata = READUINT8(demo_p); // @TODO uhhhhh do something here + + switch (extradata) { + case DXD_PST_PLAYING: + players[p].pflags |= PF_WANTSTOJOIN; // fuck you + break; + + case DXD_PST_SPECTATING: + if (!playeringame[p]) + { + CL_ClearPlayer(p); + playeringame[p] = true; + G_AddPlayer(p); + players[p].spectator = true; + P_RandomByte(); // I'm pretty sure this ISN'T right, but it syncs my one test replay. + } + else + { + players[p].spectator = true; + if (players[p].mo) + P_DamageMobj(players[p].mo, NULL, NULL, 10000); + else + players[p].playerstate = PST_REBORN; + } + break; + + case DXD_PST_LEFT: + CL_RemovePlayer(p, 0); + break; + } + + // maybe these are necessary? + if (G_BattleGametype()) + K_CheckBumpers(); // SRB2Kart + else if (G_RaceGametype()) + P_CheckRacers(); // also SRB2Kart + + CONS_Printf("Change state @ %d\n", leveltime); } @@ -4662,7 +4702,10 @@ void G_WriteDemoExtraData(void) { if (!playeringame[i]) WRITEUINT8(demo_p, DXD_PST_LEFT); - else if (players[i].spectator) + else if ( + players[i].spectator && + !(players[i].pflags & PF_WANTSTOJOIN) // <= fuck you specifically + ) WRITEUINT8(demo_p, DXD_PST_SPECTATING); else WRITEUINT8(demo_p, DXD_PST_PLAYING); @@ -6173,6 +6216,7 @@ void G_DoPlayDemo(char *defdemoname) // Look for the next player p = READUINT8(demo_p); } + R_ExecuteSetViewSize(); }