40 #include <boost/algorithm/string.hpp>
43 #define ERR_CF LOG_STREAM(err, log_config)
45 #define WRN_NG LOG_STREAM(warn, log_engine)
48 #define DBG_LB LOG_STREAM(info, log_lobby)
49 #define LOG_LB LOG_STREAM(info, log_lobby)
50 #define ERR_LB LOG_STREAM(err, log_lobby)
56 , forum_id(
c[
"forum_id"].to_int())
57 , game_id(
c[
"game_id"])
58 , registered(
c[
"registered"].to_bool())
59 , observing(
c[
"status"] ==
"observing")
60 , moderator(
c[
"moderator"].to_bool(false))
68 }
else if(
game_id == selected_game_id) {
91 const auto br =
b.get_relation();
97 const std::string& spaced_em_dash()
103 std::string make_game_type_marker(
const std::string& text,
bool color_for_missing)
105 if(color_for_missing) {
106 return formatter() <<
"<b><span color='#f00'>[" << text <<
"]</span></b> ";
108 return formatter() <<
"<b>[" << text <<
"]</b> ";
116 , map_data(
game[
"map_data"])
120 , remote_scenario(false)
124 , gold(
game[
"mp_village_gold"])
125 , support(
game[
"mp_village_support"])
126 , xp(
game[
"experience_modifier"].str() +
"%")
134 ,
fog(
game[
"mp_fog"].to_bool())
136 , observers(
game[
"observer"].to_bool(true))
139 , private_replay(
game[
"private_replay"].to_bool())
141 , password_required(
game[
"password"].to_bool())
143 , have_all_mods(true)
146 , auto_hosted(
game[
"auto_hosted"].to_bool())
154 for(
const config& addon :
game.child_range(
"addon")) {
155 if(addon.has_attribute(
"id") && addon[
"require"].to_bool(
false)) {
162 if(addon.has_attribute(
"name")) {
163 r.
message =
VGETTEXT(
"Missing addon: $name", {{
"name", addon[
"name"].str()}});
165 r.
message =
VGETTEXT(
"Missing addon: $id", {{
"id", addon[
"id"].str()}});
177 if(!
game[
"mp_era"].empty()) {
179 const bool require =
game[
"require_era"].to_bool(
true);
181 era = era_cfg[
"name"].str();
189 era =
game[
"mp_era_name"].str();
197 era =
_(
"Unknown era");
201 std::stringstream info_stream;
204 for(
const config& cfg :
game.child_range(
"modification")) {
205 mod_info.emplace_back(cfg[
"name"].str(),
true);
206 info_stream <<
' ' <<
mod_info.back().first;
208 if(cfg[
"require_modification"].to_bool(
false)) {
209 if(
auto mod =
game_config.find_child(
"modification",
"id", cfg[
"id"])) {
221 std::sort(
mod_info.begin(),
mod_info.end(), [](
const auto& lhs,
const auto& rhs) {
222 return translation::icompare(lhs.first, rhs.first) < 0;
232 info_stream <<
" — ??×??";
236 std::ostringstream msi;
243 ERR_CF <<
"map could not be loaded: " <<
e.dev_message;
253 if(!
game[
"mp_scenario"].empty() &&
game[
"mp_campaign"].empty()) {
256 const bool require =
game[
"require_scenario"].to_bool(
false);
260 level_cfg =
game_config.find_child(
"generic_multiplayer",
"id",
game[
"mp_scenario"]).ptr();
264 type_marker = make_game_type_marker(
_(
"scenario_abbreviation^S"),
false);
265 scenario = (*level_cfg)[
"name"].str();
271 if(
auto hashes =
game_config.optional_child(
"multiplayer_hashes")) {
272 std::string hash =
game[
"hash"];
273 bool hash_found =
false;
274 for(
const auto &
i : hashes->attribute_range()) {
275 if(
i.first ==
game[
"mp_scenario"] &&
i.second == hash) {
283 info_stream << spaced_em_dash();
284 info_stream <<
_(
"Remote scenario");
298 type_marker = make_game_type_marker(
_(
"scenario_abbreviation^S"),
true);
303 }
else if(!
game[
"mp_campaign"].empty()) {
304 if(
auto campaign_cfg =
game_config.find_child(
"campaign",
"id",
game[
"mp_campaign"])) {
305 type_marker = make_game_type_marker(
_(
"campaign_abbreviation^C"),
false);
307 std::stringstream campaign_text;
309 << campaign_cfg[
"name"] << spaced_em_dash()
310 <<
game[
"mp_scenario_name"];
315 if(difficulty[
"define"] ==
game[
"difficulty_define"]) {
316 campaign_text << spaced_em_dash() << difficulty[
"description"];
323 info_stream << campaign_text.rdbuf();
331 type_marker = make_game_type_marker(
_(
"campaign_abbreviation^C"),
true);
344 boost::erase_all(
name,
"\n");
350 info_stream << spaced_em_dash();
351 info_stream <<
_(
"Reloaded game");
357 const config&
s =
game.child_or_empty(
"slot_data");
358 const config&
t =
game.child_or_empty(
"turn_data");
368 status =
_(
"mp_game_available_slots^Full");
376 const int max_turns =
t[
"max"].to_int();
397 if(
game[
"mp_countdown"].to_bool()) {
399 <<
game[
"mp_countdown_init_time"].str() <<
"+"
400 <<
game[
"mp_countdown_turn_bonus"].str() <<
"/"
401 <<
game[
"mp_countdown_action_bonus"].str();
415 if(
auto game_req =
game.find_child(
"addon",
"id", local_item[
"addon_id"])) {
416 if(!game_req[
"require"].to_bool(
false)) {
423 const version_info local_ver(local_item[
"addon_version"].str());
424 version_info local_min_ver(local_item.
has_attribute(
"addon_min_version") ? local_item[
"addon_min_version"] : local_item[
"addon_version"]);
428 local_min_ver = std::min(local_min_ver, local_ver);
431 const version_info remote_ver(game_req[
"version"].str());
432 version_info remote_min_ver(game_req->has_attribute(
"min_version") ? game_req[
"min_version"] : game_req[
"version"]);
434 remote_min_ver = std::min(remote_min_ver, remote_ver);
437 if(local_min_ver > remote_ver) {
438 DBG_LB <<
"r.outcome = CANNOT_SATISFY for item='" << local_item[
"id"]
439 <<
"' addon='" << local_item[
"addon_id"]
440 <<
"' addon_min_version='" << local_item[
"addon_min_version"]
441 <<
"' addon_min_version_parsed='" << local_min_ver.
str()
442 <<
"' addon_version='" << local_item[
"addon_version"]
443 <<
"' remote_ver='" << remote_ver.
str()
447 r.message =
VGETTEXT(
"The host's version of <i>$addon</i> is incompatible. They have version <b>$host_ver</b> while you have version <b>$local_ver</b>.", {
448 {
"addon", local_item[
"addon_title"].str()},
449 {
"host_ver", remote_ver.
str()},
450 {
"local_ver", local_ver.
str()}
458 if(remote_min_ver > local_ver) {
461 r.message =
VGETTEXT(
"Your version of <i>$addon</i> is incompatible. You have version <b>$local_ver</b> while the host has version <b>$host_ver</b>.", {
462 {
"addon", local_item[
"addon_title"].str()},
463 {
"host_ver", remote_ver.
str()},
464 {
"local_ver", local_ver.
str()}
504 const std::string& s1 =
name;
506 return std::search(s1.begin(), s1.end(), filter.begin(), filter.end(),
508 || std::search(s2.begin(), s2.end(), filter.begin(), filter.end(),
std::vector< std::string > installed_addons()
Retrieves the names of all installed add-ons.
A config object defines a single node in a WML file, with access to child nodes.
bool has_attribute(config_key_type key) const
child_itors child_range(config_key_type key)
static game_config_manager * get()
const game_config_view & game_config() const
A class grating read only view to a vector of config objects, viewed as one config with all children ...
int w() const
Effective map width.
int h() const
Effective map height.
Encapsulates the map of the game.
Represents version numbers.
std::string str() const
Serializes the version number into string form.
Declarations for File-IO.
Interfaces for manipulating version numbers of engine, add-ons, etc.
static std::string _n(const char *str1, const char *str2, int n)
static std::string _(const char *str)
std::string id
Text to match against addon_info.tags()
New lexcical_cast header.
static lg::log_domain log_engine("engine")
static lg::log_domain log_lobby("lobby")
static lg::log_domain log_config("config")
Standard logging facilities (interface).
std::string read_map(const std::string &name)
Collection of helper functions relating to Pango formatting.
const std::string unicode_em_dash
const std::string unicode_multiplication_sign
std::string escape_text(const std::string &text)
Escapes the pango markup characters in a text.
Game configuration data as global variables.
config generate_difficulty_config(const config &source)
Helper function to convert old difficulty markup.
Main entry points of multiplayer mode.
bool logged_in_as_moderator()
Gets whether the currently logged-in user is a moderator.
bool is_ignored(const std::string &nick)
bool is_friend(const std::string &nick)
int icompare(const std::string &s1, const std::string &s2)
Case-insensitive lexicographical comparison.
bool chars_equal_insensitive(char a, char b)
std::vector< required_addon > required_addons
std::string map_size_info
addon_req check_addon_version_compatibility(const config &local_item, const config &game)
unsigned int current_turn
game_info(const config &c, const std::vector< std::string > &installed_addons)
disp_status display_status
const char * display_status_string() const
std::vector< std::pair< std::string, bool > > mod_info
List of modification names and whether they're installed or not.
bool match_string_filter(const std::string &filter) const
This class represents the information a client has about another player.
user_state get_state(int selected_game_id) const
user_relation get_relation() const
bool operator<(const user_info &b) const
user_info(const config &c)
The base template for associating string values with enum values.
Helper class, don't construct this directly.
static map_location::DIRECTION s
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...