/* ======================== idSnapShot::ApplyToExistingState Take uncompressed state in msg and add it to existing state ======================== */ void idSnapShot::ApplyToExistingState( int objId, idBitMsg& msg ) { objectState_t* objectState = FindObjectByID( objId ); if( !verify( objectState != NULL ) ) { return; } if( !objectState->createdFromTemplate ) { // We were created this from a template, so we shouldn't be applying it again if( net_ssTemplateDebug.GetBool() ) { idLib::Printf( "NOT ApplyToExistingState[%d] because object was created from existing base state. %d\n", objId, objectState->expectedSequence ); objectState->Print( "SS STATE" ); } return; } // Debug print the template (spawn) and delta state if( net_ssTemplateDebug.GetBool() ) { idLib::Printf( "\nApplyToExistingState[%d]. buffer size: %d msg size: %d\n", objId, objectState->buffer.Size(), msg.GetSize() ); objectState->Print( "DELTA STATE" ); PrintAlign( "SPAWN STATE" ); for( int i = 0; i < msg.GetSize(); i++ ) { if( InDebugRange( i ) ) { idLib::Printf( "%02X", msg.GetReadData()[i] ); } } idLib::Printf( "\n" ); } // Actually apply it for( objectSize_t i = 0; i < Min( objectState->buffer.Size(), msg.GetSize() ); i++ ) { objectState->buffer[i] += msg.GetReadData()[i]; } // Debug print the final state if( net_ssTemplateDebug.GetBool() ) { objectState->Print( "NEW STATE" ); idLib::Printf( "\n" ); } }
/* ======================== idLobby::UpdateSessionUserOnPeers ======================== */ void idLobby::UpdateSessionUserOnPeers( idBitMsg & msg ) { for ( int p = 0; p < peers.Num(); p++ ) { QueueReliableMessage( p, RELIABLE_UPDATE_SESSION_USER, msg.GetReadData() + msg.GetReadCount(), msg.GetSize() - msg.GetReadCount() ); } HandleUpdateSessionUser( msg ); }
/* ======================== idCommonLocal::NetReadUsercmds ======================== */ void idCommonLocal::NetReadUsercmds( int clientNum, idBitMsg& msg ) { if( clientNum == -1 ) { idLib::Warning( "NetReadUsercmds: Trying to read commands from invalid clientNum %d", clientNum ); return; } // TODO: This shouldn't actually happen. Figure out why it does. // Seen on clients when another client leaves a match. if( msg.GetReadData() == NULL ) { return; } idSerializer ser( msg, false ); usercmd_t fakeCmd; usercmd_t* base = &fakeCmd; usercmd_t lastCmd; bool gotNewCmd = false; idStaticList< usercmd_t, NUM_USERCMD_RELAY > newCmdBuffer; usercmd_t baseCmd = userCmdMgr.NewestUserCmdForPlayer( clientNum ); int curMilliseconds = baseCmd.clientGameMilliseconds; const int numCmds = msg.ReadByte(); for( int i = 0; i < numCmds; i++ ) { usercmd_t newCmd; newCmd.Serialize( ser, *base ); lastCmd = newCmd; base = &lastCmd; int newMilliseconds = newCmd.clientGameMilliseconds; if( newMilliseconds > curMilliseconds ) { if( verify( i < NUM_USERCMD_RELAY ) ) { newCmdBuffer.Append( newCmd ); gotNewCmd = true; curMilliseconds = newMilliseconds; } } } // Push the commands into the buffer. for( int i = 0; i < newCmdBuffer.Num(); ++i ) { userCmdMgr.PutUserCmdForPlayer( clientNum, newCmdBuffer[i] ); } }
void idMultiplayerGame::ReceiveAndPlayVoiceData( const idBitMsg &inMsg ) { int clientNum; if( !gameLocal.serverInfo.GetBool( "si_voiceChat" ) ) { return; } clientNum = inMsg.ReadByte(); soundSystem->PlayVoiceData( clientNum, inMsg.GetReadData(), inMsg.GetRemainingData() ); if( g_voiceChatDebug.GetInteger() & 4 ) { common->Printf( "VC: Playing %d bytes\n", inMsg.GetRemainingData() ); } }
/* =============== idCommonLocal::NetReceiveReliable =============== */ void idCommonLocal::NetReceiveReliable( int peer, int type, idBitMsg & msg ) { int clientNum = Game()->MapPeerToClient( peer ); // Only servers care about the client num. Band-aid for problems related to the host's peerIndex being -1 on clients. if ( common->IsServer() && clientNum == -1 ) { idLib::Warning( "NetReceiveReliable: Could not find client for peer %d", peer ); return; } const byte * msgData = msg.GetReadData() + msg.GetReadCount(); int msgSize = msg.GetRemainingData(); reliableMsg_t & reliable = reliableQueue.Alloc(); reliable.client = clientNum; reliable.type = type; reliable.dataSize = msgSize; reliable.data = (byte *)Mem_Alloc( msgSize, TAG_NETWORKING ); memcpy( reliable.data, msgData, msgSize ); }
void idMultiplayerGame::ReceiveAndForwardVoiceData( int clientNum, const idBitMsg &inMsg, int messageType ) { assert( clientNum >= 0 && clientNum < MAX_CLIENTS ); idBitMsg outMsg; int i; byte msgBuf[MAX_VOICE_PACKET_SIZE + 2]; idPlayer * from; from = ( idPlayer * )gameLocal.entities[clientNum]; if( !gameLocal.serverInfo.GetBool( "si_voiceChat" ) || !from ) { return; } // Create a new packet with forwarded data outMsg.Init( msgBuf, sizeof( msgBuf ) ); outMsg.WriteByte( GAME_UNRELIABLE_MESSAGE_VOICEDATA_SERVER ); outMsg.WriteByte( clientNum ); outMsg.WriteData( inMsg.GetReadData(), inMsg.GetRemainingData() ); if( g_voiceChatDebug.GetInteger() & 2 ) { common->Printf( "VC: Received %d bytes, forwarding...\n", inMsg.GetRemainingData() ); } // Forward to appropriate parties for( i = 0; i < gameLocal.numClients; i++ ) { idPlayer* to = ( idPlayer * )gameLocal.entities[i]; if( to && to->GetUserInfo() && to->GetUserInfo()->GetBool( "s_voiceChatReceive" ) ) { if( i != gameLocal.localClientNum && CanTalk( from, to, !!( messageType & 1 ) ) ) { if( messageType & 2 ) { // If "from" is testing - then only send back to him if( from == to ) { gameLocal.SendUnreliableMessage( outMsg, to->entityNumber ); } } else { if( to->AllowedVoiceDest( from->entityNumber ) ) { gameLocal.SendUnreliableMessage( outMsg, to->entityNumber ); if( g_voiceChatDebug.GetInteger() & 2 ) { common->Printf( " ... to client %d\n", to->entityNumber ); } } else { if( g_voiceChatDebug.GetInteger() ) { common->Printf( " ... suppressed packet to client %d\n", to->entityNumber ); } } } } } } #ifdef _USE_VOICECHAT // Listen servers need to manually call the receive function if ( gameLocal.isListenServer ) { // Skip over control byte outMsg.ReadByte(); idPlayer* to = gameLocal.GetLocalPlayer(); if( to->GetUserInfo()->GetBool( "s_voiceChatReceive" ) ) { if( CanTalk( from, to, !!( messageType & 1 ) ) ) { if( messageType & 2 ) { // If "from" is testing - then only send back to him if( from == to ) { ReceiveAndPlayVoiceData( outMsg ); } } else { if( to->AllowedVoiceDest( from->entityNumber ) ) { if( g_voiceChatDebug.GetInteger() & 2 ) { common->Printf( " ... to local client %d\n", gameLocal.localClientNum ); } ReceiveAndPlayVoiceData( outMsg ); } } } } } #endif }