Index: /trunk/src/defs/class_id.h
===================================================================
--- /trunk/src/defs/class_id.h	(revision 8067)
+++ /trunk/src/defs/class_id.h	(revision 8068)
@@ -134,5 +134,6 @@
   CL_GAME_WORLD_DATA            =    0x00102000,
   CL_GAME_RULES                 =    0x00104000,
-  CL_MISSION_GOAL               =    0x00105000,
+  CL_NETWORK_GAME_RULES         =    0x00108000,
+  CL_MISSION_GOAL               =    0x00110000,
 
   CL_CAMPAIGN                   =    0x00000101,
@@ -146,6 +147,6 @@
   CL_MOVIE_LOADER               =    0x00000109,
 
-  CL_MULTIPLAYER_TEAM_DEATHMATCH=    0x00104001,
-  CL_SINGLEPLAYER_SHOOTEMUP     =    0x00104002,
+  CL_MULTIPLAYER_TEAM_DEATHMATCH=    0x00000121,
+  CL_SINGLEPLAYER_SHOOTEMUP     =    0x00000122,
 
   CL_KILL_TARGET                =    0x00105001,
@@ -189,4 +190,5 @@
   CL_HOVER                      =    0x0000035e,
   CL_TURBINE_HOVER              =    0x0000035f,
+  CL_SPECTATOR                  =    0x00000360,
 
   // Powerups
@@ -368,5 +370,6 @@
   CL_NETWORK_GAME_MANAGER       =    0x00000d07,
   CL_MESSAGE_MANAGER            =    0x00000d08,
-  CL_SIMPLE_SYNC                =    0x00000d09,
+  CL_PLAYER_STATS               =    0x00000d09,
+  CL_SIMPLE_SYNC                =    0x00000d0a,
 
 
Index: /trunk/src/lib/graphics/importer/height_map.cc
===================================================================
--- /trunk/src/lib/graphics/importer/height_map.cc	(revision 8067)
+++ /trunk/src/lib/graphics/importer/height_map.cc	(revision 8068)
@@ -134,5 +134,5 @@
     w = yOffset;
 
-    PRINTF(0)("Values: i = %i, w = %i\n", i, w);
+//    PRINTF(0)("Values: i = %i, w = %i\n", i, w);
 
     // add a vertex to the list
@@ -599,7 +599,7 @@
   float c = normalVectorField [(xInt)][yInt].y;
 
-  PRINTF(0)("a: %f \n" ,a);
-  PRINTF(0)("b: %f \n" ,b);
-  PRINTF(0)("c: %f \n" ,c);
+//  PRINTF(0)("a: %f \n" ,a);
+//  PRINTF(0)("b: %f \n" ,b);
+//  PRINTF(0)("c: %f \n" ,c);
 
 
Index: /trunk/src/lib/network/Makefile.am
===================================================================
--- /trunk/src/lib/network/Makefile.am	(revision 8067)
+++ /trunk/src/lib/network/Makefile.am	(revision 8068)
@@ -23,4 +23,5 @@
 		      network_log.cc \
 		      zip.cc \
+		      player_stats.cc \
 		      \
 		      synchronizeable_var/synchronizeable_var.cc \
@@ -56,4 +57,5 @@
 		 network_log.h \
 		 zip.h \
+		 player_stats.h \
 		 \
 		 synchronizeable_var/synchronizeable_var.h \
Index: /trunk/src/lib/network/connection_monitor.cc
===================================================================
--- /trunk/src/lib/network/connection_monitor.cc	(revision 8067)
+++ /trunk/src/lib/network/connection_monitor.cc	(revision 8068)
@@ -61,8 +61,6 @@
  * @param stateId packet's state id
  */
-void ConnectionMonitor::processUnzippedOutgoingPacket( byte * data, int length, int stateId )
-{
-  int tick = SDL_GetTicks();
-  
+void ConnectionMonitor::processUnzippedOutgoingPacket( int tick, byte * data, int length, int stateId )
+{
   nOutgoingPackets++;
   
@@ -77,9 +75,9 @@
   
   // count zero bytes
-  int nZeroBytes = 0;
-  
-  for ( int i = 0; i < length; i++ )
-    if ( data[i] == '\0' )
-      nZeroBytes++;
+  //int nZeroBytes = 0;
+  
+  //for ( int i = 0; i < length; i++ )
+  //  if ( data[i] == '\0' )
+  //    nZeroBytes++;
   
   //NETPRINTF(n)( "ZEROBYTES: %d (%f%%)\n", nZeroBytes, ((float)100)*nZeroBytes/length );
@@ -93,8 +91,6 @@
  * @param ackedState state which was acked by this packet
  */
-void ConnectionMonitor::processUnzippedIncomingPacket( byte * data, int length, int stateId, int ackedState )
-{
-  int tick = SDL_GetTicks();
-  
+void ConnectionMonitor::processUnzippedIncomingPacket( int tick, byte * data, int length, int stateId, int ackedState )
+{
   nIncomingPackets++;
   
@@ -149,5 +145,6 @@
   for ( std::map<int,int>::iterator it = packetHistory.begin(); it != packetHistory.end(); it++ )
   {
-    res += it->second;
+    if ( it != packetHistory.begin() )
+      res += it->second;
   }
   
@@ -155,5 +152,5 @@
     res = 0.0f;
   else
-    res /= (float)((tick - packetHistory.begin()->first)*( 1 + 1/((float)(packetHistory.size()-1)) ));
+    res /= (float)(tick - packetHistory.begin()->first);
   
   res *= 1000.0f;
@@ -169,8 +166,6 @@
  * @param stateId packet's state id
  */
-void ConnectionMonitor::processZippedOutgoingPacket( byte * data, int length, int stateId )
-{
-  int tick = SDL_GetTicks();
-  
+void ConnectionMonitor::processZippedOutgoingPacket( int tick, byte * data, int length, int stateId )
+{
   nZOutgoingPackets++;
   
@@ -196,8 +191,6 @@
  * @param ackedState state which was acked by this packet
  */
-void ConnectionMonitor::processZippedIncomingPacket( byte * data, int length, int stateId, int ackedState )
-{
-  int tick = SDL_GetTicks();
-  
+void ConnectionMonitor::processZippedIncomingPacket( int tick, byte * data, int length )
+{
   nZIncomingPackets++;
   
@@ -233,9 +226,10 @@
 void ConnectionMonitor::printStatis( )
 {
-  NETPRINT(n)("=========NETWORKSTATS FOR USER %d=========\n", userId);
-  NETPRINT(n)("PING = %d\n", ping);
+  NETPRINT(n)("============NETWORKSTATS FOR USER %d============\n", userId);
+  NETPRINT(n)("PING = %d\n", ping );
   NETPRINT(n)("BANDWIDTH: UP: %f (%f) DOWN %f (%f)\n", outgoingZippedBandWidth, outgoingUnzippedBandWidth, incomingZippedBandWidth, incomingUnzippedBandWidth);
-  NETPRINT(n)("==========================================");
-}
-
-
+  NETPRINT(n)("PACKETS: RECIEVED %d; SENT %d\n", nIncomingPackets, nOutgoingPackets );
+  NETPRINT(n)("================================================\n");
+}
+
+
Index: /trunk/src/lib/network/connection_monitor.h
===================================================================
--- /trunk/src/lib/network/connection_monitor.h	(revision 8067)
+++ /trunk/src/lib/network/connection_monitor.h	(revision 8068)
@@ -22,9 +22,9 @@
     virtual ~ConnectionMonitor();
 
-    void processUnzippedOutgoingPacket( byte * data, int length, int stateId );
-    void processUnzippedIncomingPacket( byte * data, int length, int stateId, int ackedState );
+    void processUnzippedOutgoingPacket( int tick, byte * data, int length, int stateId );
+    void processUnzippedIncomingPacket( int tick, byte * data, int length, int stateId, int ackedState );
     
-    void processZippedOutgoingPacket( byte * data, int length, int stateId );
-    void processZippedIncomingPacket( byte * data, int length, int stateId, int ackedState );
+    void processZippedOutgoingPacket( int tick, byte * data, int length, int stateId );
+    void processZippedIncomingPacket( int tick, byte * data, int length );
     
     void calculatePing();
Index: /trunk/src/lib/network/message_manager.cc
===================================================================
--- /trunk/src/lib/network/message_manager.cc	(revision 8067)
+++ /trunk/src/lib/network/message_manager.cc	(revision 8068)
@@ -309,5 +309,6 @@
   {
     if ( 
-         recieverType == RT_ALL ||
+         recieverType == RT_ALL_ME ||
+         recieverType == RT_ALL_NOT_ME ||
          recieverType == RT_USER && it->first == reciever ||
          recieverType == RT_NOT_USER && it->first != reciever
@@ -324,7 +325,10 @@
       
       it->second.messages.push_back( msg );
-    }
-  }
-}
-
-
+      
+      if ( recieverType == RT_ALL_ME )
+        incomingMessabeBuffer.push_back( msg );
+    }
+  }
+}
+
+
Index: /trunk/src/lib/network/message_manager.h
===================================================================
--- /trunk/src/lib/network/message_manager.h	(revision 8067)
+++ /trunk/src/lib/network/message_manager.h	(revision 8068)
@@ -29,5 +29,5 @@
 {
   TESTMESSAGEID = 1,
-  MSGID_YOU_ARE
+  MSGID_DELETESYNCHRONIZEABLE
 };
 
@@ -36,7 +36,8 @@
 enum RecieverType
 {
-  RT_ALL = 1,   //!< message is sent to all users
-  RT_USER,      //!< message is only sent to reciever
-  RT_NOT_USER   //!< message is sent to all but reciever
+  RT_ALL_NOT_ME = 1,   //!< message is sent to all users
+  RT_ALL_ME,           //!< message is sent to all users
+  RT_USER,             //!< message is only sent to reciever
+  RT_NOT_USER          //!< message is sent to all but reciever
 };
 
Index: /trunk/src/lib/network/network_game_manager.cc
===================================================================
--- /trunk/src/lib/network/network_game_manager.cc	(revision 8067)
+++ /trunk/src/lib/network/network_game_manager.cc	(revision 8068)
@@ -34,4 +34,7 @@
 #include "game_world.h"
 
+#include "game_rules.h"
+#include "network_game_rules.h"
+
 #include "network_game_manager.h"
 
@@ -55,5 +58,8 @@
   this->setSynchronized(true);
   
-  MessageManager::getInstance()->registerMessageHandler( MSGID_YOU_ARE, youAreHandler, NULL );
+  MessageManager::getInstance()->registerMessageHandler( MSGID_DELETESYNCHRONIZEABLE, delSynchronizeableHandler, NULL );
+  
+  this->gameState = 0;
+  registerVar( new SynchronizeableInt( &gameState, &gameState, "gameState" ) );
 }
 
@@ -63,930 +69,116 @@
 NetworkGameManager::~NetworkGameManager()
 {
-#if 0
-  for ( int i = 0; i<outBuffer.size(); i++)
-  {
-    if ( outBuffer[i].buffer )
-      delete outBuffer[i].buffer;
-  }
-#endif
-
-}
-
-#if 0
-int NetworkGameManager::writeBytes(const byte* data, int length, int sender)
-{
-  int i = 0;
-  byte b;
-
-  while ( i<length )
-  {
-    b = data[i++];
-
-    /**************** Commands only processed by servers ****************/
-    if ( isServer() )
-    {
-      if ( b == NET_REQUEST_CREATE )
-      {
-        if ( !handleRequestCreate( i, data, length, sender ) )
-          return i;
-        continue;
-      }
-      else if ( b == NET_REQUEST_REMOVE )
-      {
-        if ( !handleRequestRemove( i, data, length, sender ) )
-          return i;
-        continue;
-      }
-      else if ( b == NET_REQUEST_PNODE_PATH )
-      {
-        if ( !handleRequestPNodePath( i, data, length, sender ) )
-          return i;
-        continue;
-      }
-    }
-    else
-    {
-      /**************** Commands only processed by clients ****************/
-      if ( b == NET_CREATE_ENTITY )
-      {
-        PRINTF(0)("CREATE_ENTITY\n");
-        if ( !handleCreateEntity( i, data, length, sender ) )
-          return i;
-        continue;
-      }
-      else if ( b == NET_REMOVE_ENTITY )
-      {
-        if ( !handleRemoveEntity( i, data, length, sender ) )
-          return i;
-        continue;
-      }
-      else if ( b == NET_CREATE_ENTITY_LIST )
-      {
-        if ( !handleCreateEntityList( i, data, length, sender ) )
-          return i;
-        continue;
-      }
-      else if ( b == NET_REMOVE_ENTITY_LIST )
-      {
-        if ( !handleRemoveEntityList( i, data, length, sender ) )
-          return i;
-        continue;
-      }
-      else if ( b == NET_YOU_ARE_ENTITY )
-      {
-        if ( !handleYouAreEntity( i, data, length, sender ) )
-          return i;
-        continue;
-      }
-    }
-
-    /**************** Commands processed by servers and clients ****************/
-    if ( b == NET_REQUEST_ENTITY_LIST )
-    {
-      sendEntityList( sender );
-      continue;
-    }
-
-
-    PRINTF(1)("Network is asynchronous: couldn't decode the command sent by %i\n", sender);
-    PRINTF(1)("Probably this is because the network protocol has different \n");
-    PRINTF(1)("versions or there occured an error in the sending algorithm\n");
-    PRINTF(1)("Data is not in the right format! i=%d\n", i);
-    return i;
-  }
-
-  return i;
-}
-#endif
-
-#if 0
-int NetworkGameManager::readBytes(byte* data, int maxLength, int * reciever)
-{
-  if ( !isServer() && !hasRequestedWorld )
-  {
-    assert( maxLength >= 1 );
-    data[0] = NET_REQUEST_ENTITY_LIST;
-    hasRequestedWorld = true;
-    return 1;
-  }
-
-  for ( int i = 0; i<outBuffer.size(); i++ )
-  {
-    *reciever = i;
-    if ( outBuffer[i].length>0 )
-    {
-      int nbytes = outBuffer[i].length;
-      outBuffer[i].length = 0;
-
-      if ( nbytes > maxLength )
-      {
-        PRINTF(1)("OutBuffer.length (%d) > (%d) networkStreamBuffer.maxLength\n", nbytes, maxLength);
-        return 0;
-      }
-
-      memcpy(data, outBuffer[i].buffer, nbytes);
-      return nbytes;
-    }
-  }
-
-  return 0;
-}
-#endif
-
-#if 0
-void NetworkGameManager::writeDebug() const
-{
-}
-
-void NetworkGameManager::readDebug() const
-{
-}
-#endif
-
-
-/*!
- * Checks whether this is connected to a server or a client
- * and afterwards creates the needed entity
- * @param classID: The ID of the class of which an entity should be created
- */
-int NetworkGameManager::createEntity( ClassID classID, int owner )
-{
-  if ( this->isServer())
-  {
-    int res = this->executeCreateEntity( classID, SharedNetworkData::getInstance()->getNewUniqueID(), owner );
-    
-    if ( res < 0 )
-    {
-      PRINTF(1)("Cannot create entity! There are no more uniqueIDs left!\n");
-      return -1;
-    }
-    
-    return res;
-  }
-  else
-  {
-#if 0
-    this->requestCreateEntity( classID );
-#endif
-    return -1;
-  }
 }
 
 
-/*!
- * Checks whether this is connected to a server or a client
- * and afterwards creates the needed entity
- * @param classID: The ID of the class of which an entity should be created
+/**
+ * insert new player into game
+ * @param userId 
+ * @return 
  */
-BaseObject* NetworkGameManager::createEntity(const TiXmlElement* element)
+bool NetworkGameManager::signalNewPlayer( int userId )
 {
-  if ( this->isServer() )
-  {
-    if ( SharedNetworkData::getInstance()->getNewUniqueID() < 0 )
-    {
-      PRINTF(1)("Cannot create entity! There are no more uniqueIDs left!\n");
-      return NULL;
-    }
-
-    BaseObject * b = Factory::fabricate( element );
-
-    if ( !b )
-    {
-      PRINTF(1)("Could not fabricate Object with className %s\n", element->Value() );
-      return NULL;
-    }
-
-
-    if ( b->isA(CL_SYNCHRONIZEABLE) )
-    {
-      Synchronizeable * s = dynamic_cast<Synchronizeable*>(b);
-      s->setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() );
-      s->setOwner( 0 );
-      // all entities created via this function are added automaticaly to the synchronizeable list
-      s->setSynchronized(true);
-      return b;
-    }
-    else
-    {
-      PRINTF(1)("Class %s is not a synchronizeable!\n", b->getClassName() );
-      delete b;
-    }
-
-  }
-  else
-
-  {
-    PRINTF(1)("This node is not a server and cannot create id %x\n", element->Value());
-  }
-  return NULL;
+  assert( SharedNetworkData::getInstance()->isGameServer() );
+  assert( State::getGameRules() );
+  assert( State::getGameRules()->isA( CL_NETWORK_GAME_RULES ) );
+  
+  NetworkGameRules & rules = *(dynamic_cast<NetworkGameRules*>(State::getGameRules()));
+  
+  int team = rules.getTeamForNewUser();
+  ClassID playableClassId = rules.getPlayableClassId( team );
+  std::string playableModel = rules.getPlayableModelFileName( team, playableClassId );
+  
+  BaseObject * bo = Factory::fabricate( playableClassId );
+  
+  assert( bo != NULL );
+  assert( bo->isA( CL_PLAYABLE ) );
+  
+  Playable & playable = *(dynamic_cast<Playable*>(bo));
+  
+  playable.loadModel( playableModel );
+  playable.setOwner( userId );
+  playable.setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() );
+  playable.setSynchronized( true );
+  
+  PlayerStats * stats = rules.getNewPlayerStats( userId );
+  
+  stats->setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() );
+  stats->setSynchronized( true );
+  stats->setOwner( getHostID() );
+  
+  stats->setTeamId( team );
+  stats->setPlayableClassId( playableClassId );
+  stats->setPlayableUniqueId( playable.getUniqueID() );
+  stats->setModelFileName( playableModel );
 }
 
 
