diff --git a/r5dev/game/server/player.cpp b/r5dev/game/server/player.cpp index 122f6b98..9032bb4c 100644 --- a/r5dev/game/server/player.cpp +++ b/r5dev/game/server/player.cpp @@ -112,65 +112,6 @@ void CPlayer::SetTotalExtraClientCmdTimeAttempted(float flAttemptedTime) } } -//------------------------------------------------------------------------------ -// Purpose: clamps the unlag amount to sv_unlag + clockdrift -// Input : *cmd - -//------------------------------------------------------------------------------ -void CPlayer::ClampUnlag(CUserCmd* cmd) -{ - const CClient* client = g_pServer->GetClient(GetEdict() - 1); - const CNetChan* chan = client->GetNetChan(); - - const float clockDriftMsecs = sv_clockcorrection_msecs->GetFloat() / 1000.0f; - const float maxUnlag = sv_maxunlag->GetFloat(); - const float latencyAmount = Clamp(chan->GetLatency(FLOW_OUTGOING), 0.0f, maxUnlag); - const float serverTime = (*g_pGlobals)->m_flCurTime; - - // Command issue time from client, note that this value can be altered - // from the client, and therefore be used to exploit lag compensation. - const float commandTime = cmd->command_time; - const float lastCommandTime = m_LastCmd.command_time; - const float commandDelta = fabs(commandTime - serverTime); - - bool recomputeUnlag = false; - - // Check delta first, otherwise player could set commandTime to a fixed - // time and circumvent the system, as commandTime < lastCommandTime or - // commandTime > localCurTime will always fail. - if (commandDelta > maxUnlag) - { - // Too much to unlag, clamp to max !!! - recomputeUnlag = true; - DevWarning(eDLL_T::SERVER, "%s: commandDelta( %f ) > maxUnlag( %f ) !!!\n", - __FUNCTION__, commandDelta, maxUnlag); - } - else if (commandTime < (lastCommandTime - clockDriftMsecs)) - { - // Can never be lower than last !!! - recomputeUnlag = true; - DevWarning(eDLL_T::SERVER, "%s: cmd->command_time( %f ) < (m_LastCmd.command_time( %f ) - clockDriftMsecs( %f )) !!!\n", - __FUNCTION__, commandTime, lastCommandTime, clockDriftMsecs); - } - else if (commandTime > (serverTime + clockDriftMsecs)) - { - // Too far in the future, clamp to max !!! - recomputeUnlag = true; - DevWarning(eDLL_T::SERVER, "%s: cmd->command_time( %f ) > (g_pGlobals->m_flCurTime( %f ) + clockDriftMsecs( %f )) !!!\n", - __FUNCTION__, commandTime, serverTime, clockDriftMsecs); - } - - if (recomputeUnlag) - { - // Clamp it to server time minus latency. Note that it could still - // be lower than previous, hence the clamp on the recomputation. - float newCommandTime = Clamp(serverTime - latencyAmount, lastCommandTime, serverTime); - cmd->command_time = newCommandTime; - - DevWarning(eDLL_T::SERVER, "%s: Clamped cmd->command_time( %f ) to %f !!!\n", - __FUNCTION__, commandTime, newCommandTime); - } -} - //------------------------------------------------------------------------------ // Purpose: processes user cmd's for this player // Input : *cmds - @@ -182,7 +123,7 @@ void CPlayer::ClampUnlag(CUserCmd* cmd) // TODO: this code is experimental and has reported problems from players with // high latency, needs to be debugged or a different approach needs to be taken! // Defaulted to OFF for now -static ConVar sv_unlag_clamp("sv_unlag_clamp", "0", FCVAR_RELEASE, "Clamp the difference between the current time and received command time to sv_maxunlag + sv_clockcorrection_msecs."); +static ConVar sv_unlag_clamp("sv_unlag_clamp", "0", FCVAR_RELEASE, "Clamp the difference between the current time and received command time to sv_maxunlag."); void CPlayer::ProcessUserCmds(CUserCmd* cmds, int numCmds, int totalCmds, int droppedPackets, bool paused) @@ -192,6 +133,9 @@ void CPlayer::ProcessUserCmds(CUserCmd* cmds, int numCmds, int totalCmds, CUserCmd* lastCmd = &m_Commands[MAX_QUEUED_COMMANDS_PROCESS]; + const float maxUnlag = sv_maxunlag->GetFloat(); + const float currTime = (*g_pGlobals)->m_flCurTime; + for (int i = totalCmds - 1; i >= 0; i--) { CUserCmd* cmd = &cmds[i]; @@ -206,8 +150,22 @@ void CPlayer::ProcessUserCmds(CUserCmd* cmds, int numCmds, int totalCmds, if (lastCommandNumber == MAX_QUEUED_COMMANDS_PROCESS) return; + // TODO: why are grenades not clamped to sv_maxunlag ??? + // TODO: the command_time is set from the client itself in CInput::CreateMove + // to gpGlobals->curtime in the ucmd packet, perhaps just calculate it from + // the server based on ucmd ticks ??? + // + // Possible solutions that need to be explored and worked out further: + // + // cmd->command_time = TICKS_TO_TIME(cmd->command_number + cmd->tick_count) // seems to be the closest, but also still manipulatable from the client. + // cmd->command_time = TICKS_TO_TIME(client->GetDeltaTick() + cmd->command_number) // delta tick is not necessarily the same as actual ucmd tick, and will be -1 on baseline request. + // cmd->command_time = TICKS_TO_TIME(m_lastUCmdSimulationRemainderTime) + m_totalExtraClientCmdTimeAttempted; // player timebase; also up to 100ms difference between orig sent value. + // + // ... reverse more ticks and floats in CClient since there seem to be a + // bunch still in the padded bytes, possibly one of them is what we could + // and should actually use to get the remote client time since ucmd was sent. if (sv_unlag_clamp.GetBool()) - ClampUnlag(cmd); + cmd->command_time = Min(Max(cmd->command_time, Max(currTime - maxUnlag, 0.0f)), currTime + maxUnlag); CUserCmd* queuedCmd = &m_Commands[lastCommandNumber]; queuedCmd->Copy(cmd);