Skip to content

Fix 26.1.2 predicate previews 修复方块预览属性组合 - #145

Closed
WhereisFff wants to merge 1 commit into
Anvil-Dev:dev/26.1from
WhereisFff:codex/fix-5206-predicate-render-states-26.1
Closed

WhereisFff wants to merge 1 commit into
Anvil-Dev:dev/26.1from
WhereisFff:codex/fix-5206-predicate-render-states-26.1

Conversation

@WhereisFff

Copy link
Copy Markdown
Contributor

@Gugle2308

Copy link
Copy Markdown

⚠️ Dangerous command requires approval:

curl -s "https://api.github.com/repos/Anvil-Dev/AnvilLib/pulls/145" -o /tmp/pr145.json; grep -o '"state": *"[a-z]*"' /tmp/pr145.json; grep -o '"merged": *[a-z]*' /tmp/pr145.json; grep -o '"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

⏱️ Rate limited. Waiting 2.5s (attempt 2/3)...

@Gugle2308

Copy link
Copy Markdown

⏱️ Rate limited. Waiting 2.3s (attempt 2/3)...

@Gugle2308

Copy link
Copy Markdown

⏱️ Rate limited. Waiting 2.0s (attempt 2/3)...

@Gugle2308

Copy link
Copy Markdown

⏱️ Rate limited. Waiting 4.1s (attempt 3/3)...

@Gugle2308

Copy link
Copy Markdown

❌ Rate limited after 3 retries — Concurrency limit exceeded for user, please retry later

@Gugle2308

Copy link
Copy Markdown

API call failed after 3 retries: Concurrency limit exceeded for user, please retry later

@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 ✅ Compatible 0
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.

@WhereisFff
WhereisFff marked this pull request as ready for review October 4, 2026 14:30
@Gugle2308

Copy link
Copy Markdown

代码审查摘要 — AnvilLib PR #145

操作: ready_for_review(PR 状态 pullOpened,未合并)
仓库: Anvil-Dev/AnvilLib codex/fix-5206-predicate-render-states-26.1 → dev/26.1
范围: 1 个文件 / +11 −3(module.util/.../v2/util/predicate/BlockStatePredicate.java,2 个 hunk)
diff 完整性: md5 cef9a3c8d8f1700e6c61565c311f440b;已用 dev/26.1 原始源码核对 - 侧、用 head 分支原始源码核对 + 侧,无截断、无 ghost 文件。

🔴 关键问题

无。

✅ 修复正确性核验(逐条对照语义)

检查项 结论
范围判据方向(hunk 2) ✅ v >= min / v <= max,与 RangedMatcher.match()(t < min → false、t <= max)完全一致。修复前的 < min / > max 是反转判据,与 match 自相矛盾
组合语义(hunk 1) ✅ 新的「链式 flatMap + 组内 allMatch(match) 过滤」与 testWithoutEntity() 的「组内 AND、组间 OR」语义一一对应,渲染列表终于与真实匹配谓词同构
过滤器是否必要 ✅ 必要,不是冗余:后续 matcher 的 applyToState 会整体重写属性值域,可能覆盖/推翻前面 matcher 在同属性上的约束(如 age=1 与 age=2 同组),allMatch 正是剔除这类矛盾组合;且不会产生假阴性(ExactMatcher/RangedMatcher 的 match 与其 applyToState 判据等价)
空 AND 组 ✅ 现在会落到 allMatch 空流 = true,产出 default state;旧实现产出空。与 test 语义一致(空组视为恒真),是行为改进
旧实现为何导致 #5206 因果链成立:范围判据反转 ⇒ 值域落在 [min,max] 内的谓词(只要写 min 或 max 且域在范围内)整组被剔除 → getStatesCache() 为空 ⇒ AnvilCollisionCraftRecipe.getResult() 走 isEmpty() 回退分支返回普通铁砧 = issue 里「产物的巨型铁砧时有时无」;同组多属性取并集而非组合 ⇒ 预览状态属性不自洽 = 「楼梯朝向时而正确时而错误」。两个 hunk 正好各自对症

⚠️ 警告(非阻塞,建议一并处理)

  1. states 仍是 HashSet,getFirst() 语义不稳定 — List.copyOf(states) 保留 HashSet 迭代顺序,而 BlockState 全继承链未覆写 equals/hashCode(已用 1.21.1 客户端 jar + client_mappings 核对:BlockState(dtc) → BlockStateBase(dtb$a) → dte → Object,链上无 equals/hashCode),即身份哈希语义;HotSpot 身份哈希按进程随机种子生成,跨启动顺序可以不同。下游多处直接依赖「第一个元素」:AnvilCollisionCraftRecipe.getResult()(本地 26.1 克隆 src/main/java/dev/dubhe/anvilcraft/recipe/anvil/collision/AnvilCollisionCraftRecipe.java:402 → getStatesCache().getFirst().getBlock().asItem() 作为配方产物物品)、MineralFountainRecipe.assemble():85、MineralFountainChanceRecipe:93、SqueezingCategory:143 / BlockCrushCategory:142 的 tooltip。当谓词覆盖 HolderSet 多方块(如铁砧 tag)而这次修复又让列表由空变非空、元素集合发生变化时,getFirst() 命中的方块可能不再是预期项 —— 「时有时无」有残留风险。
    建议: 把 Set<BlockState> states = new HashSet<>() 改为 LinkedHashSet(构造顺序 = 逐方块、逐 OR 组、链式展开顺序,default 派生状态优先,稳定且可读),或末尾按 Block.getId + 属性值做一次稳定排序。开销为零,且顺带消除同类问题。

  2. 笛卡尔积无上界 — 链式 flatMap 使同组 matcher 展开为乘积:3 个属性 × 各 5 值 = 125 个状态(旧实现是 15),同属性 min/max 拆成两个 matcher 时会先展开出 N² 中间态再被 allMatch 剪掉。该列表被缓存并被 JEI 每帧 states.stream().filter(...).findFirst() 线性扫描(JeiBlockIngredientUtil.getDisplayedState),也被 ColliderHandler.refreshColliderTargetItems() 全量遍历。当前量级(几十~几百)可接受,但语义边界宽松的 tag 谓词可能进一步放大。
    建议: 先按属性求交(每个属性聚合出允许值集合)再一次性做组合,可省掉中间膨胀,并天然得到稳定插入顺序(与建议 1 互补);若库侧希望更保守,可在 constructStatesForRender() 加一个上限/去重保护。

