49 #define LOG_SAVE LOG_STREAM(info, log_engine) 
   50 #define ERR_SAVE LOG_STREAM(err, log_engine) 
   53 #define LOG_RG LOG_STREAM(info, log_enginerefac) 
   66     const std::string prefix = 
label + 
"-" + 
_(
"Auto-Save");
 
   67     LOG_SAVE << 
"Cleaning saves with prefix '" << prefix << 
"'";
 
   70     for(
const auto& save : manager->get_saves_list()) {
 
   71         if(save.name().compare(0, prefix.length(), prefix) == 0) {
 
   72             LOG_SAVE << 
"Deleting savegame '" << save.name() << 
"'";
 
   73             manager->delete_game(save.name());
 
   80 bool show_difficulty_dialog(load_game_metadata& load_data)
 
   82     std::string campaign_id = 
load_data.summary[
"campaign"];
 
   85     if(
const auto campaign = 
game_config.find_child(
"campaign", 
"id", campaign_id)) {
 
   89         if(!difficulty_dlg.show()) {
 
   93         load_data.difficulty = difficulty_dlg.selected_difficulty();
 
  108     auto era = replay_start->optional_child(
"era");
 
  118     snapshot->add_child(
"era", *era);
 
  122 bool check_version_compatibility(
const version_info& save_version)
 
  143             = 
_(
"This save is from an old, unsupported version ($version_number|) and cannot be loaded.");
 
  145         symbols[
"version_number"] = save_version.
str();
 
  150     if(
prefs::get().confirm_load_save_from_different_version()) {
 
  152             = 
_(
"This save is from a different version of the game ($version_number|), and might not work with this " 
  155                 "<b>Warning:</b> saves in the middle of campaigns are especially likely to fail, and you should either " 
  156                 "use the old version or restart the campaign. Even when a saved game seems to load successfully, " 
  157                 "subtler aspects like gameplay balance and story progression could be impacted. The difficulty, the " 
  158                 "challenge, the <i>fun</i> may be missing.\n" 
  160                 "For example, the campaign may have been rebalanced with fewer enemies in the early scenarios, but " 
  161                 "expecting your recall list to have correspondingly less experience in the late scenarios.\n" 
  163                 "Do you wish to continue?");
 
  165         symbols[
"version_number"] = save_version.
str();
 
  175 bool check_version_compatibility(
const config& 
cfg)
 
  177     return check_version_compatibility(
cfg[
"version"].str());
 
  211         return utils::nullopt;
 
  219         return utils::nullopt;
 
  224             return utils::nullopt;
 
  228     if(!check_version_compatibility(
load_data.load_config)) {
 
  229         return utils::nullopt;
 
  242         return utils::nullopt;
 
  255         return utils::nullopt;
 
  260         return utils::nullopt;
 
  265     if(!metadata.is_multiplayer()) {
 
  267         return utils::nullopt;
 
  270     if(!check_version_compatibility(metadata.version)) {
 
  271         return utils::nullopt;
 
  288     , gamestate_(gamestate)
 
  289     , error_message_(
_(
"The game could not be saved: "))
 
  290     , show_confirmation_(false)
 
  291     , compress_saves_(compress_saves)
 
  295 bool savegame::save_game_automatic(
bool ask_for_overwrite, 
const std::string& 
filename)
 
  303     if(ask_for_overwrite) {
 
  304         if(!check_overwrite()) {
 
  305             return save_game_interactive(
"", savegame::OK_CANCEL);
 
  312 bool savegame::save_game_interactive(
const std::string& message, 
DIALOG_TYPE dialog_type)
 
  314     show_confirmation_ = 
true;
 
  317     const int res = show_save_dialog(message, dialog_type);
 
  330 int savegame::show_save_dialog(
const std::string& message, 
DIALOG_TYPE dialog_type)
 
  334     if(dialog_type == OK_CANCEL) {
 
  338     } 
else if(dialog_type == YES_NO) {
 
  351 bool savegame::check_overwrite()
 
  357     std::ostringstream message;
 
  358     message << 
_(
"Save already exists. Do you want to overwrite it?") << 
"\n" << 
_(
"Name: ") << 
filename_;
 
  363 bool savegame::check_filename(
const std::string& 
filename)
 
  371         gui2::show_error_message(
_(
"Save names may not end with a dot, or contain two dots or any of the following characters:\n    \" * / : < > ? \\ | ~"));
 
  378 std::string savegame::create_filename(
unsigned int turn_number)
 const 
  380     return create_initial_filename(turn_number);
 
  383 void savegame::before_save()
 
  387 bool savegame::save_game(
const std::string& 
filename)
 
  390         utils::optional<const utils::ms_optimer> timer([
this](
const auto& timer) {
 
  418         if(show_confirmation_) {
 
  433 void savegame::write_game_to_disk(
const std::string& 
filename)
 
  440     std::stringstream ss;
 
  444         finish_save_game(out);
 
  461     gamestate_.write_general_info(out);
 
  486     : 
savegame(gamestate, compress_saves)
 
  503     : 
savegame(gamestate, compress_saves, 
_(
"Save Replay"))
 
  540     manager->delete_old_auto_saves(autosave_max, infinite_autosaves);
 
  579     : 
savegame(gamestate, compress_saves, 
_(
"Save Game"))
 
  592     if(!
gamestate().get_starting_point().validate_wml()) {
 
  624             carryover.add_child(
"menu_item", menu_item);
 
  635         if(!snapshot.
empty()) {
 
  651         } 
else if(!replay_start.
empty()) {
 
  664         if(!snapshot.
empty()) {
 
  665             if(
auto variables_from_snapshot = snapshot.
optional_child(
"variables")) {
 
  666                 carryover.add_child(
"variables", *variables_from_snapshot);
 
  669                 carryover.add_child(
"variables", *variables_from_cfg);
 
  670                 carryover_start.
add_child(
"variables", *variables_from_cfg);
 
  672         } 
else if(!replay_start.
empty()) {
 
  674                 carryover.add_child(
"variables", *variables);
 
  675                 carryover_start.
add_child(
"variables", *variables);
 
  683         cfg.
add_child(
"carryover_sides_start", carryover_start);
 
  688         LOG_RG << 
"removing replay_start";
 
  694         LOG_RG << 
"removing replay";
 
  698     if(snapshot.
empty()) {
 
  699         LOG_RG << 
"removing snapshot";
 
  707         if(!carryover_sides_start->has_attribute(
"next_underlying_unit_id")) {
 
  708             carryover_sides_start[
"next_underlying_unit_id"] = 
cfg[
"next_underlying_unit_id"];
 
  723             snapshot->add_child(
"end_level_data", *end_level);
 
  724             snapshot->clear_children(
"end_level");
 
  742                 "mp_use_map_settings",
 
  752         if(multiplayer[
"mp_era"] == 
"era_blank") {
 
  753             multiplayer[
"mp_era"] = 
"era_default";
 
  760             for(
config& 
unit : side.child_range(
"unit")) {
 
  761                 if(
auto modifications = 
unit.optional_child(
"modifications")) {
 
  763                         modifications->add_child(
"advancement", advancement);
 
  765                     modifications->clear_children(
"advance");
 
  772         if(snapshot.has_attribute(
"used_items")) {
 
  774             for(
const std::string& item : 
utils::split(snapshot[
"used_items"])) {
 
  775                 used_items[item] = 
true;
 
  779             snapshot.add_child(
"used_items", used_items);
 
  787     if(
cfg[
"era_id"].empty()) {
 
  791     if(
cfg[
"active_mods"].empty()) {
 
  817     LOG_RG << 
"cfg after conversion " << 
cfg;
 
Class for writing a config out to a file in pieces.
 
void close_child(const std::string &key)
 
void write_child(const std::string &key, const config &cfg)
 
void write_key_val(const std::string &key, const T &value)
This template function will work with any type that can be assigned to an attribute_value.
 
void open_child(const std::string &key)
 
A config object defines a single node in a WML file, with access to child nodes.
 
void remove_attribute(std::string_view key)
 
config & add_child(std::string_view key)
 
optional_config_impl< config > optional_child(std::string_view key, int n=0)
Equivalent to mandatory_child, but returns an empty optional if the nth child was not found.
 
child_itors child_range(std::string_view key)
 
void clear_children(T... keys)
 
bool has_child(std::string_view key) const
Determine whether a config has a child or not.
 
const config & child_or_empty(std::string_view key) const
Returns the first child with the given key, or an empty config if there is none.
 
config & mandatory_child(std::string_view key, int n=0)
Returns the nth child with the given key, or throws an error if there is none.
 
std::string label
Name of the game (e.g.
 
static game_config_manager * get()
 
const game_config_view & game_config() const
 
A class grating read only view to a vector of config objects, viewed as one config with all children ...
 
static bool execute(savegame::load_game_metadata &data)
 
@ yes_no_buttons
Shows a yes and no button.
 
bool show(const unsigned auto_close_time=0)
Shows the window.
 
void write(config_writer &out) const
 
game_classification & classification()
 
void set_data(config &&cfg)
 
replay_recorder_base & get_replay()
 
void write_carryover(config_writer &out) const
 
void autosave(const bool disable_autosave, const int autosave_max, const int infinite_autosaves)
 
autosave_savegame(saved_game &gamestate, const compression::format compress_saves)
 
virtual std::string create_initial_filename(unsigned int turn_number) const override
Create a filename for automatic saves.
 
Class for "normal" midgame saves.
 
ingame_savegame(saved_game &gamestate, const compression::format compress_saves)
 
void write_game(config_writer &out) override
Writing the savegame config to a file.
 
virtual std::string create_initial_filename(unsigned int turn_number) const override
Create a filename for automatic saves.
 
Exception used to signal that the user has decided to abort a game, and to load another game instead.
 
oos_savegame(saved_game &gamestate, bool &ignore)
 
virtual int show_save_dialog(const std::string &message, DIALOG_TYPE dialog_type) override
Display the save game dialog.
 
void write_game(config_writer &out) override
Writing the savegame config to a file.
 
virtual std::string create_initial_filename(unsigned int turn_number) const override
Create a filename for automatic saves.
 
replay_savegame(saved_game &gamestate, const compression::format compress_saves)
 
static std::shared_ptr< save_index_class > default_saves_dir()
Returns an instance for managing saves in filesystem::get_saves_dir()
 
The base class for all savegame stuff.
 
bool check_filename(const std::string &filename)
Check, if the filename contains illegal constructs like ".gz".
 
std::string filename_
Filename of the savegame file on disk.
 
bool save_game_automatic(bool ask_for_overwrite=false, const std::string &filename="")
Saves a game without user interaction, unless the file exists and it should be asked to overwrite it.
 
virtual void write_game(config_writer &out)
Writing the savegame config to a file.
 
std::string create_filename() const
Build the filename according to the specific savegame's needs.
 
const std::string & title() const
 
const std::string & filename() const
 
void set_error_message(const std::string &error_message)
Customize the standard error message.
 
const saved_game & gamestate() const
 
scenariostart_savegame(saved_game &gamestate, const compression::format compress_saves)
 
void write_game(config_writer &out) override
Writing the savegame config to a file.
 
virtual std::string create_initial_filename(unsigned int turn_number) const override
Create a filename for automatic saves.
 
This class represents a single unit of a specific type.
 
Represents version numbers.
 
std::string str() const
Serializes the version number into string form.
 
unsigned int minor_version() const
Retrieves the minor version number (x2 in "x1.x2.x3").
 
unsigned int major_version() const
Retrieves the major version number (x1 in "x1.x2.x3").
 
Contains the exception interfaces used to signal completion of a scenario, campaign or turn.
 
void throw_quit_game_exception()
 
Interfaces for manipulating version numbers of engine, add-ons, etc.
 
static std::string _(const char *str)
 
std::string label
What to show in the filter's drop-down list.
 
Standard logging facilities (interface).
 
#define log_scope(description)
 
auto format_local_timestamp(const std::chrono::system_clock::time_point &time, std::string_view format="%F %T")
 
std::string format_extension(format compression_format)
 
static bool file_exists(const bfs::path &fpath)
 
bool is_legal_user_file_name(const std::string &name, bool allow_whitespace=true)
Returns whether the given filename is a legal name for a user-created file.
 
bool is_compressed_file(const std::string &filename)
 
filesystem::scoped_ostream ostream_file(const std::string &fname, std::ios_base::openmode mode, bool create_directory)
 
std::unique_ptr< std::ostream > scoped_ostream
 
Game configuration data as global variables.
 
const version_info min_savegame_version(MIN_SAVEGAME_VERSION)
 
const version_info test_version("test")
 
const version_info wesnoth_version(VERSION)
 
void show_transient_error_message(const std::string &message, const std::string &image, const bool message_use_markup)
Shows a transient error message to the user.
 
void show_transient_message(const std::string &title, const std::string &message, const std::string &image, const bool message_use_markup, const bool title_use_markup)
Shows a transient message to the user.
 
void show_error_message(const std::string &msg, bool message_use_markup)
Shows an error message to the user.
 
void show_message(const std::string &title, const std::string &msg, const std::string &button_caption, const bool auto_close, const bool message_use_markup, const bool title_use_markup)
Shows a message to the user.
 
@ OK
Dialog was closed with the OK button.
 
@ CANCEL
Dialog was closed with the CANCEL button.
 
persist_manager * persist
 
game_classification * classification
 
config read_save_file(const std::string &dir, const std::string &name)
Read the complete config information out of a savefile.
 
void clean_saves(const std::string &label)
Delete all autosaves of a certain scenario from the default save directory.
 
static void convert_old_saves_1_13_0(config &cfg)
 
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...
 
void convert_old_saves(config &cfg)
converts saves from older versions of wesnoth
 
utils::optional< load_game_metadata > load_interactive_for_multiplayer()
 
bool is_replay_save(const config &summary)
 
void load_interactive_by_exception()
load_interactive wrapper for in-game save loading.
 
void set_gamestate(saved_game &gamestate, load_game_metadata &load_data)
 
static void convert_old_saves_1_11_0(config &cfg)
 
static void convert_old_saves_1_13_1(config &cfg)
 
utils::optional< load_game_metadata > load_interactive()
 
static void convert_old_saves_1_15_3(config &cfg)
 
std::string interpolate_variables_into_string(const std::string &str, const string_map *const symbols)
Function which will interpolate variables, starting with '$' in the string 'str' with the equivalent ...
 
std::map< std::string, t_string > string_map
 
std::vector< std::string > split(const config_attribute_value &val)
 
bool headless()
The game is running headless.
 
static lg::log_domain log_engine("engine")
 
static lg::log_domain log_enginerefac("enginerefac")
 
std::string filename
Filename.
 
An exception object used when an IO error occurs.
 
Error used when game loading fails.
 
Error used when game saving fails.