basic network-projectiles
authorterom
Sat, 06 Dec 2008 18:49:51 +0000
changeset 223 2fcaf54ed37b
parent 222 293ddf4c067d
child 224 e6faefba2ec1
basic network-projectiles
src/Network/Client.cc
src/Network/Client.hh
src/Network/Object.cc
src/Network/Object.hh
src/Network/Protocol.hh
src/Network/Server.cc
src/Network/Server.hh
src/PhysicsObject.cc
src/Player.cc
src/Player.hh
src/Projectile.hh
src/Terrain.cc
src/Weapon.cc
src/Weapon.hh
--- a/src/Network/Client.cc	Sat Dec 06 17:51:19 2008 +0000
+++ b/src/Network/Client.cc	Sat Dec 06 18:49:51 2008 +0000
@@ -11,33 +11,15 @@
     state(state), netsession(NETWORK_MAGIC_ID), server(netsession.connect(connect_to)), netobjs(netsession, NETCHAN_CORE, server) {
     
     // connect slots
-    slots.connect(netobjs.sig_create(), this, &NetworkClient::on_create);
+    slots.connect(netobjs.sig_create(NETMSG_SERVER_HELLO), this, &NetworkClient::on_server_hello);
+    slots.connect(netobjs.sig_create(NETMSG_PLAYER_INFO), this, &NetworkClient::on_player_info);
+    slots.connect(netobjs.sig_create(NETMSG_PLAYER_JOIN), this, &NetworkClient::on_player_join);
+    slots.connect(netobjs.sig_create(NETMSG_PROJECTILE_CREATE), this, &NetworkClient::on_projectile_create);
+
     slots.connect(netsession.sig_chan_message(NETCHAN_TERRAIN_ARRAY), this, &NetworkClient::on_terrain_array);
 
     // XXX: sig_disconnected
 }
-
-void NetworkClient::on_create (NetworkObject_Client *obj, NetworkMessageID msg_id, NetworkPacketInput &pkt) {
-    switch (msg_id) {
-        case NETMSG_SERVER_HELLO:
-            on_server_hello(obj, pkt);
-
-            break;
-        
-        case NETMSG_PLAYER_INFO:
-            on_player_info(obj, pkt);
-
-            break;
-        
-        case NETMSG_PLAYER_JOIN:
-            on_player_join(obj, pkt);
-
-            break;
-
-        default:
-            Engine::log(WARN, "client.on_create_object") << "unknown msg_id=" << msg_id << " for obj=" << obj;
-    }
-}
         
 void NetworkClient::on_server_hello (NetworkObject_Client *obj, NetworkPacketInput &pkt) {
     // read the packet
@@ -79,6 +61,18 @@
     state.newPlayer(player);
 }
         
+void NetworkClient::on_projectile_create (NetworkObject_Client *obj, NetworkPacketInput &pkt) {
+    // read the packet
+    Vector position = pkt.read_vector();
+    Vector velocity = pkt.read_vector();
+    float explosionRadius = pkt.read_float32();
+
+    Engine::log(INFO, "client.on_projectile_create") << "obj=" << obj << ", pos=" << position << ", velocity=" << velocity;
+
+    // create the NetworkClientPorjectile object
+    new NetworkClientProjectile(*this, obj, position, velocity, explosionRadius);
+}
+        
 void NetworkClient::on_terrain_array (NetworkPacketInput &pkt, NetworkNode *node) {
     // ignore if not from server
     if (node != server)
@@ -110,9 +104,21 @@
     //  delete player;
 }
 
+/*
+ * NetworkClientObjectHelper
+ */
+NetworkClientObjectHelper::NetworkClientObjectHelper (NetworkClient &client, NetworkObject_Client *obj) :
+    client(client), obj(obj)
+{
+
+}
+
+/*
+ * NetworkClientPlayerHelper
+ */
 NetworkClientPlayerHelper::NetworkClientPlayerHelper (NetworkClient &client, Vector position, NetworkObject_Client *obj) :
