CUserCmd ("user command") is the networkable representation of the player's input, including keys pressed and viewangle. By default, updates are sent from client to server at a rate of 30 per second (cl_cmdrate) in the form of delta-compressed usercmds. Delta compression and decompression are handled in
Usercmds intended for transmission to the server are created when the engine invokes
IBaseClientDLL::CreateMove (once per tick). The usercmds created are stored in a circular buffer (
CInput::PerUserInput_t::m_pCommands) until the engine invokes
IBaseClientDLL::WriteUsercmdDeltaToBuffer to compress and serialize them to the server.
The current client mode is also given a chance to manipulate the newly created usercmd via
IClientMode::CreateMove. The default implementation (
ClientModeShared::CreateMove) delegates to the local player via
C_BasePlayer::CreateMove, which in turn passes the usercmd to
CBaseCombatWeapon::CreateMove on the active weapon.
IBaseClientDLL::ExtraMouseSample, which can be run by the engine between calls to
CreateMove, executes most of the same client code. However, in this case, the generated usercmd is effectively discarded after being used to update
The default implementations of both of these
IBaseClientDLL methods in class
CHLClient delegate almost all of the work to the
The incoming usercmds are consumed on the server when the engine invokes
IGameServerClients::ProcessUsercmds. This method handles decompressing the delta usercmds, and then dispatches them to
CBasePlayer::ProcessUsercmds. The player caches each such batch of commands together in a
CCommandContext object to be processed later.
IServerGameDLL::GameFrame is called, the player's
PhysicsSimulate method executes the cached usercmds via
CBasePlayer::PlayerRunCommand. From here, the active CPlayerMove-derived class executes (pre/post)think for the player, as well as populating g_pMoveData and executing
IGameMovement::ProcessMovement for the player.
The code path for most things that occur during client prediction is very similar to the equivalent server code path, but the entry point from the engine is
CPrediction::RunSimulation invokes the client implementation of
C_BasePlayer::PhysicsSimulate on the local player. From here, the player calls back into
CPrediction::RunCommand, which very closely mirrors the server
PlayerRunCommand functionality: pre-think, think, game movement, and post-think are all executed for the local player using the values from the outgoing usercmd (stored in