Skip to content

Commit 92300c0

Browse files
committed
Add error handling if queue has content not know by the client
Old situation: * unknown scenario - defaults to aethermaw * unknown era - crash * unknown modification - ignored and game continues without it New situation: all three possibilities now kick the player back to the MP lobby with an error message stating what wasn't found.
1 parent 49c30bd commit 92300c0

6 files changed

Lines changed: 57 additions & 6 deletions

File tree

src/game_initialization/create_engine.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -371,9 +371,9 @@ void create_engine::prepare_for_new_level()
371371
state_.expand_random_scenario();
372372
}
373373

374-
void create_engine::prepare_for_era_and_mods()
374+
void create_engine::prepare_for_era_and_mods(const std::string era_id)
375375
{
376-
get_parameters();
376+
get_parameters(era_id);
377377
state_.classification().era_define = game_config_.find_mandatory_child("era", "id", state_.classification().era_id)["define"].str();
378378
for(const std::string& mod_id : state_.classification().active_mods) {
379379
state_.classification().mod_defines.push_back(game_config_.find_mandatory_child("modification", "id", mod_id)["define"].str());
@@ -648,11 +648,16 @@ const config& create_engine::curent_era_cfg() const
648648
return *eras_[era_index]->cfg;
649649
}
650650

651-
const mp_game_settings& create_engine::get_parameters()
651+
const mp_game_settings& create_engine::get_parameters(const std::string era_id)
652652
{
653653
DBG_MP << "getting parameter values";
654654

655655
int era_index = current_level().allow_era_choice() ? current_era_index_ : 0;
656+
// in case of joining a server queue with an unknown era
657+
// the depcheck's get_era_index() returns -1 when not found
658+
if(era_index == -1) {
659+
throw config::error(_("Era not found: ")+era_id);
660+
}
656661
state_.classification().era_id = eras_[era_index]->id;
657662
state_.mp_settings().mp_era_name = eras_[era_index]->name;
658663

src/game_initialization/create_engine.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ class create_engine
289289
void init_generated_level_data();
290290

291291
void prepare_for_new_level();
292-
void prepare_for_era_and_mods();
292+
void prepare_for_era_and_mods(const std::string era_id = "");
293293
void prepare_for_scenario();
294294
void prepare_for_campaign(const std::string& difficulty = "");
295295
void prepare_for_saved_game();
@@ -387,7 +387,7 @@ class create_engine
387387
std::vector<std::string>& active_mods();
388388
std::vector<extras_metadata_ptr> active_mods_data();
389389

390-
const mp_game_settings& get_parameters();
390+
const mp_game_settings& get_parameters(const std::string era_id = "");
391391

392392
saved_game& get_state();
393393

src/game_initialization/multiplayer.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,10 @@ bool mp_manager::enter_lobby_mode()
584584
gui2::show_error_message(error.message);
585585
}
586586

587+
if(dlg_retval == gui2::dialogs::mp_lobby::CREATE_PRESET) {
588+
connection->send_data(config{"queue_game_create_failure", config{"reason", error.message, "queue_id", queue_id}});
589+
}
590+
587591
// Update lobby content
588592
connection->send_data(config{"refresh_lobby"});
589593
}

src/gui/dialogs/multiplayer/mp_create_game.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,16 +156,21 @@ void mp_create_game::quick_mp_setup(saved_game& state, const config presets)
156156
// from pre_show
157157
create.set_current_level_type(level_type::type::scenario);
158158
const auto& levels = create.get_levels_by_type(level_type::type::scenario);
159+
bool found_scenario = false;
159160
for(std::size_t i = 0; i < levels.size(); i++) {
160161
if(levels[i]->id() == presets["scenario"].str()) {
161162
create.set_current_level(i);
163+
found_scenario = true;
162164
}
163165
}
166+
if(!found_scenario) {
167+
throw config::error(_("Scenario not found: ")+presets["scenario"].str());
168+
}
164169

