16 #define GETTEXT_DOMAIN "wesnoth-lib" 58 #define DBG_LB LOG_STREAM(debug, log_lobby) 59 #define LOG_LB LOG_STREAM(info, log_lobby) 60 #define ERR_LB LOG_STREAM(err, log_lobby) 61 #define SCOPE_LB log_scope2(log_lobby, __func__) 69 return show_prompt(
_(
"Do you really want to log out?"));
75 , gamelistbox_(nullptr)
78 , filter_friends_(register_bool(
"filter_with_friends",
82 std::bind(&
mp_lobby::update_gamelist_filter, this)))
83 , filter_ignored_(register_bool(
"filter_with_ignored",
87 std::bind(&
mp_lobby::update_gamelist_filter, this)))
88 , filter_slots_(register_bool(
"filter_vacant_slots",
92 std::bind(&
mp_lobby::update_gamelist_filter, this)))
93 , filter_invert_(register_bool(
"filter_invert",
97 std::bind(&
mp_lobby::update_gamelist_filter, this)))
98 , filter_auto_hosted_(false)
99 , filter_text_(nullptr)
100 , selected_game_id_()
101 , player_list_(
std::bind(&
mp_lobby::user_dialog_callback, this,
std::placeholders::_1))
102 , player_list_dirty_(true)
103 , gamelist_dirty_(true)
104 , last_lobby_update_(0)
105 , gamelist_diff_update_(true)
106 , network_connection_(connection)
107 , lobby_update_timer_(0)
108 , gamelist_id_at_row_()
109 , delay_playerlist_update_(false)
110 , delay_gamelist_update_(false)
111 , joined_game_id_(joined_game)
133 l.delay_gamelist_update_ =
false;
149 for(
const auto& v : map) {
150 const std::string& key = v.first;
163 for(
const auto & vv : strmap) {
164 if(vv.first ==
"label") {
166 }
else if(vv.first ==
"tooltip") {
173 bool handle_addon_requirements_gui(
const std::vector<mp::game_info::required_addon>& reqs,
mp::game_info::addon_req addon_outcome)
176 std::string e_title =
_(
"Incompatible User-made Content");
177 std::string err_msg =
_(
"This game cannot be joined because the host has out-of-date add-ons that are incompatible with your version. You might wish to suggest that the host's add-ons be updated.");
180 err_msg +=
_(
"Details:");
192 std::string e_title =
_(
"Missing User-made Content");
193 std::string err_msg =
_(
"This game requires one or more user-made addons to be installed or updated in order to join.\nDo you want to try to install them?");
196 err_msg +=
_(
"Details:");
199 std::vector<std::string> needs_download;
204 needs_download.push_back(
a.addon_id);
208 assert(needs_download.size() > 0);
244 LOG_LB <<
"Adding game to listbox (1)" << game.
id;
268 int list_rows_deleted = 0;
272 std::vector<int> next_gamelist_id_at_row;
283 LOG_LB <<
"Adding game to listbox " << game.
id;
287 DBG_LB <<
"Added a game listbox row not at the end" << list_i
298 next_gamelist_id_at_row.push_back(game.
id);
301 ERR_LB <<
"Ran out of listbox items -- triggering a full refresh";
307 ERR_LB <<
"gamelist_id_at_row_ overflow! " << list_i <<
" + " 310 <<
" -- triggering a full refresh";
316 if(game.
id != listbox_game_id) {
317 ERR_LB <<
"Listbox game id does not match expected id " 318 << listbox_game_id <<
" " << game.
id <<
" (row " << list_i <<
")";
324 LOG_LB <<
"Modifying game in listbox " << game.
id <<
" (row " << list_i <<
")";
329 next_gamelist_id_at_row.push_back(game.
id);
331 LOG_LB <<
"Deleting game from listbox " << game.
id <<
" (row " 337 LOG_LB <<
"Clean game in listbox " << game.
id <<
" (row " << list_i <<
")";
338 next_gamelist_id_at_row.push_back(game.
id);
344 for(
unsigned i = 0;
i < next_gamelist_id_at_row.size(); ++
i) {
352 ERR_LB <<
"Would select a row beyond the listbox" << select_row <<
" " 370 const std::string games_string =
VGETTEXT(
"Games: showing $num_shown out of $num_total", {
385 item[
"use_markup"] =
"true";
392 const std::string scenario_text =
VGETTEXT(
"$game_name (Era: $era_name)", {
394 {
"era_name", game.
era}
398 data.emplace(
"name", item);
401 data.emplace(
"scenario", item);
404 data.emplace(
"status", item);
419 std::ostringstream ss;
421 const auto mark_missing = [&ss]() {
437 ss <<
_(
"active_modifications^None") <<
"\n";
439 for(
const auto& mod : mods) {
451 const auto yes_or_no = [](
bool val) {
return val ?
_(
"yes") :
_(
"no"); };
454 ss <<
_(
"Experience modifier:") <<
" " << game.
xp <<
"\n";
455 ss <<
_(
"Gold per village:") <<
" " << game.
gold <<
"\n";
457 ss <<
_(
"Reloaded:") <<
" " << yes_or_no(game.
reloaded) <<
"\n";
458 ss <<
_(
"Shared vision:") <<
" " << game.
vision <<
"\n";
459 ss <<
_(
"Shuffle sides:") <<
" " << yes_or_no(game.
shuffle_sides) <<
"\n";
460 ss <<
_(
"Time limit:") <<
" " << game.
time_limit <<
"\n";
463 image& info_icon = find_widget<image>(
grid,
"game_info",
false);
466 info_icon.
set_label(
"icons/icon-info-error.png");
468 ss <<
"\n\n<span color='#f00' size='x-large'>! </span>";
469 ss <<
_(
"One or more add-ons need to be installed\nin order to join this game.");
471 info_icon.
set_label(
"icons/icon-info.png");
479 image& password_icon = find_widget<image>(
grid,
"needs_password",
false);
490 image& observer_icon = find_widget<image>(
grid,
"observer_icon",
false);
496 observer_icon.
set_label(
"misc/no_observer.png");
503 minimap& map = find_widget<minimap>(
grid,
"minimap",
false);
517 DBG_LB <<
"mp_lobby::update_gamelist_filter";
542 bool can_join =
false, can_observe =
false;
575 window.set_enter_disabled(
true);
590 find_widget<button>(&window,
"show_preferences",
false),
594 find_widget<button>(&window,
"join_global",
false),
600 find_widget<button>(&window,
"observe_global",
false),
604 find_widget<button>(&window,
"server_info",
false),
609 menu_button& replay_options = find_widget<menu_button>(&
window,
"replay_options",
false);
647 if(
auto* profile_panel = find_widget<panel>(&window,
"profile",
false,
false)) {
652 find_widget<label>(profile_panel,
"username",
false).
set_label(your_info->name);
654 auto& profile_button = find_widget<button>(profile_panel,
"view_profile",
false);
658 find_widget<button>(profile_panel,
"view_match_history",
false).
set_active(
false);
662 listbox& tab_bar = find_widget<listbox>(&
window,
"games_list_tab_bar",
false);
716 LOG_LB <<
"caught wesnothd_error in network_handler: " << e.
message;
748 }
else if(data.
child(
"gamelist")) {
750 }
else if(
const config& gamelist_diff = data.
child(
"gamelist_diff")) {
753 if(
info[
"type"] ==
"server_info") {
756 }
else if(
info[
"type"] ==
"announcements") {
770 DBG_LB <<
"Received gamelist";
780 DBG_LB <<
"Received gamelist diff";
783 ERR_LB <<
"process_gamelist_diff failed!";
786 const int joined = data.
child_count(
"insert_child");
788 if(joined > 0 || left > 0) {
802 ERR_LB <<
"Attempted to join a game with no vacant slots";
809 ERR_LB <<
"Attempted to observe a game with observers disabled";
820 DBG_LB <<
"Cannot join or observe a game.";
834 const bool try_join = mode ==
DO_JOIN;
842 gui2::show_error_message(
_(
"Something is wrong with the addon version check database supporting the multiplayer lobby. Please report this at https://bugs.wesnoth.org."));
859 join_data[
"id"] = std::to_string(game.
id);
860 join_data[
"observe"] = try_obsv;
869 if(!gui2::dialogs::mp_join_game_password_prompt::execute(password)) {
887 }
catch(
const std::out_of_range&) {
889 ERR_LB <<
"Attempted to join/observe a game with index out of range: " << index <<
". " 899 ERR_LB <<
"Attempted to join/observe a game with an invalid id: " << game_id;
923 gui2::dialogs::preferences_dialog::display();
972 if(key == SDLK_RETURN || key == SDLK_KP_ENTER) {
1003 const int value = find_widget<menu_button>(
get_window(),
"replay_options",
false).get_value();
Define the common log macros for the gui toolkit.
void game_filter_keypress_callback(const SDL_Keycode key)
window(const builder_window::window_resolution &definition)
< Needs to be initialized in show.
void switch_to_window(lobby_chat_window *t)
Switch to the window given by a valid pointer (e.g.
void active_window_changed()
An error occurred during when trying to communicate with the wesnothd server.
const mp::user_info * get_selected_info() const
Dialog was closed with the CANCEL button.
Class for a toggle button.
static std::string announcements_
show_mode mode() const
Returns the dialog mode for this window.
#define REGISTER_DIALOG(window_id)
Wrapper for REGISTER_DIALOG2.
void show_message(const std::string &title, const std::string &msg, const std::string &button_caption, const bool auto_close, const bool message_use_markup, const bool title_use_markup)
Shows a message to the user.
std::string map_size_info
bool gamelist_diff_update_
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 set_map_data(const std::string &map_data)
void skip_replay_changed_callback()
void show_help(const std::string &show_topic, int xloc, int yloc)
Open the help browser, show topic with id show_topic.
const config & gamelist() const
Returns the raw game list config data.
field_bool * filter_invert_
std::vector< int > gamelist_id_at_row_
void enter_game_by_index(const int index, JOIN_MODE mode)
Entry wrapper for enter_game, where game is located by index.
std::vector< std::pair< std::string, bool > > mod_info
List of modification names and whether they're installed or not.
bool is_game_visible(const game_info &)
Returns whether the game would be visible after the game filters are applied.
void clear_game_filters()
Clears all game filter functions.
std::size_t lobby_update_timer_
Timer for updating the lobby.
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button click.
void register_hotkey(const hotkey::HOTKEY_COMMAND id, const hotkey_function &function)
Registers a hotkey.
bool has_attribute(config_key_type key) const
This class represents the info a client has about a game on the server.
const color_t TITLE_COLOR
void set_fi_vacant_slots(bool value)
unsigned child_count(config_key_type key) const
virtual void pre_show(window &window) override
Actions to be taken before showing the window.
std::string get_value() const
static std::string server_information_
This class represents the collective information the client has about the players and games on the se...
void set_game_filter_invert(std::function< bool(bool)> value)
Sets whether the result of each game filter should be inverted.
void add_game_filter(game_filter_func func)
Adds a new filter function to be considered when apply_game_filter is called.
grid & add_row(const widget_item &item, const int index=-1)
When an item in the list is selected by the user we need to update the state.
bool delay_playerlist_update_
void adjust_game_row_contents(const mp::game_info &game, grid *grid, bool add_callbacks=true)
void set_fi_blocked_in_game(bool value)
void set_fi_friends_in_game(bool value)
int get_selected_row() const
Returns the first selected row.
bool receive_data(config &result)
Receives the next pending data pack from the server, if available.
Implements some helper classes to ease adding fields to a dialog and hide the synchronization needed...
void process_network_data(const config &data)
void update_selected_game()
static std::string _(const char *str)
void enter_selected_game(JOIN_MODE mode)
Enter game by index, where index is the selected game listbox row.
bool show(const unsigned auto_close_time=0)
Shows the window.
field_bool * filter_ignored_
void update_visible_games()
void process_gamelist(const config &data)
Process a full game list.
void apply_game_filter()
Generates a new list of games that match the current filter functions and inversion setting...
bool select_row(const unsigned row, const bool select=true)
Selects a row.
static lg::log_domain log_lobby("lobby")
bool fi_blocked_in_game()
bool logged_in_as_moderator()
Gets whether the currently logged-in user is a moderator.
game_info * get_game_by_id(int id)
Returns info on a game with the given game ID.
std::string get_profile_link(int user_id)
Gets the forum profile link for the given user.
std::string span_color(const color_t &color)
Returns a Pango formatting string using the provided color_t object.
Desktop environment interaction functions.
void do_notify(notify_mode mode, const std::string &sender, const std::string &message)
void set_active_window_changed_callback(const std::function< void(void)> &f)
std::map< std::string, t_string > widget_item
void enter_game_by_id(const int game_id, JOIN_MODE mode)
Entry wrapper for enter_game, where game is located by game id.
bool ad_hoc_addon_fetch_session(const std::vector< std::string > &addon_ids)
Conducts an ad-hoc add-ons server connection to download an add-on with a particular id and all it's ...
This file contains the settings handling of the widget library.
void set_show_even_without_video(const bool show_even_without_video)
~lobby_delay_gamelist_update_guard()
void clear()
Removes all the rows in the listbox, clearing it.
std::unique_ptr< plugins_context > plugins_context_
unsigned lobby_network_timer
Implements a quit confirmation dialog.
void show_preferences_button_callback()
lobby_chat_window * whisper_window_open(const std::string &name, bool open_new)
Check if a whisper window for user "name" is open, if open_new is true then it will be created if not...
A class that represents a TCP/IP connection to the wesnothd server.
void set_fi_invert(bool value)
virtual void send_chat_message(const std::string &message, bool allies_only) override
Inherited form chat_handler.
The basic class for representing 8-bit RGB or RGBA colour values.
void update_gamelist_filter()
void load_log(std::map< std::string, chatroom_log > &log, bool show_lobby)
disp_status display_status
widget * find(const std::string &id, const bool must_be_active) override
See widget::find.
Modify, read and display user preferences.
lobby_delay_gamelist_update_guard(mp_lobby &l)
unsigned get_item_count() const
Returns the number of items in the listbox.
Shows a yes and no button.
void process_gamelist_diff(const config &data)
void update_gamelist_diff()
bool delay_gamelist_update_
const color_t YELLOW_COLOR
void set_blindfold_replay(bool value)
std::function< void()> begin_state_sync()
Updates the game pointer list and returns a second stage cleanup function to be called after any acti...
lobby_player_list_helper player_list_
void tab_switch_callback()
window * get_window()
Returns a pointer to the dialog's window.
static bool quit()
Shows the quit confirmation if needed.
void user_dialog_callback(const mp::user_info *info)
void process_network_data(const ::config &data)
const boost::dynamic_bitset & games_visibility() const
bool open_object([[maybe_unused]] const std::string &path_or_url)
void network_handler()
Network polling callback.
void enter_game(const mp::game_info &game, JOIN_MODE mode)
Exits the lobby and enters the given game.
widget_data make_game_row_data(const mp::game_info &game)
static void display(const std::string &info, const std::string &announcements)
The display function.
const std::vector< game_info * > & games() const
static map_location::DIRECTION s
bool gamelist_initialized() const
std::string password(const std::string &server, const std::string &login)
Contains the gui2 timer routines.
T get_widget_value()
Gets the value of the field.
std::size_t add_timer(const uint32_t interval, const std::function< void(std::size_t id)> &callback, const bool repeat)
Adds a new timer.
void set_skip_mp_replay(bool value)
unsigned last_lobby_update_
void set_retval(const int retval, const bool close_window=true)
Sets there return value of the window.
mp_lobby(mp::lobby_info &info, wesnothd_connection &connection, int &joined_game)
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
const std::string unicode_bullet
void process_gamelist(const config &data)
bool process_gamelist_diff(const config &data)
Process a gamelist diff.
virtual void set_active(const bool active) override
See styled_widget::set_active.
config & add_child(config_key_type key)
bool fi_friends_in_game()
const grid * get_row_grid(const unsigned row) const
Returns the grid of the wanted row.
This class represents the information a client has about another player.
void set_allow_plugin_skip(const bool allow_plugin_skip)
std::vector< std::string > split(const config_attribute_value &val)
field_bool * filter_slots_
std::map< std::string, chatroom_log > default_chat_log
Abstract base class for all modal dialogs.
Functions to load and save images from/to disk.
void connect_signal_pre_key_press(dispatcher &dispatcher, const signal_keyboard &signal)
Connects the signal for 'snooping' on the keypress.
void connect_signal_mouse_left_double_click(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button double click.
void remove_row(const unsigned row, unsigned count=1)
Removes a row in the listbox.
wesnothd_connection & network_connection_
std::vector< required_addon > required_addons
void show_error_message(const std::string &msg, bool message_use_markup)
Shows an error message to the user.
field_bool * filter_friends_
std::map< std::string, widget_item > widget_data
void send_to_server(const config &data)
Attempts to send given data to server if a connection is open.
mp::lobby_info & lobby_info_
Dialog was closed with the OK button.
const std::vector< user_info > & users() const
A config object defines a single node in a WML file, with access to child nodes.
void update(const std::vector< mp::user_info > &user_info, int focused_game)
Updates the tree contents based on the given user data.
virtual void post_show(window &window) override
Actions to be taken after the window has been shown.
base class of top level items, the only item which needs to store the final canvases to draw on...
lobby_chat_window * room_window_open(const std::string &room, const bool open_new, const bool allow_close=true)
Check if a room window for "room" is open, if open_new is true then it will be created if not found...
Networked add-ons (campaignd) client interface.
bool exit_hook(window &window)
void show_help_callback()
void connect_signal_notify_modified(dispatcher &dispatcher, const signal_notification &signal)
Connects a signal handler for getting a notification upon modification.
std::pair< std::string, unsigned > item
bool result_open_whisper() const
bool match_string_filter(const std::string &filter) const
void set_always_save_fields(const bool always_save_fields)
bool remove_timer(const std::size_t id)
Removes a timer.