-/*!
- * Checks whether this is connected to a server or a client
- * and afterwards removes the specified entity
- * @param uniqueID: The ID of the entity object which should be removed
+/**
+ * remove player from game
+ * @param userID 
+ * @return 
  */
-void NetworkGameManager::removeEntity(int uniqueID)
+bool NetworkGameManager::signalLeftPlayer(int userID)
 {
-  if ( this->isServer() )
-  {
-    this->executeRemoveEntity( uniqueID );
-  }
-  else
-  {
-#if 0
-    this->requestRemoveEntity( uniqueID );
-#endif
-  }
-}
-
-
-#if 0
-/*!
- * Creates the needed entity on the server if possible
- * @param classID: The ID of the class of which an entity should be created
- */
-void NetworkGameManager::requestCreateEntity(ClassID classID)
-{
-  for ( int i = 0; i<outBuffer.size(); i++)
-  {
-    if ( !this->networkStream->isUserIdActive( i ) )
-      continue;
-
-    if ( !writeToClientBuffer( outBuffer[i], (byte)NET_REQUEST_CREATE ) )
-      return;
-    if ( !writeToClientBuffer( outBuffer[i], (int)classID ) )
-      return;
-  }
-}
-#endif
-
-#if 0
-/*!
- * Removes the specified entity on the server
- * @param uniqueID: The ID of the entity object which should be removed
- */
-void NetworkGameManager::requestRemoveEntity(int uniqueID)
-{
-  for ( int i = 0; i<outBuffer.size(); i++)
-  {
-    if ( !this->networkStream->isUserIdActive( i ) )
-      continue;
-
-    if ( !writeToClientBuffer( outBuffer[i], (byte)NET_REQUEST_REMOVE ) )
-      return;
-    if ( !writeToClientBuffer( outBuffer[i], uniqueID ) )
-      return;
-  }
-}
-#endif
-
-/*!
- * Creates the needed entity if possible
- * This function is called if this is a server
- * @param classID: The ID of the class of which an entity should be created
- */
-int NetworkGameManager::executeCreateEntity(ClassID classID, int uniqueID, int owner)
-{
-#if 0
-  for ( int i = 0; i<outBuffer.size(); i++)
-  {
-    if ( !this->networkStream->isUserIdActive( i ) )
-      continue;
-
-    if ( !writeToClientBuffer( outBuffer[i], (byte)NET_CREATE_ENTITY ) )
-      return -1;
-    if ( !writeToClientBuffer( outBuffer[i], (int)classID ) )
-      return -1;
-    if ( !writeToClientBuffer( outBuffer[i], uniqueID ) )
-      return -1;
-    if ( !writeToClientBuffer( outBuffer[i], owner ) )
-      return -1;
-  }
-#endif
-  PRINTF(0)("ExecuteCreateEntity: server side: classID: %x, uniqueID: %i, owner: %i\n", classID, uniqueID, owner);
-  doCreateEntity( classID, uniqueID, owner );
-
-  return uniqueID;
-}
-
-/*!
- * Removes the specified entity
- * This function is called if this is a server
- * @param uniqueID: The ID of the entity object which should be removed
- */
-void NetworkGameManager::executeRemoveEntity(int uniqueID)
-{
-#if 0
-  for ( int i = 0; i<outBuffer.size(); i++)
-  {
-    if ( !this->networkStream->isUserIdActive( i ) )
-      continue;
-
-    if ( !writeToClientBuffer( outBuffer[i], (byte)NET_REMOVE_ENTITY ) )
-      return;
-    if ( !writeToClientBuffer( outBuffer[i], uniqueID ) )
-      return;
-  }
-#endif
-
-  doRemoveEntity(uniqueID);
-}
-
-/*!
- * Checks whether it is possible to create an entity of a given class
- * @return: true if the entity can be created, false otherwise
- */
-bool NetworkGameManager::canCreateEntity(ClassID classID)
-{
-  return true;
-}
-
-#if 0
-/*!
- * Sends the Entities to the new connected client
- * @param userID: The ID of the user
- */
-void NetworkGameManager::sendEntityList( int userID )
-{
-  if ( !isServer() )
-    return;
-
-  if ( userID >= outBuffer.size() )
-    resizeBufferVector( userID );
-
-  SynchronizeableList::const_iterator it, e;
-
-  it = this->networkStream->getSyncBegin();
-  e = this->networkStream->getSyncEnd();
-
-  // send the packet header
-  if ( !writeToClientBuffer( outBuffer[userID], (byte)NET_CREATE_ENTITY_LIST ) )
-    return;
-
-  // send the number of entities: -2 because you must not send network_game_manager and handshake
-  if ( !writeToClientBuffer( outBuffer[userID], networkStream->getSyncCount() ) )
-    return;
-
-  //PRINTF(0)("SendEntityList: n = %d\n", networkStream->getSyncCount()-2 );
-
-  // first send the NullParent
-  if ( !writeToClientBuffer( outBuffer[userID], (int)PNode::getNullParent()->getLeafClassID()) )
-    return;
-  if ( !writeToClientBuffer( outBuffer[userID], (int)PNode::getNullParent()->getUniqueID()) )
-    return;
-  if ( !writeToClientBuffer( outBuffer[userID], (int)PNode::getNullParent()->getOwner()) )
-    return;
-
-  // now send the rest of the entities
-  while ( it != e )
-  {
-    if( (*it)->beSynchronized() && (*it) != PNode::getNullParent())
-    {
-      PRINTF(0)("SENDING ENTITY %s classid: %x, uniqueid %d\n", (*it)->getClassName(), (*it)->getLeafClassID(), (*it)->getUniqueID() );
-      if ( !writeToClientBuffer( outBuffer[userID], (int)((*it)->getLeafClassID()) ) )
-        return;
-
-      if ( !writeToClientBuffer( outBuffer[userID], (int)((*it)->getUniqueID()) ) )
-        return;
-
-      if ( !writeToClientBuffer( outBuffer[userID], (int)((*it)->getOwner()) ) )
-        return;
-    }
-    it++;
-  }
-
-  signalNewPlayer( userID );
-}
-#endif
-
-
-
-bool NetworkGameManager::signalNewPlayer(int userId)
-{
-  /* create new playable for Player*/
-  PRINTF(0)("Request for creation: %i\n", userId);
-  int uniqueId = this->createEntity(CL_SPACE_SHIP, userId);
-  PRINTF(0)("Request for creation: userid: %i, uniqueid: %i\n", userId, uniqueId);
-  this->sendYouAre(uniqueId, userId);
+  delete PlayerStats::getStats( userID )->getPlayable();
+  delete PlayerStats::getStats( userID );
 }
 
 
 
