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);
159 return utils::nullopt;
167 return utils::nullopt;
172 return utils::nullopt;
177 return utils::nullopt;
203 const std::string message
204 =
_(
"This save is from an old, unsupported version ($version_number|) and cannot be loaded.");
206 symbols[
"version_number"] = save_version.
str();
211 if(
prefs::get().confirm_load_save_from_different_version()) {
212 const std::string message
213 =
_(
"This save is from a different version of the game ($version_number|), and might not work with this "
216 "<b>Warning:</b> saves in the middle of campaigns are especially likely to fail, and you should either "
217 "use the old version or restart the campaign. Even when a saved game seems to load successfully, "
218 "subtler aspects like gameplay balance and story progression could be impacted. The difficulty, the "
219 "challenge, the <i>fun</i> may be missing.\n"
221 "For example, the campaign may have been rebalanced with fewer enemies in the early scenarios, but "
222 "expecting your recall list to have correspondingly less experience in the late scenarios.\n"
224 "Do you wish to continue?");
226 symbols[
"version_number"] = save_version.
str();
242 return utils::nullopt;
255 return utils::nullopt;
260 return utils::nullopt;
265 if(!metadata.is_multiplayer()) {
267 return utils::nullopt;
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.
const config & child_or_empty(config_key_type key) const
Returns the first child with the given key, or an empty config if there is none.
config & mandatory_child(config_key_type key, int n=0)
Returns the nth child with the given key, or throws an error if there is none.
void clear_children(T... keys)
bool has_child(config_key_type key) const
Determine whether a config has a child or not.
child_itors child_range(config_key_type key)
void remove_attribute(config_key_type key)
optional_config_impl< config > optional_child(config_key_type key, int n=0)
Equivalent to mandatory_child, but returns an empty optional if the nth child was not found.
config & add_child(config_key_type key)
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 check_version_compatibility(const version_info &version)
Confirms attempts to load saves from previous game versions.
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.