14 #define GETTEXT_DOMAIN "wesnoth-lib" 53 #define DBG_LB LOG_STREAM(debug, log_lobby) 54 #define LOG_LB LOG_STREAM(info, log_lobby) 55 #define ERR_LB LOG_STREAM(err, log_lobby) 56 #define SCOPE_LB log_scope2(log_lobby, __func__) 67 tree_view& parent_tree = find_widget<tree_view>(&
w,
"player_tree",
false);
69 std::map<std::string, string_map> tree_group_item;
70 tree_group_item[
"tree_view_node_label"][
"label"] = lbl;
72 tree = &parent_tree.
add_node(
"player_group", tree_group_item);
78 tree_label = find_widget<label>(tree,
"tree_view_node_label",
false,
true);
79 label_player_count = find_widget<label>(tree,
"player_count",
false,
true);
82 assert(label_player_count);
102 active_game.init(w,
_(
"Selected Game"),
true);
103 other_rooms.init(w,
_(
"Lobby"),
true);
104 #ifdef ENABLE_ROOM_MEMBER_TREE 105 active_room.init(w,
_(
"Current Room"));
107 other_games.init(w,
_(
"Other Games"));
109 tree = find_widget<tree_view>(&
w,
"player_tree",
false,
true);
114 return show_prompt(
_(
"Do you really want to log out?"));
119 , game_config_(game_config)
120 , gamelistbox_(nullptr)
123 , filter_friends_(nullptr)
124 , filter_ignored_(nullptr)
125 , filter_slots_(nullptr)
126 , filter_invert_(nullptr)
127 , filter_text_(nullptr)
128 , selected_game_id_()
130 , player_list_dirty_(true)
131 , gamelist_dirty_(true)
132 , last_lobby_update_(0)
133 , gamelist_diff_update_(true)
134 , network_connection_(connection)
135 , lobby_update_timer_(0)
136 , gamelist_id_at_row_()
137 , delay_playerlist_update_(false)
138 , delay_gamelist_update_(false)
154 l.delay_gamelist_update_ =
false;
175 void modify_grid_with_data(
grid*
grid,
const std::map<std::string, string_map>& map)
177 for(
const auto& v : map) {
178 const std::string& key = v.first;
191 for(
const auto & vv : strmap) {
192 if(vv.first ==
"label") {
194 }
else if(vv.first ==
"tooltip") {
201 std::string colorize(
const std::string& str,
const color_t& color)
206 bool handle_addon_requirements_gui(
const std::vector<mp::game_info::required_addon>& reqs,
mp::game_info::ADDON_REQ addon_outcome)
209 std::string e_title =
_(
"Incompatible User-made Content.");
210 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.");
213 err_msg +=
_(
"Details:");
225 std::string e_title =
_(
"Missing User-made Content.");
226 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?");
229 err_msg +=
_(
"Details:");
232 std::vector<std::string> needs_download;
237 needs_download.push_back(
a.addon_id);
241 assert(needs_download.size() > 0);
270 LOG_LB <<
"Adding game to listbox (1)" << game.
id <<
"\n";
295 int list_rows_deleted = 0;
297 std::vector<int> next_gamelist_id_at_row;
302 LOG_LB <<
"Adding game to listbox " << game.
id <<
"\n";
306 DBG_LB <<
"Added a game listbox row not at the end" << list_i
317 next_gamelist_id_at_row.push_back(game.
id);
320 ERR_LB <<
"Ran out of listbox items -- triggering a full refresh\n";
326 ERR_LB <<
"gamelist_id_at_row_ overflow! " << list_i <<
" + " 329 <<
" -- triggering a full refresh\n";
335 if(game.
id != listbox_game_id) {
336 ERR_LB <<
"Listbox game id does not match expected id " 337 << listbox_game_id <<
" " << game.
id <<
" (row " << list_i <<
")\n";
343 LOG_LB <<
"Modifying game in listbox " << game.
id <<
" (row " << list_i <<
")\n";
348 next_gamelist_id_at_row.push_back(game.
id);
350 LOG_LB <<
"Deleting game from listbox " << game.
id <<
" (row " 356 LOG_LB <<
"Clean game in listbox " << game.
id <<
" (row " << list_i <<
")\n";
357 next_gamelist_id_at_row.push_back(game.
id);
363 for(
unsigned i = 0;
i < next_gamelist_id_at_row.size(); ++
i) {
371 ERR_LB <<
"Would select a row beyond the listbox" << select_row <<
" " 391 const std::string games_string =
VGETTEXT(
"Games: showing $num_shown out of $num_total", {
396 find_widget<label>(
gamelistbox_,
"map",
false).set_label(games_string);
401 std::map<std::string, string_map> data;
404 item[
"use_markup"] =
"true";
411 const std::string scenario_text =
VGETTEXT(
"$game_name (Era: $era_name)", {
413 {
"era_name", game.
era}
417 data.emplace(
"name", item);
420 data.emplace(
"scenario", item);
422 item[
"label"] = colorize(game.
status, color_string);
423 data.emplace(
"status", item);
430 find_widget<styled_widget>(
grid,
"name",
false).set_use_markup(
true);
431 find_widget<styled_widget>(
grid,
"status",
false).set_use_markup(
true);
438 std::ostringstream ss;
440 const auto mark_missing = [&ss]() {
456 ss <<
_(
"active_modifications^None") <<
"\n";
458 for(
const auto& mod : mods) {
470 const auto yes_or_no = [](
bool val) {
return val ?
_(
"yes") :
_(
"no"); };
473 ss <<
_(
"Experience modifier:") <<
" " << game.
xp <<
"\n";
474 ss <<
_(
"Gold per village:") <<
" " << game.
gold <<
"\n";
476 ss <<
_(
"Reloaded:") <<
" " << yes_or_no(game.
reloaded) <<
"\n";
477 ss <<
_(
"Shared vision:") <<
" " << game.
vision <<
"\n";
478 ss <<
_(
"Shuffle sides:") <<
" " << yes_or_no(game.
shuffle_sides) <<
"\n";
479 ss <<
_(
"Time limit:") <<
" " << game.
time_limit <<
"\n";
482 image& info_icon = find_widget<image>(
grid,
"game_info",
false);
485 info_icon.
set_label(
"icons/icon-info-error.png");
487 ss <<
"\n\n<span color='#f00' size='x-large'>! </span>";
488 ss <<
_(
"One or more add-ons need to be installed\nin order to join this game.");
490 info_icon.
set_label(
"icons/icon-info.png");
498 image& password_icon = find_widget<image>(
grid,
"needs_password",
false);
509 image& observer_icon = find_widget<image>(
grid,
"observer_icon",
false);
515 observer_icon.
set_label(
"misc/no_observer.png");
522 minimap& map = find_widget<minimap>(
grid,
"minimap",
false);
537 DBG_LB <<
"mp_lobby::update_gamelist_filter\n";
553 #ifdef ENABLE_ROOM_MEMBER_TREE 556 if(ri->name() ==
"lobby") {
563 #ifdef ENABLE_ROOM_MEMBER_TREE 572 #ifdef ENABLE_ROOM_MEMBER_TREE 581 std::string
name = user.name;
583 std::stringstream icon_ss;
584 icon_ss <<
"lobby/status";
586 #ifdef ENABLE_ROOM_MEMBER_TREE 600 name = colorize(name, {0, 255, 255});
601 icon_ss << (user.observing ?
"-obs" :
"-playing");
606 icon_ss << (user.observing ?
"-obs" :
"-playing");
610 ERR_LB <<
"Bad user state in lobby: " << user.name <<
": " 611 << user.state <<
"\n";
615 switch(user.relation) {
629 ERR_LB <<
"Bad user relation in lobby: " << user.relation
638 if(user.registered) {
639 name =
"<b>" + name +
"</b>";
649 assert(target_list->
tree);
652 std::map<std::string, string_map> tree_group_item;
655 tree_group_field[
"label"] = icon_ss.str();
656 tree_group_item[
"icon"] = tree_group_field;
658 tree_group_field[
"label"] =
name;
659 tree_group_field[
"use_markup"] =
"true";
660 tree_group_item[
"name"] = tree_group_field;
669 #ifdef ENABLE_ROOM_MEMBER_TREE 687 bool can_join =
false, can_observe =
false;
698 find_widget<button>(
get_window(),
"observe_global",
false).set_active(can_observe);
699 find_widget<button>(
get_window(),
"join_global",
false).set_active(can_join);
717 gamelistbox_ = find_widget<listbox>(&window,
"game_list",
false,
true);
724 window.set_enter_disabled(
true);
729 chatbox_ = find_widget<chatbox>(&window,
"chat",
false,
true);
738 find_widget<button>(&window,
"create",
false).set_retval(
CREATE);
741 find_widget<button>(&window,
"show_preferences",
false),
745 find_widget<button>(&window,
"join_global",
false),
748 find_widget<button>(&window,
"join_global",
false).set_active(
false);
751 find_widget<button>(&window,
"observe_global",
false),
754 find_widget<button>(&window,
"observe_global",
false).set_active(
false);
756 menu_button& replay_options = find_widget<menu_button>(&window,
"replay_options",
false);
769 filter_friends_ = find_widget<toggle_button>(&window,
"filter_with_friends",
false,
true);
770 filter_ignored_ = find_widget<toggle_button>(&window,
"filter_without_ignored",
false,
true);
771 filter_slots_ = find_widget<toggle_button>(&window,
"filter_vacant_slots",
false,
true);
772 filter_invert_ = find_widget<toggle_button>(&window,
"filter_invert",
false,
true);
773 filter_text_ = find_widget<text_box>(&window,
"filter_text",
false,
true);
844 LOG_LB <<
"caught wesnothd_error in network_handler: " << e.
message <<
"\n";
876 }
else if(data.
child(
"gamelist")) {
878 }
else if(
const config& gamelist_diff = data.
child(
"gamelist_diff")) {
888 DBG_LB <<
"Received gamelist\n";
896 DBG_LB <<
"Received gamelist diff\n";
899 ERR_LB <<
"process_gamelist_diff failed!" << std::endl;
902 const int joined = data.
child_count(
"insert_child");
904 if(joined > 0 || left > 0) {
918 ERR_LB <<
"Attempted to join a game with no vacant slots" << std::endl;
925 ERR_LB <<
"Attempted to observe a game with observers disabled" << std::endl;
936 DBG_LB <<
"Cannot join or observe a game." << std::endl;
943 const bool try_join = mode ==
DO_JOIN;
951 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."));
968 join_data[
"id"] = std::to_string(game.
id);
969 join_data[
"observe"] = try_obsv;
974 if(!gui2::dialogs::mp_join_game_password_prompt::execute(password)) {
992 }
catch(
const std::out_of_range&) {
994 ERR_LB <<
"Attempted to join/observe a game with index out of range: " << index <<
". " 1004 ERR_LB <<
"Attempted to join/observe a game with an invalid id: " << game_id << std::endl;
1081 if(key == SDLK_RETURN || key == SDLK_KP_ENTER) {
1132 const int value = find_widget<menu_button>(&window,
"replay_options",
false).get_value();
Define the common log macros for the gui toolkit.
void game_filter_keypress_callback(const SDL_Keycode key)
void send_data(const configr_of &request)
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 coommunicate with the wesnothd server.
Dialog was closed with the CANCEL button.
Class for a toggle button.
#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)
const config & gamelist() const
Returns the raw game list config data.
void set_lobby_info(mp::lobby_info &i)
label * label_player_count
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.
std::size_t lobby_update_timer_
Timer for updating the lobby.
sub_player_list active_room
void register_hotkey(const hotkey::HOTKEY_COMMAND id, const hotkey_function &function)
Registers a hotkey.
static l_noret error(LoadState *S, const char *why)
bool get_value_bool() const
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
unsigned child_count(config_key_type key) const
virtual void pre_show(window &window) override
Inherited from modal_dialog.
std::string get_value() const
void update_user_statuses(int game_id, const room_info *room)
This class represents the collective information the client has about the players and games on the se...
void skip_replay_changed_callback(window &window)
void add_game_filter(game_filter_func func)
Adds a new filter function to be considered when apply_game_filter is called.
void user_dialog_callback(mp::user_info *info)
bool delay_playerlist_update_
void adjust_game_row_contents(const mp::game_info &game, grid *grid, bool add_callbacks=true)
window * get_window() const
Returns a pointer to the dialog's window.
static bool logout_prompt()
unsigned gamemap_width
The size of the map area, if not available equal to the screen size.
int get_selected_row() const
Returns the first selected row.
bool receive_data(config &result)
void process_network_data(const config &data)
void update_selected_game()
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.
void process_gamelist(const config &data)
Process a full game list.
std::vector< std::string > split(const std::string &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
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")
void update_gamelist_header()
std::size_t count_children() const
The number of children in this widget.
void gamelist_change_callback()
game_info * get_game_by_id(int id)
Returns info on a game with the given game ID.
void make_games_vector()
Generates a new vector of game pointers from the ID/game map.
sub_player_list other_rooms
static const char * name(const std::vector< SDL_Joystick *> &joysticks, const std::size_t index)
std::string span_color(const color_t &color)
Returns a Pango formatting string using the provided color_t object.
static UNUSEDNOWARN std::string _(const char *str)
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)
void enter_game_by_id(const int game_id, JOIN_MODE mode)
Entry wrapper for enter_game, where game is located by game id.
void connect_signal_notify_modified(dispatcher &dispatcher, const signal_notification_function &signal)
Connects a signal handler for getting a notification upon modification.
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 sync_games_display_status()
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal_function &signal)
Connects a signal handler for a left mouse button click.
void init()
Initializes the GUI subsystems.
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.
virtual void send_chat_message(const std::string &message, bool allies_only) override
Inherited form chat_handler.
void update_gamelist_filter()
void load_log(std::map< std::string, chatroom_log > &log, bool show_lobby)
widget * find(const std::string &id, const bool must_be_active) override
See widget::find.
mp_lobby(const config &game_config, mp::lobby_info &info, wesnothd_connection &connection)
void set_game_filter_invert(bool value)
Sets whether the result of each game filter should be inverted.
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 player_filter_callback()
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)
void connect_signal_mouse_left_double_click(dispatcher &dispatcher, const signal_function &signal)
Connects a signal handler for a left mouse button double click.
std::map< std::string, string_map > make_game_row_data(const mp::game_info &game)
Various uncategorised dialogs.
static bool quit()
Shows the quit confirmation if needed.
mp::room_info * active_window_room()
Get the room* corresponding to the currently active window, or nullptr if a whisper window is active ...
void process_network_data(const ::config &data)
const boost::dynamic_bitset & games_visibility() const
void set_config(const ::config *terrain)
void game_filter_reload()
void clear()
Removes all child items from the widget.
void show_preferences_button_callback(window &window)
static void display(const config &game_cfg, const preferences::PREFERENCE_VIEW initial_view=preferences::VIEW_DEFAULT)
The display function – see modal_dialog for more information.
void network_handler()
Network polling callback.
void update_player_count_label()
void enter_game(const mp::game_info &game, JOIN_MODE mode)
Exits the lobby and enters the given game.
const std::vector< game_info * > & games() const
Game configuration data as global variables.
static map_location::DIRECTION s
bool gamelist_initialized() const
std::string password(const std::string &server, const std::string &login)
void game_filter_change_callback()
Contains the gui2 timer routines.
toggle_button * filter_invert_
void unfold(const bool recursive=false)
grid & add_row(const string_map &item, const int index=-1)
When an item in the list is selected by the user we need to update the state.
unsigned screen_width
The screen resolution should be available for all widgets since their drawing method will depend on i...
This class represents the information a client has about a room.
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)
sub_player_list other_games
unsigned last_lobby_update_
void set_retval(const int retval, const bool close_window=true)
Sets there return value of the window.
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)
void clear_game_filter()
Clears all game filter functions.
bool process_gamelist_diff(const config &data)
Process a gamelist diff.
config & add_child(config_key_type key)
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.
virtual void post_build(window &window) override
Inherited from modal_dialog.
void connect_signal_pre_key_press(dispatcher &dispatcher, const signal_keyboard_function &signal)
Connects the signal for 'snooping' on the keypress.
void set_allow_plugin_skip(const bool allow_plugin_skip)
sub_player_list active_game
std::map< std::string, chatroom_log > default_chat_log
void set_wesnothd_connection(wesnothd_connection &c)
this module manages the cache of images.
void remove_row(const unsigned row, unsigned count=1)
Removes a row in the listbox.
wesnothd_connection & network_connection_
game_display_status display_status
void invalidate_layout()
Updates the size of the window.
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.
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.
SDL_Rect screen_area(bool as_pixels=true) const
Returns the current window renderer area, either in pixels or screen coordinates. ...
tree_view_node & add_child(const std::string &id, const std::map< std::string, string_map > &data, const int index=-1)
Constructs a new child node.
virtual void post_show(window &window) override
Inherited from modal_dialog.
base class of top level items, the only item which needs to store the final canvases to draw on ...
void set_row_shown(const unsigned row, const bool shown)
Makes a row visible or invisible.
toggle_button * filter_ignored_
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...
bool exit_hook(window &window)
tree_view_node & add_node(const std::string &id, const std::map< std::string, string_map > &data, const int index=-1)
toggle_button * filter_friends_
bool playerlist_group_players()
bool result_open_whisper() const
bool match_string_filter(const std::string &filter) const
bool remove_timer(const std::size_t id)
Removes a timer.
const config & game_config_
toggle_button * filter_slots_