--- a/src/Network/Object.hh Mon Dec 08 16:14:23 2008 +0000
+++ b/src/Network/Object.hh Mon Dec 08 16:23:30 2008 +0000
@@ -7,7 +7,14 @@
#include <map>
+/**
+ * A NetworkObject's ID is a 32-bit integer
+ */
typedef uint32_t NetworkObjectID;
+
+/**
+ * A NetworkObject's message type is a 16-bit integer
+ */
typedef uint16_t NetworkMessageID;
// forward-declare
@@ -15,32 +22,65 @@
class NetworkObject_Client;
class NetworkObject_Server;
+/**
+ * A NetworkObjectController contains a mapping of NetworkObjectID -> NetworkObject, and handles the
+ * messages received on our channel from the NetworkSession.
+ *
+ * Additionally, this provides methods to read/write NetworkObject references from/to a NetworkPacket
+ */
class NetworkObjectController {
friend class NetworkObject;
friend class NetworkObject_Server;
friend class NetworkObject_Client;
private:
+ /**
+ * The NetworkSession that we use
+ */
NetworkSession &session;
+
+ /**
+ * The NetworkChannelID that we use to communicate
+ */
NetworkChannelID channel_id;
-
+
+ /**
+ * Our map of NetworkObjectID -> NetworkObject
+ */
std::map<NetworkObjectID, NetworkObject*> objects;
-
+
CL_Slot slot_message;
protected:
+ /**
+ * Construct a NetworkObjectController to use the given NetworkSession and NetworkChannelID
+ */
NetworkObjectController (NetworkSession &session, NetworkChannelID channel_id);
private:
+ /**
+ * Our NetworkSession::sig_chan_message handler
+ *
+ * Reads the NetworkObjectID and NetworkMessageID from the packet, and then either calls handle_create or
+ * NetworkObject::handle_packet.
+ */
void on_message (NetworkPacketInput &pkt, NetworkNode *node);
protected:
+ /**
+ * Abstract method called by on_message if we recieve a message for an unknown NetworkObjectID
+ *
+ * @param obj_id the unknown NetworkObjectID
+ * @param msg_id the packet's NetworkMessageID
+ * @param pkt the packet itself, with the header read
+ * @param node the node that we got this packet from
+ */
virtual void handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacketInput &pkt, NetworkNode *node) = 0;
public:
/**
* Read an NetworkObjectID from the given packet, and return the corresponding NetworkObject, or NULL if we
- * don't know it
+ * don't know it.
*/
NetworkObject* read_object (NetworkPacketInput &pkt);
@@ -50,94 +90,251 @@
void write_object (NetworkPacketOutput &pkt, NetworkObject *obj);
};
+/**
+ * A NetworkObjectController intended for use with a server.
+ *
+ * This has an id_pool that new NetworkObjectIDs can be generated from, and this doesn't accept unknown
+ * NetworkObjectIDs from clients.
+ */
class NetworkObject_ServerController : public NetworkObjectController {
friend class NetworkObject_Server;
private:
+ /**
+ * The id_pool that we use to generate NetworkObjectIDs for new NetworkObject's
+ */
NetworkObjectID id_pool;
public:
+ /**
+ * @see NetworkObjectController
+ */
NetworkObject_ServerController (NetworkSession &session, NetworkChannelID channel_id);
protected:
+ /**
+ * Get a new NetworkObjectID
+ */
NetworkObjectID getObjectID (void);
-
+
+ /**
+ * Throw an error, as we don't accept unknown NetworkObjects from clients
+ */
virtual void handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacketInput &pkt, NetworkNode *node);
};
+/**
+ * A NetworkObjectController intended for use with a client.
+ *
+ * This provides two ways to handle unknown objects: override handle_create, or use sig_create
+ */
class NetworkObject_ClientController : public NetworkObjectController {
friend class NetworkObject_Client;
- private:
+ protected:
+ /**
+ * The server node, as returned by NetworkSession::connect
+ */
NetworkNode *server;
-
+
+ /**
+ * A mapping of NetworkMessageID -> sig_create, used by the default handle_create
+ */
std::map<NetworkMessageID, CL_Signal_v2<NetworkObject_Client*, NetworkPacketInput&> > _map_sig_create;
public:
+ /**
+ * Construct a NetworkObjectController using the given NetworkNode (as returned by NetworkSession::connect) as
+ * a server.
+ *
+ * @see NetworkObjectController
+ */
NetworkObject_ClientController (NetworkSession &session, NetworkChannelID channel_id, NetworkNode *server);
protected:
+ /**
+ * Handle unknown NetworkObjectIDs by constructing a new NetworkObject_Client and calling sig_create.
+ *
+ * This can be overriden to handle this differently, e.g. to create an instance of a NetworkObject_Client
+ * subclass instead.
+ */
virtual void handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacketInput &pkt, NetworkNode *node);
public:
+ /**
+ * Signal triggered by default handle_create when we get a message for an unknown NetworkObject.
+ * The signal gets the new NetworkObject_Client, and the packet itself.
+ *
+ * @param msg_id the NetworkMessageID to handle creates for
+ */
CL_Signal_v2<NetworkObject_Client*, NetworkPacketInput&>& sig_create (NetworkMessageID msg_id) { return _map_sig_create[msg_id]; }
};
+/**
+ * Base class of NetworkObject_(Client/Server)
+ *
+ * A NetworkObject has an NetworkObjectID, and can handle packets to/from this object
+ */
class NetworkObject {
friend class NetworkObjectController;
friend std::ostream& operator<< (std::ostream &s, const NetworkObject &obj);
protected:
+ /**
+ * This object's object id
+ */
NetworkObjectID obj_id;
protected:
+ /**
+ * Construct a NetworkObject using the given controller and object id
+ *
+ * @param controller the NetworkObjectController (subclass)
+ * @param obj_id our NetworkObjectID
+ */
NetworkObject (NetworkObjectController &controller, NetworkObjectID obj_id);
+ /**
+ * Abstract method to handle packets sent to this object
+ *
+ * @param node the NetworkNode that sent this packet to us
+ * @param msg_id the packet's NetworkMessageID
+ * @param pkt the packet itself, with the headers read
+ */
virtual void handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacketInput &pkt) = 0;
-
+
+ /**
+ * Prepare an outgoing packet, writing the header and the payload
+ *
+ * @param pkt the packet to prepare
+ * @param msg_id the packet's message id
+ * @param payload the packet's payload
+ */
void buildPacket (NetworkPacketOutput &pkt, NetworkMessageID msg_id, const NetworkPacketBuffer &payload);
};
+/**
+ * Formats the object as "<NetworkObject #" <obj_id> ">"
+ */
std::ostream& operator<< (std::ostream &s, const NetworkObject &obj);
+/**
+ * A server-side NetworkObject
+ */
class NetworkObject_Server : public NetworkObject {
friend class NetworkObject_ServerController;
- private:
+ protected:
+ /**
+ * The NetworkObject_ServerController
+ */
NetworkObject_ServerController &controller;
-
+
+ /**
+ * Mapping of NetworkMessageID -> sig_message used for received messages
+ */
std::map<NetworkMessageID, CL_Signal_v2<NetworkNode*, NetworkPacketInput&> > _map_sig_message;
public:
+ /**
+ * @see NetworkObject
+ */
NetworkObject_Server (NetworkObject_ServerController &controller);
protected:
+ /**
+ * Handle an incoming packet by invoking the appopriate sig_message
+ *
+ * @see NetworkObject::handlePacket
+ */
virtual void handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacketInput &pkt);
public:
+ /**
+ * Send a message on this object to the given node
+ *
+ * @param dst the NetworkNode to send the message to
+ * @param msg_id the type of message to send
+ * @param pkt the packet payload
+ * @param reliable Whether to use TCP or UDP
+ */
void send_to (NetworkNode *dst, NetworkMessageID msg_id, const NetworkPacketBuffer &pkt, bool reliable = true);
+
+ /**
+ * Send a message on this object to all nodes on our controller's NetworkSession
+ *
+ * @param msg_id the type of message to send
+ * @param pkt the packet payload
+ * @param reliable Whether to use TCP or UDP
+ */
void send_all (NetworkMessageID msg_id, const NetworkPacketBuffer &pkt, bool reliable = true);
+
+ /**
+ * Send a message on this object to all nodes on our controller's NetworkSession, except the given node
+ *
+ * @param msg_id the type of message to send
+ * @param pkt the packet payload
+ * @param black_sheep the node to *NOT* send the message to
+ * @param reliable Whether to use TCP or UDP
+ */
void send_all_except (NetworkMessageID msg_id, const NetworkPacketBuffer &pkt, NetworkNode *black_sheep, bool reliable = true);
-
+
+ /**
+ * Triggered whenever we receive a message of the given type on this object, giving the node that sent it and the
+ * packet itself
+ *
+ * @param msg_id the NetworkMessageID to handle
+ */
CL_Signal_v2<NetworkNode*, NetworkPacketInput&>& sig_message (NetworkMessageID msg_id) { return _map_sig_message[msg_id]; }
};
+/**
+ * A client-side NetworkObject
+ */
class NetworkObject_Client : public NetworkObject {
friend class NetworkObject_ClientController;
- private:
+ protected:
+ /**
+ * Our NetworkObject_ClientController
+ */
NetworkObject_ClientController &controller;
-
+
+ /**
+ * Our mapping of NetworkMessageID -> sig_message, used to handle received packets
+ */
std::map<NetworkMessageID, CL_Signal_v1<NetworkPacketInput&> > _map_sig_message;
protected:
+ /**
+ * @see NetworkObject
+ */
NetworkObject_Client (NetworkObject_ClientController &controller, NetworkObjectID id);
+ /**
+ * Handle an incoming packet by invoking the appropriate sig_message.
+ *
+ * This assumes that packets only come from the server
+ *
+ * @see NetworkObject::handlePacket
+ */
virtual void handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacketInput &pkt);
public:
+ /**
+ * Send a message on this object to the server
+ *
+ * @param msg_id the type of message to send
+ * @param pkt the packet payload
+ * @param reliable Whether to use TCP or UDP
+ */
void send (NetworkMessageID msg_id, const NetworkPacketBuffer &pkt, bool reliable = true);
+ /**
+ * Triggered whenever we receive a message of the given type on this object from the server.
+ *
+ * @param msg_id the NetworkMessageID to handle
+ */
CL_Signal_v1<NetworkPacketInput&>& sig_message (NetworkMessageID msg_id) { return _map_sig_message[msg_id]; }
};
--- a/src/Network/Server.cc Mon Dec 08 16:14:23 2008 +0000
+++ b/src/Network/Server.cc Mon Dec 08 16:23:30 2008 +0000
@@ -28,9 +28,6 @@
}
void NetworkServer::handle_disconnect (NetworkServerPlayer *player) {
- // remove from state
- state.removePlayer(player);
-
// remove from list
players.remove(player);
}
--- a/src/Network/Server.hh Mon Dec 08 16:14:23 2008 +0000
+++ b/src/Network/Server.hh Mon Dec 08 16:23:30 2008 +0000
@@ -12,65 +12,159 @@
// 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;
- 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 NetworkAddress &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);
};
+/**
+ * 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:
- // override from Player to replicate side effects of events to clients
+ // @{
+ /**
+ * 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);
+ // @}
+ //
+
+ 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);
- private:
- 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 the constructor to send the initial Terrain data using the NETCHAN_TERRAIN_ARRAY channel.
+ */
void send_terrain_data (void);
+
+ /**
+ * 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);
};