Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 6238 was 6238, checked in by patrick, 18 years ago

network: singleton fix

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