Skip to content

Fix creative tab section padding 修复创造栏分区占位兼容性(1.21.1) - #159

Merged
PigeonNian merged 1 commit into
Anvil-Dev:dev/1.21.1from
WhereisFff:codex/issue-5626-1.21.1
Oct 22, 2026
Merged

PigeonNian merged 1 commit into
Anvil-Dev:dev/1.21.1from
WhereisFff:codex/issue-5626-1.21.1

Conversation

@WhereisFff

@WhereisFff WhereisFff commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

fix(registrum): 修复创造栏分区占位兼容性

  • 将分区占位和变体折叠移至客户端选择创造模式分类时处理
  • 保持共享物品列表不含布局空格,避免空物品整理破坏分区横幅占位
  • 保留分区内物品顺序与搜索栏完整物品列表
  • 保留无分区分类原有的变体折叠时机与第三方分类处理
  • 关联 [Bug] 创造物品栏分栏BUG AnvilCraft#5626

@Gugle2308

Copy link
Copy Markdown

❌ Non-retryable error (HTTP 400): HTTP 400: Upstream request failed: [invalid_request_error] The reasoning_content in the thinking mode must be passed back to the API. (request_id: 8884671a-5375-413f-bc91-48d7e9985cb3)

@Gugle2308

Copy link
Copy Markdown

HTTP 400: Upstream request failed: [invalid_request_error] The reasoning_content in the thinking mode must be passed back to the API. (request_id: 8884671a-5375-413f-bc91-48d7e9985cb3)

- 将分区占位和变体折叠移至客户端选择创造模式分类时处理
- 保持共享物品列表不含布局空格,避免空物品整理破坏分区横幅占位
- 保留分区内物品顺序与搜索栏完整物品列表
- 保留无分区分类原有的变体折叠时机与第三方分类处理
- 关联 Anvil-Dev/AnvilCraft#5626
@WhereisFff
WhereisFff force-pushed the codex/issue-5626-1.21.1 branch from 6a16a29 to bcb85f5 Compare October 21, 2026 14:24
@Gugle2308

Copy link
Copy Markdown

⚠️ Dangerous command requires approval:

cd /tmp && mkdir -p pr159cls && cd pr159cls && (unzip -o -q /opt/data/workspace/mcprobe/client-1.21.1.jar 'fpi*' 2>/dev/null || python3 -c "x" ) ; ls | head

Reason: script execution via -e/-c flag

Reply /approve to execute, /approve session to approve this pattern for the session, /approve always to approve permanently, or /deny to cancel.

@Gugle2308

Copy link
Copy Markdown

❌ Non-retryable error (HTTP 400): HTTP 400: Upstream request failed: [invalid_request_error] The reasoning_content in the thinking mode must be passed back to the API. (request_id: 69d03916-10ba-493a-86ba-a29e49fb8b3b)

@Gugle2308

Copy link
Copy Markdown

HTTP 400: Upstream request failed: [invalid_request_error] The reasoning_content in the thinking mode must be passed back to the API. (request_id: 69d03916-10ba-493a-86ba-a29e49fb8b3b)

@Gugle2308

Copy link
Copy Markdown

Diff 已复核:md5 与 head sha(bcb85f5)均未变化。以下是审查结论。


代码审查摘要 — PR #159

操作: synchronize(pullOpened;本次审查对应 head bcb85f5,与 dev/1.21.1 当前 tip 397b2be 无分叉)
范围: 3 个文件(3 Java,0 新增/删除)/ 83 行 diff
关联: Anvil-Dev/AnvilCraft#5626

变更理解(先确认我没有误读)

  1. CreativeModeTabMixin(common)在 buildContents TAIL 不再把 arrange() 结果写回共享字段;对 hasSections(tabId) 的标签页连 fold 也跳过,改为纯 anvillib$foldVariants。
  2. 客户端 selectTab 用 @ModifyExpressionValue 拦截 CreativeModeTab.getDisplayItems(),在 hasSections 时做 arrange(tabId, fold(items))。
  3. CreativeTabSections.hasSections() = LAYOUTS.containsKey(tabId)。

我用 Mojang client_mappings + 1.21.1 client jar 反汇编核对了注入点,结论:注入点选得对。CreativeModeInventoryScreen.selectTab(CreativeModeTab) 字节码为 @0 getstatic selectedTab; @3 astore_2; @4 aload_1; @5 putstatic selectedTab —— 字段在方法头就已更新,而 @288-@294 正是 if (type == CATEGORY) menu.items.addAll(selectedTab.getDisplayItems())(fpi$b.k = NonNullList items)。你钩住的表达式与 menu.items 的填充是同一个读取,且 CreativeModeTab.Type 常量序为 CATEGORY(a)/INVENTORY(b)/HOTBAR(c)/SEARCH(d),与 hasSections 的语义一致。mixinextras 也不用加依赖(NeoForge 传递 0.5.3,AnvilCraft 侧已在用 @ModifyExpressionValue),mixins.json 的 client 段已注册本 mixin。

