32 #define ERR_GAME LOG_STREAM(err, log_server)
33 #define WRN_GAME LOG_STREAM(warn, log_server)
34 #define LOG_GAME LOG_STREAM(info, log_server)
35 #define DBG_GAME LOG_STREAM(debug, log_server)
37 #define WRN_CONFIG LOG_STREAM(warn, log_config)
41 struct split_conv_impl
46 res.push_back(span.
to_int());
50 template<
typename TResult,
typename TConvert>
53 std::vector<TResult>
res;
57 while (i2 != val.
end()) {
76 WRN_GAME << func <<
"(): Could not find user (socket:\t<some C++ pointer>"
77 <<
") in player_info_ in game:\t\"" <<
name_ <<
"\" (" <<
id_ <<
")\n";
83 player_connections_(player_connections),
97 description_(nullptr),
100 all_observers_muted_(false),
103 save_replays_(save_replays),
104 replay_save_path_(replay_save_path),
106 last_choice_request_id_(-1)
116 iter->info().mark_available(
id_,
name_);
126 for (user_vector::const_iterator u = users.begin(); u != users.end(); ++u) {
140 ERR_GAME <<
"no [multiplayer] found. Returning root\n";
173 std::string describe_turns(
int turn,
int num_turns)
177 if(num_turns == -1) {
178 snprintf(buf,
sizeof(buf),
"%d/-", turn);
180 snprintf(buf,
sizeof(buf),
"%d/%d", turn, num_turns);
191 return iter->info().name();
201 for(
const user_vector::value_type& user : users) {
204 if (!list.empty()) list +=
", ";
205 list += iter->info().name();
215 DBG_GAME <<
"****\n Performing controller tweaks. sides = " << std::endl;
221 for(simple_wml::node::child_list::const_iterator
s = sides.begin();
s != sides.end(); ++
s) {
222 if ((**
s)[
"controller"] !=
"null") {
223 const size_t side_index =
s - sides.begin();
224 if (
sides_[side_index] == 0) {
226 std::stringstream
msg;
227 msg <<
"Side " << side_index + 1 <<
" had no controller during controller tweaks! The host was assigned control.";
228 LOG_GAME << msg.str() <<
" (game id: " <<
id_ <<
")\n";
233 std::string user_name =
"null (server missing user)";
237 user_name =
username(user->socket());
253 (*s)->set_attr(
"is_local",
"no");
255 if (
sides_[side_index] == 0) {
256 std::stringstream
msg;
257 msg <<
"Side " << side_index + 1 <<
" had no controller AFTER controller tweaks! Ruh Roh!";
258 LOG_GAME << msg.str() <<
" (game id: " <<
id_ <<
")\n";
273 DBG_GAME <<
"****\n Starting game. sides = " << std::endl;
282 const bool save = multiplayer[
"savegame"].to_bool();
285 << (save ?
" reloaded" :
"") <<
" game:\t\"" <<
name_ <<
"\" (" <<
id_
287 <<
") with: " <<
list_users(
players_, __func__) <<
". Settings: map: " << multiplayer[
"mp_scenario"]
289 <<
"\tera: " << multiplayer[
"mp_era"]
290 <<
"\tXP: " << multiplayer[
"experience_modifier"]
291 <<
"\tGPV: " << multiplayer[
"mp_village_gold"]
292 <<
"\tfog: " << multiplayer[
"mp_fog"]
293 <<
"\tshroud: " << multiplayer[
"mp_shroud"]
294 <<
"\tobservers: " << multiplayer[
"observer"]
295 <<
"\tshuffle: " << multiplayer[
"shuffle_sides"]
296 <<
"\ttimer: " << multiplayer[
"mp_countdown"]
297 << (multiplayer[
"mp_countdown"].to_bool() ?
298 "\treservoir time: " + multiplayer[
"mp_countdown_reservoir_time"].to_string() +
299 "\tinit time: " + multiplayer[
"mp_countdown_init_time"].to_string() +
300 "\taction bonus: " + multiplayer[
"mp_countdown_action_bonus"].to_string() +
301 "\tturn bonus: " + multiplayer[
"mp_countdown_turn_bonus"].to_string() :
"")
304 for(simple_wml::node::child_list::const_iterator
s = sides.begin();
s != sides.end(); ++
s) {
305 if ((**
s)[
"controller"] !=
"null") {
306 const size_t side_index =
s - sides.begin();
307 if(side_index >=
sides_.size()) {
310 if (
sides_[side_index] == 0) {
311 std::stringstream
msg;
312 msg <<
"Side " << side_index + 1 <<
" has no controller but should! The host needs to assign control for the game to proceed past that side's turn.";
313 LOG_GAME << msg.str() <<
" (game id: " <<
id_ <<
")\n";
324 turn = lexical_cast_default<int>((*snapshot)[
"turn_at"], 1);
325 side = lexical_cast_default<int>((*snapshot)[
"playing_team"], 0);
326 LOG_GAME <<
"Reload from turn: " << turn
327 <<
". Current side is: " << side + 1 <<
".\n";
329 end_turn_ = (turn - 1) * nsides_ + side - 1;
349 const size_t side_index = (**side)[
"side"].to_int() - 1;
351 if (side_index >=
sides_.size())
return false;
352 if (
sides_[side_index] != 0)
return false;
374 for(simple_wml::node::child_list::const_iterator side = sides.begin(); side != sides.end(); ++side) {
375 if(((**side)[
"controller"] ==
"human" || (**side)[
"controller"] ==
"reserved")
382 for(simple_wml::node::child_list::const_iterator side = sides.begin(); side != sides.end(); ++side) {
383 if((**side)[
"controller"] ==
"human") {
387 DBG_GAME <<
"take_side: there are no more sides available\n";
409 DBG_GAME <<
"update_side_data...\n";
421 for (user_vector::const_iterator user = users.begin(); user != users.end(); ++user) {
428 bool side_found =
false;
429 for (simple_wml::node::child_list::const_iterator side = level_sides.begin();
430 side != level_sides.end(); ++side)
432 const size_t side_index = side - level_sides.begin();
433 if (side_index >=
sides_.size()
434 ||
sides_[side_index] != 0)
continue;
438 if ( player_id == iter->info().name().c_str()) {
439 if(controller !=
"human" && controller !=
"ai") {
444 sides_[side_index] = *user;
447 else if (*user ==
owner_ && (controller ==
"null")) {
465 DBG_GAME <<
"transfer_side_control...\n";
472 const unsigned int side_num = cfg[
"side"].to_int();
473 if(side_num < 1 || side_num >
sides_.size()) {
474 std::ostringstream
msg;
475 msg <<
"The side number has to be between 1 and "
493 if (newplayer_name.
empty()) {
494 std::stringstream
msg;
495 msg <<
"Recived invalid [change_controller] with no player= attribute specified";
502 if (!(sock == old_player || sock ==
owner_)) {
503 std::stringstream
msg;
504 msg <<
"You can't give away side " << side_num <<
". It's controlled by '"
505 << old_player_name <<
"' not you.";
519 if (newplayer == old_player) {
520 std::stringstream
msg;
521 msg <<
"That's already " << newplayer_name <<
"'s side, silly.";
554 const bool player_left)
558 const std::string& side = lexical_cast_default<std::string, size_t>(side_index + 1);
559 sides_[side_index] = sock;
572 change.
set_attr(
"side", side.c_str());
573 change.
set_attr(
"player", player_name.c_str());
608 int available_slots = 0;
612 for(simple_wml::node::child_list::const_iterator it = side_list.begin(); it != side_list.end(); ++it, ++
i) {
613 if (((**it)[
"allow_player"].to_bool(
true) ==
false) || (**it)[
"controller"] ==
"null") {
615 }
else if (
sides_[i] == 0) {
620 snprintf(buf,
sizeof(buf),
"%d/%d", available_slots, num_sides);
631 std::vector<std::string>::const_iterator ban =
633 return ban !=
bans_.end();
664 if (username.
empty()) {
704 if (username.
empty()) {
748 }
else if (user == kicker) {
779 }
else if (user == banner) {
832 ERR_GAME <<
"No owner in game::process_message" << std::endl;
848 const bool is_host = user ==
owner_;
852 const size_t from_side_index = command[
"from_side"].to_int() - 1;
853 if(command[
"from_side"] ==
"server") {
857 if(from_side_index >=
sides_.size() ||
sides_[from_side_index] != user) {
862 if(is_current)
return true;
868 if (command.
child(
"speak"))
return true;
869 if (is_player && command.
has_attr(
"dependent") && command.
has_attr(
"from_side"))
874 if ((is_player || is_host)
875 && (command.
child(
"label")
876 || command.
child(
"clear_labels")
877 || command.
child(
"rename")
878 || command.
child(
"countdown_update")
890 bool turn_ended =
false;
894 bool repackage =
false;
896 std::vector<int> marked;
898 simple_wml::node::child_list::const_iterator command;
899 for (command = commands.begin(); command != commands.end(); ++command) {
900 DBG_GAME <<
"game " <<
id_ <<
" recieved [" << (**command).first_child() <<
"] from player '" <<
username(user) <<
"'(" << user <<
") during turn " <<
end_turn_ <<
"\n";
902 LOG_GAME <<
"ILLEGAL COMMAND in game: " <<
id_ <<
" ((("
904 std::stringstream
msg;
905 msg <<
"Removing illegal command '" << (**command).first_child().to_string()
907 <<
". Current player is: "
909 <<
" (" << end_turn_ + 1 <<
"/" <<
nsides_ <<
").";
911 <<
") (game id: " <<
id_ <<
")\n";
914 marked.push_back(index - marked.size());
915 }
else if ((**command).child(
"speak")) {
918 DBG_GAME <<
"repackaging..." << std::endl;
930 const size_t side_index = speak[
"side"].to_int() - 1;
931 if (side_index >=
sides_.size()
932 ||
sides_[side_index] != user) {
936 const side_vector::const_iterator
s =
938 speak.
set_attr_dup(
"side", lexical_cast_default<std::string>(s -
sides_.begin() + 1).c_str());
948 for(std::vector<int>::const_iterator j = marked.begin(); j != marked.end(); ++j) {
959 for (command = commands.begin(); command != commands.end(); ++command) {
961 if (speak ==
nullptr) {
980 if (to_sides ==
"") {
981 send_data(*message, user,
"game message");
998 stream << std::setfill(
'0') << std::setw(
sizeof(
uint32_t)*2) << std::hex << seed;
1004 random_seed.
set_attr_dup(
"new_seed",stream.str().c_str());
1005 command.
set_attr(
"from_side",
"server");
1006 command.
set_attr(
"dependent",
"yes");
1013 const size_t side_index = req[
"side"].to_int() - 1;
1014 CONTROLLER new_controller;
1015 CONTROLLER old_controller;
1016 if(!new_controller.parse(req[
"new_controller"])) {
1017 send_and_record_server_message(
"Could not handle [request_choice] [change_controller] with invalid controller '" + req[
"new_controller"].to_string() +
"'");
1020 if(!old_controller.parse(req[
"old_controller"])) {
1021 send_and_record_server_message(
"Could not handle [request_choice] [change_controller] with invalid controller '" + req[
"old_controller"].to_string() +
"'");
1027 if(side_index >=
sides_.size()) {
1032 const bool becomes_null = new_controller == CONTROLLER::EMPTY;
1034 assert(
sides_[side_index] == 0);
1046 change_controller_wml.
set_attr(
"controller", new_controller.to_cstring());
1047 change_controller_wml.
set_attr(
"is_local",
"yes");
1048 command.
set_attr(
"from_side",
"server");
1049 command.
set_attr(
"dependent",
"yes");
1050 if(
sides_[side_index] != 0) {
1054 change_controller_wml.
set_attr(
"is_local",
"no");
1072 int request_id = lexical_cast_default<int>(data[
"request_id"], -10);
1078 DBG_GAME <<
"answering seed request " << request_id <<
" by player " <<
player_connections_.find(user)->info().name() <<
"(" << user <<
")" << std::endl;
1102 size_t const side_index = wb_node[
"side"].to_int() - 1;
1103 if(side_index >=
sides_.size()
1104 ||
sides_[side_index] != user)
1106 std::ostringstream
msg;
1107 msg <<
"Ignoring illegal whiteboard data, sent from user '" <<
player_connections_.find(user)->info().name()
1108 <<
"' which had an invalid side '" << side_index + 1 <<
"' specified" << std::endl;
1125 const int num_turns = ctw_node[
"max"].to_int();
1126 if(num_turns > 10000 || current_turn > 10000) {
1133 assert(static_cast<int>(this->
current_turn()) == current_turn);
1141 bool turn_ended =
false;
1152 if (!turn_ended)
return false;
1167 ERR_GAME <<
"ERROR: Player is already in this game. (socket: "
1175 bool became_observer =
false;
1185 became_observer =
true;
1188 DBG_GAME <<
"adding observer...\n";
1199 <<
"\tjoined game:\t\"" <<
name_ <<
"\" (" <<
id_ <<
")"
1200 << (observer ?
" as an observer" :
"")
1201 <<
". (socket: " << player <<
")\n";
1223 if (!clones.empty()) {
1227 if (became_observer) {
1236 ERR_GAME <<
"ERROR: User is not in this game. (socket: "
1241 DBG_GAME <<
"removing player...\n";
1252 << ((game_ended && !(observer && destruct))
1253 ? (
started_ ?
"\tended" :
"\taborted") :
"\thas left")
1254 <<
" game:\t\"" <<
name_ <<
"\" (" <<
id_ <<
")"
1255 << (game_ended &&
started_ && !(observer && destruct) ?
" at turn: "
1256 + lexical_cast_default<std::string,size_t>(
current_turn())
1258 << (observer ?
" as an observer" :
"")
1259 << (disconnect ?
" and disconnected" :
"")
1260 <<
". (socket: " << user <<
")\n";
1261 if (game_ended &&
started_ && !(observer && destruct)) {
1264 if (game_ended || destruct)
return game_ended;
1275 + (disconnect ?
" has disconnected." :
" has left the game."), player);
1283 bool ai_transfer =
false;
1287 size_t side_index = side -
sides_.begin();
1288 if (*side != player)
continue;
1294 DBG_GAME <<
"making the owner a player...\n";
1302 const std::string side_drop = lexical_cast_default<std::string, size_t>(side_index + 1);
1307 DBG_GAME <<
"*** sending side drop: \n" << drop.output() << std::endl;
1327 for(user_vector::const_iterator
p = users.begin();
p != users.end(); ++
p) {
1345 DBG_GAME <<
"****\n loading next scenario for a client. sides info = " << std::endl;
1371 for (
const auto& side_user :
sides_) {
1373 cfg_controller.
set_attr(
"is_local", side_user == user ?
"yes" :
"no");
1391 struct controls_side_helper
1413 std::vector<int> sides_vec = ::split<int>(sides, ::split_conv_impl());
1415 decltype(
players_) filtered_players;
1416 std::copy_if(
players_.begin(),
players_.end(), filtered_players.begin(), controls_side_helper(*
this, sides_vec));
1422 for (
int side : sides)
1424 size_t side_index = side - 1;
1425 if(side_index <
sides_.size() &&
sides_[side_index] == player) {
1436 for (user_vector::const_iterator
i = users.begin();
i != users.end(); ++
i) {
1440 clones += (clones.empty() ?
"" :
", ") + pl->info().name();
1449 if (*ob == sock)
continue;
1499 return !(isalnum(c) || (c ==
'_') || (c ==
'-') || (c ==
'.')
1500 || (c ==
'(') || (c ==
')') || (c ==
'#') || (c ==
',')
1501 || (c ==
'!') || (c ==
'?') || (c ==
'^') || (c ==
'+')
1502 || (c ==
'*') || (c ==
':') || (c ==
'=') || (c ==
'@')
1503 || (c ==
'%') || (c ==
'\''));
1512 for (simple_wml::node::child_list::const_iterator turn = turn_list.begin(); turn != turn_list.end(); ++turn) {
1518 std::stringstream
name;
1521 std::stringstream replay_data;
1526 const bool has_old_replay =
level_.
child(
"replay") !=
nullptr;
1535 << (has_old_replay ?
"" :
"\t[command]\n\t\t[start]\n\t\t[/start]\n\t[/command]\n")
1538 name <<
" (" <<
id_ <<
").bz2";
1544 std::replace(filename.begin(), filename.end(),
' ',
'_');
1546 DBG_GAME <<
"saving replay: " << filename << std::endl;
1548 (*os) <<
replay.output_compressed(
true);
1551 ERR_GAME <<
"Could not save replay! (" << filename <<
")" << std::endl;
1596 std::stringstream
result;
1597 result <<
"game id: " <<
id_ <<
"\n";
1602 result <<
"player: " << user->info().name().c_str() <<
"\n";
1605 result <<
"player: '" << *
p <<
"' not found\n";
1612 result <<
"observer: " << user->info().name().c_str() <<
"\n";
1615 result <<
"observer: '" << *o <<
"' not found\n";
1623 return result.str();
1627 std::stringstream
result;
1628 result <<
"game id: " <<
id_ <<
"\n";
1631 result <<
"\t\t level, server\n";
1632 for(simple_wml::node::child_list::const_iterator
s = sides.begin();
s != sides.end(); ++
s) {
1633 result <<
"side " << (**s)[
"side"].to_int() <<
" :\t" << (**s)[
"controller"].to_string()
1635 <<
"\t( " <<
sides_[(**s)[
"side"].to_int()-1] <<
",\t"
1636 << (**s)[
"current_player"].to_string() <<
" )\n";
1639 return result.str();
1646 return iter->socket();
1670 if(docptr ==
nullptr) {
bool process_turn(simple_wml::document &data, const socket_ptr user)
Handles [end_turn], repackages [commands] with private [speak]s in them and sends the data...
node & add_child(const char *name)
const char * const_iterator
bool player_is_banned(const socket_ptr player) const
Checks whether the connection's ip address is banned.
void start_game(const socket_ptr starter)
rand_rng::mt_rng rng_
A wrapper for mersenne twister rng which generates randomness for this game.
bool allow_observers() const
void set_current_turn(int turn)
std::string debug_sides_info() const
Helps debugging controller tweaks.
std::string to_string() const
GLenum GLenum GLvoid GLvoid GLvoid * span
void unmute_observer(const simple_wml::node &unmute, const socket_ptr unmuter)
void send_observerquit(const socket_ptr observer) const
const wesnothd::game & game_
player_connections & player_connections_
const std::string & name() const
void send_server_message(const char *message, socket_ptr sock=socket_ptr(), simple_wml::document *doc=nullptr) const
void handle_random_choice(const simple_wml::node &data)
void change_controller(const size_t side_num, const socket_ptr sock, const std::string &player_name, const bool player_left=true)
Send [change_controller] message to tell all clients the new controller's name or controller type (hu...
user_vector muted_observers_
uint32_t get_next_random()
Get a new random number.
void update_side_data()
Resets the side configuration according to the scenario data.
std::string has_same_ip(const socket_ptr user, bool observer) const
Checks whether a user has the same IP as members of this game.
node & set_attr(const char *key, const char *value)
void transfer_side_control(const socket_ptr sock, const simple_wml::node &cfg)
Let's a player owning a side give it to another player or observer.
GLuint const GLfloat * val
int nsides_
Number of sides in the current scenario.
user_vector observers_
A vector of observers (members not owning a side).
void process_message(simple_wml::document &data, const socket_ptr user)
const user_vector all_game_users() const
Adds players and observers into one vector and returns that.
socket_ptr find_user(const simple_wml::string_span &name)
Shortcut to a convenience function for finding a user by name.
bool is_member(const socket_ptr player) const
bool all_observers_muted_
size_t current_side() const
const simple_wml::node::child_list & get_sides_list() const
GLint GLenum GLsizei GLint GLsizei const GLvoid * data
node & set_attr_dup(const char *key, const char *value)
std::vector< std::string > bans_
bool take_side(const socket_ptr user)
Figures out which side to take and tells that side to the game owner.
bool is_player(const socket_ptr player) const
node * child(const char *name)
node * child(const char *name)
socket_ptr kick_member(const simple_wml::node &kick, const socket_ptr kicker)
Kick a member by name.
socket_ptr current_player() const
bool send_taken_side(simple_wml::document &cfg, const simple_wml::node::child_list::const_iterator side) const
void handle_choice(const simple_wml::node &data, const socket_ptr user)
int last_choice_request_id_
void truncate_message(const simple_wml::string_span &str, simple_wml::node &message)
Function to ensure a text message is within the allowed length.
void send_and_record_server_message(const char *message, const socket_ptr exclude=socket_ptr())
Send data to all players in this game except 'exclude'.
std::string username(const socket_ptr pl) const
Returns the name of the user or "(unfound)".
static lg::log_domain log_server("server")
void reset_sides()
calculates the initial value for sides_, side_controllerds_, nsides_
static lg::log_domain log_config("config")
void send_data(simple_wml::document &data, const socket_ptr exclude=socket_ptr(), std::string packet_type="") const
std::vector< CONTROLLER > side_controllers_
void remove_child(const char *name, size_t index)
const std::string & termination_reason() const
void handle_controller_choice(const simple_wml::node &data)
bool describe_slots()
Set the description to the number of available slots.
socket_ptr ban_user(const simple_wml::node &ban, const socket_ptr banner)
Ban and kick a user by name.
static bool is_invalid_filename_char(char c)
bool controls_side(const std::vector< int > &sides, const socket_ptr player) const
Function which returns true iff 'player' controls any of the sides spcified in 'sides'.
std::ostream * ostream_file(std::string const &fname, bool create_directory=true)
bool registered_users_only() const
bool has_attr(const char *key) const
GLenum GLuint GLsizei const char * buf
void missing_user(socket_ptr socket, const std::string &func) const
Function to log when we don't find a connection in player_info_.
bool is_legal_command(const simple_wml::node &command, const socket_ptr user)
Templates and utility-routines for strings and numbers.
void perform_controller_tweaks()
void send_to_player(socket_ptr socket, simple_wml::document &doc)
std::string client_address(socket_ptr socket)
bool add_player(const socket_ptr player, bool observer=false)
Add a user to the game.
void send_leave_game(socket_ptr user) const
void send_history(const socket_ptr sock) const
socket_ptr owner_
The game host or later owner (if the host left).
static simple_wml::node * starting_pos(simple_wml::node &data)
bool is_observer(const socket_ptr player) const
node & set_attr_dup(const char *key, const char *value)
void process_whiteboard(simple_wml::document &data, const socket_ptr user)
Handles incoming [whiteboard] data.
std::string list_users(user_vector users, const std::string &func) const
Returns a comma separated list of user names.
multi_index_container< player_record, indexed_by< ordered_unique< tag< socket_t >, BOOST_MULTI_INDEX_CONST_MEM_FUN(player_record, const socket_ptr, socket)>, hashed_unique< tag< name_t >, BOOST_MULTI_INDEX_CONST_MEM_FUN(player_record, const std::string &, name)>, ordered_non_unique< tag< game_t >, BOOST_MULTI_INDEX_CONST_MEM_FUN(player_record, int, game_id)> >> player_connections
std::vector< node * > child_list
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
void copy_into(node &n) const
const child_list & children(const char *name) const
Declarations for File-IO.
void record_data(simple_wml::document *data)
side_vector sides_
A vector of side owners.
void notify_new_host()
In case of a host transfer, notify the new host about its status.
bool disconnect(connection s)
Function to disconnect from a certain host, or close all connections if connection_num is 0...
static void save(LexState *ls, int c)
void load_next_scenario(const socket_ptr user)
A user (player only?) asks for the next scenario to advance to.
void set_description(simple_wml::node *desc)
Functions to set/get the address of the game's summary description as sent to players in the lobby...
static const simple_wml::node & get_multiplayer(const simple_wml::node &root)
returns const so that operator [] won't create empty keys if not existent
void send_server_message_to_all(const char *message, socket_ptr exclude=socket_ptr()) const
size_t current_turn() const
std::string replace(std::string str, const std::string &src, const std::string &dst)
Replace all instances of src in str with dst.
const char * begin() const
GLuint const GLchar * name
simple_wml::node * description_
Pointer to the game's description in the games_and_users_list_.
std::string name_
The name of the game.
bool is_current_player(const socket_ptr player) const
bool is_muted_observer(const socket_ptr player) const
bool find(E event, F functor)
Tests whether an event handler is available.
std::string replay_save_path_
void send_data_sides(simple_wml::document &data, const simple_wml::string_span &sides, const socket_ptr exclude=socket_ptr(), std::string packet_type="") const
Standard logging facilities (interface).
user_vector players_
A vector of players (members owning a side).
std::vector< socket_ptr > user_vector
GLsizei GLenum GLuint GLuint GLsizei char * message
void send_observerjoins(const socket_ptr sock=socket_ptr()) const
Send [observer] tags of all the observers in the game to the user or everyone if none given...
const std::string remove
remove directive
std::vector< std::string > split(std::string const &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
void process_change_turns_wml(simple_wml::document &data, const socket_ptr user)
Handles incoming [change_turns_wml] data.
boost::shared_ptr< boost::asio::ip::tcp::socket > socket_ptr
void mute_observer(const simple_wml::node &mute, const socket_ptr muter)
Mute an observer or give a message of all currently muted observers if no name is given...
void send_user_list(const socket_ptr exclude=socket_ptr()) const
Function to send a list of users to all clients.
std::string debug_player_info() const
Helps debugging player and observer lists.
bool end_turn()
Function which should be called every time a player ends their turn (i.e.
void unban_user(const simple_wml::node &unban, const socket_ptr unbanner)
simple_wml::document level_
The current scenario data.
GLsizei const GLcharARB ** string
void send_muted_observers(const socket_ptr user) const
void mute_all_observers()
bool remove_player(const socket_ptr player, const bool disconnect=false, const bool destruct=false)
Removes a user from the game.
const std::vector< int > & sides_
void send_to_players(simple_wml::document &data, const Container &players, socket_ptr exclude=socket_ptr())
void set_termination_reason(const std::string &reason)
std::string node_to_string(const node &n)
const std::string observer_team_name
observer team name used for observer team chat