diff --git a/r5dev/game/CMakeLists.txt b/r5dev/game/CMakeLists.txt index 43efc0f3..4138ea05 100644 --- a/r5dev/game/CMakeLists.txt +++ b/r5dev/game/CMakeLists.txt @@ -19,6 +19,7 @@ add_sources( SOURCE_GROUP "Shared" "shared/shared_classnames.h" "shared/shareddefs.h" "shared/takedamageinfo.h" + "shared/usercmd.cpp" "shared/usercmd.h" "shared/util_shared.cpp" "shared/util_shared.h" diff --git a/r5dev/game/shared/usercmd.cpp b/r5dev/game/shared/usercmd.cpp new file mode 100644 index 00000000..c55d0e16 --- /dev/null +++ b/r5dev/game/shared/usercmd.cpp @@ -0,0 +1,43 @@ +//====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#include "usercmd.h" + +//----------------------------------------------------------------------------- +// Purpose: Read in a delta compressed usercommand. +// Input : *buf - +// *move - +// *from - +// Output : random seed +//----------------------------------------------------------------------------- +int ReadUserCmd(bf_read* buf, CUserCmd* move, CUserCmd* from) +{ + int seed = v_ReadUserCmd(buf, move, from); + + // On the client, the frame time must be within 'usercmd_frametime_min' + // and 'usercmd_frametime_max'. Testing revealed that speed hacking could + // be achieved by sending bogus frametimes. Clamp the networked frame time + // to the exact values that the client should be using to make sure it + // couldn't be circumvented by busting out the client side clamps. + if (host_timescale->GetFloat() == 1.0f) + move->frametime = clamp(move->frametime, + usercmd_frametime_min->GetFloat(), + usercmd_frametime_max->GetFloat()); + + return seed; +} + +//----------------------------------------------------------------------------- +void VUserCmd::Attach() const +{ + DetourAttach(&v_ReadUserCmd, &ReadUserCmd); +} + +void VUserCmd::Detach() const +{ + DetourDetach(&v_ReadUserCmd, &ReadUserCmd); +} diff --git a/r5dev/game/shared/usercmd.h b/r5dev/game/shared/usercmd.h index d403aa58..c947eff5 100644 --- a/r5dev/game/shared/usercmd.h +++ b/r5dev/game/shared/usercmd.h @@ -10,6 +10,7 @@ #ifdef _WIN32 #pragma once #endif +#include "tier1/bitbuf.h" #include "mathlib/vector.h" //------------------------------------------------------------------------------------- @@ -23,6 +24,9 @@ inline auto v_CUserCmd__Reset = p_CUserCmd__Reset.RCast<void(*)(CUserCmd* pUserC inline CMemory p_CUserCmd__Copy; inline auto v_CUserCmd__Copy = p_CUserCmd__Copy.RCast<CUserCmd*(*)(CUserCmd* pDest, CUserCmd* pSource)>(); +inline CMemory p_ReadUserCmd; +inline auto v_ReadUserCmd = p_ReadUserCmd.RCast<int (*)(bf_read* buf, CUserCmd* move, CUserCmd* from)>(); + //------------------------------------------------------------------------------------- // //------------------------------------------------------------------------------------- @@ -34,21 +38,15 @@ public: Reset(); } - CUserCmd* Copy(CUserCmd* pSource) - { - return v_CUserCmd__Copy(this, pSource); - } - - void Reset() - { - v_CUserCmd__Reset(this); - } + inline CUserCmd* Copy(CUserCmd* pSource) { return v_CUserCmd__Copy(this, pSource); } + inline void Reset() { v_CUserCmd__Reset(this); } int32_t command_number; int32_t tick_count; float curtime; QAngle viewangles; - char pad_0x0018[12]; + float maybe; + char pad_0x0018[8]; float forwardmove; float sidemove; float upmove; @@ -58,9 +56,11 @@ public: char pad_0x0188[8]; Vector3D headposition; float maxpitch; - char pad_0x01A0[60]; + char pad_0x01A0[56]; + float frametime; }; +static_assert(sizeof(CUserCmd) == 0x1DC); /////////////////////////////////////////////////////////////////////////////// class VUserCmd : public IDetour @@ -69,6 +69,7 @@ class VUserCmd : public IDetour { LogFunAdr("CUserCmd::Reset", p_CUserCmd__Reset.GetPtr()); LogFunAdr("CUserCmd::Copy", p_CUserCmd__Copy.GetPtr()); + LogFunAdr("ReadUserCmd", p_ReadUserCmd.GetPtr()); } virtual void GetFun(void) const { @@ -77,11 +78,14 @@ class VUserCmd : public IDetour p_CUserCmd__Copy = g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 4C 8B 9B ?? ?? ?? ??").FollowNearCallSelf(); v_CUserCmd__Copy = p_CUserCmd__Copy.RCast<CUserCmd* (*)(CUserCmd*, CUserCmd*)>(); + + p_ReadUserCmd = g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 4C 8B C6 48 81 C6 ?? ?? ?? ??").FollowNearCallSelf(); + v_ReadUserCmd = p_ReadUserCmd.RCast<int (*)(bf_read*, CUserCmd*, CUserCmd*)>(); } virtual void GetVar(void) const { } virtual void GetCon(void) const { } - virtual void Attach(void) const { } - virtual void Detach(void) const { } + virtual void Attach(void) const; + virtual void Detach(void) const; }; ///////////////////////////////////////////////////////////////////////////////