Index: data/gui/default/window/mp_depcheck_select_new.cfg
===================================================================
--- data/gui/default/window/mp_depcheck_select_new.cfg	(revision 0)
+++ data/gui/default/window/mp_depcheck_select_new.cfg	(working copy)
@@ -0,0 +1,167 @@
+#textdomain wesnoth-lib
+###
+### Proposes a list of compaitble components if the currently selected
+### one is incompatible. Currently used for scenarios and eras.
+###
+
+[window]
+	id = "mp_depcheck_select_new"
+	description = "Select new era or scenario"
+
+	[resolution]
+		definition = "default"
+
+		automatic_placement = "true"
+		horizontal_placement = "center"
+		vertical_placement = "center"
+
+		maximum_height = 400
+		maximum_width = 600
+
+		[tooltip]
+			id = "tooltip_large"
+		[/tooltip]
+
+		[helptip]
+			id = "tooltip_large"
+		[/helptip]
+
+		[grid]
+
+			[row]
+				grow_factor = 0
+
+				[column]
+					grow_factor = 1
+
+					border = "all"
+					border_size = 5
+					horizontal_alignment = "left"
+
+					[label]
+						definition = "title"
+						label = _ "User interaction required"
+					[/label]
+
+				[/column]
+
+			[/row]
+
+			[row]
+				grow_factor = 0
+
+				[column]
+					grow_factor = 1
+
+					border = "all"
+					border_size = 5
+					horizontal_alignment = "left"
+
+					[label]
+						definition = "default"
+						label = _ "User interaction required"
+						id = "message"
+					[/label]
+
+				[/column]
+
+			[/row]
+
+			[row]
+				grow_factor = 1
+
+				[column]
+					grow_factor = 1
+					horizontal_grow = "true"
+					vertical_grow = "true"
+
+					border = "all"
+					border_size = 5
+
+					[listbox]
+						definition = "default"
+						id = "itemlist"
+
+						[list_definition]
+
+							[row]
+
+								[column]
+									grow_factor = 1
+									horizontal_grow = "true"
+
+									[toggle_button]
+										definition = "listbox_text"
+
+										return_value_id = "ok"
+									[/toggle_button]
+
+								[/column]
+
+							[/row]
+
+						[/list_definition]
+
+					[/listbox]
+
+				[/column]
+
+			[/row]
+
+			[row]
+				grow_factor = 0
+
+				[column]
+					grow_factor = 1
+
+					border = "all"
+					border_size = 5
+					horizontal_alignment = "right"
+
+					[grid]
+
+						[row]
+							grow_factor = 0
+
+							[column]
+								grow_factor = 0
+
+								border = "all"
+								border_size = 5
+								horizontal_alignment = "center"
+
+								[button]
+									id = "ok"
+									label = _ "OK"
+								[/button]
+
+							[/column]
+
+							[column]
+								grow_factor = 1
+
+								border = "all"
+								border_size = 5
+								horizontal_alignment = "right"
+
+								[button]
+									id = "cancel"
+									label = _ "Cancel"
+								[/button]
+
+							[/column]
+
+
+						[/row]
+
+					[/grid]
+
+				[/column]
+
+			[/row]
+
+		[/grid]
+
+	[/resolution]
+
+[/window]
Index: data/gui/default/window/mp_create_game_choose_mods.cfg
===================================================================
--- data/gui/default/window/mp_create_game_choose_mods.cfg	(revision 0)
+++ data/gui/default/window/mp_create_game_choose_mods.cfg	(working copy)
@@ -0,0 +1,191 @@
+#textdomain wesnoth-lib
+###
+### Select the modifications to be active during the game
+###
+
+[window]
+	id = "mp_create_game_choose_mods"
+	description = "Dialog for choosing modifications for MP games."
+
+	[resolution]
+		definition = "default"
+
+		automatic_placement = "true"
+		vertical_placement = "center"
+		horizontal_placement = "center"
+
+		maximum_width = 800
+		maximum_height = 480
+
+		[linked_group]
+			id = "checkbox"
+			fixed_width = "true"
+		[/linked_group]
+
+		[linked_group]
+			id = "name"
+			fixed_width = "true"
+		[/linked_group]
+
+		[linked_group]
+			id = "description"
+			fixed_width = "true"
+		[/linked_group]
+
+		[tooltip]
+			id = "tooltip_large"
+		[/tooltip]
+
+		[helptip]
+			id = "tooltip_large"
+		[/helptip]
+
+		[grid]
+
+			[row]
+				grow_factor = 0
+
+				[column]
+					grow_factor = 1
+
+					border = "all"
+					border_size = 5
+					horizontal_alignment = "left"
+					[label]
+						definition = "title"
+
+						label = _ "Choose Modifications"
+					[/label]
+
+				[/column]
+
+			[/row]
+
+			[row]
+				grow_factor = 0
+
+				[column]
+
+					border = "all"
+					border_size = 5
+					horizontal_alignment = "left"
+					[label]
+						definition = "default"
+						id = "message"
+
+						label = _ "Enable the modifications you want to be active during the game."
+					[/label]
+
+				[/column]
+
+			[/row]
+
+			[row]
+				grow_factor = 1
+
+				[column]
+					grow_factor = 1
+
+					horizontal_grow = "true"
+					vertical_grow = "true"
+
+					border = "all"
+					border_size = 5
+
+					[listbox]
+						id = "mod_list"
+						definition = "default"
+
+						[list_definition]
+
+							[row]
+
+								[column]
+								 	vertical_grow = "true"
+								 	horizontal_grow = "true"
+								 	[toggle_panel]
+										definition = "default"
+										[grid]
+											[row]
+												[column]
+													grow_factor = 0
+													horizontal_alignment = "left"
+													border = "all"
+													border_size = 5
+													[toggle_button]
+														id = "checkbox"
+														definition = "default"
+														linked_group = "checkbox"
+													[/toggle_button]
+												[/column]
+												[column]
+													grow_factor = 1
+													horizontal_grow = "true"
+													border = "all"
+													border_size = 5
+													[label]
+														id = "name"
+														definition = "default_large"
+														linked_group = "name"
+													[/label]
+												[/column]
+											[/row]
+											[row]
+												[column]
+													grow_factor = 0
+													horizontal_alignment = "left"
+													border = "all"
+													border_size = 5
+													[spacer]
+													[/spacer]
+												[/column]
+												[column]
+													grow_factor = 1
+													horizontal_alignment = "left"
+													border = "all"
+													border_size = 5
+													[label]
+														id = "description"
+														definition = "default"
+														linked_group = "description"
+													[/label]
+												[/column]
+											[/row]
+										[/grid]
+									[/toggle_panel]
+								[/column]
+
+							[/row]
+
+						[/list_definition]
+
+					[/listbox]
+
+				[/column]
+
+			[/row]
+
+			[row]
+				grow_factor = 0
+
+				[column]
+
+					border = "all"
+					border_size = 5
+					horizontal_alignment = "right"
+
+					[button]
+						id = "ok"
+						definition = "default"
+
+						label = _ "Close"
+						return_value = "0"
+					[/button]
+				[/column]
+			[/row]
+		[/grid]
+
+	[/resolution]
+
+[/window]
+
Index: data/gui/default/window/mp_depcheck_confirm_change.cfg
===================================================================
--- data/gui/default/window/mp_depcheck_confirm_change.cfg	(revision 0)
+++ data/gui/default/window/mp_depcheck_confirm_change.cfg	(working copy)
@@ -0,0 +1,164 @@
+#textdomain wesnoth-lib
+###
+### Prompts the user to confirm some changes required to satisfy
+### dependencies. Currently used for enabling/disabling modifications.
+###
+
+[window]
+	id = "mp_depcheck_confirm_change"
+	description = "Enable/disable modifications"
+
+	[resolution]
+		definition = "default"
+
+		automatic_placement = "true"
+		vertical_placement = "center"
+		horizontal_placement = "center"
+
+		maximum_height = 400
+		maximum_width = 600
+
+		[tooltip]
+			id = "tooltip_large"
+		[/tooltip]
+
+		[helptip]
+			id = "tooltip_large"
+		[/helptip]
+
+		[grid]
+
+			[row]
+				grow_factor = 0
+
+				[column]
+					grow_factor = 1
+
+					border = "all"
+					border_size = 5
+					horizontal_alignment = "left"
+
+					[label]
+						definition = "title"
+						label = _ "Confirmation requested"
+					[/label]
+
+				[/column]
+
+			[/row]
+
+			[row]
+				grow_factor = 0
+
+				[column]
+					grow_factor = 1
+
+					border = "all"
+					border_size = 5
+					horizontal_alignment = "left"
+
+					[label]
+						definition = "default"
+						label = "text is set by C++"
+						id = "message"
+					[/label]
+
+				[/column]
+
+			[/row]
+
+			[row]
+				grow_factor = 1
+
+				[column]
+					grow_factor = 1
+
+					border = "all"
+					border_size = 5
+					horizontal_alignment = "left"
+
+					[scroll_label]
+						id = "itemlist"
+						label = "text set by c++"
+						definition = "default"
+					[/scroll_label]
+
+				[/column]
+
+			[/row]
+
+			[row]
+				grow_factor = 0
+
+				[column]
+					grow_factor = 1
+
+					border = "all"
+					border_size = 5
+					horizontal_alignment = "left"
+
+					[label]
+						label = _ "Would you like to apply the changes?"
+						definition = "default"
+					[/label]
+
+				[/column]
+
+			[/row]
+
+			[row]
+				grow_factor = 0
+
+				[column]
+					grow_factor = 1
+
+					border = "all"
+					border_size = 5
+					horizontal_alignment = "right"
+
+					[grid]
+
+						[row]
+							grow_factor = 0
+
+							[column]
+								grow_factor = 0
+
+								border = "all"
+								border_size = 5
+								horizontal_alignment = "center"
+
+								[button]
+									id = "ok"
+									label = _ "Yes"
+								[/button]
+
+							[/column]
+
+							[column]
+								grow_factor = 1
+
+								border = "all"
+								border_size = 5
+								horizontal_alignment = "right"
+
+								[button]
+									id = "cancel"
+									label = _ "No"
+								[/button]
+
+							[/column]
+
+						[/row]
+
+					[/grid]
+
+				[/column]
+
+			[/row]
+
+		[/grid]
+
+	[/resolution]
+
+[/window]
Index: src/mp_depcheck.cpp
===================================================================
--- src/mp_depcheck.cpp	(revision 0)
+++ src/mp_depcheck.cpp	(working copy)
@@ -0,0 +1,678 @@
+/*
+   Copyright (C) 2012 by Boldizsár Lipka <lipka.boldizsar@gmail.com>
+   Part of the Battle for Wesnoth Project http://www.wesnoth.org/
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY.
+
+   See the COPYING file for more details.
+*/
+
+#include "mp_depcheck.hpp"
+
+#include <algorithm>
+#include <map>
+
+#include "foreach.hpp"
+#include "formula_string_utils.hpp"
+#include "gettext.hpp"
+
+#include "gui/dialogs/mp_depcheck_confirm_change.hpp"
+#include "gui/dialogs/mp_depcheck_select_new.hpp"
+#include "gui/dialogs/message.hpp"
+
+namespace {
+//helper function
+void copy_keys(config& out,
+			   const config& in,
+			   const std::string& type,
+			   bool copy_force_key=false)
+{
+	if (in.has_attribute("allow_" + type)) {
+		out["allow_" + type] = in["allow_" + type];
+	} else if (in.has_attribute("disallow_" + type)) {
+		out["disallow_" + type] = in["disallow_" + type];
+	}
+
+	if (in.has_attribute("ignore_incompatible_" + type)) {
+		out["ignore_incompatible_" + type] = in["ignore_incompatible_" + type];
+	}
+
+	if (copy_force_key) {
+		if (in.has_attribute("force_" + type)) {
+			out["force_" + type] = in["force_" + type];
+		}
+	}
+}
+
+//helper function
+inline bool contains(const std::vector<std::string>& container,
+					 const std::string& value)
+{
+	return 	std::find(container.begin(), container.end(), value)
+			!= container.end();
+}
+
+} //anonymous namespace
+
+namespace mp
+{
+
+namespace depcheck
+{
+
+manager::manager(const config& gamecfg, CVideo& video)
+	: video_(video)
+	, depinfo_()
+	, era_()
+	, scenario_()
+	, mods_()
+	, prev_era_()
+	, prev_scenario_()
+	, prev_mods_()
+{
+	foreach (const config& cfg, gamecfg.child_range("modification")) {
+		config info;
+		info["id"] = cfg["id"];
+		info["name"] = cfg["name"];
+
+		copy_keys(info, cfg, "scenario");
+		copy_keys(info, cfg, "era");
+		copy_keys(info, cfg, "modification");
+
+		depinfo_.add_child("modification", info);
+	}
+
+	foreach (const config& cfg, gamecfg.child_range("era")) {
+		config info;
+		info["id"] = cfg["id"];
+		info["name"] = cfg["name"];
+
+		copy_keys(info, cfg, "scenario");
+		copy_keys(info, cfg, "modification", true);
+
+		depinfo_.add_child("era", info);
+	}
+
+	foreach (const config& cfg, gamecfg.child_range("multiplayer")) {
+		config info;
+		info["id"] = cfg["id"];
+		info["name"] = cfg["name"];
+
+		copy_keys(info, cfg, "era");
+		copy_keys(info, cfg, "modification", true);
+
+		depinfo_.add_child("scenario", info);
+	}
+}
+
+
+void manager::save_state() {
+	prev_era_ = era_;
+	prev_scenario_ = scenario_;
+	prev_mods_ = mods_;
+}
+
+void manager::revert() {
+	era_ = prev_era_;
+	scenario_ = prev_scenario_;
+	mods_ = prev_mods_;
+}
+
+bool manager::exists(const elem& e) const
+{
+	foreach (const config& cfg, depinfo_.child_range(e.type)) {
+		if (cfg["id"] == e.id)
+			return true;
+	}
+
+	return false;
+}
+
+std::vector<std::string>
+		manager::get_required_not_installed(const elem& e) const
+{
+	std::vector<std::string> result;
+
+	std::vector<std::string> items = get_required(e);
+
+	foreach (const std::string& str, items) {
+		if (!exists(elem(str, "modification")))
+			result.push_back(str);
+	}
+
+	return result;
+}
+
+std::vector<std::string> manager::get_required(const elem& e) const
+{
+	std::vector<std::string> result;
+
+	if (e.type == "modification")
+		return result;
+
+	config data = depinfo_.find_child(e.type, "id", e.id);
+
+	if (data.has_attribute("force_modification")) {
+		result = utils::split(data["force_modification"], ',');
+	}
+
+	return result;
+}
+
+std::vector<std::string> manager::get_required_not_enabled(const elem& e) const
+{
+	std::vector<std::string> required = get_required(e);
+	std::vector<std::string> result;
+
+	foreach (std::string str, required) {
+		if (!contains(mods_, str)) {
+			result.push_back(str);
+		}
+	}
+
+	return result;
+}
+
+std::vector<std::string> manager::get_conflicting_enabled(const elem& e) const
+{
+	std::vector<std::string> result;
+
+	foreach(const std::string& mod, mods_) {
+		if (conflicts(elem(mod, "modification"), e))
+			result.push_back(mod);
+	}
+
+	return result;
+}
+
+bool manager::conflicts(const elem& e1, const elem& e2, bool directonly) const
+{
+	if (e1 == e2)
+		return false;
+
+	// We ignore inexistent elements at this point, they will generate
+	// errors in change_era()/change_scenario() anyways.
+	if (!exists(e1) || !exists(e2)) {
+		return false;
+	}
+
+	config data1 = depinfo_.find_child(e1.type, "id", e1.id);
+	config data2 = depinfo_.find_child(e2.type, "id", e2.id);
+
+	// Whether we should skip the check entirely
+	if (data1.has_attribute("ignore_incompatible_" + e2.type)) {
+		std::vector<std::string> ignored =
+						utils::split(data1["ignore_incompatible_" + e2.type]);
+
+		if (contains(ignored, e2.id))
+			return false;
+	}
+
+	if (data2.has_attribute("ignore_incompatible_" + e1.type)) {
+		std::vector<std::string> ignored =
+						utils::split(data2["ignore_incompatible_" + e1.type]);
+
+		if (contains(ignored, e1.id))
+			return false;
+	}
+
+	bool result = false;
+
+	// Checking for direct conflicts between e1 and e2
+	if (data1.has_attribute("allow_" + e2.type)) {
+		std::vector<std::string> allowed =
+						utils::split(data1["allow_" + e2.type]);
+
+		result = !contains(allowed, e2.id) && !requires(e1, e2);
+	} else if (data1.has_attribute("disallow_" + e2.type)) {
+		std::vector<std::string> disallowed =
+						utils::split(data1["disallow_" + e2.type]);
+
+		result = contains(disallowed, e2.id);
+	}
+
+	if (data2.has_attribute("allow_" + e1.type)) {
+		std::vector<std::string> allowed =
+						utils::split(data2["allow_" + e1.type]);
+
+		result = result || (!contains(allowed, e1.id) && !requires(e2, e1));
+	} else if (data2.has_attribute("disallow_" + e1.type)) {
+		std::vector<std::string> disallowed =
+						utils::split(data2["disallow_" + e1.type]);
+
+		result = result || contains(disallowed, e1.id);
+	}
+
+	if (result)
+		return true;
+
+	// Checking for indirect conflicts (i.e. conflicts between dependencies)
+	if (!directonly) {
+		std::vector<std::string>	req1 = get_required(e1),
+									req2 = get_required(e2);
+
+		foreach (const std::string& s, req1) {
+			elem m(s, "modification");
+
+			if (conflicts(e2, m, true))
+				return true;
+		}
+
+		foreach (const std::string& s, req2) {
+			elem m(s, "modification");
+
+			if (conflicts(e1, m, true))
+				return true;
+		}
+
+		foreach (const std::string& l, req1) {
+			elem m1(l, "modification");
+
+			foreach (const std::string& k, req2) {
+				elem m2(k, "modification");
+
+				if (conflicts(m1, m2)) {
+					return true;
+				}
+			}
+		}
+	}
+
+	return false;
+}
+
+
+bool manager::requires(const elem& e1, const elem& e2) const
+{
+	if (e2.type != "modification")
+		return false;
+
+	config data = depinfo_.find_child(e1.type, "id", e1.id);
+
+	if (data.has_attribute("force_modification")) {
+		std::vector<std::string> required =
+							utils::split(data["force_modification"]);
+
+		return contains(required, e2.id);
+	}
+
+	return false;
+}
+
+void manager::try_era(const std::string& id, bool force)
+{
+	save_state();
+
+	if (force)
+		era_ = id;
+	else if (!change_era(id))
+		revert();
+
+}
+
+void manager::try_scenario(const std::string& id, bool force)
+{
+	save_state();
+
+	if (force)
+		scenario_ = id;
+	else if (!change_scenario(id))
+		revert();
+}
+
+void manager::try_modifications(const std::vector<std::string>& ids, bool force)
+{
+	save_state();
+
+	if (force)
+		mods_ = ids;
+	else if (!change_modifications(ids))
+		revert();
+}
+
+void manager::try_era_by_index(int index, bool force)
+{
+	try_era(depinfo_.child("era", index)["id"], force);
+}
+
+void manager::try_scenario_by_index(int index, bool force)
+{
+	try_scenario(depinfo_.child("scenario", index - 1)["id"], force);
+}
+
+int manager::get_era_index() const
+{
+	int result = 0;
+
+	foreach (const config& i, depinfo_.child_range("era"))
+	{
+		if (i["id"] == era_)
+			return result;
+		result++;
+	}
+
+	return -1;
+}
+
+int manager::get_scenario_index() const
+{
+	int result = 1;
+
+	foreach (const config& i, depinfo_.child_range("scenario"))
+	{
+		if (i["id"] == scenario_) {
+			return result;
+		}
+		result++;
+	}
+
+	return -1;
+}
+
+
+bool manager::enable_mods_dialog(const std::vector<std::string>& mods)
+{
+	std::vector<std::string> items;
+	foreach (const std::string& mod, mods) {
+		items.push_back(depinfo_.find_child("modification", "id", mod)["name"]);
+	}
+
+	gui2::tmp_depcheck_confirm_change dialog(true, items, _("A component"));
+	return dialog.show(video_);
+}
+
+bool manager::disable_mods_dialog(const std::vector<std::string>& mods)
+{
+	std::vector<std::string> items;
+	foreach (const std::string& mod, mods) {
+		items.push_back(depinfo_.find_child("modification", "id", mod)["name"]);
+	}
+
+	gui2::tmp_depcheck_confirm_change dialog(false, items, _("A component"));
+	return dialog.show(video_);
+}
+
+std::string manager::change_era_dialog(const std::vector<std::string>& eras)
+{
+	std::vector<std::string> items;
+	foreach(const std::string& era, eras) {
+		items.push_back(depinfo_.find_child("era", "id", era)["name"]);
+	}
+
+	gui2::tmp_depcheck_select_new dialog(ERA, items);
+
+	if (dialog.show(video_))
+		return eras[dialog.result()];
+
+	return "";
+}
+
+std::string
+	manager::change_scenario_dialog(const std::vector<std::string>& scenarios)
+{
+	std::vector<std::string> items;
+	foreach (const std::string& scenario, scenarios) {
+		items.push_back(depinfo_.find_child("scenario", "id", scenario)["name"]);
+	}
+
+	gui2::tmp_depcheck_select_new dialog(SCENARIO, items);
+	if (dialog.show(video_))
+		return scenarios[dialog.result()];
+
+	return "";
+}
+
+void manager::failure_dialog(const std::string& msg)
+{
+	gui2::show_message
+				(video_, _("Failed to resolve dependencies"), msg, _("OK"));
+}
+
+
+void manager::insert_element(component_type type, const config& data, int index)
+{
+	std::string type_str;
+	switch (type) {
+		case ERA:
+			type_str = "era";
+			break;
+		case SCENARIO:
+			type_str = "scenario";
+			break;
+		case MODIFICATION:
+			type_str = "modification";
+	}
+
+	depinfo_.add_child_at(type_str, data, index);
+}
+
+bool manager::change_scenario(const std::string& id)
+{
+	// Checking for missing dependencies
+	if (!get_required_not_installed(elem(id, "scenario")).empty()) {
+		std::string msg =
+			_("Scenario can't be activated. Some dependencies are missing: ");
+
+		msg +=
+			utils::join(get_required_not_installed(elem(id, "scenario")), ", ");
+
+		failure_dialog(msg);
+		return false;
+	}
+
+	scenario_ = id;
+
+	elem scen = elem(id, "scenario");
+
+	// Firstly, we check if we have to enable/disable any mods
+	std::vector<std::string> req = get_required_not_enabled(scen);
+	std::vector<std::string> con = get_conflicting_enabled(scen);
+
+	if (!req.empty()) {
+		if (!enable_mods_dialog(req)) {
+			return false;
+		}
+	}
+
+	if (!con.empty()) {
+		if (!disable_mods_dialog(con)) {
+			return false;
+		}
+	}
+
+	std::vector<std::string> newmods = req;
+	foreach (const std::string& i, mods_)
+		if (!contains(con, i))
+			newmods.push_back(i);
+
+
+	mods_ = newmods;
+
+	// Now checking if the currently selected era conflicts the scenario
+	// and changing era if necessary
+	if (!conflicts(scen, elem(era_, "era")))
+		return true;
+
+	std::vector<std::string> compatible;
+	foreach (const config& i, depinfo_.child_range("era")) {
+		if (!conflicts(scen, elem(i["id"], "era")))
+			compatible.push_back(i["id"]);
+	}
+
+	if (!compatible.empty())
+		era_ = change_era_dialog(compatible);
+	else {
+		failure_dialog(_("No compatible eras found."));
+		return false;
+	}
+
+	if (era_.empty())
+		return false;
+
+	change_era(era_);
+
+	return true;
+}
+
+bool manager::change_era(const std::string& id)
+{
+	// Checking for missing dependenciess
+	if (!get_required_not_installed(elem(id, "era")).empty()) {
+		std::string msg =
+				_("Era can't be activated. Some dependencies are missing: ");
+
+		msg += utils::join(get_required_not_installed(elem(id, "era")), ", ");
+		failure_dialog(msg);
+		return false;
+	}
+
+	era_ = id;
+
+	elem era = elem(id, "era");
+
+	std::vector<std::string> req = get_required_not_enabled(era);
+	std::vector<std::string> con = get_conflicting_enabled(era);
+
+	// Firstly, we check if we have to enable/disable any mods
+	if (!req.empty()) {
+		if (!enable_mods_dialog(req)) {
+			return false;
+		}
+	}
+
+	if (!con.empty()) {
+		if (!disable_mods_dialog(con)) {
+			return false;
+		}
+	}
+
+	std::vector<std::string> newmods = req;
+	foreach (const std::string& i, mods_)
+		if (!contains(con, i))
+			newmods.push_back(i);
+
+	mods_ = newmods;
+
+	// Now checking if the currently selected scenarop conflicts the era
+	// and changing scenario if necessary
+	if (!conflicts(era, elem(scenario_, "scenario")))
+		return true;
+
+	std::vector<std::string> compatible;
+	foreach (const config& i, depinfo_.child_range("scenario")) {
+		if (!conflicts(era, elem(i["id"], "scenario")))
+			compatible.push_back(i["id"]);
+	}
+
+	if (!compatible.empty())
+		scenario_ = change_scenario_dialog(compatible);
+	else {
+		failure_dialog(_("No compatible scenarios found."));
+		return false;
+	}
+
+	if (scenario_.empty())
+		return false;
+
+	change_scenario(scenario_);
+
+	return true;
+}
+
+bool manager::change_modifications
+					(const std::vector<std::string>& modifications)
+{
+	// Checking if the selected combination of mods is valid at all
+	std::vector<std::string> filtered;
+	foreach (const std::string& i, modifications) {
+		bool ok = true;
+		elem ei(i, "modification");
+		foreach (const std::string& j, filtered) {
+			ok = ok && !conflicts(ei, elem(j, "modification"));
+		}
+
+		if (ok)
+			filtered.push_back(i);
+	}
+
+	if (filtered.size() != modifications.size())
+		failure_dialog(_("Not all of the chosen modifications are compatible." \
+						 " Some of them will be disabled."));
+
+	mods_ = filtered;
+
+	// Checking if the currently selected era is compatible with the set
+	// modifications, and changing era if necessary
+	std::vector<std::string> compatible;
+	foreach (const config& c, depinfo_.child_range("era")) {
+		elem era(c["id"], "era");
+		bool ok = true;
+		foreach (const std::string& s, mods_) {
+			ok = ok && !conflicts(era, elem(s, "modification"));
+		}
+
+		if (ok)
+			compatible.push_back(era.id);
+	}
+
+	if (!contains(compatible, era_)) {
+		if (!compatible.empty())
+			era_ = change_era_dialog(compatible);
+		else {
+			failure_dialog(_("No compatible eras found."));
+			return false;
+		}
+
+		if (era_.empty())
+			return false;
+
+		if (!change_era(era_))
+			return false;
+	} else {
+		change_era(era_);
+	}
+
+	compatible.clear();
+
+	// Checking if the currently selected scenario is compatible with
+	// the set modifications, and changing scenario if necessary
+	foreach (const config& c, depinfo_.child_range("scenario")) {
+		elem scen(c["id"], "scenario");
+		bool ok = true;
+		foreach (const std::string& s, mods_) {
+			ok = ok && !conflicts(scen, elem(s, "modification"));
+		}
+
+		if (ok)
+			compatible.push_back(scen.id);
+	}
+
+	if (!contains(compatible, scenario_)) {
+		if (!compatible.empty())
+			scenario_ = change_scenario_dialog(compatible);
+		else {
+			failure_dialog(_("No compatible scenarios found."));
+			return false;
+		}
+
+		if (scenario_.empty())
+			return false;
+
+		return change_scenario(scenario_);
+	} else {
+		change_scenario(scenario_);
+	}
+
+	return true;
+}
+
+
+
+} //namespace depcheck
+
+} //namespace mp
Index: src/CMakeLists.txt
===================================================================
--- src/CMakeLists.txt	(revision 54406)
+++ src/CMakeLists.txt	(working copy)
@@ -519,7 +519,10 @@
 	gui/dialogs/mp_cmd_wrapper.cpp
 	gui/dialogs/mp_connect.cpp
 	gui/dialogs/mp_create_game.cpp
