Index: changelog
===================================================================
--- changelog	(revision 54671)
+++ changelog	(working copy)
@@ -157,6 +157,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:
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,220 @@
+#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"
+
+		[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"
+
+					[grid]
+
+						[row]
+
+							[column]
+
+								border = "all"
+								border_size = 5
+								horizontal_alignment = "right"
+
+								[button]
+									id = "ok"
+									definition = "default"
+
+									label = _ "OK"
+								[/button]
+							[/column]
+
+							[column]
+
+								border = "all"
+								border_size = 5
+								horizontal_alignment = "right"
+
+								[button]
+									id = "cancel"
+									definition = "default"
+
+									label = _ "Cancel"
+								[/button]
+
+							[/column]
+
+						[/row]
+
+					[/grid]
+
+				[/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,161 @@
+#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"
+
+		[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: 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,164 @@
+#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"
+
+		[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: src/mp_game_settings.hpp
===================================================================
--- src/mp_game_settings.hpp	(revision 54671)
+++ 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/multiplayer_connect.cpp
===================================================================
--- src/multiplayer_connect.cpp	(revision 54671)
+++ src/multiplayer_connect.cpp	(working copy)
@@ -1690,6 +1690,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_lobby.cpp
===================================================================
--- src/multiplayer_lobby.cpp	(revision 54671)
+++ src/multiplayer_lobby.cpp	(working copy)
@@ -159,6 +159,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));
@@ -179,7 +182,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(
@@ -191,6 +194,18 @@
 	}
 
 	// 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);
+	}
+
+	// Fourth line
 	ypos = item_rect.y + item_rect.h  - margin_;
 
 	// Draw observer icon
@@ -525,6 +540,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;
+			BOOST_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/server/simple_wml.hpp
===================================================================
--- src/server/simple_wml.hpp	(revision 54671)
+++ src/server/simple_wml.hpp	(working copy)
@@ -242,6 +242,10 @@
 		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/server/server.cpp
===================================================================
--- src/server/server.cpp	(revision 54671)
+++ 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 {
@@ -2425,6 +2426,14 @@
 			}
 		}
 
+		const simple_wml::node::child_list& mlist = data.children("modification");
+		BOOST_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);
 		// The host already put himself in the scenario so we just need
@@ -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/game_preferences.hpp
===================================================================
--- src/game_preferences.hpp	(revision 54671)
+++ src/game_preferences.hpp	(working copy)
@@ -23,6 +23,7 @@
 #include "preferences.hpp"
 
 #include <set>
