src/Network/Server.cc
changeset 431 c6d7272a164b
parent 428 712b943195a6
child 432 82b0f4e55a13
--- a/src/Network/Server.cc	Mon Jan 26 19:52:52 2009 +0200
+++ b/src/Network/Server.cc	Mon Jan 26 23:03:47 2009 +0200
@@ -5,6 +5,9 @@
 #include "../Engine.hh"
 #include "../Logger.hh"
 
+// XXX: move
+#include "Message.hh"
+
 #include <cassert>
 
 NetworkServer::NetworkServer (GameState &state, const NetworkEndpoint &listen_addr) : 
@@ -23,16 +26,16 @@
     Engine::log(INFO, "net.server") << "Client connected, sending terrain data: " << node->getRemoteAddress();
 
     // send the terrain data
-    send_terrain_data(node);
+    send_terrain_data(*node);
 
     // create the player object (it logs it)
-    NetworkServerPlayer *player = new NetworkServerPlayer(*this, node);
+    NetworkServerPlayer *player = new NetworkServerPlayer(*this, *node);
 
     // add to players
     players.push_back(player);
 }
  
-void NetworkServer::send_terrain_data (NetworkNode *node) {
+void NetworkServer::send_terrain_data (NetworkNode &node) {
     Terrain &terrain = state.world.terrain;
     
     // dimensions?
@@ -57,7 +60,7 @@
     );
     
     // write netsession header
-    node->write_packet_header(pkt, NETCHAN_TERRAIN_ARRAY);
+    netsession.write_packet_header(pkt, NETCHAN_TERRAIN_ARRAY);
 
     // write terrain dimensions
     pkt.write_uint32(map.x);
@@ -67,7 +70,7 @@
     pkt.write_compressed(terrain_buf, terrain_size);
 
     // send
-    node->send_raw(pkt, true);
+    node.send_raw(pkt, true);
 }
 
        
@@ -88,53 +91,64 @@
 /*
  * NetworkServerPlayer
  */
-NetworkServerPlayer::NetworkServerPlayer (NetworkServer &server, NetworkNode *node) : 
+NetworkServerPlayer::NetworkServerPlayer (NetworkServer &server, NetworkNode &node) : 
     Player(server.state, Vector(PLAYER_INITIAL_X, PLAYER_INITIAL_Y), true), NetworkServerObject(server), node(node) 
 {
     // messages
-    slots.connect(node->sig_disconnected(), this, &NetworkServerPlayer::on_disconnected);
+    slots.connect(node.sig_disconnected(), this, &NetworkServerPlayer::on_disconnected);
     slots.connect(this->sig_message(NETMSG_CLIENT_INPUT), this, &NetworkServerPlayer::on_input);
 
     // the initial NETMSG_PLAYER_HELLO
-    NetworkPacket hello_pkt;
-    hello_pkt.write_vector(getPosition());
+    NetworkMessage hello_msg(*this, NETMSG_SERVER_HELLO);
+    hello_msg.write_vector(getPosition());
+    node.send_raw(hello_msg);
 
-    this->send_to(node, NETMSG_SERVER_HELLO, hello_pkt, true);
-
-    // send other player objects
+    // sync other players
     for (std::list<NetworkServerPlayer*>::iterator it = server.players.begin(); it != server.players.end(); it++) {
-        NetworkPacket player_pkt;
+        NetworkMessage player_msg(*this, NETMSG_PLAYER_INFO);
         NetworkServerPlayer *player = *it;
         
         // player is not in players list yet
         assert(player != this);
         
         // write packet
-        player_pkt.write_vector(player->getPosition());
-
-        player->send_to(node, NETMSG_PLAYER_INFO, player_pkt, true);
+        player_msg.write_vector(player->getPosition());
+        
+        // send message to client
+        node.send_raw(player_msg);
 
         // XXX: send rope info...
     }
 
-    // XXX: send projectiles? Or let the client handle the events that the unknown projectiles generate?
+    // sync projectiles
+    for (std::list<Projectile*>::iterator it = server.state.projectiles.begin(); it != server.state.projectiles.end(); it++) {
+        NetworkServerProjectile *proj = dynamic_cast<NetworkServerProjectile*>(*it);
+        
+        // all projectiles should be under the control of the server
+        assert(proj);
+
+        // XXX: send info
+    }
 
     // broadcast NETMSG_PLAYER_JOIN to all clients except current
-    this->send_all_except(NETMSG_PLAYER_JOIN, hello_pkt, node, true);
-
-    Engine::log(INFO, "net.server") << "Player joined: " << this << " from " << node->getRemoteAddress();
-}
+    NetworkMessage join_msg(*this, NETMSG_PLAYER_JOIN);
+    join_msg.write_vector(getPosition());
+    server.netsession.all_nodes_except(node).send_raw(join_msg);
 
