Merge branch 'dump-consistency-for-the-modern-age' into 'master'

DUMPCONSISTENCY for the modern age

See merge request KartKrew/Kart!2483
This commit is contained in:
Sal 2024-10-25 17:48:21 +00:00
commit 8ff2e13c7d
7 changed files with 73 additions and 67 deletions

View file

@ -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);
@ -623,7 +620,6 @@ consvar_t cv_maxsend = NetVar("maxsend", "51200").min_max(0, 51200);
consvar_t cv_noticedownload = NetVar("noticedownload", "Off").on_off();
consvar_t cv_pingtimeout = NetVar("maxdelaytimeout", "10").min_max(8, 120);
consvar_t cv_resynchattempts = NetVar("resynchattempts", "2").min_max(1, 20, {{0, "No"}});
consvar_t cv_showjoinaddress = NetVar("showjoinaddress", "Off").on_off();
consvar_t cv_zvote_delay = NetVar("zvote_delay", "20").values(CV_Unsigned);

View file

@ -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;
}
@ -5132,32 +5151,21 @@ static void HandlePacketFromPlayer(SINT8 node)
&& !resendingsavegame[node] && savegameresendcooldown[node] <= I_GetTime()
&& !SV_ResendingSavegameToAnyone())
{
if (cv_resynchattempts.value)
{
// Tell the client we are about to resend them the gamestate
netbuffer->packettype = PT_WILLRESENDGAMESTATE;
HSendPacket(node, true, 0, 0);
// Tell the client we are about to resend them the gamestate
netbuffer->packettype = PT_WILLRESENDGAMESTATE;
HSendPacket(node, true, 0, 0);
resendingsavegame[node] = true;
resendingsavegame[node] = true;
if (cv_blamecfail.value)
CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"),
netconsole+1, player_names[netconsole],
consistancy[realstart%BACKUPTICS],
SHORT(netbuffer->u.clientpak.consistancy));
DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n",
netconsole, realstart, consistancy[realstart%BACKUPTICS],
SHORT(netbuffer->u.clientpak.consistancy)));
break;
}
else
{
SendKick(netconsole, KICK_MSG_CON_FAIL);
DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n",
netconsole, realstart, consistancy[realstart%BACKUPTICS],
SHORT(netbuffer->u.clientpak.consistancy)));
break;
}
if (cv_blamecfail.value)
CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"),
netconsole+1, player_names[netconsole],
consistancy[realstart%BACKUPTICS],
SHORT(netbuffer->u.clientpak.consistancy));
DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n",
netconsole, realstart, consistancy[realstart%BACKUPTICS],
SHORT(netbuffer->u.clientpak.consistancy)));
break;
}
break;
case PT_BASICKEEPALIVE:

View file

@ -565,7 +565,7 @@ extern boolean server_lagless;
extern consvar_t cv_mindelay;
extern consvar_t cv_netticbuffer, cv_allownewplayer, cv_maxconnections, cv_joindelay;
extern consvar_t cv_pingtimeout, cv_resynchattempts, cv_blamecfail;
extern consvar_t cv_pingtimeout, cv_blamecfail;
extern consvar_t cv_maxsend, cv_noticedownload, cv_downloadspeed;
#ifdef VANILLAJOINNEXTROUND

View file

@ -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

View file

@ -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.

View file

@ -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);

View file

@ -27,9 +27,6 @@ menuitem_t OPTIONS_ServerAdvanced[] =
{IT_HEADER, "Network Connection", NULL,
NULL, {NULL}, 0, 0},
{IT_STRING | IT_CVAR, "Resynch. Attempts", "How many times to attempt sending data to desynchronized players.",
NULL, {.cvar = &cv_resynchattempts}, 0, 0},
{IT_STRING | IT_CVAR, "Delay Limit (tics)", "Players above the delay limit will get kicked from the server.",
NULL, {.cvar = &cv_maxping}, 0, 0},