38 #include <boost/algorithm/string.hpp>
41 #define ERR_CF LOG_STREAM(err, log_config)
43 #define WRN_NG LOG_STREAM(warn, log_engine)
46 #define DBG_LB LOG_STREAM(info, log_lobby)
47 #define LOG_LB LOG_STREAM(info, log_lobby)
48 #define ERR_LB LOG_STREAM(err, log_lobby)
54 , forum_id(
c[
"forum_id"].to_int())
55 , game_id(
c[
"game_id"].to_int())
56 , registered(
c[
"registered"].to_bool())
57 , observing(
c[
"status"] ==
"observing")
58 , moderator(
c[
"moderator"].to_bool(false))
66 }
else if(
game_id == selected_game_id) {
89 const auto br =
b.get_relation();
95 const std::string& spaced_em_dash()
101 std::string make_game_type_marker(
const std::string& text,
bool color_for_missing)
103 if(color_for_missing) {
114 , 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();
269 if(
auto hashes =
game_config.optional_child(
"multiplayer_hashes")) {
270 std::string hash =
game[
"hash"];
271 bool hash_found =
false;
272 for(
const auto &
i : hashes->attribute_range()) {
273 if(
i.first ==
game[
"mp_scenario"] &&
i.second == hash) {
281 info_stream << spaced_em_dash();
282 info_stream <<
_(
"Remote scenario");
296 type_marker = make_game_type_marker(
_(
"scenario_abbreviation^S"),
true);
301 }
else if(!
game[
"mp_campaign"].empty()) {
302 if(
auto campaign_cfg =
game_config.find_child(
"campaign",
"id",
game[
"mp_campaign"])) {
303 type_marker = make_game_type_marker(
_(
"campaign_abbreviation^C"),
false);
305 std::stringstream campaign_text;
307 << campaign_cfg[
"name"] << spaced_em_dash()
308 <<
game[
"mp_scenario_name"];
313 if(difficulty[
"define"] ==
game[
"difficulty_define"]) {
314 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(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.
static const std::string br
std::string bold(Args &&... data)
std::string span_color(const color_t &color, Args &&... data)
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...