Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

another new gamestate concept ;)

  • server does an individual object composition (to be sent) for every client
  • atm objects have sync frequencies and are priorized after their frequency (not clienbased yet)
  • after highlevel diff (object composition) a lowlevel diff is done
  • afterwards compression

→ 65 to 80 percent less data to be transmitted

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