28 #define DBG_MP LOG_STREAM(debug, log_mp_create_depcheck)
32 void copy_keys(
config& out,
35 bool copy_force_key=
false)
38 out[
"allow_" +
type] = in[
"allow_" +
type];
40 out[
"disallow_" +
type] = in[
"disallow_" +
type];
44 out[
"ignore_incompatible_" +
type] = in[
"ignore_incompatible_" +
type];
49 out[
"force_" +
type] = in[
"force_" +
type];
71 DBG_MP <<
"Initializing the dependency manager" << std::endl;
73 component_availabilty
type = cfg[
"type"].to_enum<component_availabilty>(component_availabilty::HYBRID);
74 if((type != component_availabilty::MP || mp) && (type != component_availabilty::SP || !mp) ) {
76 info[
"id"] = cfg[
"id"];
77 info[
"name"] = cfg[
"name"];
79 copy_keys(info, cfg,
"scenario");
80 copy_keys(info, cfg,
"era");
81 copy_keys(info, cfg,
"modification");
83 depinfo_.add_child(
"modification", info);
88 component_availabilty type = cfg[
"type"].to_enum<component_availabilty>(component_availabilty::MP);
89 if((type != component_availabilty::MP || mp) && (type != component_availabilty::SP || !mp) ) {
91 info[
"id"] = cfg[
"id"];
92 info[
"name"] = cfg[
"name"];
94 copy_keys(info, cfg,
"scenario");
95 copy_keys(info, cfg,
"modification",
true);
97 depinfo_.add_child(
"era", info);
102 if (cfg[
"allow_new_game"].to_bool(
true)) {
104 info[
"id"] = cfg[
"id"];
105 info[
"name"] = cfg[
"name"];
107 copy_keys(info, cfg,
"era");
108 copy_keys(info, cfg,
"modification",
true);
110 depinfo_.add_child(
"scenario", info);
116 void manager::save_state()
118 DBG_MP <<
"Saving current state" << std::endl;
120 prev_scenario_ = scenario_;
124 void manager::revert()
126 DBG_MP <<
"Restoring previous state" << std::endl;
128 scenario_ = prev_scenario_;
135 if (cfg[
"id"] == e.id) {
143 std::string manager::find_name_for(
const elem& e)
const
150 std::vector<std::string>
151 manager::get_required_not_installed(
const elem& e)
const
153 std::vector<std::string>
result;
155 std::vector<std::string>
items = get_required(e);
158 if (!
exists(elem(str,
"modification"))) {
159 result.push_back(str);
166 std::vector<std::string> manager::get_required(
const elem& e)
const
168 std::vector<std::string>
result;
170 if (e.type ==
"modification") {
183 std::vector<std::string> manager::get_required_not_enabled(
const elem& e)
const
185 std::vector<std::string> required = get_required(e);
186 std::vector<std::string>
result;
190 result.push_back(str);
197 std::vector<std::string> manager::get_conflicting_enabled(
const elem& e)
const
199 std::vector<std::string>
result;
202 if (conflicts(elem(mod,
"modification"), e)) {
203 result.push_back(mod);
210 bool manager::conflicts(
const elem& elem1,
const elem& elem2,
bool directonly)
const
212 if (elem1 == elem2) {
226 if (data1.
has_attribute(
"ignore_incompatible_" + elem2.type)) {
227 std::vector<std::string> ignored =
228 utils::split(data1[
"ignore_incompatible_" + elem2.type]);
235 if (data2.
has_attribute(
"ignore_incompatible_" + elem1.type)) {
236 std::vector<std::string> ignored =
237 utils::split(data2[
"ignore_incompatible_" + elem1.type]);
248 std::vector<std::string> allowed =
251 result = !
util::contains(allowed, elem2.id) && !requires(elem1, elem2);
253 std::vector<std::string> disallowed =
260 std::vector<std::string> allowed =
263 result = result || (!
util::contains(allowed, elem1.id) && !requires(elem2, elem1));
265 std::vector<std::string> disallowed =
277 std::vector<std::string> req1 = get_required(elem1),
278 req2 = get_required(elem2);
281 elem
m(
s,
"modification");
283 if (conflicts(elem2,
m,
true)) {
289 elem
m(
s,
"modification");
291 if (conflicts(elem1,
m,
true)) {
297 elem m1(id1,
"modification");
300 elem m2(id2,
"modification");
302 if (conflicts(m1, m2)) {
313 bool manager::requires(
const elem& elem1,
const elem& elem2)
const
315 if (elem2.type !=
"modification") {
322 std::vector<std::string> required =
331 void manager::try_era(
const std::string&
id,
bool force)
337 }
else if (!change_era(
id)) {
342 void manager::try_scenario(
const std::string&
id,
bool force)
348 }
else if (!change_scenario(
id)) {
353 void manager::try_modifications(
const std::vector<std::string>&
ids,
bool force)
359 }
else if (!change_modifications(ids)) {
364 void manager::try_modification_by_index(
int index,
bool activate,
bool force)
366 std::string id = depinfo_.child(
"modification", index)[
"id"];
367 std::vector<std::string> mods_copy = mods_;
369 if (
std::find(mods_copy.begin(), mods_copy.end(),
id) == mods_copy.end()) {
370 mods_copy.push_back(
id);
374 if (pos != mods_copy.end()) {
375 mods_copy.erase(pos);
379 try_modifications(mods_copy, force);
382 void manager::try_era_by_index(
int index,
bool force)
384 try_era(depinfo_.child(
"era", index)[
"id"], force);
387 void manager::try_scenario_by_index(
int index,
bool force)
389 try_scenario(depinfo_.child(
"scenario", index)[
"id"], force);
392 int manager::get_era_index()
const
395 for (
const config&
i : depinfo_.child_range(
"era"))
397 if (
i[
"id"] == era_) {
406 int manager::get_scenario_index()
const
410 for (
const config&
i : depinfo_.child_range(
"scenario"))
412 if (
i[
"id"] == scenario_) {
421 bool manager::is_modification_active(
int index)
const
423 std::string id = depinfo_.child(
"modification", index)[
"id"];
424 return std::find(mods_.begin(), mods_.end(),
id) != mods_.end();
429 bool manager::enable_mods_dialog(
const std::vector<std::string>& mods,
432 std::vector<std::string>
items;
434 items.push_back(depinfo_.find_child(
"modification",
"id", mod)[
"name"]);
438 return dialog.show(video_);
441 bool manager::disable_mods_dialog(
const std::vector<std::string>& mods,
444 std::vector<std::string>
items;
446 items.push_back(depinfo_.find_child(
"modification",
"id", mod)[
"name"]);
450 return dialog.show(video_);
453 std::string manager::change_era_dialog(
const std::vector<std::string>& eras)
455 std::vector<std::string>
items;
457 items.push_back(depinfo_.find_child(
"era",
"id",
era)[
"name"]);
462 if (dialog.show(video_)) {
463 return eras[dialog.result()];
470 manager::change_scenario_dialog(
const std::vector<std::string>& scenarios)
472 std::vector<std::string>
items;
474 items.push_back(depinfo_.find_child(
"scenario",
"id", scenario)[
"name"]);
478 if (dialog.show(video_)) {
479 return scenarios[dialog.result()];
488 (video_,
_(
"Failed to resolve dependencies"), msg,
_(
"OK"));
500 type_str =
"scenario";
503 type_str =
"modification";
506 depinfo_.add_child_at(type_str, data, index);
509 bool manager::change_scenario(
const std::string&
id)
512 if (!get_required_not_installed(elem(
id,
"scenario")).empty()) {
514 _(
"Scenario can't be activated. Some dependencies are missing: ");
517 utils::join(get_required_not_installed(elem(
id,
"scenario")),
", ");
525 elem scen = elem(
id,
"scenario");
529 std::vector<std::string> req = get_required_not_enabled(scen);
530 std::vector<std::string> con = get_conflicting_enabled(scen);
533 if (!enable_mods_dialog(req, scen_name)) {
539 if (!disable_mods_dialog(con, scen_name)) {
544 std::vector<std::string> newmods = req;
547 newmods.push_back(
i);
556 if (!conflicts(scen, elem(era_,
"era"))) {
560 std::vector<std::string> compatible;
561 for (
const config&
i : depinfo_.child_range(
"era")) {
562 if (!conflicts(scen, elem(
i[
"id"],
"era"))) {
563 compatible.push_back(
i[
"id"]);
567 if (!compatible.empty()) {
568 era_ = change_era_dialog(compatible);
570 failure_dialog(
_(
"No compatible eras found."));
578 return change_era(era_);
584 if (!get_required_not_installed(elem(
id,
"era")).empty()) {
586 _(
"Era can't be activated. Some dependencies are missing: ");
588 msg +=
utils::join(get_required_not_installed(elem(
id,
"era")),
", ");
595 elem
era = elem(
id,
"era");
598 std::vector<std::string> req = get_required_not_enabled(era);
599 std::vector<std::string> con = get_conflicting_enabled(era);
603 if (!enable_mods_dialog(req, era_name)) {
609 if (!disable_mods_dialog(con, era_name)) {
614 std::vector<std::string> newmods = req;
617 newmods.push_back(
i);
625 if (!conflicts(era, elem(scenario_,
"scenario"))) {
629 std::vector<std::string> compatible;
630 for (
const config&
i : depinfo_.child_range(
"scenario")) {
631 if (!conflicts(era, elem(
i[
"id"],
"scenario"))) {
632 compatible.push_back(
i[
"id"]);
636 if (!compatible.empty()) {
637 scenario_ = change_scenario_dialog(compatible);
639 failure_dialog(
_(
"No compatible scenarios found."));
643 if (scenario_.empty()) {
647 return change_scenario(scenario_);
650 bool manager::change_modifications
654 std::vector<std::string> filtered;
657 elem ei(
i,
"modification");
659 ok = ok && !conflicts(ei, elem(j,
"modification"));
663 filtered.push_back(
i);
667 if (filtered.size() != modifications.size()) {
668 failure_dialog(
_(
"Not all of the chosen modifications are compatible." \
669 " Some of them will be disabled."));
676 std::vector<std::string> compatible;
678 elem
era(
c[
"id"],
"era");
681 ok = ok && !conflicts(era, elem(
s,
"modification"));
685 compatible.push_back(era.id);
690 if (!compatible.empty()) {
691 era_ = change_era_dialog(compatible);
693 failure_dialog(
_(
"No compatible eras found."));
701 if (!change_era(era_)) {
705 if (!change_era(era_)) {
715 elem scen(
c[
"id"],
"scenario");
718 ok = ok && !conflicts(scen, elem(
s,
"modification"));
722 compatible.push_back(scen.id);
727 if (!compatible.empty()) {
728 scenario_ = change_scenario_dialog(compatible);
730 failure_dialog(
_(
"No compatible scenarios found."));
734 if (scenario_.empty()) {
738 return change_scenario(scenario_);
740 if (!change_scenario(scenario_)) {
child_itors child_range(const std::string &key)
bool contains(const Container &container, const Value &value)
Returns true iff value is found in container.
GLuint GLuint GLsizei GLenum type
const std::vector< std::string > items
GLint GLenum GLsizei GLint GLsizei const GLvoid * data
This module controls the multiplayer lobby.
bool exists(const image::locator &i_locator)
returns true if the given image actually exists, without loading it.
static UNUSEDNOWARN std::string _(const char *str)
static lg::log_domain log_mp_create_depcheck("mp/create/depcheck")
void show_message(CVideo &video, const std::string &title, const std::string &message, const std::string &button_caption, const bool auto_close, const bool message_use_markup)
Shows a message to the user.
std::string join(T const &v, const std::string &s=",")
Generates a new string joining container items in a list.
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
const std::vector< std::string > & modifications(bool mp)
bool has_attribute(const std::string &key) const
bool find(E event, F functor)
Tests whether an event handler is available.
config & find_child(const std::string &key, const std::string &name, const std::string &value)
Returns the first child of tag key with a name attribute containing value.
Standard logging facilities (interface).
std::vector< std::string > split(std::string const &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
A config object defines a single node in a WML file, with access to child nodes.
GLsizei const GLcharARB ** string