Skip to content

开发者

本页介绍如何从源码构建 PracLab 的两层组件,以及项目结构说明。部署产物请参考安装部署

1. 编译依赖

1.1 L1(C# 插件)

依赖 版本 说明
.NET SDK 10.0+ 编译 L1
CounterStrikeSharp.API 1.0.371+ NuGet 自动还原

1.2 L2(C++ Metamod 插件)

依赖 版本 说明
Visual Studio 2022+ MSVC 14.51+ Windows 编译
CMake 3.20+ 构建系统
Ninja 任意 CMake 生成器
HL2SDK CS2 与服务器匹配 环境变量 HL2SDKCS2
Metamod:Source 源码 与服务器匹配 环境变量 MMSOURCE_DEV
protoc 3.21.x 环境变量 PROTOC
funchook v1.1.3 CMake FetchContent 自动拉取(或本地源码)
nlohmann/json v3.11.3 CMake FetchContent 自动拉取(或本地源码)

2. 构建 L1(PracLab C# 插件)

# 在仓库根目录执行
dotnet build PracLab.csproj -c Release

产物路径:

bin/Release/net10.0/
├── PracLab.dll                # 主程序集
└── lang/
    ├── zh-CN.json             # 中文本地化(构建时自动复制)
    └── en.json                # 英文本地化

3. 构建 L2(PracLabReplayEngine C++ 插件)

3.1 准备 SDK

将 HL2SDK CS2、Metamod 源码、protoc 解压到 d:\PracLab\deps\

deps/
├── hl2sdk-cs2/
├── metamod-source/
├── protoc-3.21.8/
│   └── bin/protoc.exe
├── funchook/                 # funchook 源码(可选,否则 CMake 在线拉取)
└── nlohmann_json/            # nlohmann/json 源码(可选,否则 CMake 在线拉取)

3.2 配置 CMake

cd d:\PracLab\replay-engine
.\configure.ps1

configure.ps1 会自动设置 MSVC 环境变量、清理旧缓存并用 Ninja 生成 Release 构建目录。脚本内硬编码了 MSVC 与 Windows SDK 路径,环境不同请按实际情况修改。

3.3 编译

.\build.ps1

成功时输出:

=== SUCCESS ===
DLL: d:\PracLab\replay-engine\out\build\x64-Release\package\addons\PracLabReplayEngine\bin\win64\PracLabReplayEngine.dll
Size: XXX.XX KB

3.4 关键构建约束

以下源于引擎行为与项目规范:

  • protoc 版本:为 3.21.x,CMakeLists.txt 会校验。
  • 静态运行时:Windows 使用 /MT(静态链接 CRT),保证插件可独立部署。
  • protoc 生成代码.pb.h 中类的 final 关键字会被自动移除,以允许 PlayerCommand 继承 CSGOUserCmdPB
  • gamedata.json:包含引擎函数签名,CS2 更新后可能需要重新扫描签名。详见 replay-engine/configs/addons/PracLabReplayEngine/gamedata.json

4. 项目结构

PracLab/
├── PracLab.cs                # 插件主类(路由表/门控/配置加载/共享数据)
├── PracLab.csproj            # .NET 10 项目文件
├── Commands/                 # 各功能 partial 类
│   ├── BotCommands.cs            # .bot / .crouchbot / .kick / .kickall
│   ├── BotCollisionHandler.cs    # Bot 碰撞管理 + 重生传送
│   ├── ClearCommands.cs          # .clear / .break
│   ├── ConVarCommands.cs         # .solid / .impacts / .traj
│   ├── DamageHandler.cs          # 实时伤害提示
│   ├── DryRunCommands.cs         # .dryrun / .restartround
│   ├── EventHandlers.cs          # OnMapStart / OnEntitySpawned / EventPlayerBlind 等
│   ├── GrenadeCommands.cs        # .rethrow* / .last
│   ├── GrenadeFunctions.cs       # 投掷物生成辅助
│   ├── HelpCommand.cs            # .help
│   ├── PracticeCommands.cs       # .prac / .map
│   ├── ReplayCommands.cs         # .record / .replay / .clearrecord* / .currentrecord
│   ├── SpawnCommands.cs          # .spawn 系列 9 条
│   ├── SpawnMarkerCommands.cs    # .showspawns / .hidespawns + E 键传送
│   ├── TeamCommands.cs           # .watch / .fas
│   ├── TimeGodCommands.cs        # .fastforward / .noflash / .god
│   └── TimerCommand.cs           # .timer
├── cfg/PracLab/              # 服务器配置文件
│   ├── config.cfg                # 插件总开关 + 默认语言
│   ├── prac.cfg                  # 练习模式 ConVar
│   └── dryrun.cfg                # 竞技模式 ConVar
├── lang/                     # 本地化
│   ├── zh-CN.json
│   └── en.json
├── replay-engine/            # Layer 2 C++ Metamod 插件
│   ├── src/                      # 录制/回放/hook 实现
│   ├── include/praclab_replay.h  # 跨语言 ABI 头文件
│   ├── configs/                  # Metamod VDF + gamedata.json
│   ├── configure.ps1             # CMake 配置脚本
│   ├── build.ps1                 # 编译脚本
│   └── CMakeLists.txt
└── documentation/            # 本文档(MkDocs)
    ├── docs/
    └── mkdocs.yml

5. 跨语言 ABI 契约

Layer 1(C#)与 Layer 2(C++)之间通过 P/Invoke 调用 PRL_* 系列 C 函数通信。头文件位于 replay-engine/include/praclab_replay.h

修改 ABI 时须同步更新两层代码:

修改类型 Layer 1(C#) Layer 2(C++)
新增/修改结构体字段 Commands/ReplayCommands.cs 中的 [StructLayout] include/praclab_replay.h + src/exports.cpp
新增导出函数 Commands/ReplayCommands.cs 中的 [DllImport] 声明 include/praclab_replay.h 声明 + src/exports.cpp 实现
字段顺序调整 必须同步 必须同步(影响内存布局)

6. 本地化文件维护

所有面向玩家的文本必须从 lang/*.json 加载:

  • lang/zh-CN.json — 中文(默认语言)
  • lang/en.json — 英文