bool CGameClient::ProcessMove(CLC_Move *msg) { // Don't process usercmds until the client is active. If we do, there can be weird behavior // like the game trying to send reliable messages to the client and having those messages discarded. if ( !IsActive() ) return true; if ( m_LastMovementTick == sv.m_nTickCount ) { // Only one movement command per frame, someone is cheating. return true; } m_LastMovementTick = sv.m_nTickCount; int totalcmds =msg->m_nBackupCommands + msg->m_nNewCommands; // Decrement drop count by held back packet count int netdrop = m_NetChannel->GetDropNumber(); bool ignore = !sv.IsActive(); #ifdef SWDS bool paused = sv.IsPaused(); #else bool paused = sv.IsPaused() || ( !sv.IsMultiplayer() && Con_IsVisible() ); #endif // Make sure player knows of correct server time g_ServerGlobalVariables.curtime = sv.GetTime(); g_ServerGlobalVariables.frametime = host_state.interval_per_tick; // COM_Log( "sv.log", " executing %i move commands from client starting with command %i(%i)\n", // numcmds, // m_Client->m_NetChan->incoming_sequence, // m_Client->m_NetChan->incoming_sequence & SV_UPDATE_MASK ); int startbit = msg->m_DataIn.GetNumBitsRead(); serverGameClients->ProcessUsercmds ( edict, // Player edict &msg->m_DataIn, msg->m_nNewCommands, totalcmds, // Commands in packet netdrop, // Number of dropped commands ignore, // Don't actually run anything paused // Run, but don't actually do any movement ); if ( msg->m_DataIn.IsOverflowed() ) { Disconnect( "ProcessUsercmds: Overflowed reading usercmd data (check sending and receiving code for mismatches)!\n" ); return false; } int endbit = msg->m_DataIn.GetNumBitsRead(); if ( msg->m_nLength != (endbit-startbit) ) { Disconnect( "ProcessUsercmds: Incorrect reading frame (check sending and receiving code for mismatches)!\n" ); return false; } return true; }
/* ============================== SV_ParseMove ============================== */ void SV_ParseMove(client_t *cl) { int numbackup = 2; int numcmds; int totalcmds; client_frame_t *frame; bf_read *pBuf = MSG_GetReadBuf(); if ( g_lastmovementtick == sv.tickcount ) // Only one movement command per frame, someone is cheating. { pBuf->SetOverflowFlag(); return; } g_lastmovementtick = sv.tickcount; // Calculate ping time for client based on last frame that the client ack'd frame = &host_client->frames[ host_client->netchan.incoming_acknowledged & SV_UPDATE_MASK ]; cl->m_bLoopback = !!pBuf->ReadOneBit(); numbackup = pBuf->ReadUBitLong( NUM_BACKUP_COMMAND_BITS );; numcmds = pBuf->ReadByte(); totalcmds = numbackup + numcmds; // Decrement drop count by held back packet count net_drop -= ( numcmds - 1 ); bool ignore = !sv.active || ( !host_client->active && !host_client->spawned ); #ifdef SWDS bool paused = ( sv.paused || ( (svs.maxclients <= 1) ) ); #else bool paused = ( sv.paused || ( (svs.maxclients <= 1) && (Con_IsVisible()) ) ); #endif // Make sure player knows of correct server time g_ServerGlobalVariables.curtime = sv.gettime(); g_ServerGlobalVariables.frametime = TICK_RATE; // COM_Log( "sv.log", " executing %i move commands from client starting with command %i(%i)\n", // numcmds, // host_client->netchan.incoming_sequence, // host_client->netchan.incoming_sequence & SV_UPDATE_MASK ); float lastcmdtime = serverGameClients->ProcessUsercmds ( sv_player, // Player edict pBuf, numcmds, totalcmds, // Commands in packet net_drop, // Number of dropped commands ignore, // Don't actually run anything paused // Run, but don't actually do any movement ); // Adjust latency time by 1/2 last client frame since the message probably arrived 1/2 through client's frame loop frame->latency -= 0.5 * lastcmdtime; frame->latency = max( 0.0f, frame->latency ); if ( pBuf->IsOverflowed() ) { SV_DropClient( host_client, false, "ProcessUsercmds: Overflowed reading usercmd data (check sending and receiving code for mismatches)!\n" ); return; } unsigned int tag = pBuf->ReadUBitLong( 32 ); if ( tag != 0xffffffff ) { SV_DropClient( host_client, false, "ProcessUsercmds: Incorrect reading frame (check sending and receiving code for mismatches)!\n" ); pBuf->SetOverflowFlag(); return; } }