Skip to content

Commit

Permalink
libcommon|SaveInfo|SaveSlots: Associate the saved game state file nam…
Browse files Browse the repository at this point in the history
…e with SaveInfo

When a new SaveInfo is instantiated or copied from another save slot
the game state file name bound to associated save slot is applied.
This file name can be directly queried from the SaveInfo and thus
avoiding the need to pass it along with said info, or, interact with
the SaveSlots container/wrapper.
  • Loading branch information
danij-deng committed Feb 21, 2014
1 parent 3e071da commit 8e9739d
Show file tree
Hide file tree
Showing 13 changed files with 183 additions and 145 deletions.
30 changes: 12 additions & 18 deletions doomsday/plugins/common/include/gamestatereader.h
Expand Up @@ -45,23 +45,19 @@ class IGameStateReader
* Attempt to load (read/interpret) the saved game state.
*
* @param info SaveInfo for the saved game state to be read/interpreted.
* @param path Path to the saved game state to be read.
*
* @todo @a path should be provided by SaveInfo.
*/
virtual void read(SaveInfo &info, de::Path path) = 0;
virtual void read(SaveInfo &info) = 0;
};

/**
* Game state recognizer function ptr.
*
* The job of a recognizer function is to determine whether the resource file on @a path is
* interpretable as a potentially loadable savegame state.
* The job of a recognizer function is to determine whether the game session associated
* with the given save @a info is interpretable as a potentially loadable savegame state.
*
* @param info SaveInfo to attempt to read game session header into.
* @param path Path to the resource file to be recognized.
*/
typedef bool (*GameStateRecognizeFunc)(SaveInfo &info, de::Path path);
typedef bool (*GameStateRecognizeFunc)(SaveInfo &info);

/// Game state reader instantiator function ptr.
typedef IGameStateReader *(*GameStateReaderMakeFunc)();
Expand Down Expand Up @@ -92,15 +88,14 @@ class GameStateReaderFactory
* is available and if so, reads the game session header.
*
* @param saveInfo The game session header will be written here if recognized.
* @param path Path to the resource file to be recognized.
*
* @return @c true= the game session header was read successfully.
*
* @see recognizeAndMakeReader()
*/
bool recognize(SaveInfo &saveInfo, de::Path path) const
bool recognize(SaveInfo &saveInfo) const
{
return readGameSessionHeader(saveInfo, path) != 0;
return readGameSessionHeader(saveInfo) != 0;
}

