Added the old clock correction, new one caused flickering
This commit is contained in:
parent
a9b7bf8e2f
commit
ad3b1ca178
7 changed files with 196 additions and 42 deletions
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "client.h"
|
||||
#include "client_pch.h"
|
||||
#include "clockdriftmgr.h"
|
||||
#include "sound.h"
|
||||
#include <inetchannel.h>
|
||||
#include "checksum_engine.h"
|
||||
|
@ -508,6 +509,8 @@ Updates the local time and reads/handles messages on client net connection.
|
|||
=================
|
||||
*/
|
||||
|
||||
extern ConVar cl_clock_correction;
|
||||
|
||||
void CL_ReadPackets ( bool bFinalTick )
|
||||
{
|
||||
VPROF_BUDGET( "CL_ReadPackets", VPROF_BUDGETGROUP_OTHER_NETWORKING );
|
||||
|
@ -517,26 +520,20 @@ void CL_ReadPackets ( bool bFinalTick )
|
|||
return;
|
||||
|
||||
// update client times/tick
|
||||
if (!CClockDriftMgr::IsClockCorrectionEnabled())
|
||||
if (cl_clock_correction.GetInt() <= 1)
|
||||
{
|
||||
cl.oldtickcount = cl.GetServerTickCount();
|
||||
}
|
||||
|
||||
// Moved after process socket so we can receive the lastest updates.
|
||||
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.SetClientTickCount(cl.GetClientTickCount() + 1);
|
||||
cl.SetServerTickCount(cl.GetClientTickCount());
|
||||
if ( !CClockDriftMgr::IsClockCorrectionEnabled() )
|
||||
cl.SetServerTickCount( cl.GetClientTickCount() );
|
||||
|
||||
g_ClientGlobalVariables.tickcount = cl.GetClientTickCount();
|
||||
g_ClientGlobalVariables.curtime = cl.GetTime();
|
||||
}
|
||||
}
|
||||
|
||||
if (!CClockDriftMgr::IsClockCorrectionEnabled())
|
||||
{
|
||||
// 0 or tick_rate if simulating
|
||||
g_ClientGlobalVariables.frametime = cl.GetFrameTime();
|
||||
}
|
||||
|
@ -583,6 +580,8 @@ void CL_ReadPackets ( bool bFinalTick )
|
|||
}
|
||||
#endif
|
||||
|
||||
if (cl_clock_correction.GetInt() >= 2)
|
||||
{
|
||||
if (CClockDriftMgr::IsClockCorrectionEnabled())
|
||||
{
|
||||
cl.oldtickcount = cl.GetServerTickCount();
|
||||
|
@ -605,7 +604,7 @@ void CL_ReadPackets ( bool bFinalTick )
|
|||
// 0 or tick_rate if simulating
|
||||
g_ClientGlobalVariables.frametime = cl.GetFrameTime();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include "enginethreads.h"
|
||||
|
||||
|
||||
ConVar cl_clock_correction( "cl_clock_correction", "0", FCVAR_CHEAT, "Enable/disable clock correction on the client." );
|
||||
ConVar cl_clock_correction( "cl_clock_correction", "1", 0, "Enable/disable clock correction on the client." );
|
||||
|
||||
ConVar cl_clockdrift_max_ms( "cl_clockdrift_max_ms", "150", FCVAR_CHEAT, "Maximum number of milliseconds the clock is allowed to drift before the client snaps its clock to the server's." );
|
||||
ConVar cl_clockdrift_max_ms_threadmode( "cl_clockdrift_max_ms_threadmode", "0", FCVAR_CHEAT, "Maximum number of milliseconds the clock is allowed to drift before the client snaps its clock to the server's." );
|
||||
|
@ -20,6 +20,32 @@ ConVar cl_clock_showdebuginfo( "cl_clock_showdebuginfo", "0", FCVAR_CHEAT, "Show
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------- /
|
||||
// CClockDriftMgr implementation.
|
||||
|
@ -39,6 +65,9 @@ void CClockDriftMgr::Clear()
|
|||
m_nLaggedClientTick = 0;
|
||||
m_flServerHostFrametime = 0.0f;
|
||||
m_flServerHostFrametimeStdDeviation = 0.0f;
|
||||
|
||||
m_iCurClockOffset = 0;
|
||||
memset( m_ClockOffsets, 0, sizeof( m_ClockOffsets ) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -66,7 +95,8 @@ void CClockDriftMgr::SetServerTick( int nTick, int nLaggedTick, float flServerHo
|
|||
|
||||
if (cl_clock_correction_force_server_tick.GetInt() == 999)
|
||||
{
|
||||
if (IsClockCorrectionEnabled())
|
||||
// TODO_ENHANCED: !!!!!!!!! This needs to be corrected !!!!!!!!!!
|
||||
if (IsClockCorrectionEnabled() && cl_clock_correction.GetInt() >= 2)
|
||||
{
|
||||
// Take the difference between last sent client tick and server tick
|
||||
// This will give how much we are shifted from the server perfectly
|
||||
|
@ -90,6 +120,13 @@ void CClockDriftMgr::SetServerTick( int nTick, int nLaggedTick, float flServerHo
|
|||
m_nClientTick = (nTick + cl_clock_correction_force_server_tick.GetInt());
|
||||
}
|
||||
|
||||
if (cl_clock_correction.GetInt() <= 1)
|
||||
{
|
||||
// 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
|
||||
|
@ -105,6 +142,58 @@ void CClockDriftMgr::IncrementCachedTickCount(bool bFinalTick)
|
|||
m_nClientTick = m_nCachedRealClientTick + m_nLagDiff;
|
||||
}
|
||||
|
||||
float CClockDriftMgr::AdjustFrameTime( float inputFrameTime )
|
||||
{
|
||||
float flAdjustmentThisFrame = 0;
|
||||
float flAdjustmentPerSec = 0;
|
||||
if ( IsClockCorrectionEnabled()
|
||||
#if !defined( _XBOX ) && !defined( SWDS )
|
||||
&& !demoplayer->IsPlayingBack()
|
||||
#endif
|
||||
&& cl_clock_correction.GetInt() <= 1)
|
||||
{
|
||||
// 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 );
|
||||
}
|
||||
|
||||
return inputFrameTime + flAdjustmentThisFrame;
|
||||
}
|
||||
|
||||
|
||||
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()
|
||||
{
|
||||
#if !defined( SWDS )
|
||||
|
@ -124,6 +213,22 @@ void CClockDriftMgr::ShowDebugInfo()
|
|||
#endif
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
extern float NET_GetFakeLag();
|
||||
extern ConVar net_usesocketsforloopback;
|
||||
|
||||
|
|
|
@ -29,10 +29,32 @@ public:
|
|||
void SetServerTick( int iServerTick, int nLaggedTick, float flServerHostFrametime, float flServerHostFrametimeStdDeviation);
|
||||
void IncrementCachedTickCount(bool bFinalTick);
|
||||
|
||||
// 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;
|
||||
|
||||
private:
|
||||
|
||||
void ShowDebugInfo();
|
||||
|
||||
// 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 );
|
||||
|
||||
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;
|
||||
|
|
|
@ -1944,6 +1944,11 @@ 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);
|
||||
|
||||
|
@ -3051,6 +3056,7 @@ void _Host_RunFrame (float time)
|
|||
static double host_remainder = 0.0f;
|
||||
double prevremainder;
|
||||
bool shouldrender;
|
||||
float angleframetime = 0.0f;
|
||||
|
||||
#if defined( RAD_TELEMETRY_ENABLED )
|
||||
if( g_Telemetry.DemoTickEnd == ( uint32 )-1 )
|
||||
|
@ -3411,6 +3417,9 @@ void _Host_RunFrame (float time)
|
|||
CL_RunPrediction( PREDICTION_NORMAL );
|
||||
|
||||
CL_ApplyAddAngle();
|
||||
|
||||
// Ensure we get the right frametime
|
||||
angleframetime = g_ClientGlobalVariables.frametime;
|
||||
}
|
||||
#endif
|
||||
#if defined( REPLAY_ENABLED )
|
||||
|
@ -3498,6 +3507,9 @@ void _Host_RunFrame (float time)
|
|||
// This causes cl.gettime() to return the true clock being used for rendering (tickcount * rate + remainder)
|
||||
Host_SetClientInSimulation( false );
|
||||
|
||||
// Ensure we get the right frametime
|
||||
angleframetime = g_ClientGlobalVariables.frametime;
|
||||
|
||||
//-------------------
|
||||
// Run prediction if it hasn't been run yet
|
||||
//-------------------
|
||||
|
@ -3666,15 +3678,16 @@ void _Host_RunFrame (float time)
|
|||
} // Profile scope, protect from setjmp() problems
|
||||
|
||||
Host_ShowIPCCallCount();
|
||||
|
||||
#ifndef SWDS
|
||||
// TODO_ENHANCED:
|
||||
// Update the mouse as last so we can get the right prediction viewangles on a frame
|
||||
// Update the mouse as last so we can get the right viewangles while taking screenshot.
|
||||
// The mouse is always simulated for the current frame's time
|
||||
// This makes updates smooth in every case
|
||||
// continuous controllers affecting the view are also simulated this way
|
||||
// but they have a cap applied by IN_SetSampleTime() so they are not also
|
||||
// simulated during input gathering
|
||||
CL_ExtraMouseUpdate( g_ClientGlobalVariables.frametime );
|
||||
CL_ExtraMouseUpdate( angleframetime );
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
|
|
|
@ -149,7 +149,7 @@ extern int host_currentframetick;
|
|||
|
||||
// PERFORMANCE INFO
|
||||
#define MIN_FPS 0.1 // Host minimum fps value for maxfps.
|
||||
#define MAX_FPS 1000.0 // Upper limit for maxfps.
|
||||
#define MAX_FPS 100000000.0 // Upper limit for maxfps.
|
||||
|
||||
#define MAX_FRAMETIME 0.1
|
||||
#define MIN_FRAMETIME 0.001
|
||||
|
|
|
@ -279,6 +279,21 @@ bool CEngine::FilterTime( float dt )
|
|||
return false;
|
||||
}
|
||||
}
|
||||
else if ( fps == 0 )
|
||||
{
|
||||
m_flMinFrameTime = 0.0f;
|
||||
|
||||
if (
|
||||
#if !defined(SWDS)
|
||||
!demoplayer->IsPlayingTimeDemo() &&
|
||||
#endif
|
||||
!g_bDedicatedServerBenchmarkMode &&
|
||||
dt < 0.0f )
|
||||
{
|
||||
// framerate is too high
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -767,7 +767,7 @@ C_CSPlayer::C_CSPlayer() :
|
|||
{
|
||||
m_angEyeAngles.Init();
|
||||
|
||||
// AddVar( &m_angEyeAngles, &m_iv_angEyeAngles, LATCH_ANIMATION_VAR );
|
||||
// AddVar( &m_angEyeAngles, &m_iv_angEyeAngles, LATCH_SIMULATION_VAR );
|
||||
|
||||
m_iLastAddonBits = m_iAddonBits = 0;
|
||||
m_iLastPrimaryAddon = m_iLastSecondaryAddon = WEAPON_NONE;
|
||||
|
|
Loading…
Reference in a new issue