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) 53 const std::string& user,
54 const std::string& message)
55 : timestamp(timestamp), user(user), message(message)
64 const std::string& user,
65 const std::string& message)
67 history_.emplace_back(timestamp, user, message);
111 , game_id(c[
"game_id"])
113 , state(game_id == 0 ? LOBBY : GAME)
114 , registered(c[
"registered"].to_bool())
115 , observing(c[
"status"] ==
"observing")
124 if(
game_id == selected_game_id) {
130 if(current_room !=
nullptr && current_room->
is_member(
name)) {
159 const std::string& spaced_em_dash()
165 std::string make_game_type_marker(
const std::string& text,
bool color_for_missing)
167 if(color_for_missing) {
168 return formatter() <<
"<b><span color='#f00'>[" << text <<
"]</span></b> ";
170 return formatter() <<
"<b>[" << text <<
"]</b> ";
178 , map_data(game[
"map_data"])
181 , remote_scenario(false)
185 , gold(game[
"mp_village_gold"])
186 , support(game[
"mp_village_support"])
187 , xp(game[
"experience_modifier"].str() +
"%")
195 ,
fog(game[
"mp_fog"].to_bool())
196 ,
shroud(game[
"mp_shroud"].to_bool())
197 , observers(game[
"observer"].to_bool(true))
201 , private_replay(game[
"private_replay"].to_bool())
203 , password_required(game[
"password"].to_bool())
205 , have_all_mods(true)
208 , display_status(NEW)
210 , addons_outcome(SATISFIED)
216 if(addon.has_attribute(
"id")) {
217 if(
std::find(installed_addons.begin(), installed_addons.end(), addon[
"id"].str()) == installed_addons.end()) {
223 if(addon.has_attribute(
"name")) {
224 r.
message =
VGETTEXT(
"Missing addon: $name", {{
"name", addon[
"name"].str()}});
226 r.
message =
VGETTEXT(
"Missing addon: $id", {{
"id", addon[
"id"].str()}});
238 if(!game[
"mp_era"].empty()) {
239 const config& era_cfg = game_config.
find_child(
"era",
"id", game[
"mp_era"]);
240 const bool require = game[
"require_era"].to_bool(
true);
242 era = era_cfg[
"name"].str();
250 era = game[
"mp_era_name"].str();
258 era =
_(
"Unknown era");
262 std::stringstream info_stream;
266 mod_info.emplace_back(cfg[
"name"].str(),
true);
267 info_stream <<
' ' <<
mod_info.back().first;
269 if(cfg[
"require_modification"].to_bool(
false)) {
270 if(
const config& mod = game_config.
find_child(
"modification",
"id", cfg[
"id"])) {
293 info_stream <<
" — ??×??";
296 gamemap map(std::make_shared<terrain_type_data>(game_config),
map_data);
297 std::ostringstream msi;
314 if(!game[
"mp_scenario"].empty() && game[
"mp_campaign"].empty()) {
316 const config* level_cfg = &game_config.
find_child(
"multiplayer",
"id", game[
"mp_scenario"]);
317 const bool require = game[
"require_scenario"].to_bool(
false);
321 level_cfg = &game_config.
find_child(
"generic_multiplayer",
"id", game[
"mp_scenario"]);
325 scenario =
formatter() << make_game_type_marker(
_(
"scenario_abbreviation^S"),
false) << (*level_cfg)[
"name"].
str();
331 if(
const config& hashes = game_config.
child(
"multiplayer_hashes")) {
332 std::string hash = game[
"hash"];
333 bool hash_found =
false;
334 for(
const auto &
i : hashes.attribute_range()) {
335 if(
i.first == game[
"mp_scenario"] &&
i.second == hash) {
343 info_stream << spaced_em_dash();
344 info_stream <<
_(
"Remote scenario");
358 scenario =
formatter() << make_game_type_marker(
_(
"scenario_abbreviation^S"),
true) << game[
"mp_scenario_name"].str();
362 }
else if(!game[
"mp_campaign"].empty()) {
363 if(
const config& campaign_cfg = game_config.
find_child(
"campaign",
"id", game[
"mp_campaign"])) {
364 std::stringstream campaign_text;
366 << make_game_type_marker(
_(
"campaign_abbreviation^C"),
false)
367 << campaign_cfg[
"name"] << spaced_em_dash()
368 << game[
"mp_scenario_name"];
373 if(difficulty[
"define"] == game[
"difficulty_define"]) {
374 campaign_text << spaced_em_dash() << difficulty[
"description"];
381 info_stream << campaign_text.rdbuf();
389 scenario =
formatter() << make_game_type_marker(
_(
"campaign_abbreviation^C"),
true) << game[
"mp_campaign_name"].str();
403 info_stream << spaced_em_dash();
404 info_stream <<
_(
"Reloaded game");
421 status =
_(
"mp_game_available_slots^Full");
429 const int max_turns = t[
"max"].to_int();
432 status =
formatter() <<
_(
"Turn") <<
" " << t[
"current"] <<
"/" << max_turns;
450 if(game[
"mp_countdown"].to_bool()) {
452 << game[
"mp_countdown_init_time"].str() <<
"+" 453 << game[
"mp_countdown_turn_bonus"].str() <<
"/" 454 << game[
"mp_countdown_action_bonus"].str();
468 if(
const config& game_req = game.
find_child(
"addon",
"id", local_item[
"addon_id"])) {
472 const version_info local_ver(local_item[
"addon_version"].str());
473 version_info local_min_ver(local_item.
has_attribute(
"addon_min_version") ? local_item[
"addon_min_version"] : local_item[
"addon_version"]);
477 local_min_ver = std::min(local_min_ver, local_ver);
480 const version_info remote_ver(game_req[
"version"].str());
481 version_info remote_min_ver(game_req.has_attribute(
"min_version") ? game_req[
"min_version"] : game_req[
"version"]);
483 remote_min_ver = std::min(remote_min_ver, remote_ver);
486 if(local_min_ver > remote_ver) {
487 DBG_LB <<
"r.outcome = CANNOT_SATISFY for item='" << local_item[
"id"]
488 <<
"' addon='" << local_item[
"addon_id"]
489 <<
"' addon_min_version='" << local_item[
"addon_min_version"]
490 <<
"' addon_min_version_parsed='" << local_min_ver.str()
491 <<
"' addon_version='" << local_item[
"addon_version"]
492 <<
"' remote_ver='" << remote_ver.
str()
496 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>.", {
497 {
"addon", local_item[
"addon_title"].str()},
498 {
"host_ver", remote_ver.
str()},
499 {
"local_ver", local_ver.
str()}
507 if(remote_min_ver > local_ver) {
510 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>.", {
511 {
"addon", local_item[
"addon_title"].str()},
512 {
"host_ver", remote_ver.
str()},
513 {
"local_ver", local_ver.
str()}
553 const std::string& s1 =
name;
555 return std::search(s1.begin(), s1.end(), filter.begin(), filter.end(),
557 || std::search(s2.begin(), s2.end(), filter.begin(), filter.end(),
std::string map_size_info
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
void add_message(const std::time_t ×tamp, const std::string &user, const std::string &message)
int h() const
Effective map height, in hexes.
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.
Note: Specific to sdl_ttf.
unsigned int current_turn
std::deque< chat_message > history_
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)
std::set< std::string > members_
bool chars_equal_insensitive(char a, char b)
Definitions for the interface to Wesnoth Markup Language (WML).
static lg::log_domain log_lobby("lobby")
Pubic entry points for the MP workflow.
static game_config_manager * get()
user_info(const config &c)
static UNUSEDNOWARN std::string _(const char *str)
chat_message(const std::time_t ×tamp, const std::string &user, const std::string &message)
Create a chat message.
bool is_friend(const std::string &nick)
const std::string unicode_multiplication_sign
Encapsulates the map of the game.
static UNUSEDNOWARN std::string _n(const char *str1, const char *str2, int n)
static lg::log_domain log_config("config")
std::vector< std::string > installed_addons()
Retrieves the names of all installed add-ons.
bool is_member(const std::string &user) const
bool registered_users_only()
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...
int w() const
Effective map width, in hexes.
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")
Default, unset return value.
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)
This class represents the information a client has about a room.
Declarations for File-IO.
static int sort(lua_State *L)
Represents version numbers.
This class represents the information a client has about another player.
void update_state(int selected_game_id, const room_info *current_room=nullptr)
room_info(const std::string &name)
bool find(E event, F functor)
Tests whether an event handler is available.
int icompare(const std::string &s1, const std::string &s2)
Case-insensitive lexicographical comparison.
const std::string unicode_em_dash
void remove_member(const std::string &user)
Standard logging facilities (interface).
std::string str() const
Serializes the version number into string form.
game_display_status display_status
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.
bool operator<(const user_info &b) const
const config & game_config() const
void process_room_members(const config &data)
bool match_string_filter(const std::string &filter) const
const std::string & name() const
void add_member(const std::string &user)