M_FinaliseGameData

Creates a central landing point where gamedata loads/creates can be finalised properly.

In addition, gamedata wipes caused by data erase or custom SOC gamedata can no longer be saved in a partway corrupted state if they were to crash midway through.
This commit is contained in:
toaster 2023-08-19 12:21:15 +01:00
parent 7f89bee3f2
commit fb8795c8da
6 changed files with 26 additions and 11 deletions

View file

@ -3007,6 +3007,7 @@ void readmaincfg(MYFILE *f, boolean mainfile)
strlwr(gamedatafilename); strlwr(gamedatafilename);
savemoddata = true; savemoddata = true;
majormods = false; majormods = false;
gamedata->loaded = false;
// Also save a time attack folder // Also save a time attack folder
filenamelen = strlen(gamedatafilename)-4; // Strip off the extension filenamelen = strlen(gamedatafilename)-4; // Strip off the extension

View file

@ -607,7 +607,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
if (gamedataadded) if (gamedataadded)
G_LoadGameData(); G_LoadGameData();
if (gamestate == GS_TITLESCREEN) if (gamestate == GS_MENU || gamestate == GS_TITLESCREEN)
{ {
if (introchanged) if (introchanged)
{ {

View file

@ -4863,14 +4863,7 @@ void G_LoadGameData(void)
finalisegamedata: finalisegamedata:
{ {
// Don't consider loaded until it's a success! M_FinaliseGameData();
// It used to do this much earlier, but this would cause the gamedata to
// save over itself when it I_Errors from the corruption landing point below,
// which can accidentally delete players' legitimate data if the code ever has any tiny mistakes!
gamedata->loaded = true;
// Silent update unlockables in case they're out of sync with conditions
M_UpdateUnlockablesAndExtraEmblems(false, true);
return; return;
} }

View file

@ -640,6 +640,21 @@ void M_ClearSecrets(void)
gamedata->chaokeys = 3; // Start with 3 !! gamedata->chaokeys = 3; // Start with 3 !!
} }
void M_FinaliseGameData(void)
{
//M_PopulateChallengeGrid(); -- This can be done lazily when we actually need it
// Don't consider loaded until it's a success!
// It used to do this much earlier, but this would cause the gamedata
// to save over itself when it I_Errors from corruption, which can
// accidentally delete players' legitimate data if the code ever has
// any tiny mistakes!
gamedata->loaded = true;
// Silent update unlockables in case they're out of sync with conditions
M_UpdateUnlockablesAndExtraEmblems(false, true);
}
// ---------------------- // ----------------------
// Condition set checking // Condition set checking
// ---------------------- // ----------------------

View file

@ -257,6 +257,8 @@ struct gamedata_t
{ {
// WHENEVER OR NOT WE'RE READY TO SAVE // WHENEVER OR NOT WE'RE READY TO SAVE
boolean loaded; boolean loaded;
// DEFERRED EVENTS RELATING TO CHALLENGE PROCESSING
boolean deferredsave; boolean deferredsave;
boolean deferredconditioncheck; boolean deferredconditioncheck;
@ -338,10 +340,11 @@ char *M_BuildConditionSetString(UINT16 unlockid);
void M_AddRawCondition(UINT16 set, UINT8 id, conditiontype_t c, INT32 r, INT16 x1, INT16 x2, char *stringvar); void M_AddRawCondition(UINT16 set, UINT8 id, conditiontype_t c, INT32 r, INT16 x1, INT16 x2, char *stringvar);
void M_UpdateConditionSetsPending(void); void M_UpdateConditionSetsPending(void);
// Clearing secrets // Gamedata clear/init
void M_ClearConditionSet(UINT16 set); void M_ClearConditionSet(UINT16 set);
void M_ClearSecrets(void); void M_ClearSecrets(void);
void M_ClearStats(void); void M_ClearStats(void);
void M_FinaliseGameData(void);
boolean M_NotFreePlay(void); boolean M_NotFreePlay(void);
UINT16 M_CheckCupEmeralds(UINT8 difficulty); UINT16 M_CheckCupEmeralds(UINT8 difficulty);

View file

@ -60,6 +60,9 @@ static void M_EraseDataResponse(INT32 ch)
// Delete the data // Delete the data
// see also G_LoadGameData // see also G_LoadGameData
// We do these in backwards order to prevent things from being immediately re-unlocked. // We do these in backwards order to prevent things from being immediately re-unlocked.
gamedata->loaded = false;
if (optionsmenu.erasecontext & EC_TIMEATTACK) if (optionsmenu.erasecontext & EC_TIMEATTACK)
G_ClearRecords(); G_ClearRecords();
if (optionsmenu.erasecontext & EC_STATISTICS) if (optionsmenu.erasecontext & EC_STATISTICS)
@ -67,7 +70,7 @@ static void M_EraseDataResponse(INT32 ch)
if (optionsmenu.erasecontext & EC_CHALLENGES) if (optionsmenu.erasecontext & EC_CHALLENGES)
M_ClearSecrets(); M_ClearSecrets();
M_UpdateUnlockablesAndExtraEmblems(false, true); M_FinaliseGameData();
// Don't softlock the Stereo on if you won't be able to access it anymore!? // Don't softlock the Stereo on if you won't be able to access it anymore!?
if (soundtest.playing && M_SecretUnlocked(SECRET_SOUNDTEST, true) == false) if (soundtest.playing && M_SecretUnlocked(SECRET_SOUNDTEST, true) == false)