send initial terrain data to clients using a new NETCHAN_TERRAIN_ARRAY channel using raw BigNetworkPacket
authorterom
Thu, 04 Dec 2008 22:33:43 +0000
changeset 203 3ec7ab40755f
parent 202 b3f5d766391e
child 204 4c386e9c950f
send initial terrain data to clients using a new NETCHAN_TERRAIN_ARRAY channel using raw BigNetworkPacket
src/Network/Client.cc
src/Network/Client.hh
src/Network/Packet.hh
src/Network/Protocol.hh
src/Network/Server.cc
src/Network/Server.hh
src/Network/Session.hh
src/Network/TCP.cc
src/Terrain.hh
--- a/src/Network/Client.cc	Thu Dec 04 22:14:45 2008 +0000
+++ b/src/Network/Client.cc	Thu Dec 04 22:33:43 2008 +0000
@@ -12,6 +12,7 @@
     
     // connect slots
     slots.connect(netobjs.sig_create(), this, &NetworkClient::on_create);
+    slots.connect(netsession.sig_chan_message(NETCHAN_TERRAIN_ARRAY), this, &NetworkClient::on_terrain_array);
 
     // XXX: sig_disconnected
 }
@@ -78,6 +79,28 @@
     state.newRemotePlayer(player);
 }
         
+void NetworkClient::on_terrain_array (NetworkPacketInput &pkt, NetworkNode *node) {
+    // ignore if not from server
+    if (node != server)
+        return;
+
+    Terrain &terrain = state.world;
+
+    // read map width/height
+    uint32_t map_w = pkt.read_uint32();
+    uint32_t map_h = pkt.read_uint32();
+
+    // read map data
+    for (int x = 0; x < map_w; x++) {
+        for (int y = 0; y < map_h; y++) {
+            terrain.terrain[x][y] = (TerrainType) pkt.read_uint8();
+        }
+    }
+
+    // update the pixbuf
+    terrain.generatePixelBuffer();
+}
+        
 void NetworkClient::player_quit (NetworkClientRemotePlayer *player) {
     // inform state
     state.removePlayer(player);
--- a/src/Network/Client.hh	Thu Dec 04 22:14:45 2008 +0000
+++ b/src/Network/Client.hh	Thu Dec 04 22:33:43 2008 +0000
@@ -31,6 +31,8 @@
         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_terrain_array (NetworkPacketInput &pkt, NetworkNode *node);
     
     public:
         void player_quit (NetworkClientRemotePlayer *player);
--- a/src/Network/Packet.hh	Thu Dec 04 22:14:45 2008 +0000
+++ b/src/Network/Packet.hh	Thu Dec 04 22:33:43 2008 +0000
@@ -153,7 +153,7 @@
         BigNetworkPacket (const BigNetworkPacket &pkt);
         BigNetworkPacket& operator= (const BigNetworkPacket &pkt);
 
-    protected:
+    public:
         virtual ~BigNetworkPacket (void);
 };
 
--- a/src/Network/Protocol.hh	Thu Dec 04 22:14:45 2008 +0000
+++ b/src/Network/Protocol.hh	Thu Dec 04 22:33:43 2008 +0000
@@ -9,7 +9,16 @@
     /*
      * Core channel used for NetworkSession
      */
-    NETCHAN_CORE            = 0x01,
+    NETCHAN_CORE            = 0x0001,
+
+    /*
+     * Channel used to send initial terrain array
+     *
+     * uint32_t                 map_w
+     * uint32_t                 map_h
+     * uint8_t[map_w][map_h]    terrain
+     */
+    NETCHAN_TERRAIN_ARRAY   = 0x0010,
 };
 
 enum NetworkPhysicsFlags {
--- a/src/Network/Server.cc	Thu Dec 04 22:14:45 2008 +0000
+++ b/src/Network/Server.cc	Thu Dec 04 22:33:43 2008 +0000
@@ -69,6 +69,9 @@
 
     // broadcast NETMSG_PLAYER_JOIN to all clients except current
     obj.send_all_except(NETMSG_PLAYER_JOIN, hello_pkt, node, true);
+
+    // send terrain data...
+    send_terrain_data();
 }
 
 void NetworkServerPlayer::handleDig (Vector position, float radius) {
@@ -119,6 +122,33 @@
     send_position_update();
 }
         
