From 66e23fcb3d2beb13e9cd33be07ef3f225567a332 Mon Sep 17 00:00:00 2001 From: danij Date: Mon, 17 Feb 2014 11:11:42 +0000 Subject: [PATCH] libcommon|GameStateWriter|GameStateReader: Continued cleaning up savegame file management --- doomsday/libdeng1/src/writer.c | 1 + doomsday/plugins/common/include/saveslots.h | 9 +++-- .../plugins/common/src/gamestatereader.cpp | 38 ++++++++---------- .../plugins/common/src/gamestatewriter.cpp | 10 ++++- .../plugins/common/src/mapstatereader.cpp | 20 +++++++++- .../plugins/common/src/mapstatewriter.cpp | 13 +++++- doomsday/plugins/common/src/p_saveg.cpp | 15 ++++--- doomsday/plugins/common/src/saveinfo.cpp | 2 +- doomsday/plugins/common/src/saveslots.cpp | 40 ++++++++++--------- 9 files changed, 92 insertions(+), 56 deletions(-) diff --git a/doomsday/libdeng1/src/writer.c b/doomsday/libdeng1/src/writer.c index d19558fa8a..aaa8bed691 100644 --- a/doomsday/libdeng1/src/writer.c +++ b/doomsday/libdeng1/src/writer.c @@ -142,6 +142,7 @@ Writer *Writer_NewWithCallbacks(Writer_Callback_WriteInt8 writeInt8, void Writer_Delete(Writer *writer) { + if(!writer) return; if(writer->isDynamic) { // The buffer was allocated by us. diff --git a/doomsday/plugins/common/include/saveslots.h b/doomsday/plugins/common/include/saveslots.h index a1ca14884b..6357d68f1e 100644 --- a/doomsday/plugins/common/include/saveslots.h +++ b/doomsday/plugins/common/include/saveslots.h @@ -148,14 +148,16 @@ class SaveSlots void copySlot(int sourceSlot, int destSlot); /** - * Compose the (possibly relative) file path to the game state associated with save @a slot. + * Compose the (possibly relative) file path to the map state associated with save @a slot. * * @param slot Slot to compose the identifier of. - * @param map If @c >= 0 include this logical map index in the composed path. + * @param map Logical map index. * * @return The composed path if reachable (else a zero-length string). */ - AutoStr *composeSavePathForSlot(int slot, int map = -1) const; + AutoStr *composeMapSavePathForSlot(int slot, uint map) const; + + AutoStr *composeSavePathForSlot(int slot) const; /** * Register the console commands and variables of this module. @@ -194,7 +196,6 @@ SaveInfo *SaveSlots_SaveInfo(SaveSlots *sslots, int slot); void SaveSlots_ReplaceSaveInfo(SaveSlots *sslots, int slot, SaveInfo *newInfo); void SaveSlots_ClearSlot(SaveSlots *sslots, int slot); void SaveSlots_CopySlot(SaveSlots *sslots, int sourceSlot, int destSlot); -AutoStr *SaveSlots_ComposeSavePathForSlot(SaveSlots const *sslots, int slot, int map); void SaveSlots_ConsoleRegister(); diff --git a/doomsday/plugins/common/src/gamestatereader.cpp b/doomsday/plugins/common/src/gamestatereader.cpp index 78919a17a6..bb9a60a2c2 100644 --- a/doomsday/plugins/common/src/gamestatereader.cpp +++ b/doomsday/plugins/common/src/gamestatereader.cpp @@ -33,7 +33,7 @@ DENG2_PIMPL(GameStateReader) { - SaveInfo *saveInfo; ///< Info for the save state to be read. + SaveInfo *saveInfo; ///< Info for the save state to be read. Not owned. Reader *reader; dd_bool loaded[MAXPLAYERS]; dd_bool infile[MAXPLAYERS]; @@ -47,6 +47,11 @@ DENG2_PIMPL(GameStateReader) de::zap(infile); } + ~Instance() + { + Reader_Delete(reader); + } + /// Assumes the reader is currently positioned at the start of the stream. void seekToGameState() { @@ -105,10 +110,9 @@ DENG2_PIMPL(GameStateReader) #if __JHEXEN__ // The map state is actually read from a separate file. // Close the game state file. Z_Free(saveBuffer); - SV_CloseFile(); // Open the map state file. - AutoStr *path = saveSlots->composeSavePathForSlot(BASE_SLOT, gameMap + 1); + AutoStr *path = saveSlots->composeMapSavePathForSlot(BASE_SLOT, gameMap); if(!SV_OpenMapSaveFile(path)) { throw FileAccessError("GameStateReader", "Failed opening \"" + de::String(Str_Text(path)) + "\""); @@ -120,9 +124,11 @@ DENG2_PIMPL(GameStateReader) readConsistencyBytes(); #if __JHEXEN__ Z_Free(saveBuffer); - SV_ClearTargetPlayers(); #else SV_CloseFile(); +#endif +#if __JHEXEN__ + SV_ClearTargetPlayers(); #endif } @@ -208,17 +214,19 @@ DENG2_PIMPL(GameStateReader) { for(int i = 0; i < MAXPLAYERS; ++i) { - dd_bool notLoaded = false; + bool notLoaded = false; #if __JHEXEN__ if(players[i].plr->inGame) { // Try to find a saved player that corresponds this one. - uint k; + int k; for(k = 0; k < MAXPLAYERS; ++k) { if(saveToRealPlayerNum[k] == i) + { break; + } } if(k < MAXPLAYERS) continue; // Found; don't bother this player. @@ -269,29 +277,15 @@ GameStateReader::~GameStateReader() bool GameStateReader::recognize(SaveInfo &info, Str const *path) // static { - DENG_ASSERT(path != 0); - if(!SV_ExistingFile(path)) return false; - -#if __JHEXEN__ - /// @todo Do not buffer the whole file. - byte *readBuffer; - size_t fileSize = M_ReadFile(Str_Text(path), (char **) &readBuffer); - if(!fileSize) return false; - - // Set the save pointer. - SV_HxSavePtr()->b = readBuffer; - SV_HxSetSaveEndPtr(readBuffer + fileSize); -#else - if(!SV_OpenFile(path, "rp")) return false; -#endif + if(!SV_OpenGameSaveFile(path, false/*for reading*/)) return false; Reader *reader = SV_NewReader(); info.read(reader); Reader_Delete(reader); #if __JHEXEN__ - Z_Free(readBuffer); + Z_Free(saveBuffer); #else SV_CloseFile(); #endif diff --git a/doomsday/plugins/common/src/gamestatewriter.cpp b/doomsday/plugins/common/src/gamestatewriter.cpp index 862c294daa..810d498dbc 100644 --- a/doomsday/plugins/common/src/gamestatewriter.cpp +++ b/doomsday/plugins/common/src/gamestatewriter.cpp @@ -30,7 +30,7 @@ DENG2_PIMPL(GameStateWriter) { - SaveInfo *saveInfo; ///< Info for the save state to be written. + SaveInfo *saveInfo; ///< Info for the save state to be written. Not owned. ThingArchive *thingArchive; Writer *writer; @@ -41,6 +41,12 @@ DENG2_PIMPL(GameStateWriter) , writer(0) {} + ~Instance() + { + Writer_Delete(writer); + delete thingArchive; + } + void beginSegment(int segId) { #if __JHEXEN__ @@ -82,7 +88,7 @@ DENG2_PIMPL(GameStateWriter) SV_CloseFile(); // Open the map state file. - SV_OpenFile(saveSlots->composeSavePathForSlot(BASE_SLOT, gameMap + 1), "wp"); + SV_OpenFile(saveSlots->composeMapSavePathForSlot(BASE_SLOT, gameMap), "wp"); #endif MapStateWriter(*thingArchive).write(writer); diff --git a/doomsday/plugins/common/src/mapstatereader.cpp b/doomsday/plugins/common/src/mapstatereader.cpp index cd15710323..bce129248e 100644 --- a/doomsday/plugins/common/src/mapstatereader.cpp +++ b/doomsday/plugins/common/src/mapstatereader.cpp @@ -54,7 +54,7 @@ using namespace internal; DENG2_PIMPL(MapStateReader) { - Reader *reader; + Reader *reader; // Not owned. int saveVersion; int mapVersion; bool formatHasMapVersionNumber; @@ -77,6 +77,13 @@ DENG2_PIMPL(MapStateReader) , sideArchive(0) {} + ~Instance() + { + delete thingArchive; + delete sideArchive; + MaterialArchive_Delete(materialArchive); + } + void beginSegment(int segId) { #if __JHEXEN__ @@ -364,7 +371,9 @@ DENG2_PIMPL(MapStateReader) #if __JHEXEN__ if(reachedSpecialsBlock) #endif + { tClass = Reader_ReadByte(reader); + } #if __JHEXEN__ if(mapVersion < 4) @@ -376,7 +385,9 @@ DENG2_PIMPL(MapStateReader) // are differrent, so we need to manipulate the thinker // class identifier value. if(tClass != TC_END) + { tClass += 2; + } } else { @@ -400,9 +411,13 @@ DENG2_PIMPL(MapStateReader) // the end of the specials data so we need to manipulate // the thinker class identifier value. if(tClass == PRE_VER5_END_SPECIALS) + { tClass = TC_END; + } else + { tClass += 3; + } } else if(tClass == TC_END) { @@ -412,6 +427,7 @@ DENG2_PIMPL(MapStateReader) } } #endif + if(tClass == TC_END) break; // End of the list. @@ -445,7 +461,9 @@ DENG2_PIMPL(MapStateReader) #if __JHEXEN__ if(tClass == TC_MOBJ) + { i++; + } #endif } diff --git a/doomsday/plugins/common/src/mapstatewriter.cpp b/doomsday/plugins/common/src/mapstatewriter.cpp index 026e41f524..4d38a72106 100644 --- a/doomsday/plugins/common/src/mapstatewriter.cpp +++ b/doomsday/plugins/common/src/mapstatewriter.cpp @@ -43,9 +43,9 @@ using namespace internal; DENG2_PIMPL(MapStateWriter) { - ThingArchive *thingArchive; + ThingArchive *thingArchive; // Not owned. MaterialArchive *materialArchive; - Writer *writer; + Writer *writer; // Not owned. Instance(Public *i) : Base(i) @@ -54,6 +54,11 @@ DENG2_PIMPL(MapStateWriter) , writer(0) {} + ~Instance() + { + MaterialArchive_Delete(materialArchive); + } + void beginSegment(int segId) { #if __JHEXEN__ @@ -139,12 +144,16 @@ DENG2_PIMPL(MapStateWriter) if(p.excludePlayers) { if(th->function == (thinkfunc_t) P_MobjThinker && ((mobj_t *) th)->player) + { return false; + } } // Only the server saves this class of thinker? if((thInfo->flags & TSF_SERVERONLY) && IS_CLIENT) + { return false; + } // Write the header block for this thinker. Writer_WriteByte(p.msw->writer(), thInfo->thinkclass); // Thinker type byte. diff --git a/doomsday/plugins/common/src/p_saveg.cpp b/doomsday/plugins/common/src/p_saveg.cpp index d002c77fec..6968e7f008 100644 --- a/doomsday/plugins/common/src/p_saveg.cpp +++ b/doomsday/plugins/common/src/p_saveg.cpp @@ -88,10 +88,13 @@ dd_bool SV_OpenGameSaveFile(Str const *path, dd_bool write) #if __JHEXEN__ if(!write) { - bool result = M_ReadFile(Str_Text(path), (char **)&saveBuffer) > 0; - // Set the save pointer. + size_t bufferSize = M_ReadFile(Str_Text(path), (char **)&saveBuffer); + if(!bufferSize) return false; + SV_HxSavePtr()->b = saveBuffer; - return result; + SV_HxSetSaveEndPtr(saveBuffer + bufferSize); + + return true; } else #endif @@ -122,7 +125,7 @@ dd_bool SV_OpenMapSaveFile(Str const *path) dd_bool SV_HxHaveMapStateForSlot(int slot, uint map) { DENG_ASSERT(inited); - AutoStr *path = saveSlots->composeSavePathForSlot(slot, (int)map + 1); + AutoStr *path = saveSlots->composeMapSavePathForSlot(slot, map); if(path && !Str_IsEmpty(path)) { return SV_ExistingFile(path); @@ -1144,7 +1147,7 @@ void SV_LoadGameClient(uint sessionId) #if __JHEXEN__ void SV_HxSaveHubMap() { - SV_OpenFile(saveSlots->composeSavePathForSlot(BASE_SLOT, gameMap + 1), "wp"); + SV_OpenFile(saveSlots->composeMapSavePathForSlot(BASE_SLOT, gameMap), "wp"); // Set the mobj archive numbers ThingArchive thingArchive; @@ -1175,7 +1178,7 @@ void SV_HxLoadHubMap() // Been here before, load the previous map state. try { - AutoStr *path = saveSlots->composeSavePathForSlot(BASE_SLOT, gameMap + 1); + AutoStr *path = saveSlots->composeMapSavePathForSlot(BASE_SLOT, gameMap); if(!SV_OpenMapSaveFile(path)) { throw de::Error("SV_HxLoadHubMap", "Failed opening \"" + de::String(Str_Text(path)) + "\" for read"); diff --git a/doomsday/plugins/common/src/saveinfo.cpp b/doomsday/plugins/common/src/saveinfo.cpp index 9c9b8f23a1..1a9e36f68e 100644 --- a/doomsday/plugins/common/src/saveinfo.cpp +++ b/doomsday/plugins/common/src/saveinfo.cpp @@ -291,7 +291,7 @@ void SaveInfo::updateFromFile(Str const *path) // Is this a recognized game state? if(!SV_RecognizeGameState(*this, path)) { - // Clear the info for this slot. + // Clear the info. setDescription(0); setSessionId(0); return; diff --git a/doomsday/plugins/common/src/saveslots.cpp b/doomsday/plugins/common/src/saveslots.cpp index 02a17acd72..dce882cf28 100644 --- a/doomsday/plugins/common/src/saveslots.cpp +++ b/doomsday/plugins/common/src/saveslots.cpp @@ -278,7 +278,7 @@ void SaveSlots::clearSlot(int slot) for(int i = 0; i < MAX_HUB_MAPS; ++i) { - AutoStr *path = composeSavePathForSlot(slot, i); + AutoStr *path = composeMapSavePathForSlot(slot, i); SV_RemoveFile(path); } @@ -309,8 +309,8 @@ void SaveSlots::copySlot(int sourceSlot, int destSlot) AutoStr *src, *dst; for(int i = 0; i < MAX_HUB_MAPS; ++i) { - src = composeSavePathForSlot(sourceSlot, i); - dst = composeSavePathForSlot(destSlot, i); + src = composeMapSavePathForSlot(sourceSlot, i); + dst = composeMapSavePathForSlot(destSlot, i); SV_CopyFile(src, dst); } @@ -322,7 +322,7 @@ void SaveSlots::copySlot(int sourceSlot, int destSlot) replaceSaveInfo(destSlot, new SaveInfo(saveInfo(sourceSlot))); } -AutoStr *SaveSlots::composeSavePathForSlot(int slot, int map) const +AutoStr *SaveSlots::composeMapSavePathForSlot(int slot, uint map) const { AutoStr *path = AutoStr_NewStd(); @@ -334,14 +334,24 @@ AutoStr *SaveSlots::composeSavePathForSlot(int slot, int map) const if(!F_MakePath(SV_SavePath())) return path; // Compose the full game-save path and filename. - if(map >= 0) - { - Str_Appendf(path, "%s" SAVEGAMENAME "%i%02i." SAVEGAMEEXTENSION, SV_SavePath(), slot, map); - } - else - { - Str_Appendf(path, "%s" SAVEGAMENAME "%i." SAVEGAMEEXTENSION, SV_SavePath(), slot); - } + Str_Appendf(path, "%s" SAVEGAMENAME "%i%02i." SAVEGAMEEXTENSION, SV_SavePath(), slot, map + 1); + F_TranslatePath(path, path); + return path; +} + +AutoStr *SaveSlots::composeSavePathForSlot(int slot) const +{ + AutoStr *path = AutoStr_NewStd(); + + // A valid slot? + if(!isValidSlot(slot)) return path; + + // Do we have a valid path? + /// @todo Do not do alter the file system until necessary. + if(!F_MakePath(SV_SavePath())) return path; + + // Compose the full game-save path and filename. + Str_Appendf(path, "%s" SAVEGAMENAME "%i." SAVEGAMEEXTENSION, SV_SavePath(), slot); F_TranslatePath(path, path); return path; } @@ -451,12 +461,6 @@ void SaveSlots_CopySlot(SaveSlots *sslots, int sourceSlot, int destSlot) sslots->copySlot(sourceSlot, destSlot); } -AutoStr *SaveSlots_ComposeSavePathForSlot(SaveSlots const *sslots, int slot, int map) -{ - DENG_ASSERT(sslots != 0); - return sslots->composeSavePathForSlot(slot, map); -} - void SaveSlots_ConsoleRegister() { SaveSlots::consoleRegister();