💡 建议

  • 1.21.1 线未同步:issue #5206 报告的版本是 anvilcraft-neoforge-1.21.1-1.6.0+snapshot.2416,本地 dev/1.21.1 的 module.util 里是同一份缺陷代码(BlockStatePredicate.java:227 的 states.addAll(...) 并集 + 同一处反转判据)。本 PR 只修 26.1,请确认是否 backport / cherry-pick,否则报告者的版本仍会复现。
  • 新实现会合法地产出空列表(同属性矛盾条件、min > max 的反向 range)。下游无守卫的 .getFirst() 调用点(MineralFountainRecipe.assemble():85、BlockCrushCategory:142、SqueezingCategory:143)在配方写错时会抛 NoSuchElementException;AnvilCollisionCraftRecipe.getResult() 的 isEmpty() 守卫是可参考的范式,建议后续 PR 统一加固(本 PR 不阻塞)。
  • statesCache 为非 volatile 字段、可能被渲染线程与服务端线程(ColliderHandler)并发首访;结果不可变故为良性竞态(既有问题,非本次引入),如需洁癖可改为一次性 Supplier/synchronized 初始化。
  • 标题:Fix 26.1.2 predicate previews 修复方块预览属性组合 中「26.1.2」与目标分支 dev/26.1 不符、描述偏笼统。建议改为:
    Fix BlockStatePredicate render-state combination and ranged matching 修复方块状态谓词预览的属性组合与范围匹配
    (本次 gh auth status 显示 /opt/data/home/.config/gh/hosts.yml token 已失效,未自动修改,仅给出建议。)

📋 声称验证表

声称 状态 证据
修复预览状态的属性组合 ✅ hunk 1:链式展开 + 组内 allMatch 过滤,与 testWithoutEntity() 的 AND/OR 语义同构
修复…范围匹配 ✅ hunk 2:>= min / <= max,与 RangedMatcher.match() 一致
fixed Anvil-Dev/AnvilCraft#5206 ✅(26.1 线)/ ⚠️(1.21.1 线) 症状因果链已核实;但报告版本在 1.21.1 线,该线同源缺陷仍在

🧪 测试建议

被测目标 推荐测试场景 优先级
BlockStatePredicate.constructStatesForRender() 单 matcher 范围谓词 [min,max] 覆盖全值域 ⇒ 非空且全部落在区间内(回归旧版反转判据) 🔴
同上 同组同属性 min/max 两个 matcher ⇒ 结果 = 交集,且与 testWithoutEntity 逐状态一致(render ⊆ test) 🔴
同上 同组矛盾条件(age=1 + age=2)⇒ 空列表且不抛异常 🟡
同上 空 AND 组 / 属性不存在于方块 ⇒ 不产生非法状态 🟡
getStatesCache() 同一谓词多次/跨进程取 getFirst() 稳定(若采纳 LinkedHashSet) 🟡

结论: APPROVE(建议合并) — 两处修改对症、语义自洽、diff 干净,未发现阻塞性问题;#5206 的两类症状都能由此解释并修复。上述 ⚠️ 1/2 与 1.21.1 backport 建议属非阻塞,建议在合并前顺手采纳 LinkedHashSet(一行改动即可消除 getFirst() 的跨运行不稳定)。


由 Hermes Agent 审查

@Gugle2308

Copy link
Copy Markdown

💾 Self-improvement review: Patched SKILL.md in skill 'blockstate-predicate-review' (1 replacement). · Patched references/predicate-preview-fix-series-and-branch-coverage.md in skill 'blockstate-predicate-review' (1 replacement).

@WhereisFff WhereisFff closed this Oct 6, 2026
@WhereisFff
WhereisFff deleted the codex/fix-5206-predicate-render-states-26.1 branch October 6, 2026 03:23
@Gugle2308

Copy link
Copy Markdown

收到,PR #145 的操作类型是 closed(已关闭)。按 webhook 审查规则(closed/labeled → 停止),本次不拉取 diff、不输出审查意见、不发表任何评论。

未执行任何 curl / gh 命令,无评论产生。

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.

[Bug] JEI内多方块合成和多方块转化配方显示异常

2 participants