+	gui/dialogs/mp_create_game_choose_mods.cpp
 	gui/dialogs/mp_create_game_set_password.cpp
+	gui/dialogs/mp_depcheck_confirm_change.cpp
+	gui/dialogs/mp_depcheck_select_new.cpp
 	gui/dialogs/mp_host_game_prompt.cpp
 	gui/dialogs/mp_login.cpp
 	gui/dialogs/mp_method_selection.cpp
@@ -580,6 +583,7 @@
 	menu_events.cpp
 	mouse_events.cpp
 	mouse_handler_base.cpp
+	mp_depcheck.cpp
 	mp_game_settings.cpp
 	multiplayer.cpp
 	multiplayer_connect.cpp
Index: src/multiplayer_create.hpp
===================================================================
--- src/multiplayer_create.hpp	(revision 54406)
+++ src/multiplayer_create.hpp	(working copy)
@@ -18,6 +18,7 @@
 #ifndef MULTIPLAYER_CREATE_HPP_INCLUDED
 #define MULTIPLAYER_CREATE_HPP_INCLUDED

+#include "mp_depcheck.hpp"
 #include "mp_game_settings.hpp"
 #include "multiplayer_ui.hpp"
 #include "widgets/slider.hpp"
@@ -43,9 +44,12 @@

 private:

