Skip to content

Fix creative section rendering 修复创造栏分区显示与提示框层级(26.1.2) - #157

Merged
PigeonNian merged 1 commit into
Anvil-Dev:dev/26.1from
WhereisFff:codex/26.1-section-5315
Oct 20, 2026
Merged

PigeonNian merged 1 commit into
Anvil-Dev:dev/26.1from
WhereisFff:codex/26.1-section-5315

Conversation

@WhereisFff

Copy link
Copy Markdown
Contributor

fix(registrum): 修复创造栏分区显示与提示框层级

  • 在配方查看器绘制前景前绘制创造栏分区,避免配方收藏预览导致分区消失
  • 移除分区额外的渲染高度与层级提升,防止遮挡配方查看器提示框
  • 保留分区悬停提示、长文本滚动及变体选择交互

- 在配方查看器绘制前景前绘制创造栏分区,避免配方收藏预览导致分区消失
- 移除分区额外的渲染高度与层级提升,防止遮挡配方查看器提示框
- 保留分区悬停提示、长文本滚动及变体选择交互
@Gugle2308

Copy link
Copy Markdown

代码审查摘要 — PR #157 fix(registrum): 修复创造栏分区显示与提示框层级

状态: OPEN(data-status="pullOpened",head 9423e0b0,本轮审查期间 head 未前进、diff md5 复核一致)
范围: 2 个文件(+40 / −9):新增 CreativeTabSectionRenderListener(35 行),改 CreativeModeInventoryScreenMixin


🔍 关键机制核对(已离线取证,结论可用)

  1. 钩子点选对了,-leftPos/-topPos 的抵消也是对的
    拉取 neoforge-26.1.2.76-userdev.jar 的 patch 与 26.1.2 client.jar 反汇编:

    • AbstractContainerScreen.extractContents 首部 pose().pushMatrix() + translate(leftPos, topPos),尾部 popMatrix();NeoForge 把 ContainerScreenEvent.Render.Foreground 恰好插在 popMatrix() 之前(patch 上下文:onStopHovering(...) → post 事件 → popMatrix)。
    • 即事件触发时 pose 已被平移到容器左上角,所以监听器里的 translate(-leftPos, -topPos) 是必须的抵消,anvillib$renderSections 里沿用 this.leftPos + ... 的绝对坐标才继续成立。这条不明显但正确。
    • extractRenderState 先调 extractContents(字节码 offset 6)再调 extractTooltip(offset 25)⇒ 分区现在确实早于提示框提取,也早于同事件上优先级更低的其余监听器(配方查看器的前景绘制)——与 PR 描述的动机一致。事件 javadoc 也明确「after foreground/elements, before tooltips and dragged stack」。
  2. 删掉 nextStratum() 不会让横幅掉到物品下面
    26.1 的分层是自动的:GuiGraphicsExtractor.blit → GuiRenderState.addGuiElement → findAppropriateNode → navigateToAboveHighestElementWithIntersectingBounds,凡是与已有内容 bounds 相交的元素会被自动抬到更上一层。显式 nextStratum() 只是无条件多开一层(正是「额外的层级提升」),移除后横幅与其覆盖的物品格仍是「相交 ⇒ 上抬」的关系。✅ 这个改法安全,不是靠运气。

  3. @EventBusSubscriber(modid = "anvillib_registrum") 会生效:module.registrum/gradle.properties 的 mod_id=anvillib_registrum、neoforge.mods.toml 的 modId = "${mod_id}" 一致,value = Dist.CLIENT 也正确隔离服务端。

  4. 状态字段没有时序回归:anvillib$hoveredSection 只被渲染/提示路径读取(无点击逻辑依赖),hoveredSlot = null 的时机相对 extractSlotHighlight*/extractSlots 与旧实现等价。


⚠️ 警告(建议处理)

  • client/CreativeTabSectionRenderListener.java:23 — 依赖未文档化的 pose 前置条件。 NeoForge 的 ContainerScreenEvent.Render.Foreground javadoc 没有声明触发时 pose 已 translate(leftPos, topPos);整个正确性建立在这条未公开的实现细节上。若上游把 post 挪到 popMatrix() 之后(或改成未平移的 pose),横幅会整体偏移 (-leftPos, -topPos),表现为跑出屏幕左上角。建议:在类 javadoc 或 Renderer 契约里写明「graphics 的 pose 已被还原为屏幕绝对坐标(依赖 NeoForge 26.1 在 extractContents 的 popMatrix() 前派发该事件)」,这样将来失效时能被一句话定位。
  • CreativeVariantPickerOverlay.java:84 / 125 / 153 — 同类问题未同步处理。 变体选择弹窗仍在 extractTooltip 阶段、仍调用 3 次 nextStratum();extractTooltip 在 extractContents 之后,因此它仍具备「压住配方查看器在同一位置绘制的内容」的旧行为。请在装有 JEI/EMI 的环境回归:打开变体弹窗后把鼠标移到附近的配方提示框上,看是否仍被压住;若存在,建议按本 PR 同一思路收敛(去掉显式层级 / 或一并移到前景阶段绘制),否则这次只是修了横幅这一半。
  • 新包缺 package-info.java。 ...registrum.client 目前没有 @NullMarked(同类包如 client/gui、mixin/client 都有),而仓库 AGENTS.md 明确只认 jspecify。建议把该监听器放进 client/gui,或补 client/package-info.java(@NullMarked)。

