Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/network/src/network/packet/Gamestate.cc @ 2351

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

some changes. still not working yet, but will correct theese problems after merge with network64

  • Property svn:eol-style set to native
File size: 19.8 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) 2008
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "Gamestate.h"
30#include "network/ClientInformation.h"
31#include "network/GamestateHandler.h"
32#include "core/CoreIncludes.h"
33#include "core/Iterator.h"
34
35#include <zlib.h>
36#include <assert.h>
37
38
39
40namespace network {
41
42namespace packet {
43
44#define GAMESTATE_START(data) (data + sizeof(GamestateHeader))
45#define GAMESTATE_HEADER(data) ((GamestateHeader *)data)
46#define HEADER GAMESTATE_HEADER(data_)
47
48
49#define PACKET_FLAG_GAMESTATE  ENET_PACKET_FLAG_RELIABLE
50
51Gamestate::Gamestate()
52{
53  flags_ = flags_ | PACKET_FLAG_GAMESTATE;
54}
55
56Gamestate::Gamestate(uint8_t *data, unsigned int clientID):
57    Packet(data, clientID)
58{
59  flags_ = flags_ | PACKET_FLAG_GAMESTATE;
60}
61
62Gamestate::Gamestate(uint8_t *data)
63{
64  flags_ = flags_ | PACKET_FLAG_GAMESTATE;
65  data_=data;
66}
67
68
69Gamestate::~Gamestate()
70{
71}
72
73bool Gamestate::collectData(int id, int mode)
74{
75  int tempsize=0, currentsize=0;
76  assert(data_==0);
77  int size = calcGamestateSize(id, mode);
78
79  COUT(4) << "G.ST.Man: producing gamestate with id: " << id << std::endl;
80  if(size==0)
81    return false;
82  data_ = new unsigned char[size + sizeof(GamestateHeader)];
83  if(!data_){
84    COUT(2) << "GameStateManager: could not allocate memory" << std::endl;
85    return false;
86  }
87
88#ifndef NDEBUG
89  std::list<Synchronisable*> slist;
90  std::list<Synchronisable*>::iterator iit;
91#endif
92  //start collect data synchronisable by synchronisable
93  uint8_t *mem=data_;
94  mem+=sizeof(GamestateHeader);
95  orxonox::ObjectList<Synchronisable>::iterator it;
96  for(it = orxonox::ObjectList<Synchronisable>::begin(); it; ++it){
97    tempsize=it->getSize(id, mode);
98
99    if(currentsize+tempsize > size){
100      // start allocate additional memory
101      COUT(3) << "G.St.Man: need additional memory" << std::endl;
102      orxonox::ObjectList<Synchronisable>::iterator temp = it;
103      int addsize=tempsize;
104      while(++temp)
105        addsize+=temp->getSize(id, mode);
106      data_ = (uint8_t *)realloc(data_, sizeof(GamestateHeader) + currentsize + addsize);
107      if(!data_)
108        return false;
109      size = currentsize+addsize;
110    }// stop allocate additional memory
111
112#ifndef NDEBUG
113    for(iit=slist.begin(); iit!=slist.end(); iit++)
114      assert((*iit)!=*it);
115    slist.push_back(*it);
116#endif
117
118    //if(it->doSelection(id))
119    dataMap_.push_back( obj(it->getObjectID(), it->getCreatorID(), tempsize, mem-data_) );
120//     dataMap_[mem-data_]=(*it);  // save the mem location of the synchronisable data
121    if(!it->getData(mem, id, mode))
122      return false; // mem pointer gets automatically increased because of call by reference
123    // increase size counter by size of current synchronisable
124    currentsize+=tempsize;
125  }
126
127
128  //start write gamestate header
129  HEADER->packetType = ENUM::Gamestate;
130  assert( *(ENUM::Type *)(data_) == ENUM::Gamestate);
131  HEADER->datasize = currentsize;
132  HEADER->id = id;
133  HEADER->diffed = false;
134  HEADER->complete = true;
135  HEADER->compressed = false;
136  //stop write gamestate header
137
138  COUT(5) << "G.ST.Man: Gamestate size: " << currentsize << std::endl;
139  COUT(5) << "G.ST.Man: 'estimated' (and corrected) Gamestate size: " << size << std::endl;
140  return true;
141}
142
143bool Gamestate::spreadData(int mode)
144{
145  assert(data_);
146  assert(!HEADER->compressed);
147  assert(!HEADER->diffed);
148  uint8_t *mem=data_+sizeof(GamestateHeader);
149    // get the start of the Synchronisable list
150  //orxonox::ObjectList<Synchronisable>::iterator it=orxonox::ObjectList<Synchronisable>::begin();
151  Synchronisable *s;
152
153  // update the data of the objects we received
154  while(mem < data_+sizeof(GamestateHeader)+HEADER->datasize){
155    synchronisableHeader *objectheader = (synchronisableHeader*)mem;
156
157    s = Synchronisable::getSynchronisable( objectheader->objectID );
158    if(!s)
159    {
160      Synchronisable::fabricate(mem, mode);
161    }
162    else
163    {
164      bool b = s->updateData(mem, mode);
165      assert(b);
166      //if(!s->updateData(mem, mode))
167        //return false;
168    }
169  }
170
171  return true;
172}
173
174
175
176int Gamestate::getID(){
177  return HEADER->id;
178}
179
180unsigned int Gamestate::getSize() const
181{
182  assert(data_);
183  if(HEADER->compressed)
184    return HEADER->compsize+sizeof(GamestateHeader);
185  else
186  {
187    return HEADER->datasize+sizeof(GamestateHeader);
188  }
189}
190
191bool Gamestate::operator==(packet::Gamestate gs){
192  uint8_t *d1 = data_+sizeof(GamestateHeader);
193  uint8_t *d2 = gs.data_+sizeof(GamestateHeader);
194  assert(!isCompressed());
195  assert(!gs.isCompressed());
196  while(d1<data_+HEADER->datasize)
197  {
198    if(*d1!=*d2)
199      return false;
200    d1++;
201    d2++;
202  }
203  return true;
204}
205
206bool Gamestate::process()
207{
208  return GamestateHandler::addGamestate(this, getClientID());
209}
210
211
212
213bool Gamestate::compressData()
214{
215  assert(HEADER);
216  assert(!HEADER->compressed);
217  uLongf buffer = (uLongf)(((HEADER->datasize + 12)*1.01)+1);
218  if(buffer==0)
219    return false;
220
221  uint8_t *ndata = new uint8_t[buffer+sizeof(GamestateHeader)];
222  uint8_t *dest = GAMESTATE_START(ndata);
223  //unsigned char *dest = new unsigned char[buffer];
224  uint8_t *source = GAMESTATE_START(data_);
225  int retval;
226  retval = compress( dest, &buffer, source, (uLong)(HEADER->datasize) );
227  switch ( retval ) {
228    case Z_OK: COUT(5) << "G.St.Man: compress: successfully compressed" << std::endl; break;
229    case Z_MEM_ERROR: COUT(1) << "G.St.Man: compress: not enough memory available in gamestate.compress" << std::endl; return false;
230    case Z_BUF_ERROR: COUT(2) << "G.St.Man: compress: not enough memory available in the buffer in gamestate.compress" << std::endl; return false;
231    case Z_DATA_ERROR: COUT(2) << "G.St.Man: compress: data corrupted in gamestate.compress" << std::endl; return false;
232  }
233#ifndef NDEBUG
234  //decompress and compare the start and the decompressed data
235  uint8_t *rdata = new uint8_t[HEADER->datasize+sizeof(GamestateHeader)];
236  uint8_t *d2 = GAMESTATE_START(rdata);
237  uLongf length2 = HEADER->datasize;
238  uncompress(d2, &length2, dest, buffer);
239  for(unsigned int i=0; i<HEADER->datasize; i++){
240    assert(*(source+i)==*(d2+i));
241  }
242  delete[] rdata;
243#endif
244
245  //copy and modify header
246#ifndef NDEBUG
247  HEADER->crc32 = calcCRC(data_+sizeof(GamestateHeader), HEADER->datasize);
248#endif
249  *GAMESTATE_HEADER(ndata) = *HEADER;
250  //delete old data
251  delete[] data_;
252  //save new data
253  data_ = ndata;
254  HEADER->compsize = buffer;
255  HEADER->compressed = true;
256  assert(HEADER->compressed);
257  COUT(4) << "gamestate compress datasize: " << HEADER->datasize << " compsize: " << HEADER->compsize << std::endl;
258  return true;
259}
260bool Gamestate::decompressData()
261{
262  assert(HEADER);
263  assert(HEADER->compressed);
264  COUT(4) << "GameStateClient: uncompressing gamestate. id: " << HEADER->id << ", baseid: " << HEADER->base_id << ", datasize: " << HEADER->datasize << ", compsize: " << HEADER->compsize << std::endl;
265  unsigned int datasize = HEADER->datasize;
266  unsigned int compsize = HEADER->compsize;
267  unsigned int bufsize;
268//  assert(compsize<=datasize);
269  bufsize = datasize;
270  assert(bufsize!=0);
271  uint8_t *ndata = new uint8_t[bufsize + sizeof(GamestateHeader)];
272  uint8_t *dest = ndata + sizeof(GamestateHeader);
273  uint8_t *source = data_ + sizeof(GamestateHeader);
274  int retval;
275  uLongf length=bufsize;
276  retval = uncompress( dest, &length, source, (uLong)compsize );
277  switch ( retval ) {
278    case Z_OK: COUT(5) << "successfully decompressed" << std::endl; break;
279    case Z_MEM_ERROR: COUT(1) << "not enough memory available" << std::endl; return false;
280    case Z_BUF_ERROR: COUT(2) << "not enough memory available in the buffer" << std::endl; return false;
281    case Z_DATA_ERROR: COUT(2) << "data corrupted (zlib)" << std::endl; return false;
282  }
283#ifndef NDEBUG
284  assert(HEADER->crc32==calcCRC(ndata+sizeof(GamestateHeader), HEADER->datasize));
285#endif
286
287  //copy over the header
288  *GAMESTATE_HEADER(ndata) = *HEADER;
289  //delete old (compressed data)
290  delete[] data_;
291  //set new pointers
292  data_ = ndata;
293  HEADER->compressed = false;
294  assert(HEADER->datasize==datasize);
295  assert(HEADER->compsize==compsize);
296  return true;
297}
298
299Gamestate *Gamestate::diff(Gamestate *base)
300{
301  assert(HEADER);
302  assert(!HEADER->compressed);
303  assert(!HEADER->diffed);
304  //unsigned char *basep = base->getGs()/*, *gs = getGs()*/;
305  uint8_t *basep = GAMESTATE_START(base->data_), *gs = GAMESTATE_START(this->data_);
306  unsigned int of=0; // pointers offset
307  unsigned int dest_length=0;
308  dest_length=HEADER->datasize;
309  if(dest_length==0)
310    return NULL;
311  uint8_t *ndata = new uint8_t[dest_length*sizeof(uint8_t)+sizeof(GamestateHeader)];
312  uint8_t *dest = ndata + sizeof(GamestateHeader);
313  while(of < GAMESTATE_HEADER(base->data_)->datasize && of < HEADER->datasize){
314    *(dest+of)=*(basep+of)^*(gs+of); // do the xor
315    ++of;
316  }
317  if(GAMESTATE_HEADER(base->data_)->datasize!=HEADER->datasize){
318    uint8_t n=0;
319    if(GAMESTATE_HEADER(base->data_)->datasize < HEADER->datasize){
320      while(of<dest_length){
321        *(dest+of)=n^*(gs+of);
322        of++;
323      }
324    }
325  }
326
327  *GAMESTATE_HEADER(ndata) = *HEADER;
328  GAMESTATE_HEADER(ndata)->diffed = true;
329  GAMESTATE_HEADER(ndata)->base_id = base->getID();
330  Gamestate *g = new Gamestate(ndata, getClientID());
331  g->flags_=flags_;
332  g->packetDirection_ = packetDirection_;
333  return g;
334}
335
336Gamestate* Gamestate::doSelection(unsigned int clientID, unsigned int targetSize){
337  assert(data_);
338  std::vector<obj>::iterator it;
339
340  // allocate memory for new data
341  uint8_t *gdata = new uint8_t[HEADER->datasize+sizeof(GamestateHeader)];
342  // create a gamestate out of it
343  Gamestate *gs = new Gamestate(gdata);
344  uint8_t *newdata = gdata + sizeof(GamestateHeader);
345//   uint8_t *origdata = GAMESTATE_START(data_);
346
347  //copy the GamestateHeader
348  *(GamestateHeader*)gdata = *HEADER;
349
350  synchronisableHeader *oldobjectheader, *newobjectheader;
351  unsigned int objectOffset;
352  unsigned int objectsize;
353  Synchronisable *object;
354
355  //copy in the zeros
356  for(it=dataMap_.begin(); it!=dataMap_.end(); it++){
357    oldobjectheader = (synchronisableHeader*)(data_ + (*it).objDataOffset);
358    newobjectheader = (synchronisableHeader*)newdata;
359    objectsize = oldobjectheader->size;
360    object = Synchronisable::getSynchronisable( (*it).objID );
361    assert(object->objectID == oldobjectheader->objectID);
362    *newobjectheader = *oldobjectheader;
363    objectOffset=sizeof(uint8_t)+sizeof(bool); //skip the size and the availableDate variables in the objectheader
364    if ( object->doSelection(HEADER->id) ){
365      newobjectheader->dataAvailable=true; //TODO: probably not neccessary
366      while(objectOffset<objectsize){
367        *(newdata + objectOffset)=*(data_ + (*it).objDataOffset + objectOffset);    // copy the data
368        objectOffset++;
369      }
370    }else{
371      newobjectheader->dataAvailable=false;
372      while(objectOffset<objectsize){
373        *(data_ + (*it).objDataOffset + objectOffset)=0;    // set to 0
374        objectOffset++;
375      }
376      assert(objectOffset==objectsize);
377    }
378    newdata += objectsize;
379//     origdata += objectsize;
380  }
381  return gs;
382}
383
384
385Gamestate* Gamestate::intelligentDiff(Gamestate *base, unsigned int clientID){
386  // asserts
387  assert(data_);
388  assert(base->data_);
389  assert(!GAMESTATE_HEADER(base->data_)->diffed);
390  assert(!GAMESTATE_HEADER(base->data_)->compressed);
391  assert(!HEADER->compressed);
392  assert(!HEADER->diffed);
393
394  //preparations
395  std::vector<obj>::iterator it;
396  uint8_t *origdata, *basedata, *destdata, *ndata;
397  unsigned int objectOffset, streamOffset=0;    //data offset
398  unsigned int minsize = (HEADER->datasize < GAMESTATE_HEADER(base->data_)->datasize) ? HEADER->datasize : GAMESTATE_HEADER(base->data_)->datasize;
399  synchronisableHeader *origheader;
400  synchronisableHeader *destheader;
401  Synchronisable *object;
402
403  origdata = GAMESTATE_START(this->data_);
404  basedata = GAMESTATE_START(base->data_);
405  ndata = new uint8_t[HEADER->datasize + sizeof(GamestateHeader)];
406  destdata = ndata + sizeof(GamestateHeader);
407
408  // do the diff
409  for(it=dataMap_.begin(); it!=dataMap_.end(); it++){
410    assert(streamOffset<HEADER->datasize);
411    origheader = (synchronisableHeader *)(origdata+streamOffset);
412    destheader = (synchronisableHeader *)(destdata+streamOffset);
413    object = Synchronisable::getSynchronisable(origheader->objectID);
414    bool sendData = object->doSelection(HEADER->id);
415
416    //copy and partially diff the object header
417    assert(sizeof(synchronisableHeader)==3*sizeof(unsigned int)+sizeof(bool));
418    *(uint32_t*)destdata = *(uint32_t*)origdata; //size (do not diff)
419    *(bool*)(destdata+sizeof(uint32_t)) = sendData;
420    if(sendData){
421      *(uint32_t*)(destdata+sizeof(uint32_t)+sizeof(bool)) = *(uint32_t*)(basedata+sizeof(uint32_t)+sizeof(bool)) ^ *(uint32_t*)(origdata+sizeof(uint32_t)+sizeof(bool)); //objectid (diff it)
422      *(uint32_t*)(destdata+2*sizeof(uint32_t)+sizeof(bool)) = *(uint32_t*)(basedata+2*sizeof(uint32_t)+sizeof(bool)) ^ *(uint32_t*)(origdata+2*sizeof(uint32_t)+sizeof(bool)); //classid (diff it)
423    }else{
424      *(uint32_t*)(destdata+sizeof(uint32_t)+sizeof(bool)) = 0;
425      *(uint32_t*)(destdata+2*sizeof(uint32_t)+sizeof(bool)) = 0;
426    }
427    objectOffset=sizeof(synchronisableHeader);
428    streamOffset+=sizeof(synchronisableHeader);
429
430    //now handle the object data or fill with zeros
431    while(objectOffset<origheader->size ){
432
433      if(sendData && streamOffset<minsize)
434        *(destdata+objectOffset)=*(basedata+objectOffset)^*(origdata+objectOffset); // do the xor
435      else if(sendData)
436        *(destdata+objectOffset)=((uint8_t)0)^*(origdata+objectOffset); // xor with 0 (basestream is too short)
437      else
438        *(destdata+objectOffset)=0; // set to 0 because this object should not be transfered
439
440      objectOffset++;
441      streamOffset++;
442    }
443    destdata+=objectOffset;
444    origdata+=objectOffset;
445    basedata+=objectOffset;
446  }
447
448  //copy over the gamestate header and set the diffed flag
449  *(GamestateHeader *)ndata = *HEADER; //copy over the header
450  Gamestate *gs = new Gamestate(ndata);
451  GAMESTATE_HEADER(ndata)->diffed=true;
452  return gs;
453}
454
455Gamestate* Gamestate::intelligentUnDiff(Gamestate *base){
456  // asserts
457  assert(data_);
458  assert(base->data_);
459  assert(!GAMESTATE_HEADER(base->data_)->diffed);
460  assert(!GAMESTATE_HEADER(base->data_)->compressed);
461  assert(!HEADER->compressed);
462  assert(HEADER->diffed);
463
464  //preparations
465  std::vector<obj>::iterator it;
466  uint8_t *origdata, *basedata, *destdata, *ndata;
467  unsigned int objectOffset, streamOffset=0;    //data offset
468  unsigned int minsize = (HEADER->datasize < GAMESTATE_HEADER(base->data_)->datasize) ? HEADER->datasize : GAMESTATE_HEADER(base->data_)->datasize;
469  synchronisableHeader *origheader;
470  synchronisableHeader *destheader;
471  Synchronisable *object;
472
473  origdata = GAMESTATE_START(this->data_);
474  basedata = GAMESTATE_START(base->data_);
475  ndata = new uint8_t[HEADER->datasize + sizeof(GamestateHeader)];
476  destdata = ndata + sizeof(GamestateHeader);
477
478  // do the undiff
479  for(it=dataMap_.begin(); it!=dataMap_.end(); it++){
480    assert(streamOffset<HEADER->datasize);
481    origheader = (synchronisableHeader *)(origdata+streamOffset);
482    destheader = (synchronisableHeader *)(destdata+streamOffset);
483    object = Synchronisable::getSynchronisable( origheader->objectID );
484    bool sendData;
485
486    //copy and partially diff the object header
487    assert(sizeof(synchronisableHeader)==3*sizeof(unsigned int)+sizeof(bool));
488    *(unsigned int*)destdata = *(unsigned int*)origdata; //size (do not diff)
489    *(bool*)(destdata+sizeof(unsigned int)) = *(bool*)(origdata+sizeof(unsigned int));
490    sendData = *(bool*)(origdata+sizeof(unsigned int));
491    if(sendData){
492      *(unsigned int*)(destdata+sizeof(unsigned int)+sizeof(bool)) = *(unsigned int*)(basedata+sizeof(unsigned int)+sizeof(bool)) ^ *(unsigned int*)(origdata+sizeof(unsigned int)+sizeof(bool)); //objectid (diff it)
493      *(unsigned int*)(destdata+2*sizeof(unsigned int)+sizeof(bool)) = *(unsigned int*)(basedata+2*sizeof(unsigned int)+sizeof(bool)) ^ *(unsigned int*)(origdata+2*sizeof(unsigned int)+sizeof(bool)); //classid (diff it)
494    }else{
495      *(unsigned int*)(destdata+sizeof(unsigned int)+sizeof(bool)) = 0;
496      *(unsigned int*)(destdata+2*sizeof(unsigned int)+sizeof(bool)) = 0;
497    }
498    objectOffset=sizeof(synchronisableHeader);
499    streamOffset+=sizeof(synchronisableHeader);
500
501    //now handle the object data or fill with zeros
502    while(objectOffset<origheader->size ){
503
504      if(sendData && streamOffset<minsize)
505        *(destdata+objectOffset)=*(basedata+objectOffset)^*(origdata+objectOffset); // do the xor
506      else if(sendData)
507        *(destdata+objectOffset)=((unsigned char)0)^*(origdata+objectOffset); // xor with 0 (basestream is too short)
508      else
509        *(destdata+objectOffset)=0; // set to 0 because this object should not be transfered
510
511      objectOffset++;
512      streamOffset++;
513    }
514    destdata+=objectOffset;
515    origdata+=objectOffset;
516    basedata+=objectOffset;
517  }
518
519  //copy over the gamestate header and set the diffed flag
520  *(GamestateHeader *)ndata = *HEADER; //copy over the header
521  Gamestate *gs = new Gamestate(ndata);
522  GAMESTATE_HEADER(ndata)->diffed=false;
523  return gs;
524}
525
526Gamestate *Gamestate::undiff(Gamestate *base)
527{
528  assert(this && base);assert(HEADER);
529  assert(HEADER->diffed);
530  assert(!HEADER->compressed && !GAMESTATE_HEADER(base->data_)->compressed);
531  //unsigned char *basep = base->getGs()/*, *gs = getGs()*/;
532  uint8_t *basep = GAMESTATE_START(base->data_);
533  uint8_t *gs = GAMESTATE_START(this->data_);
534  unsigned int of=0; // pointers offset
535  unsigned int dest_length=0;
536  dest_length=HEADER->datasize;
537  if(dest_length==0)
538    return NULL;
539  uint8_t *ndata = new uint8_t[dest_length*sizeof(uint8_t)+sizeof(GamestateHeader)];
540  uint8_t *dest = ndata + sizeof(GamestateHeader);
541  while(of < GAMESTATE_HEADER(base->data_)->datasize && of < HEADER->datasize){
542    *(dest+of)=*(basep+of)^*(gs+of); // do the xor
543    ++of;
544  }
545  if(GAMESTATE_HEADER(base->data_)->datasize!=HEADER->datasize){
546    uint8_t n=0;
547    if(GAMESTATE_HEADER(base->data_)->datasize < HEADER->datasize){
548      while(of < dest_length){
549        *(dest+of)=n^*(gs+of);
550        of++;
551      }
552    }
553  }
554  *GAMESTATE_HEADER(ndata) = *HEADER;
555  GAMESTATE_HEADER(ndata)->diffed = false;
556  Gamestate *g = new Gamestate(ndata, getClientID());
557  g->flags_=flags_;
558  g->packetDirection_ = packetDirection_;
559  assert(!g->isDiffed());
560  assert(!g->isCompressed());
561  return g;
562}
563
564
565unsigned int Gamestate::calcGamestateSize(unsigned int id, int mode)
566{
567  int size=0;
568    // get the start of the Synchronisable list
569  orxonox::ObjectList<Synchronisable>::iterator it;
570    // get total size of gamestate
571  for(it = orxonox::ObjectList<Synchronisable>::begin(); it; ++it)
572    size+=it->getSize(id, mode); // size of the actual data of the synchronisable
573//  size+=sizeof(GamestateHeader);
574  return size;
575}
576
577/**
578 * This function removes a Synchronisable out of the universe
579 * @param it iterator of the list pointing to the object
580 * @return iterator pointing to the next object in the list
581 */
582  void Gamestate::removeObject(orxonox::ObjectList<Synchronisable>::iterator &it) {
583    orxonox::ObjectList<Synchronisable>::iterator temp=it;
584    ++it;
585    delete  *temp;
586  }
587
588  bool Gamestate::isDiffed(){
589    return HEADER->diffed;
590  }
591
592  bool Gamestate::isCompressed(){
593    return HEADER->compressed;
594  }
595
596  int Gamestate::getBaseID(){
597    return HEADER->base_id;
598  }
599}
600
601}
Note: See TracBrowser for help on using the repository browser.