+	void synchronize_selections();
+
 	bool local_players_only_;

 	tooltips::manager tooltip_manager_;
+	int era_selection_;
 	int map_selection_;
 	int mp_countdown_init_time_;
 	int mp_countdown_reservoir_time_;
@@ -53,6 +57,7 @@

 	std::vector<std::string> user_maps_;
 	std::vector<std::string> map_options_;
+	config available_mods_;

 	/**
 	 * Due to maps not available the index of the selected map and mp scenarios
@@ -96,6 +101,7 @@
 	gui::button regenerate_map_;
 	gui::button generator_settings_;
 	gui::button password_button_;
+	gui::button choose_mods_;

 	gui::combo era_combo_;
 	gui::combo vision_combo_;
@@ -108,6 +114,8 @@

 	int num_turns_;
 	mp_game_settings parameters_;
+
+	depcheck::manager dependency_manager_;
 };

 } // end namespace mp
Index: src/multiplayer_lobby.hpp
===================================================================
--- src/multiplayer_lobby.hpp	(revision 54406)
+++ src/multiplayer_lobby.hpp	(working copy)
@@ -44,6 +44,7 @@
 			name(),
 			map_info(),
 			map_info_size(),
+			mod_info(),
 			gold(),
 			xp(),
 			vision(),
@@ -60,7 +61,8 @@
 			use_map_settings(false),
 			verified(false),
 			password_required(false),
-			have_era(false)
+			have_era(false),
+			have_all_mods(false)
 		{
 		}

@@ -70,6 +72,7 @@
 		std::string name;
 		std::string map_info;
 		std::string map_info_size;
+		std::string mod_info;
 		std::string gold;
 		std::string xp;
 		std::string vision;
@@ -87,6 +90,7 @@
 		bool verified;
 		bool password_required;
 		bool have_era;
+		bool have_all_mods;
 	};
 	gamebrowser(CVideo& video, const config &map_hashes);
 	void scroll(unsigned int pos);
@@ -100,9 +104,9 @@
 	SDL_Rect get_item_rect(size_t index) const;
 	bool empty() const { return games_.empty(); }
 	bool selection_is_joinable() const
-	{ return empty() ? false : (games_[selected_].vacant_slots > 0 && !games_[selected_].started && games_[selected_].have_era); }
+	{ return empty() ? false : (games_[selected_].vacant_slots > 0 && !games_[selected_].started && games_[selected_].have_era && games_[selected_].have_all_mods); }
 	// Moderators may observe any game.
-	bool selection_is_observable() const { return empty() ? false : (games_[selected_].observers && games_[selected_].have_era) || preferences::is_authenticated(); }
+	bool selection_is_observable() const { return empty() ? false : (games_[selected_].observers && games_[selected_].have_era && games_[selected_].have_all_mods) || preferences::is_authenticated(); }
 	bool selected() const { return double_clicked_ && !empty(); }
 	void reset_selection() { double_clicked_ = false; }
 	int selection() const { return selected_; }
Index: src/game_preferences.cpp
===================================================================
--- src/game_preferences.cpp	(revision 54406)
+++ src/game_preferences.cpp	(working copy)
@@ -52,6 +52,10 @@
 bool friends_initialized = false;
 bool ignores_initialized = false;

+std::vector<std::string> mp_modifications;
+
+bool modifications_initialized = false;
+
 bool authenticated = false;

 const char WRAP_CHAR = '@';
@@ -76,10 +80,17 @@
 	return raw.substr(1, raw.length() - 2);
 }

+void initialize_modifications()
+{
+	mp_modifications = utils::split(preferences::get("modifications"), ',');
+	modifications_initialized = true;
+}
+
 } // anon namespace

 namespace preferences {

+
 manager::manager() :
 	base()
 {
@@ -693,6 +704,20 @@
 	preferences::set("mp_map", value);
 }

+const std::vector<std::string>& modifications()
+{
+	if (!modifications_initialized)
+		initialize_modifications();
+
+	return mp_modifications;
+}
+
+void set_modifications(const std::vector<std::string>& value)
+{
+	preferences::set("modifications", utils::join(value, ","));
+	modifications_initialized = false;
+}
+
 bool show_ai_moves()
 {
 	return preferences::get("show_ai_moves", true);
Index: src/mp_game_settings.hpp
===================================================================
--- src/mp_game_settings.hpp	(revision 54406)
+++ src/mp_game_settings.hpp	(working copy)
@@ -39,6 +39,7 @@
 	std::string hash;
 	std::string mp_era;
 	std::string mp_scenario;
+	std::vector<std::string> active_mods;

 	int village_gold;
 	int village_support;
Index: src/server/server.cpp
===================================================================
--- src/server/server.cpp	(revision 54406)
+++ src/server/server.cpp	(working copy)
@@ -2401,6 +2401,7 @@
 				rooms_.lobby().send_server_message("The scenario data is missing the [multiplayer] tag which contains the game settings. Game aborted.", sock);
 				return;
 			}
+
 			g->set_description(&desc);
 			desc.set_attr_dup("id", lexical_cast<std::string>(g->id()).c_str());
 		} else {
@@ -2424,6 +2425,14 @@
 				desc.set_attr("require_era", "no");
 			}
 		}
+
+		const simple_wml::node::child_list& mlist = data.children("modification");
+		foreach (const simple_wml::node* m, mlist) {
+			desc.add_child_at("modification", 0);
+			desc.child("modification")->set_attr_dup("id", m->attr("id"));
+			if (m->attr("require_modification").to_bool(false))
+				desc.child("modification")->set_attr("require_modification", "yes");
+		}

 		// Record the full scenario in g->level()
 		g->level().swap(data);
@@ -2494,6 +2503,7 @@
 			rooms_.lobby().send_server_message("The scenario data is missing the [multiplayer] tag which contains the game settings. Game aborted.", sock);
 			return;
 		}
+
 		// If there is no shroud, then tell players in the lobby
 		// what the map looks like.
 		const simple_wml::node& s = g->level().root();
Index: src/server/simple_wml.hpp
===================================================================
--- src/server/simple_wml.hpp	(revision 54406)
+++ src/server/simple_wml.hpp	(working copy)
@@ -241,6 +241,10 @@
 	const node* child(const char* name) const {
 		return root().child(name);
 	}
+
+	const node::child_list& children(const char* name) const {
+		return root().children(name);
+	}

 	node& set_attr(const char* key, const char* value) {
 		return root().set_attr(key, value);
Index: src/mp_depcheck.hpp
===================================================================
--- src/mp_depcheck.hpp	(revision 0)
+++ src/mp_depcheck.hpp	(working copy)
@@ -0,0 +1,325 @@
+/*
+   Copyright (C) 2012 by Boldizsár Lipka <lipka.boldizsar@gmail.com>
+   Part of the Battle for Wesnoth Project http://www.wesnoth.org/
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY.
+
+   See the COPYING file for more details.
+*/
+
+#ifndef MP_DEPCHECK_HPP_INCLUDED
+#define MP_DEPCHECK_HPP_INCLUDED
+
+#include <string>
+#include <vector>
+#include <map>
+#include "config.hpp"
+#include "game_display.hpp"
+
+namespace mp
+{
+
+namespace depcheck
+{
+
+enum component_type
+{
+	ERA,
+	SCENARIO,
+	MODIFICATION
+};
+
+/**
+ * Note to all triers:
+ * It's not guaranteed that the specified component will be selected
+ * (if the user denies to perform dependency resolution, all changes
+ * will be reverted). Consequently, it's essential to check the
+ * selected values after calling any trier.
+ *
+ * Note to ctor & insert_element:
+ * Please note that the ctor collects data for scenario elements from
+ * "multiplayer" nodes, while insert_element from "scenario" nodes.
+ */
+class manager
+{
+public:
+	manager(const config& gamecfg, CVideo& video);
+
+	/**
+	 * Tries to set the selected era
+	 * @param id the id of the era
+	 * @param force whether to skip dependency check
+	 */
+	void try_era(const std::string& id, bool force = false);
+
+	/**
+	 * Tries to set the selected scenario
+	 * @param id the id of the scenario
+	 * @param force whether to skip dependency check
+	 */
+	void try_scenario(const std::string& id, bool force = false);
+
+	/**
+	 * Tries to set the enabled modifications
+	 * @param ids the ids of the modifications
+	 * @param force whether to skip dependency check
+	 */
+	void try_modifications(const std::vector<std::string>& ids,
+						   bool force = false	);
+
+	/**
+	 * Tries to set the selected era
+	 * @param index the index of the era
+	 * @param force whether to skip dependency check
+	 */
+	void try_era_by_index(int index, bool force = false);
+
+	/**
+	 * Tries to set the selected scenario
+	 * @param index the index of the scenario
+	 * @param force whether to skip dependency check
+	 */
+	void try_scenario_by_index(int index, bool force = false);
+
+	/**
+	 * Returns the selected era
+	 * @return the id of the era
+	 */
+	const std::string& get_era() const { return era_; }
+
+	/**
+	 * Returns the selected scenario
+	 * @return the id of the scenario
+	 */
+	const std::string& get_scenario() const { return scenario_; }
+
+	/**
+	 * Returns the enabled modifications
+	 * @return the ids of the modifications
+	 */
+	const std::vector<std::string>& get_modifications() const { return mods_; }
+
+	/**
+	 * Returns the selected era
+	 * @return the index of the era
+	 */
+	int get_era_index() const;
+
+	/**
+	 * Returns the selected scenario
+	 * @return the index of the scenario
+	 */
+	int get_scenario_index() const;
+
+	/**
+	 * Adds a new element to the manager's database
+	 * @param type the type of the element
+	 * @param data a config object containing the dependency info for element
+	 * @param index where to insert the element
+	 */
+	void insert_element(component_type type, const config& data, int index = 0);
+
+private:
+
+	/** represents a component (era, modification or scenario)*/
+	struct elem {
+		elem(const std::string& _id, const std::string& _type)
+			: id(_id)
+			, type(_type)
+		{}
+
+		std::string id;
+		std::string type;
+
+		bool operator ==(const elem& e) const
+				{ return id == e.id && type == e.type; }
+
+		bool operator !=(const elem& e) const { return !(*this == e); }
+	};
+
+	/** the screen to display dialogs on */
+	CVideo& video_;
+
+	/** holds all required info about the components and their dependencies */
+	config depinfo_;
+
+	/** the id of the currently selected era */
+	std::string era_;
+
+	/** the id of the currently selected scenario */
+	std::string scenario_;
+
+	/** the ids of the currently selected modifications */
+	std::vector<std::string> mods_;
+
+	/** used by save_state() and revert() to backup/restore era_ */
+	std::string prev_era_;
+
+	/** used by save_state() and revert() to backup/restore scenario_ */
+	std::string prev_scenario_;
+
+	/** used by save_state() and revert() to backup/restore mods_ */
+	std::vector<std::string> prev_mods_;
+
+	/** saves the current values of era_, scenarios_ and mods_ */
+	void save_state();
+
+	/** restores the lastly saved values of era_, scenarios_ and mods_ */
+	void revert();
+
+	/**
+	 * Attempts to change the selected scenario.
+	 *
+	 * @param id the scenario's id
+	 * @return true if the selection was changed; false if not
+	 */
+	bool change_scenario(const std::string& id);
+
+	/**
+	 * Attempts to change the selected era.
+	 *
+	 * @param id the era's id
+	 * @return true if the selection was changed; false if not
+	 */
+	bool change_era(const std::string& id);
+
+	/**
+	 * Attempts to change the selected modifications.
+	 *
+	 * @param modifications the list of the modifications' ids
+	 * @return true if the selection was changed; false if not
+	 */
+	bool change_modifications(const std::vector<std::string>& modifications);
+
+	/**
+	 * Decides if two components are conflicting or not
+	 *
+	 * @param e1 the first component
+	 * @param e2 the second component
+	 * @param directonly if the function should ignore any possible
+	 * conflicts between the components' dependencies.
+	 *
+	 * @return true if e1 and e2 conflict, false if not
+	 */
+	bool conflicts(const elem& e1, const elem& e2, bool directonly=false) const;
+
+	/**
+	 * Decides whether e1 requires e2
+	 *
+	 * @param e1 a component; by definition, passing a modification here
+	 * makes no sense
+	 * @param e2 another component; by definition, passing anything else
+	 * than a modification here makes no sense
+	 *
+	 * @return true if e2 is required by e1, false if not
+	 */
+	bool requires(const elem& e1, const elem& e2) const;
+
+	/**
+	 * Get the list of modifications required by a certain component
+	 *
+	 * @param e the component
+	 *
+	 * @return the list of the modifications' ids
+	 */
+	std::vector<std::string> get_required(const elem& e) const;
+
+	/**
+	 * Get the list of modifications which are required by a certain
+	 * component, but aren't currently enabled
+	 *
+	 * @param e the component
+	 *
+	 * @return the list of the modifications' ids
+	 */
+	std::vector<std::string> get_required_not_enabled(const elem& e) const;
+
+	/**
+	 * Get the list of modifications which are conflicting a certain
+	 * component and are currently enabled
+	 *
+	 * @param e the component
+	 *
+	 * @return the list of the modifications' ids
+	 */
+	std::vector<std::string> get_conflicting_enabled(const elem& e) const;
+
+	/**
+	 * Get the list of modifications which are required by a certain
+	 * component, but currently unavailable on the computer
+	 *
+	 * @param e the component
+	 *
+	 * @return the list of the modifications' ids
+	 */
+	std::vector<std::string> get_required_not_installed(const elem& e) const;
+
+	/**
+	 * Display a dialog requesting confirmation for enabling some
+	 * modifications
+	 *
+	 * @param mods the list of modifications to be enabled
+	 *
+	 * @return true, if the user accepted the change, false if not
+	 */
+	bool enable_mods_dialog(const std::vector<std::string>& mods);
+
+	/**
+	 * Display a dialog requesting confirmation for disabling some
+	 * modifications
+	 *
+	 * @param mods the list of modifications to be disabled
+	 *
+	 * @return true, if the user accepted the change, false if not
+	 */
+	bool disable_mods_dialog(const std::vector<std::string>& mods);
+
+	/**
+	 * Display a dialog requesting the user to select a new era
+	 *
+	 * @param eras the possible options (ids)
+	 *
+	 * @return the selected era's id or empty string if the user refused
+	 * to select any
+	 */
+	std::string change_era_dialog(const std::vector<std::string>& eras);
+
+	/**
+	 * Display a dialog requesting the user to select a new scenario
+	 *
+	 * @param scenarios the possible options (ids)
+	 *
+	 * @return the selected scenario's id or empty string if the user
+	 * refused to select any
+	 */
+	std::string change_scenario_dialog
+				(const std::vector<std::string>& scenarios);
+
+	/**
+	 * Shows an error message
+	 *
+	 * @param msg the message to be displayed
+	 */
+	void failure_dialog(const std::string& msg);
+
+	/**
+	 * Decides whether a certain component is installed or not
+	 *
+	 * @param e the component
+	 *
+	 * @return true if the component exists false if not
+	 */
+	bool exists(const elem& e) const;
+
+};
+
+} //namespace depcheck
+
+} //namespace mp
+
+#endif
Index: src/play_controller.cpp
===================================================================
--- src/play_controller.cpp	(revision 54406)
+++ src/play_controller.cpp	(working copy)
@@ -270,10 +270,17 @@
 	browse_ = true;

 	init_managers();
