Added GUI2 MP Join Game dialog
Note the faction select dialog doesn't appear for some reason.
This commit is contained in:
parent
fe2e119b25
commit
45ea8c6a43
9 changed files with 1113 additions and 140 deletions
505
data/gui/window/mp_join_game.cfg
Normal file
505
data/gui/window/mp_join_game.cfg
Normal file
|
@ -0,0 +1,505 @@
|
|||
#textdomain wesnoth-lib
|
||||
###
|
||||
### Definition of the mp game staging screen
|
||||
###
|
||||
|
||||
#define _GUI_SIDE_LIST
|
||||
[listbox]
|
||||
id = "side_list"
|
||||
definition = "default"
|
||||
|
||||
vertical_scrollbar_mode = "always"
|
||||
horizontal_scrollbar_mode = "never"
|
||||
|
||||
[list_definition]
|
||||
|
||||
[row]
|
||||
|
||||
[column]
|
||||
horizontal_grow = "true"
|
||||
vertical_grow = "true"
|
||||
|
||||
[toggle_panel]
|
||||
id = "panel"
|
||||
definition = "default"
|
||||
|
||||
[grid]
|
||||
|
||||
[row]
|
||||
|
||||
[column]
|
||||
grow_factor = 0
|
||||
border = "all"
|
||||
border_size = 10
|
||||
horizontal_grow = "true"
|
||||
vertical_alignment = "top"
|
||||
|
||||
[label]
|
||||
id = "side_number"
|
||||
definition = "default_large"
|
||||
linked_group = "side_number"
|
||||
[/label]
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
horizontal_grow = "true"
|
||||
#vertical_grow = "true"
|
||||
|
||||
[grid]
|
||||
linked_group = "leader"
|
||||
|
||||
[row]
|
||||
|
||||
[column]
|
||||
grow_factor = 0
|
||||
horizontal_grow = "true"
|
||||
border = "all"
|
||||
border_size = 5
|
||||
|
||||
[image]
|
||||
id = "leader_image"
|
||||
definition = "default"
|
||||
[/image]
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
horizontal_grow = "true"
|
||||
vertical_grow = "true"
|
||||
|
||||
[grid]
|
||||
|
||||
[row]
|
||||
grow_factor = 1
|
||||
|
||||
[column]
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_grow = "true"
|
||||
vertical_grow = "true"
|
||||
|
||||
[label]
|
||||
id = "leader_type"
|
||||
definition = "default_large"
|
||||
use_markup = "true"
|
||||
[/label]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[row]
|
||||
grow_factor = 0
|
||||
|
||||
[column]
|
||||
horizontal_grow = "true"
|
||||
#vertical_grow = "true"
|
||||
|
||||
[grid]
|
||||
|
||||
[row]
|
||||
|
||||
[column]
|
||||
grow_factor = 0
|
||||
border = "left,bottom"
|
||||
border_size = 5
|
||||
|
||||
[label]
|
||||
definition = "default_small"
|
||||
label = _ "<b>Faction:</b>"
|
||||
use_markup = "true"
|
||||
[/label]
|
||||
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
border = "left,bottom,right"
|
||||
border_size = 5
|
||||
horizontal_grow = "true"
|
||||
vertical_grow = "true"
|
||||
|
||||
[label]
|
||||
id = "leader_faction"
|
||||
definition = "default_small"
|
||||
use_markup = "true"
|
||||
[/label]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[row]
|
||||
|
||||
[column]
|
||||
grow_factor = 0
|
||||
border = "left,bottom"
|
||||
border_size = 5
|
||||
|
||||
[label]
|
||||
definition = "default_small"
|
||||
label = _ "<b>Gender:</b>"
|
||||
use_markup = "true"
|
||||
[/label]
|
||||
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
border = "left,bottom,right"
|
||||
border_size = 5
|
||||
horizontal_grow = "true"
|
||||
vertical_grow = "true"
|
||||
|
||||
[image]
|
||||
id = "leader_gender"
|
||||
definition = "default_small"
|
||||
[/image]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/grid]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/grid]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/grid]
|
||||
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 0
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_grow = "true"
|
||||
|
||||
[label]
|
||||
id = "side_team"
|
||||
definition = "default"
|
||||
[/label]
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 0
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_grow = "true"
|
||||
|
||||
[label]
|
||||
id = "side_gold"
|
||||
definition = "default"
|
||||
[/label]
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 0
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_grow = "true"
|
||||
|
||||
[label]
|
||||
id = "side_income"
|
||||
definition = "default"
|
||||
[/label]
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 0
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_grow = "true"
|
||||
|
||||
[label]
|
||||
id = "side_color"
|
||||
definition = "default"
|
||||
[/label]
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/grid]
|
||||
|
||||
[/toggle_panel]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/list_definition]
|
||||
|
||||
[/listbox]
|
||||
#enddef
|
||||
|
||||
#define _GUI_CONTROL_AREA
|
||||
[grid]
|
||||
|
||||
[row]
|
||||
grow_factor = 1
|
||||
|
||||
[column]
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_grow = "true"
|
||||
vertical_grow = "true"
|
||||
|
||||
[listbox]
|
||||
id = "player_list"
|
||||
definition = "default"
|
||||
|
||||
horizontal_scrollbar_mode = "never"
|
||||
|
||||
[list_definition]
|
||||
|
||||
[row]
|
||||
|
||||
[column]
|
||||
horizontal_grow = "true"
|
||||
|
||||
[toggle_panel]
|
||||
id = "panel"
|
||||
definition = "default"
|
||||
|
||||
[grid]
|
||||
|
||||
[row]
|
||||
|
||||
[column]
|
||||
border = "all"
|
||||
border_size = 5
|
||||
horizontal_grow = "true"
|
||||
|
||||
[label]
|
||||
id = "player_name"
|
||||
definition = "default"
|
||||
[/label]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/grid]
|
||||
|
||||
[/toggle_panel]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/list_definition]
|
||||
|
||||
[/listbox]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[row]
|
||||
grow_factor = 0
|
||||
|
||||
[column]
|
||||
|
||||
[grid]
|
||||
|
||||
[row]
|
||||
|
||||
[column]
|
||||
border = "all"
|
||||
border_size = 5
|
||||
|
||||
[button]
|
||||
id = "ok"
|
||||
definition = "large"
|
||||
label = _ "I’m Ready"
|
||||
[/button]
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
border = "all"
|
||||
border_size = 5
|
||||
|
||||
[button]
|
||||
id = "cancel"
|
||||
definition = "large"
|
||||
label = _ "Cancel"
|
||||
[/button]
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/grid]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/grid]
|
||||
#enddef
|
||||
|
||||
[window]
|
||||
id = "mp_join_game"
|
||||
description = "MP join game."
|
||||
|
||||
[resolution]
|
||||
definition = "borderless"
|
||||
|
||||
{GUI_WINDOW_FULLSCREEN}
|
||||
|
||||
[linked_group]
|
||||
id = "side_number"
|
||||
fixed_width = "true"
|
||||
[/linked_group]
|
||||
|
||||
[linked_group]
|
||||
id = "controller"
|
||||
fixed_width = "true"
|
||||
[/linked_group]
|
||||
|
||||
[linked_group]
|
||||
id = "leader"
|
||||
fixed_width = "true"
|
||||
[/linked_group]
|
||||
|
||||
[linked_group]
|
||||
id = "team_and_color"
|
||||
fixed_width = "true"
|
||||
[/linked_group]
|
||||
|
||||
[linked_group]
|
||||
id = "gold_and_income"
|
||||
fixed_width = "true"
|
||||
[/linked_group]
|
||||
|
||||
[tooltip]
|
||||
id = "tooltip"
|
||||
[/tooltip]
|
||||
|
||||
[helptip]
|
||||
id = "tooltip"
|
||||
[/helptip]
|
||||
|
||||
[grid]
|
||||
|
||||
[row]
|
||||
grow_factor = 0
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
horizontal_alignment = "left"
|
||||
border = "all"
|
||||
border_size = 5
|
||||
|
||||
[label]
|
||||
id = "title"
|
||||
definition = "title"
|
||||
label = _ "Game Lobby"
|
||||
[/label]
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[row]
|
||||
grow_factor = 1
|
||||
|
||||
[column]
|
||||
horizontal_grow = "true"
|
||||
vertical_grow = "true"
|
||||
|
||||
[grid]
|
||||
|
||||
[row]
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
vertical_grow = "true"
|
||||
horizontal_grow = "true"
|
||||
|
||||
[grid]
|
||||
|
||||
[row]
|
||||
grow_factor = 1
|
||||
|
||||
[column]
|
||||
horizontal_grow = "true"
|
||||
vertical_grow = "true"
|
||||
|
||||
{GUI_FORCE_WIDGET_MINIMUM_SIZE 0 "((screen_height * 55) / 100)" (
|
||||
border = "all"
|
||||
border_size = 5
|
||||
{_GUI_SIDE_LIST}
|
||||
)}
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[row]
|
||||
grow_factor = 0
|
||||
|
||||
[column]
|
||||
grow_factor = 1
|
||||
horizontal_grow = "true"
|
||||
border = "all"
|
||||
border_size = 5
|
||||
|
||||
[label]
|
||||
id = "status_label"
|
||||
definition = "default_small"
|
||||
label = _ "Waiting for players to join..."
|
||||
[/label]
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[row]
|
||||
grow_factor = 0
|
||||
|
||||
[column]
|
||||
horizontal_grow = "true"
|
||||
vertical_grow = "true"
|
||||
|
||||
{GUI_FORCE_WIDGET_MINIMUM_SIZE 0 "((screen_height * 25 / 100))" (
|
||||
[chatbox]
|
||||
id = "chat"
|
||||
[/chatbox]
|
||||
)}
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/grid]
|
||||
|
||||
[/column]
|
||||
|
||||
[column]
|
||||
grow_factor = 0
|
||||
horizontal_grow = "true"
|
||||
vertical_grow = "true"
|
||||
|
||||
{_GUI_CONTROL_AREA}
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/grid]
|
||||
|
||||
[/column]
|
||||
|
||||
[/row]
|
||||
|
||||
[/grid]
|
||||
|
||||
[/resolution]
|
||||
|
||||
[/window]
|
||||
|
||||
#undef _GUI_CONTROL_AREA
|
||||
#undef _GUI_SIDE_LIST
|
|
@ -607,6 +607,8 @@
|
|||
<Unit filename="../../src/gui/dialogs/multiplayer/mp_create_game_set_password.hpp" />
|
||||
<Unit filename="../../src/gui/dialogs/multiplayer/mp_host_game_prompt.cpp" />
|
||||
<Unit filename="../../src/gui/dialogs/multiplayer/mp_host_game_prompt.hpp" />
|
||||
<Unit filename="../../src/gui/dialogs/multiplayer/mp_join_game.cpp" />
|
||||
<Unit filename="../../src/gui/dialogs/multiplayer/mp_join_game.hpp" />
|
||||
<Unit filename="../../src/gui/dialogs/multiplayer/mp_join_game_password_prompt.cpp" />
|
||||
<Unit filename="../../src/gui/dialogs/multiplayer/mp_join_game_password_prompt.hpp" />
|
||||
<Unit filename="../../src/gui/dialogs/multiplayer/mp_login.cpp" />
|
||||
|
|
|
@ -829,6 +829,7 @@ set(wesnoth-main_SRC
|
|||
gui/dialogs/multiplayer/mp_create_game.cpp
|
||||
gui/dialogs/multiplayer/mp_create_game_set_password.cpp
|
||||
gui/dialogs/multiplayer/mp_host_game_prompt.cpp
|
||||
gui/dialogs/multiplayer/mp_join_game.cpp
|
||||
gui/dialogs/multiplayer/mp_join_game_password_prompt.cpp
|
||||
gui/dialogs/multiplayer/mp_login.cpp
|
||||
gui/dialogs/multiplayer/mp_method_selection.cpp
|
||||
|
|
|
@ -404,6 +404,7 @@ wesnoth_sources = Split("""
|
|||
gui/dialogs/multiplayer/mp_create_game_set_password.cpp
|
||||
gui/dialogs/multiplayer/mp_create_game.cpp
|
||||
gui/dialogs/multiplayer/mp_host_game_prompt.cpp
|
||||
gui/dialogs/multiplayer/mp_join_game.cpp
|
||||
gui/dialogs/multiplayer/mp_join_game_password_prompt.cpp
|
||||
gui/dialogs/multiplayer/mp_login.cpp
|
||||
gui/dialogs/multiplayer/mp_method_selection.cpp
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "gui/dialogs/message.hpp"
|
||||
#include "gui/dialogs/multiplayer/mp_connect.hpp"
|
||||
#include "gui/dialogs/multiplayer/mp_create_game.hpp"
|
||||
#include "gui/dialogs/multiplayer/mp_join_game.hpp"
|
||||
#include "gui/dialogs/multiplayer/mp_login.hpp"
|
||||
#include "gui/dialogs/multiplayer/mp_staging.hpp"
|
||||
#include "gui/dialogs/network_transmission.hpp"
|
||||
|
@ -405,17 +406,6 @@ static std::unique_ptr<twesnothd_connection> open_connection(CVideo& video, cons
|
|||
// The functions enter_(screen)_mode are simple functions that take care of
|
||||
// creating the dialogs, then, according to the dialog result, of calling other
|
||||
// of those screen functions.
|
||||
|
||||
static config& get_scenario(config& c)
|
||||
{
|
||||
if(config& scenario = c.child("scenario"))
|
||||
return scenario;
|
||||
else if(config& snapshot = c.child("snapshot"))
|
||||
return snapshot;
|
||||
else
|
||||
return c;
|
||||
}
|
||||
|
||||
static void enter_wait_mode(CVideo& video, const config& game_config, saved_game& state, twesnothd_connection* wesnothd_connection,
|
||||
lobby_info& li, bool observe, int current_turn = 0)
|
||||
{
|
||||
|
@ -435,131 +425,8 @@ static void enter_wait_mode(CVideo& video, const config& game_config, saved_game
|
|||
|
||||
{
|
||||
if(preferences::new_lobby()) {
|
||||
bool download_res = true;
|
||||
|
||||
assert(wesnothd_connection);
|
||||
config level;
|
||||
DBG_MP << "download_level_data()\n";
|
||||
|
||||
if(!true) {
|
||||
// Ask for the next scenario data.
|
||||
wesnothd_connection->send_data(config("load_next_scenario"));
|
||||
}
|
||||
|
||||
bool has_scenario_and_controllers = false;
|
||||
while(!has_scenario_and_controllers) {
|
||||
config revc;
|
||||
bool data_res = gui2::tnetwork_transmission::wesnothd_receive_dialog(
|
||||
video, "download level data", revc, *wesnothd_connection);
|
||||
|
||||
if(!data_res) {
|
||||
DBG_MP << "download_level_data bad results\n";
|
||||
download_res = false;
|
||||
}
|
||||
|
||||
mp::check_response(data_res, revc);
|
||||
|
||||
if(revc.child("leave_game")) {
|
||||
download_res = false;
|
||||
} else if(config& next_scenario = revc.child("next_scenario")) {
|
||||
level.swap(next_scenario);
|
||||
} else if(revc.has_attribute("version")) {
|
||||
level.swap(revc);
|
||||
has_scenario_and_controllers = true;
|
||||
} else if(config& controllers = revc.child("controllers")) {
|
||||
int index = 0;
|
||||
for(const config& controller : controllers.child_range("controller")) {
|
||||
if(config& side = get_scenario(level).child("side", index)) {
|
||||
side["is_local"] = controller["is_local"];
|
||||
}
|
||||
++index;
|
||||
}
|
||||
has_scenario_and_controllers = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::cerr << "download_level_data() success.\n";
|
||||
|
||||
if(!download_res) {
|
||||
DBG_MP << "mp wait: could not download level data, quitting...";
|
||||
//set_result(QUIT);
|
||||
return;
|
||||
} else if(level["started"].to_bool()) {
|
||||
//set_result(PLAY);
|
||||
return;
|
||||
}
|
||||
|
||||
if(true) {
|
||||
state = saved_game();
|
||||
state.classification() = game_classification(level);
|
||||
|
||||
if(state.classification().campaign_type != game_classification::CAMPAIGN_TYPE::MULTIPLAYER) {
|
||||
//ERR_MP << "Mp wait recieved a game that is not a multiplayer game\n";
|
||||
}
|
||||
// Make sure that we have the same config as host, if possible.
|
||||
game_config_manager::get()->load_game_config_for_game(state.classification());
|
||||
}
|
||||
|
||||
// Add the map name to the title.
|
||||
//append_to_title(": " + get_scenario(level)["name"].t_str());
|
||||
|
||||
game_config::add_color_info(get_scenario(level));
|
||||
if(!observe) {
|
||||
//search for an appropriate vacant slot. If a description is set
|
||||
//(i.e. we're loading from a saved game), then prefer to get the side
|
||||
//with the same description as our login. Otherwise just choose the first
|
||||
//available side.
|
||||
const config *side_choice = nullptr;
|
||||
//int side_num = -1, nb_sides = 0;
|
||||
for(const config &sd : get_scenario(level).child_range("side")) {
|
||||
//std::cerr << "*** side " << nb_sides << "***\n" << sd.debug() << "***\n";
|
||||
|
||||
if(sd["controller"] == "reserved" && sd["current_player"] == preferences::login()) {
|
||||
side_choice = &sd;
|
||||
//side_num = nb_sides;
|
||||
break;
|
||||
}
|
||||
|
||||
if(sd["controller"] == "human" && sd["player_id"].empty()) {
|
||||
if(!side_choice) { // found the first empty side
|
||||
side_choice = &sd;
|
||||
//side_num = nb_sides;
|
||||
}
|
||||
|
||||
if(sd["current_player"] == preferences::login()) {
|
||||
side_choice = &sd;
|
||||
//side_num = nb_sides;
|
||||
break; // found the preferred one
|
||||
}
|
||||
}
|
||||
|
||||
if(sd["player_id"] == preferences::login()) {
|
||||
//We already own a side in this game.
|
||||
//generate_menu();
|
||||
return;
|
||||
}
|
||||
//++nb_sides;
|
||||
}
|
||||
|
||||
if(!side_choice) {
|
||||
DBG_MP << "could not find a side, all " << get_scenario(level).child_count("side") << " sides were unsuitable\n";
|
||||
//set_result(QUIT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mp::level_to_gamestate(level, state);
|
||||
|
||||
campaign_info.reset(new mp_campaign_info(*wesnothd_connection));
|
||||
|
||||
//campaign_info->connected_players.insert(li.users().begin(), li.users().end());
|
||||
|
||||
ng::connect_engine_ptr connect_engine(new ng::connect_engine(state, true, campaign_info.get()));
|
||||
|
||||
connect_engine->receive_from_server(level);
|
||||
|
||||
gui2::tmp_staging dlg(*connect_engine, li, wesnothd_connection);
|
||||
gui2::tmp_join_game dlg(state, li, *wesnothd_connection, true, observe);
|
||||
dlg.show(video);
|
||||
|
||||
if(dlg.get_retval() == gui2::twindow::OK) {
|
||||
|
@ -568,9 +435,9 @@ static void enter_wait_mode(CVideo& video, const config& game_config, saved_game
|
|||
controller.play_game();
|
||||
}
|
||||
|
||||
//if(wesnothd_connection) {
|
||||
// wesnothd_connection->send_data(config("leave_game"));
|
||||
//}
|
||||
if(wesnothd_connection) {
|
||||
wesnothd_connection->send_data(config("leave_game"));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
508
src/gui/dialogs/multiplayer/mp_join_game.cpp
Normal file
508
src/gui/dialogs/multiplayer/mp_join_game.cpp
Normal file
|
@ -0,0 +1,508 @@
|
|||
/*
|
||||
Copyright (C) 2008 - 2016 by the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#define GETTEXT_DOMAIN "wesnoth-lib"
|
||||
|
||||
#include "gui/dialogs/multiplayer/mp_join_game.hpp"
|
||||
|
||||
#include "config_assign.hpp"
|
||||
#include "formula/string_utils.hpp"
|
||||
#include "game_config_manager.hpp"
|
||||
#include "game_initialization/mp_game_utils.hpp"
|
||||
#include "game_preferences.hpp"
|
||||
#include "gettext.hpp"
|
||||
#include "gui/auxiliary/field.hpp"
|
||||
#include "gui/dialogs/helper.hpp"
|
||||
#include "gui/dialogs/message.hpp"
|
||||
#include "gui/dialogs/multiplayer/faction_select.hpp"
|
||||
#include "gui/dialogs/network_transmission.hpp"
|
||||
#include "gui/dialogs/transient_message.hpp"
|
||||
#include "gui/widgets/integer_selector.hpp"
|
||||
#include "gui/widgets/button.hpp"
|
||||
#include "gui/widgets/chatbox.hpp"
|
||||
#include "gui/widgets/menu_button.hpp"
|
||||
#include "gui/widgets/image.hpp"
|
||||
#ifdef GUI2_EXPERIMENTAL_LISTBOX
|
||||
#include "gui/widgets/list.hpp"
|
||||
#else
|
||||
#include "gui/widgets/listbox.hpp"
|
||||
#endif
|
||||
#include "gui/widgets/minimap.hpp"
|
||||
#include "gui/widgets/settings.hpp"
|
||||
#include "gui/widgets/label.hpp"
|
||||
#include "gui/widgets/slider.hpp"
|
||||
#include "gui/widgets/stacked_widget.hpp"
|
||||
#include "gui/widgets/status_label_helper.hpp"
|
||||
#include "gui/widgets/toggle_button.hpp"
|
||||
#include "gui/widgets/toggle_panel.hpp"
|
||||
#include "gui/widgets/text_box.hpp"
|
||||
#include "game_config.hpp"
|
||||
#include "mp_ui_alerts.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "statistics.hpp"
|
||||
#include "units/types.hpp"
|
||||
#include "formatter.hpp"
|
||||
#include "wesnothd_connection.hpp"
|
||||
|
||||
#ifdef GUI2_EXPERIMENTAL_LISTBOX
|
||||
#include "utils/functional.hpp"
|
||||
#endif
|
||||
|
||||
namespace gui2
|
||||
{
|
||||
|
||||
REGISTER_DIALOG(mp_join_game)
|
||||
|
||||
tmp_join_game::tmp_join_game(saved_game& state, lobby_info& lobby_info, twesnothd_connection& wesnothd_connection, const bool first_scenario, const bool observe_game)
|
||||
: level_()
|
||||
, state_(state)
|
||||
, lobby_info_(lobby_info)
|
||||
, wesnothd_connection_(wesnothd_connection)
|
||||
, update_timer_(0)
|
||||
, first_scenario_(first_scenario)
|
||||
, observe_game_(observe_game)
|
||||
, stop_updates_(false)
|
||||
{
|
||||
set_show_even_without_video(true);
|
||||
}
|
||||
|
||||
tmp_join_game::~tmp_join_game()
|
||||
{
|
||||
if(update_timer_ != 0) {
|
||||
remove_timer(update_timer_);
|
||||
update_timer_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch the selected game's config from the server and prompts an initial faction selection.
|
||||
*/
|
||||
void tmp_join_game::post_build(twindow& window)
|
||||
{
|
||||
// Ask for the next scenario data, if applicable
|
||||
if(!first_scenario_) {
|
||||
wesnothd_connection_.send_data(config("load_next_scenario"));
|
||||
}
|
||||
|
||||
bool has_scenario_and_controllers = false;
|
||||
while(!has_scenario_and_controllers) {
|
||||
config revc;
|
||||
const bool data_res = gui2::tnetwork_transmission::wesnothd_receive_dialog(
|
||||
window.video(), "download level data", revc, wesnothd_connection_);
|
||||
|
||||
if(!data_res) {
|
||||
window.set_retval(twindow::CANCEL);
|
||||
}
|
||||
|
||||
mp::check_response(data_res, revc);
|
||||
|
||||
if(revc.child("leave_game")) {
|
||||
window.set_retval(twindow::CANCEL);
|
||||
} else if(config& next_scenario = revc.child("next_scenario")) {
|
||||
level_.swap(next_scenario);
|
||||
} else if(revc.has_attribute("version")) {
|
||||
level_.swap(revc);
|
||||
|
||||
has_scenario_and_controllers = true;
|
||||
} else if(config& controllers = revc.child("controllers")) {
|
||||
int index = 0;
|
||||
for(const config& controller : controllers.child_range("controller")) {
|
||||
if(config& side = get_scenario().child("side", index)) {
|
||||
side["is_local"] = controller["is_local"];
|
||||
}
|
||||
++index;
|
||||
}
|
||||
|
||||
has_scenario_and_controllers = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(level_["started"].to_bool()) {
|
||||
window.set_retval(twindow::OK);
|
||||
}
|
||||
|
||||
if(first_scenario_) {
|
||||
state_ = saved_game();
|
||||
state_.classification() = game_classification(level_);
|
||||
|
||||
// Make sure that we have the same config as host, if possible.
|
||||
game_config_manager::get()->load_game_config_for_game(state_.classification());
|
||||
}
|
||||
|
||||
game_config::add_color_info(get_scenario());
|
||||
|
||||
// If we're just an observer, we don't need to find an appropriate side and set faction selection
|
||||
if(observe_game_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Search for an appropriate vacant slot. If a description is set (i.e. we're loading from a saved game),
|
||||
// then prefer to get the side with the same description as our login. Otherwise just choose the first
|
||||
// available side.
|
||||
const config* side_choice = nullptr;
|
||||
|
||||
int side_num = 0, nb_sides = 0;
|
||||
for(const config& side : get_scenario().child_range("side")) {
|
||||
if(side["controller"] == "reserved" && side["current_player"] == preferences::login()) {
|
||||
side_choice = &side;
|
||||
side_num = nb_sides;
|
||||
break;
|
||||
}
|
||||
|
||||
if(side["controller"] == "human" && side["player_id"].empty()) {
|
||||
if(!side_choice) { // Found the first empty side
|
||||
side_choice = &side;
|
||||
side_num = nb_sides;
|
||||
}
|
||||
|
||||
if(side["current_player"] == preferences::login()) {
|
||||
side_choice = &side;
|
||||
side_num = nb_sides;
|
||||
break; // Found the preferred one
|
||||
}
|
||||
}
|
||||
|
||||
if(side["player_id"] == preferences::login()) {
|
||||
// We already own a side in this game
|
||||
return;
|
||||
}
|
||||
|
||||
++nb_sides;
|
||||
}
|
||||
|
||||
if(!side_choice) {
|
||||
window.set_retval(twindow::CANCEL);
|
||||
}
|
||||
|
||||
const bool allow_choice = (*side_choice)["allow_changes"].to_bool(true);
|
||||
|
||||
// If the client is allowed to choose their team, do that here instead of having it set by the server
|
||||
if(allow_choice) {
|
||||
events::event_context context;
|
||||
|
||||
const config& era = level_.child("era");
|
||||
// TODO: Check whether we have the era. If we don't, inform the player
|
||||
if(!era) {
|
||||
throw config::error(_("No era information found."));
|
||||
}
|
||||
|
||||
config::const_child_itors possible_sides = era.child_range("multiplayer_side");
|
||||
if(possible_sides.empty()) {
|
||||
// TODO: is this set_retval needed?
|
||||
window.set_retval(twindow::CANCEL);
|
||||
|
||||
throw config::error(_("No multiplayer sides found"));
|
||||
}
|
||||
|
||||
const std::string color = (*side_choice)["color"].str();
|
||||
|
||||
std::vector<const config*> era_factions;
|
||||
for(const config& side : possible_sides) {
|
||||
era_factions.push_back(&side);
|
||||
}
|
||||
|
||||
const bool is_mp = state_.classification().is_normal_mp_game();
|
||||
const bool lock_settings = get_scenario()["force_lock_settings"].to_bool(!is_mp);
|
||||
const bool use_map_settings = level_.child("multiplayer")["mp_use_map_settings"].to_bool();
|
||||
const bool saved_game = level_.child("multiplayer")["savegame"].to_bool();
|
||||
|
||||
ng::flg_manager flg(era_factions, *side_choice, lock_settings, use_map_settings, saved_game);
|
||||
|
||||
// FIXME: this dialog doesn't show!
|
||||
gui2::tfaction_select dlg(flg, color, side_num);
|
||||
dlg.show(window.video());
|
||||
|
||||
if(dlg.get_retval() != gui2::twindow::OK) {
|
||||
window.set_retval(twindow::CANCEL);
|
||||
return;
|
||||
}
|
||||
|
||||
config faction;
|
||||
config& change = faction.add_child("change_faction");
|
||||
change["change_faction"] = true;
|
||||
change["name"] = preferences::login();
|
||||
change["faction"] = flg.current_faction()["id"];
|
||||
change["leader"] = flg.current_leader();
|
||||
change["gender"] = flg.current_gender();
|
||||
|
||||
wesnothd_connection_.send_data(faction);
|
||||
}
|
||||
}
|
||||
|
||||
static std::string generate_user_description(const config& side)
|
||||
{
|
||||
// Allow the host to override, since only the host knows the ai_algorithm.
|
||||
if(const config::attribute_value* desc = side.get("user_description")) {
|
||||
return desc->str();
|
||||
}
|
||||
|
||||
const std::string controller_type = side["controller"].str();
|
||||
const std::string reservation = side["reserved_for"].str();
|
||||
const std::string owner = side["player_id"].str();
|
||||
|
||||
if(controller_type == "ai") {
|
||||
return _("Computer Player");
|
||||
} else if(controller_type == "null") {
|
||||
return _("Empty slot");
|
||||
} else if(controller_type == "reserved") {
|
||||
return vgettext("Reserved for $playername", {{"playername", reservation}});
|
||||
} else if(owner.empty()) {
|
||||
return _("Vacant slot");
|
||||
} else if(controller_type == "human" || controller_type == "network") {
|
||||
return owner;
|
||||
} else {
|
||||
return _("empty");
|
||||
}
|
||||
}
|
||||
|
||||
void tmp_join_game::pre_show(twindow& window)
|
||||
{
|
||||
window.set_enter_disabled(true);
|
||||
|
||||
//
|
||||
// Set title
|
||||
//
|
||||
tlabel& title = find_widget<tlabel>(&window, "title", false);
|
||||
title.set_label((formatter() << title.label() << " " << utils::unicode_em_dash << " " << get_scenario()["name"].t_str()).str());
|
||||
|
||||
//
|
||||
// Set up sides list
|
||||
//
|
||||
generate_side_list(window);
|
||||
|
||||
//
|
||||
// Initialize chatbox and game rooms
|
||||
//
|
||||
tchatbox& chat = find_widget<tchatbox>(&window, "chat", false);
|
||||
|
||||
chat.set_lobby_info(lobby_info_);
|
||||
chat.set_wesnothd_connection(wesnothd_connection_);
|
||||
|
||||
chat.room_window_open("this game", true); // TODO: better title?
|
||||
chat.active_window_changed();
|
||||
|
||||
//
|
||||
// Set up player list
|
||||
//
|
||||
update_player_list(window);
|
||||
|
||||
//
|
||||
// Set up the network handling
|
||||
//
|
||||
update_timer_ = add_timer(game_config::lobby_network_timer, std::bind(&tmp_join_game::network_handler, this, std::ref(window)), true);
|
||||
|
||||
//
|
||||
// Set up the Lua plugin context
|
||||
//
|
||||
plugins_context_.reset(new plugins_context("Multiplayer Join Game"));
|
||||
|
||||
plugins_context_->set_callback("launch", [&window](const config&) { window.set_retval(twindow::OK); }, false);
|
||||
plugins_context_->set_callback("quit", [&window](const config&) { window.set_retval(twindow::CANCEL); }, false);
|
||||
plugins_context_->set_callback("chat", [&chat](const config& cfg) { chat.send_chat_message(cfg["message"], false); }, true);
|
||||
|
||||
// TODO: the old mp wait dialog didn't have an OK button. Evaluate if we want to add one. Hiding it for now
|
||||
find_widget<tbutton>(&window, "ok", false).set_visible(twidget::tvisible::hidden);
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't need the full widget setup as is done initially, just value setters.
|
||||
*/
|
||||
void tmp_join_game::generate_side_list(twindow& window)
|
||||
{
|
||||
if(stop_updates_) {
|
||||
return;
|
||||
}
|
||||
|
||||
tlistbox& list = find_widget<tlistbox>(&window, "side_list", false);
|
||||
|
||||
window.keyboard_capture(&list);
|
||||
|
||||
list.clear();
|
||||
|
||||
for(const auto& side : get_scenario().child_range("side")) {
|
||||
if(!side["allow_player"].to_bool(true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::map<std::string, string_map> data;
|
||||
string_map item;
|
||||
|
||||
item["label"] = side["side"];
|
||||
data.emplace("side_number", item);
|
||||
|
||||
std::string leader_image = ng::random_enemy_picture;
|
||||
std::string leader_type = side["type"];
|
||||
std::string leader_name;
|
||||
|
||||
const std::string leader_gender = side["gender"];
|
||||
|
||||
// If there is a unit which can recruit, use it as a leader.
|
||||
// Necessary to display leader information when loading saves.
|
||||
for(const config& side_unit : side.child_range("unit")) {
|
||||
if(side_unit["canrecruit"].to_bool()) {
|
||||
leader_type = side_unit["type"].str();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(const unit_type* ut = unit_types.find(leader_type)) {
|
||||
const unit_type& type = ut->get_gender_unit_type(leader_gender);
|
||||
|
||||
const std::string color = !side["color"].empty() ? side["color"] : side["side"].str();
|
||||
|
||||
leader_image = formatter() << type.image() << "~RC(" << type.flag_rgb() << ">" << color << ")";
|
||||
leader_name = type.type_name();
|
||||
}
|
||||
|
||||
item["label"] = leader_image;
|
||||
data.emplace("leader_image", item);
|
||||
|
||||
std::string description = generate_user_description(side);
|
||||
if(!leader_name.empty()) {
|
||||
description += formatter() << " (<i>" << leader_name << "</i>)";
|
||||
}
|
||||
|
||||
item["label"] = description;
|
||||
data.emplace("leader_type", item);
|
||||
|
||||
item["label"] = (formatter() << "<span color='#a69275'>" << side["faction_name"] << "</span>").str();
|
||||
data.emplace("leader_faction", item);
|
||||
|
||||
std::string gender_icon = "icons/icon-random.png";
|
||||
if(side["gender"] != "null") {
|
||||
gender_icon = formatter() << "icons/icon-" << leader_gender << ".png";
|
||||
}
|
||||
|
||||
item["label"] = gender_icon;
|
||||
item["tooltip"] = side["gender"];
|
||||
data.emplace("leader_gender", item);
|
||||
|
||||
item.clear();
|
||||
|
||||
// TODO: why this tstring stuff?
|
||||
item["label"] = t_string::from_serialized(side["user_team_name"].str());
|
||||
data.emplace("side_team", item);
|
||||
|
||||
// Don't show gold for saved games
|
||||
// TODO: gold icon
|
||||
if(side["allow_changes"].to_bool()) {
|
||||
item["label"] = side["gold"].str() + " " + "Gold";
|
||||
data.emplace("side_gold", item);
|
||||
}
|
||||
|
||||
const int income_amt = side["income"];
|
||||
if(income_amt != 0) {
|
||||
const std::string income_string = formatter() << (income_amt > 0 ? "+" : "") << income_amt << "Income";
|
||||
|
||||
item["label"] = income_string;
|
||||
data.emplace("side_income", item);
|
||||
}
|
||||
|
||||
// TODO: colorize
|
||||
item["label"] = side["color"];
|
||||
data.emplace("side_color", item);
|
||||
|
||||
list.add_row(data);
|
||||
}
|
||||
}
|
||||
|
||||
void tmp_join_game::update_player_list(twindow& window)
|
||||
{
|
||||
tlistbox& player_list = find_widget<tlistbox>(&window, "player_list", false);
|
||||
|
||||
player_list.clear();
|
||||
|
||||
for(const auto& side : get_scenario().child_range("side")) {
|
||||
std::map<std::string, string_map> data;
|
||||
string_map item;
|
||||
|
||||
item["label"] = side["player_id"];
|
||||
data.emplace("player_name", item);
|
||||
|
||||
player_list.add_row(data);
|
||||
}
|
||||
}
|
||||
|
||||
void tmp_join_game::network_handler(twindow& window)
|
||||
{
|
||||
config data;
|
||||
if(!wesnothd_connection_.receive_data(data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update chat
|
||||
find_widget<tchatbox>(&window, "chat", false).process_network_data(data);
|
||||
|
||||
if(!data["message"].empty()) {
|
||||
gui2::show_transient_message(window.video(), _("Response") , data["message"]);
|
||||
}
|
||||
|
||||
if(data["failed"].to_bool()) {
|
||||
window.set_retval(twindow::CANCEL);
|
||||
} else if(data.child("start_game")) {
|
||||
window.set_retval(twindow::OK);
|
||||
} else if(data.child("leave_game")) {
|
||||
window.set_retval(twindow::CANCEL);
|
||||
}
|
||||
|
||||
if(data.child("stop_updates")) {
|
||||
stop_updates_ = true;
|
||||
} else if(const config& c = data.child("scenario_diff")) {
|
||||
// TODO: We should catch config::error and then leave the game.
|
||||
level_.apply_diff(c);
|
||||
|
||||
generate_side_list(window);
|
||||
} else if(const config& change = data.child("change_controller")) {
|
||||
if(config& side_to_change = get_scenario().find_child("side", "side", change["side"])) {
|
||||
side_to_change.merge_with(change);
|
||||
}
|
||||
} else if(data.has_child("scenario") || data.has_child("snapshot") || data.child("next_scenario")) {
|
||||
level_ = first_scenario_ ? data : data.child("next_scenario");
|
||||
|
||||
generate_side_list(window);
|
||||
}
|
||||
|
||||
// Update player list
|
||||
// TODO: optimally, it wouldn't regenerate the entire list every single refresh cycle
|
||||
update_player_list(window);
|
||||
}
|
||||
|
||||
config& tmp_join_game::get_scenario()
|
||||
{
|
||||
if(config& scenario = level_.child("scenario")) {
|
||||
return scenario;
|
||||
} else if(config& snapshot = level_.child("snapshot")) {
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
return level_;
|
||||
}
|
||||
|
||||
void tmp_join_game::post_show(twindow& window)
|
||||
{
|
||||
if(window.get_retval() == twindow::OK) {
|
||||
if(const config& stats = level_.child("statistics")) {
|
||||
statistics::fresh_stats();
|
||||
statistics::read_stats(stats);
|
||||
}
|
||||
|
||||
mp::level_to_gamestate(level_, state_);
|
||||
|
||||
mp_ui_alerts::game_has_begun();
|
||||
} else {
|
||||
wesnothd_connection_.send_data(config("leave_game"));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gui2
|
87
src/gui/dialogs/multiplayer/mp_join_game.hpp
Normal file
87
src/gui/dialogs/multiplayer/mp_join_game.hpp
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
Copyright (C) 2008 - 2016 by the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#ifndef GUI_DIALOGS_MP_JOIN_GAME_HPP_INCLUDED
|
||||
#define GUI_DIALOGS_MP_JOIN_GAME_HPP_INCLUDED
|
||||
|
||||
#include "ai/configuration.hpp"
|
||||
#include "gui/dialogs/dialog.hpp"
|
||||
#include "gui/dialogs/lobby/info.hpp"
|
||||
#include "gui/dialogs/multiplayer/plugin_executor.hpp"
|
||||
|
||||
#include "game_initialization/connect_engine.hpp"
|
||||
#include "game_initialization/multiplayer.hpp"
|
||||
#include "mp_game_settings.hpp"
|
||||
|
||||
class config;
|
||||
|
||||
namespace gui2
|
||||
{
|
||||
|
||||
class ttoggle_button;
|
||||
class ttoggle_panel;
|
||||
class tslider;
|
||||
class tlabel;
|
||||
class tmenu_button;
|
||||
class twidget;
|
||||
|
||||
class tmp_join_game : public tdialog, private plugin_executor
|
||||
{
|
||||
public:
|
||||
tmp_join_game(saved_game& state, lobby_info& lobby_info, twesnothd_connection& wesnothd_connection,
|
||||
const bool first_scenario = true, const bool observe_game = false);
|
||||
|
||||
~tmp_join_game();
|
||||
|
||||
private:
|
||||
/** Inherited from tdialog, implemented by REGISTER_DIALOG. */
|
||||
virtual const std::string& window_id() const;
|
||||
|
||||
/** Inherited from tdialog. */
|
||||
void post_build(twindow& window);
|
||||
|
||||
/** Inherited from tdialog. */
|
||||
void pre_show(twindow& window);
|
||||
|
||||
/** Inherited from tdialog. */
|
||||
void post_show(twindow& window);
|
||||
|
||||
void generate_side_list(twindow& window);
|
||||
|
||||
void update_player_list(twindow& window);
|
||||
|
||||
void update_leader_display(ng::side_engine& side, tgrid& row_grid);
|
||||
|
||||
void network_handler(twindow& window);
|
||||
|
||||
config& get_scenario();
|
||||
|
||||
config level_;
|
||||
|
||||
saved_game& state_;
|
||||
|
||||
lobby_info& lobby_info_;
|
||||
|
||||
twesnothd_connection& wesnothd_connection_;
|
||||
|
||||
size_t update_timer_;
|
||||
|
||||
const bool first_scenario_;
|
||||
const bool observe_game_;
|
||||
|
||||
bool stop_updates_;
|
||||
};
|
||||
|
||||
} // namespace gui2
|
||||
|
||||
#endif
|
|
@ -468,8 +468,7 @@ void tmp_staging::post_show(twindow& window)
|
|||
{
|
||||
if(window.get_retval() == twindow::OK) {
|
||||
connect_engine_.start_game();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
connect_engine_.leave_game();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
#include "gui/dialogs/multiplayer/mp_connect.hpp"
|
||||
#include "gui/dialogs/multiplayer/mp_create_game.hpp"
|
||||
#include "gui/dialogs/multiplayer/mp_create_game_set_password.hpp"
|
||||
#include "gui/dialogs/multiplayer/mp_join_game.hpp"
|
||||
#include "gui/dialogs/multiplayer/mp_join_game_password_prompt.hpp"
|
||||
#include "gui/dialogs/multiplayer/mp_staging.hpp"
|
||||
#include "gui/dialogs/depcheck_confirm_change.hpp"
|
||||
|
@ -410,6 +411,7 @@ BOOST_AUTO_TEST_CASE(test_gui2)
|
|||
test<gui2::tmp_connect>();
|
||||
//test<gui2::tmp_create_game>();
|
||||
test<gui2::tmp_create_game_set_password>();
|
||||
test<gui2::tmp_join_game>();
|
||||
test<gui2::tmp_join_game_password_prompt>();
|
||||
test<gui2::tdepcheck_confirm_change>();
|
||||
test<gui2::tdepcheck_select_new>();
|
||||
|
@ -486,6 +488,7 @@ BOOST_AUTO_TEST_CASE(test_gui2)
|
|||
"title_screen",
|
||||
"end_credits",
|
||||
"mp_staging",
|
||||
"mp_join_game",
|
||||
};
|
||||
std::sort(list.begin(), list.end());
|
||||
std::sort(omitted.begin(), omitted.end());
|
||||
|
|
Loading…
Add table
Reference in a new issue