-    Player(client.state, position, true), client(client), obj(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);
@@ -150,7 +156,7 @@
     NetworkPacket pkt;
     pkt.write_uint16(input);
 
-    obj->send(NETMSG_CLIENT_MOVE, pkt, false);
+    obj->send(NETMSG_CLIENT_INPUT, pkt, false);
     
     // do not handle locally
 }
@@ -171,4 +177,10 @@
     client.player_quit(this);
 }
 
+NetworkClientProjectile::NetworkClientProjectile (NetworkClient &client, NetworkObject_Client *obj, Vector position,
+        Vector velocity, float explosionRadius) :
+    NetworkClientObjectHelper(client, obj), Projectile(client.state, position, velocity, true, explosionRadius)
+{
+    // XXX: register messages
+}
 
--- a/src/Network/Client.hh	Sat Dec 06 17:51:19 2008 +0000
+++ b/src/Network/Client.hh	Sat Dec 06 18:49:51 2008 +0000
@@ -13,6 +13,7 @@
     friend class NetworkClientPlayerHelper;
     friend class NetworkClientLocalPlayer;
     friend class NetworkClientRemotePlayer;
+    friend class NetworkClientProjectile;
 
     protected:
         GameState &state;
@@ -32,6 +33,7 @@
         void on_server_hello (NetworkObject_Client *obj, NetworkPacketInput &pkt);
         void on_player_info (NetworkObject_Client *obj, NetworkPacketInput &pkt);
         void on_player_join (NetworkObject_Client *obj, NetworkPacketInput &pkt);
+        void on_projectile_create (NetworkObject_Client *obj, NetworkPacketInput &pkt);
 
         void on_terrain_array (NetworkPacketInput &pkt, NetworkNode *node);
     
@@ -39,7 +41,7 @@
         void player_quit (NetworkClientRemotePlayer *player);
 };
 
-class NetworkClientPlayerHelper : public virtual Player {
+class NetworkClientObjectHelper {
     protected:
         NetworkClient &client;
 
@@ -47,6 +49,10 @@
 
         NetworkObject_Client *obj;
 
+        NetworkClientObjectHelper (NetworkClient &client, NetworkObject_Client *obj);
+};
+
+class NetworkClientPlayerHelper : public NetworkClientObjectHelper, public virtual Player {
     protected:
         NetworkClientPlayerHelper (NetworkClient &client, Vector position, NetworkObject_Client *obj);
     
@@ -71,4 +77,10 @@
     
 };
 
+class NetworkClientProjectile : public NetworkClientObjectHelper, public Projectile {
+    public:
+        NetworkClientProjectile (NetworkClient &client, NetworkObject_Client *obj, Vector position, Vector velocity,
+                float explosionRadius);
+};
+
 #endif
--- a/src/Network/Object.cc	Sat Dec 06 17:51:19 2008 +0000
+++ b/src/Network/Object.cc	Sat Dec 06 18:49:51 2008 +0000
@@ -67,7 +67,8 @@
     NetworkObject_Client *obj = new NetworkObject_Client(*this, obj_id);
     
     // signal
-   _sig_create(obj, msg_id, pkt); 
+    // XXX: this leaks if it's not handled
+   _map_sig_create[msg_id](obj, pkt); 
 }
 
 /* 
--- a/src/Network/Object.hh	Sat Dec 06 17:51:19 2008 +0000
+++ b/src/Network/Object.hh	Sat Dec 06 18:49:51 2008 +0000
@@ -59,7 +59,7 @@
     private:
         NetworkNode *server;
 
-        CL_Signal_v3<NetworkObject_Client*, NetworkMessageID, NetworkPacketInput&> _sig_create;
+        std::map<NetworkMessageID, CL_Signal_v2<NetworkObject_Client*, NetworkPacketInput&> > _map_sig_create;
     
     public:
         NetworkObject_ClientController (NetworkSession &session, NetworkChannelID channel_id, NetworkNode *server);
@@ -68,7 +68,7 @@
         virtual void handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacketInput &pkt, NetworkNode *node);
     
     public:  
-        CL_Signal_v3<NetworkObject_Client*, NetworkMessageID, NetworkPacketInput&>& sig_create (void) { return _sig_create; }
+        CL_Signal_v2<NetworkObject_Client*, NetworkPacketInput&>& sig_create (NetworkMessageID msg_id) { return _map_sig_create[msg_id]; }
 };
 
 class NetworkObject {
--- a/src/Network/Protocol.hh	Sat Dec 06 17:51:19 2008 +0000
+++ b/src/Network/Protocol.hh	Sat Dec 06 18:49:51 2008 +0000
@@ -27,41 +27,41 @@
 };
 
 enum NetworkMessage {
-    NETMSG_PACKET_INVALID   = 0x0000,
+    NETMSG_PACKET_INVALID       = 0x0000,
 
     /*
      * You have joined the game:
      *
      *  Vector      initial_position
      */
