Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 407 was 407, checked in by dumenim, 17 years ago

compress/decompress funcions added

File size: 6.3 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()
17{
18}
19
20GameStateManager::~GameStateManager()
21{
22}
23
24/**
25 * This function goes through the whole list of synchronisables and
26 * saves all the synchronisables to a flat "list".
27 * @return struct of type gamestate containing the size of the whole gamestate and a pointer linking to the flat list
28 */
29GameStateCompressed GameStateManager::getSnapshot(int id)
30{
31  //the size of the gamestate
32  int totalsize=0;
33  //the size of one specific synchronisable
34  int tempsize=0;
35  // get the start of the Synchronisable list
36  orxonox::Iterator<Synchronisable> it;
37  // struct for return value of Synchronisable::getData()
38  syncData sync;
39 
40  GameState retval; //return value
41  retval.id=id;
42  // reserve a little memory and increase it later on
43  retval.data = (unsigned char*)malloc(1);
44 
45  // offset of memory functions
46  int offset=0;
47  // go through all Synchronisables
48  for(it = orxonox::ObjectList<Synchronisable>::start(); it != 0; ++it){
49    //get size of the synchronisable
50    tempsize=it->getSize();
51    // add place for data and 3 ints (length,classid,objectid)
52    totalsize+=tempsize+3*sizeof(int);
53    // allocate additional space
54    retval.data = (unsigned char *)realloc((void *)retval.data, totalsize);
55   
56    // run Synchronisable::getData with offset and additional place for 3 ints in between (for ids and length)
57    sync=it->getData(retval.data+offset+3*sizeof(int));
58    *(retval.data+offset)=sync.length;
59    *(retval.data+offset+sizeof(int))=sync.objectID;
60    *(retval.data+offset+2*sizeof(int))=sync.classID;
61    // increase data pointer
62    offset+=tempsize+3*sizeof(int);
63  }
64  retval.size=totalsize;
65  return compress(retval);
66}
67
68/**
69 * This function loads a Snapshort of the gamestate into the universe
70 * @param state a GameState struct containing the size of the gamestate and a pointer linking to a flat list (returned by getSnapshot)
71 */
72bool GameStateManager::loadSnapshot(GameStateCompressed compstate)
73{
74  GameState state = decompress(compstate);
75  unsigned char *data=state.data;
76  // get the start of the Synchronisable list
77  orxonox::Iterator<Synchronisable> it=orxonox::ObjectList<Synchronisable>::start();
78  syncData sync;
79  // loop as long as we have some data ;)
80  while(data < state.data+state.size){
81    // prepare the syncData struct
82    sync.length = *(int *)data;
83    data+=sizeof(int);
84    sync.objectID = *(int *)data;
85    data+=sizeof(int);
86    sync.classID = *(int *)data;
87    data+=sizeof(int);
88    sync.data = data;
89    data+=sync.length;
90   
91    if(it->objectID!=sync.objectID){
92      // bad luck ;)
93      // delete the synchronisable (obviously seems to be deleted on the server)
94      while(it != 0 && it->objectID!=sync.objectID){
95        removeObject(it);
96      }
97      if(it==0){  // add the new object
98        // =================== factory command to add object
99        // can we be sure the object really was added?
100        it=orxonox::ObjectList<Synchronisable>::end();
101        it->objectID=sync.objectID;
102        it->classID=sync.classID;
103      }
104    } else {
105      // we have our object
106      if(! it->updateData(sync))
107        std::cout << "We couldn't update objectID: " \
108          << sync.objectID << "; classID: " << sync.classID << std::endl;
109    }
110   
111  }
112 
113  return true;
114}
115
116/**
117 * This function removes a Synchronisable out of the universe
118 * @param it iterator of the list pointing to the object
119 * @return iterator pointing to the next object in the list
120 */
121void GameStateManager::removeObject(orxonox::Iterator<Synchronisable> &it){
122  orxonox::Iterator<Synchronisable> temp=it;
123  ++it;
124  delete  *temp;
125//   return it;
126}
127
128GameStateCompressed GameStateManager::encode(GameState a, GameState b){
129  GameState r = diff(a,b);
130  return compress(r);
131}
132
133GameState GameStateManager::decode(GameState a, GameStateCompressed x){
134  GameState t = decompress(x);
135  return diff(a, t);
136}
137
138GameState GameStateManager::diff(GameState a, GameState b){
139  unsigned char *ap = a.data, *bp = b.data;
140  int of=0; // pointers offset
141  int dest_length=0;
142  if(a.size>=b.size)
143    dest_length=a.size;
144  else
145    dest_length=b.size;
146  unsigned char *dp = (unsigned char *)malloc(dest_length*sizeof(unsigned char));
147  while(of<a.size && of<b.size){
148    *(dp+of)=*(ap+of)^*(bp+of); // do the xor
149    ++of;
150  }
151  if(a.size!=b.size){ // do we have to fill up ?
152    unsigned char n=0;
153    if(a.size<b.size){
154      while(of<dest_length){
155        *(dp+of)=n^*(bp+of);
156        of++;
157      }
158    } else{
159      while(of<dest_length){
160        *(dp+of)=*(ap+of)^n;
161        of++;
162      }
163    }
164  }
165  // should be finished now
166  GameState r = {b.id, dest_length, dp};
167  return r;
168}
169
170GameStateCompressed GameStateManager::compress(GameState a) {
171  int size = a.size;
172  uLongf buffer = (uLongf)((a.size + 12)*1.01)+1;
173  unsigned char* dest = (unsigned char*)malloc( buffer );
174  int retval;
175  retval = compress( dest, &buffer, a.data, (uLong)size ); 
176 
177  switch ( retval ) {
178  case Z_OK: cout << "successfully compressed" << endl; break;
179  case Z_MEM_ERROR: cout << "not enough memory available" << endl; break;
180  case Z_BUF_ERROR: cout << "not enough memory available in the buffer" << endl; break;
181  case Z_DATA_ERROR: cout << "data corrupted" << endl; break;
182  }
183 
184  GameStateCompressed compressedGamestate = new GameStateCompressed;
185  compressedGamestate.compsize = buffer;
186  compressedGamestate.normsize = size;
187  compressedGamestate.id = GAMESTATE;
188  compressedGamestate.data = dest;
189 
190  return compressedGamestate;
191}
192
193GameState GameStateManager::decompress(GameStateCompressed a){
194  int normsize = a.normsize;
195  int compsize = a.compsize;
196  unsigned char* dest = (unsigned char*)malloc( normsize );
197  int retval;
198  retval = uncompress( dest, &normsize, a.data, compsize );
199 
200  switch ( retval ) {
201  case Z_OK: cout << "successfully compressed" << endl; break;
202  case Z_MEM_ERROR: cout << "not enough memory available" << endl; break;
203  case Z_BUF_ERROR: cout << "not enough memory available in the buffer" << endl; break;
204  case Z_DATA_ERROR: cout << "data corrupted" << endl; break;
205  }
206 
207  GameState gamestate = new GameState;
208  gamestate.id = a.id;
209  gamestate.size = normsize;
210  gamestate.data = dest;
211 
212  return gamestate;
213}
214
215}
216
217
Note: See TracBrowser for help on using the repository browser.