Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/network/network_game_manager.cc @ 10184

Last change on this file since 10184 was 10114, checked in by patrick, 17 years ago

merged network back to trunk

File size: 10.9 KB
RevLine 
[6067]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:
[9406]12   main-programmer: Christoph Renner rennerc@ee.ethz.ch
13   co-programmer:   Patrick Boenzli  boenzlip@orxonox.ethz.ch
14
15     June 2006: finishing work on the network stream for pps presentation (rennerc@ee.ethz.ch)
16     July 2006: some code rearangement and integration of the proxy server mechanism (boenzlip@ee.ethz.ch)
[6067]17*/
18
19
[9406]20
[6067]21#define DEBUG_MODULE_NETWORK
22
[7193]23#include "util/loading/factory.h"
[7349]24#include "state.h"
[8623]25#include "debug.h"
[7349]26
[6341]27#include "network_stream.h"
[7349]28#include "shared_network_data.h"
[6341]29#include "converter.h"
[7954]30#include "message_manager.h"
[6341]31
[6498]32#include "playable.h"
33#include "player.h"
[6424]34
[7349]35#include "game_world.h"
[6424]36
[8068]37#include "game_rules.h"
38#include "network_game_rules.h"
39
[6116]40#include "network_game_manager.h"
[6067]41
[9008]42#include "multiplayer_team_deathmatch.h"
[6067]43
[9869]44#include "parser/preferences/preferences.h"
[9008]45
[9235]46
[6067]47
[9869]48ObjectListDefinition(NetworkGameManager);
[6341]49NetworkGameManager* NetworkGameManager::singletonRef = NULL;
50
[6067]51/*!
52 * Standard constructor
53 */
[6116]54NetworkGameManager::NetworkGameManager()
[6695]55  : Synchronizeable()
[6067]56{
[6341]57  PRINTF(0)("START\n");
58
[6067]59  /* set the class id for the base object */
[9869]60  this->registerObject(this, NetworkGameManager::_objectList);
[6341]61
[6695]62  this->setSynchronized(true);
[9406]63
[8068]64  MessageManager::getInstance()->registerMessageHandler( MSGID_DELETESYNCHRONIZEABLE, delSynchronizeableHandler, NULL );
[8147]65  MessageManager::getInstance()->registerMessageHandler( MSGID_PREFEREDTEAM, preferedTeamHandler, NULL );
[8623]66  MessageManager::getInstance()->registerMessageHandler( MSGID_CHATMESSAGE, chatMessageHandler, NULL );
[9406]67
[8068]68  this->gameState = 0;
[9656]69  registerVar( new SynchronizeableInt( &gameState, &gameState, "gameState", PERMISSION_MASTER_SERVER ) );
[6067]70}
71
72/*!
73 * Standard destructor
74 */
[6116]75NetworkGameManager::~NetworkGameManager()
[6067]76{
[8623]77  delete MessageManager::getInstance();
[9406]78
[8623]79  PlayerStats::deleteAllPlayerStats();
[9406]80
[9059]81  NetworkGameManager::singletonRef = NULL;
[6067]82}
83
[6341]84
[8068]85/**
86 * insert new player into game
[9406]87 * @param userId
88 * @return
[6067]89 */
[8068]90bool NetworkGameManager::signalNewPlayer( int userId )
[6067]91{
[9656]92  assert( SharedNetworkData::getInstance()->isMasterServer());
[8068]93  assert( State::getGameRules() );
[9869]94  assert( State::getGameRules()->isA( NetworkGameRules::staticClassID()) );
[9406]95
[8068]96  NetworkGameRules & rules = *(dynamic_cast<NetworkGameRules*>(State::getGameRules()));
[9406]97
[9656]98  int          team = rules.getTeamForNewUser();
[9869]99  ClassID   playableClassId = rules.getPlayableClassId( userId, team );
[9656]100  std::string  playableModel = rules.getPlayableModelFileName( userId, team, playableClassId );
101  std::string  playableTexture = rules.getPlayableModelFileName( userId, team, playableClassId );
102  float        playableScale = rules.getPlayableScale( userId, team, playableClassId );
[9406]103
[8068]104  BaseObject * bo = Factory::fabricate( playableClassId );
[9406]105
[8068]106  assert( bo != NULL );
[9869]107  assert( bo->isA( Playable::staticClassID()) );
[9406]108
[8068]109  Playable & playable = *(dynamic_cast<Playable*>(bo));
[9406]110
[9235]111  playable.loadMD2Texture( playableTexture );
[9656]112  playable.setTeam(team);
[10114]113  playable.loadModel( playableModel, playableScale );
[8068]114  playable.setOwner( userId );
115  playable.setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() );
116  playable.setSynchronized( true );
[9406]117
[8068]118  PlayerStats * stats = rules.getNewPlayerStats( userId );
[9406]119
[8068]120  stats->setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() );
121  stats->setSynchronized( true );
[8708]122  stats->setOwner( SharedNetworkData::getInstance()->getHostID() );
[9406]123
[8068]124  stats->setTeamId( team );
125  stats->setPlayableClassId( playableClassId );
126  stats->setPlayableUniqueId( playable.getUniqueID() );
127  stats->setModelFileName( playableModel );
[9406]128
[9235]129  if ( userId == 0 )
130    stats->setNickName( Preferences::getInstance()->getString( "multiplayer", "nickname", "Server" ) );
[9406]131
[9869]132  if ( rules.isA( MultiplayerTeamDeathmatch::staticClassID()) )
[9008]133    dynamic_cast<MultiplayerTeamDeathmatch*>(&rules)->respawnPlayable( &playable, team, 0.0f );
[9406]134
[8228]135  return true;
[6737]136}
137
[6341]138
139/**
[8068]140 * remove player from game
[9406]141 * @param userID
142 * @return
[6341]143 */
[8068]144bool NetworkGameManager::signalLeftPlayer(int userID)
[6341]145{
[8228]146  if ( PlayerStats::getStats( userID ) )
147  {
148    if ( PlayerStats::getStats( userID )->getPlayable() )
149      delete PlayerStats::getStats( userID )->getPlayable();
150    delete PlayerStats::getStats( userID );
151  }
[9406]152
[8228]153  return true;
[6341]154}
155
156
157
158/**
[8068]159 * handler for remove synchronizeable messages
[9656]160 * @param messageType
[9406]161 * @param data
162 * @param dataLength
163 * @param someData
164 * @param userId
[8068]165 * @return true on successfull handling else handler will be called again
[6341]166 */
[9656]167bool NetworkGameManager::delSynchronizeableHandler( MessageType messageType, byte * data, int dataLength, void * someData, int senderId, int destinationId  )
[6341]168{
[9494]169
170  PRINTF(0)(" del synchronizeable\n");
171
172  if ( SharedNetworkData::getInstance()->isMasterServer() ||
[9656]173       SharedNetworkData::getInstance()->isProxyServerActive() && SharedNetworkData::getInstance()->isUserClient(senderId))
[6341]174  {
[9656]175    PRINTF(0)("Recieved DeleteSynchronizeable message from client %d!\n", senderId);
[8068]176    return true;
[6341]177  }
[9406]178
[8068]179  int uniqueId = 0;
180  int len = Converter::byteArrayToInt( data, &uniqueId );
[9406]181
[8068]182  if ( len != dataLength )
[6341]183  {
[9656]184    PRINTF(2)("Recieved DeleteSynchronizeable message with incorrect size (%d) from client %d!\n", dataLength, senderId);
[8068]185    return true;
[6341]186  }
[9406]187
[9869]188  for (ObjectList<Synchronizeable>::const_iterator it = Synchronizeable::objectList().begin();
189       it != Synchronizeable::objectList().end();
190      ++it)
[6341]191  {
[9869]192    if ( (*it)->getUniqueID() == uniqueId )
[6341]193    {
[9869]194      if ( (*it)->isA(Playable::staticClassID()) )
[8147]195      {
196        getInstance()->playablesToDelete.push_back( dynamic_cast<Playable*>(*it) );
197        return true;
198      }
[9406]199
[9869]200      delete (*it);
[8068]201      return true;
[6341]202    }
203  }
[9406]204
[8228]205  return true;
[6341]206}
207
[6695]208/**
[8068]209 * removes synchronizeable (also on clients)
210 * @param uniqueId uniqueid to delete
[6695]211 */
[8068]212void NetworkGameManager::removeSynchronizeable( int uniqueId )
[6695]213{
[8068]214  byte buf[INTSIZE];
[9406]215
[8068]216  assert( Converter::intToByteArray( uniqueId, buf, INTSIZE ) == INTSIZE );
[8362]217
[9656]218  MessageManager::getInstance()->sendMessage( MSGID_DELETESYNCHRONIZEABLE, buf, INTSIZE, RT_ALL_BUT_ME, NET_UNASSIGNED, MP_HIGHBANDWIDTH );
[7954]219}
220
[6341]221
222
[8147]223/**
224 * handler for MSGID_PREFEREDTEAM message
[9656]225 * @param messageType
[9406]226 * @param data
227 * @param dataLength
228 * @param someData
229 * @param userId
230 * @return
[8147]231 */
[9656]232bool NetworkGameManager::preferedTeamHandler( MessageType messageType, byte * data, int dataLength, void * someData, int senderId, int destinationId  )
[8147]233{
[9656]234  assert( SharedNetworkData::getInstance()->isMasterServer() );
[9406]235
[8147]236  int teamId = 0;
237  int len = Converter::byteArrayToInt( data, &teamId );
[9406]238
[8147]239  if ( len != dataLength )
240  {
[9656]241    PRINTF(2)("Recieved DeleteSynchronizeable message with incorrect size (%d) from client %d!\n", dataLength, senderId);
[8147]242    return true;
243  }
[9406]244
[9656]245  PRINTF(0)("Client %i wishes to play in team %i\n", senderId, teamId);
246  NetworkGameManager::getInstance()->setPreferedTeam( senderId, teamId );
[9406]247
[8228]248  return true;
[8147]249}
[6341]250
[9656]251
252/**
253 * this actualy sets the new prefered team id
254 * @param userId: the user that changes team
255 * @param teamId: the new team id for the user
256 */
[8147]257void NetworkGameManager::setPreferedTeam( int userId, int teamId )
258{
259  if ( !PlayerStats::getStats( userId ) )
260    return;
[9406]261
[8147]262  PlayerStats & stats = *(PlayerStats::getStats( userId ));
[9406]263
[8147]264  stats.setPreferedTeamId( teamId );
265}
[7954]266
[9656]267
[8147]268/**
269 * set prefered team for this host
[9406]270 * @param teamId
[8147]271 */
272void NetworkGameManager::prefereTeam( int teamId )
273{
[9656]274  if ( SharedNetworkData::getInstance()->isMasterServer() )
275    this->setPreferedTeam( SharedNetworkData::getInstance()->getHostID(), teamId );
[8147]276  else
277  {
278    byte buf[INTSIZE];
[9406]279
[8147]280    assert( Converter::intToByteArray( teamId, buf, INTSIZE) == INTSIZE );
[9406]281
[9656]282    // send this message to the master server
283    MessageManager::getInstance()->sendMessage( MSGID_PREFEREDTEAM, buf, INTSIZE, RT_USER, NET_ID_MASTER_SERVER, MP_HIGHBANDWIDTH );
[8147]284  }
285}
[6341]286
[8147]287/**
288 * this function will be called periodically by networkManager
289 * @param ds time elapsed since last call of tick
290 */
291void NetworkGameManager::tick( float ds )
292{
293  //delete playables if they are not assigned to local player anymore
294  for ( std::list<Playable*>::iterator it = playablesToDelete.begin(); it != playablesToDelete.end();  )
295  {
296    if ( State::getPlayer()->getPlayable() != *it )
297    {
[9869]298      if ( std::find( Playable::objectList().begin(), Playable::objectList().end(), *it ) != Playable::objectList().end() )
[9406]299      {
300        PRINTF(0)("Delete unused playable: %s owner: %d\n", (*it)->getClassCName(), (*it)->getOwner() );
[9059]301        std::list<Playable*>::iterator delit = it;
302        it++;
303        delete *delit;
304        playablesToDelete.erase( delit );
305        continue;
306      }
[8147]307    }
308    it++;
309  }
310}
311
312
313
[9656]314bool NetworkGameManager::chatMessageHandler( MessageType messageType, byte * data, int dataLength, void * someData, int senderId, int destinationId  )
[8623]315{
[9656]316  PRINTF(0)("NetworkGameManager::chatMessageHandler %d %d\n", senderId, SharedNetworkData::getInstance()->getHostID() );
317  if ( (SharedNetworkData::getInstance()->isMasterServer() /*|| SharedNetworkData::getInstance()->isProxyServerActive()*/) && senderId !=  SharedNetworkData::getInstance()->getHostID() )
[8708]318  {
[9656]319    MessageManager::getInstance()->sendMessage( messageType, data, dataLength, RT_ALL_BUT_ME, NET_UNASSIGNED, MP_HIGHBANDWIDTH );
[8708]320  }
[9406]321
[8623]322  assert( State::getGameRules() );
[9869]323  assert( State::getGameRules()->isA( NetworkGameRules::staticClassID()) );
[9406]324
[8623]325  NetworkGameRules & rules = *(dynamic_cast<NetworkGameRules*>(State::getGameRules()));
[9406]326
[8708]327  if ( dataLength < 3*INTSIZE )
[8623]328  {
[9656]329    PRINTF(2)("got too small chatmessage from client %d\n", senderId);
[9406]330
[8623]331    return true;
332  }
[9406]333
[9656]334  int chatType = 0;
335  Converter::byteArrayToInt( data, &chatType);
[8708]336  int senderUserId = 0;
337  Converter::byteArrayToInt( data+INTSIZE, &senderUserId );
[8623]338  std::string message;
[8708]339  Converter::byteArrayToString( data+2*INTSIZE, message, dataLength-2*INTSIZE );
[9406]340
[9656]341  rules.handleChatMessage( senderUserId, message, chatType);
[8147]342
[8623]343  return true;
344}
345
346/**
347 * send chat message
348 * @param message message text
349 * @param messageType some int
350 */
[8708]351void NetworkGameManager::sendChatMessage( const std::string & message, int messageType )
[8623]352{
[8708]353  byte * buf = new byte[message.length()+3*INTSIZE];
[8623]354
355  assert( Converter::intToByteArray( messageType, buf, INTSIZE ) == INTSIZE );
[8708]356  assert( Converter::intToByteArray( SharedNetworkData::getInstance()->getHostID(), buf+INTSIZE, INTSIZE ) == INTSIZE );
357  assert( Converter::stringToByteArray(message, buf+2*INTSIZE, message.length()+INTSIZE) == message.length()+INTSIZE );
[9406]358
[9494]359  if ( SharedNetworkData::getInstance()->isMasterServer() /*|| SharedNetworkData::getInstance()->isProxyServerActive()*/)
[9656]360    MessageManager::getInstance()->sendMessage( MSGID_CHATMESSAGE, buf, message.length()+3*INTSIZE, RT_ALL_ME, NET_UNASSIGNED, MP_HIGHBANDWIDTH );
[8623]361  else
[9656]362    MessageManager::getInstance()->sendMessage( MSGID_CHATMESSAGE, buf, message.length()+3*INTSIZE, RT_ALL_BUT_ME, NET_UNASSIGNED, MP_HIGHBANDWIDTH );
[8708]363
[9406]364
[8623]365  delete [] buf;
366}
367
368
369
Note: See TracBrowser for help on using the repository browser.