-    NETMSG_SERVER_HELLO     = 0x0100,
+    NETMSG_SERVER_HELLO         = 0x0100,
 
     /*
      * New client has connected to server:
      *  
      *  Vector      initial_position
      */
-    NETMSG_PLAYER_JOIN      = 0x0101,
+    NETMSG_PLAYER_JOIN          = 0x0101,
 
     /*
      * Client has left server:
      *
      */
-    NETMSG_PLAYER_QUIT      = 0x0102,
+    NETMSG_PLAYER_QUIT          = 0x0102,
 
     /*
-     * Client has moved
+     * Client has input to process
      *
-     *  uint16_t    PlayerInput_Move
+     *  uint16_t    PlayerInput
      */
-    NETMSG_CLIENT_MOVE      = 0x0201,
+    NETMSG_CLIENT_INPUT         = 0x0201,
     
     /*
      * Initial player info
      *
      *  Vector      initial_position
      */
-    NETMSG_PLAYER_INFO      = 0x0300,
+    NETMSG_PLAYER_INFO          = 0x0300,
 
     /*
      * Player position update
@@ -71,7 +71,7 @@
      * uint8_t  NetworkPhysicsFlags
      * float32  aim
      */
-    NETMSG_PLAYER_POSITION  = 0x0301,
+    NETMSG_PLAYER_POSITION      = 0x0301,
 
     /*
      * Terrain update, removeGround
@@ -79,7 +79,16 @@
      * Vector   position 
      * float32  radius          
      */
-    NETMSG_PLAYER_DIG       = 0x0302,
+    NETMSG_PLAYER_DIG           = 0x0302,
+
+    /*
+     * New projectile spawned
+     *
+     * Vector   position
+     * Vector   velocity
+     * float    explosionRadius
+     */
+    NETMSG_PROJECTILE_CREATE    = 0x0401,
 };
 
 #endif
--- a/src/Network/Server.cc	Sat Dec 06 17:51:19 2008 +0000
+++ b/src/Network/Server.cc	Sat Dec 06 18:49:51 2008 +0000
@@ -46,7 +46,7 @@
 
     // messages
     slots.connect(node->sig_disconnected(), this, &NetworkServerPlayer::on_disconnected);
-    slots.connect(obj.sig_message(NETMSG_CLIENT_MOVE), this, &NetworkServerPlayer::on_move);
+    slots.connect(obj.sig_message(NETMSG_CLIENT_INPUT), this, &NetworkServerPlayer::on_input);
 
     // the initial NETMSG_PLAYER_HELLO
     NetworkPacket hello_pkt;
@@ -89,6 +89,13 @@
     Player::handleDig(position, radius);
 }
 
