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