Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/network/GamestateManager.cc @ 5944

Last change on this file since 5944 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: 8.8 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 *      Oliver Scheuss
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29//
30// C++ Implementation: GameStateManager
31//
32// Description:
33//
34//
35// Author:  Oliver Scheuss, (C) 2007
36//
37// Copyright: See COPYING file that comes with this distribution
38//
39//
40
41#include "GamestateManager.h"
42
43#include <cassert>
44#include <queue>
45// #include <boost/thread/mutex.hpp>
46
47#include "util/Debug.h"
48#include "core/Executor.h"
49#include "core/ThreadPool.h"
50#include "ClientInformation.h"
51#include "packet/Acknowledgement.h"
52#include "packet/Gamestate.h"
53#include "synchronisable/NetworkCallbackManager.h"
54#include "TrafficControl.h"
55
56namespace orxonox
57{
58  GamestateManager::GamestateManager() :
59  reference(0), id_(0)
60  {
61    trafficControl_ = new TrafficControl();
62//     threadMutex_ = new boost::mutex();
63//     threadPool_ = new ThreadPool();
64  }
65
66  GamestateManager::~GamestateManager()
67  {
68    if( this->reference )
69        delete this->reference;std::map<unsigned int, packet::Gamestate*>::iterator it;
70    for( it = gamestateQueue.begin(); it != gamestateQueue.end(); ++it )
71      delete (*it).second;
72    std::map<unsigned int, std::map<unsigned int, packet::Gamestate*> >::iterator it1;
73    std::map<unsigned int, packet::Gamestate*>::iterator it2;
74    for( it1 = gamestateMap_.begin(); it1 != gamestateMap_.end(); ++it1 )
75    {
76      for( it2 = it1->second.begin(); it2 != it1->second.end(); ++it2 )
77        delete (*it2).second;
78    }
79    this->trafficControl_->destroy();
80//     delete this->threadMutex_;
81//     delete this->threadPool_;
82  }
83
84  bool GamestateManager::update(){
85//     cleanup();
86    return getSnapshot();
87  }
88
89  bool GamestateManager::add(packet::Gamestate *gs, unsigned int clientID){
90    assert(gs);
91    std::map<unsigned int, packet::Gamestate*>::iterator it = gamestateQueue.find(clientID);
92    if(it!=gamestateQueue.end()){
93      // delete obsolete gamestate
94      delete it->second;
95    }
96    gamestateQueue[clientID] = gs;
97    return true;
98  }
99
100  bool GamestateManager::processGamestates(){
101    if( this->gamestateQueue.empty() )
102        return true;
103    std::map<unsigned int, packet::Gamestate*>::iterator it;
104    // now push only the most recent gamestates we received (ignore obsolete ones)
105    for(it = gamestateQueue.begin(); it!=gamestateQueue.end(); it++){
106      bool b = processGamestate(it->second);
107      assert(b);
108      delete it->second;
109    }
110    // now clear the queue
111    gamestateQueue.clear();
112    //and call all queued callbacks
113    NetworkCallbackManager::callCallbacks();
114    return true;
115  }
116
117
118  bool GamestateManager::getSnapshot(){
119    if ( reference != 0 )
120      delete reference;
121    reference = new packet::Gamestate();
122    if(!reference->collectData(++id_, 0x1)){ //we have no data to send
123      delete reference;
124      reference=0;
125    }
126    return true;
127  }
128 
129  void GamestateManager::sendGamestates()
130  {
131    ClientInformation *temp = ClientInformation::getBegin();
132    std::queue<packet::Gamestate*> clientGamestates;
133    while(temp != NULL){
134      if( !(temp->getSynched()) ){
135        COUT(5) << "Server: not sending gamestate" << std::endl;
136        temp=temp->next();
137        if(!temp)
138          break;
139        continue;
140      }
141      COUT(4) << "client id: " << temp->getID() << " RTT: " << temp->getRTT() << " loss: " << temp->getPacketLoss() << std::endl;
142      COUT(5) << "Server: doing gamestate gamestate preparation" << std::endl;
143      int cid = temp->getID(); //get client id
144     
145      unsigned int gID = temp->getGamestateID();
146      if(!reference)
147        return;
148     
149      packet::Gamestate *client=0;
150      if(gID != GAMESTATEID_INITIAL){
151        assert(gamestateMap_.find(cid)!=gamestateMap_.end());
152        std::map<unsigned int, packet::Gamestate*>::iterator it = gamestateMap_[cid].find(gID);
153        if(it!=gamestateMap_[cid].end())
154        {
155          client = it->second;
156        }
157      }
158     
159      clientGamestates.push(0);
160      finishGamestate( cid, &clientGamestates.back(), client, reference );
161      //FunctorMember<GamestateManager>* functor =
162//       ExecutorMember<GamestateManager>* executor = createExecutor( createFunctor(&GamestateManager::finishGamestate, this) );
163//       executor->setDefaultValues( cid, &clientGamestates.back(), client, reference );
164//       (*static_cast<Executor*>(executor))();
165//       this->threadPool_->passFunction( executor, true );
166//       (*functor)( cid, &(clientGamestates.back()), client, reference );
167     
168      temp = temp->next();
169    }
170   
171//     threadPool_->synchronise();
172   
173    while( !clientGamestates.empty() )
174    {
175      if(clientGamestates.front())
176        clientGamestates.front()->send();
177      clientGamestates.pop();
178    }
179  }
180
181
182  void GamestateManager::finishGamestate( unsigned int clientID, packet::Gamestate** destgamestate, packet::Gamestate* base, packet::Gamestate* gamestate ) {
183    //why are we searching the same client's gamestate id as we searched in
184    //Server::sendGameState?
185    // save the (undiffed) gamestate in the clients gamestate map
186    //chose wheather the next gamestate is the first or not
187   
188    packet::Gamestate *gs = gamestate->doSelection(clientID, 20000);
189//     packet::Gamestate *gs = new packet::Gamestate(*gamestate);
190//     packet::Gamestate *gs = new packet::Gamestate();
191//     gs->collectData( id_, 0x1 );
192//     this->threadMutex_->lock();
193    gamestateMap_[clientID][gamestate->getID()]=gs;
194//     this->threadMutex_->unlock();
195   
196    if(base)
197    {
198       
199//       COUT(3) << "diffing" << std::endl;
200//       packet::Gamestate* gs1  = gs;
201      packet::Gamestate *diffed = gs->diff(base);
202      //packet::Gamestate *gs2 = diffed->undiff(gs);
203//       assert(*gs == *gs2);
204      gs = diffed;
205//       packet::Gamestate* gs2 = gs->undiff(client);
206//       gs = new packet::Gamestate(*gs);
207//       assert(*gs1==*gs2);
208    }
209    else{
210      gs = new packet::Gamestate(*gs);
211    }
212   
213   
214    bool b = gs->compressData();
215    assert(b);
216//     COUT(4) << "sending gamestate with id " << gs->getID();
217//     if(gamestate->isDiffed())
218//     COUT(4) << " and baseid " << gs->getBaseID() << endl;
219//     else
220//     COUT(4) << endl;
221    gs->setClientID(clientID);
222    *destgamestate = gs;
223  }
224
225
226  bool GamestateManager::ack(unsigned int gamestateID, unsigned int clientID) {
227    ClientInformation *temp = ClientInformation::findClient(clientID);
228    assert(temp);
229    unsigned int curid = temp->getGamestateID();
230
231    if(gamestateID == ACKID_NACK){
232      temp->setGamestateID(GAMESTATEID_INITIAL);
233      // now delete all saved gamestates for this client
234      std::map<unsigned int, packet::Gamestate*>::iterator it;
235      for(it = gamestateMap_[clientID].begin(); it!=gamestateMap_[clientID].end(); ){
236        delete it->second;
237
238        gamestateMap_[clientID].erase(it++);
239      }
240      return true;
241    }
242
243    assert(curid==GAMESTATEID_INITIAL || curid<gamestateID);
244    COUT(5) << "acking gamestate " << gamestateID << " for clientid: " << clientID << " curid: " << curid << std::endl;
245    std::map<unsigned int, packet::Gamestate*>::iterator it;
246    for(it = gamestateMap_[clientID].begin(); it!=gamestateMap_[clientID].end() && it->first<gamestateID; ){
247      delete it->second;
248      gamestateMap_[clientID].erase(it++);
249    }
250    temp->setGamestateID(gamestateID);
251    TrafficControl::processAck(clientID, gamestateID);
252    return true;
253  }
254
255  void GamestateManager::removeClient(ClientInformation* client){
256    assert(client);
257    std::map<unsigned int, std::map<unsigned int, packet::Gamestate*> >::iterator clientMap = gamestateMap_.find(client->getID());
258    // first delete all remained gamestates
259    std::map<unsigned int, packet::Gamestate*>::iterator it;
260    for(it=clientMap->second.begin(); it!=clientMap->second.end(); it++)
261      delete it->second;
262    // now delete the clients gamestatemap
263    gamestateMap_.erase(clientMap);
264  }
265
266  bool GamestateManager::processGamestate(packet::Gamestate *gs){
267    if(gs->isCompressed())
268    {
269       bool b = gs->decompressData();
270       assert(b);
271    }
272    assert(!gs->isDiffed());
273    return gs->spreadData(0x1);
274  }
275
276}
Note: See TracBrowser for help on using the repository browser.