Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

new the message handler is checking, if this message is also for the local host. if not the system tries to relay the message

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"
25#include "class_list.h"
[8623]26#include "debug.h"
[7349]27
[6341]28#include "network_stream.h"
[7349]29#include "shared_network_data.h"
[6341]30#include "converter.h"
[7954]31#include "message_manager.h"
[6341]32
[6498]33#include "playable.h"
34#include "player.h"
[6424]35
[7349]36#include "game_world.h"
[6424]37
[8068]38#include "game_rules.h"
39#include "network_game_rules.h"
40
[6116]41#include "network_game_manager.h"
[6067]42
[9008]43#include "multiplayer_team_deathmatch.h"
[6067]44
[9235]45#include "preferences.h"
[9008]46
[9235]47
[6067]48
[9406]49
[6341]50NetworkGameManager* NetworkGameManager::singletonRef = NULL;
51
[6067]52/*!
53 * Standard constructor
54 */
[6116]55NetworkGameManager::NetworkGameManager()
[6695]56  : Synchronizeable()
[6067]57{
[6341]58  PRINTF(0)("START\n");
59
[6067]60  /* set the class id for the base object */
[6341]61  this->setClassID(CL_NETWORK_GAME_MANAGER, "NetworkGameManager");
62
[6695]63  this->setSynchronized(true);
[9406]64
[8068]65  MessageManager::getInstance()->registerMessageHandler( MSGID_DELETESYNCHRONIZEABLE, delSynchronizeableHandler, NULL );
[8147]66  MessageManager::getInstance()->registerMessageHandler( MSGID_PREFEREDTEAM, preferedTeamHandler, NULL );
[8623]67  MessageManager::getInstance()->registerMessageHandler( MSGID_CHATMESSAGE, chatMessageHandler, NULL );
[9406]68
[8068]69  this->gameState = 0;
70  registerVar( new SynchronizeableInt( &gameState, &gameState, "gameState" ) );
[6067]71}
72
73/*!
74 * Standard destructor
75 */
[6116]76NetworkGameManager::~NetworkGameManager()
[6067]77{
[8623]78  delete MessageManager::getInstance();
[9406]79
[8623]80  PlayerStats::deleteAllPlayerStats();
[9406]81
[9059]82  NetworkGameManager::singletonRef = NULL;
[6067]83}
84
[6341]85
[8068]86/**
87 * insert new player into game
[9406]88 * @param userId
89 * @return
[6067]90 */
[8068]91bool NetworkGameManager::signalNewPlayer( int userId )
[6067]92{
[9494]93  assert( SharedNetworkData::getInstance()->isMasterServer() ||  SharedNetworkData::getInstance()->isProxyServerActive());
[8068]94  assert( State::getGameRules() );
95  assert( State::getGameRules()->isA( CL_NETWORK_GAME_RULES ) );
[9406]96
[8068]97  NetworkGameRules & rules = *(dynamic_cast<NetworkGameRules*>(State::getGameRules()));
[9406]98
[8068]99  int team = rules.getTeamForNewUser();
[8147]100  ClassID playableClassId = rules.getPlayableClassId( userId, team );
101  std::string playableModel = rules.getPlayableModelFileName( userId, team, playableClassId );
[9110]102  std::string playableTexture = rules.getPlayableModelFileName( userId, team, playableClassId );
[9235]103  float       playableScale = rules.getPlayableScale( userId, team, playableClassId );
[9406]104
[8068]105  BaseObject * bo = Factory::fabricate( playableClassId );
[9406]106
[8068]107  assert( bo != NULL );
108  assert( bo->isA( CL_PLAYABLE ) );
[9406]109
[8068]110  Playable & playable = *(dynamic_cast<Playable*>(bo));
[9406]111
[9235]112  playable.loadMD2Texture( playableTexture );
[9503]113  playable.setTeam(team);
[9235]114  playable.loadModel( playableModel, 100.0f );
[8068]115  playable.setOwner( userId );
116  playable.setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() );
117  playable.setSynchronized( true );
[9406]118
[8068]119  PlayerStats * stats = rules.getNewPlayerStats( userId );
[9406]120
[8068]121  stats->setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() );
122  stats->setSynchronized( true );
[8708]123  stats->setOwner( SharedNetworkData::getInstance()->getHostID() );
[9406]124
[8068]125  stats->setTeamId( team );
126  stats->setPlayableClassId( playableClassId );
127  stats->setPlayableUniqueId( playable.getUniqueID() );
128  stats->setModelFileName( playableModel );
[9406]129
[9235]130  if ( userId == 0 )
131    stats->setNickName( Preferences::getInstance()->getString( "multiplayer", "nickname", "Server" ) );
[9406]132
[9008]133  if ( rules.isA( CL_MULTIPLAYER_TEAM_DEATHMATCH ) )
134    dynamic_cast<MultiplayerTeamDeathmatch*>(&rules)->respawnPlayable( &playable, team, 0.0f );
[9406]135
[8228]136  return true;
[6737]137}
138
[6341]139
140/**
[8068]141 * remove player from game
[9406]142 * @param userID
143 * @return
[6341]144 */
[8068]145bool NetworkGameManager::signalLeftPlayer(int userID)
[6341]146{
[8228]147  if ( PlayerStats::getStats( userID ) )
148  {
149    if ( PlayerStats::getStats( userID )->getPlayable() )
150      delete PlayerStats::getStats( userID )->getPlayable();
151    delete PlayerStats::getStats( userID );
152  }
[9406]153
[8228]154  return true;
[6341]155}
156
157
158
159/**
[8068]160 * handler for remove synchronizeable messages
[9508]161 * @param messageType
[9406]162 * @param data
163 * @param dataLength
164 * @param someData
165 * @param userId
[8068]166 * @return true on successfull handling else handler will be called again
[6341]167 */
[9521]168bool NetworkGameManager::delSynchronizeableHandler( MessageType messageType, byte * data, int dataLength, void * someData, int senderId, int destinationId  )
[6341]169{
[9494]170
171  PRINTF(0)(" del synchronizeable\n");
172
173  if ( SharedNetworkData::getInstance()->isMasterServer() ||
[9521]174       SharedNetworkData::getInstance()->isProxyServerActive() && SharedNetworkData::getInstance()->isUserClient(senderId))
[6341]175  {
[9521]176    PRINTF(0)("Recieved DeleteSynchronizeable message from client %d!\n", senderId);
[8068]177    return true;
[6341]178  }
[9406]179
[8068]180  int uniqueId = 0;
181  int len = Converter::byteArrayToInt( data, &uniqueId );
[9406]182
[8068]183  if ( len != dataLength )
[6341]184  {
[9521]185    PRINTF(2)("Recieved DeleteSynchronizeable message with incorrect size (%d) from client %d!\n", dataLength, senderId);
[8068]186    return true;
[6341]187  }
[9406]188
[8068]189  const std::list<BaseObject*> * list = ClassList::getList( CL_SYNCHRONIZEABLE );
[9406]190
[8068]191  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
[6341]192  {
[8068]193    if ( dynamic_cast<Synchronizeable*>(*it)->getUniqueID() == uniqueId )
[6341]194    {
[8147]195      if ( (*it)->isA(CL_PLAYABLE) )
196      {
197        getInstance()->playablesToDelete.push_back( dynamic_cast<Playable*>(*it) );
198        return true;
199      }
[9406]200
[8068]201      delete dynamic_cast<Synchronizeable*>(*it);
202      return true;
[6341]203    }
204  }
[9406]205
[8228]206  return true;
[6341]207}
208
[6695]209/**
[8068]210 * removes synchronizeable (also on clients)
211 * @param uniqueId uniqueid to delete
[6695]212 */
[8068]213void NetworkGameManager::removeSynchronizeable( int uniqueId )
[6695]214{
[8068]215  byte buf[INTSIZE];
[9406]216
[8068]217  assert( Converter::intToByteArray( uniqueId, buf, INTSIZE ) == INTSIZE );
[8362]218
[9522]219  MessageManager::getInstance()->sendMessage( MSGID_DELETESYNCHRONIZEABLE, buf, INTSIZE, RT_ALL_BUT_ME, NET_UNASSIGNED, MP_HIGHBANDWIDTH );
[7954]220}
221
[6341]222
223
[8147]224/**
225 * handler for MSGID_PREFEREDTEAM message
[9508]226 * @param messageType
[9406]227 * @param data
228 * @param dataLength
229 * @param someData
230 * @param userId
231 * @return
[8147]232 */
[9521]233bool NetworkGameManager::preferedTeamHandler( MessageType messageType, byte * data, int dataLength, void * someData, int senderId, int destinationId  )
[8147]234{
[9499]235  assert( SharedNetworkData::getInstance()->isMasterServer() /*||  SharedNetworkData::getInstance()->isProxyServerActive()*/);
[9406]236
[8147]237  int teamId = 0;
238  int len = Converter::byteArrayToInt( data, &teamId );
[9406]239
[8147]240  if ( len != dataLength )
241  {
[9521]242    PRINTF(2)("Recieved DeleteSynchronizeable message with incorrect size (%d) from client %d!\n", dataLength, senderId);
[8147]243    return true;
244  }
[9406]245
[9521]246  NetworkGameManager::getInstance()->setPreferedTeam( senderId, teamId );
[9406]247
[8228]248  return true;
[8147]249}
[6341]250
[9499]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
[9499]267
[8147]268/**
269 * set prefered team for this host
[9406]270 * @param teamId
[8147]271 */
272void NetworkGameManager::prefereTeam( int teamId )
273{
[9507]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
[9507]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    {
[9059]298      const std::list<BaseObject*> * list = ClassList::getList( CL_PLAYABLE );
[9406]299
[9059]300      if ( list && std::find( list->begin(), list->end(), *it ) != list->end() )
[9406]301      {
302        PRINTF(0)("Delete unused playable: %s owner: %d\n", (*it)->getClassCName(), (*it)->getOwner() );
[9059]303        std::list<Playable*>::iterator delit = it;
304        it++;
305        delete *delit;
306        playablesToDelete.erase( delit );
307        continue;
308      }
[8147]309    }
310    it++;
311  }
312}
313
314
315
[9521]316bool NetworkGameManager::chatMessageHandler( MessageType messageType, byte * data, int dataLength, void * someData, int senderId, int destinationId  )
[8623]317{
[9521]318  PRINTF(0)("NetworkGameManager::chatMessageHandler %d %d\n", senderId, SharedNetworkData::getInstance()->getHostID() );
319  if ( (SharedNetworkData::getInstance()->isMasterServer() /*|| SharedNetworkData::getInstance()->isProxyServerActive()*/) && senderId !=  SharedNetworkData::getInstance()->getHostID() )
[8708]320  {
[9522]321    MessageManager::getInstance()->sendMessage( messageType, data, dataLength, RT_ALL_BUT_ME, NET_UNASSIGNED, MP_HIGHBANDWIDTH );
[8708]322  }
[9406]323
[8623]324  assert( State::getGameRules() );
325  assert( State::getGameRules()->isA( CL_NETWORK_GAME_RULES ) );
[9406]326
[8623]327  NetworkGameRules & rules = *(dynamic_cast<NetworkGameRules*>(State::getGameRules()));
[9406]328
[8708]329  if ( dataLength < 3*INTSIZE )
[8623]330  {
[9521]331    PRINTF(2)("got too small chatmessage from client %d\n", senderId);
[9406]332
[8623]333    return true;
334  }
[9406]335
[9508]336  int chatType = 0;
337  Converter::byteArrayToInt( data, &chatType);
[8708]338  int senderUserId = 0;
339  Converter::byteArrayToInt( data+INTSIZE, &senderUserId );
[8623]340  std::string message;
[8708]341  Converter::byteArrayToString( data+2*INTSIZE, message, dataLength-2*INTSIZE );
[9406]342
[9508]343  rules.handleChatMessage( senderUserId, message, chatType);
[8147]344
[8623]345  return true;
346}
347
348/**
349 * send chat message
350 * @param message message text
351 * @param messageType some int
352 */
[8708]353void NetworkGameManager::sendChatMessage( const std::string & message, int messageType )
[8623]354{
[8708]355  byte * buf = new byte[message.length()+3*INTSIZE];
[8623]356
357  assert( Converter::intToByteArray( messageType, buf, INTSIZE ) == INTSIZE );
[8708]358  assert( Converter::intToByteArray( SharedNetworkData::getInstance()->getHostID(), buf+INTSIZE, INTSIZE ) == INTSIZE );
359  assert( Converter::stringToByteArray(message, buf+2*INTSIZE, message.length()+INTSIZE) == message.length()+INTSIZE );
[9406]360
[9494]361  if ( SharedNetworkData::getInstance()->isMasterServer() /*|| SharedNetworkData::getInstance()->isProxyServerActive()*/)
[9522]362    MessageManager::getInstance()->sendMessage( MSGID_CHATMESSAGE, buf, message.length()+3*INTSIZE, RT_ALL_ME, NET_UNASSIGNED, MP_HIGHBANDWIDTH );
[8623]363  else
[9522]364    MessageManager::getInstance()->sendMessage( MSGID_CHATMESSAGE, buf, message.length()+3*INTSIZE, RT_ALL_BUT_ME, NET_UNASSIGNED, MP_HIGHBANDWIDTH );
[8708]365
[9406]366
[8623]367  delete [] buf;
368}
369
370
371
Note: See TracBrowser for help on using the repository browser.