Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/FICN/src/network/GameStateManager.cc @ 458

Last change on this file since 458 was 436, checked in by scheusso, 17 years ago

extended gamestatehandling for diffed and not diffed gamestates (initial states, etc)

File size: 5.2 KB
RevLine 
[247]1//
2// C++ Implementation: GameStateManager
3//
4// Description:
5//
6//
7// Author:  Oliver Scheuss, (C) 2007
8//
9// Copyright: See COPYING file that comes with this distribution
10//
11//
12#include "GameStateManager.h"
13
14namespace network {
15
[436]16GameStateManager::GameStateManager(ClientInformation *head)
[247]17{
[413]18  id=0;
[436]19  head_=head;
[247]20}
21
22GameStateManager::~GameStateManager()
23{
24}
25
[413]26void GameStateManager::update(){
[422]27  reference = getSnapshot(id);
[436]28  gameStateMap.insert(std::pair<int, GameState*>(id, reference));
29  gameStateUsed[id]=0;
[422]30  ++id;
[413]31  return;
32}
33
34GameStateCompressed GameStateManager::popGameState(int clientID){
[436]35  int gID = head_->findClient(clientID)->getGamestateID();
36  if(gID!=GAMESTATEID_INITIAL){
37    GameState *client = gameStateMap[gID];
38    GameState *server = reference;
39    return encode(client, server);
40  }
[422]41  GameState *server = reference;
[436]42  return encode(server);
43  // return an undiffed gamestate and set appropriate flags
[413]44}
45
46
47
[332]48/**
49 * This function goes through the whole list of synchronisables and
50 * saves all the synchronisables to a flat "list".
51 * @return struct of type gamestate containing the size of the whole gamestate and a pointer linking to the flat list
52 */
[422]53GameState *GameStateManager::getSnapshot(int id)
[332]54{
55  //the size of the gamestate
56  int totalsize=0;
57  //the size of one specific synchronisable
58  int tempsize=0;
59  // get the start of the Synchronisable list
60  orxonox::Iterator<Synchronisable> it;
61  // struct for return value of Synchronisable::getData()
62  syncData sync;
[247]63 
[422]64  GameState *retval=new GameState; //return value
65  retval->id=id;
[332]66  // reserve a little memory and increase it later on
[422]67  retval->data = (unsigned char*)malloc(1);
[332]68 
69  // offset of memory functions
70  int offset=0;
71  // go through all Synchronisables
72  for(it = orxonox::ObjectList<Synchronisable>::start(); it != 0; ++it){
73    //get size of the synchronisable
74    tempsize=it->getSize();
75    // add place for data and 3 ints (length,classid,objectid)
76    totalsize+=tempsize+3*sizeof(int);
77    // allocate additional space
[422]78    retval->data = (unsigned char *)realloc((void *)retval->data, totalsize);
[332]79   
80    // run Synchronisable::getData with offset and additional place for 3 ints in between (for ids and length)
[422]81    sync=it->getData(retval->data+offset+3*sizeof(int));
82    *(retval->data+offset)=sync.length;
83    *(retval->data+offset+sizeof(int))=sync.objectID;
84    *(retval->data+offset+2*sizeof(int))=sync.classID;
[332]85    // increase data pointer
86    offset+=tempsize+3*sizeof(int);
87  }
[422]88  retval->size=totalsize;
[413]89  return retval;
[247]90}
91
92
[332]93
[413]94GameStateCompressed GameStateManager::encode(GameState *a, GameState *b){
[436]95    GameState r = diff(a,b);
96  r.diffed = true;
97  return compress_(&r);
[385]98}
[332]99
[436]100GameStateCompressed GameStateManager::encode(GameState *a){
101  a->diffed=false;
102  return compress_(a);
103}
[332]104
[413]105GameState GameStateManager::diff(GameState *a, GameState *b){
106  unsigned char *ap = a->data, *bp = b->data;
[385]107  int of=0; // pointers offset
108  int dest_length=0;
[413]109  if(a->size>=b->size)
110    dest_length=a->size;
[385]111  else
[413]112    dest_length=b->size;
[385]113  unsigned char *dp = (unsigned char *)malloc(dest_length*sizeof(unsigned char));
[413]114  while(of<a->size && of<b->size){
[385]115    *(dp+of)=*(ap+of)^*(bp+of); // do the xor
116    ++of;
117  }
[413]118  if(a->size!=b->size){ // do we have to fill up ?
[385]119    unsigned char n=0;
[413]120    if(a->size<b->size){
[385]121      while(of<dest_length){
122        *(dp+of)=n^*(bp+of);
123        of++;
124      }
125    } else{
126      while(of<dest_length){
127        *(dp+of)=*(ap+of)^n;
128        of++;
129      }
130    }
131  }
132  // should be finished now
[413]133  GameState r = {b->id, dest_length, dp};
[385]134  return r;
135}
[332]136
[436]137GameStateCompressed GameStateManager::compress_(GameState *a) {
138  int size = a->size;
139  uLongf buffer = (uLongf)((a->size + 12)*1.01)+1;
[407]140  unsigned char* dest = (unsigned char*)malloc( buffer );
141  int retval;
[436]142  retval = compress( dest, &buffer, a->data, (uLong)size ); 
[407]143 
144  switch ( retval ) {
[413]145  case Z_OK: std::cout << "successfully compressed" << std::endl; break;
146  case Z_MEM_ERROR: std::cout << "not enough memory available" << std::endl; break;
147  case Z_BUF_ERROR: std::cout << "not enough memory available in the buffer" << std::endl; break;
148  case Z_DATA_ERROR: std::cout << "data corrupted" << std::endl; break;
[407]149  }
150 
[413]151  GameStateCompressed compressedGamestate;
[407]152  compressedGamestate.compsize = buffer;
153  compressedGamestate.normsize = size;
154  compressedGamestate.id = GAMESTATE;
155  compressedGamestate.data = dest;
[436]156  compressedGamestate.diffed = a->diffed;
[407]157 
158  return compressedGamestate;
[385]159}
160
[422]161void GameStateManager::ackGameState(int clientID, int gamestateID){
[436]162  ClientInformation *temp = head_->findClient(clientID);
163  int curid = temp->getID();
164  // decrease usage of gamestate and save it
165  deleteUnusedGameState(curid);
166  //increase gamestateused
167  ++gameStateUsed.find(gamestateID)->second;
168  temp->setGamestateID(gamestateID);
169  /*
[422]170  GameState *old = clientGameState[clientID];
171  deleteUnusedGameState(old);
[436]172  clientGameState[clientID]=idGameState[gamestateID];*/
[422]173}
[385]174
[436]175bool GameStateManager::deleteUnusedGameState(int gamestateID){
176  int used = --(gameStateUsed.find(gamestateID)->second);
177  if(id-gamestateID>KEEP_GAMESTATES && used==0){
178    // delete gamestate
179    delete gameStateMap.find(gamestateID)->second;
180    gameStateMap.erase(gamestateID);
181    return true;
[422]182  }
[436]183  return false;
[422]184}
[413]185
[385]186}
187
188
Note: See TracBrowser for help on using the repository browser.