diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c504a738b85..97f9fcf9a05 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -425,6 +425,7 @@ SET(wesnothd_SRC server/player_network.cpp server/proxy.cpp server/room.cpp + server/room_manager.cpp server/server.cpp server/simple_wml.cpp server/user_handler.cpp diff --git a/src/Makefile.am b/src/Makefile.am index b689917b2a7..c0bf4f2250b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -250,6 +250,7 @@ wesnothd_SOURCES = \ server/player_network.cpp \ server/proxy.cpp \ server/room.cpp \ + server/room_manager.cpp \ server/server.cpp \ server/simple_wml.cpp \ server/user_handler.cpp \ diff --git a/src/SConscript b/src/SConscript index 0d393cbf25e..22891c7bc1d 100644 --- a/src/SConscript +++ b/src/SConscript @@ -364,6 +364,7 @@ wesnothd_sources = Split(""" server/player_network.cpp server/proxy.cpp server/room.cpp + server/room_manager.cpp server/sample_user_handler.cpp server/simple_wml.cpp server/user_handler.cpp diff --git a/src/server/player.cpp b/src/server/player.cpp index dc1e319ee8e..cba2803ed35 100644 --- a/src/server/player.cpp +++ b/src/server/player.cpp @@ -16,8 +16,9 @@ #include "player.hpp" -player::player(const std::string& n, simple_wml::node& cfg, bool registered, - const size_t max_messages, const size_t time_period, const bool sp) +wesnothd::player::player(const std::string& n, simple_wml::node& cfg, + bool registered, const size_t max_messages, + const size_t time_period, const bool sp) : name_(n) , cfg_(cfg) , selective_ping_(sp) @@ -33,19 +34,22 @@ player::player(const std::string& n, simple_wml::node& cfg, bool registered, } // keep 'available' and game name ('location') for backward compatibility -void player::mark_available(const int game_id, const std::string location) +void wesnothd::player::mark_available(const int game_id, + const std::string location) { cfg_.set_attr("available", (game_id == 0) ? "yes" : "no"); cfg_.set_attr_dup("game_id", lexical_cast(game_id).c_str()); cfg_.set_attr_dup("location", location.c_str()); } -void player::mark_registered(bool registered) { +void wesnothd::player::mark_registered(bool registered) +{ cfg_.set_attr("registered", registered ? "yes" : "no"); registered_ = registered; } -bool player::is_message_flooding() { +bool wesnothd::player::is_message_flooding() +{ const time_t now = time(NULL); if (flood_start_ == 0) { flood_start_ = now; @@ -60,6 +64,5 @@ bool player::is_message_flooding() { } else if (messages_since_flood_start_ == MaxMessages) { return true; } - return false; } diff --git a/src/server/player.hpp b/src/server/player.hpp index 222284c5a00..e868926937a 100644 --- a/src/server/player.hpp +++ b/src/server/player.hpp @@ -15,13 +15,18 @@ #ifndef PLAYER_HPP_INCLUDED #define PLAYER_HPP_INCLUDED -#include #include "../config.hpp" #include "simple_wml.hpp" +#include +#include #include +namespace wesnothd { + +class game; + class player { public: @@ -43,6 +48,19 @@ public: bool silenced() const { return messages_since_flood_start_ > MaxMessages; } bool is_message_flooding(); + /** + * @return true iff the player is in a game + */ + bool in_game() const { return get_game() != NULL; } + + /** + * @return a pointer to the game the player is in, or NULL if he/she is not + * in a game at the moment + */ + const game* get_game() const; + + void set_game(game* g); + private: const std::string name_; simple_wml::node& cfg_; @@ -54,6 +72,9 @@ private: unsigned int messages_since_flood_start_; const size_t MaxMessages; const time_t TimePeriod; + game* game_; }; +} //namespace wesnothd + #endif diff --git a/src/server/room.cpp b/src/server/room.cpp index 4330f3a68c4..291f476cc35 100644 --- a/src/server/room.cpp +++ b/src/server/room.cpp @@ -25,11 +25,16 @@ static lg::log_domain log_server("server"); namespace wesnothd { -room::room() - : members_() +room::room(const std::string& name) + : members_(), name_(name) { } +const std::string& room::name() const +{ + return name_; +} + bool room::add_player(network::connection player) { if (is_member(player)) { @@ -98,33 +103,6 @@ void room::send_server_message(const char* message, void room::process_message(simple_wml::document& data, const player_map::iterator user) { - if (user->second.silenced()) { - return; - } else if (user->second.is_message_flooding()) { - send_server_message( - "Warning: you are sending too many messages too fast. " - "Your message has not been relayed.", user->first); - return; - } - - simple_wml::node* const message = data.root().child("message"); - assert(message); - message->set_attr_dup("sender", user->second.name().c_str()); - - const simple_wml::string_span& msg = (*message)["message"]; - chat_message::truncate_message(msg, *message); - - if (msg.size() >= 3 && simple_wml::string_span(msg.begin(), 4) == "/me ") { - LOG_ROOM << network::ip_address(user->first) - << "\t<" << user->second.name() - << simple_wml::string_span(msg.begin() + 3, msg.size() - 3) - << ">\n"; - } else { - LOG_ROOM << network::ip_address(user->first) << "\t<" - << user->second.name() << "> " << msg << "\n"; - } - - send_data(data, user->first, "message"); } } //end namespace wesnothd diff --git a/src/server/room.hpp b/src/server/room.hpp index 700cf5557f5..ee8767dc685 100644 --- a/src/server/room.hpp +++ b/src/server/room.hpp @@ -22,7 +22,7 @@ namespace wesnothd { typedef std::vector connection_vector; - +typedef std::map player_map; class game; /** @@ -33,7 +33,9 @@ public: /** * Construct a room */ - room(); + room(const std::string& name); + + const std::string& name() const; /** * Return the number of players in this room @@ -107,7 +109,9 @@ public: void send_server_message(const char* message, network::connection sock, simple_wml::document* docptr = NULL) const; + private: + std::string name_; connection_vector members_; }; diff --git a/src/server/room_manager.cpp b/src/server/room_manager.cpp new file mode 100644 index 00000000000..23770d03b42 --- /dev/null +++ b/src/server/room_manager.cpp @@ -0,0 +1,188 @@ +/* $Id$ */ +/* + Copyright (C) 2009 by Tomasz Sniatowski + Part of 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 version 2 + 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. +*/ + +#include "player_network.hpp" +#include "room_manager.hpp" +#include "../foreach.hpp" +#include "../log.hpp" +static lg::log_domain log_server_lobby("server/lobby"); +#define ERR_LOBBY LOG_STREAM(err, log_server_lobby) +#define WRN_LOBBY LOG_STREAM(warn, log_server_lobby) +#define LOG_LOBBY LOG_STREAM(info, log_server_lobby) +#define DBG_LOBBY LOG_STREAM(debug, log_server_lobby) + +namespace wesnothd { + +room_manager::room_manager(player_map &all_players) +: all_players_(all_players), lobby_(NULL) +{ + lobby_ = create_room("lobby"); +} + +room_manager::~room_manager() +{ + // this assumes the server is shutting down, so there's no need to + // send the actual room-quit messages to clients + foreach (t_rooms_by_name_::value_type i, rooms_by_name_) { + delete i.second; + } +} + +room* room_manager::get_room(const std::string &name) +{ + t_rooms_by_name_::iterator i = rooms_by_name_.find(name); + if (i != rooms_by_name_.end()) { + return i->second; + } else { + return NULL; + } +} + +bool room_manager::room_exists(const std::string &name) const +{ + return rooms_by_name_.find(name) != rooms_by_name_.end(); +} + +room* room_manager::create_room(const std::string &name) +{ + if (room_exists(name)) { + DBG_LOBBY << "Requested creation of already existing room '" << name << "'\n"; + return NULL; + } + room* r = new room(name); + rooms_by_name_.insert(std::make_pair(name, r)); + return r; +} + +void room_manager::delete_room(const std::string &name) +{ + room* r = get_room(name); + if (r == NULL) { + DBG_LOBBY << "Requested deletion of nonexistant room '" << name << "'\n"; + return; + } + simple_wml::document doc; + simple_wml::node& exit = doc.root().add_child("exit_room"); + exit.set_attr_dup("room", name.c_str()); + exit.set_attr("reason", "room deleted"); + r->send_data(doc); + rooms_by_name_.erase(name); + foreach (network::connection p, r->members()) { + rooms_by_player_[p].erase(r); + } +} + +void room_manager::enter_lobby(network::connection player) +{ + lobby_->add_player(player); +} + +void room_manager::enter_lobby(const wesnothd::game &game) +{ + lobby_->add_players(game); +} + +void room_manager::exit_lobby(network::connection player) +{ + lobby_->remove_player(player); +} + +bool room_manager::in_lobby(network::connection player) const +{ + return lobby_->is_member(player); +} + +void room_manager::remove_player(network::connection player) +{ + lobby_->remove_player(player); + t_rooms_by_player_::iterator i = rooms_by_player_.find(player); + if (i != rooms_by_player_.end()) { + foreach (room* r, i->second) { + r->remove_player(player); + } + } + rooms_by_player_.erase(player); +} + +void room_manager::player_joins_room(network::connection player, wesnothd::room *room) +{ + room->add_player(player); + rooms_by_player_[player].insert(room); + simple_wml::document doc; + simple_wml::node& join = doc.root().add_child("join"); + join.set_attr_dup("room", room->name().c_str()); + player_map::const_iterator i = all_players_.find(player); + if (i == all_players_.end()) { + WRN_LOBBY << "player " << player << " joins room but is not in all_players\n"; + return; + } + join.set_attr_dup("player", i->second.name().c_str()); + room->send_data(doc, player); + foreach (network::connection m, room->members()) { + simple_wml::node& member = join.add_child("member"); + player_map::const_iterator mi = all_players_.find(m); + if (mi != all_players_.end()) { + member.set_attr_dup("name", mi->second.name().c_str()); + } + } + send_to_one(doc, player); +} + +void room_manager::player_quits_room(network::connection player, wesnothd::room *room) +{ + room->remove_player(player); + rooms_by_player_[player].erase(room); + simple_wml::document doc; + simple_wml::node& quit = doc.root().add_child("quit"); + quit.set_attr_dup("room", room->name().c_str()); + player_map::const_iterator i = all_players_.find(player); + if (i == all_players_.end()) { + WRN_LOBBY << "player " << player << " quits room but is not in all_players\n"; + return; + } + quit.set_attr_dup("player", i->second.name().c_str()); + room->send_data(doc); +} + +void room_manager::process_message(simple_wml::document &data, const player_map::iterator user) +{ + if (user->second.silenced()) { + return; + } else if (user->second.is_message_flooding()) { + lobby_->send_server_message( + "Warning: you are sending too many messages too fast. " + "Your message has not been relayed.", user->first); + return; + } + simple_wml::node* const message = data.root().child("message"); + assert (message); + message->set_attr_dup("sender", user->second.name().c_str()); + std::string room_name = message->attr("room").to_string(); + //todo: dispatch to the appropriate room, check if the player is in that room ... + const simple_wml::string_span& msg = (*message)["message"]; + chat_message::truncate_message(msg, *message); + if (msg.size() >= 3 && simple_wml::string_span(msg.begin(), 4) == "/me ") { + LOG_LOBBY << network::ip_address(user->first) + << "\t<" << user->second.name() + << simple_wml::string_span(msg.begin() + 3, msg.size() - 3) + << ">\n"; + } else { + LOG_LOBBY << network::ip_address(user->first) << "\t<" + << user->second.name() << "> " << msg << "\n"; + } + lobby_->send_data(data, user->first, "message"); +} + + +} //namespace wesnothd \ No newline at end of file diff --git a/src/server/room_manager.hpp b/src/server/room_manager.hpp new file mode 100644 index 00000000000..feefda6da9b --- /dev/null +++ b/src/server/room_manager.hpp @@ -0,0 +1,111 @@ +/* $Id$ */ +/* + Copyright (C) 2009 by Tomasz Sniatowski + Part of 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 version 2 + 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. +*/ + +#include "room.hpp" + +#include + +#ifndef SERVER_ROOM_MANAGER_HPP_INCLUDED +#define SERVER_ROOM_MANAGER_HPP_INCLUDED + +namespace wesnothd { + +/** + * The room manager manages the lobby and other rooms in the server, and related + * client message processing. + * The lobby represents players that are on the server, but not in any game. + */ +class room_manager : private boost::noncopyable +{ +public: + room_manager(player_map& all_players); + ~room_manager(); + + /** + * Get a room by name, or NULL if it does not exist + */ + room* get_room(const std::string& name); + + /** + * @param name the room name to check + * @return true iif the room existst + */ + bool room_exists(const std::string& name) const; + + /** + * Create room named "name" if it does not exist already. + */ + room* create_room(const std::string& name); + + /** + * Delete a room. Players in the room are kicked from it. + */ + void delete_room(const std::string& name); + + /** + * @return true iif the player is in the lobby + */ + bool in_lobby(network::connection player) const; + + /** + * Player-enters-lobby action. Will auto(re)join the default room(s) + */ + void enter_lobby(network::connection player); + + /** + * All players from a game re-enter the lobby + */ + void enter_lobby(const game& game); + + /** + * Player exits lobby. + * TODO: should it remove information about the rooms the player is in? + */ + void exit_lobby(network::connection player); + + /** + * Remove info abut given player from all rooms + */ + void remove_player(network::connection player); + + void process_message(simple_wml::document& data, const player_map::iterator user); + + const room& lobby() const { return *lobby_; } +private: + /** + * Adds a player to a room, notifies current members + */ + void player_joins_room(network::connection player, room* room); + + /** + * Removes a player from a room, notifies remaining members + */ + void player_quits_room(network::connection player, room* room); + + + + player_map& all_players_; + room* lobby_; + typedef std::map t_rooms_by_name_; + t_rooms_by_name_ rooms_by_name_; + typedef std::map > t_rooms_by_player_; + t_rooms_by_player_ rooms_by_player_; + + +}; + +} //namespace wesnothd + + +#endif diff --git a/src/server/server.cpp b/src/server/server.cpp index a6cb8436e37..67ab998d9e4 100644 --- a/src/server/server.cpp +++ b/src/server/server.cpp @@ -297,7 +297,7 @@ server::server(int port, const std::string& config_file, size_t min_threads, ghost_players_(), games_(), not_logged_in_(), - lobby_(), + rooms_(players_), input_(), config_file_(config_file), cfg_(read_config()), @@ -530,7 +530,7 @@ void server::dump_stats(const time_t& now) { << "\tnumber_of_games = " << games_.size() << "\tnumber_of_users = " << players_.size() << "\tnumber_of_ghost_users = " << ghost_players_.size() - << "\tlobby_users = " << lobby_.size() << "\n"; + << "\trooms_users = " << rooms_.lobby().size() << "\n"; } void server::clean_user_handler(const time_t& now) { @@ -754,7 +754,7 @@ void server::run() { simple_wml::document diff; if(make_delete_diff(games_and_users_list_.root(), NULL, "user", pl_it->second.config_address(), diff)) { - lobby_.send_data(diff, e.socket); + rooms_.lobby().send_data(diff, e.socket); } games_and_users_list_.root().remove_child("user",index); @@ -763,8 +763,8 @@ void server::run() { << pl_it->second.name() << " in games_and_users_list_.\n"; } // Was the player in the lobby or a game? - if (lobby_.is_member(e.socket)) { - lobby_.remove_player(e.socket); + if (rooms_.in_lobby(e.socket)) { + rooms_.remove_player(e.socket); LOG_SERVER << ip << "\t" << pl_it->second.name() << "\thas logged off. (socket: " << e.socket << ")\n"; @@ -839,7 +839,7 @@ void server::process_data(const network::connection sock, process_nickserv(sock, *nickserv); } else if (simple_wml::node* whisper = root.child("whisper")) { process_whisper(sock, *whisper); - } else if (lobby_.is_member(sock)) { + } else if (rooms_.in_lobby(sock)) { process_data_lobby(sock, data); } else { process_data_game(sock, data); @@ -1059,30 +1059,30 @@ void server::process_login(const network::connection sock, send_doc(join_lobby_response_, sock); simple_wml::node& player_cfg = games_and_users_list_.root().add_child("user"); - const player new_player(username, player_cfg, registered, default_max_messages_, - default_time_period_, selective_ping ); + const wesnothd::player new_player(username, player_cfg, registered, + default_max_messages_, default_time_period_, selective_ping); // If the new player does not have selective ping enabled, immediately // add the player to the ghost player's list. This ensures a client won't // have to wait as long as x2 the current ping delay; which could cause // a client-side disconnection. - players_.insert(std::pair(sock, new_player)); + players_.insert(std::make_pair(sock, new_player)); if( !selective_ping ) ghost_players_.insert(sock) ; not_logged_in_.erase(sock); - lobby_.add_player(sock); + rooms_.enter_lobby(sock); // Send the new player the entire list of games and players send_doc(games_and_users_list_, sock); if (motd_ != "") { - lobby_.send_server_message(motd_.c_str(), sock); + rooms_.lobby().send_server_message(motd_.c_str(), sock); } // Send other players in the lobby the update that the player has joined simple_wml::document diff; make_add_diff(games_and_users_list_.root(), NULL, "user", diff); - lobby_.send_data(diff, sock); + rooms_.lobby().send_data(diff, sock); LOG_SERVER << network::ip_address(sock) << "\t" << username << "\thas logged on" << (registered ? " to a registered account" : "") @@ -1099,7 +1099,7 @@ void server::process_login(const network::connection sock, << username << std::endl; admins_.insert(sock); // This string is parsed by the client! - lobby_.send_server_message("You are now recognized as an administrator. " + rooms_.lobby().send_server_message("You are now recognized as an administrator. " "If you no longer want to be automatically authenticated use '/query signout'.", sock); } @@ -1172,7 +1172,7 @@ void server::process_query(const network::connection sock, } else { response << "Error: unrecognized query: '" << command << "'\n" << help_msg; } - lobby_.send_server_message(response.str().c_str(), sock); + rooms_.lobby().send_server_message(response.str().c_str(), sock); } void server::start_new_server() { @@ -1251,7 +1251,7 @@ std::string server::process_command(const std::string& query, const std::string& out << "Number of games = " << games_.size() << "\nTotal number of users = " << players_.size() << "\nNumber of ghost users = " << ghost_players_.size() - << "\nNumber of users in the lobby = " << lobby_.size(); + << "\nNumber of users in the lobby = " << rooms_.lobby().size(); return out.str(); } else if (command == "metrics") { out << metrics_; @@ -1301,7 +1301,7 @@ std::string server::process_command(const std::string& query, const std::string& if (parameters == "") { return "You must type a message."; } - lobby_.send_server_message_to_all(parameters.c_str()); + rooms_.lobby().send_server_message_to_all(parameters.c_str()); if (command == "msg") { for (std::vector::const_iterator g = games_.begin(); g != games_.end(); ++g) { (*g)->send_server_message_to_all(parameters.c_str()); @@ -1578,7 +1578,7 @@ void server::process_nickserv(const network::connection sock, simple_wml::node& // Check if this server allows nick registration at all if(!user_handler_) { - lobby_.send_server_message("This server does not allow username registration.", sock); + rooms_.lobby().send_server_message("This server does not allow username registration.", sock); return; } @@ -1592,7 +1592,7 @@ void server::process_nickserv(const network::connection sock, simple_wml::node& // Warn that providing an email address might be a good idea ((*data.child("register"))["mail"].empty() ? " It is recommended that you provide an email address for password recovery." : ""); - lobby_.send_server_message(msg.str().c_str(), sock); + rooms_.lobby().send_server_message(msg.str().c_str(), sock); // Mark the player as registered and send the other clients // an update to dislpay this change @@ -1601,10 +1601,10 @@ void server::process_nickserv(const network::connection sock, simple_wml::node& simple_wml::document diff; make_change_diff(games_and_users_list_.root(), NULL, "user", pl->second.config_address(), diff); - lobby_.send_data(diff); + rooms_.lobby().send_data(diff); } catch (user_handler::error e) { - lobby_.send_server_message(("There was an error registering your username. The error message was: " + rooms_.lobby().send_server_message(("There was an error registering your username. The error message was: " + e.message).c_str(), sock); } return; @@ -1613,7 +1613,7 @@ void server::process_nickserv(const network::connection sock, simple_wml::node& // A user requested to update his password or mail if(data.child("set")) { if(!(user_handler_->user_exists(pl->second.name()))) { - lobby_.send_server_message("You are not registered. Please register first.", + rooms_.lobby().send_server_message("You are not registered. Please register first.", sock); return; } @@ -1623,10 +1623,10 @@ void server::process_nickserv(const network::connection sock, simple_wml::node& try { user_handler_->set_user_detail(pl->second.name(), set["detail"].to_string(), set["value"].to_string()); - lobby_.send_server_message("Your details have been updated.", sock); + rooms_.lobby().send_server_message("Your details have been updated.", sock); } catch (user_handler::error e) { - lobby_.send_server_message(("There was an error updating your details. The error message was: " + rooms_.lobby().send_server_message(("There was an error updating your details. The error message was: " + e.message).c_str(), sock); } @@ -1635,7 +1635,7 @@ void server::process_nickserv(const network::connection sock, simple_wml::node& // A user requested information about another user if(data.child("details")) { - lobby_.send_server_message(("Valid details for this server are: " + + rooms_.lobby().send_server_message(("Valid details for this server are: " + user_handler_->get_valid_details()).c_str(), sock); return; } @@ -1644,9 +1644,9 @@ void server::process_nickserv(const network::connection sock, simple_wml::node& if(data.child("info")) { try { std::string res = user_handler_->user_info((*data.child("info"))["name"].to_string()); - lobby_.send_server_message(res.c_str(), sock); + rooms_.lobby().send_server_message(res.c_str(), sock); } catch (user_handler::error e) { - lobby_.send_server_message(("There was an error looking up the details of the user '" + + rooms_.lobby().send_server_message(("There was an error looking up the details of the user '" + (*data.child("info"))["name"].to_string() + "'. " +" The error message was: " + e.message).c_str(), sock); } @@ -1656,7 +1656,7 @@ void server::process_nickserv(const network::connection sock, simple_wml::node& // A user requested to delete his nick if(data.child("drop")) { if(!(user_handler_->user_exists(pl->second.name()))) { - lobby_.send_server_message("You are not registered.", + rooms_.lobby().send_server_message("You are not registered.", sock); return; } @@ -1665,14 +1665,14 @@ void server::process_nickserv(const network::connection sock, simple_wml::node& // registerd username without the password we should never get // to call this if(!(pl->second.registered())) { - lobby_.send_server_message("You are not logged in.", + rooms_.lobby().send_server_message("You are not logged in.", sock); return; } try { user_handler_->remove_user(pl->second.name()); - lobby_.send_server_message("Your username has been dropped.", sock); + rooms_.lobby().send_server_message("Your username has been dropped.", sock); // Mark the player as not registered and send the other clients // an update to dislpay this change @@ -1681,9 +1681,9 @@ void server::process_nickserv(const network::connection sock, simple_wml::node& simple_wml::document diff; make_change_diff(games_and_users_list_.root(), NULL, "user", pl->second.config_address(), diff); - lobby_.send_data(diff); + rooms_.lobby().send_data(diff); } catch (user_handler::error e) { - lobby_.send_server_message(("There was an error dropping your username. The error message was: " + rooms_.lobby().send_server_message(("There was an error dropping your username. The error message was: " + e.message).c_str(), sock); } return; @@ -1760,7 +1760,7 @@ void server::process_data_lobby(const network::connection sock, if (graceful_restart) { static simple_wml::document leave_game_doc("[leave_game]\n[/leave_game]\n", simple_wml::INIT_COMPRESSED); send_doc(leave_game_doc, sock); - lobby_.send_server_message("This server is shutting down. You aren't allowed to make new games. Please reconnect to the new server.", sock); + rooms_.lobby().send_server_message("This server is shutting down. You aren't allowed to make new games. Please reconnect to the new server.", sock); send_doc(games_and_users_list_, sock); return; } @@ -1777,11 +1777,11 @@ void server::process_data_lobby(const network::connection sock, } data.root().child("create_game")->copy_into(g.level().root()); - lobby_.remove_player(sock); + rooms_.exit_lobby(sock); simple_wml::document diff; if(make_change_diff(games_and_users_list_.root(), NULL, "user", pl->second.config_address(), diff)) { - lobby_.send_data(diff); + rooms_.lobby().send_data(diff); } return; } @@ -1801,7 +1801,7 @@ void server::process_data_lobby(const network::connection sock, WRN_SERVER << network::ip_address(sock) << "\t" << pl->second.name() << "\tattempted to join unknown game:\t" << game_id << ".\n"; send_doc(leave_game_doc, sock); - lobby_.send_server_message("Attempt to join unknown game.", sock); + rooms_.lobby().send_server_message("Attempt to join unknown game.", sock); send_doc(games_and_users_list_, sock); return; } else if (!(*g)->level_init()) { @@ -1809,7 +1809,7 @@ void server::process_data_lobby(const network::connection sock, << "\tattempted to join uninitialized game:\t\"" << (*g)->name() << "\" (" << game_id << ").\n"; send_doc(leave_game_doc, sock); - lobby_.send_server_message("Attempt to join an uninitialized game.", sock); + rooms_.lobby().send_server_message("Attempt to join an uninitialized game.", sock); send_doc(games_and_users_list_, sock); return; } else if (admin) { @@ -1819,7 +1819,7 @@ void server::process_data_lobby(const network::connection sock, << pl->second.name() << "\tfrom game:\t\"" << (*g)->name() << "\" (" << game_id << ").\n"; send_doc(leave_game_doc, sock); - lobby_.send_server_message("You are banned from this game.", sock); + rooms_.lobby().send_server_message("You are banned from this game.", sock); send_doc(games_and_users_list_, sock); return; } else if(!observer && !(*g)->password_matches(password)) { @@ -1827,7 +1827,7 @@ void server::process_data_lobby(const network::connection sock, << "\tattempted to join game:\t\"" << (*g)->name() << "\" (" << game_id << ") with bad password\n"; send_doc(leave_game_doc, sock); - lobby_.send_server_message("Incorrect password.", sock); + rooms_.lobby().send_server_message("Incorrect password.", sock); send_doc(games_and_users_list_, sock); return; } @@ -1849,11 +1849,11 @@ void server::process_data_lobby(const network::connection sock, << "\tattempted to observe game:\t\"" << (*g)->name() << "\" (" << game_id << ") which doesn't allow observers.\n"; send_doc(leave_game_doc, sock); - lobby_.send_server_message("Attempt to observe a game that doesn't allow observers. (You probably joined the game shortly after it filled up.)", sock); + rooms_.lobby().send_server_message("Attempt to observe a game that doesn't allow observers. (You probably joined the game shortly after it filled up.)", sock); send_doc(games_and_users_list_, sock); return; } - lobby_.remove_player(sock); + rooms_.exit_lobby(sock); (*g)->describe_slots(); //send notification of changes to the game and user @@ -1863,14 +1863,16 @@ void server::process_data_lobby(const network::connection sock, bool diff2 = make_change_diff(games_and_users_list_.root(), NULL, "user", pl->second.config_address(), diff); if (diff1 || diff2) { - lobby_.send_data(diff); + rooms_.lobby().send_data(diff); } } + //TODO: process room joins/quits + // See if it's a message, in which case we add the name of the sender, // and forward it to all players in the lobby. if (data.child("message")) { - lobby_.process_message(data, pl); + rooms_.process_message(data, pl); } // Player requests update of lobby content, @@ -1919,7 +1921,7 @@ void server::process_data_game(const network::connection sock, std::stringstream msg; msg << "This server does not support games with more than " << gamemap::MAX_PLAYERS << " sides."; - lobby_.send_server_message(msg.str().c_str(), sock); + rooms_.lobby().send_server_message(msg.str().c_str(), sock); return; } @@ -2002,7 +2004,7 @@ void server::process_data_game(const network::connection sock, // Send the update of the game description to the lobby. simple_wml::document diff; make_add_diff(*games_and_users_list_.child("gamelist"), "gamelist", "game", diff); - lobby_.send_data(diff); + rooms_.lobby().send_data(diff); /** @todo FIXME: Why not save the level data in the history_? */ return; @@ -2033,7 +2035,7 @@ void server::process_data_game(const network::connection sock, std::stringstream msg; msg << "This server does not support games with more than " << gamemap::MAX_PLAYERS << " sides."; - lobby_.send_server_message(msg.str().c_str(), sock); + rooms_.lobby().send_server_message(msg.str().c_str(), sock); return; } const simple_wml::node& s = *data.child("store_next_scenario"); @@ -2114,7 +2116,7 @@ void server::process_data_game(const network::connection sock, delete_game(itor); } else { g->remove_player(sock); - lobby_.add_player(sock); + rooms_.enter_lobby(sock); g->describe_slots(); // Send all other players in the lobby the update to the gamelist. @@ -2124,7 +2126,7 @@ void server::process_data_game(const network::connection sock, bool diff2 = make_change_diff(games_and_users_list_.root(), NULL, "user", pl->second.config_address(), diff); if (diff1 || diff2) { - lobby_.send_data(diff, sock); + rooms_.lobby().send_data(diff, sock); } // Send the player who has quit the gamelist. @@ -2179,7 +2181,7 @@ void server::process_data_game(const network::connection sock, (ban ? g->ban_user(*data.child("ban"), pl) : g->kick_member(*data.child("kick"), pl)); if (user) { - lobby_.add_player(user); + rooms_.enter_lobby(user); if (g->describe_slots()) { update_game_in_lobby(g, user); } @@ -2195,7 +2197,7 @@ void server::process_data_game(const network::connection sock, make_change_diff(games_and_users_list_.root(), NULL, "user", pl2->second.config_address(), diff); } - lobby_.send_data(diff, sock); + rooms_.lobby().send_data(diff, sock); // Send the removed user the lobby game list. send_doc(games_and_users_list_, user); } @@ -2247,7 +2249,7 @@ void server::delete_game(std::vector::iterator game_it) { simple_wml::document diff; if(make_delete_diff(*gamelist, "gamelist", "game", (*game_it)->description(), diff)) { - lobby_.send_data(diff); + rooms_.lobby().send_data(diff); } // Delete the game from the games_and_users_list_. @@ -2274,7 +2276,7 @@ void server::delete_game(std::vector::iterator game_it) { simple_wml::document udiff; if (make_change_diff(games_and_users_list_.root(), NULL, "user", pl->second.config_address(), udiff)) { - lobby_.send_data(udiff); + rooms_.lobby().send_data(udiff); } } else { ERR_SERVER << "ERROR: delete_game(): Could not find user in players_. (socket: " @@ -2286,7 +2288,7 @@ void server::delete_game(std::vector::iterator game_it) { static simple_wml::document leave_game_doc("[leave_game]\n[/leave_game]\n", simple_wml::INIT_COMPRESSED); (*game_it)->send_data(leave_game_doc); // Put the remaining users back in the lobby. - lobby_.add_players(**game_it); + rooms_.enter_lobby(**game_it); (*game_it)->send_data(games_and_users_list_); @@ -2298,7 +2300,7 @@ void server::update_game_in_lobby(const wesnothd::game* g, network::connection e { simple_wml::document diff; if(make_change_diff(*games_and_users_list_.root().child("gamelist"), "gamelist", "game", g->description(), diff)) { - lobby_.send_data(diff, exclude); + rooms_.lobby().send_data(diff, exclude); } } diff --git a/src/server/server.hpp b/src/server/server.hpp index 6a86731b675..5e3e4e32a1c 100644 --- a/src/server/server.hpp +++ b/src/server/server.hpp @@ -4,7 +4,7 @@ #include "../network.hpp" #include "ban.hpp" #include "player.hpp" -#include "room.hpp" +#include "room_manager.hpp" #include "simple_wml.hpp" #include "user_handler.hpp" #include @@ -40,8 +40,7 @@ private: std::vector games_; std::set not_logged_in_; - /** The lobby is implemented as a room. */ - wesnothd::room lobby_; + wesnothd::room_manager rooms_; /** server socket/fifo. */ boost::scoped_ptr input_;