Index: code/trunk/src/libraries/network/CMakeLists.txt
===================================================================
--- code/trunk/src/libraries/network/CMakeLists.txt	(revision 6746)
+++ code/trunk/src/libraries/network/CMakeLists.txt	(revision 7163)
@@ -29,4 +29,6 @@
   GamestateClient.cc
   GamestateHandler.cc
+  LANDiscoverable.cc
+  LANDiscovery.cc
   NetworkFunction.cc
   Host.cc
@@ -48,4 +50,6 @@
   GamestateManager.h
   Host.h
+  LANDiscoverable.h
+  LANDiscovery.h
   NetworkFunction.h
   NetworkPrecompiledHeaders.h
@@ -60,6 +64,7 @@
 
 ORXONOX_ADD_LIBRARY(network
-  DEFINE_SYMBOL
-    "NETWORK_SHARED_BUILD"
+  TOLUA_FILES
+    Client.h
+    LANDiscovery.h
   PCH_FILE
     NetworkPrecompiledHeaders.h
Index: code/trunk/src/libraries/network/ChatListener.cc
===================================================================
--- code/trunk/src/libraries/network/ChatListener.cc	(revision 6746)
+++ code/trunk/src/libraries/network/ChatListener.cc	(revision 7163)
@@ -36,4 +36,14 @@
         RegisterRootObject(ChatListener);
     }
+
+    //void ChatListener::incomingChat( const std::string& message,
+      //unsigned int senderID )
+    //{
+      //COUT(0) << "Chat: \"" << message << "\"\n";
+
+
+    //}
+
+
 }
 
Index: code/trunk/src/libraries/network/ChatListener.h
===================================================================
--- code/trunk/src/libraries/network/ChatListener.h	(revision 6746)
+++ code/trunk/src/libraries/network/ChatListener.h	(revision 7163)
@@ -38,7 +38,9 @@
     {
         public:
+            /* constructor, destructor */
             ChatListener();
             virtual ~ChatListener() {}
 
+            /* What to do with incoming chat */
             virtual void incomingChat(const std::string& message, unsigned int senderID) = 0;
     };
Index: code/trunk/src/libraries/network/Client.cc
===================================================================
--- code/trunk/src/libraries/network/Client.cc	(revision 6746)
+++ code/trunk/src/libraries/network/Client.cc	(revision 7163)
@@ -50,9 +50,12 @@
 #include "FunctionCallManager.h"
 #include "core/CoreIncludes.h"
+#include "core/CommandLineParser.h"
 #include "core/Game.h"