💡 建议(非阻塞)

  • Renderer 作为新增公开接口需要契约定位:实现方只有内部 mixin,而仓库 chore(annotations): 添加 ApiStatus.Internal 注解到内部接口和类 #93 才刚给内部接口/类加上 @ApiStatus.Internal。建议二选一——加 @ApiStatus.Internal,或显式当作对外扩展点并在 javadoc 写清「仅 AbstractContainerScreen 生效、pose 已在屏幕原点」。
  • 命名:嵌套名 Renderer 过于泛化(client 包里还有真实渲染器概念),CreativeTabSectionRenderer / SectionRenderHost 更清楚;接口方法沿用了 mixin 注入风格的 anvillib$renderSections,作为跨类公开契约建议改成不带 $ 的 renderSections。
  • "anvillib_registrum" 字面量与 gradle mod_id 重复(当前仓库没有 MOD_ID 常量,可接受);若以后引入常量请一并替换,避免 modid 漂移导致订阅静默失效。

🟢 看起来不错

  • 用「屏幕实现接口 + 客户端事件」替代在 mixin 里再注入第二个方法,职责清晰,也不影响其它 ContainerScreen(instanceof 守卫)。
  • pushMatrix / try-finally-popMatrix 平衡,enableScissor/disableScissor 也在 renderBannerText 内成对。
  • priority = HIGHEST 把「必须先于配方查看器」这个隐含约束写成了代码意图,比依赖事件注册顺序稳。
  • 移除无意义的层级提升,少一次 stratum 分配;长文本滚动、悬停提示、变体选择交互逻辑未受扰动。

📋 结论

COMMENT(建议合并) — 无阻塞缺陷;机制层面(钩子点、pose 抵消、自动分层)我已用 26.1.2 的 NeoForge patch + 客户端字节码 + GuiRenderState 反汇编逐条核对通过。合并前建议至少完成两件事:① ⚠️ 第 2 条(变体弹窗的 nextStratum 是否同样压住配方提示框)在有 JEI/EMI 的实例里回归确认;② 补 client 包 null-mark 约定。
另外:审查时该 head 的 CI 为 23 个 check 中 10 个 success、13 个 queued,其中未见 registrum 模块的最终结果,请确认 registrum 的 check/build 已通过再合。

🧪 测试建议

被测目标 场景 优先级
CreativeTabSectionRenderListener.renderSections 装 JEI/EMI + 收藏配方预览,确认分区横幅不消失、不遮挡配方提示框 🔴
同上 界面缩放(1x/2x/auto)、窗口尺寸变化下横幅坐标不偏移 🔴
anvillib$renderSections 悬停 横幅悬停提示、超长文本滚动、横幅覆盖物品格时的 slot 高亮/物品 tooltip 抑制 🟡
CreativeVariantPickerOverlay 弹窗开启时相邻配方提示框是否被压住(见 ⚠️2) 🟡
其它 AbstractContainerScreen 箱子/工作台等界面无额外绘制、无 pose 泄漏 🟢

建议标题: Fix creative tab section layering with recipe viewers 修复创造栏分区层级避免遮挡配方提示框
(本次因 gh auth status 显示 token 失效,未自动执行 gh pr edit)


由 Hermes Agent 审查(对应 head 9423e0b0)

@PigeonNian
PigeonNian merged commit a10b35b into Anvil-Dev:dev/26.1 Oct 20, 2026
42 checks passed
@Gugle2308

Copy link
Copy Markdown

PR #157 已经是 closed(且已合并到 dev/26.1,merged_at = 2026-10-20T16:02:56Z)。

按约束 1(closed/labeled → 停止,不发布评论),本次不做审查、不输出审查意见,也不修改标题。

(另:gh auth status 显示 Gugle2308 的 token 已失效,后续若需要 gh pr edit 改标题,得先重新 gh auth login。)

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