Skip to content

Fix bugs about storage system 修复仓储系统相关问题 - #4668

Merged
PigeonNian merged 6 commits into
Anvil-Dev:dev/1.21/1.6from
QiuShui1012:fix/1.21/1.6
Sep 1, 2026
Merged

Fix bugs about storage system 修复仓储系统相关问题#4668
PigeonNian merged 6 commits into
Anvil-Dev:dev/1.21/1.6from
QiuShui1012:fix/1.21/1.6

Conversation

@QiuShui1012

Copy link
Copy Markdown
Collaborator

No description provided.

@Gugle2308

Copy link
Copy Markdown
Collaborator

⚠️ Dangerous command requires approval:

curl -sL "https://api.github.com/repos/Anvil-Dev/AnvilCraft/pulls/4668" -o /tmp/pr4668.json && python3 -c "
import json
d=json.load(open('/tmp/pr4668.json'))
print('title:', d.get('title'))
print('sta...

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
Collaborator

审查完成。以下是完整审查意见:


代码审查摘要 — PR #4668

操作: opened(draft)
范围: 11 个文件(全 Java)/ 917 行 diff(+235 / −296),0 新增、0 删除、0 EOF 缺失
PR 状态: draft,base dev/1.21/1.6 @ 2679cd9,2 commits,mergeable_state: clean

变更概览

  1. 潜影终端重构 — 删除 ShulkerBoxesStorage/ShulkerBoxesItemHandler(聚合潜影盒视图),改为「优先连接身上已有 UUID 的潜影集装箱,无 UUID 时打开终端惰性授予」+ 64 格内世界集装箱兜底;RemoteTarget.SHULKER_BOXES 分支全链清理
  2. 合成取结果修复consumeCraftingInput 从「整槽清空」改为「每槽 −1」(原版语义)
  3. Shift+点击取全部 — 新增 craftingTakeAll RPC + 客户端 StorageScreen 分支
  4. 终端交互修复BundleLikeItem 新增 canInsertInto() 钩子,TerminalItem 覆写为 false 放行 vanilla 交换
  5. 浮窗状态合并selected/keyboardActive 两个布尔折叠为 cursor >= 0 + searchBoxFocused()
  6. JEI API 现代化castToItemStackType()getItemStack()getTooltip@Nullable Player

🔴 关键

  • StorageServerStub.craftingTakeAll() 存在无限循环风险(服务端线程死循环)while (true) 无任何终止守卫。终止依赖 consumeCraftingInput 改变合成网格,但当配方存在「不消耗型输入」时(getRemainingItemsFor 返回的剩余物与输入完全相同——典型如催化剂/模具类 modded 配方,或水桶做无限水源的 mod),新 consumeCraftingInputgrid.set(i, left.copy()) 写回的是与输入相同的物品,网格永不变化assembleCraftingResult 每次返回相同产物 → 服务端 RPC 线程死循环,冻结服务器。建议:consume 前后比对网格(或输入栈)是否变化,无变化立即 break;或加最大迭代次数上限。

⚠️ 警告

  • placeCraftingResult 部分插入时丢弃并继续循环view.insert 返回 0 < inserted < count 时丢弃剩余但返回 true,循环继续下一次合成 → 仓储只剩少量空间时反复「合成→部分放入→丢弃」,浪费且产出不可控。建议部分插入时也 break 截断。
  • grantIdToFirstShulkerContainerfindPlayerShulkerContainer 交互 — 混合场景(槽 0 的集装箱无 UUID、槽 1 的有 UUID):findPlayerShulkerContainer 先命中槽 1,grant 分支永不执行,「最靠前」实际语义变成「最靠前且有 UUID 的」。行为可接受但建议注释说明。
  • 批量合成阻塞时长craftingTakeAll 单次 RPC 内连续合成(几百次)都在服务端线程完成,无分帧/进度回传,客户端只能等最终结果;量大时注意卡顿。

💡 建议

  • consumeCraftingInput 的「整槽清空 → 每槽 −1」是本 PR 最有价值的修复(原 bug:取 1 个结果消耗整叠 64 材料),建议在 PR 描述中明确标注这是行为修复,便于 changelog。
  • StorageScreen 结果槽 tooltip 可提示「Shift+点击取全部」。

🟢 看起来不错

  • ShulkerBoxesStorage/ShulkerBoxesItemHandler 删除彻底——全仓 git grep SHULKER_BOXES 仅剩 vanilla 的 BlockTags.SHULKER_BOXES(无关),无残留引用;findTerminalStacksourceReachablegetView 的 switch 分支同步清理干净
  • TerminalItem.canInsertInto() = false 修复了终端被当 Bundle 收纳的交互,语义清晰
  • cursor/searchBoxFocused() 状态合并重构行为等价(reset() 复位 −1、refresh() 仅在选择有效时 clamp,均正确)
  • 删除的 DataComponents/ItemContainerContents import 同步清理;assembleCraftingResult 抽取后单取路径行为等价(已验证旧 craftingTakeResult 逻辑逐行比对)
  • @SuppressWarnings 收窄准确,无滥用

📋 声称验证表

声称(bug fix) 状态 对应实现
修复仓储系统问题 潜影终端重构(不再聚合潜影盒)、取结果消耗修复、Shift 取全部、终端交互修复、浮窗状态合并
取合成结果消耗正确性 consumeCraftingInput 每槽 −1 + 剩余物(桶/碗)保留
潜影终端连接目标修正 findPlayerShulkerContainer + grantIdToFirstShulkerContainer + 世界集装箱兜底

结论: REQUEST_CHANGEScraftingTakeAllwhile(true) 需要终止守卫(不消耗型输入会死循环冻结服务端)。其余修改质量高、清理彻底,修好该点后即可合并。

由 Hermes Agent 审查

@Gugle2308

Copy link
Copy Markdown
Collaborator

💾 Self-improvement review: Patched SKILL.md in skill 'github-webhook-pr-review' (1 replacement). · Patched SKILL.md in skill 'anvilcraft-storage-system-review' (1 replacement).

@Gugle2308

Copy link
Copy Markdown
Collaborator

⚠️ Dangerous command requires approval:

cd /opt/data/workspace/AnvilCraft && echo "=== computeValidAction ==="; grep -n -B3 -A8 "computeValidAction" src/main/java/dev/dubhe/anvilcraft/item/BundleLikeItem.java | head -20; echo "=== Screen.ha...

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
Collaborator

en_ud 的翻转值与 en_us "Need Crafting Table and Stonecutter in the storage" 的 180° 翻转一致("ǝᵷɐɹoʇs ǝɥʇ uᴉ ɹǝʇʇnɔǝuoʇS puɐ ǝꞁqɐ⟘ ᵷuᴉʇɟɐɹƆ pǝǝN" = 逆序+翻转的 "Need Crafting Table and Stonecutter in the storage")✅

所有交叉验证完成。gh auth 已失效(token invalid),无法修改 PR 标题——但审查内容不受影响。现在输出审查意见。

代码审查摘要 — PR #4668

操作: synchronize
范围: 14 个文件(12 Java, 2 生成资源)/ 965 行 diff
分支: fix/1.21/1.6 → dev/1.21/1.6(1.21.x,非 26.1 迁移,跳过 API 迁移健康度检查)

📋 变更概览

本 PR 修复仓储系统多处 bug,核心分四块:

  1. Shift 点击批量合成(新增 craftingTakeAll RPC + placeCraftingResult + 提取 assembleCraftingResult
  2. 移除潜影终端"聚合普通潜影盒"功能(删除 ShulkerBoxesStorage/ShulkerBoxesItemHandler/findShulkerBoxes/RemoteTarget.SHULKER_BOXES,改为仅连接潜影集装箱,空箱惰性授予 UUID)
  3. 终端浮窗状态重构selected/keyboardActive 两个布尔合并为 cursor == -1 语义 + searchBoxFocused()
  4. Bundle/终端交互修复(新增 canInsertInto 覆写,终端点击放行 vanilla 交换)
  5. 杂项:tooltip 文案键重命名(missing_workbench_or_stonecuttermissing_workbench)、JEI API 现代化、注解清理

🔴 关键

  • StorageScreen.java:2029-2052(新增 Shift 取全部)— 多物品连续取走时飞行动画缺失craftingTakeAll 一次返回最终 carriedany,但客户端 only 知道"是否有产出",不知道每步产出的单个物品。若一次 Shift 连合出多种物品(如先合出 A 再合出 B),飞行动画只会飞最后一个 carried 物品(takeFuture 回调里 animateResult(result) 大概只处理最终结果),中间产物没有动画/音效。建议:要么在服务端返回每步产物列表让客户端逐项动画,要么至少保证最后一项动画完整。需确认 StorageScreen 回调如何处理多物品。

  • StorageServerStub.placeCraftingResult(L565-605)— 仓储部分插入时产物可能因"后续插入 0"而错误丢弃view.insert(resource, count) 内部对每个 storage 调 insertIntoinsertInto 对空栈返回 0。虽然 result 非空,但若 canStore(primary, result) 为 false(如产物是潜影集装箱/终端),insert 直接返回 0 → 走 inserted == 0 → 返回 false → 外层 craftingTakeAll 丢弃整个产物。这与注释"部分放入仓储时剩余部分丢弃"的预期不一致——产物既没进仓储也没进背包就被 player.drop 丢弃了。实际上 canStore 返回 false 时产物应该直接进背包而非丢弃。建议在 placeCraftingResult 中当 inserted == 0 时回退到背包/直接返回 false(不丢弃),由调用方决定。

⚠️ 警告

  • StorageServerStub.craftingTakeAll(L508-529)— 无限循环风险(低概率)assembleCraftingResult 返回非空但 consumeCraftingInput 后输入未减少时(如自定义配方 assemble 产物非空但 getRemainingItems 也返回非空且输入槽无净消耗的边界配方),while(true) 会死循环。vanilla 配方通常不触发,但 mod 环境有自定义配方风险。建议加最大迭代次数(如 64 或 256)保险。

  • StorageServerStub.grantIdToFirstShulkerContainer(L731-751)— 多次调用重复授予:空集装箱无 UUID 时每次打开终端都会授予新的随机 UUID(旧 UUID 的 StorageRef 被覆盖,旧存储数据可能泄漏为孤儿)。首次授予后 ref.id() 已 present,后续 grantIdToFirstShulkerContainer 会跳过——但同一 tick 内 openRemoteterminalStorages 的调用顺序若导致重复授予,可能产生孤儿 UUID。建议授予前检查是否已有有效 id,且授予后立即持久化。

  • TerminalRemoteOverlay.javasearchBoxFocused() 语义变化:原 keyboardActive 由 Tab 键显式切换,新实现依赖 searchBox.isFocused()。若 ensureSearchBox() 未在点击搜索框时同步 setFocused(true)(diff 中 mouseClicked 确实调用了 setFocused(true) ✅),行为等价。但 charTypedisFocused() 为 false 时直接 return false,原代码在 keyboardActive=true 但 searchBox 未聚焦时也放行——现在聚焦状态完全绑定 searchBox,若用户 Tab 接管后点其它地方导致 focus 丢失,键盘会意外放行。需确认 ensureSearchBox() 在渲染时是否重置 focus。

  • JeiBlockIngredientUtil.java 新增 javax.annotation.Nullable:项目 AGENTS.md 明确要求 nullness 注解只用 JSpecifyorg.jspecify.annotations),禁止 javax.annotation。此 PR 在 getTooltip 参数加了 @Nullable Player 用的是 javax——与项目规范冲突,应改用 org.jspecify.annotations.Nullable

  • TerminalJeiTransferSupport.java(L364-370)getItemStack().ifPresent(variants::add):旧代码 castToItemStackType() 检查 null 后再 add;新代码用 Optional。行为等价 ✅,但若 JEI 版本中 getItemStack() 对非 ItemStack 类型返回 empty Optional 而旧代码 castToItemStackType() 也返回 null——等价。无问题,仅确认 JEI 版本兼容。

💡 建议

  • StorageScreen.java — Shift 取全部时,interactionPending/interactionRequest 竞态:craftingTakeAll 是长操作,期间用户再次点击可能使 request 失效。当前 request != this.interactionRequest 检查能兜底 ✅,但建议在取全部期间禁用按钮点击(taking 标志)。
  • StorageServerStub.craftingTakeResult 抽取assembleCraftingResult 提取后单次取走逻辑完全等价 ✅,代码更清晰。
  • ScreenLang.java + lang 文件 — tooltip 键重命名一致性:en_us/en_ud 已同步更新 ✅,但中文语言文件(zh_cn)未在 diff 中(仓库仅 en_us/en_ud 生成,zh_cn 可能走 weblate 或不存在——已确认目标分支只有 en_us/en_ud 两个生成 lang)。若 zh_cn 由外部维护则无需处理。
  • TerminalRemoteOverlay.reset()cursor = -1 初始化 ✅ 修复了原先 cursor = 0 导致"未选择却选中第一格"的旧 bug,行为更正确。

🟢 看起来不错

  • craftingTakeAllplaceCraftingResult 插入顺序(指针 → 背包 → 仓储)合理,且部分插入时 rest.shrink(inserted) 安全(insertInto 空栈返回 0 不会导致 shrink 溢出)
  • consumeCraftingInput 修复:原代码把所有非剩余槽置 EMPTY(一次合成消耗整组),新代码每槽只减 1(原版语义),且剩余物(桶/碗)正确保留——这是实质 bug 修复 ✅
  • 潜影终端移除聚合普通潜影盒:删除完整(目标分支上 SHULKER_BOXES/findShulkerBoxes/ShulkerBoxesStorage/ShulkerBoxesItemHandler 全部引用点都在 StorageServerStub.java 内部且被 PR 全部删除,无跨文件残留)✅
  • BundleLikeItem.canInsertInto:终端类覆写为 false 放行 vanilla 交换,收纳类默认 true,设计清晰 ✅
  • cursor == -1 语义统一hasSelection()/mouseClicked/mouseScrolled/refresh 全部一致,消除了原先 selected/keyboardActive 双布尔的状态混乱 ✅
  • en_ud 翻转正确:与 en_us 新文案 "Need Crafting Table and Stonecutter in the storage" 的 180° 翻转完全一致 ✅

📋 声称验证表

声称 状态 对应文件
修复仓储系统 bug StorageServerStub, StorageScreen, TerminalRemoteOverlay 等 12 Java 文件
Shift 批量合成 StorageClientStub.craftingTakeAll, StorageServerStub.craftingTakeAll, StorageScreen
移除潜影盒聚合 StorageServerStub(删除 ShulkerBoxesStorage 等)
潜影箱 UUID 惰性授予 grantIdToFirstShulkerContainer
浮窗状态重构 TerminalRemoteOverlay(selected/keyboardActive → cursor)
Bundle/终端交互 BundleLikeItem.canInsertInto, TerminalItem

结论: REQUEST_CHANGES — 两个关键问题(多物品动画缺失、仓储部分插入时产物被丢弃)需修复后再合并;另有 javax Nullable 规范冲突与死循环保险建议。

注:gh auth status 显示 token 已失效(X Failed to log in),无法执行 gh pr edit 修改 PR 标题。标题 "synchronize: Fix bugs about storage system 修复仓储系统相关问题" 已足够清晰,无需修改。

@Gugle2308

Copy link
Copy Markdown
Collaborator

💾 Self-improvement review: Patched SKILL.md in skill 'github-webhook-pr-review' (1 replacement). · Patched SKILL.md in skill 'anvilcraft-storage-system-review' (1 replacement).

@Gugle2308

Copy link
Copy Markdown
Collaborator

The javax.annotation.Nullable usage is pre-existing on the target branch (consistent with existing code, not introduced by this PR). I have completed a thorough review. Let me compile the final review.

代码审查摘要 — PR #4668

操作: synchronize
范围: 15 个文件 (13 Java, 2 lang) / 1003 行 diff

PR 标题: synchronize: Fix bugs about storage system 修复仓储系统相关问题


变更概览

模块 变更
潜影终端 删除「聚合多个潜影盒」路径(ShulkerBoxesStorage/ShulkerBoxesItemHandler/SHULKER_BOXES),仅保留潜影集装箱目标;新增空集装箱打开时惰性授予 UUID(grantIdToFirstShulkerContainer
Shift 批量合成 新增 craftingTakeAll RPC + StorageScreen Shift 点击③/④ 结果槽取全部产物
合成消耗修复 consumeCraftingInput 修复每槽只消耗 1 个、剩余物(桶/碗)保留
终端浮窗状态 selected/keyboardActive 两个布尔合并为 cursor = -1 哨兵 + searchBoxFocused()
终端槽位交互 TerminalItem.canInsertInto=false 放行 vanilla 交换,BundleLikeItem 新增 canInsertInto 钩子
CategoryButton 允许右击(isValidClickButton 放行 button 1)
杂项 浮窗文案修正、JEI getItemStack() 简化、UI 点击音效

🔴 关键问题

  1. craftingTakeAll 无限循环风险(配方产物可堆叠且大量材料时)

    • rpc/StorageServerStub.java craftingTakeAll()while(true) 循环。placeCraftingResult 把产物放入指针/背包/存储后 consumeCraftingInput 每槽只消耗 1 个材料。若材料充足且存储有空间,将连续合成数百上千个产物,客户端一次 RPC 请求内同步执行,服务端 tick 可能卡顿。
    • 建议:加单次调用上限(如 64 或 256 个),或改为分块(每 tick 合成 N 个)。
    • 参考:consumeCraftingInput 新逻辑 shrunk.shrink(1)(每槽消耗 1),配合大材料堆,单次调用可产生大量物品。
  2. craftingTakeAll 放置产物失败时物品语义不一致

    • placeCraftingResultcarried.isEmpty()setCarried(result) 直接放入指针;但未调用 consumeCraftingInput 之前,craftingTakeAll 的循环是 placeCraftingResult 成功后才 consumeCraftingInput。若 placeCraftingResult 成功但 consumeCraftingInput 抛异常(如 getRemainingItemsFor 对非标准配方返回异常),产物已入背包但输入未消耗 → 物品复制。虽然 assembleCraftingResult 先计算不消耗,但产物入包与输入消耗非原子,异常时可能不一致。
    • 低概率但建议将 consumeCraftingInput 放入 try/catch 或先消耗再放置(若放置失败再回滚)。
  3. grantIdToFirstShulkerContainer 的 UUID 授予时机

    • openRemote 中:findPlayerShulkerContainer 找不到 → grantIdToFirstShulkerContainer 授予。但授予的是「身上槽位最靠前的无 UUID 集装箱」,而 findPlayerShulkerContainer 找的是「有 UUID 的集装箱」。若玩家有多个集装箱,第一个无 UUID 的会被授予并连接——符合注释「优先连接身上槽位最靠前的潜影集装箱」。但注意:授予的 UUID 写回物品 STORAGE 组件,若玩家把该集装箱放入箱子/丢弃,UUID 仍保留。多次打开/关闭终端时,grantIdToFirstShulkerContainer 会为每个无 UUID 集装箱授予不同 UUID,但 shulkerTerminalStorages 只解析会话 ID(shulkerTerminalId(playerId)),不会重复授予——逻辑自洽,但潜在问题grantIdToFirstShulkerContainer 每次 openRemote 只授予一个,若玩家有两个无 UUID 集装箱,第二次打开会授予第二个,第三次又回到第一个(有 UUID 了)→ 目标在两次打开间切换。建议确认这是预期行为。

⚠️ 警告

  1. craftingTakeAll 的存储插入可能部分成功

    • placeCraftingResult 调用 view.insert(result.copyWithCount(1), result.getCount())StorageView.insert 在多存储间分片插入,若 inserted < amount(部分放入),代码 rest.shrink(inserted); player.drop(rest) 丢弃剩余——丢弃是合理回退,但未通知客户端。低概率,存储几乎满时会出现物品「消失」成掉落物。可接受但值得记录。
  2. CategoryButton.isValidClickButton 允许右击,但 onClickchangeMode(button == 1)

    • changeMode(button == 1) 右击切换模式。super.onClick 会触发 onPress。需确认 CategorySettingsScreencategoryOnPress 对右击的处理(该 PR 未改 CategorySettingsScreen,但 CategoryList 的按钮右击现在会触发 onPress——检查是否有副作用)。
  3. TerminalRemoteOverlay charTyped 在未聚焦时吞掉 Tab

    • charTyped 前置 searchBoxFocused() 判断,未聚焦返回 false 放行。但 keyPressed 中未聚焦分支:非 Tab 键 return false(放行),Tab 键聚焦。逻辑正确。但 mouseClicked 中点击搜索框 setFocused(true)keyboardActive 被移除,改用 searchBoxFocused() 判断——行为等价,验证通过。
  4. StorageScreen clickCraftingResult Shift 分支缺少音效

    • 普通 craftingTakeResult 无音效,但 clickCraftingRecipe 新增了 UI_BUTTON_CLICK 音效。Shift 取全部(craftingTakeAll)无音效反馈——不一致但非 bug。

💡 建议

  1. placeCraftingResultcarried 合并检查可提前

    • carried.isEmpty() 分支直接 setCarried(result),但 craftingTakeAll 循环下一次迭代会重新读取 carriedgetCarried),若产物堆叠上限 < 结果数量,ItemStack.isSameItemSameComponents + getMaxStackSize 检查会正确拒绝——逻辑正确,仅建议代码顺序优化。
  2. en_ud.json 仅更新了一个 key — 确认 missing_workbench_or_stonecutter 在 en_ud 中也被替换为 missing_workbench(diff 显示 en_ud 有对应变更)。zh_cn 等其他语言文件未在 diff 中(该仓库 lang 目录只有 en_ud/en_us,符合项目现状)。

  3. JeiBlockIngredientUtilgetTooltip 重载

    • @SuppressWarnings("removal") 标记保留。JEI 19.50.0.414 API 的 getItemStack() 返回 Optional<ItemStack>,替代 castToItemStackType() 更简洁——正确。

🟢 看起来不错

  • consumeCraftingInput 修复:从「整槽清空」改为「每槽消耗 1 个 + 剩余物保留」,修复了之前合成时桶/碗等剩余物被错误清空的问题,符合原版合成语义。
  • 潜影终端聚合删除ShulkerBoxesStorage/ShulkerBoxesItemHandler 整个删除,无残留引用(grep SHULKER_BOXES 干净),RemoteTarget.SHULKER_BOXES 常量删除且所有 switch 分支同步更新。
  • TerminalRemoteOverlay 状态合并selected + keyboardActivecursor = -1 哨兵 + searchBoxFocused()reset() 正确重置 cursor = -1refresh()cursor >= 0 才 clamp(避免 -1 被钳到 0 导致未选择却高亮),逻辑严密。
  • isValidClickButton 右击支持:CategoryButton 现在右击可切换模式,符合 onClickchangeMode(button == 1) 的既有设计意图。
  • 新 lang key missing_workbench 文案 "Need Crafting Table and Stonecutter in the storage" 与 craftingAvailable 服务端判定(workbench AND stonecutter 均需)一致。

📋 声称验证表

声称 状态 对应文件
修复仓储系统相关问题 StorageServerStub, StorageScreen, TerminalRemoteOverlay 等 13 个 Java 文件

结论: COMMENT — 修复质量整体较高(潜影终端聚合删除干净、合成消耗语义修复正确、终端浮窗状态机重构严密),但 craftingTakeAll 的无限循环风险(大量产物单次合成)与产物放置/输入消耗非原子性建议修复后合并。若接受当前行为(单次 Shift 批量合成,产物可堆叠),则此 PR 可 APPROVE;建议至少为 craftingTakeAll 增加单次数量上限。


由 Hermes Agent 审查

@Gugle2308

Copy link
Copy Markdown
Collaborator

💾 Self-improvement review: Patched SKILL.md in skill 'anvilcraft-storage-system-review' (1 replacement).

@Gugle2308

Copy link
Copy Markdown
Collaborator

gh token 已失效(Gugle2308 的 token invalid),但本 PR 标题「synchronize: Fix bugs about storage system 修复仓储系统相关问题」已包含英文+中文格式且准确描述变更,无需修改标题(约束 7 不触发)。审查完成。

代码审查摘要 — PR #4668

操作: synchronize
范围: 15 个文件(13 Java + 2 生成语言文件)/ 1208 行 diff(无新增/删除文件,无 EOF 缺换行)

变更概览

仓储系统 bug 修复 PR,四组核心变更:

  1. Shift 连续合成(take-all):新增服务端 craftingTakeAll RPC(分块,单次最多 64 次合成)+ 客户端 takeAllChunk 递归循环,替代单次 craftingTakeResultcraftingTakeResult 内的配方计算提取为 assembleCraftingResult 复用
  2. 潜影终端简化:删除 SHULKER_BOXES 聚合目标(vanilla 潜影盒聚合视图)及整个 ShulkerBoxesStorage/ShulkerBoxesItemHandler(约 240 行);连接目标收敛为「身上最靠前的潜影集装箱(打开时惰性授予 UUID)」或「64 格内最近世界潜影集装箱」
  3. 终端浮窗交互修复selected/keyboardActive 两个布尔态合并为 cursor == -1 哨兵;新增 CategoryButton.isValidClickButton 允许右键;新增 canInsertInto 门控修复「手持物品点击终端槽被 insertOne 吞掉」的 bug
  4. 杂项:切石机配方选择补点击音效、JEI tooltip API 现代化(getItemStack().ifPresent)、lang key 重命名

🔴 关键

无阻塞性问题。

⚠️ 警告

  • StorageServerStub.craftingTakeAll — 指针持有异种物品时产物被静默丢弃placeCraftingResult 在 carried 非空且与产物异种时返回 NONEplayer.drop(result, false) 把产物直接扔地上,同时 done=true 截断。这与原版合成语义(指针异种时拒绝取出、不消耗输入)不一致——玩家手里拿着别的东西 Shift 点④ 时,材料被消耗、产物掉地上,且 changed=true 客户端只刷新面板,玩家可能注意不到。建议改为「不消耗、立即截断返回 done=true」,或至少明确告知。
  • craftingTakeAll 无输入校验的 RPC 暴露面craftingTakeResult 原有「指针不兼容先拒绝、避免误消耗输入」的保护,craftingTakeAll 里产物直接落背包/仓储。若玩家在打开仓储界面的同时用另一个设备/物品栏操作改变了背包布局,循环内的 placeCraftingResult 每次都是实时读背包,行为仍是安全的,只是要注意 StorageAccessValidator 只校验访问权,不校验玩家当前 GUI 状态。

💡 建议

  • StorageScreen.takeAllChunk 递归链:64 块 × 每块 64 次 = 最多 4096 次合成,全部串行 RPC 在 screenExecutor 排队;虽然每次 whenCompleteAsync 让出事件循环,但高延迟网络下可能卡顿数秒。建议分块上限调小(8~16)或每 tick 处理一块节流。非阻塞。
  • 旧 lang key missing_workbench_or_stonecutter:本 PR 内引用已全部更新(ScreenLangStorageScreen、en_us/en_ud),但仓库内可能还有第三方文档/Jade 集成引用,建议 grep 确认。
  • TerminalRemoteOverlay.searchBoxFocused()BooleanMethodIsAlwaysInverted 抑制合理;「搜索框聚焦 = 键盘接管」的不变量依赖 ensureSearchBox() 调用时机,注释已覆盖,可保持。

🟢 看起来不错

  • 潜影终端删除聚合视图:240 行直接读写潜影盒 minecraft:container 组件的复杂 handler 完全移除,跨文件删除完整性良好——RemoteTarget.SHULKER_BOXESfindTerminalStack case、sourceReachablegetViewshulkerTerminalStorages 全部收敛到单一 SHULKER_CONTAINER,无残留引用(已用 git grep 验证目标分支)。
  • findOrGrantFrontmostShulkerContainer 惰性授予设计:只在 openRemote(右键打开)时授予 UUID 并 broadcastChanges,只读路径(悬停可达性、JEI 补库、均衡)不写回物品组件,避免悬停时意外持久化——设计正确。
  • craftingTakeAll 防御性终止:材料耗尽 / 无处可放 / 不消耗型配方(consumeCraftingInput 返回 false)三重终止 + 分块上限,注释清晰,杜绝服务端 RPC 线程死循环。
  • consumeCraftingInput 修复了原版 remaining 语义 bug:旧代码 i >= remaining.size() || remaining.get(i).isEmpty() 会把「无剩余物的槽」清空——但若配方有剩余物(如桶)则保留;新代码逐槽 shrink 1 个 + remaining 替换,语义更接近原版合成。
  • BundleLikeItem.canInsertInto 门控:终端类物品覆写 false 放行 vanilla 交换,修复手持物品点击终端槽被吞的问题,且默认 true 保持 Bundle/收纳类行为不变。

📋 声称验证表

声称 状态 对应文件
修复仓储系统相关问题(Shift 连续合成) StorageServerStub.craftingTakeAll/assembleCraftingResult/placeCraftingResult/consumeCraftingInput, StorageScreen.takeAllChunk/MAX_TAKE_ALL_CHUNKS, StorageClientStub.craftingTakeAll
修复仓储系统相关问题(潜影终端) StorageServerStub(删 SHULKER_BOXES/ShulkerBoxesStorage、findOrGrantFrontmostShulkerContainerfindBoundPlayerShulkerContainer
修复仓储系统相关问题(终端浮窗交互) TerminalRemoteOverlay(cursor 哨兵合并状态)、CategoryButton.isValidClickButton
修复仓储系统相关问题(手持物品点击终端槽) BundleLikeItem.canInsertInto + TerminalItem 覆写

结论: APPROVE — 变更质量高,跨文件删除完整,防御性逻辑周到。craftingTakeAll 的「异种指针产物落地」语义偏差建议后续跟进(非阻塞)。PR 标题已含中英文且准确,无需修改(注:gh token 已失效,本次未做任何评论/标题操作)。


由 Hermes Agent 审查

@Gugle2308

Copy link
Copy Markdown
Collaborator

💾 Self-improvement review: Patched SKILL.md in skill 'anvilcraft-storage-system-review' (1 replacement).

@QiuShui1012
QiuShui1012 marked this pull request as ready for review September 1, 2026 07:27
@PigeonNian
PigeonNian merged commit 38c1323 into Anvil-Dev:dev/1.21/1.6 Sep 1, 2026
2 checks passed
@Gugle2308

Copy link
Copy Markdown
Collaborator

PR #4668 状态为 closed(已于 2026-09-01 合并),按约束规则(closed/labeled → stop here,不发布评论),本次不输出审查意见,不发表任何评论。

@Gugle2308

Copy link
Copy Markdown
Collaborator

⚠️ Iteration budget exhausted (90/90) — asking model to summarise

@Gugle2308

Copy link
Copy Markdown
Collaborator

I reached the maximum iterations (90) but couldn't summarize. Error:

<title>504 Gateway Time-out</title>

504 Gateway Time-out


openresty

@Gugle2308

Copy link
Copy Markdown
Collaborator

💾 Self-improvement review: Patched SKILL.md in skill 'anvilcraft-storage-system-review' (1 replacement).

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