diff --git a/r5dev/common/global.cpp b/r5dev/common/global.cpp index 04520773..0a751fcf 100644 --- a/r5dev/common/global.cpp +++ b/r5dev/common/global.cpp @@ -104,6 +104,8 @@ ConVar* sv_forceChatToTeamOnly = nullptr; ConVar* sv_single_core_dedi = nullptr; +ConVar* sv_maxunlag_delta = nullptr; + ConVar* sv_updaterate_sp = nullptr; ConVar* sv_updaterate_mp = nullptr; @@ -326,6 +328,8 @@ void ConVar_StaticInit(void) sv_autoReloadRate = ConVar::StaticCreate("sv_autoReloadRate" , "0" , FCVAR_RELEASE, "Time in seconds between each server auto-reload (disabled if null).", true, 0.f, false, 0.f, nullptr, nullptr); sv_simulateBots = ConVar::StaticCreate("sv_simulateBots", "1", FCVAR_RELEASE, "Simulate user commands for bots on the server.", true, 0.f, false, 0.f, nullptr, nullptr); + sv_maxunlag_delta = ConVar::StaticCreate("sv_maxunlag_delta", "0.3", FCVAR_RELEASE, "Maximum amount of deviation in seconds between server and UserCmd's issue time for unlag (excludes latency).", true, 0.f, true, 1.f, nullptr, nullptr); + sv_rcon_debug = ConVar::StaticCreate("sv_rcon_debug" , "0" , FCVAR_RELEASE, "Show rcon debug information ( !slower! ).", false, 0.f, false, 0.f, nullptr, nullptr); sv_rcon_sendlogs = ConVar::StaticCreate("sv_rcon_sendlogs" , "0" , FCVAR_RELEASE, "Network console logs to connected and authenticated sockets.", false, 0.f, false, 0.f, nullptr, nullptr); //sv_rcon_banpenalty = ConVar::StaticCreate("sv_rcon_banpenalty" , "10", FCVAR_RELEASE, "Number of minutes to ban users who fail rcon authentication.", false, 0.f, false, 0.f, nullptr, nullptr); diff --git a/r5dev/common/global.h b/r5dev/common/global.h index 48f46310..848042fe 100644 --- a/r5dev/common/global.h +++ b/r5dev/common/global.h @@ -93,6 +93,8 @@ extern ConVar* sv_forceChatToTeamOnly; extern ConVar* sv_single_core_dedi; +extern ConVar* sv_maxunlag_delta; + extern ConVar* sv_updaterate_sp; extern ConVar* sv_updaterate_mp; diff --git a/r5dev/game/server/player.cpp b/r5dev/game/server/player.cpp index 2c896611..f6d989dc 100644 --- a/r5dev/game/server/player.cpp +++ b/r5dev/game/server/player.cpp @@ -11,6 +11,8 @@ #include "gameinterface.h" #include "player.h" +#include "engine/server/server.h" + //------------------------------------------------------------------------------ // Purpose: executes a null command for this player //------------------------------------------------------------------------------ @@ -118,11 +120,34 @@ void CPlayer::ProcessUserCmds(CUserCmd* cmds, int numCmds, int totalCmds, if (totalCmds <= 0) return; + const CClient* client = g_pServer->GetClient(GetEdict() - 1); + const CNetChan* chan = client->GetNetChan(); + CUserCmd* lastCmd = &m_Commands[MAX_QUEUED_COMMANDS_PROCESS]; + const float latencyAmount = chan->GetLatency(FLOW_OUTGOING); + const float maxCommandDelta = sv_maxunlag_delta->GetFloat(); + const float localCurTime = (*g_pGlobals)->m_flCurTime; + const float lastCommandTime = m_LastCmd.command_time; + for (int i = totalCmds - 1; i >= 0; i--) { CUserCmd* cmd = &cmds[i]; + + const float commandTime = cmd->command_time; + const float commandDelta = fabs(commandTime - localCurTime) - latencyAmount; + + if (/*commandTime < lastCommandTime ||*/ commandDelta > maxCommandDelta) + { + cmd->command_time = localCurTime - latencyAmount; + + if (IsDebug()) + { + Warning(eDLL_T::SERVER, "%s: Command delta of %f exceeded maximum of %f; commandTime=%f, lastCommandTime=%f, localCurTime=%f, latencyAmount=%f\n", + __FUNCTION__, commandDelta, maxCommandDelta, commandTime, lastCommandTime, localCurTime, latencyAmount); + } + } + const int commandNumber = cmd->command_number; if (commandNumber > m_latestCommandQueued)