Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 9701 was 9656, checked in by bensch, 18 years ago

orxonox/trunk: merged the proxy bache back with no conflicts

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