diff --git a/src/cvars.cpp b/src/cvars.cpp index de8859f4a..32dffe32e 100644 --- a/src/cvars.cpp +++ b/src/cvars.cpp @@ -244,10 +244,6 @@ X (cvlist_timer); X (cvlist_execversion); -#ifdef DUMPCONSISTENCY - X (cvlist_dumpconsistency); -#endif - #undef X namespace @@ -602,9 +598,10 @@ consvar_t cv_blamecfail = NetVar("blamecfail", "Off").on_off(); // Speed of file downloading (in packets per tic) consvar_t cv_downloadspeed = NetVar("downloadspeed", "32").min_max(1, 300); -#ifdef DUMPCONSISTENCY - consvar_t cv_dumpconsistency = NetVar(cvlist_dumpconsistency)("dumpconsistency", "Off").on_off(); -#endif +// Dump gamestates to an external file when a resync occurs. +// This is a cheat because enabling this can take up file storage +// for connected players very fast. +consvar_t cv_dumpconsistency = OnlineCheat("dumpconsistency", "Off").on_off(); // Intermission time Tails 04-19-2002 consvar_t cv_inttime = NetVar("inttime", "10").min_max(0, 3600); diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 30e4fe110..0ddb7ddcb 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1317,26 +1317,18 @@ static void SV_SendSaveGame(INT32 node, boolean resending) freezetimeout[node] = I_GetTime() + jointimeout + length / 1024; // 1 extra tic for each kilobyte } -#ifdef DUMPCONSISTENCY -#define TMPSAVENAME "badmath.sav" - -static void SV_SavedGame(void) +static void CL_DumpConsistency(const char *file_name) { - extern consvar_t *cv_dumpconsistency; - size_t length; savebuffer_t save = {0}; - char tmpsave[256]; + char tmpsave[1024]; - if (!cv_dumpconsistency.value) - return; - - sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); + snprintf(tmpsave, sizeof(tmpsave), "%s" PATHSEP "%s", srb2home, file_name); // first save it in a malloced buffer if (P_SaveBufferAlloc(&save, NETSAVEGAMESIZE) == false) { - CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); + CONS_Alert(CONS_ERROR, M_GetText("No more free memory for consistency dump\n")); return; } @@ -1346,21 +1338,18 @@ static void SV_SavedGame(void) if (length > NETSAVEGAMESIZE) { P_SaveBufferFree(&save); - I_Error("Savegame buffer overrun"); + I_Error("Consistency dump buffer overrun"); } // then save it! if (!FIL_WriteFile(tmpsave, save.buffer, length)) - CONS_Printf(M_GetText("Didn't save %s for netgame"), tmpsave); + CONS_Printf(M_GetText("Didn't save %s for consistency dump"), tmpsave); P_SaveBufferFree(&save); } -#undef TMPSAVENAME -#endif #define TMPSAVENAME "$$$.sav" - static void CL_LoadReceivedSavegame(boolean reloading) { savebuffer_t save = {0}; @@ -1451,8 +1440,13 @@ static void CL_LoadReceivedSavegame(boolean reloading) static void CL_ReloadReceivedSavegame(void) { - INT32 i; + extern consvar_t cv_dumpconsistency; + if (cv_dumpconsistency.value) + { + CL_DumpConsistency("TEMP.consdump"); + } + INT32 i; for (i = 0; i < MAXPLAYERS; i++) { LUA_InvalidatePlayer(&players[i]); @@ -1478,6 +1472,26 @@ static void CL_ReloadReceivedSavegame(void) cl_redownloadinggamestate = false; CONS_Printf(M_GetText("Game state reloaded\n")); + + if (cv_dumpconsistency.value) + { + // This is dumb, but we want the file names + // to be pairable together with the server's + // version, and gametic being randomly off + // is a deal breaker. + char dump_name[1024]; + snprintf( + dump_name, sizeof(dump_name), + "%s_%u_%s-client.consdump", + server_context, + gametic, + player_names[consoleplayer] + ); + if (FIL_RenameFile("TEMP.consdump", dump_name) == false) + { + CONS_Alert(CONS_WARNING, "Failed to rename temporary consdump file.\n"); + } + } } static void SendAskInfo(INT32 node) @@ -3074,9 +3088,6 @@ static void Got_KickCmd(const UINT8 **p, INT32 playernum) if (playernode[pnum] == playernode[consoleplayer]) { -#ifdef DUMPCONSISTENCY - if (msg == KICK_MSG_CON_FAIL) SV_SavedGame(); -#endif LUA_HookBool(false, HOOK(GameQuit)); //Lua hooks handled differently now Command_ExitGame_f(); @@ -3283,12 +3294,6 @@ void D_ClientServerInit(void) RegisterNetXCmd(XD_ADDPLAYER, Got_AddPlayer); RegisterNetXCmd(XD_REMOVEPLAYER, Got_RemovePlayer); RegisterNetXCmd(XD_ADDBOT, Got_AddBot); -#ifdef DUMPCONSISTENCY - { - extern struct CVarList *cvlist_dumpconsistency; - CV_RegisterList(cvlist_dumpconsistency); - } -#endif gametic = 0; localgametic = 0; @@ -4361,7 +4366,7 @@ static void HandleServerInfo(SINT8 node) static void PT_WillResendGamestate(void) { - char tmpsave[256]; + char tmpsave[1024]; if (server || cl_redownloadinggamestate) return; @@ -4400,6 +4405,20 @@ static void PT_CanReceiveGamestate(SINT8 node) CONS_Printf(M_GetText("Resending game state to %s...\n"), player_names[nodetoplayer[node]]); + extern consvar_t cv_dumpconsistency; + if (cv_dumpconsistency.value) + { + char dump_name[1024]; + snprintf( + dump_name, sizeof(dump_name), + "%s_%u_%s-server.consdump", + server_context, + gametic, + player_names[nodetoplayer[node]] + ); + CL_DumpConsistency(dump_name); + } + SV_SendSaveGame(node, true); // Resend a complete game state resendingsavegame[node] = true; } diff --git a/src/doomdef.h b/src/doomdef.h index 3b0df2279..62a482f4b 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -663,9 +663,6 @@ extern int // None of these that are disabled in the normal build are guaranteed to work perfectly // Compile them at your own risk! -/// Dumps the contents of a network save game upon consistency failure for debugging. -//#define DUMPCONSISTENCY - /// Who put weights on my recycler? ... Inuyasha did. /// \note XMOD port. //#define WEIGHTEDRECYCLER diff --git a/src/m_misc.cpp b/src/m_misc.cpp index 9b488b93c..582455b35 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -341,6 +341,12 @@ boolean FIL_ConvertTextFileToBinary(const char *textfilename, const char *binfil return success; } +boolean FIL_RenameFile(char const *old_name, char const *new_name) +{ + int result = rename(old_name, new_name); + return (result == 0); +} + /** Check if the filename exists * * \param name Filename to check. diff --git a/src/m_misc.h b/src/m_misc.h index 4ef377074..75bb4a5c8 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -90,6 +90,8 @@ size_t FIL_ReadFileTag(char const *name, UINT8 **buffer, INT32 tag); boolean FIL_ConvertTextFileToBinary(const char *textfilename, const char *binfilename); +boolean FIL_RenameFile(const char *old_name, const char *new_name); + boolean FIL_FileExists(const char *name); boolean FIL_WriteFileOK(char const *name); boolean FIL_ReadFileOK(char const *name);