Skip to content

Fix 1.21.8 predicate previews 修复方块预览属性组合 - #143

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

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

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/AnvilCraft/issues/5206" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['title']); print(d['state']); print(d['body'][:2500])" 2>/dev/nul...

Reason: Security scan — [HIGH] Pipe to interpreter: curl | python3: Command pipes output from 'curl' directly to interpreter 'python3'. Downloaded content will be executed without inspection.
Safer: tirith run https://api.github.com/repos/Anvil-Dev/AnvilCraft/issues/5206 — or: vet https://api.github.com/repos/Anvil-Dev/AnvilCraft/issues/5206 (https://getvet.sh); 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

代码审查摘要 — AnvilLib PR #143

操作: opened(2026-10-04,state=open,merged_at=null,未合并)
范围: 1 个文件 / 35 行 diff(+11 / −3)
module.util/.../v2/util/predicate/BlockStatePredicate.java
diff 完整性: patch-diff 与 API Accept: vnd.github.v3.diff 两条路径 md5 一致(92b748de…),与 API 元数据 changed_files=1 / additions=11 / deletions=3 吻合,无截断。


🔴 关键

未发现本次改动新引入的阻塞性缺陷。改动方向、边界处理与既有 match() 语义一致。

⚠️ 警告

  1. 分支覆盖:修复落在 dev/1.21.8,但 issue #5206 的报告环境是 AnvilCraft 1.21.1
    • issue 内容:anvilcraft-neoforge-1.21.1-1.6.0+snapshot.2416,MC 1.21.1 / NeoForge。
    • AnvilCraft dev/1.21/1.6(minecraft_version_range=[1.21,1.21.1))依赖 anvillib-neoforge-1.21.1 2.0.0+snapshot.546,即 AnvilLib dev/1.21.1 线;该分支存在完全相同的反转逻辑(<0 / >0,第 616/618 行),dev/1.21.11、dev/26.1 同样如此(已逐一核对 raw 源码)。
    • 结论:只改 dev/1.21.8 不会修到 issue 报告的那个版本。若目标是关闭 #5206,请一并 backport 到 dev/1.21.1(以及 dev/21.11/dev/26.1)。

💡 建议

  1. ExactMatcher.applyToState 对「属性存在但值无法解析」仍返回 List.of(state)(第 574–576 行)。现在靠外层 allMatch 兜底把它过滤掉,行为正确,但 applyToState 局部不变式(“产出的每个状态都满足 match()”)依旧不成立。建议与 PropertyMatcher.applyToState(属性不存在返回 List.of())统一,改为返回值无法解析时返回 List.of(),让链条自身语义自洽、外层过滤退化为纯防御。
  2. 加一行注释说明折叠+过滤的设计意图:先按 matcher 逐个折叠候选(组合),最后统一按 allMatch 校验,避免后人误删 filter。
  3. 空匹配组的语义变化:properties: [{}] 经 PROPERTIES_CODEC(unboundedMap + listOf)可解码为 List.of(List.of())。旧实现对该组不产生任何状态,新实现因 allMatch(空流)=true 会加入 defaultBlockState()。而 testWithoutEntity() 里空组是“空真”⇒ 匹配该方块任意状态,所以只给 default 仍不完整。属低风险行为变化,建议显式确认(要显示 default、显示全部、还是跳过空组)。
  4. 候选数上限:AND 组内多个 RangedMatcher 时 candidates 是笛卡尔积(Π 各属性可选值数),旧实现是求和。现有配方绝大多数是 exact matcher(每个塌缩为 1 个候选,反而比旧实现更省),且有 statesCache 缓存,暂不构成问题;但若将来出现“多属性大范围”的谓词,建议留意。
  5. 补测试:AnvilLib 各 module 目前没有 src/test(已确认)。这个类被 test() 与 constructStatesForRender() 双边使用,值得加最小回归用例(见下方测试建议)。
  6. 方法名 constructStatesForRender() 声明“不应用于除渲染外的任何用法”,但 getStatesCache() 实际还被 ColliderHandler、配方结果推导(AnvilCollisionCraftRecipe/MineralFountainRecipe 的 getStatesCache().getFirst())等非渲染路径消费 —— 本次改动在这些路径上表现为“更严格且更正确”(exact 组不再混入 default 状态;ranged 组从空集变为正确集合),建议联同 these 路径做一次 in-game 冒烟验证。

