引擎运行时总览(engine/)
engine.dll 是连接平台系统与游戏 DLL 的调度中心:它拥有主循环、tick 时钟、网络通道、实体复制、地图与碰撞、demo/GOTV、声音与语音,并以接口形式向 client.dll/server.dll 提供服务。它不包含具体玩法;玩法通过 IServerGameDLL/IBaseClientDLL 回调插入(见 游戏 DLL 契约)。
子页面:
- 主循环、HostState 与 Tick
- 网络通道、协议与连接
- 实体复制:快照、SendTable 与差量编码
- 地图加载与碰撞追踪
- Demo 录制回放与 GOTV
- 引擎音频管线
- 语音与视频
- 输入与命令:从按键到 CUserCmd 与命令缓冲
- 服务器运维面:RCON、查询、认证、封禁与纯净服务器
- VGUI 与本地化
1. 文件到职责的映射#
engine/ 根目录有 486 个跟踪文件,另有 audio/(152)与 voice_codecs/(93)子目录。下表只列出理解运行流程所需的核心文件。
| 职责 | 核心文件 / 实体 | 证据 |
|---|---|---|
| 启动与模块装配 | sys_dll2.cpp:CEngineAPI、CModAppSystemGroup、CDedicatedServerAPI | engine/sys_dll2.cpp:410、engine/sys_dll2.cpp:451、engine/sys_dll2.cpp:2491 |
| 游戏 DLL 工厂聚合 | sys_dll.cpp:GameFactory、Sys_InitGame | engine/sys_dll.cpp:1014-1062、engine/sys_dll.cpp:1073 |
| 帧驱动 | sys_engine.cpp:CEngine::Frame/FilterTime | engine/sys_engine.cpp:418 |
| 状态机 | host_state.cpp:CHostState | engine/host_state.cpp:54-67 |
| 主循环与子系统初始化 | host.cpp:_Host_RunFrame、Host_Init、Host_NewGame | engine/host.cpp:3982、engine/host.cpp:5466、engine/host.cpp:6193 |
| 服务端引擎 | sv_main.cpp(CGameServer、SV_Frame)、baseserver.cpp、sv_client.cpp(CGameClient) | engine/sv_main.cpp:3428、engine/baseserver.cpp:3261、engine/sv_client.cpp:253 |
| 客户端引擎 | cl_main.cpp(CL_Move)、client.cpp/baseclientstate.cpp(CClientState)、cl_ents_parse.cpp、cl_pred.cpp | engine/cl_main.cpp:2736、engine/client.cpp:1490、engine/cl_ents_parse.cpp:574、engine/cl_pred.cpp:41 |
| 网络 | net_chan.cpp(CNetChan)、net_ws.cpp(套接字、NET_RunFrame) | engine/net_chan.cpp:1980、engine/net_ws.cpp:3640 |
| 实体复制 | sv_framesnapshot.cpp、sv_packedentities.cpp、sv_ents_write.cpp、dt_send_eng.cpp、dt_recv_eng.cpp | engine/sv_framesnapshot.cpp:138、engine/sv_packedentities.cpp:614、engine/sv_ents_write.cpp:817、engine/dt_send_eng.cpp:621、engine/dt_recv_eng.cpp:624 |
| 字符串表 | networkstringtable.cpp | engine/networkstringtable.cpp |
| 游戏事件 | GameEventManager.cpp | engine/GameEventManager.cpp:495 |
| 世界与碰撞 | modelloader.cpp、cmodel.cpp、enginetrace.cpp | engine/modelloader.cpp:5048、engine/cmodel.cpp:334、engine/enginetrace.cpp:2786 |
| 渲染桥接 | gl_screen.cpp、view.cpp、l_studio.cpp(CModelRender) | engine/gl_screen.cpp:209、engine/view.cpp:210、engine/l_studio.cpp:2491 |
| Demo / GOTV | cl_demo.cpp、hltvserver.cpp | engine/cl_demo.cpp:863、engine/hltvserver.cpp:2738 |
| 声音 | audio/private/snd_dma.cpp(S_Init、S_Update) | engine/audio/private/snd_dma.cpp:974、engine/audio/private/snd_dma.cpp:8203 |
| 对游戏暴露的接口 | IVEngineServer、IVEngineClient | engine/vengineserver_impl.cpp:2059、engine/cdll_engine_int.cpp:736 |
2. 引擎内部的“两半”#
同一个进程里,引擎同时扮演服务器(sv,类型 CGameServer)与客户端(GetBaseLocalClient(),类型 CClientState)。监听服务器时二者都活跃,每个 tick 依次执行“输入→服务器→客户端”:engine/host.cpp:4239-4271。专用服务器构建(DEDICATED 宏)编译掉客户端相关文件:engine/engine_inc.vpc:81-116。
单人/本地模式下服务器与客户端之间可以绕过真实网络:SV_ComputeClientPacks 检测到 g_pLocalNetworkBackdoor 时直接把实体状态写进客户端,而不是编码成数据包:engine/sv_packedentities.cpp:644-696。
3. 初始化顺序摘要#
Host_Init 的顺序决定了哪些子系统可以在何时被游戏 DLL 使用:服务器对象与 server.dll 先于客户端子系统与 client.dll 初始化:engine/host.cpp:5614-5621、engine/host.cpp:5636-5661。详细列表见 客户端启动链。
4. 游戏 DLL 如何拿到引擎接口#
server.dll 的 DLLInit 用工厂逐一获取 IVEngineServer、语音、网络字符串表、静态道具、声音、空间分区、模型信息、追踪、游戏事件、datacache 等接口,任何一个缺失都直接返回 false:game/server/gameinterface.cpp:727-786。工厂是引擎的 g_GameSystemFactory(先查 AppSystem 组,再查 matchmaking、client、GameUI):engine/sv_main.cpp:1095、engine/sys_dll.cpp:1014-1057。
约束与边界#
- 引擎通过大量
#ifndef DEDICATED与IsX360()/IsPS3()分支服务多个平台;本 Wiki 以 Windows PC 客户端与专用服务器为主线,主机平台分支只做标记。 - 各子系统页面的覆盖状态与有意排除项见 审计。