From 73e0e4b17a340884ca4a269da4256ecfcac68dec Mon Sep 17 00:00:00 2001 From: Steve Date: Tue, 24 Apr 2018 08:27:42 +0100 Subject: [PATCH] Attempt to save the game and world data atomically. --- src/game/game.c | 11 +++++++++-- src/game/title.c | 2 +- src/game/title.h | 2 +- src/hub/hub.c | 4 ++-- src/hub/hub.h | 2 +- src/hub/postMission.c | 39 ++++++++++++++++++++++++++++----------- src/hub/postMission.h | 4 +++- src/system/io.c | 5 +++++ src/test/worldTest.c | 2 +- src/test/worldTest.h | 2 +- src/world/worldSaver.c | 2 +- 11 files changed, 53 insertions(+), 22 deletions(-) diff --git a/src/game/game.c b/src/game/game.c index 23e882e..5e5973e 100644 --- a/src/game/game.c +++ b/src/game/game.c @@ -345,7 +345,7 @@ void loadGame(int slot) free(filename); } -void saveGame(void) +void saveGame(int isTempFile) { cJSON *root, *statsJSON, *keysJSON, *keyJSON, *missionsJSON, *missionJSON, *trophiesJSON, *trophyJSON; char *filename, *out; @@ -353,7 +353,14 @@ void saveGame(void) Trophy *trophy; int i; - filename = buildFormattedString("%s/%d/game.json", app.saveDir, game.saveSlot); + if (!isTempFile) + { + filename = buildFormattedString("%s/%d/game.json", app.saveDir, game.saveSlot); + } + else + { + filename = buildFormattedString("%s/%d/game.json.tmp", app.saveDir, game.saveSlot); + } SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Saving game to '%s' ...", filename); diff --git a/src/game/title.c b/src/game/title.c index 4ee9be3..e8c6147 100644 --- a/src/game/title.c +++ b/src/game/title.c @@ -339,7 +339,7 @@ static void doOK(void) game.saveSlot = saveSlot; - saveGame(); + saveGame(0); } static void doCancel(void) diff --git a/src/game/title.h b/src/game/title.h index f971b42..54dee3e 100644 --- a/src/game/title.h +++ b/src/game/title.h @@ -49,7 +49,7 @@ extern void loadGame(int slot); extern void loadMusic(char *filename); extern void newGame(void); extern void playMusic(int loop); -extern void saveGame(void); +extern void saveGame(int isTempFile); extern void setSelectedWidget(char *name, char *group); extern void showWidgetGroup(char *group); extern void startSectionTransition(void); diff --git a/src/hub/hub.c b/src/hub/hub.c index 3431dc8..4c9c25e 100644 --- a/src/hub/hub.c +++ b/src/hub/hub.c @@ -596,7 +596,7 @@ static void startMission(void) { STRNCPY(game.worldId, selectedMission->id, MAX_NAME_LENGTH); - saveGame(); + saveGame(0); stopMusic(); @@ -764,7 +764,7 @@ static void awardMissionTrophies(void) if (save) { - saveGame(); + saveGame(0); } } diff --git a/src/hub/hub.h b/src/hub/hub.h index 4af4c57..565c988 100644 --- a/src/hub/hub.h +++ b/src/hub/hub.h @@ -67,7 +67,7 @@ extern void playMusic(int loop); extern void playSound(int snd, int ch); extern double randF(void); extern char *readFile(const char *filename); -extern void saveGame(void); +extern void saveGame(int isTempFile); extern void scrollBackground(float x, float y); extern Widget *selectWidgetAt(int x, int y); extern void showWidgetGroup(char *group); diff --git a/src/hub/postMission.c b/src/hub/postMission.c index 19a0713..5a4a9dd 100644 --- a/src/hub/postMission.c +++ b/src/hub/postMission.c @@ -24,6 +24,7 @@ static void logic(void); static void draw(void); static void updateMissionStatus(void); static int getPostMissionStatus(void); +static void saveGameAndWorld(void); static int status; static float missionCompleteY; @@ -43,9 +44,7 @@ void initPostMission(void) if (world.state == WS_GAME_COMPLETE) { - saveGame(); - - saveWorld(); + saveGameAndWorld(); destroyWorld(); @@ -66,9 +65,7 @@ void initPostMission(void) app.delegate.logic = &logic; app.delegate.draw = &draw; - saveGame(); - - saveWorld(); + saveGameAndWorld(); endSectionTransition(); } @@ -76,26 +73,46 @@ void initPostMission(void) { if (world.isReturnVisit) { - saveWorld(); + saveGameAndWorld(); } else { restoreGameState(); + + saveGame(0); } - saveGame(); - destroyWorld(); initHub(); } } +static void saveGameAndWorld(void) +{ + char *src, *dest; + + saveGame(1); + + saveWorld(); + + src = buildFormattedString("%s/%d/%s.json.tmp", app.saveDir, game.saveSlot, world.id); + dest = buildFormattedString("%s/%d/%s.json", app.saveDir, game.saveSlot, world.id); + renameFile(src, dest); + + src = buildFormattedString("%s/%d/game.json.tmp", app.saveDir, game.saveSlot); + dest = buildFormattedString("%s/%d/game.json", app.saveDir, game.saveSlot, world.id); + renameFile(src, dest); + + free(src); + free(dest); +} + void retryMission(void) { restoreGameState(); - saveGame(); + saveGame(0); initWorld(); } @@ -104,7 +121,7 @@ void returnToHub(void) { restoreGameState(); - saveGame(); + saveGame(0); destroyWorld(); diff --git a/src/hub/postMission.h b/src/hub/postMission.h index 6868ff3..0303399 100644 --- a/src/hub/postMission.h +++ b/src/hub/postMission.h @@ -34,9 +34,11 @@ extern int isAcceptControl(void); extern float limit(float i, float low, float high); extern void playSound(int snd, int ch); extern void restoreGameState(void); -extern void saveGame(void); +extern void saveGame(int isTempFile); extern void saveWorld(void); extern void startSectionTransition(void); +extern char *buildFormattedString(const char *format, ...); +extern int renameFile(char *src, char *dest); extern App app; extern Colors colors; diff --git a/src/system/io.c b/src/system/io.c index 9b50b6d..881b607 100644 --- a/src/system/io.c +++ b/src/system/io.c @@ -200,6 +200,11 @@ int deleteFile(char *path) return unlink(path) == 0; } +int renameFile(char *src, char *dest) +{ + return rename(src, dest) == 0; +} + static int stringComparator(const void *a, const void *b) { char **s1 = (char **)a; diff --git a/src/test/worldTest.c b/src/test/worldTest.c index 9bc1b6a..ec71e8d 100644 --- a/src/test/worldTest.c +++ b/src/test/worldTest.c @@ -24,7 +24,7 @@ void initWorldTest(char *worldId) { loadGame(0); - saveGame(); + saveGame(0); if (worldId != NULL) { diff --git a/src/test/worldTest.h b/src/test/worldTest.h index 167b3f7..70bd3da 100644 --- a/src/test/worldTest.h +++ b/src/test/worldTest.h @@ -23,6 +23,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern void initHub(void); extern void initWorld(void); extern void loadGame(int slot); -extern void saveGame(void); +extern void saveGame(int isTempFile); extern Game game; diff --git a/src/world/worldSaver.c b/src/world/worldSaver.c index fa319de..d7d9a55 100644 --- a/src/world/worldSaver.c +++ b/src/world/worldSaver.c @@ -32,7 +32,7 @@ void saveWorld(void) cJSON *root; char *filename, *out; - filename = buildFormattedString("%s/%d/%s.json", app.saveDir, game.saveSlot, world.id); + filename = buildFormattedString("%s/%d/%s.json.tmp", app.saveDir, game.saveSlot, world.id); SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Saving world to '%s' ...", filename);