🟢 看起来不错

  • 根因定位准确,与 issue 症状机制完全对得上:AnvilCraft 的 LevelLike 用
    blocks.get(pos).get((int)(System.currentTimeMillis()/1000) % blocks.size()).state()(1.21.1 LevelLike.java 第 203 行)逐秒轮换预览状态。旧实现是并集:
    对 giant_anvil_1.json 符号 B(cut_heavy_iron_stairs, facing=south, half=bottom, waterlogged=false)来说,half/waterlogged 两个 matcher 作用在默认状态上恰好等于默认值,于是把 facing=north 的 default 状态也塞进了列表 → 每两秒切换一次“正确的朝南 / 全部朝北”,正是报告的“时而正确、时而全部朝向北方”。
  • 恢复了被破坏的不变式:test() 用 match()(语义一直正确,所以配方本身能合成、只是预览错),而 constructStatesForRender() 却产生“不满足 match() 的状态”。修复后两者一致。
  • 范围比较翻转正确:<0 → >=0、>0 → <=0,与 RangedMatcher.match() 的判据(<0 拒绝 / <=0 接受)严格对齐;旧判据 “value < min AND value > max” 在 min<=max 时恒为空集,导致 ranged 符号预览为空。
  • 结构与风格与既有代码一致(distinct() 只作去重优化,正确性由最终 allMatch 保证;结果仍由 HashSet 去重,与旧实现一致)。

📋 声称验证表

声称 状态 证据
修复预览状态的属性组合 ✅ 并集 → 折叠+交集过滤;模拟脚本 CASE 1:旧 2 个状态(含 facing=north 的 default),新 1 个正确状态
修复范围匹配 ✅ 模拟脚本 CASE 2:旧 applyToState → [],新 → [1,2];CASE 3(exact+ranged 混合组)旧给出不满足 match 的状态 (west,0),新给出 (west,1/2/3)
fixed Anvil-Dev/AnvilCraft#5206 ⚠️ 部分 症状一(楼梯朝向周期性错误)机制吻合、可判定已修;症状二“产物的巨型铁砧时有时无”不由本改动路径解释(MultiBlockCraftingCategory 输出槽是固定 getResult();getRenderablePreviewState 是确定性映射),需在含此修复的构建上复测确认

复现证据脚本:/opt/data/workspace/pr143_predicate_sim.py(python3 /opt/data/workspace/pr143_predicate_sim.py),按 applyToState/match 语义逐字转写新逻辑并对旧逻辑对照,输出如上。

🧪 测试建议

被测目标 推荐测试场景 优先级
BlockStatePredicate.constructStatesForRender() 单 exact matcher;exact 值==默认值(回归本次 bug,断言不含 default)+ 混合 exact/ranged 组;多 OR 组并集;properties=[[]] 空组;无法解析的属性值(断言不产出 default) 🔴
不变式断言 constructStatesForRender() 的每个状态都满足 testWithoutEntity()(本次被破坏的不变式,最值得固化) 🔴
RangedMatcher.applyToState() 仅 min / 仅 max / min+max / min>max / 值不可解析(property.getValue 为空) 🟡
RangedMatcher.match() 与 applyToState 边界的对称性(>=/<= 含端值) 🟡

注意:BlockState 依赖 Bootstrap.bootStrap()/注册表,普通 JUnit 直接跑会失败。可考虑 GameTest,或把“候选折叠 + 过滤”抽成不依赖 MC 类型的纯函数再单测。

结论: APPROVE(附评论) — 改动小而正确,根因表述与 issue 症状吻合,无阻塞问题。
合并前请决定 backport 范围(dev/1.21.1 等,否则 #5206 的报告版本仍受影响),并补上 constructStatesForRender() 的回归测试。


补充:gh 未认证(/opt/data/home/.config/gh/hosts.yml token invalid),本次未执行 gh pr edit。如需更精确的标题,建议:Fix predicate preview states: compose AND matchers and correct ranged bounds 修复方块预览属性组合与范围匹配。

由 Hermes Agent 审查

@Gugle2308

Copy link
Copy Markdown

🌿 Roseau API Breaking Change Report

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

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

@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
@Gugle2308

Copy link
Copy Markdown

PR #143 状态为 closed,按 webhook 审查规则跳过,不产出审查意见(无评论发布)。

  • 原因:仅对 opened / ready_for_review 等活跃状态执行审查;closed(含已合并)无需再评。
  • 未下载 diff、未做标题修改。

如需在重新开启或后续 PR 上审查,请再次触发。

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.

2 participants