The Battle for Wesnoth  1.15.5+dev
savegame.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2018 by Jörg Hinrichs, refactored from various
3  places formerly created by David White <dave@whitevine.net>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #pragma once
17 
18 #include "config.hpp"
19 #include "filesystem.hpp"
21 #include "save_index.hpp"
22 #include "saved_game.hpp"
24 
25 #include <exception>
26 
27 class config_writer;
28 class game_config_view;
29 class version_info;
30 
31 namespace savegame
32 {
33 /** converts saves from older versions of wesnoth*/
34 void convert_old_saves(config& cfg);
35 
36 /**
37  * Returns true if there is already a savegame with this name, looking only in the default save
38  * directory. Only expected to be used to check whether a subsequent save would overwrite an
39  * existing file, therefore only expected to be used for the default save dir.
40  */
41 bool save_game_exists(std::string name, compression::format compressed);
42 
43 /**
44  * Delete all autosaves of a certain scenario from the default save directory.
45  *
46  * This is only expected to be called when the player starts the next scenario (or finishes the
47  * campaign, in the case of the last scenario), so it's expected to correspond to the next scenario
48  * being written to the default save directory.
49  */
50 void clean_saves(const std::string& label);
51 
53 {
54  /** There may be different instances of the index for different directories */
55  std::shared_ptr<save_index_class> manager;
56 
57  /** Name of the savefile to be loaded (not including the directory). */
59 
60  /** The difficulty the save is meant to be loaded with. */
62 
63  /** State of the "show_replay" checkbox in the load-game dialog. */
65 
66  /** State of the "cancel_orders" checkbox in the load-game dialog. */
68 
69  /** State of the "change_difficulty" checkbox in the load-game dialog. */
71 
72  /** Summary config of the save selected in the load game dialog. */
74 
75  /** Config information of the savefile to be loaded. */
77 
78  explicit load_game_metadata(std::shared_ptr<save_index_class> index,
79  const std::string& fname = "", const std::string& hard = "",
80  bool replay = false, bool stop = false, bool change = false,
81  const config& summary = config(), const config& info = config())
82  : manager(index), filename(fname), difficulty(hard)
83  , show_replay(replay), cancel_orders(stop), select_difficulty(change)
84  , summary(summary), load_config(info)
85  {
86  }
87 };
88 
89 /**
90 * Exception used to signal that the user has decided to abortt a game,
91 * and to load another game instead.
92 */
94  : public lua_jailbreak_exception, public std::exception
95 {
96 public:
99  , data_(data)
100  {
101  }
103 private:
104 
106 };
107 
108 /** The class for loading a savefile. */
109 class loadgame
110 {
111 public:
112  loadgame(const std::shared_ptr<save_index_class>& index, const game_config_view& game_config, saved_game& gamestate);
113  virtual ~loadgame() {}
114 
115  /* In any of the following three function, a bool value of false indicates
116  some failure or abort of the load process */
117 
118  /** Load a game without providing any information. */
119  bool load_game_ingame();
120  /** Load a game with pre-setting information for the load-game dialog. */
121  bool load_game();
122  /** Loading a game from within the multiplayer-create dialog. */
123  bool load_multiplayer_game();
124  /** Generate the gamestate out of the loaded game config. */
125  void set_gamestate();
126 
127  // Getter-methods
129  {
130  return load_data_;
131  }
132 
133  /** GUI Dialog sequence which confirms attempts to load saves from previous game versions. */
134  static bool check_version_compatibility(const version_info & version);
135 
136  static bool is_replay_save(const config& cfg)
137  {
138  return cfg["replay"].to_bool() && !cfg["snapshot"].to_bool(true);
139  }
140 
141 private:
142  /** Display the difficulty dialog. */
143  bool show_difficulty_dialog();
144  /** Call check_version_compatibility above, using the version of this savefile. */
145  bool check_version_compatibility();
146  /** Copy era information into the snapshot. */
147  void copy_era(config& cfg);
148 
150 
151  saved_game& gamestate_; /** Primary output information. */
152 
154 };
155 /**
156  * The base class for all savegame stuff.
157  * This should not be used directly, as it does not directly produce usable saves.
158  * Instead, use one of the derived classes.
159  *
160  * Saves are only created in filesystem::get_saves_dir() - files can be loaded
161  * from elsewhere, but writes are only to that directory.
162  */
163 class savegame
164 {
165 protected:
166  /** The only constructor of savegame. The title parameter is only necessary if you
167  intend to do interactive saves. */
168  savegame(saved_game& gamestate, const compression::format compress_saves, const std::string& title = "Save");
169 
170 public:
171  enum DIALOG_TYPE { YES_NO, OK_CANCEL};
172 
173  virtual ~savegame() {}
174 
175  /** Saves a game without user interaction, unless the file exists and it should be asked
176  to overwrite it. The return value denotes, if the save was successful or not.
177  This is used by automatically generated replays, start-of-scenario saves, autosaves,
178  and saves from the console (e.g. ":w").
179  */
180  bool save_game_automatic(bool ask_for_overwrite = false, const std::string& filename = "");
181 
182  /** Save a game interactively through the savegame dialog. Used for manual midgame and replay
183  saves. The return value denotes, if the save was successful or not. */
184  bool save_game_interactive(const std::string& message,
185  DIALOG_TYPE dialog_type);
186 
187  const std::string& filename() const { return filename_; }
188 
189  /** Build the filename according to the specific savegame's needs. */
191  {
192  return create_filename(gamestate().get_starting_point()["turn_at"]);
193  }
194 
195  /** Build the filename for the specified turn. */
196  std::string create_filename(unsigned int turn_number) const;
197 
198 protected:
199  /**
200  Save a game without any further user interaction.
201  The return value denotes, if the save was successful or not.
202  */
203  bool save_game(const std::string& filename = "");
204 
205  /** Check, if the filename contains illegal constructs like ".gz". */
206  bool check_filename(const std::string& filename);
207 
208  /** Customize the standard error message */
209  void set_error_message(const std::string& error_message) { error_message_ = error_message; }
210 
211  const std::string& title() const { return title_; }
212  const saved_game& gamestate() const { return gamestate_; }
213 
214  /** If there needs to be some data fiddling before saving the game, this is the place to go. */
215  void before_save();
216 
217  /** Writing the savegame config to a file. */
218  virtual void write_game(config_writer &out);
219 
220  /** Filename of the savegame file on disk */
222 
223  /** Title of the savegame dialog */
225 
226  /** Will (at the time of writing) be save_index_class::default_saves_dir().
227  There may be different instances the index for different directories, however
228  writing is only expected to happen in the default save directory.
229 
230  Making this a class member anyway, while I'm refactoring. */
231  std::shared_ptr<save_index_class> save_index_manager_;
232 
233 private:
234  /** Subclass-specific part of filename building. */
235  virtual std::string create_initial_filename(unsigned int turn_number) const = 0;
236  /** Display the save game dialog. */
237  virtual int show_save_dialog(const std::string& message, DIALOG_TYPE dialog_type);
238  /** Ask the user if an existing file should be overwritten. */
239  bool check_overwrite();
240 
241  /** The actual method for saving the game to disk. All interactive filename choosing and
242  data manipulation has to happen before calling this method. */
243  void write_game_to_disk(const std::string& filename);
244 
245  /** Update the save_index */
246  void finish_save_game(const config_writer &out);
247  /** Throws game::save_game_failed. */
248  filesystem::scoped_ostream open_save_game(const std::string &label);
249  friend class save_info;
250  //before_save (write replay data) changes this so it cannot be const
252 
253  std::string error_message_; /** Error message to be displayed if the savefile could not be generated. */
254 
255  bool show_confirmation_; /** Determines if a confirmation of successful saving the game is shown. */
256 
257  compression::format compress_saves_; /** Determines, what compression format is used for the savegame file */
258 };
259 
260 /** Class for "normal" midgame saves. The additional members are needed for creating the snapshot
261  information. */
262 class ingame_savegame : public savegame
263 {
264 public:
265  ingame_savegame(saved_game& gamestate, const compression::format compress_saves);
266 
267 private:
268  /** Create a filename for automatic saves */
269  virtual std::string create_initial_filename(unsigned int turn_number) const override;
270 
271 
272  void write_game(config_writer &out) override;
273 };
274 
275 /** Class for replay saves (either manually or automatically). */
276 class replay_savegame : public savegame
277 {
278 public:
279  replay_savegame(saved_game& gamestate, const compression::format compress_saves);
280 
281 private:
282  /** Create a filename for automatic saves */
283  virtual std::string create_initial_filename(unsigned int turn_number) const override;
284 
285  void write_game(config_writer &out) override;
286 };
287 
288 /** Class for autosaves. */
290 {
291 public:
292  autosave_savegame(saved_game &gamestate, const compression::format compress_saves);
293 
294  void autosave(const bool disable_autosave, const int autosave_max, const int infinite_autosaves);
295 private:
296  /** Create a filename for automatic saves */
297  virtual std::string create_initial_filename(unsigned int turn_number) const override;
298 };
299 
301 {
302 public:
303  oos_savegame(saved_game& gamestate, bool& ignore);
304 
305  /** Customize the dialog's caption. */
306  void set_title(const std::string& val) { title_ = val; }
307 
308 private:
309  /** Display the save game dialog. */
310  virtual int show_save_dialog(const std::string& message, DIALOG_TYPE dialog_type) override;
311  bool& ignore_;
312 };
313 
314 /** Class for start-of-scenario saves */
316 {
317 public:
318  scenariostart_savegame(saved_game& gamestate, const compression::format compress_saves);
319 
320 private:
321  /** Create a filename for automatic saves */
322  virtual std::string create_initial_filename(unsigned int turn_number) const override;
323 
324  void write_game(config_writer &out) override;
325 };
326 
327 } //end of namespace savegame
Class for start-of-scenario saves.
Definition: savegame.hpp:315
The class for loading a savefile.
Definition: savegame.hpp:109
std::string filename
Name of the savefile to be loaded (not including the directory).
Definition: savegame.hpp:58
const game_config_view & game_config_
Definition: savegame.hpp:149
#define IMPLEMENT_LUA_JAILBREAK_EXCEPTION(type)
Helper macro for classes deriving from lua_jailbreak_exception.
bool cancel_orders
State of the "cancel_orders" checkbox in the load-game dialog.
Definition: savegame.hpp:67
const std::string & filename() const
Definition: savegame.hpp:187
logger & info()
Definition: log.cpp:90
Class for autosaves.
Definition: savegame.hpp:289
load_game_metadata load_data_
Primary output information.
Definition: savegame.hpp:153
Class for "normal" midgame saves.
Definition: savegame.hpp:262
compression::format compress_saves_
Determines if a confirmation of successful saving the game is shown.
Definition: savegame.hpp:257
Definitions for the interface to Wesnoth Markup Language (WML).
void set_title(const std::string &val)
Customize the dialog&#39;s caption.
Definition: savegame.hpp:306
load_game_metadata & data()
Definition: savegame.hpp:128
load_game_metadata data_
Definition: savegame.hpp:102
std::string filename_
Definition: action_wml.cpp:558
load_game_exception(load_game_metadata &&data)
Definition: savegame.hpp:97
const saved_game & gamestate() const
Definition: savegame.hpp:212
Class for writing a config out to a file in pieces.
bool disable_autosave
virtual ~loadgame()
Definition: savegame.hpp:113
saved_game & gamestate_
Definition: savegame.hpp:151
std::string create_filename() const
Build the filename according to the specific savegame&#39;s needs.
Definition: savegame.hpp:190
static bool is_replay_save(const config &cfg)
Definition: savegame.hpp:136
std::string error_message_
Definition: savegame.hpp:253
load_game_metadata(std::shared_ptr< save_index_class > index, const std::string &fname="", const std::string &hard="", bool replay=false, bool stop=false, bool change=false, const config &summary=config(), const config &info=config())
Definition: savegame.hpp:78
void convert_old_saves(config &cfg)
converts saves from older versions of wesnoth
Definition: savegame.cpp:854
std::unique_ptr< std::ostream > scoped_ostream
Definition: filesystem.hpp:40
Exception used to signal that the user has decided to abortt a game, and to load another game instead...
Definition: savegame.hpp:93
std::shared_ptr< save_index_class > save_index_manager_
Will (at the time of writing) be save_index_class::default_saves_dir().
Definition: savegame.hpp:231
void clean_saves(const std::string &label)
Delete all autosaves of a certain scenario from the default save directory.
Definition: savegame.cpp:70
Game configuration data as global variables.
Definition: build_info.cpp:55
saved_game & gamestate_
Definition: savegame.hpp:251
std::string title_
Title of the savegame dialog.
Definition: savegame.hpp:224
std::string difficulty
The difficulty the save is meant to be loaded with.
Definition: savegame.hpp:61
bool show_confirmation_
Error message to be displayed if the savefile could not be generated.
Definition: savegame.hpp:255
Declarations for File-IO.
config summary
Summary config of the save selected in the load game dialog.
Definition: savegame.hpp:73
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:71
Class for replay saves (either manually or automatically).
Definition: savegame.hpp:276
Represents version numbers.
void set_error_message(const std::string &error_message)
Customize the standard error message.
Definition: savegame.hpp:209
virtual ~savegame()
Definition: savegame.hpp:173
std::shared_ptr< save_index_class > manager
There may be different instances of the index for different directories.
Definition: savegame.hpp:55
bool show_replay
State of the "show_replay" checkbox in the load-game dialog.
Definition: savegame.hpp:64
Filename and modification date for a file list.
Definition: save_index.hpp:26
bool select_difficulty
State of the "change_difficulty" checkbox in the load-game dialog.
Definition: savegame.hpp:70
const std::string & title() const
Definition: savegame.hpp:211
std::string filename_
Filename of the savegame file on disk.
Definition: savegame.hpp:221
bool save_game_exists(std::string name, compression::format compressed)
Returns true if there is already a savegame with this name, looking only in the default save director...
Definition: savegame.cpp:63
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:68
Base class for exceptions that want to be thrown &#39;through&#39; lua.
config load_config
Config information of the savefile to be loaded.
Definition: savegame.hpp:76