15 #define GETTEXT_DOMAIN "wesnoth-lib" 53 #define DBG_MP LOG_STREAM(debug, log_mp_connect_engine) 54 #define LOG_MP LOG_STREAM(info, log_mp_connect_engine) 55 #define WRN_MP LOG_STREAM(warn, log_mp_connect_engine) 56 #define ERR_MP LOG_STREAM(err, log_mp_connect_engine) 67 , network_connection_(connection)
69 , first_scenario_(first_scenario)
70 , observe_game_(observe_game)
71 , stop_updates_(false)
72 , player_list_(
nullptr)
73 , flg_dialog_(
nullptr)
75 set_show_even_without_video(
true);
96 bool has_scenario_and_controllers =
false;
97 while(!has_scenario_and_controllers) {
108 }
else if(revc.
child(
"leave_game")) {
115 has_scenario_and_controllers =
true;
116 }
else if(
config& controllers = revc.
child(
"controllers")) {
125 has_scenario_and_controllers =
true;
129 if(
level_[
"started"].to_bool()) {
142 if(scenario_id ==
"") {
144 for(
const auto& content : addon.child_range(
"content")) {
145 if(content[
"type"] ==
"scenario") {
146 scenario_id = content[
"id"].str();
164 const config* side_choice =
nullptr;
166 int side_num_choice = 1, side_num_counter = 1;
170 if(side[
"controller"] == side_controller::reserved && side[
"current_player"] ==
preferences::login()) {
172 side_num_choice = side_num_counter;
176 if(side[
"controller"] == side_controller::human && side[
"player_id"].empty()) {
179 side_num_choice = side_num_counter;
184 side_num_choice = side_num_counter;
203 if((*side_choice)[
"allow_changes"].to_bool(
true)) {
219 const std::string controller_type = side[
"controller"].str();
220 const std::string reservation = side[
"current_player"].str();
221 const std::string owner = side[
"player_id"].str();
223 if(controller_type == side_controller::ai) {
224 return _(
"Computer Player");
225 }
else if(controller_type == side_controller::none) {
226 return _(
"Empty slot");
227 }
else if(controller_type == side_controller::reserved) {
228 return VGETTEXT(
"Reserved for $playername", {{
"playername", reservation}});
229 }
else if(owner.empty()) {
230 return _(
"Vacant slot");
231 }
else if(controller_type == side_controller::human) {
246 label& title = find_widget<label>(&
window,
"title",
false);
258 chatbox& chat = find_widget<chatbox>(&
window,
"chat",
false);
287 if(!side_choice[
"allow_changes"].to_bool(
true)) {
293 ERR_MP <<
"no era information";
298 if(possible_sides.empty()) {
299 WRN_MP <<
"no [multiplayer_side] found in era '" << era[
"id"] <<
"'.";
303 const std::string color = side_choice[
"color"].str();
305 std::vector<const config*> era_factions;
308 for(
const config& side : possible_sides) {
310 era_factions.push_back(&side_new);
314 const bool lock_settings =
get_scenario()[
"force_lock_settings"].to_bool(!is_mp);
318 ng::flg_manager flg(era_factions, side_choice, lock_settings, use_map_settings, saved_game == saved_game_mode::type::midgame);
324 if(!flg_dialog.
show() && !first_time) {
331 change[
"change_faction"] =
true;
337 change[
"side_num"] = side_num;
358 for(
const auto& side :
get_scenario().child_range(
"side")) {
360 if(!side[
"allow_player"].to_bool(
true)) {
370 data.emplace(
"tree_view_node_label", item);
381 const std::string color = !side[
"color"].empty() ? side[
"color"] : side[
"side"].str();
384 data.emplace(
"side_number", item);
387 std::string leader_type = side[
"type"];
388 std::string leader_gender = side[
"gender"];
389 std::string leader_name;
394 if(side_unit[
"canrecruit"].to_bool()) {
395 leader_type = side_unit[
"type"].str();
396 leader_gender = side_unit[
"gender"].str();
402 const unit_type&
type = ut->get_gender_unit_type(leader_gender);
408 item[
"label"] = leader_image;
409 data.emplace(
"leader_image", item);
412 if(!leader_name.empty()) {
413 description +=
formatter() <<
" (<i>" << leader_name <<
"</i>)";
416 item[
"label"] = description;
417 data.emplace(
"leader_type", item);
419 item[
"label"] = (
formatter() <<
"<span color='#a69275'>" << side[
"faction_name"] <<
"</span>").str();
420 data.emplace(
"leader_faction", item);
422 std::string gender_icon =
"icons/icon-random.png";
423 if(leader_gender !=
"null") {
424 gender_icon =
formatter() <<
"icons/icon-" << leader_gender <<
".png";
425 item[
"tooltip"] = leader_gender;
428 item[
"label"] = gender_icon;
429 data.emplace(
"leader_gender", item);
435 if(side[
"allow_changes"].to_bool()) {
436 item[
"label"] = side[
"gold"].
str() +
" " +
_(
"Gold");
437 data.emplace(
"side_gold", item);
440 const int income_amt = side[
"income"];
441 if(income_amt != 0) {
442 const std::string income_string =
formatter() << (income_amt > 0 ?
"+" :
"") << income_amt <<
" " <<
_(
"Income");
444 item[
"label"] = income_string;
445 data.emplace(
"side_income", item);
452 auto* select_leader_button = find_widget<button>(&row_grid,
"select_leader",
false,
false);
453 if(select_leader_button) {
454 if(side[
"player_id"] ==
preferences::login() && side[
"allow_changes"].to_bool(
true)) {
461 const auto handler = [
this, side_num](
bool& handled,
bool& halt) {
469 handled = halt =
true;
478 if(income_amt == 0) {
497 if(
level_[
"started"].to_bool()) {
508 find_widget<chatbox>(
get_window(),
"chat",
false).process_network_data(data);
510 if(!data[
"message"].empty()) {
514 if(data[
"failed"].to_bool()) {
518 }
else if(data.
child(
"start_game")) {
523 }
else if(data.
child(
"leave_game")) {
529 if(data.
child(
"stop_updates")) {
531 }
else if(
const config&
c = data.
child(
"scenario_diff")) {
536 }
else if(
const config& change = data.
child(
"change_controller")) {
538 side_to_change.merge_with(change);
551 ERR_MP <<
"received replay data\n" << data <<
"\n in mp join";
window(const builder_window::window_resolution &definition)
< Needs to be initialized in show.
void active_window_changed()
An error occurred during when trying to communicate with the wesnothd server.
Dialog was closed with the CANCEL button.
#define REGISTER_DIALOG(window_id)
Wrapper for REGISTER_DIALOG2.
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...
const unit_type * find(const std::string &key, unit_type::BUILD_STATUS status=unit_type::FULL) const
Finds a unit_type by its id() and makes sure it is built to the specified level.
const std::string & current_gender() const
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button click.
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.
Variant for storing WML attributes.
tree_view_node & add_node(const std::string &id, const widget_data &data, const int index=-1)
static game_config_view wrap(const config &cfg)
bool has_attribute(config_key_type key) const
bool has_child(config_key_type key) const
Determine whether a config has a child or not.
const std::string & flag_rgb() const
child_itors child_range(config_key_type key)
static void progress(loading_stage stage=loading_stage::none)
Report what is being loaded to the loading screen.
void load_game_config_for_game(const game_classification &classification, const std::string &scenario_id)
const attribute_value * get(config_key_type key) const
Returns a pointer to the attribute with the given key or nullptr if it does not exist.
bool is_normal_mp_game() const
const bool first_scenario_
unit_type_data unit_types
faction_select * flg_dialog_
static lg::log_domain log_mp_connect_engine("mp/connect/engine")
void set_escape_disabled(const bool escape_disabled)
Disable the escape key.
static const std::string & type()
Static type getter that does not rely on the widget being constructed.
A label displays a text, the text can be wrapped but no scrollbars are provided.
bool receive_data(config &result)
Receives the next pending data pack from the server, if available.
void level_to_gamestate(const config &level, saved_game &state)
static std::string _(const char *str)
FLG stands for faction, leader and gender.
bool show(const unsigned auto_close_time=0)
Shows the window.
std::size_t update_timer_
wesnothd_connection & network_connection_
A single unit type that the player may recruit.
std::string get_scenario_id() const
static game_config_manager * get()
std::string get_pango_color_from_id(const std::string &id)
Returns a hex color string from a color range.
std::map< std::string, t_string > widget_item
const t_string & type_name() const
The name of the unit in the current language setting.
std::unique_ptr< plugins_context > plugins_context_
unsigned lobby_network_timer
const std::string & current_leader() const
void show_transient_message(const std::string &title, const std::string &message, const std::string &image, const bool message_use_markup, const bool title_use_markup)
Shows a transient message to the user.
A class that represents a TCP/IP connection to the wesnothd server.
bool show_flg_select(int side_num, bool first_time=false)
virtual void send_chat_message(const std::string &message, bool allies_only) override
Inherited form chat_handler.
void load_log(std::map< std::string, chatroom_log > &log, bool show_lobby)
void read_stats(const config &cfg)
A tree view is a control that holds several items of the same or different types. ...
void close_faction_select_dialog_if_open()
Will close the Faction Select dialog if it's open.
void apply_diff(const config &diff, bool track=false)
A function to apply a diff config onto this config object.
static void add_color_info(const game_config_view &v, bool build_defaults)
window * get_window()
Returns a pointer to the dialog's window.
boost::iterator_range< const_child_iterator > const_child_itors
std::unique_ptr< player_list_helper > player_list_
const config & current_faction() const
Data-based RAII scope guard.
static constexpr std::optional< enum_type > get_enum(const std::string_view value)
Converts a string into its enum equivalent.
Contains the gui2 timer routines.
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.
static t_string from_serialized(const std::string &string)
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.
config & add_child(config_key_type key)
const std::string random_enemy_picture("units/random-dice.png")
const std::string & image() const
static void display(std::function< void()> f)
tree_view_node & add_sibling(const std::string &id, const widget_data &data)
Adds a sibbling for a node at the end of the list.
std::map< std::string, tree_view_node * > team_tree_map_
game_classification & classification()
const std::string unicode_em_dash
std::map< std::string, chatroom_log > default_chat_log
virtual void post_show(window &window) override
Actions to be taken after the window has been shown.
Abstract base class for all modal dialogs.
Standard logging facilities (interface).
bool wait_and_receive_data(config &data)
Unlike receive_data, waits until data is available instead of returning immediately.
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.
virtual void pre_show(window &window) override
Actions to be taken before showing the window.
static std::string generate_user_description(const config &side)
Dialog was closed with the OK button.
A config object defines a single node in a WML file, with access to child nodes.
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...
std::pair< std::string, unsigned > item
bool remove_timer(const std::size_t id)
Removes a timer.
void generate_side_list()
void set_enter_disabled(const bool enter_disabled)
Disable the enter key.