Frame Order: Difference between revisions
(Lots of new client prediction and render sections code.) |
(Rewrite Template:Lang to Template:LanguageBar. This action was performed by a bot.) |
||
(8 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
{{LanguageBar|Frame Order}} | |||
==Engine== | ==Engine== | ||
Line 15: | Line 10: | ||
* ''Italics - Client code, occurs on any client engine, client-only or listenserver'' | * ''Italics - Client code, occurs on any client engine, client-only or listenserver'' | ||
* <u>Underline - Code path for a dedicated server</u> (Non underline items do not run on a dedicated server.) | * <u>Underline - Code path for a dedicated server</u> (Non underline items do not run on a dedicated server.) | ||
* <font color=green>Green - Function call from the engine into game source</font> | |||
===Non-threaded model=== | ===Non-threaded model=== | ||
* ''<code>FrameStageNotify | * ''[[#Device_input|Device input]]'' | ||
* ''<code><font color=green>CHLClient::FrameStageNotify(FRAME_START)</font></code>'' | |||
* '''''<u>[[#Console_commands|Console commands]]</u>''''' | * '''''<u>[[#Console_commands|Console commands]]</u>''''' | ||
* For each tick: | * For each tick: | ||
Line 27: | Line 23: | ||
** ''[[#Client_logic|Client logic]]'' | ** ''[[#Client_logic|Client logic]]'' | ||
** ''[[#Client_prediction|Client prediction]]'' | ** ''[[#Client_prediction|Client prediction]]'' | ||
* ''[#Rendering|Rendering]]'' | * ''[[#Rendering|Rendering]]'' | ||
* ''Sound'' | * ''[[#Sound|Sound]]'' | ||
* ''Client HUD update'' | * ''[[#Client_HUD_update|Client HUD update]]'' | ||
===Threaded model=== | ===Threaded model=== | ||
* ''<code>FrameStageNotify | * ''[[#Device_input|Device input]]'' | ||
* ''<code><font color=green>CHLClient::FrameStageNotify(FRAME_START)</font></code>'' | |||
* '''''[[#Console_commands|Console commands]]''''' | * '''''[[#Console_commands|Console commands]]''''' | ||
* For each client tick: | * For each client tick: | ||
Line 41: | Line 38: | ||
* For each server tick: | * For each server tick: | ||
** ''[[#Input|Input]]'' | ** ''[[#Input|Input]]'' | ||
** '''''Networking''''' | ** '''''[[#Networking|Networking]]''''' | ||
* '''[[#Server_game_code|Server game code]]''' (in a separate thread) | * '''[[#Server_game_code|Server game code]]''' (in a separate thread) | ||
* ''[#Rendering|Rendering]]'' | * ''[[#Rendering|Rendering]]'' | ||
* ''Sound'' | * ''[[#Sound|Sound]]'' | ||
* ''Client HUD update'' | * ''[[#Client_HUD_update|Client HUD update]]'' | ||
==Sections== | ==Sections== | ||
Legend: | |||
* <font color=green>Green - Function call from the engine into game source</font> | |||
* <font color=purple>Purple - Code that exists inside the game sources available to modders</font> | |||
* <font color=darkred>Red - Special information</font> | |||
===Device input=== | |||
This section reads messages from the operating system and handles keyboard and window events. | |||
Key events are sent by priority first to tools (PET, Actbusy, etc) then to VGUI, then to the client game code, and finally to the engine. If one does not process it, it is then sent to the next. | |||
* If a key is pressed: <code><font color=green>CHLClient::IN_KeyEvent</font></code> | |||
===Console commands=== | ===Console commands=== | ||
Line 59: | Line 69: | ||
===Input=== | ===Input=== | ||
This section reads and processes input | This section reads and processes input messages. It runs only on client or localhost engines. | ||
* <code>CHLClient::HudProcessInput()</code> | * <code><font color=green>CHLClient::HudProcessInput()</font></code> | ||
* Process [[#Console_commands|console commands]] | * Process [[#Console_commands|console commands]] | ||
* Process player movement commands | * Process player movement commands | ||
** <code>CHLClient::CreateMove()</code> | ** <code><font color=green>CHLClient::CreateMove()</font></code> | ||
** Queue movement commands to network to the server | ** Queue movement commands to network to the server | ||
===Server game code=== | ===Server game code=== | ||
Line 91: | Line 81: | ||
This section calls <code>Think</code> functions for each entity and processes game logic. | This section calls <code>Think</code> functions for each entity and processes game logic. | ||
* If this is the last tick in the frame: <code>CServerGameDLL::Think()</code> | * If this is the last tick in the frame: <code><font color=green>CServerGameDLL::Think()</font></code> | ||
* Read network input | * Read network input | ||
* For each plugin: <code>IServerPluginCallbacks::GameFrame()</code> | * For each plugin: <code><font color=green>IServerPluginCallbacks::GameFrame()</font></code> | ||
* <code>CServerGameDLL::GameFrame()</code> | * <code><font color=green>CServerGameDLL::GameFrame()</font></code> | ||
** For each game system: <code>FrameUpdatePreEntityThink()</code> | ** <font color=purple>For each game system: <code>FrameUpdatePreEntityThink()</code> | ||
** <code>GameRules::Think()</code> | ** <code>GameRules::Think()</code> | ||
** Physics simulations | ** Physics simulations | ||
*** For each | *** For each player: <code>CBasePlayer::PlayerRunCommand()</code> | ||
** For each game system: <code>FrameUpdatePostEntityThink()</code> | ** For each game system: <code>FrameUpdatePostEntityThink()</code></font> | ||
* If this is the last tick in the frame: | * If this is the last tick in the frame: ''(This part of the tree occurs in a separate thread if the engine is threaded.)'' | ||
** <code>CServerGameDLL::PreClientUpdate()</code> | ** <code><font color=green>CServerGameDLL::PreClientUpdate()</font></code> | ||
*** For each game system: <code>PreClientUpdate()</code> | *** <font color=purple>For each game system: <code>PreClientUpdate()</code></font> | ||
** Transmit queued network messages | ** Transmit queued network messages | ||
** Set up | ** For every client: | ||
*** <code>CServerGameClients::ClientSetupVisibility()</code> | *** Set up network pack data | ||
* | **** <code><font color=green>CServerGameClients::ClientSetupVisibility()</font></code> | ||
**** <code><font color=green>CServerGameEnts::CheckTransmit()</font></code> | |||
**** In a singleplayer game, [[#Client_logic|Client logic]] is run through the local network backdoor (using memcpy instead of a slower network loopback) | |||
**** Changed entity data tables are packed for network transmission, and snapshots are sent to clients | |||
** <code><font color=green>CServerGameClients::PostClientMessagesSent()</font></code> | |||
===Client logic=== | |||
This section reads network packets and updates the entities on the client. | |||
* Read packets | |||
** If message is an entity packet: | |||
*** If multiplayer or if there are extra commands: | |||
**** Run [[#Client_prediction|prediction]] | |||
*** <code><font color=green>CPrediction::PreEntityPacketReceived</font></code> | |||
*** <code><font color=green>CHLClient::FrameStageNotify(FRAME_NET_UPDATE_START)</font></code> | |||
**** <font color=darkred>Absolute origin/angle queries invalidated</font> | |||
*** Update baseline, update entity data tables | |||
**** Calls to <code><font color=green>C_BaseEntity::PreDataUpdate</font></code> as necessary. | |||
*** <code><font color=green>CHLClient::FrameStageNotify(FRAME_NET_UPDATE_POSTDATAUPDATE_START)</font></code> | |||
*** For every updated entity: <code><font color=green>C_BaseEntity::PostDataUpdate()</font></code> | |||
*** <code><font color=green>CHLClient::FrameStageNotify(FRAME_NET_UPDATE_POSTDATAUPDATE_END)</font></code> | |||
**** <code><font color=purple>CPrediction::PostEntityPacketReceived()</font></code> | |||
*** If an entity has entered or exited the client's PVS: <code><font color=green>C_BaseEntity::NotifyShouldTransmit()</font></code> | |||
*** <code><font color=green>CHLClient::FrameStageNotify(FRAME_NET_UPDATE_END)</font></code> | |||
**** <font color=darkred>Absolute origin/angle queries re-validated</font> | |||
*** <code><font color=green>CPrediction::PostNetworkDataReceived()</font></code> | |||
** If message is an entity message: | |||
*** <code><font color=green>CHLClient::DispatchUserMessage()</font></code> | |||
** If message is a game event: | |||
*** <code><font color=green>ClientModeShared::FireGameEvent()</font></code> | |||
===Client prediction=== | ===Client prediction=== | ||
Line 112: | Line 132: | ||
This section runs prediction code for the local client. | This section runs prediction code for the local client. | ||
* <code>CPrediction::Update()</code> | * <code><font color=green>CPrediction::Update()</font></code> | ||
** Perform prediction | ** <font color=purple>Perform prediction. For every player movement command: | ||
*** | *** <code>CPrediction::RunSimulation()</code> | ||
* Update view angles with | *** For every predictable entity: | ||
** <code>CPrediction::SetLocalViewAngles()</code> | **** If data table has changed: <code>C_BaseEntity::OnPreDataChanged()</code> | ||
* <code>CHLClient::ExtraMouseSample()</code> | **** <code>C_BaseEntity::PhysicsSimulate()</code> | ||
***** <code>CPrediction::RunCommand()</code> | |||
***** If the entity is a player: | |||
****** <code>C_BasePlayer::PreThink()</code> | |||
****** <code>CPrediction::SetupMove()</code> | |||
****** <code>CGameMovement::ProcessMovement()</code> | |||
****** <code>CPrediction::FinishMove()</code> | |||
****** <code>C_BasePlayer::PostThink()</code> | |||
****** <code>CMoveHelperClient::ProcessImpacts()</code> | |||
***** If the entity is not a player: | |||
****** Run physics simulation and <code>C_BaseEntity::Think()</code> | |||
** <code>CPrediction::Untouch()</code> | |||
</font> | |||
* Update view angles with input information | |||
** <code><font color=green>CPrediction::SetLocalViewAngles()</font></code> | |||
* <code><font color=green>CHLClient::ExtraMouseSample()</font></code> | |||
===Rendering=== | ===Rendering=== | ||
Line 123: | Line 158: | ||
Rendering code sets up the view, updates all entities, and then renders the scene and user interface. | Rendering code sets up the view, updates all entities, and then renders the scene and user interface. | ||
* <code>CHLClient::FrameStageNotify(FRAME_RENDER_START)</code> | * <code><font color=green>CHLClient::FrameStageNotify(FRAME_RENDER_START)</font></code> | ||
** <code>CInput::CAM_Think()</code> | ** <font color=purple><code>CInput::CAM_Think()</code></font> | ||
** <code>CViewRender::OnRenderStart()</code> | ** <font color=purple><code>CViewRender::OnRenderStart()</code> | ||
*** <code>CViewRender::SetUpView()</code> | *** <code>CViewRender::SetUpView()</code> | ||
**** <code>CBasePlayer::CalcView()</code> | **** <code>CBasePlayer::CalcView()</code> | ||
Line 132: | Line 167: | ||
*** <code>ProcessOnDataChangedEvents()</code> | *** <code>ProcessOnDataChangedEvents()</code> | ||
**** For every entity with data changed: <code>C_BaseEntity::OnDataChanged()</code> | **** For every entity with data changed: <code>C_BaseEntity::OnDataChanged()</code> | ||
*** Update entities, tempents, particle systems, simulate physics | *** Update entities, tempents, particle systems, simulate physics, call ClientThink() functions</font> | ||
* <code>CHLClient::View_Render()</code> | * <code><font color=green>CHLClient::View_Render()</font></code> | ||
** Draws world and then UI | ** <font color=purple>Draws world and then UI</font> | ||
* | * <code><font color=green>CHLClient::FrameStageNotify(FRAME_RENDER_END)</font></code> | ||
===Sound=== | |||
Sound code processes and plays sounds on the client. It makes no calls into the game code. | |||
===Client HUD update=== | |||
This section calls one thing: | |||
* <code><font color=green>CHLClient::HudUpdate()</font></code> | |||
** <font color=purple>Update HUD and game systems</font> | |||
[[Category:Programming]] | [[Category:Programming]] |
Latest revision as of 17:54, 18 July 2025
Engine
The engine has two modes of execution, a threaded path and a non-threaded path. The host_thread_mode
cvar determines which path is taken. Dedicated servers will ignore this cvar and always use the non-threaded path. XBox 360 runs in threaded mode by default, while PC runs in non-threaded mode by default. Threaded mode was introduced with the Orange Box version of the Source engine, and does not exist in Episode 1 or previous versions.
Listenservers (ie, singleplayer games, or multiplayer games hosted by one of the players) will run all sections of code, calling both client.dll and server.dll functions from the same thread and in the same engine loop. Clients connected to a remote server will run the italicized sections only, and dedicated servers will run the bold items only. Dedicated server builds (Linux or Windows SrcDs) will run only the underlined sections.
Legend:
- Bold - Server code, occurs on any server engine, server-only or listenserver
- Italics - Client code, occurs on any client engine, client-only or listenserver
- Underline - Code path for a dedicated server (Non underline items do not run on a dedicated server.)
- Green - Function call from the engine into game source
Non-threaded model
- Device input
CHLClient::FrameStageNotify(FRAME_START)
- Console commands
- For each tick:
- Rendering
- Sound
- Client HUD update
Threaded model
- Device input
CHLClient::FrameStageNotify(FRAME_START)
- Console commands
- For each client tick:
- Client prediction
- For each server tick:
- Server game code (in a separate thread)
- Rendering
- Sound
- Client HUD update
Sections
Legend:
- Green - Function call from the engine into game source
- Purple - Code that exists inside the game sources available to modders
- Red - Special information
Device input
This section reads messages from the operating system and handles keyboard and window events.
Key events are sent by priority first to tools (PET, Actbusy, etc) then to VGUI, then to the client game code, and finally to the engine. If one does not process it, it is then sent to the next.
- If a key is pressed:
CHLClient::IN_KeyEvent
Console commands
This section evaluates and executes commands input into the game console. If the console command is a ConCommand created by the game code, it will execute a callback into the game code through ConCommand::Dispatch( const CCommand &command )
in convar.cpp
.
Networking
This section sends and receives network messages. It runs on a localhost server through an internal backdoor loopback device. On server-only or client-only instances it runs over a UDP connection. No game code callbacks are made during this time.
Input
This section reads and processes input messages. It runs only on client or localhost engines.
CHLClient::HudProcessInput()
- Process console commands
- Process player movement commands
CHLClient::CreateMove()
- Queue movement commands to network to the server
Server game code
This section calls Think
functions for each entity and processes game logic.
- If this is the last tick in the frame:
CServerGameDLL::Think()
- Read network input
- For each plugin:
IServerPluginCallbacks::GameFrame()
CServerGameDLL::GameFrame()
- For each game system:
FrameUpdatePreEntityThink()
GameRules::Think()
- Physics simulations
- For each player:
CBasePlayer::PlayerRunCommand()
- For each player:
- For each game system:
FrameUpdatePostEntityThink()
- For each game system:
- If this is the last tick in the frame: (This part of the tree occurs in a separate thread if the engine is threaded.)
CServerGameDLL::PreClientUpdate()
- For each game system:
PreClientUpdate()
- For each game system:
- Transmit queued network messages
- For every client:
- Set up network pack data
CServerGameClients::ClientSetupVisibility()
CServerGameEnts::CheckTransmit()
- In a singleplayer game, Client logic is run through the local network backdoor (using memcpy instead of a slower network loopback)
- Changed entity data tables are packed for network transmission, and snapshots are sent to clients
- Set up network pack data
CServerGameClients::PostClientMessagesSent()
Client logic
This section reads network packets and updates the entities on the client.
- Read packets
- If message is an entity packet:
- If multiplayer or if there are extra commands:
- Run prediction
CPrediction::PreEntityPacketReceived
CHLClient::FrameStageNotify(FRAME_NET_UPDATE_START)
- Absolute origin/angle queries invalidated
- Update baseline, update entity data tables
- Calls to
C_BaseEntity::PreDataUpdate
as necessary.
- Calls to
CHLClient::FrameStageNotify(FRAME_NET_UPDATE_POSTDATAUPDATE_START)
- For every updated entity:
C_BaseEntity::PostDataUpdate()
CHLClient::FrameStageNotify(FRAME_NET_UPDATE_POSTDATAUPDATE_END)
CPrediction::PostEntityPacketReceived()
- If an entity has entered or exited the client's PVS:
C_BaseEntity::NotifyShouldTransmit()
CHLClient::FrameStageNotify(FRAME_NET_UPDATE_END)
- Absolute origin/angle queries re-validated
CPrediction::PostNetworkDataReceived()
- If multiplayer or if there are extra commands:
- If message is an entity message:
CHLClient::DispatchUserMessage()
- If message is a game event:
ClientModeShared::FireGameEvent()
- If message is an entity packet:
Client prediction
This section runs prediction code for the local client.
CPrediction::Update()
- Perform prediction. For every player movement command:
CPrediction::RunSimulation()
- For every predictable entity:
- If data table has changed:
C_BaseEntity::OnPreDataChanged()
C_BaseEntity::PhysicsSimulate()
CPrediction::RunCommand()
- If the entity is a player:
C_BasePlayer::PreThink()
CPrediction::SetupMove()
CGameMovement::ProcessMovement()
CPrediction::FinishMove()
C_BasePlayer::PostThink()
CMoveHelperClient::ProcessImpacts()
- If the entity is not a player:
- Run physics simulation and
C_BaseEntity::Think()
- Run physics simulation and
- If data table has changed:
CPrediction::Untouch()
- Perform prediction. For every player movement command:
- Update view angles with input information
CPrediction::SetLocalViewAngles()
CHLClient::ExtraMouseSample()
Rendering
Rendering code sets up the view, updates all entities, and then renders the scene and user interface.
CHLClient::FrameStageNotify(FRAME_RENDER_START)
CInput::CAM_Think()
CViewRender::OnRenderStart()
CViewRender::SetUpView()
CBasePlayer::CalcView()
- For every player:
CBasePlayer::UpdateClientSideAnimation()
CMultiPlayerAnimState::Update()
ProcessOnDataChangedEvents()
- For every entity with data changed:
C_BaseEntity::OnDataChanged()
- For every entity with data changed:
- Update entities, tempents, particle systems, simulate physics, call ClientThink() functions
CHLClient::View_Render()
- Draws world and then UI
CHLClient::FrameStageNotify(FRAME_RENDER_END)
Sound
Sound code processes and plays sounds on the client. It makes no calls into the game code.
Client HUD update
This section calls one thing:
CHLClient::HudUpdate()
- Update HUD and game systems