Index: branches/network/src/lib/network/message_manager.h
===================================================================
--- branches/network/src/lib/network/message_manager.h	(revision 8070)
+++ branches/network/src/lib/network/message_manager.h	(revision 8096)
@@ -29,5 +29,6 @@
 {
   TESTMESSAGEID = 1,
-  MSGID_DELETESYNCHRONIZEABLE
+  MSGID_DELETESYNCHRONIZEABLE,
+  MSGID_PREFEREDTEAM
 };
 
Index: branches/network/src/lib/network/network_game_manager.cc
===================================================================
--- branches/network/src/lib/network/network_game_manager.cc	(revision 8070)
+++ branches/network/src/lib/network/network_game_manager.cc	(revision 8096)
@@ -59,4 +59,5 @@
   
   MessageManager::getInstance()->registerMessageHandler( MSGID_DELETESYNCHRONIZEABLE, delSynchronizeableHandler, NULL );
+  MessageManager::getInstance()->registerMessageHandler( MSGID_PREFEREDTEAM, preferedTeamHandler, NULL );
   
   this->gameState = 0;
@@ -86,6 +87,6 @@
   
   int team = rules.getTeamForNewUser();
-  ClassID playableClassId = rules.getPlayableClassId( team );
-  std::string playableModel = rules.getPlayableModelFileName( team, playableClassId );
+  ClassID playableClassId = rules.getPlayableClassId( userId, team );
+  std::string playableModel = rules.getPlayableModelFileName( userId, team, playableClassId );
   
   BaseObject * bo = Factory::fabricate( playableClassId );
@@ -180,5 +181,59 @@
 
 
-
-
-
+/**
+ * handler for MSGID_PREFEREDTEAM message
+ * @param messageId 
+ * @param data 
+ * @param dataLength 
+ * @param someData 
+ * @param userId 
+ * @return 
+ */
+bool NetworkGameManager::preferedTeamHandler( MessageId messageId, byte * data, int dataLength, void * someData, int userId )
+{
+  assert( NetworkGameManager::getInstance()->isServer() );
+  
+  int teamId = 0;
+  int len = Converter::byteArrayToInt( data, &teamId );
+  
+  if ( len != dataLength )
+  {
+    PRINTF(2)("Recieved DeleteSynchronizeable message with incorrect size (%d) from client %d!\n", dataLength, userId);
+    return true;
+  }
+  
+  NetworkGameManager::getInstance()->setPreferedTeam( userId, teamId );
+}
+
+void NetworkGameManager::setPreferedTeam( int userId, int teamId )
+{
+  if ( !PlayerStats::getStats( userId ) )
+    return;
+  
+  PlayerStats & stats = *(PlayerStats::getStats( userId ));
+  
+  stats.setPreferedTeamId( teamId );
+  
+}
+
+/**
+ * set prefered team for this host
+ * @param teamId 
+ */
+void NetworkGameManager::prefereTeam( int teamId )
+{
+  if ( isServer() )
+    setPreferedTeam( getHostID(), teamId );
+  else
+  {
+    byte buf[INTSIZE];
+    
+    assert( Converter::intToByteArray( teamId, buf, INTSIZE) == INTSIZE );
+    
+    MessageManager::getInstance()->sendMessage( MSGID_PREFEREDTEAM, buf, INTSIZE, RT_USER, 0, MP_HIGHBANDWIDTH );
+  }
+}
+
+
+
+
Index: branches/network/src/lib/network/network_game_manager.h
===================================================================
--- branches/network/src/lib/network/network_game_manager.h	(revision 8070)
+++ branches/network/src/lib/network/network_game_manager.h	(revision 8096)
@@ -56,4 +56,6 @@
     
     void removeSynchronizeable( int uniqueId );
+    
+    void prefereTeam( int teamId );
 
     inline void setGameState( int gameState ){ this->gameState = gameState; }
@@ -64,4 +66,7 @@
     
     static bool delSynchronizeableHandler( MessageId messageId, byte * data, int dataLength, void * someData, int userId );
+    static bool preferedTeamHandler( MessageId messageId, byte * data, int dataLength, void * someData, int userId );
+    
+    void setPreferedTeam( int userId, int teamId );
 
     static NetworkGameManager*    singletonRef;
Index: branches/network/src/lib/network/player_stats.cc
===================================================================
--- branches/network/src/lib/network/player_stats.cc	(revision 8070)
+++ branches/network/src/lib/network/player_stats.cc	(revision 8096)
@@ -86,7 +86,4 @@
     
     PRINTF(0)("uniqueID changed %d %d\n", userId, getHostID());
-    
-    if ( userId == getHostID() )
-      State::getPlayer()->setPlayable( getPlayable() );
   }
 }
