Index: code/branches/objecthierarchy/src/orxonox/objects/infos/HumanPlayer.cc
===================================================================
--- code/branches/objecthierarchy/src/orxonox/objects/infos/HumanPlayer.cc	(revision 2019)
+++ code/branches/objecthierarchy/src/orxonox/objects/infos/HumanPlayer.cc	(revision 2019)
@@ -0,0 +1,142 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "OrxonoxStableHeaders.h"
+#include "HumanPlayer.h"
+
+#include "core/Core.h"
+#include "core/CoreIncludes.h"
+#include "core/ConfigValueIncludes.h"
+#include "network/ClientInformation.h"
+#include "network/Host.h"
+#include "objects/controllers/HumanController.h"
+#include "objects/gametypes/Gametype.h"
+
+namespace orxonox
+{
+    CreateUnloadableFactory(HumanPlayer);
+
+    HumanPlayer::HumanPlayer(BaseObject* creator) : PlayerInfo(creator)
+    {
+        RegisterObject(HumanPlayer);
+
+        this->server_ready_ = Core::isMaster();
+        this->client_ready_ = false;
+
+        this->bHumanPlayer_ = true;
+        this->defaultController_ = Class(HumanController);
+
+        this->setConfigValues();
+        this->registerVariables();
+
+        COUT(0) << "HumanPlayer created" << std::endl;
+    }
+
+    HumanPlayer::~HumanPlayer()
+    {
+    }
+
+    void HumanPlayer::setConfigValues()
+    {
+        SetConfigValue(nick_, "Player").callback(this, &HumanPlayer::configvaluecallback_changednick);
+    }
+
+    void HumanPlayer::registerVariables()
+    {
+        REGISTERSTRING(this->synchronize_nick_, network::direction::toserver, new network::NetworkCallback<HumanPlayer>(this, &HumanPlayer::networkcallback_changednick));
+
+        REGISTERDATA(this->clientID_,     network::direction::toclient, new network::NetworkCallback<HumanPlayer>(this, &HumanPlayer::networkcallback_clientIDchanged));
+        REGISTERDATA(this->server_ready_, network::direction::toclient, new network::NetworkCallback<HumanPlayer>(this, &HumanPlayer::networkcallback_server_ready));
+        REGISTERDATA(this->client_ready_, network::direction::toserver, new network::NetworkCallback<HumanPlayer>(this, &HumanPlayer::networkcallback_client_ready));
+    }
+
+    void HumanPlayer::configvaluecallback_changednick()
+    {
+        if (this->isLocalPlayer())
+        {
+            this->synchronize_nick_ = this->nick_;
+
+            if (Core::isMaster())
+                this->setName(this->nick_);
+        }
+    }
+
+    void HumanPlayer::networkcallback_changednick()
+    {
+        this->setName(this->synchronize_nick_);
+    }
+
+    void HumanPlayer::networkcallback_clientIDchanged()
+    {
+        if (this->clientID_ == network::Host::getPlayerID())
+        {
+            this->bLocalPlayer_ = true;
+            this->synchronize_nick_ = this->nick_;
+            this->client_ready_ = true;
+
+            if (!Core::isMaster())
+                this->setObjectMode(network::direction::bidirectional);
+            else
+                this->setName(this->nick_);
+
+            this->createController();
+        }
+    }
+
+    void HumanPlayer::networkcallback_server_ready()
+    {
+        this->client_ready_ = true;
+    }
+
+    void HumanPlayer::networkcallback_client_ready()
+    {
+        if (this->getGametype())
+            this->getGametype()->playerEntered(this);
+    }
+
+    bool HumanPlayer::isReady() const
+    {
+        return (this->server_ready_ && this->client_ready_);
+    }
+
+    float HumanPlayer::getPing() const
+    {
+        return network::ClientInformation::findClient(this->getClientID())->getRTT();
+    }
+
+    float HumanPlayer::getPacketLossRatio() const
+    {
+        return network::ClientInformation::findClient(this->getClientID())->getPacketLoss();
+    }
+
+    void HumanPlayer::setClientID(unsigned int clientID)
+    {
+        this->clientID_ = clientID;
+        this->networkcallback_clientIDchanged();
+    }
+}
Index: code/branches/objecthierarchy/src/orxonox/objects/infos/HumanPlayer.h
===================================================================
--- code/branches/objecthierarchy/src/orxonox/objects/infos/HumanPlayer.h	(revision 2019)
+++ code/branches/objecthierarchy/src/orxonox/objects/infos/HumanPlayer.h	(revision 2019)
@@ -0,0 +1,69 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _HumanPlayer_H__
+#define _HumanPlayer_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "PlayerInfo.h"
+#include "core/Identifier.h"
+#include "objects/controllers/Controller.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport HumanPlayer : public PlayerInfo
+    {
+        public:
+            HumanPlayer(BaseObject* creator);
+            virtual ~HumanPlayer();
+
+            void registerVariables();
+            void setConfigValues();
+
+            bool isReady() const;
+            float getPing() const;
+            float getPacketLossRatio() const;
+
+            void setClientID(unsigned int clientID);
+
+        protected:
+            void configvaluecallback_changednick();
+            void networkcallback_changednick();
+            void networkcallback_clientIDchanged();
+            void networkcallback_server_ready();
+            void networkcallback_client_ready();
+
+            std::string nick_;
+            std::string synchronize_nick_;
+            bool server_ready_;
+            bool client_ready_;
+    };
+}
+
+#endif /* _HumanPlayer_H__ */
Index: code/branches/objecthierarchy/src/orxonox/objects/infos/Info.cc
===================================================================
--- code/branches/objecthierarchy/src/orxonox/objects/infos/Info.cc	(revision 2012)
+++ code/branches/objecthierarchy/src/orxonox/objects/infos/Info.cc	(revision 2019)
@@ -34,5 +34,5 @@
 namespace orxonox
 {
-    Info::Info()
+    Info::Info(BaseObject* creator) : BaseObject(creator)
     {
         RegisterObject(Info);
Index: code/branches/objecthierarchy/src/orxonox/objects/infos/Info.h
===================================================================
--- code/branches/objecthierarchy/src/orxonox/objects/infos/Info.h	(revision 2012)
+++ code/branches/objecthierarchy/src/orxonox/objects/infos/Info.h	(revision 2019)
@@ -40,5 +40,5 @@
     {
         public:
-            Info();
+            Info(BaseObject* creator);
             virtual ~Info() {}
     };
Index: code/branches/objecthierarchy/src/orxonox/objects/infos/Level.cc
===================================================================
--- code/branches/objecthierarchy/src/orxonox/objects/infos/Level.cc	(revision 2012)
+++ code/branches/objecthierarchy/src/orxonox/objects/infos/Level.cc	(revision 2019)
@@ -30,18 +30,14 @@
 #include "Level.h"
 
-#include <OgreSceneManager.h>
-#include <OgreLight.h>
-
 #include "core/CoreIncludes.h"
 #include "core/XMLPort.h"
-#include "core/Core.h"
-#include "core/ConsoleCommand.h"
 #include "core/Loader.h"
 #include "core/XMLFile.h"
 #include "core/Template.h"
 
-#include "GraphicsEngine.h"
 #include "Settings.h"
+#include "LevelManager.h"
 #include "PlayerInfo.h"
+#include "objects/gametypes/Gametype.h"
 
 #include "util/Math.h"
@@ -49,97 +45,25 @@
 namespace orxonox
 {
-    SetConsoleCommand(Level, listPlayers, true);
-
     CreateFactory(Level);
 
-    Level::Level()
+    Level::Level(BaseObject* creator) : Info(creator)
     {
         RegisterObject(Level);
 
-        this->rootGametype_ = 0;
         this->registerVariables();
-
-        // test test test
-        {
-            Ogre::Light* light;
-            light = GraphicsEngine::getInstance().getLevelSceneManager()->createLight("Light0");
-            light->setType(Ogre::Light::LT_DIRECTIONAL);
-            light->setDiffuseColour(ColourValue(1.0, 0.9, 0.6, 1.0));
-            light->setSpecularColour(ColourValue(1.0, 0.9, 0.6, 1.0));
-            light->setDirection(1, -0.2, 0.2);
-        }
-        // test test test
+        this->xmlfilename_ = this->getFilename();
 
         COUT(0) << "created Level" << std::endl;
     }
 
-    Level* Level::getActiveLevel()
+    Level::~Level()
     {
-        for (ObjectList<Level>::iterator it = ObjectList<Level>::begin(); it != ObjectList<Level>::end(); ++it)
-            if (it->isActive())
-                return (*it);
+        if (this->isInitialized())
+        {
+            LevelManager::getInstance().releaseActivity(this);
 
-        return 0;
-    }
-
-    PlayerInfo* Level::getClient(unsigned int clientID)
-    {
-        Level* level = Level::getActiveLevel();
-
-        if (level)
-        {
-            std::map<unsigned int, PlayerInfo*>::const_iterator it = level->clients_.find(clientID);
-            if (it != level->clients_.end())
-                return it->second;
+            if (this->xmlfile_)
+                Loader::unload(this->xmlfile_);
         }
-        else
-        {
-            for (ObjectList<PlayerInfo>::iterator it = ObjectList<PlayerInfo>::begin(); it != ObjectList<PlayerInfo>::end(); ++it)
-                if (it->getClientID() == clientID)
-                    return (*it);
-        }
-        return 0;
-    }
-
-    void Level::listPlayers()
-    {
-        Level* level = Level::getActiveLevel();
-
-        if (level->getGametype())
-        {
-            for (std::set<PlayerInfo*>::const_iterator it = level->getGametype()->getPlayers().begin(); it != level->getGametype()->getPlayers().end(); ++it)
-                COUT(0) << "ID: " << (*it)->getClientID() << ", Name: " << (*it)->getName() << std::endl;
-        }
-        else
-        {
-            for (ObjectList<PlayerInfo>::iterator it = ObjectList<PlayerInfo>::begin(); it != ObjectList<PlayerInfo>::end(); ++it)
-                COUT(0) << "ID: " << (*it)->getClientID() << ", Name: " << (*it)->getName() << std::endl;
-        }
-    }
-
-    void Level::clientConnected(unsigned int clientID)
-    {
-        COUT(0) << "client connected" << std::endl;
-
-        // create new PlayerInfo instance
-        PlayerInfo* player = new PlayerInfo();
-        player->setGametype(this->getGametype());
-        player->setClientID(clientID);
-
-        // add to clients-map
-        assert(!this->clients_[clientID]);
-        this->clients_[clientID] = player;
-    }
-
-    void Level::clientDisconnected(unsigned int clientID)
-    {
-        COUT(0) << "client disconnected" << std::endl;
-
-        // remove from clients-map
-        PlayerInfo* player = this->clients_[clientID];
-        this->clients_.erase(clientID);
-
-        // delete PlayerInfo instance
-        delete player;
     }
 
@@ -150,22 +74,18 @@
         XMLPortParam(Level, "description", setDescription, getDescription, xmlelement, mode);
         XMLPortParam(Level, "gametype", setGametypeString, getGametypeString, xmlelement, mode).defaultValues("Gametype");
-        XMLPortParam(Level, "skybox", setSkybox, getSkybox, xmlelement, mode);
-        XMLPortParam(Level, "ambientlight", setAmbientLight, getAmbientLight, xmlelement, mode).defaultValues(ColourValue(0.2, 0.2, 0.2, 1));
 
-        this->xmlfile_ = this->getFilename();
+        XMLPortObjectExtended(Level, BaseObject, "", addObject, getObject, xmlelement, mode, true, false);
     }
 
     void Level::registerVariables()
     {
-        REGISTERSTRING(this->xmlfile_,     network::direction::toclient, new network::NetworkCallback<Level>(this, &Level::networkcallback_applyXMLFile));
+        REGISTERSTRING(this->xmlfilename_, network::direction::toclient, new network::NetworkCallback<Level>(this, &Level::networkcallback_applyXMLFile));
         REGISTERSTRING(this->name_,        network::direction::toclient, new network::NetworkCallback<Level>(this, &Level::changedName));
         REGISTERSTRING(this->description_, network::direction::toclient);
-        REGISTERSTRING(this->skybox_,      network::direction::toclient, new network::NetworkCallback<Level>(this, &Level::networkcallback_applySkybox));
-        REGISTERDATA(this->ambientLight_,  network::direction::toclient, new network::NetworkCallback<Level>(this, &Level::networkcallback_applyAmbientLight));
     }
 
     void Level::networkcallback_applyXMLFile()
     {
-        COUT(0) << "Loading level \"" << this->xmlfile_ << "\"..." << std::endl;
+        COUT(0) << "Loading level \"" << this->xmlfilename_ << "\"..." << std::endl;
 
         ClassTreeMask mask;
@@ -173,24 +93,7 @@
         mask.include(Class(Template));
 
-        XMLFile* file = new XMLFile(Settings::getDataPath() + this->xmlfile_, mask);
+        this->xmlfile_ = new XMLFile(Settings::getDataPath() + this->xmlfilename_, mask);
 
-        Loader::open(file);
-    }
-
-    void Level::setSkybox(const std::string& skybox)
-    {
-        if (Core::showsGraphics())
-            if (GraphicsEngine::getInstance().getLevelSceneManager())
-                GraphicsEngine::getInstance().getLevelSceneManager()->setSkyBox(true, skybox);
-
-        this->skybox_ = skybox;
-    }
-
-    void Level::setAmbientLight(const ColourValue& colour)
-    {
-        if (Core::showsGraphics())
-            GraphicsEngine::getInstance().getLevelSceneManager()->setAmbientLight(colour);
-
-        this->ambientLight_ = colour;
+        Loader::open(this->xmlfile_);
     }
 
@@ -198,11 +101,46 @@
     {
         Identifier* identifier = ClassByString(gametype);
-        if (identifier)
+        if (identifier && identifier->isA(Class(Gametype)))
         {
             this->gametype_ = gametype;
-            this->gametypeIdentifier_ = identifier;
-            this->rootGametype_ = this->gametypeIdentifier_.fabricate();
-            this->getConnectedClients();
+
+            Gametype* rootgametype = dynamic_cast<Gametype*>(identifier->fabricate(this));
+            this->setGametype(rootgametype);
+
+            for (std::list<BaseObject*>::iterator it = this->objects_.begin(); it != this->objects_.end(); ++it)
+                (*it)->setGametype(rootgametype);
+
+            LevelManager::getInstance().requestActivity(this);
         }
     }
+
+
+    void Level::addObject(BaseObject* object)
+    {
+        this->objects_.push_back(object);
+        object->setGametype(this->getGametype());
+    }
+
+    BaseObject* Level::getObject(unsigned int index) const
+    {
+        unsigned int i = 0;
+        for (std::list<BaseObject*>::const_iterator it = this->objects_.begin(); it != this->objects_.end(); ++it)
+        {
+            if (i == index)
+                return (*it);
+            ++i;
+        }
+        return 0;
+    }
+
+    void Level::playerEntered(PlayerInfo* player)
+    {
+        COUT(0) << "player entered level" << std::endl;
+        player->setGametype(this->getGametype());
+    }
+
+    void Level::playerLeft(PlayerInfo* player)
+    {
+        player->setGametype(0);
+    }
 }
Index: code/branches/objecthierarchy/src/orxonox/objects/infos/Level.h
===================================================================
--- code/branches/objecthierarchy/src/orxonox/objects/infos/Level.h	(revision 2012)
+++ code/branches/objecthierarchy/src/orxonox/objects/infos/Level.h	(revision 2019)
@@ -33,23 +33,15 @@
 
 #include "Info.h"
-#include "util/Math.h"
-#include "core/Identifier.h"
-
-#include "objects/gametypes/Gametype.h"
-#include "network/ClientConnectionListener.h"
 
 namespace orxonox
 {
-    class _OrxonoxExport Level : public Info, public network::ClientConnectionListener
+    class _OrxonoxExport Level : public Info
     {
         public:
-            Level();
-            virtual ~Level() {}
+            Level(BaseObject* creator);
+            virtual ~Level();
 
             virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
             void registerVariables();
-
-            inline const std::map<unsigned int, PlayerInfo*>& getClients() const
-                { return this->clients_; }
 
             inline void setDescription(const std::string& description)
@@ -58,41 +50,22 @@
                 { return this->description_; }
 
-            void setSkybox(const std::string& skybox);
-            inline const std::string& getSkybox() const
-                { return this->skybox_; }
+            void playerEntered(PlayerInfo* player);
+            void playerLeft(PlayerInfo* player);
 
-            void setAmbientLight(const ColourValue& colour);
-            inline const ColourValue& getAmbientLight() const
-                { return this->ambientLight_; }
+        private:
+            void addObject(BaseObject* object);
+            BaseObject* getObject(unsigned int index) const;
 
             void setGametypeString(const std::string& gametype);
             inline const std::string& getGametypeString() const
                 { return this->gametype_; }
-            inline Gametype* getGametype() const
-                { return this->rootGametype_; }
-
-            static Level* getActiveLevel();
-            static void listPlayers();
-            static PlayerInfo* getClient(unsigned int clientID);
-
-        private:
-            virtual void clientConnected(unsigned int clientID);
-            virtual void clientDisconnected(unsigned int clientID);
 
             void networkcallback_applyXMLFile();
 
-            void networkcallback_applySkybox()
-                { this->setSkybox(this->skybox_); }
-            void networkcallback_applyAmbientLight()
-                { this->setAmbientLight(this->ambientLight_); }
-
-            std::map<unsigned int, PlayerInfo*> clients_;
-            std::string description_;
-            std::string skybox_;
-            ColourValue ambientLight_;
-            std::string gametype_;
-            SubclassIdentifier<Gametype> gametypeIdentifier_;
-            Gametype* rootGametype_;
-            std::string xmlfile_;
+            std::string            description_;
+            std::string            gametype_;
+            std::string            xmlfilename_;
+            XMLFile*               xmlfile_;
+            std::list<BaseObject*> objects_;
     };
 }
Index: code/branches/objecthierarchy/src/orxonox/objects/infos/PlayerInfo.cc
===================================================================
--- code/branches/objecthierarchy/src/orxonox/objects/infos/PlayerInfo.cc	(revision 2012)
+++ code/branches/objecthierarchy/src/orxonox/objects/infos/PlayerInfo.cc	(revision 2019)
@@ -27,43 +27,27 @@
  */
 
+#include <cassert>
+
 #include "OrxonoxStableHeaders.h"
 #include "PlayerInfo.h"
 
-#include <OgreSceneManager.h>
-
 #include "core/CoreIncludes.h"
-#include "core/ConfigValueIncludes.h"
-#include "core/XMLPort.h"
-#include "core/Core.h"
-
-#include "network/Host.h"
 #include "network/ClientInformation.h"
-
-#include "GraphicsEngine.h"
 #include "objects/gametypes/Gametype.h"
-#include "objects/worldentities/ControllableEntity.h"
-#include "objects/controllers/HumanController.h"
 
 namespace orxonox
 {
-    CreateUnloadableFactory(PlayerInfo);
-
-    PlayerInfo::PlayerInfo()
+    PlayerInfo::PlayerInfo(BaseObject* creator) : Info(creator)
     {
         RegisterObject(PlayerInfo);
 
-        this->ping_ = -1;
         this->clientID_ = network::CLIENTID_UNKNOWN;
+        this->bHumanPlayer_ = false;
         this->bLocalPlayer_ = false;
-        this->bHumanPlayer_ = false;
-        this->bFinishedSetup_ = false;
-        this->gametype_ = 0;
+        this->bReadyToSpawn_ = false;
+        this->controller_ = 0;
+        this->controllableEntity_ = 0;
+        this->controllableEntityID_ = network::CLIENTID_UNKNOWN;
 
-        this->pawn_ = 0;
-        this->pawnID_ = network::OBJECTID_UNKNOWN;
-        this->controller_ = 0;
-        this->setDefaultController(Class(HumanController));
-
-        this->setConfigValues();
         this->registerVariables();
     }
@@ -73,119 +57,105 @@
         if (this->isInitialized())
         {
-            if (this->gametype_)
-                this->gametype_->removePlayer(this);
+            this->stopControl(this->controllableEntity_);
 
             if (this->controller_)
+            {
                 delete this->controller_;
-
-            if (this->pawn_)
-                this->pawn_->removePlayer();
+                this->controller_ = 0;
+            }
         }
     }
 
-    void PlayerInfo::setConfigValues()
+    void PlayerInfo::registerVariables()
     {
-        SetConfigValue(nick_, "Player").callback(this, &PlayerInfo::checkNick);
-    }
-
-    void PlayerInfo::checkNick()
-    {
-        if (this->bLocalPlayer_)
-        {
-            this->playerName_ = this->nick_;
-
-            if (Core::isMaster())
-                this->setName(this->playerName_);
-        }
+        REGISTERSTRING(this->name_,                 network::direction::toclient, new network::NetworkCallback<PlayerInfo>(this, &PlayerInfo::changedName));
+        REGISTERDATA  (this->controllableEntityID_, network::direction::toclient, new network::NetworkCallback<PlayerInfo>(this, &PlayerInfo::networkcallback_changedcontrollableentityID));
     }
 
     void PlayerInfo::changedName()
     {
-        if (this->gametype_)
-            this->gametype_->playerChangedName(this);
+        if (this->isReady() && this->getGametype())
+            this->getGametype()->playerChangedName(this);
     }
 
-    void PlayerInfo::registerVariables()
+    void PlayerInfo::changedGametype()
     {
-        REGISTERSTRING(name_,         network::direction::toclient, new network::NetworkCallback<PlayerInfo>(this, &PlayerInfo::changedName));
-        REGISTERSTRING(playerName_,   network::direction::toserver, new network::NetworkCallback<PlayerInfo>(this, &PlayerInfo::clientChangedName));
-        REGISTERDATA(clientID_,       network::direction::toclient, new network::NetworkCallback<PlayerInfo>(this, &PlayerInfo::checkClientID));
-        REGISTERDATA(ping_,           network::direction::toclient);
-        REGISTERDATA(bHumanPlayer_,   network::direction::toclient);
-        REGISTERDATA(pawnID_,         network::direction::toclient, new network::NetworkCallback<PlayerInfo>(this, &PlayerInfo::updatePawn));
-        REGISTERDATA(bFinishedSetup_, network::direction::bidirectional, new network::NetworkCallback<PlayerInfo>(this, &PlayerInfo::finishedSetup));
-    }
+        if (this->isReady())
+        {
+            if (this->getOldGametype())
+            {
+                if (this->getGametype())
+                    this->getOldGametype()->playerSwitched(this, this->getGametype());
+                else
+                    this->getOldGametype()->playerLeft(this);
+            }
 
-    void PlayerInfo::clientChangedName()
-    {
-        this->setName(this->playerName_);
-    }
-
-    void PlayerInfo::checkClientID()
-    {
-        this->bHumanPlayer_ = true;
-
-        if (this->clientID_ == network::Host::getPlayerID())
-        {
-            this->takeLocalControl();
-
-            if (Core::isClient())
-                this->setObjectMode(network::direction::bidirectional);
-            else
+            if (this->getGametype())
             {
-                this->clientChangedName();
-                this->bFinishedSetup_ = true;
-                this->finishedSetup();
+                if (this->getOldGametype())
+                    this->getGametype()->playerSwitchedBack(this, this->getOldGametype());
+                else
+                    this->getGametype()->playerEntered(this);
             }
         }
     }
 
-    void PlayerInfo::finishedSetup()
+    void PlayerInfo::createController()
     {
-        if (Core::isClient())
-            this->bFinishedSetup_ = true;
-        else if (this->bFinishedSetup_)
+        this->controller_ = this->defaultController_.fabricate(this);
+        assert(this->controller_);
+        this->controller_->setPlayer(this);
+        if (this->controllableEntity_)
+            this->controller_->setControllableEntity(this->controllableEntity_);
+    }
+
+    void PlayerInfo::startControl(ControllableEntity* entity)
+    {
+        if (this->controllableEntity_)
+            this->stopControl(this->controllableEntity_);
+
+        this->controllableEntity_ = entity;
+
+        if (entity)
         {
-            if (this->gametype_)
-                this->gametype_->addPlayer(this);
+            this->controllableEntityID_ = entity->getObjectID();
+            entity->setPlayer(this);
+        }
+        else
+        {
+            this->controllableEntityID_ = network::OBJECTID_UNKNOWN;
+        }
+
+        if (this->controller_)
+            this->controller_->setControllableEntity(entity);
+    }
+
+    void PlayerInfo::stopControl(ControllableEntity* entity)
+    {
+        if (entity && this->controllableEntity_ == entity)
+        {
+            this->controllableEntity_ = 0;
+            this->controllableEntityID_ = network::OBJECTID_UNKNOWN;
+
+            if (this->controller_)
+                this->controller_->setControllableEntity(0);
+
+            entity->removePlayer();
         }
     }
 
-    void PlayerInfo::startControl(ControllableEntity* pawn)
+    void PlayerInfo::networkcallback_changedcontrollableentityID()
     {
-        pawn->setPlayer(this);
-        this->pawn_ = pawn;
-        this->pawnID_ = pawn->getObjectID();
+        if (this->controllableEntityID_ != network::OBJECTID_UNKNOWN)
+        {
+            Synchronisable* temp = Synchronisable::getSynchronisable(this->controllableEntityID_);
+            ControllableEntity* entity = dynamic_cast<ControllableEntity*>(temp);
 
-        if (this->controller_)
-            this->controller_->setPawn(this->pawn_);
-    }
-
-    void PlayerInfo::stopControl()
-    {
-        if (this->pawn_)
-            this->pawn_->removePlayer();
-        this->pawn_ = 0;
-        this->pawnID_ = network::OBJECTID_UNKNOWN;
-    }
-
-    void PlayerInfo::takeLocalControl()
-    {
-        this->bLocalPlayer_ = true;
-        this->playerName_ = this->nick_;
-        this->createController();
-    }
-
-    void PlayerInfo::createController()
-    {
-        this->controller_ = this->defaultController_.fabricate();
-        this->controller_->setPawn(this->pawn_);
-    }
-
-    void PlayerInfo::updatePawn()
-    {
-        this->pawn_ = dynamic_cast<ControllableEntity*>(network::Synchronisable::getSynchronisable(this->pawnID_));
-        if (this->pawn_ && (this->pawn_->getPlayer() != this))
-            this->pawn_->setPlayer(this);
+            this->startControl(entity);
+        }
+        else
+        {
+            this->stopControl(this->controllableEntity_);
+        }
     }
 }
Index: code/branches/objecthierarchy/src/orxonox/objects/infos/PlayerInfo.h
===================================================================
--- code/branches/objecthierarchy/src/orxonox/objects/infos/PlayerInfo.h	(revision 2012)
+++ code/branches/objecthierarchy/src/orxonox/objects/infos/PlayerInfo.h	(revision 2019)
@@ -41,67 +41,46 @@
     {
         public:
-            PlayerInfo();
+            PlayerInfo(BaseObject* creator);
             virtual ~PlayerInfo();
 
-            void setConfigValues();
             void registerVariables();
 
             virtual void changedName();
-
-            inline void setClientID(unsigned int clientID)
-                { this->clientID_ = clientID; this->checkClientID(); }
-            inline unsigned int getClientID() const
-                { return this->clientID_; }
+            virtual void changedGametype();
 
             inline bool isHumanPlayer() const
                 { return this->bHumanPlayer_; }
-
             inline bool isLocalPlayer() const
                 { return this->bLocalPlayer_; }
+            inline unsigned int getClientID() const
+                { return this->clientID_; }
+            inline bool isReadyToSpawn() const
+                { return this->bReadyToSpawn_; }
 
-            virtual void startControl(ControllableEntity* pawn);
-            virtual void stopControl();
+            virtual bool isReady() const = 0;
+            virtual float getPing() const = 0;
+            virtual float getPacketLossRatio() const = 0;
 
-            inline ControllableEntity* getPawn() const
-                { return this->pawn_; }
-/*
-            inline void setController(Controller* controller)
-                { this->controller_ = controller; }
-            inline Controller* getController() const
-                { return this->controller_; }
-*/
-            inline void setGametype(Gametype* gametype)
-                { this->gametype_ = gametype; }
-            inline Gametype* getGametype() const
-                { return this->gametype_; }
+            inline void setReadyToSpawn(bool bReady)
+                { this->bReadyToSpawn_ = bReady; }
+
+            void startControl(ControllableEntity* entity);
+            void stopControl(ControllableEntity* entity);
+
+            inline ControllableEntity* getControllableEntity() const
+                { return this->controllableEntity_; }
 
         protected:
-            inline void setDefaultController(Identifier* identifier)
-                { this->defaultController_ = identifier; }
+            void createController();
+            void networkcallback_changedcontrollableentityID();
 
-        private:
-            virtual void createController();
-            virtual void takeLocalControl();
-
-            void checkClientID();
-            void finishedSetup();
-            void checkNick();
-            void clientChangedName();
-            void updatePawn();
-
+            bool bHumanPlayer_;
+            bool bLocalPlayer_;
+            bool bReadyToSpawn_;
+            SubclassIdentifier<Controller> defaultController_;
+            Controller* controller_;
+            ControllableEntity* controllableEntity_;
+            unsigned int controllableEntityID_;
             unsigned int clientID_;
-            float ping_;
-            bool bLocalPlayer_;
-            bool bHumanPlayer_;
-            bool bFinishedSetup_;
-
-            std::string playerName_;
-            std::string nick_;
-
-            ControllableEntity* pawn_;
-            unsigned int pawnID_;
-            Controller* controller_;
-            SubclassIdentifier<Controller> defaultController_;
-            Gametype* gametype_;
     };
 }
