Merge remote-tracking branch 'origin/resend-gamestate' into netcode-tests

This commit is contained in:
Steel Titanium 2020-03-08 14:52:19 -04:00
commit 9d0c959bb4
10 changed files with 201 additions and 970 deletions

File diff suppressed because it is too large Load diff

View file

@ -64,8 +64,10 @@ typedef enum
PT_REQUESTFILE, // Client requests a file transfer PT_REQUESTFILE, // Client requests a file transfer
PT_ASKINFOVIAMS, // Packet from the MS requesting info be sent to new client. PT_ASKINFOVIAMS, // Packet from the MS requesting info be sent to new client.
// If this ID changes, update masterserver definition. // If this ID changes, update masterserver definition.
PT_RESYNCHEND, // Player is now resynched and is being requested to remake the gametic
PT_RESYNCHGET, // Player got resynch packet PT_WILLRESENDGAMESTATE, // Hey Client, I am about to resend you the gamestate!
PT_CANRECEIVEGAMESTATE, // Okay Server, I'm ready to receive it, you can go ahead.
PT_RECEIVEDGAMESTATE, // Thank you Server, I am ready to play again!
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
PT_SENDINGLUAFILE, // Server telling a client Lua needs to open a file PT_SENDINGLUAFILE, // Server telling a client Lua needs to open a file
@ -85,8 +87,6 @@ typedef enum
PT_TEXTCMD2, // Splitscreen text commands. PT_TEXTCMD2, // Splitscreen text commands.
PT_CLIENTJOIN, // Client wants to join; used in start game. PT_CLIENTJOIN, // Client wants to join; used in start game.
PT_NODETIMEOUT, // Packet sent to self if the connection times out. PT_NODETIMEOUT, // Packet sent to self if the connection times out.
PT_RESYNCHING, // Packet sent to resync players.
// Blocks game advance until synched.
PT_LOGIN, // Login attempt from the client. PT_LOGIN, // Login attempt from the client.
@ -139,165 +139,6 @@ typedef struct
ticcmd_t cmds[45]; // Normally [BACKUPTIC][MAXPLAYERS] but too large ticcmd_t cmds[45]; // Normally [BACKUPTIC][MAXPLAYERS] but too large
} ATTRPACK servertics_pak; } ATTRPACK servertics_pak;
// Sent to client when all consistency data
// for players has been restored
typedef struct
{
UINT32 randomseed;
// CTF flag stuff
SINT8 flagplayer[2];
INT32 flagloose[2];
INT32 flagflags[2];
fixed_t flagx[2];
fixed_t flagy[2];
fixed_t flagz[2];
UINT32 ingame; // Spectator bit for each player
UINT32 outofcoop; // outofcoop bit for each player
INT32 ctfteam[MAXPLAYERS]; // Which team? (can't be 1 bit, since in regular Match there are no teams)
// Resynch game scores and the like all at once
UINT32 score[MAXPLAYERS]; // Everyone's score
INT16 numboxes[MAXPLAYERS];
INT16 totalring[MAXPLAYERS];
tic_t realtime[MAXPLAYERS];
UINT8 laps[MAXPLAYERS];
} ATTRPACK resynchend_pak;
typedef struct
{
// Player stuff
UINT8 playernum;
// Do not send anything visual related.
// Only send data that we need to know for physics.
UINT8 playerstate; // playerstate_t
UINT32 pflags; // pflags_t
UINT8 panim; // panim_t
angle_t aiming;
INT32 currentweapon;
INT32 ringweapons;
UINT16 ammoremoval;
tic_t ammoremovaltimer;
INT32 ammoremovalweapon;
UINT16 powers[NUMPOWERS];
// Score is resynched in the confirm resync packet
INT16 rings;
INT16 spheres;
SINT8 lives;
SINT8 continues;
UINT8 scoreadd;
SINT8 xtralife;
SINT8 pity;
UINT8 skincolor;
INT32 skin;
UINT32 availabilities;
// Just in case Lua does something like
// modify these at runtime
fixed_t camerascale;
fixed_t shieldscale;
fixed_t normalspeed;
fixed_t runspeed;
UINT8 thrustfactor;
UINT8 accelstart;
UINT8 acceleration;
UINT8 charability;
UINT8 charability2;
UINT32 charflags;
UINT32 thokitem; // mobjtype_t
UINT32 spinitem; // mobjtype_t
UINT32 revitem; // mobjtype_t
UINT32 followitem; // mobjtype_t
fixed_t actionspd;
fixed_t mindash;
fixed_t maxdash;
fixed_t jumpfactor;
fixed_t playerheight;
fixed_t playerspinheight;
fixed_t speed;
UINT8 secondjump;
UINT8 fly1;
tic_t glidetime;
UINT8 climbing;
INT32 deadtimer;
tic_t exiting;
UINT8 homing;
tic_t dashmode;
tic_t skidtime;
fixed_t cmomx;
fixed_t cmomy;
fixed_t rmomx;
fixed_t rmomy;
INT32 weapondelay;
INT32 tossdelay;
INT16 starpostx;
INT16 starposty;
INT16 starpostz;
INT32 starpostnum;
tic_t starposttime;
angle_t starpostangle;
fixed_t starpostscale;
INT32 maxlink;
fixed_t dashspeed;
angle_t angle_pos;
angle_t old_angle_pos;
tic_t bumpertime;
INT32 flyangle;
tic_t drilltimer;
INT32 linkcount;
tic_t linktimer;
INT32 anotherflyangle;
tic_t nightstime;
INT32 drillmeter;
UINT8 drilldelay;
UINT8 bonustime;
UINT8 mare;
INT16 lastsidehit, lastlinehit;
tic_t losstime;
UINT8 timeshit;
INT32 onconveyor;
//player->mo stuff
UINT8 hasmo; // Boolean
INT32 health;
angle_t angle;
angle_t rollangle;
fixed_t x;
fixed_t y;
fixed_t z;
fixed_t momx;
fixed_t momy;
fixed_t momz;
fixed_t friction;
fixed_t movefactor;
spritenum_t sprite;
UINT32 frame;
UINT8 sprite2;
UINT16 anim_duration;
INT32 tics;
statenum_t statenum;
UINT32 flags;
UINT32 flags2;
UINT16 eflags;
fixed_t radius;
fixed_t height;
fixed_t scale;
fixed_t destscale;
fixed_t scalespeed;
} ATTRPACK resynch_pak;
typedef struct typedef struct
{ {
UINT8 version; // Different versions don't work UINT8 version; // Different versions don't work
@ -311,18 +152,10 @@ typedef struct
UINT8 clientnode; UINT8 clientnode;
UINT8 gamestate; UINT8 gamestate;
// 0xFF == not in game; else player skin num
UINT8 playerskins[MAXPLAYERS];
UINT8 playercolor[MAXPLAYERS];
UINT32 playeravailabilities[MAXPLAYERS];
UINT8 gametype; UINT8 gametype;
UINT8 modifiedgame; UINT8 modifiedgame;
SINT8 adminplayers[MAXPLAYERS]; // Needs to be signed
char server_context[8]; // Unique context id, generated at server startup. char server_context[8]; // Unique context id, generated at server startup.
UINT8 varlengthinputs[0]; // Playernames and netvars
} ATTRPACK serverconfig_pak; } ATTRPACK serverconfig_pak;
typedef struct { typedef struct {
@ -442,9 +275,6 @@ typedef struct
client2cmd_pak client2pak; // 200 bytes client2cmd_pak client2pak; // 200 bytes
servertics_pak serverpak; // 132495 bytes (more around 360, no?) servertics_pak serverpak; // 132495 bytes (more around 360, no?)
serverconfig_pak servercfg; // 773 bytes serverconfig_pak servercfg; // 773 bytes
resynchend_pak resynchend; //
resynch_pak resynchpak; //
UINT8 resynchgot; //
UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...) UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...)
filetx_pak filetxpak; // 139 bytes filetx_pak filetxpak; // 139 bytes
clientconfig_pak clientcfg; // 136 bytes clientconfig_pak clientcfg; // 136 bytes
@ -579,7 +409,7 @@ UINT8 GetFreeXCmdSize(void);
void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest); void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest);
extern UINT8 hu_resynching; extern UINT8 hu_redownloadinggamestate;
extern UINT8 adminpassmd5[16]; extern UINT8 adminpassmd5[16];
extern boolean adminpasswordset; extern boolean adminpasswordset;

