Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/network/src/network/GamestateManager.cc @ 1742

Last change on this file since 1742 was 1742, checked in by scheusso, 16 years ago

compressing and diffing works now (also shipCache on client). server can't move while client connected. preparations for synchronise frequency of synchronisables

File size: 5.9 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 <assert.h>
47
48#include "core/CoreIncludes.h"
49#include "core/BaseObject.h"
50#include "ClientInformation.h"
51#include "Synchronisable.h"
52
53namespace network
54{
55  GamestateManager::GamestateManager() {
56    id_=0;
57  }
58
59  GamestateManager::~GamestateManager() {
60  }
61
62  bool GamestateManager::update(){
63    cleanup();
64    return getSnapshot();
65  }
66 
67  bool GamestateManager::add(packet::Gamestate *gs, int clientID){
68    assert(gs);
69    std::map<int, packet::Gamestate*>::iterator it = gamestateQueue.find(clientID);
70    if(it!=gamestateQueue.end()){
71      // delete obsolete gamestate
72      delete it->second;
73    }
74    gamestateQueue[clientID] = gs;
75    return true;
76  }
77 
78  bool GamestateManager::processGamestates(){
79    std::map<int, packet::Gamestate*>::iterator it;
80    // now push only the most recent gamestates we received (ignore obsolete ones)
81    for(it = gamestateQueue.begin(); it!=gamestateQueue.end(); it++){
82      assert(processGamestate(it->second));
83      delete it->second;
84    }
85    // now clear the queue
86    gamestateQueue.clear();
87    return true;
88  }
89 
90 
91  bool GamestateManager::getSnapshot(){
92    reference = new packet::Gamestate();
93    reference->collectData(++id_);
94    COUT(4) << "inserting gamestate: " << reference << std::endl;
95    gamestateMap.insert(std::pair<int, packet::Gamestate*>(id_, reference));
96    gamestateUsed[id_]=0;
97    return true;
98  }
99 
100  /**
101   * this function is used to keep the memory usage low
102   * it tries to delete all the unused gamestates
103   *
104   *
105   */
106  void GamestateManager::cleanup(){
107    std::map<int,int>::iterator it = gamestateUsed.begin();
108    while(it!=gamestateUsed.end()){
109      if((id_-(*it).first)<KEEP_GAMESTATES)
110        break;
111      if( (*it).second <= 0 ){
112        COUT(5) << "GameStateManager: deleting gamestate with id: " << (*it).first << ", uses: " << (*it).second << std::endl;
113        std::map<int, packet::Gamestate *>::iterator tempit = gamestateMap.find((*it).first);
114        if( tempit != gamestateMap.end() ){
115          packet::Gamestate *temp = tempit->second;
116          if(temp){
117            delete gamestateMap[(*it).first];
118            gamestateMap.erase((*it).first);
119          }
120        }
121        gamestateUsed.erase(it++);
122        continue;
123      }
124      it++;
125    }
126  }
127
128  packet::Gamestate *GamestateManager::popGameState(int clientID) {
129    //why are we searching the same client's gamestate id as we searched in
130    //Server::sendGameState?
131    packet::Gamestate *gs;
132    int gID = ClientInformation::findClient(clientID)->getGamestateID();
133    //COUT(4) << "G.St.Man: popgamestate: sending gstate_id: " << id_ << " diffed from: " << gID << std::endl;
134    //chose wheather the next gamestate is the first or not
135    if(gID != GAMESTATEID_INITIAL){
136      packet::Gamestate *client=NULL;
137      std::map<int, packet::Gamestate*>::iterator it = gamestateMap.find(gID);
138      if(it!=gamestateMap.end())
139        client = it->second;
140      if(client)
141        gs = reference->diff(client);
142      else
143        gs = new packet::Gamestate(*reference);
144    } else {
145      COUT(4) << "we got a GAMESTATEID_INITIAL for clientID: " << clientID << std::endl;
146      gs = new packet::Gamestate(*reference);
147    }
148    assert(gs->compressData());
149    return gs;
150  }
151 
152 
153  bool GamestateManager::ack(int gamestateID, int clientID) {
154    ClientInformation *temp = ClientInformation::findClient(clientID);
155    if(temp==0)
156      return false;
157    int curid = temp->getGamestateID();
158   
159    if(gamestateID == GAMESTATEID_INITIAL){
160      temp->setGamestateID(GAMESTATEID_INITIAL);
161      if(curid!=GAMESTATEID_INITIAL){
162        assert(gamestateUsed.find(curid)!=gamestateUsed.end());
163        --(gamestateUsed.find(curid)->second);
164      }
165      return false;
166    }
167    if(curid > gamestateID)
168      // the network packets got messed up
169      return true;
170    COUT(4) << "acking gamestate " << gamestateID << " for clientid: " << clientID << " curid: " << curid << std::endl;
171    // decrease usage of gamestate and save it
172//     deleteUnusedGameState(curid);
173    //increase gamestateused
174    std::map<int, int>::iterator it = gamestateUsed.find(curid);
175    if(curid!=GAMESTATEID_INITIAL){
176      if(it!=gamestateUsed.end())
177        --(it->second);
178    }
179    it = gamestateUsed.find(gamestateID);
180    if(it!=gamestateUsed.end()){
181      ++(it->second);
182      temp->setGamestateID(gamestateID);
183    }
184    return true;
185  }
186
187  void GamestateManager::removeClient(ClientInformation* client){
188    if(!client)
189      return;
190    if(client->getGamestateID()>=0)
191      gamestateUsed[client->getGamestateID()]--;
192  }
193 
194  bool GamestateManager::processGamestate(packet::Gamestate *gs){
195    if(gs->isCompressed())
196       assert(gs->decompressData());
197    assert(!gs->isDiffed());
198    return gs->spreadData();
199  }
200
201}
Note: See TracBrowser for help on using the repository browser.