Add doxygen docs to wesnothd's game.hpp. (#6017)

Also removed some methods/parameters that are not used.
This commit is contained in:
Pentarctagon 2021-09-08 13:18:15 -05:00 committed by GitHub
parent b34b8a9dcd
commit 43f60a9d8b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 451 additions and 131 deletions

View file

@ -219,10 +219,6 @@ void game::perform_controller_tweaks()
// Issue change_controller command, transferring this side to its owner with proper name and controller.
// Ensures that what the server now thinks is true is effected on all of the clients.
//
// We use the "player_left" field as follows. Normally change_controller sends one message to the owner,
// and one message to everyone else. In case that a player drops, the owner is gone and should not get
// a message, instead the host gets a [side_drop] message.
//
// In the server controller tweaks, we want to avoid sending controller change messages to the host.
// Doing this has the negative consequence that all of the AI side names are given the owners name.
// Therefore, if the side belongs to the host, we pass player_left = true, otherwise player_left = false.
@ -326,14 +322,6 @@ void game::start_game(player_iterator starter)
send_observerjoins();
}
void game::update_game()
{
started_ = false;
update_side_data();
describe_slots();
}
bool game::send_taken_side(simple_wml::document& cfg, const simple_wml::node* side) const
{
const std::size_t side_index = (*side)["side"].to_int() - 1;
@ -594,7 +582,7 @@ void game::change_controller(
auto response = change_controller_type(side_index, player, player_name);
if(started_) {
// the purpose of these records is so that observers, replay viewers, get controller updates correctly
// the purpose of these records is so that observers, replay viewers, etc get controller updates correctly
record_data(response->clone());
}
@ -616,7 +604,6 @@ std::unique_ptr<simple_wml::document> game::change_controller_type(const std::si
change.set_attr_dup("side", side.c_str());
change.set_attr_dup("player", player_name.c_str());
// Tell everyone but the source player that this side's controller changed.
change.set_attr_dup("controller", side_controllers_[side_index].to_cstring());
change.set_attr("is_local", "no");
@ -711,9 +698,8 @@ void game::mute_observer(const simple_wml::node& mute, player_iterator muter)
auto user { find_user(username) };
/**
* @todo FIXME: Maybe rather save muted nicks as a set of strings and
* also allow muting of usernames not in the game.
/*
* @todo FIXME: Maybe rather save muted nicks as a set of strings and also allow muting of usernames not in the game.
*/
if(!user || !is_observer(*user)) {
send_server_message("Observer '" + username.to_string() + "' not found.", muter);
@ -889,7 +875,7 @@ void game::process_message(simple_wml::document& data, player_iterator user)
const simple_wml::string_span& msg = (*message)["message"];
chat_message::truncate_message(msg, *message);
send_data(data, user, "game message");
send_data(data, user);
}
bool game::is_legal_command(const simple_wml::node& command, player_iterator user)
@ -1062,7 +1048,7 @@ bool game::process_turn(simple_wml::document& data, player_iterator user)
if(!repackage) {
record_data(data.clone());
send_data(data, user, "game replay");
send_data(data, user);
return turn_ended;
}
@ -1072,7 +1058,7 @@ bool game::process_turn(simple_wml::document& data, player_iterator user)
auto mdata = std::make_unique<simple_wml::document>();
simple_wml::node& mturn = mdata->root().add_child("turn");
(*command).copy_into(mturn.add_child("command"));
send_data(*mdata, user, "game replay");
send_data(*mdata, user);
record_data(std::move(mdata));
continue;
}
@ -1092,7 +1078,7 @@ bool game::process_turn(simple_wml::document& data, player_iterator user)
speak->copy_into(message_turn_command.add_child("speak"));
if(to_sides.empty()) {
send_data(*message, user, "game message");
send_data(*message, user);
record_data(std::move(message));
} else if(to_sides == game_config::observer_team_name) {
send_to_players(*message, observers_, user);
@ -1105,7 +1091,7 @@ bool game::process_turn(simple_wml::document& data, player_iterator user)
return turn_ended;
}
void game::handle_random_choice(const simple_wml::node&)
void game::handle_random_choice()
{
uint32_t seed = rng_.get_next_random();
@ -1122,11 +1108,11 @@ void game::handle_random_choice(const simple_wml::node&)
command.set_attr("from_side", "server");
command.set_attr("dependent", "yes");
send_data(*mdata, {}, "game replay");
send_data(*mdata, {});
record_data(std::move(mdata));
}
void game::handle_add_side_wml(const simple_wml::node&)
void game::handle_add_side_wml()
{
++nsides_;
side_controllers_.push_back(CONTROLLER::EMPTY);
@ -1193,7 +1179,7 @@ void game::handle_controller_choice(const simple_wml::node& req)
change_controller_wml.set_attr("is_local", "no");
send_data(*mdata, sides_[side_index], "game replay");
send_data(*mdata, sides_[side_index]);
record_data(std::move(mdata));
}
@ -1226,16 +1212,16 @@ void game::handle_choice(const simple_wml::node& data, player_iterator user)
return;
}
DBG_GAME << "answering seed request " << request_id << " by player "
DBG_GAME << "answering choice request " << request_id << " by player "
<< user->info().name() << std::endl;
last_choice_request_id_ = request_id;
if(const simple_wml::node* rand = data.child("random_seed")) {
handle_random_choice(*rand);
if(data.child("random_seed")) {
handle_random_choice();
} else if(const simple_wml::node* ccw = data.child("change_controller_wml")) {
handle_controller_choice(*ccw);
} else if(const simple_wml::node* asw = data.child("add_side_wml")) {
handle_add_side_wml(*asw);
} else if(data.child("add_side_wml")) {
handle_add_side_wml();
} else {
send_and_record_server_message("Found unknown server choice request: [" + data.first_child().to_string() + "]");
}
@ -1282,7 +1268,7 @@ void game::process_change_turns_wml(simple_wml::document& data, player_iterator
return;
}
set_current_turn(current_turn);
current_turn_ = current_turn;
num_turns_ = num_turns;
assert(static_cast<int>(this->current_turn()) == current_turn);
@ -1342,13 +1328,8 @@ void game::update_turn_data()
turns_cfg->set_attr_int("current", current_turn());
turns_cfg->set_attr_int("max", num_turns_);
}
/**
* @todo differentiate between "observers not allowed" and "player already in the game" errors.
* maybe return a string with an error message.
*/
bool game::add_player(player_iterator player, bool observer)
{
if(is_member(player)) {
@ -1638,7 +1619,7 @@ void game::send_to_players(simple_wml::document& data, const Container& players,
}
}
void game::send_data(simple_wml::document& data, std::optional<player_iterator> exclude, std::string /*packet_type*/)
void game::send_data(simple_wml::document& data, std::optional<player_iterator> exclude)
{
send_to_players(data, all_game_users(), exclude);
}
@ -1880,20 +1861,14 @@ std::string game::debug_player_info() const
std::stringstream result;
result << "game id: " << id_ << ", " << db_id_ << "\n";
// result << "players_.size: " << players_.size() << "\n";
for(auto user : players_) {
result << "player: " << user->info().name().c_str() << "\n";
}
// result << "observers_.size: " << observers_.size() << "\n";
for(auto user : observers_) {
result << "observer: " << user->info().name().c_str() << "\n";
}
/* result << "player_info_: begin\n";
for (player_map::const_iterator info = player_info_->begin(); info != player_info_->end(); info++){
result << info->second.name().c_str() << "\n";
}
result << "player_info_: end\n";*/
return result.str();
}
@ -1930,7 +1905,7 @@ void game::send_and_record_server_message(const char* message, std::optional<pla
{
auto doc = std::make_unique<simple_wml::document>();
send_server_message(message, {}, doc.get());
send_data(*doc, exclude, "message");
send_data(*doc, exclude);
if(started_) {
record_data(std::move(doc));
@ -1941,7 +1916,7 @@ void game::send_server_message_to_all(const char* message, std::optional<player_
{
simple_wml::document doc;
send_server_message(message, {}, &doc);
send_data(doc, exclude, "message");
send_data(doc, exclude);
}
void game::send_server_message(const char* message, std::optional<player_iterator> player, simple_wml::document* docptr) const

View file

@ -50,51 +50,108 @@ public:
~game();
/**
* This ID is reused between scenarios of MP campaigns.
* This ID resets when wesnothd is restarted.
* This is generally used when needing to find a particular running game.
* @return an ID that uniquely identifies the game within the currently running wesnothd instance.
*/
int id() const
{
return id_;
}
/**
* This ID is not reused between scenarios of MP campaigns.
* This ID resets when wesnothd is restarted.
* This is generally used during database queries.
*
* @return an ID that uniquely identifies the game within the currently running wesnothd instance.
*/
int db_id() const
{
return db_id_;
}
/**
* Increments the ID used when running database queries.
*/
void next_db_id()
{
db_id_ = db_id_num++;
}
/**
* @return The game's name.
*/
const std::string& name() const
{
return name_;
}
/**
* @param player The player being checked.
* @return Whether the provided player is the game's owner(host).
*/
bool is_owner(player_iterator player) const
{
return (player == owner_);
}
/**
* @param player The player being checked.
* @return Whether the provided player has joined the game.
*/
bool is_member(player_iterator player) const
{
return is_player(player) || is_observer(player);
}
/**
* @return Whether observers are allowed to join.
*/
bool allow_observers() const;
/**
* @param player The player being checked.
* @return Whether the provided player is an observer of this game.
*/
bool is_observer(player_iterator player) const;
/**
* @param player The player being checked.
* @return Whether the provided player is playing this game (aka owns one or more sides).
*/
bool is_player(player_iterator player) const;
/** Checks whether the connection's ip address or username is banned. */
/**
* @param player The player being checked (by iterator).
* @param name The player being checked (by username).
* @return Whether the connection's ip address or username is banned from this game.
*/
bool player_is_banned(player_iterator player, const std::string& name) const;
/** when the host sends the new scenario of a mp campaign */
void new_scenario(player_iterator player);
/**
* When the host sends the new scenario of a mp campaign
*
* @param sender The player sending the scenario data.
*/
void new_scenario(player_iterator sender);
/**
* @return Whether this game contains scenario data and thus has been initialized.
*/
bool level_init() const
{
return level_.child("snapshot") || level_.child("scenario");
}
/**
* The non-const version.
*
* @param data The data describing the level for a game.
* @return The [scenario] child node if it exists, else the [snapshot] child if it exists, else @a data.
*/
static simple_wml::node* starting_pos(simple_wml::node& data)
{
if(simple_wml::node* scenario = data.child("scenario")) {
@ -106,6 +163,12 @@ public:
return &data;
}
/**
* The const version.
*
* @param data The data describing the level for a game.
* @return The [scenario] child node if it exists, else the [snapshot] child if it exists, else @a data.
*/
static const simple_wml::node* starting_pos(const simple_wml::node& data)
{
if(const simple_wml::node* scenario = data.child("scenario")) {
@ -117,199 +180,352 @@ public:
return &data;
}
/**
* @return The nodes containing the sides in this game.
*/
const simple_wml::node::child_list& get_sides_list() const
{
return starting_pos(level_.root())->children("side");
}
/**
* @return Whether this game has started yet.
*/
bool started() const
{
return started_;
}
/**
* @return The number of players. One player can have multiple sides.
*/
std::size_t nplayers() const
{
return players_.size();
}
/**
* @return The number of observers in this game.
*/
std::size_t nobservers() const
{
return observers_.size();
}
/**
* @return This game's current turn.
*/
std::size_t current_turn() const
{
return current_turn_;
}
void set_current_turn(int turn)
{
current_turn_ = turn;
}
/**
* @return The name of the replay for this game.
*/
std::string get_replay_filename();
/** Toggles whether all observers are muted or not. */
void mute_all_observers();
/**
* Mute an observer or give a message of all currently muted observers if no
* name is given.
* Mute an observer or give a message of all currently muted observers if no name is given.
*
* @param mute The observer to mute. Empty if sending a message to muted observers.
* @param muter The player doing the muting.
*/
void mute_observer(const simple_wml::node& mute, player_iterator muter);
/**
* Unmute an observer or unmute all currently muted observers if no name is given.
*
* @param unmute The observer to unmute. Empty if unmuting all observers.
* @param unmuter The player doing the unmuting.
*/
void unmute_observer(const simple_wml::node& unmute, player_iterator unmuter);
/**
* Kick a member by name.
* Kick a user from this game by name.
*
* @return The iterator to the removed member if
* successful, empty optional otherwise.
* @param kick The user to kick.
* @param kicker The player doing the kicking.
* @return The iterator to the removed member if successful, empty optional otherwise.
*/
std::optional<player_iterator> kick_member(const simple_wml::node& kick, player_iterator kicker);
/**
* Ban and kick a user by name.
* Ban a user by name.
*
* The user does not need to be in this game but logged in.
*
* @return The iterator to the banned player if he
* was in this game, empty optional otherwise.
* @param ban The user to ban.
* @param banner The player doing the banning.
* @return The iterator to the banned player if he was in this game, empty optional otherwise.
*/
std::optional<player_iterator> ban_user(const simple_wml::node& ban, player_iterator banner);
/**
* Unban a user by name.
*
* The user does not need to be in this game but logged in.
*
* @param unban The user to unban.
* @param unbanner The player doing the unbanning.
*/
void unban_user(const simple_wml::node& unban, player_iterator unbanner);
/**
* Add a user to the game.
*
* @return True iff the user successfully joined the game.
* @todo differentiate between "observers not allowed" and "player already in the game" errors.
* maybe return a string with an error message.
*
* @param player The player to add.
* @param observer Whether to add the player as an observer.
* @return True if the user successfully joined the game, false otherwise.
*/
bool add_player(player_iterator player, bool observer = false);
/**
* Removes a user from the game.
*
* @return True iff the game ends. That is, if there are
* no more players or the host left on a not yet
* started game.
* @param player The player to remove.
* @param disconnect If the player disconnected from the server entirely.
* @param destruct If the game is ending as well.
* @return True if the player's removal ends the game. That is, if there are no more players or the host left on a not yet started game.
*/
bool remove_player(player_iterator player, const bool disconnect = false, const bool destruct = false);
/** Adds players and observers into one vector and returns that. */
/**
* @return A vector containing all players and observers currently in this game.
*/
const user_vector all_game_users() const;
/**
* Starts the game (if a new game) or starts the next scenario of an MP campaign.
* @param starter The game's host.
*/
void start_game(player_iterator starter);
// this is performed just before starting and before [start_game] signal
// send scenario_diff's specific to each client so that they locally
// control their human sides
/**
* This is performed just before starting and before the [start_game] signal.
* Sends [scenario_diff]s specific to each client so that they locally control their human sides.
*/
void perform_controller_tweaks();
void update_game();
/** A user (player only?) asks for the next scenario to advance to. */
void load_next_scenario(player_iterator user); // const
// iceiceice: I unmarked this const because I want to send and record server messages when I fail to tweak sides
// properly
/**
* A user asks for the next scenario to advance to.
*
* @param user The user asking for the next scenario.
*/
void load_next_scenario(player_iterator user);
/** Resets the side configuration according to the scenario data. */
void update_side_data();
/** Let's a player owning a side give it to another player or observer. */
/**
* Lets a player owning a side give it to another player or observer.
*
* @param player The player owning the side.
* @param cfg The node containing the transfer information.
*/
void transfer_side_control(player_iterator player, const simple_wml::node& cfg);
void process_message(simple_wml::document& data, player_iterator);
/**
* Sends an ingame message to all other players.
*
* @param data The message to send.
* @param user The user sending the message.
*/
void process_message(simple_wml::document& data, player_iterator user);
/**
* Handles [end_turn], repackages [commands] with private [speak]s in them
* and sends the data.
* Also filters commands from all but the current player.
* Currently removes all commands but [speak] for observers and all but
* [speak], [label] and [rename] for players.
* [speak], [label], and [rename] for players.
*
* @returns True if the turn ended.
* @param data The turn commands.
* @param user The user who sent a command to be processed during the turn. This may not be the player whose turn it currently is.
* @returns True if the turn ended.
*/
bool process_turn(simple_wml::document& data, player_iterator user);
/** Handles incoming [whiteboard] data. */
/**
* Handles incoming [whiteboard] data.
*
* @param data The whiteboard data.
* @param user The user sending the whiteboard data.
*/
void process_whiteboard(simple_wml::document& data, player_iterator user);
/** Handles incoming [change_turns_wml] data. */
/**
* Handles incoming [change_turns_wml] data.
*
* @param data The [change_turns_wml] data.
* @param user The player changing turns.
*/
void process_change_turns_wml(simple_wml::document& data, player_iterator user);
/**
* Set the description to the number of available slots.
*
* @returns True iff the number of slots has changed.
* @returns True if the number of slots has changed.
*/
bool describe_slots();
/**
* Sends a message to all players in this game that aren't excluded.
*
* @param message The message to send.
* @param exclude The players to not send the message to.
*/
void send_server_message_to_all(const char* message, std::optional<player_iterator> exclude = {});
/**
* @ref send_server_message_to_all
*/
void send_server_message_to_all(const std::string& message, std::optional<player_iterator> exclude = {})
{
send_server_message_to_all(message.c_str(), exclude);
}
/**
* Send a server message to the specified player.
*
* @param message The message to send.
* @param player The player to send the message to. If empty then the message is not sent.
* @param doc The document to create the message in. If nullptr then a new document is created.
*/
void send_server_message(
const char* message, std::optional<player_iterator> player = {}, simple_wml::document* doc = nullptr) const;
/**
* @ref send_server_message
*/
void send_server_message(
const std::string& message, std::optional<player_iterator> player = {}, simple_wml::document* doc = nullptr) const
{
send_server_message(message.c_str(), player, doc);
}
/** Send data to all players in this game except 'exclude'. */
/**
* Send data to all players in this game except 'exclude'.
* Also record this data for the replay.
*
* @param message The message to send.
* @param exclude The players to not send the message to.
*/
void send_and_record_server_message(const char* message, std::optional<player_iterator> exclude = {});
/**
* @ref send_and_record_server_message
*/
void send_and_record_server_message(const std::string& message, std::optional<player_iterator> exclude = {})
{
send_and_record_server_message(message.c_str(), exclude);
}
/**
* Send data to all players except those excluded.
* For example, to send a message to all players except the player who typed the original message.
*
* @param data The data to send.
* @param players The players to send the data to.
* @param exclude The player from @a players to not send the data to.
*/
template<typename Container>
void send_to_players(simple_wml::document& data, const Container& players, std::optional<player_iterator> exclude = {});
void send_data(simple_wml::document& data, std::optional<player_iterator> exclude = {}, std::string packet_type = "");
/**
* Send data to all players and observers except those excluded.
*
* @param data The data to send.
* @param exclude The players/observers to not send the data to.
*/
void send_data(simple_wml::document& data, std::optional<player_iterator> exclude = {});
/**
* Clears the history of recorded WML documents.
*/
void clear_history();
/**
* Records a WML document in the game's history.
*
* @param data The WML document to record.
*/
void record_data(std::unique_ptr<simple_wml::document> data);
/**
* Move the level information and recorded history into a replay file and save it.
*/
void save_replay();
/** The full scenario data. */
/**
* @return The full scenario data.
*/
simple_wml::document& level()
{
return level_;
}
/**
* Functions to set/get the address of the game's summary description as
* sent to players in the lobby.
* Set the game's description.
* Also set the game as requiring a password if a password is set.
*
* @param desc The node containing the game's description.
*/
void set_description(simple_wml::node* desc);
/**
* @return The node containing the game's current description.
*/
simple_wml::node* description() const
{
return description_;
}
/**
* Sets the password required to access the game.
*
* @param passwd The password to set.
*/
void set_password(const std::string& passwd)
{
password_ = passwd;
}
/**
* Set a list of usernames that should all be banned from joining the game.
*
* @param name_bans The list of usernames.
*/
void set_name_bans(const std::vector<std::string> name_bans)
{
name_bans_ = name_bans;
}
/**
* @param passwd The password to join with.
* @return True if the game's password is empty or if the provided password matches, false otherwise.
*/
bool password_matches(const std::string& passwd) const
{
return password_.empty() || passwd == password_;
}
/**
* @return Whether the game has a password set.
*/
bool has_password() const
{
return !password_.empty();
}
/**
* Provides the reason the game was ended.
*
* @return Either that the game was aborted (after starting), not started, or has some other reason set.
*/
const std::string& termination_reason() const
{
static const std::string aborted = "aborted";
@ -318,26 +534,58 @@ public:
return started_ ? (termination_.empty() ? aborted : termination_) : not_started;
}
/**
* Sets the termination reason for this game.
*
* @param reason The termination reason.
*/
void set_termination_reason(const std::string& reason);
/**
* Handle a choice requested by a client, such as changing a side's controller, if initiated by WML/lua.
*
* @param data The data needed to process the choice.
* @param user The player making the request.
*/
void handle_choice(const simple_wml::node& data, player_iterator user);
void handle_random_choice(const simple_wml::node& data);
/**
* Send a randomly generated number to the requestor.
*/
void handle_random_choice();
/**
* Handle a request to change a side's controller.
* Note that this does not change who owns a side.
*
* @param data Contains the information about which side to change the controller of.
*/
void handle_controller_choice(const simple_wml::node& data);
void handle_add_side_wml(const simple_wml::node& req);
/**
* Adds a new, empty side owned by no one.
*/
void handle_add_side_wml();
/**
* Reset the internal counter for choice requests made by clients to the server.
*/
void reset_last_synced_context_id()
{
last_choice_request_id_ = -1;
}
/**
* Function which returns true iff 'player' controls any of the sides spcified in 'sides'.
* Function which returns true if 'player' controls any of the sides specified in 'sides'.
*
* @param sides The list of sides in this game.
* @param player The player being checked for whether they own any sides.
*/
bool controls_side(const std::vector<int>& sides, player_iterator player) const;
/**
* @return Whether the loaded WML has the attribute indicating that this is a reloaded savegame rather than a brand new game.
*/
bool is_reload() const;
private:
@ -345,29 +593,59 @@ private:
game(const game&) = delete;
game& operator=(const game&) = delete;
/**
* @return 0 if there are no sides, or the current side index otherwise.
*/
std::size_t current_side() const
{
return nsides_ ? (current_side_index_ % nsides_) : 0;
return nsides_ != 0 ? (current_side_index_ % nsides_) : 0;
}
/**
* @return The player who owns the current side.
*/
std::optional<player_iterator> current_player() const
{
return sides_[current_side()];
}
/**
* @param player The player being checked.
* @return Whether the player being checked is the current player taking their turn.
*/
bool is_current_player(player_iterator player) const
{
return (current_player() == player);
}
/**
* @param player The observer being checked.
* @return True if the observer is muted or if all observers are muted, false otherwise.
*/
bool is_muted_observer(player_iterator player) const;
/**
* @return True if all observers have been muted via that command (not if each individual observer happens to have been manually muted).
*/
bool all_observers_muted() const
{
return all_observers_muted_;
}
/**
* Sends a message either stating that all observers are muted or listing the observers that are muted.
*
* @param user The player to send the message to.
*/
void send_muted_observers(player_iterator user) const;
/**
* Tell the host who owns a side.
*
* @param cfg The document to send to the host.
* @param side The side information to send.
* @return True if the document was sent, false otherwise.
*/
bool send_taken_side(simple_wml::document& cfg, const simple_wml::node* side) const;
/**
@ -378,38 +656,61 @@ private:
* happen.
* First we look for a side where save_id= or current_player= matches the
* new user's name then we search for the first controller="network" side.
*
* @param user The player taking a side.
* @return True if the side was taken, false otherwise.
*/
bool take_side(player_iterator user);
/**
* Send [change_controller] message to tell all clients the new controller's name
* or controller type (human or ai).
* Send [change_controller] message to tell all clients the new controller's name or controller type (human or ai).
*
* @param side_index The index of the side whose controller is changing.
* @param player The player who is taking control of the side.
* @param player_name The name of the player who is taking control of the side.
* @param player_left We use the "player_left" field as follows. Normally change_controller sends one message to the owner, and one message to everyone else.
* In case that a player drops, the owner is gone and should not get a message, instead the host gets a [side_drop] message.
*/
void change_controller(const std::size_t side_num,
player_iterator sock,
void change_controller(const std::size_t side_index,
player_iterator player,
const std::string& player_name,
const bool player_left = true);
std::unique_ptr<simple_wml::document> change_controller_type(const std::size_t side_num,
/**
* Tell everyone else but the source player that the controller type changed.
*
* @param side_index The index of the side whose controller type is changing.
* @param player The player who owns the side whose controller type is changing.
* @param player_name The name of the player who owns the side whose controller type is changing.
* @return The document that was sent to all other players.
*/
std::unique_ptr<simple_wml::document> change_controller_type(const std::size_t side_index,
player_iterator player,
const std::string& player_name);
void transfer_ai_sides(player_iterator player);
/**
* Tells a player to leave the game.
*
* @param user The player leaving the game.
*/
void send_leave_game(player_iterator user) const;
/**
* @param data the data to be sent to the sides.
* @param sides a comma sperated list of side numbers to which the package should be sent.
* @param exclude sides to not send the data to.
* Sends a document to the provided list of sides.
*
* @param data The data to be sent to the provided sides.
* @param sides A comma sperated list of side numbers to which the document should be sent.
* @param exclude Players to not send the data to.
*/
void send_data_sides(simple_wml::document& data,
const simple_wml::string_span& sides,
std::optional<player_iterator> exclude = {});
void send_data_observers(
simple_wml::document& data, std::optional<player_iterator> exclude = {}, std::string packet_type = "") const;
/**
* Send [observer] tags of all the observers in the game to the user or
* everyone if none given.
* Send a document per observer in the game.
* If @a player is blank, send these documents to everyone, else send them to just the observer who joined.
*
* @param player The observer who joined.
*/
void send_observerjoins(std::optional<player_iterator> player = {});
void send_observerquit(player_iterator observer);
@ -418,19 +719,14 @@ private:
/** In case of a host transfer, notify the new host about its status. */
void notify_new_host();
/** Shortcut to a convenience function for finding a user by name. */
/**
* Shortcut to a convenience function for finding a user by name.
*
* @param name The name of the user to find.
* @return The player if found, else empty.
*/
std::optional<player_iterator> find_user(const simple_wml::string_span& name);
bool observers_can_label() const
{
return false;
}
bool observers_can_chat() const
{
return true;
}
bool is_legal_command(const simple_wml::node& command, player_iterator user);
/**
@ -442,49 +738,80 @@ private:
/**
* Function which should be called every time a player ends their turn
* (i.e. [end_turn] received). This will update the 'turn' attribute for
* the game's description when appropriate. Will return true iff there has
* been a change.
* the game's description when appropriate.
*
* @param new_side The side number whose turn to move it has become.
* @return True if the current side and-or current turn values have been updated, false otherwise.
*/
bool end_turn(int new_side);
/**
* Set or update the current and max turn values in the game's description.
*/
void update_turn_data();
/**
* Function to send a list of users to all clients.
*
* Only sends data if the game is initialized but not yet started.
*
* @param exclude The players to not send the list of users to.
*/
void send_user_list(std::optional<player_iterator> exclude = {});
/** Returns the name of the user or "(unfound)". */
/**
* @param pl The player.
* @return The player's username.
*/
std::string username(player_iterator pl) const;
/** Returns a comma separated list of user names. */
/**
* @param users The users to create a comma separated list from.
* @return A comma separated list of user names.
*/
std::string list_users(user_vector users) const;
/** calculates the initial value for sides_, side_controllerds_, nsides_*/
void reset_sides();
/** Helps debugging player and observer lists. */
/**
* Helps debugging player and observer lists.
*
* @return A string listing the game IDs, players, and observers.
*/
std::string debug_player_info() const;
/** Helps debugging controller tweaks. */
/**
* Helps debugging controller tweaks.
*
* @return A string listing the game IDs and side information.
*/
std::string debug_sides_info() const;
/** The wesnothd server instance this game exists on. */
wesnothd::server& server;
player_connections& player_connections_;
// used for unique identification of game instances within wesnothd
/**
* Incremented to retrieve a unique ID for game instances within wesnothd.
*/
static int id_num;
/** This game's ID within wesnothd */
int id_;
// used for unique identification of games played in the database
// necessary since for MP campaigns multiple scenarios can be played within the same game instance
// and we need a unique ID per scenario played, not per game instance
/**
* Incremented to retrieve a unique ID per wesnothd instance for game instances within the database.
*/
static int db_id_num;
/**
* Used for unique identification of games played in the database.
* Necessary since for MP campaigns multiple scenarios can be played within the same game instance
* and we need a unique ID per scenario played, not per game instance.
*/
int db_id_;
/** The name of the game. */
std::string name_;
/** The password needed to join the game. */
std::string password_;
/** The game host or later owner (if the host left). */
@ -495,25 +822,30 @@ private:
/** A vector of observers (members not owning a side). */
user_vector observers_;
/** A vector of muted observers. */
user_vector muted_observers_;
/** A vector of side owners. */
side_vector sides_;
/** A vector containiner the controller type for each side. */
std::vector<CONTROLLER> side_controllers_;
/** Number of sides in the current scenario. */
int nsides_;
/** Whether the game has been started or not. */
bool started_;
/**
The current scenario data.´
The current scenario data.
WRONG! This contains the initial state or the state from which
the game was loaded from.
Using this to make assumptions about the current gamestate is
extremely dangerous and should especially not be done for anything
that can be nodified by wml (especially by [modify_side]),
like team_name, controller ... in [side].
FIXME: move every code here that uses this object to query those
information to the clients. But note that there are some checks
(like controller == null) that are definitely needed by the server and
@ -530,14 +862,20 @@ private:
/** Pointer to the game's description in the games_and_users_list_. */
simple_wml::node* description_;
/** The game's current turn. */
int current_turn_;
/** The index of the current side. The side number is current_side_index_+1. */
int current_side_index_;
/** The maximum number of turns before the game ends. */
int num_turns_;
/** Whether all observers should be treated as muted. */
bool all_observers_muted_;
// IP ban list and name ban list
/** List of banned IPs */
std::vector<std::string> bans_;
/** List of banned usernames */
std::vector<std::string> name_bans_;
/**
* in multiplayer campaigns it can happen that some players are still in the previous scenario
* keep track of those players because processing certain
@ -545,13 +883,20 @@ private:
*/
std::set<const player_record*> players_not_advanced_;
/** The reason the game ended. */
std::string termination_;
/** Whether to save a replay of this game. */
bool save_replays_;
/** Where to save the replay of this game. */
std::string replay_save_path_;
/** A wrapper for mersenne twister rng which generates randomness for this game */
randomness::mt_rng rng_;
/**
* The ID of the last request received from a client.
* New requests should never have a lower value than this.
*/
int last_choice_request_id_;
};