+#include <vector>
 
 namespace preferences {
 
@@ -172,6 +173,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/mp_depcheck.cpp
===================================================================
--- src/mp_depcheck.cpp	(revision 0)
+++ src/mp_depcheck.cpp	(working copy)
@@ -0,0 +1,677 @@
+/*
+   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 "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_()
+{
+	BOOST_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);
+	}
+
+	BOOST_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);
+	}
+
+	BOOST_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
+{
+	BOOST_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);
+
+	BOOST_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;
+
+	BOOST_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;
+
+	BOOST_FOREACH(const std::string& mod, mods_) {
+		if (conflicts(elem(mod, "modification"), e))
+			result.push_back(mod);
+	}
+
+	return result;
+}
+
+bool manager::conflicts(const elem& elem1, const elem& elem2, bool directonly) const
+{
+	if (elem1 == elem2)
+		return false;
+
+	// We ignore inexistent elements at this point, they will generate
+	// errors in change_era()/change_scenario() anyways.
+	if (!exists(elem1) || !exists(elem2)) {
+		return false;
+	}
+
+	config data1 = depinfo_.find_child(elem1.type, "id", elem1.id);
+	config data2 = depinfo_.find_child(elem2.type, "id", elem2.id);
+
+	// Whether we should skip the check entirely
+	if (data1.has_attribute("ignore_incompatible_" + elem2.type)) {
+		std::vector<std::string> ignored =
+						utils::split(data1["ignore_incompatible_" + elem2.type]);
+
+		if (contains(ignored, elem2.id))
+			return false;
+	}
+
+	if (data2.has_attribute("ignore_incompatible_" + elem1.type)) {
+		std::vector<std::string> ignored =
+						utils::split(data2["ignore_incompatible_" + elem1.type]);
+
+		if (contains(ignored, elem1.id))
+			return false;
+	}
+
+	bool result = false;
+
+	// Checking for direct conflicts between elem1 and elem2
+	if (data1.has_attribute("allow_" + elem2.type)) {
+		std::vector<std::string> allowed =
+						utils::split(data1["allow_" + elem2.type]);
+
+		result = !contains(allowed, elem2.id) && !requires(elem1, elem2);
+	} else if (data1.has_attribute("disallow_" + elem2.type)) {
+		std::vector<std::string> disallowed =
+						utils::split(data1["disallow_" + elem2.type]);
+
+		result = contains(disallowed, elem2.id);
+	}
+
+	if (data2.has_attribute("allow_" + elem1.type)) {
+		std::vector<std::string> allowed =
+						utils::split(data2["allow_" + elem1.type]);
+
+		result = result || (!contains(allowed, elem1.id) && !requires(elem2, elem1));
+	} else if (data2.has_attribute("disallow_" + elem1.type)) {
+		std::vector<std::string> disallowed =
+						utils::split(data2["disallow_" + elem1.type]);
+
+		result = result || contains(disallowed, elem1.id);
+	}
+
+	if (result)
+		return true;
+
+	// Checking for indirect conflicts (i.e. conflicts between dependencies)
+	if (!directonly) {
+		std::vector<std::string>	req1 = get_required(elem1),
+									req2 = get_required(elem2);
+
+		BOOST_FOREACH (const std::string& s, req1) {
+			elem m(s, "modification");
+
+			if (conflicts(elem2, m, true))
+				return true;
+		}
+
+		BOOST_FOREACH (const std::string& s, req2) {
+			elem m(s, "modification");
+
+			if (conflicts(elem1, m, true))
+				return true;
+		}
+
+		BOOST_FOREACH (const std::string& id1, req1) {
+			elem m1(id1, "modification");
+
+			BOOST_FOREACH (const std::string& id2, req2) {
+				elem m2(id2, "modification");
+
+				if (conflicts(m1, m2)) {
+					return true;
+				}
+			}
+		}
+	}
+
+	return false;
+}
+
+
+bool manager::requires(const elem& elem1, const elem& elem2) const
+{
+	if (elem2.type != "modification")
+		return false;
+
+	config data = depinfo_.find_child(elem1.type, "id", elem1.id);
+
+	if (data.has_attribute("force_modification")) {
+		std::vector<std::string> required =
+							utils::split(data["force_modification"]);
+
+		return contains(required, elem2.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;
+
+	BOOST_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;
+
+	BOOST_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;
+	BOOST_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;
+	BOOST_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;
+	BOOST_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;
+	BOOST_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;
+	BOOST_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;
+	BOOST_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;
+
+	return change_era(era_);
+}
+
+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;
+	BOOST_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;
+	BOOST_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;
+
+	return change_scenario(scenario_);
+}
+
+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;
+	BOOST_FOREACH (const std::string& i, modifications) {
+		bool ok = true;
+		elem ei(i, "modification");
+		BOOST_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;
+	BOOST_FOREACH (const config& c, depinfo_.child_range("era")) {
+		elem era(c["id"], "era");
+		bool ok = true;
+		BOOST_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 {
+		if (!change_era(era_))
+			return false;
+	}
+
+	compatible.clear();
+
+	// Checking if the currently selected scenario is compatible with
+	// the set modifications, and changing scenario if necessary
+	BOOST_FOREACH (const config& c, depinfo_.child_range("scenario")) {
+		elem scen(c["id"], "scenario");
+		bool ok = true;
+		BOOST_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 {
+		if (!change_scenario(scenario_))
+			return false;
+	}
+
+	return true;
+}
+
+
+
+} //namespace depcheck
+
+} //namespace mp
Index: src/multiplayer_lobby.hpp
===================================================================
--- src/multiplayer_lobby.hpp	(revision 54671)
+++ 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/SConscript
===================================================================
--- src/SConscript	(revision 54671)
+++ 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
@@ -415,6 +418,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.cpp
===================================================================
--- src/multiplayer_create.cpp	(revision 54671)
+++ 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"
@@ -59,11 +60,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>()),
@@ -100,6 +103,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),
@@ -107,7 +111,8 @@
 	minimap_rect_(null_rect),
 	generator_(NULL),
 	num_turns_(0),
-	parameters_()
+	parameters_(),
+	dependency_manager_(cfg, disp.video())
 {
 	// Build the list of scenarios to play
 
@@ -128,6 +133,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
@@ -146,8 +160,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);
@@ -239,10 +255,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
+	BOOST_FOREACH (const config& mod, cfg.child_range("modification")) {
+		available_mods_.add_child("modification", mod);
+	}
+
+	BOOST_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));
@@ -272,8 +302,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.
@@ -375,6 +406,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();
 
@@ -447,9 +496,22 @@
 
 	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);
 
@@ -776,6 +838,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;
@@ -878,5 +942,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/mp_depcheck.hpp
===================================================================
--- src/mp_depcheck.hpp	(revision 0)
+++ src/mp_depcheck.hpp	(working copy)
@@ -0,0 +1,337 @@
+/*
+   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 the
+	 * 					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 elem1 			the first component
+	 * @param elem2 			the second component
+	 * @param directonly 		whether 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& elem1, const elem& elem2, bool directonly=false) const;
+
+	/**
+	 * Decides whether e1 requires e2
+	 * 
+	 * @param elem1 	a component; by definition, passing a modification here
+	 * 					makes no sense
+	 * @param elem2 	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& elem1, const elem& elem2) 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/mp_game_settings.cpp
===================================================================
--- src/mp_game_settings.cpp	(revision 54671)
+++ 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: src/play_controller.cpp
===================================================================
--- src/play_controller.cpp	(revision 54671)
+++ src/play_controller.cpp	(working copy)
@@ -271,11 +271,18 @@
 	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")) {
+		BOOST_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/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 [in]	the list of the currently activated modifications
+	 * @param result [out]	the list of all activated modifications
+	 */
+	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 reference 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,110 @@
+/*
+   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 can't 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);
+
+	BOOST_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/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,114 @@
+/*
+   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 "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 $
+ *
+ * -checkbox & & toggle_button & o &
+ * 		enable/disable a modification $
+ *
+ * -name & & label & o &
+ * 		displays the modification's name $
+ *
+ * -description & & label & o &
+ * 		displays the modification's description $
+ * 
+ * ok & & button & m &
+ * 		closes the dialog, applies changes $
+ *
+ * cancel & & button & m &
+ * 		closes the dialog, discards changes $
+ * 
+ * @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;
+
+	BOOST_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());
+	}
+
+}
+
+void tmp_create_game_choose_mods::post_show(twindow& /*window*/)
+{
+	if (get_retval() == twindow::OK) {
+		result_.clear();
+
+		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,77 @@
+/*
+   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)
+{
+	utils::string_map symbols;
+	symbols["requester"] = requester;
+	std::string message;
+	if (action) {
+		message = vgettext("$requester requires the following modifications to be enabled:", symbols);
+	} else {
+		message = vgettext("$requester requires the following modifications to be disabled:", symbols);
+	}
+
+	std::string list = "\t";
+	list += utils::join(mods, "\n\t");
+
+	register_label("message", false, message);
+
+	register_label("itemlist", false, list);
+}
+
+}
Index: src/CMakeLists.txt
===================================================================
--- src/CMakeLists.txt	(revision 54671)
+++ src/CMakeLists.txt	(working copy)
@@ -713,7 +713,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
@@ -734,6 +737,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 54671)
+++ 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/scripting/lua.cpp
===================================================================
--- src/scripting/lua.cpp	(revision 54671)
+++ src/scripting/lua.cpp	(working copy)
@@ -3852,9 +3852,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/game_preferences.cpp
===================================================================
--- src/game_preferences.cpp	(revision 54671)
+++ src/game_preferences.cpp	(working copy)
@@ -53,6 +53,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 = '@';
@@ -77,10 +81,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()
 {
@@ -694,6 +705,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);