@@ -100,4 +97,7 @@
 {
   const std::list<BaseObject*> * list = ClassList::getList( CL_PLAYER_STATS );
+  
+  if ( !list )
+    return NULL;
   
   for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
@@ -121,4 +121,10 @@
   const std::list<BaseObject*> * list = ClassList::getList( CL_PLAYABLE );
   
+  if ( !list )
+  {
+    this->playableUniqueId = uniqueId;
+    return;
+  }
+  
   this->playable = NULL;
   for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
@@ -130,4 +136,7 @@
     }
   }
+  
+  if ( /*this->playable &&*/ userId == getHostID() )
+    State::getPlayer()->setPlayable( this->playable );
   
   this->playableUniqueId = uniqueId;
Index: branches/network/src/lib/network/synchronizeable.cc
===================================================================
--- branches/network/src/lib/network/synchronizeable.cc	(revision 8070)
+++ branches/network/src/lib/network/synchronizeable.cc	(revision 8096)
@@ -108,5 +108,8 @@
 
   for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
+  {
+    //PRINTF(0)("SIZE = %d %s\n", (*it)->getSize(), (*it)->getName().c_str());
     neededSize += (*it)->getSize();
+  }
 
   if ( !( neededSize <= maxLength ) )
@@ -183,5 +186,5 @@
                     );
     
-    if ( ( hasPermission && (*it)->getPriority() >= priorityTH ) || sizeIter == stateFrom->sizeList.end() )
+    if ( ( sizeIter != stateFrom->sizeList.end() && *sizeIter != (*it)->getSize() ) || ( hasPermission && (*it)->getPriority() >= priorityTH ) || sizeIter == stateFrom->sizeList.end() )
     {
       n = (*it)->writeToBuf( stateTo->data+i, stateTo->dataLength - i );
@@ -209,5 +212,9 @@
   sentStates[userId].push_back( stateTo );
   
-  assert( i == neededSize );
+  if ( i != neededSize )
+  {
+    PRINTF(0)("strange error: (%s) %d != %d\n", this->getClassName(), i, neededSize);
+    assert(false);
+  }
 
   //write diff to data
Index: branches/network/src/lib/network/synchronizeable_var/synchronizeable_string.cc
===================================================================
--- branches/network/src/lib/network/synchronizeable_var/synchronizeable_string.cc	(revision 8070)
+++ branches/network/src/lib/network/synchronizeable_var/synchronizeable_string.cc	(revision 8096)
@@ -48,4 +48,5 @@
   
   assert( res > 0 );
+  assert( res == vPtrIn->length()+INTSIZE );
   
   return res;
Index: branches/network/src/util/multiplayer_team_deathmatch.cc
===================================================================
--- branches/network/src/util/multiplayer_team_deathmatch.cc	(revision 8070)
+++ branches/network/src/util/multiplayer_team_deathmatch.cc	(revision 8096)
@@ -37,4 +37,10 @@
 
 #include "network_game_manager.h"
+
+#include "event_handler.h"
+
+#include "glgui.h"
+
+#include "story_entity.h"
 
 
@@ -59,4 +65,6 @@
   this->currentGameState = GAMESTATE_PRE_GAME;
   this->gameStateTimer = 10.0f;
+  
+  this->box = NULL;
 
   this->deathScreen = new ImagePlane();
@@ -138,9 +146,71 @@
 void MultiplayerTeamDeathmatch::tick(float dt)
 {
+  //on client side hostId is -1 until hanshake finished
+  if ( SharedNetworkData::getInstance()->getHostID() < 0 )
+    return;
+  
+  if ( currentGameState == GAMESTATE_PRE_GAME )
+  {
+    if ( PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() )
+         && PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() )->getPreferedTeamId() == TEAM_NOTEAM 
+         && box == NULL
+       )
+    {
+      EventHandler::getInstance()->pushState( ES_MENU );
+      
+      OrxGui::GLGuiHandler::getInstance()->activateCursor();
+      
+      box = new OrxGui::GLGuiBox();
+      box->setAbsCoor2D( 300, 100 );
+      
+      OrxGui::GLGuiPushButton * buttonSpectator = new OrxGui::GLGuiPushButton("Spectator");
+      box->pack( buttonSpectator );
+      buttonSpectator->connect(SIGNAL(buttonSpectator, released), this, SLOT(MultiplayerTeamDeathmatch, onButtonSpectator));
+      
+      OrxGui::GLGuiPushButton * buttonRandom = new OrxGui::GLGuiPushButton("Random");
+      box->pack( buttonRandom );
+      buttonRandom->connect(SIGNAL(buttonRandom, released), this, SLOT(MultiplayerTeamDeathmatch, onButtonRandom));
+      
+      OrxGui::GLGuiPushButton * buttonTeam0 = new OrxGui::GLGuiPushButton("Blue Team");
+      box->pack( buttonTeam0 );
+      buttonTeam0->connect(SIGNAL(buttonTeam0, released), this, SLOT(MultiplayerTeamDeathmatch, onButtonTeam0));
+      
+      OrxGui::GLGuiPushButton * buttonTeam1 = new OrxGui::GLGuiPushButton("Red Team");
+      box->pack( buttonTeam1 );
+      buttonTeam1->connect(SIGNAL(buttonTeam1, released), this, SLOT(MultiplayerTeamDeathmatch, onButtonTeam1));
+      
+      OrxGui::GLGuiPushButton * buttonExit = new OrxGui::GLGuiPushButton("Exit");
+      box->pack( buttonExit );
+      buttonExit->connect(SIGNAL(buttonExit, released), this, SLOT(MultiplayerTeamDeathmatch, onButtonExit));
+      
+      box->showAll();
+    }
+  }
+
+  if ( box != NULL
+       && PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() )
+       && PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() )->getPreferedTeamId() != TEAM_NOTEAM 
+     )
+  {
+    delete box;
+    box = NULL;
+      
+    OrxGui::GLGuiHandler::getInstance()->deactivateCursor( true );
+      
+    EventHandler::getInstance()->popState();
+  }
+  
+  if ( box != NULL )
+  {
+    OrxGui::GLGuiHandler::getInstance()->tick( dt );
+  }
+  
+  assignPlayable();
+  
   if ( !SharedNetworkData::getInstance()->isGameServer() )
     return;
   
   gameStateTimer -= dt;