-	// add era events for MP game
+	// add era & mod events for MP game
 	if (const config &era_cfg = level_.child("era")) {
 		game_events::add_events(era_cfg.child_range("event"), "era_events");
 	}
+
+	if (level_.child_or_empty("modification")) {
+		foreach (const config& mod_cfg, level_.child_range("modification")) {
+			game_events::add_events(mod_cfg.child_range("event"),
+									"mod_" + mod_cfg["id"].str() + "_events");
+		}
+	}

 	loadscreen::global_loadscreen->start_stage("start game");
 	loadscreen_manager->reset();
Index: src/game_preferences.hpp
===================================================================
--- src/game_preferences.hpp	(revision 54406)
+++ src/game_preferences.hpp	(working copy)
@@ -23,6 +23,7 @@
 #include "preferences.hpp"

 #include <set>
+#include <vector>

 namespace preferences {

@@ -171,6 +172,9 @@

 	int map();
 	void set_map(int value);
+
+	const std::vector<std::string>& modifications();
+	void set_modifications(const std::vector<std::string>& value);

 	bool show_ai_moves();
 	void set_show_ai_moves(bool value);
Index: src/gui/dialogs/mp_depcheck_select_new.hpp
===================================================================
--- src/gui/dialogs/mp_depcheck_select_new.hpp	(revision 0)
+++ src/gui/dialogs/mp_depcheck_select_new.hpp	(working copy)
@@ -0,0 +1,66 @@
+/*
+   Copyright (C) 2012 by Boldizsár Lipka <lipka.boldizsar@gmail.com>
+   Part of the Battle for Wesnoth Project http://www.wesnoth.org/
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY.
+
+   See the COPYING file for more details.
+*/
+
+#ifndef GUI_DIALOGS_MP_DEPCHECK_SELECT_NEW_HPP_INCLUDED
+#define GUI_DIALOGS_MP_DEPCHECK_SELECT_NEW_HPP_INCLUDED
+
+#include "gui/dialogs/dialog.hpp"
+#include "mp_depcheck.hpp"
+#include <vector>
+
+
+namespace gui2
+{
+
+class tmp_depcheck_select_new
+		: public tdialog
+{
+public:
+	/**
+	 * Constructor.
+	 *
+	 * @param name the type of which we want to select a new item
+	 * @param options the names of the components which can be choosed
+	 */
+	tmp_depcheck_select_new(mp::depcheck::component_type name,
+							const std::vector<std::string>&	options);
+
+	/**
+	 * Returns the selected item.
+	 *
+	 * @return the index of the selected item, or -1 if none was selected
+	 * (the dialog was closed with the cancel button)
+	 */
+	int result() const { return result_; }
+
+protected:
+	/** Inherited from tdialog, implemented by REGISTER_DIALOG. */
+	virtual const std::string& window_id() const;
+
+	/** Inherited from tdialog */
+	virtual void pre_show(CVideo& video, twindow& window);
+
+	/** Inherited from tdialog */
+	virtual void post_show(twindow& window);
+
+private:
+	/** the options available */
+	std::vector<std::string> items_;
+
+	/** the index of the selected item */
+	int result_;
+};
+
+}
+#endif
Index: src/gui/dialogs/mp_create_game_choose_mods.cpp
===================================================================
--- src/gui/dialogs/mp_create_game_choose_mods.cpp	(revision 0)
+++ src/gui/dialogs/mp_create_game_choose_mods.cpp	(working copy)
@@ -0,0 +1,100 @@
+/*
+   Copyright (C) 2012 by Boldizsár Lipka <lipka.boldizsar@gmail.com>
+   Part of the Battle for Wesnoth Project http://www.wesnoth.org/
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY.
+
+   See the COPYING file for more details.
+*/
+
+#define GETTEXT_DOMAIN "wesnoth-lib"
+
+#include "gui/dialogs/mp_create_game_choose_mods.hpp"
+
+#include "foreach.hpp"
+#include "game_preferences.hpp"
+#include "gui/dialogs/field.hpp"
+#include "gui/dialogs/helper.hpp"
+#include "gui/widgets/settings.hpp"
+#include "gui/widgets/toggle_button.hpp"
+#include "../../settings.hpp"
+#include "gettext.hpp"
+
+namespace gui2 {
+
+/*WIKI
+ * @page = GUIWindowDefinitionWML
+ * @order = 2_mp_create_game_choose_mods
+ *
+ * == Create Game: Choose Modifications ==
+ *
+ * The dialog for selecting modifications.
+ *
+ * @begin{table}{dialog_widgets}
+ *
+ * mod_list & & listbox & m &
+ * 		displays the list of the available modifications
+ *
+ * ok & & button & m &
+ * 		closes the dialog
+ *
+ * @end{table}
+ */
+
+REGISTER_DIALOG(mp_create_game_choose_mods)
+
+tmp_create_game_choose_mods::tmp_create_game_choose_mods
+					(const config& game_cfg,
+					 std::vector<std::string>& result)
+	: result_(&result)
+	, game_cfg_(game_cfg)
+{
+}
+
+void tmp_create_game_choose_mods::pre_show(CVideo &/*video*/, twindow &window)
+{
+	mod_list_ = find_widget<tlistbox>(&window, "mod_list", false, true);
+	std::vector<string_map>::iterator mod_itor;
+
+	foreach (const config& mod, game_cfg_.child_range("modification")) {
+
+		string_map column;
+		std::map<std::string, string_map> item;
+		column["label"] = mod["name"];
+		item.insert(std::make_pair("name", column));
+		column["label"] = mod["description"];
+		item.insert(std::make_pair("description", column));
+
+		mod_list_->add_row(item);
+
+		tgrid *grid = mod_list_->get_row_grid(mod_list_->get_item_count()-1);
+		ttoggle_button &checkbox =
+					find_widget<ttoggle_button>(grid, "checkbox", false);
+
+		checkbox.set_value(std::find(	result_->begin(), result_->end(),
+										mod["id"]) != result_->end());
+	}
+
+	result_->clear();
+}
+
+void tmp_create_game_choose_mods::post_show(twindow& /*window*/)
+{
+	for(unsigned int i = 0; i < mod_list_->get_item_count(); i++) {
+		const tgrid *grid = mod_list_->get_row_grid(i);
+		const ttoggle_button &checkbox =
+					find_widget<const ttoggle_button>(grid, "checkbox", false);
+
+		if (checkbox.get_value()) {
+			result_->push_back(game_cfg_.child("modification", i)["id"]);
+		}
+	}
+}
+
+} // namespace gui2
+
Index: src/gui/dialogs/mp_depcheck_confirm_change.cpp
===================================================================
--- src/gui/dialogs/mp_depcheck_confirm_change.cpp	(revision 0)
+++ src/gui/dialogs/mp_depcheck_confirm_change.cpp	(working copy)
@@ -0,0 +1,73 @@
+/*
+   Copyright (C) 2012 by Boldizsár Lipka <lipka.boldizsar@gmail.com>
+   Part of the Battle for Wesnoth Project http://www.wesnoth.org/
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY.
+
+   See the COPYING file for more details.
+*/
+
+#define GETTEXT_DOMAIN "wesnoth-lib"
+
+#include "gui/dialogs/mp_depcheck_confirm_change.hpp"
+
+#include "gui/widgets/settings.hpp"
+#include "gui/widgets/window.hpp"
+#include "formula_string_utils.hpp"
+#include "gettext.hpp"
+
+namespace gui2
+{
+
+/*WIKI
+ * @page = GUIWindowDefinitionWML
+ * @order = 2_mp_depcheck_confirm_change
+ *
+ * == MP Dependency Check: Confirm Change ==
+ *
+ * Asks the user to confirm a change required to proceed. Currently used
+ * for enabling/disabling modifications
+ *
+ * @begin{table}{dialog_widgets}
+ *
+ * message & & label & m &
+ * 		displays the details of the required changes $
+ *
+ * itemlist & & scroll_label & m &
+ * 		displays the list of affected items $
+ *
+ * cancel & & button & m &
+ * 		refuse to apply changes $
+ *
+ * ok & & button & m &
+ * 		agree to apply changes $
+ *
+ * @end{table}
+ */
+
+REGISTER_DIALOG(mp_depcheck_confirm_change)
+
+tmp_depcheck_confirm_change::tmp_depcheck_confirm_change
+			(bool action,
+			 const std::vector<std::string>& mods,
+			 const std::string&	requester)
+{
+	std::string message = requester;
+	message += 	action
+				? _(" requires the following modifications to be enabled:")
+				: _(" requires the following modifications to be disabled:");
+
+	std::string list = "\t";
+	list += utils::join(mods, "\n\t");
+
+	register_label("message", false, message);
+
+	register_label("itemlist", false, list);
+}
+
+}
Index: src/gui/dialogs/mp_create_game_choose_mods.hpp
===================================================================
--- src/gui/dialogs/mp_create_game_choose_mods.hpp	(revision 0)
+++ src/gui/dialogs/mp_create_game_choose_mods.hpp	(working copy)
@@ -0,0 +1,67 @@
+/*
+   Copyright (C) 2012 by Boldizsár Lipka <lipka.boldizsar@gmail.com>
+   Part of the Battle for Wesnoth Project http://www.wesnoth.org/
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY.
+
+   See the COPYING file for more details.
+*/
+
+#ifndef GUI_DIALOGS_MP_CREATE_GAME_CHOOSE_MODS_HPP_INCLUDED
+#define GUI_DIALOGS_MP_CREATE_GAME_CHOOSE_MODS_HPP_INCLUDED
+
+#include "gui/dialogs/dialog.hpp"
+#include "gui/widgets/listbox.hpp"
+#include "gui/widgets/button.hpp"
+#include <utility>
+#include <vector>
+#include <string>
+
+class config;
+
+namespace gui2 {
+
+class tmp_create_game_choose_mods : public tdialog
+{
+public:
+
+	/**
+	 * Constructor.
+	 *
+	 * @param game_cfg the config which contains the information for the
+	 * modifications
+	 * @param result the variable which the ids of the selected items
+	 * should be written to
+	 */
+	tmp_create_game_choose_mods(const config& game_cfg,
+								std::vector<std::string>& result);
+
+private:
+
+	/** Inherited from tdialog, implemented by REGISTER_DIALOG. */
+	virtual const std::string& window_id() const;
+
+	/** Inherited from tdialog */
+	void pre_show(CVideo &video, twindow &window);
+
+	/** Inherited from tdialog */
+	void post_show(twindow &window);
+
+	/** a pointer to the variable the result should be written into */
+	std::vector<std::string> *result_;
+
+	/** a reference to the config which contains the info about modifications*/
+	const config& game_cfg_;
+
+	/** a pointer to the listbox which displays the items */
+	gui2::tlistbox *mod_list_;
+};
+
+} // namespace gui2
+
+#endif
Index: src/gui/dialogs/mp_depcheck_select_new.cpp
===================================================================
--- src/gui/dialogs/mp_depcheck_select_new.cpp	(revision 0)
+++ src/gui/dialogs/mp_depcheck_select_new.cpp	(working copy)
@@ -0,0 +1,111 @@
+/*
+   Copyright (C) 2012 by Boldizsár Lipka <lipka.boldizsar@gmail.com>
+   Part of the Battle for Wesnoth Project http://www.wesnoth.org/
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY.
+
+   See the COPYING file for more details.
+*/
+
+#define GETTEXT_DOMAIN "wesnoth-lib"
+
+#include "gui/dialogs/mp_depcheck_select_new.hpp"
+
+#include "gui/widgets/settings.hpp"
+#include "gui/widgets/window.hpp"
+#include "gui/widgets/listbox.hpp"
+#include "gettext.hpp"
+
+namespace gui2
+{
+
+/*WIKI
+ * @page = GUIWindowDefinitionWML
+ * @order = 2_mp_depcheck_select_new
+ *
+ * == MP Dependency Check: Select New ==
+ *
+ * Offers a list of compatible items if a currently selected one is
+ * incompatible. Currently used for switching era or map.
+ *
+ * @begin{table}{dialog_widgets}
+ *
+ * message & & label & m &
+ * 		displays the details of the required changes
+ *
+ * itemlist & & listbox & m &
+ * 		displays the available items to choose from
+ *
+ * cancel & & button & m &
+ * 		refuse to apply any changes
+ *
+ * ok & & button & m &
+ * 		select the chosen item
+ *
+ * @end{table}
+ *
+ */
+
+REGISTER_DIALOG(mp_depcheck_select_new)
+
+tmp_depcheck_select_new::tmp_depcheck_select_new
+				(	mp::depcheck::component_type	name,
+					const std::vector<std::string>&	items	)
+	: items_(items)
+	, result_(-1)
+{
+
+	std::string message;
+
+	switch (name)
+	{
+		case mp::depcheck::SCENARIO:
+			message = _(	"The currently chosen scenario" \
+							"is not compatible with your setup." \
+							"\nPlease select a compatible one.");
+			break;
+		case mp::depcheck::ERA:
+			message = _(	"The currently chosen era" \
+							"is not compatible with your setup." \
+							"\nPlease select a compatible one.");
+			break;
+		case mp::depcheck::MODIFICATION:
+		//currently this isn't supposed
+		//to happen, but be prepared for anything...
+			message = _(	"The currently chosen modification" \
+							"is not compatible with your setup." \
+							"\nPlease select a compatible one.");
+	}
+
+	register_label("message", false, message);
+
+}
+
+void tmp_depcheck_select_new::pre_show(CVideo& /*video*/, twindow& window)
+{
+	tlistbox& listbox = find_widget<tlistbox>(&window, "itemlist", false);
+
+	foreach(const std::string& item, items_) {
+		string_map current;
+		current.insert(std::make_pair("label", item));
+
+		listbox.add_row(current);
+	}
+
+	listbox.select_row(0);
+}
+
+void tmp_depcheck_select_new::post_show(twindow& window)
+{
+	if (get_retval() == twindow::OK) {
+		tlistbox& listbox = find_widget<tlistbox>(&window, "itemlist", false);
+		result_ = listbox.get_selected_row();
+	}
+}
+
+}
Index: src/gui/dialogs/mp_depcheck_confirm_change.hpp
===================================================================
--- src/gui/dialogs/mp_depcheck_confirm_change.hpp	(revision 0)
+++ src/gui/dialogs/mp_depcheck_confirm_change.hpp	(working copy)
@@ -0,0 +1,51 @@
+/*
+   Copyright (C) 2012 by Boldizsár Lipka <lipka.boldizsar@gmail.com>
+   Part of the Battle for Wesnoth Project http://www.wesnoth.org/
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY.
+
+   See the COPYING file for more details.
+*/
+
+#ifndef GUI_DIALOGS_MP_DEPCHECK_CONFIRM_CHANGE_HPP_INCLUDED
+#define GUI_DIALOGS_MP_DEPCHECK_CONFIRM_CHANGE_HPP_INCLUDED
+
+#include "gui/dialogs/dialog.hpp"
+#include <vector>
+#include <string>
+
+namespace gui2
+{
+
+class tmp_depcheck_confirm_change
+		: public tdialog
+{
+public:
+	/**
+	 * Constructor.
+	 *
+	 * @param action true if the listed modifications are to be enabled,
+	 * false if they're to be disabled
+	 * @param mods the names of the affected modifications
+	 * @param requester the name of the component which requests the change
+	 *
+	 */
+	tmp_depcheck_confirm_change(bool action,
+							    const std::vector<std::string>& mods,
+							    const std::string& requester );
+
+protected:
+
+	/** Inherited from tdialog, implemented by REGISTER_DIALOG. */
+	virtual const std::string& window_id() const;
+
+};
+
+} //namespace gui2
+
+#endif
Index: src/SConscript
===================================================================
--- src/SConscript	(revision 54406)
+++ src/SConscript	(working copy)
@@ -355,7 +355,10 @@
     gui/dialogs/mp_change_control.cpp
     gui/dialogs/mp_connect.cpp
     gui/dialogs/mp_create_game.cpp
+    gui/dialogs/mp_create_game_choose_mods.cpp
     gui/dialogs/mp_create_game_set_password.cpp
+    gui/dialogs/mp_depcheck_confirm_change.cpp
+    gui/dialogs/mp_depcheck_select_new.cpp
     gui/dialogs/mp_host_game_prompt.cpp
     gui/dialogs/mp_login.cpp
     gui/dialogs/mp_method_selection.cpp
@@ -414,6 +417,7 @@
     menu_events.cpp
     mouse_events.cpp
     mouse_handler_base.cpp
+    mp_depcheck.cpp
     mp_game_settings.cpp
     multiplayer.cpp
     multiplayer_connect.cpp
Index: src/scripting/lua.cpp
===================================================================
--- src/scripting/lua.cpp	(revision 54406)
+++ src/scripting/lua.cpp	(working copy)
@@ -3837,9 +3837,9 @@

 static char const *handled_file_tags[] = {
 	"color_palette", "color_range", "era", "event", "generator",
-	"label", "lua", "map", "menu_item", "music", "side", "sound_source", "story",
-	"terrain_graphics", "time", "time_area", "tunnel", "variables", "endlevel",
-	"display",
+	"label", "lua", "map", "menu_item", "modification", "music", "side",
+	"sound_source", "story","terrain_graphics", "time", "time_area", "tunnel",
+	"variables", "endlevel", "display",
 	//TODO: These are only needed for MP campaigns and only for subsequent scenarios, see bug #18883
 	"snapshot", "multiplayer", "replay_start"
 };
Index: src/multiplayer_connect.cpp
===================================================================
--- src/multiplayer_connect.cpp	(revision 54406)
+++ src/multiplayer_connect.cpp	(working copy)
@@ -1689,6 +1689,13 @@
 		}
 		level_.add_child("era", era_cfg);
 	}
