Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3256 was 3240, checked in by scheusso, 15 years ago

a lot of cleanup
some bugfixes (Thread, ThreadPool)
the biggest part of the network (~80% cpu time) is now multithreaded (1 thread for each client)

  • Property svn:eol-style set to native
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 *      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#ifndef ORXONOX_PLATFORM_WINDOWS
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        this->commandLine_ = new unsigned char[MAX_COMMAND_LENGTH];
68//         memset( this->commandLine_, 0, MAX_COMMAND_LENGTH );
69    }
70
71    GSDedicated::~GSDedicated()
72    {
73    }
74
75    void GSDedicated::activate()
76    {
77        GameMode::setHasServer(true);
78       
79        this->inputThread_ = new boost::thread(boost::bind(&GSDedicated::inputThread, this));
80       
81#ifndef ORXONOX_PLATFORM_WINDOWS
82        this->originalTerminalSettings_ = new termios;
83        this->setTerminalMode();
84#endif
85
86        this->server_ = new Server(CommandLine::getValue("port"));
87        COUT(0) << "Loading scene in server mode" << std::endl;
88
89        server_->open();
90    }
91
92    void GSDedicated::deactivate()
93    {
94        this->server_->close();
95        delete this->server_;
96       
97        closeThread_ = true;
98#ifndef ORXONOX_PLATFORM_WINDOWS
99        std::cout << "\033[0G\033[K";
100        std::cout.flush();
101        resetTerminalMode();
102        delete this->originalTerminalSettings_;
103#endif
104        //inputThread_->join();
105        delete this->inputThread_;
106
107        GameMode::setHasServer(false);
108    }
109
110    void GSDedicated::update(const Clock& time)
111    {
112        timeSinceLastUpdate_ += time.getDeltaTime();
113        if (timeSinceLastUpdate_ >= NETWORK_PERIOD)
114        {
115            timeSinceLastUpdate_ -= static_cast<unsigned int>(timeSinceLastUpdate_ / NETWORK_PERIOD) * NETWORK_PERIOD;
116            server_->update(time);
117        }
118        else
119        {
120            msleep(static_cast<unsigned int>((NETWORK_PERIOD - timeSinceLastUpdate_)*1000));
121            msleep(static_cast<unsigned int>(NETWORK_PERIOD*1000)); // NOTE: this is to throttle the non-network framerate
122//            COUT(0) << "sleeping for " << (int)((NETWORK_PERIOD - timeSinceLastUpdate_) * 1000 * 1000) << " usec" << endl;
123        }
124        processQueue();
125        printLine();
126    }
127   
128    void GSDedicated::inputThread()
129    {
130        unsigned char c;
131        unsigned int  escapeChar=0;
132        while(!closeThread_)
133        {
134            c = getchar();
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((char*)this->commandLine_, CommandExecutor::complete( std::string((const char*)this->commandLine_,inputIterator_) ).c_str(), MAX_COMMAND_LENGTH);
197                            inputIterator_ = strlen((const char*)this->commandLine_);
198                            break;
199                        }
200                        case '\033': // 1. escape character
201                            escapeChar = 1;
202                            break;
203                        default:
204                            insertCharacter( this->cursorX_, c );
205                            break;
206                    }
207                }
208            }
209        }
210    }
211   
212    void GSDedicated::printLine()
213    {
214#ifndef ORXONOX_PLATFORM_WINDOWS
215        // set cursor to the begining of the line and erase the line
216        std::cout << "\033[0G\033[K";
217//         boost::recursive_mutex::scoped_lock(this->inputLineMutex_);
218        // print status line
219        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 # ";
220        //save cursor position
221        std::cout << "\033[s";
222        //print commandLine buffer
223        std::cout << std::string((const char*)this->commandLine_, inputIterator_);
224        //restore cursor position and move it cursorX_ to the right
225        std::cout << "\033[u";
226        if( this->cursorX_ > 0 )
227            std::cout << "\033[" << this->cursorX_ << "C";
228        std::cout.flush();
229#endif
230    }
231   
232    void GSDedicated::processQueue()
233    {
234        std::string tempstr;
235        {
236            boost::recursive_mutex::scoped_lock lock1(this->inputQueueMutex_);
237            while(true)
238            {
239                if ( !this->commandQueue_.empty() )
240                {
241                    tempstr = this->commandQueue_.front();
242                    this->commandQueue_.pop();
243                    lock1.unlock();
244                }
245                else
246                    break;
247                CommandExecutor::execute(tempstr, true);
248            }
249        }
250    }
251   
252    void GSDedicated::setTerminalMode()
253    {
254#ifndef ORXONOX_PLATFORM_WINDOWS
255        termios new_settings;
256     
257        tcgetattr(0,this->originalTerminalSettings_);
258        new_settings = *this->originalTerminalSettings_;
259        new_settings.c_lflag &= ~( ICANON | ECHO );
260//         new_settings.c_lflag |= ( ISIG | IEXTEN );
261        new_settings.c_cc[VTIME] = 0;
262        new_settings.c_cc[VMIN] = 1;
263        tcsetattr(0,TCSANOW,&new_settings);
264        COUT(0) << endl;
265//       atexit(&GSDedicated::resetTerminalMode);
266#endif
267    }
268   
269    void GSDedicated::resetTerminalMode()
270    {
271#ifndef ORXONOX_PLATFORM_WINDOWS
272        tcsetattr(0, TCSANOW, GSDedicated::originalTerminalSettings_);
273#endif
274    }
275   
276    void GSDedicated::insertCharacter( unsigned int position, char c )
277    {
278//         std::cout << endl << (unsigned int)c << endl;
279        // check that we do not exceed MAX_COMMAND_LENGTH
280        if( inputIterator_+1 < MAX_COMMAND_LENGTH )
281        {
282            // if cursor not at end of line then move the rest of the line
283            if( position != this->inputIterator_ )
284                    memmove( this->commandLine_+position+1, this->commandLine_+position, this->inputIterator_-position);
285//             boost::recursive_mutex::scoped_lock(this->inputLineMutex_);
286            this->commandLine_[position] = c;
287            ++this->cursorX_;
288            ++this->inputIterator_;
289        }
290    }
291    void GSDedicated::deleteCharacter( unsigned int position )
292    {
293//         boost::recursive_mutex::scoped_lock(this->inputLineMutex_);
294        if ( this->inputIterator_>0 && position>0 )
295        {
296            if ( position != this->inputIterator_ )
297                memmove( this->commandLine_+position-1, this->commandLine_+position, this->inputIterator_-position);
298            --this->cursorX_;
299            --this->inputIterator_;
300        }
301    }
302   
303}
Note: See TracBrowser for help on using the repository browser.