15 #define GETTEXT_DOMAIN "wesnoth-lib"
49 #define DBG_MP LOG_STREAM(debug, log_mp_connect_engine)
50 #define LOG_MP LOG_STREAM(info, log_mp_connect_engine)
51 #define WRN_MP LOG_STREAM(warn, log_mp_connect_engine)
52 #define ERR_MP LOG_STREAM(err, log_mp_connect_engine)
63 , network_connection_(connection)
65 , first_scenario_(first_scenario)
66 , observe_game_(observe_game)
67 , stop_updates_(false)
68 , player_list_(
nullptr)
69 , flg_dialog_(
nullptr)
71 set_show_even_without_video(
true);
92 bool has_scenario_and_controllers =
false;
93 while(!has_scenario_and_controllers) {
104 }
else if(revc.
has_child(
"leave_game")) {
111 has_scenario_and_controllers =
true;
112 }
else if(
auto controllers = revc.
optional_child(
"controllers")) {
121 has_scenario_and_controllers =
true;
125 if(
level_[
"started"].to_bool()) {
138 if(scenario_id ==
"") {
140 for(
const auto& content : addon.child_range(
"content")) {
141 if(content[
"type"] ==
"scenario") {
142 scenario_id = content[
"id"].str();
160 const config* side_choice =
nullptr;
162 int side_num_choice = 1, side_num_counter = 1;
166 if(side[
"controller"] == side_controller::reserved && side[
"current_player"] ==
prefs::get().login()) {
168 side_num_choice = side_num_counter;
172 if(side[
"controller"] == side_controller::human && side[
"player_id"].empty()) {
175 side_num_choice = side_num_counter;
178 if(side[
"current_player"] ==
prefs::get().login()) {
180 side_num_choice = side_num_counter;
185 if(side[
"player_id"] ==
prefs::get().login()) {
199 if((*side_choice)[
"allow_changes"].to_bool(
true)) {
215 const std::string controller_type = side[
"controller"].str();
216 const std::string reservation = side[
"current_player"].str();
217 const std::string owner = side[
"player_id"].str();
219 if(controller_type == side_controller::ai) {
220 return _(
"Computer Player");
221 }
else if(controller_type == side_controller::none) {
222 return _(
"Empty slot");
223 }
else if(controller_type == side_controller::reserved) {
224 return VGETTEXT(
"Reserved for $playername", {{
"playername", reservation}});
225 }
else if(owner.empty()) {
226 return _(
"Vacant slot");
227 }
else if(controller_type == side_controller::human) {
242 label& title = find_widget<label>(
"title");
254 chatbox& chat = find_widget<chatbox>(
"chat");
282 if(
auto side_choice =
get_scenario().optional_child(
"side", side_num - 1)) {
283 if(!side_choice[
"allow_changes"].to_bool(
true)) {
289 ERR_MP <<
"no era information";
294 if(possible_sides.empty()) {
295 WRN_MP <<
"no [multiplayer_side] found in era '" << era[
"id"] <<
"'.";
299 const std::string color = side_choice[
"color"].str();
301 std::vector<const config*> era_factions;
304 for(
const config& side : possible_sides) {
306 era_factions.push_back(&side_new);
310 const bool lock_settings =
get_scenario()[
"force_lock_settings"].to_bool(!is_mp);
311 const bool use_map_settings =
level_.
mandatory_child(
"multiplayer")[
"mp_use_map_settings"].to_bool();
314 ng::flg_manager flg(era_factions, *side_choice, lock_settings, use_map_settings,
saved_game == saved_game_mode::type::midgame);
320 if(!flg_dialog.
show() && !first_time) {
327 change[
"change_faction"] =
true;
333 change[
"side_num"] = side_num;
347 tree_view& tree = find_widget<tree_view>(
"side_list");
354 for(
const auto& side :
get_scenario().child_range(
"side")) {
356 if(!side[
"allow_player"].to_bool(
true)) {
366 data.emplace(
"tree_view_node_label", item);
377 const std::string color_str = !side[
"color"].empty() ? side[
"color"] : side[
"side"].str();
383 item[
"label"] = side[
"side"];
385 data.emplace(
"side_number", item);
388 std::string leader_type = side[
"type"];
389 std::string leader_gender = side[
"gender"];
390 std::string leader_name;
395 if(side_unit[
"canrecruit"].to_bool()) {
396 leader_type = side_unit[
"type"].str();
397 leader_gender = side_unit[
"gender"].str();
403 const unit_type&
type = ut->get_gender_unit_type(leader_gender);
405 leader_image =
formatter() <<
type.image() <<
"~RC(" <<
type.flag_rgb() <<
">" << color_str <<
")";
406 leader_name =
type.type_name();
409 item[
"label"] = leader_image;
410 data.emplace(
"leader_image", item);
413 if(!leader_name.empty()) {
414 description +=
formatter() <<
" (<i>" << leader_name <<
"</i>)";
417 item[
"label"] = description;
418 data.emplace(
"leader_type", item);
420 item[
"label"] = side[
"faction_name"];
421 data.emplace(
"leader_faction", item);
423 std::string gender_icon =
"icons/icon-random.png";
424 if(leader_gender !=
"null") {
425 gender_icon =
formatter() <<
"icons/icon-" << leader_gender <<
".png";
426 item[
"tooltip"] = leader_gender;
429 item[
"label"] = gender_icon;
430 data.emplace(
"leader_gender", item);
436 if(side[
"allow_changes"].to_bool()) {
437 item[
"label"] = side[
"gold"].str() +
" " +
_(
"Gold");
438 data.emplace(
"side_gold", item);
441 const int income_amt = side[
"income"].to_int();
442 if(income_amt != 0) {
443 const std::string income_string =
formatter() << (income_amt > 0 ?
"+" :
"") << income_amt <<
" " <<
_(
"Income");
445 item[
"label"] = income_string;
446 data.emplace(
"side_income", item);
453 auto* select_leader_button = &row_grid.
find_widget<
button>(
"select_leader",
false);
454 if(select_leader_button) {
455 if(side[
"player_id"] ==
prefs::get().
login() && side[
"allow_changes"].to_bool(
true)) {
462 const auto handler = [
this, side_num](
bool& handled,
bool& halt) {
470 handled = halt =
true;
479 if(income_amt == 0) {
498 if(
level_[
"started"].to_bool()) {
509 find_widget<chatbox>(
"chat").process_network_data(
data);
511 if(!
data[
"message"].empty()) {
515 if(
data[
"failed"].to_bool()) {
519 }
else if(
data.has_child(
"start_game")) {
524 }
else if(
data.has_child(
"leave_game")) {
530 if(
data.has_child(
"stop_updates")) {
532 }
else if(
auto c =
data.optional_child(
"scenario_diff")) {
537 }
else if(
auto change =
data.optional_child(
"change_controller")) {
538 if(
auto side_to_change =
get_scenario().find_child(
"side",
"side", change[
"side"])) {
539 side_to_change->merge_with(*change);
545 }
else if(
data.has_child(
"scenario") ||
data.has_child(
"snapshot") ||
data.has_child(
"next_scenario")) {
551 if(
data.has_child(
"turn")) {
552 ERR_MP <<
"received replay data\n" <<
data <<
"\n in mp join";
556 if(
data.has_child(
"user")) {
std::map< std::string, chatroom_log > default_chat_log
Variant for storing WML attributes.
A config object defines a single node in a WML file, with access to child nodes.
config & mandatory_child(config_key_type key, int n=0)
Returns the nth child with the given key, or throws an error if there is none.
bool has_child(config_key_type key) const
Determine whether a config has a child or not.
bool has_attribute(config_key_type key) const
child_itors child_range(config_key_type key)
void apply_diff(const config &diff, bool track=false)
A function to apply a diff config onto this config object.
boost::iterator_range< const_child_iterator > const_child_itors
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.
optional_config_impl< config > optional_child(config_key_type key, int n=0)
Equivalent to mandatory_child, but returns an empty optional if the nth child was not found.
config & add_child(config_key_type key)
bool is_normal_mp_game() const
static game_config_manager * get()
void load_game_config_for_game(const game_classification &classification, const std::string &scenario_id)
static game_config_view wrap(const config &cfg)
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.
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 active_window_changed()
static void progress(loading_stage stage=loading_stage::none)
Report what is being loaded to the loading screen.
static void display(std::function< void()> f)
Abstract base class for all modal dialogs.
bool show(const unsigned auto_close_time=0)
Shows the window.
int get_retval() const
Returns the cached window exit code.
void generate_side_list()
std::unique_ptr< player_list_helper > player_list_
std::size_t update_timer_
virtual void pre_show() override
Actions to be taken before showing the window.
const bool first_scenario_
faction_select * flg_dialog_
std::map< std::string, tree_view_node * > team_tree_map_
virtual void post_show() override
Actions to be taken after the window has been shown.
bool show_flg_select(int side_num, bool first_time=false)
void close_faction_select_dialog_if_open()
Will close the Faction Select dialog if it's open.
wesnothd_connection & network_connection_
std::unique_ptr< plugins_context > plugins_context_
tree_view_node & add_sibling(const std::string &id, const widget_data &data)
Adds a sibling for a node at the end of the list.
tree_view_node & add_node(const std::string &id, const widget_data &data, const int index=-1)
base class of top level items, the only item which needs to store the final canvases to draw on.
void set_enter_disabled(const bool enter_disabled)
Disable the enter key.
void set_retval(const int retval, const bool close_window=true)
Sets there return value of the window.
static const std::string & type()
Static type getter that does not rely on the widget being constructed.
void set_escape_disabled(const bool escape_disabled)
Disable the escape key.
FLG stands for faction, leader and gender.
const std::string & current_gender() const
const config & current_faction() const
const std::string & current_leader() const
game_classification & classification()
std::string get_scenario_id() const
static t_string from_serialized(const std::string &string)
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.
A single unit type that the player may recruit.
Data-based RAII scope guard.
A class that represents a TCP/IP connection to the wesnothd server.
bool receive_data(config &result)
Receives the next pending data pack from the server, if available.
bool wait_and_receive_data(config &data)
Unlike receive_data, waits until data is available instead of returning immediately.
static std::string _(const char *str)
Standard logging facilities (interface).
static lg::log_domain log_mp_connect_engine("mp/connect/engine")
const std::string unicode_em_dash
static void add_color_info(const game_config_view &v, bool build_defaults)
std::chrono::milliseconds lobby_network_timer
std::map< std::string, std::vector< color_t >, std::less<> > team_rgb_colors
static std::string generate_user_description(const config &side)
REGISTER_DIALOG(editor_edit_unit)
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button click.
std::size_t add_timer(const std::chrono::milliseconds &interval, const std::function< void(std::size_t id)> &callback, const bool repeat)
Adds a new timer.
std::map< std::string, widget_item > widget_data
std::map< std::string, t_string > widget_item
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.
bool remove_timer(const std::size_t id)
Removes a timer.
@ OK
Dialog was closed with the OK button.
@ CANCEL
Dialog was closed with the CANCEL button.
Functions to load and save images from/to disk.
std::string span_color(const color_t &color, Args &&... data)
void level_to_gamestate(const config &level, saved_game &state)
void send_to_server(const config &data)
Attempts to send given data to server if a connection is open.
const std::string random_enemy_picture("units/random-dice.png")
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.
static constexpr utils::optional< enum_type > get_enum(const std::string_view value)
Converts a string into its enum equivalent.
An error occurred during when trying to communicate with the wesnothd server.
Contains the gui2 timer routines.
unit_type_data unit_types