+
+	// Add modifications
+	const std::vector<std::string>& mods = params_.active_mods;
+	for (unsigned i = 0; i<mods.size(); i++) {
+		level_.add_child("modification",
+					game_config().find_child("modification", "id", mods[i]));
+	}

 	gold_title_label_.hide(params_.saved_game);
 	income_title_label_.hide(params_.saved_game);
Index: src/multiplayer_create.cpp
===================================================================
--- src/multiplayer_create.cpp	(revision 54406)
+++ src/multiplayer_create.cpp	(working copy)
@@ -30,6 +30,7 @@
 #include "map_exception.hpp"
 #include "map_create.hpp"
 #include "gui/dialogs/message.hpp"
+#include "gui/dialogs/mp_create_game_choose_mods.hpp"
 #include "gui/dialogs/mp_create_game_set_password.hpp"
 #include "gui/dialogs/transient_message.hpp"
 #include "minimap.hpp"
@@ -57,11 +58,13 @@

 	local_players_only_(local_players_only),
 	tooltip_manager_(disp.video()),
+	era_selection_(-1),
 	map_selection_(-1),
 	mp_countdown_init_time_(270),
 	mp_countdown_reservoir_time_(330),
 	user_maps_(),
 	map_options_(),
+	available_mods_(),
 	map_index_(),

 	maps_menu_(disp.video(), std::vector<std::string>()),