+void NetworkServerPlayer::handleCreateProjectile (Weapon &weapon, Vector position, Vector velocity) {
+    Engine::log(INFO, "server_player.create_projectile") << /* "weapon=" << weapon << ", */ "position=" << position << ", velocity=" << velocity;
+
+    // create new NetworkServerProjectile object
+    new NetworkServerProjectile(server, position, velocity, weapon.getExplosionRadius(), weapon.getExpireTicks());
+}
+
 void NetworkServerPlayer::on_disconnected (void) {
     NetworkPacket pkt;
     
@@ -104,16 +111,16 @@
 //    delete this;
 }
 
-void NetworkServerPlayer::on_move (NetworkNode *src, NetworkPacketInput &pkt) {
+void NetworkServerPlayer::on_input (NetworkNode *src, NetworkPacketInput &pkt) {
     // sanity-check, other players shouldn't move
     if (src != node) {
-        Engine::log(WARN, "server_player.on_move") << "packet from wrong src=" << src << ", node=" << node;
+        Engine::log(WARN, "server_player.on_input") << "packet from wrong src=" << src << ", node=" << node;
         return;
     }
     
     PlayerInput input = pkt.read_uint16();
 
-    Engine::log(INFO, "server_player.on_move") << "player=" << obj << ", old_pos=" << position << ", input=" << input;
+    Engine::log(INFO, "server_player.on_input") << "player=" << obj << ", old_pos=" << position << ", input=" << input;
     
     // apply input
     handleInput(input);  
@@ -164,3 +171,19 @@
     obj.send_all(NETMSG_PLAYER_POSITION, pkt, false);
 }
 
+/* 
+ * NetworkServerProjectile
+ */
+NetworkServerProjectile::NetworkServerProjectile (NetworkServer &server, Vector position, Vector velocity, 
+        float explosionRadius, TickCount age) :
+    Projectile(server.state, position, velocity, true, explosionRadius, age), server(server), obj(server.netobjs)
+{
+    NetworkPacket pkt;
+
+    pkt.write_vector(position);
+    pkt.write_vector(velocity);
+    pkt.write_float32(explosionRadius);
+
+    obj.send_all(NETMSG_PROJECTILE_CREATE, pkt, true);
+}
+
--- a/src/Network/Server.hh	Sat Dec 06 17:51:19 2008 +0000
+++ b/src/Network/Server.hh	Sat Dec 06 18:49:51 2008 +0000
@@ -14,6 +14,7 @@
 
 class NetworkServer {
     friend class NetworkServerPlayer;
+    friend class NetworkServerProjectile;
 
     protected:
         GameState &state;
@@ -43,15 +44,26 @@
         
     public:
         NetworkServerPlayer (NetworkServer &server, NetworkNode *node);
-
+        
+        // override from Player to replicate side effects of events to clients
         virtual void handleDig (Vector position, float radius);
+        virtual void handleCreateProjectile (Weapon &weapon, Vector position, Vector velocity);
 
     private:
         void on_disconnected (void);
-        void on_move (NetworkNode *node, NetworkPacketInput &pkt);
+        void on_input (NetworkNode *node, NetworkPacketInput &pkt);
         
         void send_terrain_data (void);
         void send_position_update (void);
 };
 
+class NetworkServerProjectile : public Projectile {
+    private:
+        NetworkServer &server;
+        NetworkObject_Server obj;
+    
+    public:
+        NetworkServerProjectile (NetworkServer &server, Vector position, Vector velocity, float explosionRadius, TickCount age);
+};
+
 #endif
--- a/src/PhysicsObject.cc	Sat Dec 06 17:51:19 2008 +0000
+++ b/src/PhysicsObject.cc	Sat Dec 06 18:49:51 2008 +0000
@@ -11,11 +11,7 @@
 }
 
 PhysicsObject::~PhysicsObject (void) {
-    Engine::log(DEBUG, "PhysicsObject.destructor") << this /* << ": objects.size=" << ((int) world.objects.size()) */;
-
-    // world.objects.remove(this);
-
-    Engine::log(DEBUG, "PhysicsObject.destructor") << this /* << ": objects.size=" << ((int) world.objects.size()) */;
+    // Engine::log(DEBUG, "PhysicsObject.destructor") << this /* << ": objects.size=" << ((int) world.objects.size()) */;
 }
 
 /**
@@ -146,10 +142,8 @@
     // If the worm is not in the air make it walk,
     // otherwise integrate the new position and velocity
     if (!this->inAir) {
-        //std::cout << "Tryin to walk" << std::endl;
         // It walks only if there's some vertical force
         if (total.x != 0) {
-            std::cout << "Succeeding to walk" << std::endl;
             walk(dt, total.x > 0);
             this->velocity = Vector(0,0);
         }
--- a/src/Player.cc	Sat Dec 06 17:51:19 2008 +0000
+++ b/src/Player.cc	Sat Dec 06 18:49:51 2008 +0000
@@ -51,20 +51,8 @@
 
 }
 
-void Player::handleShoot (Weapon &weapon) {
-    Vector unitVectorAim = (facingRight ? 
-        Vector(std::cos(aim), -std::sin(aim)) : 
-        Vector(-std::cos(aim), -std::sin(aim))
-    );
-    
-    // XXX: what does the PHYSICS_TICK_MS stuff mean?
-    float shotspeed = weapon.getVelocity() * PHYSICS_TICK_MS / 2;
-
-    Vector shotRelativeVelocity = unitVectorAim * shotspeed;
-    Vector shotVelocity = this->velocity + shotRelativeVelocity;
-    Vector shotPosition = this->position + unitVectorAim * 10;
-    
-    weapon.shoot(shotPosition, shotVelocity);
+void Player::handleCreateProjectile (Weapon &weapon, Vector position, Vector velocity) {
+    new Projectile(state, position, velocity, true, weapon.getExplosionRadius());
 }
 
 void Player::printDebugInfo (void) {
@@ -79,6 +67,27 @@
     getWeapon().tickReload(dt);
 }
 
+void LocalPlayer::fireWeapon (Weapon &weapon) {
+    // update reload timer
+    weapon.reload();
+    
+    // calculate unit vector
+    Vector unitVectorAim = (facingRight ? 
+        Vector(std::cos(aim), -std::sin(aim)) : 
+        Vector(-std::cos(aim), -std::sin(aim))
+    );
+    
+    // XXX: what does the PHYSICS_TICK_MS stuff mean?
+    float shotspeed = weapon.getVelocity() * PHYSICS_TICK_MS / 2;
+
+    Vector shotRelativeVelocity = unitVectorAim * shotspeed;
+    Vector shotVelocity = this->velocity + shotRelativeVelocity;
+    Vector shotPosition = this->position + unitVectorAim * 10;
+
+    // execute
+    handleCreateProjectile(weapon, shotPosition, shotVelocity);
+}
+
 void LocalPlayer::handleInput (PlayerInput input) {
     // Movement force, vertical is always zero
     Vector move_force = Vector(0, 0); 
@@ -142,9 +151,8 @@
     }
     
     // validate shoot events, and then outsource to handleShoot so Network can intercept it
-    if (input & INPUT_SHOOT && getWeapon().canShoot()) {
-        this->handleShoot(getWeapon());
-    }
+    if (input & INPUT_SHOOT && getWeapon().canShoot())
+        fireWeapon(getWeapon());
     
     // XXX: how should this be written?
     if (move_force.x != 0) 
--- a/src/Player.hh	Sat Dec 06 17:51:19 2008 +0000
+++ b/src/Player.hh	Sat Dec 06 18:49:51 2008 +0000
@@ -31,10 +31,10 @@
         
         // used by the network code to execute actions for players
         virtual void handleDig (Vector position, float radius);
-        virtual void handleShoot (Weapon &weapon);
+        virtual void handleCreateProjectile (Weapon &weapon, Vector position, Vector velocity);
         
         /*
-         *
+         * The currently selected weapon
          */
         Weapon& getWeapon();
 
