19 #include "addon/manager.hpp" 47 #define ERR_CONFIG LOG_STREAM(err, log_config) 48 #define WRN_CONFIG LOG_STREAM(warn, log_config) 49 #define LOG_CONFIG LOG_STREAM(info, log_config) 56 : cmdline_opts_(cmdline_opts)
80 if(
const std::string last_cleaned =
preferences::get(
"_last_cache_cleaned_ver"); !last_cleaned.empty()) {
144 return std::all_of(special.begin(), special.end(), [&
general](
const auto& pair) {
145 const auto it = general.find(pair.first);
146 return it != general.end() && it->second == pair.second;
156 out <<
"load_game_config: defines:";
159 out << pair.first <<
",";
169 bool reload_everything =
true;
174 reload_everything =
false;
178 reload_everything =
false;
182 LOG_CONFIG <<
"load_game_config reload everything: " << reload_everything;
205 if(reload_everything) {
219 std::vector<std::string> user_dirs;
222 std::vector<std::string> user_files;
227 for(
const std::string& umc : user_dirs) {
228 const std::string cores_file = umc +
"/cores.cfg";
238 bool current_core_valid =
false;
239 std::string wml_tree_root;
242 const std::string&
id = core[
"id"];
246 _(
"Error validating data core."),
247 _(
"Found a core without id attribute.")
248 +
'\n' +
_(
"Skipping the core."));
253 if(*&valid_cores.
find_child(
"core",
"id",
id)) {
256 _(
"Error validating data core."),
258 +
'\n' +
_(
"The ID is already in use.")
259 +
'\n' +
_(
"Skipping the core."));
264 const std::string&
path = core[
"path"];
268 _(
"Error validating data core."),
270 +
'\n' +
_(
"Core Path: ") + path
271 +
'\n' +
_(
"File not found.")
272 +
'\n' +
_(
"Skipping the core."));
277 if(
id ==
"default" && !current_core_valid) {
278 wml_tree_root =
path;
281 current_core_valid =
true;
282 wml_tree_root =
path;
288 if(!current_core_valid) {
291 _(
"Error loading core data."),
293 +
'\n' +
_(
"Error loading the core with named id.")
294 +
'\n' +
_(
"Falling back to the default core."));
300 if(wml_tree_root.empty()) {
303 _(
"Error loading core data."),
304 _(
"Can't locate the default core.")
305 +
'\n' +
_(
"The game will now exit."));
311 std::unique_ptr<schema_validation::schema_validator> validator;
320 main_transaction.
lock();
331 std::set<std::string> active_addons = classification->
active_addons(scenario_id);
334 LOG_CONFIG <<
"Configs not reloaded and active add-ons remain the same; returning early.";
366 _(
"Error loading custom game configuration files. The game will try without loading add-ons."),
373 _(
"Error loading custom game configuration files. The game will fallback to the default core files."),
382 _(
"Error loading default core game configuration files. The game will now exit."),
399 std::vector<std::string> error_log;
400 std::vector<std::string> error_addons;
401 std::vector<std::string> user_dirs;
402 std::vector<std::string> user_files;
407 for(
const std::string& file : user_files) {
408 const int size_minus_extension = file.size() - 4;
410 if(file.substr(size_minus_extension, file.size()) ==
".cfg") {
411 ERR_CONFIG <<
"error reading usermade add-on '" << file <<
"'";
413 error_addons.push_back(file);
415 const int userdata_loc = file.find(
"data/add-ons") + 5;
418 << file.substr(userdata_loc)
419 <<
"' (for single-file add-ons) is not supported anymore, use '~" 420 << file.substr(userdata_loc, size_minus_extension - userdata_loc)
421 <<
"/_main.cfg' instead.";
423 error_log.push_back(log_msg);
427 loading_screen::spin();
436 loading_screen::spin();
439 for(
const std::string& addon_id : user_dirs) {
441 const std::string addon_dir = user_campaign_dir +
"/" + addon_id;
443 const std::string main_cfg = addon_dir +
"/_main.cfg";
444 const std::string info_cfg = addon_dir +
"/_info.cfg";
450 loading_screen::spin();
463 <<
"The provided addon has an invalid pbl file" 467 error_addons.push_back(e.
message);
468 error_log.push_back(log_msg);
478 std::string using_core = metadata[
"core"];
479 if(using_core.empty()) {
480 using_core =
"default";
489 std::string addon_title = metadata[
"title"].str();
490 if(addon_title.empty()) {
491 addon_title = addon_id;
497 std::unique_ptr<schema_validation::schema_validator> validator;
503 loading_screen::spin();
509 static const std::set<std::string> tags_with_addon_id {
521 if(tags_with_addon_id.count(child.key) > 0) {
522 auto& cfg = child.cfg;
523 cfg[
"addon_id"] = addon_id;
524 cfg[
"addon_title"] = addon_title;
526 cfg[
"addon_version"] = addon_version.
str();
530 loading_screen::spin();
533 for(
auto&
unit_type : units.child_range(
"unit_type")) {
534 for(
const auto& advancefrom :
unit_type.child_range(
"advancefrom")) {
536 {
"lower_level", advancefrom[
"unit"]},
543 "Error: [advancefrom] no longer works. ‘$lower_level’ units will not be able to advance to ‘$higher_level’; please ask the add-on author to use [modify_unit_type] instead.",
547 unit_type.remove_children(
"advancefrom", [](
const config&){
return true;});
551 loading_screen::spin();
554 static const std::set<std::string> deprecated_defines {
556 "DISABLE_GRAND_MARSHAL",
557 "ENABLE_ARMAGEDDON_DRAKE",
558 "ENABLE_DWARVISH_ARCANISTER",
559 "ENABLE_DWARVISH_RUNESMITH",
560 "ENABLE_WOLF_ADVANCEMENT",
562 "ENABLE_TROLL_SHAMAN",
563 "ENABLE_ANCIENT_LICH",
564 "ENABLE_DEATH_KNIGHT",
568 for(
auto& campaign : umc_cfg.
child_range(
"campaign")) {
569 for(
auto str :
utils::split(campaign[
"extra_defines"])) {
570 if(deprecated_defines.count(str) > 0) {
578 "campaign id='" + campaign[
"id"].str() +
"' has extra_defines=" + str,
581 _(
"instead, use the macro with the same name in the [campaign] tag")
587 loading_screen::spin();
589 static const std::set<std::string> entry_tags {
598 for(
const std::string& tagname : entry_tags) {
602 loading_screen::spin();
606 ERR_CONFIG <<
"config error reading usermade add-on '" << main_cfg <<
"'";
608 error_addons.push_back(main_cfg);
609 error_log.push_back(err.
message);
611 ERR_CONFIG <<
"preprocessor config error reading usermade add-on '" << main_cfg <<
"'";
613 error_addons.push_back(main_cfg);
614 error_log.push_back(err.
message);
616 ERR_CONFIG <<
"filesystem I/O error reading usermade add-on '" << main_cfg <<
"'";
617 error_addons.push_back(main_cfg);
623 ERR_CONFIG <<
"Didn’t find an add-on for --validate-addon - check whether the id has a typo";
625 <<
"Didn't find an add-on for --validate-addon - check whether the id has a typo";
626 error_log.push_back(log_msg);
627 throw game::error(
"Did not find an add-on for --validate-addon");
630 WRN_CONFIG <<
"Note: for --validate-addon to find errors, you have to play (in the GUI) a game that uses the add-on.";
633 if(!error_addons.empty()) {
634 const std::size_t
n = error_addons.size();
635 const std::string& msg1 =
636 _n(
"The following add-on had errors and could not be loaded:",
637 "The following add-ons had errors and could not be loaded:",
639 const std::string& msg2 =
640 _n(
"Please report this to the author or maintainer of this add-on.",
641 "Please report this to the respective authors or maintainers of these add-ons.",
644 const std::string& report =
utils::join(error_log,
"\n\n");
655 hashes[ch[
"id"].str()] = ch.
hash();
706 std::deque<game_config::scoped_preproc_define> extra_defines;
708 extra_defines.emplace_back(extra_define);
711 std::deque<game_config::scoped_preproc_define> modification_defines;
712 for(
const std::string& mod_define : classification.
mod_defines) {
713 modification_defines.emplace_back(mod_define, !mod_define.empty());
721 std::deque<game_config::scoped_preproc_define> previous_defines;
723 previous_defines.emplace_back(preproc.first);
751 std::deque<game_config::scoped_preproc_define> previous_defines;
753 previous_defines.emplace_back(preproc.first);
767 for(
const std::string&
id : addon_ids) {
771 vec.push_back(it->second);
773 ERR_CONFIG <<
"Attempted to enable add-on '" <<
id <<
"' but its config could not be found";
786 LOG_CONFIG <<
"Enabling add-on " << pair.first;
787 vec.push_back(pair.second);
void load_game_config(bool reload_everything, const game_classification *classification, const std::string &scenario_id)
Don't reload if the previous defines include the new defines.
void set_enabled_addon_all()
static std::string _n(const char *str1, const char *str2, int n)
bool any_validation_option() const
True if the –validate or any of the –validate-* options are given.
void reload()
Reads the mainline achievements.cfg and then all the achievements of each installed add-on...
bool mptest
True if –mp-test was given on the command line.
const_all_children_itors all_children_range() const
In-order iteration over all children.
std::map< std::string, t_string > string_map
Interfaces for manipulating version numbers of engine, add-ons, etc.
std::optional< std::string > test
Non-empty if –test was given on the command line.
game_classification * classification
void append(const config &cfg)
Append data from another config object to this one.
std::string join(const T &v, const std::string &s=",")
Generates a new string joining container items in a list.
void append_children_by_move(config &cfg, const std::string &key)
Moves children with the given name from the given config to this one.
config & find_child(config_key_type key, const std::string &name, const std::string &value)
Returns the first child of tag key with a name attribute containing value.
bool noaddons
True if –noaddons was given on the command line.
Exception thrown when the WML parser fails to read a .pbl file.
void lock()
Lock the transaction so no more macros are added.
void load_game_config_with_loadscreen(FORCE_RELOAD_CONFIG force_reload, const game_classification *classification, const std::string &scenario_id)
static bool file_exists(const bfs::path &fpath)
static void init(const game_config_view &game_config)
Init the parameters of ai configuration parser.
child_itors child_range(config_key_type key)
filesystem::binary_paths_manager paths_manager_
static void progress(loading_stage stage=loading_stage::none)
Report what is being loaded to the loading screen.
void load_game_config_for_game(const game_classification &classification, const std::string &scenario_id)
const std::string DEFAULT_DIFFICULTY
The default difficulty setting for campaigns.
config get_addon_pbl_info(const std::string &addon_name, bool do_validate)
Gets the publish information for an add-on.
achievements achievements_
static void set_known_themes(const game_config_view *cfg)
Copies the theme configs from the main game config.
unit_type_data unit_types
void set(const std::string &key, bool value)
Don't reload if the previous defines equal the new defines.
static lg::log_domain log_config("config")
void init_textdomains(const game_config_view &cfg)
Initializes the list of textdomains from a configuration object.
static std::string _(const char *str)
void load_config(const config &v)
A single unit type that the player may recruit.
Used to set and unset scoped defines to preproc_map.
void call_in_main_thread(const std::function< void(void)> &f)
constexpr uint32_t scope_main
void flush_cache()
Purges all image caches.
void clear_binary_paths_cache()
One of the realizations of serialization/validator.hpp abstract validator.
void load_game_config_for_editor()
std::set< std::string > active_addons_
static game_config_manager * get()
void set_about(const game_config_view &cfg)
Regenerates the credits data.
std::string get(const std::string &key)
std::set< std::string > active_addons(const std::string &scenario_id) const
std::string deprecated_message(const std::string &elem_name, DEP_LEVEL level, const version_info &version, const std::string &detail)
bool clean_cache()
Deletes stale cache files not in use by the game.
const std::string message
Error message to display.
preproc_map old_defines_map_
std::optional< std::string > validate_addon
Non-empty if –validate-addon was given on the command line.
void get_files_in_dir(const std::string &dir, std::vector< std::string > *files, std::vector< std::string > *dirs, name_mode mode, filter_mode filter, reorder_mode reorder, file_tree_checksum *checksum)
Get a list of all files and/or directories in a given directory.
std::string campaign_define
If there is a define the campaign uses to customize data.
const game_config_view & game_config() const
game_config_view game_config_view_
void set_force_valid_cache(bool force)
Enable/disable cache validation.
void set_core_id(const std::string &core_id)
static game_config_manager * singleton
#define log_scope2(domain, description)
bool multiplayer
True if –multiplayer was given on the command line.
void refresh_addon_version_info_cache()
Refreshes the per-session cache of add-on's version information structs.
void set_multiplayer_hashes()
static void add_color_info(const game_config_view &v, bool build_defaults)
bool is_multiplayer() const
bool init_strings(const game_config_view &cfg)
Initializes certain English strings.
std::string era_define
If there is a define the era uses to customize data.
void get_config(const std::string &path, config &cfg, abstract_validator *validator=nullptr)
Gets a config object from given path.
void set_use_cache(bool use)
Enable/disable caching.
std::string id
Text to match against addon_info.tags()
#define FORCE_LOG_TO(logger, domain)
void clear_defines()
Clear stored defines map to default values.
bool nocache
True if –nocache was given on the command line.
void set_enabled_addon(std::set< std::string > addon_ids)
std::vector< std::string > campaign_xtra_defines
more customization of data
std::string get_wml_location(const std::string &filename, const std::string ¤t_dir)
Returns a complete path to the actual WML file or directory or an empty string if the file isn't pres...
bool have_addon_pbl_info(const std::string &addon_name)
Returns whether a .pbl file is present for the specified add-on or not.
void load_game_config_for_create(bool is_mp, bool is_test=false)
Game configuration data as global variables.
const preproc_map & get_preproc_map() const
An exception object used when an IO error occurs.
std::string scenario_define
If there is a define the scenario uses to customize data.
std::vector< std::string > mod_defines
If there are defines the modifications use to customize data.
Definitions related to theme-support.
Definitions for the terrain builder.
const version_info wesnoth_version(VERSION)
static void display(const std::string &summary, const std::string &post_summary, const std::vector< std::string > &files, const std::string &details)
The display function; see modal_dialog for more information.
Represents version numbers.
config & add_child(config_key_type key)
const file_tree_checksum & data_tree_checksum(bool reset=false)
Get the time at which the data/ tree was last modified at.
std::string difficulty
The difficulty level the game is being played on.
Used to share macros between cache objects You have to create transaction object to load all macros t...
void set_paths(const game_config_view &cfg)
static void display(std::function< void()> f)
game_config_manager(const commandline_options &cmdline_opts)
void set_config(const game_config_view &cfg)
Resets all data based on the provided config.
std::vector< std::string > split(const config_attribute_value &val)
Base class for all the errors encountered by the engine.
std::string get_addons_dir()
Managing the AIs configuration - headers.
bool validate_core
True if –validate-core was given on the command line.
Standard logging facilities (interface).
void load_default_hotkeys(const game_config_view &cfg)
Registers all hotkeys present in this config.
std::string str() const
Serializes the version number into string form.
const commandline_options & cmdline_opts_
bool validcache
True if –validcache was given on the command line.
std::optional< std::string > editor
Non-empty if –editor was given on the command line.
game_config::config_cache & cache_
std::map< std::string, struct preproc_define > preproc_map
Realization of serialization/validator.hpp abstract validator.
void reload_changed_game_config()
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.
void set_create_exceptions(bool value)
A config object defines a single node in a WML file, with access to child nodes.
static void set_terrain_rules_cfg(const game_config_view &cfg)
Set the config where we will parse the global terrain rules.
static map_location::DIRECTION n
bool init_game_config(FORCE_RELOAD_CONFIG force_reload)
std::map< std::string, config > addon_cfgs_
config_array_view & data()
void init_advanced_manager(const game_config_view &gc)
Initializes the manager singleton.
static void extract_preload_scripts(const game_config_view &game_config)
std::shared_ptr< terrain_type_data > tdata_
void recheck_filetree_checksum()
Force cache checksum validation.