+#include "core/ScopedSingletonManager.h"
 
 namespace orxonox
 {
 
+  ManageScopedSingleton( Client, ScopeID::Root, true );
 
   /**
@@ -61,25 +64,14 @@
   */
   Client::Client():
+      gamestate(0),
       isSynched_(false),
       gameStateFailure_(false),
       timeSinceLastUpdate_(0)
   {
-  }
-
-  /**
-  * Constructor for the Client class
-  * @param address the server address
-  * @param port port of the application on the server
-  */
-  Client::Client(const std::string& address, int port):
-      isSynched_(false),
-      gameStateFailure_(false),
-      timeSinceLastUpdate_(0)
-  {
-      setPort( port );
-      setServerAddress( address );
-  }
-
-  Client::~Client(){
+    this->setDestination( CommandLineParser::getValue("dest").getString(), CommandLineParser::getValue("port") );
+  }
+
+  Client::~Client()
+  {
     if ( ClientConnection::isConnected() )
       closeConnection();
@@ -90,7 +82,15 @@
   * @return true/false
   */
-  bool Client::establishConnection(){
+  bool Client::establishConnection()
+  {
     Synchronisable::setClient(true);
-    return ClientConnection::establishConnection();
+    this->gamestate = new GamestateClient();
+    if( ClientConnection::establishConnection() )
+    {
+      Host::setActive(true);
+      return true;
+    }
+    else
+      return false;
   }
 
@@ -99,9 +99,21 @@
   * @return true/false
   */
-  bool Client::closeConnection(){
+  bool Client::closeConnection()
+  {
+    assert(this->gamestate);
+    delete this->gamestate;
+    this->gamestate = 0;
+    Host::setActive(false);
     return ClientConnection::closeConnection();
   }
-
-  bool Client::queuePacket(ENetPacket *packet, int clientID){
+  
+  void Client::setDestination(const std::string& serverAddress, unsigned int port)
+  {
+    ClientConnection::setServerAddress(serverAddress);
+    ClientConnection::setPort(port);
+  }
+
+  bool Client::queuePacket(ENetPacket *packet, int clientID)
+  {
     bool b = ClientConnection::addPacket(packet);
     assert(b);
@@ -109,10 +121,12 @@
   }
 
-  bool Client::processChat(const std::string& message, unsigned int playerID){
+  bool Client::processChat(const std::string& message, unsigned int playerID)
+  {
 //    COUT(1) << "Player " << playerID << ": " << message << std::endl;
     return true;
   }
 
-  void Client::printRTT(){
+  void Client::printRTT()
+  {
     COUT(0) << "Round trip time to server is " << ClientConnection::getRTT() << " ms" << endl;
   }
@@ -123,5 +137,6 @@
    * @return result(true/false)
    */
-  bool Client::chat(const std::string& message){
+  bool Client::chat(const std::string& message)
+  {
     packet::Chat *m = new packet::Chat(message, Host::getPlayerID());
     return m->send();
@@ -133,5 +148,6 @@
    * @param time
    */
-  void Client::update(const Clock& time){
+  void Client::update(const Clock& time)
+  {
     //this steers our network frequency
     timeSinceLastUpdate_+=time.getDeltaTime();
@@ -143,5 +159,5 @@
       {
         COUT(4) << "popping partial gamestate: " << std::endl;
-        packet::Gamestate *gs = gamestate.getGamestate();
+        packet::Gamestate *gs = gamestate->getGamestate();
         //assert(gs); <--- there might be the case that no data has to be sent, so its commented out now
         if(gs){
@@ -157,10 +173,10 @@
 
     Connection::processQueue();
-    if(gamestate.processGamestates())
+    if(gamestate->processGamestates())
     {
       if(!isSynched_)
         isSynched_=true;
     }
-    gamestate.cleanup();
+    gamestate->cleanup();
     Connection::sendPackets();
 
@@ -184,3 +200,5 @@
   }
 
+
+
 }
Index: code/trunk/src/libraries/network/Client.h
===================================================================
--- code/trunk/src/libraries/network/Client.h	(revision 6746)
+++ code/trunk/src/libraries/network/Client.h	(revision 7163)
@@ -47,10 +47,15 @@
 
 #include "util/UtilPrereqs.h"
+#include "util/Singleton.h"
 #include "ClientConnection.h"
 #include "GamestateClient.h"
 #include "Host.h"
+#include "LANDiscovery.h"
+#include "packet/ServerInformation.h"
 
+// tolua_begin
 namespace orxonox
 {
+// tolua_end
   /**
   Client *client;
@@ -60,11 +65,16 @@
   *
   */
-  class _NetworkExport Client : public Host, public ClientConnection{
+  class _NetworkExport Client // tolua_export
+    : public Host, protected ClientConnection, public Singleton<Client>
+  { // tolua_export
+  friend class Singleton<Client>;
   public:
     Client();
-    Client(const std::string& address, int port);
     ~Client();
+    
+    static Client* getInstance(){ return singletonPtr_s; } // tolua_export
 
     bool establishConnection();
+    void setDestination( const std::string& serverAddress, unsigned int port ); // tolua_export
     bool closeConnection();
     bool queuePacket(ENetPacket *packet, int clientID);
@@ -81,13 +91,14 @@
     virtual bool isServer_(){return false;}
 
-    GamestateClient gamestate;
+    static Client* singletonPtr_s;
+    GamestateClient* gamestate;
     bool isSynched_;
 
     bool gameStateFailure_;
     float timeSinceLastUpdate_;
-  };
+  }; // tolua_export
 
 
-}
+} // tolua_export
 
 #endif /* _Client_H__ */
Index: code/trunk/src/libraries/network/Connection.cc
===================================================================
--- code/trunk/src/libraries/network/Connection.cc	(revision 6746)
+++ code/trunk/src/libraries/network/Connection.cc	(revision 7163)
@@ -36,11 +36,11 @@
 namespace orxonox
 {
-  Connection *Connection::instance_=0;
+//   Connection *Connection::instance_=0;
 
   Connection::Connection():
     host_(0)
   {
-    assert(instance_==0);
-    Connection::instance_=this;
+//     assert(instance_==0);
+//     Connection::instance_=this;
     enet_initialize();
     atexit(enet_deinitialize);
@@ -48,5 +48,5 @@
 
   Connection::~Connection(){
-    Connection::instance_=0;
+//     Connection::instance_=0;
   }
 
@@ -67,5 +67,5 @@
 
   bool Connection::sendPackets() {
-    if ( !Connection::instance_ || this->host_==NULL )
+    if ( /*!Connection::instance_ || */this->host_==NULL )
       return false;
     enet_host_flush(this->host_);
Index: code/trunk/src/libraries/network/Connection.h
===================================================================
--- code/trunk/src/libraries/network/Connection.h	(revision 6746)
+++ code/trunk/src/libraries/network/Connection.h	(revision 7163)
@@ -61,5 +61,5 @@
   protected:
     Connection();
-    static Connection* getInstance(){ return Connection::instance_; }
+//     static Connection* getInstance(){ return Connection::instance_; }
 
     int service(ENetEvent* event);
@@ -75,5 +75,5 @@
     ENetAddress *bindAddress_;
 
-    static Connection *instance_;
+//     static Connection *instance_;
 
   };
Index: code/trunk/src/libraries/network/GamestateClient.cc
===================================================================
--- code/trunk/src/libraries/network/GamestateClient.cc	(revision 6746)
+++ code/trunk/src/libraries/network/GamestateClient.cc	(revision 7163)
@@ -161,16 +161,19 @@
       assert(b);
     }
-    if(gs->isDiffed()){
-      packet::Gamestate *base = gamestateMap_[gs->getBaseID()];
-      if(!base){
-        COUT(3) << "could not find base gamestate id: " << gs->getBaseID() << endl;
-        delete gs;
-        return 0;
-      }
-//       assert(base); //TODO: fix this
-      packet::Gamestate *undiffed = gs->undiff(base);
-      delete gs;
-      gs=undiffed;
-      COUT(5) << "successfully undiffed gamestate id: " << undiffed->getID() << std::endl;
+    if(gs->isDiffed())
+    {
+      assert(0);
+//       packet::Gamestate *base = gamestateMap_[gs->getBaseID()];
+//       if(!base)
+//       {
+//         COUT(0) << "could not find base gamestate id: " << gs->getBaseID() << endl;
+//         assert(0);
+//         delete gs;
+//         return 0;
+//       }
+//       packet::Gamestate *undiffed = gs->undiff(base);
+//       delete gs;
+//       gs=undiffed;
+//       COUT(5) << "successfully undiffed gamestate id: " << undiffed->getID() << std::endl;
     }
     if(gs->spreadData(0x2))
@@ -178,5 +181,6 @@
     else
     {
-      COUT(3) << "could not spread gamestate" << endl;
+      COUT(0) << "could not spread gamestate" << endl;
+      assert(0);
       return NULL;
     }
Index: code/trunk/src/libraries/network/GamestateManager.cc
===================================================================
--- code/trunk/src/libraries/network/GamestateManager.cc	(revision 6746)
+++ code/trunk/src/libraries/network/GamestateManager.cc	(revision 7163)
@@ -43,4 +43,5 @@
 #include <cassert>
 #include <queue>
+#include "util/Clock.h"
 // #include <boost/thread/mutex.hpp>
 
@@ -158,5 +159,5 @@
 
       clientGamestates.push(0);
-      finishGamestate( cid, &clientGamestates.back(), client, reference );
+      finishGamestate( cid, clientGamestates.back(), client, reference );
       //FunctorMember<GamestateManager>* functor =
 //       ExecutorMember<GamestateManager>* executor = createExecutor( createFunctor(&GamestateManager::finishGamestate, this) );
@@ -180,5 +181,5 @@
 
 
-  void GamestateManager::finishGamestate( unsigned int clientID, packet::Gamestate** destgamestate, packet::Gamestate* base, packet::Gamestate* gamestate ) {
+  void GamestateManager::finishGamestate( unsigned int clientID, packet::Gamestate*& destgamestate, packet::Gamestate* base, packet::Gamestate* gamestate ) {
     //why are we searching the same client's gamestate id as we searched in
     //Server::sendGameState?
@@ -186,6 +187,8 @@
     //chose wheather the next gamestate is the first or not
 
-    packet::Gamestate *gs = gamestate->doSelection(clientID, 20000);
-//     packet::Gamestate *gs = new packet::Gamestate(*gamestate);
+//     packet::Gamestate *gs = gamestate->doSelection(clientID, 20000);
+//       packet::Gamestate* gs = new packet::Gamestate(*gamestate);
+//     packet::Gamestate* gs = gamestate;
+    packet::Gamestate *gs = new packet::Gamestate(*gamestate); //TODO: is this neccessary ?
 //     packet::Gamestate *gs = new packet::Gamestate();
 //     gs->collectData( id_, 0x1 );
@@ -193,19 +196,20 @@
     gamestateMap_[clientID][gamestate->getID()]=gs;
 //     this->threadMutex_->unlock();
+      Clock clock;
+      clock.capture();
 
     if(base)
     {
-
-//       COUT(3) << "diffing" << std::endl;
-//       packet::Gamestate* gs1  = gs;
-      packet::Gamestate *diffed = gs->diff(base);
-      //packet::Gamestate *gs2 = diffed->undiff(gs);
-//       assert(*gs == *gs2);
-      gs = diffed;
-//       packet::Gamestate* gs2 = gs->undiff(client);
-//       gs = new packet::Gamestate(*gs);
-//       assert(*gs1==*gs2);
-    }
-    else{
+      packet::Gamestate *diffed1 = gs->diffVariables(base);
+      if( diffed1->getDataSize() == 0 )
+      {
+        delete diffed1;
+        destgamestate = 0;
+        return;
+      }
+      gs = diffed1;
+    }
+    else
+    {
       gs = new packet::Gamestate(*gs);
     }
@@ -214,11 +218,13 @@
     bool b = gs->compressData();
     assert(b);
-//     COUT(4) << "sending gamestate with id " << gs->getID();
+      clock.capture();
+      COUT(0) << "diff time: " << clock.getDeltaTime() << endl;
+//     COUT(5) << "sending gamestate with id " << gs->getID();
 //     if(gamestate->isDiffed())
-//     COUT(4) << " and baseid " << gs->getBaseID() << endl;
+//       COUT(5) << " and baseid " << gs->getBaseID() << endl;
 //     else
-//     COUT(4) << endl;
+//       COUT(5) << endl;
     gs->setClientID(clientID);
-    *destgamestate = gs;
+    destgamestate = gs;
   }
 
Index: code/trunk/src/libraries/network/GamestateManager.h
===================================================================
--- code/trunk/src/libraries/network/GamestateManager.h	(revision 6746)
+++ code/trunk/src/libraries/network/GamestateManager.h	(revision 7163)
@@ -76,5 +76,5 @@
     void sendGamestates();
 //     packet::Gamestate *popGameState(unsigned int clientID);
-    void finishGamestate( unsigned int clientID, packet::Gamestate** destgamestate, packet::Gamestate* base, packet::Gamestate* gamestate );
+    void finishGamestate( unsigned int clientID, packet::Gamestate*& destgamestate, packet::Gamestate* base, packet::Gamestate* gamestate );
 
     bool getSnapshot();
Index: code/trunk/src/libraries/network/Host.cc
===================================================================
--- code/trunk/src/libraries/network/Host.cc	(revision 6746)
+++ code/trunk/src/libraries/network/Host.cc	(revision 7163)
@@ -38,81 +38,127 @@
 namespace orxonox {
 
-SetConsoleCommandShortcut(Host, Chat);
+  SetConsoleCommandShortcut(Host, Chat);
 
-Host *Host::instance_=0;
+  // Host*               Host::instance_=0;
+  uint32_t            Host::clientID_s=0;
+  uint32_t            Host::shipID_s=-1;
+  std::vector<Host*>  Host::instances_s;
 
-/**
- * @brief Constructor: assures that only one reference will be created and sets the pointer
- */
-Host::Host()
-{
-  clientID_=0;
-  assert(instance_==0);
-  instance_=this;
-  this->printRTTCC_ = createConsoleCommand( createFunctor(&Host::printRTT, this), "printRTT" );
-  CommandExecutor::addConsoleCommandShortcut( this->printRTTCC_ );
-}
+  /**
+  * @brief Constructor: assures that only one reference will be created and sets the pointer
+  */
+  Host::Host()
+  {
+  //   assert(instance_==0);
+    instances_s.push_back(this);
+    this->printRTTCC_ = createConsoleCommand( createFunctor(&Host::printRTT, this), "printRTT" );
+    CommandExecutor::addConsoleCommandShortcut( this->printRTTCC_ );
+    this->bIsActive_ = false;
+  }
 
 
-/**
- * @brief Destructor: resets the instance pointer to 0
- */
-Host::~Host()
-{
-  instance_=0;
-  if( this->printRTTCC_ )
-    delete this->printRTTCC_;
-}
+  /**
+  * @brief Destructor: resets the instance pointer to 0
+  */
+  Host::~Host()
+  {
+    assert( std::find( instances_s.begin(), instances_s.end(), this )!=instances_s.end() );
+    instances_s.erase(std::find( instances_s.begin(), instances_s.end(), this ));
+    if( this->printRTTCC_ )
+      delete this->printRTTCC_;
+  }
 
-/**
- * This function is used to add an enetpacket to be sent to another peer
- * @param packet Packet to be added
- * @param clientID ID of the client the packet should be sent to
- * @return success?
- */
-bool Host::addPacket(ENetPacket *packet, int clientID){
-  if(instance_)
-    return instance_->queuePacket(packet, clientID);
-  else
-    return false;
-}
+  /**
+  * This function is used to add an enetpacket to be sent to another peer
+  * @param packet Packet to be added
+  * @param clientID ID of the client the packet should be sent to
+  * @return success?
+  */
+  bool Host::addPacket(ENetPacket *packet, int clientID)
+  {
+    bool result = true;
+    for( std::vector<Host*>::iterator it = instances_s.begin(); it!=instances_s.end(); ++it )
+    {
+      if( (*it)->isActive() )
+      {
+        if( !(*it)->queuePacket(packet, clientID) )
+          result = false;
+      }
+    }
+    return result;
+  }
 
-/**
- * This function returns the ID of the player
- * @return playerID
- */
-unsigned int Host::getPlayerID(){
-  if(!instance_)
-    return 0;
-  return instance_->clientID_;
-}
+  bool Host::Chat(const std::string& message)
+  {
+    if(instances_s.size()==0)
+    {
+      for (ObjectList<ChatListener>::iterator it = ObjectList<ChatListener>::begin(); it != ObjectList<ChatListener>::end(); ++it)
+        it->incomingChat(message, 0);
+      return true;
+    }
+    else
+    {
+      bool result = true;
+      for( std::vector<Host*>::iterator it = instances_s.begin(); it!=instances_s.end(); ++it )
+      {
+        if( (*it)->isActive() )
+        {
+          if( !(*it)->chat(message) )
+            result = false;
+        }
+      }
+      return result;
+    }
+  }
 
-bool Host::Chat(const std::string& message){
-  if(!instance_)
+  bool Host::Broadcast(const std::string& message)
+  {
+    if(instances_s.size()==0)
+    {
+      for (ObjectList<ChatListener>::iterator it = ObjectList<ChatListener>::begin(); it != ObjectList<ChatListener>::end(); ++it)
+        it->incomingChat(message, CLIENTID_UNKNOWN);
+      return true;
+    }
+    else
+    {
+      bool result = true;
+      for( std::vector<Host*>::iterator it = instances_s.begin(); it!=instances_s.end(); ++it )
+      {
+        if( (*it)->isActive() )
+        {
+          if( !(*it)->broadcast(message) )
+            result = false;
+        }
+      }
+      return result;
+    }
+  }
+
+  bool Host::incomingChat(const std::string& message, unsigned int playerID)
   {
     for (ObjectList<ChatListener>::iterator it = ObjectList<ChatListener>::begin(); it != ObjectList<ChatListener>::end(); ++it)
-      it->incomingChat(message, 0);
-    return true;
+      it->incomingChat(message, playerID);
+    
+    bool result = true;
+    for( std::vector<Host*>::iterator it = instances_s.begin(); it!=instances_s.end(); ++it )
+    {
+      if( (*it)->isActive() )
+      {
+        if( !(*it)->processChat(message, playerID) )
+          result = false;
+      }
+    }
+    return result;
   }
-  return instance_->chat(message);
-}
 
-bool Host::Broadcast(const std::string& message){
-  if(!instance_)
+  bool Host::isServer()
   {
-    for (ObjectList<ChatListener>::iterator it = ObjectList<ChatListener>::begin(); it != ObjectList<ChatListener>::end(); ++it)
-      it->incomingChat(message, CLIENTID_UNKNOWN);
-    return true;
+    for (std::vector<Host*>::iterator it=instances_s.begin(); it!=instances_s.end(); ++it )
+    {
+      if( (*it)->isServer_() )
+        return true;
+    }
+    return false;
   }
-  else
-    return instance_->broadcast(message);
-}
-
-bool Host::incomingChat(const std::string& message, unsigned int playerID){
-  for (ObjectList<ChatListener>::iterator it = ObjectList<ChatListener>::begin(); it != ObjectList<ChatListener>::end(); ++it)
-    it->incomingChat(message, playerID);
-
-  return instance_->processChat(message, playerID);
-}
 
 }//namespace orxonox
Index: code/trunk/src/libraries/network/Host.h
===================================================================
--- code/trunk/src/libraries/network/Host.h	(revision 6746)
+++ code/trunk/src/libraries/network/Host.h	(revision 7163)
@@ -33,8 +33,10 @@
 #include "core/CorePrereqs.h"
 
+#include <vector>
+
 namespace orxonox {
 
   const unsigned int CLIENTID_SERVER = 0;
-  const unsigned int NETWORK_FREQUENCY = 30;
+  const unsigned int NETWORK_FREQUENCY = 25;
   const float NETWORK_PERIOD = 1.0f/NETWORK_FREQUENCY;
 
@@ -49,5 +51,5 @@
 class _NetworkExport Host{
   private:
-    //TODO add theese functions or adequate
+    //TODO add these functions or adequate
     //virtual bool processChat(packet::Chat *message, unsigned int clientID)=0;
     //virtual bool sendChat(packet::Chat *chat)=0;
@@ -63,24 +65,29 @@
     Host();
     virtual ~Host();
-    static Host *instance_;
-    unsigned int clientID_;
-    unsigned int shipID_;
+    void setActive( bool bActive ){ bIsActive_ = bActive; }
+//     static Host *instance_;
 
   public:
-    static bool running(){return instance_!=0;}
+//     static Host* getInstance(){ return instance_; }
+    static bool running(){ return instances_s.size(); }
     static bool addPacket(ENetPacket *packet, int clientID=0);
     //static bool chat(std::string& message);
 //     static bool receiveChat(packet::Chat *message, unsigned int clientID);
-    static unsigned int getPlayerID();
-    static unsigned int getShipID(){return instance_->shipID_;}
-    static void setClientID(unsigned int id){ instance_->clientID_ = id; }
-    static void setShipID(unsigned int id){ instance_->shipID_ = id; }
-    static bool isServer(){ return instance_->isServer_(); }
+    static unsigned int getPlayerID(){ return clientID_s; }
+    static unsigned int getShipID(){return shipID_s;}
+    static void setClientID(unsigned int id){ clientID_s = id; }
+    static void setShipID(unsigned int id){ shipID_s = id; }
+    static bool isServer();
     static bool Chat(const std::string& message);
     static bool Broadcast(const std::string& message);
     static bool incomingChat(const std::string& message, unsigned int playerID);
     virtual void printRTT()=0;
+    bool isActive(){ return bIsActive_; }
   private:
     ConsoleCommand* printRTTCC_;
+    static uint32_t clientID_s;
+    static uint32_t shipID_s;
+    static std::vector<Host*> instances_s;
+    bool bIsActive_;
 };
 
Index: code/trunk/src/libraries/network/LANDiscoverable.cc
===================================================================
--- code/trunk/src/libraries/network/LANDiscoverable.cc	(revision 7163)
+++ code/trunk/src/libraries/network/LANDiscoverable.cc	(revision 7163)
@@ -0,0 +1,109 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   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
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "LANDiscoverable.h"
+
+#include "NetworkPrereqs.h"
+#include "packet/ServerInformation.h"
+
+#include <enet/enet.h>
+#include <cassert>
+#include <cstring>
+
+namespace orxonox
+{
+  const char* LAN_DISCOVERY_MESSAGE = "Orxonox Client";
+  const char* LAN_DISCOVERY_ACK     = "Orxonox Server Ack";
+
+  LANDiscoverable::LANDiscoverable()
+  {
+    this->host_ = 0;
+    this->bActive_ = false;
+    this->setActivity(true);
+  }
+
+  LANDiscoverable::~LANDiscoverable()
+  {
+    if( this->host_ )
+    {
+      enet_host_destroy( this->host_ );
+      assert( this->bActive_ );
+    }
+  }
+
+  void LANDiscoverable::setActivity(bool bActive)
+  {
+    if( bActive == this->bActive_ )        // no change
+      return;
+    
+    if( bActive )
+    {
+      ENetAddress bindAddress = { ENET_HOST_ANY, LAN_DISCOVERY_PORT };
+      assert( this->host_ == 0 );
+      this->host_ = enet_host_create( &bindAddress, 10, 0, 0 );
+    }
+    else
+    {
+      enet_host_destroy( this->host_ );
+      this->host_ = 0;
+    }
+      this->bActive_ = bActive;
+  }
+
+  void LANDiscoverable::update()
+  {
+    ENetEvent event;
+    
+    if( this->bActive_==false )
+      return;
+    assert(this->host_);
+    
+    while( enet_host_service( this->host_, &event, 0 ) > 0 )
+    {
+      switch(event.type)
+      {
+        case ENET_EVENT_TYPE_CONNECT:
+        case ENET_EVENT_TYPE_DISCONNECT:
+        case ENET_EVENT_TYPE_NONE:
+          break;
+        case ENET_EVENT_TYPE_RECEIVE:
+          if( strcmp( LAN_DISCOVERY_MESSAGE, (char*)event.packet->data ) == 0 )      // check for a suitable orxonox client
+          {
+            packet::ServerInformation info;
+            info.setServerName("Orxonox Server");
+            info.send(event.peer);
+//             ENetPacket* packet = enet_packet_create( LAN_DISCOVERY_ACK, strlen(LAN_DISCOVERY_ACK)+1, ENET_PACKET_FLAG_RELIABLE );
+//             enet_peer_send(event.peer, 0, packet );
+            enet_host_flush(this->host_);
+          }
+          break;
+      }
+    }
+  }
+
+}
Index: code/trunk/src/libraries/network/LANDiscoverable.h
===================================================================
--- code/trunk/src/libraries/network/LANDiscoverable.h	(revision 7163)
+++ code/trunk/src/libraries/network/LANDiscoverable.h	(revision 7163)
@@ -0,0 +1,52 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   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
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _LANDISCOVERABLE_H__
+#define _LANDISCOVERABLE_H__
+
+#include "NetworkPrereqs.h"
+
+namespace orxonox
+{
+  
+  class LANDiscoverable
+  {
+    public:
+      LANDiscoverable();
+      ~LANDiscoverable();
+      void setActivity( bool bActive );
+      void update();
+      
+    private:
+      bool            bActive_;
+      ENetHost*       host_;
+  };
+
+}
+
+#endif // LANDISCOVERABLE_H
Index: code/trunk/src/libraries/network/LANDiscovery.cc
===================================================================
--- code/trunk/src/libraries/network/LANDiscovery.cc	(revision 7163)
+++ code/trunk/src/libraries/network/LANDiscovery.cc	(revision 7163)
@@ -0,0 +1,113 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   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
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "LANDiscovery.h"
+
+#include <enet/enet.h>
+#include <cstring>
+
+#include "core/CoreIncludes.h"
+#include "core/ScopedSingletonManager.h"
+
+
+namespace orxonox
+{ 
+  ManageScopedSingleton(LANDiscovery, ScopeID::Root, true);
+  
+  LANDiscovery::LANDiscovery()
+  {
+    this->host_ = enet_host_create(NULL, 10, 0, 0 );
+  }
+
+  LANDiscovery::~LANDiscovery()
+  {
+    enet_host_destroy(this->host_);
+  }
+  
+  void LANDiscovery::discover()
+  {
+    this->servers_.clear();
+    ENetAddress address;
+    enet_address_set_host(&address, "255.255.255.255");
+    address.port = LAN_DISCOVERY_PORT;
+    
+    ENetPeer* peer;
+    peer = enet_host_connect(this->host_, &address, 0);
+    
+    ENetEvent event;
+    while( enet_host_service(this->host_, &event, 1000 ) )
+    {
+      switch( event.type )
+      {
+        case ENET_EVENT_TYPE_CONNECT:
+        {
+          COUT(0) << "connect from server: " << event.peer->address.host << endl;
+          ENetPacket* packet = enet_packet_create(LAN_DISCOVERY_MESSAGE, strlen(LAN_DISCOVERY_MESSAGE)+1, ENET_PACKET_FLAG_RELIABLE);
+          enet_peer_send(event.peer, 0, packet);
+          break;
+        }
+        case ENET_EVENT_TYPE_RECEIVE:
+          {
+            packet::ServerInformation info(&event);
+            COUT(0) << "received server information; name: " << info.getServerName() << ", IP: " << info.getServerIP() << ", RTT: " << info.getServerRTT() << endl;
+            std::vector<packet::ServerInformation>::iterator it;
+            for( it=this->servers_.begin(); it!=this->servers_.end(); ++it )
+            {
+              if( (*it).getServerIP() == info.getServerIP() )
+                break;
+            }
+            if( it==this->servers_.end() )
+              this->servers_.push_back(info);
+          }
+//           enet_address_get_host_ip(&event.peer->address, buffer, buflen );
+//           serverIPs.push_back(std::string(buffer));
+          break;
+        default:
+          break;
+      }
+    }
+  }
+  
+  std::string LANDiscovery::getServerListItemName(unsigned int index)
+  {
+    if( index >= this->servers_.size() )
+      return BLANKSTRING;
+    else
+      return this->servers_[index].getServerName();
+  }
+  
+  std::string LANDiscovery::getServerListItemIP(unsigned int index)
+  {
+    if( index >= this->servers_.size() )
+      return BLANKSTRING;
+    else
+      return this->servers_[index].getServerIP();
+  }
+  
+  
+} // namespace orxonox
Index: code/trunk/src/libraries/network/LANDiscovery.h
===================================================================
--- code/trunk/src/libraries/network/LANDiscovery.h	(revision 7163)
+++ code/trunk/src/libraries/network/LANDiscovery.h	(revision 7163)
@@ -0,0 +1,63 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   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
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef LANDISCOVERY_H
+#define LANDISCOVERY_H
+
+#include "NetworkPrereqs.h"
+#include "packet/ServerInformation.h"
+#include "util/Singleton.h"
+
+#include <vector>
+
+// tolua_begin
+namespace orxonox
+{
+
+  class _NetworkExport LANDiscovery
+// tolua_end
+    : public Singleton<LANDiscovery>
+  { // tolua_export
+    friend class Singleton<LANDiscovery>;
+    public:
+      LANDiscovery();
+      ~LANDiscovery();
+      void discover(); // tolua_export
+      std::string getServerListItemName( unsigned int index ); // tolua_export
+      std::string getServerListItemIP( unsigned int index ); // tolua_export
+      static LANDiscovery& getInstance(){ return Singleton<LANDiscovery>::getInstance(); } // tolua_export
+      
+    private:
+      static LANDiscovery* singletonPtr_s;
+      ENetHost* host_;
+      std::vector<packet::ServerInformation> servers_;
+  }; // tolua_export
+
+} // tolua_export
+
+#endif // LANDISCOVERY_H
Index: code/trunk/src/libraries/network/NetworkPrereqs.h
===================================================================
--- code/trunk/src/libraries/network/NetworkPrereqs.h	(revision 6746)
+++ code/trunk/src/libraries/network/NetworkPrereqs.h	(revision 7163)
@@ -64,6 +64,9 @@
 namespace orxonox
 {
-  static const unsigned int GAMESTATEID_INITIAL = static_cast<unsigned int>(-1);
-  static const unsigned int CLIENTID_UNKNOWN    = static_cast<unsigned int>(-2);
+  static const unsigned int GAMESTATEID_INITIAL     = static_cast<unsigned int>(-1);
+  static const unsigned int CLIENTID_UNKNOWN        = static_cast<unsigned int>(-2);
+  extern const char* LAN_DISCOVERY_MESSAGE;
+  extern const char* LAN_DISCOVERY_ACK;
+  static const unsigned int LAN_DISCOVERY_PORT      = 55557;
 }
 
Index: code/trunk/src/libraries/network/Server.cc
===================================================================
--- code/trunk/src/libraries/network/Server.cc	(revision 6746)
+++ code/trunk/src/libraries/network/Server.cc	(revision 7163)
@@ -69,9 +69,11 @@
   *
   */
-  Server::Server() {
+  Server::Server()
+  {
     this->timeSinceLastUpdate_=0;
   }
 
-  Server::Server(int port){
+  Server::Server(int port)
+  {
     this->setPort( port );
     this->timeSinceLastUpdate_=0;
@@ -83,5 +85,6 @@
   * @param bindAddress Address to listen on
   */
-  Server::Server(int port, const std::string& bindAddress) {
+  Server::Server(int port, const std::string& bindAddress)
+  {
     this->setPort( port );
     this->setBindAddress( bindAddress );
@@ -92,5 +95,6 @@
   * @brief Destructor
   */
-  Server::~Server(){
+  Server::~Server()
+  {
   }
 
@@ -98,7 +102,10 @@
   * This function opens the server by creating the listener thread
   */
-  void Server::open() {
+  void Server::open()
+  {
+    Host::setActive(true);
     COUT(4) << "opening server" << endl;
     this->openListener();
+    LANDiscoverable::setActivity(true);
     return;
   }
@@ -107,12 +114,16 @@
   * This function closes the server
   */
-  void Server::close() {
+  void Server::close()
+  {
+    Host::setActive(false);
     COUT(4) << "closing server" << endl;
     this->disconnectClients();
     this->closeListener();
+    LANDiscoverable::setActivity(false);
     return;
   }
 
-  bool Server::processChat(const std::string& message, unsigned int playerID){
+  bool Server::processChat(const std::string& message, unsigned int playerID)
+  {
     ClientInformation *temp = ClientInformation::getBegin();
     packet::Chat *chat;
@@ -134,7 +145,10 @@
   * @param time time since last tick
   */
-  void Server::update(const Clock& time) {
+  void Server::update(const Clock& time)
+  {
     // receive incoming packets
     Connection::processQueue();
+    // receive and process incoming discovery packets
+    LANDiscoverable::update();
 
     if ( ClientInformation::hasClients() )
@@ -157,5 +171,6 @@
   }
 
-  bool Server::queuePacket(ENetPacket *packet, int clientID){
+  bool Server::queuePacket(ENetPacket *packet, int clientID)
+  {
     return ServerConnection::addPacket(packet, clientID);
   }
@@ -164,5 +179,6 @@
    * @brief: returns ping time to client in milliseconds
    */
-  unsigned int Server::getRTT(unsigned int clientID){
+  unsigned int Server::getRTT(unsigned int clientID)
+  {
     assert(ClientInformation::findClient(clientID));
     return ClientInformation::findClient(clientID)->getRTT();
@@ -178,5 +194,6 @@
    * @brief: return packet loss ratio to client (scales from 0 to 1)
    */
-  double Server::getPacketLoss(unsigned int clientID){
+  double Server::getPacketLoss(unsigned int clientID)
+  {
     assert(ClientInformation::findClient(clientID));
     return ClientInformation::findClient(clientID)->getPacketLoss();
@@ -186,5 +203,6 @@
   * takes a new snapshot of the gamestate and sends it to the clients
   */
-  void Server::updateGamestate() {
+  void Server::updateGamestate()
+  {
     if( ClientInformation::getBegin()==NULL )
       //no client connected
@@ -208,5 +226,6 @@
   * sends the gamestate
   */
-  bool Server::sendGameState() {
+  bool Server::sendGameState()
+  {
 //     COUT(5) << "Server: starting function sendGameState" << std::endl;
 //     ClientInformation *temp = ClientInformation::getBegin();
@@ -244,5 +263,6 @@
   }
 
-  bool Server::sendObjectDeletes(){
+  bool Server::sendObjectDeletes()
+  {
     ClientInformation *temp = ClientInformation::getBegin();
     if( temp == NULL )
@@ -257,5 +277,6 @@
 //     COUT(3) << "sending DeleteObjects" << std::endl;
     while(temp != NULL){
-      if( !(temp->getSynched()) ){
+      if( !(temp->getSynched()) )
+      {
         COUT(5) << "Server: not sending gamestate" << std::endl;
         temp=temp->next();
@@ -276,10 +297,12 @@
 
 
-  void Server::addPeer(ENetEvent *event){
+  void Server::addPeer(ENetEvent *event)
+  {
     static unsigned int newid=1;
 
     COUT(2) << "Server: adding client" << std::endl;
     ClientInformation *temp = ClientInformation::insertBack(new ClientInformation);
-    if(!temp){
+    if(!temp)
+    {
       COUT(2) << "Server: could not add client" << std::endl;
     }
@@ -310,7 +333,9 @@
   }
 
-  bool Server::createClient(int clientID){
+  bool Server::createClient(int clientID)
+  {
     ClientInformation *temp = ClientInformation::findClient(clientID);
-    if(!temp){
+    if(!temp)
+    {
       COUT(2) << "Conn.Man. could not create client with id: " << clientID << std::endl;
       return false;
@@ -345,5 +370,6 @@
   }
 
-  void Server::disconnectClient( ClientInformation *client ){
+  void Server::disconnectClient( ClientInformation *client )
+  {
     ServerConnection::disconnectClient( client );
     GamestateManager::removeClient(client);
@@ -352,16 +378,20 @@
   }
 
-  bool Server::chat(const std::string& message){
+  bool Server::chat(const std::string& message)
+  {
       return this->sendChat(message, Host::getPlayerID());
   }
 
-  bool Server::broadcast(const std::string& message){
+  bool Server::broadcast(const std::string& message)
+  {
       return this->sendChat(message, CLIENTID_UNKNOWN);
   }
 
-  bool Server::sendChat(const std::string& message, unsigned int clientID){
+  bool Server::sendChat(const std::string& message, unsigned int clientID)
+  {
     ClientInformation *temp = ClientInformation::getBegin();
     packet::Chat *chat;
-    while(temp){
+    while(temp)
+    {
       chat = new packet::Chat(message, clientID);
       chat->setClientID(temp->getID());
@@ -377,5 +407,6 @@
   }
 
-  void Server::syncClassid(unsigned int clientID) {
+  void Server::syncClassid(unsigned int clientID)
+  {
     int failures=0;
     packet::ClassID *classid = new packet::ClassID();
Index: code/trunk/src/libraries/network/Server.h
===================================================================
--- code/trunk/src/libraries/network/Server.h	(revision 6746)
+++ code/trunk/src/libraries/network/Server.h	(revision 7163)
@@ -37,4 +37,5 @@
 #include "GamestateManager.h"
 #include "ServerConnection.h"
+#include "LANDiscoverable.h"
 
 namespace orxonox
@@ -45,5 +46,5 @@
   * It implements all functions necessary for a Server
   */
-  class _NetworkExport Server : public Host, public ServerConnection, public GamestateManager{
+  class _NetworkExport Server : public Host, public ServerConnection, public GamestateManager, public LANDiscoverable{
   public:
     Server();
Index: code/trunk/src/libraries/network/ServerConnection.cc
===================================================================
--- code/trunk/src/libraries/network/ServerConnection.cc	(revision 6746)
+++ code/trunk/src/libraries/network/ServerConnection.cc	(revision 7163)
@@ -94,7 +94,7 @@
 
   bool ServerConnection::addPacketAll(ENetPacket *packet) {
-    if ( !Connection::getInstance() )
-      return false;
-    enet_host_broadcast( Connection::getInstance()->getHost(), 0, packet);
+//     if ( !Connection::getInstance() )
+//       return false;
+    enet_host_broadcast( Connection::getHost(), 0, packet);
     return true;
   }
Index: code/trunk/src/libraries/network/ServerConnection.h
===================================================================
--- code/trunk/src/libraries/network/ServerConnection.h	(revision 6746)
+++ code/trunk/src/libraries/network/ServerConnection.h	(revision 7163)
@@ -56,6 +56,6 @@
     bool openListener();
     bool closeListener();
-    static bool addPacket(ENetPacket *packet, unsigned int ID);
-    static bool addPacketAll(ENetPacket *packet);
+    bool addPacket(ENetPacket *packet, unsigned int ID);
+    bool addPacketAll(ENetPacket *packet);
     virtual void disconnectClient(ClientInformation *client);
     void disconnectClient(int clientID);
Index: code/trunk/src/libraries/network/packet/CMakeLists.txt
===================================================================
--- code/trunk/src/libraries/network/packet/CMakeLists.txt	(revision 6746)
+++ code/trunk/src/libraries/network/packet/CMakeLists.txt	(revision 7163)
@@ -11,4 +11,5 @@
   Welcome.cc
 COMPILATION_END
+  ServerInformation.cc
 )
 
@@ -23,4 +24,5 @@
   Gamestate.h
   Packet.h
+  ServerInformation.h
   Welcome.h
 )
Index: code/trunk/src/libraries/network/packet/Chat.cc
===================================================================
--- code/trunk/src/libraries/network/packet/Chat.cc	(revision 6746)
+++ code/trunk/src/libraries/network/packet/Chat.cc	(revision 7163)
@@ -37,4 +37,6 @@
 
 #define   PACKET_FLAGS_CHAT PacketFlag::Reliable
+
+/* Some lengths */
 #define   _PACKETID         0
 const int _PLAYERID     =   _PACKETID + sizeof(Type::Value);
@@ -45,10 +47,20 @@
  : Packet()
 {
+  /* Add chat flag to packet flags */
   flags_ = flags_ | PACKET_FLAGS_CHAT;
+
+  /* set message length to length of input string + 1 */
   messageLength_ = message.length()+1;
+
+  /* allocate memory for the data */
   data_=new unsigned char[ getSize() ];
+
   *(Type::Value *)(data_ + _PACKETID ) = Type::Chat;
   *(unsigned int *)(data_ + _PLAYERID ) = playerID;
   *(unsigned int *)(data_ + _MESSAGELENGTH ) = messageLength_;
+
+  /* cast the hell out of the message string, and copy it into the
+   * data buffer.
+   */
   memcpy( data_+_MESSAGE, static_cast<void*>(const_cast<char*>(message.c_str())), messageLength_ );
 }
Index: code/trunk/src/libraries/network/packet/Chat.h
===================================================================
--- code/trunk/src/libraries/network/packet/Chat.h	(revision 6746)
+++ code/trunk/src/libraries/network/packet/Chat.h	(revision 7163)
@@ -41,15 +41,29 @@
 {
 public:
+  /* constructors */
   Chat( const std::string& message, unsigned int playerID );
   Chat( uint8_t* data, unsigned int clientID );
+
+  /* destructor */
   ~Chat();
 
+  /* get size of packet */
   inline unsigned int getSize() const;
+
+  /* process chat message packet and remove it afterwards */
   bool process();
 
+  /* Get the length of the message (not the full size of the packet) */
   unsigned int getMessageLength(){ return messageLength_; };
+
+  /* return message content */
   unsigned char *getMessage();
+
 private:
+
+  /* Message length */
   uint32_t messageLength_;
+
+  /* Client ID (an integral value for identification) */
   unsigned int clientID_;
 };
Index: code/trunk/src/libraries/network/packet/ClassID.cc
===================================================================
--- code/trunk/src/libraries/network/packet/ClassID.cc	(revision 6746)
+++ code/trunk/src/libraries/network/packet/ClassID.cc	(revision 7163)
@@ -65,5 +65,5 @@
     tempQueue.push( std::pair<unsigned int, std::string>(network_id, classname) );
     ++nrOfClasses;
-    packetSize += (classname.size()+1)+sizeof(uint32_t)+sizeof(uint32_t);
+    packetSize += (classname.size()+1)+sizeof(network_id)+sizeof(uint32_t);
   }
 
@@ -80,4 +80,5 @@
   // now save all classids and classnames
   std::pair<uint32_t, std::string> tempPair;
+  uint32_t tempsize = 2*sizeof(uint32_t); // packetid and nrOfClasses
   while( !tempQueue.empty() ){
     tempPair = tempQueue.front();
@@ -87,5 +88,7 @@
     memcpy(temp+2*sizeof(uint32_t), tempPair.second.c_str(), tempPair.second.size()+1);
     temp+=2*sizeof(uint32_t)+tempPair.second.size()+1;
+    tempsize+=2*sizeof(uint32_t)+tempPair.second.size()+1;
   }
+  assert(tempsize==packetSize);
 
   COUT(5) << "classid packetSize is " << packetSize << endl;
@@ -111,4 +114,5 @@
   for(unsigned int i=0; i<nrOfClasses; i++){
     totalsize += 2*sizeof(uint32_t) + *(uint32_t*)(temp + sizeof(uint32_t));
+    temp += 2*sizeof(uint32_t) + *(uint32_t*)(temp + sizeof(uint32_t));
   }
   return totalsize;
@@ -141,5 +145,5 @@
     COUT(3) << "processing classid: " << networkID << " name: " << classname << " id: " << id << std::endl;
     if(id==NULL){
-      COUT(0) << "Recieved a bad classname" << endl;
+      COUT(0) << "Received a bad classname" << endl;
       abort();
     }
Index: code/trunk/src/libraries/network/packet/Gamestate.cc
===================================================================
--- code/trunk/src/libraries/network/packet/Gamestate.cc	(revision 6746)
+++ code/trunk/src/libraries/network/packet/Gamestate.cc	(revision 7163)
@@ -45,13 +45,32 @@
 #define PACKET_FLAG_GAMESTATE  PacketFlag::Reliable
 
-
-Gamestate::Gamestate()
+inline bool memzero( uint8_t* data, uint32_t datalength)
+{
+  uint64_t* d = (uint64_t*)data;
+
+  for( unsigned int i=0; i<datalength/8; i++ )
+  {
+    if( *(d+i) != 0 )
+      return false;
+  }
+  // now process the rest (when datalength isn't a multiple of 4)
+  for( unsigned int j = 8*(datalength/8); j<datalength; j++ )
+  {
+    if( *(data+j) != 0 )
+      return false;
+  }
+  return true;
+}
+
+
+Gamestate::Gamestate():
+  header_(0)
 {
   flags_ = flags_ | PACKET_FLAG_GAMESTATE;
-  header_ = 0;
-}
+}
+
 
 Gamestate::Gamestate(uint8_t *data, unsigned int clientID):
-    Packet(data, clientID)
+  Packet(data, clientID)
 {
   flags_ = flags_ | PACKET_FLAG_GAMESTATE;
@@ -59,16 +78,19 @@
 }
 
+
 Gamestate::Gamestate(uint8_t *data)
 {
   flags_ = flags_ | PACKET_FLAG_GAMESTATE;
-  data_=data;
+  data_ = data;
   header_ = new GamestateHeader(data_);
 }
 
+
 Gamestate::Gamestate(const Gamestate& g) :
-    Packet( *(Packet*)&g )
+    Packet( *(Packet*)&g ), nrOfVariables_(0)
 {
   flags_ = flags_ | PACKET_FLAG_GAMESTATE;
   header_ = new GamestateHeader(data_);
+  sizes_ = g.sizes_;
 }
 
@@ -79,4 +101,5 @@
     delete header_;
 }
+
 
 bool Gamestate::collectData(int id, uint8_t mode)
@@ -91,5 +114,6 @@
     return false;
   data_ = new uint8_t[size + GamestateHeader::getSize()];
-  if(!data_){
+  if(!data_)
+  {
     COUT(2) << "GameStateManager: could not allocate memory" << std::endl;
     return false;
@@ -101,17 +125,19 @@
 
   //start collect data synchronisable by synchronisable
-  uint8_t *mem=data_;
+  uint8_t *mem = data_; // in this stream store all data of the variables and the headers of the synchronisable
   mem += GamestateHeader::getSize();
   ObjectList<Synchronisable>::iterator it;
-  for(it = ObjectList<Synchronisable>::begin(); it; ++it){
+  for(it = ObjectList<Synchronisable>::begin(); it; ++it)
+  {
 
 //     tempsize=it->getSize(id, mode);
 
-    tempsize = it->getData(mem, id, mode);
+    tempsize = it->getData(mem, this->sizes_, id, mode);
     if ( tempsize != 0 )
       dataVector_.push_back( obj(it->getObjectID(), it->getCreatorID(), tempsize, mem-data_) );
 
 #ifndef NDEBUG
-    if(currentsize+tempsize > size){
+    if(currentsize+tempsize > size)
+    {
       assert(0); // if we don't use multithreading this part shouldn't be neccessary
       // start allocate additional memory
@@ -148,4 +174,5 @@
 }
 
+
 bool Gamestate::spreadData(uint8_t mode)
 {
@@ -153,10 +180,10 @@
   assert(data_);
   assert(!header_->isCompressed());
-  assert(!header_->isDiffed());
   uint8_t *mem=data_+GamestateHeader::getSize();
   Synchronisable *s;
 
   // update the data of the objects we received
-  while(mem < data_+GamestateHeader::getSize()+header_->getDataSize()){
+  while(mem < data_+GamestateHeader::getSize()+header_->getDataSize())
+  {
     SynchronisableHeader objectheader(mem);
 
@@ -170,5 +197,5 @@
       else
       {
-        mem += objectheader.getDataSize();
+        mem += objectheader.getDataSize() + ( objectheader.isDiffed() ? SynchronisableHeaderLight::getSize() : SynchronisableHeader::getSize() );
       }
     }
@@ -181,10 +208,14 @@
    // In debug mode, check first, whether there are no duplicate objectIDs
 #ifndef NDEBUG
-  if(this->getID()%1000==0){
+  if(this->getID()%1000==1)
+  {
     std::list<uint32_t> v1;
     ObjectList<Synchronisable>::iterator it;
-    for (it = ObjectList<Synchronisable>::begin(); it != ObjectList<Synchronisable>::end(); ++it) {
-      if (it->getObjectID() == OBJECTID_UNKNOWN) {
-        if (it->objectMode_ != 0x0) {
+    for (it = ObjectList<Synchronisable>::begin(); it != ObjectList<Synchronisable>::end(); ++it)
+    {
+      if (it->getObjectID() == OBJECTID_UNKNOWN)
+      {
+        if (it->objectMode_ != 0x0)
+        {
           COUT(0) << "Found object with OBJECTID_UNKNOWN on the client with objectMode != 0x0!" << std::endl;
           COUT(0) << "Possible reason for this error: Client created a synchronized object without the Server's approval." << std::endl;
@@ -193,8 +224,11 @@
         }
       }
-      else {
+      else
+      {
         std::list<uint32_t>::iterator it2;
-        for (it2 = v1.begin(); it2 != v1.end(); ++it2) {
-          if (it->getObjectID() == *it2) {
+        for (it2 = v1.begin(); it2 != v1.end(); ++it2)
+        {
+          if (it->getObjectID() == *it2)
+          {
             COUT(0) << "Found duplicate objectIDs on the client!" << std::endl
                     << "Are you sure you don't create a Sychnronisable objcect with 'new' \
@@ -211,4 +245,5 @@
 }
 
+
 uint32_t Gamestate::getSize() const
 {
@@ -222,5 +257,7 @@
 }
 
-bool Gamestate::operator==(packet::Gamestate gs){
+
+bool Gamestate::operator==(packet::Gamestate gs)
+{
   uint8_t *d1 = data_+GamestateHeader::getSize();
   uint8_t *d2 = gs.data_+GamestateHeader::getSize();
@@ -233,9 +270,9 @@
 }
 
+
 bool Gamestate::process()
 {
   return GamestateHandler::addGamestate(this, getClientID());
 }
-
 
 
@@ -253,5 +290,6 @@
   int retval;
   retval = compress( dest, &buffer, source, (uLong)(header_->getDataSize()) );
-  switch ( retval ) {
+  switch ( retval )
+  {
     case Z_OK: COUT(5) << "G.St.Man: compress: successfully compressed" << std::endl; break;
     case Z_MEM_ERROR: COUT(1) << "G.St.Man: compress: not enough memory available in gamestate.compress" << std::endl; return false;
@@ -270,7 +308,9 @@
   header_->setCompSize( buffer );
   header_->setCompressed( true );
-  COUT(5) << "gamestate compress datasize: " << header_->getDataSize() << " compsize: " << header_->getCompSize() << std::endl;
+  COUT(0) << "gamestate compress datasize: " << header_->getDataSize() << " compsize: " << header_->getCompSize() << std::endl;
   return true;
 }
+
+
 bool Gamestate::decompressData()
 {
@@ -289,5 +329,6 @@
   uLongf length=bufsize;
   retval = uncompress( dest, &length, source, (uLong)compsize );
-  switch ( retval ) {
+  switch ( retval )
+  {
     case Z_OK: COUT(5) << "successfully decompressed" << std::endl; break;
     case Z_MEM_ERROR: COUT(1) << "not enough memory available" << std::endl; return false;
@@ -301,10 +342,12 @@
   delete temp;
 
-  if (this->bDataENetAllocated_){
+  if (this->bDataENetAllocated_)
+  {
     // Memory was allocated by ENet. --> We let it be since enet_packet_destroy will
     // deallocated it anyway. So data and packet stay together.
     this->bDataENetAllocated_ = false;
   }
-  else{
+  else
+  {
     // We allocated the memory in the first place (unlikely). So we destroy the old data
     // and overwrite it with the new decompressed data.
@@ -320,42 +363,221 @@
 }
 
-/*Gamestate *Gamestate::diff(Gamestate *base)
-{
-  assert(data_);
-  assert(!header_->isCompressed());
+
+Gamestate* Gamestate::diffVariables(Gamestate *base)
+{
+  assert(this && base); assert(data_ && base->data_);
+  assert(!header_->isCompressed() && !base->header_->isCompressed());
   assert(!header_->isDiffed());
-  GamestateHeader diffHeader(base->data_);
-  uint8_t *basep = GAMESTATE_START(base->data_), *gs = GAMESTATE_START(this->data_);
-  uint32_t of=0; // pointers offset
-  uint32_t dest_length=0;
-  dest_length=header_->getDataSize();
-  if(dest_length==0)
-    return NULL;
-  uint8_t *ndata = new uint8_t[dest_length*sizeof(uint8_t)+GamestateHeader::getSize()];
-  uint8_t *dest = ndata + GamestateHeader::getSize();
-  while(of < diffHeader.getDataSize() && of < header_->getDataSize()){
-    *(dest+of)=*(basep+of)^*(gs+of); // do the xor
-    ++of;
-  }
-  if(diffHeader.getDataSize()!=header_->getDataSize()){
-    uint8_t n=0;
-    if(diffHeader.getDataSize() < header_->getDataSize()){
-      while(of<dest_length){
-        *(dest+of)=n^*(gs+of);
-        of++;
-      }
-    }
-  }
-
-  Gamestate *g = new Gamestate(ndata, getClientID());
+
+
+  // *** first do a raw diff of the two gamestates
+
+  uint8_t *baseData = GAMESTATE_START(base->data_);
+  uint8_t *origData = GAMESTATE_START(this->data_);
+  uint32_t origLength = header_->getDataSize();
+  uint32_t baseLength = base->header_->getDataSize();
+
+  assert( origLength && baseLength );
+
+  uint8_t *nData = new uint8_t[origLength + GamestateHeader::getSize() + sizeof(uint32_t)*this->nrOfVariables_]; // this is the maximum size needed in the worst case
+  uint8_t *dest = GAMESTATE_START(nData);
+
+  uint32_t baseOffset = 0; //offset in the diffed stream
+  uint32_t origOffset = 0; //offset in the new stream with removed 0's
+  std::vector<uint32_t>::iterator sizes = this->sizes_.begin();
+
+  while( origOffset < origLength )
+  {
+    //iterate through all objects
+
+    SynchronisableHeader h(origData+origOffset);
+
+    // Find (if possible) the current object in the datastream of the old gamestate
+    // Start at the current offset position
+    if(baseOffset >= baseLength)
+      baseOffset = 0;
+    uint8_t* temp = baseData + baseOffset;
+    uint32_t objectID = h.getObjectID();
+    assert(temp < baseData+baseLength);
+    assert(dest < nData + origLength + GamestateHeader::getSize() + sizeof(uint32_t)*this->nrOfVariables_);
+    assert(sizes != this->sizes_.end());
+    while ( temp < baseData+baseLength )
+    {
+      SynchronisableHeader htemp(temp);
+      assert( htemp.getDataSize()!=0 );
+      if ( htemp.getObjectID() == objectID )
+      {
+        assert( h.getClassID() == htemp.getClassID() );
+        goto DODIFF;
+      }
+//       {
+//         SynchronisableHeader htemp2(temp+htemp.getDataSize()+SynchronisableHeader::getSize());
+//         if( temp+htemp.getDataSize()+SynchronisableHeader::getSize() < baseData+baseLength )
+//         {
+//           assert(htemp2.getClassID()<500);
+//           assert(htemp2.getDataSize()!=0 && htemp2.getDataSize()<1000);
+//           assert(htemp2.isDiffed()==false);
+//         }
+//       }
+      temp += htemp.getDataSize()+SynchronisableHeader::getSize();
+        
+    }
+    // If not found start looking at the beginning
+    assert( temp==baseData+baseLength );
+    temp = baseData;
+//     {
+//       SynchronisableHeader htemp2(temp);
+//       if( temp < baseData+baseLength )
+//       {
+//         assert(htemp2.getClassID()<500);
+//         assert(htemp2.getDataSize()!=0 && htemp2.getDataSize()<1000);
+//         assert(htemp2.isDiffed()==false);
+//       }
+//     }
+    while ( temp < baseData+baseOffset )
+    {
+      SynchronisableHeader htemp(temp);
+      if ( htemp.getObjectID() == objectID )
+      {
+        assert( h.getClassID() == htemp.getClassID() );
+        goto DODIFF;
+      }
+//       {
+//         SynchronisableHeader htemp2(temp+htemp.getDataSize()+SynchronisableHeader::getSize());
+//         if( temp+htemp.getDataSize()+SynchronisableHeader::getSize() < baseData+baseLength )
+//         {
+//           assert(htemp2.getClassID()<500);
+//           assert(htemp2.getDataSize()!=0 && htemp2.getDataSize()<1000);
+//           assert(htemp2.isDiffed()==false);
+//         }
+//       }
+      temp += htemp.getDataSize()+SynchronisableHeader::getSize();
+    }
+    // Object is new, thus never transmitted -> just copy over
+    goto DOCOPY;
+
+
+DODIFF:
+    {
+//       COUT(4) << "dodiff" << endl;
+//       if(baseOffset==0)
+//       {
+//         assert(origOffset==0);
+//       }
+      uint32_t objectOffset = SynchronisableHeader::getSize(); // offset inside the object in the origData and baseData
+      // Check whether the whole object stayed the same
+      if( memcmp( origData+origOffset+objectOffset, temp+objectOffset, h.getDataSize()) == 0 )
+      {
+//         COUT(4) << "skip object" << Synchronisable::getSynchronisable(h.getObjectID())->getIdentifier()->getName() << endl;
+        origOffset += objectOffset+ h.getDataSize(); // skip the whole object
+        baseOffset = temp + h.getDataSize()+SynchronisableHeader::getSize() - baseData;
+        sizes += Synchronisable::getSynchronisable(h.getObjectID())->getNrOfVariables();
+      }
+      else
+      {
+//         if( Synchronisable::getSynchronisable(h.getObjectID())->getIdentifier()->getName() == "Bot" )
+//           COUT(0) << "blub" << endl;
+//         COUT(4) << "object diff: " << Synchronisable::getSynchronisable(h.getObjectID())->getIdentifier()->getName() << endl;
+//         COUT(4) << "diff " << h.getObjectID() << ":";
+        // Now start to diff the Object
+        SynchronisableHeaderLight h2(dest);
+        h2 = h; // copy over the objectheader
+        VariableID variableID = 0;
+        uint32_t newObjectOffset = SynchronisableHeaderLight::getSize();
+        // iterate through all variables
+        while( objectOffset < h.getDataSize()+SynchronisableHeader::getSize() )
+        {
+          // check whether variable changed and write id and copy over variable to the new stream
+          // otherwise skip variable
+          assert(sizes != this->sizes_.end());
+          uint32_t varSize = *sizes;
+          assert( varSize == Synchronisable::getSynchronisable(h.getObjectID())->getVarSize(variableID) );
+          if ( varSize != 0 )
+          {
+            if ( memcmp(origData+origOffset+objectOffset, temp+objectOffset, varSize) != 0 )
+            {
+//               COUT(4) << "copy variable" << endl;
+              *(VariableID*)(dest+newObjectOffset) = variableID; // copy over the variableID
+              newObjectOffset += sizeof(VariableID);
+              memcpy( dest+newObjectOffset, origData+origOffset+objectOffset, varSize );
+              newObjectOffset += varSize;
+              objectOffset += varSize;
+            }
+            else
+            {
+//               COUT(4) << "skip variable" << endl;
+              objectOffset += varSize;
+            }
+          }
+//           else
+//             COUT(4) << "varsize 0" << endl;
+
+          ++variableID;
+          ++sizes;
+        }
+        
+        if( Synchronisable::getSynchronisable(h.getObjectID())->getNrOfVariables() != variableID )
+          sizes += Synchronisable::getSynchronisable(h.getObjectID())->getNrOfVariables() - variableID;
+//         COUT(4) << endl;
+        h2.setDiffed(true);
+        h2.setDataSize(newObjectOffset-SynchronisableHeaderLight::getSize());
+        assert(objectOffset == h.getDataSize()+SynchronisableHeader::getSize());
+        origOffset += objectOffset;
+//         baseOffset += temp + h.getDataSize()+SynchronisableHeader::getSize() - baseData;
+        //baseOffset += objectOffset;
+//         SynchronisableHeader htemp(temp);
+//         baseOffset += SynchronisableHeader::getSize() + htemp.getDataSize();
+//         {
+//           SynchronisableHeader htemp2( baseData+(temp-baseData+objectOffset) );
+//           if( baseData+(temp-baseData+objectOffset) < baseData+baseLength )
+//           {
+//             assert(htemp2.getClassID()<500);
+//             assert(htemp2.getDataSize()!=0 && htemp2.getDataSize()<1000);
+//             assert(htemp2.isDiffed()==false);
+//           }
+//         }
+        baseOffset = temp-baseData + objectOffset;
+        dest += newObjectOffset;
+      }
+
+      continue;
+    }
+
+DOCOPY:
+    {
+//       COUT(4) << "docopy" << endl;
+      // Just copy over the whole Object
+      memcpy( dest, origData+origOffset, h.getDataSize()+SynchronisableHeader::getSize() );
+      dest += h.getDataSize()+SynchronisableHeader::getSize();
+      origOffset += h.getDataSize()+SynchronisableHeader::getSize();
+      assert( Synchronisable::getSynchronisable(h.getObjectID()) );
+//       COUT(4) << "copy " << h.getObjectID() << endl;
+//       COUT(4) << "copy " << h.getObjectID() << ":";
+      //sizes += Synchronisable::getSynchronisable(h.getObjectID())->getNrOfVariables();
+      for( unsigned int i = 0; i < Synchronisable::getSynchronisable(h.getObjectID())->getNrOfVariables(); ++i )
+      {
+//         COUT(4) << " " << *sizes;
+        ++sizes;
+      }
+//       COUT(4) << endl;
+      assert(sizes != this->sizes_.end() || origOffset>=origLength);
+      continue;
+    }
+  }
+
+
+  Gamestate *g = new Gamestate(nData, getClientID());
+  assert(g->header_);
   *(g->header_) = *header_;
-  g->header_->setDiffed( true );
   g->header_->setBaseID( base->getID() );
+  g->header_->setDataSize(dest - nData - GamestateHeader::getSize());
   g->flags_=flags_;
   g->packetDirection_ = packetDirection_;
+  assert(!g->isCompressed());
   return g;
-}*/
-
-Gamestate *Gamestate::diff(Gamestate *base)
+}
+
+
+Gamestate* Gamestate::diffData(Gamestate *base)
 {
   assert(this && base); assert(data_ && base->data_);
@@ -393,5 +615,6 @@
 }
 
-Gamestate *Gamestate::undiff(Gamestate *base)
+
+Gamestate* Gamestate::undiff(Gamestate *base)
 {
   assert(this && base); assert(data_ && base->data_);
@@ -423,57 +646,4 @@
 
 
-// Gamestate *Gamestate::diff(Gamestate *base)
-// {
-//   assert(data_);
-//   assert(!header_->isCompressed());
-//   assert(!header_->isDiffed());
-//   GamestateHeader diffHeader(base->data_);
-//   uint8_t *basep = GAMESTATE_START(base->data_), *gs = GAMESTATE_START(this->data_);
-//   uint32_t of=0; // pointers offset
-//   uint32_t dest_length=0;
-//   dest_length=header_->getDataSize();
-//   if(dest_length==0)
-//     return NULL;
-//   uint8_t *ndata = new uint8_t[dest_length*sizeof(uint8_t)+GamestateHeader::getSize()];
-//   uint8_t *dest = ndata + GamestateHeader::getSize();
-//
-//
-//   // LOOP-UNROLLED DIFFING
-//   uint32_t *dest32 = (uint32_t*)dest, *base32 = (uint32_t*)basep, *gs32 = (uint32_t*)gs;
-//   // diff in 4-byte steps
-//   while( of < (uint32_t)(header_->getDataSize())/4 ){
-//     if( of < (uint32_t)(diffHeader.getDataSize())/4 )
-//     {
-//       *(dest32+of)=*(base32+of) ^ *(gs32+of); // do the xor
-//       ++of;
-//     }
-//     else
-//     {
-//       *(dest32+of)=*(gs32+of); // same as 0 ^ *(gs32+of)
-//       ++of;
-//     }
-//   }
-//   for( unsigned int of2 = 0; of2 < header_->getDataSize()%4; ++of2 )
-//   {
-//     if( of*4+of2 < diffHeader.getDataSize() )
-//     {
-//       *(dest+4*of+of2)=*(basep+4*of+of2) ^ *(gs+4*of+of2); // do the xor
-//     }
-//     else
-//     {
-//       *(dest+4*of+of2)=*(gs+4*of+of2); // same as 0 ^ *(gs32+of)
-//     }
-//   }
-//
-//   Gamestate *g = new Gamestate(ndata, getClientID());
-//   *(g->header_) = *header_;
-//   g->header_->setDiffed( true );
-//   g->header_->setBaseID( base->getID() );
-//   g->flags_=flags_;
-//   g->packetDirection_ = packetDirection_;
-//   return g;
-// }
-
-
 void Gamestate::rawDiff( uint8_t* newdata, uint8_t* data, uint8_t* basedata, uint32_t datalength, uint32_t baselength)
 {
@@ -501,4 +671,5 @@
   assert(j==datalength);
 }
+
 
 Gamestate* Gamestate::doSelection(unsigned int clientID, unsigned int targetSize){
@@ -529,23 +700,21 @@
 //   COUT(0) << "myvector contains:";
 //   for ( itt=dataVector_.begin() ; itt!=dataVector_.end(); itt++ )
-//     COUT(0) << ' ' << (*itt).objID;
+//     COUT(0) << " " << (*itt).objID;
 //   COUT(0) << endl;
   for(it=dataVector_.begin(); it!=dataVector_.end();){
     SynchronisableHeader oldobjectheader(origdata);
     SynchronisableHeader newobjectheader(newdata);
-    if ( it->objSize == 0 )
+    if ( (*it).objSize == 0 )
     {
       ++it;
       continue;
     }
-    objectsize = oldobjectheader.getDataSize();
+    objectsize = oldobjectheader.getDataSize()+SynchronisableHeader::getSize();
     objectOffset=SynchronisableHeader::getSize(); //skip the size and the availableData variables in the objectheader
-    if ( it->objID == oldobjectheader.getObjectID() ){
+    if ( (*it).objID == oldobjectheader.getObjectID() ){
       memcpy(newdata, origdata, objectsize);
-      assert(newobjectheader.isDataAvailable()==true);
       ++it;
     }else{
       newobjectheader = oldobjectheader;
-      newobjectheader.setDataAvailable(false);
       memset(newdata+objectOffset, 0, objectsize-objectOffset);
     }
@@ -559,5 +728,5 @@
   {
     SynchronisableHeader oldobjectheader(origdata);
-    objectsize = oldobjectheader.getDataSize();
+    objectsize = oldobjectheader.getDataSize()+SynchronisableHeader::getSize();
     origdata += objectsize;
     origsize += objectsize;
@@ -571,52 +740,20 @@
 
 
-/*Gamestate *Gamestate::undiff(Gamestate *base)
-{
-  assert(this && base);assert(data_);
-  assert(header_->isDiffed());
-  assert(!header_->isCompressed() && !base->header_->isCompressed());
-  uint8_t *basep = GAMESTATE_START(base->data_);
-  uint8_t *gs = GAMESTATE_START(this->data_);
-  uint32_t of=0; // pointers offset
-  uint32_t dest_length=0;
-  dest_length=header_->getDataSize();
-  if(dest_length==0)
-    return NULL;
-  uint8_t *ndata = new uint8_t[dest_length*sizeof(uint8_t)+GamestateHeader::getSize()];
-  uint8_t *dest = ndata + GamestateHeader::getSize();
-  while(of < base->header_->getDataSize() && of < header_->getDataSize()){
-    *(dest+of)=*(basep+of)^*(gs+of); // do the xor
-    ++of;
-  }
-  if(base->header_->getDataSize()!=header_->getDataSize()){
-    uint8_t n=0;
-    if(base->header_->getDataSize() < header_->getDataSize()){
-      while(of < dest_length){
-        *(dest+of)=n^*(gs+of);
-        of++;
-      }
-    }
-  }
-  Gamestate *g = new Gamestate(ndata, getClientID());
-  assert(g->header_);
-  *(g->header_) = *header_;
-  g->header_->setDiffed( false );
-  g->flags_=flags_;
-  g->packetDirection_ = packetDirection_;
-  assert(!g->isDiffed());
-  assert(!g->isCompressed());
-  return g;
-}*/
-
 uint32_t Gamestate::calcGamestateSize(int32_t id, uint8_t mode)
 {
-  uint32_t size=0;
+  uint32_t size = 0;
+  uint32_t nrOfVariables = 0;
     // get the start of the Synchronisable list
   ObjectList<Synchronisable>::iterator it;
     // get total size of gamestate
-  for(it = ObjectList<Synchronisable>::begin(); it; ++it)
+  for(it = ObjectList<Synchronisable>::begin(); it; ++it){
     size+=it->getSize(id, mode); // size of the actual data of the synchronisable
+    nrOfVariables += it->getNrOfVariables();
+  }
+//   COUT(0) << "allocating " << nrOfVariables << " ints" << endl;
+  this->sizes_.reserve(nrOfVariables);
   return size;
 }
+
 
 } //namespace packet
Index: code/trunk/src/libraries/network/packet/Gamestate.h
===================================================================
--- code/trunk/src/libraries/network/packet/Gamestate.h	(revision 6746)
+++ code/trunk/src/libraries/network/packet/Gamestate.h	(revision 7163)
@@ -36,4 +36,5 @@
 #include <cstring>
 #include <list>
+#include <vector>
 
 #include "util/CRC32.h"
@@ -113,5 +114,7 @@
     inline bool isCompressed() const { return header_->isCompressed(); }
     inline int32_t getBaseID() const { return header_->getBaseID(); }
-    Gamestate *diff(Gamestate *base);
+    inline uint32_t getDataSize() const { return header_->getDataSize(); }
+    Gamestate* diffVariables(Gamestate *base);
+    Gamestate* diffData(Gamestate *base);
     Gamestate *undiff(Gamestate *base);
     Gamestate* doSelection(unsigned int clientID, unsigned int targetSize);
@@ -123,11 +126,13 @@
   private:
     void rawDiff( uint8_t* newdata, uint8_t* data, uint8_t* basedata, uint32_t datalength, uint32_t baselength);
+    inline uint32_t findObject( const SynchronisableHeader& header, uint8_t* mem, uint32_t dataLength, uint32_t startPosition = 0 );
     virtual uint32_t getSize() const;
     virtual inline bool process();
-
-  private:
     uint32_t calcGamestateSize(int32_t id, uint8_t mode=0x0);
-    std::list<obj> dataVector_;
-    GamestateHeader* header_;
+    
+    std::list<obj>          dataVector_;
+    GamestateHeader*        header_;
+    std::vector<uint32_t>   sizes_;
+    uint32_t                nrOfVariables_;
 };
 
Index: code/trunk/src/libraries/network/packet/Packet.cc
===================================================================
--- code/trunk/src/libraries/network/packet/Packet.cc	(revision 6746)
+++ code/trunk/src/libraries/network/packet/Packet.cc	(revision 7163)
@@ -62,5 +62,6 @@
 std::map<size_t, Packet *> Packet::packetMap_;
 
-Packet::Packet(){
+Packet::Packet()
+{
   flags_ = PACKET_FLAG_DEFAULT;
   packetDirection_ = Direction::Outgoing;
@@ -71,9 +72,6 @@
 }
 
-void blub(ENetPacket *packet){
-  COUT(4) << "blubb" << std::endl;
-}
-
-Packet::Packet(uint8_t *data, unsigned int clientID){
+Packet::Packet(uint8_t *data, unsigned int clientID)
+{
   flags_ = PACKET_FLAG_DEFAULT;
   packetDirection_ = Direction::Incoming;
Index: code/trunk/src/libraries/network/packet/ServerInformation.cc
===================================================================
--- code/trunk/src/libraries/network/packet/ServerInformation.cc	(revision 7163)
+++ code/trunk/src/libraries/network/packet/ServerInformation.cc	(revision 7163)
@@ -0,0 +1,84 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   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
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ServerInformation.h"
+
+#include <enet/enet.h>
+#include <cassert>
+#include <cstring>
+
+#include "util/Serialise.h"
+
+namespace orxonox
+{
+  namespace packet
+  {
+    
+    ServerInformation::ServerInformation()
+    {
+      
+    }
+    
+    ServerInformation::ServerInformation(ENetEvent* event)
+    {
+      // Save Server Round Trip Time
+      this->serverRTT_ = event->peer->roundTripTime;
+      // Save Server IP
+      char* serverIP = new char[16];
+      enet_address_get_host_ip(&event->peer->address, serverIP, 16);
+      this->serverIP_ = std::string(serverIP);
+      // Save ACK
+      uint8_t* temp = event->packet->data;
+      char* ack = new char[strlen(LAN_DISCOVERY_ACK)+1];
+      loadAndIncrease((char*&)ack, temp);
+      assert(strcmp(ack, (const char*)LAN_DISCOVERY_ACK)==0);
+      // Save Server Name
+      loadAndIncrease(this->serverName_, temp);
+    }
+
+    ServerInformation::~ServerInformation()
+    {
+      
+    }
+
+    void ServerInformation::send(ENetPeer* peer)
+    {
+      uint32_t size = returnSize((char*&)LAN_DISCOVERY_ACK) + returnSize(this->serverName_);
+      uint8_t* temp = new uint8_t[size];
+      uint8_t* temp2 = temp;
+      saveAndIncrease((char*&)LAN_DISCOVERY_ACK, temp2);
+      saveAndIncrease(this->serverName_, temp2);
+      ENetPacket* packet = enet_packet_create( temp, size, 0 );
+      enet_peer_send(peer, 0, packet);
+      
+      delete[] temp;
+    }
+  
+  } // namespace packet
+} // namespace orxonox
+
Index: code/trunk/src/libraries/network/packet/ServerInformation.h
===================================================================
--- code/trunk/src/libraries/network/packet/ServerInformation.h	(revision 7163)
+++ code/trunk/src/libraries/network/packet/ServerInformation.h	(revision 7163)
@@ -0,0 +1,63 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   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
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "../NetworkPrereqs.h"
+
+#include <string>
+
+#ifndef SERVERINFORMATION_H
+#define SERVERINFORMATION_H
+
+namespace orxonox
+{
+  namespace packet
+  {
+
+    class ServerInformation
+    {
+      public:
+        ServerInformation();
+        ServerInformation(ENetEvent* event);
+        ~ServerInformation();
+        
+        void          send( ENetPeer* peer );
+        std::string   getServerIP() { return this->serverIP_; }
+        std::string   getServerName() { return this->serverName_; }
+        void          setServerName(std::string name) { this->serverName_ = name; }
+        uint32_t      getServerRTT() { return this->serverRTT_; }
+        
+      private:
+        std::string   serverName_;
+        std::string   serverIP_;
+        uint32_t      serverRTT_;
+    };
+
+  }
+}
+
+#endif // SERVERINFORMATION_H
Index: code/trunk/src/libraries/network/synchronisable/Serialise.h
===================================================================
--- code/trunk/src/libraries/network/synchronisable/Serialise.h	(revision 6746)
+++ code/trunk/src/libraries/network/synchronisable/Serialise.h	(revision 7163)
@@ -38,4 +38,6 @@
 #include "util/TypeTraits.h"
 #include "core/CorePrereqs.h"
+#include "core/CoreIncludes.h"
+#include "core/SmartPtr.h"
 
 namespace orxonox{
@@ -72,4 +74,74 @@
             return *(uint32_t*)(mem) == variable->getObjectID();
         else
+            return variable == variable->getSynchronisable(*(uint32_t*)(mem));
+    }
+    
+    // These functions implement loading / saving / etc. for SmartPtr<T>
+    
+    /** @brief returns the size of the objectID needed to synchronise the pointer */
+    template <class T> inline uint32_t returnSize( const SmartPtr<T>& variable )
+    {
+        return sizeof(uint32_t);
+    }
+    
+    /** @brief reads the objectID of a pointer out of the bytestream and increases the mem pointer */
+    template <class T> inline void loadAndIncrease( const SmartPtr<T>& variable, uint8_t*& mem )
+    {
+//         *const_cast<typename Loki::TypeTraits<T*>::UnqualifiedType*>(&variable) = dynamic_cast<T*>(variable->getSynchronisable( *(uint32_t*)(mem) ));
+        *const_cast<typename Loki::TypeTraits<SmartPtr<T> >::UnqualifiedType*>(&variable) = orxonox_cast<T*>(T::getSynchronisable(*(uint32_t*)(mem)));
+        mem += returnSize( variable );
+    }
+    
+    /** @brief saves the objectID of a pointer into the bytestream and increases the mem pointer */
+    template <class T> inline void saveAndIncrease( const SmartPtr<T>& variable, uint8_t*& mem )
+    {
+        if ( variable.get() )
+            *(uint32_t*)(mem) = static_cast<uint32_t>(variable->getObjectID());
+        else
+            *(uint32_t*)(mem) = OBJECTID_UNKNOWN;
+        mem += returnSize( variable );
+    }
+    
+    /** @brief checks whether the objectID of the variable is the same as in the bytestream */
+    template <class T> inline  bool checkEquality( const SmartPtr<T>& variable, uint8_t* mem )
+    {
+        if ( variable.get() )
+            return *(uint32_t*)(mem) == variable->getObjectID();
+        else
+            return *(uint32_t*)(mem) == OBJECTID_UNKNOWN;
+    }
+    
+    // These functions implement loading / saving / etc. for WeakPtr<T>
+    
+    /** @brief returns the size of the objectID needed to synchronise the pointer */
+    template <class T> inline uint32_t returnSize( const WeakPtr<T>& variable )
+    {
+        return sizeof(uint32_t);
+    }
+    
+    /** @brief reads the objectID of a pointer out of the bytestream and increases the mem pointer */
+    template <class T> inline void loadAndIncrease( const WeakPtr<T>& variable, uint8_t*& mem )
+    {
+        //         *const_cast<typename Loki::TypeTraits<T*>::UnqualifiedType*>(&variable) = dynamic_cast<T*>(variable->getSynchronisable( *(uint32_t*)(mem) ));
+        *const_cast<typename Loki::TypeTraits<SmartPtr<T> >::UnqualifiedType*>(&variable) = orxonox_cast<T*>(T::getSynchronisable(*(uint32_t*)(mem)));
+        mem += returnSize( variable );
+    }
+    
+    /** @brief saves the objectID of a pointer into the bytestream and increases the mem pointer */
+    template <class T> inline void saveAndIncrease( const WeakPtr<T>& variable, uint8_t*& mem )
+    {
+        if ( variable.get() )
+            *(uint32_t*)(mem) = static_cast<uint32_t>(variable->getObjectID());
+        else
+            *(uint32_t*)(mem) = OBJECTID_UNKNOWN;
+        mem += returnSize( variable );
+    }
+    
+    /** @brief checks whether the objectID of the variable is the same as in the bytestream */
+    template <class T> inline  bool checkEquality( const WeakPtr<T>& variable, uint8_t* mem )
+    {
+        if ( variable.get() )
+            return *(uint32_t*)(mem) == variable->getObjectID();
+        else
             return *(uint32_t*)(mem) == OBJECTID_UNKNOWN;
     }
Index: code/trunk/src/libraries/network/synchronisable/Synchronisable.cc
===================================================================
--- code/trunk/src/libraries/network/synchronisable/Synchronisable.cc	(revision 6746)
+++ code/trunk/src/libraries/network/synchronisable/Synchronisable.cc	(revision 7163)
@@ -49,9 +49,10 @@
   * Initializes all Variables and sets the right objectID_
   */
-  Synchronisable::Synchronisable(BaseObject* creator ){
+  Synchronisable::Synchronisable(BaseObject* creator )
+  {
     RegisterRootObject(Synchronisable);
     static uint32_t idCounter=0;
     objectMode_=0x1; // by default do not send data to server
-    if ( GameMode::isMaster() || ( Host::running() && Host::isServer() ) )
+    if ( GameMode::isMaster()/* || ( Host::running() && Host::isServer() )*/ )
     {
       this->setObjectID( idCounter++ );
@@ -73,19 +74,4 @@
     else
       this->creatorID_ = OBJECTID_UNKNOWN;
-
-    /*searchcreatorID:
-    if (creator)
-    {
-        Synchronisable* synchronisable_creator = orxonox_cast<Synchronisable*>(creator);
-        if (synchronisable_creator && synchronisable_creator->objectMode_)
-        {
-            this->creatorID = synchronisable_creator->getScene()->getObjectID();
-        }
-        else if (creator != creator->getCreator())
-        {
-            creator = creator->getCreator();
-            goto searchcreatorID;
-        }
-    }*/
   }
 
@@ -94,5 +80,6 @@
    * Delete all callback objects and remove objectID_ from the objectMap_
    */
-  Synchronisable::~Synchronisable(){
+  Synchronisable::~Synchronisable()
+  {
     // delete callback function objects
     if(!Identifier::isCreatingHierarchy()){
@@ -101,9 +88,9 @@
         deletedObjects_.push(objectID_);
     }
-    // delete all Synchronisable Variables from syncList ( which are also in stringList )
-    for(std::vector<SynchronisableVariableBase*>::iterator it = syncList.begin(); it!=syncList.end(); it++)
+    // delete all Synchronisable Variables from syncList_ ( which are also in stringList_ )
+    for(std::vector<SynchronisableVariableBase*>::iterator it = syncList_.begin(); it!=syncList_.end(); it++)
       delete (*it);
-    syncList.clear();
-    stringList.clear();
+    syncList_.clear();
+    stringList_.clear();
     std::map<uint32_t, Synchronisable*>::iterator it;
     it = objectMap_.find(objectID_);
@@ -118,5 +105,6 @@
    * @param b true if this object is located on a client or on a server
    */
-  void Synchronisable::setClient(bool b){
+  void Synchronisable::setClient(bool b)
+  {
     if(b) // client
       state_=0x2;
@@ -135,10 +123,5 @@
   {
     SynchronisableHeader header(mem);
-
-    if(!header.isDataAvailable())
-    {
-      mem += header.getDataSize();
-      return 0;
-    }
+    assert( !header.isDiffed() );
 
     COUT(4) << "fabricating object with id: " << header.getObjectID() << std::endl;
@@ -160,5 +143,5 @@
       if (!synchronisable_creator)
       {
-        mem += header.getDataSize(); //.TODO: this suckz.... remove size from header
+        mem += header.getDataSize()+SynchronisableHeader::getSize(); //.TODO: this suckz.... remove size from header
         assert(0); // TODO: uncomment this if we have a clean objecthierarchy (with destruction of children of objects) ^^
         return 0;
@@ -177,4 +160,6 @@
     no->setClassID(header.getClassID());
     assert(no->creatorID_ == header.getCreatorID());
+    if( creator )
+      bo->setLevel(creator->getLevel());          // Note: this ensures that the level is known on the client for child objects of the scene (and the scene itself)
     //assert(no->classID_ == header.getClassID());
     COUT(4) << "fabricate objectID_: " << no->objectID_ << " classID_: " << no->classID_ << std::endl;
@@ -196,5 +181,6 @@
    * @return true/false
    */
-  bool Synchronisable::deleteObject(uint32_t objectID_){
+  bool Synchronisable::deleteObject(uint32_t objectID_)
+  {
     if(!getSynchronisable(objectID_))
       return false;
@@ -213,17 +199,10 @@
    * @return pointer to the Synchronisable with the objectID_
    */
-  Synchronisable* Synchronisable::getSynchronisable(uint32_t objectID_){
+  Synchronisable* Synchronisable::getSynchronisable(uint32_t objectID_)
+  {
     std::map<uint32_t, Synchronisable*>::iterator it1;
     it1 = objectMap_.find(objectID_);
     if (it1 != objectMap_.end())
       return it1->second;
-
-//     ObjectList<Synchronisable>::iterator it;
-//     for(it = ObjectList<Synchronisable>::begin(); it; ++it){
-//       if( it->getObjectID()==objectID_ ){
-//         objectMap_[objectID_] = *it;
-//         return *it;
-//       }
-//     }
     // if the objects not in the map it should'nt exist at all anymore
     return NULL;
@@ -245,5 +224,7 @@
    * @return true: if !doSync or if everything was successfully saved
    */
-  uint32_t Synchronisable::getData(uint8_t*& mem, int32_t id, uint8_t mode){
+  uint32_t Synchronisable::getData(uint8_t*& mem, std::vector<uint32_t>& sizes, int32_t id, uint8_t mode)
+  {
+    unsigned int test = 0;
     if(mode==0x0)
       mode=state_;
@@ -253,4 +234,5 @@
     uint32_t tempsize = 0;
 #ifndef NDEBUG
+    uint8_t* oldmem = mem;
     if (this->classID_==0)
       COUT(3) << "classid 0 " << this->getIdentifier()->getName() << std::endl;
@@ -270,18 +252,26 @@
     // end copy header
 
-
-    COUT(5) << "Synchronisable getting data from objectID_: " << objectID_ << " classID_: " << classID_ << std::endl;
+    CCOUT(5) << "getting data from objectID_: " << objectID_ << ", classID_: " << classID_ << std::endl;
+//     COUT(4) << "objectid: " << this->objectID_ << ":";
     // copy to location
-    for(i=syncList.begin(); i!=syncList.end(); ++i){
-      tempsize += (*i)->getData( mem, mode );
+    for(i=syncList_.begin(); i!=syncList_.end(); ++i)
+    {
+      uint32_t varsize = (*i)->getData( mem, mode );
+//       COUT(4) << " " << varsize;
+      tempsize += varsize;
+      sizes.push_back(varsize);
+      ++test;
       //tempsize += (*i)->getSize( mode );
     }
-
-    tempsize += SynchronisableHeader::getSize();
+//     COUT(4) << endl;
+
     header.setObjectID( this->objectID_ );
     header.setCreatorID( this->creatorID_ );
     header.setClassID( this->classID_ );
-    header.setDataAvailable( true );
     header.setDataSize( tempsize );
+    assert( tempsize == mem-oldmem-SynchronisableHeader::getSize() );
+    assert( test == this->getNrOfVariables() );
+    header.setDiffed(false);
+    tempsize += SynchronisableHeader::getSize();
 
 #ifndef NDEBUG
@@ -300,11 +290,12 @@
    * @return true/false
    */
-  bool Synchronisable::updateData(uint8_t*& mem, uint8_t mode, bool forceCallback){
+  bool Synchronisable::updateData(uint8_t*& mem, uint8_t mode, bool forceCallback)
+  {
     if(mode==0x0)
       mode=state_;
-    std::vector<SynchronisableVariableBase *>::iterator i;
-    if(syncList.empty()){
+    if(syncList_.empty())
+    {
       assert(0);
-      COUT(4) << "Synchronisable::updateData syncList is empty" << std::endl;
+      COUT(2) << "Synchronisable::updateData syncList_ is empty" << std::endl;
       return false;
     }
@@ -312,23 +303,36 @@
     uint8_t* data=mem;
     // start extract header
-    SynchronisableHeader syncHeader(mem);
-    assert(syncHeader.getObjectID()==this->objectID_);
-    assert(syncHeader.getCreatorID()==this->creatorID_);
-    assert(syncHeader.getClassID()==this->classID_);
-    if(syncHeader.isDataAvailable()==false){
-      mem += syncHeader.getDataSize();
-      return true;
-    }
-
-    mem += SynchronisableHeader::getSize();
-    // stop extract header
+    SynchronisableHeaderLight syncHeaderLight(mem);
+    assert(syncHeaderLight.getObjectID()==this->getObjectID());
 
     //COUT(5) << "Synchronisable: objectID_ " << syncHeader.getObjectID() << ", classID_ " << syncHeader.getClassID() << " size: " << syncHeader.getDataSize() << " synchronising data" << std::endl;
-    for(i=syncList.begin(); i!=syncList.end(); i++)
-    {
-      assert( mem <= data+syncHeader.getDataSize() ); // always make sure we don't exceed the datasize in our stream
-      (*i)->putData( mem, mode, forceCallback );
-    }
-    assert(mem == data+syncHeader.getDataSize());
+    if( !syncHeaderLight.isDiffed() )
+    {
+      SynchronisableHeader syncHeader2(mem);
+      assert( this->getClassID() == syncHeader2.getClassID() );
+      assert( this->getCreatorID() == syncHeader2.getCreatorID() );
+      mem += SynchronisableHeader::getSize();
+      std::vector<SynchronisableVariableBase *>::iterator i;
+      for(i=syncList_.begin(); i!=syncList_.end(); i++)
+      {
+        assert( mem <= data+syncHeader2.getDataSize()+SynchronisableHeader::getSize() ); // always make sure we don't exceed the datasize in our stream
+        (*i)->putData( mem, mode, forceCallback );
+      }
+      assert(mem == data+syncHeaderLight.getDataSize()+SynchronisableHeader::getSize() );
+    }
+    else
+    {
+      mem += SynchronisableHeaderLight::getSize();
+//       COUT(0) << "objectID: " << this->objectID_ << endl;
+      while( mem < data+syncHeaderLight.getDataSize()+SynchronisableHeaderLight::getSize() )
+      {
+        VariableID varID = *(VariableID*)mem;
+//         COUT(0) << "varID: " << varID << endl;
+        assert( varID < syncList_.size() );
+        mem += sizeof(VariableID);
+        syncList_[varID]->putData( mem, mode, forceCallback );
+      }
+      assert(mem == data+syncHeaderLight.getDataSize()+SynchronisableHeaderLight::getSize() );
+    }
     return true;
   }
@@ -340,6 +344,7 @@
   * @return amount of bytes
   */
-  uint32_t Synchronisable::getSize(int32_t id, uint8_t mode){
-    int tsize=SynchronisableHeader::getSize();
+  uint32_t Synchronisable::getSize(int32_t id, uint8_t mode)
+  {
+    uint32_t tsize=SynchronisableHeader::getSize();
     if (mode==0x0)
       mode=state_;
@@ -349,5 +354,6 @@
     tsize += this->dataSize_;
     std::vector<SynchronisableVariableBase*>::iterator i;
-    for(i=stringList.begin(); i!=stringList.end(); ++i){
+    for(i=stringList_.begin(); i!=stringList_.end(); ++i)
+    {
       tsize += (*i)->getSize( mode );
     }
@@ -360,19 +366,9 @@
    * @return true/false
    */
-  bool Synchronisable::doSync(int32_t id, uint8_t mode){
+  bool Synchronisable::doSync(int32_t id, uint8_t mode)
+  {
     if(mode==0x0)
       mode=state_;
-    return ( (this->objectMode_ & mode)!=0 && (!syncList.empty() ) );
-  }
-
-  /**
-   * This function looks at the header located in the bytestream and checks wheter objectID_ and classID_ match with the Synchronisables ones
-   * @param mem pointer to the bytestream
-   */
-  bool Synchronisable::isMyData(uint8_t* mem)
-  {
-    SynchronisableHeader header(mem);
-    assert(header.getObjectID()==this->objectID_);
-    return header.isDataAvailable();
+    return ( (this->objectMode_ & mode)!=0 && (!syncList_.empty() ) );
   }
 
@@ -385,5 +381,6 @@
    * @param mode same as in registerVar
    */
-  void Synchronisable::setSyncMode(uint8_t mode){
+  void Synchronisable::setSyncMode(uint8_t mode)
+  {
     assert(mode==0x0 || mode==0x1 || mode==0x2 || mode==0x3);
     this->objectMode_=mode;
@@ -397,6 +394,41 @@
     else
       sv = new SynchronisableVariable<std::string>(variable, mode, cb);
-    syncList.push_back(sv);
-    stringList.push_back(sv);
+    syncList_.push_back(sv);
+    stringList_.push_back(sv);
+  }
+
+template <> void Synchronisable::unregisterVariable( std::string& variable )
+  {
+    bool unregistered_nonexistent_variable = true;
+    std::vector<SynchronisableVariableBase*>::iterator it = syncList_.begin();
+    while(it!=syncList_.end())
+    {
+      if( ((*it)->getReference()) == &variable )
+      {
+        delete (*it);
+        syncList_.erase(it);
+        unregistered_nonexistent_variable = false;
+        break;
+      }
+      else
+        ++it;
+    }
+    assert(unregistered_nonexistent_variable == false);
+    
+    it = stringList_.begin();
+    while(it!=stringList_.end())
+    {
+      if( ((*it)->getReference()) == &variable )
+      {
+        delete (*it);
+        stringList_.erase(it);
+        return;
+      }
+      else
+        ++it;
+    }
+    unregistered_nonexistent_variable = true;
+    assert(unregistered_nonexistent_variable == false); //if we reach this point something went wrong:
+    // the variable has not been registered before
   }
 
Index: code/trunk/src/libraries/network/synchronisable/Synchronisable.h
===================================================================
--- code/trunk/src/libraries/network/synchronisable/Synchronisable.h	(revision 6746)
+++ code/trunk/src/libraries/network/synchronisable/Synchronisable.h	(revision 7163)
@@ -37,4 +37,5 @@
 #include <map>
 #include <queue>
+#include <set>
 
 #include "util/mbool.h"
@@ -64,4 +65,6 @@
     };
   }
+  
+  typedef uint8_t VariableID;
 
   /**
@@ -71,5 +74,5 @@
    * in an emulated bitset.
    * Bit 1 to 31 store the size of the Data the synchronisable consumes in the stream
-   * Bit 32 is a bool and defines whether the data is actually stored or is just filled up with 0
+   * Bit 32 is a bool and defines whether the variables are stored in diff mode
    * Byte 5 to 8: objectID_
    * Byte 9 to 12: classID_
@@ -77,35 +80,68 @@
    */
   class _NetworkExport SynchronisableHeader{
+    friend class SynchronisableHeaderLight;
     private:
-      uint8_t *data_;
+      uint8_t* data_;
     public:
       SynchronisableHeader(uint8_t* data)
         { data_ = data; }
       inline static uint32_t getSize()
-        { return 16; }
-      inline uint32_t getDataSize() const
-        { return (*(uint32_t*)data_) & 0x7FFFFFFF; } //only use the first 31 bits
-      inline void setDataSize(uint32_t size)
-        { *(uint32_t*)(data_) = (size & 0x7FFFFFFF) | (*(uint32_t*)(data_) & 0x80000000 ); }
-      inline bool isDataAvailable() const
-        { return ( (*(uint32_t*)data_) & 0x80000000 ) == 0x80000000; }
-      inline void setDataAvailable( bool b)
-        { *(uint32_t*)(data_) = (b << 31) | (*(uint32_t*)(data_) & 0x7FFFFFFF ); }
+        { return 14; }
+      inline uint16_t getDataSize() const
+        { return (*(uint16_t*)data_) & 0x7FFF; } //only use the first 15 bits
+      inline void setDataSize(uint16_t size)
+        { *(uint16_t*)(data_) = (size & 0x7FFF) | (*(uint16_t*)(data_) & 0x8000 ); }
+      inline bool isDiffed() const
+        { return ( (*(uint16_t*)data_) & 0x8000 ) == 0x8000; }
+      inline void setDiffed( bool b)
+        { *(uint16_t*)(data_) = (b << 15) | (*(uint16_t*)(data_) & 0x7FFF ); }
       inline uint32_t getObjectID() const
-        { return *(uint32_t*)(data_+4); }
+        { return *(uint32_t*)(data_+2); }
       inline void setObjectID(uint32_t objectID_)
-        { *(uint32_t*)(data_+4) = objectID_; }
+        { *(uint32_t*)(data_+2) = objectID_; }
       inline uint32_t getClassID() const
-        { return *(uint32_t*)(data_+8); }
+        { return *(uint32_t*)(data_+6); }
       inline void setClassID(uint32_t classID_)
-        { *(uint32_t*)(data_+8) = classID_; }
+        { *(uint32_t*)(data_+6) = classID_; }
       inline uint32_t getCreatorID() const
-        { return *(uint32_t*)(data_+12); }
+        { return *(uint32_t*)(data_+10); }
       inline void setCreatorID(uint32_t creatorID_)
-        { *(uint32_t*)(data_+12) = creatorID_; }
+        { *(uint32_t*)(data_+10) = creatorID_; }
       inline void operator=(SynchronisableHeader& h)
         { memcpy(data_, h.data_, getSize()); }
   };
 
+    /**
+   * @brief: stores information about a Synchronisable (light version)
+   *
+   * This class stores the information about a Synchronisable (objectID_, dataSize)
+   * in an emulated bitset.
+   * Bit 1 to 31 store the size of the Data the synchronisable consumes in the stream
+   * Bit 32 is a bool and defines whether the variables are stored in diff mode
+   * Byte 5 to 8: objectID_
+   */
+  class _NetworkExport SynchronisableHeaderLight{
+    private:
+      uint8_t* data_;
+    public:
+      SynchronisableHeaderLight(uint8_t* data)
+        { data_ = data; }
+      inline static uint32_t getSize()
+        { return 6; }
+      inline uint16_t getDataSize() const
+        { return (*(uint16_t*)data_) & 0x7FFF; } //only use the first 31 bits
+      inline void setDataSize(uint16_t size)
+        { *(uint16_t*)(data_) = (size & 0x7FFFFFFF) | (*(uint16_t*)(data_) & 0x8000 ); }
+      inline bool isDiffed() const
+        { return ( (*(uint16_t*)data_) & 0x8000 ) == 0x8000; }
+      inline void setDiffed( bool b)
+        { *(uint16_t*)(data_) = (b << 15) | (*(uint16_t*)(data_) & 0x7FFF ); }
+      inline uint32_t getObjectID() const
+        { return *(uint32_t*)(data_+2); }
+      inline void setObjectID(uint32_t objectID_)
+        { *(uint32_t*)(data_+2) = objectID_; }
+      inline void operator=(SynchronisableHeader& h)
+        { memcpy(data_, h.data_, getSize()); }
+  };
 
   /**
@@ -134,8 +170,14 @@
 
     void setSyncMode(uint8_t mode);
+    
+    inline uint32_t getNrOfVariables(){ return this->syncList_.size(); }
+    inline uint32_t getVarSize( VariableID ID )
+    { return this->syncList_[ID]->getSize(state_); }
 
   protected:
     Synchronisable(BaseObject* creator);
     template <class T> void registerVariable(T& variable, uint8_t mode=0x1, NetworkCallbackBase *cb=0, bool bidirectional=false);
+    template <class T> void registerVariable(std::set<T>& variable, uint8_t mode=0x1, NetworkCallbackBase *cb=0, bool bidirectional=false);
+    template <class T> void unregisterVariable(T& var);
 
     void setPriority(unsigned int freq){ objectFrequency_ = freq; }
@@ -143,8 +185,7 @@
 
   private:
-    uint32_t getData(uint8_t*& men, int32_t id, uint8_t mode=0x0);
+    uint32_t getData(uint8_t*& mem, std::vector<uint32_t>& sizes, int32_t id, uint8_t mode);
     uint32_t getSize(int32_t id, uint8_t mode=0x0);
     bool updateData(uint8_t*& mem, uint8_t mode=0x0, bool forceCallback=false);
-    bool isMyData(uint8_t* mem);
     bool doSync(int32_t id, uint8_t mode=0x0);
 
@@ -156,6 +197,6 @@
     uint32_t classID_;
 
-    std::vector<SynchronisableVariableBase*> syncList;
-    std::vector<SynchronisableVariableBase*> stringList;
+    std::vector<SynchronisableVariableBase*> syncList_;
+    std::vector<SynchronisableVariableBase*> stringList_;
     uint32_t dataSize_; //size of all variables except strings
     static uint8_t state_; // detemines wheter we are server (default) or client
@@ -171,16 +212,46 @@
     if (bidirectional)
     {
-      syncList.push_back(new SynchronisableVariableBidirectional<T>(variable, mode, cb));
-      this->dataSize_ += syncList.back()->getSize(state_);
+      syncList_.push_back(new SynchronisableVariableBidirectional<T>(variable, mode, cb));
+      this->dataSize_ += syncList_.back()->getSize(state_);
     }
     else
     {
-      syncList.push_back(new SynchronisableVariable<T>(variable, mode, cb));
+      syncList_.push_back(new SynchronisableVariable<T>(variable, mode, cb));
       if ( this->state_ == mode )
-        this->dataSize_ += syncList.back()->getSize(state_);
+        this->dataSize_ += syncList_.back()->getSize(state_);
     }
   }
+  
+  template <class T> void Synchronisable::unregisterVariable(T& variable){
+    std::vector<SynchronisableVariableBase*>::iterator it = syncList_.begin();
+    while(it!=syncList_.end()){
+      if( ((*it)->getReference()) == &variable ){
+        this->dataSize_ -= (*it)->getSize(Synchronisable::state_);
+        delete (*it);
+        syncList_.erase(it);
+        return;
+      }
+      else
+        it++;
+    }
+    bool unregistered_nonexistent_variable = false;
+    assert(unregistered_nonexistent_variable); //if we reach this point something went wrong:
+    // the variable has not been registered before
+  }
+
+  template <class T> void Synchronisable::registerVariable( std::set<T>& variable, uint8_t mode, NetworkCallbackBase *cb, bool bidirectional)
+  {
+    SynchronisableVariableBase* sv;
+    if (bidirectional)
+      sv = new SynchronisableVariableBidirectional<std::set<T> >(variable, mode, cb);
+    else
+      sv = new SynchronisableVariable<std::set<T> >(variable, mode, cb);
+    syncList_.push_back(sv);
+    stringList_.push_back(sv);
+  }
 
   template <> _NetworkExport void Synchronisable::registerVariable( std::string& variable, uint8_t mode, NetworkCallbackBase *cb, bool bidirectional);
+//   template <class T> _NetworkExport void Synchronisable::registerVariable<std::set<T> >( std::set<T>& variable, uint8_t mode, NetworkCallbackBase *cb, bool bidirectional);
+  template <> _NetworkExport void Synchronisable::unregisterVariable( std::string& variable );
 
 
