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())
152 for(
const config& addon :
game.child_range(
"addon")) {
153 if(addon.has_attribute(
"id") && addon[
"required"].to_bool(
false)) {
160 if(addon.has_attribute(
"name")) {
161 r.
message =
VGETTEXT(
"Missing addon: $name", {{
"name", addon[
"name"].str()}});
163 r.
message =
VGETTEXT(
"Missing addon: $id", {{
"id", addon[
"id"].str()}});
175 if(!
game[
"mp_era"].empty()) {
177 const bool require =
game[
"require_era"].to_bool(
true);
179 era = era_cfg[
"name"].str();
187 era =
game[
"mp_era_name"].str();
195 era =
_(
"Unknown era");
199 std::stringstream info_stream;
202 for(
const config& cfg :
game.child_range(
"modification")) {
203 mod_info.emplace_back(cfg[
"name"].str(),
true);
204 info_stream <<
' ' <<
mod_info.back().first;
206 if(cfg[
"require_modification"].to_bool(
true)) {
207 if(
auto mod =
game_config.find_child(
"modification",
"id", cfg[
"id"])) {
219 std::sort(
mod_info.begin(),
mod_info.end(), [](
const auto& lhs,
const auto& rhs) {
220 return translation::icompare(lhs.first, rhs.first) < 0;
230 info_stream <<
" — ??×??";
234 std::ostringstream msi;
241 ERR_CF <<
"map could not be loaded: " <<
e.dev_message;
251 if(!
game[
"mp_scenario"].empty() &&
game[
"mp_campaign"].empty()) {
254 const bool require =
game[
"require_scenario"].to_bool(
false);
258 level_cfg =
game_config.find_child(
"generic_multiplayer",
"id",
game[
"mp_scenario"]).ptr();
262 type_marker = make_game_type_marker(
_(
"scenario_abbreviation^S"),
false);
263 scenario = (*level_cfg)[
"name"].str();
270 if(
auto hashes =
game_config.optional_child(
"multiplayer_hashes")) {
271 std::string hash =
game[
"hash"];
272 bool hash_found =
false;
273 for(
const auto &
i : hashes->attribute_range()) {
274 if(
i.first ==
game[
"mp_scenario"] &&
i.second == hash) {
282 info_stream << spaced_em_dash();
283 info_stream <<
_(
"Remote scenario");
297 type_marker = make_game_type_marker(
_(
"scenario_abbreviation^S"),
true);
302 }
else if(!
game[
"mp_campaign"].empty()) {
303 if(
auto campaign_cfg =
game_config.find_child(
"campaign",
"id",
game[
"mp_campaign"])) {
304 type_marker = make_game_type_marker(
_(
"campaign_abbreviation^C"),
false);
306 std::stringstream campaign_text;
308 << campaign_cfg[
"name"] << spaced_em_dash()
309 <<
game[
"mp_scenario_name"];
313 if(difficulty[
"define"] ==
game[
"difficulty_define"]) {
314 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)
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.
constexpr std::string_view br
A Help markup tag corresponding to a linebreak.
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...