Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/gamestates/GSDedicated.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 ;)

  • 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 <iomanip>
32#include <iostream>
33#include <boost/bind.hpp>
34
35#include "util/Clock.h"
36#include "util/Debug.h"
37#include "util/Sleep.h"
38#include "core/CommandLine.h"
39#include "core/CommandExecutor.h"
40#include "core/Game.h"
41#include "core/GameMode.h"
42#include "network/Server.h"
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.