Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/mergeFS18/src/libraries/network/packet/Gamestate.cc

Last change on this file was 12027, checked in by merholzl, 6 years ago

Merged Masterserver, refresh button had to be removed

  • Property svn:eol-style set to native
File size: 19.8 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:
[3084]23 *      Oliver Scheuss
[1711]24 *   Co-authors:
25 *      ...
26 *
27 */
28
[1701]29#include "Gamestate.h"
[3214]30
[2773]31#include <zlib.h>
[3214]32
[8858]33#include "util/Output.h"
[8373]34#include "util/OrxAssert.h"
[9667]35#include "core/CoreIncludes.h"
[2896]36#include "core/GameMode.h"
[9667]37#include "core/object/ObjectList.h"
[3214]38#include "network/synchronisable/Synchronisable.h"
39#include "network/GamestateHandler.h"
[7801]40#include "network/Host.h"
[1701]41
[2171]42namespace orxonox {
[1701]43
44namespace packet {
45
[2662]46#define GAMESTATE_START(data) (data + GamestateHeader::getSize())
[1740]47
[7801]48#define PACKET_FLAG_GAMESTATE  0
[2087]49
[7163]50inline bool memzero( uint8_t* data, uint32_t datalength)
51{
52  uint64_t* d = (uint64_t*)data;
[2662]53
[7163]54  for( unsigned int i=0; i<datalength/8; i++ )
55  {
56    if( *(d+i) != 0 )
57      return false;
58  }
59  // now process the rest (when datalength isn't a multiple of 4)
60  for( unsigned int j = 8*(datalength/8); j<datalength; j++ )
61  {
62    if( *(data+j) != 0 )
63      return false;
64  }
65  return true;
66}
67
68
69Gamestate::Gamestate():
[7801]70  header_()
[1701]71{
[1907]72  flags_ = flags_ | PACKET_FLAG_GAMESTATE;
[1701]73}
74
[7163]75
[1907]76Gamestate::Gamestate(uint8_t *data, unsigned int clientID):
[7801]77  Packet(data, clientID), header_(data)
[1701]78{
[1907]79  flags_ = flags_ | PACKET_FLAG_GAMESTATE;
[1701]80}
81
[7163]82
[7801]83Gamestate::Gamestate(uint8_t *data):
84  header_(data)
[1907]85{
86  flags_ = flags_ | PACKET_FLAG_GAMESTATE;
[7163]87  data_ = data;
[1907]88}
[1701]89
[7163]90
[2662]91Gamestate::Gamestate(const Gamestate& g) :
[7801]92  Packet( *(Packet*)&g ), header_(this->data_), nrOfVariables_(0)
[2662]93{
94  flags_ = flags_ | PACKET_FLAG_GAMESTATE;
[7163]95  sizes_ = g.sizes_;
[2662]96}
[1907]97
[2662]98
[1701]99Gamestate::~Gamestate()
100{
101}
102
[12027]103//AV: This takes all synchronisables and packs it in a GameState, to be sent over the network
[2171]104bool Gamestate::collectData(int id, uint8_t mode)
[1701]105{
[2662]106  uint32_t tempsize=0, currentsize=0;
[11071]107  assert(data_==nullptr);
[2662]108  uint32_t size = calcGamestateSize(id, mode);
[1740]109
[8858]110  orxout(verbose_more, context::packets) << "G.ST.Man: producing gamestate with id: " << id << endl;
[1701]111  if(size==0)
112    return false;
[2662]113  data_ = new uint8_t[size + GamestateHeader::getSize()];
[7163]114  if(!data_)
115  {
[8858]116    orxout(internal_warning, context::packets) << "GameStateManager: could not allocate memory" << endl;
[1701]117    return false;
118  }
[6417]119
[7801]120  // tell the gamestate header where to store the data
121  header_.setData(this->data_);
[2087]122
[1701]123  //start collect data synchronisable by synchronisable
[7163]124  uint8_t *mem = data_; // in this stream store all data of the variables and the headers of the synchronisable
[2662]125  mem += GamestateHeader::getSize();
[2171]126  ObjectList<Synchronisable>::iterator it;
[11071]127  for(it = ObjectList<Synchronisable>().begin(); it; ++it)
[7163]128  {
[6417]129
[7163]130    tempsize = it->getData(mem, this->sizes_, id, mode);
[3084]131    if ( tempsize != 0 )
[11071]132      dataVector_.emplace_back(it->getObjectID(), it->getContextID(), tempsize, mem-data_);
[6417]133
[2662]134#ifndef NDEBUG
[7163]135    if(currentsize+tempsize > size)
136    {
[2171]137      assert(0); // if we don't use multithreading this part shouldn't be neccessary
[1701]138      // start allocate additional memory
[8858]139      orxout(internal_info, context::packets) << "Gamestate: need additional memory" << endl;
[2171]140      ObjectList<Synchronisable>::iterator temp = it;
[2662]141      uint32_t addsize=tempsize;
[1701]142      while(++temp)
[1907]143        addsize+=temp->getSize(id, mode);
[2662]144      data_ = (uint8_t *)realloc(data_, GamestateHeader::getSize() + currentsize + addsize);
[1701]145      if(!data_)
146        return false;
147      size = currentsize+addsize;
148    }// stop allocate additional memory
[2662]149#endif
[3084]150//     if(!it->getData(mem, id, mode))
151//       return false; // mem pointer gets automatically increased because of call by reference
[1701]152    // increase size counter by size of current synchronisable
153    currentsize+=tempsize;
154  }
[1740]155
156
[1701]157  //start write gamestate header
[7801]158  header_.setDataSize( currentsize );
[8327]159  header_.setCompSize( 0 );
[7801]160  header_.setID( id );
161  header_.setBaseID( GAMESTATEID_INITIAL );
162  header_.setDiffed( false );
163  header_.setComplete( true );
164  header_.setCompressed( false );
[1701]165  //stop write gamestate header
[1740]166
[8858]167  orxout(verbose_more, context::packets) << "Gamestate: Gamestate size: " << currentsize << endl;
168  orxout(verbose_more, context::packets) << "Gamestate: 'estimated' (and corrected) Gamestate size: " << size << endl;
[1701]169  return true;
170}
171
[12027]172//AV: This takes the Gamestate received from the network and "unpacks" it back to a list of Objects/Synchronisables, thus updating the data
[2171]173bool Gamestate::spreadData(uint8_t mode)
[1701]174{
[8858]175  orxout(verbose_more, context::packets) << "processing gamestate with id " << header_.getID() << endl;
[1751]176  assert(data_);
[7801]177  assert(!header_.isCompressed());
[2662]178  uint8_t *mem=data_+GamestateHeader::getSize();
[1907]179  Synchronisable *s;
[7801]180 
[1907]181  // update the data of the objects we received
[7801]182  while(mem < data_+GamestateHeader::getSize()+header_.getDataSize())
[7163]183  {
[2662]184    SynchronisableHeader objectheader(mem);
[1701]185
[2662]186    s = Synchronisable::getSynchronisable( objectheader.getObjectID() );
[1907]187    if(!s)
[1701]188    {
[2896]189      if (!GameMode::isMaster())
[2662]190      {
191        Synchronisable::fabricate(mem, mode);
192      }
193      else
194      {
[7163]195        mem += objectheader.getDataSize() + ( objectheader.isDiffed() ? SynchronisableHeaderLight::getSize() : SynchronisableHeader::getSize() );
[2662]196      }
[1701]197    }
[1907]198    else
199    {
[8394]200      OrxVerify(s->updateData(mem, mode), "ERROR: could not update Synchronisable with Gamestate data");
[1907]201    }
[1701]202  }
[7844]203  assert((uintptr_t)(mem-data_) == GamestateHeader::getSize()+header_.getDataSize());
[1701]204  return true;
205}
206
[7163]207
[2662]208uint32_t Gamestate::getSize() const
[1701]209{
[1711]210  assert(data_);
[7801]211  if(header_.isCompressed())
212    return header_.getCompSize()+GamestateHeader::getSize();
[1701]213  else
214  {
[7801]215    return header_.getDataSize()+GamestateHeader::getSize();
[1701]216  }
217}
218
[7163]219
220bool Gamestate::operator==(packet::Gamestate gs)
221{
[2662]222  uint8_t *d1 = data_+GamestateHeader::getSize();
223  uint8_t *d2 = gs.data_+GamestateHeader::getSize();
[8394]224  GamestateHeader h1(data_);
225  GamestateHeader h2(gs.data_);
226  assert(h1.getDataSize() == h2.getDataSize());
[1751]227  assert(!isCompressed());
228  assert(!gs.isCompressed());
[8394]229  return memcmp(d1, d2, h1.getDataSize())==0;
[1751]230}
231
[7163]232
[7801]233bool Gamestate::process(orxonox::Host* host)
[1701]234{
[7801]235  return host->addGamestate(this, getPeerID());
[1701]236}
237
[12027]238//AV: This function takes the Gamestate and compresses it for transmission over the network
[1701]239bool Gamestate::compressData()
240{
[2662]241  assert(data_);
[7801]242  assert(!header_.isCompressed());
243  uLongf buffer = (uLongf)(((header_.getDataSize() + 12)*1.01)+1);
[1701]244  if(buffer==0)
245    return false;
[1740]246
[2662]247  uint8_t *ndata = new uint8_t[buffer+GamestateHeader::getSize()];
248  uint8_t *dest = ndata + GamestateHeader::getSize();
249  uint8_t *source = data_ + GamestateHeader::getSize();
[1701]250  int retval;
[7801]251  retval = compress( dest, &buffer, source, (uLong)(header_.getDataSize()) );
[7163]252  switch ( retval )
253  {
[8858]254    case Z_OK: orxout(verbose_more, context::packets) << "G.St.Man: compress: successfully compressed" << endl; break;
255    case Z_MEM_ERROR: orxout(internal_error, context::packets) << "G.St.Man: compress: not enough memory available in gamestate.compress" << endl; return false;
256    case Z_BUF_ERROR: orxout(internal_warning, context::packets) << "G.St.Man: compress: not enough memory available in the buffer in gamestate.compress" << endl; return false;
257    case Z_DATA_ERROR: orxout(internal_warning, context::packets) << "G.St.Man: compress: data corrupted in gamestate.compress" << endl; return false;
[1701]258  }
259
260  //copy and modify header
[7801]261  GamestateHeader *temp = new GamestateHeader(data_);
262  header_.setData(ndata);
263  header_ = *temp;
[2662]264  delete temp;
[1701]265  //delete old data
266  delete[] data_;
267  //save new data
268  data_ = ndata;
[7801]269  header_.setCompSize( buffer );
270  header_.setCompressed( true );
[8858]271  orxout(verbose, context::packets) << "gamestate compress datasize: " << header_.getDataSize() << " compsize: " << header_.getCompSize() << endl;
[1701]272  return true;
273}
[7163]274
[12027]275//AV: This function takes the compressed Gamestate received from the network and decompresses it for further unpacking
[1701]276bool Gamestate::decompressData()
277{
[2662]278  assert(data_);
[7801]279  assert(header_.isCompressed());
[8858]280  orxout(verbose, context::packets) << "GameStateClient: uncompressing gamestate. id: " << header_.getID() << ", baseid: " << header_.getBaseID() << ", datasize: " << header_.getDataSize() << ", compsize: " << header_.getCompSize() << endl;
[7801]281  uint32_t datasize = header_.getDataSize();
282  uint32_t compsize = header_.getCompSize();
[2662]283  uint32_t bufsize;
[1907]284  bufsize = datasize;
[1751]285  assert(bufsize!=0);
[2662]286  uint8_t *ndata = new uint8_t[bufsize + GamestateHeader::getSize()];
287  uint8_t *dest = ndata + GamestateHeader::getSize();
288  uint8_t *source = data_ + GamestateHeader::getSize();
[1701]289  int retval;
[1751]290  uLongf length=bufsize;
291  retval = uncompress( dest, &length, source, (uLong)compsize );
[7163]292  switch ( retval )
293  {
[8858]294    case Z_OK: orxout(verbose_more, context::packets) << "successfully decompressed" << endl; break;
295    case Z_MEM_ERROR: orxout(internal_error, context::packets) << "not enough memory available" << endl; return false;
296    case Z_BUF_ERROR: orxout(internal_warning, context::packets) << "not enough memory available in the buffer" << endl; return false;
297    case Z_DATA_ERROR: orxout(internal_warning, context::packets) << "data corrupted (zlib)" << endl; return false;
[1701]298  }
[1752]299
[1701]300  //copy over the header
[7801]301  GamestateHeader* temp = new GamestateHeader( data_ );
302  header_.setData(ndata);
303  header_ = *temp;
[2662]304  delete temp;
[2087]305
[7163]306  if (this->bDataENetAllocated_)
307  {
[2087]308    // Memory was allocated by ENet. --> We let it be since enet_packet_destroy will
309    // deallocated it anyway. So data and packet stay together.
310    this->bDataENetAllocated_ = false;
311  }
[7163]312  else
313  {
[2087]314    // We allocated the memory in the first place (unlikely). So we destroy the old data
315    // and overwrite it with the new decompressed data.
316    delete[] this->data_;
317  }
318
[1751]319  //set new pointers
[1701]320  data_ = ndata;
[7801]321  header_.setCompressed( false );
322  assert(header_.getDataSize()==datasize);
323  assert(header_.getCompSize()==compsize);
[1701]324  return true;
325}
326
[7163]327
[7801]328inline void /*Gamestate::*/diffObject( uint8_t*& newDataPtr, uint8_t*& origDataPtr, uint8_t*& baseDataPtr, SynchronisableHeader& objectHeader, std::vector<uint32_t>::iterator& sizes )
329{
330  assert( objectHeader.getDataSize() == SynchronisableHeader(baseDataPtr).getDataSize() );
331 
332  uint32_t objectOffset = SynchronisableHeader::getSize(); // offset inside the object in the origData and baseData
333  // Check whether the whole object stayed the same
334  if( memcmp( origDataPtr+objectOffset, baseDataPtr+objectOffset, objectHeader.getDataSize()) == 0 )
335  {
336    origDataPtr += objectOffset + objectHeader.getDataSize(); // skip the whole object
337    baseDataPtr += objectOffset + objectHeader.getDataSize();
338    sizes += Synchronisable::getSynchronisable(objectHeader.getObjectID())->getNrOfVariables();
339  }
340  else
341  {
342    // Now start to diff the Object
343    SynchronisableHeaderLight newObjectHeader(newDataPtr);
344    newObjectHeader = objectHeader; // copy over the objectheader
345    VariableID variableID = 0;
346    uint32_t diffedObjectOffset = SynchronisableHeaderLight::getSize();
347    // iterate through all variables
348    while( objectOffset < objectHeader.getDataSize()+SynchronisableHeader::getSize() )
349    {
350      // check whether variable changed and write id and copy over variable to the new stream
351      // otherwise skip variable
352      uint32_t varSize = *sizes;
353      assert( varSize == Synchronisable::getSynchronisable(objectHeader.getObjectID())->getVarSize(variableID) );
354      if ( varSize != 0 )
355      {
356        if ( memcmp(origDataPtr+objectOffset, baseDataPtr+objectOffset, varSize) != 0 )
357        {
358          *(VariableID*)(newDataPtr+diffedObjectOffset) = variableID; // copy over the variableID
359          diffedObjectOffset += sizeof(VariableID);
360          memcpy( newDataPtr+diffedObjectOffset, origDataPtr+objectOffset, varSize );
361          diffedObjectOffset += varSize;
362          objectOffset += varSize;
363        }
364        else
365        {
366          objectOffset += varSize;
367        }
368      }
369
370      ++variableID;
371      ++sizes;
372    }
373   
374    // if there are variables from this object with 0 size left in sizes
375    if( Synchronisable::getSynchronisable(objectHeader.getObjectID())->getNrOfVariables() != variableID )
376      sizes += Synchronisable::getSynchronisable(objectHeader.getObjectID())->getNrOfVariables() - variableID;
377   
378    newObjectHeader.setDiffed(true);
379    newObjectHeader.setDataSize(diffedObjectOffset-SynchronisableHeaderLight::getSize());
380    assert(objectOffset == objectHeader.getDataSize()+SynchronisableHeader::getSize());
381    assert(newObjectHeader.getDataSize()>0);
382   
383    origDataPtr += objectOffset;
384    baseDataPtr += objectOffset;
385    newDataPtr += diffedObjectOffset;
386  }
387}
388
389inline void /*Gamestate::*/copyObject( uint8_t*& newData, uint8_t*& origData, uint8_t*& baseData, SynchronisableHeader& objectHeader, std::vector<uint32_t>::iterator& sizes )
390{
391  // Just copy over the whole Object
392  memcpy( newData, origData, objectHeader.getDataSize()+SynchronisableHeader::getSize() );
393  SynchronisableHeader(newData).setDiffed(false);
394 
395  newData += objectHeader.getDataSize()+SynchronisableHeader::getSize();
396  origData += objectHeader.getDataSize()+SynchronisableHeader::getSize();
[12027]397
[7801]398  sizes += Synchronisable::getSynchronisable(objectHeader.getObjectID())->getNrOfVariables();
[12027]399
[7801]400}
401
402inline bool findObject(uint8_t*& dataPtr, uint8_t* endPtr, SynchronisableHeader& objectHeader)
403{
404  // Some assertions to make sure the dataPtr is valid (pointing to a SynchronisableHeader)
405  {
406    SynchronisableHeader htemp2(dataPtr);
407    assert(htemp2.getClassID()<500);
408    assert(htemp2.getDataSize()!=0 && htemp2.getDataSize()<1000);
409    assert(htemp2.isDiffed()==false);
410  }
411  uint32_t objectID = objectHeader.getObjectID();
412  while ( dataPtr < endPtr )
413  {
414    SynchronisableHeader htemp(dataPtr);
415    assert( htemp.getDataSize()!=0 );
416    if ( htemp.getObjectID() == objectID )
417    {
418      assert( objectHeader.getClassID() == htemp.getClassID() );
[9667]419      assert( objectHeader.getContextID() == htemp.getContextID() );
[7801]420      return true;
421    }
422    {
423      if( dataPtr+htemp.getDataSize()+SynchronisableHeader::getSize() < endPtr )
424      {
425        SynchronisableHeader htemp2(dataPtr+htemp.getDataSize()+SynchronisableHeader::getSize());
426        assert(htemp2.getClassID()<500);
427        assert(htemp2.getDataSize()!=0 && htemp2.getDataSize()<1000);
428        assert(htemp2.isDiffed()==false);
429      }
430    }
431    dataPtr += htemp.getDataSize()+SynchronisableHeader::getSize();
432   
433  }
434  assert(dataPtr == endPtr);
435 
436  return false;
437}
438
[7163]439Gamestate* Gamestate::diffVariables(Gamestate *base)
[1701]440{
[11083]441  assert(base); assert(data_ && base->data_);
[7801]442  assert(!header_.isCompressed() && !base->header_.isCompressed());
443  assert(!header_.isDiffed());
444  assert( header_.getDataSize() && base->header_.getDataSize() );
[7163]445
446
447  // *** first do a raw diff of the two gamestates
448
[7801]449  uint8_t *baseDataPtr = GAMESTATE_START(base->data_);
450  uint8_t *origDataPtr = GAMESTATE_START(this->data_);
451  uint8_t *origDataEnd = origDataPtr + header_.getDataSize();
452  uint8_t *baseDataEnd = baseDataPtr + base->header_.getDataSize();
[7163]453
[12027]454
[7801]455  // Allocate new space for diffed gamestate
456  uint32_t newDataSize = header_.getDataSize() + GamestateHeader::getSize() + sizeof(uint32_t)*this->nrOfVariables_;
457  uint8_t *newData = new uint8_t[newDataSize]; // this is the maximum size needed in the worst case
458  uint8_t *destDataPtr = GAMESTATE_START(newData);
[7163]459
[7801]460  std::vector<uint32_t>::iterator sizesIt = this->sizes_.begin();
[7163]461
[7801]462  while( origDataPtr < origDataEnd )
[7163]463  {
464    //iterate through all objects
465
[7801]466    SynchronisableHeader origHeader(origDataPtr);
[7163]467
468    // Find (if possible) the current object in the datastream of the old gamestate
469    // Start at the current offset position
[7801]470    if(baseDataPtr == baseDataEnd)
471      baseDataPtr = GAMESTATE_START(base->data_);
472    uint8_t* oldBaseDataPtr = baseDataPtr;
473   
474    assert(baseDataPtr < baseDataEnd);
475    assert(destDataPtr < newData + newDataSize);
476    assert(sizesIt != this->sizes_.end());
477   
478    assert(Synchronisable::getSynchronisable(origHeader.getObjectID()));
479    assert(ClassByID(origHeader.getClassID()));
480    assert(origHeader.getDataSize() < 500);
481   
482    if( findObject(baseDataPtr, baseDataEnd, origHeader) )
[7163]483    {
[7801]484      SynchronisableHeader baseHeader(baseDataPtr);
485      assert(Synchronisable::getSynchronisable(baseHeader.getObjectID()));
486      assert(ClassByID(baseHeader.getClassID()));
487      assert(baseHeader.getDataSize() < 500);
488      if( SynchronisableHeader(baseDataPtr).getDataSize()==origHeader.getDataSize() )
[7163]489      {
[8858]490//         orxout(verbose, context::packets) << "diffing object in order: " << Synchronisable::getSynchronisable(origHeader.getObjectID())->getIdentifier()->getName() << endl;
[7801]491        diffObject(destDataPtr, origDataPtr, baseDataPtr, origHeader, sizesIt);
[1701]492      }
[7801]493      else
[7163]494      {
[8858]495//         orxout(verbose, context::packets) << "copy object because of different data sizes (1): " << Synchronisable::getSynchronisable(origHeader.getObjectID())->getIdentifier()->getName() << endl;
[7801]496        copyObject(destDataPtr, origDataPtr, baseDataPtr, origHeader, sizesIt);
497        assert(sizesIt != this->sizes_.end() || origDataPtr==origDataEnd);
[7163]498      }
[7801]499       
[7163]500    }
[7801]501    else
[7163]502    {
[7801]503      assert( baseDataPtr == baseDataEnd );
504      baseDataPtr = GAMESTATE_START(base->data_);
505      if( findObject(baseDataPtr, oldBaseDataPtr, origHeader) )
[7163]506      {
[7801]507        SynchronisableHeader baseHeader(baseDataPtr);
508        assert(Synchronisable::getSynchronisable(baseHeader.getObjectID()));
509        assert(ClassByID(baseHeader.getClassID()));
510        assert(baseHeader.getDataSize() < 500);
511        if( SynchronisableHeader(baseDataPtr).getDataSize()==origHeader.getDataSize() )
[7163]512        {
[8858]513//           orxout(verbose, context::packets) << "diffing object out of order: " << Synchronisable::getSynchronisable(origHeader.getObjectID())->getIdentifier()->getName() << endl;
[7801]514          diffObject(destDataPtr, origDataPtr, baseDataPtr, origHeader, sizesIt);
[7163]515        }
[7801]516        else
517        {
[8858]518//           orxout(verbose, context::packets) << "copy object because of different data sizes (2): " << Synchronisable::getSynchronisable(origHeader.getObjectID())->getIdentifier()->getName() << endl;
[7801]519          copyObject(destDataPtr, origDataPtr, baseDataPtr, origHeader, sizesIt);
520          assert(sizesIt != this->sizes_.end() || origDataPtr==origDataEnd);
521        }
[7163]522      }
[7801]523      else
[7163]524      {
[8858]525//         orxout(verbose, context::packets) << "copy object: " << Synchronisable::getSynchronisable(origHeader.getObjectID())->getIdentifier()->getName() << endl;
[7801]526        assert(baseDataPtr == oldBaseDataPtr);
527        copyObject(destDataPtr, origDataPtr, baseDataPtr, origHeader, sizesIt);
528        assert(sizesIt != this->sizes_.end() || origDataPtr==origDataEnd);
[7163]529      }
530    }
[1701]531  }
[7801]532  assert(sizesIt==this->sizes_.end());
[1701]533
[7163]534
[7801]535  Gamestate *g = new Gamestate(newData, getPeerID());
536  (g->header_) = header_;
537  g->header_.setBaseID( base->getID() );
538  g->header_.setDataSize(destDataPtr - newData - GamestateHeader::getSize());
[1751]539  g->flags_=flags_;
540  g->packetDirection_ = packetDirection_;
[7163]541  assert(!g->isCompressed());
[1701]542  return g;
[7163]543}
[3198]544
[7163]545
[7801]546uint32_t Gamestate::calcGamestateSize(uint32_t id, uint8_t mode)
[1701]547{
[7163]548  uint32_t size = 0;
549  uint32_t nrOfVariables = 0;
[1701]550    // get total size of gamestate
[11071]551  for(Synchronisable* synchronisable : ObjectList<Synchronisable>()){
552    size+=synchronisable->getSize(id, mode); // size of the actual data of the synchronisable
553    nrOfVariables += synchronisable->getNrOfVariables();
[7163]554  }
[8858]555//   orxout() << "allocating " << nrOfVariables << " ints" << endl;
[7163]556  this->sizes_.reserve(nrOfVariables);
[1701]557  return size;
558}
559
[7163]560
[2662]561} //namespace packet
562} //namespace orxonox
Note: See TracBrowser for help on using the repository browser.