diff --git a/r5dev/common/callback.cpp b/r5dev/common/callback.cpp index b69b065a..fc3920be 100644 --- a/r5dev/common/callback.cpp +++ b/r5dev/common/callback.cpp @@ -1495,6 +1495,10 @@ void CC_CreateFakePlayer_f(const CCommand& args) } #endif // !CLIENT_DLL +#ifndef DEDICATED +static double s_flScriptExecTimeBase = 0.0f; +static int s_nScriptExecCount = 0; +#endif // !DEDICATED /* ===================== Cmd_Exec_f @@ -1508,12 +1512,31 @@ void Cmd_Exec_f(const CCommand& args) // Prevent users from running neo strafe commands and other quick hacks. // TODO: when reBar becomes a thing, we should verify this function and // flag users that patch them out. - if (!ThreadInServerFrameThread() && (!sv_allowClientSideCfgExec->GetBool() && g_pClientState->IsActive())) + if (!ThreadInServerFrameThread() && g_pClientState->IsActive()) { - DevWarning(eDLL_T::ENGINE, "Client is simulating and %s = false; dropped exec command: %s\n", - sv_allowClientSideCfgExec->GetName(), args.ArgS()); + const int execQuota = sv_quota_scriptExecsPerSecond->GetInt(); - return; + if (execQuota > 0) + { + const double flCurrentTime = Plat_FloatTime(); + + // Reset every second. + if ((flCurrentTime - s_flScriptExecTimeBase) > 1.0) + { + s_flScriptExecTimeBase = flCurrentTime; + s_nScriptExecCount = 0; + } + + if (s_nScriptExecCount >= execQuota) + { + DevWarning(eDLL_T::ENGINE, "Client is simulating and exec count = %d of %d; dropped exec command: %s\n", + s_nScriptExecCount, execQuota, args.ArgS()); + + return; + } + + s_nScriptExecCount++; + } } #endif // !DEDICATED _Cmd_Exec_f(args); diff --git a/r5dev/common/global.cpp b/r5dev/common/global.cpp index 0226c48c..7c410e6c 100644 --- a/r5dev/common/global.cpp +++ b/r5dev/common/global.cpp @@ -171,7 +171,7 @@ ConVar* sv_rcon_maxpacketsize = nullptr; ConVar* sv_rcon_whitelist_address = nullptr; //#endif // DEDICATED #endif // !CLIENT_DLL -ConVar* sv_allowClientSideCfgExec = nullptr; +ConVar* sv_quota_scriptExecsPerSecond = nullptr; ConVar* sv_cheats = nullptr; ConVar* sv_visualizetraces = nullptr; ConVar* sv_visualizetraces_duration = nullptr; @@ -411,7 +411,7 @@ void ConVar_StaticInit(void) sv_onlineAuthValidateIssuedAt = ConVar::StaticCreate("sv_onlineAuthValidateIssuedAt" , "1" , FCVAR_RELEASE, "Validate the online authentication token 'issued at' claim.", true, 0.f, true, 1.f, nullptr, nullptr); sv_onlineAuthIssuedAtTolerance = ConVar::StaticCreate("sv_onlineAuthIssuedAtTolerance", "30", FCVAR_RELEASE, "The online authentication token 'issued at' claim tolerance in seconds.", true, 0.f, true, float(UINT8_MAX), nullptr, "Must range between [0,255]"); #endif // !CLIENT_DLL - sv_allowClientSideCfgExec = ConVar::StaticCreate("sv_allowClientSideCfgExec", "0", FCVAR_REPLICATED | FCVAR_RELEASE, "Allow clients to execute script files while being connected to this server.", false, 0.f, false, 0.f, nullptr, nullptr); + sv_quota_scriptExecsPerSecond = ConVar::StaticCreate("sv_quota_scriptExecsPerSecond", "4", FCVAR_REPLICATED | FCVAR_RELEASE, "How many script executions per second clients are allowed to submit, 0 to disable the limitation thereof.", true, 0.f, false, 0.f, nullptr, nullptr); #if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1) bhit_depth_test = ConVar::StaticCreate("bhit_depth_test", "0", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED, "Use depth test for bullet ray trace overlay.", false, 0.f, false, 0.f, nullptr, nullptr); bhit_abs_origin = ConVar::StaticCreate("bhit_abs_origin", "1", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED, "Draw entity's predicted abs origin upon bullet impact for trajectory debugging (requires 'r_visualizetraces' to be set!).", false, 0.f, false, 0.f, nullptr, nullptr); diff --git a/r5dev/common/global.h b/r5dev/common/global.h index bc86b60b..f90583a8 100644 --- a/r5dev/common/global.h +++ b/r5dev/common/global.h @@ -161,7 +161,7 @@ extern ConVar* sv_rcon_maxpacketsize; extern ConVar* sv_rcon_whitelist_address; //#endif // DEDICATED #endif // CLIENT_DLL -extern ConVar* sv_allowClientSideCfgExec; +extern ConVar* sv_quota_scriptExecsPerSecond; extern ConVar* sv_cheats; extern ConVar* sv_visualizetraces; extern ConVar* sv_visualizetraces_duration;