@@ -98,6 +101,7 @@
 	regenerate_map_(disp.video(), _("Regenerate")),
 	generator_settings_(disp.video(), _("Settings...")),
 	password_button_(disp.video(), _("Set Password...")),
+	choose_mods_(disp.video(), _("Modifications...")),
 	era_combo_(disp, std::vector<std::string>()),
 	vision_combo_(disp, std::vector<std::string>()),
 	name_entry_(disp.video(), 32),
@@ -105,7 +109,8 @@
 	minimap_rect_(null_rect),
 	generator_(NULL),
 	num_turns_(0),
-	parameters_()
+	parameters_(),
+	dependency_manager_(cfg, disp.video())
 {
 	// Build the list of scenarios to play

@@ -126,6 +131,15 @@
 	{
 		menu_help_str = help_sep + user_maps_[i];
 		map_options_.push_back(user_maps_[i] + menu_help_str);
+
+		// Since user maps are treated as scenarios,
+		// some dependency info is required
+		config depinfo;
+
+		depinfo["id"] = user_maps_[i];
+		depinfo["name"] = user_maps_[i];
+
+		dependency_manager_.insert_element(depcheck::SCENARIO, depinfo, i);
 	}

 	// Standard maps
@@ -144,8 +158,10 @@

 	// Create the scenarios menu
 	maps_menu_.set_items(map_options_);
-	if (size_t(preferences::map()) < map_options_.size())
+	if (size_t(preferences::map()) < map_options_.size()) {
 		maps_menu_.move_selection(preferences::map());
+		dependency_manager_.try_scenario_by_index(preferences::map(), true);
+	}
 	maps_menu_.set_numeric_keypress_selection(false);

 	turns_slider_.set_min(settings::turns_min);
@@ -237,10 +253,24 @@
 	if (size_t(preferences::era()) < eras.size()) {
 		era_combo_.set_selected(preferences::era());
 	} else {
-		era_combo_.set_selected(0);
+		era_combo_.set_selected(preferences::era());
 	}
+
+	dependency_manager_.try_era_by_index(era_selection_, true);
+
+	// Available modifications
+	foreach (const config& mod, cfg.child_range("modification")) {
+		available_mods_.add_child("modification", mod);
+	}
+
+	foreach (const std::string& str, preferences::modifications()) {
+		if (cfg.find_child("modification", "id", str))
+			parameters_.active_mods.push_back(str);
+	}
+
+	dependency_manager_.try_modifications(parameters_.active_mods, true);
+

-
 	utils::string_map i18n_symbols;
 	i18n_symbols["login"] = preferences::login();
 	name_entry_.set_text(vgettext("$login|’s game", i18n_symbols));
@@ -270,8 +300,9 @@
 	preferences::set_countdown_turn_bonus(parameters_.mp_countdown_turn_bonus);
 	preferences::set_countdown_reservoir_time(parameters_.mp_countdown_reservoir_time);
 	preferences::set_countdown_action_bonus(parameters_.mp_countdown_action_bonus);
-	preferences::set_era(era_combo_.selected()); /** @todo FIXME: may be broken if new eras are added. */
+	preferences::set_era(era_selection_); /** @todo FIXME: may be broken if new eras are added. */
 	preferences::set_map(map_selection_);
+	preferences::set_modifications(parameters_.active_mods);

 	// When using map settings, the following variables are determined by the map,
 	// so don't store them as the new preferences.
@@ -373,6 +404,24 @@
 				, disp_.video());

 	}
