/// \file /// /// This file is part of RakNet Copyright 2003 Kevin Jenkins. /// /// Usage of RakNet is subject to the appropriate license agreement. /// Creative Commons Licensees are subject to the /// license found at /// http://creativecommons.org/licenses/by-nc/2.5/ /// Single application licensees are subject to the license found at /// http://www.rakkarsoft.com/SingleApplicationLicense.html /// Custom license users are subject to the terms therein. /// GPL license users are subject to the GNU General Public /// License as published by the Free /// Software Foundation; either version 2 of the License, or (at your /// option) any later version. #include "RakClient.h" #include "PacketEnumerations.h" #include "GetTime.h" #ifdef _MSC_VER #pragma warning( push ) #endif // Constructor RakClient::RakClient() { unsigned i; for ( i = 0; i < 32; i++ ) otherClients[ i ].isActive = false; nextSeedUpdate = 0; } // Destructor RakClient::~RakClient() {} #ifdef _MSC_VER #pragma warning( disable : 4100 ) // warning C4100: 'depreciated' : unreferenced formal parameter #endif bool RakClient::Connect( const char* host, unsigned short serverPort, unsigned short clientPort, unsigned int depreciated, int threadSleepTimer ) { RakPeer::Disconnect( 100 ); RakPeer::Initialize( 1, clientPort, threadSleepTimer ); if ( host[ 0 ] < '0' || host[ 0 ] > '2' ) { #if !defined(_COMPATIBILITY_1) host = ( char* ) SocketLayer::Instance()->DomainNameToIP( host ); #else return false; #endif } unsigned i; for ( i = 0; i < 32; i++ ) { otherClients[ i ].isActive = false; otherClients[ i ].playerId = UNASSIGNED_PLAYER_ID; otherClients[ i ].staticData.Reset(); } // ignore depreciated. A pointless variable return RakPeer::Connect( host, serverPort, ( char* ) password.GetData(), password.GetNumberOfBytesUsed() ); } void RakClient::Disconnect( unsigned int blockDuration, unsigned char orderingChannel ) { RakPeer::Disconnect( blockDuration, orderingChannel ); } void RakClient::InitializeSecurity( const char *privKeyP, const char *privKeyQ ) { RakPeer::InitializeSecurity( privKeyP, privKeyQ, 0, 0 ); } void RakClient::SetPassword( const char *_password ) { if ( _password == 0 || _password[ 0 ] == 0 ) password.Reset(); else { password.Reset(); password.Write( _password, ( int ) strlen( _password ) + 1 ); } } bool RakClient::HasPassword( void ) const { return password.GetNumberOfBytesUsed() > 0; } bool RakClient::Send( const char *data, const int length, PacketPriority priority, PacketReliability reliability, char orderingChannel ) { if ( remoteSystemList == 0 ) return false; return RakPeer::Send( data, length, priority, reliability, orderingChannel, remoteSystemList[ 0 ].playerId, false ); } bool RakClient::Send( RakNet::BitStream * bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel ) { if ( remoteSystemList == 0 ) return false; return RakPeer::Send( bitStream, priority, reliability, orderingChannel, remoteSystemList[ 0 ].playerId, false ); } Packet* RakClient::Receive( void ) { Packet * packet = RakPeer::Receive(); // Intercept specific client / server feature packets if ( packet ) { RakNet::BitStream bitStream( packet->data, packet->length, false ); int i; if ( packet->data[ 0 ] == ID_CONNECTION_REQUEST_ACCEPTED ) { // ConnectionAcceptStruct cas; // cas.Deserialize(bitStream); // unsigned short remotePort; // PlayerID externalID; PlayerIndex playerIndex; RakNet::BitStream inBitStream(packet->data, packet->length, false); inBitStream.IgnoreBits(8); // ID_CONNECTION_REQUEST_ACCEPTED inBitStream.IgnoreBits(8 * sizeof(unsigned short)); //inBitStream.Read(remotePort); inBitStream.IgnoreBits(8 * sizeof(unsigned int)); //inBitStream.Read(externalID.binaryAddress); inBitStream.IgnoreBits(8 * sizeof(unsigned short)); //inBitStream.Read(externalID.port); inBitStream.Read(playerIndex); localPlayerIndex = playerIndex; packet->playerIndex = playerIndex; } else if ( packet->data[ 0 ] == ID_REMOTE_NEW_INCOMING_CONNECTION || packet->data[ 0 ] == ID_REMOTE_EXISTING_CONNECTION || packet->data[ 0 ] == ID_REMOTE_DISCONNECTION_NOTIFICATION || packet->data[ 0 ] == ID_REMOTE_CONNECTION_LOST ) { bitStream.IgnoreBits( 8 ); // Ignore identifier bitStream.Read( packet->playerId.binaryAddress ); bitStream.Read( packet->playerId.port ); if ( bitStream.Read( ( unsigned short& ) packet->playerIndex ) == false ) { DeallocatePacket( packet ); return 0; } if ( packet->data[ 0 ] == ID_REMOTE_DISCONNECTION_NOTIFICATION || packet->data[ 0 ] == ID_REMOTE_CONNECTION_LOST ) { i = GetOtherClientIndexByPlayerID( packet->playerId ); if ( i >= 0 ) otherClients[ i ].isActive = false; } } else if ( packet->data[ 0 ] == ID_REMOTE_STATIC_DATA ) { bitStream.IgnoreBits( 8 ); // Ignore identifier bitStream.Read( packet->playerId.binaryAddress ); bitStream.Read( packet->playerId.port ); bitStream.Read( packet->playerIndex ); // ADDED BY KURI i = GetOtherClientIndexByPlayerID( packet->playerId ); if ( i < 0 ) i = GetFreeOtherClientIndex(); if ( i >= 0 ) { otherClients[ i ].playerId = packet->playerId; otherClients[ i ].isActive = true; otherClients[ i ].staticData.Reset(); // The static data is what is left over in the stream otherClients[ i ].staticData.Write( ( char* ) bitStream.GetData() + BITS_TO_BYTES( bitStream.GetReadOffset() ), bitStream.GetNumberOfBytesUsed() - BITS_TO_BYTES( bitStream.GetReadOffset() ) ); } } else if ( packet->data[ 0 ] == ID_BROADCAST_PINGS ) { PlayerID playerId; int index; bitStream.IgnoreBits( 8 ); // Ignore identifier for ( i = 0; i < 32; i++ ) { if ( bitStream.Read( playerId.binaryAddress ) == false ) break; // No remaining data! bitStream.Read( playerId.port ); index = GetOtherClientIndexByPlayerID( playerId ); if ( index >= 0 ) bitStream.Read( otherClients[ index ].ping ); else { index = GetFreeOtherClientIndex(); if ( index >= 0 ) { otherClients[ index ].isActive = true; bitStream.Read( otherClients[ index ].ping ); otherClients[ index ].playerId = playerId; otherClients[ index ].staticData.Reset(); } else bitStream.IgnoreBits( sizeof( short ) * 8 ); } } DeallocatePacket( packet ); return 0; } else if ( packet->data[ 0 ] == ID_TIMESTAMP && packet->length == sizeof(unsigned char)+sizeof(unsigned int)+sizeof(unsigned char)+sizeof(unsigned int)+sizeof(unsigned int) ) { RakNet::BitStream inBitStream(packet->data, packet->length, false); RakNetTime timeStamp; unsigned char typeId; unsigned int in_seed; unsigned int in_nextSeed; inBitStream.IgnoreBits(8); // ID_TIMESTAMP inBitStream.Read(timeStamp); inBitStream.Read(typeId); // ID_SET_RANDOM_NUMBER_SEED ? // Check to see if this is a user TIMESTAMP message which // accidentally has length SetRandomNumberSeedStruct_Size if ( typeId != ID_SET_RANDOM_NUMBER_SEED ) return packet; inBitStream.Read(in_seed); inBitStream.Read(in_nextSeed); seed = in_seed; nextSeed = in_nextSeed; nextSeedUpdate = timeStamp + 9000; // Seeds are updated every 9 seconds DeallocatePacket( packet ); return 0; } } return packet; } void RakClient::DeallocatePacket( Packet *packet ) { RakPeer::DeallocatePacket( packet ); } void RakClient::PingServer( void ) { if ( remoteSystemList == 0 ) return ; RakPeer::Ping( remoteSystemList[ 0 ].playerId ); } void RakClient::PingServer( const char* host, unsigned short serverPort, unsigned short clientPort, bool onlyReplyOnAcceptingConnections ) { RakPeer::Initialize( 1, clientPort, 0 ); RakPeer::Ping( host, serverPort, onlyReplyOnAcceptingConnections ); } int RakClient::GetAveragePing( void ) { if ( remoteSystemList == 0 ) return -1; return RakPeer::GetAveragePing( remoteSystemList[ 0 ].playerId ); } int RakClient::GetLastPing( void ) const { if ( remoteSystemList == 0 ) return -1; return RakPeer::GetLastPing( remoteSystemList[ 0 ].playerId ); } int RakClient::GetLowestPing( void ) const { if ( remoteSystemList == 0 ) return -1; return RakPeer::GetLowestPing( remoteSystemList[ 0 ].playerId ); } int RakClient::GetPlayerPing( const PlayerID playerId ) { int i; for ( i = 0; i < 32; i++ ) if ( otherClients[ i ].playerId == playerId ) return otherClients[ i ].ping; return -1; } void RakClient::StartOccasionalPing( void ) { RakPeer::SetOccasionalPing( true ); } void RakClient::StopOccasionalPing( void ) { RakPeer::SetOccasionalPing( false ); } bool RakClient::IsConnected( void ) const { unsigned short numberOfSystems; RakPeer::GetConnectionList( 0, &numberOfSystems ); return numberOfSystems == 1; } unsigned int RakClient::GetSynchronizedRandomInteger( void ) const { if ( RakNet::GetTime() > nextSeedUpdate ) return nextSeed; else return seed; } bool RakClient::GenerateCompressionLayer( unsigned int inputFrequencyTable[ 256 ], bool inputLayer ) { return RakPeer::GenerateCompressionLayer( inputFrequencyTable, inputLayer ); } bool RakClient::DeleteCompressionLayer( bool inputLayer ) { return RakPeer::DeleteCompressionLayer( inputLayer ); } void RakClient::RegisterAsRemoteProcedureCall( char* uniqueID, void ( *functionPointer ) ( RPCParameters *rpcParms ) ) { RakPeer::RegisterAsRemoteProcedureCall( uniqueID, functionPointer ); } void RakClient::RegisterClassMemberRPC( char* uniqueID, void *functionPointer ) { RakPeer::RegisterClassMemberRPC( uniqueID, functionPointer ); } void RakClient::UnregisterAsRemoteProcedureCall( char* uniqueID ) { RakPeer::UnregisterAsRemoteProcedureCall( uniqueID ); } bool RakClient::RPC( char* uniqueID, const char *data, unsigned int bitLength, PacketPriority priority, PacketReliability reliability, char orderingChannel, bool shiftTimestamp, NetworkID networkID, RakNet::BitStream *replyFromTarget ) { if ( remoteSystemList == 0 ) return false; return RakPeer::RPC( uniqueID, data, bitLength, priority, reliability, orderingChannel, remoteSystemList[ 0 ].playerId, false, shiftTimestamp, networkID, replyFromTarget ); } bool RakClient::RPC( char* uniqueID, RakNet::BitStream *parameters, PacketPriority priority, PacketReliability reliability, char orderingChannel, bool shiftTimestamp, NetworkID networkID, RakNet::BitStream *replyFromTarget ) { if ( remoteSystemList == 0 ) return false; return RakPeer::RPC( uniqueID, parameters, priority, reliability, orderingChannel, remoteSystemList[ 0 ].playerId, false, shiftTimestamp, networkID, replyFromTarget ); } // SAMPSRV (adding this just as a tag for next RakNet upgrade) bool RakClient::RPC( char* uniqueID, RakNet::BitStream *parameters, PacketPriority priority, PacketReliability reliability, char orderingChannel, bool shiftTimestamp ) { if ( remoteSystemList == 0 ) return false; return RakPeer::RPC( uniqueID, parameters, priority, reliability, orderingChannel, remoteSystemList[ 0 ].playerId, false, shiftTimestamp, UNASSIGNED_NETWORK_ID, 0 ); } // SAMPSRV end void RakClient::SetTrackFrequencyTable( bool b ) { RakPeer::SetCompileFrequencyTable( b ); } bool RakClient::GetSendFrequencyTable( unsigned int outputFrequencyTable[ 256 ] ) { return RakPeer::GetOutgoingFrequencyTable( outputFrequencyTable ); } float RakClient::GetCompressionRatio( void ) const { return RakPeer::GetCompressionRatio(); } float RakClient::GetDecompressionRatio( void ) const { return RakPeer::GetDecompressionRatio(); } void RakClient::AttachPlugin( PluginInterface *messageHandler ) { RakPeer::AttachPlugin(messageHandler); } void RakClient::DetachPlugin( PluginInterface *messageHandler ) { RakPeer::DetachPlugin(messageHandler); } RakNet::BitStream * RakClient::GetStaticServerData( void ) { if ( remoteSystemList == 0 ) return 0; return RakPeer::GetRemoteStaticData( remoteSystemList[ 0 ].playerId ); } void RakClient::SetStaticServerData( const char *data, const int length ) { if ( remoteSystemList == 0 ) return ; RakPeer::SetRemoteStaticData( remoteSystemList[ 0 ].playerId, data, length ); } RakNet::BitStream * RakClient::GetStaticClientData( const PlayerID playerId ) { int i; if ( playerId == UNASSIGNED_PLAYER_ID ) { return & localStaticData; } else { i = GetOtherClientIndexByPlayerID( playerId ); if ( i >= 0 ) { return & ( otherClients[ i ].staticData ); } } return 0; } void RakClient::SetStaticClientData( const PlayerID playerId, const char *data, const int length ) { int i; if ( playerId == UNASSIGNED_PLAYER_ID ) { localStaticData.Reset(); localStaticData.Write( data, length ); } else { i = GetOtherClientIndexByPlayerID( playerId ); if ( i >= 0 ) { otherClients[ i ].staticData.Reset(); otherClients[ i ].staticData.Write( data, length ); } else RakPeer::SetRemoteStaticData( playerId, data, length ); } } void RakClient::SendStaticClientDataToServer( void ) { if ( remoteSystemList == 0 ) return ; RakPeer::SendStaticData( remoteSystemList[ 0 ].playerId ); } PlayerID RakClient::GetServerID( void ) const { if ( remoteSystemList == 0 ) return UNASSIGNED_PLAYER_ID; return remoteSystemList[ 0 ].playerId; } PlayerID RakClient::GetPlayerID( void ) const { if ( remoteSystemList == 0 ) return UNASSIGNED_PLAYER_ID; // GetExternalID is more accurate because it reflects our external IP and port to the server. // GetInternalID only matches the parameters we passed PlayerID myID = RakPeer::GetExternalID( remoteSystemList[ 0 ].playerId ); if ( myID == UNASSIGNED_PLAYER_ID ) return RakPeer::GetInternalID(); else return myID; } PlayerID RakClient::GetInternalID( void ) const { return RakPeer::GetInternalID(); } const char* RakClient::PlayerIDToDottedIP( const PlayerID playerId ) const { return RakPeer::PlayerIDToDottedIP( playerId ); } void RakClient::PushBackPacket( Packet *packet, bool pushAtHead ) { RakPeer::PushBackPacket(packet, pushAtHead); } void RakClient::SetRouterInterface( RouterInterface *routerInterface ) { RakPeer::SetRouterInterface(routerInterface); } void RakClient::RemoveRouterInterface( RouterInterface *routerInterface ) { RakPeer::RemoveRouterInterface(routerInterface); } void RakClient::SetTimeoutTime( RakNetTime timeMS ) { RakPeer::SetTimeoutTime( timeMS, GetServerID() ); } bool RakClient::SetMTUSize( int size ) { return RakPeer::SetMTUSize( size ); } int RakClient::GetMTUSize( void ) const { return RakPeer::GetMTUSize(); } void RakClient::AllowConnectionResponseIPMigration( bool allow ) { RakPeer::AllowConnectionResponseIPMigration( allow ); } void RakClient::AdvertiseSystem( const char *host, unsigned short remotePort, const char *data, int dataLength ) { RakPeer::AdvertiseSystem( host, remotePort, data, dataLength ); } RakNetStatisticsStruct* const RakClient::GetStatistics( void ) { return RakPeer::GetStatistics( remoteSystemList[ 0 ].playerId ); } void RakClient::ApplyNetworkSimulator( double maxSendBPS, unsigned short minExtraPing, unsigned short extraPingVariance) { RakPeer::ApplyNetworkSimulator( maxSendBPS, minExtraPing, extraPingVariance ); } bool RakClient::IsNetworkSimulatorActive( void ) { return RakPeer::IsNetworkSimulatorActive(); } int RakClient::GetOtherClientIndexByPlayerID( const PlayerID playerId ) { unsigned i; for ( i = 0; i < 32; i++ ) { if ( otherClients[ i ].playerId == playerId ) return i; } return -1; } int RakClient::GetFreeOtherClientIndex( void ) { unsigned i; for ( i = 0; i < 32; i++ ) { if ( otherClients[ i ].isActive == false ) return i; } return -1; } PlayerIndex RakClient::GetPlayerIndex( void ) { return localPlayerIndex; } #ifdef _MSC_VER #pragma warning( pop ) #endif