Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/network/src/lib/network/network_game_manager.cc @ 6256

Last change on this file since 6256 was 6256, checked in by rennerc, 18 years ago

network_socket: can now send more than 255 bytes
network_game_manager: fixed some bugs

File size: 17.2 KB
RevLine 
[6067]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
11### File Specific:
12   main-programmer: Benjamin Wuest
13   co-programmer: ...
14*/
15
16
17/* this is for debug output. It just says, that all calls to PRINT() belong to the DEBUG_MODULE_NETWORK module
18   For more information refere to https://www.orxonox.net/cgi-bin/trac.cgi/wiki/DebugOutput
19*/
20#define DEBUG_MODULE_NETWORK
21
[6190]22#include "factory.h"
23#include "network_stream.h"
[6214]24#include "converter.h"
[6190]25
[6067]26/* include your own header */
[6116]27#include "network_game_manager.h"
[6067]28
29
30/* using namespace std is default, this needs to be here */
31using namespace std;
32
[6238]33NetworkGameManager* NetworkGameManager::singletonRef = NULL;
[6230]34
[6067]35/*!
36 * Standard constructor
37 */
[6116]38NetworkGameManager::NetworkGameManager()
[6067]39{
[6250]40  PRINTF(0)("START\n");
41
[6067]42  /* set the class id for the base object */
43  this->setClassID(CL_ENTITY_MANAGER, "EntityManager");
[6214]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;
[6067]52}
53
54/*!
55 * Standard destructor
56 */
[6116]57NetworkGameManager::~NetworkGameManager()
[6067]58{
[6214]59  for ( int i = 0; i<outBuffer.size(); i++)
[6190]60  {
61    if ( outBuffer[i].buffer )
62      delete outBuffer[i].buffer;
63  }
[6214]64
65  if ( allOutBuffer.buffer )
66    delete allOutBuffer.buffer;
[6067]67}
68
69
[6190]70void NetworkGameManager::writeBytes(const byte* data, int length, int sender)
[6067]71{
[6214]72  int i = 0;
73  byte b;
74
[6256]75  while ( i<length-1 )
[6214]76  {
77    b = data[i++];
78
[6256]79    PRINTF(0)("WriteBytes: b = %d\n", b);
80
[6219]81    if ( isServer() )
[6214]82    {
[6219]83      if ( b == REQUEST_CREATE )
84      {
85        if ( !handleRequestCreate( i, data, length, sender ) )
86          return;
87        continue;
88      }
89      if ( b == REQUEST_REMOVE )
90      {
91        if ( !handleRequestRemove( i, data, length, sender ) )
92          return;
93        continue;
94      }
[6214]95    }
[6256]96    else
[6214]97    {
[6219]98      if ( b == CREATE_ENTITY )
99      {
100        if ( !handleCreateEntity( i, data, length, sender ) )
101          return;
102        continue;
103      }
104      if ( b == REMOVE_ENTITY )
105      {
106        if ( !handleRemoveEntity( i, data, length, sender ) )
107          return;
108        continue;
109      }
110      if ( b == CREATE_ENTITY_LIST )
111      {
112        if ( !handleCreateEntityList( i, data, length, sender ) )
113          return;
114        continue;
115      }
116      if ( b == REMOVE_ENTITY_LIST )
117      {
118        if ( !handleRemoveEntityList( i, data, length, sender ) )
119          return;
120        continue;
121      }
122      if ( b == YOU_ARE_ENTITY )
123      {
124        if ( !handleYouAreEntity( i, data, length, sender ) )
125          return;
126        continue;
127      }
[6214]128    }
[6219]129
[6214]130    if ( b == REQUEST_SYNC )
131    {
[6219]132      if ( !handleRequestSync( i, data, length, sender ) )
133        return;
134      continue;
[6214]135    }
[6219]136
137    //if we get her something with data is wrong
138    PRINTF(1)("Data is not in the right format! i=%d\n", i);
139    return;
[6214]140  }
[6067]141}
142
[6116]143int NetworkGameManager::readBytes(byte* data, int maxLength, int * reciever)
[6067]144{
[6214]145  for ( int i = 0; i<outBuffer.size(); i++ )
146  {
147    if ( outBuffer[i].length>0 )
148    {
149      int nbytes = outBuffer[i].length;
150
151      if ( nbytes > maxLength )
152      {
153        PRINTF(1)("OutBuffer.length (%d) > (%d) networkStreamBuffer.maxLength\n", nbytes, maxLength);
154        return 0;
155      }
156
157      memcpy(data, outBuffer[i].buffer, nbytes);
158      return nbytes;
159    }
160  }
161
162  int nbytes = allOutBuffer.length;
163
164  if ( nbytes <=0 )
165    return 0;
166
167  if ( nbytes > maxLength )
168  {
169    PRINTF(1)("OutBuffer.length (%d) > (%d) networkStreamBuffer.length\n", nbytes, maxLength);
170    return 0;
171  }
172
173  memcpy( data, allOutBuffer.buffer, nbytes );
174  return nbytes;
[6067]175}
176
[6116]177void NetworkGameManager::writeDebug() const
[6067]178{
179}
180
[6116]181void NetworkGameManager::readDebug() const
[6067]182{
183}
184
185
186/*!
187 * Checks whether this is connected to a server or a client
[6214]188 * and afterwards creates the needed entity
[6067]189 * @param classID: The ID of the class of which an entity should be created
190 */
[6219]191void NetworkGameManager::createEntity( ClassID classID, int owner )
[6067]192{
[6214]193  if ( this->isServer() )
194  {
195    if ( newUniqueID < 0 )
196    {
197      PRINTF(1)("Cannot create entity! There are no more uniqueIDs left!\n");
198      return;
199    }
200
[6219]201    this->executeCreateEntity( classID, newUniqueID++, owner );
[6214]202  }
203  else
204  {
[6219]205    this->requestCreateEntity( classID );
[6214]206  }
[6067]207}
208
[6250]209
[6067]210/*!
211 * Checks whether this is connected to a server or a client
[6250]212 * and afterwards creates the needed entity
213 * @param classID: The ID of the class of which an entity should be created
214 */
215BaseObject* NetworkGameManager::createEntity( TiXmlElement* element)
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 NULL;
223    }
224    newUniqueID++;
225
226    BaseObject * b = Factory::fabricate( element );
227
228    if ( !b )
229    {
230      PRINTF(1)("Could not fabricate Object with classID %x\n", element->Value() );
231      return NULL;
232    }
233
234    if ( b->isA(CL_SYNCHRONIZEABLE) )
235    {
236      Synchronizeable * s = dynamic_cast<Synchronizeable*>(b);
237      s->setUniqueID( newUniqueID );
238      s->setOwner( 0 );
239      this->networkStream->connectSynchronizeable( *s );
240      return b;
241    }
242    else
243    {
244      PRINTF(1)("Class %s is not a synchronizeable!\n", b->getClassName() );
245      delete b;
246    }
247  }
248  else
249  {
250    PRINTF(1)("This node is not a server and cannot create id %x\n", element->Value());
251  }
252  return NULL;
253}
254
255
256/*!
257 * Checks whether this is connected to a server or a client
[6067]258 * and afterwards removes the specified entity
259 * @param uniqueID: The ID of the entity object which should be removed
260 */
[6116]261void NetworkGameManager::removeEntity(int uniqueID)
[6067]262{
[6214]263  if ( this->isServer() )
264  {
265    this->executeRemoveEntity( uniqueID );
266  }
267  else
268  {
269    this->requestRemoveEntity( uniqueID );
270  }
[6067]271}
272
273
274
275/*!
276 * Creates the needed entity on the server if possible
277 * @param classID: The ID of the class of which an entity should be created
278 */
[6214]279void NetworkGameManager::requestCreateEntity(ClassID classID)
[6067]280{
[6231]281  if ( !writeToClientBuffer( allOutBuffer, (byte)REQUEST_CREATE ) )
[6214]282    return;
[6231]283  if ( !writeToClientBuffer( allOutBuffer, (int)classID ) )
[6214]284    return;
[6067]285}
286
287/*!
288 * Removes the specified entity on the server
289 * @param uniqueID: The ID of the entity object which should be removed
290 */
[6116]291void NetworkGameManager::requestRemoveEntity(int uniqueID)
[6067]292{
[6231]293  if ( !writeToClientBuffer( allOutBuffer, (byte)REQUEST_REMOVE ) )
[6214]294    return;
[6231]295  if ( !writeToClientBuffer( allOutBuffer, uniqueID ) )
[6214]296    return;
[6067]297}
298
299/*!
300 * Creates the needed entity if possible
301 * This function is called if this is a server
302 * @param classID: The ID of the class of which an entity should be created
303 */
[6214]304void NetworkGameManager::executeCreateEntity(ClassID classID, int uniqueID, int owner)
[6067]305{
[6231]306  if ( !writeToClientBuffer( allOutBuffer, (byte)CREATE_ENTITY ) )
[6214]307    return;
[6231]308  if ( !writeToClientBuffer( allOutBuffer, (int)classID ) )
[6214]309    return;
[6231]310  if ( !writeToClientBuffer( allOutBuffer, uniqueID ) )
[6214]311    return;
[6231]312  if ( !writeToClientBuffer( allOutBuffer, owner ) )
[6214]313    return;
314
315  doCreateEntity( classID, uniqueID, owner );
[6067]316}
317
318/*!
319 * Removes the specified entity
320 * This function is called if this is a server
321 * @param uniqueID: The ID of the entity object which should be removed
322 */
[6116]323void NetworkGameManager::executeRemoveEntity(int uniqueID)
[6067]324{
[6231]325  if ( !writeToClientBuffer( allOutBuffer, (byte)REMOVE_ENTITY ) )
[6214]326    return;
[6231]327  if ( !writeToClientBuffer( allOutBuffer, uniqueID ) )
[6214]328    return;
329
330  doRemoveEntity(uniqueID);
[6067]331}
332
333/*!
334 * Checks whether it is possible to create an entity of a given class
335 * @return: true if the entity can be created, false otherwise
336 */
[6214]337bool NetworkGameManager::canCreateEntity(ClassID classID)
[6067]338{
[6190]339  return true;
[6067]340}
[6190]341
342/*!
343 * Sends the Entities to the new connected client
344 * @param userID: The ID of the user
345 */
346void NetworkGameManager::sendEntityList( int userID )
347{
[6214]348  if ( !isServer() )
349    return;
350
351  if ( userID > outBuffer.size() )
352    resizeBufferVector( userID );
353
354  SynchronizeableList::const_iterator it, e;
355
356  it = this->networkStream->getSyncBegin();
357  e = this->networkStream->getSyncEnd();
358
[6231]359  if ( !writeToClientBuffer( outBuffer[userID], (byte)CREATE_ENTITY_LIST ) )
[6214]360    return;
361
[6231]362  if ( !writeToClientBuffer( outBuffer[userID], networkStream->getSyncCount() ) )
[6214]363    return;
364
[6256]365  PRINTF(0)("SendEntityList: n = %d\n", networkStream->getSyncCount());
366
[6214]367  while ( it != e )
368  {
[6231]369    if ( !writeToClientBuffer( outBuffer[userID], (*it)->getClassID() ) )
[6214]370      return;
371
[6256]372    PRINTF(0)("SendEntityList: ClassID = %x\n", (*it)->getClassID());
373
[6231]374    if ( !writeToClientBuffer( outBuffer[userID], (*it)->getUniqueID() ) )
[6214]375      return;
376
[6231]377    if ( !writeToClientBuffer( outBuffer[userID], (*it)->getOwner() ) )
[6214]378      return;
379
380    it++;
381  }
[6190]382}
383
384/**
385 * Creates a buffer for user n
386 * @param n The ID of the user
387 */
388void NetworkGameManager::resizeBufferVector( int n )
389{
[6214]390  for ( int i = outBuffer.size(); i<=n; i++)
[6190]391  {
392    clientBuffer outBuf;
393
394    outBuf.length = 0;
395
396    outBuf.maxLength = 5*1024;
397
398    outBuf.buffer = new byte[5*1014];
399
400    outBuffer.push_back(outBuf);
401  }
402}
403
404/**
405 * Creates the entity on this host
406 * @param classID: ClassID of the entity to create
407 * @param uniqueID: Unique ID to assign to the synchronizeable
408 * @param owner: owner of this synchronizealbe
409 */
410void NetworkGameManager::doCreateEntity( ClassID classID, int uniqueID, int owner )
411{
[6214]412  BaseObject * b = Factory::fabricate( classID );
[6190]413
[6214]414  if ( !b )
415  {
[6256]416    PRINTF(1)("Could not fabricate Object with classID %x\n", classID);
[6214]417    return;
418  }
[6256]419  else
420  {
421    PRINTF(0)("Fabricated entity: %s\n", b->getClassName());
422  }
[6214]423
[6190]424  if ( b->isA(CL_SYNCHRONIZEABLE) )
425  {
426    Synchronizeable * s = dynamic_cast<Synchronizeable*>(b);
427    s->setUniqueID( uniqueID );
428    s->setOwner( owner );
429    this->networkStream->connectSynchronizeable( *s );
430  }
431  else
432  {
[6256]433    PRINTF(1)("Class with ID %x is not a synchronizeable!", (int)classID);
[6190]434    delete b;
435  }
436}
437
438/**
439 * Removes a entity on this host
440 * @param uniqueID: unique ID assigned with the entity to remove
441 */
442void NetworkGameManager::doRemoveEntity( int uniqueID )
443{
444  SynchronizeableList::const_iterator it,e;
445  it = this->networkStream->getSyncBegin();
446  e = this->networkStream->getSyncEnd();
447
448  while ( it != e )
449  {
450    if ( (*it)->getUniqueID() == uniqueID )
451    {
452      delete *it;
453      break;
454    }
[6214]455    it++;
[6190]456  }
457}
458
459/**
460 * Tell the synchronizeable that a user's synchronizeable is out of sync
461 * @param uniqueID: unique ID assigned with the entity which is out of sync
462 * @param userID: user ID who's synchronizeable is out of sync
463 */
464void NetworkGameManager::doRequestSync( int uniqueID, int userID )
465{
466  SynchronizeableList::const_iterator it,e;
467  it = this->networkStream->getSyncBegin();
468  e = this->networkStream->getSyncEnd();
469
470  while ( it != e )
471  {
472    if ( (*it)->getUniqueID() == uniqueID )
473    {
474      (*it)->requestSync( userID );
475      break;
476    }
[6214]477    it++;
[6190]478  }
479}
[6214]480
481/**
482 * Copies length bytes to the clientBuffer with error checking
483 * @param clientBuffer: the clientBuffer to write to
484 * @param data: buffer to the data
485 * @param length: length of data
486 * @return false on error true else
487 */
488bool NetworkGameManager::writeToClientBuffer( clientBuffer &cb, byte * data, int length )
489{
490  if ( length > cb.maxLength-cb.length )
491  {
492    PRINTF(1)("No space left in clientBuffer\n");
493    return false;
494  }
495
496  memcpy( cb.buffer+cb.length, data, length );
497  return true;
498}
499
500/**
501 * Reads data from clientBuffer with error checking
502 * @param clientBuffer: the clientBuffer to read from
503 * @param data: pointer to the buffer
504 * @param length:
505 * @return
506 */
507bool NetworkGameManager::readFromClientBuffer( clientBuffer &cb, byte * data, int length )
508{
509  if ( cb.length < length )
510  {
511    PRINTF(0)("There is not enough data in clientBuffer\n");
512    return 0;
513  }
514
515  memcpy( data, cb.buffer+cb.length-length, length );
516  return true;
517}
518
519/**
520 * Tells this client that he has to control this entity
521 * @param uniqueID: the entity's uniqeID
522 */
523void NetworkGameManager::doYouAre( int uniqueID )
524{
525  //TODO: what has to be done
526}
527
528/**
529 * Tells a remote client that he has to control this entity
530 * @param uniqueID: the entity's uniqeID
531 * @param userID: the users ID
532 */
533void NetworkGameManager::sendYouAre( int uniqueID, int userID )
534{
535  if ( !isServer() )
536    return;
537
538  if ( userID != 0 )
539  {
[6231]540    if ( !writeToClientBuffer( outBuffer[userID], (byte)YOU_ARE_ENTITY ) )
[6214]541      return;
542
[6231]543    if ( !writeToClientBuffer( outBuffer[userID], uniqueID ) )
[6214]544      return;
545  }
546  else
547  {
548    doYouAre(uniqueID);
549  }
550}
551
[6219]552bool NetworkGameManager::handleRequestCreate( int & i, const byte * data, int length, int sender )
553{
554  if ( INTSIZE > length-i )
555  {
556    PRINTF(1)("Cannot read classID from buffer! Not enough data left!\n");
557    return false;
558  }
[6231]559  int classID;
[6256]560  i += Converter::byteArrayToInt( &data[i], &classID );
[6219]561
562  createEntity( (ClassID)classID );
563
564  return true;
565}
566
567bool NetworkGameManager::handleRequestRemove( int & i, const byte * data, int length, int sender )
568{
569  if ( INTSIZE > length-i )
570  {
571    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
572    return false;
573  }
[6231]574  int uniqueID;
[6256]575  i += Converter::byteArrayToInt( &data[i], &uniqueID );
[6219]576
577  removeEntity( uniqueID );
578
579  return true;
580}
581
582bool NetworkGameManager::handleCreateEntity( int & i, const byte * data, int length, int sender )
583{
584  if ( INTSIZE > length-i )
585  {
586    PRINTF(1)("Cannot read classID from buffer! Not enough data left!\n");
587    return false;
588  }
[6231]589  int classID;
[6256]590  i += Converter::byteArrayToInt( &data[i], &classID );
[6219]591
592  if ( INTSIZE > length-i )
593  {
594    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
595    return false;
596  }
[6231]597  int uniqueID;
[6256]598  i += Converter::byteArrayToInt( &data[i], &uniqueID );
[6219]599
600  if ( INTSIZE > length-i )
601  {
602    PRINTF(1)("Cannot read owner from buffer! Not enough data left!\n");
603    return false;
604  }
[6231]605  int owner;
[6256]606  i += Converter::byteArrayToInt( &data[i], &owner );
[6219]607
608  doCreateEntity( (ClassID)classID, uniqueID, owner );
609
610  return true;
611}
612
613bool NetworkGameManager::handleRemoveEntity( int & i, const byte * data, int length, int sender )
614{
615  if ( INTSIZE > length-i )
616  {
617    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
618    return false;
619  }
[6231]620  int uniqueID;
[6256]621  i += Converter::byteArrayToInt( &data[i], &uniqueID );
[6219]622
623  doRemoveEntity( uniqueID );
624
625  return true;
626}
627
628bool NetworkGameManager::handleCreateEntityList( int & i, const byte * data, int length, int sender )
629{
630  if ( INTSIZE > length-i )
631  {
632    PRINTF(1)("Cannot read n from buffer! Not enough data left!\n");
633    return false;
634  }
[6256]635
636  PRINTF(0)("HandleCreateEntityList:  data[i..i+3] = %d %d %d %d\n", data[i], data[i+1], data[i+2], data[i+3]);
637
[6231]638  int n;
[6256]639  i += Converter::byteArrayToInt( &data[i], &n );
[6219]640
[6256]641
642  PRINTF(0)("HandleCreateEntityList: n = %d\n", n);
643
[6219]644  int classID, uniqueID, owner;
645
646  for ( int j = 0; j<n; j++ )
647  {
648
649    if ( INTSIZE > length-i )
650    {
651      PRINTF(1)("Cannot read classID from buffer! Not enough data left!\n");
652      return false;
653    }
[6256]654    i += Converter::byteArrayToInt( &data[i], &classID );
[6219]655
656    if ( INTSIZE > length-i )
657    {
658      PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
659      return false;
660    }
[6256]661    i += Converter::byteArrayToInt( &data[i], &uniqueID );
[6219]662
663    if ( INTSIZE > length-i )
664    {
665      PRINTF(1)("Cannot read owner from buffer! Not enough data left!\n");
666      return false;
667    }
[6256]668    i += Converter::byteArrayToInt( &data[i], &owner );
[6219]669
670    doCreateEntity( (ClassID)classID, uniqueID, owner );
671
672  }
673  return true;
674}
675
676bool NetworkGameManager::handleRemoveEntityList( int & i, const byte * data, int length, int sender )
677{
678  if ( INTSIZE > length-i )
679  {
680    PRINTF(1)("Cannot read n from buffer! Not enough data left!\n");
681    return false;
682  }
[6231]683  int n;
[6256]684  i += Converter::byteArrayToInt( &data[i], &n );
[6219]685
686  int uniqueID;
687
688  for ( int j = 0; j<n; j++ )
689  {
690
691    if ( INTSIZE > length-i )
692    {
693      PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
694      return false;
695    }
[6256]696    i += Converter::byteArrayToInt( &data[i], &uniqueID );
[6219]697
698    doRemoveEntity( uniqueID );
699  }
700
701  return true;
702}
703
704bool NetworkGameManager::handleYouAreEntity( int & i, const byte * data, int length, int sender )
705{
706  if ( INTSIZE > length-i )
707  {
708    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
709    return false;
710  }
711
[6231]712  int uniqueID;
[6256]713  i += Converter::byteArrayToInt( &data[i], &uniqueID );
[6231]714
[6219]715  doYouAre( uniqueID );
716
717  return true;
718}
719
720bool NetworkGameManager::handleRequestSync( int & i, const byte * data, int length, int sender )
721{
722  if ( INTSIZE > length-i )
723  {
724    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
725    return false;
726  }
[6231]727  int uniqueID;
[6256]728  i += Converter::byteArrayToInt( &data[i], &uniqueID );
[6219]729
730  doRequestSync( uniqueID, sender );
731
732  return true;
733}
734
[6231]735bool NetworkGameManager::writeToClientBuffer( clientBuffer & cb, byte b )
736{
737  if ( cb.maxLength-cb.length < 1 )
738  {
739    PRINTF(1)("Cannot write to clientBuffer! Not enough space for 1 byte\n");
740    return false;
741  }
742
743  cb.buffer[cb.length++] = b;
744
745  return true;
746}
747
748bool NetworkGameManager::writeToClientBuffer( clientBuffer & cb, int i )
749{
[6256]750  int n = Converter::intToByteArray( i, cb.buffer+cb.length, cb.maxLength-cb.length );
[6231]751  cb.length += n;
752
753  if ( n <= 0 )
754  {
755    PRINTF(1)("Cannot write to clientBuffer! Not enough space for 1 int\n");
756    return false;
757  }
758
759  return true;
760}
761
Note: See TracBrowser for help on using the repository browser.