🔴/⚠️ 主要问题:containerTick() 里还有第二条填充路径没有被拦截

getDisplayItems() → menu.items 在 1.21.1 里不止 selectTab 一处:

containerTick()                                    // CreativeModeInventoryScreen
 └─ tryRefreshInvalidatedTabs(FeatureFlagSet, boolean, HolderLookup.Provider)
     ├─ tryRebuildTabContents(...)  返回 true(内容刚重建)
     └─ for (tab : CreativeModeTabs.allTabs())
          if (tab != selectedTab) continue;
          if (type == CATEGORY && items.isEmpty()) selectTab(defaultTab);
          else setItems(tab.getDisplayItems());     // ← @111-@114,原始集合,未 fold/arrange

(已用字节码确认:tryRefreshInvalidatedTabs 的唯一调用者是 containerTick,CreativeModeTabs.tryRebuildTabContents 在 client 侧的唯一调用链也在这里。)

tryRebuildTabContents 在「本会话首次构建 / /reload(holders 变)/ 权限变化(/op、/deop,hasPermissions 变)/ 特性开关变」时返回 true,于是:

  • 本会话第一次打开创造栏:init() 里的 selectTab(...) 早于内容构建,displayItems 还是空集合 → arrange 对空列表跑一遍 → PLACEMENTS 被写成空表;随后第一个 tick 才把内容建好并用 setItems(raw) 填格子。结果:分区横幅完全不出现、变体也不折叠,必须切一次标签页再切回来才恢复。
  • 打开状态下 /reload 或权限变化:PLACEMENTS 保留旧(含占位空格)的索引,而格子换成了不含占位空格的原始列表 → 横幅画在错误行上(renderSections 用 placedSection.itemIndex()/9 定位),比"不显示"更容易被当成渲染 bug 报上来。

(说明:如果别的 mod/框架提前触发过内容构建,首开症状会被掩盖,所以这条建议以"实测 + 补钩子"为准;但上述路径本身是确定的。)

建议修法(最小):把 selectTab 与 tryRefreshInvalidatedTabs 两处 getDisplayItems() 的变换收敛成一个方法,两个 @ModifyExpressionValue 都指向它;或更彻底地放到"写入 menu.items"的那一步做一次。顺便能让 PLACEMENTS 的写入口径只有"实际填格子"这一处,不会再出现索引与列表脱节。

@ModifyExpressionValue(method = "tryRefreshInvalidatedTabs",
    at = @At(value = "INVOKE",
        target = "Lnet/minecraft/world/item/CreativeModeTab;getDisplayItems()Ljava/util/Collection;"))
private Collection<ItemStack> anvillib$arrangeSectionsOnRefresh(Collection<ItemStack> items) { ... }

💡 建议

  • CreativeModeInventoryScreenMixin.java:89 — 客户端这个 handler 实际做的是 fold + arrange,名字 anvillib$arrangeSections 与服务端新名 anvillib$foldVariants 语义不对称,建议改成 anvillib$arrangeSectionedItems 之类,便于后续判断"哪一侧负责什么"。
  • CreativeTabSections.java:106 — hasSections() 现在成了 mixin 的公共门禁(决定服务端是否折叠),建议补一行 javadoc 说明"registered layout ≠ 一定会放置横幅(整段为空时 arrange 不插占位)",否则调用方容易把它当"该标签页一定有分区"用。
  • 行为变化需在 PR 描述里点明 — 分区标签页的服务端/客户端 CreativeModeTab.getDisplayItems() 现在是未折叠的原始列表(以前是 fold 后的)。这是本 PR 想要的效果,但它是公共 API 的可观测变化(第三方读 getDisplayItems() 做自己的物品选择器/JEI 集成时会重新看到全部 16 色变体),值得写进描述而不是只提"不含布局空格"。
  • 之前工作区里那份 0001-fix-registrum-displayItems-mod-removeIf.patch(给 displayItems 包 new ArrayList<> 保可变性)在本方案下已经不需要了 —— 只要不再替换共享字段,bits_n_bobs 之类对 displayItems 做 removeIf 的 mixin 自然不会撞不可变集合。方向是对的,比"包一层可变副本"更干净。

