Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 6326 was 6326, checked in by rennerc, 18 years ago
File size: 18.5 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    PRINTF(0)("the world is enough! id=%d\n", this->getUniqueID());
161    return SYNCHELP_WRITE_N;
162  }
163  for ( int i = 0; i<outBuffer.size(); i++ )
164  {
165    *reciever = i;
166    if ( outBuffer[i].length>0 )
167    {
168      int nbytes = outBuffer[i].length;
169      outBuffer[i].length = 0;
170
171      if ( nbytes > maxLength )
172      {
173        PRINTF(1)("OutBuffer.length (%d) > (%d) networkStreamBuffer.maxLength\n", nbytes, maxLength);
174        return 0;
175      }
176
177      memcpy(data, outBuffer[i].buffer, nbytes);
178      return nbytes;
179    }
180  }
181
182  *reciever = 0;
183  int nbytes = allOutBuffer.length;
184  allOutBuffer.length = 0;
185
186  if ( nbytes <=0 )
187    return 0;
188
189  if ( nbytes > maxLength )
190  {
191    PRINTF(1)("OutBuffer.length (%d) > (%d) networkStreamBuffer.length\n", nbytes, maxLength);
192    return 0;
193  }
194
195  memcpy( data, allOutBuffer.buffer, nbytes );
196  return nbytes;
197}
198
199void NetworkGameManager::writeDebug() const
200{
201}
202
203void NetworkGameManager::readDebug() const
204{
205}
206
207
208/*!
209 * Checks whether this is connected to a server or a client
210 * and afterwards creates the needed entity
211 * @param classID: The ID of the class of which an entity should be created
212 */
213void NetworkGameManager::createEntity( ClassID classID, int owner )
214{
215  if ( this->isServer() )
216  {
217    if ( newUniqueID < 0 )
218    {
219      PRINTF(1)("Cannot create entity! There are no more uniqueIDs left!\n");
220      return;
221    }
222
223    this->executeCreateEntity( classID, newUniqueID++, owner );
224  }
225  else
226  {
227    this->requestCreateEntity( classID );
228  }
229}
230
231
232/*!
233 * Checks whether this is connected to a server or a client
234 * and afterwards creates the needed entity
235 * @param classID: The ID of the class of which an entity should be created
236 */
237BaseObject* NetworkGameManager::createEntity( TiXmlElement* element)
238{
239  if ( this->isServer() )
240  {
241    if ( newUniqueID < 0 )
242    {
243      PRINTF(1)("Cannot create entity! There are no more uniqueIDs left!\n");
244      return NULL;
245    }
246    newUniqueID++;
247
248    BaseObject * b = Factory::fabricate( element );
249
250    if ( !b )
251    {
252      PRINTF(1)("Could not fabricate Object with classID %x\n", element->Value() );
253      return NULL;
254    }
255
256
257    if ( b->isA(CL_SYNCHRONIZEABLE) )
258    {
259      Synchronizeable * s = dynamic_cast<Synchronizeable*>(b);
260      s->setUniqueID( newUniqueID );
261      s->setOwner( 0 );
262      this->networkStream->connectSynchronizeable( *s );
263      return b;
264    }
265    else
266    {
267      PRINTF(1)("Class %s is not a synchronizeable!\n", b->getClassName() );
268      delete b;
269    }
270  }
271  else
272  {
273    PRINTF(1)("This node is not a server and cannot create id %x\n", element->Value());
274  }
275  return NULL;
276}
277
278
279/*!
280 * Checks whether this is connected to a server or a client
281 * and afterwards removes the specified entity
282 * @param uniqueID: The ID of the entity object which should be removed
283 */
284void NetworkGameManager::removeEntity(int uniqueID)
285{
286  if ( this->isServer() )
287  {
288    this->executeRemoveEntity( uniqueID );
289  }
290  else
291  {
292    this->requestRemoveEntity( uniqueID );
293  }
294}
295
296
297
298/*!
299 * Creates the needed entity on the server if possible
300 * @param classID: The ID of the class of which an entity should be created
301 */
302void NetworkGameManager::requestCreateEntity(ClassID classID)
303{
304  if ( !writeToClientBuffer( allOutBuffer, (byte)REQUEST_CREATE ) )
305    return;
306  if ( !writeToClientBuffer( allOutBuffer, (int)classID ) )
307    return;
308}
309
310/*!
311 * Removes the specified entity on the server
312 * @param uniqueID: The ID of the entity object which should be removed
313 */
314void NetworkGameManager::requestRemoveEntity(int uniqueID)
315{
316  if ( !writeToClientBuffer( allOutBuffer, (byte)REQUEST_REMOVE ) )
317    return;
318  if ( !writeToClientBuffer( allOutBuffer, uniqueID ) )
319    return;
320}
321
322/*!
323 * Creates the needed entity if possible
324 * This function is called if this is a server
325 * @param classID: The ID of the class of which an entity should be created
326 */
327void NetworkGameManager::executeCreateEntity(ClassID classID, int uniqueID, int owner)
328{
329  if ( !writeToClientBuffer( allOutBuffer, (byte)CREATE_ENTITY ) )
330    return;
331  if ( !writeToClientBuffer( allOutBuffer, (int)classID ) )
332    return;
333  if ( !writeToClientBuffer( allOutBuffer, uniqueID ) )
334    return;
335  if ( !writeToClientBuffer( allOutBuffer, owner ) )
336    return;
337
338  doCreateEntity( classID, uniqueID, owner );
339}
340
341/*!
342 * Removes the specified entity
343 * This function is called if this is a server
344 * @param uniqueID: The ID of the entity object which should be removed
345 */
346void NetworkGameManager::executeRemoveEntity(int uniqueID)
347{
348  if ( !writeToClientBuffer( allOutBuffer, (byte)REMOVE_ENTITY ) )
349    return;
350  if ( !writeToClientBuffer( allOutBuffer, uniqueID ) )
351    return;
352
353  doRemoveEntity(uniqueID);
354}
355
356/*!
357 * Checks whether it is possible to create an entity of a given class
358 * @return: true if the entity can be created, false otherwise
359 */
360bool NetworkGameManager::canCreateEntity(ClassID classID)
361{
362  return true;
363}
364
365/*!
366 * Sends the Entities to the new connected client
367 * @param userID: The ID of the user
368 */
369void NetworkGameManager::sendEntityList( int userID )
370{
371  if ( !isServer() )
372    return;
373
374  if ( userID >= outBuffer.size() )
375    resizeBufferVector( userID );
376
377  SynchronizeableList::const_iterator it, e;
378
379  it = this->networkStream->getSyncBegin();
380  e = this->networkStream->getSyncEnd();
381
382  if ( !writeToClientBuffer( outBuffer[userID], (byte)CREATE_ENTITY_LIST ) )
383    return;
384
385  // -2 because you must not send network_game_manager and handshake
386  if ( !writeToClientBuffer( outBuffer[userID], networkStream->getSyncCount() ) )
387    return;
388
389  //PRINTF(0)("SendEntityList: n = %d\n", networkStream->getSyncCount()-2 );
390
391  while ( it != e )
392  {
393
394    if ( !writeToClientBuffer( outBuffer[userID], (int)((*it)->getLeafID()) ) )
395      return;
396      //PRINTF(0)("SendEntityList: ClassID = %x\n", (*it)->getRealClassID());
397
398    if ( !writeToClientBuffer( outBuffer[userID], (int)((*it)->getUniqueID()) ) )
399      return;
400
401    if ( !writeToClientBuffer( outBuffer[userID], (int)((*it)->getOwner()) ) )
402      return;
403
404    it++;
405  }
406
407
408}
409
410/**
411 * Creates a buffer for user n
412 * @param n The ID of the user
413 */
414void NetworkGameManager::resizeBufferVector( int n )
415{
416  for ( int i = outBuffer.size(); i<=n; i++)
417  {
418    clientBuffer outBuf;
419
420    outBuf.length = 0;
421
422    outBuf.maxLength = 5*1024;
423
424    outBuf.buffer = new byte[5*1014];
425
426    outBuffer.push_back(outBuf);
427  }
428}
429
430/**
431 * Creates the entity on this host
432 * @param classID: ClassID of the entity to create
433 * @param uniqueID: Unique ID to assign to the synchronizeable
434 * @param owner: owner of this synchronizealbe
435 */
436void NetworkGameManager::doCreateEntity( ClassID classID, int uniqueID, int owner )
437{
438  BaseObject * b = Factory::fabricate( classID );
439
440  if ( !b )
441  {
442    PRINTF(1)("Could not fabricate Object with classID %x\n", classID);
443    return;
444  }
445
446  if ( b->isA(CL_SYNCHRONIZEABLE) )
447  {
448    Synchronizeable * s = dynamic_cast<Synchronizeable*>(b);
449    s->setUniqueID( uniqueID );
450    s->setOwner( owner );
451    this->networkStream->connectSynchronizeable( *s );
452    if ( !isServer() )
453      s->setIsOutOfSync( true );
454    PRINTF(0)("Fabricated %s with id %d\n", s->getClassName(), s->getUniqueID());
455  }
456  else
457  {
458    PRINTF(1)("Class with ID %x is not a synchronizeable!", (int)classID);
459    delete b;
460  }
461}
462
463/**
464 * Removes a entity on this host
465 * @param uniqueID: unique ID assigned with the entity to remove
466 */
467void NetworkGameManager::doRemoveEntity( int uniqueID )
468{
469  SynchronizeableList::const_iterator it,e;
470  it = this->networkStream->getSyncBegin();
471  e = this->networkStream->getSyncEnd();
472
473  while ( it != e )
474  {
475    if ( (*it)->getUniqueID() == uniqueID )
476    {
477      delete *it;
478      break;
479    }
480    it++;
481  }
482}
483
484/**
485 * Tell the synchronizeable that a user's synchronizeable is out of sync
486 * @param uniqueID: unique ID assigned with the entity which is out of sync
487 * @param userID: user ID who's synchronizeable is out of sync
488 */
489void NetworkGameManager::doRequestSync( int uniqueID, int userID )
490{
491  SynchronizeableList::const_iterator it,e;
492  it = this->networkStream->getSyncBegin();
493  e = this->networkStream->getSyncEnd();
494
495  while ( it != e )
496  {
497    if ( (*it)->getUniqueID() == uniqueID )
498    {
499      (*it)->requestSync( userID );
500      break;
501    }
502    it++;
503  }
504}
505
506/**
507 * Copies length bytes to the clientBuffer with error checking
508 * @param clientBuffer: the clientBuffer to write to
509 * @param data: buffer to the data
510 * @param length: length of data
511 * @return false on error true else
512 */
513bool NetworkGameManager::writeToClientBuffer( clientBuffer &cb, byte * data, int length )
514{
515  if ( length > cb.maxLength-cb.length )
516  {
517    PRINTF(1)("No space left in clientBuffer\n");
518    return false;
519  }
520
521  memcpy( cb.buffer+cb.length, data, length );
522  return true;
523}
524
525/**
526 * Reads data from clientBuffer with error checking
527 * @param clientBuffer: the clientBuffer to read from
528 * @param data: pointer to the buffer
529 * @param length:
530 * @return
531 */
532bool NetworkGameManager::readFromClientBuffer( clientBuffer &cb, byte * data, int length )
533{
534  if ( cb.length < length )
535  {
536    PRINTF(0)("There is not enough data in clientBuffer\n");
537    return 0;
538  }
539
540  memcpy( data, cb.buffer+cb.length-length, length );
541  return true;
542}
543
544/**
545 * Tells this client that he has to control this entity
546 * @param uniqueID: the entity's uniqeID
547 */
548void NetworkGameManager::doYouAre( int uniqueID )
549{
550  //TODO: what has to be done
551}
552
553/**
554 * Tells a remote client that he has to control this entity
555 * @param uniqueID: the entity's uniqeID
556 * @param userID: the users ID
557 */
558void NetworkGameManager::sendYouAre( int uniqueID, int userID )
559{
560  if ( !isServer() )
561    return;
562
563  if ( userID != 0 )
564  {
565    if ( !writeToClientBuffer( outBuffer[userID], (byte)YOU_ARE_ENTITY ) )
566      return;
567
568    if ( !writeToClientBuffer( outBuffer[userID], uniqueID ) )
569      return;
570  }
571  else
572  {
573    doYouAre(uniqueID);
574  }
575}
576
577bool NetworkGameManager::handleRequestCreate( int & i, const byte * data, int length, int sender )
578{
579  if ( INTSIZE > length-i )
580  {
581    PRINTF(1)("Cannot read classID from buffer! Not enough data left!\n");
582    return false;
583  }
584  int classID;
585  i += Converter::byteArrayToInt( &data[i], &classID );
586
587  createEntity( (ClassID)classID );
588
589  return true;
590}
591
592bool NetworkGameManager::handleRequestRemove( int & i, const byte * data, int length, int sender )
593{
594  if ( INTSIZE > length-i )
595  {
596    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
597    return false;
598  }
599  int uniqueID;
600  i += Converter::byteArrayToInt( &data[i], &uniqueID );
601
602  removeEntity( uniqueID );
603
604  return true;
605}
606
607bool NetworkGameManager::handleCreateEntity( int & i, const byte * data, int length, int sender )
608{
609  if ( INTSIZE > length-i )
610  {
611    PRINTF(1)("Cannot read classID from buffer! Not enough data left!\n");
612    return false;
613  }
614  int classID;
615  i += Converter::byteArrayToInt( &data[i], &classID );
616
617  if ( INTSIZE > length-i )
618  {
619    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
620    return false;
621  }
622  int uniqueID;
623  i += Converter::byteArrayToInt( &data[i], &uniqueID );
624
625  if ( INTSIZE > length-i )
626  {
627    PRINTF(1)("Cannot read owner from buffer! Not enough data left!\n");
628    return false;
629  }
630  int owner;
631  i += Converter::byteArrayToInt( &data[i], &owner );
632
633  doCreateEntity( (ClassID)classID, uniqueID, owner );
634
635  return true;
636}
637
638bool NetworkGameManager::handleRemoveEntity( int & i, const byte * data, int length, int sender )
639{
640  if ( INTSIZE > length-i )
641  {
642    PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
643    return false;
644  }
645  int uniqueID;
646  i += Converter::byteArrayToInt( &data[i], &uniqueID );
647
648  doRemoveEntity( uniqueID );
649
650  return true;
651}
652
653bool NetworkGameManager::handleCreateEntityList( int & i, const byte * data, int length, int sender )
654{
655  if ( INTSIZE > length-i )
656  {
657    PRINTF(1)("Cannot read n from buffer! Not enough data left!\n");
658    return false;
659  }
660
661  PRINTF(0)("HandleCreateEntityList:  data[i..i+3] = %d %d %d %d\n", data[i], data[i+1], data[i+2], data[i+3]);
662
663  int n;
664  i += Converter::byteArrayToInt( &data[i], &n );
665
666
667  PRINTF(0)("HandleCreateEntityList: n = %d\n", n);
668
669  int classID, uniqueID, owner;
670
671  for ( int j = 0; j<n; j++ )
672  {
673
674    if ( INTSIZE > length-i )
675    {
676      PRINTF(1)("Cannot read classID from buffer! Not enough data left!\n");
677      return false;
678    }
679    i += Converter::byteArrayToInt( &data[i], &classID );
680
681    if ( INTSIZE > length-i )
682    {
683      PRINTF(1)("Cannot read uniqueID from buffer! Not enough data left!\n");
684      return false;
685    }
686    i += Converter::byteArrayToInt( &data[i], &uniqueID );
687
688    if ( INTSIZE > length-i )
689    {
690      PRINTF(1)("Cannot read owner from buffer! Not enough data left!\n");
691      return false;
692    }
693    i += Converter::byteArrayToInt( &data[i], &owner );
694
695    if ( classID != CL_NETWORK_GAME_MANAGER && classID != CL_HANDSHAKE )
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.