Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

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

File size: 5.2 KB
Line 
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
16GameStateManager::GameStateManager(ClientInformation *head)
17{
18  id=0;
19  head_=head;
20}
21
22GameStateManager::~GameStateManager()
23{
24}
25
26void GameStateManager::update(){
27  reference = getSnapshot(id);
28  gameStateMap.insert(std::pair<int, GameState*>(id, reference));
29  gameStateUsed[id]=0;
30  ++id;
31  return;
32}
33
34GameStateCompressed GameStateManager::popGameState(int clientID){
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  }
41  GameState *server = reference;
42  return encode(server);
43  // return an undiffed gamestate and set appropriate flags
44}
45
46
47
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 */
53GameState *GameStateManager::getSnapshot(int id)
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;
63 
64  GameState *retval=new GameState; //return value
65  retval->id=id;
66  // reserve a little memory and increase it later on
67  retval->data = (unsigned char*)malloc(1);
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
78    retval->data = (unsigned char *)realloc((void *)retval->data, totalsize);
79   
80    // run Synchronisable::getData with offset and additional place for 3 ints in between (for ids and length)
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;
85    // increase data pointer
86    offset+=tempsize+3*sizeof(int);
87  }
88  retval->size=totalsize;
89  return retval;
90}
91
92
93
94GameStateCompressed GameStateManager::encode(GameState *a, GameState *b){
95    GameState r = diff(a,b);
96  r.diffed = true;
97  return compress_(&r);
98}
99
100GameStateCompressed GameStateManager::encode(GameState *a){
101  a->diffed=false;
102  return compress_(a);
103}
104
105GameState GameStateManager::diff(GameState *a, GameState *b){
106  unsigned char *ap = a->data, *bp = b->data;
107  int of=0; // pointers offset
108  int dest_length=0;
109  if(a->size>=b->size)
110    dest_length=a->size;
111  else
112    dest_length=b->size;
113  unsigned char *dp = (unsigned char *)malloc(dest_length*sizeof(unsigned char));
114  while(of<a->size && of<b->size){
115    *(dp+of)=*(ap+of)^*(bp+of); // do the xor
116    ++of;
117  }
118  if(a->size!=b->size){ // do we have to fill up ?
119    unsigned char n=0;
120    if(a->size<b->size){
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
133  GameState r = {b->id, dest_length, dp};
134  return r;
135}
136
137GameStateCompressed GameStateManager::compress_(GameState *a) {
138  int size = a->size;
139  uLongf buffer = (uLongf)((a->size + 12)*1.01)+1;
140  unsigned char* dest = (unsigned char*)malloc( buffer );
141  int retval;
142  retval = compress( dest, &buffer, a->data, (uLong)size ); 
143 
144  switch ( retval ) {
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;
149  }
150 
151  GameStateCompressed compressedGamestate;
152  compressedGamestate.compsize = buffer;
153  compressedGamestate.normsize = size;
154  compressedGamestate.id = GAMESTATE;
155  compressedGamestate.data = dest;
156  compressedGamestate.diffed = a->diffed;
157 
158  return compressedGamestate;
159}
160
161void GameStateManager::ackGameState(int clientID, int gamestateID){
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  /*
170  GameState *old = clientGameState[clientID];
171  deleteUnusedGameState(old);
172  clientGameState[clientID]=idGameState[gamestateID];*/
173}
174
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;
182  }
183  return false;
184}
185
186}
187
188
Note: See TracBrowser for help on using the repository browser.