2023-01-19 15:25:45 +01:00
|
|
|
//======== Copyright (c) Valve Corporation, All rights reserved. ============//
|
|
|
|
//
|
|
|
|
// Purpose:
|
|
|
|
//
|
|
|
|
//===========================================================================//
|
|
|
|
#include "core/stdafx.h"
|
2023-07-02 21:49:35 +02:00
|
|
|
#include "common/protocol.h"
|
2023-01-19 15:25:45 +01:00
|
|
|
#include "game/shared/shareddefs.h"
|
2023-01-19 20:48:41 +01:00
|
|
|
#include "game/shared/usercmd.h"
|
|
|
|
#include "game/server/movehelper_server.h"
|
2023-07-02 21:49:35 +02:00
|
|
|
#include "gameinterface.h"
|
|
|
|
#include "player.h"
|
2023-01-19 15:25:45 +01:00
|
|
|
|
2023-08-14 20:47:02 +02:00
|
|
|
#include "engine/server/server.h"
|
|
|
|
|
2023-01-19 15:25:45 +01:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: executes a null command for this player
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void CPlayer::RunNullCommand(void)
|
|
|
|
{
|
2023-01-19 20:48:41 +01:00
|
|
|
CUserCmd cmd;
|
|
|
|
|
2023-02-12 15:06:08 +01:00
|
|
|
float flOldFrameTime = (*g_pGlobals)->m_flFrameTime;
|
|
|
|
float flOldCurTime = (*g_pGlobals)->m_flCurTime;
|
2023-01-19 15:25:45 +01:00
|
|
|
|
2023-08-17 02:00:50 +02:00
|
|
|
cmd.frametime = flOldFrameTime;
|
|
|
|
cmd.command_time = flOldCurTime;
|
|
|
|
|
2023-01-19 15:25:45 +01:00
|
|
|
pl.fixangle = FIXANGLE_NONE;
|
2023-01-19 20:48:41 +01:00
|
|
|
EyeAngles(&cmd.viewangles);
|
2023-01-19 15:25:45 +01:00
|
|
|
|
2023-02-12 15:06:08 +01:00
|
|
|
SetTimeBase((*g_pGlobals)->m_flCurTime);
|
2023-01-19 20:48:41 +01:00
|
|
|
MoveHelperServer()->SetHost(this);
|
|
|
|
|
|
|
|
PlayerRunCommand(&cmd, MoveHelperServer());
|
|
|
|
SetLastUserCommand(&cmd);
|
2023-01-19 15:25:45 +01:00
|
|
|
|
2023-02-12 15:06:08 +01:00
|
|
|
(*g_pGlobals)->m_flFrameTime = flOldFrameTime;
|
|
|
|
(*g_pGlobals)->m_flCurTime = flOldCurTime;
|
2023-01-19 21:45:15 +01:00
|
|
|
|
|
|
|
MoveHelperServer()->SetHost(NULL);
|
2023-01-19 15:25:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: gets the eye angles of this player
|
2023-01-19 20:48:41 +01:00
|
|
|
// Input : *pAngles -
|
2023-01-19 15:25:45 +01:00
|
|
|
// Output : QAngle*
|
|
|
|
//------------------------------------------------------------------------------
|
2023-01-19 20:48:41 +01:00
|
|
|
QAngle* CPlayer::EyeAngles(QAngle* pAngles)
|
2023-01-19 15:25:45 +01:00
|
|
|
{
|
2024-01-02 15:21:36 +01:00
|
|
|
return CPlayer__EyeAngles(this, pAngles);
|
2023-01-19 15:25:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: sets the time base for this player
|
|
|
|
// Input : flTimeBase -
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
inline void CPlayer::SetTimeBase(float flTimeBase)
|
|
|
|
{
|
2023-04-02 00:59:24 +02:00
|
|
|
float flTime = float(TIME_TO_TICKS(flTimeBase));
|
2023-01-19 15:25:45 +01:00
|
|
|
|
|
|
|
if (flTime < 0.0f)
|
|
|
|
flTime = 0.0f;
|
|
|
|
|
|
|
|
SetLastUCmdSimulationRemainderTime(flTime);
|
|
|
|
|
2023-08-18 00:43:44 +02:00
|
|
|
float flSimulationTime = flTimeBase - m_lastUCmdSimulationRemainderTime * (*g_pGlobals)->m_flTickInterval;
|
|
|
|
if (flSimulationTime >= 0.0f)
|
2023-01-19 15:25:45 +01:00
|
|
|
{
|
2023-08-18 00:43:44 +02:00
|
|
|
flTime = flSimulationTime;
|
2023-01-19 15:25:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
SetTotalExtraClientCmdTimeAttempted(flTime);
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: sets the last user cmd simulation remainder time
|
|
|
|
// Input : flRemainderTime -
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void CPlayer::SetLastUCmdSimulationRemainderTime(float flRemainderTime)
|
|
|
|
{
|
|
|
|
if (m_lastUCmdSimulationRemainderTime != flRemainderTime)
|
|
|
|
{
|
|
|
|
edict_t nEdict = NetworkProp()->GetEdict();
|
|
|
|
if (nEdict != FL_EDICT_INVALID)
|
|
|
|
{
|
2023-02-12 15:06:08 +01:00
|
|
|
_InterlockedOr16((SHORT*)(*g_pGlobals)->m_pEdicts + nEdict + 32, 0x200u);
|
2023-01-19 15:25:45 +01:00
|
|
|
}
|
|
|
|
|
2023-01-19 15:29:53 +01:00
|
|
|
m_lastUCmdSimulationRemainderTime = flRemainderTime;
|
2023-01-19 15:25:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: sets the total extra client cmd time attempted
|
|
|
|
// Input : flAttemptedTime -
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void CPlayer::SetTotalExtraClientCmdTimeAttempted(float flAttemptedTime)
|
|
|
|
{
|
|
|
|
if (m_totalExtraClientCmdTimeAttempted != flAttemptedTime)
|
|
|
|
{
|
|
|
|
edict_t nEdict = NetworkProp()->GetEdict();
|
|
|
|
if (nEdict != FL_EDICT_INVALID)
|
|
|
|
{
|
2023-02-12 15:06:08 +01:00
|
|
|
_InterlockedOr16((SHORT*)(*g_pGlobals)->m_pEdicts + nEdict + 32, 0x200u);
|
2023-01-19 15:25:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
m_totalExtraClientCmdTimeAttempted = flAttemptedTime;
|
|
|
|
}
|
|
|
|
}
|
2023-01-19 20:48:41 +01:00
|
|
|
|
2023-10-25 23:31:02 +02:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-02 21:49:35 +02:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// 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];
|
2023-08-15 00:45:58 +02:00
|
|
|
const int commandNumber = cmd->command_number;
|
|
|
|
|
|
|
|
if (commandNumber <= m_latestCommandQueued)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
m_latestCommandQueued = commandNumber;
|
|
|
|
const int lastCommandNumber = lastCmd->command_number;
|
|
|
|
|
|
|
|
if (lastCommandNumber == MAX_QUEUED_COMMANDS_PROCESS)
|
|
|
|
return;
|
2023-08-14 20:47:02 +02:00
|
|
|
|
2023-10-25 23:31:02 +02:00
|
|
|
if (sv_unlag_clamp->GetBool())
|
|
|
|
ClampUnlag(cmd);
|
2023-08-15 00:45:58 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2023-07-02 21:49:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
lastCmd->tick_count += droppedPackets;
|
|
|
|
m_bGamePaused = paused;
|
|
|
|
}
|
|
|
|
|
2023-01-19 20:48:41 +01:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: runs user command for this player
|
|
|
|
// Input : *pUserCmd -
|
|
|
|
// *pMover -
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void CPlayer::PlayerRunCommand(CUserCmd* pUserCmd, IMoveHelper* pMover)
|
|
|
|
{
|
2024-01-02 15:21:36 +01:00
|
|
|
CPlayer__PlayerRunCommand(this, pUserCmd, pMover);
|
2023-01-19 20:48:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Purpose: stores off a user command
|
|
|
|
// Input : *pUserCmd -
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void CPlayer::SetLastUserCommand(CUserCmd* pUserCmd)
|
|
|
|
{
|
|
|
|
m_LastCmd.Copy(pUserCmd);
|
|
|
|
}
|