Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

made some adjustments mostly to the networkid (classid) in order to have it platform independent

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