Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/gamestates/GSDedicated.cc @ 4906

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

Merged resource branch back to the trunk. Changes:

  • Automated graphics loading by evaluating whether a GameState requires it
  • Using native Tcl library (x3n)

Windows users: Update your dependency package!

  • Property svn:eol-style set to native
File size: 10.1 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 *      Fabian 'x3n' Landau
26 *
27 */
28
29#include "GSDedicated.h"
30
31#include "util/Debug.h"
32#include "util/Sleep.h"
33#include "core/Clock.h"
34#include "core/CommandLine.h"
35#include "core/CommandExecutor.h"
36#include "core/Game.h"
37#include "core/GameMode.h"
38#include "network/Server.h"
39
40#include <iostream>
41#include <iomanip>
42#include <boost/bind.hpp>
43
44#ifdef ORXONOX_PLATFORM_UNIX
45#include <termios.h>
46#endif
47
48
49namespace orxonox
50{
51    const unsigned int MAX_COMMAND_LENGTH = 255;
52   
53    DeclareGameState(GSDedicated, "dedicated", false, false);
54   
55    termios* GSDedicated::originalTerminalSettings_;
56
57    GSDedicated::GSDedicated(const GameStateInfo& info)
58        : GameState(info)
59        , server_(0)
60        , closeThread_(false)
61        , cleanLine_(true)
62        , inputIterator_(0)
63        , cursorX_(0)
64        , cursorY_(0)
65    {
66    }
67
68    GSDedicated::~GSDedicated()
69    {
70    }
71
72    void GSDedicated::activate()
73    {
74        GameMode::setHasServer(true);
75       
76        this->inputThread_ = new boost::thread(boost::bind(&GSDedicated::inputThread, this));
77       
78#ifndef ORXONOX_PLATFORM_WINDOWS
79        this->originalTerminalSettings_ = new termios;
80        this->setTerminalMode();
81#endif
82
83        this->server_ = new Server(CommandLine::getValue("port"));
84        COUT(0) << "Loading scene in server mode" << std::endl;
85
86        server_->open();
87    }
88
89    void GSDedicated::deactivate()
90    {
91        this->server_->close();
92        delete this->server_;
93       
94        closeThread_ = true;
95#ifdef ORXONOX_PLATFORM_UNIX
96        std::cout << "\033[0G\033[K";
97        std::cout.flush();
98        resetTerminalMode();
99        delete this->originalTerminalSettings_;
100#else
101        COUT(0) << "Press enter to end the game..." << std::endl;
102#endif
103        inputThread_->join();
104        delete this->inputThread_;
105
106        GameMode::setHasServer(false);
107    }
108
109    void GSDedicated::update(const Clock& time)
110    {
111        server_->update(time);
112        processQueue();
113        printLine();
114    }
115   
116    void GSDedicated::inputThread()
117    {
118        this->commandLine_ = new unsigned char[MAX_COMMAND_LENGTH];
119//         memset( this->commandLine_, 0, MAX_COMMAND_LENGTH );
120        unsigned char c;
121        unsigned int  escapeChar=0;
122        while(!closeThread_)
123        {
124#ifdef ORXONOX_PLATFORM_UNIX
125            size_t count = read(STDIN_FILENO, &c, 1);
126            if (count == 1)
127#else
128            c = getchar();
129#endif
130            {
131//                 boost::recursive_mutex::scoped_lock(this->inputLineMutex_);
132                if ( inputIterator_>=MAX_COMMAND_LENGTH-1 && c!='\n' )
133                    continue;
134                if( escapeChar > 0 )
135                {
136                    if( c == '[' )
137                    {
138                        escapeChar = 2;
139                        continue;
140                    }
141                    else if ( escapeChar == 2 )
142                    {
143                        switch (c)
144                        {
145                            case 'A': //keyup
146                               
147                                break;
148                            case 'B': //keydown
149                               
150                                break;
151                            case 'C': //keyright
152                                if(cursorX_<inputIterator_)
153                                    ++cursorX_;
154                                break;
155                            case 'D': //keyleft
156                                if(cursorX_>0)
157                                    --cursorX_;
158                                break;
159                            default: //not supported...
160//                                 std::cout << endl << c << endl;
161                                break;
162                        }
163                        escapeChar = 0;
164                    }
165                }
166                else // not in escape sequence mode
167                {
168                    switch (c)
169                    {
170                        case '\n':
171                            this->cleanLine_ = true;
172                            {
173                                boost::recursive_mutex::scoped_lock(this->inputQueueMutex_);
174                                boost::recursive_mutex::scoped_lock(this->inputLineMutex_);
175                                this->commandQueue_.push( std::string((const char*)this->commandLine_,inputIterator_) );
176                            }
177                            memset( this->commandLine_, 0, inputIterator_ );
178                            inputIterator_ = 0;
179                            this->cursorX_ = 0;
180                            this->cursorY_ = 0;
181                            std::cout << endl;
182                            break;
183                        case 127: // backspace
184                        case '\b':
185                            deleteCharacter( this->cursorX_ );
186                            break;
187                        case '\t':
188                        {
189//                             boost::recursive_mutex::scoped_lock(this->inputLineMutex_);
190                            std::cout << endl << CommandExecutor::hint( std::string((const char*)this->commandLine_,inputIterator_) ) << endl;
191                            strncpy(reinterpret_cast<char*>(this->commandLine_), CommandExecutor::complete( std::string(reinterpret_cast<char*>(this->commandLine_),inputIterator_) ).c_str(), MAX_COMMAND_LENGTH);
192                            this->inputIterator_ = strlen((const char*)this->commandLine_);
193                            this->cursorX_ = this->inputIterator_;
194                            break;
195                        }
196                        case '\033': // 1. escape character
197                            escapeChar = 1;
198                            break;
199                        default:
200                            insertCharacter( this->cursorX_, c );
201                            break;
202                    }
203                }
204            }
205        }
206
207        delete[] this->commandLine_;
208    }
209   
210    void GSDedicated::printLine()
211    {
212#ifdef ORXONOX_PLATFORM_UNIX
213        // set cursor to the begining of the line and erase the line
214        std::cout << "\033[0G\033[K";
215//         boost::recursive_mutex::scoped_lock(this->inputLineMutex_);
216        // print status line
217        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 # ";
218        //save cursor position
219        std::cout << "\033[s";
220        //print commandLine buffer
221        std::cout << std::string((const char*)this->commandLine_, inputIterator_);
222        //restore cursor position and move it cursorX_ to the right
223        std::cout << "\033[u";
224        if( this->cursorX_ > 0 )
225            std::cout << "\033[" << this->cursorX_ << "C";
226        std::cout.flush();
227#endif
228    }
229   
230    void GSDedicated::processQueue()
231    {
232        std::string tempstr;
233        {
234            boost::recursive_mutex::scoped_lock lock1(this->inputQueueMutex_);
235            while(true)
236            {
237                if ( !this->commandQueue_.empty() )
238                {
239                    tempstr = this->commandQueue_.front();
240                    this->commandQueue_.pop();
241                    lock1.unlock();
242                }
243                else
244                    break;
245                CommandExecutor::execute(tempstr, true);
246            }
247        }
248    }
249   
250    void GSDedicated::setTerminalMode()
251    {
252#ifdef ORXONOX_PLATFORM_UNIX
253        termios new_settings;
254     
255        tcgetattr(0,this->originalTerminalSettings_);
256        new_settings = *this->originalTerminalSettings_;
257        new_settings.c_lflag &= ~( ICANON | ECHO );
258//         new_settings.c_lflag |= ( ISIG | IEXTEN );
259        new_settings.c_cc[VTIME] = 1;
260        new_settings.c_cc[VMIN] = 0;
261        tcsetattr(0,TCSANOW,&new_settings);
262        COUT(0) << endl;
263//       atexit(&GSDedicated::resetTerminalMode);
264#endif
265    }
266   
267    void GSDedicated::resetTerminalMode()
268    {
269#ifdef ORXONOX_PLATFORM_UNIX
270        tcsetattr(0, TCSANOW, GSDedicated::originalTerminalSettings_);
271#endif
272    }
273   
274    void GSDedicated::insertCharacter( unsigned int position, char c )
275    {
276//         std::cout << endl << static_cast<unsigned int>(c) << endl;
277        // check that we do not exceed MAX_COMMAND_LENGTH
278        if( inputIterator_+1 < MAX_COMMAND_LENGTH )
279        {
280            // if cursor not at end of line then move the rest of the line
281            if( position != this->inputIterator_ )
282                    memmove( this->commandLine_+position+1, this->commandLine_+position, this->inputIterator_-position);
283//             boost::recursive_mutex::scoped_lock(this->inputLineMutex_);
284            this->commandLine_[position] = c;
285            ++this->cursorX_;
286            ++this->inputIterator_;
287        }
288    }
289    void GSDedicated::deleteCharacter( unsigned int position )
290    {
291//         boost::recursive_mutex::scoped_lock(this->inputLineMutex_);
292        if ( this->inputIterator_>0 && position>0 )
293        {
294            if ( position != this->inputIterator_ )
295                memmove( this->commandLine_+position-1, this->commandLine_+position, this->inputIterator_-position);
296            --this->cursorX_;
297            --this->inputIterator_;
298        }
299    }
300   
301}
Note: See TracBrowser for help on using the repository browser.