-bool NetworkGameManager::signalLeftPlayer(int userID)
+/**
+ * handler for remove synchronizeable messages
+ * @param messageId 
+ * @param data 
+ * @param dataLength 
+ * @param someData 
+ * @param userId 
+ * @return true on successfull handling else handler will be called again
+ */
+bool NetworkGameManager::delSynchronizeableHandler( MessageId messageId, byte * data, int dataLength, void * someData, int userId )
 {
-  const std::list<BaseObject*>* playableList = ClassList::getList(CL_PLAYABLE);
+  if ( getInstance()->isServer() )
+  {
+    PRINTF(2)("Recieved DeleteSynchronizeable message from client %d!\n", userId);
+    return true;
+  }
   
-  if ( !playableList )
-    return false;
+  int uniqueId = 0;
+  int len = Converter::byteArrayToInt( data, &uniqueId );
   
-  std::list<BaseObject*>::const_iterator it = playableList->begin();
-
-  for(; it != playableList->end(); it++)
+  if ( len != dataLength )
   {
-    if( dynamic_cast<Synchronizeable*>(*it)->getOwner() == userID )
+    PRINTF(2)("Recieved DeleteSynchronizeable message with incorrect size (%d) from client %d!\n", dataLength, userId);
+    return true;
+  }
+  
+  const std::list<BaseObject*> * list = ClassList::getList( CL_SYNCHRONIZEABLE );
+  
+  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
+  {
+    if ( dynamic_cast<Synchronizeable*>(*it)->getUniqueID() == uniqueId )
     {
-      PRINTF(0)("remove playable from %i\n", userID);
-      this->removeEntity(dynamic_cast<Synchronizeable*>(*it)->getUniqueID());
+      delete dynamic_cast<Synchronizeable*>(*it);
       return true;
     }
   }
-  return false;
-}
-
-#if 0
-/**
- * Creates a buffer for user n
- * @param n The ID of the user
- */
-void NetworkGameManager::resizeBufferVector( int n )
-{
-  for ( int i = outBuffer.size(); i<=n; i++)
-  {
-    clientBuffer outBuf;
-
-    outBuf.length = 0;
-
-    outBuf.maxLength = 5*1024;
-
-    outBuf.buffer = new byte[5*1014];
-
-    outBuffer.push_back(outBuf);
-  }
-}
-#endif
-
-/**
- * Creates the entity on this host
- * @param classID: ClassID of the entity to create
- * @param uniqueID: Unique ID to assign to the synchronizeable
- * @param owner: owner of this synchronizealbe
- */
-BaseObject* NetworkGameManager::doCreateEntity( ClassID classID, int uniqueID, int owner )
-{
-  PRINTF(0)("Creating Entity via Factory: classid: %x, uniqueID: %i, owner: %i\n", classID, uniqueID, owner);
-
-  BaseObject * b;
-  /* These are some small exeptions in creation: Not all objects can/should be created via Factory */
-  /* Exception 1: NullParent */
-  if( classID == CL_NULL_PARENT)
-  {
-    b = (BaseObject*)PNode::getNullParent();
-  }
-  else
-    b = Factory::fabricate( classID );
-
-  if ( !b )
-  {
-    PRINTF(1)("Could not fabricate Object with classID %x\n", classID);
-    return NULL;
-  }
-
-  if ( b->isA(CL_SYNCHRONIZEABLE) )
-  {
-    Synchronizeable * s = dynamic_cast<Synchronizeable*>(b);
-    s->setUniqueID( uniqueID );
-    s->setOwner( owner );
-    s->setSynchronized(true);
-    //this->networkStream->connectSynchronizeable( *s );
-
-    PRINTF(0)("Fabricated %s with id %d\n", s->getClassName(), s->getUniqueID());
-
-    //TODO HACK: hack to prevent collision
-    if ( b->isA(CL_WORLD_ENTITY) && !b->isA(CL_PLAYABLE) )
-    {
-      if ( SharedNetworkData::getInstance()->getHostID()!=0 )
-      {
-        static Vector pos = Vector(1000.0, 1000.0, 1000.0);
-        PNode *p = dynamic_cast<PNode*>(b);
-        p->setAbsCoor(pos);
-        p->updateNode(0);
-        pos += Vector(1000.0, 1000.0, 1000.0);
-      }
-    }
-    ///TODO HACK this is only for network multiplayer games.
-    if( b->isA(CL_PLAYABLE))
-    {
-      Playable* ss = dynamic_cast<Playable*>(b);
-      if( owner%2 == 0)
-      {
-
-        ss->loadModel("models/ships/reap_0.obj");
-        ss->toList(OM_GROUP_00);
-        ss->setAbsCoor(213.37, 57.71, -47.98);
-        ss->setAbsDir(Quaternion(0.16, 0.98, -0.10));
-      }
-      else
-      {
-        ss->loadModel( "models/ships/fighter.obj" );
-        ss->toList(OM_GROUP_01);
-        ss->setAbsCoor(-314.450, 40.701, 83.554);
-      }
-    }
-
-    return b;
-  }
-  else
-  {
-    PRINTF(1)("Class with ID %x is not a synchronizeable!", (int)classID);
-    delete b;
-  }
-  return NULL;
 }
 
 /**
- * Removes a entity on this host
- * @param uniqueID: unique ID assigned with the entity to remove
+ * removes synchronizeable (also on clients)
+ * @param uniqueId uniqueid to delete
  */
