Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

synchronizeable: added macros to help write/read data

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