src/Network/Server.hh
author Tero Marttila <terom@fixme.fi>
Tue, 20 Jan 2009 23:30:18 +0200
changeset 408 e6cfc44266af
parent 400 d64bf28c4340
child 431 c6d7272a164b
permissions -rw-r--r--
reorganize Terrain/PhysicsWorld/GameState/Engine to use NetworkClientConnect, and hence handle the connection process asynchronously, and finally properly implement receiving the terrain data from the server
#ifndef NETWORKSERVER_HH
#define NETWORKSERVER_HH

/**
 * @file
 *
 * Game server implementation
 */

#include "../GameState.hh"
#include "Session.hh"
#include "Object.hh"

#include <list>
#include <map>
#include <ClanLib/core.h>

// forward-declare
class NetworkServerPlayer;

/**
 * Our game's NetworkServer... this has the GameState, NetworkSession, etc
 */
class NetworkServer {
    friend class NetworkServerObject;
    friend class NetworkServerPlayer;
    friend class NetworkServerProjectile;

    protected:
        /**
         * The GameState
         */ 
        GameState &state;
        CL_SlotContainer slots;
        
        /**
         * The server-mode NetworkSession
         */
        NetworkSession netsession;

        /**
         * The NetworkObject_ServerController that we use
         */
        NetworkObject_ServerController controller;

        /**
         * A list of NetworkServerPlayer's, used when a new player connects to send it information about existing
         * NetworkServerPlayer objects
         */
        std::list<NetworkServerPlayer *> players;

    public:
        /**
         * Construct a NetworkServer, using the given GameState and listening on the given address
         */
        NetworkServer (GameState &state, const NetworkEndpoint &listen_addr);
    
    protected:
        /**
         * Called by NetworkServerPlayer when it disconnects, this removes it from our list
         */
        void handle_disconnect (NetworkServerPlayer *player);

    private:
        /**
         * Our NetworkSession::sig_node_connected handler, this creates a new NetworkServerPlayer and adds it to
         * our list of players
         */
        void on_node_connected (NetworkNode *node);
        
        /**
         * Called from on_node_connected to send the initial Terrain data using the NETCHAN_TERRAIN_ARRAY channel to
         * the given node.
         */
        void send_terrain_data (NetworkNode *node);
};

/**
 * Our base NetworkObject_Server class, that also holds the NetworkServer reference and a CL_SlotContainer for
 * conveniance.
 */
class NetworkServerObject : public NetworkObject_Server {
    protected:
        /**
         * Our NetworkServer
         */
        NetworkServer &server;
        CL_SlotContainer slots;
        
        /**
         * Constructs this NetworkServerObject, passing the server's controller to the NetworkObject_Server constructor
         */
        NetworkServerObject (NetworkServer &server);
};

/**
 * A remote player on this server, this is both a LocalPlayer and a NetworkServerObject
 */
class NetworkServerPlayer : public LocalPlayer, public NetworkServerObject {
    protected:
        /**
         * The remote node that represents this actual player
         */
        NetworkNode *node;

    public:
        /**
         * Construct this using the given server (for NetworkServerObject) and node (for node).
         *
         * We send the initial NETMSG_SERVER_HELLO to the client, then a set of NETMSG_PLAYER_INFOs
         * for all the other players, a NETMSG_PLAYER_JOIN to all the other clients, and then calls
         * send_terrain_data to sync the initial terrain.
         *
         * @see NetworkServerObject
         */
        NetworkServerPlayer (NetworkServer &server, NetworkNode *node);
    
    protected:    
        // @{
        /**
         * These methods are overriden from Player to replicate events to our clients
         */
        virtual void handleDig (Vector position, float radius);
        virtual void handleFireWeapon (Weapon *weapon, Vector position, Vector velocity);
        virtual void handleChangeWeapon (unsigned int weaponIndex);
        virtual void handleRopeState (RopeState state);
        virtual void handleRopeLength (float length);
    
        virtual void spawn (Vector position);
        virtual void die (bool start_timer = true);
        // @}
        //
        
    private:
        /**
         * Our NetworkNode::sig_disconnected handler. This calls NetworkServer::handle_disconnect, sends a 
         * NETMSG_PLAYER_QUIT message to all remaining clients, and destroys this player.
         */
        void on_disconnected (void);

        /*
         * Our NETMSG_PLAYER_INPUT handler. This calls our superclass LocalPlayer::handleInput, which may then call
         * the various handle* methods. After this, we call send_position_update
         */
        void on_input (NetworkNode *node, NetworkPacketInput &pkt);
        
        /**
         * Called from on_input to broadcast an unreliable position update with this player's physics state
         */
        void send_position_update (void);
};

/**
 * A Projectile, replicated across the network.
 *
 * These are created by NetworkServerPlayer::handleFireWeapon
 */
class NetworkServerProjectile : public Projectile, public NetworkServerObject {
    public:
        /**
         * Call the Projectile construtor, and then send NETMSG_PROJECTILE_PLAYER_FIRED
         *
         * @param server the NetworkServer
         * @param player the NetworkServerPlayer that fired the weapon
         * @param position the Projectile's initial position
         * @param velocity the Projectile's initial velocity
         * @param weapon the Player's Weapon that was fired
         */
        NetworkServerProjectile (NetworkServer &server, NetworkServerPlayer *player, Vector position, Vector velocity, Weapon *weapon);
    
    protected:
        /**
         * Overriden from Projectile to send a NETMSG_PROJECTILE_DESTROY with the given position and flags
         *
         * @param position the Projectile's final position, where the ground gets removed
         * @param removeGround controls the NETWORK_PROJECTILE_REMOVE_GROUND flag
         */
        virtual void onDestroy (Vector position, bool removeGround);
        
        /**
         * Overriden from Projectile to send a NETMSG_PROJECTILE_HIT_PLAYER with the given player
         *
         * @param player the NetworkServerPlayer that got hit
         */
        virtual void onHitPlayer (Player *player_ptr);
};

#endif