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"].to_int())
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) {
113 , map_data(
game[
"map_data"])
118 , remote_scenario(false)
122 , gold(
game[
"mp_village_gold"])
123 , support(
game[
"mp_village_support"])
124 , xp(
game[
"experience_modifier"].str() +
"%")
132 , fog(
game[
"mp_fog"].to_bool())
133 , shroud(
game[
"mp_shroud"].to_bool())
134 , observers(
game[
"observer"].to_bool(true))
135 , shuffle_sides(
game[
"shuffle_sides"].to_bool(true))
136 , use_map_settings(
game[
"mp_use_map_settings"].to_bool())
137 , private_replay(
game[
"private_replay"].to_bool())
139 , password_required(
game[
"password"].to_bool())
141 , have_all_mods(true)
144 , auto_hosted(
game[
"auto_hosted"].to_bool())
145 , game_preset(
game[
"game_preset"].to_bool())
153 for(
const config& addon :
game.child_range(
"addon")) {
154 if(addon.has_attribute(
"id") && addon[
"required"].to_bool(
false)) {
161 if(addon.has_attribute(
"name")) {
162 r.
message =
VGETTEXT(
"Missing addon: $name", {{
"name", addon[
"name"].str()}});
164 r.
message =
VGETTEXT(
"Missing addon: $id", {{
"id", addon[
"id"].str()}});
176 if(!
game[
"mp_era"].empty()) {
178 const bool require =
game[
"require_era"].to_bool(
true);
180 era = era_cfg[
"name"].str();
188 era =
game[
"mp_era_name"].str();
196 era =
_(
"Unknown era");
200 std::stringstream info_stream;
203 for(
const config& cfg :
game.child_range(
"modification")) {
204 mod_info.emplace_back(cfg[
"name"].str(),
true);
205 info_stream <<
' ' <<
mod_info.back().first;
207 if(cfg[
"require_modification"].to_bool(
true)) {
208 if(
auto mod =
game_config.find_child(
"modification",
"id", cfg[
"id"])) {
220 std::sort(
mod_info.begin(),
mod_info.end(), [](
const auto& lhs,
const auto& rhs) {
221 return translation::icompare(lhs.first, rhs.first) < 0;
231 info_stream <<
" — ??×??";
235 std::ostringstream msi;
242 ERR_CF <<
"map could not be loaded: " <<
e.dev_message;
252 if(!
game[
"mp_scenario"].empty() &&
game[
"mp_campaign"].empty()) {
255 const bool require =
game[
"require_scenario"].to_bool(
false);
259 level_cfg =
game_config.find_child(
"generic_multiplayer",
"id",
game[
"mp_scenario"]).ptr();
263 type_marker = make_game_type_marker(
_(
"scenario_abbreviation^S"),
false);
264 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"];
314 if(difficulty[
"define"] ==
game[
"difficulty_define"]) {
315 campaign_text << spaced_em_dash() << difficulty[
"description"];
321 info_stream << campaign_text.rdbuf();
329 type_marker = make_game_type_marker(
_(
"campaign_abbreviation^C"),
true);
342 boost::erase_all(
name,
"\n");
348 info_stream << spaced_em_dash();
349 info_stream <<
_(
"Reloaded game");
355 const config&
s =
game.child_or_empty(
"slot_data");
356 const config&
t =
game.child_or_empty(
"turn_data");
366 status =
_(
"mp_game_available_slots^Full");
374 const int max_turns =
t[
"max"].to_int();
395 if(
game[
"mp_countdown"].to_bool()) {
397 <<
game[
"mp_countdown_init_time"].str() <<
"+"
398 <<
game[
"mp_countdown_turn_bonus"].str() <<
"/"
399 <<
game[
"mp_countdown_action_bonus"].str();
413 if(
auto game_req =
game.find_child(
"addon",
"id", local_item[
"addon_id"])) {
414 if(!game_req[
"required"].to_bool(
false)) {
421 const version_info local_ver(local_item[
"addon_version"].str());
422 version_info local_min_ver(local_item.
has_attribute(
"addon_min_version") ? local_item[
"addon_min_version"] : local_item[
"addon_version"]);
426 local_min_ver = std::min(local_min_ver, local_ver);
429 const version_info remote_ver(game_req[
"version"].str());
430 version_info remote_min_ver(game_req->has_attribute(
"min_version") ? game_req[
"min_version"] : game_req[
"version"]);
432 remote_min_ver = std::min(remote_min_ver, remote_ver);
435 if(local_min_ver > remote_ver) {
436 DBG_LB <<
"r.outcome = CANNOT_SATISFY for item='" << local_item[
"id"]
437 <<
"' addon='" << local_item[
"addon_id"]
438 <<
"' addon_min_version='" << local_item[
"addon_min_version"]
439 <<
"' addon_min_version_parsed='" << local_min_ver.
str()
440 <<
"' addon_version='" << local_item[
"addon_version"]
441 <<
"' remote_ver='" << remote_ver.
str()
445 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>.", {
446 {
"addon", local_item[
"addon_title"].str()},
447 {
"host_ver", remote_ver.
str()},
448 {
"local_ver", local_ver.
str()}
456 if(remote_min_ver > local_ver) {
459 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>.", {
460 {
"addon", local_item[
"addon_title"].str()},
461 {
"host_ver", remote_ver.
str()},
462 {
"local_ver", local_ver.
str()}
502 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)
const std::string unicode_em_dash
const std::string unicode_multiplication_sign
std::string escape_text(std::string_view text)
Escapes the pango markup characters in a text.
Game configuration data as global variables.
std::string bold(Args &&... data)
Applies bold Pango markup to the input.
std::string span_color(const color_t &color, Args &&... data)
Applies Pango markup to the input specifying its display color.
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)
Case-insensitive search.
auto * find(Container &container, const Value &value)
Convenience wrapper for using find on a container without needing to comare to end()
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...