Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

network_game_manager: implemented some functions

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