🟢 看起来不错

  • 把"布局占位"从共享物品列表里剥离、只在显示用列表里注入,正是 #5626 的根因对策:displayItems 保持干净后,其它 mod 的排序/removeIf、hasAnyItems()、搜索集合都不再被 ItemStack.EMPTY 污染。
  • displayItemsSearchTab(搜索集)本来就在 buildContents 内部、于 TAIL 注入之前生成,因此搜索栏"完整物品列表"这一条本来就成立且不受影响 ✅。
  • hasSections 的门控时机正确:LAYOUTS 在生成器(CreativeTabSections.build)里写入,早于 buildContents TAIL,所以服务端判定不会拿到旧值。
  • fold/arrange 都返回可变 ArrayList,menu.items.addAll 只是拷贝,无别名/不可变集合风险;PLACEMENTS/LAYOUTS 是 ConcurrentHashMap,写入与读取都在客户端线程。
  • CreativeTabBuilder 没有 type setter(默认 CATEGORY),所以"分区标签页一定是 CATEGORY"这一前提成立,hasSections 跳过服务端折叠不会波及非 CATEGORY 场景。

📋 声称验证表

PR 声称 状态 依据
分区占位与变体折叠移至客户端选择分类时处理 ✅(不含 containerTick 路径) CreativeModeInventoryScreenMixin:82-93
共享物品列表不再含布局空格 ✅ CreativeModeTabMixin 不再写回 displayItems
保留分区内物品顺序 ✅ arrange 仅插入 EMPTY,subList 顺序保持
保留搜索栏完整物品列表 ✅(原本即不受影响) 搜索集在 buildContents 内生成,早于 TAIL
关联 #5626 ✅ 方向吻合 不再改共享字段

结论: 建议修补后合并(REQUEST_CHANGES,唯一阻塞项是"第二条填充路径") —— 主体设计正确且比原方案干净,但分区布局现在只挂在 selectTab 上,containerTick → tryRefreshInvalidatedTabs → setItems(getDisplayItems()) 这条同样会重填格子的路径没有覆盖,会在"本会话首开创造栏 / 热重载 / 权限变化"时让横幅消失或错位。补一处 @ModifyExpressionValue(或把变换下沉到填格子那一步)即可。

🧪 测试建议

被测目标 场景 优先级
首开创造栏 新开存档首次打开创造物品栏,分区标签页横幅/占位是否立即生效(不切标签) 🔴
热重载 打开创造栏后 /reload,横幅位置是否仍与物品对齐 🔴
权限变化 创造栏打开状态下 /op、/deop 后网格重填 🟡
变体折叠 分区标签页 vs 非分区标签页的折叠结果一致;搜索栏仍能搜到被折叠的 16 色变体 🟡
第三方兼容 bits_n_bobs 等对 displayItems 做 removeIf 的 mixin 不再抛 UnsupportedOperationException 🟡

标题

gh auth status 报 token 失效(The token in .../hosts.yml is invalid),故未自动改标题。建议标题(英文侧"padding"不准确,实际是占位空格 + 变体折叠的处理时机):

Move creative tab section spacers and variant folding to client-side tab selection 修复创造栏分区占位兼容性(1.21.1)


由 Hermes Agent 审查

@Gugle2308

Copy link
Copy Markdown

🌿 Roseau API Breaking Change Report

Module Status Breaking Changes
codec ✅ Compatible 0
collision ✅ Compatible 0
cube ✅ Compatible 0
config ✅ Compatible 0
integration ✅ Compatible 0
moveable-entity-block ✅ Compatible 0
network ✅ Compatible 0
rendering ⚪ Skipped —
space-select ✅ Compatible 0
font ✅ Compatible 0
util ✅ Compatible 0
explosion ✅ Compatible 0
rpc ✅ Compatible 0
math ✅ Compatible 0
multiblock ✅ Compatible 0
recipe ✅ Compatible 0
registrum ✅ Compatible 0
sync ✅ Compatible 0
wheel ✅ Compatible 0
main ✅ Compatible 0

Full CSVs: see the Artifacts section of this workflow run.

@Gugle2308

Copy link
Copy Markdown

🌿 Roseau API Breaking Change Report

Module Status Breaking Changes
codec ✅ Compatible 0
collision ✅ Compatible 0
cube ✅ Compatible 0
config ✅ Compatible 0
integration ✅ Compatible 0
moveable-entity-block ✅ Compatible 0
network ✅ Compatible 0
rendering ⚪ Skipped —
space-select ✅ Compatible 0
font ✅ Compatible 0
util ✅ Compatible 0
explosion ✅ Compatible 0
rpc ✅ Compatible 0
math ✅ Compatible 0
multiblock ✅ Compatible 0
recipe ✅ Compatible 0
registrum ✅ Compatible 0
sync ✅ Compatible 0
wheel ✅ Compatible 0
main ✅ Compatible 0

Full CSVs: see the Artifacts section of this workflow run.

@PigeonNian
PigeonNian merged commit 68e63d3 into Anvil-Dev:dev/1.21.1 Oct 22, 2026
42 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants