# HG changeset patch # User terom # Date 1229913463 0 # Node ID 294ce7ae8140fd6abb4e9762831b35ae1ed572a5 # Parent 2f019ecb4aa9142bb372f5f8601d98dcfb003a1b dirty implementation of compressed terrain array data diff -r 2f019ecb4aa9 -r 294ce7ae8140 src/Network/Client.cc --- a/src/Network/Client.cc Mon Dec 22 02:37:28 2008 +0000 +++ b/src/Network/Client.cc Mon Dec 22 02:37:43 2008 +0000 @@ -6,6 +6,7 @@ #include "../Logger.hh" #include +#include NetworkClient::NetworkClient (Engine &engine, GameState &state, const NetworkEndpoint &connect_to) : engine(engine), state(state), netsession(NETWORK_MAGIC_ID), server(netsession.connect(connect_to)), @@ -29,14 +30,30 @@ Terrain &terrain = state.world; // read map width/height - // XXX: over 2**31? PixelDimension map_w = pkt.read_uint32(); PixelDimension map_h = pkt.read_uint32(); - // read map data + // the terrain byte array + size_t terrain_size = map_w * map_h; + uint8_t terrain_buf[map_w][map_h]; + + // compressed packet data + unsigned long inflate_size = terrain_size; + unsigned long deflate_size = pkt.tell_remaining(); + const uint8_t *deflate_ptr = (const uint8_t *) pkt.read_ptr(deflate_size); + + // uncompress the rest of the packet data + if (uncompress((uint8_t *) terrain_buf, &inflate_size, deflate_ptr, deflate_size) != Z_OK) + throw Error("uncompress"); + + // invalid data? + if (inflate_size != terrain_size) + throw Error("Corrupt terrain data"); + + // translate map data to terrain vector for (PixelDimension x = 0; x < map_w; x++) { for (PixelDimension y = 0; y < map_h; y++) { - terrain.terrain[x][y] = (TerrainType) pkt.read_uint8(); + terrain.terrain[x][y] = (TerrainType) terrain_buf[x][y]; } } diff -r 2f019ecb4aa9 -r 294ce7ae8140 src/Network/Packet.cc --- a/src/Network/Packet.cc Mon Dec 22 02:37:28 2008 +0000 +++ b/src/Network/Packet.cc Mon Dec 22 02:37:43 2008 +0000 @@ -135,28 +135,55 @@ if (offset + item_size > data_size) throw NetworkPacketError("not enough data to read"); } - -void NetworkPacketBuffer::write (const void *ptr, size_t len) { + +const void* NetworkPacketBuffer::read_ptr (size_t len) { // check buffer overflow check_write_size(len); - // set value - memcpy(buf_ptr + offset, ptr, len); + // pointer value... + const void *ptr = buf_ptr + offset; + + // update offset + offset += len; + + // return pointer + return ptr; +} + +void* NetworkPacketBuffer::write_ptr (size_t len) { + // check buffer overflow + check_write_size(len); + + // pointer value... + void *ptr = buf_ptr + offset; // update offset and size offset += len; data_size += len; + + // return pointer + return ptr; } void NetworkPacketBuffer::read (void *ptr, size_t len) { - // check buffer underflow - check_read_size(len); + // get input pointer... + const void *input_ptr = read_ptr(len); - // set value - memcpy(ptr, buf_ptr + offset, len); + // copy value out + memcpy(ptr, input_ptr, len); +} + +void NetworkPacketBuffer::write (const void *ptr, size_t len) { + // get output pointer... + void *output_ptr = write_ptr(len); - // update offset - offset += len; + // copy value in + memcpy(output_ptr, ptr, len); +} + +size_t NetworkPacketBuffer::tell_remaining (void) { + // number of bytes in total - number of bytes read + return data_size - offset; } /* diff -r 2f019ecb4aa9 -r 294ce7ae8140 src/Network/Packet.hh --- a/src/Network/Packet.hh Mon Dec 22 02:37:28 2008 +0000 +++ b/src/Network/Packet.hh Mon Dec 22 02:37:43 2008 +0000 @@ -22,13 +22,20 @@ class NetworkPacketInput { public: /** + * Abstract method to get a pointer to \a len bytes of raw in-memory binary data, advancing the read offset + * + * @param len the number of bytes to consume + */ + virtual const void* read_ptr (size_t len) = 0; + + /** * Abstract method that copies len bytes from the packet to ptr, first testing that they exist */ virtual void read ( void *ptr, //<<< where to copy size_t len //<<< number of bytes to copy ) = 0; - + /** * Convenience function to read() and return the value of the given type * @@ -72,6 +79,13 @@ * @return Vector (vec_x, vec_y) */ Vector read_vector (void); + + /** + * Abstract method to get the number of input bytes remaining. + * + * @return number of input bytes still readable + */ + virtual size_t tell_remaining (void) = 0; }; /** @@ -80,6 +94,13 @@ class NetworkPacketOutput { public: /** + * Abstract method to get a pointer to \a len bytes of raw in-memory binary data, advancing the write offset + * + * @param len number of bytes to commit + */ + virtual void* write_ptr (size_t len) = 0; + + /** * Abstract method that copies len bytes from ptr to the packet, first testing that they fit */ virtual void write ( @@ -177,7 +198,23 @@ * Construct the NetworkPacketBuffer using the given buf_ptr, buf_size and data_size */ NetworkPacketBuffer (char *buf_ptr, size_t buf_size, size_t data_size); - + + /** + * Returns a read-only pointer to \a len bytes of internal buffer memory, calling check_read_size first and + * updating offset + * + * @param len number of bytes from the buffer to consume + */ + virtual const void* read_ptr (size_t len); + + /** + * Returns a read-write pointer to \a len bytes of internal buffer memory, calling check_write_size first and + * updating offset+data_size + * + * @param len number of bytes in the buffer to commit + */ + virtual void* write_ptr (size_t len); + /** * Copy bytes from the packet buffer to ptr using memcpy(), calling check_read_size first. * @@ -193,6 +230,11 @@ * @param len number of bytes to copy */ virtual void write (const void *ptr, size_t len); + + /** + * Returns our data_size - read-offset + */ + virtual size_t tell_remaining (void); /* * Accessor functions, used by the actual socket code to read/write the buffer diff -r 2f019ecb4aa9 -r 294ce7ae8140 src/Network/Server.cc --- a/src/Network/Server.cc Mon Dec 22 02:37:28 2008 +0000 +++ b/src/Network/Server.cc Mon Dec 22 02:37:43 2008 +0000 @@ -6,6 +6,7 @@ #include "../Logger.hh" #include +#include NetworkServer::NetworkServer (GameState &state, const NetworkEndpoint &listen_addr) : state(state), netsession(NETWORK_MAGIC_ID), controller(netsession, NETCHAN_CORE) { @@ -235,26 +236,44 @@ void NetworkServerPlayer::send_terrain_data (void) { Terrain &terrain = server.state.world; - // XXX: over 2**31? - PixelDimension map_w = terrain.terrain.size(); - PixelDimension map_h = terrain.terrain[0].size(); + // dimensions? + PixelCoordinate map = terrain.getDimensions(); + // translate to a byte array + size_t terrain_size = map.x * map.y; + uint8_t terrain_buf[map.x][map.y]; + + // copy over from terrain vector + for (PixelDimension x = 0; x < map.x; x++) { + for (PixelDimension y = 0; y < map.y; y++) { + terrain_buf[x][y] = (uint8_t) terrain.terrain[x][y]; + } + } + + // compress the terrain buffer + unsigned long deflate_size = compressBound(terrain_size); + uint8_t deflate_buf[deflate_size]; + + // and compress + if (compress(deflate_buf, &deflate_size, (const uint8_t *) terrain_buf, terrain_size) != Z_OK) + throw Error("compress failed"); + // allocate our packet... - BigNetworkPacket pkt (NETWORK_SESSION_HEADER_SIZE + 2 * sizeof(uint32_t) + map_w * map_h); + BigNetworkPacket pkt ( + NETWORK_SESSION_HEADER_SIZE // NetworkChannel header + + 3 * sizeof(uint32_t) // our own header + + deflate_size // compressed terrain buffer + ); // write netsession header node->write_packet_header(pkt, NETCHAN_TERRAIN_ARRAY); // write terrain dimensions - pkt.write_uint32(map_w); - pkt.write_uint32(map_h); + pkt.write_uint32(map.x); + pkt.write_uint32(map.y); - // write out terrain data - for (PixelDimension x = 0; x < map_w; x++) { - for (PixelDimension y = 0; y < map_h; y++) { - pkt.write_uint8((uint8_t) terrain.terrain[x][y]); - } - } + // write compressed data + pkt.write(deflate_buf, deflate_size); // send node->send_raw(pkt, true);