-void NetworkGameManager::doRemoveEntity( int uniqueID )
+void NetworkGameManager::removeSynchronizeable( int uniqueId )
 {
-  SynchronizeableList::const_iterator it,e;
-  it = this->networkStream->getSyncBegin();
-  e = this->networkStream->getSyncEnd();
-
-  while ( it != e )
-  {
-    if ( (*it)->getUniqueID() == uniqueID )
-    {
-      assert((*it)->isA(CL_WORLD_ENTITY));
-      dynamic_cast<WorldEntity*>(*it)->leaveWorld();
-      dynamic_cast<WorldEntity*>(*it)->toList(OM_DEAD);
-      break;
-    }
-    it++;
-  }
-}
-
-#if 0
-/**
- * Copies length bytes to the clientBuffer with error checking
- * @param clientBuffer: the clientBuffer to write to
- * @param data: buffer to the data
- * @param length: length of data
- * @return false on error true else
- */
-bool NetworkGameManager::writeToClientBuffer( clientBuffer &cb, byte * data, int length )
-{
-  if ( length > cb.maxLength-cb.length )
-  {
-    PRINTF(1)("No space left in clientBuffer\n");
-    return false;
-  }
-
-  memcpy( cb.buffer+cb.length, data, length );
-  return true;
-}
-#endif
-
-#if 0
-/**
- * Reads data from clientBuffer with error checking
- * @param clientBuffer: the clientBuffer to read from
- * @param data: pointer to the buffer
- * @param length:
- * @return
- */
-bool NetworkGameManager::readFromClientBuffer( clientBuffer &cb, byte * data, int length )
-{
-  if ( cb.length < length )
-  {
-    PRINTF(0)("There is not enough data in clientBuffer\n");
-    return 0;
-  }
-
-  memcpy( data, cb.buffer+cb.length-length, length );
-  return true;
-}
-#endif
-
-/**
- * Tells this client that he has to control this entity
- * @param uniqueID: the entity's uniqeID
- */
-void NetworkGameManager::doYouAre( int uniqueID )
-{
-
-  SynchronizeableList::const_iterator it = this->networkStream->getSyncBegin();
-
-  Playable *p = NULL;
-  Synchronizeable *s = NULL;
-
-  for ( ; it !=networkStream->getSyncEnd(); it++ )
-  {
-    if ( (*it)->getUniqueID()==uniqueID )
-    {
-      if ( (*it)->isA( CL_SYNCHRONIZEABLE ) )
-      {
-        s = dynamic_cast<Synchronizeable*>(*it);
-      }
-      if ( (*it)->isA( CL_PLAYABLE ) )
-      {
-        p = dynamic_cast<Playable*>(*it);
-        break;
-      } else
-      {
-        PRINTF(1)("UniqueID %d is not a Playable\n", uniqueID);
-      }
-    }
-  }
-
-  Player* player = State::getPlayer();
-  assert(p != NULL);
-  assert(s != NULL);
-  assert(player != NULL);
-
-  PRINTF(0)("uniqueID = %d\n", s->getUniqueID());
-
-  player->setPlayable(p);
-
-
-}
-
-/**
- * Tells a remote client that he has to control this entity
- * @param uniqueID: the entity's uniqeID
- * @param userID: the users ID
- */
-void NetworkGameManager::sendYouAre( int uniqueID, int userID )
-{
-  if ( !isServer() )
-    return;
-  
   byte buf[INTSIZE];
   
-  Converter::intToByteArray( uniqueID, buf, INTSIZE );
+  assert( Converter::intToByteArray( uniqueId, buf, INTSIZE ) == INTSIZE );
   
-  MessageManager::getInstance()->sendMessage( MSGID_YOU_ARE, buf, INTSIZE, RT_USER, userID, MP_HIGHBANDWIDTH);
-}
-
-bool NetworkGameManager::handleRequestCreate( int & i, const byte * data, int length, int sender )
-{
-  if ( INTSIZE > length-i )
-  {
-    PRINTF(1)("Cannot read classID from buffer! Not enough data left!\n");
-    return false;
-  }
-  int classID;
-  i += Converter::byteArrayToInt( &data[i], &classID );
-
-  createEntity( (ClassID)classID );
-
-  return true;
-}
-
-bool NetworkGameManager::handleRequestRemove( int & i, const byte * data, int length, int sender )
-{
-  if ( INTSIZE > length-i )
-  {
-    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
-    return false;
-  }
-  int uniqueID;
-  i += Converter::byteArrayToInt( &data[i], &uniqueID );
-
-  removeEntity( uniqueID );
-
-  return true;
-}
-
-bool NetworkGameManager::handleCreateEntity( int & i, const byte * data, int length, int sender )
-{
-  if ( INTSIZE > length-i )
-  {
-    PRINTF(1)("Cannot read classID from buffer! Not enough data left!\n");
-    return false;
-  }
-  int classID;
-  i += Converter::byteArrayToInt( &data[i], &classID );
-
-  if ( INTSIZE > length-i )
-  {
-    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
-    return false;
-  }
-  int uniqueID;
-  i += Converter::byteArrayToInt( &data[i], &uniqueID );
-
-  if ( INTSIZE > length-i )
-  {
-    PRINTF(1)("Cannot read owner from buffer! Not enough data left!\n");
-    return false;
-  }
-  int owner;
-  i += Converter::byteArrayToInt( &data[i], &owner );
-
-  PRINTF(0)("handleCreateEntity: client side: classID: %x, uniqueID: %i, owner: %i\n", classID, uniqueID, owner);
-  doCreateEntity( (ClassID)classID, uniqueID, owner );
-
-  return true;
-}
-
-bool NetworkGameManager::handleRemoveEntity( int & i, const byte * data, int length, int sender )
-{
-  if ( INTSIZE > length-i )
-  {
-    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
-    return false;
-  }
-  int uniqueID;
-  i += Converter::byteArrayToInt( &data[i], &uniqueID );
-
-  doRemoveEntity( uniqueID );
-
-  return true;
-}
-
-bool NetworkGameManager::handleCreateEntityList( int & i, const byte * data, int length, int sender )
-{
-  if ( INTSIZE > length-i )
-  {
-    PRINTF(1)("Cannot read n from buffer! Not enough data left!\n");
-    return false;
-  }
-
-  PRINTF(0)("HandleCreateEntityList:  data[i..i+3] = %d %d %d %d\n", data[i], data[i+1], data[i+2], data[i+3]);
-
-  int n;
-  i += Converter::byteArrayToInt( &data[i], &n );
-
-
-  PRINTF(0)("HandleCreateEntityList: n = %d\n", n);
-
-  int classID, uniqueID, owner;
-
-  for ( int j = 0; j<n; j++ )
-  {
-
-    if ( INTSIZE > length-i )
-    {
-      PRINTF(1)("Cannot read classID from buffer! Not enough data left!\n");
-      return false;
-    }
-    i += Converter::byteArrayToInt( &data[i], &classID );
-
-    if ( INTSIZE > length-i )
-    {
-      PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
-      return false;
-    }
-    i += Converter::byteArrayToInt( &data[i], &uniqueID );
-
-    if ( INTSIZE > length-i )
-    {
-      PRINTF(1)("Cannot read owner from buffer! Not enough data left!\n");
-      return false;
-    }
-    i += Converter::byteArrayToInt( &data[i], &owner );
-
-    if ( classID != CL_NETWORK_GAME_MANAGER && classID != CL_HANDSHAKE )
-    {
-      BaseObject* b = doCreateEntity( (ClassID)classID, uniqueID, owner );
-    }
-
-  }
-
-  return true;
-}
-
-bool NetworkGameManager::handleRemoveEntityList( int & i, const byte * data, int length, int sender )
-{
-  if ( INTSIZE > length-i )
-  {
-    PRINTF(1)("Cannot read n from buffer! Not enough data left!\n");
-    return false;
-  }
-  int n;
-  i += Converter::byteArrayToInt( &data[i], &n );
-
-  int uniqueID;
-
-  for ( int j = 0; j<n; j++ )
-  {
-
-    if ( INTSIZE > length-i )
-    {
-      PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
-      return false;
-    }
-    i += Converter::byteArrayToInt( &data[i], &uniqueID );
-
-    doRemoveEntity( uniqueID );
-  }
-
-  return true;
-}
-
-bool NetworkGameManager::handleYouAreEntity( int & i, const byte * data, int length, int sender )
-{
-  if ( INTSIZE > length-i )
-  {
-    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
-    return false;
-  }
-
-  int uniqueID;
-  i += Converter::byteArrayToInt( &data[i], &uniqueID );
-
-  doYouAre( uniqueID );
-
-  return true;
-}
-
-/**
- *  handles the network signal NET_REQUEST_PNODE_PATH
- * @param i byte offset in the buffer
- * @param data data array
- * @param length length of the data arary
- * @param sender the sender id
- * @return true if process terminated sucessfully
- */
-bool NetworkGameManager::handleRequestPNodePath(int& i, const byte* data, int length, int sender)
-{
-  if( INTSIZE > length-i )
-  {
-    PRINTF(1)("Cannot read n from buffer! Not enough data left!\n");
-    return false;
-  }
-  PRINTF(0)("HandleRequestPNodePath:  data[i..i+3] = %d %d %d %d\n", data[i], data[i+1], data[i+2], data[i+3]);
-
-  int uniqueID1, uniqueID2;
-  if( INTSIZE > length-i )
-  {
-    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
-    return false;
-  }
-  i += Converter::byteArrayToInt( &data[i], &uniqueID1 );
-
-  if( INTSIZE > length-i )
-  {
-    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
-    return false;
-  }
-  i += Converter::byteArrayToInt( &data[i], &uniqueID2 );
-
-
-  PRINTF(0)("HandleRequestPNodePath: got a request for path from uid %i to uid %i\n", uniqueID1, uniqueID2);
-
-  return true;
-}
-
-bool NetworkGameManager::youAreHandler( MessageId messageId, byte * data, int dataLength, void * someData, int userId )
-{
-  assert( dataLength == INTSIZE );
-  int uniqueId;
-  
-  Converter::byteArrayToInt( data, &uniqueId );
-  
-  SynchronizeableList::const_iterator it = NetworkGameManager::getInstance()->networkStream->getSyncBegin();
-
-  Playable *p = NULL;
-  Synchronizeable *s = NULL;
-
-  for ( ; it !=NetworkGameManager::getInstance()->networkStream->getSyncEnd(); it++ )
-  {
-    if ( (*it)->getUniqueID()==uniqueId )
-    {
-      break;
-    }
-  }
-  
-  if ( it == NetworkGameManager::getInstance()->networkStream->getSyncEnd() )
-    return false;
-  
-  NetworkGameManager::getInstance()->doYouAre( uniqueId );
-  
-  return true;
-}
-
-#if 0
-bool NetworkGameManager::writeToClientBuffer( clientBuffer & cb, byte b )
-{
-  if ( cb.maxLength-cb.length < 1 )
-  {
-    PRINTF(1)("Cannot write to clientBuffer! Not enough space for 1 byte\n");
-    return false;
-  }
-
-  cb.buffer[cb.length++] = b;
-
-  return true;
+  MessageManager::getInstance()->sendMessage( MSGID_DELETESYNCHRONIZEABLE, buf, INTSIZE, RT_ALL_NOT_ME, 0, MP_HIGHBANDWIDTH );
 }
 
 
-bool NetworkGameManager::writeToClientBuffer( clientBuffer & cb, int i )
-{
-  int n = Converter::intToByteArray( i, cb.buffer+cb.length, cb.maxLength-cb.length );
-  cb.length += n;
-
-  if ( n <= 0 )
-  {
-    PRINTF(1)("Cannot write to clientBuffer! Not enough space for 1 int\n");
-    return false;
-  }
-
-  return true;
-}
-#endif
 
 
+
+
Index: /trunk/src/lib/network/network_game_manager.h
===================================================================
--- /trunk/src/lib/network/network_game_manager.h	(revision 8067)
+++ /trunk/src/lib/network/network_game_manager.h	(revision 8068)
@@ -47,78 +47,25 @@
   public:
     virtual ~NetworkGameManager();
-
+    
     static NetworkGameManager* NetworkGameManager::getInstance()
     { if (!NetworkGameManager::singletonRef) NetworkGameManager::singletonRef = new NetworkGameManager(); return NetworkGameManager::singletonRef; }
 
-#if 0
-    virtual int writeBytes(const byte* data, int length, int sender);
-    virtual int readBytes(byte* data, int maxLength, int * reciever);
-    virtual void writeDebug() const;
-    virtual void readDebug() const;
-#endif
 
-    int createEntity( ClassID classID, int owner = 0 );
-    BaseObject* createEntity(const TiXmlElement* element);
-    void removeEntity( int uniqueID );
-    void sendYouAre( int uniqueID, int userID );
+    bool signalNewPlayer( int userId );
+    bool signalLeftPlayer( int userID );
+    
+    void removeSynchronizeable( int uniqueId );
 
-#if 0
-    void sendEntityList(int userID);
-#endif
-
-    bool signalNewPlayer(int userId);
-    bool signalLeftPlayer(int userID);
-
+    inline void setGameState( int gameState ){ this->gameState = gameState; }
+    inline int getGameState(){ return this->gameState; }
 
   private:
     NetworkGameManager();
     
-    static bool youAreHandler(MessageId messageId, byte * data, int dataLength, void * someData, int userId );
+    static bool delSynchronizeableHandler( MessageId messageId, byte * data, int dataLength, void * someData, int userId );
 
-
-    /* some network signal handlers */
-    bool handleRequestCreate( int& i, const byte* data, int length, int sender );
-    bool handleRequestRemove( int& i, const byte* data, int length, int sender );
-    bool handleCreateEntity( int& i, const byte* data, int length, int sender );
-    bool handleRemoveEntity( int& i, const byte* data, int length, int sender );
-    bool handleCreateEntityList( int& i, const byte* data, int length, int sender );
-    bool handleRemoveEntityList( int& i, const byte* data, int length, int sender );
-    bool handleYouAreEntity( int& i, const byte* data, int length, int sender );
-    bool handleRequestPNodePath(int& i, const byte* data, int length, int sender);
-    bool handleSendPNodePath(int& i, const byte* data, int length, int sender);
-
-
-    /* some network handlers helper functions */
-//    void requestCreateEntity(ClassID classID);
-    int executeCreateEntity(ClassID classID, int uniqueID = 0, int owner = 0);
-    BaseObject* doCreateEntity(ClassID classID, int uniqueID, int owner);
-
-//    void requestRemoveEntity(int uniqueID);
-    void executeRemoveEntity(int uniqueID);
-    void doRemoveEntity(int uniqueID);
-
-    void doYouAre( int uniqueID );
-
-//    void requestPNodePath(const PNode* node1, const PNode* node2);
-    void executeRequestPNodePath(const PNode* node2, const PNode* node2);
-    void doRequestPNodePath(const PNode* node1, const PNode* node2);
-
-    bool canCreateEntity(ClassID classID);
-#if 0
-    void resizeBufferVector(int n);
-
-
-    bool writeToClientBuffer( clientBuffer &cb, byte*data, int length );
-    bool writeToClientBuffer( clientBuffer &cb, byte b );
-    bool writeToClientBuffer( clientBuffer &cb, int i );
-    bool readFromClientBuffer( clientBuffer &cb, byte*data, int length );
-#endif
-
-  private:
-#if 0
-    std::vector<clientBuffer>     outBuffer;
-    //clientBuffer                  allOutBuffer;
-#endif
     static NetworkGameManager*    singletonRef;
+    
+    int                           gameState;
 };
 
Index: /trunk/src/lib/network/network_stream.cc
===================================================================
--- /trunk/src/lib/network/network_stream.cc	(revision 8067)
+++ /trunk/src/lib/network/network_stream.cc	(revision 8068)
@@ -177,4 +177,6 @@
 void NetworkStream::processData()
 {
+  int tick = SDL_GetTicks();
+  
   currentState++;
   
@@ -207,6 +209,6 @@
   // order of up/downstream is important!!!!
   // don't change it
-  handleDownstream();
-  handleUpstream();
+  handleDownstream( tick );
+  handleUpstream( tick );
 
 }
@@ -277,5 +279,5 @@
       PRINTF(0)("Client is gone: %d (%s)\n", it->second.userId, reason.c_str());
       
-      assert(false);
+      //assert(false);
 
       it->second.socket->disconnectServer();
@@ -391,10 +393,10 @@
  * handle upstream network traffic
  */
