Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/gamestates/GSDedicatedClient.cc @ 5929

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

Merged core5 branch back to the trunk.
Key features include clean level unloading and an extended XML event system.

Two important notes:
Delete your keybindings.ini files! * or you will still get parser errors when loading the key bindings.
Delete build_dir/lib/modules/libgamestates.module! * or orxonox won't start.
Best thing to do is to delete the build folder ;)

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.