+    Engine::log(INFO, "net.server") << "Player joined: " << this << " from " << node.getRemoteAddress();
+}
+        
 void NetworkServerPlayer::handleDig (Vector position, float radius) {
-    NetworkPacket pkt;
-
-    pkt.write_vector(position);
-    pkt.write_float32(radius);
+    NetworkMessage msg(*this, NETMSG_PLAYER_DIG);
 
     Engine::log(DEBUG, "server_player.handle_dig") << "position=" << position << ", radius=" << radius;
+
+    // write packet
+    msg.write_vector(position);
+    msg.write_float32(radius);
     
-    // tell everyone... make this reliable... 
-    this->send_all(NETMSG_PLAYER_DIG, pkt, true);
+    // broadcast packet
+    server.netsession.all_nodes().send_raw(msg);
 
     // and carry out the actual dig on the server as well
     Player::handleDig(position, radius);
@@ -151,94 +165,100 @@
 }
 
 void NetworkServerPlayer::handleChangeWeapon (unsigned int weaponIndex) {
-    NetworkPacket pkt;
+    NetworkMessage msg(*this, NETMSG_PLAYER_WEAPON_CHANGE);
 
     Engine::log(DEBUG, "server_player.change_weapon") << "weaponIndex=" << weaponIndex;
     
     // write packet
-    pkt.write_uint8(weaponIndex);
+    msg.write_uint8(weaponIndex);
     
     // XXX: only tell the client itself?
-    send_all(NETMSG_PLAYER_WEAPON_CHANGE, pkt, true);
+    server.netsession.all_nodes().send_raw(msg);
     
     // pass through
     Player::handleChangeWeapon(weaponIndex);
 }
         
 void NetworkServerPlayer::handleRopeState (RopeState state) {
-    NetworkPacket pkt; 
-
     Engine::log(DEBUG, "server_player.rope_state") << "state=" << rope.getState() << ", position=" << rope.getPosition() << ", velocity=" << rope.getVelocity() << ", length=" << rope.getLength() << ", pivotPlayer=" << rope.getPivotPlayer();
 
     switch (state) {
-    case ROPE_FLYING:
-        pkt.write_vector(rope.getPosition());
-        pkt.write_vector(rope.getVelocity());
-        pkt.write_float32(rope.getLength());
+    case ROPE_FLYING: {
+        NetworkMessage msg(*this, NETMSG_PLAYER_ROPE_THROW);
 
-        send_all(NETMSG_PLAYER_ROPE_THROW, pkt, true);
+        msg.write_vector(rope.getPosition());
+        msg.write_vector(rope.getVelocity());
+        msg.write_float32(rope.getLength());
         
-        break;
+        server.netsession.all_nodes().send_raw(msg);
+       
+        } break;
 
     case ROPE_FIXED: {
+        NetworkMessage msg(*this, NETMSG_PLAYER_ROPE_FIXED);
+
         Player *player_base = rope.getPivotPlayer();
         NetworkServerPlayer *player = NULL;
 
         if (player_base != NULL && (player = dynamic_cast<NetworkServerPlayer*>(player_base)) == NULL)
             throw Error("NetworkServerPlayer::handleRopeState: rope's pivotPlayer is not a NetworkServerPlayer");
         
-        pkt.write_vector(rope.getPosition());
-        pkt.write_float32(rope.getLength());
-        controller.write_object(pkt, player);    // may be NULL
+        msg.write_vector(rope.getPosition());
+        msg.write_float32(rope.getLength());
+        controller.write_object(msg, player);    // may be NULL
         
-        send_all(NETMSG_PLAYER_ROPE_FIXED, pkt, true);
+        server.netsession.all_nodes().send_raw(msg);
 
-    } break;
+        } break;
     
-    case ROPE_FOLDED:
-        send_all(NETMSG_PLAYER_ROPE_RELEASED, pkt, true);
+    case ROPE_FOLDED: {
+        NetworkMessage msg(*this, NETMSG_PLAYER_ROPE_RELEASED);
 
-        break;
+        server.netsession.all_nodes().send_raw(msg);
+
+        } break;
     }
 }
         
 void NetworkServerPlayer::handleRopeLength (float length) {
-    NetworkPacket pkt;
-
-    pkt.write_float32(length);
-
-    send_all(NETMSG_PLAYER_ROPE_LENGTH, pkt, true);
+    NetworkMessage msg(*this, NETMSG_PLAYER_ROPE_LENGTH);
+    
+    // write packet
+    msg.write_float32(length);
+        
+    // send packet
+    server.netsession.all_nodes().send_raw(msg);
 }
 
 void NetworkServerPlayer::spawn (Vector position) {
-    NetworkPacket pkt;
+    NetworkMessage msg(*this, NETMSG_PLAYER_SPAWN);
     
     // write packet
-    pkt.write_vector(position);
+    msg.write_vector(position);
 
     Engine::log(DEBUG, "server_player.spawn") << this << ": position=" << position;
     
-    // send
-    send_all(NETMSG_PLAYER_SPAWN, pkt, true);
+    // send packet
+    server.netsession.all_nodes().send_raw(msg);
     
     // super
     Player::spawn(position);
 }
         
 void NetworkServerPlayer::die (bool start_timer) {
-    NetworkPacket pkt;
+    NetworkMessage msg(*this, NETMSG_PLAYER_DIE);
 
     Engine::log(DEBUG, "server_player.die") << this;
     
-    // send
-    send_all(NETMSG_PLAYER_DIE, pkt, true);
+    // send packet
+    server.netsession.all_nodes().send_raw(msg);
 
     // super
     Player::die(start_timer);
 }
 
 void NetworkServerPlayer::on_disconnected (void) {
-    NetworkPacket pkt;
+    NetworkMessage msg(*this, NETMSG_PLAYER_QUIT);
     
     Engine::log(INFO, "net.server") << "Player disconnected: " << this;
     
@@ -246,16 +266,16 @@
     server.handle_disconnect(this);
     
     // tell other clients
-    send_all(NETMSG_PLAYER_QUIT, pkt, true);
+    server.netsession.all_nodes().send_raw(msg);
 
-    // free
+    // XXX: free
 //    delete this;
 }
 
 void NetworkServerPlayer::on_input (NetworkNode *src, NetworkPacketInput &pkt) {
     // sanity-check, other players shouldn't move
-    if (src != node) {
-        Engine::log(WARN, "server_player.on_input") << "packet from wrong src=" << src << ", node=" << node;
+    if (src != &node) {
+        Engine::log(WARN, "server_player.on_input") << "packet from wrong src=" << src << ", node=" << &node;
         return;
     }
     
@@ -273,20 +293,20 @@
 }
         
 void NetworkServerPlayer::send_position_update (void) {
-    NetworkPacket pkt;
+    NetworkMessage msg(*this, NETMSG_PLAYER_POSITION);
     
     int flags = 
         (inAir ? NETWORK_PHYSICS_INAIR : 0) | 
         (facing == FACING_RIGHT ? NETWORK_PHYSICS_FACE_RIGHT : 0);
 
-    pkt.write_vector(getPosition());
-    pkt.write_vector(getVelocity());
-    pkt.write_uint8(flags);
-    pkt.write_float32(aim);
+    msg.write_vector(getPosition());
+    msg.write_vector(getVelocity());
+    msg.write_uint8(flags);
+    msg.write_float32(aim);
 
 //    Engine::log(INFO, "server_player.send_position_update") << "obj=" << obj << " -> " << position << "+" << velocity << " [" << flags << "]";
 
-    send_all(NETMSG_PLAYER_POSITION, pkt, false);
+    server.netsession.all_nodes().send_raw(msg);
 }
 
 /* 
@@ -296,25 +316,29 @@
         Vector velocity, Weapon *weapon) :
     Projectile(player, position, velocity, weapon, true), NetworkServerObject(server)
 {
-    NetworkPacket pkt;
+    NetworkMessage msg(*this, NETMSG_PROJECTILE_PLAYER_FIRED);
+
+    // write out packet
+    server.controller.write_object(msg, player);
+    msg.write_vector(getPosition());
+    msg.write_vector(getVelocity());
+    msg.write_uint8(weapon->getID());
     
-    server.controller.write_object(pkt, player);
-    pkt.write_vector(position);
-    pkt.write_vector(velocity);
-    pkt.write_uint8(weapon->getID());
-
-    send_all(NETMSG_PROJECTILE_PLAYER_FIRED, pkt, true);
+    // send to given target
+    server.netsession.all_nodes().send_raw(msg);
 }
 
 void NetworkServerProjectile::onDestroy (Vector position, bool removeGround) {
-    NetworkPacket pkt;
+    NetworkMessage msg(*this, NETMSG_PROJECTILE_DESTROY);
 
     Engine::log(DEBUG, "server_projectile.destroy") << this << "position=" << position << ", removeGround=" << removeGround;
     
-    pkt.write_vector(position);
-    pkt.write_uint8(removeGround ? NETWORK_PROJECTILE_REMOVE_GROUND : 0);
-
-    send_all(NETMSG_PROJECTILE_DESTROY, pkt, true);
+    // write packet
+    msg.write_vector(position);
+    msg.write_uint8(removeGround ? NETWORK_PROJECTILE_REMOVE_GROUND : 0);
+    
+    // broadcast packet
+    server.netsession.all_nodes().send_raw(msg);
 
     // XXX: leak obj, not yet implemented:  obj.destory();
     
@@ -323,7 +347,7 @@
 }
 
 void NetworkServerProjectile::onHitPlayer (Player *player_ptr) {
-    NetworkPacket pkt;
+    NetworkMessage msg(*this, NETMSG_PROJECTILE_HIT_PLAYER);
     NetworkServerPlayer *player = dynamic_cast<NetworkServerPlayer*>(player_ptr);
 
     if (player == NULL) 
@@ -332,10 +356,10 @@
     Engine::log(DEBUG, "server_projectile.hit_player") << this << ": player=" << player;
     
     // write packet
-    controller.write_object(pkt, player);
+    controller.write_object(msg, player);
 
-    // send
-    send_all(NETMSG_PROJECTILE_HIT_PLAYER, pkt, true);
+    // send packet
+    server.netsession.all_nodes().send_raw(msg);
 
     // super
     Projectile::onHitPlayer(player_ptr);