The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
depcheck.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2012 - 2025
3 by Boldizsár Lipka <lipkab@zoho.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 <algorithm>
19
22#include "gettext.hpp"
23#include "log.hpp"
24#include "utils/general.hpp"
25
29#include "game_config_view.hpp"
30
31static lg::log_domain log_mp_create_depcheck("mp/create/depcheck");
32#define DBG_MP LOG_STREAM(debug, log_mp_create_depcheck)
33
34namespace
35{
36// helper function
37void copy_keys(config& out, const config& in, const std::string& type, bool copy_force_key = false)
38{
39 if(in.has_attribute("allow_" + type)) {
40 out["allow_" + type] = in["allow_" + type];
41 } else if(in.has_attribute("disallow_" + type)) {
42 out["disallow_" + type] = in["disallow_" + type];
43 }
44
45 if(in.has_attribute("ignore_incompatible_" + type)) {
46 out["ignore_incompatible_" + type] = in["ignore_incompatible_" + type];
47 }
48
49 if(copy_force_key) {
50 if(in.has_attribute("force_" + type)) {
51 out["force_" + type] = in["force_" + type];
52 }
53 }
54}
55} // anonymous namespace
56
57namespace ng
58{
59namespace depcheck
60{
62 : depinfo_()
63 , era_()
64 , scenario_()
65 , mods_()
66 , prev_era_()
67 , prev_scenario_()
68 , prev_mods_()
69{
70 DBG_MP << "Initializing the dependency manager";
71
72 for(const config& cfg : gamecfg.child_range("modification")) {
73 component_availability::type type = component_availability::get_enum(cfg["type"].str()).value_or(component_availability::type::hybrid);
74
75 if((type != component_availability::type::mp || mp) && (type != component_availability::type::sp || !mp)) {
76 config info;
77 info["id"] = cfg["id"];
78 info["name"] = cfg["name"];
79
80 copy_keys(info, cfg, "scenario");
81 copy_keys(info, cfg, "era");
82 copy_keys(info, cfg, "modification");
83
84 depinfo_.add_child("modification", std::move(info));
85 }
86 }
87
88 for(const config& cfg : gamecfg.child_range("era")) {
89 component_availability::type type = component_availability::get_enum(cfg["type"].str()).value_or(component_availability::type::mp);
90
91 if((type != component_availability::type::mp || mp) && (type != component_availability::type::sp || !mp)) {
92 config info;
93 info["id"] = cfg["id"];
94 info["name"] = cfg["name"];
95
96 copy_keys(info, cfg, "scenario");
97 copy_keys(info, cfg, "modification", true);
98
99 depinfo_.add_child("era", std::move(info));
100 }
101 }
102
103 for(const config& cfg : gamecfg.child_range("multiplayer")) {
104 if(cfg["allow_new_game"].to_bool(true)) {
105 config info;
106 info["id"] = cfg["id"];
107 info["name"] = cfg["name"];
108
109 copy_keys(info, cfg, "era");
110 copy_keys(info, cfg, "modification", true);
111
112 depinfo_.add_child("scenario", std::move(info));
113 }
114 }
115
116 for(const config& cfg : gamecfg.child_range("campaign")) {
117 config info;
118 info["id"] = cfg["id"];
119 info["name"] = cfg["name"];
120 info["allow_era_choice"] = cfg["allow_era_choice"];
121
122 copy_keys(info, cfg, "era");
123 copy_keys(info, cfg, "modification", true);
124
125 depinfo_.add_child("scenario", std::move(info));
126 }
127}
128
130{
131 DBG_MP << "Saving current state";
132 prev_era_ = era_;
135}
136
138{
139 DBG_MP << "Restoring previous state";
140 era_ = prev_era_;
143}
144
145bool manager::exists(const elem& e) const
146{
147 for(const config& cfg : depinfo_.child_range(e.type)) {
148 if(cfg["id"] == e.id) {
149 return true;
150 }
151 }
152
153 return false;
154}
155
156std::string manager::find_name_for(const elem& e) const
157{
158 auto cfg = depinfo_.find_mandatory_child(e.type, "id", e.id);
159 return cfg["name"];
160}
161
162std::vector<std::string> manager::get_required_not_installed(const elem& e) const
163{
164 std::vector<std::string> result;
165
166 std::vector<std::string> items = get_required(e);
167
168 for(const std::string& str : items) {
169 if(!exists(elem(str, "modification"))) {
170 result.push_back(str);
171 }
172 }
173
174 return result;
175}
176
177std::vector<std::string> manager::get_required(const elem& e) const
178{
179 std::vector<std::string> result;
180
181 if(e.type == "modification") {
182 return result;
183 }
184
185 config data = depinfo_.find_mandatory_child(e.type, "id", e.id);
186
187 if(data.has_attribute("force_modification")) {
188 result = utils::split(data["force_modification"].str(), ',');
189 }
190
191 return result;
192}
193
194std::vector<std::string> manager::get_required_not_enabled(const elem& e) const
195{
196 std::vector<std::string> required = get_required(e);
197 std::vector<std::string> result;
198
199 for(std::string str : required) {
200 if(!utils::contains(mods_, str)) {
201 result.push_back(str);
202 }
203 }
204
205 return result;
206}
207
208std::vector<std::string> manager::get_conflicting_enabled(const elem& e) const
209{
210 std::vector<std::string> result;
211
212 for(const std::string& mod : mods_) {
213 if(does_conflict(elem(mod, "modification"), e)) {
214 result.push_back(mod);
215 }
216 }
217
218 return result;
219}
220
221bool manager::does_conflict(const elem& elem1, const elem& elem2, bool directonly) const
222{
223 if(elem1 == elem2) {
224 return false;
225 }
226
227 // We ignore nonexistent elements at this point, they will generate
228 // errors in change_era()/change_scenario() anyways.
229 if(!exists(elem1) || !exists(elem2)) {
230 return false;
231 }
232
233 config data1 = depinfo_.find_mandatory_child(elem1.type, "id", elem1.id);
234 config data2 = depinfo_.find_mandatory_child(elem2.type, "id", elem2.id);
235
236 // Whether we should skip the check entirely
237 if(data1.has_attribute("ignore_incompatible_" + elem2.type)) {
238 std::vector<std::string> ignored = utils::split(data1["ignore_incompatible_" + elem2.type]);
239
240 if(utils::contains(ignored, elem2.id)) {
241 return false;
242 }
243 }
244
245 if(data2.has_attribute("ignore_incompatible_" + elem1.type)) {
246 std::vector<std::string> ignored = utils::split(data2["ignore_incompatible_" + elem1.type]);
247
248 if(utils::contains(ignored, elem1.id)) {
249 return false;
250 }
251 }
252
253 if((elem1.type == "era" && data2["allow_era_choice"].to_bool(false)) ||(elem2.type == "era" && data1["allow_era_choice"].to_bool(false))) {
254 return false;
255 }
256
257 bool result = false;
258
259 // Checking for direct conflicts between elem1 and elem2
260 if(data1.has_attribute("allow_" + elem2.type)) {
261 std::vector<std::string> allowed = utils::split(data1["allow_" + elem2.type]);
262
263 result = !utils::contains(allowed, elem2.id) && !does_require(elem1, elem2);
264 } else if(data1.has_attribute("disallow_" + elem2.type)) {
265 std::vector<std::string> disallowed = utils::split(data1["disallow_" + elem2.type]);
266
267 result = utils::contains(disallowed, elem2.id);
268 }
269
270 if(data2.has_attribute("allow_" + elem1.type)) {
271 std::vector<std::string> allowed = utils::split(data2["allow_" + elem1.type]);
272
273 result = result || (!utils::contains(allowed, elem1.id) && !does_require(elem2, elem1));
274 } else if(data2.has_attribute("disallow_" + elem1.type)) {
275 std::vector<std::string> disallowed = utils::split(data2["disallow_" + elem1.type]);
276
277 result = result || utils::contains(disallowed, elem1.id);
278 }
279
280 if(result) {
281 return true;
282 }
283
284 // Checking for indirect conflicts (i.e. conflicts between dependencies)
285 if(!directonly) {
286 std::vector<std::string> req1 = get_required(elem1), req2 = get_required(elem2);
287
288 for(const std::string& s : req1) {
289 elem m(s, "modification");
290
291 if(does_conflict(elem2, m, true)) {
292 return true;
293 }
294 }
295
296 for(const std::string& s : req2) {
297 elem m(s, "modification");
298
299 if(does_conflict(elem1, m, true)) {
300 return true;
301 }
302 }
303
304 for(const std::string& id1 : req1) {
305 elem m1(id1, "modification");
306
307 for(const std::string& id2 : req2) {
308 elem m2(id2, "modification");
309
310 if(does_conflict(m1, m2)) {
311 return true;
312 }
313 }
314 }
315 }
316
317 return false;
318}
319
320bool manager::does_require(const elem& elem1, const elem& elem2) const
321{
322 if(elem2.type != "modification") {
323 return false;
324 }
325
326 config data = depinfo_.find_mandatory_child(elem1.type, "id", elem1.id);
327
328 if(data.has_attribute("force_modification")) {
329 std::vector<std::string> required = utils::split(data["force_modification"]);
330
331 return utils::contains(required, elem2.id);
332 }
333
334 return false;
335}
336
337void manager::try_era(const std::string& id, bool force)
338{
339 save_state();
340
341 if(force) {
342 era_ = id;
343 } else if(!change_era(id)) {
344 revert();
345 }
346}
347
348void manager::try_scenario(const std::string& id, bool force)
349{
350 save_state();
351
352 if(force) {
353 scenario_ = id;
354 } else if(!change_scenario(id)) {
355 revert();
356 }
357}
358
359void manager::try_modifications(const std::vector<std::string>& ids, bool force)
360{
361 save_state();
362
363 if(force) {
364 mods_ = ids;
365 } else if(!change_modifications(ids)) {
366 revert();
367 }
368}
369
370void manager::try_modification_by_id(const std::string& id, bool activate, bool force)
371{
372 std::vector<std::string> mods_copy = mods_;
373
374 if(activate) {
375 if(!utils::contains(mods_copy, id) ) {
376 mods_copy.push_back(id);
377 }
378 } else {
379 std::vector<std::string>::iterator pos = std::find(mods_copy.begin(), mods_copy.end(), id);
380 if(pos != mods_copy.end()) {
381 mods_copy.erase(pos);
382 }
383 }
384
385 try_modifications(mods_copy, force);
386}
387
388void manager::try_era_by_index(int index, bool force)
389{
390 try_era(depinfo_.mandatory_child("era", index)["id"], force);
391}
392
393void manager::try_scenario_by_index(int index, bool force)
394{
395 try_scenario(depinfo_.mandatory_child("scenario", index)["id"], force);
396}
397
399{
400 return get_era_index(era_);
401}
402
403int manager::get_era_index(const std::string& id) const
404{
405 int result = 0;
406 for(const config& i : depinfo_.child_range("era")) {
407 if(i["id"] == id) {
408 return result;
409 }
410
411 result++;
412 }
413
414 return -1;
415}
416
418{
419 int result = 0;
420
421 for(const config& i : depinfo_.child_range("scenario")) {
422 if(i["id"] == scenario_) {
423 return result;
424 }
425
426 result++;
427 }
428
429 return -1;
430}
431
433{
434 return utils::contains(mods_, depinfo_.mandatory_child("modification", index)["id"].str());
435}
436
437bool manager::is_modification_active(const std::string& id) const
438{
439 return utils::contains(mods_, id);
440}
441
442bool manager::enable_mods_dialog(const std::vector<std::string>& mods, const std::string& requester)
443{
444 std::vector<std::string> items;
445 for(const std::string& mod : mods) {
446 items.push_back(depinfo_.find_mandatory_child("modification", "id", mod)["name"]);
447 }
448
449 return gui2::dialogs::depcheck_confirm_change::execute(true, items, requester);
450}
451
452bool manager::disable_mods_dialog(const std::vector<std::string>& mods, const std::string& requester)
453{
454 std::vector<std::string> items;
455 for(const std::string& mod : mods) {
456 items.push_back(depinfo_.find_mandatory_child("modification", "id", mod)["name"]);
457 }
458
459 return gui2::dialogs::depcheck_confirm_change::execute(false, items, requester);
460}
461
462std::string manager::change_era_dialog(const std::vector<std::string>& eras)
463{
464 std::vector<std::string> items;
465 for(const std::string& era : eras) {
466 items.push_back(depinfo_.find_mandatory_child("era", "id", era)["name"]);
467 }
468
470
471 if(dialog.show()) {
472 return eras[dialog.result()];
473 }
474
475 return "";
476}
477
478std::string manager::change_scenario_dialog(const std::vector<std::string>& scenarios)
479{
480 std::vector<std::string> items;
481 for(const std::string& scenario : scenarios) {
482 items.push_back(depinfo_.find_mandatory_child("scenario", "id", scenario)["name"]);
483 }
484
486 if(dialog.show()) {
487 return scenarios[dialog.result()];
488 }
489
490 return "";
491}
492
493void manager::failure_dialog(const std::string& msg)
494{
495 gui2::show_message(_("Failed to resolve dependencies"), msg, _("OK"));
496}
497
499{
500 std::string type_str;
501
502 switch(type) {
503 case ERA:
504 type_str = "era";
505 break;
506 case SCENARIO:
507 type_str = "scenario";
508 break;
509 case MODIFICATION:
510 type_str = "modification";
511 }
512
513 depinfo_.add_child_at(type_str, data, index);
514}
515
516bool manager::change_scenario(const std::string& id)
517{
518 // Checking for missing dependencies
519 if(!get_required_not_installed(elem(id, "scenario")).empty()) {
520 std::string msg = _("Scenario can’t be activated. Some dependencies are missing: ");
521
522 msg += utils::join(get_required_not_installed(elem(id, "scenario")), ", ");
523
524 failure_dialog(msg);
525 return false;
526 }
527
528 scenario_ = id;
529
530 elem scen = elem(id, "scenario");
531 std::string scen_name = find_name_for(scen);
532
533 // Firstly, we check if we have to enable/disable any mods
534 std::vector<std::string> req = get_required_not_enabled(scen);
535 std::vector<std::string> con = get_conflicting_enabled(scen);
536
537 if(!req.empty()) {
538 if(!enable_mods_dialog(req, scen_name)) {
539 return false;
540 }
541 }
542
543 if(!con.empty()) {
544 if(!disable_mods_dialog(con, scen_name)) {
545 return false;
546 }
547 }
548
549 std::vector<std::string> newmods = req;
550 for(const std::string& i : mods_) {
551 if(!utils::contains(con, i)) {
552 newmods.push_back(i);
553 }
554 }
555
556 mods_ = newmods;
557
558 // Now checking if the currently selected era conflicts the scenario
559 // and changing era if necessary
560 if(!does_conflict(scen, elem(era_, "era"))) {
561 return true;
562 }
563
564 std::vector<std::string> compatible;
565 for(const config& i : depinfo_.child_range("era")) {
566 if(!does_conflict(scen, elem(i["id"], "era"))) {
567 compatible.push_back(i["id"]);
568 }
569 }
570
571 if(!compatible.empty()) {
572 era_ = change_era_dialog(compatible);
573 } else {
574 failure_dialog(_("No compatible eras found."));
575 return false;
576 }
577
578 if(era_.empty()) {
579 return false;
580 }
581
582 return change_era(era_);
583}
584
585bool manager::change_era(const std::string& id)
586{
587 // Checking for missing dependencies
588 if(!get_required_not_installed(elem(id, "era")).empty()) {
589 std::string msg = _("Era can’t be activated. Some dependencies are missing: ");
590
591 msg += utils::join(get_required_not_installed(elem(id, "era")), ", ");
592 failure_dialog(msg);
593 return false;
594 }
595
596 era_ = id;
597
598 elem era = elem(id, "era");
599 std::string era_name = find_name_for(era);
600
601 std::vector<std::string> req = get_required_not_enabled(era);
602 std::vector<std::string> con = get_conflicting_enabled(era);
603
604 // Firstly, we check if we have to enable/disable any mods
605 if(!req.empty()) {
606 if(!enable_mods_dialog(req, era_name)) {
607 return false;
608 }
609 }
610
611 if(!con.empty()) {
612 if(!disable_mods_dialog(con, era_name)) {
613 return false;
614 }
615 }
616
617 std::vector<std::string> newmods = req;
618 for(const std::string& i : mods_) {
619 if(!utils::contains(con, i)) {
620 newmods.push_back(i);
621 }
622 }
623
624 mods_ = newmods;
625
626 // Now checking if the currently selected scenario conflicts the era
627 // and changing scenario if necessary
628 if(!does_conflict(era, elem(scenario_, "scenario"))) {
629 return true;
630 }
631
632 std::vector<std::string> compatible;
633 for(const config& i : depinfo_.child_range("scenario")) {
634 if(!does_conflict(era, elem(i["id"], "scenario"))) {
635 compatible.push_back(i["id"]);
636 }
637 }
638
639 if(!compatible.empty()) {
640 scenario_ = change_scenario_dialog(compatible);
641 } else {
642 failure_dialog(_("No compatible scenarios found."));
643 return false;
644 }
645
646 if(scenario_.empty()) {
647 return false;
648 }
649
651}
652
653bool manager::change_modifications(const std::vector<std::string>& modifications)
654{
655 // Checking if the selected combination of mods is valid at all
656 std::vector<std::string> filtered;
657 for(const std::string& i : modifications) {
658 bool ok = true;
659 elem ei(i, "modification");
660
661 for(const std::string& j : filtered) {
662 ok = ok && !does_conflict(ei, elem(j, "modification"));
663 }
664
665 if(ok) {
666 filtered.push_back(i);
667 }
668 }
669
670 if(filtered.size() != modifications.size()) {
671 failure_dialog(_("Not all of the chosen modifications are compatible."
672 " Some of them will be disabled."));
673 }
674
675 mods_ = filtered;
676
677 // Checking if the currently selected era is compatible with the set
678 // modifications, and changing era if necessary
679 std::vector<std::string> compatible;
680 for(const config& c : depinfo_.child_range("era")) {
681 elem era(c["id"], "era");
682 bool ok = true;
683
684 for(const std::string& s : mods_) {
685 ok = ok && !does_conflict(era, elem(s, "modification"));
686 }
687
688 if(ok) {
689 compatible.push_back(era.id);
690 }
691 }
692
693 if(!utils::contains(compatible, era_)) {
694 if(!compatible.empty()) {
695 era_ = change_era_dialog(compatible);
696 } else {
697 failure_dialog(_("No compatible eras found."));
698 return false;
699 }
700
701 if(era_.empty()) {
702 return false;
703 }
704
705 if(!change_era(era_)) {
706 return false;
707 }
708 } else {
709 if(!change_era(era_)) {
710 return false;
711 }
712 }
713
714 compatible.clear();
715
716 // Checking if the currently selected scenario is compatible with
717 // the set modifications, and changing scenario if necessary
718 for(const config& c : depinfo_.child_range("scenario")) {
719 elem scen(c["id"], "scenario");
720 bool ok = true;
721 for(const std::string& s : mods_) {
722 ok = ok && !does_conflict(scen, elem(s, "modification"));
723 }
724
725 if(ok) {
726 compatible.push_back(scen.id);
727 }
728 }
729
730 if(!utils::contains(compatible, scenario_)) {
731 if(!compatible.empty()) {
732 scenario_ = change_scenario_dialog(compatible);
733 } else {
734 failure_dialog(_("No compatible scenarios found."));
735 return false;
736 }
737
738 if(scenario_.empty()) {
739 return false;
740 }
741
743 } else {
745 return false;
746 }
747 }
748
749 return true;
750}
751
752} // namespace depcheck
753
754} // namespace ng
unsigned in
If equal to search_counter, the node is off the list.
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
config & find_mandatory_child(std::string_view key, const std::string &name, const std::string &value)
Definition config.cpp:784
child_itors child_range(std::string_view key)
Definition config.cpp:268
bool has_attribute(std::string_view key) const
Definition config.cpp:157
config & add_child_at(std::string_view key, const config &val, std::size_t index)
Definition config.cpp:465
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.
Definition config.cpp:362
A class grating read only view to a vector of config objects, viewed as one config with all children ...
config_array_view child_range(std::string_view key) const
int result() const
Returns the selected item.
bool show(const unsigned auto_close_time=0)
Shows the window.
bool change_scenario(const std::string &id)
Attempts to change the selected scenario.
Definition depcheck.cpp:516
void try_era_by_index(int index, bool force=false)
Tries to set the selected era.
Definition depcheck.cpp:388
bool change_modifications(const std::vector< std::string > &modifications)
Attempts to change the selected modifications.
Definition depcheck.cpp:653
void revert()
restores the lastly saved values of era_, scenarios_ and mods_
Definition depcheck.cpp:137
void try_modifications(const std::vector< std::string > &ids, bool force=false)
Tries to set the enabled modifications.
Definition depcheck.cpp:359
bool disable_mods_dialog(const std::vector< std::string > &mods, const std::string &requester=_("A component"))
Display a dialog requesting confirmation for disabling some modifications.
Definition depcheck.cpp:452
bool exists(const elem &e) const
Decides whether a certain component is installed or not.
Definition depcheck.cpp:145
void insert_element(component_type type, const config &data, int index=0)
Adds a new element to the manager's database.
Definition depcheck.cpp:498
std::string change_era_dialog(const std::vector< std::string > &eras)
Display a dialog requesting the user to select a new era.
Definition depcheck.cpp:462
void try_era(const std::string &id, bool force=false)
Tries to set the selected era.
Definition depcheck.cpp:337
bool enable_mods_dialog(const std::vector< std::string > &mods, const std::string &requester=_("A component"))
Display a dialog requesting confirmation for enabling some modifications.
Definition depcheck.cpp:442
bool does_conflict(const elem &elem1, const elem &elem2, bool directonly=false) const
Decides if two components are conflicting or not.
Definition depcheck.cpp:221
config depinfo_
holds all required info about the components and their dependencies
Definition depcheck.hpp:187
std::vector< std::string > get_required(const elem &e) const
Get the list of modifications required by a certain component.
Definition depcheck.cpp:177
std::string prev_era_
used by save_state() and revert() to backup/restore era_
Definition depcheck.hpp:199
std::vector< std::string > get_conflicting_enabled(const elem &e) const
Get the list of modifications which are conflicting a certain component and are currently enabled.
Definition depcheck.cpp:208
std::string find_name_for(const elem &e) const
Look up the name of a given component.
Definition depcheck.cpp:156
bool does_require(const elem &elem1, const elem &elem2) const
Decides whether e1 requires e2.
Definition depcheck.cpp:320
std::vector< std::string > mods_
the ids of the currently selected modifications
Definition depcheck.hpp:196
int get_era_index() const
Returns the selected era.
Definition depcheck.cpp:398
std::string scenario_
the id of the currently selected scenario
Definition depcheck.hpp:193
std::vector< std::string > get_required_not_installed(const elem &e) const
Get the list of modifications which are required by a certain component, but currently unavailable on...
Definition depcheck.cpp:162
std::string change_scenario_dialog(const std::vector< std::string > &scenarios)
Display a dialog requesting the user to select a new scenario.
Definition depcheck.cpp:478
bool is_modification_active(int index) const
Tells whether a certain mod is activated.
Definition depcheck.cpp:432
std::string era_
the id of the currently selected era
Definition depcheck.hpp:190
void try_scenario(const std::string &id, bool force=false)
Tries to set the selected scenario.
Definition depcheck.cpp:348
void try_scenario_by_index(int index, bool force=false)
Tries to set the selected scenario.
Definition depcheck.cpp:393
manager(const game_config_view &gamecfg, bool mp)
Definition depcheck.cpp:61
void failure_dialog(const std::string &msg)
Shows an error message.
Definition depcheck.cpp:493
bool change_era(const std::string &id)
Attempts to change the selected era.
Definition depcheck.cpp:585
void save_state()
saves the current values of era_, scenarios_ and mods_
Definition depcheck.cpp:129
std::string prev_scenario_
used by save_state() and revert() to backup/restore scenario_
Definition depcheck.hpp:202
int get_scenario_index() const
Returns the selected scenario.
Definition depcheck.cpp:417
std::vector< std::string > get_required_not_enabled(const elem &e) const
Get the list of modifications which are required by a certain component, but aren't currently enabled...
Definition depcheck.cpp:194
void try_modification_by_id(const std::string &id, bool activate, bool force=false)
Tries to enable/disable a specific modification.
Definition depcheck.cpp:370
std::vector< std::string > prev_mods_
used by save_state() and revert() to backup/restore mods_
Definition depcheck.hpp:205
#define DBG_MP
static lg::log_domain log_mp_create_depcheck("mp/create/depcheck")
const config * cfg
static std::string _(const char *str)
Definition gettext.hpp:100
std::string id
Text to match against addon_info.tags()
Definition manager.cpp:199
Standard logging facilities (interface).
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.
Definition message.cpp:148
Main entry points of multiplayer mode.
bool contains(const Container &container, const Value &value)
Returns true iff value is found in container.
Definition general.hpp:88
std::string join(const Range &v, const std::string &s=",")
Generates a new string joining container items in a list.
std::vector< std::string > split(const config_attribute_value &val)
std::string_view data
Definition picture.cpp:188
represents a component (era, modification or scenario)
Definition depcheck.hpp:171
static constexpr utils::optional< enum_type > get_enum(const std::string_view value)
Converts a string into its enum equivalent.
Definition enum_base.hpp:57
static map_location::direction s
#define i
#define e
#define c