feat: ID 映射支持叠加单独导出的数据包,并纳入 event 表

D:/A031OptDump/Root 是比 G:\Package 更新的一层增补(曲目到 12024、宴曲
111537/111765/112002),原来的 --package 只认整合包内的 A??? 目录,套不到它。

- 新增可重复的 --data-root,把一个目录直接当数据根,按传参顺序追加、后者覆盖
  同 ID 行;--package 与 --data-root 可混用。
- 新增 events.json(eventId → 活动名 / alwaysOpen / infoType / disableArea)。
  本地 event 表没有日期窗口,开没开由服务器 GetGameEventApi 的
  GameEvent{startDate,endDate} 决定,README 里写明了这一点,免得误用它判状态。
- 合并两层后:music 1367→1378、map 168→169、title 3000→3001、event 824。
  11820 在两层数据包里都不存在,结论不变。
- lockType 分布按合并后数据更正为 Unlock 1347 / Lock 18 / Challenge 5 /
  Transmission 2 / KaleidScope 6,顺带说明大多数歌 lockType==Unlock、
  本来就可玩,不查 itemKind 5。
This commit is contained in:
Cookiues committed 2026-10-02 01:16:15 +08:00
1 parent 264b1d0aa7
commit 2c7f9c1de7
7 files changed
+6071 -37

No files matched your search

+19 -5
View File
@@ -168,7 +168,11 @@ data/id_mapping/ # 由 tools/gen_id_mapping.dart 从机台数据包抽
「上传成功但没生效」。为此把机台数据包里的表抽成可查的映射:
```bash
# 整合包(自动找 <pkg>/Sinmai_Data/StreamingAssets/A0xx/)
dart run tools/gen_id_mapping.dart --package G:/Package
# 再叠一层单独导出的数据包,后面的覆盖前面的同 ID 行
dart run tools/gen_id_mapping.dart --package G:/Package --data-root D:/A031OptDump/Root
```
产物落在 `data/id_mapping/`:
@@ -179,22 +183,32 @@ dart run tools/gen_id_mapping.dart --package G:/Package
| `items.json` | 按 `ItemKind` 分组(1 姓名框 2 称号 3 头像 9 角色 10 搭档 11 背景板 12 功能票)的 id → 名称 |
| `maps.json` | mapId → 区域名 / `IslandId` / `OpenEventId` / `ColorId` / `BonusMusicId` / `IsInfinity` / `IsCollabo` |
| `gates.json` | 万花筒三张表:`gateList`(gateId → 门名 / `gateType` / `eventName`)、`courseList`(courseId ↔ gateId ↔ keyId)、`keyList` |
| `events.json` | eventId → 活动名 / `alwaysOpen` / `infoType` / `disableArea` |
要点:
- 真正的 ID 在 XML 的 `<name><id>` 里,**目录名只是 `dataName`,两者不相等**
(`icon/icon550201/Icon.xml` 的 `name.id` 实际是 1)。
(`icon/icon550201/Icon.xml` 的 `name.id` 实际是 1;`music/music111537` 的
`name.id` 是 111537,属宴曲段)。
- 数据包按 `Sinmai_Data/StreamingAssets/A0xx/` 分基础包与增补包,抽取时按目录名
升序合并、同 ID 后者覆盖前者,与客户端 `DataManager.LoadData` 的语义一致。
- **本地 event 表没有日期窗口**:开关状态是服务器 `GetGameEventApi` 的
`GameEvent{startDate,endDate}` 决定的。`events.json` 只能告诉你某个
`eventName.id` 是哪个活动、是否 `alwaysOpen`,判断「现在开没开」得问服务器。
- 放在 `data/` 而不是 `assets/`:目前还没有代码在运行时读它,进 `assets/` 会被
原样打进每个安装包(约 1.2MB)。真要接进 App 时再连同 `pubspec.yaml` 一起挪。
顺手用这份表核出来的几个事实,都能解释此前的「不显示」:
- **musicId 11820 在曲表里根本不存在**(11819、11821 也不在;11814 之后直接跳到
11822)。它不是万花筒锁——`lockType = 4 (KaleidScope)` 的歌整张表只有 6 首
(11740 / 11745 / 11749 / 11753 / 11809 / 11814)。11820 属于「机台没有这首歌」,
任何 `UpsertUserAll` 都变不出来。
- **musicId 11820 在任何一层数据包里都不存在**(11819、11821 也不在;11814 之后
直接跳到 11822,G:\Package 与 D:/A031OptDump 两层都查过)。它不是万花筒锁——
`lockType = 4 (KaleidScope)` 的歌整张表只有 6 首(11740 / 11745 / 11749 /
11753 / 11809 / 11814)。11820 属于「机台没这首歌」,任何 `UpsertUserAll`
都变不出来。
- `lockType` 的分布是 `Unlock=1347 / Lock=18 / Challenge=5 / Transmission=2 /
KaleidScope=6`(合并两层数据包后共 1378 首),所以绝大多数歌根本不查
`itemKind 5`(`lockType == Unlock` 时 `IsPlayable` 直接为 true)——这也解释了
为什么有些「解歌」包发下去看不出效果:那首歌本来就可玩。
- **角色(旅行伙伴)1001 不存在**,合法 ID 从 101 起,整表 983 条、上界到 605905。
以前页面里「例如 1001」的提示正是这个坑。
- **万花筒只有 gate 1~6**(蓝/白/紫/黑/黄/红,course 与 key 同为 1~6 一一对应)。