Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

extended the sharednetworkdata inteface. now synchronizeables should also be removed on proxy servers by message handling

File size: 10.5 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" ) );
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() ||  SharedNetworkData::getInstance()->isProxyServerActive());
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
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 messageId
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( MessageId messageId, byte * data, int dataLength, void * someData, int userId )
169{
170  if ( SharedNetworkData::getInstance()->isMasterServer() ||
171       SharedNetworkData::getInstance()->isProxyServerActive() && SharedNetworkData::getInstance()->isUserClient(userId))
172  {
173    PRINTF(2)("Recieved DeleteSynchronizeable message from client %d!\n", userId);
174    return true;
175  }
176
177  int uniqueId = 0;
178  int len = Converter::byteArrayToInt( data, &uniqueId );
179
180  if ( len != dataLength )
181  {
182    PRINTF(2)("Recieved DeleteSynchronizeable message with incorrect size (%d) from client %d!\n", dataLength, userId);
183    return true;
184  }
185
186  const std::list<BaseObject*> * list = ClassList::getList( CL_SYNCHRONIZEABLE );
187
188  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
189  {
190    if ( dynamic_cast<Synchronizeable*>(*it)->getUniqueID() == uniqueId )
191    {
192      if ( (*it)->isA(CL_PLAYABLE) )
193      {
194        getInstance()->playablesToDelete.push_back( dynamic_cast<Playable*>(*it) );
195        return true;
196      }
197
198      delete dynamic_cast<Synchronizeable*>(*it);
199      return true;
200    }
201  }
202
203  return true;
204}
205
206/**
207 * removes synchronizeable (also on clients)
208 * @param uniqueId uniqueid to delete
209 */
210void NetworkGameManager::removeSynchronizeable( int uniqueId )
211{
212  byte buf[INTSIZE];
213
214  assert( Converter::intToByteArray( uniqueId, buf, INTSIZE ) == INTSIZE );
215
216  MessageManager::getInstance()->sendMessage( MSGID_DELETESYNCHRONIZEABLE, buf, INTSIZE, RT_ALL_BUT_ME, 0, MP_HIGHBANDWIDTH );
217}
218
219
220
221/**
222 * handler for MSGID_PREFEREDTEAM message
223 * @param messageId
224 * @param data
225 * @param dataLength
226 * @param someData
227 * @param userId
228 * @return
229 */
230bool NetworkGameManager::preferedTeamHandler( MessageId messageId, byte * data, int dataLength, void * someData, int userId )
231{
232  assert( SharedNetworkData::getInstance()->isMasterServer() ||  SharedNetworkData::getInstance()->isProxyServerActive());
233
234  int teamId = 0;
235  int len = Converter::byteArrayToInt( data, &teamId );
236
237  if ( len != dataLength )
238  {
239    PRINTF(2)("Recieved DeleteSynchronizeable message with incorrect size (%d) from client %d!\n", dataLength, userId);
240    return true;
241  }
242
243  NetworkGameManager::getInstance()->setPreferedTeam( userId, teamId );
244
245  return true;
246}
247
248void NetworkGameManager::setPreferedTeam( int userId, int teamId )
249{
250  if ( !PlayerStats::getStats( userId ) )
251    return;
252
253  PlayerStats & stats = *(PlayerStats::getStats( userId ));
254
255  stats.setPreferedTeamId( teamId );
256}
257
258/**
259 * set prefered team for this host
260 * @param teamId
261 */
262void NetworkGameManager::prefereTeam( int teamId )
263{
264  if ( SharedNetworkData::getInstance()->isMasterServer() /*|| SharedNetworkData::getInstance()->isProxyServerActive()*/)
265    setPreferedTeam( SharedNetworkData::getInstance()->getHostID(), teamId );
266  else
267  {
268    byte buf[INTSIZE];
269
270    assert( Converter::intToByteArray( teamId, buf, INTSIZE) == INTSIZE );
271
272    MessageManager::getInstance()->sendMessage( MSGID_PREFEREDTEAM, buf, INTSIZE, RT_USER, 0, MP_HIGHBANDWIDTH );
273  }
274}
275
276/**
277 * this function will be called periodically by networkManager
278 * @param ds time elapsed since last call of tick
279 */
280void NetworkGameManager::tick( float ds )
281{
282  //delete playables if they are not assigned to local player anymore
283  for ( std::list<Playable*>::iterator it = playablesToDelete.begin(); it != playablesToDelete.end();  )
284  {
285    if ( State::getPlayer()->getPlayable() != *it )
286    {
287      const std::list<BaseObject*> * list = ClassList::getList( CL_PLAYABLE );
288
289      if ( list && std::find( list->begin(), list->end(), *it ) != list->end() )
290      {
291        PRINTF(0)("Delete unused playable: %s owner: %d\n", (*it)->getClassCName(), (*it)->getOwner() );
292        std::list<Playable*>::iterator delit = it;
293        it++;
294        delete *delit;
295        playablesToDelete.erase( delit );
296        continue;
297      }
298    }
299    it++;
300  }
301}
302
303
304
305bool NetworkGameManager::chatMessageHandler( MessageId messageId, byte * data, int dataLength, void * someData, int userId )
306{
307  PRINTF(0)("NetworkGameManager::chatMessageHandler %d %d\n", userId, SharedNetworkData::getInstance()->getHostID() );
308  if ( (SharedNetworkData::getInstance()->isMasterServer() /*|| SharedNetworkData::getInstance()->isProxyServerActive()*/) && userId !=  SharedNetworkData::getInstance()->getHostID() )
309  {
310    MessageManager::getInstance()->sendMessage( messageId, data, dataLength, RT_ALL_BUT_ME, 0, MP_HIGHBANDWIDTH );
311  }
312
313  assert( State::getGameRules() );
314  assert( State::getGameRules()->isA( CL_NETWORK_GAME_RULES ) );
315
316  NetworkGameRules & rules = *(dynamic_cast<NetworkGameRules*>(State::getGameRules()));
317
318  if ( dataLength < 3*INTSIZE )
319  {
320    PRINTF(2)("got too small chatmessage from client %d\n", userId);
321
322    return true;
323  }
324
325  int messageType = 0;
326  Converter::byteArrayToInt( data, &messageType );
327  int senderUserId = 0;
328  Converter::byteArrayToInt( data+INTSIZE, &senderUserId );
329  std::string message;
330  Converter::byteArrayToString( data+2*INTSIZE, message, dataLength-2*INTSIZE );
331
332  rules.handleChatMessage( senderUserId, message, messageType );
333
334  return true;
335}
336
337/**
338 * send chat message
339 * @param message message text
340 * @param messageType some int
341 */
342void NetworkGameManager::sendChatMessage( const std::string & message, int messageType )
343{
344  byte * buf = new byte[message.length()+3*INTSIZE];
345
346  assert( Converter::intToByteArray( messageType, buf, INTSIZE ) == INTSIZE );
347  assert( Converter::intToByteArray( SharedNetworkData::getInstance()->getHostID(), buf+INTSIZE, INTSIZE ) == INTSIZE );
348  assert( Converter::stringToByteArray(message, buf+2*INTSIZE, message.length()+INTSIZE) == message.length()+INTSIZE );
349
350  if ( SharedNetworkData::getInstance()->isMasterServer() /*|| SharedNetworkData::getInstance()->isProxyServerActive()*/)
351    MessageManager::getInstance()->sendMessage( MSGID_CHATMESSAGE, buf, message.length()+3*INTSIZE, RT_ALL_ME, 0, MP_HIGHBANDWIDTH );
352  else
353    MessageManager::getInstance()->sendMessage( MSGID_CHATMESSAGE, buf, message.length()+3*INTSIZE, RT_ALL_BUT_ME, 0, MP_HIGHBANDWIDTH );
354
355
356  delete [] buf;
357}
358
359
360
Note: See TracBrowser for help on using the repository browser.