Skip to content

Commit

Permalink
- store CVARs non-destructively in savegames.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
coelckers committed Jan 12, 2020
1 parent 3e9a43d commit e3eae62
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 6 deletions.
42 changes: 42 additions & 0 deletions src/console/c_cvars.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -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<char*>(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);
Expand Down
4 changes: 4 additions & 0 deletions src/console/c_cvars.h
Expand Up @@ -37,6 +37,7 @@
#include "zstring.h"
#include "tarray.h"

class FSerializer;
/*
==========================================================
Expand Down Expand Up @@ -168,6 +169,7 @@ class FBaseCVar
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);
Expand All @@ -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);
Expand Down
10 changes: 5 additions & 5 deletions src/g_game.cpp
Expand Up @@ -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 };

Expand Down Expand Up @@ -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)
{
Expand Down
2 changes: 1 addition & 1 deletion src/version.h
Expand Up @@ -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"
Expand Down

0 comments on commit e3eae62

Please sign in to comment.