+
+	if(choose_mods_.pressed()) {
+		if (available_mods_.empty()) {
+			gui2::show_transient_message(disp_.video(), "",
+			_(	"There are no modifications currently installed." \
+				" To download modifications, connect to the add-ons server" \
+				" by choosing the 'Add-ons' option on the main screen."		));
+		} else {
+
+			gui2::tmp_create_game_choose_mods
+						dialog(available_mods_, parameters_.active_mods);
+
+			dialog.show(disp_.video());
+
+			dependency_manager_.try_modifications(parameters_.active_mods);
+			synchronize_selections();
+		}
+	}

 	// Turns per game
 	const int cur_turns = turns_slider_.value();
@@ -445,9 +494,22 @@
 	buf << _("Experience modifier: ") << xpmod << "%";

 	xp_modifier_label_.set_text(buf.str());
+
+	bool era_changed = era_selection_ != era_combo_.selected();
+	era_selection_ = era_combo_.selected();
+
+	if (era_changed) {
+		dependency_manager_.try_era_by_index(era_selection_);
+		synchronize_selections();
+	}

 	bool map_changed = map_selection_ != maps_menu_.selection();
 	map_selection_ = maps_menu_.selection();
+
+	if (map_changed) {
+		dependency_manager_.try_scenario_by_index(map_selection_);
+		synchronize_selections();
+	}

 	if(map_changed) {
 		generator_.assign(NULL);
@@ -757,6 +819,8 @@
 	ypos += era_label_.height() + border_size;
 	era_combo_.set_location(xpos, ypos);
 	ypos += era_combo_.height() + border_size;
+	choose_mods_.set_location(xpos, ypos);
+	ypos += choose_mods_.height() + border_size;
 	if(!local_players_only_) {
 		password_button_.set_location(xpos, ypos);
 		ypos += password_button_.height() + border_size;
@@ -859,5 +923,20 @@
 	                          gui::ButtonHPadding, ca.y + ca.h - left_button->height());
 }

