Navigation Menu

Skip to content

Commit

Permalink
Refactor|libcommon|SavedSessionRepository: Require that a map URI is …
Browse files Browse the repository at this point in the history
…always specified when forming file paths
  • Loading branch information
danij-deng committed Mar 5, 2014
1 parent bd2c65a commit 7da834f
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 96 deletions.
6 changes: 3 additions & 3 deletions doomsday/plugins/common/include/savedsessionrepository.h
Expand Up @@ -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;

Expand All @@ -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.
Expand Down
6 changes: 2 additions & 4 deletions doomsday/plugins/common/src/g_game.cpp
Expand Up @@ -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*/))
{
Expand Down Expand Up @@ -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*/))
{
Expand Down Expand Up @@ -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__
Expand Down
2 changes: 1 addition & 1 deletion doomsday/plugins/common/src/gamestatereader.cpp
Expand Up @@ -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() + "\"");
Expand Down
3 changes: 2 additions & 1 deletion doomsday/plugins/common/src/gamestatewriter.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
Expand Down
176 changes: 89 additions & 87 deletions doomsday/plugins/common/src/savedsessionrepository.cpp
Expand Up @@ -22,8 +22,8 @@

#include "g_common.h"
#include "gamestatereader.h"
//#include "p_savedef.h"
#include "p_saveio.h"
#include "p_savedef.h"
#include <de/Log>
#include <de/NativePath>
#include <cstring>
Expand Down Expand Up @@ -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();
Expand All @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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())
Expand All @@ -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
Expand Down

0 comments on commit 7da834f

Please sign in to comment.