mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-09-18 06:34:54 +08:00
补齐解析模块维护冻结规则,并同步 CURRENT_STATUS、CURRENT_GAPS、PROJECT_PLAN、RPC 参考、部署指南、用户指南和官方资源运行说明。 文档同时反映 bat-api 资源 bootstrap/分发边界、官方同步解析缓存、TextUnit 队列、双目录发布和 patch 入口的当前状态。 验证:未运行新命令;本轮已按要求停止重复构建/测试。
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# AssetBundle 与资源解析路线图
|
||||
|
||||
- **更新时间**:2026-07-25
|
||||
- **更新时间**:2026-07-26
|
||||
- **适用范围**:Rust 解析引擎、官方同步后的解析缓存、CAS/ResourceRepository 接入、后续文本提取和 Patch 发布。
|
||||
- **权威关联**:`PROJECT_PLAN.md` Milestone 3/4/5/8,`docs/reports/CURRENT_GAPS.md` G-005/G-007/G-011/G-011D。
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
1. 官方资源同步负责拉取、校验和发布原版资源。
|
||||
2. 解析器只读取已发布或 staging 中已校验的资源,不修改原始文件。
|
||||
3. 解析结果写入派生缓存、CAS 索引或后续文本提取索引。
|
||||
4. 汉化产物只能由 Patch/发布阶段写入 `localized-output`,不能写回官方资源目录。
|
||||
4. 汉化产物只能由 Patch/发布阶段写入 `--localized-output` / `BAT_LOCALIZED_OUTPUT` 指定的汉化发布根,不能写回官方资源目录。
|
||||
5. 解析器必须与 CLI、daemon、Go API、Patch 业务流程解耦。
|
||||
|
||||
当前官方同步完成后会维护 `official-parse-cache.json`。它是官方 release 的派生索引,不是汉化产物;本地 URL、相对路径、size 和 BLAKE3 未变化时应复用旧解析结果并跳过重复解析。
|
||||
当前官方同步在新 release 发布后会先维护 `official-resource-changes.json` 和 `crowdin-translation-handoff.json`,再维护 `official-parse-cache.json`、`official-textunit-index.json`、`official-textunit-tasks.json` 和 `crowdin-textunit-queue.json`。这些都是官方 release 的派生索引,不是汉化产物;up-to-date 轮询在已有有效解析缓存、TextUnit 明细索引和 TextUnit 队列时只读取摘要,不重复解析。
|
||||
|
||||
---
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
| Addressables catalog | `catalog_*.zip` 内 JSON/bin catalog、`catalog_*.hash` | asset path、provider、dependencies、size、CRC、bundle name | JSON/compact 当前样本已覆盖,仍需更多真实结构变体 |
|
||||
| UnityFS container | `.bundle`、zip 内 bundle | header、block、directory、解压文件、基础摘要 | 已支持基础解包、LZ4/LZMA、边界校验 |
|
||||
| Serialized file | UnityFS directory 文件 | header、type table、TypeTree node、object table、TextAsset bytes | 已支持基础表结构和 TextAsset bytes |
|
||||
| Unity 对象字段 | TextAsset、MonoBehaviour、ScriptableObject | 可翻译文本单元、上下文、资源定位 | TextAsset bytes 已有入口,字段级反序列化未完成 |
|
||||
| Patch 发布前解析 | 已翻译文本、中间格式、原版资源 | 可验证 patch manifest、汉化 release 目录 | 未完成 |
|
||||
| Unity 对象字段 | TextAsset、MonoBehaviour、ScriptableObject | 可翻译文本单元、上下文、资源定位 | TypeTree 基础字段读取、`SerializedReference` / prefixed managed-reference metadata alias、payload 提取和字符串提取已落地,真实结构覆盖继续扩大 |
|
||||
| Patch 发布前解析 | 已翻译文本、中间格式、原版资源 | 可验证 patch manifest、汉化 release 目录 | UnityFS TextAsset 前置已落地,通用 Binary/JSON/Text Patch 与文件级 patch / UnityFS 写入入口可用,发布级 build/rollback 未开放 |
|
||||
|
||||
---
|
||||
|
||||
@@ -45,16 +45,17 @@
|
||||
4. 能从 UnityFS directory 提取文件 bytes。
|
||||
5. `serialized` 模块能读取 Unity serialized file header、type table、TypeTree node 元数据、object table。
|
||||
6. 能提取 TextAsset 的 name 和原始 bytes。
|
||||
7. `ResourceImportService` 能把 AssetBundle 摘要、TextAsset/Table/Media 分类写入导入报告。
|
||||
8. 官方同步后 `OfficialParseCacheService` 能从 `official-download-manifest.json` 遍历所有资源,解析直接 bundle 和 zip 内条目,非候选资源记录为 unsupported。
|
||||
7. TypeTree field reader 已支持基础标量、string、bytes、array、vector/staticvector 嵌套 `Array` 形态、`List<T>` / `HashSet<T>` 集合 alias、map、PPtr、enum `value__` backing field、`LayerMask` / `BitField` 的 `m_Bits` backing field、嵌套对象、常见固定 Unity float/int/hash 值类型的 leaf 和 direct child TypeTree 形态、unknown fixed-size raw bytes 保留和同长度替换、TypeTree-covered managed reference、TypeTree-covered managed reference registry 记录、`m_ManagedReferences` / `RefIds` / `m_RefIds` / verbose type 字段等 registry 命名变体、`id` / `typeInfo` 等 metadata 命名变体、`data` / `value` / `payload` / `object` / `managedReferencePayload` / `referencePayload` / `serializedReferencePayload` / `managedReferenceValue` / `referenceValue` / `serializedReferenceValue` / `managedReferenceObject` / `referenceObject` / `serializedReferenceObject` / `managedReferenceData` / `referenceData` / `serializedData` 等 payload 命名变体、managed-reference full typename 拆解和字段 offset/size 诊断。
|
||||
8. `TextUnitExtractor` 已把 JSON/CSV/TSV/plain TextAsset、TypeTree 字符串字段和 TypeTree-covered managed reference payload 字符串输出为可序列化 TextUnit/JSONL;zip 场景保留 archive entry,TextUnit 明细包含 serialized file、path id、class id、field path、字段 offset/byte size、format、asset name 和上下文。managed-reference 类型元数据保留为 payload context,不进入翻译文本队列;即使 registry 暂时只能走 fallback 字段遍历,`RefIds`、`className`、`namespaceName`、`asmName` 等元数据别名也会被跳过,payload/value/object 家族和 `managedReferenceData` / `referenceData` / `serializedData` 仍按 payload 处理,并按 `RefIds[n]` 等记录前缀或子字段推导 metadata,避免多条 fallback record 混用 managed-reference context。
|
||||
9. `ResourceImportService` 能把 AssetBundle 摘要、TextAsset/Table/Media 分类和 TextUnit 摘要写入导入报告。
|
||||
10. 官方同步后 `OfficialParseCacheService` 能从 `official-download-manifest.json` 遍历所有资源,解析直接 bundle 和 zip 内条目,非候选资源记录为 unsupported,并缓存 TextUnit 数量/格式/诊断摘要,同时写出 `official-textunit-index.json` 供 `parse.text_units` / `parse.errors` 查询。
|
||||
|
||||
当前还不能宣称完整:
|
||||
|
||||
1. MonoBehaviour/ScriptableObject 的 TypeTree 字段级反序列化未完成。
|
||||
2. Unity managed reference、PPtr、array/map、string alignment 等复杂字段未完整覆盖。
|
||||
3. Addressables bin/compact catalog 结构变体仍需真实样本驱动补齐。
|
||||
4. 解析结果尚未自动进入用户级 CAS + ResourceRepository 查询流程。
|
||||
5. 不能重写 AssetBundle,也不能生成可发布汉化 patch。
|
||||
1. TypeTree-covered managed reference 字段和 registry 记录已可结构化解码并参与文本提取,常见 registry 命名别名(含 `m_ManagedReferences`、`RefIds`、`m_RefIds`、verbose type 字段)、metadata 命名别名(含 `id`、`typeInfo`)、payload 命名别名(含 `data`、`value`、`payload`、`object`、`managedReferencePayload`、`referencePayload`、`serializedReferencePayload`、`managedReferenceValue`、`referenceValue`、`serializedReferenceValue`、`managedReferenceObject`、`referenceObject`、`serializedReferenceObject`、`managedReferenceData`、`referenceData`、`serializedData`)、full typename 拆解和 payload-only TextUnit 提取已有回归覆盖,多记录 registry 聚合也已有单元回归;fallback 字段遍历会跳过常见 registry 元数据字符串,避免误入翻译队列,并按记录前缀或子字段可推导 metadata 保留 managed-reference TextUnit context。enum `value__` backing field 和 `LayerMask` / `BitField` 的 `m_Bits` backing field 已可语义化解码和替换;`Vector2f/3f/4f`、`Quaternionf`、`ColorRGBA`、`Rectf`、`AABB/Bounds/Ray`、`Matrix4x4f`、`Vector2Int/Vector3Int`、`RectInt`、`BoundsInt`、`RangeInt`、`GUID`、`Hash128` 等固定 Unity 值类型的 leaf 和 direct child TypeTree 形态已可结构化解码和语义替换;array/vector/staticvector/List/HashSet/map 元素与 registry payload 字段已保留独立 field path、offset 和 byte size,可用于字符串元素 patch,managed-reference registry payload 字符串、enum、bit_field、unknown fixed-size raw bytes、object 字段组合和 TypeTree schema 支撑的 array/vector/List/HashSet/map 已可整体变长替换,`first/second` 与 `key/value` map entry schema 已有 serialized 和 UnityFS 重建回归,ScriptableObject `key/value` map 解析、变长替换和 UnityFS 重建已有专门回归,且嵌套 vector `Array`、`List<T>` / `HashSet<T>` 集合 alias、enum、bit_field、unknown fixed-size raw bytes 与 managed-reference payload 字段已有重建回归覆盖;解析模块当前处于维护冻结,未见样本驱动的完整 managed reference registry / map entry 变体、unknown 字段结构语义和版本差异冻结后再推进。
|
||||
2. Addressables bin/compact catalog 结构变体仍需真实样本驱动补齐。
|
||||
3. 官方 release 已可配置导入 CAS + ResourceRepository,并可通过 `resource.index` 查询现有资源索引;Resource metadata 已记录 release、平台、bundle path、parse status、TextAsset 名称和 TextUnit 摘要。
|
||||
4. 不能完成复杂对象字段重打包,也不能从真实 Crowdin 结果自动生成完整汉化文件集合。
|
||||
|
||||
---
|
||||
|
||||
@@ -66,17 +67,23 @@
|
||||
|
||||
交付:
|
||||
|
||||
1. `official-parse-cache.json` 记录 manifest entry、zip entry、解析状态、Unity 版本、文件数、TextAsset 数、错误摘要和缓存复用状态。
|
||||
2. 解析直接 `.bundle` / `.unity3d` 和 zip 内全部文件条目,不能只假设 `FullPatch_*.zip`。
|
||||
3. 非候选资源记录为 unsupported,不影响官方同步发布。
|
||||
4. 缺失、损坏或无法解析的 bundle 记录 failed,但不回滚已经完成校验的官方原版 release。
|
||||
5. 用合成 fixture、隔离真实样本和回归 fixture 覆盖缓存复用、zip 内条目、非候选资源、解析失败。
|
||||
1. `official-resource-changes.json` 记录当前 release 相对上一完整 release 的新增、变更、删除资源,以及解析/翻译候选计数。
|
||||
2. `crowdin-translation-handoff.json` 只包含新增+变更资源,作为后续 Crowdin worker 的本地队列输入;当前解析阶段不直接调用 Crowdin API。
|
||||
3. `official-parse-cache.json` 记录 manifest entry、zip entry、解析状态、Unity 版本、文件数、TextAsset 数、TextUnit 数/格式、错误摘要和缓存复用状态。
|
||||
4. `official-textunit-index.json` 持久化单条 TextUnit 和解析错误,保留 destination、archive entry、serialized file、path id、class id、field path、offset 和 format 等定位信息。
|
||||
5. `official-textunit-tasks.json` 只从 Added/Modified 资源、parse cache 和 TextUnit 明细索引派生,记录可翻译 TextUnit 任务和跳过原因。
|
||||
6. `crowdin-textunit-queue.json` 只包含已经产生 TextUnit 的离线任务,当前不调用 Crowdin 网络 API。
|
||||
7. 解析直接 `.bundle` / `.unity3d` 和 zip 内全部文件条目,不能只假设 `FullPatch_*.zip`。
|
||||
8. 非候选资源记录为 unsupported,不影响官方同步发布。
|
||||
9. 缺失、损坏或无法解析的 bundle 记录 failed,但不回滚已经完成校验的官方原版 release。
|
||||
10. 用合成 fixture、隔离真实样本和回归 fixture 覆盖资源变更集、Crowdin handoff、TextUnit 队列、缓存复用、zip 内条目、非候选资源、解析失败。
|
||||
|
||||
验收:
|
||||
|
||||
1. 第二次运行同一 release 时能看到解析缓存复用计数。
|
||||
2. 修改任意 manifest entry 的 size/BLAKE3 后,只重新解析对应资源。
|
||||
3. 解析缓存不会写入 `localized-output`。
|
||||
1. 新 release 发布时能生成资源变更集,新增+变更资源进入解析/翻译候选,删除资源不进入翻译队列。
|
||||
2. 第二次 up-to-date 轮询不会重复解析已有有效缓存和 TextUnit 明细索引。
|
||||
3. 修改任意 manifest entry 的 size/BLAKE3 后,变更集能标记对应资源并让后续解析/翻译只消费候选。
|
||||
4. 解析缓存、handoff 和 TextUnit 队列不会写入汉化发布根。
|
||||
|
||||
### P1:Addressables catalog 完整化
|
||||
|
||||
@@ -103,10 +110,10 @@
|
||||
交付:
|
||||
|
||||
1. TypeTree schema 内部表示稳定化:node path、type、name、size、flags、array 信息。
|
||||
2. 实现基础字段 reader:bool、integer、float、string、bytes、array、map、PPtr、managed reference 占位。
|
||||
3. 支持 TextAsset script/name 的结构化读取,而不只保留 raw bytes。
|
||||
4. 支持 MonoBehaviour 和 ScriptableObject 的 TypeTree 字段遍历。
|
||||
5. 对缺 TypeTree 或 stripped 类型返回可诊断错误,保留 raw object bytes 作为后备。
|
||||
2. 基础字段 reader 已支持 bool、integer、float、string、bytes、array、vector/staticvector 嵌套 `Array`、`List<T>` / `HashSet<T>` 集合 alias、map、PPtr、enum `value__` backing field、`LayerMask` / `BitField` 的 `m_Bits` backing field、常见固定 Unity 值类型的 leaf/direct-child 形态,以及 unknown fixed-size raw bytes 保留和同长度替换。
|
||||
3. TextAsset 已有专用 name/bytes 读取,避免和字段级遍历重复报错。
|
||||
4. MonoBehaviour 和 ScriptableObject 的 TypeTree 字段遍历入口已落地,复杂版本差异继续补 fixture。
|
||||
5. 对缺 TypeTree 或 stripped 类型返回可诊断结果,保留 raw object bytes 作为后备。
|
||||
|
||||
验收:
|
||||
|
||||
@@ -120,11 +127,11 @@
|
||||
|
||||
交付:
|
||||
|
||||
1. 定义 `TextUnit`:source text、resource path、archive entry、object path id、field path、语言、版本、上下文。
|
||||
2. TextAsset 支持 JSON/CSV/TSV/plain text 的可配置探测。
|
||||
3. MonoBehaviour/ScriptableObject 按字段路径和类型策略提取字符串。
|
||||
1. 已定义 `TextUnit`:source text、bundle path、archive entry、serialized file、object path id、class id、field path、字段 offset/byte size、版本和上下文;managed-reference payload 会额外写入 reference id、full type name、assembly、namespace 和 class 上下文。
|
||||
2. TextAsset 已支持 JSON/CSV/TSV/plain text 探测,二进制 payload 单独计数。
|
||||
3. MonoBehaviour/ScriptableObject 已按字段路径提取字符串。
|
||||
4. 保留重复文本和上下文,不在解析阶段做会丢定位的合并。
|
||||
5. 导出 JSONL 作为第一稳定格式,CSV/XLIFF 可后置。
|
||||
5. 已提供 JSONL 第一稳定格式,CSV/XLIFF 可后置。
|
||||
|
||||
验收:
|
||||
|
||||
@@ -138,15 +145,15 @@
|
||||
|
||||
交付:
|
||||
|
||||
1. 官方同步完成后可配置触发导入 CAS + ResourceRepository。
|
||||
2. ResourceRepository 保存版本、平台、资源类型、bundle path、TextAsset 名称、TextUnit 索引摘要。
|
||||
3. 支持 CLI/RPC 查询资源、bundle、TextAsset、解析错误和缓存状态。
|
||||
4. schema 迁移版本化,旧库可重复升级。
|
||||
1. 官方同步完成后可配置触发导入 CAS + ResourceRepository(已具备 `--import-repository` / `BAT_IMPORT_REPOSITORY=1`)。
|
||||
2. ResourceRepository 已保存官方 manifest 资源的类型、路径、hash、size 和 metadata;metadata 包含 release、平台、bundle path、parse status、TextAsset 名称、TextUnit 数量/格式。
|
||||
3. 支持 RPC/CLI 查询资源、bundle、TextAsset、解析错误和缓存状态;当前 `resource.index` 会返回资源 metadata,`parse-status` 会返回 TextUnit 索引和队列摘要,`parse-text-units` / `parse-errors` 会按当前 release 查询明细,`localized-status` 会校验 patch manifest。
|
||||
4. schema 迁移可重复执行;当前 SQLite 已有 `crc` 和 `metadata_json` 兼容迁移。
|
||||
|
||||
验收:
|
||||
|
||||
1. 可以按版本、路径、类型、hash、TextAsset 名称查询。
|
||||
2. 解析缓存和 repository 数据能从同一 manifest fingerprint 追溯。
|
||||
1. 可以按版本、路径、类型、hash 查询,并在结果 metadata 中看到 TextAsset / TextUnit 摘要。
|
||||
2. 解析缓存、资源变更集和 repository 数据能从同一 manifest fingerprint 追溯。
|
||||
3. CAS 对象跨版本复用,不重复存储相同文件。
|
||||
|
||||
### P5:Patch 发布前置解析
|
||||
@@ -155,17 +162,17 @@
|
||||
|
||||
交付:
|
||||
|
||||
1. 定义 patch manifest:目标官方版本、输入 TextUnit 版本、输出文件、hash、回滚信息。
|
||||
2. 支持 TextAsset raw bytes 替换的最小 patch 路径。
|
||||
1. 已定义 `localized-patch-manifest.json`:目标官方版本、localized release、输出文件、hash、size、byte delta、TextAsset 操作和回滚信息。
|
||||
2. 已支持 UnityFS TextAsset raw bytes 替换的最小 patch 路径。
|
||||
3. MonoBehaviour/ScriptableObject 字段替换必须依赖 P2 字段级解析结果。
|
||||
4. Patch 产物写入 `localized-output/.staging/<id>`,校验通过后发布到 `localized-output/versions/<id>` 并切换 `current`。
|
||||
5. 成功后发布状态从 `not_localized` 切到 `localized`。
|
||||
4. Patch 产物写入配置化汉化发布根下的 `.staging/<id>`,校验通过后发布到 `versions/<id>` 并切换 `current`。
|
||||
5. 成功后发布状态从 `not_localized` 切到 `localized`;`localized.status` 要求 state、current symlink 和 patch manifest 同时匹配当前官方 release。
|
||||
|
||||
验收:
|
||||
|
||||
1. Patch 失败不影响 `bat-resources/current`。
|
||||
2. 汉化 release 保留官方相对目录结构。
|
||||
3. `localized` 状态能证明原版和汉化两套资源都已发布。
|
||||
3. `localized` 状态能证明原版和汉化两套资源都已发布,且 patch manifest 可验证。
|
||||
|
||||
---
|
||||
|
||||
@@ -194,6 +201,6 @@
|
||||
|
||||
1. 完成 Addressables Windows/Android 当前版本 catalog 样本集合,关闭 G-007 当前阶段。
|
||||
2. 完成 TypeTree 字段 reader 和 MonoBehaviour/ScriptableObject 遍历,推进 G-005。
|
||||
3. 将 `official-parse-cache.json` 摘要接入 CAS/ResourceRepository 用户级导入,推进 G-011。
|
||||
4. 定义 TextUnit JSONL 和最小 TextAsset 提取命令,衔接 Milestone 5。
|
||||
5. 在 Patch 引擎落地后实现 `localized` 发布状态切换,关闭 G-011D 的核心发布缺口。
|
||||
3. 将 `crowdin-textunit-queue.json` 接入真实 Crowdin worker、翻译记忆和 Patch 构建。
|
||||
4. 将翻译任务状态接入 CAS/ResourceRepository 查询面,推进 G-011。
|
||||
5. 在通用 Binary/JSON/Text Patch 基础上继续扩展复杂 AssetBundle 重打包和发布流程统一,保留当前 UnityFS TextAsset patch 发布前置链路。
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
| 清单层 | 解析 `BundlePackingInfo.bytes`、`TableCatalog.bytes`、`MediaCatalog.bytes` | 得到完整文件清单 |
|
||||
| 计划层 | 合并 discovery + inventory,去重并保序 | 得到全量 pull plan |
|
||||
| 下载层 | 校验官方 URL,调用下载器,落盘并记录字节数 | 得到本地资源副本 |
|
||||
| 导入层 | 将 bundle 写入 CAS 和 ResourceRepository | 得到可查询的资源索引 |
|
||||
| 导入层 | 可配置将已校验官方 release 写入 CAS 和 ResourceRepository | 得到可查询的资源索引 |
|
||||
| 同步层 | 比较当前快照和历史快照 | 决定下载、校验、发布 |
|
||||
| 更新层 | 保存上次官方 snapshot,定期执行 discovery + diff + pull | 形成自动更新闭环 |
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
3. 不要求把生产环境当作客户端安装目录。
|
||||
4. 可以显式执行 official metadata discovery 自动发现 `server-info` URL、`connection-group` 和 `app-version`。
|
||||
5. 也可以通过配置、调度状态或已审计 metadata snapshot 显式提供这些值。
|
||||
6. `--auto-discover` 只允许通过官方 HTTP metadata 和临时目录解析 `GameMainConfig`;launcher metadata 未变时必须复用缓存,metadata 变化时才按 manifest 重新下载必要 `resources.assets` 或旧版官方 game zip。
|
||||
6. `--auto-discover` 只允许通过官方 HTTP metadata 和临时目录解析 `GameMainConfig`;launcher metadata 与 remote manifest 文件列表 digest 均未变时必须复用缓存,任一变化时才按 manifest 重新下载必要 `resources.assets` 或旧版官方 game zip。
|
||||
|
||||
### 3.1 发现官方资源根
|
||||
|
||||
@@ -135,16 +135,17 @@
|
||||
6. `TableCatalog.bytes`、`BundlePackingInfo.bytes`、`MediaCatalog.bytes` 总是刷新并用官方 `.hash` 强校验;该 `.hash` 是 `xxHash32(seed=0)` 的十进制文本。
|
||||
7. `catalog_*.hash` 当前只作为 Addressables catalog 变更标记,不作为 zip/JSON 内容校验算法;Unity Addressables/SBP builder 对 JSON/bin catalog 使用 `HashingMethods.Calculate` 生成 `Hash128` 文本,运行时用它判断 remote catalog cache 是否过期,它不能套用 seed catalog 的 `xxHash32` 规则。
|
||||
8. 官方 seed `.hash` 校验失败会让当前下载失败,并移除对应 data/hash URL 的本地 manifest 条目,避免失败产物在下一轮被本地 BLAKE3 audit 误判为健康缓存。
|
||||
9. 存在 `.part` 临时文件时通过 `curl --continue-at -` 尝试断点续传。
|
||||
10. 新下载写入 `.part`,成功并通过必要校验后原子 rename 到 staging 内最终路径;断点续传后的 `.zip` 如果结构无效,会删除 `.part` 并重新全量下载。
|
||||
11. 成功下载后更新本地下载清单。
|
||||
12. 上一轮失败或中断留下的 staging 只有在 `official-version-state.json` 中存在同一 app version、bundle version 和 Addressables root 的失败记录,且 `<output>/.staging/<id>` 仍安全存在、`versions/<id>` 尚未发布时才会复用;复用后仍按 manifest、BLAKE3、ZIP 结构和官方 `.hash` 逐 URL 校验,不信任散落文件。
|
||||
13. curl 默认自动检测 `HTTPS_PROXY` / `ALL_PROXY` / `HTTP_PROXY` 及小写环境变量,保留 `NO_PROXY`;带凭据的代理推荐用这些环境变量配置。CLI 也可用 `--proxy <URL>` 显式指定代理,或用 `--no-proxy` 强制直连。代理决策会进入 progress log、daemon log 和 `doctor` 诊断输出。代理凭据全程不落世界可读位置:日志与 `status` 输出脱敏;传给 curl 子进程时经 `ALL_PROXY` 环境变量而非 `--proxy` 参数,不进 curl 的 `/proc/<pid>/cmdline`;`--daemon` 模式下经环境变量下传后台子进程,不进子进程 argv 或 `bat-status.json`,复用凭据单独存于 `bat-proxy.secret`(`0600`),`clean-stable` 会在后台停止后清除。
|
||||
14. curl 失败按 HTTP/网络类型分类:403/404/普通 4xx 不重试,5xx、429、DNS、连接、超时、中断和网络类错误按尝试次数重试。
|
||||
15. 单个 URL 最终失败时写入 `official-download-quarantine.json`,发出 Failed progress,并阻止发布不完整资源。
|
||||
16. 旧 launcher 包或 `resources.assets` 下载使用官方 launcher CDN 配置,primary CDN 失败后切换 official backup CDN;资源 patch host 不猜测非官方镜像。
|
||||
17. 记录最终文件大小、本次传输字节数、官方 hash 校验数和执行状态。
|
||||
18. 非官方 URL 直接拒绝。
|
||||
9. 官方启动器/server-info 先于 client-patch CDN 开放是合法上游状态。若 seed marker 或必需 seed catalog 在进入 staging 前返回 403/404/普通 4xx,更新服务返回 `waiting_for_official_resources` 和 `unavailable_endpoints`,保留现有 `current`,不创建失败 staging,不写入 `failed_versions`;watch/daemon 使用 `waiting` 状态按错误重试间隔继续探测。
|
||||
10. 存在 `.part` 临时文件时通过 `curl --continue-at -` 尝试断点续传。
|
||||
11. 新下载写入 `.part`,成功并通过必要校验后原子 rename 到 staging 内最终路径;断点续传后的 `.zip` 如果结构无效,会删除 `.part` 并重新全量下载。
|
||||
12. 成功下载后更新本地下载清单。
|
||||
13. 上一轮失败或中断留下的 staging 只有在 `official-version-state.json` 中存在同一 app version、bundle version 和 Addressables root 的失败记录,且 `<output>/.staging/<id>` 仍安全存在、`versions/<id>` 尚未发布时才会复用;复用后仍按 manifest、BLAKE3、ZIP 结构和官方 `.hash` 逐 URL 校验,不信任散落文件。
|
||||
14. curl 默认自动检测 `HTTPS_PROXY` / `ALL_PROXY` / `HTTP_PROXY` 及小写环境变量,保留 `NO_PROXY`;带凭据的代理推荐用这些环境变量配置。CLI 也可用 `--proxy <URL>` 显式指定代理,或用 `--no-proxy` 强制直连。代理决策会进入 progress log、daemon log 和 `doctor` 诊断输出。代理凭据全程不落世界可读位置:日志与 `status` 输出脱敏;传给 curl 子进程时经 `ALL_PROXY` 环境变量而非 `--proxy` 参数,不进 curl 的 `/proc/<pid>/cmdline`;`--daemon` 模式下经环境变量下传后台子进程,不进子进程 argv 或 `bat-status.json`,复用凭据单独存于 `bat-proxy.secret`(`0600`),`clean-stable` 会在后台停止后清除。
|
||||
15. curl 失败按 HTTP/网络类型分类:403/404/普通 4xx 不重试,5xx、429、DNS、连接、超时、中断和网络类错误按尝试次数重试。
|
||||
16. 单个 URL 最终失败时写入 `official-download-quarantine.json`,发出 Failed progress,并阻止发布不完整资源。
|
||||
17. 旧 launcher 包或 `resources.assets` 下载使用官方 launcher CDN 配置,primary CDN 失败后切换 official backup CDN;资源 patch host 不猜测非官方镜像。
|
||||
18. 记录最终文件大小、本次传输字节数、官方 hash 校验数和执行状态。
|
||||
19. 非官方 URL 直接拒绝。
|
||||
|
||||
路径映射时会做分段清理,并在写入前做输出目录安全校验、相对路径归属校验和现有路径组件 symlink 检查,避免把不安全路径写进输出目录或通过 symlink 跳出输出目录。
|
||||
|
||||
@@ -154,14 +155,24 @@
|
||||
|
||||
### 3.5 导入到 CAS 和资源仓储
|
||||
|
||||
当前实现已经提供资源导入能力,但官方同步下载完成后尚未自动作为用户级流程触发导入。手动或上层流程调用导入层时,它会:
|
||||
官方同步下载、校验并发布 release 后,可以通过 `--import-repository` 或
|
||||
`.env` 中 `BAT_IMPORT_REPOSITORY=1` 自动触发 CAS + `ResourceRepository`
|
||||
导入:
|
||||
|
||||
1. 把 bundle 原始字节写入 CAS。
|
||||
2. 解析 UnityFS 基础摘要。
|
||||
3. 把资源条目写入 `ResourceRepository`。
|
||||
4. 记录资源路径、hash、大小和解析摘要。
|
||||
1. 读取已发布 release 下的 `official-download-manifest.json`。
|
||||
2. 逐条按 manifest 的相对路径、size 和 BLAKE3 重新校验本地文件。
|
||||
3. 把已校验字节写入 CAS;默认 CAS 根目录是 `<output>/.cas`,也可用
|
||||
`--import-cas-root` / `BAT_IMPORT_CAS_ROOT` 覆盖。
|
||||
4. 将资源条目写入 SQLite `ResourceRepository`;默认索引路径是
|
||||
`<output>/resources.sqlite`,也可用 `--import-resource-db` /
|
||||
`BAT_IMPORT_RESOURCE_DB` 覆盖。
|
||||
5. AssetBundle、TextAsset、TableBundle、Media、Manifest/Other 会按资源类型分类;资源 metadata 会通过 `metadata_json` 保存 release、平台、bundle path、parse status、TextAsset 名称和 TextUnit 数量/格式。
|
||||
6. 当前 release 的单条 TextUnit 明细和解析错误会写入 `official-textunit-index.json`,可通过 `parse.text_units` / `parse.errors` RPC 和 `parse-text-units` / `parse-errors` CLI 只读查询。
|
||||
|
||||
这层的意义是把“下载到磁盘的文件”变成“可查询、可复用、可去重”的资源对象。把官方同步结果自动接入 CAS + `ResourceRepository` 仍属于 G-011 剩余工作。
|
||||
这层的意义是把“下载到磁盘的文件”变成“可查询、可复用、可去重”的资源对象。
|
||||
`resource.index` RPC / CLI 只读查询现有 SQLite 索引;索引不存在时返回
|
||||
`available=false`,不会因为查询创建空库。G-011 剩余工作是翻译任务状态、
|
||||
CAS 诊断入口和更丰富查询。
|
||||
|
||||
对应实现主要在:
|
||||
|
||||
@@ -202,8 +213,8 @@
|
||||
流程是:
|
||||
|
||||
1. 显式执行 `--auto-discover` 或读取已审计 `server-info` 输入。
|
||||
2. `--auto-discover` 先抓官方 launcher metadata;metadata 未变时复用 `official-bootstrap-cache.json` 中的 `GameMainConfig` 摘要,metadata 变化时按 manifest 临时下载 `resources.assets` 或旧版官方 game zip 并重新解析。
|
||||
3. 生成当前 v2 snapshot,记录 `app_version`、`connection_group`、`bundle_version`、`addressables_root`、endpoint URL、seed `.hash` 内容、`catalog_*.hash` marker、launcher metadata 摘要和 `GameMainConfig` 摘要。
|
||||
2. `--auto-discover` 先抓官方 launcher metadata、launcher CDN config 和 remote manifest;metadata 与 remote manifest 文件列表 digest 均未变时复用 `official-bootstrap-cache.json` 中的 `GameMainConfig` 摘要,任一变化时按 manifest 临时下载 `resources.assets` 或旧版官方 game zip 并重新解析。
|
||||
3. 生成当前 v2 snapshot,记录 `app_version`、`connection_group`、`bundle_version`、`addressables_root`、endpoint URL、seed `.hash` 内容、`catalog_*.hash` marker、launcher metadata 摘要、remote manifest 文件列表 digest 和 `GameMainConfig` 摘要。
|
||||
4. 读取上一次成功同步写出的 snapshot。
|
||||
5. 使用 `OfficialSyncPlan` 和扩展 snapshot diff 判断是否需要下载;URL 未变但 `.hash` / marker 内容变化也会触发更新。
|
||||
6. 每轮都会基于最新 seed catalog 构建当前 pull plan,并检查输出目录是否已有当前 plan 的 manifest 条目或目标文件。
|
||||
@@ -211,10 +222,14 @@
|
||||
8. 远端无变化且本地已有资源时执行 download manifest audit,检查路径、size、BLAKE3 和 ZIP 结构。
|
||||
9. 远端变化、本地 audit 发现 repair_needed,首次空目录运行,或缺少 `current` 原子发布指针时,进入下载/发布流程。
|
||||
10. 下载先写入 `<output>/.staging/<id>`;若已有 active release,会先 seed staging 以复用已验证文件;若 version-state 中存在同一版本的失败 staging,则优先复用该 staging 并跳过 active seed,避免旧 active 覆盖已下载的新文件。
|
||||
11. 下载、manifest、本地 BLAKE3、ZIP 和官方 `.hash` 校验完成后写入新的 snapshot。
|
||||
11. 下载、manifest、本地 BLAKE3、ZIP 和官方 `.hash` 校验完成后写入新的 snapshot,并在 staging 中写入 `official-launcher-bootstrap.json`(若本轮启用 `--auto-discover`)。
|
||||
12. 将 staging rename 为 `<output>/versions/<id>`,再原子替换 `<output>/current` symlink 指向该 versioned 目录。
|
||||
13. 发布完成后刷新 active release 下的 `official-parse-cache.json`;未变化文件按 manifest 的 URL、相对路径、size 和 BLAKE3 复用旧解析结果。
|
||||
14. 官方同步报告默认给出 `localized_release_status=not_localized`,表示原版资源已发布、汉化资源未发布;后续 Patch 发布阶段完成后才切换为 `localized`,表示原版和汉化两套资源都已发布。
|
||||
13. 发布完成后先对比上一完整 release 和当前 release 的 `official-download-manifest.json`,写出 `official-resource-changes.json` 和 `crowdin-translation-handoff.json`。同一 destination 只有 size 或 BLAKE3 变化才算 modified;新增+变更资源进入解析/翻译 handoff,删除资源只进入差异记录。当前只预留 Crowdin 本地 handoff,不发外部 API 请求。
|
||||
14. 随后刷新 active release 下的 `official-parse-cache.json` 和 `official-textunit-index.json`,并从 Added/Modified 资源、parse cache 与 TextUnit 明细索引派生 `official-textunit-tasks.json` 和 `crowdin-textunit-queue.json`;up-to-date 轮询在已有有效解析缓存、TextUnit 明细索引和 TextUnit 队列时只读取摘要,不重复解析。
|
||||
15. 若启用 `--import-repository`,已校验 release 会被导入 CAS + `ResourceRepository`,并可经 `resource.index` 查询。
|
||||
16. 官方同步报告默认给出 `localized_release_status=not_localized`,表示原版资源已发布、汉化资源未发布;UnityFS TextAsset patch 发布成功并通过 `localized-patch-manifest.json`、current symlink 和 release ID 校验后,`localized.status` 才返回 `localized`,表示原版和汉化两套资源都已发布。
|
||||
|
||||
维护期特殊分支:如果官方 launcher/server-info 已经指向新资源根,但 client-patch seed marker 或必需 seed catalog 仍返回 403/404 等未开放状态,`bat` 返回 `waiting_for_official_resources`,保留现有 `current`,不创建失败 staging;若本轮启用 `--auto-discover`,会在 `<output>/official-launcher-bootstrap.pending.json` 写入待处理 launcher bootstrap 证据,供后续排障和自研客户端开发使用。
|
||||
|
||||
该入口不安装、不执行官方启动器,也不读取生产外的本地客户端目录。Rust 正式 binary `bat` 支持单次运行、`--watch` 常驻模式、`--daemon` 后台模式,以及 `status`、`stop`、`restart`、`reload`、`logs`、`refresh`、`verify`、`repair`、`doctor`、`clean-stable` 管理命令。`--daemon` 会在后台状态目录下创建 `bat.sock`,使用 Unix socket JSON-RPC 作为 live control plane;`bat.pid`、`bat-status.json` 和 `bat-daemon.log` 是快照、诊断和兼容 fallback;`bat-events.jsonl` 是带轮转的结构化 JSONL 事件日志;`bat-control.lock` 串行化控制命令,并在 stale/corrupt 时由下一次控制命令或 `clean-stable` 恢复。`bat-status.json` 和 `status` 子命令包含最后成功时间、下次检查时间、最后错误摘要、当前阶段和当前下载 URL 进度。PID、status、log 和控制锁文件创建时使用私有权限,读取和写入时不跟随 symlink。`status`、`stop`、`logs`、`reload`、默认形态的 `refresh` 和默认形态的 `repair` 优先走 RPC;`reload` 会唤醒或排队 watch 循环重新自动发现并强制刷新,默认 `repair` 会通过 `resource.repair` 入队本地 manifest 审计+修复任务,`restart` 才负责重启进程或替换启动参数;显式 `--proxy` / `--no-proxy` 会作为启动参数保存并在后台重启时复用。后台 daemon 管理某个资源目录时,前台 `run/watch/refresh/repair` 不允许直接写入同一目录;默认形态 `refresh` 会通过 RPC 触发后台刷新,默认形态 `repair` 会通过 RPC 入队任务。正常情况下默认每 1 小时执行一次检查;每天北京时间(UTC+8)`03:00`、`16:00`、`18:00` 会中断普通 sleep 并强制执行一次自动刷新,该轮注入 `force=true`。远端和本地一致时静默等待下次检查,不一致时自动下载或 repair。下载、发现或校验失败时不等待完整正常周期,默认 60 秒后重试;如果固定时间强制刷新失败,会保留 pending force 并按失败重试周期继续重试,可用 `--error-retry` 或 `--error-retry-seconds` 调整。默认官方原版资源输出目录是 `./bat-resources`,默认汉化产物目录是 `./bat-localized`,默认后台状态目录是 `/tmp/bat-pid`,三者分别通过 `--output`、`--localized-output` 和 `--state-dir` 配置;官方目录和汉化目录不能相同或互相嵌套。单次运行仍保留为核心幂等路径,systemd service、容器或 Go 进程可以只负责守护该常驻进程;cron/systemd timer 调单次模式只是可选集成方式。项目是否热更新、热重载或重启进程,由上层业务集成决定。
|
||||
|
||||
@@ -254,10 +269,11 @@ Linux 生产路径:
|
||||
- pull plan 会同时包含 discovery URLs 和 content URLs
|
||||
- 全量样本下是 `2` 个 discovery URL + `5` 个内容 URL = `7` 个 URL
|
||||
- `OfficialUpdateService` 能持久化 v2 snapshot,并在远端 marker 内容变化时触发下载决策
|
||||
- `bat` 默认向 stderr 输出 `BlueArchiveToolkit` ASCII banner 和 progress log,stdout 默认输出人类可读摘要;progress log 覆盖代理决策、下载已完成计数、单文件开始/完成状态、下载中断失败分类和校验结果摘要;支持 `--proxy` / `--no-proxy` 控制 curl 传输代理,支持 `--json` 输出稳定 JSON,支持 `--no-progress` 关闭进度日志,支持 `--no-banner` 只关闭横幅,支持 `--watch --interval 1h --error-retry 60s` 常驻运行,支持 `--daemon` Unix socket JSON-RPC live control/backend(`daemon.status/logs/stop/reload/refresh/doctor`、`resource.sync/verify/repair/state/manifest/list`、`catalog.*`、`task.*`);`restart` 与 `clean-stable` 仍由 CLI 侧按进程生命周期显式执行,非 dry-run 使用 `.official-sync.lock` 防止并发写资源目录,控制命令使用 `bat-control.lock` 防止并发状态修改,资源发布使用 `.staging`、`versions` 和 `current` 原子切换,daemon 写 `bat-events.jsonl` 结构化日志并在 `status` 中暴露下载进度、失败类型、HTTP 状态和调度状态
|
||||
- `bat` 默认向 stderr 输出 `BlueArchiveToolkit` ASCII banner 和 progress log,stdout 默认输出人类可读摘要;progress log 覆盖代理决策、下载已完成计数、单文件开始/完成状态、下载中断失败分类和校验结果摘要;支持 `--proxy` / `--no-proxy` 控制 curl 传输代理,支持 `--json` 输出稳定 JSON,支持 `--no-progress` 关闭进度日志,支持 `--no-banner` 只关闭横幅,支持 `--watch --interval 1h --error-retry 60s` 常驻运行,支持 `--daemon` Unix socket JSON-RPC live control/backend(`daemon.status/logs/stop/reload/refresh/doctor`、`resource.sync/verify/repair/state/manifest/list/index`、`parse.status/text_units/errors`、`localized.status`、`catalog.*`、`task.*`);`restart` 与 `clean-stable` 仍由 CLI 侧按进程生命周期显式执行,非 dry-run 使用 `.official-sync.lock` 防止并发写资源目录,控制命令使用 `bat-control.lock` 防止并发状态修改,资源发布使用 `.staging`、`versions` 和 `current` 原子切换,daemon 写 `bat-events.jsonl` 结构化日志并在 `status` 中暴露下载进度、失败类型、HTTP 状态和调度状态
|
||||
- curl 失败分类和重试策略已覆盖 404 不重试、5xx 重试耗尽后 quarantine、launcher primary CDN 失败后切换 official backup CDN
|
||||
- `official-version-state.json` 已覆盖当前完成版本、正在拉取版本、上一个可用版本和失败版本;同一 app version、bundle version 和 Addressables root 的失败只保留最新一条,重新拉取或成功发布后清理同版本失败记录,同版本失败 staging 会在路径安全且未发布时复用,`bat status` 会暴露版本状态摘要和最近历史失败原因
|
||||
- 资源导入链路已覆盖 CAS 写入、`ResourceRepository` 索引、AssetBundle UnityFS 摘要,以及 TextAsset/Table/Media 分类
|
||||
- 资源导入链路已覆盖可配置 CAS 写入、`ResourceRepository` 索引、`metadata_json` release/平台/bundle/TextAsset/TextUnit 摘要,以及 TextAsset/Table/Media 分类;`resource.index` 可只读查询现有索引
|
||||
- 官方 release 发布后会生成 `official-resource-changes.json`、`crowdin-translation-handoff.json`、`official-parse-cache.json`、`official-textunit-index.json`、`official-textunit-tasks.json` 和 `crowdin-textunit-queue.json`,为后续增量解析和 Crowdin worker 预留稳定输入
|
||||
- 离线回归样本已覆盖当前 catalog、上一个版本 catalog、catalog 结构变化、403、404 和 seed hash mismatch
|
||||
- `OfficialUpdateService` 能读写 `official-bootstrap-cache.json`,并支持默认开启的 `audit_local` / `repair` CLI 行为
|
||||
- 下载层能在本地文件 size/BLAKE3/path、ZIP 结构或 manifest 不匹配时重新下载
|
||||
@@ -304,30 +320,42 @@ JSON-RPC 2.0 服务,是面向上层服务(Go 层)的**主要跨语言边
|
||||
watch 循环经进程内锁互斥。任务历史持久化于 `<state-dir>/bat-tasks.json`
|
||||
(版本化、`0600` 原子写,生命周期转换时落盘),daemon 重启后历史任务
|
||||
仍可经 `task.*` 查询,中断任务标记 `task_interrupted`(700005)。
|
||||
- 方法命名空间与实现状态、请求/响应示例见 `USERGUIDE.md` §6:
|
||||
`daemon.status/logs/stop/reload/refresh/doctor`、`resource.state/sync/verify/repair/manifest/list`、
|
||||
`catalog.*` 与 `task.status/list/cancel/logs` 已实现;`patch.*` / `unityfs.*`
|
||||
待引擎;`task.create` 按设计暂不开放通用任务入口;`daemon.restart` /
|
||||
`daemon.clean-stable` 仍由 CLI 侧按进程生命周期显式执行。
|
||||
- 方法命名空间与实现状态、请求/响应示例见
|
||||
`docs/reference/rpc-backend-api.md`:`daemon.status/logs/stop/reload/refresh/doctor`、
|
||||
`resource.state/sync/verify/repair/manifest/list/index`、`parse.status/text_units/errors`、
|
||||
`localized.status`、`catalog.*` 与 `task.status/list/cancel/logs` 已实现;
|
||||
`patch.*` / `unityfs.*` 待引擎;`task.create` 按设计暂不开放通用任务入口;
|
||||
`daemon.restart` / `daemon.clean-stable` 仍由 CLI 侧按进程生命周期显式执行。
|
||||
|
||||
### 7.2 Go 层职责边界
|
||||
|
||||
- Go 层负责:资源内容分发(`cmd/bat-api`)、HTTP API 进程配置、以及通过
|
||||
`internal/backendrpc` 作为 RPC client 调用本机 daemon(连接 `bat.sock`,
|
||||
每行一个 JSON-RPC 请求/响应)。`cmd/bat` 仍是试验骨架,不是产品级用户 CLI。
|
||||
- Rust `bat` / daemon 是资源生产者和状态拥有者;Go `bat-api` 是资源读侧、
|
||||
bootstrap 和 HTTP 分发入口。二者之间的稳定边界是 `bat.sock` RPC 和
|
||||
`resource_root` 中已发布的只读文件。
|
||||
- Go 层负责:资源 bootstrap、资源内容分发(`cmd/bat-api`)、HTTP API 进程配置、
|
||||
以及通过 `internal/backendrpc` 作为 RPC client 调用本机 daemon(连接
|
||||
`bat.sock`,每行一个 JSON-RPC 请求/响应)。`cmd/bat` 仍是试验骨架,不是产品级用户 CLI。
|
||||
- **`bat-api`(资源分发,issue #19)**:
|
||||
- 提供 `/v1/bootstrap`,把 `bat` 的 RPC 健康、release 摘要、server-info URL、
|
||||
client-patch base 和改写后的 Addressables root 组织成启动前资源发现响应。
|
||||
- 提供 `/healthz` 作为 liveness + 最近一次 RPC refresh 诊断,提供 `/readyz`
|
||||
作为 release readiness;当前无可分发 release 时 `/readyz` 返回 `503`。
|
||||
- 只读提供 Rust `bat` 已发布 release 中的资源字节(官方 CDN host/path 形态)。
|
||||
- CDN path 支持 `GET` / `HEAD` / Range / 条件请求;ETag 优先使用 download
|
||||
manifest 中的 BLAKE3,响应包含 Last-Modified、Accept-Ranges 和长期缓存头。
|
||||
- 版本/清单发现优先走 RPC:先 `daemon.status`,再 `daemon.doctor`,再
|
||||
`catalog.status` / `resource.manifest`(可用 `--socket` 指定 socket 文件)。
|
||||
- 支持 `.env` / 环境变量配置监听端口、public base URL、RPC socket,并预留
|
||||
database/redis 键供后续 API 持久化;**不**负责资源自动拉取。
|
||||
- 支持 `.env` / 环境变量配置监听端口、public base URL、RPC socket 和 RPC
|
||||
刷新周期,并预留 database/redis 键供后续 API 持久化;**不**负责资源自动拉取。
|
||||
- 可选改写 server-info 中的 `AddressablesCatalogUrlRoot` 指向自身;不伪装
|
||||
完整游戏业务 API,launcher 全链非本服务关闭条件。
|
||||
完整游戏业务 API。启动前资源 metadata 兼容属于资源 bootstrap;账号、登录、
|
||||
Gateway、游戏业务 `ApiUrl` 和鉴权全链非本服务关闭条件。
|
||||
- Rust `bat` / daemon 负责:官方资源自动发现与拉取、校验、catalog 更新检查、
|
||||
版本状态与发布、任务队列/日志/错误/进度管理等长期状态型工作。
|
||||
- Go 层**不**直接嵌入 Rust FFI,不直接读写 daemon 的状态文件;跨语言控制面
|
||||
只经 RPC 契约。文件字节从 RPC 给出的 `resource_root`(或显式
|
||||
`--resource-root`)读取,与 daemon 同机或共享文件系统部署。
|
||||
只经 RPC 契约。生产文件字节从 RPC 给出的 `resource_root` 读取,`bat-api`
|
||||
与 daemon 同服务器、同容器或同一共享文件系统部署;显式 `--resource-root`
|
||||
只用于 fixture、本地开发或 RPC 不可用时的应急只读诊断。
|
||||
|
||||
### 7.3 FFI 的定位(降级说明)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 官方资源 Release 布局与资源侧契约
|
||||
|
||||
- **更新时间**:2026-07-24
|
||||
- **用途**:冻结日服官方资源在本地发布根上的布局、URL 映射、seed 规则,以及 `bat-api` 分发 path 的 1:1 对应关系。
|
||||
- **更新时间**:2026-07-27
|
||||
- **用途**:冻结日服官方资源在本地发布根上的布局、URL 映射、seed 规则、`bat`/`bat-api` 关系,以及 `bat-api` 分发 path 的 1:1 对应关系。
|
||||
- **范围**:资源发现 / 清单 / 落盘 / 只读分发(**不是**完整游戏业务 API)。
|
||||
- **权威代码**:
|
||||
- URL / 平台 / seed:`adapters/src/official/yostar_jp.rs`
|
||||
@@ -17,7 +17,7 @@
|
||||
| 角色 | 组件 | 职责 |
|
||||
|---|---|---|
|
||||
| 同步 / 运维(近乎全自动) | Rust `bat` | auto-discover、拉取、校验、发布、watch/daemon、RPC 后端 |
|
||||
| 资源只读分发 | Go `bat-api` | 按官方 CDN path 提供已发布字节;经 `bat.sock` 发现版本 |
|
||||
| 资源 bootstrap / 只读分发 | Go `bat-api` | 同环境经 `bat.sock` 发现已发布版本和 `resource_root`,提供 `/v1/bootstrap`、server-info 改写和官方 CDN path 字节 |
|
||||
| 试验 CLI | Go `cmd/bat` → `bin/bat-go` | 非产品;禁止与 Rust `bat` 重名 |
|
||||
|
||||
**禁止**:把已安装客户端目录或 `/home/wanye/D/BlueArchive` 当作生产输入;真实全量样本优先服务器 release 或 `/tmp` 隔离目录。
|
||||
@@ -32,7 +32,11 @@
|
||||
versions/<id>/ # 已发布 versioned release(= resource_root)
|
||||
official-download-manifest.json
|
||||
official-parse-cache.json # 校验后派生解析缓存,不是汉化产物
|
||||
official-sync-snapshot.json # 常在 active root / current 下
|
||||
official-textunit-index.json # TextUnit 明细与解析错误索引,不是汉化产物
|
||||
official-textunit-tasks.json # 翻译任务候选派生队列,不发 Crowdin 网络请求
|
||||
crowdin-textunit-queue.json # Crowdin worker 离线输入队列
|
||||
official-sync-snapshot.json # 常在 active root / current 下
|
||||
official-launcher-bootstrap.json # 官方 launcher 引导链版本化产物
|
||||
prod-clientpatch.bluearchiveyostar.com/
|
||||
<root_token>/
|
||||
TableBundles/
|
||||
@@ -65,6 +69,7 @@
|
||||
.staging/<id>/ # 未发布写侧(失败可复用)
|
||||
official-version-state.json # 发布根级版本状态
|
||||
official-bootstrap-cache.json # auto-discover 缓存
|
||||
official-launcher-bootstrap.pending.json # 维护期 launcher 已前进但资源未开放时的待处理证据
|
||||
|
||||
<localized-output>/ # 汉化产物发布根(--localized-output / BAT_LOCALIZED_OUTPUT)
|
||||
current -> versions/<id> # 已汉化后才切换;未汉化状态不发布
|
||||
@@ -83,7 +88,7 @@
|
||||
|---|---|
|
||||
| 下载写入 | `<output>/.staging/<id>` |
|
||||
| 发布完成 | rename 到 `versions/<id>`,再切换 `current` |
|
||||
| 生产读取 / bat-api | `current` 解析后的 versioned 目录,或 RPC 给出的 `version.resource_root` |
|
||||
| 生产读取 / bat-api | RPC 给出的 `version.resource_root`;通常等价于 `current` 解析后的 versioned 目录 |
|
||||
|
||||
---
|
||||
|
||||
@@ -110,7 +115,7 @@ https://{host}/{path...} → <resource_root>/{host}/{path...}
|
||||
| `prod-clientpatch.bluearchiveyostar.com` | Addressables / Table / Media / PatchPack 内容 |
|
||||
| `yostar-serverinfo.bluearchiveyostar.com` | server-info JSON |
|
||||
|
||||
(launcher 包 CDN 属于启动器链,**不是**默认资源 release 主体。)
|
||||
(launcher 包 CDN 属于启动器链,**不是**默认资源 release 主体。Rust `bat` 会把启动器链中与资源发现相关的 launcher metadata、CDN config、remote manifest 文件列表、选中的 `resources.assets` 来源和 `GameMainConfig` 摘要写入 `official-launcher-bootstrap.json`,供后续 `bat-api` / 自研客户端在 Rust 侧完成前继续以 versioned release 为权威来源。)
|
||||
|
||||
### 3.2 bat-api 对外 path(1:1)
|
||||
|
||||
@@ -121,6 +126,45 @@ GET {public-base-url}/prod-clientpatch.bluearchiveyostar.com/<root_token>/...
|
||||
|
||||
默认仅服务 **download manifest 索引内且 Present + size 匹配** 的文件。
|
||||
|
||||
### 3.3 launcher 资源引导兼容
|
||||
|
||||
只读分析本机样本时可见两类启动器形态:
|
||||
|
||||
| 目录形态 | 说明 |
|
||||
|---|---|
|
||||
| `AllResources/YostarGames/BlueArchive_JP_Gamelauncher` | 官方 Electron 启动器目录 |
|
||||
| `Localized` / `Localized_Official` | 汉化或改造启动器目录 |
|
||||
| `AllResources/YostarGames/BlueArchive_JP` | 官方安装后的游戏客户端目录,含 `game-launcher-config.json`、`manifest.json` 和 `BlueArchive_Data/StreamingAssets/catalog_Remote.*` |
|
||||
|
||||
这些目录只作为开发期样本;生产链路不得依赖 `/home/wanye/D/BlueArchive` 或任何已安装客户端目录。
|
||||
|
||||
官方启动器样本中与资源发现相关的 HTTP path:
|
||||
|
||||
| Host / path | 资源侧意义 |
|
||||
|---|---|
|
||||
| `https://api-launcher-jp.yo-star.com/api/launcher/game/config` | 返回 launcher 观察到的最新客户端版本和包路径 |
|
||||
| `https://api-launcher-jp.yo-star.com/api/launcher/game/config/json?version=...&file_path=...` | 返回远端 package manifest URL |
|
||||
| `https://api-launcher-jp.yo-star.com/api/launcher/advanced/game/download/cdn` | 返回 launcher package CDN primary / backup |
|
||||
|
||||
`bat-api` 的兼容范围是**资源引导**,不是完整启动器更新服务:
|
||||
|
||||
| bat-api path | 行为 |
|
||||
|---|---|
|
||||
| `/v1/launcher/bootstrap` | 返回资源引导聚合视图:已发布 release、launcher metadata、GameMainConfig 摘要、server-info URL、client-patch base、改写后的 Addressables root |
|
||||
| `/api/launcher/game/config` | 返回 `{code,message,data}` envelope,字段来自 Rust `bat` snapshot/RPC 中的 `launcher_metadata`,并附带 `resource_bootstrap_url` |
|
||||
| `/api/launcher/game/config/json` | 返回指向 `/api-launcher-jp.yo-star.com/api/launcher/resource/bootstrap.json` 的资源引导 JSON URL,显式标记 `package_update_manifest=false` |
|
||||
| `/api/launcher/advanced/game/download/cdn` | 返回 `public-base-url` 作为资源引导 CDN 根,显式标记 `package_update_manifest=false` |
|
||||
| `/api-launcher-jp.yo-star.com/...` | 与上面裸 path 等价,便于反向代理或 hosts 映射保持官方 host 形状 |
|
||||
|
||||
数据来源只能是 Rust `bat` 已发布状态;当前 Go `bat-api` 仍主要消费 snapshot/RPC 摘要,后续字段统一与联调时应把 versioned launcher artifact 纳入 contract fixture:
|
||||
|
||||
1. `catalog.status` / `official-sync-snapshot.json` 中的 `launcher_metadata`。
|
||||
2. `catalog.status` / `official-sync-snapshot.json` 中的 `game_main_config_bootstrap`。
|
||||
3. `official-launcher-bootstrap.json` 中的官方 launcher bootstrap versioned artifact。
|
||||
4. `resource.manifest` 和磁盘 Present/size 检查得到的当前 release 索引。
|
||||
|
||||
`bat-api` 不下载 launcher 包、不生成官方 PC package update manifest、不执行启动器签名/鉴权链、不仿造登录、账号、网关或游戏业务 API。需要真实资源拉取时,仍由 Rust `bat --auto-discover` 在隔离 staging 中通过官方 HTTP metadata 完成,并把已发布结果通过 RPC 暴露给 `bat-api`。
|
||||
|
||||
---
|
||||
|
||||
## 4. `official-download-manifest.json`
|
||||
@@ -226,10 +270,14 @@ https://prod-clientpatch.bluearchiveyostar.com/<root_token>
|
||||
|
||||
| 面 | 假设(当前工程) | bat-api 行为 |
|
||||
|---|---|---|
|
||||
| client-patch 内容 | GET 官方 path;无业务鉴权头(资源 CDN) | `GET/HEAD /prod-clientpatch.../...` 原样字节 |
|
||||
| 启动前资源发现 | 客户端/补丁器需要知道当前资源版本、server-info 和 client-patch 根 | `GET /v1/bootstrap` 返回 `bat` RPC 健康、release 摘要、server-info URL、client-patch base 和改写后的 Addressables root |
|
||||
| 服务就绪 | 运维需要区分进程存活和 release 是否可分发 | `GET /healthz` 返回 liveness + RPC refresh 诊断;`GET/HEAD /readyz` 无可分发 release 时返回 `503` |
|
||||
| client-patch 内容 | GET 官方 path;无业务鉴权头(资源 CDN) | `GET/HEAD /prod-clientpatch.../...` 原样字节,支持 Range |
|
||||
| server-info | GET JSON;字段 PascalCase(`ConnectionGroups` 等) | 可选加载并**只改** `AddressablesCatalogUrlRoot` 指向 `{public-base}/prod-clientpatch.../{token}` |
|
||||
| launcher bootstrap | 启动器链会先查 launcher metadata,再找到 server-info / Addressables root | `/v1/launcher/bootstrap` 与 `/api/launcher/...` 只输出资源引导兼容信息,来源是 Rust snapshot/RPC |
|
||||
| seed `.hash` | 纯文本十进制(可含空白) | 原样分发 |
|
||||
| Range / 断点 | 官方客户端下载器用 Range;bat 用 curl `.part` | **本轮 bat-api 可不实现 Range**;记入后续 |
|
||||
| Range / 断点 | 官方客户端下载器用 Range;bat 用 curl `.part` | `ServeContent` 支持 Range / `206` / `416` / `If-Range` |
|
||||
| 缓存 / 条件请求 | 资源位于 versioned root;manifest 有 BLAKE3 | ETag 优先使用 manifest BLAKE3;返回 Last-Modified、Accept-Ranges、长期 Cache-Control |
|
||||
| 业务 ApiUrl/Gateway | 游戏协议 | **不改写、不仿造** |
|
||||
|
||||
Addressables 改写后客户端拼接:
|
||||
@@ -245,7 +293,7 @@ Addressables 改写后客户端拼接:
|
||||
|
||||
## 8. RPC 与分发发现顺序
|
||||
|
||||
`bat-api`(及任何 Go 服务层)发现当前 release:
|
||||
`bat-api`(及任何 Go 服务层)发现当前 release,并由 `/v1/bootstrap` 组织为启动前资源入口:
|
||||
|
||||
1. `daemon.status`
|
||||
2. `daemon.doctor`
|
||||
@@ -255,7 +303,7 @@ Addressables 改写后客户端拼接:
|
||||
|
||||
**不读** `bat-status.json` / `bat-tasks.json` 作为常规路径。
|
||||
|
||||
配置:`--socket` / `BAT_API_SOCKET`;应急 `--resource-root`。见 `cmd/bat-api/.env.example`。
|
||||
生产配置:`--socket` / `BAT_API_SOCKET`,`bat-api` 与 `bat` 在同服务器、同容器或同共享文件系统环境内运行。`--resource-root` 只用于本地 fixture 或应急只读诊断,不作为生产资源根配置。`BAT_API_REFRESH_INTERVAL` 控制 bat-api 周期重读 RPC,以跟随 Rust `bat` 发布新 release。见 `cmd/bat-api/.env.example`。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 稳定工程基线指南
|
||||
|
||||
- **更新时间**:2026-07-20
|
||||
- **更新时间**:2026-07-26
|
||||
- **目标**:让工作区处于可继续开发核心功能的可信状态。
|
||||
|
||||
---
|
||||
@@ -90,10 +90,11 @@ git check-ignore -v Cargo.lock CLAUDE.md AGENTS.md CONTRIBUTING.md
|
||||
|
||||
CAS V1 和 Rust 官方同步闭环完成后,下一阶段优先推进:
|
||||
|
||||
1. 收敛 Go 产品入口:当前 `cmd/bat` 仅是试验骨架,不能视为完成。
|
||||
2. 按 `docs/guides/official-full-pull-smoke.md` 执行真实官方网络全量下载 smoke,并保留隔离目录报告。
|
||||
3. 官方同步结果接入 CAS + ResourceRepository。
|
||||
4. AssetBundle UnityFS 引擎级解析。
|
||||
1. 继续联调 Go `bat-api` 与 Rust daemon 的资源分发路径;Go 同步 CLI 不再作为产品目标。
|
||||
2. 按 `docs/guides/official-full-pull-smoke.md` 在隔离目录执行真实官方网络全量下载 smoke,并保留运行报告。
|
||||
3. 将 `crowdin-textunit-queue.json` 接入真实 Crowdin worker、翻译记忆和 Patch 构建。
|
||||
4. 扩展 ResourceRepository 查询面:翻译任务状态、CAS 诊断入口和更丰富 TextUnit 查询。
|
||||
5. 继续完善 AssetBundle 复杂对象解析、复杂对象重打包和 Patch 发布流程统一;通用 Binary/JSON/Text Patch 基础与 UnityFS TextAsset patch 发布前置链路已可用。
|
||||
|
||||
优先阅读:
|
||||
|
||||
|
||||
+152
-7
@@ -5,8 +5,9 @@
|
||||
BlueArchive Toolkit 的部署文档分为当前可用模式和目标模式:
|
||||
|
||||
1. **本地开发模式**:代码在本地,连接本地或远程数据库。
|
||||
2. **官方资源同步生产任务**:当前可用,运行 Rust `bat --watch`。
|
||||
3. **完整单机/分布式部署**:尚未提供。API Server、数据库迁移和 Web 未实现前,不把它作为可执行部署方案。
|
||||
2. **官方资源同步生产任务**:当前可用,运行 Rust `bat --watch` 或 RPC/daemon 模式。
|
||||
3. **bat-api 资源 bootstrap / 分发服务**:当前可用,和 Rust `bat` 在同一服务器/容器环境运行,经 `bat.sock` RPC 获取当前 `resource_root`。
|
||||
4. **完整单机/分布式部署**:尚未提供。完整游戏业务 API、数据库迁移和 Web 未实现前,不把它作为可执行部署方案。
|
||||
|
||||
---
|
||||
|
||||
@@ -100,7 +101,7 @@ REDIS_PORT=6379
|
||||
|
||||
## 模式 3:官方资源同步生产任务
|
||||
|
||||
当前可部署的生产任务是 Rust 官方资源同步 binary。API Server 和 Web 尚未实现,不能按完整服务端产品部署。
|
||||
当前可部署的生产同步任务是 Rust 官方资源同步 binary。`bat-api` 资源 bootstrap / 分发服务见模式 4;完整游戏业务 API 和 Web 尚未实现,不能按完整服务端产品部署。
|
||||
|
||||
### 构建 release binary
|
||||
|
||||
@@ -198,14 +199,14 @@ sudo -u bat /opt/bluearchive-toolkit/bin/bat \
|
||||
--no-progress
|
||||
```
|
||||
|
||||
### 推荐模式:systemd 托管 `--watch`
|
||||
### 推荐模式:纯同步时 systemd 托管 `--watch`
|
||||
|
||||
生产推荐让 systemd 直接托管前台 `--watch` 进程,而不是在 systemd 里再启动 `--daemon`。原因:
|
||||
只需要远程长期同步资源、暂不部署 `bat-api` 时,推荐让 systemd 直接托管前台 `--watch` 进程,而不是在 systemd 里再启动 `--daemon`。原因:
|
||||
|
||||
- systemd 能直接追踪主进程、退出码、重启次数和 stop 信号。
|
||||
- 日志进入 journald,用 `journalctl` 管理,不依赖 `bat-daemon.log`。
|
||||
- Rust 内部已经负责 1 小时间隔、北京时间固定强制刷新和失败快速重试,systemd 不需要 timer。
|
||||
- `bat --daemon` 的 Unix socket RPC 适合没有进程管理器的 shell/container 场景;systemd 场景下用 `systemctl`、`journalctl`、`bat verify/doctor` 运维即可。
|
||||
- `bat --daemon` 的 Unix socket RPC 适合 shell/container 场景,也适合给同环境运行的 `bat-api` 提供 release 发现;纯同步 systemd 场景下用 `systemctl`、`journalctl`、`bat verify/doctor` 运维即可。
|
||||
|
||||
安装 unit 和可选环境文件:
|
||||
|
||||
@@ -256,6 +257,8 @@ sudo -u bat /opt/bluearchive-toolkit/bin/bat stop --state-dir /var/lib/bluearchi
|
||||
|
||||
不要同时运行 systemd `--watch` 和 standalone `--daemon` 指向同一个 `--output`。二者都会被资源锁和 live daemon 互斥保护,但生产运维上应保持单一 owner。
|
||||
|
||||
如果同一台服务器还要运行 `bat-api`,必须让 Rust `bat` 以能提供 `bat.sock` 的 RPC 形态运行,并让 `bat-api` 通过该 socket 获取当前 `resource_root`。这种部署见模式 4;不要把 `BAT_API_RESOURCE_ROOT` 当作生产主配置。
|
||||
|
||||
### 日志和状态路径
|
||||
|
||||
systemd 模式:
|
||||
@@ -351,7 +354,149 @@ sudo -u bat tar -C /var/lib/bluearchive-toolkit/official \
|
||||
|
||||
---
|
||||
|
||||
## 模式 4:完整生产环境部署
|
||||
## 模式 4:bat-api 资源 bootstrap / 分发服务
|
||||
|
||||
适用场景:真实 Rust `bat` 长期运行在远程服务器,并且同一服务器/容器环境内运行 Go `bat-api`,给客户端、补丁器或上层工具提供启动前资源入口和 CDN path 只读分发。
|
||||
|
||||
核心约束:
|
||||
|
||||
1. `bat-api` 与 Rust `bat` 同环境部署,至少要能访问同一个 Unix socket 和同一个已发布资源文件系统。
|
||||
2. 当前资源目录由 `bat.sock` RPC 返回的 `resource_root` 决定;生产不要在 `bat-api` 配置里写死 `BAT_API_RESOURCE_ROOT`。
|
||||
3. `BAT_API_RESOURCE_ROOT` 只用于本地 fixture、临时只读诊断或 RPC 不可用时的应急验证。
|
||||
4. `bat.sock` 只在服务器本机使用,不通过公网暴露;对外只发布 HTTP `bat-api`,生产建议放在反向代理和 TLS 后面。
|
||||
5. 本地开发环境不需要、也不应全量运行 `bat`;使用 Go 单测、fixture release 或远程服务器联调。
|
||||
|
||||
### 构建和安装 bat-api
|
||||
|
||||
```bash
|
||||
make build-go-api
|
||||
|
||||
VERSION="$(git rev-parse --short HEAD)"
|
||||
sudo install -d -o root -g root -m 0755 \
|
||||
/opt/bluearchive-toolkit/releases/"${VERSION}" \
|
||||
/opt/bluearchive-toolkit/bin
|
||||
sudo install -o root -g root -m 0755 \
|
||||
bin/bat-api \
|
||||
/opt/bluearchive-toolkit/releases/"${VERSION}"/bat-api
|
||||
sudo ln -sfn \
|
||||
/opt/bluearchive-toolkit/releases/"${VERSION}"/bat-api \
|
||||
/opt/bluearchive-toolkit/bin/bat-api
|
||||
/opt/bluearchive-toolkit/bin/bat-api --help
|
||||
```
|
||||
|
||||
如果 Rust `bat` 和 Go `bat-api` 使用同一个 release 目录发布,也可以把二者放在同一个 `<version-or-git-sha>` 目录下,分别通过 `/opt/bluearchive-toolkit/bin/bat` 和 `/opt/bluearchive-toolkit/bin/bat-api` 暴露稳定 symlink。
|
||||
|
||||
### bat 侧前置条件
|
||||
|
||||
`bat-api` 依赖 live RPC,而不是直接读取 daemon 状态文件。部署 `bat-api` 前,远程服务器上应已有 socket 形态的 Rust `bat`:
|
||||
|
||||
```bash
|
||||
sudo -u bat /opt/bluearchive-toolkit/bin/bat \
|
||||
--auto-discover \
|
||||
--output /var/lib/bluearchive-toolkit/official \
|
||||
--localized-output /var/lib/bluearchive-toolkit/localized \
|
||||
--state-dir /var/lib/bluearchive-toolkit/daemon-state \
|
||||
--daemon
|
||||
|
||||
sudo -u bat /opt/bluearchive-toolkit/bin/bat status \
|
||||
--state-dir /var/lib/bluearchive-toolkit/daemon-state
|
||||
```
|
||||
|
||||
确认 socket 存在:
|
||||
|
||||
```bash
|
||||
sudo -u bat test -S /var/lib/bluearchive-toolkit/daemon-state/bat.sock
|
||||
```
|
||||
|
||||
不要同时再运行一个 `--watch` service 指向 `/var/lib/bluearchive-toolkit/official`。如果当前服务器已经部署了 `bluearchive-toolkit-official-sync.service` 的纯同步 `--watch` 模式,需要先切换为 socket/RPC 形态,再启用 `bat-api`。
|
||||
|
||||
### 安装 bat-api systemd unit
|
||||
|
||||
```bash
|
||||
sudo install -o root -g root -m 0644 \
|
||||
deployments/systemd/bluearchive-toolkit-bat-api.service \
|
||||
/etc/systemd/system/bluearchive-toolkit-bat-api.service
|
||||
sudo install -o root -g root -m 0644 \
|
||||
deployments/systemd/bat-api.env.example \
|
||||
/etc/bluearchive-toolkit/bat-api.env
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now bluearchive-toolkit-bat-api.service
|
||||
```
|
||||
|
||||
默认配置只监听本机:
|
||||
|
||||
```env
|
||||
BAT_API_LISTEN=127.0.0.1:18080
|
||||
BAT_API_PUBLIC_BASE_URL=http://127.0.0.1:18080
|
||||
BAT_API_SOCKET=/var/lib/bluearchive-toolkit/daemon-state/bat.sock
|
||||
BAT_API_REFRESH_INTERVAL=1m
|
||||
BAT_API_ACCESS_LOG=true
|
||||
BAT_API_RATE_LIMIT_RPS=30
|
||||
BAT_API_RATE_LIMIT_BURST=120
|
||||
```
|
||||
|
||||
生产反向代理公开后,把 `BAT_API_PUBLIC_BASE_URL` 改成客户端实际访问的 HTTPS 根,例如:
|
||||
|
||||
```env
|
||||
BAT_API_PUBLIC_BASE_URL=https://assets.example.com
|
||||
```
|
||||
|
||||
面对玩家分发时还应通过 secret manager 或 systemd credential 注入:
|
||||
|
||||
```env
|
||||
BAT_API_AUTH_TOKEN=<secret>
|
||||
BAT_API_AUTH_QUERY_PARAM=bat_token
|
||||
BAT_API_AUTH_EXEMPT_PATHS=/healthz,/readyz
|
||||
BAT_API_MAX_RESOURCE_LIMIT=1000
|
||||
```
|
||||
|
||||
反代必须强制 HTTPS,并在转发到 `bat-api` 前清洗客户端提交的 `X-Forwarded-For` / `X-Real-IP`。只有确认反代会覆盖这些 header 时,才设置:
|
||||
|
||||
```env
|
||||
BAT_API_TRUST_PROXY_HEADERS=true
|
||||
```
|
||||
|
||||
否则保持默认 `false`,`bat-api` 会按 TCP peer IP 做限流和日志归因。应用层访问日志只记录 path,不记录 query string,避免 query token 进入日志。动态 JSON 响应使用 `Cache-Control: no-store`;CDN 字节路径仍使用长期 immutable 缓存。
|
||||
|
||||
不要在生产 env 里设置 `BAT_API_RESOURCE_ROOT`。`bat-api` 会按 `BAT_API_REFRESH_INTERVAL` 周期通过 RPC 重新读取 `catalog.status` / `resource.manifest`,从而跟随 Rust `bat` 切换 `current -> versions/<id>`。
|
||||
|
||||
### 健康检查
|
||||
|
||||
```bash
|
||||
systemctl status bluearchive-toolkit-bat-api.service
|
||||
journalctl -u bluearchive-toolkit-bat-api.service -f
|
||||
curl -fsS http://127.0.0.1:18080/healthz
|
||||
curl -fsS http://127.0.0.1:18080/readyz
|
||||
curl -fsS http://127.0.0.1:18080/v1/bootstrap
|
||||
curl -fsS http://127.0.0.1:18080/v1/launcher/bootstrap
|
||||
curl -fsS http://127.0.0.1:18080/api-launcher-jp.yo-star.com/api/launcher/game/config
|
||||
curl -fsS http://127.0.0.1:18080/openapi.yaml
|
||||
curl -fsS http://127.0.0.1:18080/admin/
|
||||
```
|
||||
|
||||
`/healthz` 是 liveness,固定返回服务存活状态,并包含最近一次 RPC refresh 的开始时间、成功时间、耗时、warning 和错误摘要。`/readyz` 是 readiness,当前没有可分发 release 时返回 `503`。`rpc_available=true` 且 `ready=true` 表示 `bat-api` 已经通过 RPC 发现可分发 release;`ready=false` 时,先检查 `bat.sock`、Rust `bat status`、`resource_root` 是否存在,以及 `official-download-manifest.json` 中的文件是否仍在磁盘上。
|
||||
|
||||
`/v1/launcher/bootstrap` 和 `/api-launcher-jp.yo-star.com/api/launcher/...` 只用于 launcher 资源 metadata / GameMainConfig 引导兼容。它们从 Rust `bat` 的已发布 snapshot/RPC 派生响应,显式标记不是完整 package update manifest;生产排障时应确认这些响应中的 `scope=resource_bootstrap_only`、`resource_bootstrap_url`、server-info URL 和 client-patch base 是否指向当前 `BAT_API_PUBLIC_BASE_URL`。
|
||||
|
||||
### 本地开发限制
|
||||
|
||||
开发机不能本地全量运行 `bat` 时,不需要伪造生产资源目录。Go 侧改动用单测和 fixture 验证:
|
||||
|
||||
```bash
|
||||
make test-go-api
|
||||
make build-go-api
|
||||
BAT_API_SKIP_ENV_FILE=1 go run ./cmd/bat-api \
|
||||
--listen 127.0.0.1:18080 \
|
||||
--public-base-url http://127.0.0.1:18080 \
|
||||
--resource-root internal/api/testdata/release \
|
||||
--refresh-interval 0
|
||||
```
|
||||
|
||||
这条本地命令只验证 HTTP 形态、server-info 改写、CDN path、Range/缓存语义和管理接口;真实全量 release 联调应在远程长期运行的 `bat` 环境里执行。
|
||||
|
||||
---
|
||||
|
||||
## 模式 5:完整生产环境部署
|
||||
|
||||
当前不可用。API Server、数据库迁移、Web 管理后台和发布编排尚未实现;不要按完整服务端产品部署本仓库。
|
||||
|
||||
|
||||
+125
-1
@@ -117,6 +117,10 @@ git push origin feature/your-feature-name
|
||||
|
||||
禁止使用 demo、临时实现、硬编码路径或只为当前测试通过的伪实现。确实未完成的能力应写入当前缺口文档,而不是用 `TODO` 或 `FIXME` 隐藏。
|
||||
|
||||
### 解析模块冻结
|
||||
|
||||
UnityFS / AssetBundle / Addressables / TypeTree 解析当前处于维护冻结。冻结期不得新增解析类型、扩大解析覆盖、开放新的写入型解析 RPC/CLI,或用合成 fixture 宣称新增能力。允许变更仅限编译、测试、clippy、真实运行回归、诊断和文档一致性修复。细则见 `docs/reports/PARSER_FREEZE.md`。
|
||||
|
||||
### Go
|
||||
- 遵循 [Effective Go](https://golang.org/doc/effective_go)
|
||||
- 使用 `gofmt` 格式化
|
||||
@@ -149,17 +153,31 @@ go vet ./internal/api/... ./internal/backendrpc/... ./cmd/bat-api/...
|
||||
Go 边界与进度以 `docs/reports/GO_STATUS.md` 为准:
|
||||
|
||||
- **同步/运维命令行** = Rust `bat`(近乎全自动)
|
||||
- **资源分发服务** = `cmd/bat-api`(`make build-go-api`)
|
||||
- **资源 bootstrap/分发服务** = `cmd/bat-api`(`make build-go-api`)
|
||||
- **默认 Go 门禁** = `make test-go-api`(无 FFI)
|
||||
- 试验 CLI 产物为 `bin/bat-go`(`make build-go-cli`),**禁止**与 Rust `bat` 重名
|
||||
- 修改 FFI 时再跑 `make test-go-ffi`
|
||||
|
||||
开发环境不能本地全量运行 Rust `bat` 时,`bat-api` 不需要真实生产资源目录。用 fixture 或 mock RPC 验证服务面;生产联调再连接远程服务器上同环境运行的 `bat.sock`:
|
||||
|
||||
```bash
|
||||
make test-go-api
|
||||
BAT_API_SKIP_ENV_FILE=1 go run ./cmd/bat-api \
|
||||
--listen 127.0.0.1:18080 \
|
||||
--public-base-url http://127.0.0.1:18080 \
|
||||
--resource-root internal/api/testdata/release \
|
||||
--refresh-interval 0
|
||||
```
|
||||
|
||||
生产默认路径仍是 `--socket` / `BAT_API_SOCKET`,资源根由 Rust `bat` RPC 返回;`--resource-root` 只用于上述 fixture 或应急只读诊断。
|
||||
|
||||
### 常用聚焦命令
|
||||
|
||||
```bash
|
||||
cargo test -p bat-core -- --nocapture
|
||||
cargo test -p bat-adapters -- --nocapture
|
||||
cargo test -p bat-ffi -- --nocapture
|
||||
cargo test -p bat-patch -- --nocapture
|
||||
cargo test -p bat-infrastructure -- --nocapture
|
||||
cargo test -p bat-infrastructure --bin bat -- --nocapture
|
||||
cargo clippy -p bat-core -p bat-adapters -p bat-infrastructure --all-targets -- -D warnings
|
||||
@@ -195,6 +213,112 @@ cargo run -p bat-infrastructure --bin bat -- \
|
||||
|
||||
开发环境真实官方资源下载默认写入 `./bat-resources`;汉化产物默认写入独立的 `./bat-localized`。如果要覆盖,官方原版资源使用 `--output` / `BAT_OUTPUT`,汉化产物使用 `--localized-output` / `BAT_LOCALIZED_OUTPUT`。两者都必须使用 `/tmp` 或其他隔离目录,不要写入现有资源目录,也不要把汉化输出覆盖到官方原版资源目录。
|
||||
|
||||
官方 release 拉取并校验完成后会在当前 release 根目录维护
|
||||
`official-resource-changes.json`、`crowdin-translation-handoff.json`、
|
||||
`official-parse-cache.json` 和 `official-textunit-index.json`,随后从
|
||||
Added/Modified 资源、parse cache 与 TextUnit 明细索引派生
|
||||
`official-textunit-tasks.json` 和 `crowdin-textunit-queue.json`。本地已有旧完整
|
||||
版本时,新版本发布后会先按 manifest destination 对比旧/新 release,只把新增和
|
||||
内容变更的资源写入解析与 Crowdin handoff;删除资源只记录差异,不进入翻译队列。
|
||||
up-to-date 轮询发现本地文件、解析缓存、TextUnit 明细索引和 TextUnit 队列未变时不会重复解析。
|
||||
Crowdin 队列当前只落本地文件,不发网络请求。
|
||||
|
||||
需要把已校验官方 release 导入 CAS + `ResourceRepository` 时,显式启用:
|
||||
|
||||
```bash
|
||||
cargo run -p bat-infrastructure --bin bat -- \
|
||||
--auto-discover \
|
||||
--import-repository \
|
||||
--import-cas-root /tmp/bat-test.cas \
|
||||
--import-resource-db /tmp/bat-test-resources.sqlite
|
||||
```
|
||||
|
||||
对应 `.env` / 环境变量键为 `BAT_IMPORT_REPOSITORY`、
|
||||
`BAT_IMPORT_CAS_ROOT` 和 `BAT_IMPORT_RESOURCE_DB`。只读查询命令:
|
||||
|
||||
```bash
|
||||
cargo run -p bat-infrastructure --bin bat -- parse-status
|
||||
cargo run -p bat-infrastructure --bin bat -- parse-text-units --limit 50
|
||||
cargo run -p bat-infrastructure --bin bat -- parse-errors --limit 50
|
||||
cargo run -p bat-infrastructure --bin bat -- localized-status
|
||||
cargo run -p bat-infrastructure --bin bat -- resource-index --limit 50
|
||||
```
|
||||
|
||||
`parse-status` 会额外显示 TextUnit 明细索引和队列摘要;`parse-text-units` /
|
||||
`parse-errors` 可按 destination、archive entry、path id、class id、field path
|
||||
和 format 分页查询当前官方 release 的 TextUnit 明细与解析错误;
|
||||
`resource-index` 返回的资源 JSON 包含 release、平台、bundle path、TextAsset 和 TextUnit metadata;
|
||||
`localized-status` 只有在 `localized-version-state.json`、`current` symlink 和
|
||||
`localized-patch-manifest.json` 都匹配当前官方 release 时才返回 `localized`。
|
||||
|
||||
文件级写入命令只处理显式输入/输出文件,不切换官方或汉化 release:
|
||||
|
||||
```bash
|
||||
cargo run -p bat-infrastructure --bin bat -- patch-apply \
|
||||
--patch-kind text \
|
||||
--source-file /tmp/bat-source.txt \
|
||||
--patch-file /tmp/bat-source.text-patch.json \
|
||||
--target-file /tmp/bat-target.txt
|
||||
|
||||
cargo run -p bat-infrastructure --bin bat -- unityfs-patch-text-asset \
|
||||
--bundle-file /tmp/source.bundle \
|
||||
--serialized-file CAB-Example \
|
||||
--object-path-id 1 \
|
||||
--replacement-file /tmp/replacement.bytes \
|
||||
--target-file /tmp/target.bundle
|
||||
|
||||
cargo run -p bat-infrastructure --bin bat -- unityfs-patch-string-field \
|
||||
--bundle-file /tmp/source.bundle \
|
||||
--serialized-file CAB-Example \
|
||||
--object-path-id 1 \
|
||||
--string-field-path message \
|
||||
--replacement-text "老师" \
|
||||
--target-file /tmp/target.bundle
|
||||
|
||||
cargo run -p bat-infrastructure --bin bat -- unityfs-patch-field \
|
||||
--bundle-file /tmp/source.bundle \
|
||||
--serialized-file CAB-Example \
|
||||
--object-path-id 1 \
|
||||
--field-path scores[1] \
|
||||
--expected-json '{"kind":"signed","value":20}' \
|
||||
--replacement-json '{"kind":"signed","value":42}' \
|
||||
--target-file /tmp/target.bundle
|
||||
|
||||
cargo run -p bat-infrastructure --bin bat -- unityfs-patch-field \
|
||||
--bundle-file /tmp/source.bundle \
|
||||
--serialized-file CAB-Example \
|
||||
--object-path-id 1 \
|
||||
--field-path difficulty \
|
||||
--expected-json '{"kind":"enum","value":{"type_name":"ScenarioDifficulty","storage_type":"int","value":2}}' \
|
||||
--replacement-json '{"kind":"enum","value":{"type_name":"ScenarioDifficulty","storage_type":"int","value":3}}' \
|
||||
--target-file /tmp/target.bundle
|
||||
|
||||
cargo run -p bat-infrastructure --bin bat -- unityfs-patch-field \
|
||||
--bundle-file /tmp/source.bundle \
|
||||
--serialized-file CAB-Example \
|
||||
--object-path-id 1 \
|
||||
--field-path target_layers \
|
||||
--expected-json '{"kind":"bit_field","value":{"type_name":"LayerMask","storage_type":"UInt32","bits":5}}' \
|
||||
--replacement-json '{"kind":"bit_field","value":{"type_name":"LayerMask","storage_type":"UInt32","bits":9}}' \
|
||||
--target-file /tmp/target.bundle
|
||||
|
||||
cargo run -p bat-infrastructure --bin bat -- unityfs-patch-field \
|
||||
--bundle-file /tmp/source.bundle \
|
||||
--serialized-file CAB-Example \
|
||||
--object-path-id 1 \
|
||||
--field-path messages \
|
||||
--replacement-json '{"kind":"array","value":[{"kind":"string","value":"你好"},{"kind":"string","value":"老师"}]}' \
|
||||
--target-file /tmp/target.bundle
|
||||
|
||||
cargo run -p bat-infrastructure --bin bat -- unityfs-patch-field \
|
||||
--bundle-file /tmp/source.bundle \
|
||||
--serialized-file CAB-Example \
|
||||
--object-path-id 1 \
|
||||
--field-path texts \
|
||||
--replacement-json '{"kind":"map","value":[{"kind":"object","value":[{"name":"first","value":{"kind":"string","value":"jp"}},{"name":"second","value":{"kind":"string","value":"你好"}}]}]}' \
|
||||
--target-file /tmp/target.bundle
|
||||
```
|
||||
|
||||
生产或 CI 环境不得依赖安装官方启动器。需要启动器信息时,只能分析启动器资源、官方 manifest 或公开更新数据,并将解析结果固化为可验证流程。
|
||||
|
||||
### 基准测试
|
||||
|
||||
@@ -97,9 +97,9 @@ Linux 生产运行时链路只走官方日服 HTTP 资源,不安装、不启
|
||||
2. 请求官方 `server-info`。
|
||||
3. 生成 Windows + Android 的官方资源 discovery 端点。
|
||||
4. 拉取 seed catalog,生成完整官方 pull plan。
|
||||
5. dry-run 只输出 URL;非 dry-run 下载全部官方 URL 到 staging,验收完成后原子发布到 `current`。
|
||||
5. dry-run 只输出 URL;非 dry-run 下载全部官方 URL 到 staging,验收完成后原子发布到 `current`,并在 release 中写入 `official-launcher-bootstrap.json`。
|
||||
|
||||
`--auto-discover` 会下载官方 metadata,并按官方 manifest 临时获取 `resources.assets` 解析 `GameMainConfig`;旧 ZIP manifest 才会下载临时 game zip。该流程不会安装官方启动器,也不会执行官方启动器进程。`--launcher-bootstrap` 只是旧命名兼容别名,新流程不要再推荐使用。
|
||||
`--auto-discover` 会下载官方 metadata,记录 launcher API 返回的 game config、CDN config、remote manifest 文件列表和选中的 `resources.assets` 来源,并按官方 manifest 临时获取 `resources.assets` 解析 `GameMainConfig`;旧 ZIP manifest 才会下载临时 game zip。该流程不会安装官方启动器,也不会执行官方启动器进程。`--launcher-bootstrap` 只是旧命名兼容别名,新流程不要再推荐使用。
|
||||
|
||||
## 2. 可选 metadata 审计
|
||||
|
||||
@@ -198,11 +198,13 @@ cargo run -p bat-infrastructure --example official_pull_plan -- \
|
||||
- 官方 seed `.hash` 校验失败会让本轮失败,并清理对应本地 manifest 条目;下一轮会继续把这类文件视为需要 repair,而不是把失败产物当作健康缓存复用。
|
||||
- curl 默认自动检测本地代理环境;也可以用 `--proxy <URL>` 显式指定代理,或用 `--no-proxy` 强制直连。代理决策会进入 progress log、daemon log 和 `doctor` 诊断输出。
|
||||
- curl 失败会按类型分类:403/404/普通 4xx 不重试,5xx、429、DNS、连接、超时、中断和网络类错误按尝试次数重试。
|
||||
- 官方维护或大版本发布窗口可能出现启动器/server-info 已经给出新版本和新 `AddressablesCatalogUrlRoot`,但 client-patch CDN 的 seed marker 或必需 seed catalog 尚未开放的状态。此时单次运行会输出 `update_status=waiting_for_official_resources`、`waiting_for_official_resources=true` 和 `unavailable_endpoints`;不会进入 staging、不会写入 `failed_versions`、不会切换 `current`。watch/daemon 会把状态置为 `waiting`,按 `--error-retry` / `BAT_ERROR_RETRY_SECONDS`(默认 60 秒)继续探测。
|
||||
- 单个 URL 最终失败后会写入 `official-download-quarantine.json`,progress log、daemon status 和 `bat-events.jsonl` 会记录失败类型、HTTP 状态、是否可重试、尝试次数和 quarantine 状态。
|
||||
- quarantine 项会跳过本轮发布并让同步失败,避免把不完整 staging 发布到 `current`;下一轮 repair/refresh 成功后会清理对应 quarantine 条目。
|
||||
- 失败或中断后的 staging 不会无条件丢弃:如果 version-state 记录的失败版本和本轮远端元数据匹配,且 staging 目录仍安全存在,下一轮会复用该 staging;已通过 manifest 校验的文件会跳过,缺失、损坏、无 manifest 或官方 seed `.hash` 需要刷新的 URL 会重新下载。
|
||||
- 旧 launcher 包或 `resources.assets` 下载路径使用官方 launcher CDN 配置,primary CDN 失败后会切换官方 backup CDN;资源 patch host 当前只使用 server-info 返回的官方 client-patch host,不猜测非官方镜像。
|
||||
- 远端和本地都一致:单次模式输出 `update_status=up_to_date`,watch 模式默认静默并等待下次检查。
|
||||
- 远端 metadata 已更新但资源端尚未开放:单次模式输出 `update_status=waiting_for_official_resources`,watch/daemon 模式保留现有资源并短间隔重试。
|
||||
- 有远端变化或本地 repair:生成 pull plan,下载完整官方资源到 staging,成功后更新 snapshot 并原子发布到 `current`。
|
||||
- 非 dry-run 会维护 `<output>/official-version-state.json`:开始下载后写入 `in_progress_version`,发布成功后写入 `current_completed_version` 和 `previous_available_version`,失败或中断后写入 `failed_versions`。同一 app version、bundle version 和 Addressables root 的失败只保留最新一条;同一版本开始重新拉取或后续发布成功时会清理对应失败记录。重新拉取同一失败版本时会复用安全存在的失败 staging,不会因为 `publish_id` 变化从空目录重新开始。
|
||||
- `--dry-run`:只报告本次是否会下载,不写 snapshot;如果 cache miss,也不会写入新的 bootstrap cache。
|
||||
@@ -210,15 +212,22 @@ cargo run -p bat-infrastructure --example official_pull_plan -- \
|
||||
- 真实更新会输出 `downloaded_count`、`resumed_count`、`skipped_count`、`transferred_bytes`、`official_seed_hash_verified_count`。
|
||||
- 校验报告分层输出 `official_seed_hash_verified_count`、`local_manifest_verified_count`、`addressables_marker_checked_count`、`unverified_marker_count`。
|
||||
- 下载阶段复用同一套本地清单、ZIP 结构校验和 `.part` 续传逻辑;没有清单或校验不匹配的文件会重新下载。
|
||||
- 校验和发布完成后会刷新 `<output>/current/official-parse-cache.json`。解析缓存从 `official-download-manifest.json` 的全部条目出发,处理直接 UnityFS bundle 和 zip 内 UnityFS 条目;catalog、hash、媒体等非 UnityFS 文件记录为不支持,不视为同步失败。本地 URL、相对路径、size 和 BLAKE3 未变化时复用缓存并跳过重复解析。
|
||||
- 非 dry-run 且启用 `--auto-discover` 时,成功发布的 release 会包含 `official-launcher-bootstrap.json`;up-to-date 轮询发现当前 release 缺少该文件时会补写。官方 launcher/server-info 已更新但 client-patch 资源尚未开放时,不切换 `current`,只在输出根写入 `official-launcher-bootstrap.pending.json` 作为维护期证据。
|
||||
- 校验和发布完成后会先对比上一完整 release 与当前 release 的 `official-download-manifest.json`,写出 `<output>/current/official-resource-changes.json` 和 `<output>/current/crowdin-translation-handoff.json`。同一 destination 只有 size 或 BLAKE3 改变才算 modified;仅 URL/CDN 根变化但内容一致不会触发解析/翻译候选。新增+变更资源进入解析和 Crowdin 翻译 handoff,删除资源只进入差异记录;当前不会直接调用 Crowdin API。
|
||||
- 随后会刷新 `<output>/current/official-parse-cache.json`。解析缓存从 `official-download-manifest.json` 的全部条目出发,处理直接 UnityFS bundle 和 zip 内 UnityFS 条目;catalog、hash、媒体等非 UnityFS 文件记录为不支持,不视为同步失败。新 release 会刷新解析缓存;远端和本地都 up-to-date 且已有有效解析缓存时只读取摘要,不重复解析。
|
||||
- 需要将已校验官方 release 导入 CAS + SQLite ResourceRepository 时,使用 `--import-repository` 或 `.env` 中 `BAT_IMPORT_REPOSITORY=1`;默认 CAS 为 `<output>/.cas`,默认索引为 `<output>/resources.sqlite`,可用 `--import-cas-root` / `BAT_IMPORT_CAS_ROOT` 和 `--import-resource-db` / `BAT_IMPORT_RESOURCE_DB` 覆盖。`resource.index` RPC 可查询现有索引,索引不存在时返回 `available=false`,不会创建空库。
|
||||
- 官方同步报告中的 `localized_release_status=not_localized` 表示原版资源已发布、汉化资源未发布,这是当前官方同步阶段的正常完成状态;后续 Patch 发布完成后才应切换为 `localized`,表示原版和汉化两套资源都已发布。
|
||||
|
||||
资源同步状态文件默认分布如下:
|
||||
|
||||
- `<output>/current/official-sync-snapshot.json`:上一次成功同步的 v2 snapshot,包含 app version、connection group、bundle version、addressables root、endpoint URL、官方 seed `.hash` 内容、Addressables `catalog_*.hash` marker、launcher metadata 摘要和 `GameMainConfig` 摘要。
|
||||
- `<output>/official-bootstrap-cache.json`:`--auto-discover` 的 `GameMainConfig` 解析缓存。launcher metadata 未变时复用缓存;metadata 变化时才通过官方 HTTP 按 manifest 下载必要 `resources.assets` 或旧版 game zip 到临时目录解析。
|
||||
- `<output>/current/official-sync-snapshot.json`:上一次成功同步的 v2 snapshot,包含 app version、connection group、bundle version、addressables root、endpoint URL、官方 seed `.hash` 内容、Addressables `catalog_*.hash` marker、launcher metadata 摘要和 `GameMainConfig` 摘要;launcher metadata 额外包含 remote manifest 文件列表 digest,用于发现同文件数但内容变化的 launcher manifest。
|
||||
- `<output>/current/official-launcher-bootstrap.json`:随已发布 release versioned 保存的官方 launcher bootstrap 产物,包含 launcher metadata、launcher CDN config、remote manifest 文件列表、选中的 `resources.assets` 来源、`GameMainConfig` 摘要和当前资源上下文。
|
||||
- `<output>/official-launcher-bootstrap.pending.json`:官方 launcher/server-info 已前进但 client-patch seed marker 或必需 seed catalog 尚未开放时写入的待处理 bootstrap 证据;它不代表资源已发布,也不会改变 `current`。
|
||||
- `<output>/official-bootstrap-cache.json`:`--auto-discover` 的 `GameMainConfig` 解析缓存。launcher metadata 与 remote manifest 文件列表 digest 都未变时复用缓存;任一变化时才通过官方 HTTP 按 manifest 下载必要 `resources.assets` 或旧版 game zip 到临时目录解析。
|
||||
- `<output>/official-version-state.json`:资源发布根目录的持久版本状态,包含当前已完成版本、正在拉取版本、上一个可用版本和失败版本。
|
||||
- `<output>/current/official-download-manifest.json`:本地下载强校验清单,记录 URL、相对路径、size 和 BLAKE3。
|
||||
- `<output>/current/official-resource-changes.json`:当前 release 相对上一完整 release 的资源差异,记录新增、变更、删除以及解析/翻译候选计数。
|
||||
- `<output>/current/crowdin-translation-handoff.json`:为后续 Crowdin worker 预留的本地队列,只包含新增+变更资源;它不是 Crowdin API 调用结果。
|
||||
- `<output>/current/official-parse-cache.json`:官方资源发布后的派生解析缓存,记录 bundle/zip 条目解析摘要和缓存复用情况;它不是汉化产物。
|
||||
- `<output>/current/official-download-quarantine.json` 或当前 staging 下同名文件:下载最终失败的 URL 诊断记录,包含失败类型、HTTP 状态、是否可重试、尝试次数和最后错误。
|
||||
|
||||
|
||||
@@ -102,9 +102,95 @@ contract 为准,不应绕过 daemon 状态文件或扩展 `bat-ffi` 作为主
|
||||
| `resource.repair` | 已实现 | `null` | `{ "task_id": "...", "kind": "resource.repair" }`。 |
|
||||
| `resource.manifest` | 已实现 | `{ "offset": 0, "limit": 100 }` | 当前 download manifest 分页。 |
|
||||
| `resource.list` | 已实现 | `{ "offset": 0, "limit": 100 }` | `resource.manifest` 的兼容别名。 |
|
||||
| `resource.index` | 已实现 | `{ "offset": 0, "limit": 100, "type": "asset_bundle", "hash": "...", "path_pattern": "*" }` | 当前 `ResourceRepository` 分页/过滤查询。 |
|
||||
|
||||
`resource.repair` 会开启本地 manifest audit + repair,不继承 `force`。
|
||||
`limit` 范围是 `1..=1000`,非法参数返回 `BAT-ERR-700002`。
|
||||
`resource.manifest` / `resource.list` 查询当前已发布 release 的
|
||||
`official-download-manifest.json`;`resource.index` 查询可选导入产生的
|
||||
SQLite `ResourceRepository`,索引不存在时返回 `ok=true` 且
|
||||
`data.available=false`,不会隐式创建数据库。`limit` 范围是 `1..=1000`,
|
||||
非法参数返回 `BAT-ERR-700002`。
|
||||
|
||||
`resource.index` 的 `entries[]` 是 `Resource` JSON,除 `id`、`local_path`、
|
||||
`entry` 外会包含 `metadata`:`official_release_id`、`platform`、
|
||||
`bundle_path`、`archive_entries`、`parse_statuses`、`unity_versions`、
|
||||
`text_assets`、`text_unit_count`、`text_unit_formats` 和
|
||||
`text_unit_error_count` 等字段。旧索引库会通过 `metadata_json` 迁移列得到
|
||||
默认空 metadata。
|
||||
|
||||
官方资源完整新版本发布后,Rust 侧会先比较上一完整 release 与当前 release
|
||||
的 download manifest,并在当前 release 根目录写出:
|
||||
|
||||
- `official-resource-changes.json`:记录 added / modified / removed 资源。
|
||||
同一 destination 只有 size 或 BLAKE3 变化才算 modified;URL 或 CDN root
|
||||
变化但内容一致时不进入解析/翻译候选。
|
||||
- `crowdin-translation-handoff.json`:只包含 added + modified 资源,作为后续
|
||||
Crowdin worker 的稳定本地队列输入;当前 RPC 不直接调用 Crowdin API。
|
||||
- `official-parse-cache.json`:解析缓存。up-to-date 轮询发现本地文件未变且缓存
|
||||
有效时只读取摘要,不重复解析。
|
||||
- `official-textunit-index.json`:TextUnit 明细和解析错误索引。up-to-date 轮询发现
|
||||
本地文件未变且索引有效时复用,不重复解析。
|
||||
- `official-textunit-tasks.json`:只由 added + modified 资源、parse cache 和
|
||||
TextUnit 明细索引派生,记录 TextUnit 任务、跳过原因和解析诊断。
|
||||
- `crowdin-textunit-queue.json`:只包含已产生 TextUnit 的离线任务,预留给后续
|
||||
Crowdin worker;当前不会发出网络请求。
|
||||
|
||||
删除资源只进入 `official-resource-changes.json`,不进入 Crowdin handoff。
|
||||
|
||||
### parse
|
||||
|
||||
| 方法 | 状态 | params | data |
|
||||
|---|---|---|---|
|
||||
| `parse.status` | 已实现 | `null` | 当前官方 release 的解析缓存状态。 |
|
||||
| `parse.text_units` | 已实现 | `{ "offset": 0, "limit": 100, "destination": "*Table*", "archive_entry": "*.bytes", "path_id": 1, "class_id": 114, "field_path": "*Text*", "format": "json" }` | 当前官方 release 的 TextUnit 明细分页。 |
|
||||
| `parse.errors` | 已实现 | `{ "offset": 0, "limit": 100, "destination": "*Table*", "archive_entry": "*.bytes", "path_id": 1, "class_id": 114, "field_path": "*Text*", "format": "json" }` | 当前官方 release 的解析错误分页。 |
|
||||
|
||||
`parse.status` 是只读查询;没有当前 release 或没有解析缓存时返回
|
||||
`ok=true` 且 `data.available=false`。解析缓存来自官方原版资源目录,不读取
|
||||
汉化输出目录。存在 `official-textunit-index.json` 时,响应会包含
|
||||
`textunit_index_available=true`、`textunit_index_path` 和
|
||||
`textunit_index_summary`;存在 `official-textunit-tasks.json` 时,响应会包含
|
||||
`textunit_queue_available=true`、`textunit_task_queue_path` 和
|
||||
`textunit_task_summary`。
|
||||
|
||||
`parse.text_units` / `parse.errors` 是只读查询;没有当前 release 或没有
|
||||
`official-textunit-index.json` 时返回 `ok=true` 且 `data.available=false`。
|
||||
分页参数 `offset` 默认 0,`limit` 默认 100,范围是 `1..=1000`。过滤参数:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `destination` | string | official download manifest destination,支持 `*` 通配。 |
|
||||
| `archive_entry` | string | zip 内条目,支持 `*` 通配;直接 bundle 通常为 `null`。 |
|
||||
| `path_id` | integer | Unity object path id。 |
|
||||
| `class_id` | integer | Unity class id。 |
|
||||
| `field_path` | string | TypeTree/TextAsset 字段路径,支持 `*` 通配。 |
|
||||
| `format` | string | TextUnit 格式,例如 `json`、`csv`、`tsv`、`plain` 或 `typetree_string`。 |
|
||||
|
||||
`parse.text_units` 的 `entries[]` 会包含 source text、source URL、
|
||||
destination、archive entry、source kind、Unity version、serialized file、
|
||||
path id、class id、field path、字段 offset/byte size、format、asset name 和
|
||||
context。`parse.errors` 的 `entries[]` 会包含 source URL、destination、
|
||||
archive entry、status、serialized file、path id、class id、field path、
|
||||
offset 和 error。TypeTree-covered managed reference 字段会进入结构化字段遍历;
|
||||
完整 managed reference registry 等暂不支持结构会进入解析错误,而不是静默降级为
|
||||
低保真文本。
|
||||
|
||||
### localized
|
||||
|
||||
| 方法 | 状态 | params | data |
|
||||
|---|---|---|---|
|
||||
| `localized.status` | 已实现 | `null` | 汉化发布状态、当前官方 release 匹配关系和汉化输出目录。 |
|
||||
|
||||
`localized.status` 严格按 daemon / `.env` 中的 `BAT_LOCALIZED_OUTPUT` 或
|
||||
`--localized-output` 查询汉化产物目录,不把 `./bat-resources` 与
|
||||
`./bat-localized` 混用。当前支持未汉化发布状态和已汉化发布状态的只读报告。
|
||||
返回 `localized` 的条件是:`localized-version-state.json` 的官方 release ID
|
||||
匹配当前官方 release,`current` symlink 指向汉化发布根下对应的
|
||||
`versions/<id>`,并且该版本目录中的
|
||||
`localized-patch-manifest.json` 存在且 release ID 匹配。响应会返回
|
||||
`patch_manifest_path`、`patch_manifest_available`、
|
||||
`patch_manifest_matches_release`、`patch_file_count`、
|
||||
`patch_text_asset_operation_count` 和 `rollback_previous_current_target`。
|
||||
|
||||
### catalog
|
||||
|
||||
@@ -151,9 +237,53 @@ daemon 重启后仍处于 `queued` 或 `running` 的历史任务会被标记为
|
||||
|
||||
### patch / unityfs
|
||||
|
||||
`patch.*` 和 `unityfs.*` 是已规划命名空间,目前返回
|
||||
`BAT-ERR-700003`。它们依赖后续 `bat-patch`、`bat-assetbundle`
|
||||
引擎,不作为 issue #1 的关闭阻塞项。
|
||||
已开放的文件级写入方法:
|
||||
|
||||
- `patch.apply`:对显式 `source_path`、`patch_path`、`target_path` 执行
|
||||
Binary/JSON/Text patch apply,`kind` 取值为 `binary`、`json` 或 `text`。
|
||||
- `unityfs.patch_text_asset`:对显式 UnityFS `bundle_path` 中的
|
||||
`serialized_file_path` / `path_id` TextAsset 应用 `replacement_path`,写入
|
||||
`target_path`,可选 `expected_name`。
|
||||
- `unityfs.patch_string_field`:对显式 UnityFS `bundle_path` 中的
|
||||
`serialized_file_path` / `path_id` / `field_path` TypeTree string 字段应用
|
||||
`replacement_text` 或 UTF-8 `replacement_path`,写入 `target_path`,可选
|
||||
`expected_value`。
|
||||
- `unityfs.patch_field`:对显式 UnityFS `bundle_path` 中的
|
||||
`serialized_file_path` / `path_id` / `field_path` TypeTree 字段应用语义
|
||||
`replacement` JSON,写入 `target_path`,可选 `expected_value`。`replacement`
|
||||
使用 `{"kind":"signed","value":42}` 这类 tagged JSON;支持
|
||||
`bool`、`signed`、`unsigned`、`float32`、`float64`、`string`、`bytes`、
|
||||
`enum`、`bit_field`、`p_ptr`、固定 Unity 叶子结构、object 字段组合和 TypeTree schema 支撑的 array/map 整体替换。enum 形如
|
||||
`{"kind":"enum","value":{"type_name":"ScenarioDifficulty","storage_type":"int","value":3}}`;
|
||||
`type_name` 是 TypeTree enum 类型名,`storage_type` 是 backing integer 类型。`LayerMask` / `BitField` 形如
|
||||
`{"kind":"bit_field","value":{"type_name":"LayerMask","storage_type":"UInt32","bits":9}}`。
|
||||
array 形如
|
||||
`{"kind":"array","value":[{"kind":"string","value":"你好"}]}`;map entry 用
|
||||
object 表达,例如
|
||||
`{"kind":"object","value":[{"name":"first","value":{"kind":"string","value":"jp"}}]}`。
|
||||
扩容时复用当前首个元素或 TypeTree data node 的编码 schema;map entry schema
|
||||
变化、unknown 字段和未覆盖的 managed reference registry 变体仍会返回明确错误。
|
||||
固定 Unity 叶子结构使用 raw bits/bytes 表达,例如
|
||||
`{"kind":"float32_struct","value":{"type_name":"Vector3f","values":[1065353216,1073741824,1077936128]}}`
|
||||
或
|
||||
`{"kind":"fixed_bytes","value":{"type_name":"GUID","bytes":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]}}`。
|
||||
|
||||
这些方法同步执行,不进入 `task.*` 队列;输出文件使用临时文件原子写入,响应
|
||||
`data` 会返回 source / patch 或 replacement / target 的 size 与 BLAKE3。`target_path`
|
||||
不能与输入文件相同。
|
||||
|
||||
仍关闭的范围:发布级 `patch build` / `patch rollback`、复杂 UnityFS 语义编辑、
|
||||
`unityfs.inspect`、通用 manifest 驱动 release 切换。调用这些规划方法仍返回
|
||||
`BAT-ERR-700003`。
|
||||
|
||||
CLI 对应关系:
|
||||
|
||||
| CLI | RPC |
|
||||
|---|---|
|
||||
| `bat patch-apply` | `patch.apply` |
|
||||
| `bat unityfs-patch-text-asset` | `unityfs.patch_text_asset` |
|
||||
| `bat unityfs-patch-string-field` | `unityfs.patch_string_field` |
|
||||
| `bat unityfs-patch-field` | `unityfs.patch_field` |
|
||||
|
||||
## Go 调用边界
|
||||
|
||||
@@ -161,9 +291,24 @@ daemon 重启后仍处于 `queued` 或 `running` 的历史任务会被标记为
|
||||
`bat` binary 是人类 CLI 和进程生命周期工具;默认 `refresh` / `repair`
|
||||
在 daemon 可用时也会作为 RPC client 调用同一个 socket。
|
||||
|
||||
人类 CLI 的只读查询命令与 RPC 对应关系如下:
|
||||
|
||||
| CLI | RPC |
|
||||
|---|---|
|
||||
| `bat parse-status` | `parse.status` |
|
||||
| `bat parse-text-units` | `parse.text_units` |
|
||||
| `bat parse-errors` | `parse.errors` |
|
||||
| `bat localized-status` | `localized.status` |
|
||||
| `bat resource-index` | `resource.index` |
|
||||
|
||||
`bat resource-index` 支持 `--offset`、`--limit`、`--resource-type`、`--hash`
|
||||
和 `--path-pattern`;`bat parse-text-units` / `bat parse-errors` 支持
|
||||
`--offset`、`--limit`、`--destination`、`--archive-entry`、`--path-id`、
|
||||
`--class-id`、`--field-path` 和 `--format`;这些过滤参数不适用于
|
||||
`parse-status` 或 `localized-status`。
|
||||
|
||||
禁止事项:
|
||||
|
||||
- Go 服务层不直接读写 `bat-status.json`、`bat-tasks.json` 等 daemon 内部状态文件。
|
||||
- Go 服务层不扩展 `bat-ffi` 为主控制面。
|
||||
- Go 服务层不通过 stdout 解析 `bat status --json` 作为常规调用路径。
|
||||
|
||||
|
||||
@@ -113,18 +113,20 @@
|
||||
|
||||
状态:**部分完成**
|
||||
|
||||
冻结状态:自 2026-07-30 起,G-005 不再作为默认推进项。解析层只接受维护冻结规则允许的稳定性修复、诊断修复、真实回归修复和文档校正;新增 TypeTree 语义类型、扩大解析覆盖和新增写入型解析入口全部暂停。冻结细则见 `docs/reports/PARSER_FREEZE.md`。
|
||||
|
||||
现象:
|
||||
|
||||
- `crates/bat-assetbundle` 已接管 UnityFS 解析,提供 `UnityFsParser`、`UnityFsBundle`、header、block info、directory、压缩模式、block info at end、LZ4/LZMA block info 解压、数据 block 解压、directory 文件提取和边界诊断。
|
||||
- `crates/bat-assetbundle::serialized` 已提供 Unity serialized file header、type table、TypeTree node 元数据、object table 和 `TextAsset` bytes 提取。
|
||||
- `crates/bat-assetbundle::serialized` 已提供 Unity serialized file header、type table、TypeTree node 元数据、object table、TextAsset bytes 和基础 TypeTree field reader。
|
||||
- `adapters/src/unity/unity_2021_3.rs` 已降为 Unity 版本选择薄层,复用 `bat-assetbundle`,不再维护第二套 UnityFS parser。
|
||||
- `ResourceImportService` 的 UnityFS 摘要已经能暴露解包文件数、serialized file 数、TextAsset 数量和名称。
|
||||
- 仍没有 `MonoBehaviour`、`ScriptableObject` 的 TypeTree 字段级反序列化和可编辑重打包入口。
|
||||
- `ResourceImportService` 的 UnityFS 摘要已经能暴露解包文件数、serialized file 数、TextAsset 名称、TextUnit 数量/格式和字段诊断。
|
||||
- `MonoBehaviour`、`ScriptableObject` 已有基础 TypeTree 字段级反序列化和字符串提取入口;array/vector/staticvector/`List<T>`/`HashSet<T>`/map 元素与 TypeTree-covered managed reference registry payload 已保留独立 field path、offset 和 byte size,enum `value__` backing field 会暴露为语义化 `{type_name, storage_type, value}`,`LayerMask` / `BitField` 的 `m_Bits` backing field 会暴露为语义化 `{type_name, storage_type, bits}`,managed-reference full typename 可拆为 assembly/namespace/class,常见 `m_ManagedReferences` / `RefIds` / `m_RefIds` / verbose type 字段命名、`managedReference*` / `serializedReference*` prefixed metadata、`SerializedReference` 节点 alias 和 `data` / `value` / `payload` / `object` / `managedReferencePayload` / `referencePayload` / `serializedReferencePayload` / `managedReferenceValue` / `referenceValue` / `serializedReferenceValue` / `managedReferenceObject` / `referenceObject` / `serializedReferenceObject` / `managedReferenceData` / `referenceData` / `serializedData` / `serializedReferenceData` payload 命名已有回归覆盖,多记录 registry 聚合已有单元回归,TextUnit 提取会跳过 registry 元数据字符串并把它们作为 payload 文本上下文,fallback 字段遍历也会跳过常见 managed-reference 元数据别名,并按 `RefIds[n]` 等记录前缀或子字段推导 metadata 写入 payload TextUnit context;当前可对 string、bool、integer、float raw bits、bytes、enum、bit_field、常见固定 Unity float/int/hash 值类型的 leaf/direct-child 形态、unknown fixed-size raw bytes 同长度替换、PPtr、object 字段组合和 TypeTree schema 支撑的 array/vector/List/HashSet/map 整体替换执行文件级 patch,map entry 的 `first/second` 与 `key/value` 字段命名已有 serialized 和 UnityFS 重建回归,ScriptableObject `key/value` map 解析、变长替换和 UnityFS 重建已有专门回归;真实版本差异、未见样本驱动的复杂 managed reference registry / map entry 变体、unknown 字段结构语义和发布级重打包入口仍未完成。
|
||||
|
||||
影响:
|
||||
|
||||
- 可以对 UnityFS 容器做结构校验、解包 directory 文件,并提取 serialized file 中的 TextAsset 原始 bytes。
|
||||
- 对日语汉化最关键的 TextAsset 索引和 bytes 提取已有基础入口,但还不能直接解析 `MonoBehaviour`/`ScriptableObject` 自定义字段或完成修改后重打包。
|
||||
- 对日语汉化最关键的 TextAsset 索引、bytes、JSONL TextUnit、MonoBehaviour/ScriptableObject 基础字符串字段、array/vector/List/HashSet/map 字符串元素和 TypeTree-covered managed reference payload 提取已有入口;managed-reference 类型元数据作为上下文保留,不进入翻译文本队列,fallback registry 字段遍历也会过滤常见元数据别名,并按记录前缀或子字段保留可推导 metadata。文件级 UnityFS 重建可覆盖 TextAsset、TypeTree string 字段、managed-reference registry payload 字符串、基础语义字段、enum、bit_field、unknown fixed-size raw bytes、object 字段组合和 TypeTree schema 支撑的 array/vector/List/HashSet/map 整体替换,但还不能完成发布级复杂对象重打包。
|
||||
|
||||
当前验收证据:
|
||||
|
||||
@@ -135,9 +137,9 @@
|
||||
|
||||
关闭前仍需:
|
||||
|
||||
- 完成 TypeTree 字段 reader:bool、integer、float、string、bytes、array、map、PPtr 和 managed reference 诊断占位。
|
||||
- 支持 MonoBehaviour、ScriptableObject 字段级遍历,形成可扩展文本提取入口。
|
||||
- 输出可追溯文本定位:bundle path、archive entry、serialized file、path id、class id、field path。
|
||||
- 冻结解除前不继续扩大 TypeTree 字段 reader 覆盖。当前 TypeTree-covered managed reference 字段与 registry 记录已可结构化解码,`m_ManagedReferences`、`RefIds` / `m_RefIds`、verbose type 字段、`managedReference*` / `serializedReference*` metadata、payload/value/object 家族、`managedReferenceData` / `referenceData` / `serializedData` / `serializedReferenceData` payload、多记录 registry 聚合、enum `value__` backing field、`LayerMask` / `BitField` 的 `m_Bits` backing field、固定 Unity float/int/hash 值类型 leaf/direct-child 形态、unknown fixed-size raw bytes 同长度替换、嵌套 vector `Array` 形态、`List<T>` / `HashSet<T>` 集合 alias、`first/second` 与 `key/value` map entry schema、空 array/vector/List/HashSet/map 扩容已有合成 fixture 覆盖;剩余真实版本差异、unknown 字段结构语义、更多 nested collection、managed reference registry / map entry 变体只记录为冻结后的工作。
|
||||
- 用真实 fixture 继续覆盖 MonoBehaviour、ScriptableObject 字段级遍历和字符串策略。
|
||||
- 输出可追溯文本定位:bundle path、archive entry、serialized file、path id、class id、field path、字段 offset/byte size。
|
||||
- 用真实资源 fixture 覆盖对象级解析、TextAsset 提取和字段级文本提取。
|
||||
- 将解析结果作为 Patch 输入;真正的重打包、Patch 生成和 `localized` 发布切换归 G-006/G-011D。
|
||||
|
||||
@@ -145,23 +147,34 @@
|
||||
|
||||
- 见 `docs/architecture/assetbundle.md` 的 P2/P3/P5。
|
||||
|
||||
### G-006:Patch 引擎仍是占位
|
||||
### G-006:Patch 引擎基础已落地,发布入口仍未完成
|
||||
|
||||
现象:
|
||||
状态:**部分关闭**
|
||||
|
||||
- `binary::apply_patch` 明确返回 `PatchError::ApplyFailed`,提示 Binary patch 尚未实现。
|
||||
- `json::apply_json_patch` 明确返回 `PatchError::ApplyFailed`,提示 JSON patch 尚未实现。
|
||||
已完成:
|
||||
|
||||
- `bat-patch::binary` 已提供确定性 Binary hunk diff/apply,应用前校验 source size/BLAKE3,应用后校验 target size/BLAKE3。
|
||||
- `bat-patch::json` 已提供 RFC 6902 JSON Patch apply,覆盖 add/remove/replace/move/copy/test 和 JSON Pointer escape。
|
||||
- `bat-patch::text` 已提供 UTF-8 Text Patch,按 source-relative byte range 替换,支持 expected 文本校验、UTF-8 边界校验、source/target BLAKE3 和 size 校验。
|
||||
- `bat-patch::manifest` 已定义通用 Patch manifest、文件级 patch kind、source/target BLAKE3、size、rollback 元数据和 manifest 文件完整性校验。
|
||||
- `LocalizedPatchManifest` 可转换为通用 `bat_patch::PatchManifest`,UnityFS TextAsset 发布链路和通用 Patch manifest 已有类型对齐点。
|
||||
- `infrastructure::patch_ops`、`patch.apply` RPC 和 `patch-apply` CLI 已开放文件级 Binary/JSON/Text patch apply;输入/输出为显式文件路径,输出原子写入并返回 size/BLAKE3。
|
||||
- `unityfs.patch_text_asset` / `unityfs.patch_string_field` / `unityfs.patch_field` RPC 和 `unityfs-patch-text-asset` / `unityfs-patch-string-field` / `unityfs-patch-field` CLI 已开放显式 UnityFS bundle 文件写入;TextAsset、TypeTree string 字段、managed-reference registry `data` / `managedReferenceData` payload 字符串、基础语义字段、enum、bit_field、固定 Unity 值类型 leaf/direct-child 形态、unknown fixed-size raw bytes、object 字段组合和 TypeTree schema 支撑的 array/vector/List/HashSet/map 整体替换会在重建后重新解析校验。
|
||||
|
||||
影响:
|
||||
|
||||
- 无法生成或应用补丁。
|
||||
- 回滚和完整性校验无法落地。
|
||||
- 通用 Binary/JSON/Text Patch crate 能力可作为后续发布流程输入。
|
||||
- 文件级写入入口可用于隔离测试和上层工具显式产物生成。
|
||||
- 发布级 `patch build` / `patch rollback`、复杂 AssetBundle 重打包和通用 manifest 在发布命令中的正式使用仍未完成。
|
||||
|
||||
验收:
|
||||
|
||||
- Binary patch 能完成 diff/apply 往返。
|
||||
- JSON patch 能应用 RFC 6902 patch。
|
||||
- Patch manifest 包含 hash、版本和回滚信息。
|
||||
- Patch 构建/应用必须写 staging,完整性校验通过后才能发布。
|
||||
- `patch.apply` / `patch-apply` 对显式文件执行 apply 时必须原子写目标文件,并返回 source/patch/target hash 与 size。
|
||||
- 失败时不得影响 `bat-resources/current` 或已发布 `bat-localized/current`。
|
||||
|
||||
### G-007:Addressables Catalog 解析不完整
|
||||
|
||||
@@ -204,33 +217,41 @@
|
||||
- **正式同步/运维命令行 = Rust `bat`**(近乎全自动:auto-discover + watch/daemon,无需持久手操维护)。
|
||||
- **不另做**产品级 Go 同步 CLI,避免与 Rust `bat` 双轨。
|
||||
- Go 试验入口 `cmd/bat` 可保留为 experimental,产物必须为 `bin/bat-go`,**禁止**再构建为 `bin/bat`。
|
||||
- Go 正式产品入口集中在 **`bat-api` 资源分发服务** + `internal/backendrpc`(G-009)。
|
||||
- Go 正式产品入口集中在 **`bat-api` 资源 bootstrap/分发服务** + `internal/backendrpc`(G-009)。
|
||||
|
||||
原验收(真实 doctor / Go sync 包装)**不再作为当前里程碑**。
|
||||
|
||||
### G-009:API Server(`bat-api`,资源分发)部分完成
|
||||
### G-009:API Server(`bat-api`,资源 bootstrap/分发)部分完成
|
||||
|
||||
状态:**资源 CDN MVP 已落地;非完整官方游戏 API**
|
||||
状态:**资源 bootstrap + CDN MVP 已落地;非完整官方游戏 API**
|
||||
|
||||
目标(对应 issue #19,**按资源面收窄**):
|
||||
|
||||
- `cmd/bat-api`:只读分发 Rust `bat` 已发布 release(官方 CDN host/path 形态)。
|
||||
- `cmd/bat-api`:组织 Rust `bat` 已发布 release 的启动前资源入口,并只读分发官方 CDN host/path 形态资源。
|
||||
- **拉取归属 Rust `bat`**;`bat-api` 不做下载器。
|
||||
- 发现经 `bat.sock`:先 `daemon.status`,再 `daemon.doctor`,再 `catalog.status` / `resource.manifest`。
|
||||
- `.env` 配置端口 / public base / RPC socket;预留 database/redis。
|
||||
- launcher 全链、完整业务 API **非关闭条件**;USERGUIDE bat-api 专章延后。
|
||||
- 生产与 Rust `bat` 同环境运行,资源根来自 RPC 返回的 `resource_root`;`--resource-root` 仅用于 fixture 或应急只读诊断。
|
||||
- `.env` 配置端口 / public base / RPC socket / RPC 刷新周期;预留 database/redis。
|
||||
- `/v1/bootstrap` 返回 RPC 健康、release 摘要、server-info URL、client-patch base 和改写后的 Addressables root。
|
||||
- `/v1/launcher/bootstrap` 和 `/api/launcher/...` 形状端点返回资源引导兼容信息,当前来源是 Rust `bat` 已发布 snapshot/RPC 中的 launcher metadata 与 GameMainConfig 摘要;Rust 侧已新增 release 内 `official-launcher-bootstrap.json` 版本化产物,后续 bat-api 字段统一和联调应以该产物加 RPC contract fixture 为准。
|
||||
- `/healthz` 暴露最近一次 RPC refresh 诊断;`/readyz` 在无可分发 release 时返回 `503`。
|
||||
- 玩家-facing HTTP 控制面必须支持 token 鉴权、限流、访问日志、反代 IP 适配、动态 JSON `no-store` 和 `/v1/resources` 分页上限。
|
||||
- CDN path 支持 `GET` / `HEAD` / `Range`、ETag、Last-Modified、Accept-Ranges 和长期缓存头。
|
||||
- launcher 完整安装包更新链、账号、登录、网关、游戏业务 API 和鉴权全链 **非关闭条件**;USERGUIDE 已补基础章节,联调后补生产排障样例。
|
||||
|
||||
已完成:
|
||||
|
||||
- `cmd/bat-api`、`internal/api`、fixture 单测、`make build-go-api` / `test-go-api`
|
||||
- `cmd/bat-api`、`internal/api`、`/v1/bootstrap`、`/v1/launcher/bootstrap`、launcher 资源 metadata 兼容端点、HTTP token 鉴权、限流、访问日志、反代 IP 适配、动态 JSON `no-store`、`/v1/resources` 分页上限、OpenAPI、`/admin/` 预留、RPC 周期刷新/诊断、`/readyz`、CDN Range/缓存头、fixture 单测、USERGUIDE 基础章节、systemd bat-api 模板、`make build-go-api` / `test-go-api`
|
||||
- 进度权威:`docs/reports/GO_STATUS.md`
|
||||
|
||||
验收(剩余):
|
||||
|
||||
- 与全量 release / 服务器 daemon 联调(SSH 实勘可后置)
|
||||
- 与远程长期运行的 `bat` / 全量 release 联调(覆盖 bootstrap、server-info、CDN path;SSH 实勘可后置)
|
||||
- Rust snapshot schema 与 Go mirror struct 的跨语言 contract fixture(需要用户审核后落入 fixture)
|
||||
- refresh 中 manifest 磁盘校验的 mtime/size 增量缓存优化(真实全量 release 观测后决定)
|
||||
- 文档与 GO_STATUS 持续一致
|
||||
|
||||
排期:P2 主体可联调;持久化 API 层与 launcher 另议。
|
||||
排期:P2 主体可联调;持久化 API 层与完整 launcher/业务链另议。
|
||||
|
||||
### G-010:Web 管理后台尚未实现
|
||||
|
||||
@@ -250,7 +271,7 @@
|
||||
|
||||
## 4. 数据与翻译缺口
|
||||
|
||||
### G-011:Resource Repository 未持久化
|
||||
### G-011:Resource Repository 查询面仍不完整
|
||||
|
||||
状态:**部分关闭**
|
||||
|
||||
@@ -258,15 +279,23 @@
|
||||
|
||||
- `SqliteResourceRepository` 已存在,可按领域 repository 接口保存资源元数据。
|
||||
- `ResourceImportService` 已能把 manifest 中有数据的资源写入 CAS + `ResourceRepository`,AssetBundle 会记录 UnityFS 摘要,TextAsset/Table/Media 会分类索引。
|
||||
- 官方同步下载结果尚未作为用户级流程自动触发导入 CAS + ResourceRepository。
|
||||
- 迁移、版本化 schema 和 CLI 查询入口仍需补齐。
|
||||
- 官方同步下载结果可用 `--import-repository` / `BAT_IMPORT_REPOSITORY=1` 在已校验 release 发布后自动导入 CAS + ResourceRepository;默认 CAS 为 `<output>/.cas`,默认 SQLite 索引为 `<output>/resources.sqlite`,也可通过 `--import-cas-root`、`--import-resource-db`、`BAT_IMPORT_CAS_ROOT`、`BAT_IMPORT_RESOURCE_DB` 覆盖。
|
||||
- `resource.index` RPC 已能按资源类型、hash、路径模式分页查询现有 SQLite 索引;数据库不存在时返回 `available=false`,不会因查询创建空库。
|
||||
- 官方 release 发布后会写出 `official-resource-changes.json` 和 `crowdin-translation-handoff.json`,新增+变更资源进入解析/翻译 handoff,删除资源只进入差异记录。
|
||||
- `Resource` metadata 已通过 SQLite `metadata_json` 兼容迁移保存 release、平台、bundle path、parse status、TextAsset 名称和 TextUnit 数量/格式;`resource.index` 会返回这些 metadata。
|
||||
- 官方 release 发布后会持久化 `official-textunit-index.json`,记录单条 TextUnit 和解析错误;`parse.text_units` / `parse.errors` RPC 和 `parse-text-units` / `parse-errors` CLI 可按 destination、archive entry、path id、class id、field path 和 format 分页过滤。
|
||||
- 官方 release 发布后会从 Added/Modified 资源、parse cache 和 TextUnit 明细索引派生 `official-textunit-tasks.json` 和 `crowdin-textunit-queue.json`;删除资源不会进入队列。
|
||||
- 翻译任务状态和 Crowdin worker 失败原因查询仍需补齐。
|
||||
|
||||
验收:
|
||||
|
||||
- schema 和迁移可重复执行。
|
||||
- 可按版本、类型、hash、路径查询资源。
|
||||
- 官方同步后的资源可通过 CLI 查询并能追溯到 CAS 对象。
|
||||
- `official-parse-cache.json` 的 bundle、zip entry、TextAsset 摘要能进入 ResourceRepository 查询面。
|
||||
- 可按版本、类型、hash、路径查询资源,且能明确区分索引缺失、版本缺失和空结果。
|
||||
- 官方同步后的资源可通过 CLI/RPC 查询并能追溯到 CAS 对象。
|
||||
- `official-parse-cache.json` 的 bundle、zip entry、TextAsset 和 TextUnit 摘要能进入 ResourceRepository 查询面。
|
||||
- `parse.status` 能报告 TextUnit 索引、TextUnit 队列路径与摘要。
|
||||
- `parse.text_units` / `parse.errors` 能分页查询当前 release 的 TextUnit 明细和解析错误。
|
||||
- Crowdin handoff 被后续翻译 worker 消费后,任务状态和失败原因能反查到对应官方 release 与资源 destination。
|
||||
|
||||
解析补全路线图:
|
||||
|
||||
@@ -319,27 +348,29 @@
|
||||
|
||||
### G-011D:汉化发布状态与 Patch 发布流程未完成
|
||||
|
||||
状态:**新建,未关闭**
|
||||
状态:**部分关闭**
|
||||
|
||||
当前已完成:
|
||||
|
||||
- 官方原版资源发布根为 `./bat-resources`,汉化产物发布根为 `./bat-localized`。
|
||||
- CLI 支持 `--localized-output` / `BAT_LOCALIZED_OUTPUT`,并拒绝官方目录和汉化目录相同或互相嵌套。
|
||||
- 官方同步报告新增 `localized_release_status=not_localized`,明确表示原版资源已发布、汉化资源未发布。
|
||||
- `LocalizedPatchService` 已具备将给定汉化文件按官方相对路径发布到 `--localized-output` / `BAT_LOCALIZED_OUTPUT` 指定目录下的 `.staging/<id>`、校验后移动到 `versions/<id>`、原子切换 `current` 并写入 `localized-version-state.json` 的基础能力。
|
||||
- `LocalizedPatchService` 已写入结构化 `localized-patch-manifest.json`,记录 TextAsset 操作、原始/汉化 hash、size、byte delta 和 rollback 信息;发布前后会校验 manifest hash/size 与 current symlink,失败时清理 staging / 未完成 version。
|
||||
- `localized.status` RPC 会读取 `.env` / daemon 配置中的汉化输出目录,校验汉化状态是否匹配当前官方 release,且要求 patch manifest 存在并匹配 release,避免写死 `./bat-localized` 或误报手工状态。
|
||||
|
||||
仍未完成:
|
||||
|
||||
- Patch 发布阶段尚未生成 `localized-output/versions/<id>`。
|
||||
- 尚未维护 `localized-output/current` 原子指针和汉化版本状态文件。
|
||||
- 尚未实现 `localized` 状态切换、回滚和汉化产物完整性校验。
|
||||
- 真实 Patch/翻译构建阶段尚未从 `crowdin-textunit-queue.json`、翻译记忆和 Crowdin 结果生成完整汉化文件集合。
|
||||
- 通用 Binary/JSON/Text Patch crate 基础和文件级 `patch.apply` / UnityFS 写入入口已经实现;复杂 AssetBundle 重打包、发布级 patch build/rollback 和与汉化发布流程的统一仍未完成。
|
||||
- 尚未实现原版资源与汉化资源双发布后的查询、分发和清理策略。
|
||||
|
||||
验收:
|
||||
|
||||
- 原版资源同步成功后保持 `not_localized`,不发布半成品汉化资源。
|
||||
- Patch 构建和校验成功后,汉化产物按官方相对路径写入 `localized-output/versions/<id>`。
|
||||
- 汉化发布必须原子切换 `localized-output/current`,失败时不影响已发布原版资源。
|
||||
- `localized` 状态能证明原版和汉化两套资源都可发布,并能被 CLI/RPC/API 查询。
|
||||
- Patch 构建和校验成功后,汉化产物按官方相对路径写入配置化汉化发布根下的 `versions/<id>`。
|
||||
- 汉化发布必须原子切换配置化汉化发布根下的 `current`,失败时不影响已发布原版资源。
|
||||
- `localized` 状态能证明原版和汉化两套资源都可发布,并能被 CLI/RPC/API 查询;缺 patch manifest 或 release 不匹配时不得返回 `localized`。
|
||||
|
||||
### G-011C:真实 fixture 与回归样本不足
|
||||
|
||||
@@ -518,14 +549,14 @@
|
||||
## 6. 当前关闭顺序建议
|
||||
|
||||
1. issue #24:失败 staging 复用回归已补;核对残余场景。
|
||||
2. issue #1:RPC 主体已落地;剩余 `patch.*` / `unityfs.*`、设计边界确认。
|
||||
2. issue #1:RPC 主体、文件级 `patch.apply` / `unityfs.patch_text_asset` / `unityfs.patch_string_field` / `unityfs.patch_field` 已落地;剩余发布级 patch build/rollback、复杂 UnityFS 语义编辑与设计边界确认。
|
||||
3. issue #17 及子 issue:已按 wontfix 关闭多线程下载(顺序下载 + 指数退避)。
|
||||
4. **G-008:已决策关闭**(同步 CLI = Rust `bat`;见 `GO_STATUS.md`)。
|
||||
5. **G-009 / issue #19**:资源分发 MVP 已编码;优先服务器联调与索引实勘,非「从零实现」。
|
||||
5. **G-009 / issue #19**:资源 bootstrap/分发 MVP 已编码;优先服务器联调与索引实勘,非「从零实现」。
|
||||
6. issue #2 / G-007(P1):Addressables 可校验字段。
|
||||
7. issue #3 / G-005(P1):UnityFS 容器基础解析已落地;对象级引擎解析继续跟踪 G-005。
|
||||
8. G-011:官方同步结果接入 CAS + ResourceRepository 用户级工作流。
|
||||
9. G-011D / G-006:汉化发布状态持久化、Patch 发布和回滚。
|
||||
10. G-012 / G-006:翻译系统、Patch 引擎。
|
||||
8. G-011:翻译任务状态、CAS 诊断和 ResourceRepository 查询面扩展。
|
||||
9. G-012 / G-006:Crowdin/翻译系统、复杂 AssetBundle 重打包和 Patch 发布流程统一。
|
||||
10. G-011D:原版/汉化双发布后的查询、分发和清理策略。
|
||||
|
||||
Go 进度以 `docs/reports/GO_STATUS.md` 为准。G-018 / G-017 已关闭。
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
# 解析模块维护冻结
|
||||
|
||||
状态:**生效中**
|
||||
|
||||
生效时间:2026-07-30
|
||||
|
||||
冻结目标:停止继续扩大 UnityFS / AssetBundle / Addressables / TypeTree 解析能力,把当前工作重心切换到运行稳定性、代码审核问题、文档一致性和发布链路可靠性。
|
||||
|
||||
## 冻结范围
|
||||
|
||||
冻结覆盖以下 Rust 解析相关模块和对外入口:
|
||||
|
||||
- `crates/bat-assetbundle`
|
||||
- `adapters/src/unity*`
|
||||
- `infrastructure/src/official_parse.rs`
|
||||
- `infrastructure/src/resources.rs` 中解析缓存、TextUnit 索引和解析状态相关逻辑
|
||||
- `unityfs.*`、`parse.*`、`text.*` 相关 RPC / CLI 契约
|
||||
- Addressables catalog、UnityFS、serialized file、TypeTree、TextUnit、AssetBundle patch 相关文档声明
|
||||
|
||||
## 允许变更
|
||||
|
||||
冻结期只允许以下解析相关变更:
|
||||
|
||||
- 修复编译失败、格式化失败、clippy 报错和测试失败。
|
||||
- 修复真实运行中已经复现的 panic、错误状态污染、重复解析、缓存失效、状态不一致或诊断误导。
|
||||
- 补充回归测试,前提是测试覆盖的是已存在能力的稳定性问题,不宣称新增解析能力。
|
||||
- 修正文档、CLI 帮助、RPC 参考和状态文件中与当前实现不一致的解析能力声明。
|
||||
- 改善错误信息、日志字段、状态记录和失败恢复,但不得改变解析输出契约,除非是修复错误契约且同步迁移说明。
|
||||
|
||||
## 禁止变更
|
||||
|
||||
冻结期禁止以下解析相关变更:
|
||||
|
||||
- 新增 TypeTree 语义类型、字段族、managed reference 变体、Unity 内建结构体覆盖或 Addressables catalog 结构覆盖。
|
||||
- 用纯合成 fixture 推进“完整解析”并把它记录为已支持能力。
|
||||
- 开放新的写入型 `unityfs.*` / `patch.*` RPC 或 CLI。
|
||||
- 修改解析结果 schema、TextUnit schema、patch field JSON 语义或缓存状态格式,除非它是阻断级 bug 修复并附带兼容策略。
|
||||
- 将解析器和官方同步、汉化发布、Go API、Crowdin 或客户端流程进一步耦合。
|
||||
|
||||
## 解冻条件
|
||||
|
||||
解析扩展重新启动前必须同时满足:
|
||||
|
||||
- Rust `bat` 官方同步、daemon、status、校验、断点续传、增量更新和解析缓存链路稳定。
|
||||
- 当前 P0/P1 维护 issue 已关闭或被明确降级。
|
||||
- `bat-api` 与 Rust RPC / CLI 契约完成字段统一和联调验证。
|
||||
- 真实资源 fixture、验证命令和验收标准已写入文档,不能只依赖合成样本。
|
||||
|
||||
## 冻结期验证
|
||||
|
||||
解析相关维护变更至少运行:
|
||||
|
||||
```bash
|
||||
cargo fmt --check
|
||||
cargo test -p bat-assetbundle --locked
|
||||
cargo clippy -p bat-assetbundle --all-targets --locked -- -D warnings
|
||||
```
|
||||
|
||||
如果变更影响 `bat` CLI、RPC、官方解析缓存或 TextUnit 索引,还必须补充对应 `bat-infrastructure` 测试或说明未运行原因。
|
||||
Reference in New Issue
Block a user