The Battle for Wesnoth  1.19.15+dev
savegame.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2025
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*/
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  /** Reads the savefile @ref filename and stores the result in @ref load_config. */
79  void read_file();
80 };
81 
82 /**
83 * Exception used to signal that the user has decided to abort a game,
84 * and to load another game instead.
85 */
87  : public lua_jailbreak_exception, public std::exception
88 {
89 public:
92  , data_(std::move(data))
93  {
94  this->store();
95  }
97 private:
98 
100 };
101 
102 /** @note This function expects a save_index summary config */
103 inline bool is_replay_save(const config& summary)
104 {
105  return summary["replay"].to_bool() && !summary["snapshot"].to_bool(true);
106 }
107 
108 utils::optional<load_game_metadata> load_interactive();
109 utils::optional<load_game_metadata> load_interactive_for_multiplayer();
110 
111 /**
112  * @ref load_interactive wrapper for in-game save loading.
113  *
114  * If load_interactive returns a load_game_metadata object,
115  * throws load_game_exception with said object as its payload.
116  * Otherwise, no exception is thrown.
117  */
119 
120 void set_gamestate(saved_game& gamestate, load_game_metadata& load_data);
121 
122 /**
123  * The base class for all savegame stuff.
124  * This should not be used directly, as it does not directly produce usable saves.
125  * Instead, use one of the derived classes.
126  *
127  * Saves are only created in filesystem::get_saves_dir() - files can be loaded
128  * from elsewhere, but writes are only to that directory.
129  */
130 class savegame
131 {
132 protected:
133  /** The only constructor of savegame. The title parameter is only necessary if you
134  intend to do interactive saves. */
135  savegame(saved_game& gamestate, const compression::format compress_saves, const std::string& title = "Save");
136 
137 public:
138  enum DIALOG_TYPE { YES_NO, OK_CANCEL};
139 
140  virtual ~savegame() {}
141 
142  /** Saves a game without user interaction, unless the file exists and it should be asked
143  to overwrite it. The return value denotes, if the save was successful or not.
144  This is used by automatically generated replays, start-of-scenario saves, autosaves,
145  and saves from the console (e.g. ":w").
146  */
147  bool save_game_automatic(bool ask_for_overwrite = false, const std::string& filename = "");
148 
149  /** Save a game interactively through the savegame dialog. Used for manual midgame and replay
150  saves. The return value denotes, if the save was successful or not. */
151  bool save_game_interactive(const std::string& message,
152  DIALOG_TYPE dialog_type);
153 
154  const std::string& filename() const { return filename_; }
155 
156  /** Build the filename according to the specific savegame's needs. */
157  std::string create_filename() const
158  {
159  return create_filename(gamestate().get_starting_point()["turn_at"].to_int());
160  }
161 
162  /** Build the filename for the specified turn. */
163  std::string create_filename(unsigned int turn_number) const;
164 
165 protected:
166  /**
167  Save a game without any further user interaction.
168  The return value denotes, if the save was successful or not.
169  */
170  bool save_game(const std::string& filename = "");
171 
172  /** Check, if the filename contains illegal constructs like ".gz". */
173  bool check_filename(const std::string& filename);
174 
175  /** Customize the standard error message */
176  void set_error_message(const std::string& error_message) { error_message_ = error_message; }
177 
178  const std::string& title() const { return title_; }
179  const saved_game& gamestate() const { return gamestate_; }
180 
181  /** If there needs to be some data fiddling before saving the game, this is the place to go. */
182  void before_save();
183 
184  /** Writing the savegame config to a file. */
185  virtual void write_game(config_writer &out);
186 
187  /** Filename of the savegame file on disk */
188  std::string filename_;
189 
190  /** Title of the savegame dialog */
191  std::string title_;
192 
193  /** Will (at the time of writing) be save_index_class::default_saves_dir().
194  There may be different instances the index for different directories, however
195  writing is only expected to happen in the default save directory.
196 
197  Making this a class member anyway, while I'm refactoring. */
198  std::shared_ptr<save_index_class> save_index_manager_;
199 
200 private:
201  /** Subclass-specific part of filename building. */
202  virtual std::string create_initial_filename(unsigned int turn_number) const = 0;
203  /** Display the save game dialog. */
204  virtual int show_save_dialog(const std::string& message, DIALOG_TYPE dialog_type);
205  /** Ask the user if an existing file should be overwritten. */
206  bool check_overwrite();
207 
208  /** The actual method for saving the game to disk. All interactive filename choosing and
209  data manipulation has to happen before calling this method. */
210  void write_game_to_disk(const std::string& filename);
211 
212  /** Update the save_index */
213  void finish_save_game(const config_writer &out);
214  /** Throws game::save_game_failed. */
215  filesystem::scoped_ostream open_save_game(const std::string &label);
216  friend class save_info;
217  //before_save (write replay data) changes this so it cannot be const
219 
220  std::string error_message_; /** Error message to be displayed if the savefile could not be generated. */
221 
222  bool show_confirmation_; /** Determines if a confirmation of successful saving the game is shown. */
223 
224  compression::format compress_saves_; /** Determines, what compression format is used for the savegame file */
225 };
226 
227 /** Class for "normal" midgame saves. The additional members are needed for creating the snapshot
228  information. */
229 class ingame_savegame : public savegame
230 {
231 public:
233 
234 private:
235  /** Create a filename for automatic saves */
236  virtual std::string create_initial_filename(unsigned int turn_number) const override;
237 
238 
239  void write_game(config_writer &out) override;
240 };
241 
242 /** Class for replay saves (either manually or automatically). */
243 class replay_savegame : public savegame
244 {
245 public:
247 
248 private:
249  /** Create a filename for automatic saves */
250  virtual std::string create_initial_filename(unsigned int turn_number) const override;
251 
252  void write_game(config_writer &out) override;
253 };
254 
255 /** Class for autosaves. */
257 {
258 public:
260 
261  void autosave(const bool disable_autosave, const int autosave_max, const int infinite_autosaves);
262 private:
263  /** Create a filename for automatic saves */
264  virtual std::string create_initial_filename(unsigned int turn_number) const override;
265 };
266 
268 {
269 public:
270  oos_savegame(saved_game& gamestate, bool& ignore);
271 
272  /** Customize the dialog's caption. */
273  void set_title(const std::string& val) { title_ = val; }
274 
275 private:
276  /** Display the save game dialog. */
277  virtual int show_save_dialog(const std::string& message, DIALOG_TYPE dialog_type) override;
278  bool& ignore_;
279 };
280 
281 /** Class for start-of-scenario saves */
283 {
284 public:
286 
287 private:
288  /** Create a filename for automatic saves */
289  virtual std::string create_initial_filename(unsigned int turn_number) const override;
290 
291  void write_game(config_writer &out) override;
292 };
293 
294 } //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:158
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:257
void autosave(const bool disable_autosave, const int autosave_max, const int infinite_autosaves)
Definition: savegame.cpp:532
autosave_savegame(saved_game &gamestate, const compression::format compress_saves)
Definition: savegame.cpp:526
virtual std::string create_initial_filename(unsigned int turn_number) const override
Create a filename for automatic saves.
Definition: savegame.cpp:543
Class for "normal" midgame saves.
Definition: savegame.hpp:230
ingame_savegame(saved_game &gamestate, const compression::format compress_saves)
Definition: savegame.cpp:578
void write_game(config_writer &out) override
Writing the savegame config to a file.
Definition: savegame.cpp:588
virtual std::string create_initial_filename(unsigned int turn_number) const override
Create a filename for automatic saves.
Definition: savegame.cpp:583
Exception used to signal that the user has decided to abort a game, and to load another game instead.
Definition: savegame.hpp:88
load_game_metadata data_
Definition: savegame.hpp:96
load_game_exception(load_game_metadata &&data)
Definition: savegame.hpp:90
oos_savegame(saved_game &gamestate, bool &ignore)
Definition: savegame.cpp:555
virtual int show_save_dialog(const std::string &message, DIALOG_TYPE dialog_type) override
Display the save game dialog.
Definition: savegame.cpp:561
void set_title(const std::string &val)
Customize the dialog's caption.
Definition: savegame.hpp:273
Class for replay saves (either manually or automatically).
Definition: savegame.hpp:244
void write_game(config_writer &out) override
Writing the savegame config to a file.
Definition: savegame.cpp:514
virtual std::string create_initial_filename(unsigned int turn_number) const override
Create a filename for automatic saves.
Definition: savegame.cpp:507
replay_savegame(saved_game &gamestate, const compression::format compress_saves)
Definition: savegame.cpp:502
Filename and modification date for a file list.
Definition: save_index.hpp:28
std::string title_
Title of the savegame dialog.
Definition: savegame.hpp:191
saved_game & gamestate_
Definition: savegame.hpp:218
std::string filename_
Filename of the savegame file on disk.
Definition: savegame.hpp:188
virtual ~savegame()
Definition: savegame.hpp:140
std::string create_filename() const
Build the filename according to the specific savegame's needs.
Definition: savegame.hpp:157
const std::string & title() const
Definition: savegame.hpp:178
bool show_confirmation_
Error message to be displayed if the savefile could not be generated.
Definition: savegame.hpp:222
std::string error_message_
Definition: savegame.hpp:220
const std::string & filename() const
Definition: savegame.hpp:154
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:198
compression::format compress_saves_
Determines if a confirmation of successful saving the game is shown.
Definition: savegame.hpp:224
void set_error_message(const std::string &error_message)
Customize the standard error message.
Definition: savegame.hpp:176
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:179
Class for start-of-scenario saves.
Definition: savegame.hpp:283
scenariostart_savegame(saved_game &gamestate, const compression::format compress_saves)
Definition: savegame.cpp:485
void write_game(config_writer &out) override
Writing the savegame config to a file.
Definition: savegame.cpp:496
virtual std::string create_initial_filename(unsigned int turn_number) const override
Create a filename for automatic saves.
Definition: savegame.cpp:491
Represents version numbers.
Definitions for the interface to Wesnoth Markup Language (WML).
const config * cfg
Declarations for File-IO.
std::string label
What to show in the filter's drop-down list.
Definition: manager.cpp:201
#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:92
void clean_saves(const std::string &label)
Delete all autosaves of a certain scenario from the default save directory.
Definition: savegame.cpp:64
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:57
void convert_old_saves(config &cfg)
converts saves from older versions of wesnoth
Definition: savegame.cpp:796
utils::optional< load_game_metadata > load_interactive_for_multiplayer()
Definition: savegame.cpp:236
bool is_replay_save(const config &summary)
Definition: savegame.hpp:103
void load_interactive_by_exception()
load_interactive wrapper for in-game save loading.
Definition: savegame.cpp:142
void set_gamestate(saved_game &gamestate, load_game_metadata &load_data)
Definition: savegame.cpp:278
utils::optional< load_game_metadata > load_interactive()
Definition: savegame.cpp:153
std::string_view data
Definition: picture.cpp:188
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
void read_file()
Reads the savefile filename and stores the result in load_config.
Definition: savegame.cpp:130
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