Index: src/mp_depcheck.hpp
===================================================================
--- src/mp_depcheck.hpp	(revision 0)
+++ src/mp_depcheck.hpp	(revision 0)
@@ -0,0 +1,178 @@
+/*
+   Copyright (C) 2012 by David White <dave@whitevine.net>
+   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
+{
+
+/**
+ * Note to all setters:
+ * 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 setter.
+ * 
+ * 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);
+	
+	/**
+	 * Sets the selected era
+	 * @param id the id of the era
+	 * @param force whether to skip dependency check
+	 */
+	void set_era(const std::string& id, bool force = false);
+	
+	/**
+	 * Sets the selected scenario
+	 * @param id the id of the scenario
+	 * @param force whether to skip dependency check
+	 */
+	void set_scenario(const std::string& id, bool force = false);
+	
+	/**
+	 * Sets the enabled modifications
+	 * @param ids the ids of the modifications
+	 * @param force whether to skip dependency check
+	 */
+	void set_modifications(const std::vector<std::string>& ids, bool force = false);
+	
+	/**
+	 * Sets the selected era
+	 * @param index the index of the era
+	 * @param force whether to skip dependency check
+	 */
+	void set_era_by_index(int index, bool force = false);
+	
+	/**
+	 * Sets the selected scenario
+	 * @param index the index of the scenario
+	 * @param force whether to skip dependency check
+	 */
+	void set_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 (recognized values are "era", "scenario" and "modification"
+	 * @param data a config object containing the dependency info for element
+	 * @param index where to insert the element
+	 */
+	void insert_element(const std::string& type, const config& data, int index = 0);
+
+private:
+
+	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); }
+	};
+
+	CVideo& video_;
+	config depinfo_;
+	
+	//data members
+	std::string era_;
+	std::string scenario_;
+	std::vector<std::string> mods_;
+	
+	//used by save_state() and revert()
+	std::string prev_era_;
+	std::string prev_scenario_;
+	std::vector<std::string> prev_mods_;
+	
+	void save_state();
+	void revert();
+	
+	bool change_scenario(const std::string& id);
+	bool change_era(const std::string& id);
+	bool change_modifications(const std::vector<std::string>& modifications);
+	
+	bool conflicts(const elem& e1, const elem& e2, bool directonly=false) const;
+	bool requires(const elem& e1, const elem& e2) const;
+	
+	std::vector<std::string> get_required(const elem& e) const;
+	std::vector<std::string> get_required_not_enabled(const elem& e) const;
+	std::vector<std::string> get_conflicting_enabled(const elem& e) const;
+	std::vector<std::string> get_required_not_installed(const elem& e) const;
+	
+	bool enable_mods_dialog(const std::vector<std::string>& mods);
+	bool disable_mods_dialog(const std::vector<std::string>& mods);
+	std::string change_era_dialog(const std::vector<std::string>& eras);
+	std::string change_scenario_dialog(const std::vector<std::string>& scenarios);
+	void failure_dialog(const std::string& msg);
+		
+	bool contains(const std::vector<std::string>& container, const std::string& value) const;
+	bool exists(const elem& e) const;
+	
+};
+
+} //namespace depcheck
+
+} //namespace mp
+
+
+#endif
Index: src/mp_game_settings.cpp
===================================================================
--- src/mp_game_settings.cpp	(revision 54332)
+++ 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/multiplayer_create.hpp
===================================================================
--- src/multiplayer_create.hpp	(revision 54332)
+++ 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/game_preferences.hpp
===================================================================
--- src/game_preferences.hpp	(revision 54332)
+++ 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/play_controller.cpp
===================================================================
--- src/play_controller.cpp	(revision 54332)
+++ src/play_controller.cpp	(working copy)
@@ -270,10 +270,16 @@
 	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/multiplayer_connect.cpp
===================================================================
--- src/multiplayer_connect.cpp	(revision 54332)
+++ src/multiplayer_connect.cpp	(working copy)
@@ -1689,6 +1689,13 @@
 		}
 		level_.add_child("era", era_cfg);
 	}
