Index: code/branches/core5/src/orxonox/gamestates/CMakeLists.txt
===================================================================
--- code/branches/core5/src/orxonox/gamestates/CMakeLists.txt	(revision 5842)
+++ code/branches/core5/src/orxonox/gamestates/CMakeLists.txt	(revision 5848)
@@ -2,4 +2,5 @@
   GSClient.cc
   GSDedicated.cc
+  GSDedicatedClient.cc
   GSGraphics.cc
   GSIOConsole.cc
Index: code/branches/core5/src/orxonox/gamestates/GSDedicatedClient.cc
===================================================================
--- code/branches/core5/src/orxonox/gamestates/GSDedicatedClient.cc	(revision 5848)
+++ code/branches/core5/src/orxonox/gamestates/GSDedicatedClient.cc	(revision 5848)
@@ -0,0 +1,306 @@
+/*
+ *   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:
+ *      Reto Grieder
+ *   Co-authors:
+ *      Oliver Scheuss
+ *
+ */
+
+#include "GSDedicatedClient.h"
+
+#include <iomanip>
+#include <iostream>
+#include <boost/bind.hpp>
+
+#include "util/Debug.h"
+#include "util/Exception.h"
+#include "util/Sleep.h"
+#include "core/Clock.h"
+#include "core/CommandLine.h"
+#include "core/CommandExecutor.h"
+#include "core/Game.h"
+#include "core/GameMode.h"
+#include "network/Client.h"
+
+#ifdef ORXONOX_PLATFORM_UNIX
+#include <termios.h>
+#endif
+
+
+namespace orxonox
+{
+    const unsigned int MAX_COMMAND_LENGTH = 255;
+    
+    DeclareGameState(GSDedicatedClient, "dedicatedClient", false, false);
+    
+    termios* GSDedicatedClient::originalTerminalSettings_;
+
+    GSDedicatedClient::GSDedicatedClient(const GameStateInfo& info)
+        : GameState(info)
+        , client_(0)
+        , closeThread_(false)
+        , cleanLine_(true)
+        , inputIterator_(0)
+        , cursorX_(0)
+        , cursorY_(0)
+    {
+    }
+
+    GSDedicatedClient::~GSDedicatedClient()
+    {
+    }
+
+    void GSDedicatedClient::activate()
+    {
+        this->inputThread_ = new boost::thread(boost::bind(&GSDedicatedClient::inputThread, this));
+        
+#ifndef ORXONOX_PLATFORM_WINDOWS
+        this->originalTerminalSettings_ = new termios;
+        this->setTerminalMode();
+#endif
+
+        this->client_ = new Client(CommandLine::getValue("ip").getString(), CommandLine::getValue("port"));
+        COUT(0) << "Loading scene in client mode" << std::endl;
+
+        if( !client_->establishConnection() )
+            ThrowException(InitialisationFailed, "Could not establish connection with server.");
+            
+        client_->update(Game::getInstance().getGameClock());
+
+
+    }
+
+    void GSDedicatedClient::deactivate()
+    {
+        if( this->client_ )
+        {
+            this->client_->closeConnection();
+            delete this->client_;
+        }
+        
+        closeThread_ = true;
+#ifdef ORXONOX_PLATFORM_UNIX
+        std::cout << "\033[0G\033[K";
+        std::cout.flush();
+        resetTerminalMode();
+        delete this->originalTerminalSettings_;
+#else
+        COUT(0) << "Press enter to end the game..." << std::endl;
+#endif
+        inputThread_->join();
+        delete this->inputThread_;
+    }
+
+    void GSDedicatedClient::update(const Clock& time)
+    {
+        client_->update(time);
+        processQueue();
+        printLine();
+    }
+    
+    void GSDedicatedClient::inputThread()
+    {
+        this->commandLine_ = new unsigned char[MAX_COMMAND_LENGTH];
+//         memset( this->commandLine_, 0, MAX_COMMAND_LENGTH );
+        unsigned char c;
+        unsigned int  escapeChar=0;
+        while(!closeThread_)
+        {
+#ifdef ORXONOX_PLATFORM_UNIX
+            size_t count = read(STDIN_FILENO, &c, 1);
+            if (count == 1)
+#else
+            c = getchar();
+#endif
+            {
+//                 boost::recursive_mutex::scoped_lock(this->inputLineMutex_);
+                if ( inputIterator_>=MAX_COMMAND_LENGTH-1 && c!='\n' )
+                    continue;
+                if( escapeChar > 0 )
+                {
+                    if( c == '[' )
+                    {
+                        escapeChar = 2;
+                        continue;
+                    }
+                    else if ( escapeChar == 2 )
+                    {
+                        switch (c)
+                        {
+                            case 'A': //keyup
+                                
+                                break;
+                            case 'B': //keydown
+                                
+                                break;
+                            case 'C': //keyright
+                                if(cursorX_<inputIterator_)
+                                    ++cursorX_;
+                                break;
+                            case 'D': //keyleft
+                                if(cursorX_>0)
+                                    --cursorX_;
+                                break;
+                            default: //not supported...
+//                                 std::cout << endl << c << endl;
+                                break;
+                        }
+                        escapeChar = 0;
+                    }
+                }
+                else // not in escape sequence mode
+                {
+                    switch (c)
+                    {
+                        case '\n':
+                            this->cleanLine_ = true;
+                            {
+                                boost::recursive_mutex::scoped_lock(this->inputQueueMutex_);
+                                boost::recursive_mutex::scoped_lock(this->inputLineMutex_);
+                                this->commandQueue_.push( std::string((const char*)this->commandLine_,inputIterator_) );
+                            }
+                            memset( this->commandLine_, 0, inputIterator_ );
+                            inputIterator_ = 0;
+                            this->cursorX_ = 0;
+                            this->cursorY_ = 0;
+                            std::cout << endl;
+                            break;
+                        case 127: // backspace
+                        case '\b':
+                            deleteCharacter( this->cursorX_ );
+                            break;
+                        case '\t':
+                        {
+//                             boost::recursive_mutex::scoped_lock(this->inputLineMutex_);
+                            std::cout << endl << CommandExecutor::hint( std::string((const char*)this->commandLine_,inputIterator_) ) << endl;
+                            strncpy(reinterpret_cast<char*>(this->commandLine_), CommandExecutor::complete( std::string(reinterpret_cast<char*>(this->commandLine_),inputIterator_) ).c_str(), MAX_COMMAND_LENGTH);
+                            this->inputIterator_ = strlen((const char*)this->commandLine_);
+                            this->cursorX_ = this->inputIterator_;
+                            break;
+                        }
+                        case '\033': // 1. escape character
+                            escapeChar = 1;
+                            break;
+                        default:
+                            insertCharacter( this->cursorX_, c );
+                            break;
+                    }
+                }
+            }
+        }
+
+        delete[] this->commandLine_;
+    }
+    
+    void GSDedicatedClient::printLine()
+    {
+#ifdef ORXONOX_PLATFORM_UNIX
+        // set cursor to the begining of the line and erase the line
+        std::cout << "\033[0G\033[K";
+//         boost::recursive_mutex::scoped_lock(this->inputLineMutex_);
+        // print status line
+        std::cout << std::fixed << std::setprecision(2) << std::setw(5) << Game::getInstance().getAvgFPS() << " fps, " << std::setprecision(2) << std::setw(5) << Game::getInstance().getAvgTickTime() << " ms avg ticktime # ";
+        //save cursor position
+        std::cout << "\033[s";
+        //print commandLine buffer
+        std::cout << std::string((const char*)this->commandLine_, inputIterator_);
+        //restore cursor position and move it cursorX_ to the right
+        std::cout << "\033[u";
+        if( this->cursorX_ > 0 )
+            std::cout << "\033[" << this->cursorX_ << "C";
+        std::cout.flush();
+#endif
+    }
+    
+    void GSDedicatedClient::processQueue()
+    {
+        std::string tempstr;
+        {
+            boost::recursive_mutex::scoped_lock lock1(this->inputQueueMutex_);
+            while(true)
+            {
+                if ( !this->commandQueue_.empty() )
+                {
+                    tempstr = this->commandQueue_.front();
+                    this->commandQueue_.pop();
+                    lock1.unlock();
+                }
+                else
+                    break;
+                CommandExecutor::execute(tempstr, true);
+            }
+        }
+    }
+    
+    void GSDedicatedClient::setTerminalMode()
+    {
+#ifdef ORXONOX_PLATFORM_UNIX
+        termios new_settings;
+     
+        tcgetattr(0,this->originalTerminalSettings_);
+        new_settings = *this->originalTerminalSettings_;
+        new_settings.c_lflag &= ~( ICANON | ECHO );
+//         new_settings.c_lflag |= ( ISIG | IEXTEN );
+        new_settings.c_cc[VTIME] = 1;
+        new_settings.c_cc[VMIN] = 0;
+        tcsetattr(0,TCSANOW,&new_settings);
+        COUT(0) << endl;
+//       atexit(&GSDedicatedClient::resetTerminalMode);
+#endif
+    }
+    
+    void GSDedicatedClient::resetTerminalMode()
+    {
+#ifdef ORXONOX_PLATFORM_UNIX
+        tcsetattr(0, TCSANOW, GSDedicatedClient::originalTerminalSettings_);
+#endif
+    }
+    
+    void GSDedicatedClient::insertCharacter( unsigned int position, char c )
+    {
+//         std::cout << endl << static_cast<unsigned int>(c) << endl;
+        // check that we do not exceed MAX_COMMAND_LENGTH
+        if( inputIterator_+1 < MAX_COMMAND_LENGTH )
+        {
+            // if cursor not at end of line then move the rest of the line
+            if( position != this->inputIterator_ )
+                    memmove( this->commandLine_+position+1, this->commandLine_+position, this->inputIterator_-position);
+//             boost::recursive_mutex::scoped_lock(this->inputLineMutex_);
+            this->commandLine_[position] = c;
+            ++this->cursorX_;
+            ++this->inputIterator_;
+        }
+    }
+    void GSDedicatedClient::deleteCharacter( unsigned int position )
+    {
+//         boost::recursive_mutex::scoped_lock(this->inputLineMutex_);
+        if ( this->inputIterator_>0 && position>0 )
+        {
+            if ( position != this->inputIterator_ )
+                memmove( this->commandLine_+position-1, this->commandLine_+position, this->inputIterator_-position);
+            --this->cursorX_;
+            --this->inputIterator_;
+        }
+    }
+    
+}
Index: code/branches/core5/src/orxonox/gamestates/GSDedicatedClient.h
===================================================================
--- code/branches/core5/src/orxonox/gamestates/GSDedicatedClient.h	(revision 5848)
+++ code/branches/core5/src/orxonox/gamestates/GSDedicatedClient.h	(revision 5848)
@@ -0,0 +1,84 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      Oliver Scheuss
+ *
+ */
+
+#ifndef _GSDedicatedClient_H__
+#define _GSDedicatedClient_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "core/GameState.h"
+#include "network/NetworkPrereqs.h"
+#include <queue>
+#include <cstring>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/recursive_mutex.hpp>
+
+struct termios;
+
+namespace orxonox
+{
+
+    class _OrxonoxExport GSDedicatedClient : public GameState
+    {
+    public:
+        GSDedicatedClient(const GameStateInfo& info);
+        ~GSDedicatedClient();
+
+        void activate();
+        void deactivate();
+        void update(const Clock& time);
+
+    private:
+        void inputThread();
+        void printLine();
+        void processQueue();
+        void setTerminalMode();
+        static void resetTerminalMode();
+
+        void insertCharacter( unsigned int position, char c );
+        void deleteCharacter( unsigned int position );
+
+        Client*                 client_;
+
+        boost::thread           *inputThread_;
+        boost::recursive_mutex  inputLineMutex_;
+        boost::recursive_mutex  inputQueueMutex_;
+        bool                    closeThread_;
+        bool                    cleanLine_;
+        unsigned char*          commandLine_;
+        unsigned int            inputIterator_;
+        std::queue<std::string> commandQueue_;
+        static termios*         originalTerminalSettings_;
+
+        unsigned int            cursorX_;
+        unsigned int            cursorY_;
+    };
+}
+
+#endif /* _GSDedicatedClient_H__ */