-  PRINTF(0)("TICK %f\n", gameStateTimer);
+  //PRINTF(0)("TICK %f\n", gameStateTimer);
   
   if ( currentGameState != GAMESTATE_GAME && gameStateTimer < 0 )
@@ -210,17 +280,28 @@
  * @return group id
  */
-int MultiplayerTeamDeathmatch::getTeamForNewUser( )
+int MultiplayerTeamDeathmatch::getTeamForNewUser()
 {
   return TEAM_NOTEAM;
 }
 
-ClassID MultiplayerTeamDeathmatch::getPlayableClassId( int team )
-{
-  return CL_SPECTATOR;
-}
-
-std::string MultiplayerTeamDeathmatch::getPlayableModelFileName( int team, ClassID classId )
-{
-  return "";
+ClassID MultiplayerTeamDeathmatch::getPlayableClassId( int userId, int team )
+{
+  if ( team == TEAM_NOTEAM || team == TEAM_SPECTATOR )
+    return CL_SPECTATOR;
+  
+  if ( team == 0 || team == 1 )
+    return CL_SPACE_SHIP;
+  
+  assert( false );
+}
+
+std::string MultiplayerTeamDeathmatch::getPlayableModelFileName( int userId, int team, ClassID classId )
+{
+  if ( team == 0 )
+    return "models/ships/reap_#.obj";
+  else if ( team == 1 )
+    return "models/ships/fighter.obj";
+  else
+    return "";
 }
 
@@ -334,5 +415,5 @@
     if ( stats.getTeamId() != stats.getPreferedTeamId() )
     {
-      if ( stats.getPreferedTeamId() == TEAM_SPECTATOR || ( stats.getPreferedTeamId() <= 0 && stats.getPreferedTeamId() < numTeams ) )
+      if ( stats.getPreferedTeamId() == TEAM_SPECTATOR || ( stats.getPreferedTeamId() >= 0 && stats.getPreferedTeamId() < numTeams ) )
       {
         teamChange( stats.getUserId() );
@@ -362,10 +443,71 @@
   PlayerStats & stats = *(PlayerStats::getStats( userId ));
   
-  assert(false);
-}
-
-
-
-
-
-
+  stats.setTeamId( stats.getPreferedTeamId() );
+  
+  Playable * oldPlayable = stats.getPlayable();
+  
+  
+  ClassID playableClassId = getPlayableClassId( userId, stats.getPreferedTeamId() );
+  std::string playableModel = getPlayableModelFileName( userId, stats.getPreferedTeamId(), 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 );
+  
+  stats.setTeamId( stats.getPreferedTeamId() );
+  stats.setPlayableClassId( playableClassId );
+  stats.setPlayableUniqueId( playable.getUniqueID() );
+  stats.setModelFileName( playableModel );
+  
+  if ( oldPlayable )
+  {
+    //if ( userId == SharedNetworkData::getInstance()->getHostID() )
+    //  State::getPlayer()->setPlayable( NULL );
+    delete oldPlayable;
+  }
+}
+
+void MultiplayerTeamDeathmatch::onButtonExit( )
+{
+  State::getCurrentStoryEntity()->stop();
+}
+
+void MultiplayerTeamDeathmatch::onButtonRandom( )
+{
+  NetworkGameManager::getInstance()->prefereTeam( TEAM_RANDOM );
+}
+
+void MultiplayerTeamDeathmatch::onButtonTeam0( )
+{
+  NetworkGameManager::getInstance()->prefereTeam( 0 );
+}
+
+void MultiplayerTeamDeathmatch::onButtonTeam1( )
+{
+  NetworkGameManager::getInstance()->prefereTeam( 1 );
+}
+
+void MultiplayerTeamDeathmatch::onButtonSpectator( )
+{
+  NetworkGameManager::getInstance()->prefereTeam( TEAM_SPECTATOR );
+}
+
+void MultiplayerTeamDeathmatch::assignPlayable( )
+{
+  if ( PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() ) )
+    PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() )->getPlayable();
+}
+
+
+
+
+
+
Index: branches/network/src/util/multiplayer_team_deathmatch.h
===================================================================
--- branches/network/src/util/multiplayer_team_deathmatch.h	(revision 8070)
+++ branches/network/src/util/multiplayer_team_deathmatch.h	(revision 8096)
@@ -12,4 +12,5 @@
 #include "network_game_rules.h"
 