+	
+	// Add modifications
+	// TODO: implement error handling
+	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/mp_depcheck.cpp
===================================================================
--- src/mp_depcheck.cpp	(revision 0)
+++ src/mp_depcheck.cpp	(revision 0)
@@ -0,0 +1,598 @@
+/*
+   Copyright (C) 2012 by David White <dave@whitevine.net>
+   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 mp
+{
+
+namespace depcheck
+{
+
+//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_scenario")) {
+		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];
+		}
+	}
+}
+	
+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::contains(const std::vector<std::string>& container, const std::string& value) const
+{
+	return std::find(container.begin(), container.end(), value) != container.end();		
+}
+
+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;
+	
+	config data1 = depinfo_.find_child(e1.type, "id", e1.id);
+	config data2 = depinfo_.find_child(e2.type, "id", e2.id);
+	
+	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;
+	
+	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;
+	
+	if (!directonly) {
+		std::vector<std::string>	req1 = get_required(e1),
+									req2 = get_required(e2);
+		
+		foreach (const std::string& s, req1)
+			if (conflicts(e2, elem(s, "modification"), true))
+				return true;
+		
+		foreach (const std::string& s, req2)
+			if (conflicts(e1, elem(s, "modification"), true))
+				return true;
+		
+		foreach (const std::string& l, req1) {
+			foreach (const std::string& k, req2) {
+				if (conflicts(elem(l, "modification"), elem(k, "modification"))) {
+					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::set_era(const std::string& id, bool force)
+{	
+	save_state();
+	
+	if (force)
+		era_ = id;
+	else if (!change_era(id))
+		revert();
+		
+}
+
+void manager::set_scenario(const std::string& id, bool force)
+{	
+	save_state();
+	
+	if (force)
+		scenario_ = id;
+	else if (!change_scenario(id))
+		revert();
+}
+
+void manager::set_modifications(const std::vector<std::string>& ids, bool force)
+{		
+	save_state();
+	
+	if (force)
+		mods_ = ids;
+	else if (!change_modifications(ids))
+		revert();
+}
+
+void manager::set_era_by_index(int index, bool force)
+{
+	set_era(depinfo_.child("era", index)["id"], force);
+}
+
+void manager::set_scenario_by_index(int index, bool force)
+{
+	set_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(const std::string &type, const config& data, int index)
+{
+	depinfo_.add_child_at(type, data, index);
+}
+
+bool manager::change_scenario(const std::string& id)
+{
+	if (!get_required_not_installed(elem(id, "scenario")).empty()) {
+		failure_dialog("Scenario can't be activated. Some dependencies are missing.");
+		return false;
+	}
+	
+	scenario_ = id;
+	
+	elem scen = elem(id, "scenario");
+	
+	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;
+	
+	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)
+{
+	if (!get_required_not_installed(elem(id, "era")).empty()) {
+		failure_dialog("Era can't be activated. Some dependencies are missing.");
+		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);
+	
+	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;
+	
+	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)
+{
+	
+	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;
+	
+	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();
+	
+	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/multiplayer_lobby.hpp
===================================================================
--- src/multiplayer_lobby.hpp	(revision 54332)
+++ 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 54332)
+++ src/SConscript	(working copy)
@@ -354,7 +354,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
@@ -413,6 +416,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 54332)
+++ 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(), _("Choose 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,14 @@
 	{
 		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("scenario", depinfo, i);
 	}
 
 	// Standard maps
@@ -144,8 +157,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_.set_scenario_by_index(preferences::map(), true);
+	}
 	maps_menu_.set_numeric_keypress_selection(false);
 
 	turns_slider_.set_min(settings::turns_min);
@@ -237,10 +252,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_.set_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_.set_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 +299,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 +403,14 @@
 				, disp_.video());
 
 	}
+	
+	if(choose_mods_.pressed()) {
+		gui2::tmp_create_game_choose_mods dialog(available_mods_, parameters_.active_mods);
+		dialog.show(disp_.video());
+		
+		dependency_manager_.set_modifications(parameters_.active_mods);
+		synchronize_selections();
+	}
 
 	// Turns per game
 	const int cur_turns = turns_slider_.value();
@@ -445,9 +483,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_.set_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_.set_scenario_by_index(map_selection_);
+		synchronize_selections();
+	}
 
 	if(map_changed) {
 		generator_.assign(NULL);
@@ -757,6 +808,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 +912,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/game_preferences.cpp
===================================================================
--- src/game_preferences.cpp	(revision 54332)
+++ 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 = '@';
@@ -693,6 +697,26 @@
 	preferences::set("mp_map", value);
 }
 
+void initialize_modifications()
+{
+	mp_modifications = utils::split(preferences::get("modifications"), ',');
+	modifications_initialized = true;
+}
+
+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/scripting/lua.cpp
===================================================================
--- src/scripting/lua.cpp	(revision 54332)
+++ src/scripting/lua.cpp	(working copy)
@@ -3809,7 +3809,7 @@
 
 static char const *handled_file_tags[] = {
 	"color_palette", "color_range", "era", "event", "generator",
-	"label", "lua", "map", "menu_item", "music", "side", "sound_source", "story",
+	"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
Index: src/server/server.cpp
===================================================================
--- src/server/server.cpp	(revision 54332)
+++ 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 54332)
+++ 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/CMakeLists.txt
===================================================================
--- src/CMakeLists.txt	(revision 54332)
+++ src/CMakeLists.txt	(working copy)
@@ -510,7 +510,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
@@ -569,6 +572,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/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	(revision 0)
@@ -0,0 +1,85 @@
+/*
+   Copyright (C) 2010 - 2012
+   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"
+
+namespace gui2 {
+
+/*WIKI
+ * @page = GUIWindowDefinitionWML
+ * @order = 2_mp_create_game_choose_mods
+ *
+ * == Create Game: Choose Modifications ==
+ *
+ * The dialog for selecting modifications.
+ *
+ */
+
+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_select_new.hpp
===================================================================
--- src/gui/dialogs/mp_depcheck_select_new.hpp	(revision 0)
+++ src/gui/dialogs/mp_depcheck_select_new.hpp	(revision 0)
@@ -0,0 +1,47 @@
+/*
+   Copyright (C) 2012
+   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 <vector>
+#include <string>
+
+namespace gui2
+{
+
+class tmp_depcheck_select_new
+		: public tdialog
+{
+public:
+	tmp_depcheck_select_new(const std::string& name, const std::vector<std::string>& options);
+	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);
+	
+	virtual void post_show(twindow& window);
+
+private:
+	std::vector<std::string> items_;
+	int result_;
+};
+
+}
+#endif
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	(revision 0)
@@ -0,0 +1,55 @@
+/*
+   Copyright (C) 2012
+   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
+ */
+
+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	(revision 0)
@@ -0,0 +1,52 @@
+/*
+   Copyright (C) 2008 - 2012
+   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:
+
+	explicit 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);
+	void post_show(twindow &window);
+
+	std::vector<std::string> *result_;
+	const config& game_cfg_;
+	
+	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	(revision 0)
@@ -0,0 +1,75 @@
+/*
+   Copyright (C) 2012
+   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.
+ * 
+ */
+
+REGISTER_DIALOG(mp_depcheck_select_new)
+
+tmp_depcheck_select_new::tmp_depcheck_select_new
+		(const std::string& name, const std::vector<std::string>& items)
+	: items_(items)
+	, result_(-1)
+{
+	std::string message = _("The currently chosen ");
+	message += name;
+	message += _(" 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	(revision 0)
@@ -0,0 +1,43 @@
+/*
+   Copyright (C) 2012
+   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:
+
+	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/mp_game_settings.hpp
===================================================================
--- src/mp_game_settings.hpp	(revision 54332)
+++ 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_lobby.cpp
===================================================================
--- src/multiplayer_lobby.cpp	(revision 54332)
+++ 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/revision.hpp
===================================================================
--- src/revision.hpp	(revision 0)
+++ src/revision.hpp	(revision 0)
@@ -0,0 +1 @@
+#define REVISION "54332M"
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	(revision 0)
@@ -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
+
+		[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]
+						id = "title"
+						definition = "title"
+
+						label = _ "Choose Modifications"
+					[/label]
+
+				[/column]
+
+			[/row]
+
+			[row]
+				grow_factor = 0
+
+				[column]
+
+					border = "all"
+					border_size = 5
+					horizontal_alignment = "left"
+					[scroll_label]
+						id = "message"
+						definition = "default"
+
+						label = _ "Enable the modifications you want to be applied to the match."
+					[/scroll_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 = _ "Done"
+						return_value = "0"
+					[/button]
+				[/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	(revision 0)
@@ -0,0 +1,166 @@
+#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 = 1
+								
+								border = "all"
+								border_size = 5
+								horizontal_alignment = "right"
+								
+								[button]
+									id = "cancel"
+									label = _ "Cancel"
+								[/button]
+							
+							[/column]
+							
+							[column]
+								grow_factor = 0
+								
+								border = "all"
+								border_size = 5
+								horizontal_alignment = "center"
+								
+								[button]
+									id = "ok"
+									label = _ "OK"
+								[/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	(revision 0)
@@ -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 = 1
+								
+								border = "all"
+								border_size = 5
+								horizontal_alignment = "right"
+								
+								[button]
+									id = "cancel"
+									label = _ "No"
+								[/button]
+							
+							[/column]
+							
+							[column]
+								grow_factor = 0
+								
+								border = "all"
+								border_size = 5
+								horizontal_alignment = "center"
+								
+								[button]
+									id = "ok"
+									label = _ "Yes"
+								[/button]
+							
+							[/column]
+						
+						[/row]
+						
+					[/grid]
+				
+				[/column]
+			
+			[/row]
+		
+		[/grid]
+	
+	[/resolution]
+
+[/window]
