Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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