/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Benjamin Wuest co-programmer: ... */ /* this is for debug output. It just says, that all calls to PRINT() belong to the DEBUG_MODULE_NETWORK module For more information refere to https://www.orxonox.net/cgi-bin/trac.cgi/wiki/DebugOutput */ #define DEBUG_MODULE_NETWORK #include "util/loading/factory.h" #include "state.h" #include "class_list.h" #include "network_stream.h" #include "shared_network_data.h" #include "converter.h" #include "message_manager.h" #include "playable.h" #include "player.h" #include "game_world.h" #include "game_rules.h" #include "network_game_rules.h" #include "network_game_manager.h" /* using namespace std is default, this needs to be here */ using namespace std; NetworkGameManager* NetworkGameManager::singletonRef = NULL; /*! * Standard constructor */ NetworkGameManager::NetworkGameManager() : Synchronizeable() { PRINTF(0)("START\n"); /* set the class id for the base object */ this->setClassID(CL_NETWORK_GAME_MANAGER, "NetworkGameManager"); this->setSynchronized(true); MessageManager::getInstance()->registerMessageHandler( MSGID_DELETESYNCHRONIZEABLE, delSynchronizeableHandler, NULL ); MessageManager::getInstance()->registerMessageHandler( MSGID_PREFEREDTEAM, preferedTeamHandler, NULL ); this->gameState = 0; registerVar( new SynchronizeableInt( &gameState, &gameState, "gameState" ) ); } /*! * Standard destructor */ NetworkGameManager::~NetworkGameManager() { } /** * insert new player into game * @param userId * @return */ bool NetworkGameManager::signalNewPlayer( int userId ) { assert( SharedNetworkData::getInstance()->isGameServer() ); assert( State::getGameRules() ); assert( State::getGameRules()->isA( CL_NETWORK_GAME_RULES ) ); NetworkGameRules & rules = *(dynamic_cast(State::getGameRules())); int team = rules.getTeamForNewUser(); ClassID playableClassId = rules.getPlayableClassId( userId, team ); std::string playableModel = rules.getPlayableModelFileName( userId, team, playableClassId ); BaseObject * bo = Factory::fabricate( playableClassId ); assert( bo != NULL ); assert( bo->isA( CL_PLAYABLE ) ); Playable & playable = *(dynamic_cast(bo)); playable.loadModel( playableModel ); playable.setOwner( userId ); playable.setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() ); playable.setSynchronized( true ); PlayerStats * stats = rules.getNewPlayerStats( userId ); stats->setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() ); stats->setSynchronized( true ); stats->setOwner( getHostID() ); stats->setTeamId( team ); stats->setPlayableClassId( playableClassId ); stats->setPlayableUniqueId( playable.getUniqueID() ); stats->setModelFileName( playableModel ); } /** * remove player from game * @param userID * @return */ bool NetworkGameManager::signalLeftPlayer(int userID) { delete PlayerStats::getStats( userID )->getPlayable(); delete PlayerStats::getStats( userID ); } /** * handler for remove synchronizeable messages * @param messageId * @param data * @param dataLength * @param someData * @param userId * @return true on successfull handling else handler will be called again */ bool NetworkGameManager::delSynchronizeableHandler( MessageId messageId, byte * data, int dataLength, void * someData, int userId ) { if ( getInstance()->isServer() ) { PRINTF(2)("Recieved DeleteSynchronizeable message from client %d!\n", userId); return true; } int uniqueId = 0; int len = Converter::byteArrayToInt( data, &uniqueId ); if ( len != dataLength ) { PRINTF(2)("Recieved DeleteSynchronizeable message with incorrect size (%d) from client %d!\n", dataLength, userId); return true; } const std::list * list = ClassList::getList( CL_SYNCHRONIZEABLE ); for ( std::list::const_iterator it = list->begin(); it != list->end(); it++ ) { if ( dynamic_cast(*it)->getUniqueID() == uniqueId ) { delete dynamic_cast(*it); return true; } } } /** * removes synchronizeable (also on clients) * @param uniqueId uniqueid to delete */ void NetworkGameManager::removeSynchronizeable( int uniqueId ) { byte buf[INTSIZE]; assert( Converter::intToByteArray( uniqueId, buf, INTSIZE ) == INTSIZE ); MessageManager::getInstance()->sendMessage( MSGID_DELETESYNCHRONIZEABLE, buf, INTSIZE, RT_ALL_NOT_ME, 0, MP_HIGHBANDWIDTH ); } /** * handler for MSGID_PREFEREDTEAM message * @param messageId * @param data * @param dataLength * @param someData * @param userId * @return */ bool NetworkGameManager::preferedTeamHandler( MessageId messageId, byte * data, int dataLength, void * someData, int userId ) { assert( NetworkGameManager::getInstance()->isServer() ); int teamId = 0; int len = Converter::byteArrayToInt( data, &teamId ); if ( len != dataLength ) { PRINTF(2)("Recieved DeleteSynchronizeable message with incorrect size (%d) from client %d!\n", dataLength, userId); return true; } NetworkGameManager::getInstance()->setPreferedTeam( userId, teamId ); } void NetworkGameManager::setPreferedTeam( int userId, int teamId ) { if ( !PlayerStats::getStats( userId ) ) return; PlayerStats & stats = *(PlayerStats::getStats( userId )); stats.setPreferedTeamId( teamId ); } /** * set prefered team for this host * @param teamId */ void NetworkGameManager::prefereTeam( int teamId ) { if ( isServer() ) setPreferedTeam( getHostID(), teamId ); else { byte buf[INTSIZE]; assert( Converter::intToByteArray( teamId, buf, INTSIZE) == INTSIZE ); MessageManager::getInstance()->sendMessage( MSGID_PREFEREDTEAM, buf, INTSIZE, RT_USER, 0, MP_HIGHBANDWIDTH ); } }