server/game.hpp

Go to the documentation of this file.
00001 /* $Id: game.hpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2003 - 2012 by David White <dave@whitevine.net>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 #ifndef GAME_HPP_INCLUDED
00017 #define GAME_HPP_INCLUDED
00018 
00019 #include "../network.hpp"
00020 #include "player.hpp"
00021 
00022 #include "simple_wml.hpp"
00023 
00024 #include <map>
00025 #include <vector>
00026 
00027 //class player;
00028 
00029 namespace wesnothd {
00030 
00031 typedef std::map<network::connection,player> player_map;
00032 typedef std::vector<network::connection> user_vector;
00033 typedef std::vector<network::connection> side_vector;
00034 
00035 class game
00036 {
00037 public:
00038     game(player_map& players, const network::connection host=0,
00039             const std::string& name="", bool save_replays=false,
00040             const std::string& replay_save_path="");
00041     ~game();
00042 
00043     int id() const { return id_; }
00044     const std::string& name() const { return name_; }
00045 
00046     bool is_owner(const network::connection player) const { return (player == owner_); }
00047     bool is_member(const network::connection player) const
00048     { return is_player(player) || is_observer(player); }
00049     bool allow_observers() const;
00050     bool is_observer(const network::connection player) const;
00051     bool is_player(const network::connection player) const;
00052 
00053     /** Checks whether the connection's ip address is banned. */
00054     bool player_is_banned(const network::connection player) const;
00055     bool level_init() const { return level_.child("side") != NULL; }
00056     bool started() const { return started_; }
00057 
00058     size_t nplayers() const { return players_.size(); }
00059     size_t nobservers() const { return observers_.size(); }
00060     size_t current_turn() const { return (nsides_ ? end_turn_ / nsides_ + 1 : 0); }
00061 
00062     void mute_all_observers();
00063 
00064     /**
00065      * Mute an observer or give a message of all currently muted observers if no
00066      * name is given.
00067      */
00068     void mute_observer(const simple_wml::node& mute, const player_map::const_iterator muter);
00069 
00070     void unmute_observer(const simple_wml::node& unmute, const player_map::const_iterator unmuter);
00071 
00072     /**
00073      * Kick a member by name.
00074      *
00075      * @return                    The network handle of the removed member if
00076      *                            successful, '0' otherwise.
00077      */
00078     network::connection kick_member(const simple_wml::node& kick, const player_map::const_iterator kicker);
00079 
00080     /**
00081      * Ban and kick a user by name.
00082      *
00083      * The user does not need to be in this game but logged in.
00084      *
00085      * @return                    The network handle of the banned player if he
00086      *                            was in this game, '0' otherwise.
00087      */
00088     network::connection ban_user(const simple_wml::node& ban, const player_map::const_iterator banner);
00089 
00090     void unban_user(const simple_wml::node& unban, const player_map::const_iterator unbanner);
00091 
00092     /**
00093      * Add a user to the game.
00094      *
00095      * @return                    True iff the user successfully joined the game.
00096      */
00097     bool add_player(const network::connection player, bool observer = false);
00098 
00099     /**
00100      * Removes a user from the game.
00101      *
00102      * @return                    True iff the game ends. That is, if there are
00103      *                            no more players or the host left on a not yet
00104      *                            started game.
00105      */
00106     bool remove_player(const network::connection player, const bool disconnect=false, const bool destruct=false);
00107 
00108     /** Adds players and observers into one vector and returns that. */
00109     const user_vector all_game_users() const;
00110 
00111     void start_game(const player_map::const_iterator starter);
00112 
00113     /** A user (player only?) asks for the next scenario to advance to. */
00114     void load_next_scenario(const player_map::const_iterator user) const;
00115 
00116     /** Resets the side configuration according to the scenario data. */
00117     void update_side_data();
00118 
00119     /** Let's a player owning a side give it to another player or observer. */
00120     void transfer_side_control(const network::connection sock, const simple_wml::node& cfg);
00121 
00122     void process_message(simple_wml::document& data, const player_map::iterator user);
00123 
00124     /**
00125      * Handles [end_turn], repackages [commands] with private [speak]s in them
00126      * and sends the data.
00127      * Also filters commands from all but the current player.
00128      * Currently removes all commands but [speak] for observers and all but
00129      * [speak], [label] and [rename] for players.
00130      *
00131      * @returns                   True if the turn ended.
00132      */
00133     bool process_turn(simple_wml::document& data, const player_map::const_iterator user);
00134 
00135     /** Handles incoming [whiteboard] data. */
00136     void process_whiteboard(simple_wml::document& data, const player_map::const_iterator user);
00137 
00138     /**
00139      * Set the description to the number of available slots.
00140      *
00141      * @returns                   True iff the number of slots has changed.
00142      */
00143     bool describe_slots();
00144 
00145     void send_server_message_to_all(const char* message, network::connection exclude=0) const;
00146     void send_server_message_to_all(const std::string& message, network::connection exclude=0) const
00147     {
00148         send_server_message_to_all(message.c_str(), exclude);
00149     }
00150 
00151     void send_server_message(const char* message, network::connection sock=0, simple_wml::document* doc=NULL) const;
00152     void send_server_message(const std::string& message, network::connection sock=0, simple_wml::document* doc=NULL) const
00153     {
00154         send_server_message(message.c_str(), sock, doc);
00155     }
00156 
00157     /** Send data to all players in this game except 'exclude'. */
00158     void send_and_record_server_message(const char* message, const network::connection exclude=0);
00159     void send_and_record_server_message(const std::string& message, const network::connection exclude=0)
00160     {
00161         send_and_record_server_message(message.c_str(), exclude);
00162     }
00163 
00164     void send_data(simple_wml::document& data, const network::connection exclude=0, std::string packet_type = "") const;
00165 
00166     void clear_history();
00167     void record_data(simple_wml::document* data);
00168     void save_replay();
00169 
00170     /** The full scenario data. */
00171     simple_wml::document& level() { return level_; }
00172 
00173     /**
00174      * Functions to set/get the address of the game's summary description as
00175      * sent to players in the lobby.
00176      */
00177     void set_description(simple_wml::node* desc);
00178     simple_wml::node* description() const { return description_; }
00179 
00180     void set_password(const std::string& passwd) { password_ = passwd; }
00181     bool password_matches(const std::string& passwd) const {
00182         return password_.empty() || passwd == password_;
00183     }
00184 
00185     const std::string& termination_reason() const {
00186         static const std::string aborted = "aborted";
00187         static const std::string not_started = "not started";
00188         return started_ ? (termination_.empty() ? aborted : termination_) : not_started;
00189     }
00190 
00191     void set_termination_reason(const std::string& reason);
00192 
00193     void allow_global(const simple_wml::document &data);
00194 
00195 private:
00196     //forbidden operations
00197     game(const game&);
00198     void operator=(const game&);
00199 
00200     size_t current_side() const { return (nsides_ ? end_turn_ % nsides_ : 0); }
00201     network::connection current_player() const
00202     { return (nsides_ ? sides_[current_side()] : 0); }
00203     bool is_current_player(const network::connection player) const
00204     { return (current_player() == player); }
00205     bool is_muted_observer(const network::connection player) const;
00206     bool all_observers_muted() const { return all_observers_muted_; }
00207     void send_muted_observers(const player_map::const_iterator user) const;
00208 
00209     bool send_taken_side(simple_wml::document& cfg, const simple_wml::node::child_list::const_iterator side) const;
00210     /**
00211      * Figures out which side to take and tells that side to the game owner.
00212      *
00213      * The owner then should send a [scenario_diff] that implements the side
00214      * change and a subsequent update_side_data() call makes it actually
00215      * happen.
00216      * First we look for a side where save_id= or current_player= matches the
00217      * new user's name then we search for the first controller="network" side.
00218      */
00219     bool take_side(const player_map::const_iterator user);
00220 
00221     /**
00222      * Send [change_controller] message to tell all clients the new controller's name
00223      * or controller type (human or ai).
00224      */
00225     void change_controller(const size_t side_num,
00226             const network::connection sock,
00227             const std::string& player_name,
00228             const bool player_left = true,
00229             const std::string& controller = "");
00230     void transfer_ai_sides(const network::connection player);
00231     void send_leave_game(network::connection user) const;
00232     void send_data_team(simple_wml::document& data, const simple_wml::string_span& team,
00233             const network::connection exclude=0, std::string packet_type = "") const;
00234     void send_data_observers(simple_wml::document& data, const network::connection exclude=0, std::string packet_type = "") const;
00235 
00236     /**
00237      * Send [observer] tags of all the observers in the game to the user or
00238      * everyone if none given.
00239      */
00240     void send_observerjoins(const network::connection sock=0) const;
00241     void send_observerquit(const player_map::const_iterator observer) const;
00242     void send_history(const network::connection sock) const;
00243 
00244     /** In case of a host transfer, notify the new host about its status. */
00245     void notify_new_host();
00246 
00247     /** Shortcut to a convenience function for finding a user by name. */
00248     player_map::iterator find_user(const simple_wml::string_span& name);
00249 
00250     bool observers_can_label() const { return false; }
00251     bool observers_can_chat() const { return true; }
00252     bool is_legal_command(const simple_wml::node& command, bool is_player);
00253 
00254     /**
00255      * Function which returns true iff 'player' is on 'team'.
00256      * AI controlled sides are not considered on a team.
00257      */
00258     bool is_on_team(const simple_wml::string_span& team, const network::connection player) const;
00259     /**
00260      * Checks whether a user has the same IP as members of this game.
00261      * If observer is true it only checks against players.
00262      * @return  A comma separated string of members with matching IPs.
00263      */
00264     std::string has_same_ip(const network::connection& user, bool observer) const;
00265 
00266     /**
00267      * Function which should be called every time a player ends their turn
00268      * (i.e. [end_turn] received). This will update the 'turn' attribute for
00269      * the game's description when appropriate. Will return true iff there has
00270      * been a change.
00271      */
00272     bool end_turn();
00273 
00274     /**
00275      * Function to send a list of users to all clients.
00276      *
00277      * Only sends data if the game is initialized but not yet started.
00278      */
00279     void send_user_list(const network::connection exclude=0) const;
00280 
00281     /** Returns the name of the user or "(unfound)". */
00282     std::string username(const player_map::const_iterator pl) const;
00283 
00284     /** Returns a comma separated list of user names. */
00285     std::string list_users(user_vector users, const std::string& func) const;
00286 
00287     /** Function to log when we don't find a connection in player_info_. */
00288     void missing_user(network::connection socket, const std::string& func) const;
00289 
00290     /** Helps debugging player and observer lists. */
00291     std::string debug_player_info() const;
00292 
00293     player_map* player_info_;
00294 
00295     static int id_num;
00296     int id_;
00297 
00298     /** The name of the game. */
00299     std::string name_;
00300     std::string password_;
00301 
00302     /** The game host or later owner (if the host left). */
00303     network::connection owner_;
00304 
00305     /** A vector of players (members owning a side). */
00306     user_vector players_;
00307 
00308     /** A vector of observers (members not owning a side). */
00309     user_vector observers_;
00310     user_vector muted_observers_;
00311 
00312     /** A vector of side owners. */
00313     side_vector sides_;
00314 
00315     /**
00316      * A vector of controller strings indicating the type.
00317      * "human"   - a side controlled by a human
00318      * "ai"      - a side controlled by an AI
00319      * "null"    - an empty side
00320      */
00321     std::vector<std::string> side_controllers_;
00322 
00323     /** Number of sides in the current scenario. */
00324     int nsides_;
00325     bool started_;
00326 
00327     /** The current scenario data. */
00328     simple_wml::document level_;
00329 
00330     /** Replay data. */
00331     mutable std::vector<simple_wml::document*> history_;
00332 
00333     /** Pointer to the game's description in the games_and_users_list_. */
00334     simple_wml::node* description_;
00335 
00336     int end_turn_;
00337 
00338     bool all_observers_muted_;
00339 
00340     std::vector<std::string> bans_;
00341 
00342     std::string termination_;
00343 
00344     bool save_replays_;
00345     std::string replay_save_path_;
00346 
00347     /** The side from which global variable data is expected*/
00348     int global_wait_side_;
00349 };
00350 
00351 struct game_is_member {
00352     game_is_member(network::connection sock) : sock_(sock) {};
00353     bool operator()(const game* g) const { return g->is_owner(sock_) || g->is_member(sock_); }
00354 
00355 private:
00356     network::connection sock_;
00357 };
00358 
00359 struct game_id_matches {
00360     game_id_matches(int id) : id_(id) {};
00361     bool operator()(const game* g) const { return g->id() == id_; }
00362 
00363 private:
00364     int id_;
00365 };
00366 }
00367 #endif
00368 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:09 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs