Create a room class separate from the game class, and use it for the lobby.
There remains some unfortunate duplicate code that will be removed in the future, not all "lobby-hacks" have yet been removed from the game class either.
This commit is contained in:
parent
24536f3c8b
commit
613189f9f0
12 changed files with 312 additions and 49 deletions
|
@ -393,6 +393,10 @@
|
|||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\server\room.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\server\sample_user_handler.cpp"
|
||||
>
|
||||
|
@ -570,6 +574,10 @@
|
|||
RelativePath="..\..\src\server\proxy.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\server\room.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\server\sample_user_handler.hpp"
|
||||
>
|
||||
|
|
|
@ -404,6 +404,7 @@ SET(wesnothd_SRC
|
|||
server/player.cpp
|
||||
server/player_network.cpp
|
||||
server/proxy.cpp
|
||||
server/room.cpp
|
||||
server/server.cpp
|
||||
server/simple_wml.cpp
|
||||
server/user_handler.cpp
|
||||
|
|
|
@ -234,6 +234,7 @@ wesnothd_SOURCES = \
|
|||
server/player.cpp \
|
||||
server/player_network.cpp \
|
||||
server/proxy.cpp \
|
||||
server/room.cpp
|
||||
server/server.cpp \
|
||||
server/simple_wml.cpp \
|
||||
server/user_handler.cpp \
|
||||
|
|
|
@ -348,6 +348,7 @@ wesnothd_sources = Split("""
|
|||
server/player.cpp
|
||||
server/player_network.cpp
|
||||
server/proxy.cpp
|
||||
server/room.cpp
|
||||
server/sample_user_handler.cpp
|
||||
server/simple_wml.cpp
|
||||
server/user_handler.cpp
|
||||
|
|
|
@ -35,23 +35,6 @@ static lg::log_domain log_server("server");
|
|||
#define LOG_GAME LOG_STREAM(info, log_server)
|
||||
#define DBG_GAME LOG_STREAM(debug, log_server)
|
||||
|
||||
namespace chat_message {
|
||||
|
||||
const size_t max_message_length = 256;
|
||||
static void truncate_message(const simple_wml::string_span& str, simple_wml::node& message) {
|
||||
// testing for msg.size() is not sufficient but we're not getting false negatives
|
||||
// and it's cheaper than always converting to wstring.
|
||||
if(str.size() > static_cast<int>(chat_message::max_message_length)) {
|
||||
std::string tmp(str.begin(), str.end());
|
||||
// The string can contain utf-8 characters so truncate as wide_string otherwise
|
||||
// a corrupted utf-8 string can be returned.
|
||||
utils::truncate_as_wstring(tmp, max_message_length);
|
||||
message.set_attr_dup("message", tmp.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
} // end chat_message namespace
|
||||
|
||||
namespace wesnothd {
|
||||
int game::id_num = 1;
|
||||
|
||||
|
@ -754,15 +737,8 @@ void game::unban_user(const simple_wml::node& unban,
|
|||
}
|
||||
|
||||
void game::process_message(simple_wml::document& data, const player_map::iterator user) {
|
||||
// Hack to handle the pseudo game lobby_.
|
||||
if (owner_ != 0) {
|
||||
} else 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;
|
||||
if (owner_ == 0) {
|
||||
ERR_GAME << "No owner in game::process_message\n";
|
||||
}
|
||||
|
||||
simple_wml::node* const message = data.root().child("message");
|
||||
|
@ -772,19 +748,7 @@ void game::process_message(simple_wml::document& data, const player_map::iterato
|
|||
const simple_wml::string_span& msg = (*message)["message"];
|
||||
chat_message::truncate_message(msg, *message);
|
||||
|
||||
// Only log in the lobby_.
|
||||
std::string game_prefix;
|
||||
if (owner_ != 0) {
|
||||
game_prefix = "game ";
|
||||
} else if (msg.size() >= 3 && simple_wml::string_span(msg.begin(), 4) == "/me ") {
|
||||
LOG_GAME << network::ip_address(user->first) << "\t<"
|
||||
<< user->second.name() << simple_wml::string_span(msg.begin() + 3, msg.size() - 3) << ">\n";
|
||||
} else {
|
||||
LOG_GAME << network::ip_address(user->first) << "\t<"
|
||||
<< user->second.name() << "> " << msg << "\n";
|
||||
}
|
||||
|
||||
send_data(data, user->first, game_prefix + "message");
|
||||
send_data(data, user->first, "game message");
|
||||
}
|
||||
|
||||
bool game::is_legal_command(const simple_wml::node& command, bool is_player) {
|
||||
|
|
77
src/server/player_group.hpp
Normal file
77
src/server/player_group.hpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2003 - 2009 by David White <dave@whitevine.net>
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef SERVER_PLAYER_GROUP_HPP_INCLUDED
|
||||
#define SERVER_PLAYER_GROUP_HPP_INCLUDED
|
||||
|
||||
#include "../network.hpp"
|
||||
#include "player.hpp"
|
||||
#include "simple_wml.hpp"
|
||||
|
||||
namespace wesnothd {
|
||||
|
||||
typedef std::map<network::connection,player> player_map;
|
||||
typedef std::vector<network::connection> connection_vector;
|
||||
|
||||
|
||||
/**
|
||||
* A player_group represents a group of players, with convenience functions for
|
||||
* sending data to all of them
|
||||
*/
|
||||
class player_group
|
||||
{
|
||||
public:
|
||||
player_group();
|
||||
|
||||
explicit player_group(const connection_vector& v);
|
||||
|
||||
/**
|
||||
* Check if the player is a member of this group
|
||||
* @return true iif the playes is a member
|
||||
*/
|
||||
bool is_member(const network::connection player) const;
|
||||
|
||||
/**
|
||||
* Add a user to the group.
|
||||
* @return True iff the user successfully joined.
|
||||
*/
|
||||
bool add_member(const network::connection player);
|
||||
|
||||
const connection_vector members() const { return members_; }
|
||||
|
||||
/** Send data to all members except 'exclude' */
|
||||
void send_and_record_server_message(const char* message, const network::connection exclude = 0);
|
||||
void send_data(simple_wml::document& data, const network::connection exclude=0, std::string packet_type = "") const;
|
||||
void send_to_one(simple_wml::document& data, const network::connection sock, std::string packet_type = "") const;
|
||||
|
||||
protected:
|
||||
connection_vector members_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class room
|
||||
{
|
||||
public:
|
||||
room(const std::string& name);
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
connection_vector members_;
|
||||
};
|
||||
|
||||
|
||||
} //end namespace wesnothd
|
||||
|
||||
#endif
|
|
@ -2,6 +2,25 @@
|
|||
|
||||
namespace wesnothd {
|
||||
|
||||
namespace chat_message {
|
||||
|
||||
const size_t max_message_length = 256;
|
||||
|
||||
void truncate_message(const simple_wml::string_span& str, simple_wml::node& message)
|
||||
{
|
||||
// testing for msg.size() is not sufficient but we're not getting false negatives
|
||||
// and it's cheaper than always converting to wstring.
|
||||
if(str.size() > static_cast<int>(chat_message::max_message_length)) {
|
||||
std::string tmp(str.begin(), str.end());
|
||||
// The string can contain utf-8 characters so truncate as wide_string otherwise
|
||||
// a corrupted utf-8 string can be returned.
|
||||
utils::truncate_as_wstring(tmp, max_message_length);
|
||||
message.set_attr_dup("message", tmp.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
} // end chat_message namespace
|
||||
|
||||
player_map::const_iterator find_user(const player_map& all_players,
|
||||
const simple_wml::string_span& name)
|
||||
{
|
||||
|
|
|
@ -23,6 +23,11 @@
|
|||
|
||||
namespace wesnothd {
|
||||
|
||||
namespace chat_message {
|
||||
void truncate_message(const simple_wml::string_span& str,
|
||||
simple_wml::node& message);
|
||||
} // end chat_message namespace
|
||||
|
||||
typedef std::map<network::connection,player> player_map;
|
||||
typedef std::vector<network::connection> connection_vector;
|
||||
|
||||
|
|
116
src/server/room.cpp
Normal file
116
src/server/room.cpp
Normal file
|
@ -0,0 +1,116 @@
|
|||
#include "game.hpp"
|
||||
#include "player_network.hpp"
|
||||
#include "room.hpp"
|
||||
#include "../foreach.hpp"
|
||||
#include "../log.hpp"
|
||||
|
||||
static lg::log_domain log_server("server");
|
||||
#define ERR_ROOM LOG_STREAM(err, log_server)
|
||||
#define LOG_ROOM LOG_STREAM(info, log_server)
|
||||
#define DBG_ROOM LOG_STREAM(debug, log_server)
|
||||
|
||||
namespace wesnothd {
|
||||
|
||||
room::room()
|
||||
: members_()
|
||||
{
|
||||
}
|
||||
|
||||
bool room::add_player(network::connection player)
|
||||
{
|
||||
if (is_member(player)) {
|
||||
ERR_ROOM << "ERROR: Player is already in this room. (socket: "
|
||||
<< player << ")\n";
|
||||
return false;
|
||||
}
|
||||
members_.push_back(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
void room::add_players(const wesnothd::game& game)
|
||||
{
|
||||
foreach (network::connection player, game.all_game_users()) {
|
||||
add_player(player);
|
||||
}
|
||||
}
|
||||
|
||||
void room::remove_player(network::connection player)
|
||||
{
|
||||
const user_vector::iterator itor =
|
||||
std::find(members_.begin(), members_.end(), player);
|
||||
if (itor != members_.end()) {
|
||||
members_.erase(itor);
|
||||
} else {
|
||||
ERR_ROOM << "ERROR: Player is not in this room. (socket: "
|
||||
<< player << ")\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void room::send_data(simple_wml::document& data,
|
||||
const network::connection exclude,
|
||||
std::string packet_type) const
|
||||
{
|
||||
wesnothd::send_to_many(data, members(), exclude, packet_type);
|
||||
}
|
||||
|
||||
void room::send_server_message_to_all(const char* message,
|
||||
network::connection exclude) const
|
||||
{
|
||||
simple_wml::document doc;
|
||||
send_server_message(message, 0, &doc);
|
||||
send_data(doc, exclude, "message");
|
||||
}
|
||||
|
||||
void room::send_server_message(const char* message,
|
||||
network::connection sock,
|
||||
simple_wml::document* docptr) const
|
||||
{
|
||||
simple_wml::document docbuf;
|
||||
if(docptr == NULL) {
|
||||
docptr = &docbuf;
|
||||
}
|
||||
simple_wml::document& doc = *docptr;
|
||||
|
||||
simple_wml::node& msg = doc.root().add_child("message");
|
||||
msg.set_attr("sender", "server");
|
||||
msg.set_attr_dup("message", message);
|
||||
|
||||
if(sock) {
|
||||
send_to_one(doc, sock, "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
|
70
src/server/room.hpp
Normal file
70
src/server/room.hpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2003 - 2009 by David White <dave@whitevine.net>
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef SERVER_ROOM_HPP_INCLUDED
|
||||
#define SERVER_ROOM_HPP_INCLUDED
|
||||
|
||||
#include "../network.hpp"
|
||||
#include "player.hpp"
|
||||
#include "simple_wml.hpp"
|
||||
|
||||
namespace wesnothd {
|
||||
|
||||
typedef std::vector<network::connection> connection_vector;
|
||||
|
||||
class game;
|
||||
|
||||
class room {
|
||||
public:
|
||||
room();
|
||||
|
||||
/**
|
||||
* Return the number of players in this room
|
||||
*/
|
||||
size_t size() const {
|
||||
return members_.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the members of this room
|
||||
*/
|
||||
const std::vector<network::connection>& members() const {
|
||||
return members_;
|
||||
}
|
||||
|
||||
bool is_member(network::connection player) const {
|
||||
return std::find(members_.begin(), members_.end(), player) != members_.end();
|
||||
}
|
||||
|
||||
bool add_player(network::connection player);
|
||||
|
||||
void add_players(const game& game);
|
||||
|
||||
void remove_player(network::connection player);
|
||||
|
||||
void process_message(simple_wml::document& data, const player_map::iterator user);
|
||||
|
||||
|
||||
void send_data(simple_wml::document& data, const network::connection exclude=0, std::string packet_type = "") const;
|
||||
|
||||
void send_server_message_to_all(const char* message, network::connection exclude=0) const;
|
||||
void send_server_message(const char* message, network::connection sock, simple_wml::document* docptr = NULL) const;
|
||||
|
||||
private:
|
||||
connection_vector members_;
|
||||
};
|
||||
|
||||
} //end namespace wesnothd
|
||||
|
||||
#endif
|
|
@ -297,7 +297,7 @@ server::server(int port, const std::string& config_file, size_t min_threads,
|
|||
ghost_players_(),
|
||||
games_(),
|
||||
not_logged_in_(players_),
|
||||
lobby_(players_),
|
||||
lobby_(),
|
||||
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_.nobservers() << "\n";
|
||||
<< "\tlobby_users = " << lobby_.size() << "\n";
|
||||
}
|
||||
|
||||
void server::clean_user_handler(const time_t& now) {
|
||||
|
@ -838,7 +838,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_observer(sock)) {
|
||||
} else if (lobby_.is_member(sock)) {
|
||||
process_data_lobby(sock, data);
|
||||
} else {
|
||||
process_data_game(sock, data);
|
||||
|
@ -1070,7 +1070,7 @@ void server::process_login(const network::connection sock,
|
|||
ghost_players_.insert(sock) ;
|
||||
|
||||
not_logged_in_.remove_player(sock);
|
||||
lobby_.add_player(sock, true);
|
||||
lobby_.add_player(sock);
|
||||
// Send the new player the entire list of games and players
|
||||
send_doc(games_and_users_list_, sock);
|
||||
|
||||
|
@ -1250,7 +1250,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_.nobservers();
|
||||
<< "\nNumber of users in the lobby = " << lobby_.size();
|
||||
return out.str();
|
||||
} else if (command == "metrics") {
|
||||
out << metrics_;
|
||||
|
@ -2113,7 +2113,7 @@ void server::process_data_game(const network::connection sock,
|
|||
delete_game(itor);
|
||||
} else {
|
||||
g->remove_player(sock);
|
||||
lobby_.add_player(sock, true);
|
||||
lobby_.add_player(sock);
|
||||
g->describe_slots();
|
||||
|
||||
// Send all other players in the lobby the update to the gamelist.
|
||||
|
@ -2178,7 +2178,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, true);
|
||||
lobby_.add_player(user);
|
||||
if (g->describe_slots()) {
|
||||
update_game_in_lobby(g, user);
|
||||
}
|
||||
|
@ -2285,7 +2285,7 @@ void server::delete_game(std::vector<wesnothd::game*>::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, true);
|
||||
lobby_.add_players(**game_it);
|
||||
|
||||
(*game_it)->send_data(games_and_users_list_);
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "../network.hpp"
|
||||
#include "ban.hpp"
|
||||
#include "player.hpp"
|
||||
#include "room.hpp"
|
||||
#include "simple_wml.hpp"
|
||||
#include "user_handler.hpp"
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
@ -39,8 +40,8 @@ private:
|
|||
std::vector<wesnothd::game*> games_;
|
||||
wesnothd::game not_logged_in_;
|
||||
|
||||
/** The lobby is implemented as a game. */
|
||||
wesnothd::game lobby_;
|
||||
/** The lobby is implemented as a room. */
|
||||
wesnothd::room lobby_;
|
||||
|
||||
/** server socket/fifo. */
|
||||
boost::scoped_ptr<input_stream> input_;
|
||||
|
|
Loading…
Add table
Reference in a new issue