Index: branches/network/src/lib/network/Makefile.am
===================================================================
--- branches/network/src/lib/network/Makefile.am	(revision 7809)
+++ branches/network/src/lib/network/Makefile.am	(revision 7851)
@@ -22,4 +22,5 @@
 		      message_manager.cc \
 		      network_log.cc \
+		      zip.cc \
 		      \
 		      synchronizeable_var/synchronizeable_var.cc \
@@ -54,4 +55,5 @@
 		 message_manager.h \
 		 network_log.h \
+		 zip.h \
 		 \
 		 synchronizeable_var/synchronizeable_var.h \
Index: branches/network/src/lib/network/connection_monitor.cc
===================================================================
--- branches/network/src/lib/network/connection_monitor.cc	(revision 7809)
+++ branches/network/src/lib/network/connection_monitor.cc	(revision 7851)
@@ -33,6 +33,10 @@
   this->incomingUnzippedBandWidth = 0;
   this->outgoingUnzippedBandWidth = 0;
+  this->incomingZippedBandWidth = 0;
+  this->outgoingZippedBandWidth = 0;
   this->nIncomingPackets = 0;
   this->nOutgoingPackets = 0;
+  this->nZIncomingPackets = 0;
+  this->nZOutgoingPackets = 0;
   
   this->lastPacketTick = 0;
@@ -56,5 +60,5 @@
   outgoingUnzippedBandWidth = calculateBandWidth( outgoingUnzippedPacketHistory, tick );
   
-  NETPRINTF(n)("UPSTREAM: user: %d bandwidth %f\n", userId, outgoingUnzippedBandWidth );
+  NETPRINTF(n)("UNZIPPED UPSTREAM: user: %d bandwidth %f\n", userId, outgoingUnzippedBandWidth );
   
   // count zero bytes
@@ -104,5 +108,5 @@
   incomingUnzippedBandWidth = calculateBandWidth( incomingUnzippedPacketHistory, tick );
   
-  NETPRINTF(n)("DOWNSTREAM: user: %d bandwidth %f\n", userId, incomingUnzippedBandWidth );
+  NETPRINTF(n)("UNZIPPED DOWNSTREAM: user: %d bandwidth %f\n", userId, incomingUnzippedBandWidth );
   
 }
@@ -132,2 +136,33 @@
 
 
+
+
+void ConnectionMonitor::processZippedOutgoingPacket( byte * data, int length, int stateId )
+{
+  int tick = SDL_GetTicks();
+  
+  nZOutgoingPackets++;
+  
+  // calculate bandwidth
+  outgoingZippedPacketHistory[tick] = length;
+  outgoingZippedBandWidth = calculateBandWidth( outgoingZippedPacketHistory, tick );
+  
+  NETPRINTF(n)("UPSTREAM: user: %d bandwidth %f\n", userId, outgoingZippedBandWidth );
+
+}
+
+
+void ConnectionMonitor::processZippedIncomingPacket( byte * data, int length, int stateId, int ackedState )
+{
+  int tick = SDL_GetTicks();
+  
+  nZIncomingPackets++;
+  
+  // calculate bandwidth
+  incomingZippedPacketHistory[tick] = length;
+  incomingZippedBandWidth = calculateBandWidth( incomingZippedPacketHistory, tick );
+  
+  NETPRINTF(n)("DOWNSTREAM: user: %d bandwidth %f\n", userId, incomingZippedBandWidth );
+  
+}
+
Index: branches/network/src/lib/network/connection_monitor.h
===================================================================
--- branches/network/src/lib/network/connection_monitor.h	(revision 7809)
+++ branches/network/src/lib/network/connection_monitor.h	(revision 7851)
@@ -24,5 +24,7 @@
     void processUnzippedOutgoingPacket( byte * data, int length, int stateId );
     void processUnzippedIncomingPacket( byte * data, int length, int stateId, int ackedState );
-    void processZippedPacket(  );
+    
+    void processZippedOutgoingPacket( byte * data, int length, int stateId );
+    void processZippedIncomingPacket( byte * data, int length, int stateId, int ackedState );
     
     void calculatePing();
