From e3eae62af225351478de8ec0b4d2178a5c2f05c7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Jan 2020 12:59:08 +0100 Subject: [PATCH] - store CVARs non-destructively in savegames. The old method using a single string with a backslash as separator is unable to handle anything with actual backslashes in the data. It now uses a JSON object with each CVAR being a separate key. --- src/console/c_cvars.cpp | 42 +++++++++++++++++++++++++++++++++++++++++ src/console/c_cvars.h | 4 ++++ src/g_game.cpp | 10 +++++----- src/version.h | 2 +- 4 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/console/c_cvars.cpp b/src/console/c_cvars.cpp index be034dc07..a8c4dd93f 100644 --- a/src/console/c_cvars.cpp +++ b/src/console/c_cvars.cpp @@ -44,6 +44,7 @@ #include "d_player.h" #include "v_video.h" #include "d_netinf.h" +#include "serializer.h" #include "menu/menu.h" #include "vm.h" @@ -1261,6 +1262,47 @@ FString C_GetMassCVarString (uint32_t filter, bool compact) return dump; } +void C_SerializeCVars(FSerializer &arc, const char *label, uint32_t filter) +{ + FBaseCVar* cvar; + FString dump; + + if (arc.BeginObject(label)) + { + if (arc.isWriting()) + { + for (cvar = CVars; cvar != NULL; cvar = cvar->m_Next) + { + if ((cvar->Flags & filter) && !(cvar->Flags & (CVAR_NOSAVE | CVAR_IGNORE | CVAR_NOSAVEGAME))) + { + UCVarValue val = cvar->GetGenericRep(CVAR_String); + char* c = const_cast(val.String); + arc(cvar->GetName(), c); + } + } + } + else + { + for (cvar = CVars; cvar != NULL; cvar = cvar->m_Next) + { + if ((cvar->Flags & filter) && !(cvar->Flags & (CVAR_NOSAVE | CVAR_IGNORE | CVAR_NOSAVEGAME))) + { + UCVarValue val; + char *c = nullptr; + arc(cvar->GetName(), c); + if (c != nullptr) + { + val.String = c; + cvar->SetGenericRep(val, CVAR_String); + delete[] c; + } + } + } + } + arc.EndObject(); + } +} + void C_ReadCVars (uint8_t **demo_p) { char *ptr = *((char **)demo_p); diff --git a/src/console/c_cvars.h b/src/console/c_cvars.h index dc498ebb8..7a3ded1ac 100644 --- a/src/console/c_cvars.h +++ b/src/console/c_cvars.h @@ -37,6 +37,7 @@ #include "zstring.h" #include "tarray.h" +class FSerializer; /* ========================================================== @@ -168,6 +169,7 @@ private: static bool m_DoNoSet; friend FString C_GetMassCVarString (uint32_t filter, bool compact); + friend void C_SerializeCVars(FSerializer& arc, const char* label, uint32_t filter); friend void C_ReadCVars (uint8_t **demo_p); friend void C_BackupCVars (void); friend FBaseCVar *FindCVar (const char *var_name, FBaseCVar **prev); @@ -191,6 +193,8 @@ void C_WriteCVars (uint8_t **demo_p, uint32_t filter, bool compact=false); // Read all cvars from *demo_p and set them appropriately. void C_ReadCVars (uint8_t **demo_p); +void C_SerializeCVars(FSerializer& arc, const char* label, uint32_t filter); + // Backup demo cvars. Called before a demo starts playing to save all // cvars the demo might change. void C_BackupCVars (void); diff --git a/src/g_game.cpp b/src/g_game.cpp index 389d86155..21d692ac8 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1925,6 +1925,10 @@ void G_DoLoadGame () uint8_t *vars_p = (uint8_t *)cvar.GetChars(); C_ReadCVars(&vars_p); } + else + { + C_SerializeCVars(arc, "servercvars", CVAR_SERVERINFO); + } uint32_t time[2] = { 1,0 }; @@ -2286,11 +2290,7 @@ void G_DoSaveGame (bool okForQuicksave, bool forceQuicksave, FString filename, c // Intermission stats for hubs G_SerializeHub(savegameglobals); - - { - FString vars = C_GetMassCVarString(CVAR_SERVERINFO); - savegameglobals.AddString("importantcvars", vars.GetChars()); - } + C_SerializeCVars(savegameglobals, "servercvars", CVAR_SERVERINFO); if (level.time != 0 || level.maptime != 0) { diff --git a/src/version.h b/src/version.h index 19f5263a1..de564c2ff 100644 --- a/src/version.h +++ b/src/version.h @@ -88,7 +88,7 @@ const char *GetVersionString(); // Use 4500 as the base git save version, since it's higher than the // SVN revision ever got. -#define SAVEVER 4556 +#define SAVEVER 4557 // This is so that derivates can use the same savegame versions without worrying about engine compatibility #define GAMESIG "GZDOOM"