The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
game_config_manager.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2013 - 2025
3 by Andrius Silinskas <silinskas.andrius@gmail.com>
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
17
18#include "about.hpp"
19#include "addon/manager.hpp"
20#include "ai/configuration.hpp"
21#include "events.hpp"
22#include "formatter.hpp"
25#include "game_config.hpp"
26#include "game_version.hpp"
27#include "gettext.hpp"
31#include "language.hpp"
32#include "log.hpp"
33#include "picture.hpp"
37#include "sound.hpp"
39#include "terrain/builder.hpp"
40#include "terrain/type_data.hpp"
41#include "theme.hpp"
42#include "units/types.hpp"
43
44static lg::log_domain log_config("config");
45#define ERR_CONFIG LOG_STREAM(err, log_config)
46#define WRN_CONFIG LOG_STREAM(warn, log_config)
47#define LOG_CONFIG LOG_STREAM(info, log_config)
48
50
52
54 : cmdline_opts_(cmdline_opts)
55 , game_config_()
56 , game_config_view_()
57 , addon_cfgs_()
58 , active_addons_()
59 , old_defines_map_()
60 , paths_manager_()
61 , cache_(game_config::config_cache::instance())
62 , tdata_(game_config())
63 , achievements_()
64{
65 assert(!singleton);
66 singleton = this;
67
68 // All of the validation options imply --nocache, as the validation happens during cache
69 // rebuilding. If the cache isn't rebuilt, validation is silently skipped.
71 cache_.set_use_cache(false);
72 }
73
76 }
77
78 // Clean the cache of any old Wesnoth version's cache data
79 if(const std::string last_cleaned = prefs::get()._last_cache_cleaned_ver(); !last_cleaned.empty()) {
80 if(version_info{last_cleaned} < game_config::wesnoth_version) {
81 if(cache_.clean_cache()) {
82 prefs::get().set__last_cache_cleaned_ver(game_config::wesnoth_version.str());
83 }
84 }
85 } else {
86 // If the preference wasn't set, set it, else the cleaning will never happen :P
87 prefs::get().set__last_cache_cleaned_ver(game_config::wesnoth_version.str());
88 }
89}
90
96
101
103{
104 // Add preproc defines according to the command line arguments.
106 game_config::scoped_preproc_define test("TEST", cmdline_opts_.test.has_value());
109#ifdef __ANDROID__
110 game_config::scoped_preproc_define android("ANDROID", true);
111#endif
112 game_config::scoped_preproc_define title_screen("TITLE_SCREEN",
114
116
117 load_game_config_with_loadscreen(force_reload, nullptr, "");
118
119 game_config::load_config(game_config().mandatory_child("game_config"));
120
121 // It's necessary to block the event thread while load_hotkeys() runs, otherwise keyboard input
122 // can cause a crash by accessing the list of hotkeys while it's being modified.
124 const hotkey::scope_changer hk_scope{hotkey::scope_main, false};
125
126 // Load the standard hotkeys, then apply any player customizations.
129 });
130
132
136
137 return true;
138}
139
140namespace
141{
142/** returns true if every define in special is also defined in general */
143bool map_includes(const preproc_map& general, const preproc_map& special)
144{
145 return std::all_of(special.begin(), special.end(), [&general](const auto& pair) {
146 const auto it = general.find(pair.first);
147 return it != general.end() && it->second == pair.second;
148 });
149}
150} // end anonymous namespace
151
153 FORCE_RELOAD_CONFIG force_reload, const game_classification* classification, const std::string& scenario_id)
154{
155 if(!lg::info().dont_log(log_config)) {
156 auto out = formatter();
157 out << "load_game_config: defines:";
158
159 for(const auto& pair : cache_.get_preproc_map()) {
160 out << pair.first << ",";
161 }
162
163 out << "\n";
164 FORCE_LOG_TO(lg::info(), log_config) << out.str();
165 }
166
167 game_config::scoped_preproc_define debug_mode("DEBUG_MODE",
169
170 bool reload_everything = true;
171
172 // Game_config already holds requested config in memory.
173 if(!game_config_.empty()) {
174 if(force_reload == NO_FORCE_RELOAD && old_defines_map_ == cache_.get_preproc_map()) {
175 reload_everything = false;
176 }
177
178 if(force_reload == NO_INCLUDE_RELOAD && map_includes(old_defines_map_, cache_.get_preproc_map())) {
179 reload_everything = false;
180 }
181 }
182
183 LOG_CONFIG << "load_game_config reload everything: " << reload_everything;
184
185 gui2::dialogs::loading_screen::display([this, reload_everything, classification, scenario_id]() {
186 load_game_config(reload_everything, classification, scenario_id);
187 });
188}
189
190void game_config_manager::load_game_config(bool reload_everything, const game_classification* classification, const std::string& scenario_id)
191{
192 // Make sure that 'debug mode' symbol is set
193 // if command line parameter is selected
194 // also if we're in multiplayer and actual debug mode is disabled.
195
196 // The loadscreen will erase the titlescreen.
197 // NOTE: even without loadscreen, needed after MP lobby.
198 try {
199 // Read all game configs.
200 // First we load all core configs, the mainline one and the ones from the addons.
201 // Validate the cores and discard the invalid.
202 // Then find the path to the selected core.
203 // Load the selected core.
204 // Handle terrains so that they are last loaded from the core.
205 // Load every compatible addon.
206 if(reload_everything) {
210
211 // Start transaction so macros are shared.
214
215 // Load mainline cores definition file.
216 config cores_cfg = cache_.get_config(game_config::path + "/data/cores.cfg");
217
218 // Append the $user_campaign_dir/*/cores.cfg files to the cores.
219 std::vector<std::string> user_dirs;
220 {
221 const std::string user_campaign_dir = filesystem::get_addons_dir();
222 std::vector<std::string> user_files;
224 user_campaign_dir, &user_files, &user_dirs, filesystem::name_mode::ENTIRE_FILE_PATH);
225 }
226
227 for(const std::string& umc : user_dirs) {
228 const std::string cores_file = umc + "/cores.cfg";
229 if(filesystem::file_exists(cores_file)) {
230 cores_cfg.append(cache_.get_config(cores_file));
231 }
232 }
233
234 // Validate every core
235 config valid_cores;
236 bool current_core_valid = false;
237 std::string wml_tree_root;
238
239 for(const config& core : cores_cfg.child_range("core")) {
240 const std::string& id = core["id"];
241 if(id.empty()) {
244 _("Error validating data core."),
245 _("Found a core without id attribute.")
246 + '\n' + _("Skipping the core."));
247 });
248 continue;
249 }
250
251 if(valid_cores.find_child("core", "id", id)) {
254 _("Error validating data core."),
255 _("Core ID: ") + id
256 + '\n' + _("The ID is already in use.")
257 + '\n' + _("Skipping the core."));
258 });
259 continue;
260 }
261
262 const std::string& path = core["path"];
266 _("Error validating data core."),
267 _("Core ID: ") + id
268 + '\n' + _("Core Path: ") + path
269 + '\n' + _("File not found.")
270 + '\n' + _("Skipping the core."));
271 });
272 continue;
273 }
274
275 if(id == "default" && !current_core_valid) {
276 wml_tree_root = path;
277 }
278 if(id == prefs::get().core()) {
279 current_core_valid = true;
280 wml_tree_root = path;
281 }
282
283 valid_cores.add_child("core", core); // append(core);
284 }
285
286 if(!current_core_valid) {
289 _("Error loading core data."),
290 _("Core ID: ") + prefs::get().core()
291 + '\n' + _("Error loading the core with named id.")
292 + '\n' + _("Falling back to the default core."));
293 });
294 prefs::get().set_core("default");
295 }
296
297 // check if we have a valid default core which should always be the case.
298 if(wml_tree_root.empty()) {
301 _("Error loading core data."),
302 _("Can’t locate the default core.")
303 + '\n' + _("The game will now exit."));
304 });
305 throw;
306 }
307
308 // Load the selected core
309 std::unique_ptr<schema_validation::schema_validator> validator;
312 validator->set_create_exceptions(false); // Don't crash if there's an error, just go ahead anyway
313 }
314
316 game_config_.append(valid_cores);
317
318 main_transaction.lock();
319
322 }
323 }
324
325 // only after addon configs have been loaded do we check for which addons are needed and whether they exist to be used
326 LOG_CONFIG << "active_addons_ has size " << active_addons_.size() << " and contents: " << utils::join(active_addons_);
327 if(classification) {
328 LOG_CONFIG << "Enabling only some add-ons!";
329 std::set<std::string> active_addons = classification->active_addons(scenario_id);
330 // IMPORTANT: this is a significant performance optimization, particularly for the worst case example of the batched WML unit tests
331 if(!reload_everything && active_addons == active_addons_) {
332 LOG_CONFIG << "Configs not reloaded and active add-ons remain the same; returning early.";
333 LOG_CONFIG << "active_addons has size " << active_addons_.size() << " and contents: " << utils::join(active_addons);
334 return;
335 }
336 active_addons_ = active_addons;
338 } else {
339 LOG_CONFIG << "Enabling all add-ons!";
341 }
342
343 // Extract the Lua scripts at toplevel.
345
348 tdata_.reset();
351
353
355
356 } catch(const game::error& e) {
357 ERR_CONFIG << "Error loading game configuration files\n" << e.message;
358
359 // Try reloading without add-ons
364 _("Error loading custom game configuration files. The game will try without loading add-ons."),
365 e.message);
366 });
367 load_game_config(reload_everything, classification, scenario_id);
368 } else if(prefs::get().core() != "default") {
371 _("Error loading custom game configuration files. The game will fallback to the default core files."),
372 e.message);
373 });
374 prefs::get().set_core("default");
376 load_game_config(reload_everything, classification, scenario_id);
377 } else {
380 _("Error loading default core game configuration files. The game will now exit."),
381 e.message);
382 });
383 throw;
384 }
385 }
386
388
389 // Set new binary paths.
391}
392static void show_deprecated_warnings(config& umc_cfg)
393{
394 for(auto& units : umc_cfg.child_range("units")) {
395 for(auto& unit_type : units.child_range("unit_type")) {
396 for(const auto& advancefrom : unit_type.child_range("advancefrom")) {
397 auto symbols = utils::string_map {
398 {"lower_level", advancefrom["unit"].str()},
399 {"higher_level", unit_type["id"].str()}
400 };
401 auto message = VGETTEXT(
402 // TRANSLATORS: For example, 'Cuttle Fish' units will not be able to advance to 'Kraken'.
403 // The substituted strings are unit ids, not translated names; hopefully any add-ons
404 // that trigger this will be quickly fixed and stop triggering the warning.
405 "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.",
406 symbols);
407 deprecated_message("[advancefrom]", DEP_LEVEL::REMOVED, {1, 15, 4}, message);
408 }
409 unit_type.remove_children("advancefrom");
410 }
411 }
412
413
414 // hardcoded list of 1.14 advancement macros, just used for the error mesage below.
415 static const std::set<std::string> deprecated_defines {
416 "ENABLE_PARAGON",
417 "DISABLE_GRAND_MARSHAL",
418 "ENABLE_ARMAGEDDON_DRAKE",
419 "ENABLE_DWARVISH_ARCANISTER",
420 "ENABLE_DWARVISH_RUNESMITH",
421 "ENABLE_WOLF_ADVANCEMENT",
422 "ENABLE_NIGHTBLADE",
423 "ENABLE_TROLL_SHAMAN",
424 "ENABLE_ANCIENT_LICH",
425 "ENABLE_DEATH_KNIGHT",
426 "ENABLE_WOSE_SHAMAN"
427 };
428
429 for(auto& campaign : umc_cfg.child_range("campaign")) {
430 for(auto str : utils::split(campaign["extra_defines"])) {
431 if(deprecated_defines.count(str) > 0) {
432 //TODO: we could try to implement a compatibility path by
433 // somehow getting the content of that macro from the
434 // cache_ object, but considering that 1) the breakage
435 // isn't that bad (just one disabled unit) and 2)
436 // it before also didn't work in all cases (see #4402)
437 // i don't think it is worth it.
439 "campaign id='" + campaign["id"].str() + "' has extra_defines=" + str,
441 {1, 15, 4},
442 _("instead, use the macro with the same name in the [campaign] tag")
443 );
444 }
445 }
446 }
447}
448
450{
451 const std::string user_campaign_dir = filesystem::get_addons_dir();
452
453 std::vector<std::string> error_log;
454 std::vector<std::string> error_addons;
455 std::vector<std::string> user_dirs;
456 std::vector<std::string> user_files;
457
458 filesystem::get_files_in_dir(user_campaign_dir, &user_files, &user_dirs, filesystem::name_mode::ENTIRE_FILE_PATH);
459
460 // Warn player about addons using the no-longer-supported single-file format.
461 for(const std::string& file : user_files) {
462
463 if(filesystem::is_cfg(file)) {
464 ERR_CONFIG << "error reading usermade add-on '" << file << "'";
465
466 error_addons.push_back(file);
467
468 const std::string short_wml_path = filesystem::get_short_wml_path(file);
469 const std::string log_msg = formatter()
470 << "The format '"
471 << short_wml_path
472 << "' (for single-file add-ons) is not supported anymore, use '"
473 << short_wml_path.substr(0, short_wml_path.size() - filesystem::wml_extension.size())
474 << "/_main.cfg' instead.";
475
476 error_log.push_back(log_msg);
477 }
478 }
479
480 loading_screen::spin();
481
482 // Rerun the directory scan using filename only, to get the addon_ids more easily.
483 user_files.clear();
484 user_dirs.clear();
485
486 filesystem::get_files_in_dir(user_campaign_dir, nullptr, &user_dirs,
488
489 loading_screen::spin();
490
491 // Load the addons.
492 for(const std::string& addon_id : user_dirs) {
493 log_scope2(log_config, "Loading add-on '" + addon_id + "'");
494 const std::string addon_dir = user_campaign_dir + "/" + addon_id;
495
496 const std::string main_cfg = addon_dir + "/_main.cfg";
497 const std::string info_cfg = addon_dir + "/_info.cfg";
498
499 if(!filesystem::file_exists(main_cfg)) {
500 continue;
501 }
502
503 loading_screen::spin();
504
505 // Try to find this addon's metadata. Author publishing info (_server.pbl) is given
506 // precedence over addon sever-generated info (_info.cfg). If neither are found, it
507 // probably means the addon was installed manually and certain defaults will be used.
508 config metadata;
509
510 if(have_addon_pbl_info(addon_id)) {
511 // Publishing info needs to be read from disk.
512 try {
513 metadata = get_addon_pbl_info(addon_id, false);
514 } catch(const invalid_pbl_exception& e) {
515 const std::string log_msg = formatter()
516 << "The provided addon has an invalid pbl file"
517 << " for addon "
518 << addon_id;
519
520 error_addons.push_back(e.message);
521 error_log.push_back(log_msg);
522 }
523 } else if(filesystem::file_exists(info_cfg)) {
524 // Addon server-generated info can be fetched from cache.
525 metadata = cache_.get_config(info_cfg).child_or_empty("info");
526 }
527
528 std::string using_core = metadata["core"];
529 if(using_core.empty()) {
530 using_core = "default";
531 }
532
533 // Skip add-ons not matching our current core. Cores themselves should be selectable
534 // at all times, so they aren't considered here.
535 if(!metadata.empty() && metadata["type"] != "core" && using_core != prefs::get().core()) {
536 continue;
537 }
538
539 std::string addon_title = metadata["title"].str();
540 if(addon_title.empty()) {
541 addon_title = addon_id;
542 }
543
544 version_info addon_version(metadata["version"]);
545
546 try {
547 std::unique_ptr<schema_validation::schema_validator> validator;
550 validator->set_create_exceptions(false); // Don't crash if there's an error, just go ahead anyway
551 }
552
553 loading_screen::spin();
554
555 // Load this addon from the cache to a config.
556 config umc_cfg = cache_.get_config(main_cfg, validator.get());
557
558 static const std::set<std::string> tags_with_addon_id {
559 "era",
560 "modification",
561 "resource",
562 "multiplayer",
563 "scenario",
564 "campaign",
565 "test"
566 };
567
568 // Annotate appropriate addon types with addon_id info.
569 for(auto [key, cfg] : umc_cfg.all_children_view()) {
570 if(tags_with_addon_id.count(key) > 0) {
571 cfg["addon_id"] = addon_id;
572 cfg["addon_title"] = addon_title;
573 // Note that this may reformat the string in a canonical form.
574 cfg["addon_version"] = addon_version.str();
575 }
576 }
577
578 loading_screen::spin();
579
581
582 loading_screen::spin();
583
584 static const std::set<std::string> entry_tags {
585 "era",
586 "modification",
587 "resource",
588 "multiplayer",
589 "scenario",
590 "campaign"
591 };
592
593 for(const std::string& tagname : entry_tags) {
594 game_config_.append_children_by_move(umc_cfg, tagname);
595 }
596
597 loading_screen::spin();
598
599 addon_cfgs_[addon_id] = std::move(umc_cfg);
600 } catch(const config::error& err) {
601 ERR_CONFIG << "config error reading usermade add-on '" << main_cfg << "'";
602 ERR_CONFIG << err.message;
603 error_addons.push_back(main_cfg);
604 error_log.push_back(err.message);
605 } catch(const preproc_config::error& err) {
606 ERR_CONFIG << "preprocessor config error reading usermade add-on '" << main_cfg << "'";
607 ERR_CONFIG << err.message;
608 error_addons.push_back(main_cfg);
609 error_log.push_back(err.message);
610 } catch(const filesystem::io_exception&) {
611 ERR_CONFIG << "filesystem I/O error reading usermade add-on '" << main_cfg << "'";
612 error_addons.push_back(main_cfg);
613 }
614 }
615
618 ERR_CONFIG << "Didn’t find an add-on for --validate-addon - check whether the id has a typo";
619 const std::string log_msg = formatter()
620 << "Didn't find an add-on for --validate-addon - check whether the id has a typo";
621 error_log.push_back(log_msg);
622 throw game::error("Did not find an add-on for --validate-addon");
623 }
624
625 WRN_CONFIG << "Note: for --validate-addon to find errors, you have to play (in the GUI) a game that uses the add-on.";
626 }
627
628 if(!error_addons.empty()) {
629 const std::size_t n = error_addons.size();
630 const std::string& msg1 =
631 _n("The following add-on had errors and could not be loaded:",
632 "The following add-ons had errors and could not be loaded:",
633 n);
634 const std::string& msg2 =
635 _n("Please report this to the author or maintainer of this add-on.",
636 "Please report this to the respective authors or maintainers of these add-ons.",
637 n);
638
639 const std::string& report = utils::join(error_log, "\n\n");
641 gui2::dialogs::wml_error::display(msg1, msg2, error_addons, report);
642 });
643 }
644}
645
647{
648 config& hashes = game_config_.add_child("multiplayer_hashes");
649 for(const config& ch : game_config().child_range("multiplayer")) {
650 hashes[ch["id"].str()] = ch.hash();
651 }
652}
653
659
661{
662 // Rebuild addon version info cache.
664
665 // Force a reload of configuration information.
667 old_defines_map_.clear();
670
673}
674
680
682 const game_classification& classification, const std::string& scenario_id)
683{
684 game_config::scoped_preproc_define difficulty(classification.difficulty,
685 !classification.difficulty.empty());
687 !classification.campaign_define.empty());
689 !classification.scenario_define.empty());
691 !classification.era_define.empty());
692 game_config::scoped_preproc_define multiplayer("MULTIPLAYER",
693 classification.is_multiplayer());
695 classification.is_multiplayer());
696
697 //
698 // NOTE: these deques aren't used here, but the objects within are utilized as RAII helpers.
699 //
700
701 std::deque<game_config::scoped_preproc_define> extra_defines;
702 for(const std::string& extra_define : classification.campaign_xtra_defines) {
703 extra_defines.emplace_back(extra_define);
704 }
705
706 std::deque<game_config::scoped_preproc_define> modification_defines;
707 for(const std::string& mod_define : classification.mod_defines) {
708 modification_defines.emplace_back(mod_define, !mod_define.empty());
709 }
710
711 try {
712 load_game_config_with_loadscreen(NO_FORCE_RELOAD, &classification, scenario_id);
713 } catch(const game::error&) {
715
716 std::deque<game_config::scoped_preproc_define> previous_defines;
717 for(const preproc_map::value_type& preproc : old_defines_map_) {
718 previous_defines.emplace_back(preproc.first);
719 }
720
722 throw;
723 }
724
725 // This needs to be done in the main thread since this function (load_game_config_for_game)
726 // might be called from a loading screen worker thread (and currently is, in fact). If the
727 // image cache is purged from the worker thread, there's a possibility for a data race where
728 // the main thread accesses the image cache and the worker thread simultaneously clears it.
730}
731
733{
734 game_config::scoped_preproc_define multiplayer("MULTIPLAYER", is_mp);
735 game_config::scoped_preproc_define test("TEST", is_test);
736 game_config::scoped_preproc_define mptest("MP_TEST", cmdline_opts_.mptest && is_mp);
737 /** During an mp game the default difficulty define is also defined so better already load it now if we already must reload config cache. */
740
741 try {
743 } catch(const game::error&) {
745
746 std::deque<game_config::scoped_preproc_define> previous_defines;
747 for (const preproc_map::value_type& preproc : old_defines_map_) {
748 previous_defines.emplace_back(preproc.first);
749 }
750
752 throw;
753 }
754}
755
756void game_config_manager::set_enabled_addon(const std::set<std::string>& addon_ids)
757{
758 auto& vec = game_config_view_.data();
759 vec.clear();
760 vec.push_back(game_config_);
761
762 for(const std::string& id : addon_ids) {
763 auto it = addon_cfgs_.find(id);
764 if(it != addon_cfgs_.end()) {
765 LOG_CONFIG << "Enabling add-on " << id;
766 vec.push_back(it->second);
767 } else {
768 ERR_CONFIG << "Attempted to enable add-on '" << id << "' but its config could not be found";
769 }
770 }
771}
772
774{
775 active_addons_.clear();
776 auto& vec = game_config_view_.data();
777 vec.clear();
778 vec.push_back(game_config_);
779
780 for(const auto& pair : addon_cfgs_) {
781 LOG_CONFIG << "Enabling add-on " << pair.first;
782 vec.push_back(pair.second);
783 active_addons_.emplace(pair.first);
784 }
785}
#define ERR_CONFIG
static lg::log_domain log_config("config")
config get_addon_pbl_info(const std::string &addon_name, bool do_validate)
Gets the publish information for an add-on.
Definition manager.cpp:71
bool have_addon_pbl_info(const std::string &addon_name)
Returns whether a .pbl file is present for the specified add-on or not.
Definition manager.cpp:66
void refresh_addon_version_info_cache()
Refreshes the per-session cache of add-on's version information structs.
Definition manager.cpp:381
Definitions for the terrain builder.
void reload()
Reads the mainline achievements.cfg and then all the achievements of each installed add-on.
static void init(const game_config_view &game_config)
Init the parameters of ai configuration parser.
utils::optional< std::string > test
Non-empty if –test was given on the command line.
utils::optional< std::string > validate_addon
Non-empty if –validate-addon was given on the command line.
bool mptest
True if –mp-test was given on the command line.
bool multiplayer
True if –multiplayer was given on the command line.
bool validcache
True if –validcache was given on the command line.
bool noaddons
True if –noaddons was given on the command line.
utils::optional< std::string > editor
Non-empty if –editor was given on the command line.
bool any_validation_option() const
True if the –validate or any of the –validate-* options are given.
bool validate_core
True if –validate-core was given on the command line.
bool nocache
True if –nocache was given on the command line.
A config object defines a single node in a WML file, with access to child nodes.
Definition config.hpp:157
config & add_child(std::string_view key)
Definition config.cpp:436
void append(const config &cfg)
Append data from another config object to this one.
Definition config.cpp:188
void append_children_by_move(config &cfg, std::string_view key)
Moves children with the given name from the given config to this one.
Definition config.cpp:224
auto all_children_view() const
In-order iteration over all children.
Definition config.hpp:795
child_itors child_range(std::string_view key)
Definition config.cpp:268
optional_config_impl< config > find_child(std::string_view key, const std::string &name, const std::string &value)
Returns the first child of tag key with a name attribute containing value.
Definition config.cpp:764
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.
Definition config.cpp:390
bool empty() const
Definition config.cpp:823
std::string hash() const
Definition config.cpp:1227
std::ostringstream wrapper.
Definition formatter.hpp:40
std::vector< std::string > campaign_xtra_defines
more customization of data
std::vector< std::string > mod_defines
If there are defines the modifications use to customize data.
std::set< std::string > active_addons(const std::string &scenario_id) const
std::string scenario_define
If there is a define the scenario uses to customize data.
std::string difficulty
The difficulty level the game is being played on.
std::string era_define
If there is a define the era uses to customize data.
std::string campaign_define
If there is a define the campaign uses to customize data.
Used to share macros between cache objects You have to create transaction object to load all macros t...
void lock()
Lock the transaction so no more macros are added.
void recheck_filetree_checksum()
Force cache checksum validation.
void set_use_cache(bool use)
Enable/disable caching.
const preproc_map & get_preproc_map() const
void clear_defines()
Clear stored defines map to default values.
bool clean_cache()
Deletes stale cache files not in use by the game.
config get_config(const std::string &path, abstract_validator *validator=nullptr)
Gets a config object from given path.
void set_force_valid_cache(bool force)
Enable/disable cache validation.
Used to set and unset scoped defines to preproc_map.
void load_game_config_with_loadscreen(FORCE_RELOAD_CONFIG force_reload, const game_classification *classification, const std::string &scenario_id)
@ FORCE_RELOAD
Always reload config.
@ NO_INCLUDE_RELOAD
Don't reload if the previous defines include the new defines.
@ NO_FORCE_RELOAD
Don't reload if the previous defines equal the new defines.
std::map< std::string, config > addon_cfgs_
bool init_game_config(FORCE_RELOAD_CONFIG force_reload)
static game_config_manager * get()
void load_game_config_for_game(const game_classification &classification, const std::string &scenario_id)
void load_game_config(bool reload_everything, const game_classification *classification, const std::string &scenario_id)
std::set< std::string > active_addons_
void load_game_config_for_create(bool is_mp, bool is_test=false)
filesystem::binary_paths_manager paths_manager_
game_config_view game_config_view_
game_config::config_cache & cache_
void set_enabled_addon(const std::set< std::string > &addon_ids)
game_config_manager(const commandline_options &cmdline_opts)
const game_config_view & game_config() const
const commandline_options & cmdline_opts_
config_array_view & data()
config_array_view child_range(std::string_view key) const
static void extract_preload_scripts(const game_config_view &game_config)
static void progress(loading_stage stage=loading_stage::none)
Report what is being loaded to the loading screen.
static void display(const std::function< void()> &f)
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.
Definition wml_error.hpp:41
static prefs & get()
void load_advanced_prefs(const game_config_view &gc)
void load_hotkeys()
Realization of serialization/validator.hpp abstract validator.
static void set_terrain_rules_cfg(const game_config_view &cfg)
Set the config where we will parse the global terrain rules.
Definition builder.cpp:279
void reset() const
Clears the database and queues reinitialization on the next call to lazy_initialization.
Definition type_data.cpp:50
static void set_known_themes(const game_config_view *cfg)
Copies the theme configs from the main game config.
Definition theme.cpp:991
void set_config(const game_config_view &cfg)
Resets all data based on the provided config.
Definition types.cpp:1067
A single unit type that the player may recruit.
Definition types.hpp:43
Represents version numbers.
std::string str() const
Serializes the version number into string form.
Managing the AIs configuration - headers.
std::string deprecated_message(const std::string &elem_name, DEP_LEVEL level, const version_info &version, const std::string &detail)
const config * cfg
#define VGETTEXT(msgid,...)
Handy wrappers around interpolate_variables_into_string and gettext.
const std::string DEFAULT_DIFFICULTY
The default difficulty setting for campaigns.
#define LOG_CONFIG
static game_config_manager * singleton
static void show_deprecated_warnings(config &umc_cfg)
#define WRN_CONFIG
static lg::log_domain log_config("config")
Interfaces for manipulating version numbers of engine, add-ons, etc.
static std::string _n(const char *str1, const char *str2, int n)
Definition gettext.hpp:104
static std::string _(const char *str)
Definition gettext.hpp:100
std::string id
Text to match against addon_info.tags()
Definition manager.cpp:199
void init_textdomains(const game_config_view &cfg)
Initializes the list of textdomains from a configuration object.
Definition language.cpp:339
bool init_strings(const game_config_view &cfg)
Initializes certain English strings.
Definition language.cpp:357
Standard logging facilities (interface).
#define log_scope2(domain, description)
Definition log.hpp:276
#define FORCE_LOG_TO(logger, domain)
Definition log.hpp:291
void set_about(const game_config_view &cfg)
Regenerates the credits data.
Definition about.cpp:119
Manage the empty-palette in the editor.
Definition action.cpp:31
void call_in_main_thread(const std::function< void(void)> &f)
Definition events.cpp:773
bool file_exists(const std::string &name)
Returns true if a file or directory with such name already exists.
void get_files_in_dir(const std::string &dir, std::vector< std::string > *files, std::vector< std::string > *dirs=nullptr, name_mode mode=name_mode::FILE_NAME_ONLY, filter_mode filter=filter_mode::NO_FILTER, reorder_mode reorder=reorder_mode::DONT_REORDER, file_tree_checksum *checksum=nullptr)
Get a list of all files and/or directories in a given directory.
const std::string wml_extension
bool is_cfg(const std::string &filename)
Returns true if the file ends with the wmlfile extension.
utils::optional< std::string > get_wml_location(const std::string &path, const utils::optional< std::string > &current_dir=utils::nullopt)
Returns a translated path to the actual file or directory, if it exists.
const file_tree_checksum & data_tree_checksum(bool reset=false)
Get the time at which the data/ tree was last modified at.
void clear_binary_paths_cache()
std::string get_short_wml_path(const std::string &filename)
Returns a short path to filename, skipping the (user) data directory.
std::string get_addons_dir()
Game configuration data as global variables.
std::string path
const version_info wesnoth_version(VERSION)
const bool & debug
static void add_color_info(const game_config_view &v, bool build_defaults)
void reset_color_info()
void load_config(const config &v)
void load_default_hotkeys(const game_config_view &cfg)
Registers all hotkeys present in this config.
constexpr uint32_t scope_main
void flush_cache()
Purges all image caches.
Definition picture.cpp:210
logger & info()
Definition log.cpp:351
void flush_cache()
Definition sound.cpp:1069
std::string join(const Range &v, const std::string &s=",")
Generates a new string joining container items in a list.
std::map< std::string, t_string > string_map
std::vector< std::string > split(const config_attribute_value &val)
std::map< std::string, struct preproc_define > preproc_map
One of the realizations of serialization/validator.hpp abstract validator.
std::unique_ptr< MIX_Audio, decltype(&MIX_DestroyAudio)> value
Definition sound.cpp:139
void set_paths(const game_config_view &cfg)
An exception object used when an IO error occurs.
Base class for all the errors encountered by the engine.
Exception thrown when the WML parser fails to read a .pbl file.
Definition manager.hpp:45
static map_location::direction n
Definitions related to theme-support.
unit_type_data unit_types
Definition types.cpp:1499
#define e