MP Join Game: cleaned up implementation of the recent players-choose-factions changes

This commit is contained in:
Charles Dang 2018-06-30 17:20:11 +11:00
parent a2a4dff050
commit fa01fb14d2
4 changed files with 58 additions and 60 deletions

View file

@ -51,19 +51,11 @@ faction_select::faction_select(ng::flg_manager& flg_manager, const std::string&
, last_faction_(flg_manager.current_faction_index())
, last_leader_(flg_manager.current_leader_index())
, last_gender_(flg_manager.current_gender_index())
, w_(nullptr)
{
}
void faction_select::cancel()
{
if(w_) {
w_->set_retval(retval::CANCEL);
}
}
void faction_select::pre_show(window& window)
{
w_ = &window;
find_widget<label>(&window, "starting_pos", false).set_label(std::to_string(side_));
//

View file

@ -32,13 +32,11 @@ public:
DEFINE_SIMPLE_EXECUTE_WRAPPER(faction_select)
void cancel();
int get_side_num() const { return side_; }
private:
ng::flg_manager& flg_manager_;
const std::string tc_color_;
const std::string tc_color_;
const int side_;
@ -46,7 +44,6 @@ private:
const int last_faction_, last_leader_, last_gender_;
gui2::window* w_;
/** Inherited from modal_dialog, implemented by REGISTER_DIALOG. */
virtual const std::string& window_id() const override;

View file

@ -74,8 +74,7 @@ mp_join_game::mp_join_game(saved_game& state, mp::lobby_info& lobby_info, wesnot
, observe_game_(observe_game)
, stop_updates_(false)
, player_list_(nullptr)
, open_flg_dialog_(nullptr)
, flg_button_callback_timer_id_(0)
, flg_dialog_(nullptr)
{
set_show_even_without_video(true);
}
@ -86,10 +85,6 @@ mp_join_game::~mp_join_game()
remove_timer(update_timer_);
update_timer_ = 0;
}
if(flg_button_callback_timer_id_ != 0) {
remove_timer(flg_button_callback_timer_id_);
flg_button_callback_timer_id_ = 0;
}
}
/*
@ -285,6 +280,7 @@ bool mp_join_game::show_flg_select(int side_num)
if(!side_choice["allow_changes"].to_bool(true)) {
return true;
}
const config& era = level_.child("era");
if(!era) {
ERR_MP << "no era information\n";
@ -313,16 +309,20 @@ bool mp_join_game::show_flg_select(int side_num)
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);
gui2::dialogs::faction_select dlg(flg, color, side_num);
{
open_flg_dialog_ = &dlg;
utils::scope_exit se([this](){ open_flg_dialog_ = nullptr; });
dlg.show();
}
// Create a new Faction Select dialog. We use a smart pointer here instead of creating
// a new scoped object on the stack since other functions (such as network_handler())
// need to acces the dialog object while its open.
flg_dialog_.reset(new gui2::dialogs::faction_select(flg, color, side_num));
if(dlg.get_retval() != gui2::retval::OK) {
return true;
// Destroy the dialog object completely on scope exit.
// Using scope_exit ensured this happens even if the dialog throws an exception.
utils::scope_exit se([this]() { flg_dialog_.reset(); });
if(!flg_dialog_->show()) {
return true;
}
}
config faction;
@ -332,11 +332,12 @@ bool mp_join_game::show_flg_select(int side_num)
change["faction"] = flg.current_faction()["id"];
change["leader"] = flg.current_leader();
change["gender"] = flg.current_gender();
//TODO: the host cannot yet handle this and always uses the first side owned by that player.
// TODO: the host cannot yet handle this and always uses the first side owned by that player.
change["side_num"] = side_num;
network_connection_.send_data(faction);
}
return true;
}
@ -452,23 +453,19 @@ void mp_join_game::generate_side_list(window& window)
auto* select_leader_button = find_widget<button>(&row_grid, "select_leader", false, false);
if(select_leader_button) {
if(side["player_id"] == preferences::login() && side["allow_changes"].to_bool(true)) {
auto handler = [this, side_num](){
if(flg_button_callback_timer_id_ != 0) {
remove_timer(flg_button_callback_timer_id_);
flg_button_callback_timer_id_ = 0;
}
if(flg_button_callback_timer_id_ == 0) {
auto real_handler = [this, side_num](size_t /*timer_id*/ ) {
show_flg_select(side_num);
//we cannot remoe the timer here as we are currently executing the timers handler.
};
//don't call this now but in a seperate callstack since the widget might be recreates while the dialog is open.
flg_button_callback_timer_id_ = add_timer(0, real_handler, /*repeat=*/false);
}
//
// Small wrapper function in order to set the handled and halt parameters and prevent
// crashes in case the dialog closes and the original button to which the callback was
// bound had already been destroyed. The other use of show_flg_select doesn't need these
// parameters, so it's easier not to declare them as function arguments.
//
const auto handler = [this, side_num](bool& handled, bool& halt) {
show_flg_select(side_num);
handled = halt = true;
};
connect_signal_mouse_left_click(*select_leader_button, std::bind(handler));
}
else {
connect_signal_mouse_left_click(*select_leader_button, std::bind(handler, _3, _4));
} else {
select_leader_button->set_visible(widget::visibility::hidden);
}
}
@ -480,6 +477,15 @@ void mp_join_game::generate_side_list(window& window)
}
}
void mp_join_game::close_faction_select_dialog_if_open()
{
if(flg_dialog_) {
if(window* w = flg_dialog_->get_window()) {
w->set_retval(retval::CANCEL);
}
}
}
void mp_join_game::network_handler(window& window)
{
// If the game has already started, close the dialog immediately.
@ -501,20 +507,17 @@ void mp_join_game::network_handler(window& window)
}
if(data["failed"].to_bool()) {
if(open_flg_dialog_) {
open_flg_dialog_->cancel();
}
close_faction_select_dialog_if_open();
window.set_retval(retval::CANCEL);
} else if(data.child("start_game")) {
if(open_flg_dialog_) {
open_flg_dialog_->cancel();
}
close_faction_select_dialog_if_open();
level_["started"] = true;
window.set_retval(retval::OK);
} else if(data.child("leave_game")) {
if(open_flg_dialog_) {
open_flg_dialog_->cancel();
}
close_faction_select_dialog_if_open();
window.set_retval(retval::CANCEL);
}
@ -529,10 +532,10 @@ void mp_join_game::network_handler(window& window)
if(config& side_to_change = get_scenario().find_child("side", "side", change["side"])) {
side_to_change.merge_with(change);
}
if(open_flg_dialog_ && open_flg_dialog_->get_side_num() == change["side"].to_int()) {
open_flg_dialog_->cancel();
}
if(flg_dialog_ && flg_dialog_->get_side_num() == change["side"].to_int()) {
close_faction_select_dialog_if_open();
}
} else if(data.has_child("scenario") || data.has_child("snapshot") || data.child("next_scenario")) {
level_ = first_scenario_ ? data : data.child("next_scenario");

View file

@ -25,13 +25,10 @@ class config;
namespace gui2
{
class tree_view_node;
namespace dialogs
{
class faction_select;
class mp_join_game : public modal_dialog, private plugin_executor
{
public:
@ -57,6 +54,17 @@ private:
void generate_side_list(window& window);
/**
* Will close the Faction Select dialog if it's open.
*
* This is used in @ref network_handler to dismiss the dialog if certain actions
* occur, such as the game starting.
*
* @todo maybe move this to a general-purpose close() function in @ref modal_dialog
* and @ref modeless_dialog? It could be useful.
*/
void close_faction_select_dialog_if_open();
void network_handler(window& window);
config& get_scenario();
@ -80,9 +88,7 @@ private:
std::unique_ptr<player_list_helper> player_list_;
gui2::dialogs::faction_select* open_flg_dialog_;
std::size_t flg_button_callback_timer_id_;
std::unique_ptr<class faction_select> flg_dialog_;
};
} // namespace dialogs