mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-09-18 07:24:55 +08:00
398 lines
15 KiB
Markdown
398 lines
15 KiB
Markdown
# 开发指南
|
||
|
||
本指南是本地开发流程的权威入口。贡献协作规则见 `../../CONTRIBUTING.md`,AI agent 长期规则见 `../../AGENTS.md`。
|
||
|
||
## 环境准备
|
||
|
||
### 安装依赖
|
||
|
||
#### Go
|
||
```bash
|
||
# 安装 Go 1.22+
|
||
# 参考:https://golang.org/doc/install
|
||
|
||
go version # 验证安装
|
||
```
|
||
|
||
#### Rust
|
||
```bash
|
||
# 安装 Rust 1.75+
|
||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||
|
||
rustc --version # 验证安装
|
||
cargo --version
|
||
```
|
||
|
||
#### 自托管 Gitea runner
|
||
|
||
`.gitea/workflows/bat.yml` 使用 `runs-on: linux`,并且不依赖 `actions/checkout`、`dtolnay/rust-toolchain` 等外部 GitHub Action。runner 需要在执行环境中预装以下命令:
|
||
|
||
```bash
|
||
git --version
|
||
rustc --version
|
||
cargo --version
|
||
rustfmt --version
|
||
cargo clippy --version
|
||
go version
|
||
```
|
||
|
||
该 workflow 会用 `GITHUB_SERVER_URL`、`GITHUB_REPOSITORY`、`GITHUB_REF` 和 `GITHUB_SHA` 手动 `git fetch` 当前提交,再执行 Rust workspace 的格式化、检查、构建、clippy 和测试,以及 Go API 门禁和文档状态门禁。这样可以避免自托管 runner 在准备阶段通过代理克隆第三方 action 仓库。
|
||
|
||
#### Docker
|
||
```bash
|
||
# 安装 Docker 和 Docker Compose
|
||
# 参考:https://docs.docker.com/get-docker/
|
||
|
||
docker --version
|
||
docker compose version
|
||
```
|
||
|
||
---
|
||
|
||
## 项目结构
|
||
|
||
请参考 [架构文档](../architecture/README.md) 了解完整的项目结构。
|
||
|
||
---
|
||
|
||
## 开发工作流
|
||
|
||
### 1. 创建功能分支
|
||
|
||
```bash
|
||
git checkout -b feature/your-feature-name
|
||
```
|
||
|
||
### 2. 开发
|
||
|
||
```bash
|
||
# 实时编译检查
|
||
make check
|
||
|
||
# 运行测试
|
||
make test
|
||
|
||
# 格式化代码
|
||
make fmt
|
||
```
|
||
|
||
开发约束:
|
||
|
||
1. 先阅读相关文档和代码,再判断实现方式。
|
||
2. 跨模块、架构、数据格式或用户工作流变更必须先说明设计取舍。
|
||
3. 保持改动聚焦,不做无关重构、批量格式化或元数据 churn。
|
||
4. 公共接口、状态文件、manifest、catalog、patch 和下载流程变更必须补充测试或 fixture。
|
||
5. 用户可见命令、运行路径、配置、状态文件、日志或缺口状态变化时,同步更新 README、指南、架构文档或 `docs/reports/CURRENT_GAPS.md`。
|
||
|
||
### 3. 提交
|
||
|
||
```bash
|
||
git add .
|
||
git commit -m "feat(cli): 添加 doctor 命令骨架"
|
||
```
|
||
|
||
提交信息遵循 [Conventional Commits](https://www.conventionalcommits.org/) 规范:
|
||
- 必须使用 `type(scope): 中文说明` 格式。
|
||
- `type` 使用 `feat`、`fix`、`docs`、`style`、`refactor`、`test`、`chore` 等 Conventional Commits 类型。
|
||
- `scope` 必须写具体模块或文档域,例如 `ffi`、`docs`、`cli`、`cas`、`official-sync`。
|
||
- 提交标题和正文默认使用简体中文;代码标识符、协议字段和命令参数仍保持英文。
|
||
|
||
示例:
|
||
|
||
- `feat(cli): 添加 doctor 命令骨架`
|
||
- `fix(docs): 修正官方同步运行说明`
|
||
- `refactor(ffi): 降级 FFI 为可选兼容层`
|
||
|
||
### 4. 推送和 PR
|
||
|
||
```bash
|
||
git push origin feature/your-feature-name
|
||
# 然后在 GitHub 创建 Pull Request
|
||
```
|
||
|
||
---
|
||
|
||
## 代码规范
|
||
|
||
默认使用简体中文写文档、提交说明、开发日志和面向用户的说明。代码标识符、协议字段、数据库字段、包名和命令参数保持英文命名规范。
|
||
|
||
禁止使用 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` 格式化
|
||
- 使用 `golangci-lint` 进行静态检查
|
||
|
||
### Rust
|
||
- 遵循 [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/)
|
||
- 使用 `cargo fmt` 格式化
|
||
- 使用 `cargo clippy` 进行静态检查
|
||
|
||
### TypeScript
|
||
- 遵循 [TypeScript Style Guide](https://google.github.io/styleguide/tsguide.html)
|
||
- 使用 ESLint 和 Prettier
|
||
|
||
---
|
||
|
||
## 测试
|
||
|
||
### 合并前通用门禁
|
||
|
||
```bash
|
||
cargo fmt --check
|
||
cargo test --workspace
|
||
cargo clippy --workspace --all-targets -- -D warnings
|
||
make test-go-api
|
||
make build-go-api
|
||
go vet ./internal/api/... ./internal/backendrpc/... ./cmd/bat-api/...
|
||
make check-docs
|
||
```
|
||
|
||
Go 边界与进度以 `docs/reports/GO_STATUS.md` 为准:
|
||
|
||
- **同步/运维命令行** = Rust `bat`(近乎全自动)
|
||
- **资源 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
|
||
```
|
||
|
||
官方资源同步、下载、daemon、status、verify 或 repair 相关改动必须至少覆盖 `bat-infrastructure` 和 `bat` 二进制测试。
|
||
|
||
`bat-ffi` 只是可选无状态 C ABI 兼容层。修改 FFI 时必须运行 `cargo test -p bat-ffi -- --nocapture`。Go 服务层默认经 `internal/backendrpc` 调 daemon;同步任务由 Rust `bat` 执行,不由 Go 试验 CLI 承担。
|
||
|
||
### 集成测试
|
||
|
||
```bash
|
||
cargo test --workspace
|
||
```
|
||
|
||
带真实本地资源的测试默认不应启用。只有在明确需要时,才通过对应 `BAT_REAL_*` 环境变量读取隔离样本路径。不要默认读取 `/home/wanye/D/BlueArchive` 或任何已有客户端目录。
|
||
|
||
### 官方资源同步手动检查
|
||
|
||
查看参数:
|
||
|
||
```bash
|
||
cargo run -p bat-infrastructure --bin bat -- --help
|
||
```
|
||
|
||
dry-run:
|
||
|
||
```bash
|
||
cargo run -p bat-infrastructure --bin bat -- \
|
||
--auto-discover \
|
||
--dry-run
|
||
```
|
||
|
||
开发环境真实官方资源下载默认写入 `./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`、
|
||
`translation-tasks.sqlite` 和 `translation-handoff.json`。本地已有旧完整
|
||
版本时,新版本发布后会先按 manifest destination 对比旧/新 release,只把新增和
|
||
内容变更的资源写入解析与 Crowdin handoff;删除资源只记录差异,不进入翻译队列。
|
||
up-to-date 轮询发现本地文件、解析缓存、TextUnit 明细索引和 TextUnit 队列未变时不会重复解析。
|
||
Crowdin 队列当前只落本地文件,不发网络请求。
|
||
|
||
官方下载服务默认使用 8 个有界 worker,`--download-concurrency` /
|
||
`BAT_DOWNLOAD_CONCURRENCY` 只接受 `1..=256`。worker 完成一个 URL 后立即从共享
|
||
队列领取下一个任务;finished 进度按实际完成顺序即时上报,完成计数单调递增,
|
||
最终 report 的资源列表仍按 pull plan 顺序。需要验证顺序模式时显式使用
|
||
`--download-concurrency 1`。本文档中的真实资源命令仅是隔离 runbook;本地轻量
|
||
验证应使用 fake-curl/fixture,不要在开发机执行真实下载或 smoke run。
|
||
|
||
需要把已校验官方 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 -- translation-tasks --task-status skipped_parse_failed --has-reason --limit 50
|
||
cargo run -p bat-infrastructure --bin bat -- translation-tasks --worker-status failed --has-failure-reason --limit 50
|
||
cargo run -p bat-infrastructure --bin bat -- translation-handoff
|
||
cargo run -p bat-infrastructure --bin bat -- localized-status
|
||
cargo run -p bat-infrastructure --bin bat -- resource-index --limit 50
|
||
cargo run -p bat-infrastructure --bin bat -- resource-index --release-id <ID> --platform windows --archive-entry <PATH> --format json --limit 50
|
||
```
|
||
|
||
`parse-status` 会额外显示 TextUnit 明细索引和队列摘要;`parse-text-units` /
|
||
`parse-errors` 可按 destination、archive entry、path id、class id、field path
|
||
和 format 分页查询当前官方 release 的 TextUnit 明细与解析错误;
|
||
`translation-tasks` 可按 release、destination、archive entry、队列任务状态、provider
|
||
worker 状态、parse status、TextUnit format、队列 reason 和 provider failure reason
|
||
查询离线 TextUnit 翻译任务状态与跳过/失败原因;发布后的状态保存在当前 release
|
||
根目录的 `translation-tasks.sqlite`,旧 release 没有状态库时回退到 JSON 队列;
|
||
`translation-handoff` / `translation.handoff` 会动态合并版本化
|
||
`translation-handoff.json` 与 SQLite 状态,返回 job、unit、provider run 的完整交接
|
||
视图;
|
||
`resource-index` 返回的资源 JSON 包含 release、平台、bundle path、TextAsset 和 TextUnit metadata,
|
||
并可按 release、平台、destination、bundle path、archive entry、parse status 和 TextUnit format 做资源级过滤;
|
||
`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 或公开更新数据,并将解析结果固化为可验证流程。
|
||
|
||
### 基准测试
|
||
|
||
```bash
|
||
make bench
|
||
```
|
||
|
||
---
|
||
|
||
## 调试
|
||
|
||
### Go
|
||
使用 Delve 调试器:
|
||
```bash
|
||
go install github.com/go-delve/delve/cmd/dlv@latest
|
||
dlv debug ./cmd/bat
|
||
```
|
||
|
||
### Rust
|
||
使用 rust-lldb 或 rust-gdb:
|
||
```bash
|
||
rust-lldb target/debug/bat-cas-engine
|
||
```
|
||
|
||
---
|
||
|
||
## 常见问题
|
||
|
||
### 1. 编译失败
|
||
|
||
确保安装了所有依赖:
|
||
```bash
|
||
go mod download
|
||
cargo fetch
|
||
```
|
||
|
||
### 2. 测试失败
|
||
|
||
先确认失败是否来自真实网络或本地资源路径。默认测试应使用 fixture/mock,不应依赖官方线上资源或开发机已有资源目录。
|
||
|
||
### 3. FFI 兼容层问题
|
||
|
||
`bat-ffi` 不是主集成边界,只用于需要 C ABI 的兼容场景。未来 Go 产品入口集成优先运行 Rust `bat --json` 或调用 daemon RPC。
|
||
|
||
重新构建兼容库:
|
||
```bash
|
||
cd crates/bat-ffi
|
||
cargo build
|
||
```
|
||
|
||
---
|
||
|
||
更多当前状态请查看 [当前状态](../../CURRENT_STATUS.md) 和 [当前缺口清单](../reports/CURRENT_GAPS.md)。
|