diff --git a/common/netmessages.cpp b/common/netmessages.cpp index 699f483b90..aaf709c3cd 100644 --- a/common/netmessages.cpp +++ b/common/netmessages.cpp @@ -1032,8 +1032,10 @@ const char *SVC_VoiceData::ToString(void) const bool NET_Tick::WriteToBuffer( bf_write &buffer ) { + VPROF( "NET_Tick::WriteToBuffer" ); buffer.WriteUBitLong( GetType(), NETMSG_TYPE_BITS ); buffer.WriteLong( m_nTick ); + buffer.WriteLong( m_nLagTick ); #if PROTOCOL_VERSION > 10 buffer.WriteUBitLong( clamp( (int)( NET_TICK_SCALEUP * m_flHostFrameTime ), 0, 65535 ), 16 ); buffer.WriteUBitLong( clamp( (int)( NET_TICK_SCALEUP * m_flHostFrameTimeStdDeviation ), 0, 65535 ), 16 ); @@ -1046,6 +1048,7 @@ bool NET_Tick::ReadFromBuffer( bf_read &buffer ) VPROF( "NET_Tick::ReadFromBuffer" ); m_nTick = buffer.ReadLong(); + m_nLagTick = buffer.ReadLong(); #if PROTOCOL_VERSION > 10 m_flHostFrameTime = (float)buffer.ReadUBitLong( 16 ) / NET_TICK_SCALEUP; m_flHostFrameTimeStdDeviation = (float)buffer.ReadUBitLong( 16 ) / NET_TICK_SCALEUP; @@ -1055,7 +1058,7 @@ bool NET_Tick::ReadFromBuffer( bf_read &buffer ) const char *NET_Tick::ToString(void) const { - Q_snprintf(s_text, sizeof(s_text), "%s: tick %i", GetName(), m_nTick ); + Q_snprintf(s_text, sizeof(s_text), "%s: tick %i, lagtick %i", GetName(), m_nTick, m_nLagTick ); return s_text; } diff --git a/common/netmessages.h b/common/netmessages.h index b9064bafd9..4d11e6d332 100644 --- a/common/netmessages.h +++ b/common/netmessages.h @@ -144,18 +144,21 @@ class NET_Tick : public CNetMessage DECLARE_NET_MESSAGE( Tick ); NET_Tick() - { - m_bReliable = false; + { + m_bReliable = false; + m_nTick = 0; + m_nLagTick = 0; #if PROTOCOL_VERSION > 10 m_flHostFrameTime = 0; m_flHostFrameTimeStdDeviation = 0; #endif }; - NET_Tick( int tick, float hostFrametime, float hostFrametime_stddeviation ) + NET_Tick( int tick, int lagTick, float hostFrametime, float hostFrametime_stddeviation ) { - m_bReliable = false; - m_nTick = tick; + m_bReliable = false; + m_nTick = tick; + m_nLagTick = lagTick; #if PROTOCOL_VERSION > 10 m_flHostFrameTime = hostFrametime; m_flHostFrameTimeStdDeviation = hostFrametime_stddeviation; @@ -166,7 +169,8 @@ class NET_Tick : public CNetMessage }; public: - int m_nTick; + int m_nTick; + int m_nLagTick; #if PROTOCOL_VERSION > 10 float m_flHostFrameTime; float m_flHostFrameTimeStdDeviation; diff --git a/engine/baseclient.cpp b/engine/baseclient.cpp index 63631cc213..32cb018358 100644 --- a/engine/baseclient.cpp +++ b/engine/baseclient.cpp @@ -529,7 +529,7 @@ void CBaseClient::SpawnPlayer( void ) } // Set client clock to match server's - NET_Tick tick( m_Server->GetTick(), host_frametime_unbounded, host_frametime_stddeviation ); + NET_Tick tick( m_Server->GetTick(), m_nClientTick, host_frametime_unbounded, host_frametime_stddeviation ); SendNetMsg( tick, true ); // Spawned into server, not fully active, though @@ -717,7 +717,7 @@ bool CBaseClient::SendServerInfo( void ) // send first tick m_nSignonTick = m_Server->m_nTickCount; - NET_Tick signonTick( m_nSignonTick, 0, 0 ); + NET_Tick signonTick( m_nSignonTick, m_nClientTick, 0, 0 ); signonTick.WriteToBuffer( msg ); // write stringtable baselines @@ -794,6 +794,7 @@ void CBaseClient::ConnectionStart(INetChannel *chan) bool CBaseClient::ProcessTick( NET_Tick *msg ) { m_NetChannel->SetRemoteFramerate( msg->m_flHostFrameTime, msg->m_flHostFrameTimeStdDeviation ); + m_nClientTick = msg->m_nLagTick; return UpdateAcknowledgedFramecount( msg->m_nTick ); } @@ -1179,7 +1180,7 @@ write_again: } // send tick time - NET_Tick tickmsg( pFrame->tick_count, host_frametime_unbounded, host_frametime_stddeviation ); + NET_Tick tickmsg( pFrame->tick_count, m_nClientTick, host_frametime_unbounded, host_frametime_stddeviation ); StartTrace( msg ); diff --git a/engine/baseclient.h b/engine/baseclient.h index b399f9e6bb..5f2a14c123 100644 --- a/engine/baseclient.h +++ b/engine/baseclient.h @@ -230,6 +230,7 @@ public: int m_nSignonState; // connection state int m_nDeltaTick; // -1 = no compression. This is where the server is creating the // compressed info from. + int m_nClientTick; int m_nStringTableAckTick; // Highest tick acked for string tables (usually m_nDeltaTick, except when it's -1) int m_nSignonTick; // tick the client got his signon data CSmartPtr m_pLastSnapshot; // last send snapshot diff --git a/engine/baseclientstate.cpp b/engine/baseclientstate.cpp index 282938e2a4..35463f3112 100644 --- a/engine/baseclientstate.cpp +++ b/engine/baseclientstate.cpp @@ -1010,8 +1010,9 @@ bool CBaseClientState::ProcessTick( NET_Tick *msg ) // Note: CClientState separates the client and server clock states and drifts // the client's clock to match the server's, but right here, we keep the two clocks in sync. - SetClientTickCount( msg->m_nTick ); - SetServerTickCount( msg->m_nTick ); + SetClientTickCount( msg->m_nTick ); + SetServerTickCount( msg->m_nTick ); + m_ClockDriftMgr.m_nLaggedClientTick = msg->m_nLagTick; if ( m_StringTableContainer ) { diff --git a/engine/cl_main.cpp b/engine/cl_main.cpp index b86515f36d..e11b78249f 100644 --- a/engine/cl_main.cpp +++ b/engine/cl_main.cpp @@ -518,19 +518,6 @@ void CL_ReadPackets ( bool bFinalTick ) // update client times/tick cl.oldtickcount = cl.GetServerTickCount(); - if ( !cl.IsPaused() ) - { - cl.SetClientTickCount( cl.GetClientTickCount() + 1 ); - - // While clock correction is off, we have the old behavior of matching the client and server clocks. - if ( !CClockDriftMgr::IsClockCorrectionEnabled() ) - cl.SetServerTickCount( cl.GetClientTickCount() ); - - g_ClientGlobalVariables.tickcount = cl.GetClientTickCount(); - g_ClientGlobalVariables.curtime = cl.GetTime(); - } - // 0 or tick_rate if simulating - g_ClientGlobalVariables.frametime = cl.GetFrameTime(); // read packets, if any in queue if ( demoplayer->IsPlayingBack() && cl.m_NetChannel ) @@ -574,6 +561,26 @@ void CL_ReadPackets ( bool bFinalTick ) } #endif + // Moved after process socket so we can receive the lastest updates. + if ( !cl.IsPaused() ) + { + // While clock correction is off, we have the old behavior of matching the client and server clocks. + if (!CClockDriftMgr::IsClockCorrectionEnabled()) + { + cl.SetClientTickCount(cl.GetClientTickCount() + 1); + cl.SetServerTickCount(cl.GetClientTickCount()); + } + else + { + cl.m_ClockDriftMgr.ApplyClockCorrection(bFinalTick); + } + + g_ClientGlobalVariables.tickcount = cl.GetClientTickCount(); + g_ClientGlobalVariables.curtime = cl.GetTime(); + } + // 0 or tick_rate if simulating + g_ClientGlobalVariables.frametime = cl.GetFrameTime(); + } //----------------------------------------------------------------------------- @@ -2128,8 +2135,6 @@ void CL_SendMove( void ) void CL_Move(float accumulated_extra_samples, bool bFinalTick ) { - CL_ReadPackets(bFinalTick); - if ( !cl.IsConnected() ) return; @@ -2228,10 +2233,10 @@ void CL_Move(float accumulated_extra_samples, bool bFinalTick ) } if ( cl.IsActive() ) - { - NET_Tick mymsg( cl.m_nDeltaTick, host_frametime_unbounded, host_frametime_stddeviation ); + { + NET_Tick mymsg( cl.m_nDeltaTick, cl.m_ClockDriftMgr.m_nCachedRealClientTick, host_frametime_unbounded, host_frametime_stddeviation ); cl.m_NetChannel->SendNetMsg( mymsg ); - } + } //COM_Log( "cl.log", "Sending command number %i(%i) to server\n", cl.m_NetChan->m_nOutSequenceNr, cl.m_NetChan->m_nOutSequenceNr & CL_UPDATE_MASK ); diff --git a/engine/clockdriftmgr.cpp b/engine/clockdriftmgr.cpp index 45d725c360..de5430c93d 100644 --- a/engine/clockdriftmgr.cpp +++ b/engine/clockdriftmgr.cpp @@ -19,33 +19,6 @@ ConVar cl_clockdrift_max_ms_threadmode( "cl_clockdrift_max_ms_threadmode", "0", ConVar cl_clock_showdebuginfo( "cl_clock_showdebuginfo", "0", FCVAR_CHEAT, "Show debugging info about the clock drift. "); ConVar cl_clock_correction_force_server_tick( "cl_clock_correction_force_server_tick", "999", FCVAR_CHEAT, "Force clock correction to match the server tick + this offset (-999 disables it)." ); - -ConVar cl_clock_correction_adjustment_max_amount( "cl_clock_correction_adjustment_max_amount", "200", FCVAR_CHEAT, - "Sets the maximum number of milliseconds per second it is allowed to correct the client clock. " - "It will only correct this amount if the difference between the client and server clock is equal to or larger than cl_clock_correction_adjustment_max_offset." ); - -ConVar cl_clock_correction_adjustment_min_offset( "cl_clock_correction_adjustment_min_offset", "10", FCVAR_CHEAT, - "If the clock offset is less than this amount (in milliseconds), then no clock correction is applied." ); - -ConVar cl_clock_correction_adjustment_max_offset( "cl_clock_correction_adjustment_max_offset", "90", FCVAR_CHEAT, - "As the clock offset goes from cl_clock_correction_adjustment_min_offset to this value (in milliseconds), " - "it moves towards applying cl_clock_correction_adjustment_max_amount of adjustment. That way, the response " - "is small when the offset is small." ); - - - -// Given the offset (in milliseconds) of the client clock from the server clock, -// returns how much correction we'd like to apply per second (in seconds). -static float GetClockAdjustmentAmount( float flCurDiffInMS ) -{ - flCurDiffInMS = clamp( flCurDiffInMS, cl_clock_correction_adjustment_min_offset.GetFloat(), cl_clock_correction_adjustment_max_offset.GetFloat() ); - - float flReturnValue = RemapVal( flCurDiffInMS, - cl_clock_correction_adjustment_min_offset.GetFloat(), cl_clock_correction_adjustment_max_offset.GetFloat(), - 0, cl_clock_correction_adjustment_max_amount.GetFloat() / 1000.0f ); - - return flReturnValue; -} // -------------------------------------------------------------------------------------------------- / @@ -60,10 +33,12 @@ CClockDriftMgr::CClockDriftMgr() void CClockDriftMgr::Clear() { - m_nClientTick = 0; + m_nClientTick = 0; m_nServerTick = 0; - m_iCurClockOffset = 0; - memset( m_ClockOffsets, 0, sizeof( m_ClockOffsets ) ); + m_nOldServerTick = 0; + m_nLaggedClientTick = 0; + m_flServerHostFrametime = 0.0f; + m_flServerHostFrametimeStdDeviation = 0.0f; } @@ -76,137 +51,76 @@ void CClockDriftMgr::Clear() // NOTE: or decrementing the client tick after receiving pause // NOTE: This is due to the fact that currently pause is applied at frame start on the server // NOTE: and frame end on the client -void CClockDriftMgr::SetServerTick( int nTick ) +void CClockDriftMgr::SetServerTick( int nTick, int nLaggedTick, float flServerHostFrametime, float flServerHostFrametimeStdDeviation ) { #if !defined( SWDS ) - m_nServerTick = nTick; + m_nServerTick = nTick; + m_nLaggedClientTick = nLaggedTick; + m_flServerHostFrametime = flServerHostFrametime; + m_flServerHostFrametimeStdDeviation = flServerHostFrametimeStdDeviation; - int nMaxDriftTicks = IsEngineThreaded() ? - TIME_TO_TICKS( (cl_clockdrift_max_ms_threadmode.GetFloat() / 1000.0) ) : - TIME_TO_TICKS( (cl_clockdrift_max_ms.GetFloat() / 1000.0) ); + int clientTick = m_nClientTick + g_ClientGlobalVariables.simTicksThisFrame - 1; + int nMaxDriftTicks = IsEngineThreaded() ? TIME_TO_TICKS((cl_clockdrift_max_ms_threadmode.GetFloat() / 1000.0)) : + TIME_TO_TICKS((cl_clockdrift_max_ms.GetFloat() / 1000.0)); - int clientTick = cl.GetClientTickCount() + g_ClientGlobalVariables.simTicksThisFrame - 1; - if ( cl_clock_correction_force_server_tick.GetInt() == 999 ) + + if (cl_clock_correction_force_server_tick.GetInt() == 999) { - // If this is the first tick from the server, or if we get further than cl_clockdrift_max_ticks off, then + if (IsClockCorrectionEnabled()) + { + // Take the difference between last sent client tick and server tick + // This will give how much we are shifted from the server perfectly + // If server fps is higher than tickrate. + m_nLagDiff = m_nServerTick - m_nLaggedClientTick; + } + // If this is the first tick from the server, or if we get further than cl_clockdrift_max_ticks off, then // use the old behavior and slam the server's tick into the client tick. - if ( !IsClockCorrectionEnabled() || - clientTick == 0 || - abs(nTick - clientTick) > nMaxDriftTicks - ) - { - cl.SetClientTickCount( nTick - (g_ClientGlobalVariables.simTicksThisFrame - 1) ); - if ( cl.GetClientTickCount() < cl.oldtickcount ) - { - cl.oldtickcount = cl.GetClientTickCount(); - } - memset( m_ClockOffsets, 0, sizeof( m_ClockOffsets ) ); - } - } + else if (!IsClockCorrectionEnabled() || clientTick == 0 || abs(nTick - clientTick) > nMaxDriftTicks) + { + m_nClientTick = (nTick - (g_ClientGlobalVariables.simTicksThisFrame - 1)); + if (m_nClientTick < cl.oldtickcount) + { + cl.oldtickcount = m_nClientTick; + } + } + } else { // Used for testing.. - cl.SetClientTickCount( nTick + cl_clock_correction_force_server_tick.GetInt() ); + m_nClientTick = (nTick + cl_clock_correction_force_server_tick.GetInt()); } - // adjust the clock offset by the clock with thread mode compensation - m_ClockOffsets[m_iCurClockOffset] = clientTick - m_nServerTick; - m_iCurClockOffset = (m_iCurClockOffset + 1) % NUM_CLOCKDRIFT_SAMPLES; + ShowDebugInfo(); + m_nOldServerTick = m_nServerTick; #endif // SWDS } - -float CClockDriftMgr::AdjustFrameTime( float inputFrameTime ) +void CClockDriftMgr::ApplyClockCorrection(bool bFinalTick) { - float flAdjustmentThisFrame = 0; - float flAdjustmentPerSec = 0; - if ( IsClockCorrectionEnabled() -#if !defined( _XBOX ) && !defined( SWDS ) - && !demoplayer->IsPlayingBack() -#endif - ) - { - // Get the clock difference in seconds. - float flCurDiffInSeconds = GetCurrentClockDifference() * host_state.interval_per_tick; - float flCurDiffInMS = flCurDiffInSeconds * 1000.0f; - - // Is the server ahead or behind us? - if ( flCurDiffInMS > cl_clock_correction_adjustment_min_offset.GetFloat() ) - { - flAdjustmentPerSec = -GetClockAdjustmentAmount( flCurDiffInMS ); - flAdjustmentThisFrame = inputFrameTime * flAdjustmentPerSec; - flAdjustmentThisFrame = max( flAdjustmentThisFrame, -flCurDiffInSeconds ); - } - else if ( flCurDiffInMS < -cl_clock_correction_adjustment_min_offset.GetFloat() ) - { - flAdjustmentPerSec = GetClockAdjustmentAmount( -flCurDiffInMS ); - flAdjustmentThisFrame = inputFrameTime * flAdjustmentPerSec; - flAdjustmentThisFrame = min( flAdjustmentThisFrame, -flCurDiffInSeconds ); - } - - if ( IsEngineThreaded() ) - { - flAdjustmentThisFrame = -flCurDiffInSeconds; - } - - AdjustAverageDifferenceBy( flAdjustmentThisFrame ); - } - - ShowDebugInfo( flAdjustmentPerSec ); - return inputFrameTime + flAdjustmentThisFrame; + if (bFinalTick) + { + m_nCachedRealClientTick++; + } + m_nClientTick = m_nCachedRealClientTick + m_nLagDiff + g_ClientGlobalVariables.simTicksThisFrame - 1; } - -float CClockDriftMgr::GetCurrentClockDifference() const -{ - // Note: this could be optimized a little by updating it each time we add - // a sample (subtract the old value from the total and add the new one in). - float total = 0; - for ( int i=0; i < NUM_CLOCKDRIFT_SAMPLES; i++ ) - total += m_ClockOffsets[i]; - - return total / NUM_CLOCKDRIFT_SAMPLES; -} - - -void CClockDriftMgr::ShowDebugInfo( float flAdjustment ) +void CClockDriftMgr::ShowDebugInfo() { +#if !defined( SWDS ) if ( !cl_clock_showdebuginfo.GetInt() ) return; if ( IsClockCorrectionEnabled() ) - { - int high=-999, low=999; - int exactDiff = cl.GetClientTickCount() - m_nServerTick; - for ( int i=0; i < NUM_CLOCKDRIFT_SAMPLES; i++ ) - { - high = max( (float)high, m_ClockOffsets[i] ); - low = min( (float)low, m_ClockOffsets[i] ); - } + { + int clientTick = m_nClientTick + g_ClientGlobalVariables.simTicksThisFrame - 1; - Msg( "Clock drift: adjustment (per sec): %.2fms, avg: %.3f, lo: %d, hi: %d, ex: %d\n", flAdjustment*1000.0f, GetCurrentClockDifference(), low, high, exactDiff ); + ConMsg( "Clock drift: client sim tick: %i, client tick: %i, server tick: %i, lagged tick: %i, cached server tick: %i\n", clientTick, m_nClientTick, m_nServerTick, m_nLaggedClientTick, m_nCachedRealClientTick); } else { - Msg( "Clock drift disabled.\n" ); - } -} - - -void CClockDriftMgr::AdjustAverageDifferenceBy( float flAmountInSeconds ) -{ - // Don't adjust the average if it's already tiny. - float c = GetCurrentClockDifference(); - if ( c < 0.05f ) - return; - - float flAmountInTicks = flAmountInSeconds / host_state.interval_per_tick; - float factor = 1 + flAmountInTicks / c; - - for ( int i=0; i < NUM_CLOCKDRIFT_SAMPLES; i++ ) - m_ClockOffsets[i] *= factor; - - Assert( fabs( GetCurrentClockDifference() - (c + flAmountInTicks) ) < 0.001f ); + ConMsg( "Clock drift disabled.\n" ); + } +#endif } extern float NET_GetFakeLag(); diff --git a/engine/clockdriftmgr.h b/engine/clockdriftmgr.h index e445596880..0d495f36d0 100644 --- a/engine/clockdriftmgr.h +++ b/engine/clockdriftmgr.h @@ -26,42 +26,24 @@ public: // This is called each time a server packet comes in. It is used to correlate // where the server is in time compared to us. - void SetServerTick( int iServerTick ); - - // Pass in the frametime you would use, and it will drift it towards the server clock. - float AdjustFrameTime( float inputFrameTime ); - - // Returns how many ticks ahead of the server the client is. - float GetCurrentClockDifference() const; - + void SetServerTick( int iServerTick, int nLaggedTick, float flServerHostFrametime, float flServerHostFrametimeStdDeviation); + void ApplyClockCorrection(bool bFinalTick); private: - void ShowDebugInfo( float flAdjustment ); - - // This scales the offsets so the average produced is equal to the - // current average + flAmount. This way, as we add corrections, - // we lower the average accordingly so we don't keep responding - // as much as we need to after we'd adjusted it a couple times. - void AdjustAverageDifferenceBy( float flAmountInSeconds ); + void ShowDebugInfo(); -private: - - enum - { - // This controls how much it smoothes out the samples from the server. - NUM_CLOCKDRIFT_SAMPLES=16 - }; - - // This holds how many ticks the client is ahead each time we get a server tick. - // We average these together to get our estimate of how far ahead we are. - float m_ClockOffsets[NUM_CLOCKDRIFT_SAMPLES]; - int m_iCurClockOffset; - +public: + int m_nLagDiff; + int m_nOldServerTick; int m_nServerTick; // Last-received tick from the server. - int m_nClientTick; // The client's own tick counter (specifically, for interpolation during rendering). - // The server may be on a slightly different tick and the client will drift towards it. + int m_nClientTick; + int m_nCachedRealClientTick; // The client's own tick counter (specifically, for interpolation during rendering). + // The server may be on a slightly different tick and the client will drift towards it. + int m_nLaggedClientTick; + float m_flServerHostFrametime; + float m_flServerHostFrametimeStdDeviation; }; diff --git a/engine/hltvclient.cpp b/engine/hltvclient.cpp index 8cbb4eeb90..e1e764da34 100644 --- a/engine/hltvclient.cpp +++ b/engine/hltvclient.cpp @@ -473,7 +473,7 @@ void CHLTVClient::SendSnapshot( CClientFrame * pFrame ) // now create client snapshot packet // send tick time - NET_Tick tickmsg( pFrame->tick_count, host_frametime_unbounded, host_frametime_stddeviation ); + NET_Tick tickmsg( pFrame->tick_count, m_nClientTick, host_frametime_unbounded, host_frametime_stddeviation ); tickmsg.WriteToBuffer( msg ); // Update shared client/server string tables. Must be done before sending entities diff --git a/engine/hltvclientstate.cpp b/engine/hltvclientstate.cpp index 79590a880e..2ccbf66734 100644 --- a/engine/hltvclientstate.cpp +++ b/engine/hltvclientstate.cpp @@ -292,7 +292,7 @@ void CHLTVClientState::SendPacket() if ( IsActive() ) { - NET_Tick tick( m_nDeltaTick, host_frametime_unbounded, host_frametime_stddeviation ); + NET_Tick tick( m_nDeltaTick, host_tickcount, host_frametime_unbounded, host_frametime_stddeviation ); m_NetChannel->SendNetMsg( tick ); } diff --git a/engine/hltvdemo.cpp b/engine/hltvdemo.cpp index 02dd059432..471d8730e3 100644 --- a/engine/hltvdemo.cpp +++ b/engine/hltvdemo.cpp @@ -96,7 +96,8 @@ void CHLTVDemoRecorder::StartRecording( const char *filename, bool bContinuously m_nFrameCount = 0; - m_nStartTick = host_tickcount; + m_nStartTick = host_tickcount; + m_nClientTick = host_tickcount; // Demo playback should read this as an incoming message. // Write the client's realtime value out so we can synchronize the reads. @@ -173,7 +174,7 @@ void CHLTVDemoRecorder::WriteServerInfo() serverinfo.WriteToBuffer( msg ); // send first tick - NET_Tick signonTick( m_nSignonTick, 0, 0 ); + NET_Tick signonTick( m_nSignonTick, m_nClientTick, 0, 0 ); signonTick.WriteToBuffer( msg ); // write stringtable baselines @@ -345,7 +346,7 @@ void CHLTVDemoRecorder::WriteFrame( CHLTVFrame *pFrame ) //now send snapshot data // send tick time - NET_Tick tickmsg( pFrame->tick_count, host_frametime_unbounded, host_frametime_stddeviation ); + NET_Tick tickmsg( pFrame->tick_count, m_nClientTick, host_frametime_unbounded, host_frametime_stddeviation ); tickmsg.WriteToBuffer( msg ); @@ -380,7 +381,8 @@ void CHLTVDemoRecorder::WriteFrame( CHLTVFrame *pFrame ) msg.WriteBits( data->GetBasePointer(), data->GetNumBitsWritten() ); // update delta tick just like fakeclients do - m_nDeltaTick = pFrame->tick_count; + m_nDeltaTick = pFrame->tick_count; + m_nClientTick = pFrame->tick_count; // write packet to demo file WriteMessages( dem_packet, msg ); diff --git a/engine/hltvdemo.h b/engine/hltvdemo.h index 422bcd82eb..d4778ccd72 100644 --- a/engine/hltvdemo.h +++ b/engine/hltvdemo.h @@ -60,7 +60,8 @@ public: int m_nFrameCount; float m_nStartTick; int m_SequenceInfo; - int m_nDeltaTick; + int m_nDeltaTick; + int m_nClientTick; int m_nSignonTick; bf_write m_MessageData; // temp buffer for all network messages }; diff --git a/engine/host.cpp b/engine/host.cpp index 9864c2e472..3b714c8b62 100644 --- a/engine/host.cpp +++ b/engine/host.cpp @@ -1943,11 +1943,6 @@ void Host_AccumulateTime( float dt ) } #endif - // Adjust the client clock very slightly to keep it in line with the server clock. - float adj = cl.GetClockDriftMgr().AdjustFrameTime( host_frametime ) - host_frametime; - host_frametime += adj; - host_frametime_unbounded += adj; - if ( g_pSoundServices ) // not present on linux server g_pSoundServices->SetSoundFrametime(dt, host_frametime); @@ -3289,7 +3284,7 @@ void _Host_RunFrame (float time) ++host_tickcount; ++host_currentframetick; #ifndef SWDS - g_ClientGlobalVariables.tickcount = cl.GetClientTickCount(); + g_ClientGlobalVariables.tickcount = cl.GetClientTickCount(); // Make sure state is correct CL_CheckClientState(); @@ -3447,7 +3442,7 @@ void _Host_RunFrame (float time) // initialize networking for dedicated server after commandline & autoexec.cfg have been parsed if ( NET_IsDedicated() && !NET_IsMultiplayer() ) NET_SetMutiplayer( true ); - g_ClientGlobalVariables.tickcount = cl.GetClientTickCount(); + g_ClientGlobalVariables.tickcount = cl.GetClientTickCount(); // Make sure state is correct CL_CheckClientState(); diff --git a/engine/servermsghandler.cpp b/engine/servermsghandler.cpp index 96788090a9..ee54fc433f 100644 --- a/engine/servermsghandler.cpp +++ b/engine/servermsghandler.cpp @@ -287,16 +287,16 @@ void CClientState::Disconnect( const char *pszReason, bool bShowMainMenu ) bool CClientState::ProcessTick( NET_Tick *msg ) { - int tick = msg->m_nTick; + int tick = msg->m_nTick; - m_NetChannel->SetRemoteFramerate( msg->m_flHostFrameTime, msg->m_flHostFrameTimeStdDeviation ); + m_NetChannel->SetRemoteFramerate(msg->m_flHostFrameTime, msg->m_flHostFrameTimeStdDeviation); - m_ClockDriftMgr.SetServerTick( tick ); + m_ClockDriftMgr.SetServerTick(tick, msg->m_nLagTick, msg->m_flHostFrameTime, msg->m_flHostFrameTimeStdDeviation); - // Remember this for GetLastTimeStamp(). - m_flLastServerTickTime = tick * host_state.interval_per_tick; + // Remember this for GetLastTimeStamp(). + m_flLastServerTickTime = tick * host_state.interval_per_tick; - // Use the server tick while reading network data (used for interpolation samples, etc). + // Use the server tick while reading network data (used for interpolation samples, etc). g_ClientGlobalVariables.tickcount = tick; g_ClientGlobalVariables.curtime = tick * host_state.interval_per_tick; g_ClientGlobalVariables.frametime = (tick - oldtickcount) * host_state.interval_per_tick; // We used to call GetFrameTime() here, but 'insimulation' is always diff --git a/engine/vprof_engine.cpp b/engine/vprof_engine.cpp index a57db191be..6ae9c1f1f0 100644 --- a/engine/vprof_engine.cpp +++ b/engine/vprof_engine.cpp @@ -567,6 +567,16 @@ DEFERRED_CON_COMMAND(vprof_reset_peaks, "Reset just the peak time in VProf profi g_VProfCurrentProfile.ResetPeaks(); } +DEFERRED_CON_COMMAND(vprof_generate_report_full, "Generate a report to the console.") +{ + g_VProfCurrentProfile.Pause(); + ConsoleLogger consoleLog; + // This used to generate six different reports, which is expensive and hard to read. Default to + // two to save time and space. + g_VProfCurrentProfile.OutputReport( VPRT_FULL ); + g_VProfCurrentProfile.Resume(); +} + DEFERRED_CON_COMMAND(vprof_generate_report, "Generate a report to the console.") { g_VProfCurrentProfile.Pause(); diff --git a/game/client/c_baseplayer.cpp b/game/client/c_baseplayer.cpp index c43d61efef..d4305bd352 100644 --- a/game/client/c_baseplayer.cpp +++ b/game/client/c_baseplayer.cpp @@ -2179,7 +2179,7 @@ void C_BasePlayer::Simulate() { auto player = UTIL_PlayerByIndex(i); - if (player && player != GetLocalPlayer()) + if (player) { player->DrawServerHitboxes(60.0f, true); } @@ -2191,7 +2191,7 @@ void C_BasePlayer::Simulate() { auto player = UTIL_PlayerByIndex(entityIndex); - if (player && player != GetLocalPlayer()) + if (player) { player->DrawServerHitboxes(60.0f, true); } diff --git a/game/server/cstrike/cs_player.cpp b/game/server/cstrike/cs_player.cpp index e78d3c2ba4..1f42025b0a 100644 --- a/game/server/cstrike/cs_player.cpp +++ b/game/server/cstrike/cs_player.cpp @@ -607,10 +607,11 @@ void CCSPlayer::PlayerRunCommand( CUserCmd *ucmd, IMoveHelper *moveHelper ) return; // don't run commands in the future - if ( !IsEngineThreaded() && - ( ucmd->tick_count > (gpGlobals->tickcount + sv_max_usercmd_future_ticks.GetInt()) ) ) + if (!IsEngineThreaded() + && ((ucmd->tick_count > (gpGlobals->tickcount + sv_max_usercmd_future_ticks.GetInt())) + || ( ucmd->tick_count < (gpGlobals->tickcount - sv_max_usercmd_future_ticks.GetInt()) ))) { - DevMsg( "Client cmd out of sync (delta %i).\n", ucmd->tick_count - gpGlobals->tickcount ); + DevMsg( "Client cmd out of sync (delta: %i, client: %i != server: %i).\n", ucmd->tick_count - gpGlobals->tickcount, ucmd->tick_count, gpGlobals->tickcount); return; } diff --git a/materialsystem/stdshaders/cable_dx8.cpp b/materialsystem/stdshaders/cable_dx8.cpp index c914e3244b..8f881d5164 100644 --- a/materialsystem/stdshaders/cable_dx8.cpp +++ b/materialsystem/stdshaders/cable_dx8.cpp @@ -113,7 +113,7 @@ BEGIN_VS_SHADER( Cable_DX8, } // This is the light direction [0,1,0,0] * A * 0.5 - float lightDir[4] = {0, A*0.5, 0, 0}; + float lightDir[4] = {0, A*0.5f, 0, 0}; if( g_pHardwareConfig->GetDXSupportLevel() >= 90) { SetVertexShaderConstantGammaToLinear( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, lightDir ); diff --git a/materialsystem/stdshaders/vortwarp_dx8.cpp b/materialsystem/stdshaders/vortwarp_dx8.cpp index 9c071e6d34..50598e3148 100644 --- a/materialsystem/stdshaders/vortwarp_dx8.cpp +++ b/materialsystem/stdshaders/vortwarp_dx8.cpp @@ -161,7 +161,7 @@ BEGIN_VS_SHADER( VortWarp_dx8, pShaderAPI->SetPixelShaderConstant( 5, c5, 1 ); float curTime = pShaderAPI->CurrentTime(); - float selfIllumScroll[4] = { .11f * curTime, .124 * curTime, 0.0f, 0.0f }; + float selfIllumScroll[4] = { .11f * curTime, .124f * curTime, 0.0f, 0.0f }; pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, selfIllumScroll, 1 ); vortwarp_vs11_Dynamic_Index vshIndex; diff --git a/public/tier0/vprof.h b/public/tier0/vprof.h index 9594f3a232..a36c85e6b8 100644 --- a/public/tier0/vprof.h +++ b/public/tier0/vprof.h @@ -61,6 +61,10 @@ #ifdef VPROF_ENABLED +#ifndef VPROF_LEVEL +#define VPROF_LEVEL 0 +#endif + #define VPROF_VTUNE_GROUP #define VPROF( name ) VPROF_(name, 1, VPROF_BUDGETGROUP_OTHER_UNACCOUNTED, false, 0) @@ -68,7 +72,7 @@ #define VPROF_( name, detail, group, bAssertAccounted, budgetFlags ) VPROF_##detail(name,group, bAssertAccounted, budgetFlags) #define VPROF_BUDGET( name, group ) VPROF_BUDGET_FLAGS(name, group, BUDGETFLAG_OTHER) -#define VPROF_BUDGET_FLAGS( name, group, flags ) VPROF_(name, 0, group, false, flags) +#define VPROF_BUDGET_FLAGS( name, group, flags ) VPROF_(name, 1, group, false, flags) #define VPROF_SCOPE_BEGIN( tag ) do { VPROF( tag ) #define VPROF_SCOPE_END() } while (0) @@ -152,10 +156,6 @@ //------------------------------------- -#ifndef VPROF_LEVEL -#define VPROF_LEVEL 0 -#endif - //these macros exist to create VProf_ variables. This is important because it avoids /analyze warnings about variable aliasing when VPROF's are nested within each other, and allows //for multiple VPROF's to exist within the same scope. Three macros must be used to force the __LINE__ to be resolved prior to the token concatenation, but just ignore the _INTERNAL macros and use //the VPROF_VAR_NAME diff --git a/public/tier1/bitbuf.h b/public/tier1/bitbuf.h index 979cb29055..07437f61ed 100644 --- a/public/tier1/bitbuf.h +++ b/public/tier1/bitbuf.h @@ -407,7 +407,7 @@ BITBUF_INLINE void bf_write::WriteUBitLong( unsigned int curData, int numbits, b SetOverflowFlag(); CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() ); return; - } + } int iCurBitMasked = m_iCurBit & 31; int iDWord = m_iCurBit >> 5; @@ -417,16 +417,17 @@ BITBUF_INLINE void bf_write::WriteUBitLong( unsigned int curData, int numbits, b Assert( (iDWord*4 + sizeof(int32)) <= (unsigned int)m_nDataBytes ); uint32 * RESTRICT pOut = &m_pData[iDWord]; - // Rotate data into dword alignment - curData = (curData << iCurBitMasked) | (curData >> (32 - iCurBitMasked)); - + // Rotate data into dword alignment + uint32 dwordCurData = LoadLittleDWord(&curData, 0); + curData = (dwordCurData << iCurBitMasked) | (dwordCurData >> (32 - iCurBitMasked)); + // Calculate bitmasks for first and second word - unsigned int temp = 1 << (numbits-1); - unsigned int mask1 = (temp*2-1) << iCurBitMasked; - unsigned int mask2 = (temp-1) >> (31 - iCurBitMasked); + unsigned int bitmask = numbits == 32 ? 0xFFFFFFFF : (1 << numbits) - 1; + unsigned int mask1 = bitmask << iCurBitMasked; + unsigned int mask2 = ((1 << (numbits - 1))-1) >> (31 - iCurBitMasked); // Only look beyond current word if necessary (avoid access violation) - int i = mask2 & 1; + unsigned int i = mask2 & 1; uint32 dword1 = LoadLittleDWord( pOut, 0 ); uint32 dword2 = LoadLittleDWord( pOut, i ); @@ -784,12 +785,7 @@ BITBUF_INLINE unsigned int bf_read::ReadUBitLong( int numbits ) RESTRICT unsigned int iWordOffset2 = iLastBit >> 5; m_iCurBit += numbits; -#if __i386__ - unsigned int bitmask = (2 << (numbits-1)) - 1; -#else - extern uint32 g_ExtraMasks[33]; - unsigned int bitmask = g_ExtraMasks[numbits]; -#endif + unsigned int bitmask = numbits == 32 ? 0xFFFFFFFF : (1 << numbits) - 1; unsigned int dw1 = LoadLittleDWord( (uint32* RESTRICT)m_pData, iWordOffset1 ) >> iStartBit; unsigned int dw2 = LoadLittleDWord( (uint32* RESTRICT)m_pData, iWordOffset2 ) << (32 - iStartBit); diff --git a/wscript b/wscript index 77fc65d3be..ad3d9d51d7 100644 --- a/wscript +++ b/wscript @@ -280,7 +280,7 @@ def define_platform(conf): ]) conf.define('GIT_COMMIT_HASH', conf.env.GIT_VERSION) - + conf.define('VPROF_LEVEL', 1) def options(opt): grp = opt.add_option_group('Common options')