/**
Expand All @@ -109,15 +104,14 @@ class GameStateReaderFactory
* for deserializing the game state.
*
* @param saveInfo The game session header will be written here if recognized.
* @param path Path to the resource file to be recognized.
*
* @return New reader instance if recognized; otherwise @c 0. Ownership given to the caller.
*
* @see recognize()
*/
IGameStateReader *recognizeAndMakeReader(SaveInfo &saveInfo, de::Path path) const
IGameStateReader *recognizeAndMakeReader(SaveInfo &saveInfo) const
{
if(ReaderInfo const *rdrInfo = readGameSessionHeader(saveInfo, path))
if(ReaderInfo const *rdrInfo = readGameSessionHeader(saveInfo))
{
return rdrInfo->newReader();
}
Expand All @@ -132,11 +126,11 @@ class GameStateReaderFactory
typedef std::list<ReaderInfo> ReaderInfos;
ReaderInfos readers;

ReaderInfo const *readGameSessionHeader(SaveInfo &info, de::Path path) const
ReaderInfo const *readGameSessionHeader(SaveInfo &info) const
{
DENG2_FOR_EACH_CONST(ReaderInfos, i, readers)
{
if(i->recognize(info, path))
if(i->recognize(info))
{
return &*i;
}
Expand All @@ -158,9 +152,9 @@ class GameStateReader : public IGameStateReader
~GameStateReader();

static IGameStateReader *make();
static bool recognize(SaveInfo &info, de::Path path);
static bool recognize(SaveInfo &info);

void read(SaveInfo &info, de::Path path);
void read(SaveInfo &info);

private:
DENG2_PRIVATE(d)
Expand Down
7 changes: 3 additions & 4 deletions doomsday/plugins/common/include/p_saveg.h
Expand Up @@ -140,13 +140,12 @@ SaveSlots &SV_SaveSlots();
void SV_DeclareGameStateReader(GameStateRecognizeFunc recognizer, GameStateReaderMakeFunc maker);

/**
* Determines whether the resource file on @a path is interpretable as a potentially loadable
* savegame state.
* Determines whether the game session associated with save @a info is interpretable as a
* potentially loadable savegame state.
*
* @param info SaveInfo to attempt to read game session header into.
* @param path Path to the resource file to be recognized.
*/
bool SV_RecognizeGameState(SaveInfo &info, de::Path path);
bool SV_RecognizeGameState(SaveInfo &info);

class MapStateReader;
class MapStateWriter;
Expand Down
24 changes: 19 additions & 5 deletions doomsday/plugins/common/include/saveinfo.h
Expand Up @@ -41,10 +41,11 @@ class SaveInfo
#endif

public:
SaveInfo();
SaveInfo(de::String const &fileName = "");
SaveInfo(SaveInfo const &other);

static SaveInfo *newWithCurrentSessionMetadata(de::String const &userDescription = "");
static SaveInfo *newWithCurrentSessionMetadata(de::String const &fileName = "",
de::String const &userDescription = "");

SaveInfo &operator = (SaveInfo const &other);

Expand All @@ -69,11 +70,24 @@ class SaveInfo
* is invalid, unreachable, or the game state is not recognized -- the save info is returned
* to a valid but non-loadable state.
*
* @param fileName Name of the resource file containing the game session header.
*
* @see isLoadable()
*/
void updateFromFile(de::String fileName);
void updateFromFile();

/**
* Returns the name of the resource file (with extension) containing the game session header.
*/
de::String fileName() const;
void setFileName(de::String newName);

/**
* Returns the name of the resource file (with extension) containing the map session state.
*
* @param map Logical map index.
*
* @see fileName()
*/
de::String fileNameForMap(uint map) const;

/**
* Update the metadata associated with the save using values derived from the current game
Expand Down
48 changes: 22 additions & 26 deletions doomsday/plugins/common/include/saveslots.h
Expand Up @@ -52,57 +52,50 @@ class SaveSlots
DENG2_ERROR(MissingInfoError);

public:
Slot(de::String const &saveName = "");
Slot(de::String const &fileName = "");

/**
* Change the save game name bound to the logical save slot.
* Returns the save game file name bound to the logical save slot.
*/
de::String fileName() const;

/**
* Change the save game file name bound to the logical save slot.
*
* @param newSaveName New save game name to apply.
* @param newName New save game file name to be bound.
*/
void bindSaveName(de::String newSaveName);
void bindFileName(de::String newName);

/**
* Returns @c true iff a saved game state exists for the logical save slot.
*/
bool isUsed() const;

/**
* Returns @c true iff save info exists for the logical save slot.
*/
bool hasSaveInfo() const;

/**
* Clear the save info for the logical save slot.
*
* @see hasSaveInfo()
*/
void clearSaveInfo();

/**
* @param newInfo New SaveInfo to replace with. Ownership is given.
*/
void replaceSaveInfo(SaveInfo *newInfo);

/**
* Returns the SaveInfo associated with the logical save slot.
*
* @param canCreate @c true= create new save info and attempt to populate it from the saved
* game session header if it does not exist.
* @see hasSaveInfo()
*/
SaveInfo &saveInfo(bool canCreate = false) const;
SaveInfo &saveInfo() const;

/**
* If no save info exists, create and attempt to populate it from the saved game session header.
*/
void addMissingSaveInfo();

/**
* Returns the save name (with file extension) for the specified @a map, for the logical
* save slot.
* Replace the existing save info with @a newInfo.
*
* @param map Logical map index.
*/
de::String saveNameForMap(uint map) const;

/**
* Returns the save name (with file extension), for the logical save slot.
* @param newInfo New SaveInfo to replace with. Ownership is given.
*/
de::String saveName() const;
void replaceSaveInfo(SaveInfo *newInfo);

private:
DENG2_PRIVATE(d)
Expand All @@ -119,6 +112,9 @@ class SaveSlots
*/
int slotCount() const;

/// @see slotCount()
inline int size() const { return slotCount(); }

/**
* Returns @c true iff @a value is interpretable as logical slot number (in range).
*
Expand Down
10 changes: 7 additions & 3 deletions doomsday/plugins/common/src/gamestatereader.cpp
Expand Up @@ -114,7 +114,7 @@ DENG2_PIMPL(GameStateReader)
SV_HxReleaseSaveBuffer();

// Open the map state file.
de::Path path = SV_SavePath() / SV_SaveSlots()[BASE_SLOT].saveNameForMap(gameMap);
de::Path path = SV_SavePath() / SV_SaveSlots()[BASE_SLOT].saveInfo().fileNameForMap(gameMap);
if(!SV_OpenMapSaveFile(path))
{
throw FileAccessError("GameStateReader", "Failed opening \"" + de::NativePath(path).pretty() + "\"");
Expand Down Expand Up @@ -277,8 +277,10 @@ GameStateReader::GameStateReader() : d(new Instance(this))
GameStateReader::~GameStateReader()
{}

bool GameStateReader::recognize(SaveInfo &info, de::Path path) // static
bool GameStateReader::recognize(SaveInfo &info) // static
{
de::Path path = SV_SavePath() / info.fileName();

if(!SV_ExistingFile(path)) return false;
if(!SV_OpenGameSaveFile(path, false/*for reading*/)) return false;

Expand Down Expand Up @@ -323,8 +325,10 @@ IGameStateReader *GameStateReader::make() // static
return new GameStateReader;
}

void GameStateReader::read(SaveInfo &info, de::Path path)
void GameStateReader::read(SaveInfo &info)
{
de::Path path = SV_SavePath() / info.fileName();

d->saveInfo = &info;

if(!SV_OpenGameSaveFile(path, false/*for reading*/))
Expand Down
2 changes: 1 addition & 1 deletion doomsday/plugins/common/src/gamestatewriter.cpp
Expand Up @@ -89,7 +89,7 @@ DENG2_PIMPL(GameStateWriter)
SV_CloseFile();

// Open the map state file.
SV_OpenFile(SV_SavePath() / SV_SaveSlots()[BASE_SLOT].saveNameForMap(gameMap), "wp");
SV_OpenFile(SV_SavePath() / SV_SaveSlots()[BASE_SLOT].saveInfo().fileNameForMap(gameMap), "wp");
#endif

MapStateWriter(*thingArchive).write(writer);
Expand Down

0 comments on commit 8e9739d

Please sign in to comment.