Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/netp6/src/orxonox/gamestates/GSDedicated.cc @ 3284

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

Move resource allocation to the corresponding thread and made compiler directives clearer.

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