@@ -58,6 +58,9 @@
 };
 
 class LocalPlayer : public virtual Player {
+    private:
+        void fireWeapon (Weapon &weapon);
+
     public:
         /*
          * Called to invoke some action on this player that we control, either by Graphics or NetworkServer.
--- a/src/Projectile.hh	Sat Dec 06 17:51:19 2008 +0000
+++ b/src/Projectile.hh	Sat Dec 06 18:49:51 2008 +0000
@@ -13,12 +13,12 @@
     bool visible;
     bool target_visible;
     float radius;
+
 public:
-
     TickCount birth_tick;
     TickCount age;
 
-    Projectile(GameState &state, Vector position, Vector velocity, bool visible, float radius, TickCount age=1000000000);
+    Projectile (GameState &state, Vector position, Vector velocity, bool visible, float radius, TickCount age=1000000000);
     virtual ~Projectile (void);
 
     virtual void draw (CL_GraphicContext *gc) const;
--- a/src/Terrain.cc	Sat Dec 06 17:51:19 2008 +0000
+++ b/src/Terrain.cc	Sat Dec 06 18:49:51 2008 +0000
@@ -171,23 +171,19 @@
     int dirIdx = getDirectionIndex(prevPoint.roundToInt() - point.roundToInt());
 //    dirIdx = (dirIdx+4)%8;
 
-    std::cout << (prevPoint.roundToInt()) - (point.roundToInt()) << prevPoint-point << std::endl;
-
     normal += DIRECTIONS[dirIdx];
-    for(int i = 1; i <= 2; i++) {
+    for (int i = 1; i <= 2; i++) {
         if(getType(point + DIRECTIONS[(dirIdx+i+8)%8]) == EMPTY) {
             normal += DIRECTIONS[(dirIdx+i+8)%8];
         }
     }
-    for(int i = 1; i <= 2; i++) {
+    for (int i = 1; i <= 2; i++) {
         if(getType(point + DIRECTIONS[(dirIdx-i+8)%8]) == EMPTY) {
             normal += DIRECTIONS[(dirIdx-i+8)%8];
         }
     }
 
-    Engine::log(DEBUG, "Physics.getNormal ") << "normal: " << normal << "   dirIdx: " << dirIdx;
-
-    if(getType(point) == EMPTY || getType(prevPoint) != EMPTY) {
+    if (getType(point) == EMPTY || getType(prevPoint) != EMPTY) {
         Engine::log(DEBUG, "Physics.getNormal ") << "logic ground error";
     }
     
--- a/src/Weapon.cc	Sat Dec 06 17:51:19 2008 +0000
+++ b/src/Weapon.cc	Sat Dec 06 18:49:51 2008 +0000
@@ -31,10 +31,8 @@
     return (reloadTimer == 0);
 }
 
-Projectile* Weapon::shoot (Vector position, Vector velocity) {
+void Weapon::reload (void) {
     // set the reload timer
     reloadTimer = reloadTime;
-
-    return new Projectile(st, position, velocity, true, explosionRadius);
 }
 
--- a/src/Weapon.hh	Sat Dec 06 17:51:19 2008 +0000
+++ b/src/Weapon.hh	Sat Dec 06 18:49:51 2008 +0000
@@ -34,13 +34,13 @@
     // can the weapon be fired (not reloading, have a clip, etc)
     bool canShoot (void);
     
-    // get the weapon projectile velocity
+    // get weapon parameters
     float getVelocity (void) { return velocity; }
-
-    /*
-     * Fire the Weapon! Position and velocity are the initial position and velocity for the resulting projectile
-     */
-    Projectile* shoot (Vector position, Vector velocity);
+    float getExplosionRadius (void) { return explosionRadius; }
+    TickCount getExpireTicks (void) { return age; }
+    
+    // start reloading
+    void reload (void);
 };
 
 #endif