Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/proxy/src/lib/network/synchronizeable.cc @ 9594

Last change on this file since 9594 was 9594, checked in by patrick, 18 years ago

the team id is set correctly again at least for locals

File size: 21.1 KB
RevLine 
[5523]1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
[5547]11
[5523]12### File Specific:
[9406]13   main-programmer: Christoph Renner (rennerc@ee.ethz.ch)
14   co-programmer: Patrick Boenzli (patrick@orxonox.ethz.ch)
[5547]15*/
[5523]16
[6139]17#define DEBUG_MODULE_NETWORK
18
[6695]19#include "shared_network_data.h"
20#include "network_stream.h"
[5547]21#include "netdefs.h"
[7954]22#include "network_log.h"
[8068]23#include "network_game_manager.h"
[5529]24
[6695]25#include "state.h"
[5996]26
[6753]27#include <cassert>
[6695]28
29#include "synchronizeable.h"
30
[9406]31#include "converter.h"
[6695]32
33
[9406]34
[5547]35/**
[5807]36 *  default constructor
[5547]37 */
[5996]38Synchronizeable::Synchronizeable()
[5997]39{
[6341]40  this->setClassID(CL_SYNCHRONIZEABLE, "Synchronizeable");
[8068]41  this->owner = 0;
[9406]42//   this->setIsServer(SharedNetworkData::getInstance()->getHostID() == 0);
[6695]43  this->uniqueID = NET_UID_UNASSIGNED;
[6145]44  this->networkStream = NULL;
[6695]45  this->bSynchronize = false;
[9406]46
[6695]47  if( State::isOnline())
48  {
49    NetworkStream* nd = SharedNetworkData::getInstance()->getDefaultSyncStream();
50    assert(nd != NULL);
51    nd->connectSynchronizeable(*this);
52    this->setUniqueID(SharedNetworkData::getInstance()->getNewUniqueID());
53  }
[7954]54
55  /* make sure loadClassId is first synced var because this is read by networkStream */
56  assert( syncVarList.size() == 0 );
57  mLeafClassId = this->registerVarId( new SynchronizeableInt( (int*)&this->getLeafClassID(), (int*)&this->getLeafClassID(), "leafClassId" ) );
[9406]58
[7954]59  this->registerVar( new SynchronizeableInt( &this->owner, &this->owner, "owner" ) );
60  this->registerVar( new SynchronizeableString( &this->objectName, &this->objectName, "objectName" ) );
[5997]61}
62
[5523]63
[5996]64
[5547]65/**
[5807]66 *  default destructor deletes all unneded stuff
[5547]67 */
68Synchronizeable::~Synchronizeable()
[6139]69{
70  if ( this->networkStream )
[9110]71  {
[6139]72    this->networkStream->disconnectSynchronizeable(*this);
[9406]73
[9494]74    // remove the message manager only by the server
75    if ( (SharedNetworkData::getInstance()->isMasterServer() )
[9406]76           && this->beSynchronized() && this->getUniqueID() > 0 && !this->isA( CL_MESSAGE_MANAGER ) )
[9110]77      NetworkGameManager::getInstance()->removeSynchronizeable( this->getUniqueID() );
78  }
[9406]79
[8623]80  for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
81  {
82    delete *it;
83  }
84  syncVarList.clear();
[9406]85
[8623]86  for ( UserStateHistory::iterator it = recvStates.begin(); it != recvStates.end(); it++ )
87  {
88    for ( StateHistory::iterator it2 = it->begin(); it2 != it->end(); it2++ )
89    {
90      if ( (*it2)->data )
91      {
92        delete [] (*it2)->data;
93        (*it2)->data = NULL;
94      }
95      delete *it2;
96    }
97
98  }
[9406]99
[8623]100  for ( UserStateHistory::iterator it = sentStates.begin(); it != sentStates.end(); it++ )
101  {
102    for ( StateHistory::iterator it2 = it->begin(); it2 != it->end(); it2++ )
103    {
104      if ( (*it2)->data )
105      {
106        delete [] (*it2)->data;
107        (*it2)->data = NULL;
108      }
109      delete *it2;
110    }
111  }
[6139]112}
[5523]113
114
[6695]115
[5547]116/**
[9406]117 * creates a diff image from two states
118 * @param userId: the userid of the user where the image will be sent to
119 * @param data: the binary data array to write to
120 * @param maxLength: maximal length of the data written (length of available space in the array)
121 * @param stateId: the state id that this diff will represent
122 * @param priorityTH: the priority threshold: all syncs below this threshold won't be synchronized
123 *
124 * @todo check for permissions
[5547]125 */
[7954]126int Synchronizeable::getStateDiff( int userId, byte* data, int maxLength, int stateId, int fromStateId, int priorityTH )
127{
128  //make sure this user has his history
129  if ( sentStates.size() <= userId )
130    sentStates.resize( userId+1 );
[5547]131
[7954]132  //calculate needed memory
133  int neededSize = 0;
[5997]134
[7954]135  for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
[8147]136  {
137    //PRINTF(0)("SIZE = %d %s\n", (*it)->getSize(), (*it)->getName().c_str());
[7954]138    neededSize += (*it)->getSize();
[8147]139  }
[5997]140
[7954]141  if ( !( neededSize <= maxLength ) )
142  {
143    PRINTF(0)( "%d > %d\n", neededSize, maxLength );
144    assert(false);
145  }
146
147  //remove older states from history than fromStateId
148  StateHistory::iterator it = sentStates[userId].begin();
149
150  while ( it != sentStates[userId].end() && (*it)->stateId < fromStateId )
151    it++;
152
153  if ( it != sentStates[userId].begin() )
154  {
155    for ( StateHistory::iterator it2 = sentStates[userId].begin(); it2 != it; it2++ )
156    {
157      if ( (*it2)->data != NULL )
158      {
159        delete [] (*it2)->data;
160        (*it2)->data = NULL;
161      }
[9406]162
[8623]163      delete *it2;
[7954]164    }
165    sentStates[userId].erase( sentStates[userId].begin(), it );
166  }
167
168  //find state to create diff from
169  StateHistoryEntry * stateFrom = NULL;
170
171  it = sentStates[userId].begin();
172  while ( it != sentStates[userId].end() && (*it)->stateId != fromStateId )
173    it++;
174
175  if ( it == sentStates[userId].end() )
176  {
177    StateHistoryEntry * initialEntry = new StateHistoryEntry();
178
179    initialEntry->stateId = fromStateId;
180    initialEntry->dataLength = 0;
181    initialEntry->data = NULL;
182
183    stateFrom = initialEntry;
[9406]184
[8623]185    sentStates[userId].push_back( stateFrom );
[7954]186  }
187  else
188    stateFrom = (*it);
189
[8623]190  StateHistoryEntry * stateTo = new StateHistoryEntry;
[7954]191
[8623]192  sentStates[userId].push_back( stateTo );
[9406]193
[7954]194  stateTo->stateId = stateId;
195  stateTo->dataLength = neededSize;
196  stateTo->data = new byte[ neededSize ];
197
198  std::list<int>::iterator sizeIter = stateFrom->sizeList.begin();
199
200  int i = 0;
201  int n;
[9406]202
203  bool hasPermission = false;
[8623]204  bool sizeChanged = false;
[7954]205
206  // now do the actual synchronization: kick all variables to write into a common buffer
207  for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
208  {
[9406]209    // DATA PERMISSIONS
210    // check if this synchronizeable has the permissions to write the data
211
[9591]212    //  MASTER_SERVER |====> *
[9406]213    if( SharedNetworkData::getInstance()->isMasterServer() && (*it)->checkPermission( PERMISSION_MASTER_SERVER ))
214      hasPermission = true;
[9591]215    else if( SharedNetworkData::getInstance()->isMasterServer() && this->owner != userId && (*it)->checkPermission( PERMISSION_OWNER ))
216      hasPermission = true;
[9592]217
[9591]218    // PROXY_SERVER  |====> *
[9494]219    else if( SharedNetworkData::getInstance()->isProxyServerActive() && (*it)->checkPermission( PERMISSION_PROXY_SERVER ))
[9406]220      hasPermission = true;
[9591]221    else if( SharedNetworkData::getInstance()->isProxyServerActive() && this->owner != userId && (*it)->checkPermission( PERMISSION_OWNER ))
222      hasPermission = true;
[9592]223    // PROXY_SERVER  |====> MASTER_SERVER
224    else if( SharedNetworkData::getInstance()->isProxyServerActive() && this->networkStream->isUserMasterServer(userId)
225             && this->networkStream->isUserLocal(userId) && (*it)->checkPermission( PERMISSION_MASTER_SERVER))
[9406]226      hasPermission = true;
[9592]227    // PROXY_SERVER  |====> CLIENT
228    else if( SharedNetworkData::getInstance()->isProxyServerActive() && this->networkStream->isUserClient(userId)
229             && this->owner != userId && (*it)->checkPermission( PERMISSION_OWNER ) )
[9406]230      hasPermission = true;
[9494]231    else if( SharedNetworkData::getInstance()->isProxyServerActive() && this->networkStream->isUserClient(userId)
[9581]232             && (*it)->checkPermission( PERMISSION_MASTER_SERVER) )
233      hasPermission = true;
[9592]234
235    // OWNER         |====> *
236    else if( this->owner == SharedNetworkData::getInstance()->getHostID() && (*it)->checkPermission( PERMISSION_OWNER ))
[9588]237      hasPermission = true;
[9592]238
239    // ALL           |====> *
240    else if( (*it)->checkPermission( PERMISSION_ALL ))
[9406]241      hasPermission = true;
[9592]242
[9406]243    else
244      hasPermission = false;
245
246
247    if ( sizeIter == stateFrom->sizeList.end() || *sizeIter != (*it)->getSize() )
[8623]248      sizeChanged = true;
[9406]249
[8623]250    if ( ( hasPermission && (*it)->getPriority() >= priorityTH ) || sizeChanged )
[7954]251    {
252      n = (*it)->writeToBuf( stateTo->data+i, stateTo->dataLength - i );
[9579]253      //NETPRINTF(0)("getvar %s %d\n", (*it)->getName().c_str(), n);
[9406]254      //PRINTF(0)("getvar %s %d\n", (*it)->getName().c_str(), n);
[7954]255      stateTo->sizeList.push_back( n );
[9406]256      // this is only for very hardcore debug sessions
257      // (*it)->debug();
[7954]258      i += n;
259    }
260    else
261    {
262      for ( int j = 0; j<(*sizeIter); j++ )
263      {
264        assert( i < stateFrom->dataLength );
265        stateTo->data[i] = stateFrom->data[i];
266        i++;
267      }
268      //NETPRINTF(0)("getvar %s %d\n", (*it)->getName().c_str(), *sizeIter);
269      stateTo->sizeList.push_back( (*sizeIter) );
270    }
271
272    if ( sizeIter != stateFrom->sizeList.end() )
273      sizeIter++;
274  }
275
[8147]276  if ( i != neededSize )
277  {
[9406]278    PRINTF(0)("strange error: (%s) %d != %d\n", this->getClassCName(), i, neededSize);
[8147]279    assert(false);
280  }
[7954]281
282  //write diff to data
283  for ( i = 0; i<neededSize; i++ )
284  {
285    if ( i < stateFrom->dataLength )
286      data[i] = stateTo->data[i] - stateFrom->data[i];
287    else
288      data[i] = stateTo->data[i];
289  }
290
291  return neededSize;
292}
293
[5997]294/**
[7954]295 * sets a new state out of a diff created on another host
296 * @param userId hostId of user who send me that diff
297 * @param data pointer to diff
298 * @param length length of diff
299 * @param stateId id of current state
300 * @param fromStateId id of the base state id
301 * @return number bytes read
[9406]302 *
[7954]303 * @todo check for permissions
[5997]304 */
[7954]305int Synchronizeable::setStateDiff( int userId, byte* data, int length, int stateId, int fromStateId )
[5997]306{
[7954]307  //make sure this user has his history
308  if ( recvStates.size() <= userId )
309    recvStates.resize( userId+1 );
310
311  //create new state
312  StateHistoryEntry * stateTo = new StateHistoryEntry();
313  stateTo->stateId = stateId;
314  stateTo->dataLength = length;
315  stateTo->data = new byte[ length ];
316
317
318  //find state to apply diff to
319  StateHistoryEntry * stateFrom = NULL;
320
[9406]321  // search the state from wich the diff is made of
[7954]322  StateHistory::iterator it = recvStates[userId].begin();
323  while ( it != recvStates[userId].end() && (*it)->stateId != fromStateId )
324    it++;
325
[9406]326  // if this is the first state to receive
[7954]327  if ( it == recvStates[userId].end() )
328  {
329    StateHistoryEntry * initialEntry = new StateHistoryEntry();
330
331    initialEntry->stateId = fromStateId;
332    initialEntry->dataLength = 0;
333    initialEntry->data = NULL;
334
335    stateFrom = initialEntry;
[9406]336
[8623]337    recvStates[userId].push_back( stateFrom );
[7954]338  }
[5997]339  else
[7954]340    stateFrom = (*it);
[9406]341
342
343  // apply diff
[7954]344  for ( int i = 0; i<length; i++ )
345  {
346    if ( i < stateFrom->dataLength )
347      stateTo->data[i] = stateFrom->data[i] + data[i];
348    else
349      stateTo->data[i] = data[i];
350  }
[9406]351
[7954]352  //add state to state history
353  recvStates[userId].push_back( stateTo );
[9406]354
[7954]355  int i = 0;
356  int n = 0;
357  std::list<int> changes;
[9406]358  bool hasPermission = false;
359
360  // extract the new state for every client
[7954]361  for ( SyncVarList::iterator it = syncVarList.begin(); it != syncVarList.end(); it++ )
362  {
[9406]363    // DATA PERMISSIONS
364    // check if this synchronizeable has the permissions to write the data
365
[9592]366#if 0
367
368    //  MASTER_SERVER |====> *
369    if( SharedNetworkData::getInstance()->isMasterServer() && (*it)->checkPermission( PERMISSION_MASTER_SERVER ))
370      hasPermission = true;
371    else if( SharedNetworkData::getInstance()->isMasterServer() && this->owner != userId && (*it)->checkPermission( PERMISSION_OWNER ))
372      hasPermission = true;
373
374    // PROXY_SERVER  |====> *
375    else if( SharedNetworkData::getInstance()->isProxyServerActive() && (*it)->checkPermission( PERMISSION_PROXY_SERVER ))
376      hasPermission = true;
377    else if( SharedNetworkData::getInstance()->isProxyServerActive() && this->owner != userId && (*it)->checkPermission( PERMISSION_OWNER ))
378      hasPermission = true;
379    // PROXY_SERVER  |====> MASTER_SERVER
380    else if( SharedNetworkData::getInstance()->isProxyServerActive() && this->networkStream->isUserMasterServer(userId)
381             && this->networkStream->isUserLocal(userId) && (*it)->checkPermission( PERMISSION_MASTER_SERVER))
382      hasPermission = true;
383    // PROXY_SERVER  |====> CLIENT
384    else if( SharedNetworkData::getInstance()->isProxyServerActive() && this->networkStream->isUserClient(userId)
385             && this->owner != userId && (*it)->checkPermission( PERMISSION_OWNER ) )
386      hasPermission = true;
387    else if( SharedNetworkData::getInstance()->isProxyServerActive() && this->networkStream->isUserClient(userId)
388             && (*it)->checkPermission( PERMISSION_MASTER_SERVER) )
389      hasPermission = true;
390
391    // OWNER         |====> *
392    else if( this->owner == SharedNetworkData::getInstance()->getHostID() && (*it)->checkPermission( PERMISSION_OWNER ))
393      hasPermission = true;
394
395    // ALL           |====> *
396    else if( (*it)->checkPermission( PERMISSION_ALL ))
397      hasPermission = true;
398
399    else
400      hasPermission = false;
401
402#endif
403
404
405    //  *              <====|  MASTER_SERVER
[9406]406    if(  this->networkStream->isUserMasterServer( userId ) && (*it)->checkPermission( PERMISSION_MASTER_SERVER ))
407      hasPermission = true;
[9592]408    else if( this->networkStream->isUserMasterServer( userId ) && this->owner != SharedNetworkData::getInstance()->getHostID()
409             && (*it)->checkPermission( PERMISSION_OWNER ))
410      hasPermission = true;
411
412    //  *              <====|  PROXY_SERVER
413    else if( this->networkStream->isUserProxyServerActive( userId ) && this->owner != SharedNetworkData::getInstance()->getHostID()
414             && (*it)->checkPermission( PERMISSION_OWNER ))
415      hasPermission = true;
416    //  CLIENT         <====|  PROXY_SERVER
417    else if( this->networkStream->isUserProxyServerActive( userId ) && SharedNetworkData::getInstance()->isClient()
418             && this->owner != SharedNetworkData::getInstance()->getHostID() && (*it)->checkPermission( PERMISSION_OWNER ))
419      hasPermission = true;
[9593]420    else if( this->networkStream->isUserProxyServerActive( userId ) && SharedNetworkData::getInstance()->isClient()
421             && this->owner != SharedNetworkData::getInstance()->getHostID() && (*it)->checkPermission( PERMISSION_MASTER_SERVER ))
422      hasPermission = true;
[9594]423    else if( this->networkStream->isUserProxyServerActive( userId )  && SharedNetworkData::getInstance()->isClient()
424             && (*it)->checkPermission( PERMISSION_MASTER_SERVER ))
425      hasPermission = true;
[9592]426    // MASTER_SERVER   <====|  PROXY_SERVER
[9590]427    else if( this->networkStream->isUserProxyServerActive( userId )  && SharedNetworkData::getInstance()->isMasterServer() &&
428             !this->networkStream->isUserLocal( userId ))
429      hasPermission = true;
[9592]430
431    //  *              <====|  OWNER
[9406]432    else if( this->owner == userId && (*it)->checkPermission( PERMISSION_OWNER ))
433      hasPermission = true;
[9592]434
435    //  *              <====|  ALL
[9406]436    else if( (*it)->checkPermission( PERMISSION_ALL ))
437      hasPermission = true;
[9592]438
[9406]439    else
440      hasPermission = false;
441
442
443
444    // if it has the permission to write do it
445    if( hasPermission)
[7954]446    {
447      n = (*it)->readFromBuf( stateTo->data + i, stateTo->dataLength - i );
448      i += n;
[9406]449      //NETPRINTF(0)("%s::setvar %s %d\n", getClassCName(), (*it)->getName().c_str(), n);
[9579]450      //PRINTF(0)("%s::setvar %s %d\n", getClassCName(), (*it)->getName().c_str(), n);
[7954]451      //(*it)->debug();
452      if ( (*it)->getHasChanged() )
453      {
454        changes.push_back( (*it)->getVarId() );
455      }
456    }
457    else
458    {
[9494]459//       PRINTF(0)("DONT SET VAR BECAUSE OF PERMISSION: %s perm: %d %d %d - %d %d %d\n", (*it)->getName().c_str(), (*it)->checkPermission( PERMISSION_MASTER_SERVER ), (*it)->checkPermission( PERMISSION_OWNER ), (*it)->checkPermission( PERMISSION_ALL ), networkStream->isUserMasterServer( userId ), this->owner, userId );
[7954]460      n = (*it)->getSizeFromBuf( stateTo->data + i, stateTo->dataLength - i );
[9406]461      //NETPRINTF(0)("%s::setvar %s %d\n", getClassCName(), (*it)->getName().c_str(), n);
[7954]462      //(*it)->debug();
463      i += n;
464    }
465  }
466
467  this->varChangeHandler( changes );
[9406]468
[7954]469  return i;
[5997]470}
471
[7954]472 /**
473 * override this function to be notified on change
474 * of your registred variables.
475 * @param id id's which have changed
476 */
477void Synchronizeable::varChangeHandler( std::list<int> & id )
478{
479}
[6695]480
[5997]481/**
[7954]482 * registers a varable to be synchronized over network
483 * @param var see src/lib/network/synchronizeable_var/ for available classes
[5997]484 */
[7954]485void Synchronizeable::registerVar( SynchronizeableVar * var )
[5997]486{
[7954]487  syncVarList.push_back( var );
[5997]488}
489
490/**
[7954]491 * registers a varable to be synchronized over network
492 * return value is passed to varChangeHandler on change
493 * @param var see src/lib/network/synchronizeable_var/ for available classes
494 * @return handle passed to varChangeHandler on changes
[5997]495 */
[7954]496int Synchronizeable::registerVarId( SynchronizeableVar * var )
[5997]497{
[7954]498  syncVarList.push_back( var );
499  var->setWatched( true );
500  var->setVarId( syncVarList.size()-1 );
501  return syncVarList.size()-1;
[5997]502}
503
504/**
[7954]505 * removed user's states from memory
506 * @param userId user to clean
[5997]507 */
[7954]508void Synchronizeable::cleanUpUser( int userId )
[5997]509{
[8228]510  if ( recvStates.size() > userId )
[7954]511  {
[8228]512    for ( std::list<StateHistoryEntry*>::iterator it = recvStates[userId].begin(); it != recvStates[userId].end(); it++ )
[7954]513    {
[8228]514      if ( (*it)->data )
[8623]515      {
[8228]516        delete [] (*it)->data;
[8623]517        (*it)->data = NULL;
518      }
[9406]519
[8228]520      delete *it;
[7954]521    }
[8228]522    recvStates[userId].clear();
[7954]523  }
[9406]524
[8228]525  if ( sentStates.size() > userId )
[7954]526  {
[9406]527
[8228]528    for ( std::list<StateHistoryEntry*>::iterator it = sentStates[userId].begin(); it != sentStates[userId].end(); it++ )
[7954]529    {
[8228]530      if ( (*it)->data )
[8623]531      {
[8228]532        delete [] (*it)->data;
[8623]533        (*it)->data = NULL;
534      }
[9406]535
[8228]536      delete *it;
[7954]537    }
[8228]538    sentStates[userId].clear();
[7954]539  }
[5997]540}
[6139]541
[6341]542/**
[7954]543 * this function is called after recieving a state.
[9406]544 * @param userId
545 * @param stateId
546 * @param fromStateId
[6341]547 */
[7954]548void Synchronizeable::handleRecvState( int userId, int stateId, int fromStateId )
[6341]549{
[7954]550   //make sure this user has his history
551  if ( recvStates.size() <= userId )
552    recvStates.resize( userId+1 );
[9406]553
[7954]554  //remove old states
555  StateHistory::iterator it = recvStates[userId].begin();
556
557#if 0
558  while ( it != recvStates[userId].end() && (*it)->stateId < fromStateId )
559    it++;
560
561  if ( it != recvStates[userId].begin() )
562  {
563    for ( StateHistory::iterator it2 = recvStates[userId].begin(); it2 != it; it2++ )
564    {
565      if ( (*it2)->data != NULL )
566      {
567        delete [] (*it2)->data;
568        (*it2)->data = NULL;
569      }
570    }
571    recvStates[userId].erase( recvStates[userId].begin(), it );
572  }
573#endif
574
575  for ( it = recvStates[userId].begin(); it != recvStates[userId].end();  )
576  {
577    if ( (*it)->stateId < fromStateId )
578    {
579      StateHistory::iterator delIt = it;
580      it ++;
[9406]581
[7954]582      if ( (*delIt)->data )
[8623]583      {
[7954]584        delete [] (*delIt)->data;
[8623]585        (*delIt)->data = NULL;
586      }
587      delete *delIt;
[7954]588      recvStates[userId].erase( delIt );
[9406]589
[7954]590      continue;
591    }
592    it++;
593  }
[9406]594
[7954]595  StateHistory::iterator fromState = recvStates[userId].end();
596  StateHistory::iterator toState = recvStates[userId].end();
[9406]597
[7954]598  for ( it = recvStates[userId].begin(); it != recvStates[userId].end(); it++ )
599  {
600    if ( (*it)->stateId == stateId )
601      toState = it;
602    if ( (*it)->stateId == fromStateId )
603      fromState = it;
[9406]604
[7954]605    if ( fromState != recvStates[userId].end() && toState != recvStates[userId].end() )
606      break;
607  }
[9406]608
[7954]609  // setStateDiff was not called and i know fromStateId
610  if ( fromState != recvStates[userId].end() && toState == recvStates[userId].end() )
611  {
612    StateHistoryEntry * entry = new StateHistoryEntry;
[9406]613
[7954]614    entry->dataLength = (*fromState)->dataLength;
615    if ( entry->dataLength > 0 )
616    {
617      entry->data = new byte[entry->dataLength];
[9406]618
[7954]619      assert( (*fromState)->data );
620      memcpy( entry->data, (*fromState)->data, entry->dataLength );
621    }
622    else
623      entry->data = NULL;
[9406]624
[7954]625    entry->sizeList = (*fromState)->sizeList;
626    entry->stateId = stateId;
[9406]627
[7954]628    recvStates[userId].push_back(entry);
629  }
[6341]630}
[6139]631
[6341]632/**
[7954]633 * this function is called after sending a state
[9406]634 * @param userId
635 * @param stateId
636 * @param fromStateId
[6341]637 */
[7954]638void Synchronizeable::handleSentState( int userId, int stateId, int fromStateId )
[6341]639{
[7954]640   //make sure this user has his history
641  if ( sentStates.size() <= userId )
642    sentStates.resize( userId+1 );
643
644   //remove old states
645  StateHistory::iterator it = sentStates[userId].begin();
646
647  for ( it = sentStates[userId].begin(); it != sentStates[userId].end();  )
648  {
649    if ( (*it)->stateId < fromStateId )
650    {
651      StateHistory::iterator delIt = it;
652      it ++;
[9406]653
[7954]654      if ( (*delIt)->data )
[8623]655      {
[7954]656        delete [] (*delIt)->data;
[8623]657        (*delIt)->data = NULL;
658      }
659      delete *delIt;
[7954]660      sentStates[userId].erase( delIt );
[9406]661
[7954]662      continue;
663    }
664    it++;
665  }
666
[9406]667
[7954]668  StateHistory::iterator fromState = sentStates[userId].end();
669  StateHistory::iterator toState = sentStates[userId].end();
[9406]670
[7954]671  for ( it = sentStates[userId].begin(); it != sentStates[userId].end(); it++ )
672  {
673    if ( (*it)->stateId == stateId )
674      toState = it;
675    if ( (*it)->stateId == fromStateId )
676      fromState = it;
[9406]677
[7954]678    if ( fromState != sentStates[userId].end() && toState != sentStates[userId].end() )
679      break;
680  }
681
[9406]682
[7954]683  // getStateDiff was not called and i know fromStateId
684  if ( fromState != sentStates[userId].end() && toState == sentStates[userId].end() )
685  {
686    StateHistoryEntry * entry = new StateHistoryEntry;
[9406]687
[7954]688    entry->dataLength = (*fromState)->dataLength;
689    if ( entry->dataLength > 0 )
690    {
691      entry->data = new byte[entry->dataLength];
[9406]692
[7954]693      assert( (*fromState)->data );
694      memcpy( entry->data, (*fromState)->data, entry->dataLength );
695    }
696    else
697      entry->data = NULL;
[9406]698
[7954]699    entry->sizeList = (*fromState)->sizeList;
700    entry->stateId = stateId;
[9406]701
[7954]702    sentStates[userId].push_back(entry);
703  }
[9406]704
[6341]705}
[6139]706
[6341]707
708
Note: See TracBrowser for help on using the repository browser.