+void create::synchronize_selections()
+{
+	if (era_selection_ != dependency_manager_.get_era_index()) {
+		era_combo_.set_selected(dependency_manager_.get_era_index());
+		process_event();
+	}
+
+	if (map_selection_ != dependency_manager_.get_scenario_index()) {
+		maps_menu_.move_selection(dependency_manager_.get_scenario_index());
+		process_event();
+	}
+
+	parameters_.active_mods = dependency_manager_.get_modifications();
+}
+
 } // namespace mp

Index: src/multiplayer_lobby.cpp
===================================================================
--- src/multiplayer_lobby.cpp	(revision 54406)
+++ src/multiplayer_lobby.cpp	(working copy)
@@ -158,6 +158,9 @@
 		font_color = font::DISABLED_COLOR;
 		no_era_string = _(" (Unknown Era)");
 	}
+	if(!game.have_all_mods && font_color != font::BAD_COLOR) {
+		font_color = font::DISABLED_COLOR;
+	}

 	const surface status_text(font::get_rendered_text(game.status,
 	    font::SIZE_NORMAL, font_color));
@@ -178,7 +181,7 @@
 	}

 	// Second line
-	ypos = item_rect.y + item_rect.h/2;
+	ypos = item_rect.y + item_rect.h/3 + margin_;

 	// Draw map info
 	const surface map_info_surf(font::get_rendered_text(
@@ -188,8 +191,20 @@
 	if(map_info_surf) {
 		video().blit_surface(xpos, ypos - map_info_surf->h/2, map_info_surf);
 	}
+
+	// Third line
+	ypos = item_rect.y + 2*item_rect.h/3 - margin_;
+
+	// Draw modifications info
+	const surface mod_info_surf(font::get_rendered_text(
+	    font::make_text_ellipsis(game.mod_info, font::SIZE_NORMAL,
+	        (item_rect.x + item_rect.w) - xpos - margin_),
+		font::SIZE_NORMAL, font::NORMAL_COLOR));
+	if(mod_info_surf) {
+		video().blit_surface(xpos, ypos - mod_info_surf->h/2, mod_info_surf);
+	}

-	// Third line
+	// Fourth line
 	ypos = item_rect.y + item_rect.h  - margin_;

 	// Draw observer icon
@@ -524,6 +539,32 @@
 			games_.back().map_info += _("Unknown scenario");
 			verified = false;
 		}
+
+		games_.back().mod_info += "Modifications: ";
+
+		if (!game.child_or_empty("modification").empty()) {
+			games_.back().have_all_mods = true;
+			foreach (const config& m, game.child_range("modification")) {
+				const config& mod_cfg = game_config.find_child("modification", "id", m["id"]);
+				if (mod_cfg) {
+					games_.back().mod_info += mod_cfg["name"].str();
+					games_.back().mod_info += ", ";
+				} else {
+					games_.back().mod_info += m["id"].str();
+					if (m["require_modification"].to_bool(false)) {
+						games_.back().have_all_mods = false;
+						games_.back().mod_info += _(" (missing)");
+					}
+					games_.back().mod_info += ", ";
+				}
+			}
+			games_.back().mod_info.erase(games_.back().mod_info.size()-2, 2);
+		} else {
+			games_.back().mod_info += "none";
+			games_.back().have_all_mods = true;
+		}
+
+
 		if (games_.back().reloaded) {
 			games_.back().map_info += " — ";
 			games_.back().map_info += _("Reloaded game");
Index: src/mp_game_settings.cpp
===================================================================
--- src/mp_game_settings.cpp	(revision 54406)
+++ src/mp_game_settings.cpp	(working copy)
@@ -20,6 +20,7 @@
  */

 #include "mp_game_settings.hpp"
+#include "formula_string_utils.hpp"

 mp_game_settings::mp_game_settings() :
 	savegame_config(),
@@ -28,6 +29,7 @@
 	hash(),
 	mp_era(),
 	mp_scenario(),
+	active_mods(),
 	village_gold(0),
 	village_support(1),
 	xp_modifier(0),
@@ -56,6 +58,7 @@
 	hash(),
 	mp_era(),
 	mp_scenario(),
+	active_mods(),
 	village_gold(0),
 	village_support(1),
 	xp_modifier(0),
@@ -85,6 +88,7 @@
 	, hash(settings.hash)
 	, mp_era(settings.mp_era)
 	, mp_scenario(settings.mp_scenario)
+	, active_mods(settings.active_mods)
 	, village_gold(settings.village_gold)
 	, village_support(settings.village_support)
 	, xp_modifier(settings.xp_modifier)
@@ -116,6 +120,7 @@
 	hash = cfg["hash"].str();
 	mp_era = cfg["mp_era"].str();
 	mp_scenario = cfg["mp_scenario"].str();
+	active_mods = utils::split(cfg["active_mods"], ',');
 	xp_modifier = cfg["experience_modifier"];
 	use_map_settings = cfg["mp_use_map_settings"].to_bool();
 	fog_game = cfg["mp_fog"].to_bool();
@@ -139,6 +144,7 @@
 	hash = "";
 	mp_era = "";
 	mp_scenario = "";
+	active_mods.clear();
 	village_gold = 0;
 	village_support = 1;
 	xp_modifier = 0;
@@ -160,6 +166,7 @@
 	cfg["hash"] = hash;
 	cfg["mp_era"] = mp_era;
 	cfg["mp_scenario"] = mp_scenario;
+	cfg["active_mods"] = utils::join(active_mods, ",");
 	cfg["experience_modifier"] = xp_modifier;
 	cfg["mp_countdown"] = mp_countdown;
 	cfg["mp_countdown_init_time"] = mp_countdown_init_time;
Index: changelog
===================================================================
--- changelog	(revision 54406)
+++ changelog	(working copy)
@@ -147,6 +147,8 @@
    * Changes to the time of day schedules of Fallenstar Lake and Silverhead
      Crossing
    * Random leader is default selection when picking faction
+   * Added support for modification tags
+   * Added support for dependencies between eras, scenarios and modifications
  * Music and sound effects:
    * Replaced some of the wolf hit sounds with lower-pitched ones
  * Terrain:
