Fix wrong behaviour in storage systems 修复存储系统中的错误行为#4190
Conversation
…port custom category and player inventory display
|
现在我拥有所有必要信息来提供全面的审查。 代码审查:PR #4190 — 修复存储系统中的错误行为作者: QiuShui1012 架构概览本次 PR 是一次重大的存储系统 UI 重构,将界面从原版 Minecraft 的
1. 修复:三种大型多方块无法打开界面 ✅根因定位正确。 大型储箱(LargeCrate)、超维存储站(HyperdimensionStorageStation)和潜影贝容器(ShulkerContainer)在获取 BlockEntity 时使用了点击位置的原始 // ❌ 旧代码(错误):直接使用点击位置 pos
BlockEntity blockEntity = level.getBlockEntity(pos);
// ✅ 新代码(正确):获取主块坐标再查 BE
BlockEntity blockEntity = level.getBlockEntity(this.getMainPartPos(pos, state));这解释了为何只有大型多方块无法打开界面——小型 CrateBlock 是单方块结构,不受此影响(CrateBlock 未使用 所有四个存储方块统一采用了 2.
|
| 类别 | 结果 | 备注 |
|---|---|---|
| 正确性 | 多方块修复正确;reorder 空方法、死代码需清理 | |
| 安全性 | ✅ | 无硬编码密钥;spectator 检查正确 |
| 序列化兼容 | PlayerSetting.storageSettings → storage 需迁移路径 |
|
| 代码质量 | ✅ | 整体重构清晰,职责分离好 |
| 死代码 | 注释掉的 checkHotbarKeyPressed 应删除 |
|
| 测试 | ❓ | 未看到测试文件变更(RPC stub 功能建议添加 unit test) |
| 语言 | ✅ | 中/英同步,无残留 |
| 删除完整性 | ✅ | 旧类完全移除,无残留引用 |
结论
基本通过,建议修复以上 3 个
- 删除
StorageScreen.java中注释掉的checkHotbarKeyPressed死代码块 - 填充或标记
StorageServerStub.reorder()的空方法体(至少加// TODO注释) - 评估
PlayerSetting.storageSettings→storage序列化变更的向后兼容性影响,必要时添加迁移码
…when outputting them into storage blocks
|
现在我对整个 PR 有了全面的了解,让我生成审查报告。 代码审查摘要 — PR #4190操作: synchronize 概览本 PR 对存储系统 GUI 进行了重大重构:
🔴 关键问题1. StorageServerStub 静态 STUBS 映射可能泄漏
2. 界面关闭时携带物品可能掉落(低风险)
|
| 声称 | 状态 | 对应文件 |
|---|---|---|
| #3582 主界面 — 玩家物品栏 | ✅ | StorageScreen.java — Screen 化重构,直接渲染 Inventory 槽位并处理输入 |
| #3582 类别设置 — 添加自定义类别 | ✅ | CategorySettingsScreen.java — 独立 Screen,管理 FilterCategory 的 listed/alternate |
| 拆分主界面和类别设置界面 | ✅ | 旧 CategorySetting widget 删除 + StorageScreen 中将设置打开改为跳转 CategorySettingsScreen |
| 修复三种大型多方块无法打开界面 | ✅ | HyperdimensionStorageStationBlock.java、LargeCrateBlock.java、ShulkerContainerBlock.java — 全部使用 getMainPartPos() |
| 架构迁移:Menu → Screen + RPC | ✅ | 新建 4 个 RPC stub 文件 + 删除 StorageMenu.java + 移除 MenuProvider 实现 + 移除 ModMenuTypes.STORAGE 注册 |
✅ 看起来不错
- 四类方块(CrateBlock + 三个多方块)的
useItemOn统一实现了新模式,代码结构一致 DistExecutor.run(Dist.CLIENT, ...)正确限制了客户端侧的屏幕打开OwnSettingValidator和StorageAccessValidator提供了合理的 RPC 安全检查- 删除
StorageMenu时同步删除了ModMenuTypes.STORAGE注册和StorageScreen的AbstractContainerScreen继承,清理完整 - Gradle 依赖
anvillib升级到2.0.0+snapshot.492(支持新 RPC 功能) - 所有 lang key 变更与 ScreenLang.java 中的更新一致
- 旧网络包
StoragePackets.sync的引用已被完全移除
结论: COMMENT — PR 代码质量较高,架构迁移设计合理,多方块 bug 修复正确。主要问题 STUBS 映射泄漏和 removed() 中物品掉落风险当前影响有限,建议在后续迭代中处理。无阻塞性问题。
Reason: script execution via -e/-c flag Reply |
|
现在我已全面理解了所有变更。以下是完整审查报告。 代码审查摘要 — PR #4190操作: 变更分类
🔴 关键1.
2.
3.
|
Reason: script execution via -e/-c flag Reply |
|
我现在已经有了对本次 PR 的全面了解。让我输出审查意见。 代码审查摘要 — PR #4190操作: edited 架构变更概览本次 PR 对存储系统做了重大的架构重构:
✅ 关键问题修复验证🔴 1. 存储方块"吞物品" — 已修复 public ItemStack quickMoveStack(Player player, int slotIndex) {
return this.getSlot(slotIndex).getItem(); // ← 经典"吞物品"存根!
}此实现违反 🔴 2. 大型多方块无法打开界面 — 已修复 // 旧(使用点击位置)→ 对于子方块,getBlockEntity(pos) 返回 null
BlockEntity blockEntity = level.getBlockEntity(pos);
// 新(归一到主块位置)
BlockEntity blockEntity = level.getBlockEntity(this.getMainPartPos(pos, state));涉及: 🔍 新增代码审查3.
4.
5. private static final Map<UUID, StorageServerStub> STUBS = new HashMap<>();
6.
📋 声称验证表
🟢 看起来不错
|
Reason: script execution via -e/-c flag Reply |
|
以下是 PR #4190 的代码审查。 PR #4190 — 审查:存储系统行为修复总览: 44 个文件变更,4364 行 diff。这是一次重大的存储系统架构重构,从 ✅ 核心问题修复1. 多方块 UI 无法打开 ✅涉及文件: 旧代码使用 修复: 改为 - BlockEntity blockEntity = level.getBlockEntity(pos);
+ BlockEntity blockEntity = level.getBlockEntity(this.getMainPartPos(pos, state));
2. 存储方块吞物品 ✅涉及文件: 旧代码的 public ItemStack quickMoveStack(Player player, int slotIndex) {
return this.getSlot(slotIndex).getItem(); // ← 经典吞物品 bug!
}这是 Shift+点击吞物品的经典 bug—— 3. 主界面与类别设置界面拆分 ✅
🔄 架构变更RPC 迁移(从自定义网络包 → anvilcraft-lib RPC)
优点: 类型安全、
类别系统重构
关键的架构决策:
|
| 项目 | 状态 | 备注 |
|---|---|---|
| 正确性 | ✅ | 多方块 BE 定位已修复;quickMoveStack 吞物品 bug 已消除 |
| 安全性 | ✅ | 携带物品清空、RPC 验证器、玩家 ID 校验 |
| 代码质量 | ✅ | 干净的架构迁移,IClientCategory → ICategory,FilterContent 更精确 |
| 测试 | 无法从 diff 确认测试覆盖。removed() 中的携带物品清空逻辑值得写测试 |
|
| 性能 | 排序缓存清除策略可能在大存储/高更新频率下成为瓶颈 | |
| 文档 | ✅ | 新增 lang 键完整;PlayerSettings.getSetting(UUID) 的 Javadoc 提示了参数类型 |
| 数据兼容性 | PlayerSetting 存格式破坏性变更——确认旧存档是否有迁移方案 |
总结
这是一个设计良好的架构重构,正确解决了所有三个目标问题:
- 多方块 UI —
getMainPartPos修复 ✅ - 吞物品 — 删除有缺陷的
StorageMenu.quickMoveStack✅ - UI 拆分 —
StorageScreen+CategorySettingsScreen独立 ✅
…display in CategoryList
PR #4190 代码审查文件变更: 46 个文件(+2160 / -1437),无 EOF 换行符缺失、无合并冲突 总体架构变更 —— 从 AbstractContainerScreen/Menu 迁移到 Screen + RPC这是本 PR 最核心的变化,解决了存储系统大量的行为错误根源:
1. ✅ 大型多方块无法打开界面的修复四种存储方块( // 旧代码(只取点击位置的BE,对于多方块非主体部位会拿到错误的BE)
BlockEntity blockEntity = level.getBlockEntity(pos);
// 新代码(从任意部位正确找到主方块)
BlockEntity blockEntity = level.getBlockEntity(this.getMainPartPos(pos, state));✅ 关键修复: 另外去掉了 server 端的 2. ✅ FilterContainer 过滤内容校验// 旧
this.content = stack.getOrDefault(ModComponents.FILTER_CONTENT, new FilterContent());
// 新
this.content = Optional.ofNullable(stack.get(ModComponents.FILTER_CONTENT))
.filter(filter -> {
for (ItemStack content : filter.list()) {
if (!content.isEmpty()) return true;
}
return false;
})
.orElse(new FilterContent());✅ 修复了空白过滤器的边缘情况:如果 filter 物品有 3. ✅ FilterContent 增加 equals/hashCode
4. ✅ ICategory 接口简化(删除 HolderHolder + IClientCategory)
5. ✅ PlayerSetting 存储设置变更// 旧: Map<UUID, StorageSetting> storageSettings — 每个存储箱都有自己的设置
// 新: StorageSetting storage — 每个玩家只有一份统一的设置✅ 简化为每个玩家只有一个 6. ✅ StorageSetting 增加 searchContent
7. ✅ RPC 校验器安全
8.
|
| 问题 | 修复方式 | 严重程度 |
|---|---|---|
| 存储方块吞物品(Shift+点击) | 删除 StorageMenu 假槽位,改为纯 Screen + RPC | 🔴 关键 |
| 大型多方块无法打开界面 | getMainPartPos() 取代直接 getBlockEntity(pos) |
🔴 关键 |
| 过滤内容空列表意外行为 | Optional.filter + fallback 到空 FilterContent | 🟡 中等 |
| FilterContent 缺少 equals/hashCode | 实现完整比较方法 | 🟡 中等 |
| 搜索文本关闭后丢失 | StorageSetting 增加 searchContent 字段持久化 | 🟢 改善 |
| 服务端无法使用配方书分类 | RecipeBookCategoryCategory 移至主包、使用 server RecipeManager | 🟢 改善 |
建议:考虑在合适的 lifecycle hook 中清除 StorageServerStub.STUBS 以防止长期运行时缓存泄漏。
总评: 这是一个重大的架构重构(从 Container-based → Screen + RPC-based),一次性解决了存储系统的多个已知 bug。代码质量高,RPC 校验器安全,序列化兼容性被谨慎处理。建议批准合并。
|
现在我已充分分析,可以进行全面审查了。 代码审查摘要 — PR #4190操作: edited 🔴 关键
|
| 声称 | 状态 | 对应文件 |
|---|---|---|
| 主界面拆分(GUI 拆分) | ✅ | StorageScreen(重写为 Screen 子类)、CategorySettingsScreen(新文件) |
| 类别设置拆分 | ✅ | CategorySettingsScreen(新,原 CategorySetting 已删除) |
| 搜索栏 | ✅ | StorageScreen.init 中的 EditBox + SwitchableButton |
| 搜索栏状态按钮 | ✅ | SwitchableButton(SearchMode.CLEAR/RETENTION) |
| 排序方式按钮 | ✅ | SwitchableButton(SortMode.COUNT/MOD/NAME) |
| 排序顺序按钮 | ✅ | SwitchableButton(OrderMode.SEQUENTIAL/REVERSE) |
| NBT 折叠按钮 | ✅ | SwitchableButton(NbtDisplayMode.UNFOLD/FOLD) |
| 类别滚动条 | ✅ | CategoryList 滚动区域从 112 扩展至 160 |
| 添加自定义类别 | ✅ | CategorySettingsScreen + SettingServerStub.addCustom |
| 修复多方块无法打开 UI | ✅ | 4 个 Block 文件的 getMainPartPos 修复 |
| 修复存储方块吞物品 | ✅ | StorageMenu 删除(移除快速移动存根) |
结论: APPROVE — 该 PR 彻底修复了存储系统的架构问题。旧版基于 MenuProvider + AbstractContainerMenu 的方案被干净的 Screen + RPC 架构取代,多个 bug(吞物品、NPE、多方块位置偏移)一次性得到解决。代码质量高,序列化/验证等边缘情况处理得当。
由 Hermes Agent 审查
|
Now I have a complete picture. Let me write the review. 代码审查摘要 — PR #4190操作: synchronize 概述此 PR 将存储系统从
✅ 架构迁移清单(参考 container-screen-rpc-migration-review)
🔴 关键问题1.
|
| 声称 | 状态 | 对应文件 |
|---|---|---|
| 主界面 UI 按钮(4/7/8/9/10/11) | ✅ | StorageScreen.java — SwitchableButton × 4(search/sort/order/nbt) |
| 类别滚动条(14) | ✅ | CategoryList.java — 滚动条区域调整 + extractScrollbar 调用 |
| 类别设置界面拆分 | ✅ | CategorySettingsScreen.java(新增 733 行) |
| 添加自定义类别(2) | ✅ | CategorySettingsScreen — addCategory 按钮 + clickPlayerInventory 选择筛选器 |
| 修复大型多方块无法打开界面 | ✅ | HyperdimensionStorageStationBlock/LargeCrateBlock/ShulkerContainerBlock — 均使用 getMainPartPos(pos, state) |
| 修复存储方块吞物品 | ✅ | StorageMenu.java 删除 — quickMoveStack 存根移除 |
结论: REQUEST_CHANGES — 关键问题 #1(STUBS 内存泄漏)和 #2(序列化不兼容)需要在合并前处理。其他警告和建议为非阻塞性改进。
具体而言:
- 必须为
StorageServerStub.STUBS添加 BE 移除时的逐条清理(而非仅依赖 ServerStopped) - 必须确认
PlayerSetting的序列化格式变更是否影响已有玩家数据
由 Hermes Agent 审查
Reason: Security scan — [MEDIUM] Variation selector characters detected: Content contains Unicode variation selectors (VS1-256). These are commonly used in emoji sequences but may indicate steganographic encoding or obfuscation Reply |
|
已确认 bug。现在整理完整审查。 代码审查摘要 — PR #4190操作: synchronize 核心变更:
🔴 关键问题1. 旧代码( boolean contentIsBlackList = content.blackList();
for (ItemStack itemStack : content.list()) {
if (filter(itemStack, stack, content.includeComponents())) {
return !contentIsBlackList; // 白名单:找到→true; 黑名单:找到→false
}
}
return contentIsBlackList; // 白名单:未找到→false; 黑名单:未找到→true新代码: return content.blackList() == content.filter(stack);
// filter(stack): 找到→!blackList; 未找到→blackList
// 化简结果: 找到→false; 未找到→true —— 永远忽略黑白名单设置!
影响: 所有使用白名单模式的筛选器完全失效——该显示的物品不显示,不该显示的反而显示。黑名单模式碰巧不受影响(因为 修复方案: // 方案 A:直接比较 filter 结果(filter(stack) 返回 true 表示"应放行")
return content.filter(stack);
// 对应修改 filter(stack) 方法,改为统一返回"应放行"语义:
// 找到 → !blackList → 白名单时 true(放行)/黑名单时 false(拒绝) ✅
// 未找到 → blackList → 白名单时 false(拒绝)/黑名单时 true(放行) ✅注意:
|
| 声称 | 状态 | 对应文件 |
|---|---|---|
| #3582 主界面 — 4:玩家物品栏 | ✅ | StorageScreen 重构 |
| #3582 主界面 — 7:搜索栏 | ✅ | StorageScreen + EditBox |
| #3582 主界面 — 8:搜索栏状态按钮 | ✅ | StorageScreen + SearchMode 按钮 |
| #3582 主界面 — 9:排序方式按钮 | ✅ | StorageScreen + SortMode 图标切换 |
| #3582 主界面 — 10:排序正序倒序按钮 | ✅ | StorageScreen + OrderMode 按钮 |
| #3582 主界面 — 11:NBT堆叠显示按钮 | ✅ | StorageScreen + NbtDisplayMode 按钮 |
| #3582 主界面 — 14:类别滚动条 | ✅ | StorageScreen + CategoryList |
| #3582 类别设置 — 2:添加自定义类别 | ✅ | CategorySettingsScreen + addCustom RPC |
| 拆分主界面和类别设置 | ✅ | StorageScreen + CategorySettingsScreen 分离 |
| 三种大型多方块无法打开界面 | ✅ | 3 个 SimpleMultiPartBlock + ShulkerContainerBlock → getMainPartPos |
| 存储方块吞物品 | ✅ | BE 移除 MenuProvider,RPC 替代容器同步 |
| FilterContent equals/hashCode | 实现存在,但白名单逻辑反转 |
结论: REQUEST_CHANGES — FilterContent 白名单筛选逻辑反转是功能性 bug,必须在合并前修复。其他变更(多方块修复、RPC 迁移、UI 拆分)质量良好。
由 Hermes Agent 审查
|
现在我已经全面了解了这个 PR。让我编写完整的审查报告。 代码审查摘要 — PR #4190操作: synchronize 📋 声称验证表
🏗️ 架构概览这是一个完整的 AbstractContainerMenu → Screen + RPC 架构迁移:
🔴 关键问题
|
|
现在我已经全面审视了整个 PR。让我整理审查。 代码审查摘要 — PR #4190分支: 架构概述此 PR 将存储系统从传统
🔴 关键 — 需修复后合并1.
影响范围: # 验证:确认 WRAPPER 是否在旧存档中被使用
grep -rn "wrapped" /opt/data/workspace/AnvilCraft/src/main/java/dev/dubhe/anvilcraft/saved/建议: 如果此分支是活跃开发分支且无需保留玩家存档兼容性,可以接受。否则需要提供
|
| 声称 | 状态 | 对应文件 |
|---|---|---|
| 主界面按钮 4/7/8/9/10/11/14 | ✅ | StorageScreen(搜索栏、搜索模式、排序、正序倒序、NBT折叠、类别列表) |
| 类别设置 2(添加自定义类别) | ✅ | CategorySettingsScreen(独立的类别设置界面) |
| 拆分主界面和类别设置界面 | ✅ | StorageScreen(Screen) + CategorySettingsScreen(Screen)替代旧 CategorySetting widget |
| 修复三种大型多方块无法打开界面 | ✅ | ShulkerContainerBlock, LargeCrateBlock, HyperdimensionStorageStationBlock(getMainPartPos) |
| 修复存储方块会吞物品 | ✅ | StorageMenu.java 删除(quickMoveStack 存根消除) |
结论: APPROVE — 架构重构设计合理,核心 bug 修复正确(多方块 GUI + 吞物品),代码质量明显提升。唯一需要关注的是 ICategory 序列化兼容性问题(WRAPPER 类型删除导致旧存档无法加载),需要根据项目阶段决定是否需要 DataFixer。
由 Hermes Agent 审查
|
现在我已全面了解了这个 PR。让我撰写审查报告。 代码审查摘要 — PR #4190操作: synchronize 📋 声称验证表
🟢 架构亮点从容器系统迁移到 RPC 架构: 这是本次 PR 最核心的改进。旧系统使用 🔴 关键问题
|
|
Now I have a thorough understanding of this PR. Let me compile the review. 代码审查摘要 — PR #4190操作: edited ✅ API 迁移健康度
🔴 关键 — 需修复后合并
|
| 声称 | 状态 | 对应文件 |
|---|---|---|
| #3582-2: 内容物显示 | ✅ | StorageScreen.java(9×6 网格渲染 + RPC sync) |
| #3582-3: 内容物滚动条 | ✅ | StorageScreen.java(scrollRow + SLIDER 纹理) |
| #3582-4: 玩家物品栏 | ✅ | StorageScreen.java(getInventorySlot + handleContainerInput) |
| #3582-7: 搜索栏 | ✅ | StorageScreen.java(EditBox search) |
| #3582-8: 搜索栏状态按钮 | ✅ | StorageScreen.java(SwitchableButton SEARCH_CLEAR/RETENTION) |
| #3582-9: 排序方式按钮 | ✅ | StorageScreen.java(SORT_COUNT/MOD/NAME) |
| #3582-10: 排序正序倒序按钮 | ✅ | StorageScreen.java(ORDER_SEQUENTIAL/REVERSE) |
| #3582-11: NBT堆叠按钮 | ✅ | StorageScreen.java(NBT_UNFOLD/FOLD) |
| #3582-14: 类别滚动条 | ✅ | StorageScreen.java(CategoryList) |
| 类别设置-2: 添加自定义类别 | ✅ | CategorySettingsScreen.java + SettingServerStub.addCustom |
| 拆分主界面和类别设置界面 | ✅ | CategorySetting.java → CategorySettingsScreen.java |
| 修复三种大型多方块无法打开界面 | ✅ | 3 个 block 改用 getMainPartPos |
| 修复存储方块吞物品 | ✅ | quickMoveStack 存根已删除 |
结论: REQUEST_CHANGES — FilterContent.filter() 静态方法的白名单逻辑反转必须修复。除此之外,架构迁移思路清晰、实现完整,所有声称的 feature 均有对应实现。
由 Hermes Agent 审查
|
现在我已经审查完毕。以下是完整的审查意见: 代码审查摘要 — PR #4190结论:🔴 需要修改(3 个关键问题,2 个警告,2 条建议) PR: #4190 — synchronize: Fix wrong behaviour in storage systems 修复存储系统中的错误行为 📋 声称验证表
🔴 关键问题1. ItemStack 不可变性导致服务端物品栏不同步 —
|
代码审查摘要 — PR #4190操作: 📋 声称验证表
🔴 关键 — 需修复后合并
|
|
现在我对 PR 有了全面的了解,让我来撰写审查报告。 代码审查摘要 — PR #4190操作: synchronize 架构概览这是一个重大架构重构:将存储系统从基于
🔴 关键
|
| PR 声称 | 状态 | 对应文件/说明 |
|---|---|---|
| #3582-2: 内容物显示 | ✅ | StorageScreen 完整重写,extractStorageContents() |
| #3582-2.1: 数量字体 | ✅ | FormattingUtil.toAbbrNum() + 小字体 small.json + small.png |
| #3582-3: 内容物滚动条 | ✅ | extractStorageSlider() + mouseScrolled() |
| #3582-4: 玩家物品栏 | ✅ | extractPlayerInventory() 渲染热键栏 + 3 行 |
| #3582-7: 搜索栏 | ✅ | EditBox 搜索组件,SearchMode 按钮 |
| #3582-8: 搜索栏状态按钮 | ✅ | SwitchableButton (CLEAR/RETENTION) |
| #3582-9: 排序方式按钮 | ✅ | SwitchableButton (COUNT/MOD/NAME) |
| #3582-10: 排序正序倒序 | ✅ | SwitchableButton (SEQUENTIAL/REVERSE) |
| #3582-11: NBT 堆叠显示 | ✅ | SwitchableButton (UNFOLD/FOLD) |
| #3582-14: 类别滚动条 | ✅ | CategoryList.extractScrollbar() 新增 |
| #3583: 大板条箱管道兼容 | ✅ | ModCapabilities 已有 LargeCrateBlock 注册(仅空白变更) + TypeLimitItemStacksResourceHandler.updateStacksSize() |
| 拆分主界面和类别设置 | ✅ | CategorySettingsScreen(733 行新文件),StorageScreen 不再内联类别设置 |
| 大型多方块无法打开界面 | ✅ | getMainPartPos() 修复(ShulkerContainer、LargeCrate、HyperdimensionStorageStation) |
| 存储方块吞物品 | ✅ | 移除 StorageMenu(其 quickMoveStack 存根是根本原因),替换为 RPC 交互 |
结论: REQUEST_CHANGES — FilterContent 静态方法中的 blackList == filter(stack) 模式对白名单过滤语义产生了布尔反转。这是一个真实的功能性 bug,需要先修复再合并。其余部分架构健全,是一次很好的重构。
由 Hermes Agent 审查
代码审查摘要 — PR #4190操作: synchronize 🎯 核心变更概述此 PR 对存储系统进行了架构级重构:
🔴 关键问题无。
|
| 声称 | 状态 | 对应文件 |
|---|---|---|
| #3582 主界面 - 内容物显示 (2) | ✅ | StorageScreen.extractStorageContents() — 完整实现 9×6 网格渲染 |
| #3582 主界面 - 数量字体 (2.1) | ✅ | FormattingUtil.toAbbrNum() + StorageScreen.itemDecorations() 用小字体显示 K/M/B |
| #3582 主界面 - 内容物滚动条 (3) | ✅ | StorageScreen.extractStorageSlider() + scrollRow / getMaxScrollRow() |
| #3582 主界面 - 玩家物品栏 (4) | ✅ | StorageScreen.extractPlayerInventory() — 完整渲染 3×9+9 槽位 |
| #3582 主界面 - 搜索栏 (7) | ✅ | StorageScreen.init() — EditBox 搜索框 + SwitchableButton 搜索模式 |
| #3582 主界面 - 搜索栏状态按钮 (8) | ✅ | StorageScreen.init() — Clear/Retention 切换按钮 |
| #3582 主界面 - 排序方式按钮 (9) | ✅ | StorageScreen.init() — Count/Mod/Name 排序切换 |
| #3582 主界面 - 排序正序倒序按钮 (10) | ✅ | StorageScreen.init() — Sequential/Reverse 切换,联动更新图标 |
| #3582 主界面 - NBT 折叠按钮 (11) | ✅ | StorageScreen.init() — Fold/Unfold NBT 模式切换 |
| #3582 主界面 - 类别滚动条 (14) | ✅ | CategoryList.extractScrollbar() — 新增滚动条渲染 |
| #3582 类别设置 - 添加自定义类别 (2) | ✅ | CategorySettingsScreen — 选择物品栏中的 Filter 添加自定义类别 |
| #3583 大板条箱物品管道兼容 | ✅ | ModCapabilities 中 crate/large_crate 的 Item.BLOCK 能力注册保留 |
| 拆分主界面和类别设置界面 | ✅ | StorageScreen 与 CategorySettingsScreen 独立类 |
| 三种大型多方块无法打开界面 | ✅ | CrateBlock/LargeCrateBlock/ShulkerContainerBlock 使用 getMainPartPos() |
| 存储方块吞物品 | ✅ | StorageMenu.quickMoveStack 存根删除 + RPC 化物品交互 |
🔍 交互安全性审查
StorageServerStub.StorageAccessValidator: 每次 RPC 调用都经过以下验证:
- 玩家在线且为
ServerPlayer playerId匹配请求者 UUID(防伪造)sourcePos对应的 BE 是StorageBlockEntity且 ID 非 null- 存储数据在
Storages.get()中存在 stillValid()检查距离/方块状态
SettingServerStub.OwnSettingValidator: 验证 playerId 匹配,防止跨玩家修改设置。
物品操作事务安全: interact、deposit、take 等方法使用 Transaction.openRoot() 包裹 NeoForge 物品传输操作,确保原子性。
结论: APPROVE — 架构重构合理,修复了所有声称的问题(吞物品、多方块 UI、界面拆分),代码质量好,RPC 交互有安全检查。上述 4 个
由 Hermes Agent 审查
Reason: script execution via -e/-c flag Reply |
|
Now I have a comprehensive view of the PR. Let me compile the review. PR #4190 审查:修复存储系统中的错误行为作者: QiuShui1012 | 分支: 规模: 50 文件变更, +3791/-2059 (净增 +1732), 11 新文件, 6 删除文件 总体评价这是一个大型架构重构 PR,将存储系统从传统的 ✅ 重要修复1. 三个大型多方块结构无法打开 GUI(关键修复)文件: // 修复前:在多方块子部件上点击时获取不到 BE
BlockEntity blockEntity = level.getBlockEntity(pos);
// 修复后:先定位多方块主部件再获取 BE
BlockEntity blockEntity = level.getBlockEntity(this.getMainPartPos(pos, state));这是经典的多方块偏移算术错误(参见
2. 存储方块吞物品问题(关键修复)旧代码 ( @Override
public ItemStack quickMoveStack(Player player, int slotIndex) {
return this.getSlot(slotIndex).getItem(); // ← 经典 quickMoveStack 存根!
}这是经典的
// 物品栏→存储
try (Transaction transaction = Transaction.openRoot()) {
int inserted = items.insert(ItemResource.of(stack), stack.getCount(), transaction);
if (inserted > 0) {
transaction.commit();
stack.shrink(inserted);
}
}
// 存储→物品栏
try (Transaction transaction = Transaction.openRoot()) {
int extracted = items.extract(slot, resource, amount, transaction);
if (extracted > 0) {
transaction.commit();
player.getInventory().add(stack.copyWithCount(extracted));
}
}3. 数据组件 Null 安全修复文件: // StorageBlockEntity.applyImplicitComponents
- if (ref.type() != this.storageType) // ← NPE 风险!
+ if (ref == null || ref.type() != this.storageType)
// FilterContainer 构造函数
- this.content = stack.getOrDefault(ModComponents.FILTER_CONTENT, new FilterContent());
+ this.content = Optional.ofNullable(stack.get(ModComponents.FILTER_CONTENT))
+ .filter(filter -> { /* 检查是否有非空内容 */ })
+ .orElse(new FilterContent());✅ 架构变更RPC 系统替代 ContainerMenu
UI 拆分
存储设置去按方块存储化// PlayerSetting 字段变更
- Map<UUID, StorageSetting> storageSettings // 每个存储方块一套设置
+ StorageSetting storage // 每个玩家一套设置
|
| 检查项 | 状态 |
|---|---|
| 多方块 BE 访问修复 | ✅ getMainPartPos 正确 |
quickMoveStack 存根删除 |
✅ 随 StorageMenu 完全删除 |
| Null 安全 | ✅ ref == null 检查, Optional.ofNullable |
| Transaction 包装 | ✅ 所有物品操作使用 Transaction.openRoot() |
equals/hashCode 一致性 |
✅ FilterContent 新增, FilterCategory 删除冗余实现(record 自动生成) |
| 静态集合清理 | ✅ remove() on logout, clear() on server stop |
| 客户端线程安全 | ✅ thenAcceptAsync(..., this.screenExecutor) |
| 翻译完整性 | ✅ en_us + en_ud 同步更新 |
总结
建议: ✅ Approve(有条件)
核心修复(多方块 GUI、吞物品、NPE)都是正确的。架构方向(RPC 替代 ContainerMenu)合理。上述"需要注意的问题"中只有第 1 点(SwitchableButton 可变列表共享)和第 5 点(en_ud 排序)建议处理,其余为改进建议,不阻塞合入。
|
现在我已全面审查了 PR #4190。以下是完整的审查报告。 PR #4190 审查:修复存储系统中的错误行为作者:QiuShui1012 架构变更总结本次 PR 实现了从
✅ 已正确修复的问题1. 存储方块吞物品 ✅旧的 2. 三种大型多方块无法打开 GUI ✅
3. isCustom 逻辑反转 ✅旧的 4. StorageBlockEntity null 安全 ✅
5. RecipeBookCategoryCategory 服务器端检查 ✅从客户端代码库移至
|
|
现在我已拥有所有必要的信息。让我来整理审查报告。 代码审查摘要 — PR #4190操作: synchronize(同步) 📋 概要本次 PR 对存储系统进行了重大架构重构——将屏幕与容器解耦( ✅ 与 PR 描述的交叉核对
🔴 关键问题未发现严重问题。
|
|
Now I have a comprehensive view of this PR. Let me compile the full review. 代码审查摘要 — PR #4190操作: synchronize 🏗️ 架构概览这次 PR 将存储系统的 UI 从 Container+Menu+Packet 架构迁移到 Screen+RPC 架构:
✅ Claim 验证
🔴 关键问题无。未发现阻塞性 bug。
|
| 删除文件 | 引用方 | 状态 |
|---|---|---|
StorageMenu.java |
StorageBlockEntity.createMenu() |
✅ 已删除 |
StorageMenuState.java |
BaseStorage, ClientEventListener, ServerLifecycleEventListener, StoragePackets |
✅ 全部迁移 |
StoragePackets.java |
4 个 block 类的 useItemOn |
✅ 全部迁移到 RPC |
CategorySetting.java |
StorageScreen |
✅ 替换为 CategorySettingsScreen |
IClientCategory.java |
FilterCategory, RecipeBookCategoryCategory |
✅ 不再需要 |
client/package-info.java |
客户端包 | ✅ 整包删除 |
结论: APPROVE — 架构迁移干净完整,修复了三方块界面打开 bug 和 quickMoveStack 吞物品 bug。mergeIntoLargeCrate 的资产销毁时序问题建议后续改进但非阻塞。RPC 架构比旧 Packet Sync 方案更清晰、更高效。
由 Hermes Agent 审查
|
Now I have all the data I need. Let me compile the review. 代码审查摘要 — PR #4190操作: edited (synchronize)
🏗️ 架构变更概览本 PR 将存储系统从
🔴 关键问题1. 复制粘贴坐标错误 — 两处
|
| 声称 | 状态 | 对应文件 |
|---|---|---|
| Fix wrong behaviour (#3582, #3583) | ✅ | StorageMenu/StoragePackets/StorageMenuState 删除 + StorageScreen 重写 |
| 拆分主界面和类别设置界面 | ✅ | CategorySettingsScreen (733行,新文件) + StorageScreen 重构 |
| 修复三种大型多方块无法打开界面 | ✅ | LargeCrateBlock, ShulkerContainerBlock, HyperdimensionStorageStationBlock — 使用 getMainPartPos() |
| 修复存储方块吞物品 | ✅ | 旧 StorageMenu.quickMoveStack 存根随 StorageMenu 删除一起清除 |
结论: REQUEST_CHANGES — 需要修复 3 个关键问题后再合并:
- 🔴 两处复制粘贴坐标错误(
int top = this.left + 7应为this.top + 7) - 🔴
PlayerSetting序列化格式破坏性变更(Map<UUID, StorageSetting>→StorageSetting)—需要 DataFixer 或确认可接受存档丢失 - 🔴
removed()缺少interactionRequest++—可能导致 Screen 关闭后 NPE
另建议处理 carried.shrink() 后缺失 setCarried)以防止 NeoForge ItemStack 不可变性导致的同步问题。
由 Hermes Agent 审查 — 容器菜单→Screen+RPC 迁移专项
|
现在我已经全面理解了 PR。让我来撰写审查报告。 代码审查摘要 — PR #4190操作: 已编辑(edited) 📋 声称验证表
🔴 关键
|
…ed filter category icons is always one, and addressed potential data loss.
代码审查摘要 — PR #4190仓库: Anvil-Dev/AnvilCraft 📋 声称验证表
🔴 关键
|
代码审查总结 — PR #4190结论:需要修改 🔴 (3 个关键问题,3 个警告,1 个建议) PR: #4190 — synchronize: Fix wrong behaviour in storage systems 修复存储系统中的错误行为 📋 声称验证
架构迁移总评: 🔴 关键问题
|
|
Now I have all the information needed for a thorough review. 代码审查摘要 — PR #4190操作: synchronize
🔴 关键1. -public record PlayerSetting(List<CategoryEntry> listed, List<ICategory> custom, Map<UUID, StorageSetting> storageSettings)
+public record PlayerSetting(List<CategoryEntry> listed, List<ICategory> custom, StorageSetting storage)旧的 需要确认:是否有迁移逻辑处理旧格式的 2. 旧代码在 // 已删除
@Override
public void setRemoved() {
super.setRemoved();
if (this.id != null) {
StorageMenuState.clear(this.id);
}
}新代码中 如果玩家在存储方块被破坏后不重新登录,旧的 stub 会一直缓存在
|
| 声称 | 状态 | 对应文件 |
|---|---|---|
| resolved #3582 | ✅ | 整个存储系统重写 |
| resolved #3583 | ✅ | 整个存储系统重写 |
| 大型板条箱替换 3x3x3 | ✅ | CrateBlock (mergeIntoLargeCrate, getLargeCrateOrigin), ModBlocks (doesSneakBypassUse) |
| 拆分主界面和类别设置 | ✅ | StorageScreen (重写 700+ 行), CategorySettingsScreen (新 733 行) |
| 修复三种大型多方块无法打开界面 | ✅ | LargeCrateBlock, ShulkerContainerBlock, HyperdimensionStorageStationBlock (全部使用 getMainPartPos) |
| 修复存储方块吞物品 | ✅ | StorageMenu (删除 quickMoveStack stub), StorageServerStub (interact 方法) |
结论: REQUEST_CHANGES — 需要解决 PlayerSetting 序列化格式变更的数据迁移问题(#1)。setRemoved() 清理缺失(#2)虽然影响较小但有改进空间。整体代码质量高,架构迁移干净,建议修复后合并。
由 Hermes Agent 审查
|
❌ Non-retryable error (HTTP 402): HTTP 402: Insufficient Balance |
|
|
Uh oh!
There was an error while loading. Please reload this page.