Ru/Frame Order

==Движок==
Движок имеет два режима работы - потоковый (многопоточный) и безпотоковый (однопоточный). Переменная host_thread_mode определяет, какой режим работы будет использован. Выделенные сервера игнорируют эту переменную и всегда используют безпотоковый (однопоточный) путь. XBox 360 по-умолчанию работает в потоковом режиме, в то время как ПК по-умолчанию работает в безпотоковом. Потоковый режим был введен вместе с Orange Box версией движка, и не существовал в Episode 1 или в предыдущих версиях.
Сервера-слушатели (listenservers) (например однопользовательские игры или сервера запущенные одним из игроков) выполняют все секции кода, вызывая функции из client.dll и server.dll в одном и том же цикле работы движка. Клиенты, подключенные к удаленному серверу могут выполнять только помеченные курсивом секции, а выделенные (dedicated) сервера могут выполнять только секции выделенные жирным. Сборки выделенного (dedicated) сервера (Linux или Windows SrcDs) могут выполнять только подчеркнутые секции.
Обозначения:
* Жирный - код сервера, работает на любом сервере, только для серверов или серверов-на-клиентах
* Курсивом - код клиента, работает на любом клиенте, только для клиента или серверов-на-клиентах
* Подчеркнуто - код для выделенного сервера (Не подчеркнутые элементы не выполняются на выделенном сервере)
* Зеленым - функции вызываемые движком внутри игрового кода
===Безпотоковая модель===
* Device input
* CHLClient::FrameStageNotify(FRAME_START)
* Console commands
* На каждом такте:
** Networking
** Input
** Server game code
** Client logic
** Client prediction
* Rendering
* Sound
* Client HUD update
===Потоковая модель===
* Device input
* CHLClient::FrameStageNotify(FRAME_START)
* Console commands
* На каждом такте:
** Networking
** Client logic
* Client prediction
* Для каждого такта сервера:
** Input
** Networking
* Server game code (в отдельном потоке)
* Rendering
* Sound
* Client HUD update
==Секции==
Обозначения:
* Зеленым - функция вызываемая движком внутри игрового кода
* Пурпурным - код существующий внутри игрового кода и доступный для изменения
* Красным - специальная информация
===Device input===
Эта секция читает сообщения от операционной системы и указателей клавиатуры и события окна.
События кнопок отправляются по очереди сначала утилитам (PET, Actbusy и т.п.), затем к системе VGUI, клиентскому коду игры, и наконец движку. Если один из элементов цепи не может обработать полученное событие, то оно отправляется на обработку следующему звену.
* При нажатии кнопки: CHLClient::IN_KeyEvent
===Console commands===
В этой секции подсчитываются и исполняются команды, введенные в игровую консоль. Если консольная команда это команда созданная игровым кодом, она выполнит возврат внутри игрового кода через ConCommand::Dispatch( const CCommand &command ) в файле convar.cpp.
===Networking===
В этой секции отправляются и принимаются сетевые сообщения. На сервере локального хоста она работает через локальную петлю (loopback). На экземплярах только для серверов или только для клиентов работает через соединение по протоколу UPD. Игровой код не вызывается в этой секции.
===Input===
Эта секция читает и исполняет входящие сообщения. Она работает только на клиенте или локальном хосте.
* CHLClient::HudProcessInput()
* Обработка console commands
* Обработка команд перемещения игрока
** CHLClient::CreateMove()
** Помещение команд перемещения в очередь для передачи по сети на сервер
===Server game code===
Эта секция вызывает функции Think для каждой сущности и выполняет игровую логику.
* Если это последний такт фрейма: CServerGameDLL::Think()
* Читает сетевой ввод
* Для каждого плагина: IServerPluginCallbacks::GameFrame()
* CServerGameDLL::GameFrame()
** Для каждой игровой системы: FrameUpdatePreEntityThink()
** GameRules::Think()
** Симуляция физики
*** Для каждого игрока: CBasePlayer::PlayerRunCommand()
** Для каждой игровой системы: FrameUpdatePostEntityThink()
* Если это последний такт фрейма: (Эта часть кода выполняется в отдельном потоке если движок работает в потоковом режиме.)
** CServerGameDLL::PreClientUpdate()
*** Для каждой игровой системы: PreClientUpdate()
** Передача очередных сетевых сообщений
** Для каждого клиента:
*** Настройка упаковки данных для сети
**** CServerGameClients::ClientSetupVisibility()
**** CServerGameEnts::CheckTransmit()
**** В одиночной игре, Client logic работает через локальный сетевой интерфейс (используя memcpy вместо медленной сетевой петли)
**** Измененные таблицы данных сущностей упаковываются для передачи по сети и снимки (snapshots) отправляются клиентам
** CServerGameClients::PostClientMessagesSent()
===Client logic===
Эта секция читает сетевые пакеты и обновляет сущности на клиенте.
* Читает пакеты
** Если сообщение является пакетом сущности:
*** Если это мультиплеер или особая команда:
**** Запуск prediction
*** CPrediction::PreEntityPacketReceived
*** CHLClient::FrameStageNotify(FRAME_NET_UPDATE_START)
**** Запрос на проверку векторов и углов
*** Обновление базовых данных, обновление таблиц данных сущностей
**** При необходимости вызов C_BaseEntity::PreDataUpdate.
*** CHLClient::FrameStageNotify(FRAME_NET_UPDATE_POSTDATAUPDATE_START)
*** Для каждой обновленной сущности: C_BaseEntity::PostDataUpdate()
*** CHLClient::FrameStageNotify(FRAME_NET_UPDATE_POSTDATAUPDATE_END)
**** CPrediction::PostEntityPacketReceived()
*** Если сущность вошла или вышла из : C_BaseEntity::NotifyShouldTransmit()
*** CHLClient::FrameStageNotify(FRAME_NET_UPDATE_END)
**** Запрос на повторную проверку векторов и углов
*** CPrediction::PostNetworkDataReceived()
** Если сообщение это сообщение сущности:
*** CHLClient::DispatchUserMessage()
** Если сообщение это игровое событие:
*** ClientModeShared::FireGameEvent()
===Client prediction===
Эта секция выполняет код прогнозирования для локального клиента.
* CPrediction::Update()
** Выполнение прогнозирования. Для каждой команды перемещения игрока:
*** CPrediction::RunSimulation()
*** Для каждой прогнозируемой сущности:
**** Если таблица была изменена: C_BaseEntity::OnPreDataChanged()
**** C_BaseEntity::PhysicsSimulate()
***** CPrediction::RunCommand()
***** Если сущность это игрок:
****** C_BasePlayer::PreThink()
****** CPrediction::SetupMove()
****** CGameMovement::ProcessMovement()
****** CPrediction::FinishMove()
****** C_BasePlayer::PostThink()
****** CMoveHelperClient::ProcessImpacts()
***** Если сущность это не игрок:
****** Запуск физической симуляции и C_BaseEntity::Think()
** CPrediction::Untouch()
* Обновление углов в соответствии с исходными данными
** CPrediction::SetLocalViewAngles()
* CHLClient::ExtraMouseSample()
===Rendering===
Настройка отрисовки видимого мира, обновление всех сущностей и отрисовка сцены и пользовательского интерфейса.
* CHLClient::FrameStageNotify(FRAME_RENDER_START)
** CInput::CAM_Think()
** CViewRender::OnRenderStart()
*** CViewRender::SetUpView()
**** CBasePlayer::CalcView()
*** Для каждого игрока: CBasePlayer::UpdateClientSideAnimation()
**** CMultiPlayerAnimState::Update()
*** ProcessOnDataChangedEvents()
**** Для каждой сущности с изменившимися данными: C_BaseEntity::OnDataChanged()
*** Обновление сущностей, временных сущностей (tempents), систем частиц, симуляция физики, вызов функции ClientThink() 
* CHLClient::View_Render()
** Рисует мир и пользовательский интерфейс
* CHLClient::FrameStageNotify(FRAME_RENDER_END)
===Sound===
Код обработки звука и воспроизведение звуков на клиенте. Это не делает вызовы в коде игры.
===Client HUD update===
Эта секция вызывает:
* CHLClient::HudUpdate()
** Обновление HUD и игровых систем