Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 2518 was 2457, checked in by rgrieder, 16 years ago

Fix didn't do the trick. Don't even know exactly what it would have done..

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