View file

@ -1539,7 +1539,7 @@ void D_SRB2Main(void)
{ {
levelstarttic = gametic; levelstarttic = gametic;
G_SetGamestate(GS_LEVEL); G_SetGamestate(GS_LEVEL);
if (!P_LoadLevel(false)) if (!P_LoadLevel(false, false))
I_Quit(); // fail so reset game stuff I_Quit(); // fail so reset game stuff
} }
} }

View file

@ -800,8 +800,9 @@ static const char *packettypename[NUMPACKETTYPE] =
"REQUESTFILE", "REQUESTFILE",
"ASKINFOVIAMS", "ASKINFOVIAMS",
"RESYNCHEND", "WILLRESENDGAMESTATE",
"RESYNCHGET", "CANRECEIVEGAMESTATE",
"RECEIVEDGAMESTATE",
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
"SENDINGLUAFILE", "SENDINGLUAFILE",
@ -814,7 +815,6 @@ static const char *packettypename[NUMPACKETTYPE] =
"TEXTCMD2", "TEXTCMD2",
"CLIENTJOIN", "CLIENTJOIN",
"NODETIMEOUT", "NODETIMEOUT",
"RESYNCHING",
"PING" "PING"
}; };

View file

@ -1839,7 +1839,7 @@ void G_DoLoadLevel(boolean resetplayer)
} }
// Setup the level. // Setup the level.
if (!P_LoadLevel(false)) // this never returns false? if (!P_LoadLevel(false, false)) // this never returns false?
{ {
// fail so reset game stuff // fail so reset game stuff
Command_ExitGame_f(); Command_ExitGame_f();

View file

@ -2206,7 +2206,7 @@ void HU_Drawer(void)
HU_DrawCrosshair2(); HU_DrawCrosshair2();
// draw desynch text // draw desynch text
if (hu_resynching) if (hu_redownloadinggamestate)
{ {
static UINT32 resynch_ticker = 0; static UINT32 resynch_ticker = 0;
char resynch_text[14]; char resynch_text[14];

View file

@ -107,13 +107,16 @@ static void P_NetArchivePlayers(void)
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
WRITESINT8(save_p, (SINT8)adminplayers[i]);
if (!playeringame[i]) if (!playeringame[i])
continue; continue;
flags = 0; flags = 0;
// no longer send ticcmds, player name, skin, or color // no longer send ticcmds
WRITESTRINGN(save_p, player_names[i], MAXPLAYERNAME);
WRITEANGLE(save_p, players[i].aiming); WRITEANGLE(save_p, players[i].aiming);
WRITEANGLE(save_p, players[i].drawangle); WRITEANGLE(save_p, players[i].drawangle);
WRITEANGLE(save_p, players[i].viewrollangle); WRITEANGLE(save_p, players[i].viewrollangle);
@ -141,6 +144,9 @@ static void P_NetArchivePlayers(void)
WRITEUINT16(save_p, players[i].flashpal); WRITEUINT16(save_p, players[i].flashpal);
WRITEUINT16(save_p, players[i].flashcount); WRITEUINT16(save_p, players[i].flashcount);
WRITEUINT8(save_p, players[i].skincolor);
WRITEINT32(save_p, players[i].skin);
WRITEUINT32(save_p, players[i].availabilities);
WRITEUINT32(save_p, players[i].score); WRITEUINT32(save_p, players[i].score);
WRITEFIXED(save_p, players[i].dashspeed); WRITEFIXED(save_p, players[i].dashspeed);
WRITESINT8(save_p, players[i].lives); WRITESINT8(save_p, players[i].lives);
@ -315,6 +321,8 @@ static void P_NetUnArchivePlayers(void)
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
adminplayers[i] = (INT32)READSINT8(save_p);
// Do NOT memset player struct to 0 // Do NOT memset player struct to 0
// other areas may initialize data elsewhere // other areas may initialize data elsewhere
//memset(&players[i], 0, sizeof (player_t)); //memset(&players[i], 0, sizeof (player_t));
@ -322,9 +330,8 @@ static void P_NetUnArchivePlayers(void)
continue; continue;
// NOTE: sending tics should (hopefully) no longer be necessary // NOTE: sending tics should (hopefully) no longer be necessary
// sending player names, skin and color should not be necessary at all!
// (that data is handled in the server config now)
READSTRINGN(save_p, player_names[i], MAXPLAYERNAME);
players[i].aiming = READANGLE(save_p); players[i].aiming = READANGLE(save_p);
players[i].drawangle = READANGLE(save_p); players[i].drawangle = READANGLE(save_p);
players[i].viewrollangle = READANGLE(save_p); players[i].viewrollangle = READANGLE(save_p);
@ -352,6 +359,9 @@ static void P_NetUnArchivePlayers(void)
players[i].flashpal = READUINT16(save_p); players[i].flashpal = READUINT16(save_p);
players[i].flashcount = READUINT16(save_p); players[i].flashcount = READUINT16(save_p);
players[i].skincolor = READUINT8(save_p);
players[i].skin = READINT32(save_p);
players[i].availabilities = READUINT32(save_p);
players[i].score = READUINT32(save_p); players[i].score = READUINT32(save_p);
players[i].dashspeed = READFIXED(save_p); // dashing speed players[i].dashspeed = READFIXED(save_p); // dashing speed
players[i].lives = READSINT8(save_p); players[i].lives = READSINT8(save_p);
@ -3984,14 +3994,17 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride)
playeringame[consoleplayer] = true; playeringame[consoleplayer] = true;
} }
static void P_NetArchiveMisc(void) static void P_NetArchiveMisc(boolean resending)
{ {
INT32 i; INT32 i;
WRITEUINT32(save_p, ARCHIVEBLOCK_MISC); WRITEUINT32(save_p, ARCHIVEBLOCK_MISC);
if (resending)
WRITEUINT32(save_p, gametic);
WRITEINT16(save_p, gamemap); WRITEINT16(save_p, gamemap);
WRITEINT16(save_p, gamestate); WRITEINT16(save_p, gamestate);
WRITEINT16(save_p, gametype);
{ {
UINT32 pig = 0; UINT32 pig = 0;
@ -4054,13 +4067,16 @@ static void P_NetArchiveMisc(void)
WRITEUINT8(save_p, 0x2e); WRITEUINT8(save_p, 0x2e);
} }
static inline boolean P_NetUnArchiveMisc(void) static inline boolean P_NetUnArchiveMisc(boolean reloading)
{ {
INT32 i; INT32 i;
if (READUINT32(save_p) != ARCHIVEBLOCK_MISC) if (READUINT32(save_p) != ARCHIVEBLOCK_MISC)
I_Error("Bad $$$.sav at archive block Misc"); I_Error("Bad $$$.sav at archive block Misc");
if (reloading)
gametic = READUINT32(save_p);
gamemap = READINT16(save_p); gamemap = READINT16(save_p);
// gamemap changed; we assume that its map header is always valid, // gamemap changed; we assume that its map header is always valid,
@ -4074,6 +4090,8 @@ static inline boolean P_NetUnArchiveMisc(void)
G_SetGamestate(READINT16(save_p)); G_SetGamestate(READINT16(save_p));
gametype = READINT16(save_p);
{ {
UINT32 pig = READUINT32(save_p); UINT32 pig = READUINT32(save_p);
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
@ -4087,7 +4105,7 @@ static inline boolean P_NetUnArchiveMisc(void)
tokenlist = READUINT32(save_p); tokenlist = READUINT32(save_p);
if (!P_LoadLevel(true)) if (!P_LoadLevel(true, reloading))
return false; return false;
// get the time // get the time
@ -4188,14 +4206,14 @@ void P_SaveGame(void)
P_ArchiveLuabanksAndConsistency(); P_ArchiveLuabanksAndConsistency();
} }
void P_SaveNetGame(void) void P_SaveNetGame(boolean resending)
{ {
thinker_t *th; thinker_t *th;
mobj_t *mobj; mobj_t *mobj;
INT32 i = 1; // don't start from 0, it'd be confused with a blank pointer otherwise INT32 i = 1; // don't start from 0, it'd be confused with a blank pointer otherwise
CV_SaveNetVars(&save_p); CV_SaveNetVars(&save_p);
P_NetArchiveMisc(); P_NetArchiveMisc(resending);
// Assign the mobjnumber for pointer tracking // Assign the mobjnumber for pointer tracking
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
@ -4246,10 +4264,10 @@ boolean P_LoadGame(INT16 mapoverride)
return true; return true;
} }
boolean P_LoadNetGame(void) boolean P_LoadNetGame(boolean reloading)
{ {
CV_LoadNetVars(&save_p); CV_LoadNetVars(&save_p);
if (!P_NetUnArchiveMisc()) if (!P_NetUnArchiveMisc(reloading))
return false; return false;
P_NetUnArchivePlayers(); P_NetUnArchivePlayers();
if (gamestate == GS_LEVEL) if (gamestate == GS_LEVEL)

View file

@ -22,9 +22,9 @@
// These are the load / save game routines. // These are the load / save game routines.
void P_SaveGame(void); void P_SaveGame(void);
void P_SaveNetGame(void); void P_SaveNetGame(boolean resending);
boolean P_LoadGame(INT16 mapoverride); boolean P_LoadGame(INT16 mapoverride);
boolean P_LoadNetGame(void); boolean P_LoadNetGame(boolean reloading);
mobj_t *P_FindNewPosition(UINT32 oldposition); mobj_t *P_FindNewPosition(UINT32 oldposition);

View file

@ -2776,8 +2776,6 @@ static void P_InitLevelSettings(void)
leveltime = 0; leveltime = 0;
localaiming = 0;
localaiming2 = 0;
modulothing = 0; modulothing = 0;
// special stage tokens, emeralds, and ring total // special stage tokens, emeralds, and ring total
@ -2892,6 +2890,9 @@ void P_RespawnThings(void)
P_InitLevelSettings(); P_InitLevelSettings();
localaiming = 0;
localaiming2 = 0;
P_SpawnMapThings(true); P_SpawnMapThings(true);
// restore skybox viewpoint/centerpoint if necessary, set them to defaults if we can't do that // restore skybox viewpoint/centerpoint if necessary, set them to defaults if we can't do that
@ -3386,7 +3387,7 @@ static void P_InitGametype(void)
* \param fromnetsave If true, skip some stuff because we're loading a netgame snapshot. * \param fromnetsave If true, skip some stuff because we're loading a netgame snapshot.
* \todo Clean up, refactor, split up; get rid of the bloat. * \todo Clean up, refactor, split up; get rid of the bloat.
*/ */
boolean P_LoadLevel(boolean fromnetsave) boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
{ {
// use gamemap to get map number. // use gamemap to get map number.
// 99% of the things already did, so. // 99% of the things already did, so.
@ -3456,6 +3457,9 @@ boolean P_LoadLevel(boolean fromnetsave)
players[consoleplayer].viewz = 1; players[consoleplayer].viewz = 1;
// Cancel all d_main.c fadeouts (keep fade in though). // Cancel all d_main.c fadeouts (keep fade in though).
if (reloadinggamestate)
wipegamestate = gamestate; // Don't fade if reloading the gamestate
else
wipegamestate = FORCEWIPEOFF; wipegamestate = FORCEWIPEOFF;
wipestyleflags = 0; wipestyleflags = 0;
@ -3490,7 +3494,7 @@ boolean P_LoadLevel(boolean fromnetsave)
// Let's fade to black here // Let's fade to black here
// But only if we didn't do the special stage wipe // But only if we didn't do the special stage wipe
if (rendermode != render_none && !ranspecialwipe) if (rendermode != render_none && !(ranspecialwipe || reloadinggamestate))
P_RunLevelWipe(); P_RunLevelWipe();
if (!titlemapinaction) if (!titlemapinaction)
@ -3621,7 +3625,12 @@ boolean P_LoadLevel(boolean fromnetsave)
if (!fromnetsave) if (!fromnetsave)
P_InitGametype(); P_InitGametype();
if (!reloadinggamestate)
{
P_InitCamera(); P_InitCamera();
localaiming = 0;
localaiming2 = 0;
}
// clear special respawning que // clear special respawning que
iquehead = iquetail = 0; iquehead = iquetail = 0;
@ -3632,7 +3641,7 @@ boolean P_LoadLevel(boolean fromnetsave)
P_MapEnd(); P_MapEnd();
// Remove the loading shit from the screen // Remove the loading shit from the screen
if (rendermode != render_none && !titlemapinaction) if (rendermode != render_none && !(titlemapinaction || reloadinggamestate))
F_WipeColorFill(levelfadecol); F_WipeColorFill(levelfadecol);
if (precache || dedicated) if (precache || dedicated)
@ -3670,8 +3679,8 @@ boolean P_LoadLevel(boolean fromnetsave)
#endif #endif
} }
// No render mode, stop here. // No render mode or reloading gamestate, stop here.
if (rendermode == render_none) if (rendermode == render_none || reloadinggamestate)
return true; return true;
// Title card! // Title card!

View file

@ -97,7 +97,7 @@ void P_SetupLevelSky(INT32 skynum, boolean global);
void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum); void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum);
#endif #endif
void P_RespawnThings(void); void P_RespawnThings(void);
boolean P_LoadLevel(boolean fromnetsave); boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate);
#ifdef HWRENDER #ifdef HWRENDER
void HWR_SetupLevel(void); void HWR_SetupLevel(void);
#endif #endif