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