-void NetworkStream::handleUpstream( )
+void NetworkStream::handleUpstream( int tick )
 {
   int offset;
   int n;
   
-  for ( PeerList::iterator peer = peers.begin(); peer != peers.end(); peer++ )
+  for ( PeerList::reverse_iterator peer = peers.rbegin(); peer != peers.rend(); peer++ )
   {
     offset = INTSIZE; //make already space for length 
@@ -496,6 +498,6 @@
       writeToNewDict( buf, offset );
     
-    peer->second.connectionMonitor->processUnzippedOutgoingPacket( buf, offset, currentState );
-    peer->second.connectionMonitor->processZippedOutgoingPacket( compBuf, compLength, currentState );
+    peer->second.connectionMonitor->processUnzippedOutgoingPacket( tick, buf, offset, currentState );
+    peer->second.connectionMonitor->processZippedOutgoingPacket( tick, compBuf, compLength, currentState );
     
     //NETPRINTF(n)("send packet: %d userId = %d\n", offset, peer->second.userId);
@@ -506,5 +508,5 @@
  * handle downstream network traffic
  */
-void NetworkStream::handleDownstream( )
+void NetworkStream::handleDownstream( int tick )
 {
   int offset = 0;
@@ -527,5 +529,6 @@
     while ( 0 < (compLength = peer->second.socket->readPacket( compBuf, UDP_PACKET_SIZE )) )
     {
-      //TODO tell monitor about zipped packet. because dropped packets dont count to bandwidth
+      peer->second.connectionMonitor->processZippedIncomingPacket( tick, compBuf, compLength );
+      
       //PRINTF(0)("GGGGGOOOOOOOOOOTTTTTTTT: %d\n", compLength);
       packetLength = Zip::getInstance()->unZip( compBuf, compLength, buf, UDP_PACKET_SIZE );
@@ -547,4 +550,6 @@
       //NETPRINTF(n)("ackedstate: %d\n", ackedState);
       offset = 4*INTSIZE;
+      
+      peer->second.connectionMonitor->processUnzippedIncomingPacket( tick, buf, offset, state, ackedState );
 
       //NETPRINTF(n)("got packet: %d, %d\n", length, packetLength);
@@ -672,7 +677,4 @@
       }
       
-      peer->second.connectionMonitor->processZippedIncomingPacket( compBuf, compLength, state, ackedState );
-      peer->second.connectionMonitor->processUnzippedIncomingPacket( buf, offset, state, ackedState );
-    
       assert( peer->second.lastAckedState <= ackedState );
       peer->second.lastAckedState = ackedState;
Index: /trunk/src/lib/network/network_stream.h
===================================================================
--- /trunk/src/lib/network/network_stream.h	(revision 8067)
+++ /trunk/src/lib/network/network_stream.h	(revision 8068)
@@ -79,6 +79,6 @@
     void updateConnectionList();
     void handleHandshakes();
-    void handleUpstream();
-    void handleDownstream(); 
+    void handleUpstream( int tick );
+    void handleDownstream(int tick ); 
     void handleNewClient( int userId );
     void cleanUpOldSyncList();
Index: /trunk/src/lib/network/player_stats.cc
===================================================================
--- /trunk/src/lib/network/player_stats.cc	(revision 8068)
+++ /trunk/src/lib/network/player_stats.cc	(revision 8068)
@@ -0,0 +1,154 @@
+/*
+   orxonox - the future of 3D-vertical-scrollers
+
+   Copyright (C) 2004 orx
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+### File Specific:
+   main-programmer: Christoph Renner
+   co-programmer: ...
+*/
+
+#include "player_stats.h"
+
+#include "class_list.h"
+#include "src/lib/util/loading/factory.h"
+
+#include "player.h"
+#include "state.h"
+
+
+CREATE_FACTORY(PlayerStats, CL_PLAYER_STATS);
+
+/**
+ * constructor
+ */
+PlayerStats::PlayerStats( int userId )
+{
+  init();
+  
+  this->userId = userId;
+}
+
+/**
+ * constructor
+ */
+PlayerStats::PlayerStats( const TiXmlElement* root )
+{
+  init();
+}
+
+void PlayerStats::init( )
+{
+  this->setClassID( CL_PLAYER_STATS, "PlayerStats" );
+
+  this->userId = 0;
+  this->teamId = TEAM_NOTEAM;
+  this->preferedTeamId = TEAM_NOTEAM;
+  this->score = 0;
+  this->playableClassId = 0;
+  this->modelFileName = "";
+  
+  userId_handle = registerVarId( new SynchronizeableInt( &userId, &userId, "userId" ) );
+  teamId_handle = registerVarId( new SynchronizeableInt( &teamId, &teamId, "teamId" ) );
+  preferedTeamId_handle = registerVarId( new SynchronizeableInt( &preferedTeamId, &preferedTeamId, "preferedUserId" ) );
+  score_handle = registerVarId( new SynchronizeableInt( &score, &score, "score" ) );
+  playableClassId_handle = registerVarId( new SynchronizeableInt( &playableClassId, &playableClassId, "playableClassId") );
+  playableUniqueId_handle = registerVarId( new SynchronizeableInt( &playableUniqueId, &playableUniqueId, "playableUniqueId" ) );
+  modelFileName_handle = registerVarId( new SynchronizeableString( &modelFileName, &modelFileName, "modelFileName" ) );
+  
+  PRINTF(0)("PlayerStats created\n");
+}
+
+
+/**
+ * standard deconstructor
+ */
+PlayerStats::~PlayerStats()
+{
+}
+
+
+ /**
+ * override this function to be notified on change
+ * of your registred variables.
+ * @param id id's which have changed
+  */
+void PlayerStats::varChangeHandler( std::list< int > & id )
+{
+  if ( std::find( id.begin(), id.end(), playableUniqueId_handle ) != id.end() )
+  {
+    this->setPlayableUniqueId( this->playableUniqueId );
+    
+    PRINTF(0)("uniqueID changed %d %d\n", userId, getHostID());
+    
+    if ( userId == getHostID() )
+      State::getPlayer()->setPlayable( getPlayable() );
+  }
+}
+
+/**
+ * get stats for user userId
+ * @param userId user's id
+ * @return stats assigned to user
+ */
+PlayerStats * PlayerStats::getStats( int userId )
+{
+  const std::list<BaseObject*> * list = ClassList::getList( CL_PLAYER_STATS );
+  
+  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
+  {
+    if ( dynamic_cast<PlayerStats*>(*it)->getUserId() == userId )
+    {
+      return dynamic_cast<PlayerStats*>(*it);
+    }
+  }
+  
+  //TODO maybe we should create an object here
+  
+  return NULL;
+}
+
+/**
+ * set playable class id and set playable
+ */
+void PlayerStats::setPlayableUniqueId( int uniqueId )
+{
+  const std::list<BaseObject*> * list = ClassList::getList( CL_PLAYABLE );
+  
+  this->playable = NULL;
+  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
+  {
+    if ( dynamic_cast<Playable*>(*it)->getUniqueID() == uniqueId )
+    {
+      this->playable = dynamic_cast<Playable*>(*it);
+      break;
+    }
+  }
+  
+  this->playableUniqueId = uniqueId;
+}
+
+/**
+ * get playable associated to player
+ * @return playable associated to player
+ */
+Playable * PlayerStats::getPlayable()
+{
+  if ( playable )
+    return playable;
+  
+  assert( playableUniqueId > 0 );
+  
+  setPlayableUniqueId( playableUniqueId );
+  
+  assert( playable );
+  
+  return playable;
+}
+
+
Index: /trunk/src/lib/network/player_stats.h
===================================================================
--- /trunk/src/lib/network/player_stats.h	(revision 8068)
+++ /trunk/src/lib/network/player_stats.h	(revision 8068)
@@ -0,0 +1,81 @@
+/*!
+ * @file player_stats.h
+ * @brief Definition of PlayerStats
+ */
+
+#ifndef _PLAYER_STATS_H
+#define _PLAYER_STATS_H
+
+#include "synchronizeable.h"
+#include "playable.h"
+
+#include <string>
+#include <list>
+
+enum
+{
+  TEAM_NOTEAM = -3,
+  TEAM_RANDOM = -2,
+  TEAM_SPECTATOR = -1
+};
+
+//! A class for storing player information
+class PlayerStats : public Synchronizeable 
+{
+
+  public:
+    PlayerStats( const TiXmlElement* root = NULL );
+    PlayerStats( int userId );
+    virtual ~PlayerStats();
+    
+    virtual void varChangeHandler( std::list<int> & id );
+    
+    static PlayerStats * getStats( int userId );
+    
+    inline int getUserId(){ return userId; }
+    
+    inline int getTeamId(){ return teamId; }
+    inline void setTeamId( int teamId ){ this->teamId = teamId; }
+    
+    inline int getPreferedTeamId(){ return preferedTeamId; }
+    inline void setPreferedTeamId( int preferedTeamId ){ this->preferedTeamId = preferedTeamId; }
+    
+    inline int getScore(){ return score; }
+    inline void setScore( int score ){ this->score = score; }
+    
+    inline int getPlayableClassId(){ return playableClassId; }
+    void setPlayableClassId( int classId ){ this->playableClassId = classId; };
+    
+    inline int getPlayableUniqueId(){ return playableUniqueId; }
+    void setPlayableUniqueId( int uniqueId );
+    
+    inline std::string getModelFileName(){ return modelFileName; }
+    inline void setModelFileName( std::string filename ){ modelFileName = filename; }
+    
+    Playable * getPlayable();
+
+  private:
+    int userId;                //!< userId
+    int teamId;                //!< teamId
+    int preferedTeamId;        //!< preferedTeamId
+
+    int score;                 //!< users score points
+    int playableClassId;       //!< players playable class id
+    int playableUniqueId;      //!< playable's uniqueId
+    std::string modelFileName; //!< model filename
+
+    Playable * playable;       //!< pointer to players playable
+
+    // handles for SynchronizeableVars
+    int userId_handle;
+    int teamId_handle;
+    int preferedTeamId_handle;
+    int score_handle;
+    int playableClassId_handle;
+    int playableUniqueId_handle;
+    int modelFileName_handle;
+    
+    void init();
+};
+
+#endif /* _PLAYER_STATS_H */
Index: /trunk/src/lib/network/synchronizeable.cc
===================================================================
--- /trunk/src/lib/network/synchronizeable.cc	(revision 8067)
+++ /trunk/src/lib/network/synchronizeable.cc	(revision 8068)
@@ -21,4 +21,5 @@
 #include "netdefs.h"
 #include "network_log.h"
+#include "network_game_manager.h"
 
 #include "state.h"
@@ -36,5 +37,5 @@
 {
   this->setClassID(CL_SYNCHRONIZEABLE, "Synchronizeable");
-  this->owner = -1;
+  this->owner = 0;
   this->hostID = SharedNetworkData::getInstance()->getHostID();
   this->setIsServer(this->hostID == 0);
@@ -68,4 +69,7 @@
   if ( this->networkStream )
     this->networkStream->disconnectSynchronizeable(*this);
+  
+  if ( this->isServer() && this->beSynchronized() && this->getUniqueID() > 0 )
+    NetworkGameManager::getInstance()->removeSynchronizeable( this->getUniqueID() );
 }
 
@@ -175,4 +179,5 @@
             this->isServer() && (*it)->checkPermission( PERMISSION_SERVER ) ||
             this->owner == this->hostID && (*it)->checkPermission( PERMISSION_OWNER ) ||
+            this->isServer() && this->owner != userId && (*it)->checkPermission( PERMISSION_OWNER ) ||
             (*it)->checkPermission( PERMISSION_ALL ) 
                     );
@@ -289,4 +294,5 @@
         (*it)->checkPermission( PERMISSION_SERVER ) && networkStream->isUserServer( userId ) ||
         (*it)->checkPermission( PERMISSION_OWNER ) && this->owner == userId ||
+        networkStream->isUserServer( userId ) && this->owner != getHostID() && (*it)->checkPermission( PERMISSION_OWNER ) ||
         (*it)->checkPermission( PERMISSION_ALL ) 
        )
@@ -331,5 +337,5 @@
 void Synchronizeable::registerVar( SynchronizeableVar * var )
 {
-  PRINTF(0)("ADDING VAR: %s\n", var->getName().c_str());
+  //PRINTF(0)("ADDING VAR: %s\n", var->getName().c_str());
   syncVarList.push_back( var );
 }
@@ -343,5 +349,5 @@
 int Synchronizeable::registerVarId( SynchronizeableVar * var )
 {
-  PRINTF(0)("ADDING VAR: %s\n", var->getName().c_str());
+  //PRINTF(0)("ADDING VAR: %s\n", var->getName().c_str());
   syncVarList.push_back( var );
   var->setWatched( true );
Index: /trunk/src/lib/network/synchronizeable.h
===================================================================
--- /trunk/src/lib/network/synchronizeable.h	(revision 8067)
+++ /trunk/src/lib/network/synchronizeable.h	(revision 8068)
@@ -61,5 +61,5 @@
     virtual void handleSentState( int userId, int stateId, int fromStateId );
     virtual void handleRecvState( int userId, int stateId, int fromStateId );
-
+    
     void registerVar( SynchronizeableVar * var );
     int registerVarId( SynchronizeableVar * var );
Index: /trunk/src/story_entities/multi_player_world.cc
===================================================================
--- /trunk/src/story_entities/multi_player_world.cc	(revision 8067)
+++ /trunk/src/story_entities/multi_player_world.cc	(revision 8068)
@@ -22,4 +22,6 @@
 #include "util/loading/load_param.h"
 #include "shell_command.h"
+
+#include "cd_engine.h"
 
 #include "network_manager.h"
@@ -86,4 +88,29 @@
 
 /**
+ * kicks the CDEngine to detect the collisions between the object groups in the world
+ */
+void MultiPlayerWorld::collisionDetection()
+{
+  CDEngine::getInstance()->checkCollisions(this->dataTank->objectManager->getObjectList(OM_PLAYERS),
+    this->dataTank->objectManager->getObjectList(OM_PLAYERS));
+  CDEngine::getInstance()->checkCollisions(this->dataTank->objectManager->getObjectList(OM_PLAYERS),
+    this->dataTank->objectManager->getObjectList(OM_PLAYERS_PROJ));
+
+  CDEngine::getInstance()->checkCollisions(this->dataTank->objectManager->getObjectList(OM_GROUP_00),
+    this->dataTank->objectManager->getObjectList(OM_GROUP_01_PROJ));
+  CDEngine::getInstance()->checkCollisions(this->dataTank->objectManager->getObjectList(OM_GROUP_01),
+    this->dataTank->objectManager->getObjectList(OM_GROUP_00_PROJ));
+  CDEngine::getInstance()->checkCollisions(this->dataTank->objectManager->getObjectList(OM_GROUP_00),
+    this->dataTank->objectManager->getObjectList(OM_GROUP_01));
+
+  CDEngine::getInstance()->checkCollisions(this->dataTank->objectManager->getObjectList(OM_GROUP_00),
+    this->dataTank->objectManager->getObjectList(OM_COMMON));
+  CDEngine::getInstance()->checkCollisions(this->dataTank->objectManager->getObjectList(OM_GROUP_01),
+    this->dataTank->objectManager->getObjectList(OM_COMMON));
+
+}
+
+
+/**
  * some debug ouptut - shell command
  */
Index: /trunk/src/story_entities/multi_player_world.h
===================================================================
--- /trunk/src/story_entities/multi_player_world.h	(revision 8067)
+++ /trunk/src/story_entities/multi_player_world.h	(revision 8068)
@@ -31,4 +31,5 @@
   protected:
     virtual void synchronize();
+    virtual void collisionDetection();
 };
 
Index: /trunk/src/story_entities/multi_player_world_data.cc
===================================================================
--- /trunk/src/story_entities/multi_player_world_data.cc	(revision 8067)
+++ /trunk/src/story_entities/multi_player_world_data.cc	(revision 8068)
@@ -45,4 +45,5 @@
 #include "network_manager.h"
 #include "network_game_manager.h"
+#include "player_stats.h"
 
 
@@ -146,5 +147,5 @@
       {
         /* pass the entity to the NetworkGameManager to be created */
-        BaseObject* created = NetworkGameManager::getInstance()->createEntity(element);
+        BaseObject* created = Factory::fabricate(element);
         if( created != NULL )
           PRINTF(1)("Created a %s: %s (0x%8x) from %s\n", created->getClassName(), created->getName(), created->getLeafClassID(), element->Value());
@@ -203,4 +204,5 @@
       this->localPlayer = new Player();
 
+#if 0
       Playable* playable;
       const std::list<BaseObject*>* playableList = ClassList::getList(CL_PLAYABLE);
@@ -215,4 +217,5 @@
         playable->setPlayDirection(Quaternion(M_PI, Vector(0.0, 1.0, 0.0)));
       }
+#endif
     }
     else
