Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Dec 30, 2005, 1:52:26 AM (18 years ago)
Author:
bensch
Message:

orxonox/branches/newtork: merged the network branche for merging to the trunk
confilcts maily resolved in favor of trunk with some minor fixes

merged with command:
svn merge https://svn.orxonox.net/orxonox/branches/network . -r6146:HEAD

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/network_merged/src/lib/network/network_game_manager.cc

    r6139 r6340  
    2020#define DEBUG_MODULE_NETWORK
    2121
     22#include "factory.h"
     23#include "network_stream.h"
     24#include "converter.h"
     25
    2226/* include your own header */
    2327#include "network_game_manager.h"
     
    2731using namespace std;
    2832
     33NetworkGameManager* NetworkGameManager::singletonRef = NULL;
     34
    2935/*!
    3036 * Standard constructor
     
    3238NetworkGameManager::NetworkGameManager()
    3339{
     40  PRINTF(0)("START\n");
     41
    3442  /* set the class id for the base object */
    35   this->setClassID(CL_ENTITY_MANAGER, "EntityManager");
     43  this->setClassID(CL_NETWORK_GAME_MANAGER, "NetworkGameManager");
     44
     45  allOutBuffer.length = 0;
     46
     47  allOutBuffer.maxLength = 10*1024;
     48
     49  allOutBuffer.buffer = new byte[10*1024];
     50
     51  newUniqueID = MAX_CONNECTIONS + 2;
     52
     53  hasRequestedWorld = false;
    3654}
    3755
     
    4159NetworkGameManager::~NetworkGameManager()
    4260{
    43 }
    44 
    45 
    46 void NetworkGameManager::writeBytes(const byte* data, int length)
    47 {
     61  for ( int i = 0; i<outBuffer.size(); i++)
     62  {
     63    if ( outBuffer[i].buffer )
     64      delete outBuffer[i].buffer;
     65  }
     66
     67  if ( allOutBuffer.buffer )
     68    delete allOutBuffer.buffer;
     69}
     70
     71
     72int NetworkGameManager::writeBytes(const byte* data, int length, int sender)
     73{
     74  int i = 0;
     75  byte b;
     76
     77  while ( i<length )
     78  {
     79    b = data[i++];
     80
     81    PRINTF(0)("WriteBytes: b = %d\n", b);
     82
     83    if ( isServer() )
     84    {
     85      if ( b == REQUEST_CREATE )
     86      {
     87        if ( !handleRequestCreate( i, data, length, sender ) )
     88          return i;
     89        continue;
     90      }
     91      if ( b == REQUEST_REMOVE )
     92      {
     93        if ( !handleRequestRemove( i, data, length, sender ) )
     94          return i;
     95        continue;
     96      }
     97    }
     98    else
     99    {
     100      if ( b == CREATE_ENTITY )
     101      {
     102        if ( !handleCreateEntity( i, data, length, sender ) )
     103          return i;
     104        continue;
     105      }
     106      if ( b == REMOVE_ENTITY )
     107      {
     108        if ( !handleRemoveEntity( i, data, length, sender ) )
     109          return i;
     110        continue;
     111      }
     112      if ( b == CREATE_ENTITY_LIST )
     113      {
     114        if ( !handleCreateEntityList( i, data, length, sender ) )
     115          return i;
     116        continue;
     117      }
     118      if ( b == REMOVE_ENTITY_LIST )
     119      {
     120        if ( !handleRemoveEntityList( i, data, length, sender ) )
     121          return i;
     122        continue;
     123      }
     124      if ( b == YOU_ARE_ENTITY )
     125      {
     126        if ( !handleYouAreEntity( i, data, length, sender ) )
     127          return i;
     128        continue;
     129      }
     130    }
     131
     132    if ( b == REQUEST_SYNC )
     133    {
     134      if ( !handleRequestSync( i, data, length, sender ) )
     135        return i;
     136      continue;
     137    }
     138
     139    if ( b == REQUEST_ENTITY_LIST )
     140    {
     141      PRINTF(0)("sending THE list\n");
     142      sendEntityList( sender );
     143      continue;
     144    }
     145
     146    //if we get her something with data is wrong
     147    PRINTF(1)("Data is not in the right format! i=%d\n", i);
     148    return i;
     149  }
     150
     151  return i;
    48152}
    49153
    50154int NetworkGameManager::readBytes(byte* data, int maxLength, int * reciever)
    51155{
     156  if ( !isServer() && !hasRequestedWorld )
     157  {
     158    SYNCHELP_WRITE_BEGIN();
     159    byte b = REQUEST_ENTITY_LIST;
     160    SYNCHELP_WRITE_BYTE( b );
     161    hasRequestedWorld = true;
     162    PRINTF(0)("the world is enough! id=%d\n", this->getUniqueID());
     163    return SYNCHELP_WRITE_N;
     164  }
     165  for ( int i = 0; i<outBuffer.size(); i++ )
     166  {
     167    *reciever = i;
     168    if ( outBuffer[i].length>0 )
     169    {
     170      int nbytes = outBuffer[i].length;
     171      outBuffer[i].length = 0;
     172
     173      if ( nbytes > maxLength )
     174      {
     175        PRINTF(1)("OutBuffer.length (%d) > (%d) networkStreamBuffer.maxLength\n", nbytes, maxLength);
     176        return 0;
     177      }
     178
     179      memcpy(data, outBuffer[i].buffer, nbytes);
     180      return nbytes;
     181    }
     182  }
     183
     184  *reciever = 0;
     185  int nbytes = allOutBuffer.length;
     186  allOutBuffer.length = 0;
     187
     188  if ( nbytes <=0 )
     189    return 0;
     190
     191  if ( nbytes > maxLength )
     192  {
     193    PRINTF(1)("OutBuffer.length (%d) > (%d) networkStreamBuffer.length\n", nbytes, maxLength);
     194    return 0;
     195  }
     196
     197  memcpy( data, allOutBuffer.buffer, nbytes );
     198  return nbytes;
    52199}
    53200
     
    63210/*!
    64211 * Checks whether this is connected to a server or a client
    65  * and afterwards creates the needed entity if possible
     212 * and afterwards creates the needed entity
    66213 * @param classID: The ID of the class of which an entity should be created
    67214 */
    68 void NetworkGameManager::createEntity(int classID)
    69 {
    70 }
     215void NetworkGameManager::createEntity( ClassID classID, int owner )
     216{
     217  if ( this->isServer() )
     218  {
     219    if ( newUniqueID < 0 )
     220    {
     221      PRINTF(1)("Cannot create entity! There are no more uniqueIDs left!\n");
     222      return;
     223    }
     224
     225    this->executeCreateEntity( classID, newUniqueID++, owner );
     226  }
     227  else
     228  {
     229    this->requestCreateEntity( classID );
     230  }
     231}
     232
     233
     234/*!
     235 * Checks whether this is connected to a server or a client
     236 * and afterwards creates the needed entity
     237 * @param classID: The ID of the class of which an entity should be created
     238 */
     239BaseObject* NetworkGameManager::createEntity( TiXmlElement* element)
     240{
     241  if ( this->isServer() )
     242  {
     243    if ( newUniqueID < 0 )
     244    {
     245      PRINTF(1)("Cannot create entity! There are no more uniqueIDs left!\n");
     246      return NULL;
     247    }
     248    newUniqueID++;
     249
     250    BaseObject * b = Factory::fabricate( element );
     251
     252    if ( !b )
     253    {
     254      PRINTF(1)("Could not fabricate Object with classID %x\n", element->Value() );
     255      return NULL;
     256    }
     257
     258
     259    if ( b->isA(CL_SYNCHRONIZEABLE) )
     260    {
     261      Synchronizeable * s = dynamic_cast<Synchronizeable*>(b);
     262      s->setUniqueID( newUniqueID );
     263      s->setOwner( 0 );
     264      this->networkStream->connectSynchronizeable( *s );
     265      return b;
     266    }
     267    else
     268    {
     269      PRINTF(1)("Class %s is not a synchronizeable!\n", b->getClassName() );
     270      delete b;
     271    }
     272  }
     273  else
     274  {
     275    PRINTF(1)("This node is not a server and cannot create id %x\n", element->Value());
     276  }
     277  return NULL;
     278}
     279
    71280
    72281/*!
     
    77286void NetworkGameManager::removeEntity(int uniqueID)
    78287{
     288  if ( this->isServer() )
     289  {
     290    this->executeRemoveEntity( uniqueID );
     291  }
     292  else
     293  {
     294    this->requestRemoveEntity( uniqueID );
     295  }
    79296}
    80297
     
    85302 * @param classID: The ID of the class of which an entity should be created
    86303 */
    87 void NetworkGameManager::requestCreateEntity(int classID)
    88 {
     304void NetworkGameManager::requestCreateEntity(ClassID classID)
     305{
     306  if ( !writeToClientBuffer( allOutBuffer, (byte)REQUEST_CREATE ) )
     307    return;
     308  if ( !writeToClientBuffer( allOutBuffer, (int)classID ) )
     309    return;
    89310}
    90311
     
    95316void NetworkGameManager::requestRemoveEntity(int uniqueID)
    96317{
     318  if ( !writeToClientBuffer( allOutBuffer, (byte)REQUEST_REMOVE ) )
     319    return;
     320  if ( !writeToClientBuffer( allOutBuffer, uniqueID ) )
     321    return;
    97322}
    98323
     
    102327 * @param classID: The ID of the class of which an entity should be created
    103328 */
    104 void NetworkGameManager::executeCreateEntity(int classID)
    105 {
     329void NetworkGameManager::executeCreateEntity(ClassID classID, int uniqueID, int owner)
     330{
     331  if ( !writeToClientBuffer( allOutBuffer, (byte)CREATE_ENTITY ) )
     332    return;
     333  if ( !writeToClientBuffer( allOutBuffer, (int)classID ) )
     334    return;
     335  if ( !writeToClientBuffer( allOutBuffer, uniqueID ) )
     336    return;
     337  if ( !writeToClientBuffer( allOutBuffer, owner ) )
     338    return;
     339
     340  doCreateEntity( classID, uniqueID, owner );
    106341}
    107342
     
    113348void NetworkGameManager::executeRemoveEntity(int uniqueID)
    114349{
     350  if ( !writeToClientBuffer( allOutBuffer, (byte)REMOVE_ENTITY ) )
     351    return;
     352  if ( !writeToClientBuffer( allOutBuffer, uniqueID ) )
     353    return;
     354
     355  doRemoveEntity(uniqueID);
    115356}
    116357
     
    119360 * @return: true if the entity can be created, false otherwise
    120361 */
    121 bool NetworkGameManager::canCreateEntity(int classID)
    122 {
    123 }
     362bool NetworkGameManager::canCreateEntity(ClassID classID)
     363{
     364  return true;
     365}
     366
     367/*!
     368 * Sends the Entities to the new connected client
     369 * @param userID: The ID of the user
     370 */
     371void NetworkGameManager::sendEntityList( int userID )
     372{
     373  if ( !isServer() )
     374    return;
     375
     376  if ( userID >= outBuffer.size() )
     377    resizeBufferVector( userID );
     378
     379  SynchronizeableList::const_iterator it, e;
     380
     381  it = this->networkStream->getSyncBegin();
     382  e = this->networkStream->getSyncEnd();
     383
     384  if ( !writeToClientBuffer( outBuffer[userID], (byte)CREATE_ENTITY_LIST ) )
     385    return;
     386
     387  // -2 because you must not send network_game_manager and handshake
     388  if ( !writeToClientBuffer( outBuffer[userID], networkStream->getSyncCount() ) )
     389    return;
     390
     391  //PRINTF(0)("SendEntityList: n = %d\n", networkStream->getSyncCount()-2 );
     392
     393  while ( it != e )
     394  {
     395
     396    if ( !writeToClientBuffer( outBuffer[userID], (int)((*it)->getLeafClassID()) ) )
     397      return;
     398      //PRINTF(0)("SendEntityList: ClassID = %x\n", (*it)->getRealClassID());
     399
     400    if ( !writeToClientBuffer( outBuffer[userID], (int)((*it)->getUniqueID()) ) )
     401      return;
     402
     403    if ( !writeToClientBuffer( outBuffer[userID], (int)((*it)->getOwner()) ) )
     404      return;
     405
     406    it++;
     407  }
     408
     409
     410}
     411
     412/**
     413 * Creates a buffer for user n
     414 * @param n The ID of the user
     415 */
     416void NetworkGameManager::resizeBufferVector( int n )
     417{
     418  for ( int i = outBuffer.size(); i<=n; i++)
     419  {
     420    clientBuffer outBuf;
     421
     422    outBuf.length = 0;
     423
     424    outBuf.maxLength = 5*1024;
     425
     426    outBuf.buffer = new byte[5*1014];
     427
     428    outBuffer.push_back(outBuf);
     429  }
     430}
     431
     432/**
     433 * Creates the entity on this host
     434 * @param classID: ClassID of the entity to create
     435 * @param uniqueID: Unique ID to assign to the synchronizeable
     436 * @param owner: owner of this synchronizealbe
     437 */
     438void NetworkGameManager::doCreateEntity( ClassID classID, int uniqueID, int owner )
     439{
     440  BaseObject * b = Factory::fabricate( classID );
     441
     442  if ( !b )
     443  {
     444    PRINTF(1)("Could not fabricate Object with classID %x\n", classID);
     445    return;
     446  }
     447
     448  if ( b->isA(CL_SYNCHRONIZEABLE) )
     449  {
     450    Synchronizeable * s = dynamic_cast<Synchronizeable*>(b);
     451    s->setUniqueID( uniqueID );
     452    s->setOwner( owner );
     453    this->networkStream->connectSynchronizeable( *s );
     454    if ( !isServer() )
     455      s->setIsOutOfSync( true );
     456    PRINTF(0)("Fabricated %s with id %d\n", s->getClassName(), s->getUniqueID());
     457  }
     458  else
     459  {
     460    PRINTF(1)("Class with ID %x is not a synchronizeable!", (int)classID);
     461    delete b;
     462  }
     463}
     464
     465/**
     466 * Removes a entity on this host
     467 * @param uniqueID: unique ID assigned with the entity to remove
     468 */
     469void NetworkGameManager::doRemoveEntity( int uniqueID )
     470{
     471  SynchronizeableList::const_iterator it,e;
     472  it = this->networkStream->getSyncBegin();
     473  e = this->networkStream->getSyncEnd();
     474
     475  while ( it != e )
     476  {
     477    if ( (*it)->getUniqueID() == uniqueID )
     478    {
     479      delete *it;
     480      break;
     481    }
     482    it++;
     483  }
     484}
     485
     486/**
     487 * Tell the synchronizeable that a user's synchronizeable is out of sync
     488 * @param uniqueID: unique ID assigned with the entity which is out of sync
     489 * @param userID: user ID who's synchronizeable is out of sync
     490 */
     491void NetworkGameManager::doRequestSync( int uniqueID, int userID )
     492{
     493  SynchronizeableList::const_iterator it,e;
     494  it = this->networkStream->getSyncBegin();
     495  e = this->networkStream->getSyncEnd();
     496
     497  while ( it != e )
     498  {
     499    if ( (*it)->getUniqueID() == uniqueID )
     500    {
     501      (*it)->requestSync( userID );
     502      break;
     503    }
     504    it++;
     505  }
     506}
     507
     508/**
     509 * Copies length bytes to the clientBuffer with error checking
     510 * @param clientBuffer: the clientBuffer to write to
     511 * @param data: buffer to the data
     512 * @param length: length of data
     513 * @return false on error true else
     514 */
     515bool NetworkGameManager::writeToClientBuffer( clientBuffer &cb, byte * data, int length )
     516{
     517  if ( length > cb.maxLength-cb.length )
     518  {
     519    PRINTF(1)("No space left in clientBuffer\n");
     520    return false;
     521  }
     522
     523  memcpy( cb.buffer+cb.length, data, length );
     524  return true;
     525}
     526
     527/**
     528 * Reads data from clientBuffer with error checking
     529 * @param clientBuffer: the clientBuffer to read from
     530 * @param data: pointer to the buffer
     531 * @param length:
     532 * @return
     533 */
     534bool NetworkGameManager::readFromClientBuffer( clientBuffer &cb, byte * data, int length )
     535{
     536  if ( cb.length < length )
     537  {
     538    PRINTF(0)("There is not enough data in clientBuffer\n");
     539    return 0;
     540  }
     541
     542  memcpy( data, cb.buffer+cb.length-length, length );
     543  return true;
     544}
     545
     546/**
     547 * Tells this client that he has to control this entity
     548 * @param uniqueID: the entity's uniqeID
     549 */
     550void NetworkGameManager::doYouAre( int uniqueID )
     551{
     552  //TODO: what has to be done
     553}
     554
     555/**
     556 * Tells a remote client that he has to control this entity
     557 * @param uniqueID: the entity's uniqeID
     558 * @param userID: the users ID
     559 */
     560void NetworkGameManager::sendYouAre( int uniqueID, int userID )
     561{
     562  if ( !isServer() )
     563    return;
     564
     565  if ( userID != 0 )
     566  {
     567    if ( !writeToClientBuffer( outBuffer[userID], (byte)YOU_ARE_ENTITY ) )
     568      return;
     569
     570    if ( !writeToClientBuffer( outBuffer[userID], uniqueID ) )
     571      return;
     572  }
     573  else
     574  {
     575    doYouAre(uniqueID);
     576  }
     577}
     578
     579bool NetworkGameManager::handleRequestCreate( int & i, const byte * data, int length, int sender )
     580{
     581  if ( INTSIZE > length-i )
     582  {
     583    PRINTF(1)("Cannot read classID from buffer! Not enough data left!\n");
     584    return false;
     585  }
     586  int classID;
     587  i += Converter::byteArrayToInt( &data[i], &classID );
     588
     589  createEntity( (ClassID)classID );
     590
     591  return true;
     592}
     593
     594bool NetworkGameManager::handleRequestRemove( int & i, const byte * data, int length, int sender )
     595{
     596  if ( INTSIZE > length-i )
     597  {
     598    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
     599    return false;
     600  }
     601  int uniqueID;
     602  i += Converter::byteArrayToInt( &data[i], &uniqueID );
     603
     604  removeEntity( uniqueID );
     605
     606  return true;
     607}
     608
     609bool NetworkGameManager::handleCreateEntity( int & i, const byte * data, int length, int sender )
     610{
     611  if ( INTSIZE > length-i )
     612  {
     613    PRINTF(1)("Cannot read classID from buffer! Not enough data left!\n");
     614    return false;
     615  }
     616  int classID;
     617  i += Converter::byteArrayToInt( &data[i], &classID );
     618
     619  if ( INTSIZE > length-i )
     620  {
     621    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
     622    return false;
     623  }
     624  int uniqueID;
     625  i += Converter::byteArrayToInt( &data[i], &uniqueID );
     626
     627  if ( INTSIZE > length-i )
     628  {
     629    PRINTF(1)("Cannot read owner from buffer! Not enough data left!\n");
     630    return false;
     631  }
     632  int owner;
     633  i += Converter::byteArrayToInt( &data[i], &owner );
     634
     635  doCreateEntity( (ClassID)classID, uniqueID, owner );
     636
     637  return true;
     638}
     639
     640bool NetworkGameManager::handleRemoveEntity( int & i, const byte * data, int length, int sender )
     641{
     642  if ( INTSIZE > length-i )
     643  {
     644    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
     645    return false;
     646  }
     647  int uniqueID;
     648  i += Converter::byteArrayToInt( &data[i], &uniqueID );
     649
     650  doRemoveEntity( uniqueID );
     651
     652  return true;
     653}
     654
     655bool NetworkGameManager::handleCreateEntityList( int & i, const byte * data, int length, int sender )
     656{
     657  if ( INTSIZE > length-i )
     658  {
     659    PRINTF(1)("Cannot read n from buffer! Not enough data left!\n");
     660    return false;
     661  }
     662
     663  PRINTF(0)("HandleCreateEntityList:  data[i..i+3] = %d %d %d %d\n", data[i], data[i+1], data[i+2], data[i+3]);
     664
     665  int n;
     666  i += Converter::byteArrayToInt( &data[i], &n );
     667
     668
     669  PRINTF(0)("HandleCreateEntityList: n = %d\n", n);
     670
     671  int classID, uniqueID, owner;
     672
     673  for ( int j = 0; j<n; j++ )
     674  {
     675
     676    if ( INTSIZE > length-i )
     677    {
     678      PRINTF(1)("Cannot read classID from buffer! Not enough data left!\n");
     679      return false;
     680    }
     681    i += Converter::byteArrayToInt( &data[i], &classID );
     682
     683    if ( INTSIZE > length-i )
     684    {
     685      PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
     686      return false;
     687    }
     688    i += Converter::byteArrayToInt( &data[i], &uniqueID );
     689
     690    if ( INTSIZE > length-i )
     691    {
     692      PRINTF(1)("Cannot read owner from buffer! Not enough data left!\n");
     693      return false;
     694    }
     695    i += Converter::byteArrayToInt( &data[i], &owner );
     696
     697    if ( classID != CL_NETWORK_GAME_MANAGER && classID != CL_HANDSHAKE )
     698      doCreateEntity( (ClassID)classID, uniqueID, owner );
     699
     700  }
     701  return true;
     702}
     703
     704bool NetworkGameManager::handleRemoveEntityList( int & i, const byte * data, int length, int sender )
     705{
     706  if ( INTSIZE > length-i )
     707  {
     708    PRINTF(1)("Cannot read n from buffer! Not enough data left!\n");
     709    return false;
     710  }
     711  int n;
     712  i += Converter::byteArrayToInt( &data[i], &n );
     713
     714  int uniqueID;
     715
     716  for ( int j = 0; j<n; j++ )
     717  {
     718
     719    if ( INTSIZE > length-i )
     720    {
     721      PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
     722      return false;
     723    }
     724    i += Converter::byteArrayToInt( &data[i], &uniqueID );
     725
     726    doRemoveEntity( uniqueID );
     727  }
     728
     729  return true;
     730}
     731
     732bool NetworkGameManager::handleYouAreEntity( int & i, const byte * data, int length, int sender )
     733{
     734  if ( INTSIZE > length-i )
     735  {
     736    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
     737    return false;
     738  }
     739
     740  int uniqueID;
     741  i += Converter::byteArrayToInt( &data[i], &uniqueID );
     742
     743  doYouAre( uniqueID );
     744
     745  return true;
     746}
     747
     748bool NetworkGameManager::handleRequestSync( int & i, const byte * data, int length, int sender )
     749{
     750  if ( INTSIZE > length-i )
     751  {
     752    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
     753    return false;
     754  }
     755  int uniqueID;
     756  i += Converter::byteArrayToInt( &data[i], &uniqueID );
     757
     758  doRequestSync( uniqueID, sender );
     759
     760  return true;
     761}
     762
     763bool NetworkGameManager::writeToClientBuffer( clientBuffer & cb, byte b )
     764{
     765  if ( cb.maxLength-cb.length < 1 )
     766  {
     767    PRINTF(1)("Cannot write to clientBuffer! Not enough space for 1 byte\n");
     768    return false;
     769  }
     770
     771  cb.buffer[cb.length++] = b;
     772
     773  return true;
     774}
     775
     776bool NetworkGameManager::writeToClientBuffer( clientBuffer & cb, int i )
     777{
     778  int n = Converter::intToByteArray( i, cb.buffer+cb.length, cb.maxLength-cb.length );
     779  cb.length += n;
     780
     781  if ( n <= 0 )
     782  {
     783    PRINTF(1)("Cannot write to clientBuffer! Not enough space for 1 int\n");
     784    return false;
     785  }
     786
     787  return true;
     788}
     789
     790void NetworkGameManager::sync( int uniqueID, int owner )
     791{
     792  if ( owner==this->getHostID() )
     793    return;
     794
     795  if ( !isServer() )
     796    executeRequestSync( uniqueID, 0 );
     797  else
     798    executeRequestSync( uniqueID, owner );
     799}
     800
     801void NetworkGameManager::executeRequestSync( int uniqueID, int user )
     802{
     803  if ( user >= outBuffer.size() )
     804    resizeBufferVector( user );
     805
     806  if ( !writeToClientBuffer( outBuffer[user], (byte)REQUEST_SYNC ) )
     807    return;
     808  if ( !writeToClientBuffer( outBuffer[user], uniqueID ) )
     809    return;
     810}
     811
Note: See TracChangeset for help on using the changeset viewer.