Added UUID for game sessions

Allows the SavegameManager to destroy all saves related to the current UUID session so hardcore mods can enforce this safely instead of needing to go nuclear.
This commit is contained in:
Boondorl 2025-07-20 14:00:05 -04:00 committed by Ricardo Luís Vaz Silva
commit 66c5beccbd
8 changed files with 52 additions and 0 deletions

View file

@ -6,6 +6,7 @@
#include "gstrings.h"
#include "version.h"
#include "m_argv.h"
#include "m_random.h"
static_assert(sizeof(void*) == 8,
"Only LP64/LLP64 builds are officially supported. "
@ -182,3 +183,12 @@ int FStartupSelectionInfo::SaveInfo()
return DefaultIWAD;
}
FString GameUUID;
static FRandom pr_uuid("GameUUID");
FString GenerateUUID()
{
FString uuid;
uuid.AppendFormat("%08X-%04X-4%03X-9%03X-%08X%04X", pr_uuid.GenRand32(), pr_uuid(UINT16_MAX), pr_uuid(4095), pr_uuid(4095), pr_uuid.GenRand32(), pr_uuid(UINT16_MAX));
return uuid;
}

View file

@ -13,6 +13,9 @@ class FConfigFile;
class FArgs;
struct FTranslationID;
extern FString GameUUID;
FString GenerateUUID();
struct SystemCallbacks
{
bool (*G_Responder)(event_t* ev); // this MUST be set, otherwise nothing will work

View file

@ -48,6 +48,7 @@
#include "savegamemanager.h"
#include "m_argv.h"
#include "i_specialpaths.h"
#include "i_interface.h"
CVAR(String, save_dir, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_SYSTEM_ONLY);
FString SavegameFolder;
@ -191,6 +192,7 @@ void FSavegameManagerBase::NotifyNewSave(const FString &file, const FString &tit
{
node->SaveTitle = title;
node->CreationTime = myasctime();
node->UUID = GameUUID;
node->bOldVersion = false;
node->bMissingWads = false;
@ -210,6 +212,7 @@ void FSavegameManagerBase::NotifyNewSave(const FString &file, const FString &tit
auto node = new FSaveGameNode;
node->SaveTitle = title;
node->CreationTime = myasctime();
node->UUID = GameUUID;
node->Filename = file;
node->bOldVersion = false;
node->bMissingWads = false;
@ -560,6 +563,27 @@ bool FSavegameManagerBase::RemoveNewSaveNode()
return false;
}
int FSavegameManagerBase::RemoveUUIDSaveSlots()
{
if (GameUUID.IsEmpty())
return -1;
// Make sure there's any saves in the list first.
if (!SaveGames.Size())
ReadSaveStrings();
int index = -1;
for (int i = SaveGames.Size() - 1; i >= 0; --i)
{
auto& save = SaveGames[i];
if (save == &NewSaveNode || save->UUID.Compare(GameUUID))
continue;
index = RemoveSaveSlot(i);
}
return index;
}
DEFINE_ACTION_FUNCTION(FSavegameManager, RemoveNewSaveNode)
{
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManagerBase);
@ -581,9 +605,15 @@ DEFINE_ACTION_FUNCTION(FSavegameManager, ExtractSaveData)
ACTION_RETURN_INT(self->ExtractSaveData(sel));
}
DEFINE_ACTION_FUNCTION(FSavegameManager, RemoveUUIDSaveSlots)
{
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManagerBase);
ACTION_RETURN_INT(self->RemoveUUIDSaveSlots());
}
DEFINE_FIELD(FSaveGameNode, SaveTitle);
DEFINE_FIELD(FSaveGameNode, Filename);
DEFINE_FIELD(FSaveGameNode, UUID);
DEFINE_FIELD(FSaveGameNode, bOldVersion);
DEFINE_FIELD(FSaveGameNode, bMissingWads);
DEFINE_FIELD(FSaveGameNode, bNoDelete);

View file

@ -12,6 +12,7 @@ struct FSaveGameNode
FString SaveTitle;
FString Filename;
FString CreationTime;
FString UUID;
bool bOldVersion = false;
bool bMissingWads = false;
bool bNoDelete = false;
@ -57,6 +58,7 @@ public:
FSaveGameNode *GetSavegame(int i);
void InsertNewSaveNode();
bool RemoveNewSaveNode();
int RemoveUUIDSaveSlots();
};

View file

@ -2009,6 +2009,7 @@ void G_DoLoadGame ()
arc("Save Version", SaveVersion);
arc("Engine", engine);
arc("Current Map", map);
arc("GameUUID", GameUUID);
if (engine.CompareNoCase(GAMESIG) != 0)
{
@ -2386,6 +2387,7 @@ void G_DoSaveGame (bool okForQuicksave, bool forceQuicksave, FString filename, c
savegameinfo.AddString("Software", buf)
.AddString("Engine", GAMESIG)
("Save Version", ver)
("GameUUID", GameUUID)
.AddString("Title", description)
.AddString("Current Map", primaryLevel->MapName.GetChars());

View file

@ -636,6 +636,7 @@ void G_InitNew (const char *mapname, bool bTitleLevel)
players[i].playerstate = PST_ENTER; // [BC]
STAT_StartNewGame(mapname);
GameUUID = GenerateUUID();
}
usergame = !bTitleLevel; // will be set false if a demo

View file

@ -102,6 +102,7 @@ void FSavegameManager::ReadSaveStrings()
FString iwad = arc.GetString("Game WAD");
FString title = arc.GetString("Title");
FString creationtime = arc.GetString("Creation Time");
FString uuid = arc.GetString("GameUUID");
if (engine.Compare(GAMESIG) != 0 || savever > SAVEVER)
@ -128,6 +129,7 @@ void FSavegameManager::ReadSaveStrings()
FSaveGameNode *node = new FSaveGameNode;
node->Filename = entry.FilePath.c_str();
node->UUID = uuid;
node->bOldVersion = oldVer;
node->bMissingWads = missing;
node->SaveTitle = title;