Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

message handler: changed some variable names - standardisations to make it better readable. added some documentation

File size: 10.8 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 */
[9508]168bool NetworkGameManager::delSynchronizeableHandler( MessageType messageType, byte * data, int dataLength, void * someData, int userId )
[6341]169{
[9494]170
171  PRINTF(0)(" del synchronizeable\n");
172
173  if ( SharedNetworkData::getInstance()->isMasterServer() ||
174       SharedNetworkData::getInstance()->isProxyServerActive() && SharedNetworkData::getInstance()->isUserClient(userId))
[6341]175  {
[9494]176    PRINTF(0)("Recieved DeleteSynchronizeable message from client %d!\n", userId);
[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  {
[8068]185    PRINTF(2)("Recieved DeleteSynchronizeable message with incorrect size (%d) from client %d!\n", dataLength, userId);
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
[9494]219  MessageManager::getInstance()->sendMessage( MSGID_DELETESYNCHRONIZEABLE, buf, INTSIZE, RT_ALL_BUT_ME, 0, 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 */
[9508]233bool NetworkGameManager::preferedTeamHandler( MessageType messageType, byte * data, int dataLength, void * someData, int userId )
[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  {
242    PRINTF(2)("Recieved DeleteSynchronizeable message with incorrect size (%d) from client %d!\n", dataLength, userId);
243    return true;
244  }
[9406]245
[8147]246  NetworkGameManager::getInstance()->setPreferedTeam( userId, 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
[9508]316bool NetworkGameManager::chatMessageHandler( MessageType messageType, byte * data, int dataLength, void * someData, int userId )
[8623]317{
[8708]318  PRINTF(0)("NetworkGameManager::chatMessageHandler %d %d\n", userId, SharedNetworkData::getInstance()->getHostID() );
[9494]319  if ( (SharedNetworkData::getInstance()->isMasterServer() /*|| SharedNetworkData::getInstance()->isProxyServerActive()*/) && userId !=  SharedNetworkData::getInstance()->getHostID() )
[8708]320  {
[9508]321    MessageManager::getInstance()->sendMessage( messageType, data, dataLength, RT_ALL_BUT_ME, 0, 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  {
331    PRINTF(2)("got too small chatmessage from client %d\n", userId);
[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()*/)
[8708]362    MessageManager::getInstance()->sendMessage( MSGID_CHATMESSAGE, buf, message.length()+3*INTSIZE, RT_ALL_ME, 0, MP_HIGHBANDWIDTH );
[8623]363  else
[9494]364    MessageManager::getInstance()->sendMessage( MSGID_CHATMESSAGE, buf, message.length()+3*INTSIZE, RT_ALL_BUT_ME, 0, MP_HIGHBANDWIDTH );
[8708]365
[9406]366
[8623]367  delete [] buf;
368}
369
370
371
Note: See TracBrowser for help on using the repository browser.