@@ -40,4 +42,7 @@
     std::map<int,int>   outgoingUnzippedPacketHistory;
     
+    std::map<int,int>   incomingZippedPacketHistory;
+    std::map<int,int>   outgoingZippedPacketHistory;
+    
     std::list<int>      ackDelay;
     int                 ping;
@@ -46,6 +51,12 @@
     float               outgoingUnzippedBandWidth;
     
+    float               incomingZippedBandWidth;
+    float               outgoingZippedBandWidth;
+    
     int                 nIncomingPackets;
     int                 nOutgoingPackets;
+    
+    int                 nZIncomingPackets;
+    int                 nZOutgoingPackets;
     
     int                 lastPacketTick;
Index: branches/network/src/lib/network/network_stream.cc
===================================================================
--- branches/network/src/lib/network/network_stream.cc	(revision 7809)
+++ branches/network/src/lib/network/network_stream.cc	(revision 7851)
@@ -30,4 +30,8 @@
 #include "shared_network_data.h"
 #include "message_manager.h"
+#include "preferences.h"
+#include "zip.h"
+
+#include "src/lib/util/loading/resource_manager.h"
 
 #include "network_log.h"
@@ -88,4 +92,8 @@
   myHostId = 0;
   currentState = 0;
+  
+  remainingBytesToWriteToDict = Preferences::getInstance()->getInt( "compression", "writedict", 0 );
+  
+  assert( Zip::getInstance()->loadDictionary( "testdict" ) );
 }
 
