Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core5/src/orxonox/gamestates/GSDedicatedClient.cc @ 5867

Last change on this file since 5867 was 5855, checked in by rgrieder, 15 years ago

Moved Clock from core to util (used in Scope anyway).

File size: 10.4 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Reto Grieder
24 *   Co-authors:
25 *      Oliver Scheuss
26 *
27 */
28
29#include "GSDedicatedClient.h"
30
31#include <iomanip>
32#include <iostream>
33#include <boost/bind.hpp>
34
35#include "util/Clock.h"
36#include "util/Debug.h"
37#include "util/Exception.h"
38#include "util/Sleep.h"
39#include "core/CommandLine.h"
40#include "core/CommandExecutor.h"
41#include "core/Game.h"
42#include "core/GameMode.h"
43#include "network/Client.h"
44
45#ifdef ORXONOX_PLATFORM_UNIX
46#include <termios.h>
47#endif
48
49
50namespace orxonox
51{
52    const unsigned int MAX_COMMAND_LENGTH = 255;
53   
54    DeclareGameState(GSDedicatedClient, "dedicatedClient", false, false);
55   
56    termios* GSDedicatedClient::originalTerminalSettings_;
57
58    GSDedicatedClient::GSDedicatedClient(const GameStateInfo& info)
59        : GameState(info)
60        , client_(0)
61        , closeThread_(false)
62        , cleanLine_(true)
63        , inputIterator_(0)
64        , cursorX_(0)
65        , cursorY_(0)
66    {
67    }
68
69    GSDedicatedClient::~GSDedicatedClient()
70    {
71    }
72
73    void GSDedicatedClient::activate()
74    {
75        this->inputThread_ = new boost::thread(boost::bind(&GSDedicatedClient::inputThread, this));
76       
77#ifndef ORXONOX_PLATFORM_WINDOWS
78        this->originalTerminalSettings_ = new termios;
79        this->setTerminalMode();
80#endif
81
82        this->client_ = new Client(CommandLine::getValue("ip").getString(), CommandLine::getValue("port"));
83        COUT(0) << "Loading scene in client mode" << std::endl;
84
85        if( !client_->establishConnection() )
86            ThrowException(InitialisationFailed, "Could not establish connection with server.");
87           
88        client_->update(Game::getInstance().getGameClock());
89
90
91    }
92
93    void GSDedicatedClient::deactivate()
94    {
95        if( this->client_ )
96        {
97            this->client_->closeConnection();
98            delete this->client_;
99        }
100       
101        closeThread_ = true;
102#ifdef ORXONOX_PLATFORM_UNIX
103        std::cout << "\033[0G\033[K";
104        std::cout.flush();
105        resetTerminalMode();
106        delete this->originalTerminalSettings_;
107#else
108        COUT(0) << "Press enter to end the game..." << std::endl;
109#endif
110        inputThread_->join();
111        delete this->inputThread_;
112    }
113
114    void GSDedicatedClient::update(const Clock& time)
115    {
116        client_->update(time);
117        processQueue();
118        printLine();
119    }
120   
121    void GSDedicatedClient::inputThread()
122    {
123        this->commandLine_ = new unsigned char[MAX_COMMAND_LENGTH];
124//         memset( this->commandLine_, 0, MAX_COMMAND_LENGTH );
125        unsigned char c;
126        unsigned int  escapeChar=0;
127        while(!closeThread_)
128        {
129#ifdef ORXONOX_PLATFORM_UNIX
130            size_t count = read(STDIN_FILENO, &c, 1);
131            if (count == 1)
132#else
133            c = getchar();
134#endif
135            {
136//                 boost::recursive_mutex::scoped_lock(this->inputLineMutex_);
137                if ( inputIterator_>=MAX_COMMAND_LENGTH-1 && c!='\n' )
138                    continue;
139                if( escapeChar > 0 )
140                {
141                    if( c == '[' )
142                    {
143                        escapeChar = 2;
144                        continue;
145                    }
146                    else if ( escapeChar == 2 )
147                    {
148                        switch (c)
149                        {
150                            case 'A': //keyup
151                               
152                                break;
153                            case 'B': //keydown
154                               
155                                break;
156                            case 'C': //keyright
157                                if(cursorX_<inputIterator_)
158                                    ++cursorX_;
159                                break;
160                            case 'D': //keyleft
161                                if(cursorX_>0)
162                                    --cursorX_;
163                                break;
164                            default: //not supported...
165//                                 std::cout << endl << c << endl;
166                                break;
167                        }
168                        escapeChar = 0;
169                    }
170                }
171                else // not in escape sequence mode
172                {
173                    switch (c)
174                    {
175                        case '\n':
176                            this->cleanLine_ = true;
177                            {
178                                boost::recursive_mutex::scoped_lock(this->inputQueueMutex_);
179                                boost::recursive_mutex::scoped_lock(this->inputLineMutex_);
180                                this->commandQueue_.push( std::string((const char*)this->commandLine_,inputIterator_) );
181                            }
182                            memset( this->commandLine_, 0, inputIterator_ );
183                            inputIterator_ = 0;
184                            this->cursorX_ = 0;
185                            this->cursorY_ = 0;
186                            std::cout << endl;
187                            break;
188                        case 127: // backspace
189                        case '\b':
190                            deleteCharacter( this->cursorX_ );
191                            break;
192                        case '\t':
193                        {
194//                             boost::recursive_mutex::scoped_lock(this->inputLineMutex_);
195                            std::cout << endl << CommandExecutor::hint( std::string((const char*)this->commandLine_,inputIterator_) ) << endl;
196                            strncpy(reinterpret_cast<char*>(this->commandLine_), CommandExecutor::complete( std::string(reinterpret_cast<char*>(this->commandLine_),inputIterator_) ).c_str(), MAX_COMMAND_LENGTH);
197                            this->inputIterator_ = strlen((const char*)this->commandLine_);
198                            this->cursorX_ = this->inputIterator_;
199                            break;
200                        }
201                        case '\033': // 1. escape character
202                            escapeChar = 1;
203                            break;
204                        default:
205                            insertCharacter( this->cursorX_, c );
206                            break;
207                    }
208                }
209            }
210        }
211
212        delete[] this->commandLine_;
213    }
214   
215    void GSDedicatedClient::printLine()
216    {
217#ifdef ORXONOX_PLATFORM_UNIX
218        // set cursor to the begining of the line and erase the line
219        std::cout << "\033[0G\033[K";
220//         boost::recursive_mutex::scoped_lock(this->inputLineMutex_);
221        // print status line
222        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 # ";
223        //save cursor position
224        std::cout << "\033[s";
225        //print commandLine buffer
226        std::cout << std::string((const char*)this->commandLine_, inputIterator_);
227        //restore cursor position and move it cursorX_ to the right
228        std::cout << "\033[u";
229        if( this->cursorX_ > 0 )
230            std::cout << "\033[" << this->cursorX_ << "C";
231        std::cout.flush();
232#endif
233    }
234   
235    void GSDedicatedClient::processQueue()
236    {
237        std::string tempstr;
238        {
239            boost::recursive_mutex::scoped_lock lock1(this->inputQueueMutex_);
240            while(true)
241            {
242                if ( !this->commandQueue_.empty() )
243                {
244                    tempstr = this->commandQueue_.front();
245                    this->commandQueue_.pop();
246                    lock1.unlock();
247                }
248                else
249                    break;
250                CommandExecutor::execute(tempstr, true);
251            }
252        }
253    }
254   
255    void GSDedicatedClient::setTerminalMode()
256    {
257#ifdef ORXONOX_PLATFORM_UNIX
258        termios new_settings;
259     
260        tcgetattr(0,this->originalTerminalSettings_);
261        new_settings = *this->originalTerminalSettings_;
262        new_settings.c_lflag &= ~( ICANON | ECHO );
263//         new_settings.c_lflag |= ( ISIG | IEXTEN );
264        new_settings.c_cc[VTIME] = 1;
265        new_settings.c_cc[VMIN] = 0;
266        tcsetattr(0,TCSANOW,&new_settings);
267        COUT(0) << endl;
268//       atexit(&GSDedicatedClient::resetTerminalMode);
269#endif
270    }
271   
272    void GSDedicatedClient::resetTerminalMode()
273    {
274#ifdef ORXONOX_PLATFORM_UNIX
275        tcsetattr(0, TCSANOW, GSDedicatedClient::originalTerminalSettings_);
276#endif
277    }
278   
279    void GSDedicatedClient::insertCharacter( unsigned int position, char c )
280    {
281//         std::cout << endl << static_cast<unsigned int>(c) << endl;
282        // check that we do not exceed MAX_COMMAND_LENGTH
283        if( inputIterator_+1 < MAX_COMMAND_LENGTH )
284        {
285            // if cursor not at end of line then move the rest of the line
286            if( position != this->inputIterator_ )
287                    memmove( this->commandLine_+position+1, this->commandLine_+position, this->inputIterator_-position);
288//             boost::recursive_mutex::scoped_lock(this->inputLineMutex_);
289            this->commandLine_[position] = c;
290            ++this->cursorX_;
291            ++this->inputIterator_;
292        }
293    }
294    void GSDedicatedClient::deleteCharacter( unsigned int position )
295    {
296//         boost::recursive_mutex::scoped_lock(this->inputLineMutex_);
297        if ( this->inputIterator_>0 && position>0 )
298        {
299            if ( position != this->inputIterator_ )
300                memmove( this->commandLine_+position-1, this->commandLine_+position, this->inputIterator_-position);
301            --this->cursorX_;
302            --this->inputIterator_;
303        }
304    }
305   
306}
Note: See TracBrowser for help on using the repository browser.