Usercmd: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
No edit summary
No edit summary
 
(4 intermediate revisions by 2 users not shown)
Line 1: Line 1:
'''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 and decompression are handled in <code>WriteUsercmd</code> and <code>ReadUsercmd</code>.
'''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 <code>WriteUsercmd</code> and <code>ReadUsercmd</code>.


== Production ==
== Production ==
Usercmds are created when the engine invokes <code>IBaseClientDLL::CreateMove</code> (once per tick). The default implementation, <code>CHLClient::CreateMove</code>, doesn't do much besides forwarding the call to <code>CInput::CreateMove</code>. The usercmds created there are stored in a circular buffer (<code>CInput::PerUserInput_t::m_pCommands</code>) until the engine invokes <code>IBaseClientDLL::WriteUsercmdDeltaToBuffer</code> to compress and serialize them to the server.
Usercmds intended for transmission to the server are created when the engine invokes <code>IBaseClientDLL::CreateMove</code> (once per tick). The usercmds created are stored in a circular buffer (<code>CInput::PerUserInput_t::m_pCommands</code>) until the engine invokes <code>IBaseClientDLL::WriteUsercmdDeltaToBuffer</code> to compress and serialize them to the server.


During <code>CInput::CreateMove</code>, the current client mode is also given a chance to manipulate the newly created usercmd via <code>IClientMode::CreateMove</code>. The default implementation (<code>ClientModeShared::CreateMove</code>) delegates to the local player via <code>C_BasePlayer::CreateMove</code>, which in turn passes the usercmd to <code>CBaseCombatWeapon::CreateMove</code> on the active weapon.
The current client mode is also given a chance to manipulate the newly created usercmd via <code>IClientMode::CreateMove</code>. The default implementation (<code>ClientModeShared::CreateMove</code>) delegates to the local player via <code>C_BasePlayer::CreateMove</code>, which in turn passes the usercmd to <code>CBaseCombatWeapon::CreateMove</code> on the active weapon.
 
{{note|<code>IBaseClientDLL::ExtraMouseSample</code>, which can be run by the engine between calls to <code>CreateMove</code>, executes most of the same client code. However, in this case, the generated usercmd is effectively discarded after being used to update <code>CPrediction::SetLocalViewAngles</code>.}}
 
The default implementations of both of these <code>IBaseClientDLL</code> methods in class <code>CHLClient</code> delegate almost all of the work to the <code>IInput</code> interface.


== Consumption ==
== Consumption ==
Line 10: Line 14:
The incoming usercmds are consumed on the server when the engine invokes <code>IGameServerClients::ProcessUsercmds</code>. This method handles decompressing the delta usercmds, and then dispatches them to <code>CBasePlayer::ProcessUsercmds</code>. The player caches each such batch of commands together in a <code>CCommandContext</code> object to be processed later.
The incoming usercmds are consumed on the server when the engine invokes <code>IGameServerClients::ProcessUsercmds</code>. This method handles decompressing the delta usercmds, and then dispatches them to <code>CBasePlayer::ProcessUsercmds</code>. The player caches each such batch of commands together in a <code>CCommandContext</code> object to be processed later.


Once <code>IServerGameDLL::GameFrame</code> is called, the player's <code>PhysicsSimulate</code> method executes the cached usercmds via <code>CBasePlayer::PlayerRunCommand</code>. From here, the active CPlayerMove-derived class executes (Pre/Post)Think for the player, as well as populating g_pMoveData and executing <code>IGameMovement::ProcessMovement</code> for the player.
Once <code>IServerGameDLL::GameFrame</code> is called, the player's <code>PhysicsSimulate</code> method executes the cached usercmds via <code>CBasePlayer::PlayerRunCommand</code>. From here, the active CPlayerMove-derived class executes (pre/post)think for the player, as well as populating g_pMoveData and executing <code>IGameMovement::ProcessMovement</code> for the player.


=== Client ===
=== Client ===
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 <code>IPrediction::Update</code> (instead of <code>IServerGameDLL::GameFrame</code>).
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 <code>IPrediction::Update</code>.


<code>CPrediction::RunSimulation</code> invokes the client implementation of <code>PhysicsSimulate</code> on the local player. From here, the player calls back into <code>CPrediction::RunCommand</code>, which very closely mirrors the server <code>PlayerRunCommand</code> 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 <code>C_BasePlayer::m_CommandContext</code>).
<code>CPrediction::RunSimulation</code> invokes the client implementation of <code>C_BasePlayer::PhysicsSimulate</code> on the local player. From here, the player calls back into <code>CPrediction::RunCommand</code>, which very closely mirrors the server <code>PlayerRunCommand</code> 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 <code>C_BasePlayer::m_CommandContext</code>).


== See also ==
== See also ==
* [[Source Multiplayer Networking]]
* [[UserCmd strings]]
* [[UserCmd strings]]


[[Category:Networking]]
[[Category:Networking]]
[[Category:Glossary]]

Latest revision as of 16:25, 10 April 2023

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.

Production

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.pngNote: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.

Consumption

Server

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.

Client

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