Index: code/branches/presentation/src/orxonox/LevelManager.cc
===================================================================
--- code/branches/presentation/src/orxonox/LevelManager.cc	(revision 8632)
+++ code/branches/presentation/src/orxonox/LevelManager.cc	(revision 8637)
@@ -222,4 +222,5 @@
                 this->nextLevel_ = this->availableLevels_.begin();
             }
+
             while(this->nextIndex_ != index)
             {
Index: code/branches/presentation/src/orxonox/gametypes/Gametype.cc
===================================================================
--- code/branches/presentation/src/orxonox/gametypes/Gametype.cc	(revision 8632)
+++ code/branches/presentation/src/orxonox/gametypes/Gametype.cc	(revision 8637)
@@ -58,5 +58,5 @@
 
         this->defaultControllableEntity_ = Class(Spectator);
-
+        
         this->bAutoStart_ = false;
         this->bForceSpawn_ = false;
@@ -121,10 +121,19 @@
         }
 
-        if (this->gtinfo_->bStartCountdownRunning_ && !this->gtinfo_->bStarted_)
-            this->gtinfo_->startCountdown_ -= dt;
-
-        if (!this->gtinfo_->bStarted_)
+        if (this->gtinfo_->isStartCountdownRunning() && !this->gtinfo_->hasStarted())
+            this->gtinfo_->countdownStartCountdown(dt);
+
+        if (!this->gtinfo_->hasStarted())
+        {
+            for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
+            {
+                // Inform the GametypeInfo that the player is ready to spawn.
+                if(it->first->isHumanPlayer() && it->first->isReadyToSpawn())
+                    this->gtinfo_->playerReadyToSpawn(it->first);
+            }
+                    
             this->checkStart();
-        else if (!this->gtinfo_->bEnded_)
+        }
+        else if (!this->gtinfo_->hasEnded())
             this->spawnDeadPlayersIfRequested();
 
@@ -136,5 +145,5 @@
         this->addBots(this->numberOfBots_);
 
-        this->gtinfo_->bStarted_ = true;
+        this->gtinfo_->start();
 
         this->spawnPlayersIfRequested();
@@ -143,5 +152,5 @@
     void Gametype::end()
     {
-        this->gtinfo_->bEnded_ = true;
+        this->gtinfo_->end();
 
         for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
@@ -173,4 +182,5 @@
     {
         this->players_[player].state_ = PlayerState::Joined;
+        this->gtinfo_->playerEntered(player);
     }
 
@@ -269,4 +279,7 @@
                     }
                 }
+
+                if(victim->getPlayer()->isHumanPlayer())
+                    this->gtinfo_->pawnKilled(victim->getPlayer());
 
                 ControllableEntity* entity = this->defaultControllableEntity_.fabricate(victim->getCreator());
@@ -345,5 +358,5 @@
                 it->second.state_ = PlayerState::Dead;
 
