37 #include <boost/algorithm/string.hpp>
40 #define ERR_CF LOG_STREAM(err, log_config)
42 #define WRN_NG LOG_STREAM(warn, log_engine)
45 #define DBG_LB LOG_STREAM(info, log_lobby)
46 #define LOG_LB LOG_STREAM(info, log_lobby)
47 #define ERR_LB LOG_STREAM(err, log_lobby)
53 , forum_id(
c[
"forum_id"].to_int())
54 , game_id(
c[
"game_id"])
55 , registered(
c[
"registered"].to_bool())
56 , observing(
c[
"status"] ==
"observing")
57 , moderator(
c[
"moderator"].to_bool(false))
65 }
else if(
game_id == selected_game_id) {
88 const auto br =
b.get_relation();
94 const std::string& spaced_em_dash()
100 std::string make_game_type_marker(
const std::string& text,
bool color_for_missing)
102 if(color_for_missing) {
103 return formatter() <<
"<b><span color='#f00'>[" << text <<
"]</span></b> ";
105 return formatter() <<
"<b>[" << text <<
"]</b> ";
113 , map_data(
game[
"map_data"])
117 , remote_scenario(false)
121 , gold(
game[
"mp_village_gold"])
122 , support(
game[
"mp_village_support"])
123 , xp(
game[
"experience_modifier"].str() +
"%")
131 , fog(
game[
"mp_fog"].to_bool())
132 , shroud(
game[
"mp_shroud"].to_bool())
133 , observers(
game[
"observer"].to_bool(true))
134 , shuffle_sides(
game[
"shuffle_sides"].to_bool(true))
135 , use_map_settings(
game[
"mp_use_map_settings"].to_bool())
136 , private_replay(
game[
"private_replay"].to_bool())
138 , password_required(
game[
"password"].to_bool())
140 , have_all_mods(true)
143 , auto_hosted(
game[
"auto_hosted"].to_bool())
151 for(
const config& addon :
game.child_range(
"addon")) {
152 if(addon.has_attribute(
"id") && addon[
"required"].to_bool(
false)) {
159 if(addon.has_attribute(
"name")) {
160 r.
message =
VGETTEXT(
"Missing addon: $name", {{
"name", addon[
"name"].str()}});
162 r.
message =
VGETTEXT(
"Missing addon: $id", {{
"id", addon[
"id"].str()}});
174 if(!
game[
"mp_era"].empty()) {
176 const bool require =
game[
"require_era"].to_bool(
true);
178 era = era_cfg[
"name"].str();
186 era =
game[
"mp_era_name"].str();
194 era =
_(
"Unknown era");
198 std::stringstream info_stream;
201 for(
const config& cfg :
game.child_range(
"modification")) {
202 mod_info.emplace_back(cfg[
"name"].str(),
true);
203 info_stream <<
' ' <<
mod_info.back().first;
205 if(cfg[
"require_modification"].to_bool(
true)) {
206 if(
auto mod =
game_config.find_child(
"modification",
"id", cfg[
"id"])) {
218 std::sort(
mod_info.begin(),
mod_info.end(), [](
const auto& lhs,
const auto& rhs) {
219 return translation::icompare(lhs.first, rhs.first) < 0;
229 info_stream <<
" — ??×??";
233 std::ostringstream msi;
240 ERR_CF <<
"map could not be loaded: " <<
e.dev_message;
250 if(!
game[
"mp_scenario"].empty() &&
game[
"mp_campaign"].empty()) {
253 const bool require =
game[
"require_scenario"].to_bool(
false);
257 level_cfg =
game_config.find_child(
"generic_multiplayer",
"id",
game[
"mp_scenario"]).ptr();
261 type_marker = make_game_type_marker(
_(
"scenario_abbreviation^S"),
false);
262 scenario = (*level_cfg)[
"name"].str();
268 if(
auto hashes =
game_config.optional_child(
"multiplayer_hashes")) {
269 std::string hash =
game[
"hash"];
270 bool hash_found =
false;
271 for(
const auto &
i : hashes->attribute_range()) {
272 if(
i.first ==
game[
"mp_scenario"] &&
i.second == hash) {
280 info_stream << spaced_em_dash();
281 info_stream <<
_(
"Remote scenario");
295 type_marker = make_game_type_marker(
_(
"scenario_abbreviation^S"),
true);
300 }
else if(!
game[
"mp_campaign"].empty()) {
301 if(
auto campaign_cfg =
game_config.find_child(
"campaign",
"id",
game[
"mp_campaign"])) {
302 type_marker = make_game_type_marker(
_(
"campaign_abbreviation^C"),
false);
304 std::stringstream campaign_text;
306 << campaign_cfg[
"name"] << spaced_em_dash()
307 <<
game[
"mp_scenario_name"];
312 if(difficulty[
"define"] ==
game[
"difficulty_define"]) {
313 campaign_text << spaced_em_dash() << difficulty[
"description"];
320 info_stream << campaign_text.rdbuf();
328 type_marker = make_game_type_marker(
_(
"campaign_abbreviation^C"),
true);
341 boost::erase_all(
name,
"\n");
347 info_stream << spaced_em_dash();
348 info_stream <<
_(
"Reloaded game");
354 const config&
s =
game.child_or_empty(
"slot_data");
355 const config&
t =
game.child_or_empty(
"turn_data");
365 status =
_(
"mp_game_available_slots^Full");
373 const int max_turns =
t[
"max"].to_int();
394 if(
game[
"mp_countdown"].to_bool()) {
396 <<
game[
"mp_countdown_init_time"].str() <<
"+"
397 <<
game[
"mp_countdown_turn_bonus"].str() <<
"/"
398 <<
game[
"mp_countdown_action_bonus"].str();
412 if(
auto game_req =
game.find_child(
"addon",
"id", local_item[
"addon_id"])) {
413 if(!game_req[
"required"].to_bool(
false)) {
420 const version_info local_ver(local_item[
"addon_version"].str());
421 version_info local_min_ver(local_item.
has_attribute(
"addon_min_version") ? local_item[
"addon_min_version"] : local_item[
"addon_version"]);
425 local_min_ver = std::min(local_min_ver, local_ver);
428 const version_info remote_ver(game_req[
"version"].str());
429 version_info remote_min_ver(game_req->has_attribute(
"min_version") ? game_req[
"min_version"] : game_req[
"version"]);
431 remote_min_ver = std::min(remote_min_ver, remote_ver);
434 if(local_min_ver > remote_ver) {
435 DBG_LB <<
"r.outcome = CANNOT_SATISFY for item='" << local_item[
"id"]
436 <<
"' addon='" << local_item[
"addon_id"]
437 <<
"' addon_min_version='" << local_item[
"addon_min_version"]
438 <<
"' addon_min_version_parsed='" << local_min_ver.
str()
439 <<
"' addon_version='" << local_item[
"addon_version"]
440 <<
"' remote_ver='" << remote_ver.
str()
444 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>.", {
445 {
"addon", local_item[
"addon_title"].str()},
446 {
"host_ver", remote_ver.
str()},
447 {
"local_ver", local_ver.
str()}
455 if(remote_min_ver > local_ver) {
458 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>.", {
459 {
"addon", local_item[
"addon_title"].str()},
460 {
"host_ver", remote_ver.
str()},
461 {
"local_ver", local_ver.
str()}
501 const std::string& s1 =
name;
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.
Definitions for the interface to Wesnoth Markup Language (WML).
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()
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.
int icompare(const std::string &s1, const std::string &s2)
Case-insensitive lexicographical comparison.
bool ci_search(const std::string &s1, const std::string &s2)
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...