Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/network/synchronizeable.cc @ 9879

Last change on this file since 9879 was 9869, checked in by bensch, 18 years ago

orxonox/trunk: merged the new_class_id branche back to the trunk.
merged with command:
svn merge https://svn.orxonox.net/orxonox/branches/new_class_id trunk -r9683:HEAD
no conflicts… puh..

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