@@ -244,4 +247,5 @@
   
   State::setPlayer(this->localPlayer);
+ 
 }
 
@@ -265,4 +269,11 @@
   /* call underlying function */
   GameWorldData::loadScene(root);
+  
+  // create server playable
+  if ( NetworkManager::getInstance()->isGameServer() )
+  {
+    NetworkGameManager::getInstance()->signalNewPlayer( 0 );
+    State::getPlayer()->setPlayable( PlayerStats::getStats( 0 )->getPlayable() );
+  }
 }
 
Index: /trunk/src/util/Makefile.am
===================================================================
--- /trunk/src/util/Makefile.am	(revision 8067)
+++ /trunk/src/util/Makefile.am	(revision 8068)
@@ -10,4 +10,5 @@
 			\
 			game_rules.cc \
+			network_game_rules.cc \
 			multiplayer_team_deathmatch.cc \
 			singleplayer_shootemup.cc \
@@ -34,4 +35,5 @@
 			\
 			game_rules.h \
+			network_game_rules.h \
 			multiplayer_team_deathmatch.h \
 			singleplayer_shootemup.h \
Index: /trunk/src/util/multiplayer_team_deathmatch.cc
===================================================================
--- /trunk/src/util/multiplayer_team_deathmatch.cc	(revision 8067)
+++ /trunk/src/util/multiplayer_team_deathmatch.cc	(revision 8068)
@@ -15,4 +15,6 @@
 #define DEBUG_MODULE_GAME_RULES
 
+#include <map>
+
 #include "multiplayer_team_deathmatch.h"
 
@@ -34,4 +36,6 @@
 #include "space_ships/space_ship.h"
 
+#include "network_game_manager.h"
+
 
 using namespace std;
@@ -45,5 +49,5 @@
  */
 MultiplayerTeamDeathmatch::MultiplayerTeamDeathmatch(const TiXmlElement* root)
-  : GameRules(root)
+  : NetworkGameRules(root)
 {
   this->setClassID(CL_MULTIPLAYER_TEAM_DEATHMATCH, "MultiplayerTeamDeathmatch");
@@ -52,4 +56,7 @@
   this->deathTimeout = 10.0f;     // 5 seconds
   this->timeout = 0.0f;
+  this->numTeams = 2;
+  this->currentGameState = GAMESTATE_PRE_GAME;
+  this->gameStateTimer = 10.0f;
 
   this->deathScreen = new ImagePlane();
@@ -87,4 +94,7 @@
   LoadParam(root, "death-screen-image", this, MultiplayerTeamDeathmatch, setDeathScreen)
       .describe("sets the death screen image");
+  
+  LoadParam(root, "num-teams", this, MultiplayerTeamDeathmatch, setNumTeams)
+      .describe("sets number of teams");
 
 }
