From cbbcf727035c8b481889f605337a96a9e58ed970 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Mon, 22 Aug 2016 01:14:08 -0300 Subject: -High Level protocol optimization (should be smaller) -Ability to set compression to ENet packets (check API) -Fixed small bug in StringDB that lead to duplicate empty strings -Added a new class, StreamPeerBuffer, useful to create your own tightly packed data --- modules/enet/networked_multiplayer_enet.cpp | 120 ++++++++++++++++++++++++++++ modules/enet/networked_multiplayer_enet.h | 26 ++++++ modules/enet/protocol.c | 2 +- 3 files changed, 147 insertions(+), 1 deletion(-) (limited to 'modules/enet') diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp index dd83a1ac5d..5ddbb83534 100644 --- a/modules/enet/networked_multiplayer_enet.cpp +++ b/modules/enet/networked_multiplayer_enet.cpp @@ -38,6 +38,7 @@ Error NetworkedMultiplayerENet::create_server(int p_port, int p_max_clients, int ERR_FAIL_COND_V(!host,ERR_CANT_CREATE); + _setup_compressor(); active=true; server=true; refuse_connections=false; @@ -58,6 +59,8 @@ Error NetworkedMultiplayerENet::create_client(const IP_Address& p_ip, int p_port ERR_FAIL_COND_V(!host,ERR_CANT_CREATE); + _setup_compressor(); + ENetAddress address; address.host=p_ip.host; address.port=p_port; @@ -494,13 +497,124 @@ bool NetworkedMultiplayerENet::is_refusing_new_connections() const { return refuse_connections; } +void NetworkedMultiplayerENet::set_compression_mode(CompressionMode p_mode) { + + compression_mode=p_mode; +} + +NetworkedMultiplayerENet::CompressionMode NetworkedMultiplayerENet::get_compression_mode() const{ + + return compression_mode; +} + +size_t NetworkedMultiplayerENet::enet_compress(void * context, const ENetBuffer * inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 * outData, size_t outLimit) { + + NetworkedMultiplayerENet *enet = (NetworkedMultiplayerENet*)(context); + + if (size_t(enet->src_compressor_mem.size())src_compressor_mem.resize( inLimit ); + } + + int total = inLimit; + int ofs=0; + while(total) { + for(size_t i=0;isrc_compressor_mem[ofs],inBuffers[i].data,to_copy); + ofs+=to_copy; + total-=to_copy; + } + } + + Compression::Mode mode; + + switch(enet->compression_mode) { + case COMPRESS_FASTLZ: { + mode=Compression::MODE_FASTLZ; + } break; + case COMPRESS_ZLIB: { + mode=Compression::MODE_DEFLATE; + } break; + default: { ERR_FAIL_V(0); } + } + + int req_size = Compression::get_max_compressed_buffer_size(ofs,mode); + if (enet->dst_compressor_mem.size()dst_compressor_mem.resize(req_size); + } + int ret=Compression::compress(enet->dst_compressor_mem.ptr(),enet->src_compressor_mem.ptr(),ofs,mode); + + if (ret<0) + return 0; + + + if (ret>int(outLimit)) + return 0; //do not bother + + copymem(outData,enet->dst_compressor_mem.ptr(),ret); + + return ret; +} + +size_t NetworkedMultiplayerENet::enet_decompress (void * context, const enet_uint8 * inData, size_t inLimit, enet_uint8 * outData, size_t outLimit){ + + NetworkedMultiplayerENet *enet = (NetworkedMultiplayerENet*)(context); + int ret = -1; + switch(enet->compression_mode) { + case COMPRESS_FASTLZ: { + + ret=Compression::decompress(outData,outLimit,inData,inLimit,Compression::MODE_FASTLZ); + } break; + case COMPRESS_ZLIB: { + + ret=Compression::decompress(outData,outLimit,inData,inLimit,Compression::MODE_DEFLATE); + } break; + default: {} + } + if (ret<0) { + return 0; + } else { + return ret; + } +} + +void NetworkedMultiplayerENet::_setup_compressor() { + + switch(compression_mode) { + + case COMPRESS_NONE: { + + enet_host_compress(host,NULL); + } break; + case COMPRESS_RANGE_CODER: { + enet_host_compress_with_range_coder(host); + } break; + case COMPRESS_FASTLZ: + case COMPRESS_ZLIB: { + + enet_host_compress(host,&enet_compressor); + } break; + } +} + +void NetworkedMultiplayerENet::enet_compressor_destroy(void * context){ + + //do none +} + void NetworkedMultiplayerENet::_bind_methods() { ObjectTypeDB::bind_method(_MD("create_server","port","max_clients","in_bandwidth","out_bandwidth"),&NetworkedMultiplayerENet::create_server,DEFVAL(32),DEFVAL(0),DEFVAL(0)); ObjectTypeDB::bind_method(_MD("create_client","ip","port","in_bandwidth","out_bandwidth"),&NetworkedMultiplayerENet::create_client,DEFVAL(0),DEFVAL(0)); ObjectTypeDB::bind_method(_MD("close_connection"),&NetworkedMultiplayerENet::close_connection); + ObjectTypeDB::bind_method(_MD("set_compression_mode","mode"),&NetworkedMultiplayerENet::set_compression_mode); + ObjectTypeDB::bind_method(_MD("get_compression_mode"),&NetworkedMultiplayerENet::get_compression_mode); + BIND_CONSTANT( COMPRESS_NONE ); + BIND_CONSTANT( COMPRESS_RANGE_CODER ); + BIND_CONSTANT( COMPRESS_FASTLZ ); + BIND_CONSTANT( COMPRESS_ZLIB ); } @@ -515,6 +629,12 @@ NetworkedMultiplayerENet::NetworkedMultiplayerENet(){ current_packet.packet=NULL; transfer_mode=TRANSFER_MODE_RELIABLE; connection_status=CONNECTION_DISCONNECTED; + compression_mode=COMPRESS_NONE; + enet_compressor.context=this; + enet_compressor.compress=enet_compress; + enet_compressor.decompress=enet_decompress; + enet_compressor.destroy=enet_compressor_destroy; + } NetworkedMultiplayerENet::~NetworkedMultiplayerENet(){ diff --git a/modules/enet/networked_multiplayer_enet.h b/modules/enet/networked_multiplayer_enet.h index 235686d143..dc86058cbb 100644 --- a/modules/enet/networked_multiplayer_enet.h +++ b/modules/enet/networked_multiplayer_enet.h @@ -3,10 +3,20 @@ #include "io/networked_multiplayer_peer.h" #include "enet/enet.h" +#include "io/compression.h" class NetworkedMultiplayerENet : public NetworkedMultiplayerPeer { OBJ_TYPE(NetworkedMultiplayerENet,NetworkedMultiplayerPeer) +public: + enum CompressionMode { + COMPRESS_NONE, + COMPRESS_RANGE_CODER, + COMPRESS_FASTLZ, + COMPRESS_ZLIB + }; +private: + enum { SYSMSG_ADD_PEER, @@ -37,6 +47,8 @@ class NetworkedMultiplayerENet : public NetworkedMultiplayerPeer { int from; }; + CompressionMode compression_mode; + mutable List incoming_packets; mutable Packet current_packet; @@ -44,6 +56,15 @@ class NetworkedMultiplayerENet : public NetworkedMultiplayerPeer { uint32_t _gen_unique_id() const; void _pop_current_packet() const; + Vector src_compressor_mem; + Vector dst_compressor_mem; + + ENetCompressor enet_compressor; + static size_t enet_compress(void * context, const ENetBuffer * inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 * outData, size_t outLimit); + static size_t enet_decompress (void * context, const enet_uint8 * inData, size_t inLimit, enet_uint8 * outData, size_t outLimit); + static void enet_compressor_destroy(void * context); + void _setup_compressor(); + protected: static void _bind_methods(); public: @@ -77,9 +98,14 @@ public: virtual int get_unique_id() const; + void set_compression_mode(CompressionMode p_mode); + CompressionMode get_compression_mode() const; + NetworkedMultiplayerENet(); ~NetworkedMultiplayerENet(); }; +VARIANT_ENUM_CAST(NetworkedMultiplayerENet::CompressionMode); + #endif // NETWORKED_MULTIPLAYER_ENET_H diff --git a/modules/enet/protocol.c b/modules/enet/protocol.c index 5225147942..4a2a4ed185 100644 --- a/modules/enet/protocol.c +++ b/modules/enet/protocol.c @@ -1692,7 +1692,7 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch & host -> buffers [1], host -> bufferCount - 1, originalSize, host -> packetData [1], - originalSize); + originalSize); if (compressedSize > 0 && compressedSize < originalSize) { host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_COMPRESSED; -- cgit v1.2.3