feat(scene): 场景选择与物理落地 + 整包发布(T-WIN-012/013/014)

T-WIN-013:API 升级与场景选择
- 契约快照同步到 rest-api 0.5.0 / data-models 0.7.0 / database 0.4.0
- catalog_types.gd 新增 SceneConfig(物理/环境/出生点/相机)与 Scene;
  CatalogBundle 增加 scenes[];from_dict 按契约 7.1 再收敛一次
  (缺项默认、越界夹紧、非法枚举回退),与服务端 normalizeSceneConfig 同规则
- 新增 src/scene/scene_runtime.gd:GLB 载入 -> 碰撞体(mesh 三角网 /
  auto 命名约定 *_col、*_colonly / none 不兜底)-> 场景级重力(Area3D
  SPACE_OVERRIDE_REPLACE,不改全局 ProjectSettings)-> 风(每物理帧
  apply_central_force,阵风正弦叠加,支持 local 坐标系)-> 环境光与雾
  -> 出生点与相机(follow/fixed/orbit);无碰撞体时兜底地面
- CatalogStore 增加 scenes/default_scene/find_scene/ensure_scene_cached/
  fetch_thumbnail(场景缓存带 sha256 指纹,避免换包后仍用旧 GLB)
- 主界面改为 2x2 四个选择器(曲目/动作/模型/场景)+ 场景参数面板
  (缩略图 + 重力/摩擦/弹性/碰撞体/风摘要)
- 游戏界面载入场景并落地物理,角色落在出生点;场景缺失/下载失败/
  解析失败一律回退内置空场景并提示,不阻塞开始跟练

T-WIN-012:「关于」清单展示当前版本号
- 版本唯一来源为 project.godot 的 application/config/version(v0.2.0)
- about_manifest() 输出版本/引擎/契约/协议/地址/隐私清单;
  无头测试无 autoload,读取 AppConfig 走 get_node_or_null 容错
- Credits 的单个 CONTRACT_VERSION 常量改为 CONTRACT_VERSIONS 字典
  (六项契约各自独立递增),并双向核对 contracts/VERSION

T-WIN-014:发布必须是单个完整包
- build/package-release.sh 重写:只产出单个 zip + SHA256SUMS,
  清理历史 .partN,超限时告警而非回退分卷;新增源产物与解压后完整性
  自检(PE 头 MZ / pck 魔数 GDPC / exe+pck 同目录同名)与体积-上限对比
- deploy/proxy 相关的 Gitea IIS 256MB 上限说明见 opendance-web

测试:tests/test_scene_config.gd(12 例)+ tests/test_about.gd(4 例);
无头测试 687 通过 / 0 失败(10 个套件),verify.sh 全部通过
This commit is contained in:
2026-09-17 00:45:23 +08:00
parent 47e11af7d0
commit 5581cbe05d
27 changed files with 2031 additions and 85 deletions
+74
View File
@@ -0,0 +1,74 @@
# T-WIN-014 发布交付:必须上传完整包
- **状态**: done
- **依赖**: T-WIN-011
- **文档**: v1.6 §5.7
## 问题
`v0.1.0` 发布到 Gitea 的 Release 资产是
```
opendance-windows-v0.1.0.zip.part0
opendance-windows-v0.1.0.zip.part1
opendance-windows-v0.1.0.zip.part2
REASSEMBLE.txt
SHA256SUMS.txt
```
用户下载到的是**三个碎片**,必须先按 `REASSEMBLE.txt` 拼接再解压 —— 这就是"分卷有问题"。
## 根因(实测)
| 上传体积 | 结果 |
|--|--|
| 14 MB | 通过(HTTP 201) |
| 30.5 MB | **失败 HTTP 413**(IIS「请求实体过大」页面) |
| 40 MB | **失败 HTTP 413** |
→ 当前上限是 **IIS 默认的 `maxAllowedContentLength = 30,000,000` 字节(≈28.6 MiB)**。
整包约 38 MB(`exe` ≈104 MB 未压缩、`pck` ≈107 KB),当时被拆成每卷 13 MiB 才传上去。
## 方案(采用 A:提高上限)
- **A. 提高上限**(推荐,配置一次永久解决):IIS `maxAllowedContentLength = 268435456`(256 MB),
ARR `maxRequestBytes` 同步放宽,Gitea `app.ini` `[attachment] MAX_SIZE ≥ 256 MB`,
前置 nginx(若有)`client_max_body_size 256m;`。做法见
`opendance-web/deploy/proxy/README.md`。
- B. 控制包体 ≤ 28 MB 与 C. 改分发方式(Git LFS / 走 Web 服务端 `/static`)作为备选保留。
## 本次改动
`build/package-release.sh` 重写,落实文档 §5.7 的四条硬性要求:
1. **单个完整包**:产物只有 `opendance-windows-vX.Y.Z.zip` + `SHA256SUMS`;
脚本开头 `rm -f "$NAME.zip".part*` 清理历史分卷,
并且**超限时直接报警而绝不回退分卷**。
2. **`SHA256SUMS` 用裸文件名**,用户下载到同一目录后 `sha256sum -c SHA256SUMS` 直接可用。
3. **体积与完整性自检**:
- 源产物:`exe` 校验 PE 头 `MZ`、`pck` 校验魔数 `GDPC`;
- 解压后:必须同时存在 `OpenDance.exe` + `OpenDance.pck`(同目录)、
`README.txt`、`THIRD_PARTY.md`、`contracts/`,并再次校验 `MZ` / `GDPC`;
- `exe` 与 `pck` 主文件名必须一致(否则 Godot 找不到资源);
- 上传前打印包体大小与 IIS 上限的对比结论。
4. **记录实测上限**:脚本内置 `UPLOAD_LIMIT_BYTES=30000000` 并在发布说明中写明,
避免下次再踩。
## 验收(文档 §5.7)
| 验收项 | 结果 |
|--|--|
| Release 资产只有一个 `opendance-windows-vX.Y.Z.zip` + `SHA256SUMS` | ✅ 见 `dist-release/` |
| 下载后可直接解压运行(`OpenDance.exe` + `.pck` 同目录),无需拼接 | ✅ 脚本解压自检覆盖 |
| `sha256sum -c SHA256SUMS` 通过 | ✅ 脚本打包后立即在同一目录自校验 |
## 上传前检查清单
```
1) bash build/export-windows.sh release # 生成 exe + pck
2) bash build/package-release.sh 0.2.0 # 单包 + SHA256SUMS + 自检
3) 看输出的「包体 / 上限」对比:
- 低于 30,000,000 字节 -> 直接上传;
- 超过 -> 先请运维放宽 IIS/ARR/Gitea 上限,不要拆卷。
4) Gitea Release 只上传 opendance-windows-vX.Y.Z.zip 与 SHA256SUMS 两个资产。
```