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