-                if (!it->first->isReadyToSpawn() || !this->gtinfo_->bStarted_)
+                if (!it->first->isReadyToSpawn() || !this->gtinfo_->hasStarted())
                 {
                     this->spawnPlayerAsDefaultPawn(it->first);
@@ -356,12 +369,12 @@
     void Gametype::checkStart()
     {
-        if (!this->gtinfo_->bStarted_)
-        {
-            if (this->gtinfo_->bStartCountdownRunning_)
-            {
-                if (this->gtinfo_->startCountdown_ <= 0)
-                {
-                    this->gtinfo_->bStartCountdownRunning_ = false;
-                    this->gtinfo_->startCountdown_ = 0;
+        if (!this->gtinfo_->hasStarted())
+        {
+            if (this->gtinfo_->isStartCountdownRunning())
+            {
+                if (this->gtinfo_->getStartCountdown() <= 0.0f)
+                {
+                    this->gtinfo_->stopStartCountdown();
+                    this->gtinfo_->setStartCountdown(0.0f);;
                     this->start();
                 }
@@ -388,8 +401,8 @@
                         // If in developer's mode, there is no start countdown.
                         if(Core::getInstance().inDevMode())
-                            this->gtinfo_->startCountdown_ = 0;
+                            this->start();
                         else
-                            this->gtinfo_->startCountdown_ = this->initialStartCountdown_;
-                        this->gtinfo_->bStartCountdownRunning_ = true;
+                            this->gtinfo_->setStartCountdown(this->initialStartCountdown_);
+                        this->gtinfo_->startStartCountdown();
                     }
                 }
@@ -401,6 +414,8 @@
     {
         for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
+        {
             if (it->first->isReadyToSpawn() || this->bForceSpawn_)
                 this->spawnPlayer(it->first);
+        }
     }
 
@@ -421,4 +436,8 @@
             player->startControl(spawnpoint->spawn());
             this->players_[player].state_ = PlayerState::Alive;
+
+            if(player->isHumanPlayer())
+                this->gtinfo_->playerSpawned(player);
+            
             this->playerPostSpawn(player);
         }
Index: code/branches/presentation/src/orxonox/gametypes/Gametype.h
===================================================================
--- code/branches/presentation/src/orxonox/gametypes/Gametype.h	(revision 8632)
+++ code/branches/presentation/src/orxonox/gametypes/Gametype.h	(revision 8637)
@@ -78,7 +78,7 @@
 
             inline bool hasStarted() const
-                { return this->gtinfo_->bStarted_; }
+                { return this->gtinfo_->hasStarted(); }
             inline bool hasEnded() const
-                { return this->gtinfo_->bEnded_; }
+                { return this->gtinfo_->hasEnded(); }
 
             virtual void start();
@@ -114,12 +114,12 @@
 
             inline bool isStartCountdownRunning() const
-                { return this->gtinfo_->bStartCountdownRunning_; }
+                { return this->gtinfo_->isStartCountdownRunning(); }
             inline float getStartCountdown() const
-                { return this->gtinfo_->startCountdown_; }
+                { return this->gtinfo_->getStartCountdown(); }
 
             inline void setHUDTemplate(const std::string& name)
-                { this->gtinfo_->hudtemplate_ = name; }
+                { this->gtinfo_->setHUDTemplate(name); }
             inline const std::string& getHUDTemplate() const
-                { return this->gtinfo_->hudtemplate_; }
+                { return this->gtinfo_->getHUDTemplate(); }
 
             void addBots(unsigned int amount);
@@ -167,5 +167,5 @@
 
             SmartPtr<GametypeInfo> gtinfo_;
-
+            
             bool bAutoStart_;
             bool bForceSpawn_;
Index: code/branches/presentation/src/orxonox/infos/GametypeInfo.cc
===================================================================
--- code/branches/presentation/src/orxonox/infos/GametypeInfo.cc	(revision 8632)
+++ code/branches/presentation/src/orxonox/infos/GametypeInfo.cc	(revision 8637)
@@ -23,7 +23,12 @@
  *      Fabian 'x3n' Landau
  *   Co-authors:
- *      ...
+ *      Damian 'Mozork' Frick
  *
  */
+
+/**
+    @file GametypeInfo.cc
+    @brief Implementation of the GametypeInfo class
+*/
 
 #include "GametypeInfo.h"
@@ -31,7 +36,13 @@
 #include "core/CoreIncludes.h"
 #include "core/GameMode.h"
+#include "network/Host.h"
 #include "network/NetworkFunction.h"
-#include "network/Host.h"
+#include "util/Convert.h"
+
+#include "controllers/HumanController.h"
 #include "interfaces/GametypeMessageListener.h"
+#include "interfaces/NotificationListener.h"
+
+#include "PlayerInfo.h"
 
 namespace orxonox
@@ -45,12 +56,24 @@
     registerMemberNetworkFunction(GametypeInfo, dispatchFadingMessage);
 
+    registerMemberNetworkFunction(GametypeInfo, changedReadyToSpawn);
+    registerMemberNetworkFunction(GametypeInfo, changedSpawned);
+
+    /*static*/ const std::string GametypeInfo::NOTIFICATION_SENDER("gameinfo");
+
+    /**
+    @brief
+        Registers and initializes the object.
+    */
     GametypeInfo::GametypeInfo(BaseObject* creator) : Info(creator)
     {
         RegisterObject(GametypeInfo);
-
+        
         this->bStarted_ = false;
         this->bEnded_ = false;
-        this->startCountdown_ = 0;
+        this->startCountdown_ = 0.0f;
         this->bStartCountdownRunning_ = false;
+        this->counter_ = 0;
+        this->spawned_ = false;
+        this->readyToSpawn_ = false;
 
         this->registerVariables();
@@ -63,10 +86,309 @@
     void GametypeInfo::registerVariables()
     {
-        registerVariable(this->bStarted_,               VariableDirection::ToClient);
-        registerVariable(this->bEnded_,                 VariableDirection::ToClient);
+        registerVariable(this->bStarted_,               VariableDirection::ToClient, new NetworkCallback<GametypeInfo>(this, &GametypeInfo::changedStarted));
+        registerVariable(this->bEnded_,                 VariableDirection::ToClient, new NetworkCallback<GametypeInfo>(this, &GametypeInfo::changedEnded));
+        registerVariable(this->bStartCountdownRunning_, VariableDirection::ToClient, new NetworkCallback<GametypeInfo>(this, &GametypeInfo::changedStartCountdownRunning));
         registerVariable(this->startCountdown_,         VariableDirection::ToClient);
-        registerVariable(this->bStartCountdownRunning_, VariableDirection::ToClient);
+        registerVariable(this->counter_,                VariableDirection::ToClient, new NetworkCallback<GametypeInfo>(this, &GametypeInfo::changedCountdownCounter));
         registerVariable(this->hudtemplate_,            VariableDirection::ToClient);
     }
+
+    /**
+    @brief
+        Is called when the game has changed to started.
+    */
+    void GametypeInfo::changedStarted(void)
+    {
+        
+    }
+
+    /**
+    @brief
+        Is called when the game has changed to ended.
+    */
+    void GametypeInfo::changedEnded(void)
+    {
+        // If the game has ended, a "Game has ended" notification is displayed.
+        if(this->hasEnded())
+            NotificationListener::sendNotification("Game has ended", GametypeInfo::NOTIFICATION_SENDER);
+    }
+
+    /**
+    @brief
+        Is called when the start countdown has been either started or stopped.
+    */
+    void GametypeInfo::changedStartCountdownRunning(void)
+    {
+        // Send first countdown notification if the countdown has started.
+        if(this->isReadyToSpawn() && !this->hasStarted() && this->isStartCountdownRunning() && !this->hasEnded())
+            NotificationListener::sendNotification(multi_cast<std::string>(this->counter_), GametypeInfo::NOTIFICATION_SENDER);
+    }
+
+    /**
+    @brief
+        Is called when the start countdown counter has changed.
+    */
+    void GametypeInfo::changedCountdownCounter(void)
+    {
+        // Send countdown notification if the counter has gone down.
+        if(this->isReadyToSpawn() &&  !this->hasStarted() && this->isStartCountdownRunning() && !this->hasEnded())
+            NotificationListener::sendNotification(multi_cast<std::string>(this->counter_), GametypeInfo::NOTIFICATION_SENDER);
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo that the local player has changed its ready to spawn status.
+    @param ready
+        Whether the player has become ready to spawn or not.
+    */
+    void GametypeInfo::changedReadyToSpawn(bool ready)
+    {
+        if(this->readyToSpawn_ == ready)
+            return;
+
+        this->readyToSpawn_ = ready;
+
+        // Send "Waiting for other players" if the player is ready to spawn but the game has not yet started nor is the countdown running.
+        if(this->readyToSpawn_ && !this->hasStarted() && !this->isStartCountdownRunning() && !this->hasEnded())
+            NotificationListener::sendNotification("Waiting for other players", GametypeInfo::NOTIFICATION_SENDER);
+        // Send current countdown if the player is ready to spawn and the countdown has already started.
+        else if(this->readyToSpawn_ && !this->hasStarted() && this->isStartCountdownRunning() && !this->hasEnded())
+            NotificationListener::sendNotification(multi_cast<std::string>(this->counter_), GametypeInfo::NOTIFICATION_SENDER);
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo that the game has started.
+    */
+    void GametypeInfo::start(void)
+    {
+        if(this->bStarted_)
+            return;
+        
+        this->bStarted_ = true;
+        this->changedStarted();
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo that the game has ended.
+    */
+    void GametypeInfo::end(void)
+    {
+        if(this->bEnded_)
+            return;
+
+        this->bEnded_ = true;
+        this->changedEnded();
+    }
+
+    /**
+    @brief
+        Set the start countdown to the input value.
+    @param countdown
+        The countdown to be set.
+    */
+    void GametypeInfo::setStartCountdown(float countdown)
+    {
+        if(this->startCountdown_ == countdown || countdown < 0.0f)
+            return;
+        
+        this->startCountdown_ = countdown;
+        // Set the counter to the ceiling of the current countdown.
+        this->counter_ = ceil(countdown);
+        this->changedCountdownCounter();
+    }
+
+    /**
+    @brief
+        Count down the start countdown by the specified value.
+    @param countDown
+        The amount by which we count down.
+    */
+    void GametypeInfo::countdownStartCountdown(float countDown)
+    {
+        float newCountdown = this->startCountdown_ - countDown;
+        // If we have switched integers or arrived at zero, we also count down the start countdown counter.
+        if(ceil(newCountdown) != ceil(this->startCountdown_) || newCountdown <= 0.0f)
+            this->countDown();
+        this->startCountdown_ = newCountdown;
+    }
+
+    /**
+    @brief
+        Count down the start countdown counter.
+    */
+    void GametypeInfo::countDown()
+    {
+        if(this->counter_ == 0)
+            return;
+        
+        this->counter_--;
+        this->changedCountdownCounter();
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo about the start of the start countdown.
+    */
+    void GametypeInfo::startStartCountdown(void)
+    {
+        if(GameMode::isMaster())
+        {
+            if(this->bStartCountdownRunning_)
+                return;
+
+            this->bStartCountdownRunning_ = true;
+            this->changedStartCountdownRunning();
+        }
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo about the stop of the start countdown.
+    */
+    void GametypeInfo::stopStartCountdown(void)
+    {
+        if(GameMode::isMaster())
+        {
+            if(!this->bStartCountdownRunning_)
+                return;
+
+            this->bStartCountdownRunning_ = false;
+            this->changedStartCountdownRunning();
+        }
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo about a player that is ready to spawn.
+    @param player
+        The player that is ready to spawn.
+    */
+    void GametypeInfo::playerReadyToSpawn(PlayerInfo* player)
+    {
+        if(GameMode::isMaster())
+        {
+            // If the player has spawned already.
+            if(this->spawnedPlayers_.find(player) != this->spawnedPlayers_.end())
+                return;
+
+            this->spawnedPlayers_.insert(player);
+            this->setReadyToSpawnHelper(player, true);
+        }
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo about a player whose Pawn has been killed.
+    @param player
+        The player whose Pawn has been killed.
+    */
+    void GametypeInfo::pawnKilled(PlayerInfo* player)
+    {
+        if(GameMode::isMaster())
+        {
+            NotificationListener::sendNotification("Press [Fire] to respawn", GametypeInfo::NOTIFICATION_SENDER, notificationMessageType::info, notificationSendMode::network, player->getClientID());
+            // Remove the player from the list of players that have spawned, since it currently is not.
+            this->spawnedPlayers_.erase(player);
+            this->setReadyToSpawnHelper(player, false);
+            this->setSpawnedHelper(player, false);
+        }
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo about a player that has spawned.
+    @param player
+        The player that has spawned.
+    */
+    void GametypeInfo::playerSpawned(PlayerInfo* player)
+    {
+        if(GameMode::isMaster())
+        {
+            if(this->hasStarted() && !this->hasEnded())
+            {
+                //NotificationListener::sendCommand("clear", GametypeInfo::NOTIFICATION_SENDER, notificationSendMode::network, player->getClientID());
+                this->setSpawnedHelper(player, true);
+            }
+        }
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo that the local player has changed its spawned status.
+    @param spawned
+        Whether the local player has changed to spawned or to not spawned.
+    */
+    void GametypeInfo::changedSpawned(bool spawned)
+    {
+        if(this->spawned_ == spawned)
+            return;
+        
+        this->spawned_ = spawned;
+        // Clear the notifications if the Player has spawned.
+        if(this->spawned_ && !this->hasEnded())
+            NotificationListener::sendCommand("clear", GametypeInfo::NOTIFICATION_SENDER);
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo about a player that has entered,
+    @param player
+        The player that has entered.
+    */
+    void GametypeInfo::playerEntered(PlayerInfo* player)
+    {
+        if(GameMode::isMaster())
+        {
+            // Display "Press [Fire] to start the match" if the game has not yet ended.
+            if(!this->hasEnded())
+                NotificationListener::sendNotification("Press [Fire] to start the match", GametypeInfo::NOTIFICATION_SENDER, notificationMessageType::info, notificationSendMode::network, player->getClientID());
+            // Else display "Game has ended".
+            else
+                NotificationListener::sendNotification("Game has ended", GametypeInfo::NOTIFICATION_SENDER, notificationMessageType::info, notificationSendMode::network, player->getClientID());
+        }
+    }
+
+    /**
+    @brief
+        Helper method. Sends changedReadyToSpawn notifiers over the network.
+    @param player
+        The player that has changed its ready to spawn status.
+    @param ready
+        The new ready to spawn status.
+    */
+    void GametypeInfo::setReadyToSpawnHelper(PlayerInfo* player, bool ready)
+    {
+        if(GameMode::isMaster())
+        {
+            if(player->getClientID() == CLIENTID_SERVER)
+                this->changedReadyToSpawn(ready);
+            else
+                callMemberNetworkFunction(GametypeInfo, changedReadyToSpawn, this->getObjectID(), player->getClientID(), ready);
+        }
+    }
+
+    /**
+    @brief
+        Helper method. Sends changedSpawned notifiers over the network.
+    @param player
+        The player that has changed its spawned status.
+    @param ready
+        The new spawned status.
+    */
+    void GametypeInfo::setSpawnedHelper(PlayerInfo* player, bool spawned)
+    {
+        if(GameMode::isMaster())
+        {
+            if(player->getClientID() == CLIENTID_SERVER)
+                    this->changedSpawned(spawned);
+            else
+                callMemberNetworkFunction(GametypeInfo, changedSpawned, this->getObjectID(), player->getClientID(), spawned);
+        }
+    }
+
+    // Announce messages.
+    // TODO: Replace with notifications.
 
     void GametypeInfo::sendAnnounceMessage(const std::string& message)
Index: code/branches/presentation/src/orxonox/infos/GametypeInfo.h
===================================================================
--- code/branches/presentation/src/orxonox/infos/GametypeInfo.h	(revision 8632)
+++ code/branches/presentation/src/orxonox/infos/GametypeInfo.h	(revision 8637)
@@ -23,7 +23,12 @@
  *      Fabian 'x3n' Landau
  *   Co-authors:
- *      ...
+ *      Damian 'Mozork' Frick
  *
  */
+
+/**
+    @file GametypeInfo.h
+    @brief Definition of the GametypeInfo class
+*/
 
 #ifndef _GametypeInfo_H__
@@ -33,8 +38,19 @@
 
 #include <string>
+
 #include "Info.h"
 
 namespace orxonox
 {
+
+    /**
+    @brief
+        The GametypeInfo class keeps track of the state of the game and provides facilities to inform the player about it.
+
+    @author
+        Fabian 'x3n' Landau
+    @author
+        Damian 'Mozork' Frick
+    */
     class _OrxonoxExport GametypeInfo : public Info
     {
@@ -45,13 +61,59 @@
             virtual ~GametypeInfo();
 
+            /**
+            @brief Get whether the game has started yet.
+            @return Returns true if the game has started, false if not.
+            */
             inline bool hasStarted() const
                 { return this->bStarted_; }
+            void changedStarted(void); // Is called when the game has changed to started.
+            
+            /**
+            @brief Get whether the game has ended yet.
+            @return Returns true if the game has ended, false if not.
+            */
             inline bool hasEnded() const
                 { return this->bEnded_; }
+            void changedEnded(void); // Is called when the game has changed to ended.
 
+            /**
+            @brief Get whether the start countdown is currently running.
+            @return Returns true if the countdown is running, false if not.
+            */
             inline bool isStartCountdownRunning() const
                 { return this->bStartCountdownRunning_; }
+            void changedStartCountdownRunning(void); // Is called when the start countdown has been either started or stopped.
+
+            /**
+            @brief Get the current value of the start countdown.
+            @return Returns the current value of the start countdown.
+            */
             inline float getStartCountdown() const
                 { return this->startCountdown_; }
+
+            /**
+            @brief Get the current start countdown counter.
+                   The start countdown counter only has integer values that correspond to the actually displayed countdown.
+            @return Returns the current integer countdown counter.
+            */
+            inline unsigned int getStartCountdownCounter() const
+                { return this->counter_; }
+            void changedCountdownCounter(void); // Is called when the start countdown counter has changed.
+
+            /**
+            @brief Get whether the local player is ready to spawn.
+            @return Returns true if the player is ready to spawn, false if not.
+            */
+            inline bool isReadyToSpawn() const
+                { return this->readyToSpawn_; }
+            void changedReadyToSpawn(bool ready); // Inform the GametypeInfo that the local player has changed its spawned status.
+            
+            /**
+            @brief Get whether the local player is spawned.
+            @return Returns true if the local player is currently spawned, false if not.
+            */
+            inline bool isSpawned() const
+                { return this->spawned_; }
+            void changedSpawned(bool spawned); // Inform the GametypeInfo that the local player has changed its spawned status.
 
             inline const std::string& getHUDTemplate() const
@@ -70,13 +132,38 @@
             void dispatchStaticMessage(const std::string& message,const ColourValue& colour);
             void dispatchFadingMessage(const std::string& message);
+            
+        protected:
+            void start(void); // Inform the GametypeInfo that the game has started.
+            void end(void); // Inform the GametypeInfo that the game has ended.
+            void setStartCountdown(float countdown); // Set the start countdown to the input value.
+            void countdownStartCountdown(float countDown); // Count down the start countdown by the specified value.
+            void countDown(); // Count down the start countdown counter.
+            void startStartCountdown(void); // Inform the GametypeInfo about the start of the start countdown.
+            void stopStartCountdown(void); // Inform the GametypeInfo about the stop of the start countdown.
+            void playerReadyToSpawn(PlayerInfo* player); // Inform the GametypeInfo about a player that is ready to spawn.
+            void pawnKilled(PlayerInfo* player); // Inform the GametypeInfo about a player whose Pawn has been killed.
+            void playerSpawned(PlayerInfo* player); // Inform the GametypeInfo about a player that has spawned.
+            void playerEntered(PlayerInfo* player); // Inform the GametypeInfo about a player that has entered,
+
+            inline void setHUDTemplate(const std::string& templateName)
+                { this->hudtemplate_ = templateName; };
 
         private:
             void registerVariables();
+            void setSpawnedHelper(PlayerInfo* player, bool spawned); // Helper method. Sends changedReadyToSpawn notifiers over the network.
+            void setReadyToSpawnHelper(PlayerInfo* player, bool ready); // Helper method. Sends changedSpawned notifiers over the network.
 
-            bool bStarted_;
-            bool bEnded_;
-            bool bStartCountdownRunning_;
-            float startCountdown_;
+            static const std::string NOTIFICATION_SENDER; //!< The name of the sender for the sending of notifications.
+
+            bool bStarted_; //!< Whether the game has started,
+            bool bEnded_; //!< Whether the game has ended.
+            bool bStartCountdownRunning_; //!< Whether the start countdown is running.
+            float startCountdown_; //!< The current value of the start countdown.
+            unsigned int counter_; //!< The current integer value of the start countdown, the start countdown counter.
             std::string hudtemplate_;
+            
+            std::set<PlayerInfo*> spawnedPlayers_; //!< A set of players that are currently spawned.
+            bool spawned_; //!< Whether the local Player is currently spawned.
+            bool readyToSpawn_; //!< Whether the local Player is ready to spawn.
     };
 }
Index: code/branches/presentation/src/orxonox/interfaces/CMakeLists.txt
===================================================================
--- code/branches/presentation/src/orxonox/interfaces/CMakeLists.txt	(revision 8632)
+++ code/branches/presentation/src/orxonox/interfaces/CMakeLists.txt	(revision 8637)
@@ -1,4 +1,5 @@
 ADD_SOURCE_FILES(ORXONOX_SRC_FILES
   InterfaceCompilation.cc
+  NotificationListener.cc
   Pickupable.cc
   PickupCarrier.cc
Index: code/branches/presentation/src/orxonox/interfaces/InterfaceCompilation.cc
===================================================================
--- code/branches/presentation/src/orxonox/interfaces/InterfaceCompilation.cc	(revision 8632)
+++ code/branches/presentation/src/orxonox/interfaces/InterfaceCompilation.cc	(revision 8637)
@@ -86,11 +86,3 @@
         RegisterRootObject(Rewardable);
     }
-
-    //----------------------------
-    // NotificationListener
-    //----------------------------
-    NotificationListener::NotificationListener()
-    {
-        RegisterRootObject(NotificationListener);
-    }
 }
Index: code/branches/presentation/src/orxonox/interfaces/NotificationListener.cc
===================================================================
--- code/branches/presentation/src/orxonox/interfaces/NotificationListener.cc	(revision 8637)
+++ code/branches/presentation/src/orxonox/interfaces/NotificationListener.cc	(revision 8637)
@@ -0,0 +1,161 @@
+/*
+ *   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:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file NotificationListener.cc
+    @brief Implementation of the NotificationListener class.
+*/
+
+#include "core/CoreIncludes.h"
+#include "network/Host.h"
+#include "network/NetworkFunction.h"
+#include "util/SubString.h"
+
+#include "interfaces/NotificationListener.h"
+
+namespace orxonox
+{
+    
+    /*static*/ const std::string NotificationListener::ALL("all");
+    /*static*/ const std::string NotificationListener::NONE("none");
+    
+    // Commands
+    /*static*/ const std::string NotificationListener::COMMAND_CLEAR("clear");
+    /*static*/ const std::string NotificationListener::COMMAND_NONE("none");
+    
+    registerStaticNetworkFunction(NotificationListener::sendHelper);
+    
+    NotificationListener::NotificationListener()
+    {
+        RegisterRootObject(NotificationListener);
+    }
+
+    /**
+    @brief
+        Helper method to send both notifications and commands over the network.
+    @param message
+        The message/command that should be sent.
+    @param sender
+        The sender that sent the notification/command.
+    @param sendMode
+        The mode in which the notification/command is sent, can be 'local' to send the notification to the client where this function is executed, 'network' if the notification is to be sent to the client with the specified clientID, or 'broadcast' if the notification should be sent to all hosts.
+    @param clientId
+        The id of the client the notification/command should be sent to.
+    @param isCommand
+        Whether the message is a notification or a command.
+    @param messageType
+        The type of the notification, can be either 'info' or 'important'.
+    */
+    /*static*/ void NotificationListener::sendNetworkHelper(const std::string& message, const std::string& sender, notificationSendMode::Value sendMode, unsigned int clientId, bool isCommand, notificationMessageType::Value messageType)
+    {
+        // If we're in standalone mode or we're already no the right client we create and send the notification/command.
+        if(GameMode::isStandalone() || sendMode == notificationSendMode::local || (sendMode ==  notificationSendMode::network && Host::getPlayerID() == clientId))
+        {
+            sendHelper(message, sender, isCommand, messageType);
+        }
+        // If we're on the server (and the server is not the intended recipient of the notification/command) we send it over the network.
+        else if(GameMode::isServer() && sendMode == notificationSendMode::network && Host::getPlayerID() != clientId)
+        {
+            callStaticNetworkFunction(NotificationListener::sendHelper, clientId, message, sender, isCommand, (unsigned int)messageType);
+        }
+        else if(GameMode::isServer() && sendMode == notificationSendMode::broadcast)
+        {
+            // TODO: Works as intended?
+            callStaticNetworkFunction(NotificationListener::sendHelper, NETWORK_PEER_ID_BROADCAST, message, sender, isCommand, (unsigned int)messageType);
+        }
+    }
+
+    /**
+    @brief
+        Helper method to register a notification/execute a command with all NotificationListeners after it has been sent over the network.
+    @param message
+        The notification/command to be sent/executed.
+    @param sender
+        The sender that sent the notification/command.
+    @param isCommand
+        Whether the message is a command or a notification.
+    @param messageType
+        The type of the notification.
+    */
+    /*static*/ void NotificationListener::sendHelper(const std::string& message, const std::string& sender, bool isCommand, unsigned int messageType)
+    {
+        // Iterate through all NotificationListeners and notify them by calling the method they overloaded.
+        for(ObjectList<NotificationListener>::iterator it = ObjectList<NotificationListener>::begin(); it != ObjectList<NotificationListener>::end(); ++it)
+        {
+            // If the notification is a message.
+            if(!isCommand)
+                it->registerNotification(message, sender, notificationMessageType::Value(messageType));
+
+            // If the notification is a command.
+            if(isCommand)
+            {
+                notificationCommand::Value command = str2Command(message);
+                if(command != notificationCommand::none)
+                    it->executeCommand(command, sender);
+            }
+        }
+    }
+
+    /**
+    @brief
+        Helper method. Converts a string into the enum for a command.
+    @param string
+        The string to be converted.
+    @return
+        Returns the corresponding enum, notificationCommand::none if the command doesn't exist.
+    */
+    /*static*/ notificationCommand::Value NotificationListener::str2Command(const std::string& string)
+    {
+        notificationCommand::Value command = notificationCommand::none;
+
+        if(string == NotificationListener::COMMAND_CLEAR)
+            command = notificationCommand::clear;
+
+        return command;
+    }
+
+    /**
+    @brief
+        Helper method. Converts a command enum into its corresponding string.
+    @param command
+        The command to be converted.
+    @return
+        Returns the corresponding string.
+    */
+    /*static*/ const std::string& NotificationListener::command2Str(notificationCommand::Value command)
+    {
+        switch(command)
+        {
+            case notificationCommand::clear:
+                return NotificationListener::COMMAND_CLEAR;
+            default:
+                return NotificationListener::COMMAND_NONE;
+        }
+    }
+    
+}
Index: code/branches/presentation/src/orxonox/interfaces/NotificationListener.h
===================================================================
--- code/branches/presentation/src/orxonox/interfaces/NotificationListener.h	(revision 8632)
+++ code/branches/presentation/src/orxonox/interfaces/NotificationListener.h	(revision 8637)
@@ -21,5 +21,5 @@
  *
  *   Author:
- *      Fabian 'x3n' Landau
+ *      Damian 'Mozork' Frick
  *   Co-authors:
  *      ...
@@ -48,17 +48,45 @@
 namespace orxonox
 {
-    class Notification;
+    // TODO: Document.
+    namespace notificationMessageType
+    {
+        enum Value {
+            info,
+            important
+        };
+    }
+    
+    namespace notificationSendMode
+    {
+        enum Value {
+            local,
+            network,
+            broadcast
+        };
+    }
+    
+    namespace notificationCommand
+    {
+        enum Value {
+            none,
+            clear
+        };
+    }
 
+    // TODO: Update doc.
     /**
     @brief
         NotificationListener interface.
 
-        The NotificationListener interface presents a means to being informed when @ref orxonox::Notification "Notifications" in the target set of this NotificationListener change. (e.g. @ref orxonox::Notification "Notifications" were added or removed)
-        When inheriting from a NotificationListener it is important to register (in the constructor) and unregister (in the destructor) it to and from the @ref orxonox::NotificationManager "NotificationManager".
+        The NotificationListener interface (or more precisely abstract class) presents a means of being informed when a new @ref orxonox::Notification "Notification" is sent.
+        The NotificationListener can be used to send a new notification message (with NotificationListener::sendNotification() ) or a new notification command (with NotificationListener::sendCommand() ). Each NotificationListener is then informed about the new @ref orxonox::Notification "Notification" and can take appropriate action. Currently the only NotificationListener ist the @ref orxonox::NotificationManager "NotificationManager" singleton.
+
+        When inheriting from a NotificationListener it is important to provide an appropriate implementation of registerNotification() and executeCommand().
 
     @author
-        Fabian 'x3n' Landau
-
+        Damian 'Mozork' Frick
+        
     @ingroup Notifications
+    @todo Consistent terminology between message, notification and command.
     */
     class _OrxonoxExport NotificationListener : virtual public OrxonoxClass
@@ -69,20 +97,60 @@
 
             /**
-            @brief Get the senders that are targets of this NotificationListener.
-            @return Returns the set of senders that are targets of this NotificationListener.
+            @brief Sends a Notification with the specified message to the specified client from the specified sender.
+            @param message The message that should be sent.
+            @param sender The sender that sent the notification. Default is 'none'.
+            @param messageType The type of the message, can be either 'info' or 'important'. Default is 'info'.
+            @param sendMode The mode in which the notification is sent, can be 'local' to send the notification to the client where this function is executed, 'network' if the notification is to be sent to the client with the specified clientID, or 'broadcast' if the notification should be sent to all hosts. Default is notificationSendMode::local.
+            @param clientId The id of the client the notification should be sent to. Default is 0.
             */
-            virtual const std::set<std::string> & getTargetsSet(void) = 0;
+            static void sendNotification(const std::string& message, const std::string& sender = NotificationListener::NONE, notificationMessageType::Value messageType = notificationMessageType::info, notificationSendMode::Value sendMode = notificationSendMode::local, unsigned int clientId = 0)
+                { NotificationListener::sendNetworkHelper(message, sender, sendMode, clientId, false, messageType); }
+            /**
+            @brief Sends a specified command to the specified client from the specified sender.
+            @param command The command that should be sent (and later executed).
+            @param sender The sender that sent the notification. Default is 'none'.
+            @param sendMode The mode in which the command is sent, can be 'local' to send the command to the client where this function is executed, 'network' if the command is to be sent to the client with the specified clientID, or 'broadcast' if the command should be sent to all hosts. Default is notificationSendMode::local.
+            @param clientId The id of the client the command should be sent to. Default is 0.
+            */
+            static void sendCommand(const std::string& command, const std::string& sender = NotificationListener::NONE, notificationSendMode::Value sendMode = notificationSendMode::local, unsigned int clientId = 0)
+                { NotificationListener::sendNetworkHelper(command, sender, sendMode, clientId, true); }
 
+            static void sendHelper(const std::string& message, const std::string& sender, bool isCommand = false, unsigned int messageMode = 0); // Helper method to register a notification/execute a command with all NotificationListeners after it has been sent over the network.
+
+            //TODO: Make protected?
+            
             /**
-            @brief Updates the whole NotificationListener.
-                   This is called by the @ref orxonox::NotificationManager "NotificationManager" when the @ref orxonox::Notification "Notifications" have changed so much, that the NotificationListener may have to re-initialize his operations.
+            @brief Registers a notification with the NotificationListener.
+                   This needs to be overloaded by each class inheriting from NotificationListener.
+            @param message The notification's message.
+            @param sender The sender of the notification.
+            @param type The type of the notification.
+            @return Returns true if the notification was successfully registered, false if not.
             */
-            virtual void update(void) = 0;
+            virtual bool registerNotification(const std::string& message, const std::string& sender, notificationMessageType::Value type)
+                { return false; }
             /**
-            @brief Updates the NotificationListener, when a new Notification has come in at the specified time.
-            @param notification A pointer to the @ref orxonox::Notification "Notification".
-            @param time The time the @ref orxonox::Notification "Notification" has come in.
+            @brief Executes a command with the NotificationListener
+                   This needs to be overloaded by each class inheriting from NotificationListener.
+            @param command The command to be executed.
+            @param sender The sender of the command.
+            @return Returns true if the command was successfully executed, false if not.
             */
-            virtual void update(Notification* notification, const std::time_t & time) = 0;
+            virtual bool executeCommand(notificationCommand::Value command, const std::string& sender) { return false; }
+
+        public:
+            
+            static const std::string ALL; //!< Static string to indicate a sender that sends to all NotificationQueues.
+            static const std::string NONE; //!< Static string to indicate a sender that sends to no specific NotificationQueues.
+            
+            //! Commands
+            static const std::string COMMAND_CLEAR;
+            static const std::string COMMAND_NONE;
+            
+        protected:
+            static void sendNetworkHelper(const std::string& message, const std::string& sender, notificationSendMode::Value sendMode, unsigned int clientId, bool isCommand = false, notificationMessageType::Value messageType = notificationMessageType::info); // Helper method to send both notifications and commands over the network.
+
+            static notificationCommand::Value str2Command(const std::string& string); // Helper method. Converts a string into the enum for a command.
+            static const std::string& command2Str(notificationCommand::Value command); // Helper method. Converts a command enum into its corresponding string.
     };
 }
