dougwithseismic/racemake-challenge

GitHub: dougwithseismic/racemake-challenge

一个面向赛车模拟游戏的遥测分析管道方案,包含 Hono API、二进制编解码器和运行时 schema 提取等生产级组件。

Stars: 1 | Forks: 0

### Hey Racemake 在布拉格,你找不到比我更契合这份工作的人选了;我专注于 C++、Rust(主要是 Tauri)和 React 领域的游戏工具与逆向工程。我的使命是摆脱无聊的 B2B SaaS 客户,追随我在游戏、AI 和自动化交叉领域的激情。 首先,重要的是 —— 你的挑战 —— 基础的、困难的,以及基于我构建 Source 2 游戏(如 Counterstrike、Dota 和 Deadlock)Game Event API 管道经验的一些关于“IRL 场景”的额外文档:**[见下文]** **过往工作** - **RL platform** — 以 20 倍速启动 Counterstrike 比赛,以构建由自我改进模型驱动的复杂机器人,该模型由 LLM 驾驶。C++, Rust, Python, React — 包括带有共享内存实时数据的 Tauri 覆盖层。 - [s2-framework](https://github.com/dougwithseismic/s2-framework) · [YouTube Demo](https://www.youtube.com/watch?v=Cj94lSUH5io) - **Reverse engineering tool** — 构建用于挂钩数千款游戏并为电子竞技、游戏辅助工具和补丁/模组构建数据管道。被 [wand.com](https://wand.com) (WeMod) 团队用于构建其新的 LLM 游戏辅助教练功能。 - [arc-probe](https://github.com/vzco/arc-probe) **挑战** — 给我一个要在 Steam 上买的赛车模拟游戏标题,我将从零开始构建整个数据管道、存储、API 层、实时覆盖层和全栈 React 应用。 **聊聊吧** — 薪水是合理的 —— 只要我能付得起房租,并且做我关心的激情项目,你很难让我只做兼职。(无薪也可以)。这就是我:[ARES](https://www.finmag.cz/obchodni-rejstrik/ares/10911243-douglas-anthony-silkstone) 很享受这个挑战 —— 希望你不介意我如此投入。在 LinkedIn 上喊我 / 给我打电话;别装酷 :) — **Doug**
## 重要链接 | 资源 | URL | |---|---| | **Live Web App** | [racemake-challenge.up.railway.app](https://racemake-challenge.up.railway.app) | | **API Documentation (Scalar)** | [racemake-challenge.up.railway.app/docs](https://racemake-challenge.up.railway.app/docs) | | **Live API Base** | [racemake-challenge.up.railway.app/api/v2](https://racemake-challenge.up.railway.app/api/v2) | | **OpenAPI Spec** | [racemake-challenge.up.railway.app/openapi.json](https://racemake-challenge.up.railway.app/openapi.json) | | **Source Code** | [github.com/dougwithseismic/racemake-challenge](https://github.com/dougwithseismic/racemake-challenge) | | **dezlock-dump** (Runtime Schema Extraction) | [github.com/dougwithseismic/dezlock-dump](https://github.com/dougwithseismic/dezlock-dump) | | **arc-probe** (AI Process Inspector) | [github.com/vzco/arc-probe](https://github.com/vzco/arc-probe) | | **s2-framework** (RL Bot Platform) | [github.com/dougwithseismic/s2-framework](https://github.com/dougwithseismic/s2-framework) | ## 结构 Turborepo monorepo。每个挑战都是一个独立的 package。 ``` apps/ api/ # Hono API — mounts all challenges with Scalar docs packages/ challenge-easy/ src/original/ # Untouched challenge file from RACEMAKE src/solution/ # Our solution — bug fix, stint extension, scaling answer challenge-hard/ src/original/ # Untouched challenge file from RACEMAKE src/solution/ # Our solution — Hono API with telemetry processing ``` ### Live API **https://racemake-challenge.up.railway.app** - **Docs (Scalar):** [/docs](https://racemake-challenge.up.railway.app/docs) - **Easy — Analyze:** [/api/v2/easy/analyze](https://racemake-challenge.up.railway.app/api/v2/easy/analyze) - **Easy — Stint:** [/api/v2/easy/stint](https://racemake-challenge.up.railway.app/api/v2/easy/stint) - **Hard — Laps:** [/api/v2/hard/laps](https://racemake-challenge.up.railway.app/api/v2/hard/laps) - **Hard — Analysis:** [/api/v2/hard/analysis](https://racemake-challenge.up.railway.app/api/v2/hard/analysis) - **IRL — Architecture:** [/api/v2/irl](https://racemake-challenge.up.railway.app/api/v2/irl) - **IRL — Wire Format Codec:** [/api/v2/irl/codec/compare](https://racemake-challenge.up.railway.app/api/v2/irl/codec/compare) - **IRL — Roundtrip Proof:** [/api/v2/irl/codec/roundtrip](https://racemake-challenge.up.railway.app/api/v2/irl/codec/roundtrip) - **IRL — SSE Stream:** [/api/v2/irl/stream](https://racemake-challenge.up.railway.app/api/v2/irl/stream) ### 快速开始(本地) ``` pnpm install # Full API with all routes + Scalar docs npx tsx apps/api/src/index.ts # Easy challenge standalone pnpm --filter @repo/challenge-easy start # Hard challenge standalone + integration test npx tsx packages/challenge-hard/src/solution/test.ts ``` ## 挑战解决方案 ### Easy — `@repo/challenge-easy` **Level 1 (Fix it):** `analyzeLap` 中的排序比较器是 `a.delta - b.delta` —— 升序。由于 `generateCoaching` 选择 `findings[0]` 作为最差的扇区,它返回的是*最少*的时间损失而不是最多的。修复:`b.delta - a.delta`。单行差异。 **Level 2 (Extend it):** 添加了 `analyzeStint()`,它为每个车手圈速运行 `analyzeLap` 并检测整个 stint 期间的扇区级趋势。跟踪每个扇区的 delta 进展,将趋势分类为恶化/稳定/改善,并生成 PitGPT stint 总结,以捕捉补偿模式(例如,早期的抬油门掩盖了因轮胎退化导致的抓地力损失)。 **Level 3 (Think about it):** 参见 `challenge.ts` 中的注释块。TL;DR —— 在 20 辆车 x 50 圈 x 120 Hz 的情况下,内存首先耗尽。流式处理进入时间序列存储,在 worker 中按车辆隔离,添加背压,在扇区边界去抖动 coaching。 ### Hard — `@repo/challenge-hard` 基于 Hono 构建的三个端点: | 端点 | 功能 | |---|---| | `POST /ingest` | 接收原始遥测帧,存储在内存中 | | `GET /laps` | 返回带有扇区分段、速度指标的已完成圈速摘要 | | `GET /analysis` | 比较圈速,找出最差圈速的最差扇区,检测问题,返回 PitGPT coaching | 处理的边缘情况: - **Out-lap 已排除** — 第 0 圈从位置 0.541 开始,而不是从起点/终点线开始 - **不完整圈速已排除** — 第 4 圈只有 S1 数据 - **静止帧已过滤** — 速度 < 5 且位置未变 - **问题检测** — 轮胎过热(>110C)在第 3 圈 S2 中正确识别 - **扇区边界插值** — 在 10Hz 下,帧间隔约 3.2 秒。一种朴素的方法(测量每个扇区帧内的时间)会丢失扇区间的间隙 —— **每圈 6.4 秒** 无法计算,且扇区总和不等于圈时间。我们在跨越每条扇区线的两帧之间插值确切的边界穿越时间,因此 S1 + S2 + S3 = lapTime 精确无误。 ## IRL 挑战:逆向工程与遥测管道 ### 问题 模拟赛车遥测是从游戏内存或 API 中提取的。当游戏更新补丁时,偏移量会移动,结构体会改变,你的管道就会崩溃。社区等待有人逆向工程新的偏移量。这种等待会扼杀你的产品。 ### 解决方案:Runtime Schema Extraction 我为 Source 2 游戏构建了这个确切的系统。与其硬编码每次更新都会损坏的偏移量: 1. **运行时注入** — 手动 PE 映射(无 LoadLibrary,对模块列表不可见)。DLL 通过 vtable 拦截挂钩到游戏进程中。 2. **从游戏本身提取 schema** — Source 2 在运行时暴露其自己的 `SchemaSystem`。以编程方式遍历它以转储每个类、字段、偏移量和继承链。游戏*告诉你*它自己的结构。 3. **生成防补丁 SDK** — 字段偏移量通过 schema 在运行时动态解析,而不是通过硬编码值。当游戏打补丁时,schema 会改变 —— 但解析机制不会。零手动工作。 4. **将其输送给下游** — 提取的 schema 直接输入到 SDK 生成器,生成类型化的 C++ 头文件(2,400+ 结构体,229 个实体类)和完整的 JSON 导出供工具消费者使用。 这就是 [dezlock-dump](https://github.com/dougwithseismic/dezlock-dump) 所做的。 ### 应用于赛车遥测 该模式对于模拟赛车是完全相同的: ``` Game Process -> DLL Injection -> Schema Extraction -> Typed SDK -> Telemetry Pipeline -> Analysis ``` 专门针对 RACEMAKE 的技术栈: - **游戏更新发布** -> 运行 schema 提取器 -> 几分钟内获得新偏移量,而不是几天 - **遥测格式更改** -> SDK 自动重新生成,根据游戏自己的定义进行类型化 - **新数据字段出现** -> 它们在任何人记录它们之前就出现在 schema 转储中 ### 保持最新:偏移量与转储 关键见解:你不再需要手动逆向工程偏移量。你构建提取它们的系统。相关工具: | 工具 | 功能 | 仓库 | |---|---|---| | **dezlock-dump** | 运行时 RTTI + schema 提取,自动 SDK 生成,跨 58+ 个 DLL 的签名扫描 | [链接](https://github.com/dougwithseismic/dezlock-dump) | | **s2-framework** | 通过 DLL 注入 + TCP 遥测流传输到 Python/PyTorch 的 ML 机器人训练。精确的注入-提取-流模式。 | [链接](https://github.com/dougwithseismic/s2-framework) | | **memory-hooking-tool** | 带有 TypeScript 脚本功能的进程内存读/写。模式扫描,PE 解析,全自动化层。 | [链接](https://github.com/dougwithseismic/memory-hooking-tool) | | **arc-probe** | AI 代理驱动的进程检查器。DLL 注入,反汇编,结构映射 —— 均可通过 Claude Code 技能控制。Tauri v2 应用 (Rust + React)。 | [链接](https://github.com/vzco/arc-probe) | ### 最佳方法 **为了 schema 稳定性:** - 运行时解析优于硬编码偏移量。始终如此。 - 模式签名(字节序列)作为后备 —— 它们可以在无法进行完整 schema 提取的小补丁中存活。 - 带有版本标签的 schema 缓存,这样你就可以在游戏版本之间进行 diff 并自动检测发生了什么变化。 **为了管道弹性:** - Protobuf/flatbuffers 作为有线格式 —— schema 演进内置于协议中。 - 记录器(Tauri/Rust 端)应该是 schema 感知的,而不仅仅是转储原始字节。如果字段移动,记录器会自适应。 - Canary 检查:在游戏启动时,根据预期范围验证少量已知字段值。如果它们错误,则 schema 发生了偏移 —— 在发送垃圾数据 downstream 之前发出警报。 **为了领先于社区:** - 构建你自己的提取器。不要等待社区转储。 - 自动化转储管道:检测到游戏更新 -> 注入 -> 提取 -> diff -> PR -> 部署。逆向工程的 CI。 - 监控游戏测试版分支 —— schema 更改通常首先出现在那里。 ### 有线格式:为什么 JSON 遥测是疯狂的 120Hz 下的原始 JSON 每帧约 131 字节。20 辆车那就是 **307 KB/s** 的纯开销 —— 每帧重复字段名,无增量编码,无 schema 版本控制。 `/api/v2/irl/codec` 路由展示了一个生产级的替代方案: | 格式 | 每帧 | 20 辆车 @ 120Hz | 减少 | |---|---|---|---| | JSON | ~131 bytes | 307 KB/s | — | | Binary (v1 schema) | 19 bytes | 45 KB/s | **85.5%** | | Delta-encoded | ~6 bytes avg | ~14 KB/s | **95.4%** | **编解码器的主要特性:** - **版本化 schema 注册表** — 当游戏打补丁并添加字段时,添加新的 schema 版本。旧消费者仍然可以工作(向前兼容性)。与 Protobuf 字段编号相同的原理。 - **双向映射** — 通过 `/roundtrip` 端点证明 `encode()` 和 `decode()` 在所有 166 个遥测帧中是无损的。量化低于传感器噪声底限。 - **Delta encoding** — 120Hz 下的连续帧可能在 3-4 个字段上有所不同。只传输变化的内容。一个 2 字节的 bitmask 头 + 变化的字段字节。 在生产中,你会使用 Protobuf(RACEMAKE 已经在用)或 FlatBuffers 来实现零拷贝。这是一个从头开始的实现,用于展示原理。 [在线试用:/api/v2/irl/codec/compare](https://racemake-challenge.up.railway.app/api/v2/irl/codec/compare)

github.com/dougwithseismic

标签:AI, Bun, C++, Dota, GNU通用公共许可证, Hono API, Node.js, Python, React, Rust, Scalar, Source 2 引擎, Syscalls, Tauri, TypeScript, Wire Format, 云资产清单, 产品工程师, 反恐精英, 可视化界面, 安全插件, 技术面试, 数据处理管道, 数据擦除, 无后门, 机器人开发, 游戏事件API, 游戏工具开发, 生产级编解码器, 网络流量审计, 网络调试, 自动化, 自动化代码审查, 自动化攻击, 计算机视觉, 远程测量分析, 逆向工具, 逆向工程