From Valve Developer Community
Jump to: navigation, search

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 WriteUsercmd and ReadUsercmd.


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.

Note.png Note: 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 CPrediction::SetLocalViewAngles.

The default implementations of both of these IBaseClientDLL methods in class CHLClient delegate almost all of the work to the IInput interface.



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.

Once 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 IPrediction::Update.

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 C_BasePlayer::m_CommandContext).

See also