From 7da834f62025814a0eeacc8c03d17dd280efe8c8 Mon Sep 17 00:00:00 2001 From: danij Date: Sat, 1 Mar 2014 11:52:47 +0000 Subject: [PATCH] Refactor|libcommon|SavedSessionRepository: Require that a map URI is always specified when forming file paths --- .../common/include/savedsessionrepository.h | 6 +- doomsday/plugins/common/src/g_game.cpp | 6 +- .../plugins/common/src/gamestatereader.cpp | 2 +- .../plugins/common/src/gamestatewriter.cpp | 3 +- .../common/src/savedsessionrepository.cpp | 176 +++++++++--------- 5 files changed, 97 insertions(+), 96 deletions(-) diff --git a/doomsday/plugins/common/include/savedsessionrepository.h b/doomsday/plugins/common/include/savedsessionrepository.h index 43fd76c540..16e7c2cb21 100644 --- a/doomsday/plugins/common/include/savedsessionrepository.h +++ b/doomsday/plugins/common/include/savedsessionrepository.h @@ -105,7 +105,7 @@ class SavedSessionRepository /** * Determines whether a saved map session exists. * - * @param mapUri Unique map identifier. If @c 0 the Uri for the @em current map is used. + * @param mapUri Unique map identifier. */ bool haveMapSession(Uri const *mapUri) const; @@ -127,11 +127,11 @@ class SavedSessionRepository /** * Returns the name of the resource file (with extension) containing the map session state. * - * @param mapUri Unique map identifier. If @c 0 the Uri for the @em current map is used. + * @param mapUri Unique map identifier. * * @see fileName() */ - de::String fileNameForMap(Uri const *mapUri = 0) const; + de::String fileNameForMap(Uri const *mapUri) const; /** * Provides read-only access to a copy of the deserialized game session metadata. diff --git a/doomsday/plugins/common/src/g_game.cpp b/doomsday/plugins/common/src/g_game.cpp index 713b111215..c347b44ee3 100644 --- a/doomsday/plugins/common/src/g_game.cpp +++ b/doomsday/plugins/common/src/g_game.cpp @@ -1404,7 +1404,7 @@ int G_DoLoadMap(loadmap_params_t *p) { SaveSlot &sslot = G_SaveSlots()["base"]; SessionRecord &record = sslot.sessionRecord(); - de::Path const path = record.repository().savePath() / record.fileNameForMap(); + de::Path const path = record.repository().savePath() / record.fileNameForMap(gameMapUri); if(!SV_OpenFile(path, false/*for read*/)) { @@ -2995,7 +2995,7 @@ void G_DoLeaveMap() // Save current map. SaveSlot &sslot = G_SaveSlots()["base"]; SessionRecord &record = sslot.sessionRecord(); - de::Path const path = record.repository().savePath() / record.fileNameForMap(); + de::Path const path = record.repository().savePath() / record.fileNameForMap(gameMapUri); if(!SV_OpenFile(path, true/*for write*/)) { @@ -3344,8 +3344,6 @@ AutoStr *G_GenerateUserSaveDescription() void G_ApplyCurrentSessionMetadata(SessionMetadata &meta) { - meta.magic = IS_NETWORK_CLIENT? MY_CLIENT_SAVE_MAGIC : MY_SAVE_MAGIC; - meta.version = MY_SAVE_VERSION; meta.gameIdentityKey = G_IdentityKey(); Uri_Copy(meta.mapUri, gameMapUri); #if !__JHEXEN__ diff --git a/doomsday/plugins/common/src/gamestatereader.cpp b/doomsday/plugins/common/src/gamestatereader.cpp index 6b2871498f..e1aadbbbfa 100644 --- a/doomsday/plugins/common/src/gamestatereader.cpp +++ b/doomsday/plugins/common/src/gamestatereader.cpp @@ -117,7 +117,7 @@ DENG2_PIMPL(GameStateReader) SV_HxReleaseSaveBuffer(); // Open the map state file. - de::Path path = record->repository().savePath() / record->fileNameForMap(); + de::Path path = record->repository().savePath() / record->fileNameForMap(gameMapUri); if(!SV_OpenFile(path, false/*for read*/)) { throw FileAccessError("GameStateReader", "Failed opening \"" + de::NativePath(path).pretty() + "\""); diff --git a/doomsday/plugins/common/src/gamestatewriter.cpp b/doomsday/plugins/common/src/gamestatewriter.cpp index 72e6853659..a0945403db 100644 --- a/doomsday/plugins/common/src/gamestatewriter.cpp +++ b/doomsday/plugins/common/src/gamestatewriter.cpp @@ -22,6 +22,7 @@ #include "gamestatewriter.h" #include "d_net.h" // NetSv_SaveGame +#include "g_common.h" // gameMapUri #include "mapstatewriter.h" #include "p_savedef.h" // CONSISTENCY #include "p_saveio.h" @@ -92,7 +93,7 @@ DENG2_PIMPL(GameStateWriter) SV_CloseFile(); // Open the map state file. - SV_OpenFile(record->repository().savePath() / record->fileNameForMap(), true/*for write*/); + SV_OpenFile(record->repository().savePath() / record->fileNameForMap(gameMapUri), true/*for write*/); #endif MapStateWriter(*thingArchive).write(writer); diff --git a/doomsday/plugins/common/src/savedsessionrepository.cpp b/doomsday/plugins/common/src/savedsessionrepository.cpp index f0ec4075d2..dabee5a506 100644 --- a/doomsday/plugins/common/src/savedsessionrepository.cpp +++ b/doomsday/plugins/common/src/savedsessionrepository.cpp @@ -22,8 +22,8 @@ #include "g_common.h" #include "gamestatereader.h" -//#include "p_savedef.h" #include "p_saveio.h" +#include "p_savedef.h" #include #include #include @@ -134,6 +134,25 @@ SessionRecord::SessionStatus SavedSessionRepository::SessionRecord::status() con return d->status; } +String SavedSessionRepository::SessionRecord::statusAsText() const +{ + static String const statusTexts[] = { + "Loadable", + "Incompatible", + "Unused", + }; + return statusTexts[int(status())]; +} + +String SavedSessionRepository::SessionRecord::description() const +{ + return meta().asText() + "\n" + + String(_E(l) "Source file: " _E(.)_E(i) "\"%1\"\n" _E(.) + _E(D) "Status: " _E(.) "%2") + .arg(NativePath(repository().savePath() / fileName()).pretty()) + .arg(statusAsText()); +} + String SavedSessionRepository::SessionRecord::fileName() const { return d->fileName + "." + repository().saveFileExtension(); @@ -150,13 +169,70 @@ void SavedSessionRepository::SessionRecord::setFileName(String newName) String SavedSessionRepository::SessionRecord::fileNameForMap(Uri const *mapUri) const { - if(!mapUri) mapUri = gameMapUri; - + DENG2_ASSERT(mapUri != 0); uint map = G_MapNumberFor(mapUri); return d->fileName + String("%1.").arg(int(map + 1), 2, 10, QChar('0')) + repository().saveFileExtension(); } +bool SavedSessionRepository::SessionRecord::haveGameSession() const +{ + return SV_ExistingFile(repository().savePath() / fileName()); +} + +bool SavedSessionRepository::SessionRecord::haveMapSession(Uri const *mapUri) const +{ + if(usingSeparateMapSessionFiles()) + { + return SV_ExistingFile(repository().savePath() / fileNameForMap(mapUri)); + } + return haveGameSession(); +} + +void SavedSessionRepository::SessionRecord::updateFromFile() +{ + LOGDEV_VERBOSE("Updating saved game SessionRecord %p from source file") << this; + + // Is this a recognized game state? + if(G_GameStateReaderFactory().recognize(*this)) + { + // Ensure we have a valid description. + if(d->meta.userDescription.isEmpty()) + { + setUserDescription("UNNAMED"); + } + } + else + { + // Unrecognized or the file could not be accessed (perhaps its a network path?). + // Clear the info. + setUserDescription(""); + setSessionId(0); + } + + d->updateStatusIfNeeded(); +} + +SessionMetadata const &SavedSessionRepository::SessionRecord::meta() const +{ + return d->meta; +} + +void SavedSessionRepository::SessionRecord::readMeta(reader_s *reader) +{ + d->meta.read(reader); + d->needUpdateStatus = true; +} + +void SavedSessionRepository::SessionRecord::applyCurrentSessionMetadata() +{ + d->meta.magic = IS_NETWORK_CLIENT? MY_CLIENT_SAVE_MAGIC : MY_SAVE_MAGIC; + d->meta.version = MY_SAVE_VERSION; + G_ApplyCurrentSessionMetadata(d->meta); + + d->needUpdateStatus = true; +} + void SavedSessionRepository::SessionRecord::setGameIdentityKey(String newGameIdentityKey) { if(d->meta.gameIdentityKey != newGameIdentityKey) @@ -166,6 +242,12 @@ void SavedSessionRepository::SessionRecord::setGameIdentityKey(String newGameIde } } +void SavedSessionRepository::SessionRecord::setGameRules(GameRuleset const &newRules) +{ + d->meta.gameRules = newRules; // Make a copy + d->needUpdateStatus = true; +} + void SavedSessionRepository::SessionRecord::setMagic(int newMagic) { if(d->meta.magic != newMagic) @@ -223,86 +305,6 @@ void SavedSessionRepository::SessionRecord::setPlayers(SessionMetadata::Players } #endif // !__JHEXEN__ -void SavedSessionRepository::SessionRecord::setGameRules(GameRuleset const &newRules) -{ - d->meta.gameRules = newRules; // Make a copy - d->needUpdateStatus = true; -} - -bool SavedSessionRepository::SessionRecord::haveGameSession() const -{ - return SV_ExistingFile(repository().savePath() / fileName()); -} - -bool SavedSessionRepository::SessionRecord::haveMapSession(Uri const *mapUri) const -{ - if(usingSeparateMapSessionFiles()) - { - return SV_ExistingFile(repository().savePath() / fileNameForMap(mapUri)); - } - return haveGameSession(); -} - -void SavedSessionRepository::SessionRecord::updateFromFile() -{ - LOGDEV_VERBOSE("Updating saved game SessionRecord %p from source file") << this; - - // Is this a recognized game state? - if(G_GameStateReaderFactory().recognize(*this)) - { - // Ensure we have a valid description. - if(d->meta.userDescription.isEmpty()) - { - setUserDescription("UNNAMED"); - } - } - else - { - // Unrecognized or the file could not be accessed (perhaps its a network path?). - // Clear the info. - setUserDescription(""); - setSessionId(0); - } - - d->updateStatusIfNeeded(); -} - -SessionMetadata const &SavedSessionRepository::SessionRecord::meta() const -{ - return d->meta; -} - -void SavedSessionRepository::SessionRecord::readMeta(reader_s *reader) -{ - d->meta.read(reader); - d->needUpdateStatus = true; -} - -void SavedSessionRepository::SessionRecord::applyCurrentSessionMetadata() -{ - G_ApplyCurrentSessionMetadata(d->meta); - d->needUpdateStatus = true; -} - -String SavedSessionRepository::SessionRecord::statusAsText() const -{ - static String const statusTexts[] = { - "Loadable", - "Incompatible", - "Unused", - }; - return statusTexts[int(status())]; -} - -String SavedSessionRepository::SessionRecord::description() const -{ - return meta().asText() + "\n" + - String(_E(l) "Source file: " _E(.)_E(i) "\"%1\"\n" _E(.) - _E(D) "Status: " _E(.) "%2") - .arg(NativePath(repository().savePath() / fileName()).pretty()) - .arg(statusAsText()); -} - DENG2_PIMPL_NOREF(SavedSessionRepository) { Path savePath; ///< e.g., "savegame" @@ -334,6 +336,8 @@ SavedSessionRepository::SavedSessionRepository() : d(new Instance) void SavedSessionRepository::setupSaveDirectory(Path newRootSaveDir, String saveFileExtension) { + LOG_AS("SavedSessionRepository"); + d->saveFileExtension = saveFileExtension; if(!newRootSaveDir.isEmpty()) @@ -360,10 +364,8 @@ void SavedSessionRepository::setupSaveDirectory(Path newRootSaveDir, String save d->savePath.clear(); d->clientSavePath.clear(); - App_Log(DE2_RES_ERROR, "SavedSessionRepository::setupSaveDirectory: \"%s\" could not be accessed." - " Perhaps it could not be created (insufficient permissions?)." - " Saving will not be possible.", - NativePath(d->savePath).pretty().toLatin1().constData()); + LOG_RES_ERROR("\"%s\" could not be accessed. Perhaps it could not be created (insufficient permissions?)." + " Saving will not be possible.") << NativePath(d->savePath).pretty(); } Path const &SavedSessionRepository::savePath() const