Ravenz16/dow-de-replay-parser

GitHub: Ravenz16/dow-de-replay-parser

针对《战争黎明》终极版回放文件进行二进制逆向解析的 Java 工具,能从命令流还原玩家操作并生成战术分析报告。

Stars: 1 | Forks: 0

# DoW 回放分析器 *其他语言阅读:[Русский](README.ru.md)* 这是一款 Java 工具,能够解析 **Dawn of War** 回放文件(`.rec`)并直接从二进制命令流中还原每位玩家的操作——包括建造顺序、据点占领、单位指令、技能以及针对每位玩家的战术总结。 由于回放格式未公开,命令流是逐字节进行逆向工程得出的。本项目即是这项工作的成果。 ## 功能简介 给定一个 `.rec` 文件,分析器会输出一份结构化报告: - **Header** — 地图、时长(ticks → 秒)以及玩家/观察者列表。 - **命令流摘要** — 解析的事件、读取的数据包、解码的子命令。 - **找到的 CMD_ID** — 遇到的每个命令操作码及其计数。 - **时间线** — 解码事件的按时间顺序列表(tick、时间、命令、实体、位置)。 - **建造/占领/发电厂事件** — 筛选出的建筑和据点占领视图。 - **玩家专属时间线** — 在两名人类玩家之间划分的事件。 - **建造顺序** — 每位玩家按顺序排列的关键经济和战术行动。 - **战术分析** — 针对每位玩家的经济状况(兵营、发电厂、LP 哨所、占领、科技)和军队状况(指令、攻击、技能)。 ## 工作原理 `.rec` 文件是一个 Relic Chunky 容器。处理流水线如下: 1. `BinaryReader` — 针对原始字节的底层小端序读取器。 2. `RecursiveRelicChunkParser` + `RelicChunkNode` + `ChunkSearch` — 遍历 chunk 树并定位元数据(地图、玩家)和 **`FOLDINFO`** chunk。 3. `CommandStreamParser` — 命令流紧随 `FOLDINFO` 开始。该类将其解码为 `GameEvent` 列表,并将其归因于对应玩家。 4. `test.Main` — 入口点;运行流水线并打印报告。 ### 命令流布局(逆向工程得出) 该流是 **packets** 的平铺序列,每个数据包代表一名玩家在一个游戏 tick 中的操作: | Offset | Field | Notes | |-------:|-------|-------| | `-4` | packet size | payload 前的 4 字节小端序前缀 | | `0` | `0x50` marker | 标识命令数据包 | | `1..4` | tick | uint32 LE;`tick / 8.0` = 秒 | | `13` | command count | 数据包中子命令的数量 | | `25..28` | inner size | 仅覆盖**第一个**子命令块 | | `30+` | sub-commands | 第一个块在此处;后续块通过尾部扫描恢复 | 每个**子命令**携带实体 ID(`+2..5`)、位于 `+27` 的 phase 字节,并且——对于 40 字节格式——还包含一个位置(`x@+34`, `y@+36`, `z@+38`, int16 LE)。子命令大小: - `28 / 33 / 35` — 进度/完成标记(无坐标)。 - `40` — 带有坐标的真实放置/指令。 - `45` — 嵌入了多个操作码的复合命令。 操作码(`cmd_id`)对于 40 字节的命令在 `+29` 处读取,其他情况在 `+23` 处读取;phase 为 `3` 的 40 字节建造格式将类型编码为 `0xC300 | byte[28]`。 ## 项目结构 ``` com.dow.replay.parser.BinaryReader low-level binary reader com.dow.replay.chunk.RelicChunkNode chunk tree node com.dow.replay.chunk.ChunkSearch chunk lookup helpers com.dow.replay.chunk.RecursiveRelicChunkParser Relic Chunky parser com.dow.replay.parser.CommandStreamParser core: command stream → events + attribution test.Main entry point / report printer ``` ## 构建与运行 要求 **JDK 17**(基于 Amazon Corretto 17 开发)。源代码编码为 UTF-8。 在 IntelliJ IDEA 中:打开项目,将 SDK 设置为 17,并将 `test.Main` 作为主类运行,同时将回放文件路径作为程序参数: ``` test.Main scr\replays\.rec ``` 从命令行运行: ``` javac -encoding UTF-8 -d out $(find src -name "*.java") java -cp out test.Main scr/replays/.rec ``` 回放文件名遵循 `W--L-` 约定(胜者/败者),例如 `#1521554-W-ORK-L-TAU.rec` 表示兽人获胜,钛帝国战败。 ## 已知局限 这是对未公开格式的严谨逆向工程,有些信息仅从命令流中无法还原: - **仅记录了状态改变指令。** Dawn of War 会记录建造、移动、攻击、技能、占领和增援——但**不包括**选择、镜头移动、控制组点击或待机指令(这些占据了原始 APM 的大部分)。因此,命令计数远低于玩家的真实 APM,这是由游戏设计决定的。 - **没有针对单条指令的玩家字段。** 经过调查已被排除:phase 字节追踪的是建造的*地图方位*,实体 ID 是全局按时间排序的计数器(玩家区间会重叠),且数据包头字节是同步哈希值。因此,玩家归属是一种**启发式算法**:种族专属命令族 + 主基地位置 + 最近邻传播。这对于技能、种族专属指令和基础设施是可靠的,但在两名玩家交替操作的窗口期,**共享指令(占领/移动/攻击)可能会被误判**。 - **`cmd_id` 的含义具有对局特异性。** 操作码是种族/建造菜单蓝图,而非通用动作代码——相同的操作码在不同的对局中可能含义不同。对于共享的命令,标签是通用的;只有在确认为种族专属时,才会使用 `TAU_*` / `ORK_*` 标签。 - **开局基础建筑可能不可见。** 一些早期建筑是通过 28 字节命令发布的,这些命令会融入完成时的噪声中,因此无法被单独解析。 - **AI/机器人指令**不会记录在回放命令流中。 - **观察者**会显示为额外的玩家槽位(一场 1v1 最多可容纳 6 名观众),但他们不会发出任何指令。 ## 状态 已针对多种对战(钛帝国 vs 黑暗灵族,兽人 vs 钛帝国)进行了深入的逆向工程。命令流布局和事件解码已趋于稳定;玩家归属目前是基于尽力的启发式算法,并将随着更多真实回放被分析而持续改进。
标签:JS文件枚举, 二进制解析, 云资产清单, 代码示例, 域名枚举, 数据分析, 文件解析, 游戏工具, 逆向工程