From fb8795c8da9372fe2a8313c1424eff7124c675b3 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 19 Aug 2023 12:21:15 +0100 Subject: [PATCH] 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. --- src/deh_soc.c | 1 + src/dehacked.c | 2 +- src/g_game.c | 9 +-------- src/m_cond.c | 15 +++++++++++++++ src/m_cond.h | 5 ++++- src/menus/options-data-erase-1.c | 5 ++++- 6 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index 7e5613444..0194af15c 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -3007,6 +3007,7 @@ void readmaincfg(MYFILE *f, boolean mainfile) strlwr(gamedatafilename); savemoddata = true; majormods = false; + gamedata->loaded = false; // Also save a time attack folder filenamelen = strlen(gamedatafilename)-4; // Strip off the extension diff --git a/src/dehacked.c b/src/dehacked.c index c63ab376b..6d44b87fb 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -607,7 +607,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) if (gamedataadded) G_LoadGameData(); - if (gamestate == GS_TITLESCREEN) + if (gamestate == GS_MENU || gamestate == GS_TITLESCREEN) { if (introchanged) { diff --git a/src/g_game.c b/src/g_game.c index 550324341..f90b1aaec 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4863,14 +4863,7 @@ void G_LoadGameData(void) finalisegamedata: { - // 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 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); + M_FinaliseGameData(); return; } diff --git a/src/m_cond.c b/src/m_cond.c index b66ee1af8..de7a032e0 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -640,6 +640,21 @@ void M_ClearSecrets(void) 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 // ---------------------- diff --git a/src/m_cond.h b/src/m_cond.h index e93ef7857..b08ff611e 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -257,6 +257,8 @@ struct gamedata_t { // WHENEVER OR NOT WE'RE READY TO SAVE boolean loaded; + + // DEFERRED EVENTS RELATING TO CHALLENGE PROCESSING boolean deferredsave; 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_UpdateConditionSetsPending(void); -// Clearing secrets +// Gamedata clear/init void M_ClearConditionSet(UINT16 set); void M_ClearSecrets(void); void M_ClearStats(void); +void M_FinaliseGameData(void); boolean M_NotFreePlay(void); UINT16 M_CheckCupEmeralds(UINT8 difficulty); diff --git a/src/menus/options-data-erase-1.c b/src/menus/options-data-erase-1.c index a4a75202c..ac31e16e2 100644 --- a/src/menus/options-data-erase-1.c +++ b/src/menus/options-data-erase-1.c @@ -60,6 +60,9 @@ static void M_EraseDataResponse(INT32 ch) // Delete the data // see also G_LoadGameData // We do these in backwards order to prevent things from being immediately re-unlocked. + + gamedata->loaded = false; + if (optionsmenu.erasecontext & EC_TIMEATTACK) G_ClearRecords(); if (optionsmenu.erasecontext & EC_STATISTICS) @@ -67,7 +70,7 @@ static void M_EraseDataResponse(INT32 ch) if (optionsmenu.erasecontext & EC_CHALLENGES) M_ClearSecrets(); - M_UpdateUnlockablesAndExtraEmblems(false, true); + M_FinaliseGameData(); // 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)