CD Code Digest Hub /CS:GO

基础库层:tier0–tier3、vstdlib、mathlib

10 分钟阅读 7 个章节

几乎所有上层模块都依赖同一组底层库。它们以“tier”命名,表达依赖方向(越低越通用),但并不是禁止跨层的严格分层。本页给出每层的职责与最常用的入口,具体的模块装配机制放在子页。

子页面:接口工厂与 AppSystem 生命周期

相关页面:构建与物理组织 · 主循环与 Tick

相关源码文件#

  • 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_BUDGETtier0/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、ConVarpublic/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/资源系统注册ConnectTier2Librariestier2/tier2.cpp:58-74
tier3更上层的模型/场景工具函数mdlutils.cpp、choreoutils.cpptier3/tier3.cpp:26
vstdlibConVar 注册表实现、线程池、KeyValues 符号表、随机数、进程工具CCvar、CThreadPool、g_pThreadPoolvstdlib/cvar.cpp:68、vstdlib/cvar.cpp:255、vstdlib/jobthread.cpp:205、vstdlib/jobthread.cpp:490
mathlib向量/矩阵/四元数、SIMD、几何与软体相关数学mathlib_base.cpp、sse.cpp、vmatrix.cppmathlib/mathlib_base.cpp

2. ConVar / ConCommand 的注册时机#

ConVar 是 Source 的“配置 + 网络复制 + 控制台命令”三合一机制,几乎所有调参都通过它暴露。

  1. 全局 ConVar 对象在 DLL 静态构造时调用 ConCommandBase::Create,若未带 FCVAR_UNREGISTERED 就挂到本模块的 s_pConCommandBases 链表;此时若访问器已存在则立即 Init:tier1/convar.cpp:164-198。
  2. 模块在 Connect/Init 阶段调用 ConVar_Register( flags ):为所有挂起的命令附加模块标志(例如 client.dll 传入 FCVAR_CLIENTDLL)、逐个 Init 注册到 ICvar,然后清空链表:tier1/convar.cpp:63-89、game/client/cdll_client_int.cpp:1437。
  3. 卸载时 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。