Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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