基础库层:tier0–tier3、vstdlib、mathlib
几乎所有上层模块都依赖同一组底层库。它们以“tier”命名,表达依赖方向(越低越通用),但并不是禁止跨层的严格分层。本页给出每层的职责与最常用的入口,具体的模块装配机制放在子页。
相关源码文件#
- tier0:
tier0/platform.cpp、tier0/threadtools.cpp、tier0/logging.cpp、tier0/vprof.cpp、tier0/memstd.cpp、tier0/commandline.cpp - tier1:
public/tier1/interface.h、tier1/convar.cpp、tier1/keyvalues.cpp、public/tier1/bitbuf.h、public/tier1/utlvector.h - tier2/tier3:
tier2/tier2.cpp、tier3/tier3.cpp - vstdlib:
vstdlib/cvar.cpp、vstdlib/jobthread.cpp、vstdlib/keyvaluessystem.cpp - 全局接口指针:
interfaces/interfaces.cpp
1. 各层职责#
| 层 | 职责 | 代表实体 | 证据 |
|---|---|---|---|
| tier0 | 平台抽象、计时、线程原语、日志、性能剖析、内存分配器、命令行 | Plat_FloatTime、ThreadSleep、LoggingSystem_Log、VPROF_BUDGET | tier0/platform.cpp:104、tier0/threadtools.cpp:471、tier0/logging.cpp:645、public/tier0/vprof.h:86-87 |
| tier1 | 容器、位流、KeyValues、ConVar/ConCommand、接口工厂 | CUtlVector、bf_write/bf_read、KeyValues、ConVar | public/tier1/utlvector.h:49-50、public/tier1/bitbuf.h:145、public/tier1/bitbuf.h:1401、public/tier1/keyvalues.h:84、public/tier1/convar.h:412 |
| tier2 | 依赖文件系统/材质系统等的便利层,以及 precache/资源系统注册 | ConnectTier2Libraries | tier2/tier2.cpp:58-74 |
| tier3 | 更上层的模型/场景工具函数 | mdlutils.cpp、choreoutils.cpp | tier3/tier3.cpp:26 |
| vstdlib | ConVar 注册表实现、线程池、KeyValues 符号表、随机数、进程工具 | CCvar、CThreadPool、g_pThreadPool | vstdlib/cvar.cpp:68、vstdlib/cvar.cpp:255、vstdlib/jobthread.cpp:205、vstdlib/jobthread.cpp:490 |
| mathlib | 向量/矩阵/四元数、SIMD、几何与软体相关数学 | mathlib_base.cpp、sse.cpp、vmatrix.cpp | mathlib/mathlib_base.cpp |
2. ConVar / ConCommand 的注册时机#
ConVar 是 Source 的“配置 + 网络复制 + 控制台命令”三合一机制,几乎所有调参都通过它暴露。
- 全局
ConVar对象在 DLL 静态构造时调用ConCommandBase::Create,若未带FCVAR_UNREGISTERED就挂到本模块的s_pConCommandBases链表;此时若访问器已存在则立即Init:tier1/convar.cpp:164-198。 - 模块在
Connect/Init阶段调用ConVar_Register( flags ):为所有挂起的命令附加模块标志(例如 client.dll 传入FCVAR_CLIENTDLL)、逐个Init注册到ICvar,然后清空链表:tier1/convar.cpp:63-89、game/client/cdll_client_int.cpp:1437。 - 卸载时
ConVar_Unregister按模块标识整体注销:tier1/convar.cpp:91-103。
常用标志(定义见 public/tier1/iconvar.h:41-79):
| 标志 | 含义 |
|---|---|
FCVAR_GAMEDLL / FCVAR_CLIENTDLL | 由哪个游戏模块定义 |
FCVAR_REPLICATED | 服务器值强制同步到客户端;服务器端变化通过 CNETMsg_SetConVar 广播(engine/sv_main.cpp:1503-1515) |
FCVAR_CHEAT | 仅在 sv_cheats 开启时可改 |
FCVAR_RELEASE | 发行版可见的变量;未带此标志的大量开发变量在零售版中隐藏 |
FCVAR_DEVELOPMENTONLY | 若定义 ALLOW_DEVELOPMENT_CVARS 则在创建时被清除(tier1/convar.cpp:177-179) |
控制台命令文本通过引擎的命令缓冲 Cbuf_AddText 入队,由 Cbuf_Execute 执行:engine/cmd.cpp:185、engine/cmd.cpp:252。所有构建中,_Host_RunFrame 在切分 tick 之前都会执行一次 Cbuf_Execute:engine/host.cpp:4112-4146。非 DEDICATED 构建还会在每个 tick 的输入阶段再执行一次:engine/host.cpp:3278-3292。命令来源、权限检查与按键绑定详见 输入与命令。
3. KeyValues:Source 的通用配置格式#
KeyValues 是层级化的文本/二进制键值树,LoadFromFile 通过文件系统按 path ID 读取:tier1/keyvalues.cpp:724、tier1/keyvalues.cpp:2294。它被用于 gameinfo.txt、游戏模式表(GameModes.txt)、物品 schema、匹配会话设置等大量场景;例如游戏模式初始化直接加载 GameModes.txt:game/shared/cstrike15/gametypes.cpp:259-284,匹配框架用 KeyValues 描述会话请求:matchmaking/mm_framework.cpp:682。
4. 位流 bf_write / bf_read#
网络层与 demo 文件都以“位”为单位读写消息与实体属性,入口类型是 bf_write/bf_read:public/tier1/bitbuf.h:145、public/tier1/bitbuf.h:1401。例如快照发送在栈上 scratch 缓冲中构造 bf_write:engine/baseclient.cpp:1430-1432;客户端用 bf_read 读取 CSVCMsg_PacketEntities 的实体数据:engine/cl_ents_parse.cpp:652。
5. 线程池#
vstdlib 提供全局线程池 g_pThreadPool:vstdlib/jobthread.cpp:490。引擎在多线程模式下把服务器 tick 包装成 CFunctorJob 投递给它:engine/host.cpp:4495-4500;材质系统在队列渲染模式下也用 CFunctorJob 执行上一帧的渲染命令队列:materialsystem/cmaterialsystem.cpp:4224。服务器快照的并行打包与发送使用 ParallelProcess:engine/sv_packedentities.cpp:593-596、engine/sv_main.cpp:2238-2243。
约束与边界#
- tier0 与 vstdlib 是动态库(POSIX 版 srcds 入口先
dlopen它们:dedicated_main/main.cpp:140-147;启动器在 Windows 上显式把 vstdlib 加入组以获取IProcessUtils:launcher/launcher.cpp:825-831),tier1/2/3、mathlib 等主要以静态库形式被各模块链接;lib/public中有它们的预编译版本(见 构建与物理组织)。 interfaces库维护的是每个模块一份的全局指针;不同 DLL 各自调用ConnectTier*Libraries填充自己的副本:interfaces/interfaces.cpp:243-272。