+void NetworkServerPlayer::send_terrain_data (void) {
+    Terrain &terrain = server.state.world;
+
+    uint32_t map_w = terrain.terrain.size();
+    uint32_t map_h = terrain.terrain[0].size();
+
+    // allocate our packet...
+    BigNetworkPacket pkt (NETWORK_SESSION_HEADER_SIZE + 2 * sizeof(uint32_t) + map_w * map_h);
+    
+    // write netsession header
+    node->write_packet_header(pkt, NETCHAN_TERRAIN_ARRAY);
+
+    // write terrain dimensions
+    pkt.write_uint32(map_w);
+    pkt.write_uint32(map_h);
+
+    // write out terrain data
+    for (int x = 0; x < map_w; x++) {
+        for (int y = 0; y < map_h; y++) {
+            pkt.write_uint8((uint8_t) terrain.terrain[x][y]);
+        }
+    }
+
+    // send
+    node->send_raw(pkt, true);
+}
+
 void NetworkServerPlayer::send_position_update (void) {
     NetworkPacket pkt;
     
--- a/src/Network/Server.hh	Thu Dec 04 22:14:45 2008 +0000
+++ b/src/Network/Server.hh	Thu Dec 04 22:33:43 2008 +0000
@@ -49,7 +49,8 @@
     private:
         void on_disconnected (void);
         void on_move (NetworkNode *node, NetworkPacketInput &pkt);
-
+        
+        void send_terrain_data (void);
         void send_position_update (void);
 };
 
--- a/src/Network/Session.hh	Thu Dec 04 22:14:45 2008 +0000
+++ b/src/Network/Session.hh	Thu Dec 04 22:33:43 2008 +0000
@@ -12,6 +12,11 @@
  */
 typedef uint16_t NetworkChannelID;
 
+/*
+ * Size of a packet header
+ */
+const size_t NETWORK_SESSION_HEADER_SIZE = sizeof(uint16_t);
+
 #include "TCP.hh"
 #include "UDP.hh"
 #include "Node.hh"
--- a/src/Network/TCP.cc	Thu Dec 04 22:14:45 2008 +0000
+++ b/src/Network/TCP.cc	Thu Dec 04 22:33:43 2008 +0000
@@ -16,11 +16,11 @@
 
 
 void NetworkTCPTransport::on_read (void) {
-    uint16_t length;
+    uint32_t length;
     char *buf_ptr;
     
     // let the in stream read length-prefixed packets and pass them on to handle_packet
-    while (in.peek_data<uint16_t>(length, buf_ptr)) {
+    while (in.peek_data<uint32_t>(length, buf_ptr)) {
         // allocate the NetworkPacketBuffer with the given buf_ptr/length
         NetworkPacketBuffer packet(buf_ptr, length, length);
         
@@ -28,7 +28,7 @@
         _sig_packet(packet);
 
         // flush it
-        in.flush_data<uint16_t>();
+        in.flush_data<uint32_t>();
     }
 }
 
@@ -43,7 +43,7 @@
 }
         
 void NetworkTCPTransport::write_packet (const NetworkPacketBuffer &packet) {
-    uint16_t prefix = packet.get_data_size();
+    uint32_t prefix = packet.get_data_size();
     
     if (prefix != packet.get_data_size())
         throw CL_Error("send prefix overflow");
--- a/src/Terrain.hh	Thu Dec 04 22:14:45 2008 +0000
+++ b/src/Terrain.hh	Thu Dec 04 22:33:43 2008 +0000
@@ -30,18 +30,19 @@
  * and it uses pixelcoordinates internally.
  */ 
 class Terrain {
-private:
+    public: // XXX: until we fix Network's access to this
     std::vector<std::vector<TerrainType> > terrain;
 
-    // Terrain graphic
-    CL_PixelBuffer pixbuf;
-
     /**
      * Generates pixelbuffer from terrain. Should be used only on
      * constructors because this is expected to be slow.
      */
     void generatePixelBuffer();
 
+private:
+    // Terrain graphic
+    CL_PixelBuffer pixbuf;
+
     /**
      * Get pixel location of a point that is in "real" units.
      *