165170
create.set_current_era_id(presets["era"]);
166171

167172
// from post_show
168-
create.prepare_for_era_and_mods();
173+
create.prepare_for_era_and_mods(presets["era"]);
169174
create.prepare_for_scenario();
170175
create.get_parameters();
171176
create.prepare_for_new_level();
@@ -224,6 +229,13 @@ void mp_create_game::quick_mp_setup(saved_game& state, const config presets)
224229
params.name = settings::game_name_default();
225230

226231
for(const std::string& mod : utils::split(presets["modifications"].str())) {
232+
std::vector<std::string> missing_mods;
233+
if(!game_config_manager::get()->game_config().find_child("modification", "id", mod)) {
234+
missing_mods.emplace_back(mod);
235+
}
236+
if(!missing_mods.empty()) {
237+
throw config::error(_("Modification(s) not found: ")+utils::join(missing_mods));
238+
}
227239
create.active_mods().push_back(mod);
228240
}
229241

src/server/wesnothd/server.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "serialization/string_utils.hpp"
3131
#include "serialization/unicode.hpp"
3232
#include "utils/charconv.hpp"
33+
#include "utils/general.hpp"
3334
#include "utils/iterable_pair.hpp"
3435
#include "game_version.hpp"
3536

@@ -1251,6 +1252,11 @@ void server::handle_player_in_lobby(player_iterator player, simple_wml::document
12511252
return;
12521253
}
12531254

1255+
if(simple_wml::node* join_server_queue = data.child("queue_game_create_failure")) {
1256+
handle_server_queue_create_failure(player, *join_server_queue);
1257+
return;
1258+
}
1259+
12541260
if(simple_wml::node* leave_server_queue = data.child("leave_server_queue")) {
12551261
handle_leave_server_queue(player, *leave_server_queue);
12561262
return;
@@ -1759,6 +1765,29 @@ void server::handle_join_server_queue(player_iterator p, simple_wml::node& data)
17591765
}
17601766
}
17611767

1768+
void server::handle_server_queue_create_failure(player_iterator p, simple_wml::node& data)
1769+
{
1770+
int queue_id = data.attr("queue_id").to_int();
1771+
1772+
if(queue_info_.count(queue_id) == 0) {
1773+
ERR_SERVER << "attempted to remove " << p->info().name() << " from non-existing server-side queue " << data.attr("queue_id");
1774+
return;
1775+
}
1776+
1777+
queue_info& queue = queue_info_.at(queue_id);
1778+
if(!utils::contains(queue.players_in_queue, p->info().name())) {
1779+
DBG_SERVER << "player " << p->info().name() << " already not in server-side queue " << data.attr("queue_id");
1780+
return;
1781+
}
1782+
1783+
// if they're in the queue, remove them
1784+
utils::erase(queue.players_in_queue, p->info().name());
1785+
p->info().remove_from_queue(queue.id);
1786+
LOG_SERVER << p->client_ip() << "\t" << p->name() << "\tremoving from " << queue.settings["scenario"] << " due to reason " << data.attr("reason");
1787+
1788+
send_queue_update(queue);
1789+
}
1790+
17621791
void server::handle_leave_server_queue(player_iterator p, simple_wml::node& data)
17631792
{
17641793
int queue_id = data.attr("queue_id").to_int();

src/server/wesnothd/server.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class server : public server_base
6969
void cleanup_game(game*); // deleter for shared_ptr
7070
void handle_join_game(player_iterator player, simple_wml::node& join);
7171
void handle_join_server_queue(player_iterator p, simple_wml::node& data);
72+
void handle_server_queue_create_failure(player_iterator p, simple_wml::node& data);
7273
void handle_leave_server_queue(player_iterator p, simple_wml::node& data);
7374
void disconnect_player(player_iterator player);
7475
void remove_player(player_iterator player);

0 commit comments

Comments
 (0)