From 610c844a7cc0c04380ad23ff363670eac9710d02 Mon Sep 17 00:00:00 2001 From: loonycyborg Date: Tue, 26 Jan 2016 02:13:12 +0300 Subject: [PATCH] Ensure that games are always deleted when all players log off --- src/server/server.cpp | 57 +++++++++++++++++++++++-------------------- src/server/server.hpp | 1 + 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/server/server.cpp b/src/server/server.cpp index ff2c635a1401..21bad876ba64 100644 --- a/src/server/server.cpp +++ b/src/server/server.cpp @@ -1266,7 +1266,9 @@ void server::create_game(PlayerRecord& host_record, simple_wml::node& create_gam // Create the new game, remove the player from the lobby // and set the player as the host/owner. - host_record.get_game().reset(new wesnothd::game(player_connections_, host_record.socket(), game_name, save_replays_, replay_save_path_)); + host_record.get_game().reset( + new wesnothd::game(player_connections_, host_record.socket(), game_name, save_replays_, replay_save_path_), + boost::bind(&server::cleanup_game, this, _1)); wesnothd::game& g = *host_record.get_game(); if(game_password.empty() == false) { g.set_password(game_password); @@ -1275,6 +1277,34 @@ void server::create_game(PlayerRecord& host_record, simple_wml::node& create_gam create_game.copy_into(g.level().root()); } +void server::cleanup_game(game* game_ptr) +{ + metrics_.game_terminated(game_ptr->termination_reason()); + + simple_wml::node* const gamelist = games_and_users_list_.child("gamelist"); + assert(gamelist != NULL); + + // Send a diff of the gamelist with the game deleted to players in the lobby + simple_wml::document diff; + if(make_delete_diff(*gamelist, "gamelist", "game", + game_ptr->description(), diff)) { + send_to_lobby(diff); + } + + // Delete the game from the games_and_users_list_. + const simple_wml::node::child_list& games = gamelist->children("game"); + const simple_wml::node::child_list::const_iterator g = + std::find(games.begin(), games.end(), game_ptr->description()); + if (g != games.end()) { + const size_t index = g - games.begin(); + gamelist->remove_child("game", index); + } else { + // Can happen when the game ends before the scenario was transferred. + LOG_SERVER << "Could not find game (" << game_ptr->id() + << ") to delete in games_and_users_list_.\n"; + } +} + void server::handle_join_game(socket_ptr socket, simple_wml::node& join) { const bool observer = join.attr("observe").to_bool(); @@ -3472,31 +3502,6 @@ void server::process_data_game(const network::connection sock, void server::delete_game(int gameid) { const boost::shared_ptr& game_ptr = player_connections_.get().find(gameid)->get_game(); - metrics_.game_terminated(game_ptr->termination_reason()); - - simple_wml::node* const gamelist = games_and_users_list_.child("gamelist"); - assert(gamelist != NULL); - - // Send a diff of the gamelist with the game deleted to players in the lobby - simple_wml::document diff; - if(make_delete_diff(*gamelist, "gamelist", "game", - game_ptr->description(), diff)) { - send_to_lobby(diff); - } - - // Delete the game from the games_and_users_list_. - const simple_wml::node::child_list& games = gamelist->children("game"); - const simple_wml::node::child_list::const_iterator g = - std::find(games.begin(), games.end(), game_ptr->description()); - if (g != games.end()) { - const size_t index = g - games.begin(); - gamelist->remove_child("game", index); - } else { - // Can happen when the game ends before the scenario was transferred. - LOG_SERVER << "Could not find game (" << game_ptr->id() - << ") to delete in games_and_users_list_.\n"; - } - // Set the availability status for all quitting users. FOREACH(const AUTO& user, player_connections_.get().equal_range(gameid)) { user.info().mark_available(); diff --git a/src/server/server.hpp b/src/server/server.hpp index d4ca0248fd05..7329d90e2b60 100644 --- a/src/server/server.hpp +++ b/src/server/server.hpp @@ -70,6 +70,7 @@ class server void handle_message(socket_ptr socket, simple_wml::node& message); void handle_create_game(socket_ptr socket, simple_wml::node& create_game); void create_game(PlayerRecord& host, simple_wml::node& create_game); + void cleanup_game(game*); // deleter for shared_ptr void handle_join_game(socket_ptr socket, simple_wml::node& join); void remove_player(socket_ptr socket);