fix: 解歌的 isNewItemList 按主键回读再算,不再一律发 1

排查「发 11820 解歌不显示」时发现两处问题:

- applyItemListPatch 的 isNewItemList 一直硬写全 '1'(新增),从没读服务器
  已有行。真机 BuildListData 是按 (itemKind, itemId) 比对快照给 0/1 的,
  重复解锁一首已存在的歌时服务器按插入冲突丢行,表现就是上传成功但没生效。
  这和角色/地图/万花筒三处的处理不一致,现补齐。
- 新增 TitleApiService.getUserItems/getUserItemKeys。GetUserItemApi 是按
  itemKind 分页的,首次 nextIndex 要按 itemKind * 1e10 编码
  (PacketGetUserItem.cs:19),发 0 只会拿到空页。
- 解锁上传后回读复查,把「服务器没存这行道具」与「存了但曲目池不给进」分开报。
- 待解锁列表含 10000~19999 的 DX 曲时提示:Master/Re:Master 不像老曲那样
  白送(IsUnlockMaster 里 id<10000 直接放过),必须显式带 itemKind 6/7。

需要说明:一首歌进不进选曲池由 NotesListManager.cs:70 决定
(IsOpenEvent(eventName) && !IsGameNgMusicId),事件窗口来自 GetGameEventApi、
曲目本体来自机台 Music.xml。11820 若卡在这一层,任何用户包都改不动,
复查那一步就是为了把这种情况和包的问题区分开。

README 补 isNew*List 语义、曲目可见性链路与 DX 段解锁规则三条说明。
删除因此不再被引用的 unlockMusicSuccess。
This commit is contained in:
Cookiues committed 2026-10-01 22:14:50 +08:00
1 parent 6438fb2171
commit 80df51c239
6 files changed
+213 -4

No files matched your search

+8 -1
View File
@@ -398,13 +398,20 @@ class UserAllPayloadBuilder {
/// Generic item patch: replace `userItemList` / `isNewItemList` in the packet.
/// Used by UnlockMusic (itemKind 5/6/7) and 收藏品获取 (itemKind 1/2/3/10/11/12).
///
/// [newFlags] 每一位对应一行:'1' 服务器没有这行(插入)、'0' 已有(更新)。
/// 省略时全按 '1' 发。真机 `BuildListData` 是按 (itemKind, itemId) 主键比对
/// 服务器快照算出这一位的,所以重复解锁同一首歌时必须发 '0',否则服务器
/// 可能当成插入冲突直接丢掉这一行。
void applyItemListPatch(
Map<String, dynamic> packet, {
required List<Map<String, dynamic>> items,
String? newFlags,
}) {
assert(newFlags == null || newFlags.length == items.length);
final upsert = packet['upsertUserAll'] as Map<String, dynamic>;
upsert['userItemList'] = items;
upsert['isNewItemList'] = List.filled(items.length, '1').join();
upsert['isNewItemList'] = newFlags ?? List.filled(items.length, '1').join();
}
/// 解锁歌曲/谱面时补一条 musicDetail 记录并标记为新增。