@@ -128,4 +138,22 @@
 void MultiplayerTeamDeathmatch::tick(float dt)
 {
+  if ( !SharedNetworkData::getInstance()->isGameServer() )
+    return;
+  
+  gameStateTimer -= dt;
+  PRINTF(0)("TICK %f\n", gameStateTimer);
+  
+  if ( currentGameState != GAMESTATE_GAME && gameStateTimer < 0 )
+    nextGameState();
+  
+  this->currentGameState = NetworkGameManager::getInstance()->getGameState();
+  
+  if ( currentGameState == GAMESTATE_GAME )
+  {
+    handleTeamChanges();
+  }
+  
+  this->calculateTeamScore();
+  
   this->checkGameRules();
 
@@ -164,95 +192,180 @@
 void MultiplayerTeamDeathmatch::checkGameRules()
 {
-
-  Vector big_left(-201, 0, 0);
-  float rBig = 176.0f;
-  Vector big_right(177, 0, 0);
-  Vector small_left(10, 0, 0);
-  Vector small_middle(0, 0, 0);
-  Vector small_right(-10, 0, 0);
-  float rSmall = 90.0f;
-
-
+  if ( !SharedNetworkData::getInstance()->isGameServer() )
+    return;
+  
   // check for max killing count
-  if( this->teamAKills >= this->maxKills)
-  {
-    // team A winns
-  }
-  else if( this->teamBKills >= this->maxKills)
-  {
-    // team B winns
-  }
-
-
-  if ( SharedNetworkData::getInstance()->isGameServer() )
-  {
-    float offsetx = 500.0f;
-    float offsety = 323.0f;
-    float offsetz = 200.0f;
-
-    offsetz += 10;
-
-    Terrain * terrain = dynamic_cast<Terrain*>(*(ClassList::getList( CL_TERRAIN )->begin()));
-    const std::list<BaseObject*> * list = ClassList::getList( CL_SPACE_SHIP );
-    for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++)
-    {
-      SpaceShip * ss = dynamic_cast<SpaceShip*>(*it);
-      float terrx = ss->getAbsCoor().x + offsetx;
-      float terry = ss->getAbsCoor().z + offsetz;
-      float terrz = ss->getAbsCoor().y + offsety;
-      if ( terrz < terrain->getHeight( terrx, terry ) && ss->getAbsCoor().x > -1000 )
+  for ( int i = 0; i<numTeams; i++ )
+  {
+    if ( teamScore[i] >= maxKills )
+    {
+      //team i wins
+      //TODO
+    }
+  }
+}
+
+/**
+ * find group for new player
+ * @return group id
+ */
+int MultiplayerTeamDeathmatch::getTeamForNewUser( )
+{
+  return TEAM_NOTEAM;
+}
+
+ClassID MultiplayerTeamDeathmatch::getPlayableClassId( int team )
+{
+  return CL_SPECTATOR;
+}
+
+std::string MultiplayerTeamDeathmatch::getPlayableModelFileName( int team, ClassID classId )
+{
+  return "";
+}
+
+/**
+ * calculate team score
+ */
+void MultiplayerTeamDeathmatch::calculateTeamScore( )
+{
+  teamScore.clear();
+  
+  for ( int i = 0; i<numTeams; i++ )
+    teamScore[i] = 0;
+  
+    
+  const std::list<BaseObject*> * list = ClassList::getList( CL_PLAYER_STATS );
+  
+  if ( !list )
+    return;
+  
+  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
+  {
+    PlayerStats & stats = *dynamic_cast<PlayerStats*>(*it);
+
+    if ( stats.getTeamId() >= 0 )
+    {
+      teamScore[stats.getTeamId()] += stats.getScore();
+    }
+  }
+}
+
+/**
+ * get team for player who choose to join random team
+ * @return smallest team
+ */
+int MultiplayerTeamDeathmatch::getRandomTeam( )
+{
+  std::map<int,int> playersInTeam;
+  
+  for ( int i = 0; i<numTeams; i++ )
+    playersInTeam[i] = 0;
+  
+  const std::list<BaseObject*> * list = ClassList::getList( CL_PLAYER_STATS );
+  
+  if ( !list )
+    return 0;
+  
+  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
+  {
+    PlayerStats & stats = *dynamic_cast<PlayerStats*>(*it);
+
+    if ( stats.getTeamId() >= 0 )
+    {
+      playersInTeam[stats.getTeamId()]++;
+    }
+  }
+  
+  
+  int minPlayers = 0xFFFF;
+  int minTeam = -1;
+  
+  for ( int i = 0; i<numTeams; i++ )
+  {
+    if ( playersInTeam[i] < minPlayers )
+    {
+      minTeam = i;
+      minPlayers = playersInTeam[i];
+    }
+  }
+  
+  assert( minTeam != -1 );
+  
+  return minTeam;
+}
+
+void MultiplayerTeamDeathmatch::nextGameState( )
+{
+  if ( currentGameState == GAMESTATE_PRE_GAME )
+  {
+    NetworkGameManager::getInstance()->setGameState( GAMESTATE_GAME );
+    
+    return;
+  }
+  
+  if ( currentGameState == GAMESTATE_GAME )
+  {
+    NetworkGameManager::getInstance()->setGameState( GAMESTATE_POST_GAME );
+    
+    return;
+  }
+  
+  if ( currentGameState == GAMESTATE_POST_GAME )
+  {
+    //TODO end game
+    
+    return;
+  }
+}
+
+void MultiplayerTeamDeathmatch::handleTeamChanges( )
+{
+  const std::list<BaseObject*> * list = ClassList::getList( CL_PLAYER_STATS );
+  
+  if ( !list )
+    return;
+  
+  //first server players with choices
+  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
+  {
+    PlayerStats & stats = *dynamic_cast<PlayerStats*>(*it);
+
+    if ( stats.getTeamId() != stats.getPreferedTeamId() )
+    {
+      if ( stats.getPreferedTeamId() == TEAM_SPECTATOR || ( stats.getPreferedTeamId() <= 0 && stats.getPreferedTeamId() < numTeams ) )
       {
-        //TODO handle this
+        teamChange( stats.getUserId() );
       }
-
-
-      float dist = (dynamic_cast<Playable*>(*it)->getAbsCoor() - big_left).len();
-      if( (dynamic_cast<Playable*>(*it)->getAbsCoor() - big_left).len() > rBig &&
-           (dynamic_cast<Playable*>(*it)->getAbsCoor() - big_right).len() > rBig &&
-           (dynamic_cast<Playable*>(*it)->getAbsCoor() - small_left).len() > rSmall &&
-           (dynamic_cast<Playable*>(*it)->getAbsCoor() - small_middle).len() > rSmall &&
-           (dynamic_cast<Playable*>(*it)->getAbsCoor() - small_right).len() > rSmall
-           && ss->getAbsCoor().x > -1000)
+    }
+  }
+  
+  //now serve player who want join a random team
+  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
+  {
+    PlayerStats & stats = *dynamic_cast<PlayerStats*>(*it);
+
+    if ( stats.getTeamId() != stats.getPreferedTeamId() )
+    {
+      if ( stats.getPreferedTeamId() == TEAM_RANDOM )
       {
-        PRINTF(0)("KILLLLLLLL\n");
-
-        if((*it)->isA(CL_SPACE_SHIP))
-        {
-          //TODO handle this
-        }
+        stats.setPreferedTeamId( getTeamForNewUser() );
+        teamChange( stats.getUserId() );
       }
     }
   }
-
-
-#if 0
-  std::list<BaseObject*>::const_iterator it;
-  const std::list<BaseObject*>* list = ClassList::getList(CL_PLAYABLE);
-
-  if( SharedNetworkData::getInstance()->isGameServer())
-  {
-    for(it = list->begin(); it != list->end(); it++)
-    {
-      float dist = (dynamic_cast<Playable*>(*it)->getAbsCoor() - big_left).len();
-      if( (dynamic_cast<Playable*>(*it)->getAbsCoor() - big_left).len() > rBig &&
-           (dynamic_cast<Playable*>(*it)->getAbsCoor() - big_right).len() > rBig &&
-           (dynamic_cast<Playable*>(*it)->getAbsCoor() - small_left).len() > rSmall &&
-           (dynamic_cast<Playable*>(*it)->getAbsCoor() - small_middle).len() > rSmall &&
-           (dynamic_cast<Playable*>(*it)->getAbsCoor() - small_right).len() > rSmall)
-      {
-        PRINTF(0)("KILLLLLLLL\n");
-
-        if((*it)->isA(CL_SPACE_SHIP))
-          dynamic_cast<SpaceShip*>(*it)->doCollideNetwork(116369220.33434f);
-      }
-    }
-  }
-#endif
-
-}
-
-
-
-
-
-
+}
+
+void MultiplayerTeamDeathmatch::teamChange( int userId )
+{
+  assert( PlayerStats::getStats( userId ) );
+  PlayerStats & stats = *(PlayerStats::getStats( userId ));
+  
+  assert(false);
+}
+
+
+
+
+
+
Index: /trunk/src/util/multiplayer_team_deathmatch.h
===================================================================
--- /trunk/src/util/multiplayer_team_deathmatch.h	(revision 8067)
+++ /trunk/src/util/multiplayer_team_deathmatch.h	(revision 8068)
@@ -10,5 +10,5 @@
 #define _MULTIPLAYER_TEAM_DEATHMATCH_H
 
-#include "game_rules.h"
+#include "network_game_rules.h"
 
 
@@ -18,6 +18,13 @@
 class ImagePlane;
 
+enum
+{
+  GAMESTATE_PRE_GAME = 0,
+  GAMESTATE_GAME,
+  GAMESTATE_POST_GAME
+};
 
-class MultiplayerTeamDeathmatch : public GameRules
+
+class MultiplayerTeamDeathmatch : public NetworkGameRules
 {
 
@@ -28,4 +35,7 @@
     virtual void loadParams(const TiXmlElement* root);
 
+    virtual int getTeamForNewUser();
+    virtual ClassID getPlayableClassId( int team );
+    virtual std::string getPlayableModelFileName( int team, ClassID classId );
 
     virtual void onPlayerSpawn();
@@ -39,4 +49,9 @@
     inline void setMaxKills(int kills) { this->maxKills = kills; }
     void setDeathScreen(const std::string& imageName);
+    
+    inline void setNumTeams( int numTeams ){ this->numTeams = numTeams; }
+    inline int getNumTeams(){ return this->numTeams; }
+    
+    int getRandomTeam();
 
   protected:
@@ -49,8 +64,17 @@
     int                maxKills;                   //!< max kills for winning condition
 
-    int                teamAKills;                 //!< kills of team A
-    int                teamBKills;                 //!< kills of team B
+    int                numTeams;                   //!< number of teams
 
-    ImagePlane*         deathScreen;                //!< the death screen
+    std::map<int,int>  teamScore;                  //!< team score
+
+    ImagePlane*        deathScreen;                //!< the death screen
+
+    int                currentGameState;           //!< game state
+    float              gameStateTimer;             //!< if less than 0 -> change game state
+
+    void calculateTeamScore();
+    void nextGameState();
+    void handleTeamChanges();
+    void teamChange( int userId );
 };
 
Index: /trunk/src/util/network_game_rules.cc
===================================================================
--- /trunk/src/util/network_game_rules.cc	(revision 8068)
+++ /trunk/src/util/network_game_rules.cc	(revision 8068)
@@ -0,0 +1,54 @@
+/*
+   orxonox - the future of 3D-vertical-scrollers
+
+   Copyright (C) 2004 orx
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+### File Specific:
+   main-programmer: ...
+   co-programmer: ...
+*/
+
+//#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_
+
+#include "network_game_rules.h"
+
+using namespace std;
+
+
+/**
+ * standard constructor
+ */
+NetworkGameRules::NetworkGameRules ( const TiXmlElement* root )
+  : GameRules( root )
+{
+  this->setClassID( CL_NETWORK_GAME_RULES, "NetworkGameRules");
+}
+
+
+/**
+ * standard deconstructor
+ */
+NetworkGameRules::~NetworkGameRules ()
+{
+}
+
+std::string NetworkGameRules::getPlayableModelFileName( int team, ClassID classId )
+{
+  return "models/ships/reap_#.obj";
+}
+
+ClassID NetworkGameRules::getPlayableClassId( int team )
+{
+  return CL_SPACE_SHIP;
+}
+
+int NetworkGameRules::getTeamForNewUser( )
+{
+  return 0;
+}
+
Index: /trunk/src/util/network_game_rules.h
===================================================================
--- /trunk/src/util/network_game_rules.h	(revision 8068)
+++ /trunk/src/util/network_game_rules.h	(revision 8068)
@@ -0,0 +1,33 @@
+/*!
+ * @file network_game_rules.h
+ * @brief Definition of NetworkGameRules
+ */
+
+#ifndef _NETWORK_GAME_RULES_H
+#define _NETWORK_GAME_RULES_H
+
+#include "game_rules.h"
+
+#include "player_stats.h"
+
+class TiXmlElement;
+
+class NetworkGameRules : public GameRules
+{
+
+  public:
+    NetworkGameRules( const TiXmlElement* root );
+    virtual ~NetworkGameRules();
+    
+    virtual int getTeamForNewUser();
+    virtual ClassID getPlayableClassId( int team );
+    virtual std::string getPlayableModelFileName( int team, ClassID classId );
+    
+    virtual PlayerStats * getNewPlayerStats( int userId ){ return new PlayerStats( userId ); }
+
+
+  private:
+
+};
+
+#endif /* _NETWORK_GAME_RULES_H */
Index: /trunk/src/util/object_manager.h
===================================================================
--- /trunk/src/util/object_manager.h	(revision 8067)
+++ /trunk/src/util/object_manager.h	(revision 8068)
@@ -20,4 +20,7 @@
   OM_BACKGROUND,
   OM_COMMON,
+
+  OM_PLAYERS,
+  OM_PLAYERS_PROJ,
 
   OM_GROUP_00,
Index: /trunk/src/util/signal_handler.cc
===================================================================
--- /trunk/src/util/signal_handler.cc	(revision 8067)
+++ /trunk/src/util/signal_handler.cc	(revision 8068)
@@ -81,10 +81,10 @@
   assert( pid != -1 );
 
+
   if ( pid == 0 )
   {
     getInstance()->dontCatch();
-
+    
     sleep(2);
-
 
     return;
@@ -92,4 +92,5 @@
   else
   {
+    getInstance()->dontCatch();
     if ( getInstance()->type == GDB_RUN_WRITE_TO_FILE && fork() == 0 )
     {
@@ -104,5 +105,5 @@
     {
       dup2( fd[0], STDIN_FILENO );
-      snprintf( command, 255, "gdb -p %d %s 1>" GDB_BT_FILE " 2>&1", pid, getInstance()->appName.c_str() );
+      snprintf( command, 255, "gdb -p %d %s 1>>" GDB_BT_FILE " 2>&1", pid, getInstance()->appName.c_str() );
     }
     else
Index: /trunk/src/world_entities/WorldEntities.am
===================================================================
--- /trunk/src/world_entities/WorldEntities.am	(revision 8067)
+++ /trunk/src/world_entities/WorldEntities.am	(revision 8068)
@@ -39,4 +39,5 @@
                 world_entities/space_ships/turbine_hover.cc \
                 world_entities/creatures/md2_creature.cc \
+                world_entities/spectator.cc \
                 \
                 \
@@ -90,4 +91,5 @@
                 space_ships/turbine_hover.h \
                 creatures/md2_creature.h \
+                spectator.h \
                 \
                 environments/water.h \
Index: /trunk/src/world_entities/spawning_point.cc
===================================================================
--- /trunk/src/world_entities/spawning_point.cc	(revision 8067)
+++ /trunk/src/world_entities/spawning_point.cc	(revision 8068)
@@ -20,5 +20,9 @@
 #include "util/loading/factory.h"
 
+#include "world_entity.h"
+
 #include "compiler.h"
+
+#include <map>
 
 
@@ -26,8 +30,8 @@
  *  constructor
  */
-SpawningPoint::SpawningPoint (ClassID classID, const Vector& position)
+SpawningPoint::SpawningPoint (ClassID classid, const Vector& position)
 {
   this->setAbsCoor(position);
-  this->classID = classID;
+  this->classid = classid;
   this->mode = SPT_ALL_AT_ONCE;
   this->delay = 0;
@@ -40,8 +44,8 @@
  *  standard constructor
  */
-SpawningPoint::SpawningPoint (const Vector& position, ClassID classID, SpawningPointMode mode, float delay)
+SpawningPoint::SpawningPoint (const Vector& position, ClassID classid, SpawningPointMode mode, float delay)
 {
   this->setAbsCoor(position);
-  this->classID = classID;
+  this->classid = classid;
   this->mode = mode;
   this->delay = delay;
@@ -90,16 +94,26 @@
 
 
+
+/**
+ * pushes a world entity to the spawning queue
+ *  @param entity WorldEntity to be added
+ */
+void SpawningPoint::pushEntity(WorldEntity* entity, float delay)
+{
+  this->queue[entity] = this->localTimer + delay;
+}
+
+
 /**
  *  spawn the entity
  */
-void SpawningPoint::spawn()
+void SpawningPoint::spawn(WorldEntity* entity)
 {
-  PRINTF(5)("Spangingpoint creates a new Entity (id: %i, delay: %f, mode: %f)\n", this->classID,
-            this->delay, this->mode);
+  PRINTF(1)("Spawningpoint spawns new Entity (%s)\n", entity->getClassName());
+
 
   //BaseObject* spawningEntity = Factory::fabricate(this->classID);
-
-//   if( likely(this->world != NULL))
-//     this->world->spawn(dynamic_cast<WorldEntity*>(spawningEntity));
+  //   if( likely(this->world != NULL))
+  //     this->world->spawn(dynamic_cast<WorldEntity*>(spawningEntity));
 }
 
@@ -114,9 +128,16 @@
 {
   this->localTimer += dt;
-  if( this->localTimer > this->delay)
+
+  std::map<WorldEntity*, float>::iterator it = this->queue.begin();
+  for( ; it != this->queue.end(); it++)
   {
-    this->spawn();
-    this->localTimer = 0.0f;
+    //
+    if( it->second <= this->localTimer)
+    {
+      //spawn the player
+      this->spawn(it->first);
+    }
   }
+
 }
 
Index: /trunk/src/world_entities/spawning_point.h
===================================================================
--- /trunk/src/world_entities/spawning_point.h	(revision 8067)
+++ /trunk/src/world_entities/spawning_point.h	(revision 8068)
@@ -9,4 +9,6 @@
 
 #include "world_entity.h"
+
+#include <map>
 
 class World;
@@ -43,5 +45,5 @@
 
     /**  sets the entity that is going to be spawned by this point @param classID: the id from the class_id.h file */
-    void SpawningPoint::setSpawningEntity(ClassID classID) { this->classID = classID; }
+    void SpawningPoint::setSpawningEntity(ClassID classid) { this->classid = classid; }
     /** sets the frequency with which the point is going to spawn entities (1/sec) @param frequency: the frequency */
     void SpawningPoint::setSpawningDelay(float delay) { this->delay = delay; }
@@ -49,9 +51,11 @@
     void SpawningPoint::setSpawningMode(int mode) { this->mode = (SpawningPointMode)mode; }
 
+    void pushEntity(WorldEntity* entity, float delay = 0);
 
     /** activates the spawning point */
-    void activate() { this->bSpawning = true; }
+    inline void activate() { this->bSpawning = true; }
     /** deactivates the spawning point */
-    void deactivate() { this->bSpawning = false; }
+    inline void deactivate() { this->bSpawning = false; }
+    inline bool isActive() const { return this->bSpawning; }
 
 
@@ -61,15 +65,15 @@
 
   private:
-    void spawn();
+    void spawn(WorldEntity* entity);
 
 
   private:
-    float                     delay;                          //!< the timer that counts down until the next spawn
-    float                     localTimer;                     //!< the local timer
-    float                     seed;                           //!< the random seed of the position
-    ClassID                   classID;                        //!< the classid of the entity to spawn
-    SpawningPointMode         mode;                           //!< the mode of the spawning point
-    ObjectManager::EntityList   queue;                          //!< queue of waiting WorldEntities to be spawned
-    bool                      bSpawning;                      //!< flag to indicate if this spawning point is active or not
+    float                           delay;                          //!< the timer that counts down until the next spawn
+    float                           localTimer;                     //!< the local timer
+    float                           seed;                           //!< the random seed of the position
+    ClassID                         classid;                        //!< the classid of the entity to spawn
+    SpawningPointMode               mode;                           //!< the mode of the spawning point
+    std::map<WorldEntity*, float>   queue;                          //!< queue of waiting WorldEntities to be spawned
+    bool                            bSpawning;                      //!< flag to indicate if this spawning point is active or not
 };
 
Index: /trunk/src/world_entities/spectator.cc
===================================================================
--- /trunk/src/world_entities/spectator.cc	(revision 8068)
+++ /trunk/src/world_entities/spectator.cc	(revision 8068)
@@ -0,0 +1,134 @@
+/*
+   orxonox - the future of 3D-vertical-scrollers
+
+   Copyright (C) 2004 orx
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+### File Specific:
+   main-programmer: Christoph Renner
+   co-programmer: ...
+
+*/
+
+#include "spectator.h"
+
+#include "src/lib/util/loading/factory.h"
+#include "key_mapper.h"
+
+
+CREATE_FACTORY(Spectator, CL_SPECTATOR);
+
+
+/**
+ * constructor
+ */
+Spectator::Spectator( const TiXmlElement * root )
+{
+  this->setClassID(CL_SPECTATOR, "Spectator");
+  
+  bool                  bLeft;
+  bool                  bRight;
+  bool                  bForward;
+  bool                  bBackward;
+    
+  float                 xMouse;             //!< mouse moved in x-Direction
+  float                 yMouse;             //!< mouse moved in y-Direction
+
+  this->bLeft = false;
+  this->bRight = false;
+  this->bForward = false;
+  this->bBackward = false;
+  this->xMouse = 0.0f;
+  this->yMouse = 0.0f;
+    
+  registerEvent(KeyMapper::PEV_FORWARD);
+  registerEvent(KeyMapper::PEV_BACKWARD);
+  registerEvent(KeyMapper::PEV_LEFT);
+  registerEvent(KeyMapper::PEV_RIGHT);
+  registerEvent(KeyMapper::PEV_FIRE1);
+  registerEvent(EV_MOUSE_MOTION);
+  
+  registerVar( new SynchronizeableBool( &bLeft, &bLeft, "bLeft", PERMISSION_OWNER ) );
+  registerVar( new SynchronizeableBool( &bRight, &bRight, "bRight", PERMISSION_OWNER ) );
+  registerVar( new SynchronizeableBool( &bForward, &bForward, "bForward", PERMISSION_OWNER ) );
+  registerVar( new SynchronizeableBool( &bBackward, &bBackward, "bBackward", PERMISSION_OWNER ) );
+  registerVar( new SynchronizeableQuaternion( &mouseDir, &mouseDir, "mouseDir", PERMISSION_OWNER ) );
+}
+
+/**
+ * destructor
+ */
+Spectator::~Spectator( )
+{
+  this->setPlayer(NULL);
+}
+
+void Spectator::setPlayDirection( const Quaternion & rot, float speed )
+{
+  this->mouseDir =  rot;
+  this->rotY = Quaternion( rot.getHeading(), Vector( 0, 1, 0) );
+  this->rotAxis = Quaternion( rot.getAttitude(), Vector( 0, 0, 1 ) );
+}
+
+void Spectator::enter( )
+{
+  this->attachCamera();
+}
+
+void Spectator::leave( )
+{
+  this->detachCamera();
+}
+
+/**
+ * collision handling
+ * @param entity other entity
+ * @param location 
+ * @todo dont allow spectator to go through walls
+ */
+void Spectator::collidesWith( WorldEntity * entity, const Vector & location )
+{
+}
+
+void Spectator::tick( float time )
+{
+  Playable::tick( time );
+  
+  if( ( xMouse != 0 || yMouse != 0 ) && this->getOwner() == this->getHostID() )
+  {
+    xMouse *= time / 10;
+    yMouse *= time / 10;
+    
+    this->rotY *= Quaternion(-M_PI/4.0*this->xMouse, Vector(0,1,0));
+    this->rotAxis *= Quaternion(-M_PI/4.0*this->yMouse, Vector(0,0,1) );
+
+    this->mouseDir = rotY * rotAxis;
+    //this->mouseDir *= Quaternion(-M_PI/4.0*this->yMouse, Vector(0,0,1));
+    xMouse = yMouse = 0;
+  }
+  
+  this->setAbsDir( this->mouseDir );
+}
+
+void Spectator::process( const Event & event )
+{
+  Playable::process(event);
+
+  if( event.type == KeyMapper::PEV_LEFT)
+    this->bLeft = event.bPressed;
+  else if( event.type == KeyMapper::PEV_RIGHT)
+    this->bRight = event.bPressed;
+  else if( event.type == KeyMapper::PEV_FORWARD)
+    this->bForward = event.bPressed; //this->shiftCoor(0,.1,0);
+  else if( event.type == KeyMapper::PEV_BACKWARD)
+    this->bBackward = event.bPressed; //this->shiftCoor(0,-.1,0);
+  else if( event.type == EV_MOUSE_MOTION)
+  {
+    this->xMouse += event.xRel;
+    this->yMouse += event.yRel;
+  }
+}
Index: /trunk/src/world_entities/spectator.h
===================================================================
--- /trunk/src/world_entities/spectator.h	(revision 8068)
+++ /trunk/src/world_entities/spectator.h	(revision 8068)
@@ -0,0 +1,41 @@
+/*!
+ * @file cpectator.h
+ * Implements a playable for lazy people
+ */
+
+#ifndef _SPECTATOR_H
+#define _SPECTATOR_H
+
+#include "playable.h"
+
+class Spectator : public Playable
+{
+  public:
+    Spectator( const TiXmlElement* root = NULL );
+    virtual ~Spectator();
+    
+    virtual void setPlayDirection(const Quaternion& rot, float speed = 0.0f);
+
+    virtual void enter();
+    virtual void leave();
+    
+    virtual void collidesWith(WorldEntity* entity, const Vector& location);
+    virtual void tick(float time);
+
+    virtual void process(const Event &event);
+    
+  private:
+    bool                  bLeft;
+    bool                  bRight;
+    bool                  bForward;
+    bool                  bBackward;
+    
+    float                 xMouse;             //!< mouse moved in x-Direction
+    float                 yMouse;             //!< mouse moved in y-Direction
+    Quaternion            mouseDir;           //!< the direction where the player wants to fly
+
+    Quaternion            rotY;
+    Quaternion            rotAxis;
+};
+
+#endif
