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