Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation/src/network/GamestateManager.cc @ 2557

Last change on this file since 2557 was 2556, checked in by scheusso, 15 years ago

found another memory leak (hope this was the last one in the network part)

  • Property svn:eol-style set to native
File size: 6.7 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, (C) 2007
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 <utility>
44#include <iostream>
45#include <zlib.h>
46#include <cassert>
47
48#include "core/CoreIncludes.h"
49#include "core/BaseObject.h"
50#include "ClientInformation.h"
51#include "synchronisable/Synchronisable.h"
52#include "synchronisable/NetworkCallbackManager.h"
53#include "packet/Acknowledgement.h"
54
55namespace orxonox
56{
57  GamestateManager::GamestateManager() :
58  reference(0), id_(0)
59  {
60    trafficControl_ = new TrafficControl();
61  }
62
63  GamestateManager::~GamestateManager()
64  {
65    delete trafficControl_;
66  }
67
68  bool GamestateManager::update(){
69//     cleanup();
70    return getSnapshot();
71  }
72
73  bool GamestateManager::add(packet::Gamestate *gs, unsigned int clientID){
74    assert(gs);
75    std::map<unsigned int, packet::Gamestate*>::iterator it = gamestateQueue.find(clientID);
76    if(it!=gamestateQueue.end()){
77      // delete obsolete gamestate
78      delete it->second;
79    }
80    gamestateQueue[clientID] = gs;
81    return true;
82  }
83
84  bool GamestateManager::processGamestates(){
85    std::map<unsigned int, packet::Gamestate*>::iterator it;
86    // now push only the most recent gamestates we received (ignore obsolete ones)
87    for(it = gamestateQueue.begin(); it!=gamestateQueue.end(); it++){
88      bool b = processGamestate(it->second);
89      assert(b);
90      delete it->second;
91    }
92    // now clear the queue
93    gamestateQueue.clear();
94    //and call all queued callbacks
95    NetworkCallbackManager::callCallbacks();
96    return true;
97  }
98
99
100  bool GamestateManager::getSnapshot(){
101    if ( reference != 0 )
102      delete reference;
103    reference = new packet::Gamestate();
104    if(!reference->collectData(++id_)){ //we have no data to send
105      delete reference;
106      reference=0;
107    }
108    return true;
109  }
110
111  /**
112   * this function is used to keep the memory usage low
113   * it tries to delete all the unused gamestates
114   *
115   *
116   */
117/*  void GamestateManager::cleanup(){
118    std::map<int,int>::iterator it = gamestateUsed.begin();
119    while(it!=gamestateUsed.end()){
120      if((id_-(*it).first)<KEEP_GAMESTATES)
121        break;
122      if( (*it).second <= 0 ){
123        COUT(5) << "GameStateManager: deleting gamestate with id: " << (*it).first << ", uses: " << (*it).second << std::endl;
124        std::map<int, packet::Gamestate *>::iterator tempit = gamestateMap.find((*it).first);
125        if( tempit != gamestateMap.end() ){
126          packet::Gamestate *temp = tempit->second;
127          if(temp){
128            delete gamestateMap[(*it).first];
129            gamestateMap.erase((*it).first);
130          }
131        }
132        gamestateUsed.erase(it++);
133        continue;
134      }
135      it++;
136    }
137  }*/
138
139  packet::Gamestate *GamestateManager::popGameState(unsigned int clientID) {
140    //why are we searching the same client's gamestate id as we searched in
141    //Server::sendGameState?
142    packet::Gamestate *gs, *tempgs;
143    unsigned int gID = ClientInformation::findClient(clientID)->getGamestateID();
144    if(!reference)
145      return 0;
146    gs = reference->doSelection(clientID, 10000);
147//     gs = new packet::Gamestate(*reference);
148    // save the (undiffed) gamestate in the clients gamestate map
149    gamestateMap_[clientID].insert(std::pair<int, packet::Gamestate*>(gs->getID(), gs));
150    //chose wheather the next gamestate is the first or not
151    packet::Gamestate *client=NULL;
152    if(gID != GAMESTATEID_INITIAL){
153      std::map<unsigned int, std::map<unsigned int, packet::Gamestate*> >::iterator clientMap = gamestateMap_.find(clientID);
154      if(clientMap!=gamestateMap_.end()){
155        std::map<unsigned int, packet::Gamestate*>::iterator it = clientMap->second.find(gID);
156        if(it!=clientMap->second.end())
157          client = it->second;
158      }
159    }
160    if(client){
161//       COUT(3) << "diffing" << std::endl;
162      tempgs = gs->diff(client);
163      delete gs;
164      gs = tempgs;
165    }
166    else{
167//       COUT(3) << "not diffing" << std::endl;
168//       gs = new packet::Gamestate(*gs); //not necessary
169    }
170    bool b = gs->compressData();
171    assert(b);
172    return gs;
173  }
174
175
176  bool GamestateManager::ack(unsigned int gamestateID, unsigned int clientID) {
177    ClientInformation *temp = ClientInformation::findClient(clientID);
178    assert(temp);
179    unsigned int curid = temp->getGamestateID();
180
181    if(gamestateID == ACKID_NACK){
182      temp->setGamestateID(GAMESTATEID_INITIAL);
183      return true;
184    }
185
186    assert(curid==(unsigned int)GAMESTATEID_INITIAL || curid<gamestateID);
187    COUT(4) << "acking gamestate " << gamestateID << " for clientid: " << clientID << " curid: " << curid << std::endl;
188    std::map<unsigned int, packet::Gamestate*>::iterator it, tempit;
189    for(it = gamestateMap_[clientID].begin(); it!=gamestateMap_[clientID].end() && it->first<gamestateID; it++){
190      delete it->second;
191      tempit=it++;
192      gamestateMap_[clientID].erase(tempit);
193    }
194    temp->setGamestateID(gamestateID);
195    TrafficControl::processAck(clientID, gamestateID);
196    return true;
197  }
198
199  void GamestateManager::removeClient(ClientInformation* client){
200    assert(client);
201    std::map<unsigned int, std::map<unsigned int, packet::Gamestate*> >::iterator clientMap = gamestateMap_.find(client->getID());
202    // first delete all remained gamestates
203    std::map<unsigned int, packet::Gamestate*>::iterator it;
204    for(it=clientMap->second.begin(); it!=clientMap->second.end(); it++)
205      delete it->second;
206    // now delete the clients gamestatemap
207    gamestateMap_.erase(clientMap);
208  }
209
210  bool GamestateManager::processGamestate(packet::Gamestate *gs){
211    if(gs->isCompressed())
212    {
213       bool b = gs->decompressData();
214       assert(b);
215    }
216    assert(!gs->isDiffed());
217    return gs->spreadData();
218  }
219
220}
Note: See TracBrowser for help on using the repository browser.