+#include "glgui_box.h"
 
 class TiXmlElement;
@@ -36,6 +37,6 @@
 
     virtual int getTeamForNewUser();
-    virtual ClassID getPlayableClassId( int team );
-    virtual std::string getPlayableModelFileName( int team, ClassID classId );
+    virtual ClassID getPlayableClassId( int userId, int team );
+    virtual std::string getPlayableModelFileName( int userId, int team, ClassID classId );
 
     virtual void onPlayerSpawn();
@@ -73,8 +74,18 @@
     float              gameStateTimer;             //!< if less than 0 -> change game state
 
+    OrxGui::GLGuiBox* box;
+
+
     void calculateTeamScore();
     void nextGameState();
     void handleTeamChanges();
     void teamChange( int userId );
+    void assignPlayable();
+    
+    void onButtonSpectator();
+    void onButtonRandom();
+    void onButtonTeam0();
+    void onButtonTeam1();
+    void onButtonExit();
 };
 
Index: branches/network/src/util/network_game_rules.cc
===================================================================
--- branches/network/src/util/network_game_rules.cc	(revision 8070)
+++ branches/network/src/util/network_game_rules.cc	(revision 8096)
@@ -38,10 +38,10 @@
 }
 
-std::string NetworkGameRules::getPlayableModelFileName( int team, ClassID classId )
+std::string NetworkGameRules::getPlayableModelFileName( int uesrId, int team, ClassID classId )
 {
   return "models/ships/reap_#.obj";
 }
 
-ClassID NetworkGameRules::getPlayableClassId( int team )
+ClassID NetworkGameRules::getPlayableClassId( int userId, int team )
 {
   return CL_SPACE_SHIP;
Index: branches/network/src/util/network_game_rules.h
===================================================================
--- branches/network/src/util/network_game_rules.h	(revision 8070)
+++ branches/network/src/util/network_game_rules.h	(revision 8096)
@@ -21,6 +21,6 @@
     
     virtual int getTeamForNewUser();
-    virtual ClassID getPlayableClassId( int team );
-    virtual std::string getPlayableModelFileName( int team, ClassID classId );
+    virtual ClassID getPlayableClassId( int userId, int team );
+    virtual std::string getPlayableModelFileName( int userId, int team, ClassID classId );
     
     virtual PlayerStats * getNewPlayerStats( int userId ){ return new PlayerStats( userId ); }
Index: branches/network/src/world_entities/playable.cc
===================================================================
--- branches/network/src/world_entities/playable.cc	(revision 8070)
+++ branches/network/src/world_entities/playable.cc	(revision 8096)
@@ -79,4 +79,5 @@
   // this->setPlayer(NULL);
   // IN ITS DESTRUCTOR.
+  detachCamera();
   assert(this->currentPlayer == NULL);
 }
@@ -281,5 +282,16 @@
  */
 void  Playable::detachCamera()
-{}
+{
+  PRINTF(0)("detach camera\n");
+  if ( (PNode*)(State::getCameraTarget()) == this )
+  {
+    PRINTF(0)("lookAt nullParent\n");
+    
+    State::getCameraNode()->setParentSoft(PNode::getNullParent());
+    State::getCameraTargetNode()->setParentSoft(PNode::getNullParent());
+    
+    State::getCamera()->lookAt( PNode::getNullParent() );
+  }
+}
 
 
Index: branches/network/src/world_entities/player.cc
===================================================================
--- branches/network/src/world_entities/player.cc	(revision 8070)
+++ branches/network/src/world_entities/player.cc	(revision 8096)
@@ -81,4 +81,7 @@
       return true;
   }
+  
+  if ( playable == NULL )
+    this->playable = NULL;
 
   return true;
