implement the ROT (Rope Over TCP) protocol
authorterom
Sun, 07 Dec 2008 01:18:59 +0000
changeset 241 e95b1602d836
parent 240 e8ca212a2739
child 242 fb517ed0ecee
implement the ROT (Rope Over TCP) protocol
src/Network/Client.cc
src/Network/Client.hh
src/Network/Protocol.hh
src/Network/Server.cc
src/Network/Server.hh
src/PhysicsObject.cc
src/Player.cc
src/Player.hh
src/Rope.cc
src/Rope.hh
--- a/src/Network/Client.cc	Sun Dec 07 00:46:04 2008 +0000
+++ b/src/Network/Client.cc	Sun Dec 07 01:18:59 2008 +0000
@@ -119,10 +119,14 @@
 NetworkClientPlayerHelper::NetworkClientPlayerHelper (NetworkClient &client, Vector position, NetworkObject_Client *obj) :
     NetworkClientObjectHelper(client, obj), Player(client.state, position, true) 
 {
-    // receive position updates
-    slots.connect(obj->sig_message(NETMSG_PLAYER_POSITION), this, &NetworkClientPlayerHelper::on_position);
-    slots.connect(obj->sig_message(NETMSG_PLAYER_DIG), this, &NetworkClientPlayerHelper::on_dig);
-    slots.connect(obj->sig_message(NETMSG_PLAYER_WEAPON_CHANGE), this, &NetworkClientPlayerHelper::on_weapon_change);
+    slots.connect(obj->sig_message(NETMSG_PLAYER_POSITION),         this,   &NetworkClientPlayerHelper::on_position         );
+    slots.connect(obj->sig_message(NETMSG_PLAYER_DIG),              this,   &NetworkClientPlayerHelper::on_dig              );
+    slots.connect(obj->sig_message(NETMSG_PLAYER_WEAPON_CHANGE),    this,   &NetworkClientPlayerHelper::on_weapon_change    );
+    slots.connect(obj->sig_message(NETMSG_PLAYER_ROPE_THROW),       this,   &NetworkClientPlayerHelper::on_rope_throw       );
+    slots.connect(obj->sig_message(NETMSG_PLAYER_ROPE_FIXED),       this,   &NetworkClientPlayerHelper::on_rope_fixed       );
+    slots.connect(obj->sig_message(NETMSG_PLAYER_ROPE_RELEASED),    this,   &NetworkClientPlayerHelper::on_rope_released    );
+    slots.connect(obj->sig_message(NETMSG_PLAYER_ROPE_LENGTH),      this,   &NetworkClientPlayerHelper::on_rope_length      );
+
 }
 
 void NetworkClientPlayerHelper::on_position (NetworkPacketInput &pkt) {
@@ -155,6 +159,40 @@
     handleChangeWeapon(weapon_index);
 }
 
