From 8933b795003f8ad202fce6e553191be8932a37b6 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Fri, 30 May 2008 19:56:10 +0000 Subject: zlib support --- README-FOR-THE-LAZY | 82 ---------------------------------------- ROADMAP | 6 +-- TODO | 25 ++++++------ configure.in | 4 +- osirion.kdevelop.pcs | Bin 728934 -> 731790 bytes osirion.kdevses | 32 ++++++++-------- src/client/view.cc | 4 +- src/core/netclient.cc | 62 ++++++++++++++++++++---------- src/core/netconnection.cc | 94 ++++++++++++++++++++++++++++++++++++---------- src/core/netconnection.h | 5 +++ src/core/stats.cc | 7 ++-- src/core/stats.h | 5 ++- src/model/mapfile.cc | 6 +++ src/server/server.cc | 15 ++++++-- 14 files changed, 183 insertions(+), 164 deletions(-) delete mode 100644 README-FOR-THE-LAZY diff --git a/README-FOR-THE-LAZY b/README-FOR-THE-LAZY deleted file mode 100644 index 9238510..0000000 --- a/README-FOR-THE-LAZY +++ /dev/null @@ -1,82 +0,0 @@ - -The Osirion Project - README FOR THE LAZY - - So? You're the lazy type? - I'll just assume you know what a directory is. - -HOW TO install the game: - - OSIRION="`pwd`/osirion" - - svn checkout svn://intranifty.no-ip.org/osirion - cd osirion/ - autoreconf -fi - ./configure - make - - svn checkout svn://intranifty.no-ip.org/osirion-data data - -HOW TO run the game: - - cd $OSIRION - src/osrion - -** The console keys is ~ or `. Keyboard is probably broken on - non-qwerty layouts. - - cl_name SpaceCowboy - cl_color 1 1 0 - connect - join - spectate - buy - buy sharkan - -** Numeric keypad keys steer left or right, keypad + and - - change thrust. Spacebar changes camera mode. Cursors keys - change the camera view. - - quit - -HOW TO run a dedicated server: - - cd $OSIRION - src/osiriond - -HOW TO connect to a dedicated server: - - cl_name SpaceCowboy - cl_color 1 1 0 - connect remote.server.net - say Hi, I am connected to the server! - -** The 'T' button opens the chat window, no need to type 'say' - in the console all the time - -HOW TO go fullscreen or change resolution: - - r_width 1280 - r_height 960 - r_fullscreen 1 - r_restart - -HOW TO find more information without reading the documentation: - - list_ent - list_func - list_var - list_model - list_ship - - ls $OSIRION/data/base - vim $OSIRION/data/base/ini/world.ini - vim $OSIRION/data/base/ini/ships.ini - -It fails! - - rm -rf $OSIRION - goto 10 - -It still fails! - - Seriously, read the README and INSTALL files. diff --git a/ROADMAP b/ROADMAP index 6241459..655d5fa 100644 --- a/ROADMAP +++ b/ROADMAP @@ -7,7 +7,7 @@ Description: one planet, one space station and one piece of yet-to-determine decoration. - Multiple players can conect to the dedicated server. They can + Multiple players can connect to the dedicated server. They can fly around and see each other. They can use chat to communicate, they can use private chat or global chat. @@ -24,7 +24,7 @@ Requires: Description: Players can shoot at each other. They can crash into the star - or the planet. + or the planet. Player ships explode on destruction. Requires: Events: explosions, weapons fire @@ -52,4 +52,4 @@ Requires: Requires: Stable network protocol - + Storyline diff --git a/TODO b/TODO index 1a48e7b..a46b22e 100644 --- a/TODO +++ b/TODO @@ -4,18 +4,18 @@ TODO (--) postponed milestone 1: - console text color and wrapping - keyboard binds + console text color and wrapping (ok) + entity axis interpolation (usable for now) + camera tracking mode (usable for now) + camera frustum clip (--) - entity axis interpolation - camera axis interpolation (--) - camera tracking mode - camera frustum clip + keyboard binds milestone 2: server-client event system, hit-once lightweight entities explosion events weapons fire events + filesystem: write a filesystem based on streams @@ -33,6 +33,7 @@ core: parse command line options (ok) execute command line options (ok) globe entity (ok) + zones execute config files (ok, autoexec.cfg still missing) game module loading/unloading @@ -41,12 +42,13 @@ network: UDP datagrams (ok) buffered sends (ok) client connection state (ok) + zlib compression (partial) + fix lag (usable for now) protocol description chat, channels rcon, commands - zlib compression - fix lag + protocol version in handshake detect and disconnect clients behaving badly @@ -64,10 +66,10 @@ render: .map models (ok) write RLE tga screenshots (ok) texture registry (ok) + add small camera light (ok) text quads render pipe - - add small camera light, fix lighting without sun + fix lighting without sun sound: engine sounds @@ -77,5 +79,6 @@ win32 port: network not functional (ok) texture loading is broken (ok) screenshots are broken (ok) - + + sound is broken directory creation diff --git a/configure.in b/configure.in index e4ec169..257549e 100644 --- a/configure.in +++ b/configure.in @@ -65,7 +65,7 @@ AC_DEFUN([KDE_FIND_PATH], AC_MSG_CHECKING([host type]) case "$host" in *-*-mingw*) - HOST_LIBS="-lws2_32" + HOST_LIBS="-lws2_32 -lz" HOST_GL_LIBS="-lopengl32 -lglu32" HOST_AL_LIBS="-lOpenAL32" ICON_CLIENT="osirion-res.o" @@ -73,7 +73,7 @@ case "$host" in AC_MSG_RESULT(win32) ;; *) - HOST_LIBS="" + HOST_LIBS="-lz" HOST_GL_LIBS="-lGL -lGLU" HOST_AL_LIBS="-lopenal" ICON_CLIENT="" diff --git a/osirion.kdevelop.pcs b/osirion.kdevelop.pcs index cb82248..382fb52 100644 Binary files a/osirion.kdevelop.pcs and b/osirion.kdevelop.pcs differ diff --git a/osirion.kdevses b/osirion.kdevses index 2b16c97..d364171 100644 --- a/osirion.kdevses +++ b/osirion.kdevses @@ -2,29 +2,29 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/src/client/view.cc b/src/client/view.cc index d5f7d49..24eb8e3 100644 --- a/src/client/view.cc +++ b/src/client/view.cc @@ -154,7 +154,7 @@ void draw_status() int minutes = (int) floorf(core::game()->clientframetime() / 60.0f); int seconds = (int) floorf( core::game()->clientframetime() - (float) minutes* 60.0f); - status << "^Ntime ^B" << std::setfill('0') << std::setw(2) << minutes << ":" << std::setfill('0') << std::setw(2) << seconds; + status << "^Ntime ^B" << std::setfill(' ') << std::setw(3) << minutes << ":" << std::setfill('0') << std::setw(2) << seconds; Text::draw(video::width-Text::fontwidth()*11-4, 4+Text::fontheight(), status); } @@ -193,7 +193,7 @@ void draw_cursor() float crosshair_size = 48.0f; float x = input::mouse_x - (crosshair_size /2); float y = input::mouse_y - (crosshair_size /2); - +// 0 using namespace render; render::Textures::bind("bitmaps/crosshair"); diff --git a/src/core/netclient.cc b/src/core/netclient.cc index b90f164..dc4a0bd 100644 --- a/src/core/netclient.cc +++ b/src/core/netclient.cc @@ -4,6 +4,8 @@ the terms of the GNU General Public License version 2 */ +#include + #include #include @@ -87,29 +89,23 @@ void NetClient::retreive(std::string & message) { // receive data and decode it into lines void NetClient::receive(char *data) { - std::string datablock; - datablock.assign(data); - - if (!datablock.size()) - return; + const char *c = data; - while(datablock.size() > 0 ) { - // scan the datablock for enters - if (datablock[0] == '\n' || datablock[0] == '\r') { - // TODO detect "begin binary block" message for zlib compression + while (*c) { + if (( *c == '\n') || (*c == '\r')) { if (messageblock.size() > 0 ) { recvq.push_back(messageblock); messageblock.clear(); } } else { if (messageblock.size() < FRAMESIZE) { - messageblock.append(datablock.substr(0,1)); + messageblock += *c; } else { con_warn << "Incoming message exceeds " << FRAMESIZE << " bytes!\n"; messageblock.clear(); } } - datablock.erase(0,1); + c++; } client_timeout = application()->time(); @@ -128,16 +124,41 @@ void NetClient::transmit(int serverfd) } else { return; } - } else if (sendq.size() >= FRAMESIZE) { - con_warn << "Outgoing message exceeds " << FRAMESIZE -1 << " bytes!\n"; - //sendq.clear(); - //return; + } else if (sendq.size() >= BLOCKSIZE - 16 ) { + con_warn << host() << ":" << port() << " outgoing data exceeds " << BLOCKSIZE - 16 << " bytes!\n"; + sendq.clear(); + return; } - ssize_t bytes_sent = 0; + char zbuf[BLOCKSIZE]; + const char *data = 0; + size_t compressed_size = BLOCKSIZE - 5; + size_t total_size = 0; + + memset(zbuf,0, sizeof(zbuf)); + + Stats::network_uncompressed_bytes_sent += sendq.size(); + + // zlib compress + int status = compress((Bytef*)(zbuf+4), &compressed_size, (Bytef*)sendq.c_str(), sendq.size()); - while (sendq.size() && !error()) { - bytes_sent = ::sendto(serverfd, sendq.c_str(), sendq.size()+1, 0, + if ((status == Z_OK) && (compressed_size + 4 < sendq.size())) { + // add a header to the compress packet + data = zbuf; + total_size = compressed_size + 4; + zbuf[0] = '\xff'; + zbuf[1] = '\xff'; + zbuf[2] = compressed_size % 256; + zbuf[3] = compressed_size >> 8; + } else { + data = sendq.c_str(); + total_size = sendq.size(); + } + + size_t total_sent = 0; + + while (total_sent < total_size && !error()) { + ssize_t bytes_sent = ::sendto(serverfd, data, total_size - total_sent, 0, (struct sockaddr *)&client_addr, sizeof(client_addr)); if (bytes_sent < 0) { @@ -145,11 +166,12 @@ void NetClient::transmit(int serverfd) return; } - sendq.erase(0, bytes_sent); + total_sent += bytes_sent; + data += bytes_sent; Stats::network_bytes_sent += bytes_sent; } - sendq.clear(); + sendq.clear(); client_keepalive = application()->time(); } diff --git a/src/core/netconnection.cc b/src/core/netconnection.cc index aa3db1a..6606a9f 100644 --- a/src/core/netconnection.cc +++ b/src/core/netconnection.cc @@ -4,6 +4,8 @@ the terms of the GNU General Public License version 2 */ +#include + #include #include "sys/sys.h" @@ -20,6 +22,10 @@ NetConnection::NetConnection() { connection_timeout = core::application()->time(); connection_state = Connecting; + + receive_compressed = false; + received_compressed_size = 0; + compressed_size = 0; } NetConnection::~NetConnection() @@ -135,13 +141,13 @@ void NetConnection::receive() ssize_t bytes_received; - memset(recvbuf, '\0', BLOCKSIZE); + memset(recvbuf, 0, BLOCKSIZE); bytes_received = ::recv(connection_fd, recvbuf, BLOCKSIZE-1, 0); Stats::network_bytes_received += bytes_received; connection_timeout = core::application()->time(); if (bytes_received == 0) { - con_print << "^BDisconnected."; + con_print << "^BDisconnected." << std::endl; abort(); return; } else if (bytes_received < 0) { @@ -151,26 +157,74 @@ void NetConnection::receive() return; } - std::string datablock; - datablock.assign(recvbuf); + const char *c = recvbuf; + + while (bytes_received) { + if (receive_compressed) { + zrecvbuf[received_compressed_size] = *c; + received_compressed_size++; + + if (received_compressed_size == compressed_size) { + // uncompress + char zunbuf[BLOCKSIZE]; + memset(zunbuf, 0, sizeof(zunbuf)); + size_t zunbuf_size = BLOCKSIZE - 1; + + int status = uncompress((Bytef *) zunbuf, &zunbuf_size, (Bytef *) zrecvbuf, compressed_size); + + if (status != Z_OK) { + con_warn << "zlib error " << status << " uncompressing incoming datablock!\n"; + } else { + const char *zc = zunbuf; + while (*zc) { + if (( *zc == '\n') || (*zc == '\r')) { + if (messageblock.size()) { + recvq.push_back(messageblock); + messageblock.clear(); + } + } else { + if (messageblock.size() < FRAMESIZE) { + messageblock += *zc; + } else { + con_warn << "Incoming uncompressed message exceeds " << FRAMESIZE << " bytes!\n"; + messageblock.clear(); + } + } + zc++; + } + } - while (datablock.size()) { - // scan the datablock for enters - if (datablock[0] == '\n' || datablock[0] == '\r') { - if (messageblock.size() >= FRAMESIZE) { - con_warn << "Incoming message exceeds " << FRAMESIZE << " bytes!\n"; - messageblock.clear(); - } else if (messageblock.size()) { - recvq.push_back(messageblock); - //con_debug << "Incoming message '" << messageblock << "'" << std::endl; + // reset + receive_compressed = false; + received_compressed_size = 0; + compressed_size = 0; + } + } else if (!messageblock.size() && (bytes_received > 3 ) && ( *c == '\xff') && (*(c+1) == '\xff')) { + + receive_compressed = true; + received_compressed_size = 0; + compressed_size = *(c+2) + (*(c+3) << 8); + c += 3; + bytes_received -= 3; + memset(zrecvbuf, 0, sizeof(zrecvbuf)); + + } else if (( *c == '\n') || (*c == '\r')) { + if (messageblock.size()) { + recvq.push_back(messageblock); messageblock.clear(); } } else { - messageblock.append(datablock.substr(0,1)); + if (messageblock.size() < FRAMESIZE) { + messageblock += *c; + } else { + con_warn << "Incoming message exceeds " << FRAMESIZE << " bytes!\n"; + messageblock.clear(); + } } - datablock.erase(0,1); + c++; + bytes_received--; } - datablock.clear(); + } void NetConnection::frame(float seconds) @@ -232,10 +286,10 @@ void NetConnection::transmit() } else { return; } - } else if (sendq.size() > FRAMESIZE) { - con_warn << "Outgoing message exceeds " << FRAMESIZE << " bytes!\n"; - //sendq.clear(); - //return; + } else if (sendq.size() >= BLOCKSIZE - 16) { + con_warn << "Outgoing data exceeds " << BLOCKSIZE - 16 << " bytes!\n"; + sendq.clear(); + return; } ssize_t bytes_sent = 0; diff --git a/src/core/netconnection.h b/src/core/netconnection.h index 3cc28db..ddc70f0 100644 --- a/src/core/netconnection.h +++ b/src/core/netconnection.h @@ -104,6 +104,11 @@ private: int connection_port; struct sockaddr_in server_addr; char recvbuf[BLOCKSIZE]; + + bool receive_compressed; + size_t received_compressed_size; + size_t compressed_size; + char zrecvbuf[BLOCKSIZE]; }; } diff --git a/src/core/stats.cc b/src/core/stats.cc index 0e6a15b..36e942f 100644 --- a/src/core/stats.cc +++ b/src/core/stats.cc @@ -8,13 +8,14 @@ namespace core { -unsigned int Stats::network_bytes_sent = 0; -unsigned int Stats::network_bytes_received = 0; - +unsigned long Stats::network_bytes_sent = 0; +unsigned long Stats::network_bytes_received = 0; +unsigned long Stats::network_uncompressed_bytes_sent = 0; void Stats::clear() { network_bytes_sent = 0; network_bytes_received = 0; + network_uncompressed_bytes_sent = 0; }; } diff --git a/src/core/stats.h b/src/core/stats.h index 9d90fdc..7bcad0d 100644 --- a/src/core/stats.h +++ b/src/core/stats.h @@ -16,8 +16,9 @@ public: /// clear statistics static void clear(); - static unsigned int network_bytes_sent; - static unsigned int network_bytes_received; + static unsigned long network_bytes_sent; + static unsigned long network_uncompressed_bytes_sent; + static unsigned long network_bytes_received; }; } diff --git a/src/model/mapfile.cc b/src/model/mapfile.cc index 922e2db..585f13b 100644 --- a/src/model/mapfile.cc +++ b/src/model/mapfile.cc @@ -403,6 +403,12 @@ void MapFile::make_brushface(Plane *face) color = new math::Color(0.25, 0.25, 0.25); } else if (face->texture() == "colors/black") { color = new math::Color(0, 0, 0); + } else if (face->texture() == "colors/red") { + color = new math::Color(1, 0, 0); + } else if (face->texture() == "colors/green") { + color = new math::Color(0, 1, 0); + } else if (face->texture() == "colors/blue") { + color = new math::Color(0, 0, 1); } else if (face->texture() == "common/entity") { color = 0; } else diff --git a/src/server/server.cc b/src/server/server.cc index ee54352..27cdf9b 100644 --- a/src/server/server.cc +++ b/src/server/server.cc @@ -100,10 +100,19 @@ void Server::shutdown() { con_print << "Shutting down server..." << std::endl; - con_debug << "Network statistics:" << std::endl; - con_debug << " bytes sent " << std::setw(6) << core::Stats::network_bytes_sent / 1024 << " Kb" << std::endl; - con_debug << " bytes received " << std::setw(6) << core::Stats::network_bytes_received / 1024 << " Kb" << std::endl; + float ratio = 0; + if (core::Stats::network_uncompressed_bytes_sent > 0) + ratio = 100.0f - floorf((float)core::Stats::network_bytes_sent / + (float) core::Stats::network_uncompressed_bytes_sent * 100.0f); + + int minutes = (int) floorf(time() / 60.0f); + int seconds = (int) floorf(time() - (float) minutes* 60.0f); + con_debug << "Statistics:" << std::endl; + con_debug << " uptime " << std::setfill(' ') << std::setw(3) << minutes << ":" << std::setfill('0') << std::setw(2) << seconds << std::endl; + con_debug << " bytes sent " << std::setfill(' ') << std::setw(6) << core::Stats::network_bytes_sent / 1024 << " Kb" << std::endl; + con_debug << " bytes received " << std::setw(6) << core::Stats::network_bytes_received / 1024 << " Kb" << std::endl; + con_debug << " compression " << std::setw(6) << ratio << " %" << std::endl; Console::shutdown(); core::Application::shutdown(); -- cgit v1.2.3