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) {
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())
135 ,
shroud(game[
"mp_shroud"].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())
155 if(addon.has_attribute(
"id") && addon[
"require"].to_bool(
false)) {
156 if(std::find(installed_addons.begin(), installed_addons.end(), addon[
"id"].str()) == installed_addons.end()) {
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()) {
178 const config& era_cfg = game_config.
find_child(
"era",
"id", game[
"mp_era"]);
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;
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(
const config& mod = game_config.
find_child(
"modification",
"id", cfg[
"id"])) {
221 std::sort(
mod_info.begin(),
mod_info.end(), [](
const auto& lhs,
const auto& rhs) {
232 info_stream <<
" — ??×??";
236 std::ostringstream msi;
253 if(!game[
"mp_scenario"].empty() && game[
"mp_campaign"].empty()) {
255 const config* level_cfg = &game_config.
find_child(
"multiplayer",
"id", game[
"mp_scenario"]);
256 const bool require = game[
"require_scenario"].to_bool(
false);
260 level_cfg = &game_config.
find_child(
"generic_multiplayer",
"id", game[
"mp_scenario"]);
264 type_marker = make_game_type_marker(
_(
"scenario_abbreviation^S"),
false);
265 scenario = (*level_cfg)[
"name"].str();
271 if(
const config& hashes = game_config.
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);
299 scenario = game[
"mp_scenario_name"].str();
303 }
else if(!game[
"mp_campaign"].empty()) {
304 if(
const config& 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);
332 scenario = game[
"mp_campaign_name"].str();
344 boost::erase_all(
name,
"\n");
350 info_stream << spaced_em_dash();
351 info_stream <<
_(
"Reloaded game");
368 status =
_(
"mp_game_available_slots^Full");
376 const int max_turns = t[
"max"].to_int();
379 status =
formatter() <<
_(
"Turn") <<
" " << t[
"current"] <<
"/" << max_turns;
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(
const config& 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::string map_size_info
static std::string _n(const char *str1, const char *str2, int n)
Interfaces for manipulating version numbers of engine, add-ons, etc.
std::vector< std::pair< std::string, bool > > mod_info
List of modification names and whether they're installed or not.
Collection of helper functions relating to Pango formatting.
unsigned int current_turn
config & find_child(config_key_type key, const std::string &name, const std::string &value)
Returns the first child of tag key with a name attribute containing value.
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
New lexcical_cast header.
bool has_attribute(config_key_type key) const
child_itors child_range(config_key_type key)
user_state get_state(int selected_game_id) const
bool chars_equal_insensitive(char a, char b)
static std::string _(const char *str)
Definitions for the interface to Wesnoth Markup Language (WML).
bool logged_in_as_moderator()
Gets whether the currently logged-in user is a moderator.
static lg::log_domain log_lobby("lobby")
Main entry points of multiplayer mode.
static game_config_manager * get()
user_info(const config &c)
bool is_friend(const std::string &nick)
int w() const
Effective map width.
user_relation get_relation() const
The base template for associating string values with enum values.
const game_config_view & game_config() const
const std::string unicode_multiplication_sign
Encapsulates the map of the game.
static lg::log_domain log_config("config")
disp_status display_status
std::vector< std::string > installed_addons()
Retrieves the names of all installed add-ons.
bool is_ignored(const std::string &nick)
std::string read_map(const std::string &name)
Helper class, don't construct this directly.
std::string dev_message
The message for developers telling which problem was triggered, this shouldn't be translated...
std::string id
Text to match against addon_info.tags()
std::string escape_text(const std::string &text)
Escapes the pango markup characters in a text.
const char * display_status_string() const
static lg::log_domain log_engine("engine")
config generate_difficulty_config(const config &source)
Helper function to convert old difficulty markup.
Game configuration data as global variables.
static map_location::DIRECTION s
addon_req check_addon_version_compatibility(const config &local_item, const config &game)
Declarations for File-IO.
Represents version numbers.
const config & find_child(config_key_type key, const std::string &name, const std::string &value) const
This class represents the information a client has about another player.
int icompare(const std::string &s1, const std::string &s2)
Case-insensitive lexicographical comparison.
const std::string unicode_em_dash
Standard logging facilities (interface).
std::string str() const
Serializes the version number into string form.
std::vector< required_addon > required_addons
game_info(const config &c, const std::vector< std::string > &installed_addons)
const config & child_or_empty(config_key_type key) const
Returns the first child with the given key, or an empty config if there is none.
A config object defines a single node in a WML file, with access to child nodes.
int h() const
Effective map height.
bool operator<(const user_info &b) const
const config & child(config_key_type key) const
bool match_string_filter(const std::string &filter) const