+void NetworkClientPlayerHelper::on_rope_throw (NetworkPacketInput &pkt) {
+    Vector position = pkt.read_vector();
+    Vector velocity = pkt.read_vector();
+    float length = pkt.read_float32();
+
+    Engine::log(INFO, "client_player.on_rope_throw") << "obj=" << obj << ", position=" << position << ", velocity=" << velocity << ", length=" << length;
+
+    rope.updateState(ROPE_FLYING, position, velocity, length);
+}
+
+void NetworkClientPlayerHelper::on_rope_fixed (NetworkPacketInput &pkt) {
+    Vector position = pkt.read_vector();
+    float length = pkt.read_float32();
+    
+    Engine::log(INFO, "client_player.on_rope_fixed") << "obj=" << obj << ", position=" << position << ", length=" << length;
+
+    rope.updateState(ROPE_FIXED, position, Vector(0, 0), length);
+}
+
+void NetworkClientPlayerHelper::on_rope_released (NetworkPacketInput &pkt) {
+    Engine::log(INFO, "client_player.on_rope_released") << "obj=" << obj;
+    
+    // use rope.getPosition() instead of e.g. Vector(0, 0) because it will collide there...
+    rope.updateState(ROPE_FOLDED, rope.getPosition(), Vector(0, 0), 0);
+}
+
+void NetworkClientPlayerHelper::on_rope_length (NetworkPacketInput &pkt) {
+    float length = pkt.read_float32();
+    
+    Engine::log(INFO, "client_player.on_rope_length") << "obj=" << obj << ", length=" << length;
+
+    rope.updateLength(length);
+}
+
 NetworkClientLocalPlayer::NetworkClientLocalPlayer (NetworkClient &client, NetworkObject_Client *obj, Vector position) :
     Player(client.state, position, true), NetworkClientPlayerHelper(client, position, obj) {
     
--- a/src/Network/Client.hh	Sun Dec 07 00:46:04 2008 +0000
+++ b/src/Network/Client.hh	Sun Dec 07 01:18:59 2008 +0000
@@ -60,6 +60,10 @@
         void on_position (NetworkPacketInput &pkt);
         void on_dig (NetworkPacketInput &pkt);
         void on_weapon_change (NetworkPacketInput &pkt);
+        void on_rope_throw (NetworkPacketInput &pkt);
+        void on_rope_fixed (NetworkPacketInput &pkt);
+        void on_rope_released (NetworkPacketInput &pkt);
+        void on_rope_length (NetworkPacketInput &pkt);
 };
 
 class NetworkClientLocalPlayer : public NetworkClientPlayerHelper, public LocalPlayer {
--- a/src/Network/Protocol.hh	Sun Dec 07 00:46:04 2008 +0000
+++ b/src/Network/Protocol.hh	Sun Dec 07 01:18:59 2008 +0000
@@ -83,14 +83,44 @@
      * Vector   position 
      * float32  radius          
      */
-    NETMSG_PLAYER_DIG           = 0x0302,
+    NETMSG_PLAYER_DIG           = 0x0312,
 
     /*
      * Player changed weapon
      *
      * uint8_t  weapon_index
      */
-    NETMSG_PLAYER_WEAPON_CHANGE = 0x0303,
+    NETMSG_PLAYER_WEAPON_CHANGE = 0x0321,
+    
+    /*
+     * Player threw the rope
+     *
+     * Vector   position
+     * Vector   velocity
+     * float    length
+     */
+    NETMSG_PLAYER_ROPE_THROW    = 0x0331,
+
+    /*
+     * Player rope fixed on to something
+     *
+     * Vector   position
+     * float    length
+     */
+    NETMSG_PLAYER_ROPE_FIXED    = 0x0332,
+
+    /*
+     * Player rope released
+     *
+     */
+    NETMSG_PLAYER_ROPE_RELEASED = 0x0333,
+    
+    /*
+     * Rope length changed
+     *
+     * float length
+     */
+    NETMSG_PLAYER_ROPE_LENGTH   = 0x0334,
 
     /*
      * New projectile spawned
--- a/src/Network/Server.cc	Sun Dec 07 00:46:04 2008 +0000
+++ b/src/Network/Server.cc	Sun Dec 07 01:18:59 2008 +0000
@@ -110,6 +110,44 @@
     // pass through
     Player::handleChangeWeapon(weaponIndex);
 }
+        
+void NetworkServerPlayer::handleRopeState (RopeState state) {
+    NetworkPacket pkt; 
+
+    Engine::log(INFO, "server_player.rope_state") << "state=" << rope.getState() << ", position=" << rope.getPosition() << ", velocity=" << rope.getVelocity() << ", length=" << rope.getLength();
+
+    switch (state) {
+    case ROPE_FLYING:
+        pkt.write_vector(rope.getPosition());
+        pkt.write_vector(rope.getVelocity());
+        pkt.write_float32(rope.getLength());
+
+        obj.send_all(NETMSG_PLAYER_ROPE_THROW, pkt, true);
+        
+        break;
+
+    case ROPE_FIXED:
+        pkt.write_vector(rope.getPosition());
+        pkt.write_float32(rope.getLength());
+        
+        obj.send_all(NETMSG_PLAYER_ROPE_FIXED, pkt, true);
+
+        break;
+    
+    case ROPE_FOLDED:
+        obj.send_all(NETMSG_PLAYER_ROPE_RELEASED, pkt, true);
+
+        break;
+    }
+}
+        
+void NetworkServerPlayer::handleRopeLength (float length) {
+    NetworkPacket pkt;
+
+    pkt.write_float32(length);
+
+    obj.send_all(NETMSG_PLAYER_ROPE_LENGTH, pkt, true);
+}
 
 void NetworkServerPlayer::on_disconnected (void) {
     NetworkPacket pkt;
--- a/src/Network/Server.hh	Sun Dec 07 00:46:04 2008 +0000
+++ b/src/Network/Server.hh	Sun Dec 07 01:18:59 2008 +0000
@@ -50,6 +50,8 @@
         virtual void handleDig (Vector position, float radius);
         virtual void handleCreateProjectile (Weapon *weapon, Vector position, Vector velocity);
         virtual void handleChangeWeapon (unsigned int weaponIndex);
+        virtual void handleRopeState (RopeState state);
+        virtual void handleRopeLength (float length);
 
     private:
         void on_disconnected (void);
--- a/src/PhysicsObject.cc	Sun Dec 07 00:46:04 2008 +0000
+++ b/src/PhysicsObject.cc	Sun Dec 07 01:18:59 2008 +0000
@@ -348,15 +348,24 @@
 }
     
 void PhysicsObject::enable (void) {
+    // only enable once until disabled
+    if (alive)
+        return;
+    
+    // mark as alive
     alive = true;
+    
+    // add the world objects list
     world.addPhysicsObject(this);
 }
 
 void PhysicsObject::disable (void) {
+    // mark as disabled
     alive = false;
 }
 
 void PhysicsObject::destroy (void) {
+    // mark as disabled and for deletion
     alive = false;
     shouldDelete = true;
 }
--- a/src/Player.cc	Sun Dec 07 00:46:04 2008 +0000
+++ b/src/Player.cc	Sun Dec 07 01:18:59 2008 +0000
@@ -71,6 +71,14 @@
     if (getCurrentWeapon())
         getCurrentWeapon()->tickReload(dt);
 }
+        
+void Player::handleRopeState (RopeState state) {
+    
+}
+
+void Player::handleRopeLength (float length) {
+
+}
 
 void LocalPlayer::fireWeapon (Weapon *weapon) {
     // update reload timer
@@ -144,17 +152,17 @@
     if ((input & INPUT_SHOOT) && getCurrentWeapon()->canShoot())
         fireWeapon(getCurrentWeapon());
     
-    // rope throw+release+changeLength
+    // rope throw+release+changeLength, but supress spurious events
     if (input & INPUT_ROPE)
         rope.throwRope();
 
-    if (input & INPUT_UNROPE)
+    if (input & INPUT_UNROPE && rope.getState() != ROPE_FOLDED)
         rope.release();
 
-    if (input & INPUT_ROPE_UP)
+    if (input & INPUT_ROPE_UP && rope.getState() == ROPE_FIXED)
         rope.changeLength(-ROPE_GROWTH_RATE);
 
-    if (input & INPUT_ROPE_DOWN)
+    if (input & INPUT_ROPE_DOWN && rope.getState() == ROPE_FIXED)
         rope.changeLength(ROPE_GROWTH_RATE);
 
     // XXX: how should this be written? What does this do? Probably broken under network play
--- a/src/Player.hh	Sun Dec 07 00:46:04 2008 +0000
+++ b/src/Player.hh	Sun Dec 07 01:18:59 2008 +0000
@@ -39,10 +39,16 @@
         Player (void);
         Player (GameState &state, Vector position, bool visible); 
 
-        // used by the network code to execute actions for players
+        /*
+         *  Used by the network code to execute various actions
+         */
         virtual void handleDig (Vector position, float radius);
         virtual void handleCreateProjectile (Weapon *weapon, Vector position, Vector velocity);
         virtual void handleChangeWeapon (unsigned int weaponIndex);
+
+        // Called by rope to handle state changes, these don't do anything by default
+        virtual void handleRopeState (RopeState state);
+        virtual void handleRopeLength (float length);
         
         /*
          * The currently selected weapon
--- a/src/Rope.cc	Sun Dec 07 00:46:04 2008 +0000
+++ b/src/Rope.cc	Sun Dec 07 01:18:59 2008 +0000
@@ -31,6 +31,9 @@
     
     // enable the physics object
     enable();
+
+    // inform network
+    player.handleRopeState(state);
 }
 
 void Rope::onCollision() {
@@ -42,6 +45,9 @@
 
     // set player's pivot
     player.setPivot(this);
+    
+    // inform network
+    player.handleRopeState(state);
 }
 
 void Rope::release (void) {
@@ -54,18 +60,58 @@
     
     // player doesn't have a pivot anymore
     player.setPivot(NULL);
+    
+    // inform network
+    player.handleRopeState(state);
 }
 
 void Rope::changeLength (float delta) {
+    // change length
     length += delta;
-
+    
+    // minimum length
     if (length < 0)
         length = 0;
+
+    // inform network
+    player.handleRopeLength(length);
 }
 
 RopeState Rope::getState (void) {
     return state;
 }
+        
+float Rope::getLength (void) {
+    return length;
+}
+
+void Rope::updateState (RopeState new_state, Vector position, Vector velocity, float new_length) {
+    // update physics enabled/disabled state
+    if (new_state == ROPE_FOLDED || new_state == ROPE_FIXED)
+        disable();
+
+    else // new_state == ROPE_FLYING
+        enable();
+    
+    // update player.pivot
+    if (new_state == ROPE_FIXED)
+        player.setPivot(this);
+
+    else if (this->state == ROPE_FIXED)
+        player.setPivot(NULL);
+
+    // update position stuff
+    updatePhysics(position, velocity, true, false, 0);
+
+    // update vars
+    this->state = new_state;
+    this->length = new_length;
+}
+
+void Rope::updateLength (float length) {
+    // update length
+    this->length = length;
+}
 
 float Rope::getPivotForce (PhysicsObject *bob) {
     if ((position - player.getPosition()).length() >= length)
--- a/src/Rope.hh	Sun Dec 07 00:46:04 2008 +0000
+++ b/src/Rope.hh	Sun Dec 07 01:18:59 2008 +0000
@@ -59,6 +59,17 @@
          * Current state
          */
         RopeState getState (void);
+
+        /*
+         * Current length
+         */
+        float getLength (void);
+
+        /*
+         * For use by NetworkClient
+         */
+        void updateState (RopeState state, Vector position, Vector velocity, float length);
+        void updateLength (float length);
         
         /*
          * Just draws it