void CLocalPlayer::SendOnFootFullSyncData() { if(m_pPlayerPed) { RakNet::BitStream bsPlayerSync; PLAYER_SYNC_DATA playerSyncData; // write packet id bsPlayerSync.Write((MessageID)ID_PLAYER_SYNC); // get the player keys playerSyncData.wKeys = m_pPlayerPed->GetKeys(); // get the player position m_pPlayerPed->GetPosition(&playerSyncData.vecPos); // get the player rotation playerSyncData.fRotation = m_pPlayerPed->GetRotation(); // get player current weapon (casted to a byte to save space) playerSyncData.byteCurrentWeapon = m_pPlayerPed->GetCurrentWeapon(); // get player shooting flags playerSyncData.byteShootingFlags = m_pPlayerPed->GetShootingFlags(); // get player health (casted to a byte to save space) playerSyncData.byteHealth = (BYTE)m_pPlayerPed->GetHealth(); // get player armour (casted to a byte to save space) playerSyncData.byteArmour = (BYTE)m_pPlayerPed->GetArmour(); // write player sync data struct bsPlayerSync.Write((char *)&playerSyncData, sizeof(PLAYER_SYNC_DATA)); // send aiming data if player has fire key held down and we have ammo if(m_pPlayerPed->IsFiring() && m_pPlayerPed->HasAmmoForCurrentWeapon()) { // write a 1 bit to say the bit stream has aim sync data bsPlayerSync.Write1(); // get the camera pointer CAMERA_TYPE * pCamera = pGame->GetCamera()->GetCamera(); // write the aim sync data bsPlayerSync.Write((char *)&pCamera->aim, sizeof(CAMERA_AIM)); } else { // write a 0 bit to say the bit stream has no aim sync data bsPlayerSync.Write0(); } // send sync data pNetowkManager->GetRakPeer()->Send(&bsPlayerSync,HIGH_PRIORITY,UNRELIABLE_SEQUENCED,0,UNASSIGNED_SYSTEM_ADDRESS,TRUE); } }
void CPlayer::BroadcastSyncData() { RakNet::BitStream bsSync; if(m_byteUpdateFromNetwork == UPDATE_TYPE_FULL_ONFOOT) { PLAYER_SYNC_DATA playerSyncData; bsSync.Write((MessageID)ID_PLAYER_SYNC); bsSync.Write(m_bytePlayerID); playerSyncData.wKeys = m_wKeys; memcpy(&playerSyncData.vecPos, &m_vecPos, sizeof(Vector3)); playerSyncData.fRotation = m_fRotation; playerSyncData.byteCurrentWeapon = m_byteCurrentWeapon; playerSyncData.byteShootingFlags = m_byteShootingFlags; playerSyncData.byteHealth = m_byteHealth; playerSyncData.byteArmour = m_byteArmour; bsSync.Write((char *)&playerSyncData, sizeof(PLAYER_SYNC_DATA)); if(m_bHasAim) { bsSync.Write1(); bsSync.Write((char *)&m_Aiming, sizeof(S_CAMERA_AIM)); m_bHasAim = false; } else { bsSync.Write0(); } pNetowkManager->BroadcastData(&bsSync,HIGH_PRIORITY,UNRELIABLE_SEQUENCED,0,m_bytePlayerID); } else if(m_byteUpdateFromNetwork == UPDATE_TYPE_FULL_INCAR) { VEHICLE_SYNC_DATA vehicleSyncData; bsSync.Write((MessageID)ID_VEHICLE_SYNC); bsSync.Write(m_bytePlayerID); vehicleSyncData.vehicleID = m_vehicleID; vehicleSyncData.wKeys = m_wKeys; memcpy(&vehicleSyncData.vecRoll, &m_vecRoll, sizeof(Vector3)); memcpy(&vehicleSyncData.vecDirection, &m_vecDirection, sizeof(Vector3)); memcpy(&vehicleSyncData.vecPos, &m_vecPos, sizeof(Vector3)); memcpy(&vehicleSyncData.vecMoveSpeed, &m_vecMoveSpeed, sizeof(Vector3)); memcpy(&vehicleSyncData.vecTurnSpeed, &m_vecTurnSpeed, sizeof(Vector3)); vehicleSyncData.byteVehicleHealth = PACK_VEHICLE_HEALTH(m_fVehicleHealth); vehicleSyncData.bytePlayerHealth = m_byteHealth; vehicleSyncData.bytePlayerArmour = m_byteArmour; bsSync.Write((char *)&vehicleSyncData, sizeof(VEHICLE_SYNC_DATA)); pNetowkManager->BroadcastData(&bsSync,HIGH_PRIORITY,UNRELIABLE_SEQUENCED,0,m_bytePlayerID); } }
void NetworkEngine::updatePingResponse() { RakNet::BitStream data; if(isLobby()) { data.Write1(); unsigned char numPlayers = (unsigned char) peer->NumberOfConnections(); data.Write(numPlayers); std::cout << "Total players: " << (unsigned int) numPlayers << std::endl; peer->SetOfflinePingResponse((char *)data.GetData(), data.GetNumberOfBytesUsed()); } else { data.Write0(); } peer->SetOfflinePingResponse((char *)data.GetData(), data.GetNumberOfBytesUsed()); }
void NetworkManager::sendMessage(const short id, const char *data, const short len, Client *destination) { RakNet::BitStream bs; bs.Write(id); if (data && len > 0) { bs.Write(len); bs.Write(data,len); } else bs.Write((short)0); SystemAddress recipient; if (destination) { recipient = destination->getSystemAddress(); bs.Write1(); } else { recipient = UNASSIGNED_SYSTEM_ADDRESS; bs.Write0(); } rakPeer->RPC("NetworkManager::RPC_Message",&bs, HIGH_PRIORITY, RELIABLE_ORDERED, 0, recipient, (destination ? false : true), 0, UNASSIGNED_NETWORK_ID,0); }
// Given a frequency table of 256 elements, all with a frequency of 1 or more, generate the tree void HuffmanEncodingTree::GenerateFromFrequencyTable( unsigned int frequencyTable[ 256 ] ) { int counter; HuffmanEncodingTreeNode * node; HuffmanEncodingTreeNode *leafList[ 256 ]; // Keep a copy of the pointers to all the leaves so we can generate the encryption table bottom-up, which is easier // 1. Make 256 trees each with a weight equal to the frequency of the corresponding character DataStructures::LinkedList<HuffmanEncodingTreeNode *> huffmanEncodingTreeNodeList; FreeMemory(); for ( counter = 0; counter < 256; counter++ ) { node = new HuffmanEncodingTreeNode; node->left = 0; node->right = 0; node->value = (unsigned char) counter; node->weight = frequencyTable[ counter ]; if ( node->weight == 0 ) node->weight = 1; // 0 weights are illegal leafList[ counter ] = node; // Used later to generate the encryption table InsertNodeIntoSortedList( node, &huffmanEncodingTreeNodeList ); // Insert and maintain sort order. } // 2. While there is more than one tree, take the two smallest trees and merge them so that the two trees are the left and right // children of a new node, where the new node has the weight the sum of the weight of the left and right child nodes. #ifdef _MSC_VER #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant #endif while ( 1 ) { huffmanEncodingTreeNodeList.Beginning(); HuffmanEncodingTreeNode *lesser, *greater; lesser = huffmanEncodingTreeNodeList.Pop(); greater = huffmanEncodingTreeNodeList.Pop(); node = new HuffmanEncodingTreeNode; node->left = lesser; node->right = greater; node->weight = lesser->weight + greater->weight; lesser->parent = node; // This is done to make generating the encryption table easier greater->parent = node; // This is done to make generating the encryption table easier if ( huffmanEncodingTreeNodeList.Size() == 0 ) { // 3. Assign the one remaining node in the list to the root node. root = node; root->parent = 0; break; } // Put the new node back into the list at the correct spot to maintain the sort. Linear search time InsertNodeIntoSortedList( node, &huffmanEncodingTreeNodeList ); } bool tempPath[ 256 ]; // Maximum path length is 256 unsigned short tempPathLength; HuffmanEncodingTreeNode *currentNode; RakNet::BitStream bitStream; // Generate the encryption table. From before, we have an array of pointers to all the leaves which contain pointers to their parents. // This can be done more efficiently but this isn't bad and it's way easier to program and debug for ( counter = 0; counter < 256; counter++ ) { // Already done at the end of the loop and before it! tempPathLength = 0; // Set the current node at the leaf currentNode = leafList[ counter ]; do { if ( currentNode->parent->left == currentNode ) // We're storing the paths in reverse order.since we are going from the leaf to the root tempPath[ tempPathLength++ ] = false; else tempPath[ tempPathLength++ ] = true; currentNode = currentNode->parent; } while ( currentNode != root ); // Write to the bitstream in the reverse order that we stored the path, which gives us the correct order from the root to the leaf while ( tempPathLength-- > 0 ) { if ( tempPath[ tempPathLength ] ) // Write 1's and 0's because writing a bool will write the BitStream TYPE_CHECKING validation bits if that is defined along with the actual data bit, which is not what we want bitStream.Write1(); else bitStream.Write0(); } // Read data from the bitstream, which is written to the encoding table in bits and bitlength. Note this function allocates the encodingTable[counter].encoding pointer encodingTable[ counter ].bitLength = ( unsigned char ) bitStream.CopyData( &encodingTable[ counter ].encoding ); // Reset the bitstream for the next iteration bitStream.Reset(); } }
void CChat::ProcessInput( void ) { // Are we not connected? if( !pCore->GetNetworkModule() || !pCore->GetNetworkModule()->IsConnected() ) return; // Was anything entered? if( m_strInput.GetLength() > 0 ) { // Is the input a command? bool bIsCommand = (m_strInput.GetChar( 0 ) == CHAT_CMD_CHAR); // Internal cmds bool bHasUsedCmd = false; // Process internal commands if( bIsCommand ) { // std::string sInput = m_strInput.Get(); // Get the end of the command size_t sCommandEnd = sInput.find( " " ); // If we don't have a valid end use the end of the string if ( sCommandEnd == std::string::npos ) sCommandEnd = sInput.length(); // Get the command name std::string strCommand = sInput.substr( 1, (sCommandEnd - 1) ); // Get the command parameters std::string strParams; // Do we have any parameters? if( sCommandEnd < sInput.length() ) strParams = sInput.substr( (sCommandEnd + 1), sInput.length() ); if( strCommand == "q" || strCommand == "quit" || strCommand == "exit" ) { // Shutdown pCore->Shutdown(); return; } else if( strCommand == "disconnect" ) { // Are we connected? if( pCore->GetNetworkModule() && pCore->GetNetworkModule()->IsConnected() ) { // Disconnect from the network pCore->GetNetworkModule()->Disconnect(); // Stop multiplayer pCore->StopMultiplayer(); // Go back to main menu pCore->GetGUI()->GetMainMenu()->SetVisible( true ); } bHasUsedCmd = true; } else if( strCommand == "savepos" ) { bHasUsedCmd = true; // Are we spawned? if( pCore->GetPlayerManager()->GetLocalPlayer()->IsSpawned() ) { // CVector3 vecPosition; CVector3 vecRotation; bool bOnFoot = true; // Is the player on-foot? if( pCore->GetPlayerManager()->GetLocalPlayer()->GetState() == ePlayerState::PLAYERSTATE_ONFOOT ) { // Get the localplayer position pCore->GetPlayerManager()->GetLocalPlayer()->GetPosition( &vecPosition ); // Get the localplayer rotation pCore->GetPlayerManager()->GetLocalPlayer()->GetRotation( &vecRotation ); } else if( pCore->GetPlayerManager()->GetLocalPlayer()->GetState() == ePlayerState::PLAYERSTATE_DRIVER || pCore->GetPlayerManager()->GetLocalPlayer()->GetState() == ePlayerState::PLAYERSTATE_PASSENGER ) { // Get the vehicle position pCore->GetPlayerManager()->GetLocalPlayer()->GetVehicle()->GetPosition( &vecPosition ); // Get the vehicle rotation pCore->GetPlayerManager()->GetLocalPlayer()->GetVehicle()->GetRotation( &vecRotation ); // bOnFoot = false; } // Open the saved positions file FILE * pFile = fopen( SharedUtility::GetAbsolutePath( "data\\savedpositions.txt" ).Get(), "a" ); // Did the file open? if( pFile ) { // Get the localplayer pointer CLocalPlayer * pLocalPlayer = pCore->GetPlayerManager()->GetLocalPlayer(); // Save the player position fprintf( pFile, "%d, %f, %f, %f, %f, %f, %f // %s\n", (bOnFoot ? pLocalPlayer->GetModel () : pLocalPlayer->GetVehicle()->GetModel ()), vecPosition.fX, vecPosition.fY, vecPosition.fZ, vecRotation.fX, vecRotation.fY, vecRotation.fZ, strParams.c_str() ); // Close the saved positions file fclose( pFile ); // AddInfoMessage( (bOnFoot ? " -> Onfoot position saved!" : " -> Invehicle position saved!") ); } else { // AddInfoMessage( CColor( 255, 0, 0, 255 ), "Failed to open savedpositions.txt" ); } } } #ifdef DEBUG else if( strCommand == "lua" ) { bHasUsedCmd = true; if( CLua::Execute( strParams.c_str() ) ) AddInfoMessage( CColor( 50, 177, 94, 255 ), strParams.c_str() ); else AddInfoMessage( CColor( 178, 40, 86, 255 ), strParams.c_str() ); } #endif } // Have we used a command? if( bHasUsedCmd ) { // Add this command to the history AddToHistory(); // This is an internal command, don't pass it to the server! return; } // Is the network module instance valid? if( pCore->GetNetworkModule() ) { // Are we connected? if( pCore->GetNetworkModule()->IsConnected() ) { RakNet::BitStream bitStream; RakNet::RakString strInput; // Is this a command? if( bIsCommand ) { // Write 1 bitStream.Write1(); // Set the input minus the command character strInput = (GetInputText() + 1); } else { // Write 0 bitStream.Write0(); // Set the input strInput = GetInputText(); } // Write the input bitStream.Write( strInput ); // Call the client event CSquirrelArguments pArguments; pArguments.push( strInput.C_String () ); // Should we send this message? if ( pCore->GetClientScriptingManager()->GetEvents()->Call( "onClientChat", &pArguments ).GetInteger() == 1 ) { // Send it to the server pCore->GetNetworkModule()->Call( RPC_PLAYER_CHAT, &bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, true ); // Add this message to the history AddToHistory(); // Add the chat message for the localplayer if it's not a command if ( !bIsCommand ) AddChatMessage( pCore->GetPlayerManager()->GetLocalPlayer(), GetInputText() ); } } } } }
void PlayerManager::HandlePacket(RakNet::Packet *packet) { RakNet::BitStream receivedData(packet->data, packet->length, false); RakNetwork *network = m_Network; RakNetGUID remotePeerGUID = packet->guid; unsigned char type; receivedData.Read(type); if (type == ID_NEW_INCOMING_CONNECTION) { // Notify new peers about the existing players if (NetworkManager::ArbitratorIsLocal()) { for (auto it = PlayerRegistry::PlayersBegin(), end = PlayerRegistry::PlayersEnd(); it != end; ++it) { RakNet::BitStream newPlayerNotification; newPlayerNotification.Write0(); // Tell the peer that the player is on another system newPlayerNotification.Write(it->NetID); if (it->LocalIndex >= s_MaxLocalPlayers) newPlayerNotification.Write(it->GUID); // Remote player (relative to this arbitrator) else newPlayerNotification.Write(NetworkManager::GetNetwork()->GetLocalGUID()); // Local player network->Send( NetDestination(remotePeerGUID, false), !Timestamped, MTID_ADDPLAYER, &newPlayerNotification, MEDIUM_PRIORITY, RELIABLE_ORDERED, CID_SYSTEM); } } } else if (type == MTID_ADDPLAYER) { if (NetworkManager::ArbitratorIsLocal()) { // So we can tell the remote peer what requested player we are adding: unsigned int remotePlayerIndex; receivedData.Read(remotePlayerIndex); PlayerID netId = m_NextNetId++;//m_UnusedNetIds.getFreeID(); PlayerRegistry::AddRemotePlayer(netId, remotePeerGUID); { RakNet::BitStream response; response.Write1(); // Tell the peer that the player being added is on their system response.Write(netId); response.Write(remotePlayerIndex); network->Send( NetDestination(remotePeerGUID, false), !Timestamped, MTID_ADDPLAYER, &response, MEDIUM_PRIORITY, RELIABLE_ORDERED, CID_SYSTEM); } { RakNet::BitStream newPlayerNotification; newPlayerNotification.Write0(); // Tell the peer that the player being added is on another system newPlayerNotification.Write(netId); newPlayerNotification.Write(remotePeerGUID); network->Send( NetDestination(remotePeerGUID, true), // Broadcast !Timestamped, MTID_ADDPLAYER, &newPlayerNotification, MEDIUM_PRIORITY, RELIABLE_ORDERED, CID_SYSTEM); } } else { bool localPlayer = receivedData.ReadBit(); // The net ID the arbiter has assigned to the new player: PlayerID netId; receivedData.Read(netId); if (localPlayer) { unsigned int localIndex; receivedData.Read(localIndex); PlayerRegistry::AddLocalPlayer(netId, localIndex); } else { RakNetGUID guid; receivedData.Read(guid); PlayerRegistry::AddRemotePlayer(netId, guid); } } } else if (type == MTID_REMOVEPLAYER) { PlayerID netId; receivedData.Read(netId); PlayerRegistry::RemovePlayer(netId); } }
void CLocalPlayer::OnLeaveVehicle( void ) { // Set the player state SetState( PLAYERSTATE_ONFOOT ); // Is the vehicle instance valid? if( m_pVehicle ) { // Get the seat of this player EntityId seat = m_seat; // Construct a new bitstream RakNet::BitStream pBitStream; // Write the vehicle id pBitStream.WriteCompressed( m_pVehicle->GetId() ); // Write the seat pBitStream.WriteCompressed( seat ); // Write if we're exiting quickly! m_bFastExitVehicle ? pBitStream.Write1() : pBitStream.Write0(); // Send to the server pCore->GetNetworkModule()->Call( RPC_EXIT_VEHICLE, &pBitStream, HIGH_PRIORITY, RELIABLE_ORDERED, true ); #ifdef DEBUG pCore->GetChat()->AddDebugMessage( "CLocalPlayer::OnExitVehicle( %d, %d ) - Forcefully: %s", m_pVehicle->GetId(), seat, (IsBeingRemovedForcefully () ? "Yes" : "No") ); #endif // Are we not being removed forcefully? if ( !IsBeingRemovedForcefully () ) { // Handle this enter with the network vehicle m_pVehicle->HandlePlayerExit( this, seat, false ); // Do we need to respawn this vehicle? (Set to true when vehicle enters water) if( bRespawnVehicle && m_seat == 0 ) { // Respawn the vehicle m_pVehicle->Respawn(); // bRespawnVehicle = false; } // Are we a passenger? if( m_seat > 0 ) { // Restore the player controls LockControls( bOldControlState ); // Restore the camera lock state pCore->GetCamera()->LockControl( bOldCameraState ); // *(DWORD *)(m_pPlayerPed->GetPed() + 0x310) = 6; } } // Reset the vehicle SetVehicle( NULL ); // Reset the seat SetSeat( INVALID_ENTITY_ID ); // Reset the target data SetEnteringVehicle( NULL, INVALID_ENTITY_ID ); // Reset the fast vehicle exit flag FlagForFastExitVehicle ( false ); // Reset the forceful exit flag SetRemoveForcefully ( false ); } }