*::ProcessUserCmds rebuild

Rebuild of the 'CServerGameClients::ProcessUserCmds' and 'CPlayer::ProcessUserCmds' methods. The rebuild is pretty much identical to the original implementation, but with additional checks for the number of commands, and total commands in 'CServerGameClients::ProcessUserCmds'. In the future, additional clamps and checks between CPlayer and the recv'd UserCMD should be incorporated in these functions.
This commit is contained in:
Kawe Mazidjatari 2023-07-02 21:49:35 +02:00
parent 64453b0661
commit 32d28d4285
5 changed files with 124 additions and 5 deletions

View File

@ -8,6 +8,10 @@
#define NUM_BACKUP_COMMAND_BITS 4 // Originally 3 bits.
#define MAX_BACKUP_COMMANDS ((1 << NUM_BACKUP_COMMAND_BITS)-1) // 15 in R5; see 'CL_Move'.
// Maximum amount of backup commands to process on the server.
#define MAX_BACKUP_COMMANDS_PROCESS (MAX_BACKUP_COMMANDS+1) * NUM_BACKUP_COMMAND_BITS
#define MAX_QUEUED_COMMANDS_PROCESS 0x1B0
enum class SIGNONSTATE : int
{
SIGNONSTATE_NONE = 0, // no state yet; about to connect.

View File

@ -10,10 +10,13 @@
#include "public/server_class.h"
#include "public/eiface.h"
#include "public/const.h"
#include "common/protocol.h"
#include "engine/server/sv_main.h"
#include "gameinterface.h"
#include "entitylist.h"
#include "baseanimating.h"
#include "game/shared/usercmd.h"
#include "game/shared/util_shared.h"
//-----------------------------------------------------------------------------
// This is called when a new game is started. (restart, map)
@ -114,6 +117,56 @@ void DrawServerHitboxes(bool bRunOverlays)
}
}
void CServerGameClients::ProcessUserCmds(CServerGameClients* thisp, edict_t edict,
bf_read* buf, int numCmds, int totalCmds, int droppedPackets, bool ignore, bool paused)
{
int i;
CUserCmd* from, * to;
// We track last three command in case we drop some
// packets but get them back.
CUserCmd cmds[MAX_BACKUP_COMMANDS_PROCESS];
CUserCmd cmdNull; // For delta compression
Assert(numCmds >= 0);
Assert((totalCmds - numCmds) >= 0);
CPlayer* pPlayer = UTIL_PlayerByIndex(edict);
// Too many commands?
if (totalCmds < 0 || totalCmds >= (MAX_BACKUP_COMMANDS_PROCESS - 1) ||
numCmds < 0 || numCmds > totalCmds)
{
//const char* name = "unknown";
//if (pPlayer)
//{
// name = pPlayer->GetPlayerName();
//}
//Warning(eDLL_T::SERVER, "%s: too many cmds %i sent for player %s\n", __FUNCTION__, totalCmds, name);
// !TODO: Drop the client from here.
buf->SetOverflowFlag();
return;
}
from = &cmdNull;
for (i = totalCmds - 1; i >= 0; i--)
{
to = &cmds[i];
ReadUserCmd(buf, to, from);
from = to;
}
// Client not fully connected or server has gone inactive or is paused, just ignore
if (ignore || !pPlayer)
{
return;
}
pPlayer->ProcessUserCmds(cmds, numCmds, totalCmds, droppedPackets, paused);
}
void RunFrameServer(double flFrameTime, bool bRunOverlays, bool bUniformUpdate)
{
DrawServerHitboxes(bRunOverlays);
@ -124,6 +177,7 @@ void VServerGameDLL::Attach() const
{
#if defined(GAMEDLL_S3)
DetourAttach((LPVOID*)&CServerGameDLL__OnReceivedSayTextMessage, &CServerGameDLL::OnReceivedSayTextMessage);
DetourAttach(&v_CServerGameClients__ProcessUserCmds, CServerGameClients::ProcessUserCmds);
#endif
DetourAttach(&v_RunFrameServer, &RunFrameServer);
}
@ -132,6 +186,7 @@ void VServerGameDLL::Detach() const
{
#if defined(GAMEDLL_S3)
DetourDetach((LPVOID*)&CServerGameDLL__OnReceivedSayTextMessage, &CServerGameDLL::OnReceivedSayTextMessage);
DetourDetach(&v_CServerGameClients__ProcessUserCmds, CServerGameClients::ProcessUserCmds);
#endif
DetourDetach(&v_RunFrameServer, &RunFrameServer);
}

View File

@ -34,6 +34,10 @@ public:
//-----------------------------------------------------------------------------
class CServerGameClients : public IServerGameClients
{
public:
static void ProcessUserCmds(CServerGameClients* thisp, edict_t edict, bf_read* buf,
int numCmds, int totalCmds, int droppedPackets, bool ignore, bool paused);
private:
};
//-----------------------------------------------------------------------------
@ -46,6 +50,10 @@ class CServerGameEnts : public IServerGameEnts
inline CMemory p_CServerGameDLL__OnReceivedSayTextMessage;
inline auto CServerGameDLL__OnReceivedSayTextMessage = p_CServerGameDLL__OnReceivedSayTextMessage.RCast<void(__fastcall*)(void* thisptr, int senderId, const char* text, bool isTeamChat)>();
inline CMemory p_CServerGameClients__ProcessUserCmds;
inline auto v_CServerGameClients__ProcessUserCmds = p_CServerGameClients__ProcessUserCmds.RCast<void(*)(CServerGameClients* thisp, edict_t edict, bf_read* buf,
int numCmds, int totalCmds, int droppedPackets, bool ignore, bool paused)>();
inline CMemory p_RunFrameServer;
inline auto v_RunFrameServer = p_RunFrameServer.RCast<void(*)(double flFrameTime, bool bRunOverlays, bool bUniformUpdate)>();
@ -61,6 +69,7 @@ class VServerGameDLL : public IDetour
virtual void GetAdr(void) const
{
LogFunAdr("CServerGameDLL::OnReceivedSayTextMessage", p_CServerGameDLL__OnReceivedSayTextMessage.GetPtr());
LogFunAdr("CServerGameClients::ProcessUserCmds", p_CServerGameClients__ProcessUserCmds.GetPtr());
LogFunAdr("RunFrameServer", p_RunFrameServer.GetPtr());
LogVarAdr("g_pServerGameDLL", reinterpret_cast<uintptr_t>(g_pServerGameDLL));
LogVarAdr("g_pServerGameClients", reinterpret_cast<uintptr_t>(g_pServerGameClients));
@ -74,9 +83,11 @@ class VServerGameDLL : public IDetour
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
p_CServerGameDLL__OnReceivedSayTextMessage = g_GameDll.FindPatternSIMD("85 D2 0F 8E ?? ?? ?? ?? 4C 8B DC");
#endif
CServerGameDLL__OnReceivedSayTextMessage = p_CServerGameDLL__OnReceivedSayTextMessage.RCast<void(__fastcall*)(void* thisptr, int senderId, const char* text, bool isTeamChat)>();
p_CServerGameClients__ProcessUserCmds = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 55 41 55 41 57");
p_RunFrameServer = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 30 0F 29 74 24 ?? 48 8D 0D ?? ?? ?? ??");
CServerGameDLL__OnReceivedSayTextMessage = p_CServerGameDLL__OnReceivedSayTextMessage.RCast<void(__fastcall*)(void*, int, const char*, bool)>();
v_CServerGameClients__ProcessUserCmds = p_CServerGameClients__ProcessUserCmds.RCast<void(*)(CServerGameClients*, edict_t, bf_read*, int, int, int, bool, bool)>();
v_RunFrameServer = p_RunFrameServer.RCast<void(*)(double, bool, bool)>();
}
virtual void GetVar(void) const

View File

@ -4,11 +4,12 @@
//
//===========================================================================//
#include "core/stdafx.h"
#include "player.h"
#include "gameinterface.h"
#include "common/protocol.h"
#include "game/shared/shareddefs.h"
#include "game/shared/usercmd.h"
#include "game/server/movehelper_server.h"
#include "gameinterface.h"
#include "player.h"
//------------------------------------------------------------------------------
// Purpose: executes a null command for this player
@ -103,6 +104,52 @@ void CPlayer::SetTotalExtraClientCmdTimeAttempted(float flAttemptedTime)
}
}
//------------------------------------------------------------------------------
// Purpose: processes user cmd's for this player
// Input : *cmds -
// numCmds -
// totalCmds -
// droppedPackets -
// paused -
//------------------------------------------------------------------------------
void CPlayer::ProcessUserCmds(CUserCmd* cmds, int numCmds, int totalCmds,
int droppedPackets, bool paused)
{
if (totalCmds <= 0)
return;
CUserCmd* lastCmd = &m_Commands[MAX_QUEUED_COMMANDS_PROCESS];
for (int i = totalCmds - 1; i >= 0; i--)
{
CUserCmd* cmd = &cmds[i];
const int commandNumber = cmd->command_number;
if (commandNumber > m_latestCommandQueued)
{
m_latestCommandQueued = commandNumber;
const int lastCommandNumber = lastCmd->command_number;
if (lastCommandNumber == MAX_QUEUED_COMMANDS_PROCESS)
return;
CUserCmd* queuedCmd = &m_Commands[lastCommandNumber];
queuedCmd->Copy(cmd);
if (++lastCmd->command_number > player_userCmdsQueueWarning->GetInt())
{
const float curTime = float(Plat_FloatTime());
if ((curTime - m_lastCommandCountWarnTime) > 0.5f)
m_lastCommandCountWarnTime = curTime;
}
}
}
lastCmd->tick_count += droppedPackets;
m_bGamePaused = paused;
}
//------------------------------------------------------------------------------
// Purpose: runs user command for this player
// Input : *pUserCmd -

View File

@ -249,6 +249,8 @@ public:
void SetLastUCmdSimulationRemainderTime(float flRemainderTime);
void SetTotalExtraClientCmdTimeAttempted(float flAttemptedTime);
void ProcessUserCmds(CUserCmd* cmds, int numCmds, int totalCmds,
int droppedPackets, bool paused);
void PlayerRunCommand(CUserCmd* pUserCmd, IMoveHelper* pMover);
void SetLastUserCommand(CUserCmd* pUserCmd);
@ -376,7 +378,7 @@ private:
float m_fNextSuicideTime;
int m_iSuicideCustomKillFlags;
int m_preNoClipPhysicsFlags;
char m_Commands[8];
CUserCmd* m_Commands;
void* m_pPhysicsController;
void* m_pShadowStand;
void* m_pShadowCrouch;