1 /** @file gamesession.h Logical game session and saved session marshalling. 2 * 3 * @authors Copyright © 2014 Daniel Swanson <danij@dengine.net> 4 * 5 * @par License 6 * GPL: http://www.gnu.org/licenses/gpl.html 7 * 8 * <small>This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. This program is distributed in the hope that it 12 * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 14 * Public License for more details. You should have received a copy of the GNU 15 * General Public License along with this program; if not, write to the Free 16 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 17 * 02110-1301 USA</small> 18 */ 19 20 #ifndef LIBCOMMON_GAMESESSION_H 21 #define LIBCOMMON_GAMESESSION_H 22 23 #include <de/String> 24 #include <doomsday/AbstractSession> 25 #include <doomsday/GameProfiles> 26 #include <doomsday/uri.h> 27 28 //#include "doomsday.h" 29 //#include "acs/system.h" 30 //#include "gamerules.h" 31 32 class GameRules; 33 34 namespace acs { class System; } 35 36 namespace common { 37 38 /** 39 * Implements high level logic for the manipulation and configuration of the logical game session. 40 * 41 * An internal backing store is used to record player progress automatically, whenever the current 42 * map changes while the session is in progress. This occurs irrespective of the user's savegame 43 * preferences. Additionally, the user may configure the game so that the internal backing store 44 * is periodically (e.g., when the map changes) copied to a new "autosave" automatically. 45 * 46 * The "scope" of a continous game session progression depends on the configuration of the Episode 47 * and the maps within it. Upon leaving one map and entering another, if both are attributed to 48 * the same logical "hub" then the current state of the map is written to the backing store so 49 * that it may be reloaded later if the player(s) decide to revisit. However, if the new map is 50 * in another hub, or no hub is defined, then all saved map progress for current hub is discarded. 51 * 52 * Note that the use of hubs is not required and some games may not use them at all (e.g., DOOM). 53 * 54 * @ingroup libcommon 55 */ 56 class GameSession : public AbstractSession 57 { 58 public: 59 typedef QList<de::Uri> VisitedMaps; 60 61 public: 62 GameSession(); 63 virtual ~GameSession(); 64 65 bool isSavingPossible(); 66 bool isLoadingPossible(); 67 68 /** 69 * Returns the current Episode definition for the game session in progress. If the session 70 * has not yet begun then @c nullptr is returned. 71 */ 72 de::Record const *episodeDef() const; 73 74 /** 75 * Returns the current episode id for the game session in progress. If the session has not 76 * yet begun then a zero-length string is returned. 77 */ 78 de::String episodeId() const; 79 80 /** 81 * Returns the current MapGraphNode definition for the game session in progress. If the 82 * session has not yet begun then @c nullptr is returned. 83 */ 84 de::Record const *mapGraphNodeDef() const; 85 86 /** 87 * Returns the current MapInfo definition for the game session in progress. If the session 88 * has not yet begun, or no definition exists for the current map then the default definition 89 * is returned instead. 90 */ 91 de::Record const &mapInfo() const; 92 93 /** 94 * Returns the player entry point for the current map, for the game session in progress. 95 * The entry point determines where players will be reborn. 96 */ 97 uint mapEntryPoint() const; 98 99 /** 100 * Returns a list of all the maps that have been visited, for the game session in progress. 101 * @note Older versions of the saved session format did not record this information (it may 102 * be empty). 103 */ 104 VisitedMaps allVisitedMaps() const; 105 106 /** 107 * Resolves a named exit according to the map progression. 108 */ 109 de::Uri mapUriForNamedExit(de::String name) const; 110 111 /** 112 * Returns the current ruleset for the game session. 113 */ 114 GameRules const &rules() const; 115 116 /** 117 * To be called when a new game begins to effect the game rules. Note that some of the rules 118 * may be overridden here (e.g., in a networked game). 119 * 120 * @todo Prevent this outright if the game session is already in progress! 121 */ 122 void applyNewRules(GameRules const &rules); 123 124 /** 125 * Determines whether saved game progress will be restored when the current map is reloaded, 126 * according to the current game state and user configuration. 127 */ 128 bool progressRestoredOnReload() const; 129 130 /** 131 * End the game session (if in progress). 132 * @see hasBegun() 133 */ 134 void end(); 135 136 /** 137 * End the game session (if in progress) and begin the title sequence. 138 * @see end(), hasBegun() 139 */ 140 void endAndBeginTitle(); 141 142 /** 143 * Configure and begin a new game session. Note that a @em new session cannot @em begin if 144 * one already @ref hasBegun() (if so, the session must be ended first). 145 * 146 * @param rules Game rules to apply. 147 * @param episodeId Episode identifier. 148 * @param mapUri Map identifier. 149 * @param mapEntryPoint Map entry point number, for player reborn. 150 * 151 * @throws InProgressError if the session has already begun. 152 */ 153 void begin(GameRules const &rules, de::String const &episodeId, de::Uri const &mapUri, 154 uint mapEntryPoint = 0); 155 156 /** 157 * Reload the @em current map, automatically loading any saved progress from the backing 158 * store if @ref progressRestoredOnReload(). If no saved progress exists then the map will 159 * be in the default state. 160 */ 161 void reloadMap(); 162 163 /** 164 * Leave the @em current map (automatically saving progress to the backing store) and then 165 * load up the next map specified. 166 * 167 * @param nextMapUri Map identifier. 168 * @param nextMapEntryPoint Map entry point number, for player reborn. 169 */ 170 void leaveMap(de::Uri const &nextMapUri, uint nextMapEntryPoint = 0); 171 172 /** 173 * Convenient method of looking up the user description of the game session in progress. 174 * 175 * @return User description of the session if it @ref hasBegun() or a zero-length string. 176 */ 177 de::String userDescription(); 178 179 public: // Systems and data structures ------------------------------------------------------ 180 181 /** 182 * Returns the "ACS" scripting system. 183 */ 184 acs::System &acsSystem(); 185 186 public: // Saved session management --------------------------------------------------------- 187 188 /** 189 * Save the current game state to a new @em user saved session. 190 * 191 * @param saveName Name of the new saved session. 192 * @param userDescription Textual description of the current game state provided either 193 * by the user or possibly generated automatically. 194 */ 195 void save(de::String const &saveName, de::String const &userDescription); 196 197 /** 198 * Load the game state from the @em user saved session specified. 199 * 200 * @param saveName Name of the saved session to be loaded. 201 */ 202 void load(de::String const &saveName); 203 204 /** 205 * Makes a copy of the @em user saved session specified in /home/savegames/<gameId> 206 * 207 * @param destName Name of the new/replaced saved session. 208 * @param sourceName Name of the saved session to be copied. 209 */ 210 void copySaved(de::String const &destName, de::String const &sourceName); 211 212 /** 213 * Removes the @em user saved session /home/savegames/<gameId>/<@a saveName>.save 214 */ 215 void removeSaved(de::String const &saveName); 216 217 /** 218 * Convenient method of looking up the @em user description of an existing saved session. 219 * 220 * @param saveName Name of the saved session to lookup. 221 * 222 * @return User description of the named session or a zero-length string if not found. 223 */ 224 de::String savedUserDescription(de::String const &saveName); 225 226 public: 227 /// Returns the singleton instance. 228 static GameSession &gameSession(); 229 230 /// Register the commands and variables of this module. 231 static void consoleRegister(); 232 233 private: 234 DENG2_PRIVATE(d) 235 }; 236 237 } // namespace common 238 239 /** 240 * Macro for conveniently accessing the common::GameSession singleton instance. 241 */ 242 #define gfw_Session() (&common::GameSession::gameSession()) 243 244 /** 245 * Returns the currently loaded game's ID. 246 */ 247 de::String gfw_GameId(); 248 249 /** 250 * Returns the current game profile, or nullptr. 251 */ 252 const GameProfile *gfw_GameProfile(); 253 254 #endif // LIBCOMMON_GAMESESSION_H 255