@@ -365,5 +373,4 @@
 void NetworkStream::handleUpstream( )
 {
-  byte buf[UDP_PACKET_SIZE];
   int offset;
   int n;
@@ -430,7 +437,19 @@
     assert( Converter::intToByteArray( offset, buf, INTSIZE ) == INTSIZE );
     
-    assert( peer->second.socket->writePacket( buf, offset ) );
+    int compLength = Zip::getInstance()->zip( buf, offset, compBuf, UDP_PACKET_SIZE );
+    
+    if ( compLength < 0 )
+    {
+      PRINTF(1)("compression failed!\n");
+      continue;
+    }
+    
+    assert( peer->second.socket->writePacket( compBuf, compLength ) );
+    
+    if ( this->remainingBytesToWriteToDict > 0 )
+      writeToNewDict( buf, offset );
     
     peer->second.connectionMonitor->processUnzippedOutgoingPacket( buf, offset, currentState );
+    peer->second.connectionMonitor->processZippedOutgoingPacket( compBuf, compLength, currentState );
     
     NETPRINTF(n)("send packet: %d userId = %d\n", offset, peer->second.userId);
@@ -443,9 +462,9 @@
 void NetworkStream::handleDownstream( )
 {
-  byte buf[UDP_PACKET_SIZE];
   int offset = 0;
   
   int length = 0;
   int packetLength = 0;
+  int compLength = 0;
   int uniqueId = 0;
   int state = 0;
@@ -460,6 +479,8 @@
       continue;
 
-    while ( 0 < (packetLength = peer->second.socket->readPacket( buf, UDP_PACKET_SIZE )) )
-    {
+    while ( 0 < (compLength = peer->second.socket->readPacket( compBuf, UDP_PACKET_SIZE )) )
+    {
+      packetLength = Zip::getInstance()->unZip( compBuf, compLength, buf, UDP_PACKET_SIZE );
+      
       if ( packetLength < 4*INTSIZE )
       {
@@ -468,4 +489,7 @@
         continue;
       }
+      
+      if ( this->remainingBytesToWriteToDict > 0 )
+        writeToNewDict( buf, packetLength );
     
       assert( Converter::byteArrayToInt( buf, &length ) == INTSIZE );
@@ -586,4 +610,5 @@
       }
       
+      peer->second.connectionMonitor->processZippedIncomingPacket( compBuf, compLength, currentState, ackedState );
       peer->second.connectionMonitor->processUnzippedIncomingPacket( buf, offset, currentState, ackedState );
     
@@ -629,7 +654,44 @@
 }
 
-
-
-
-
-
+/**
+ * writes data to DATA/dicts/newdict
+ * @param data pointer to data
+ * @param length length
+ */
+void NetworkStream::writeToNewDict( byte * data, int length )
+{
+  if ( remainingBytesToWriteToDict <= 0 )
+    return;
+  
+  if ( length > remainingBytesToWriteToDict )
+    length = remainingBytesToWriteToDict;
+  
+  std::string fileName = ResourceManager::getInstance()->getDataDir();
+  fileName += "/dicts/newdict";
+  
+  FILE * f = fopen( fileName.c_str(), "a" );
+  
+  if ( !f )
+  {
+    PRINTF(2)("could not open %s\n", fileName.c_str());
+    remainingBytesToWriteToDict = 0;
+    return;
+  }
+  
+  if ( fwrite( data, 1, length, f ) != length )
+  {
+    PRINTF(2)("could not write to file\n");
+    fclose( f );
+    return;
+  }
+  
+  fclose( f );
+  
+  remainingBytesToWriteToDict -= length;  
+}
+
+
+
+
+
+
Index: branches/network/src/lib/network/network_stream.h
===================================================================
--- branches/network/src/lib/network/network_stream.h	(revision 7809)
+++ branches/network/src/lib/network/network_stream.h	(revision 7851)
@@ -15,4 +15,5 @@
 #include "handshake.h"
 #include "connection_monitor.h"
+#include "udp_server_socket.h"
 
 class Synchronizeable;
@@ -82,4 +83,6 @@
     void handleNewClient( int userId );
     void cleanUpOldSyncList();
+    
+    void writeToNewDict( byte * data, int length );
 
 
@@ -94,9 +97,14 @@
     int                        myHostId;
     
-    int                        currentState;
+    int                        currentState;                //!< current state id
 
     NetworkGameManager*        networkGameManager;
 
-    std::map<int,int>          oldSynchronizeables;
+    std::map<int,int>          oldSynchronizeables;         //!< used to save recently deleted sync ids to not recreate them
+    
+    byte                       buf[UDP_PACKET_SIZE];        //!< used by handleUp/Downstream
+    byte                       compBuf[UDP_PACKET_SIZE];    //!< used by handleUp/Downstream
+
+    int                        remainingBytesToWriteToDict; //!< if > 0 NetworkStream will write packets to DATA/dicts/newdict
 };
 #endif /* _NETWORK_STREAM */
Index: branches/network/src/lib/network/zip.cc
===================================================================
--- branches/network/src/lib/network/zip.cc	(revision 7851)
+++ branches/network/src/lib/network/zip.cc	(revision 7851)
@@ -0,0 +1,253 @@
+/*
+   orxonox - the future of 3D-vertical-scrollers
+
+   Copyright (C) 2004 orx
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+### File Specific:
+   main-programmer: Christoph Renner
+   co-programmer: ...
+*/
+
+#include "zip.h"
+
+#include "src/lib/util/loading/resource_manager.h"
+
+/**
+ *  the singleton reference to this class
+ */
+Zip* Zip::singletonRef = NULL;
+
+
+/**
+ * standard constructor
+ */
+Zip::Zip()
+{
+
+}
+
+
+/**
+ * @brief standard deconstructor
+ */
+Zip::~Zip()
+{
+  Zip::singletonRef = NULL;
+}
+
+/**
+ * load a dictionary to unzip. you can load more than one dictionary
+ * if you call unzip with data from zip without loading the same dictionary
+ * used with zip unzip will fail
+ * @param name name of dictionary
+ * @return true on success
+ */
+bool Zip::loadDictionary( std::string name )
+{
+  std::string fileName = ResourceManager::getInstance()->getDataDir();
+  //PRINTF(0)("datadir: %s\n", fileName.c_str());
+  fileName = fileName + "/dicts/" + name;
+  //PRINTF(0)("filename: %s\n", fileName.c_str());
+  
+  FILE * f = fopen( fileName.c_str(), "r" );
+  
+  if ( !f )
+  {
+    PRINTF(1)("Could not open %d\n", fileName.c_str());
+    return false;
+  }
+  
+  byte buf[1024];
+  
+  int nBytesRead = 0;
+  
+  while ( !feof( f ) )
+  {
+    nBytesRead += fread( buf, 1, sizeof(buf), f );
+  }
+  
+  DictionaryEntry entry;
+  
+  entry.dictLen = nBytesRead;
+  entry.dict = new Byte[nBytesRead];
+  
+  fseek( f, 0, SEEK_SET );
+  
+  assert( fread( entry.dict, 1, nBytesRead, f ) == nBytesRead );
+  
+  entry.adler = adler32( adler32( 0L, Z_NULL, 0 ), entry.dict, nBytesRead );
+  
+  dicts.push_back( entry );
+  
+  PRINTF(3)("Loaded dictionary '%s' with adler = %d\n", name.c_str(), entry.adler );
+  
+  return true;
+}
+
+/**
+ * zip data. you must call loadDictionary before
+ * @param from data to compress
+ * @param fromLength length of data to compress
+ * @param to pointer to compressed data
+ * @param maxLength max bytes to compress
+ * @param dict dictionary to use. default is 0
+ * @return num bytes writen to to
+ */
+int Zip::zip( byte * from, int fromLength, byte * to, int maxLength, int dict )
+{
+  if ( dicts.size() < dict+1 )
+  {
+    PRINTF(1)("you cannot use dict nr %d. num dicts: %d\n", dict, dicts.size() );
+    return -1;
+  }
+  
+  int res;
+
+  z_stream strm;
+
+  strm.zalloc = Z_NULL;
+  strm.zfree = Z_NULL;
+  strm.opaque = Z_NULL;
+
+  res = deflateInit( &strm, 9 );
+
+  if ( res != Z_OK )
+  {
+    PRINTF(1)("deflateInit error: %s\n", strm.msg);
+    return -1;
+  }
+
+  res = deflateSetDictionary( &strm, (Bytef*)(dicts[dict].dict), dicts[dict].dictLen );
+	
+  if ( res != Z_OK )
+  {
+    PRINTF(1)("deflateSetDictionary error: %s\n", strm.msg);
+    return -1;
+  }
+
+  strm.next_out = (Bytef*)to;
+  strm.avail_out = maxLength;
+  assert( strm.total_out == 0 );
+  strm.next_in = (Bytef*)from;
+  strm.avail_in = fromLength;
+  assert( strm.total_in == 0 );
+
+  res = deflate( &strm, Z_FINISH );
+	
+  if ( res != Z_STREAM_END )
+  {
+    PRINTF(1)("buffer to small or deflate error: %s\n", strm.msg);
+    return -1;
+  }
+
+  assert( strm.avail_out != 0 );
+  assert( strm.avail_in == 0 );
+
+  int zippedlen = strm.total_out;
+
+  res = deflateEnd( &strm );
+	
+  if ( res != Z_OK )
+  {
+    if ( res == Z_STREAM_ERROR )
+      PRINTF(1)("deflateEnd error: Z_STREAM_ERROR\n");
+    else if ( res == Z_DATA_ERROR )
+      PRINTF(1)("deflateEnd error: Z_DATA_ERROR %s\n", strm.msg);
+    else
+      PRINTF(1)("deflateEnd error: dont know\n");
+    
+    return -1;
+  }
+  
+  return zippedlen;
+
+}
+
+/**
+ * uncompress data. same dict as used in zip must be loaded
+ * @param from compressed data
+ * @param fromLength length of compressed data
+ * @param to buffer to copy uncompressed data to
+ * @param maxLength max bytes to copy to to
+ * @return num bytes writen to to
+ */
+int Zip::unZip( byte * from, int fromLength, byte * to, int maxLength )
+{
+  z_stream strm;
+  int res = 0;
+  
+  strm.zalloc = Z_NULL;
+  strm.zfree = Z_NULL;
+  strm.opaque = Z_NULL;
+
+  res = inflateInit( &strm );
+
+  if ( res != Z_OK )
+  {
+    PRINTF(1)("inflateInit error: %s\n", strm.msg);
+    return -1;
+  }
+	
+  strm.next_out = (Bytef*)to;
+  strm.avail_out = maxLength;
+  assert( strm.total_out == 0 );
+  strm.next_in = (Bytef*)from;
+  strm.avail_in = fromLength;
+  assert( strm.total_in == 0 );
+
+  assert( inflate( &strm, Z_NO_FLUSH ) == Z_NEED_DICT );
+	
+  int dictId = -1;
+  
+  for ( int i = 0; i < dicts.size(); i++ )
+  {
+    if ( dicts[i].adler == strm.adler )
+    {
+      dictId = i;
+      break;
+    }
+  }
+  
+  if ( dictId == -1 )
+  {
+    PRINTF(1)("Could not find dict used to compress this packet! ( adler = %d )\n", strm.adler);
+    return -1;
+  }
+      
+  res = inflateSetDictionary( &strm, (Bytef*)dicts[dictId].dict, dicts[dictId].dictLen );
+	
+  if ( res != Z_OK )
+  {
+    PRINTF(1)("inflateSetDictionary error: %s\n", strm.msg);
+    return -1;
+  }
+
+
+  res = inflate( &strm, Z_FINISH );
+	
+  if ( res != Z_STREAM_END )
+  {
+    PRINTF(1)("inflate error: %s\n", strm.msg);
+    return -1;
+  }
+
+  assert( strm.avail_out != 0 );
+  assert( strm.avail_in == 0 );
+
+  int unzippedlen = strm.total_out;
+
+  res = inflateEnd( &strm );
+	
+  if ( res != Z_OK )
+  {
+    PRINTF(1)("inflateEnd error: %s\n", strm.msg);
+    return -1;
+  }
+  
+  return unzippedlen;
+}
Index: branches/network/src/lib/network/zip.h
===================================================================
--- branches/network/src/lib/network/zip.h	(revision 7851)
+++ branches/network/src/lib/network/zip.h	(revision 7851)
@@ -0,0 +1,43 @@
+/*!
+ * @file zip.h
+ * @brief Definition of the Zip singleton Class
+ */
+
+#ifndef _ZIP_H
+#define _ZIP_H
+
+#include <zlib.h>
+#include <string>
+#include <vector>
+
+#include "netdefs.h"
+
+struct DictionaryEntry
+{
+  byte * dict;
+  int    dictLen;
+  uLong  adler;
+};
+
+//! A class for compressing/uncompressing packes.
+class Zip 
+{
+  public:
+    virtual ~Zip(void);
+    /** @returns a Pointer to the only object of this Class */
+    inline static Zip* getInstance(void) { if (!singletonRef) singletonRef = new Zip();  return singletonRef; };
+    
+    bool loadDictionary( std::string name );
+    int zip( byte * from, int fromLength, byte * to, int maxLength, int dict = 0 );
+    int unZip( byte * from, int fromLength, byte * to, int maxLength );
+    
+    int getDictCount(){ return dicts.size(); }
+
+  private:
+    Zip();
+    static Zip* singletonRef;
+    
+    std::vector<DictionaryEntry> dicts;
+};
+
+#endif /* _PROTO_SINGLETON_H */
Index: branches/network/src/orxonox.cc
===================================================================
--- branches/network/src/orxonox.cc	(revision 7809)
+++ branches/network/src/orxonox.cc	(revision 7851)
@@ -86,4 +86,5 @@
 
 REGISTER_ARG_ARG(  t, telnetport,  "network","telnetport",        "Port to use for network debug output",               "port" );
+REGISTER_ARG_ARG(  _, write_dict,  "compression", "writedict",    "write packets to DATA/dicts/newdict",               "numBytes" );
 
 /**
