Skip to content

Expand amulet and equipment capabilities, and refine blueprint construction and storage interactions 扩展护符与装备能力并完善蓝图建造和仓储交互 - #4951

Merged
PigeonNian merged 3 commits into
Anvil-Dev:dev/1.21/1.6from
WhereisFff:dev/1.21/fix3
Sep 19, 2026

Conversation

@WhereisFff

@WhereisFff WhereisFff commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

- 新增犰狳护符及配方,支持驱离蜘蛛和潜行抗性,调整自然护符的组合效果
- 扩展现有护符的增益、伤害防护、猫狼驯服及铁傀儡友好行为
- 为耐候头盔增加稳定夜视,支持耐候靴潜行时在气泡柱中下沉
- 将结构蓝图导入导出迁移至服务端存档目录,支持单人游戏 Shift 打开目录
- 修正结构磁盘自动旋转设置、智能放置器布局与蓝图预览渲染
- 为建筑杖增加实体阻挡检测及三秒高亮提示,完善放置交互与子空间命中兼容
- 修复方块搬运后的红石信号更新及世界边界监听器遍历问题
- 修复仓储菜单盔甲与口袋槽位同步,完善创造模式口袋校验和状态效果布局及 JEI 避让
- 增加仓储分类筛选一键重置和创造物品变体标记,调整仓储端口与溜槽交互
- 新增余烬金属块与寒霜金属块时移配方,提高部分寒霜金属配方产量
- 调整超级电容与多相超限物质配方,为天体锻造相关物品和无尽收集器添加永恒属性
- 为远古海礁增加含水支持,将伐木附魔每级默认额外破坏原木数调整为四个
- 修正重戟与共振器的属性加成适用范围,统一物品提示及翻译参数并同步生成资源与双语手册
Copilot AI lite review requested due to automatic review settings September 19, 2026 14:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Gugle2308

Copy link
Copy Markdown
Collaborator

⚠️ Dangerous command requires approval:

cd /tmp; cat > extract.sh <<'EOF'
#!/bin/bash
# usage: extract.sh <pattern>
D=/tmp/pr4951.diff
START=$(grep -n "^diff --git" $D | grep -- "$1" | head -1 | cut -d: -f1)
if [ -z "$START" ]; then echo "N...

Reason: shell execution via heredoc

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

⚠️ Dangerous command requires approval:

cd /tmp; echo "=== 新增文件列表 ==="; grep -B1 'new file mode' pr4951.diff | grep '^diff --git' | sed 's|.* b/||'; echo; echo "=== PR 元数据 ==="; curl -s "https://api.github.com/repos/Anvil-Dev/AnvilCraft/pul...

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/pulls/4951 — or: vet https://api.github.com/repos/Anvil-Dev/AnvilCraft/pulls/4951 (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
Collaborator

⚠️ Dangerous command requires approval:

curl -sL "https://api.github.com/repos/Anvil-Dev/AnvilCraft/pulls/4951" | python3 -c "import sys,json;d=json.load(sys.stdin);print(d['state'],d['merged'],d['changed_files'],d['additions'],d['deletions...

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/pulls/4951 — or: vet https://api.github.com/repos/Anvil-Dev/AnvilCraft/pulls/4951 (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
Collaborator

⚠️ Dangerous command requires approval:

cd /tmp && for n in 2648 4841 4866 4875 4907 4915 4920 4921 4927 4928 4929 4931 4932 4933 4934; do r=$(curl -s "https://api.github.com/repos/Anvil-Dev/AnvilCraft/issues/$n"); echo "$n | $(echo "$r" | ...

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

⚠️ Dangerous command requires approval:

cd /tmp; unzip -l minecraft-client-1.21.1.jar 2>/dev/null | grep -c "class"; unzip -l minecraft-client-1.21.1.jar 2>/dev/null | grep -E "net/minecraft/client/Minecraft\.class|net/minecraft/world/level...

Reason: Security scan — [MEDIUM] Archive extraction to sensitive path: Archive command 'unzip' extracts to a potentially sensitive location

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

⚠️ Dangerous command requires approval:

cd /tmp; for n in 4928 4933 2648; do echo "########## #$n"; curl -s "https://api.github.com/repos/Anvil-Dev/AnvilCraft/issues/$n" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['title'...

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/$n — or: vet https://api.github.com/repos/Anvil-Dev/AnvilCraft/issues/$n (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
Collaborator

代码审查摘要 — PR #4951

操作: opened
范围: 125 文件(83 Java / 32 新增 / 0 删除)/ 5,366 行 diff(有效增删 ≈ 2.6k)+ 33 个生成资源 + 6 篇双语文档 + 2 张纹理
基线: dev/1.21/fix3dev/1.21/1.6(head 4de4797a09 / base 4f77cc7be6

🔎 本次核对方式(不只看 diff)

核对项 方法 结果
5 个新/改 Mixin 目标 1.21.1 官方 mappings + 混淆客户端字节码 见下表
@ModifyExpressionValue(CONSTANT intValue=45) handleSetCreativeModeSlot 字节码 bipush 45 命中 恰好 1 次 ✅(不会因多匹配注入失败)
GameRenderer.getNightVisionScale 静态性 类文件 access flags static ✅(@ModifyReturnValue 静态 handler 合法)
旧符号残留 全库 grep appendFixedTank / hideNonOccludingNeighbors / Thinkable.appendHoverText / BlueprintClientFiles.listFiles / acceptUpload 均无残留 ✅
语言键 ↔ 代码 遍历 head 全量 Component.translatable × 生成 en_us.json 删除的 12 个键无任何代码引用;新键全部由 maps 生成 ✅

Mixin 目标核对表

注入点 签名核对
EffectRenderingInventoryScreen.renderEffects/renderBackgrounds/renderIcons/getEffectName 全部存在,签名一致(Iterable, boolean)✅
Entity.onAboveBubbleCol/onInsideBubbleColumn(boolean) 存在 ✅
LivingEntity.setLastHurtByMob / Minecraft.shouldEntityAppearGlowing / ItemStack.finishUsingItem(Level,LivingEntity) 存在 ✅
Spider.registerGoals + AvoidEntityGoal(PathfinderMob,Class,float,double,double,Predicate) 存在,6 参构造匹配 ✅
CreativeModeInventoryScreen.renderLabels/selectedTab/CONTAINER 存在 ✅;该类继承 EffectRenderingInventoryScreen(已用字节码确认),故 PocketEffectScreenMixin 的 creative 分支与 renderLabels 注入均成立 ✅
CreativeModeInventoryScreenMixin extends AbstractContainerScreen 与既有 CreativePocketScreenMixin 同模式(线上已验证)✅

⚠️ 警告(建议合并前确认或修复)

  1. i18n:zh_cn.json 未随之更新,中文界面这批 tooltip 会整体回退英文
    本 PR 把 7 件装备的 tooltip 从 tooltip.anvilcraft.equipment.* 改键为 tooltip.anvilcraft.item.<盔甲名>(并合并成整段文本),en_us/en_ud 已重新生成,但 src/main/resources/assets/anvilcraft/lang/zh_cn.json 未动:equipment.* 7 个旧键成为死键(旧译文还在),而 28 个新键在 zh_cn 中缺失,含 ...item.armadillo_amulet...weatherproof_spacesuit_{helmet,boots,chestplate,leggings}...{frost,ember,transcendence}_{heavy_halberd,resonator}...item.lens.shiftitem.anvilcraft.armadillo_amuletscreen...structure_scanner.open_folderscreen...category.setting.tooltip...thought.progress...key/count/indented/item_count/resin_block.mob/comrade_amulet.player
    → 若走 Weblate 流程,请确认已在同步清单中标注这批「改键+合并」的键(不是纯新增,旧译文需要重组,例如 equipment.breathing → item.breathing_helmetequipment.{clear_vision,recharge,fluid_walking,full_suit,pockets} 需合并进 4 件装备的新长文本)。

  2. IonocraftBackpackItem.playerTick() 删除了已记录在案的护腿幻影物品兜底,未见替代实现
    被删代码的注释明确写了症状:背包穿戴只走 setItemSlot/onEquipItem,不经过 inventoryMenu 槽位广播,客户端 Inventory 残留上一份内容(护腿等槽位幻影),因此用 EQUIPPED_TRACKER + sendAllDataToRemote() 整表重同步。全库 grep sendAllDataToRemote 现在只剩 CreativePocketPacketMixin(非法包兜底)和 UsePillBoxPacket装备状态变化路径没有等价的重新同步。请确认根因已在别处修掉(若与 [Bug] 创造模式脱下耐候航天胸甲被吞 #4921 相关,请说明机制),否则建议保留该兜底或补一个等价 resync。

  3. BlueprintRenderView.getBlockStateBuildingRodRenderTypes.ghost 同时删除了两处预览渲染兜底
    getBlockState 现在直接返回真实状态,删掉的逻辑及其注释明确记录了两个已修问题:①流体连接高度读邻格 getFluidState(),把熔岩/含水方块藏成空气会画出阶梯与内部水面;②红石粉 canOcclude 为真但非实心立方体,会切掉下方顶面。ghost() 同时去掉了 DoubleSided(原来强制关闭背面剔除)。这两处一起回退属于「看不见的行为变化」,建议给出修复/预览前后截图对比确认是刻意为之,而不是顺带删除。

  4. 护符查询被塞进高频路径:hasAmuletInInventory() 每次都是「全背包扫描 + 事件总线 post」
    新增调用点包括 LivingEntityEventListener.onTick每实体每 tick,且 Spider 分支排在最前,蜘蛛盯人时每 tick 都会扫描)、SpiderMixinAvoidEntityGoal 谓词(每个候选玩家)、NearestAttackableTargetGoalMixin 选择器、GravityManager.ignoresCelestialGravity(每次重力向量计算)。而 AmuletAbilities.onTick 其实每 tick 已经算出过「本 tick 生效护符集合」——建议把该集合做成 per-player-per-tick 缓存供上述判定复用,避免 mob 农场/大型红石装置下的无谓开销。

  5. BuildingRodObstructions.find() 逐格做碰撞形状+实体查询;singlePlacement 可能重复拒绝
    commit() 会对整批(建筑杖允许的批量上限可达数千格)逐格 getCollisionShape + level.getEntities;同时 singlePlacement 在首次 singleAttempt 失败后会再试一次偏移位置,失败时第二次 reject()再发一次包+再显示一次消息(聊天栏双份提示)。建议按包围盒并集一次查询、并对同一 tick 的重复 reject 去重。

  6. PlacementInteractions.allowsPlacement 只被客户端预览调用 → 预览可能与真实放置不一致
    该函数新增了「仓储端口/溜槽」分支(主手不放行、副手放行),但全库唯一调用点是 LargeBlockPlacePlacePreviewEventListener。若服务端 useOn/BlockPlacementUtil 路径没有同样的仓储端口/手持判定,就会出现「预览显示了/没显示,实际结果相反」。请确认服务端侧规则同步。


💡 建议(非阻塞)

  1. BlockPointer.java:155-160 — 守卫与取值对象不对称:判断的是变换后 partTargetState.hasProperty(POWERED),取值却读 sourcePart.state().getValue(POWERED)。当前 matches() 已保证同方块(属性集一致),且 applyBlueprintStateRules 是注册表驱动的变换,实际不会抛 IllegalArgumentException;但建议守卫同时检查源状态(或改为 partTargetState.setValue(..., sourcePart.state().getValue(...)) 前做 sourcePart.state().hasProperty),避免将来规则集返回异方块状态时崩在搬运路径。
  2. NearestAttackableTargetGoalMixin — 新增的 Spider 分支写的是 Spider.class.isAssignableFrom(clazz),而相邻两行是反向的 clazz.isAssignableFrom(AbstractSkeleton/Creeper.class)。新行对 Spider/CaveSpider 都成立(✅ 功能正确),但三行方向不一致,建议统一并顺手确认旧两行是否真的能匹配到骷髅/苦力怕。
  3. StructureLoadUtil.getClientStructureDirectory() 由「返回不存在的路径」改为抛 IllegalStateException —— 我已确认 getStructureDirectory(level) 仅由 loadStructureFromDisk(唯一调用点 SmartBlockPlacerBlockEntity:859,在 !level.isClientSide() 分支内)与 readStructureFileOnServer(ServerLevel,…) 触达,当前不会在多人客户端崩溃。但对一个纯工具方法来说抛异常较脆,建议返回 Optional/null + 日志。
  4. CreativeModeInventoryScreenMixin.anvilcraft$renderVariantIndicators 直接 selectedTab.getType(),该字段是可变静态;加一行 null 守卫几乎零成本。
  5. StorageMenunew Slot(source.container, source.getSlotIndex(), x, y) 包装原菜单槽位:对「纯客户端、clicked() 空实现」的定位/渲染用途是正确的(索引→容器映射与 InventoryMenu 规范一致,已核对 0/1-4/5-8/9-35/36-44/45 全部对齐 ✅),但会丢掉原槽位的 mayPlace/isActive 语义与 PocketSlot 类型;后续若有人对 StorageMenu 的槽做 instanceof PocketSlot 判断会静默失效,建议加注释说明。
  6. PR 描述的 resolved/fixed #NNNN 不会自动关 issue:base 是 dev/1.21/1.6(非默认分支),GitHub 不会自动关闭。实测 15 个 issue 中 14 个仍 open(仅 [TODO] 约束中子锭和奇点晶体 #2648 已于 2025-08-31 关闭),合并后需手动关。
  7. 建议标题(本次 gh auth status 显示 token 失效,未自动修改):当前标题只覆盖「护符/装备 + 蓝图建造 + 仓储交互」,遗漏了配方与数值调整、配置默认值变更及若干 bug 修复。建议改为:
    Expand amulet and equipment abilities, refine blueprint building, storage interaction and recipes 扩展护符与装备能力并完善蓝图建造、仓储交互与配方

🟢 看起来不错(已核实)

  • 生成资源与 datagen 完全同源:新键全部来自 ItemTooltipManager 的 NORMAL/SHIFT maps ✅;删除的 12 个键(equipment.*resonator.descheavy_halberd.descitem.power_converter)无任何代码引用 ✅;en_ud 遵循「整体倒序 + 占位符保留」约定(如 " x%s" → "%sx "、多行行序反转)✅;新增/既有生成 JSON 尾部同样无换行符(与仓库既有文件一致,非异常)✅。
  • 纹理与按钮状态机一致:import.png/export.png = 16×96(6 帧 ×16)与 frames=6TextureSize 自读校验、StructureScannerButtonState(selected?3:0)+frame 取值范围 0-5 吻合 ✅。
  • 配方数值自洽(我按「1 块 = 9 锭」逐条复算):余烬块 9×netherite_block → 3 块, consume 9000 与既有 1×netherite_block → 3 锭, consume 1000 完全等价;寒霜块 3×royal_steel_block → 1/2/4/8 与同步上调的 frost_metal_ingot_2: 3→4ingot_3: 4→8 严格对应 ✅;multiphase_transcendium 改 3×3 有序(8 粒 + 中心相变物质)与生成 JSON 一致 ✅;JEI specialSupercapacitorRecipe 与数据配方同步改成铜块 ✅(requires(ItemLike,int) 重载存在,编译无虞)。
  • 文件迁移到服务端存档目录的防护完整:StructureBlueprintFiles 保留 isSafeName + normalize() 父目录相等 + 符号链接拒绝 + 临时文件 ATOMIC_MOVE;导出仅允许 .nbt;读取上限 MAX_BYTES 并有单侧 size 校验 ✅。网络入口 StructureScannerFilePacket.handleOnServer 校验 containerId + menu.stillValid + player.containerMenu 类型 ✅(LIST/IMPORT/EXPORT 均被限制在打开的扫描仪菜单内)。
  • CreativePocketPacketMixin 由「45 + capacity」放宽改为「仅当该槽是活跃 PocketSlot 时才放宽到该槽号」+ 非法槽取消并 sendAllDataToRemote():是收紧而非放权,且 45 常量唯一性已用字节码确认 ✅。
  • ItemTooltipManager.addNormalTooltiptooltip.set(size - previousSize, …) 这个看着别扭的下标推导实际正确(addTranslatedTooltip 逆序插入后 1..n 即 lines[0..n-1],故最后一行下标恰为 n),AQUA 恰好落在 "Full suit: …" 行,与旧行为一致 ✅。
  • OverworldLikeGenerationBootstrapList.copyOf 遍历世界边界监听器修掉 CME ✅;AncientSeaReefBlock 含水实现(createBlockStateDefinition/getStateForPlacement/getFluidState/updateShape 调度水位 tick)标准,且 noExtraModelOrState 生成物不受新属性影响(已核对 blockstate 仍为单 variant)✅;shouldSinkInFluid 抽出的谓词仍处于「穿耐候靴」分支内(无越权放松,只多加了旁观者判断)✅。
  • 双语文档成对且无残链:伐木 2→4 与配置默认值同步;spawner 标题改名在 en/zh 两侧一致,仓库内无旧标题残留 ✅。

📋 声称验证表

PR 声称 状态 对应实现
新增犰狳护符及配方、驱离蜘蛛+潜行抗性、调整自然护符组合 AmuletAbilities, SpiderMixin, ModAmulets.ARMADILLO, jewel_crafting/armadillo_amulet.json, amulet_valid/armadillo.json, NATURE 组合 FEATHER→ARMADILLO(four_to_one/permutation 已同步)
扩展护符增益/伤害防护/猫狼驯服/铁傀儡友好 AmuletAbilities(Haste/Strength/Resistance/SlowFall/Knockback/Explosion/Levitation)、onInteract 空手驯服、isGolemProtected + LivingEntityMixin.setLastHurtByMob
耐候头盔稳定夜视 + 靴子气泡柱下沉 EquipmentAbilities.afterTick 续 200t + GameRendererMixin 恒定 GAMMA;EntityMixinonInsideBubbleColumn/onAboveBubbleCol
蓝图导入导出迁移至服务端存档目录 + 单人 Shift 打开目录 StructureBlueprintFiles(world/…/anvilcraft/blueprints)、StructureScannerFiles LIST/IMPORT/EXPORT、BlueprintClientFiles.openDirectory
结构磁盘自动旋转 / 智能放置器布局 / 预览渲染修正 BlueprintLayout.autoRotate + getLayoutFacinggetBlueprintPosition(index,facing,upsideDown)StructureDiskPreviewSupport 旋转 0 速;⚠ 渲染兜底删除见警告 3
建筑杖实体阻挡 + 三秒高亮 + 光标放置/子空间命中 BuildingRodObstructionsBuildingRodObstructionHighlight(3s)、BuildingRodObstructionPacketBlockPlacementPicking 子空间提前返回
方块搬运后红石更新 / 世界边界监听器遍历 BlockPointer POWERED 保留 + 逐部件 neighborChangedOverworldLikeGenerationBootstrap List.copyOf
仓储菜单盔甲/口袋槽位同步、创造模式口袋校验、效果布局与 JEI 避让 StorageMenu 索引复用、CreativePocketPacketMixinPocketEffectLayout+PocketEffectScreenMixin+JeiPocketEffectAreaMixin ✅;但同批删除的 IonocraftBackpackItem resync 兜底需确认(警告 2)
仓储分类一键重置 / 创造物品变体标记 / 仓储端口与溜槽交互 CategoryList 右键 reset(categoryOnPress 实参为无参用法,未触发 CCE)、CreativeModeInventoryScreenMixin "+" 标记、StoragePortBlockEntity+ChuteBlockItem+PlacementInteractions
余烬/寒霜金属块时移配方 + 提高寒霜产量 TimeWarpRecipeLoader(数值等价性已复算)
超级电容/多相超限物质配方、永恒属性 ItemCompressRecipeLoader(铜块)、RegistrumItemRecipeLoader 3×3、ModBlocks ETERNAL(Eternal 已 import)
远古海礁含水 / 伐木每级 4 AncientSeaReefBlockAnvilCraftServerConfig.fellingBlockPerLevel=4 + 双语文档
重戟/共振器属性适用范围、统一提示与翻译参数、同步生成资源与手册 ✅(i18n 见警告 1) Ferocious/Merciless instanceof 排除、提示全部并入 NORMAL/SHIFT maps + resolved/fixed 15 issue

🧪 测试建议

被测目标 推荐场景 优先级
BuildingRodObstructions.reject/commit 放置区内站生物/玩家(主手/副手)、多部件蓝图、拒绝后 3s 高亮过期、大范围填充(性能与消息去重) 🔴
StructureScannerFiles.handle + StructureBlueprintFiles LIST/IMPORT/EXPORT 往返、.litematic 导入、非法名/路径穿越/符号链接/超限文件、多人服务器(无单人存档时 Shift 不应打开目录)、导出后列表自动刷新 🔴
BlockPointer.moveToPos 搬运含 POWERED 的方块后信号变化、被激活的 TNT 转化为实体、waterlogged 清除、逐部件邻居更新 🔴
StorageMenu 槽位映射 盔甲 5-8 / 主背包 9-35 / 快捷栏 36-44 / 副手 45 索引一致性、服务端广播按 index 写回正确槽、口袋槽存在与不存在两种状态 🟡
AmuletAbilities 犰狳护符(Shift 抗性 II、蜘蛛规避、洞穴蜘蛛)、食物有害效果 ThreadLocal 嵌套 finishUsingItemANVIL 击退属性修饰符的加/去对称性、旧存档 NATURE 护符行为变化 🟡
CreativePocketPacketMixin 创造模式对口袋槽/护腿锁定位/越界槽发包(应 resync 且不丢物)、非法槽不产生 IOOBE 🟡
生成资源一致性 runData 幂等(无 diff)、en_us/en_ud 键集一致、zh_cn 新键补齐后回退英文现象消失 🟡
EquipmentAbilities 夜视/下沉 戴/脱头盔的夜视残留、佩戴长时间夜视效果不被降级、潜水靴气泡柱上下行、旁观/飞行不触发下沉 🟢

结论: COMMENT(无阻断性缺陷) — 主要逻辑、Mixin 目标、生成资源与配方数值均已交叉验证通过,具备合并质量;建议合并前至少确认 警告 1(zh_cn 回退英文)警告 2(背包 resync 兜底删除)警告 3(预览渲染兜底删除) 三项,并顺手处理 BlockPointer 守卫不对称与护符扫描热路径缓存。

由 Hermes Agent 审查

Copilot AI review requested due to automatic review settings September 19, 2026 14:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Gugle2308

Copy link
Copy Markdown
Collaborator

⚠️ No activity for 15 min. If the agent does not respond soon, it will be timed out in 15 min. You can continue waiting or use /reset.

@Gugle2308

Copy link
Copy Markdown
Collaborator

⏱️ Agent inactive for 30 min — no tool calls or API responses.
Last activity: waiting for provider response (streaming) (2s ago, iteration 36/90). The agent may have been waiting on an API response.
To increase the limit, set agent.gateway_timeout in config.yaml (value in seconds, 0 = no limit) and restart the gateway.
Try again, or use /reset to start fresh.

@Gugle2308

Copy link
Copy Markdown
Collaborator

代码审查摘要 — PR #4951

操作: review_requested(state=open / merged=false / 1 commit)
分支: WhereisFff:dev/1.21/fix3Anvil-Dev:dev/1.21/1.6
范围: 125 文件(83 Java、32 新增、0 删除;+1987 / −740),diff 5366 行
diff 完整性: 下载件 125 个 diff --git 头 = API changed_files: 125 ✅;No newline 21 处(仅为 datagen JSON 末行,非异常)

整体是一份质量不错的多主题 PR,主要改动方向都成立,且我在 1.21.1 mappings + 字节码上核对了本 PR 新增/依赖的注入目标(见下)。没有发现必须阻塞合并的问题,但有几处需要确认与同步。


✅ 注入目标核对(1.21.1,mappings + 混淆客户端字节码)

Mixin 目标 结论
Spider#registerGoals()cko.B,void/无参) ✅ 存在,@Inject(TAIL) 合法
Entity#onInsideBubbleColumn(boolean) / #onAboveBubbleCol(boolean)bsr.l/m ✅ 名称与签名正确(1.21.1 未改名)
Minecraft#shouldEntityAppearGlowing(Entity)fgo.b ✅ 存在
GameRenderer#getNightVisionScale(LivingEntity,float): floatges.a ✅ 存在;静态 handler 合法
CreativeModeInventoryScreenCONTAINER(static final SimpleContainer Q)、selectedTab(static T)、ItemPickerMenufpi$b)、renderLabels(GuiGraphics,int,int)slotClicked ✅ 全部匹配,@Shadow @Final private static 用法正确
EffectRenderingInventoryScreenrenderEffects / renderBackgrounds / renderIcons / getEffectName ⚠️ 存在,但四个方法在 1.21.1 全为 privatefpl.c/a/b/a),见下建议
HeavyHalberdItem / ResonatorItem 层级 ✅ 二者是兄弟类(都是 TieredItem 子类),Ferocious/Merciless 里两个 instanceof 守卫不会互相误伤
ModAmulets / ModEntityTypeTags / BlockPlacementLayout 等跨文件引用(StoragePortConsolidatorBlockEntityPocketSlotCreativeVariantPickerRegistryModItemTags.NETHERITE_BLOCKStructureDiskData#autoRotate ✅ 目标分支均存在
AncientSeaReefBlock 新增 waterlogged 属性 ✅ 生成物 blockstates/ancient_sea_reef.json 用的是 "" 通配变体,新增属性不会掉模型(无需 runData)

⚠️ 需要确认 / 建议修正

  1. agic 手册未收录新护符(与 PR 描述的“同步…双语手册”不一致)
    ageratum/{en_us,zh_cn}/006_prop/100_amulet.md 未在本 PR 修改,仍缺 犰狳护符:frontmatter items: 列表、正文 <item id=...> 行、表格行、<recipe id="anvilcraft:jewel_crafting/armadillo_amulet"/> 都没有;同时该页的护符表也没有猫/狗“空手一次交互即可驯服”、铁傀儡友好等新效果。请补上(或改成由 datagen 生成)。

  2. IonocraftBackpackItem 的护甲槽幻影修复被整段删除,未见替代实现
    删掉了 EQUIPPED_TRACKER + 装备状态变化时的 player.inventoryMenu.sendAllDataToRemote()(原注释:创造/生存脱下背包后“护腿等槽位残留幻影物品”)。head 中 sendAllDataToRemote 只剩 CreativePocketPacketMixinUsePillBoxPacket 两处,都与背包穿脱无关。若该幻影问题已由本 PR 其它改动覆盖(例如新的 validateSlot 守卫)请在描述里点明;否则建议保留这处低成本重同步。

  3. 手工维护的语言文件未同步,且有两处是“语义已变”的陈旧翻译
    zh_cn/zh_hk/zh_tw/zh_meme/ja_jp/ko_kr/ru_ru/de_de/es_es/fr_fr/lzh 均缺新键:item.anvilcraft.armadillo_amulettooltip.anvilcraft.item.armadillo_amulettooltip.anvilcraft.keyscreen.anvilcraft.structure_scanner.open_folderscreen.anvilcraft.storage.category.setting.tooltiptooltip.anvilcraft.comrade_amulet.player
    若这些由 Weblate 回填可以忽略,但下面两条是已有键的值变了,中文玩家会看到错误信息,建议本次一并改:

    • zh_cn: tooltip.anvilcraft.item.nature_amulet = “同时有寂静、猫、狗、羽毛护符的效果” —— 代码已改为 ARMADILLO(ModAmulets + permutation + four_to_one 三处一致),英文提示也已改为 Armadillo;
    • zh_cn: item.anvilcraft.structure_disk.size = “尺寸:%s” —— 英文已改为 Size: %s x %s x %s 并传 3 个参数,中文占位符不足会丢两个数值。
  4. 护符/装备增益用 2 tick refreshEffectshowIcon=true,HUD 图标会常驻闪烁
    refreshEffect(...) = new MobEffectInstance(effect, 2, amplifier, false, false, true):原版以剩余时长 < 200 tick 判定“即将结束”并闪烁,因此 Topaz/Ruby/Sapphire/Armadillo(以及 NATURE/GEM 包装链)的图标会一直闪;夜视用常量 200 续期(正好在阈值上,作者已用 GameRendererMixin 把视觉 scale 强制为 1 来掩盖淡入淡出,但 HUD 图标闪烁仍在)。既有的 GiveEffectAmulet(…, 3, 0, false, false) 不显示图标,没有这个问题。建议统一改为更长的续期时长(如 300)、在 endsWithin(300) 时续,或 showIcon=false

  5. **#2648 “约束中子锭和奇点晶体” 在本 diff 中看不到对应实现** 本 PR 与 #2648 沾边的只有:给 4 个物品加 ModComponents.ETERNAL(无尽收集器、天体锻造砧、天体锻造增幅器、传送门),而 Eternal的语义是“每 tick 清零 DAMAGE + 加 UNBREAKABLE”,既不是“防炸防烧”,也没有confined_neutronium_ingot/singularity_crystal` 的新方块、物品与多块配方。请确认 [TODO] 约束中子锭和奇点晶体 #2648 是已在其它 PR 关闭,还是描述需要修正(例如改成“为天体锻造物品与无尽收集器添加永恒属性”)。

  6. #4928 / #4933 两条崩溃报告缺少“哪一处修改修复”的指向
    两条都是第三方模组组合下的客户端崩溃([Bug] 启动时游戏崩溃 #4928trinkets-3.10.0 经 Connector 加载;[Bug] 进入世界时崩溃 #4933experiencelib + databank),堆栈里是超长 mod 列表 + GL 报错,diff 中没有直接针对这些模组的改动。若修复来自「移除 BuildingRodRenderTypes 里自定义 RenderType 子类」或「WorldBorder listener 改 List.copyOf」这类删减,请在描述里点明,便于回归验证。


💡 建议(非阻塞)

  • PocketEffectScreenMixin:三个 @Shadow 目标在 1.21.1 都是 private,建议声明为 private abstract(与目标可见性一致,不依赖 Mixin 对“宽于目标”shadow 的宽松处理);getEffectName 也一并核对该页的 tooltip 版本。
  • AmuletAbilitiesonTick 每 tick 都做一次全背包扫描(getAmuletsFromInventoryAmuletEvent.Find 事件分发),而 SpiderMixin/NearestAttackableTargetGoalMixin/LivingEntityEventListener 里的谓词会对每只怪每 tick 再各扫一次。新增蜘蛛/铁傀儡分支后调用点变多,建议把本 tick 的 active 集合缓存到玩家侧(tick 级),供各事件/谓词复用。
  • LivingEntityMixin#setLastHurtByMob:为了 IronGolemLivingEntity 上注入 + (Object) this instanceof IronGolem,每只实体受击都会走一次;直接 @Mixin(IronGolem.class) 更精准,也减少与其它模组在 LivingEntity 上的注入竞争。
  • BuildingRodObstructions.find:每个 cell 一次 getCollisionShape + level.getEntities(AABB)commit 时对整份蓝图全量扫描、singleAttempt 失败路径还会再扫一次;建议先按 state.isAir()/无碰撞形状快速过滤,或只对“实体所在 chunk 有候选实体”的 cell 做精确相交。
  • BlockPointer:搬运后对每个部件 × 6 方向调用 level.neighborChanged(...)(签名用法正确),但 Level.setBlock 已通知过邻居,大结构搬移会显著放大红石级联;若只为解决本 PR 新引入的 POWERED 保留场景,建议只在 hasProperty(POWERED)(或红石类方块)上做这 6 次自更新。
  • 多人环境:蓝图 LIST/IMPORT/EXPORT 现在完全落在服务端存档目录(文件名白名单、软链接、大小均已校验 ✅),任何能打开结构扫描仪 GUI 的玩家都可向存档目录写入 ≤ MAX_BYTES.nbt;若不想如此,建议加服务端配置开关/权限门槛。
  • 可审查性:1 个 commit 混入 15+ 主题(护符、装备、蓝图 I/O、仓储、配方、红石、本地化、手册)。不阻塞合并,但后续建议按主题拆 commit/PR,行内问题更容易被定位。

🟢 看起来不错

  • StorageMenu 改为复用 inventoryMenu 的槽位映射:这是根因修复——旧版硬编码 46 槽,inventoryMenu 追加口袋槽(>45)后索引错位,才出现盔甲/口袋同步问题;隐藏槽仍用 -1000 坐标不可点击,clicked/quickMoveStack/setSynchronizer 仍为空实现只在客户端兜底,getCarried/setCarried 仍委托给 inventoryMenu,语义自洽。
  • CreativePocketPacketMixin@ModifyConstant@ModifyExpressionValue + 携带 packet 参数,Math.max(original, slot) 与原版 slotNum() >= 1 && slotNum() <= 45 的边界写法自洽(pocket 槽 ≥46 时 slot <= slot 成立);新增 validateSlot 的三种守卫(负槽丢物品不拦、非活跃 pocket 拦、slot == 7 锁定护腿拦)逻辑正确,且都会 sendAllDataToRemote() 先纠正客户端。
  • OverworldLikeGenerationBootstrapList.copyOf(...) 后再 removeListener,正确修掉了遍历中修改 WorldBorder listener 列表的 ConcurrentModificationException[Bug] 进入世界时崩溃 #4933 方向的典型症状)。
  • BlockPointer 保留 POWERED + 搬移后重发邻居信号,思路正确(neighborChanged(pos, neighborBlock, neighborPos) 用法无误)。
  • AncientSeaReefBlockSimpleWaterloggedBlockgetStateForPlacement/getFluidState/updateShape(含水 tick)实现完整;ModBlocks 泛型同步改为 BlockEntry<AncientSeaReefBlock>
  • BuildingRodObstructionHighlight:客户端单线程使用,WeakHashMap + 3 秒过期 + show() 时清理,无泄漏;只在拒绝放置时才发包、3 秒后自动失效,与描述一致。
  • AmuletAbilities.consumeFoodThreadLocal 用 try/finally 正确恢复(支持嵌套),onEffect 的四个分支与工具提示文案一一对应;SpiderMixin 通过 AmuletManager + 标签判定(含 cave_spider)而非硬编码物品,符合既有做法。
  • ItemTooltipManager 重构NORMAL_ARGUMENTS + addTranslatedTooltip(..., Object...) 复用既有 TooltipUtil.translatedLines(key, style, args)(基类已有 varargs 签名 ✅);previousSize/size()-previousSize 的插入下标运算正确;LENS 三行配色顺序(Royal/Frost/Ember)与文案顺序一致,护甲 full_suit 行 AQUA 与旧行为一致;已确认 else if (NORMAL.containsKey(item)) 分支保留,护符/护甲/能量转换器提示不会丢。
  • Ferocious/Merciless 的守卫方向正确(兄弟类层级已核对),TimeWarpRecipeLoader/RegistrumItemRecipeLoader 的配方与生成 JSON、advancement、lang 三方一致(multiphase_transcendium 8×锭粒 + 1×多相物质;超级电容改铜块;余烬/寒霜块各 4 条 + 霜金属锭 4/8)✅。
  • AnvilCraftServerConfig.fellingBlockPerLevel 2→4 与 ageratum en/zh 手册同步修改 ✅(提醒:已有存档的 config 不会自动更新,老存档仍是旧值,属预期行为)。

📋 声称验证表

PR 描述条目 状态 对应产物
新增犰狳护符及配方 / 驱离蜘蛛 / 潜行抗性 / 调整自然护符 ✅(手册未同步见 ⚠️1) ModAmulets.ARMADILLOModAmuletDefinitions(+json)、ModItems.ARMADILLO_AMULETjewel_crafting/armadillo_amuletamulet_valid/armadillo(spider+cave_spider)、SpiderMixin/NearestAttackableTargetGoalMixin/LivingEntityEventListenerAmuletAbilities 潜行 Resistance II、NATURE 包装改为 ARMADILLO(三处配方+英文提示一致)
扩展护符:增益 / 伤害防护 / 猫狼驯服 / 铁傀儡友好 AmuletAbilities.onTick/onEffect/onInteract/isGolemProtectedLivingEntityMixin#setLastHurtByMobGravityManager 天体重力豁免、AnvilAmulet 击退免疫
耐候头盔稳定夜视 + 耐候靴气泡柱下沉 ✅(HUD 闪烁见 ⚠️4) EquipmentAbilities.afterTickGameRendererMixin#getNightVisionScaleshouldSinkInFluid + EntityMixin 两个气泡柱方法
蓝图导入导出迁移服务端存档目录 + 单人 Shift 开目录 StructureBlueprintFiles(新)、StructureScannerFiles LIST/IMPORT/EXPORT、BlueprintClientFilesStructureScannerFilePacket(Action)StructureScannerScreen.folderModeStructureLoadUtil 改为要求服务端世界
结构磁盘自动旋转 / 智能放置器布局 / 预览渲染 StructureDiskPreviewSupport(0.0f/2.0f)、BlueprintLayout.autoRotate+getLayoutFacingSmartBlockPlacerBlockEntity#getBlueprintPosition + Screen 预览、BlueprintRenderView/BuildingRodRenderTypes 清理
建筑杖实体阻挡 + 三秒高亮 + 子空间命中兼容 BuildingRodObstructions/Highlight/PacketBuildingRodService.rejectMinecraftClientMixin#shouldEntityAppearGlowingPlacementInteractionsBlockPlacementPicking range 判定
方块搬运后红石信号 / 世界边界监听器遍历 BlockPointer POWERED 保留 + 自更新、OverworldLikeGenerationBootstrap List.copyOf
仓储菜单盔甲与口袋同步 / 创造模式口袋校验 / 状态效果布局 / JEI 避让 ✅(⚠️2 请确认背包幻影) StorageMenu 槽位复用、CreativePocketPacketMixinPocketEffectLayout/PocketEffectScreenMixin/JeiPocketEffectAreaMixin(+mixins.json)
仓储筛选一键重置 / 创造物品变体标记 / 端口与溜槽交互 CategoryList 右键重置(+tooltip lang)、CreativeModeInventoryScreenMixin#renderLabels 画 “+”、ChuteBlockItem/StoragePortBlockEntity/PlacementInteractions 覆盖 StoragePortConsolidatorBlockEntity、潜影集装箱禁入缓冲
余烬/寒霜金属块时移配方 + 提高霜金属产量 TimeWarpRecipeLoader + 8 个配方/advancement JSON + frost_metal_ingot_2/3
超级电容与多相超限物质配方 + 永恒属性 ItemCompressRecipeLoader(铜块)、RegistrumItemRecipeLoader(3×3: 8 锭粒+多相物质)、ModBlocks 4 处 ETERNALItemCompressCategory
远古海礁含水 / 伐木附魔每级 4 个 AncientSeaReefBlockAnvilCraftServerConfig 2→4、手册 en/zh 同步
重戟/共振器属性加成适用范围 + 提示与翻译参数统一 + 双语手册 Ferocious/Merciless 守卫、DiskItem/StructureToolItem/CannedFoodItem/SpectralSlingshotItem/FluidTankMinecartItem/AnvilRailgunItem/HasMobBlockItem 改 translatable + ItemTooltipLang 新键数组、ageratum en/zh
resolved #2648 / #4841 / #4866 / #4915 / #4920 / #4927 / #4929 / #4931 / #4932 / #4934 与 diff 内容一一对应(#4841 筛选重置、#4866 建筑杖实体检测、#4915 打开文件夹、#4920 夜视、#4927 护符、#4929 潜影集装箱、#4931 气泡柱下沉、#4932 残暴/无情、#4934 变体标记)
fixed #4875 / #4907 / #4921 #4875 智能放置器信号(BlockPointer POWERED)、#4907 物理化方块放置(BlockPlacementPicking 子空间命中)、#4921 创造模式脱下被吞(CreativePocketPacketMixin 守卫)
resolved #2648(约束中子锭/奇点晶体) ⚠️ diff 中无对应新方块/物品/配方,仅有 4 处 ETERNAL(见 ⚠️5)
fixed #4928 / #4933(启动/进世界崩溃) ⚠️ 均为第三方模组组合崩溃,缺少“修复点”指向(见 ⚠️6);List.copyOf 方向合理

🧪 测试建议

被测目标 推荐场景 优先级
StructureBlueprintFiles.read/write/resolve 路径穿越(..、子目录)、软链接、超 MAX_BYTES、空文件、非 .nbt 导出名、目录被并发替换 🔴
AmuletAbilities.onTick/onEffect/onConsume 潜行/水中/着火切换时效果增减与降级;NATURE/GEM 包装链;食物有害效果抑制窗口(含嵌套消耗);ANVIL 修饰符加删对称 🔴
CreativePocketPacketMixin 负槽丢物品、非活跃 pocket、锁定护腿三条守卫;slotNum 恰好 45/46/边界 🟡
StorageMenu 槽位映射 有/无口袋槽(46 vs 46+capacity)时与 InventoryMenu 索引对齐、盔甲槽写入落到真实容器 🟡
BlueprintLayout.getLayoutFacing/getPosition autoRotate 开/关 × 4 个水平 targetFacing × scannerFacing × upsideDowngetStategetPosition 朝向一致 🟡
BuildingRodObstructions.find 空碰撞形状、实体跨格、实体仅贴边(AABB 精确相交)、多 cell 去重 🟡
PocketEffectLayout.areas count=0/1/2/N、创造模式双排、窗口极窄时的 clamp 🟢

结论: COMMENT(可合并,建议先处理 ⚠️1–3) — 主体实现与声称一致、注入目标已核对、StorageMenu/CreativePocketPacketMixin/BlockPointer/WorldBorder 几处都是正确的根因修复;阻塞点在于:蓝图中护符页与语言文件未同步(含两处语义已变的错误翻译)、一个已被删除的背包护甲槽重同步缺少替代、#2648/#4928/#4933 三条关联缺少可验证的修复指向。PR 标题(英文+中文)与内容基本相符,本次未改动标题。

由 Hermes Agent 审查

@Gugle2308

Copy link
Copy Markdown
Collaborator

审查完成。以下是审查意见(直接输出,未执行任何评论命令;gh auth status 显示 token 失效,故未自动改标题)。

代码审查摘要 — PR #4951

操作: edited(重新审查)
范围: 125 个文件(83 Java,32 新增,0 删除)/ +1987 −740
目标分支: dev/1.21/fix3dev/1.21/1.6(1.21.x,非 26.1 迁移 PR → 跳过 jspecify/Identifier 等迁移健康度检查;新增代码用 javax.annotation.Nullable,与本分支 AGENTS.md("When a value may be null, explicitly annotate it with javax.annotation.Nullable")一致 ✅。顺带核对了 diff 完整性:changed_files=125 与本地 125 个 diff --git 一致,additions/deletions(1987/740) 与统计(1985/738)吻合,未截断。

📋 声称验证表(描述里的 13 条 bullet + 15 个 issue)

声称 状态 关键实现
#2468 犰狳护符 ModItems.ARMADILLO_AMULET(16 蜘蛛眼+4 犰狳鳞+银锭,已核对生成配方)、amulet_definition/armadillo.jsonamulet_valid/armadillo=spider+cave_spider、SpiderMixinNearestAttackableTargetGoalMixinLivingEntityEventListener
#4927 护符调整 AmuletAbilities(新):TOPAS 急迫/RUBY 力量(着火 II)/SAPPHIRE 抗性/ARMADILLO 潜行抗性 II/ANVIL 击退+悬浮免疫、伤害防护、onInteract 空手驯服猫狼、isGolemProtected+LivingEntityMixin.setLastHurtByMob、铁傀儡 stopBeingAngry
#4920 耐候头盔夜视 EquipmentAbilities.afterTick + GameRendererMixin.getNightVisionScale 强制 1.0
#4931 气泡柱下沉 EquipmentAbilities.shouldSinkInFluid + EntityMixin.@ModifyVariable(onInsideBubbleColumn/onAboveBubbleCol);顺带把原「任何玩家潜行都下沉」收紧为需穿耐候靴
#4915 导入导出开文件夹 BlueprintClientFiles.canOpenDirectory/openDirectoryfolderMode + screen...open_folder
蓝图迁移至服务端存档目录 StructureBlueprintFiles(新) + StructureScannerFiles LIST/IMPORT/EXPORT + StructureScannerFilePacket.Action + 6 帧按钮贴图(实测 16×96 与 frames=6 匹配)
#4875/#4907 搬运红石信号、子空间命中 BlockPointer 保留 POWERED + 邻居更新循环;BlockPlacementPicking 命中点超范围即不改算射线
#4933 进世界崩溃 OverworldLikeGenerationBootstrapList.copyOf(...) 遍历世界边界监听器
#4841 仓储筛选一键还原 CategoryList.resetFilterModes + 右键回调 + 新 tooltip 键
#4934 创造物品变体辨识度 CreativeModeInventoryScreenMixin.renderLabels 画 "+"(CreativeVariantPickerRegistry
#4921/#4929 创造模式口袋校验、潜影箱 CreativePocketPacketMixin(@ModifyExpressionValue + 槽位校验)、StoragePortBlockEntity.isItemValid/onRightClickChuteBlockItem/PlacementInteractions 支持 Consolidator
#4932 残暴/无情适用范围 Ferocious/Merciless 对 Resonator 跳过攻击力、对 HeavyHalberd 跳过挖掘效率
时移/压缩/相变配方 + 永恒属性 TimeWarpRecipeLoader(8 个新配方,生成 JSON 逐值核对无误)、ItemCompressRecipeLoader+in-world 触发+JEI 特例三处同步(铜块×2)、multiphaseTranscendium 改 shaped(8 粒+1 团)、4 个天体锻造/无尽收集器加 ETERNAL
远古海礁含水 / 伐木默认 4 AncientSeaReefBlock(新,blockstate JSON 无属性变体故无需重生成)、fellingBlockPerLevel 2→4 + 中英手册同步
统一提示/翻译参数 + 双语手册 新增 13 个 lang 键全部有代码引用、被删键无残留引用、en_ud 对称(含 %s 保留)、ageratum 术语改名与交叉链接中英同步

⚠️ 警告

  1. api/pointer/BlockPointer.java:154-160 — POWERED 属性读取不对称,数据包「方块转换」规则下会抛 IllegalArgumentException
    目标态由 BlockPlacementRules.applyBlueprintStateRules() 得出,而其中的 applyStateRules 支持 block:id[prop->,prop=value] 转换语法(BlockPlacementRuleSet.applyBlockTransformation 会返回任意方块defaultBlockState())。当前写法只校验了 目标 有 POWERED,却从 取值:

    if (applyBlueprintRules && partTargetState.hasProperty(POWERED)) {
        partTargetState = partTargetState.setValue(POWERED, sourcePart.state().getValue(POWERED)); // 源可能没有该属性
    }

    matches() 只保证「源方块 == 蓝图方块」,同块时 inheritBlueprintState 走 baseState 分支是安全的;但一旦某条规则把蓝图方块转换成含 POWERED 的另一方块,这里就会 getValue 失败(搬运中断/日志刷屏)。建议:

    partTargetState = partTargetState.setValue(POWERED,
        sourcePart.state().hasProperty(POWERED) ? sourcePart.state().getValue(POWERED) : partTargetState.getValue(POWERED));
  2. 蓝图目录迁移没有兼容处理(用户可见的「文件消失」)。
    导入导出目录从客户端 <gameDir>/anvilcraft/structures 改成服务端 <world>/anvilcraft/blueprintsStructureBlueprintFiles.directory),旧目录里的 .nbt/.litematic 在新版本里不再出现在列表中(文件还在,但读不到)。建议在首次打开扫描器/进入世界时做一次性拷贝迁移,或至少在更新说明与手册中写明目录变更(当前 ageratum 没有提及新路径)。注意这套与结构磁盘用的 <world>/anvilcraft/structuresStructureScannerFiles:123,未变)是两套目录,容易混淆。

  3. 建筑杖的 SHIFT 详细说明被整体删除,且相关翻译键已成死键。
    ItemTooltipManagerBUILDING_ROD 的 SHIFT 条目被删(旧文本含框选/Ctrl+Z 撤销/水桶注水/100FE 每方块),NORMAL 只剩一行;item.anvilcraft.building_rod.{controls,fluids,energy,import} 这些键在代码中没有任何引用(仅 BuildingRodLang 生成,仓库内未消费)。若是有意精简请忽略,否则建议用这些键补齐「按 Shift 查看详情」的提示(tooltip.anvilcraft.item.building_rod.shift 已从 lang 中移除,玩家的详细信息入口就此消失)。

  4. client/building/BuildingRodRenderTypes.java 移除了 DoubleSidedRenderSystem.disableCull())。
    幽灵预览不再双面渲染,从内部/背面看会缺面。若移除是因为 RenderType 构造器/继承在新版本不可用,建议改用 RenderTypefaceCulling/RenderPipeline 等价配置确认视觉可接受(本次 PR 未替换任何等价的关剔除逻辑)。

  5. item/IonocraftBackpackItem.java 删掉了 EQUIPPED_TRACKER + inventoryMenu.sendAllDataToRemote() 兜底。
    原注释明确记录该兜底是为了修「穿戴/脱下背包后护腿等槽位出现客户端幻影物品」。现在把修复责任交给了新的 StorageMenu 槽位映射——请确认幻影槽问题在这条路径被真正覆盖(建议实测:创造/生存下穿脱鞘翅背包 + 打开仓储界面 + 点击护甲槽)。

  6. mixin/NearestAttackableTargetGoalMixin.java:50 新旧分支方向相反。
    新增的 Spider 分支用 Spider.class.isAssignableFrom(clazz)(正确方向,覆盖蜘蛛/洞穴蜘蛛),而紧邻的原有分支是 clazz.isAssignableFrom(AbstractSkeleton.class)(反向)——后者对 Skeleton/Stray/WitherSkeleton 实际恒为 false(骷髅侧其实是靠 LivingEntityEventListenerEntityTypeTags.SKELETONS 兜住的)。属既有问题,但既然本 PR 动了这个 switch,建议统一成 X.class.isAssignableFrom(clazz)

💡 建议

  • item/FluidTankMinecartItem.java:53-56 硬编码 "Tank"/"Fluid" 字符串,而 FluidTankMinecartEntity.TAG_TANKFluidTankItemTooltip.TAG_TANK/TAG_FLUID 常量已存在,建议复用避免 NBT 键漂移。
  • 每 tick 效果刷新会造成每 tick 一次效果更新包EquipmentAbilities.afterTicknightVision == null || nightVision.endsWithin(200)duration=200endsWithin<=,故每 tick 都重新入效果)与 AmuletAbilities.refreshEffect(duration=2) 同理。建议改为「长持续 + 低阈值刷新」(如 400 tick、剩余 ≤40 时刷新),图标稳定性不变但可省掉 20 包/秒/玩家/效果。
  • client/building/BuildingRodObstructionHighlightWeakHashMap(无锁),show() 与渲染线程均为主线程故安全;但过期项仅在 show()/查询时清理,若想更稳可用 ConcurrentHashMap + 显式过期剔除(并注意该表内容会随高亮实体增长)。
  • client/gui/screen/StorageMenu 现在用普通 Slot 包装 inventoryMenu.slots:槽位 0–4 原本是 ResultSlot/CraftingSlot 语义(mayPlace 等),请确认客户端侧点击转发仍然走原菜单(若转发到真实 inventoryMenu.clicked 则无影响)。
  • AmuletAbilities.onEffect 的四个 &&/|| 混合条件依赖优先级(&& 高于 ||,结果正确),建议加括号提升可读性。
  • en_ud 观感tooltip.anvilcraft.item.weatherproof_spacesuit_helmet%s 由代码插入 effect.minecraft.night_vision,反向语言下该段不会被翻转,属可接受的轻微不一致。
  • 标题建议gh token 失效未能自动修改,见文末):当前标题准确但漏掉了最显眼的两项用户可见变更(蓝图导入导出目录迁移、配方/文档调整),可考虑改为
    Move blueprint import/export to the world save folder, expand amulet and equipment abilities 蓝图导入导出迁移至存档目录,扩展护符与装备能力

🟢 看起来不错

  • 蓝图读写路径安全做得很扎实:isSafeName + normalize + 父目录校验 + 拒绝符号链接 + 大小上限 + 临时文件原子替换;服务端只接受 .nbt 导出名,内容由服务端生成,未开任意写口子。
  • StructureScannerFilePacket 新增 LIST/IMPORT/EXPORT 后仍保持 containerId 校验 + menu.stillValid(player)
  • 新增 13 个 lang 键与代码引用一一对应,被删除的键无残留引用;en_uden_us 同步;ageratum 中英术语改名 + 交叉链接 + 伐木数值三处一致。
  • 配方改动做到「loader + in-world 触发条件 + JEI 特例」三处同步(超级电容),生成 JSON 与 loader 逐值核对一致。
  • Math.max(original, slot) 替代 original + capacity,并按 PocketSlot.isActive() 精确放行,比原来的常量放宽更严谨;slot >= 0 守卫避免了 getSlot(-1)
  • PocketEffectScreenMixin 完全接管原版 renderEffects(cancellable)避免重复绘制,PocketEffectLayout 纯参数化便于测试。
  • 三处新 mixin 均已登记 anvilcraft.mixins.json,6 帧状态机与 16×96 贴图严格匹配;ServerPlayerContainerListenerMixin 等既有模式保持一致。
  • AncientSeaReefBlockSimpleWaterloggedBlock 实现(getStateForPlacement/getFluidState/updateShape 补 tick)与 base 的 blockstate JSON(variants:{"":...})核对后确认无需重跑 datagen。

🧪 测试建议

被测目标 推荐场景 优先级
BlockPointer.moveToPos + applyBlueprintStateRules 含 POWERED 的搬运(红石灯/活塞/门)、含 block: 转换规则的数据包、副部件多方块 🔴
StructureBlueprintFiles.read/write/list 超限文件、.litematic、符号链接、路径穿越名、导出覆盖同名文件、原子写失败回滚 🔴
BlueprintClientFiles 状态机 LIST/IMPORT/EXPORT 交错、超时(60s)、关屏取消、导出后自动刷新列表 🟡
BuildingRodObstructions.find + 高亮 实体阻挡拒绝提交、3 秒过期、跨维度/卸载实体 🟡
PocketEffectLayout.areas count=0/1/20、创造模式两行布局、超窄窗口、JEI 避让区域 🟡
StorageMenu 槽位映射 护甲/口袋槽同步、创造模式 Slot 点击、crafting 槽语义 🟡
AmuletAbilities 效果叠加/移除同行、空手驯服(猫/狼)、铁傀儡怒气、食物有害效果豁免、ThreadLocal 重入 🟡
CreativePocketPacketMixin 创造模式槽位 45±、非活动 PocketSlot、潜行锁定护腿槽 🟡
AncientSeaReefBlock 水中放置/破坏、流动水 tick、含水与无水流体状态 🟢

结论: COMMENT — 无阻塞性缺陷,声称与实现逐条可核(15 个 issue 均能在 diff 中定位到对应改动);建议合并前优先处理 ⚠️1(POWERED 属性读取健壮性)与 ⚠️2(旧蓝图目录兼容/说明)。标题建议见上(本次 gh auth status 显示 token invalid,按流程未尝试修复凭据、未自动改标题,仅给出建议标题)。


由 Hermes Agent 审查

@Gugle2308

Copy link
Copy Markdown
Collaborator

💾 Self-improvement review: Patched SKILL.md in skill 'mixin-injection-verification' (1 replacement). · Skill updated

@Gugle2308

Copy link
Copy Markdown
Collaborator

💾 Self-improvement review: Patched references/shell-only-diff-navigation.md in skill 'github-webhook-pr-review' (1 replacement).

Copilot AI review requested due to automatic review settings September 19, 2026 15:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@PigeonNian
PigeonNian merged commit db61fc6 into Anvil-Dev:dev/1.21/1.6 Sep 19, 2026
2 checks passed
@Gugle2308

Copy link
Copy Markdown
Collaborator

PR #4951closed(且已 merged,merged_at 2026-09-19T15:14:15Z),触发动作为 closed

按审查流程约束第 1 条:closed / labeled 事件直接停止,不发布任何审查评论。本次不做代码审查,不发表评论,也不修改 PR 标题。


由 Hermes Agent 处理(webhook,action=closed → 跳过审查)

@Gugle2308

Copy link
Copy Markdown
Collaborator

⚠️ Dangerous command requires approval:

cd /opt/data/workspace/AnvilCraft; B=rvbase4951; echo "=== base ember_metal_ingot_0..3 / frost_metal_ingot_0,1 配方 ==="; for f in ember_metal_ingot_0 ember_metal_ingot_1 ember_metal_ingot_2 ember_metal...

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 #4951 的完整审查(下载 diff 138 文件 / 6255 行,并用 1.21.1 Mojang mappings + 混淆字节码交叉验证了所有 Mixin 注入目标)。以下是审查意见。


代码审查摘要 — PR #4951

操作: review_requested(PR 状态 openmerged: falsemergeable: true
范围: 138 个文件(95 Java / 35 新增 / 0 删除)/ +2445 −747,333 个 hunk

🚨 首先:本 PR 的内容已经出现在目标分支上

  • 目标分支 dev/1.21/1.6 当前 tip = db61fc6,其提交信息与本 PR 标题完全一致("Expand amulet and equipment capabilities, and refine blueprint construction and storage in…")。
  • 我逐文件对 head 6b1b636 与 base tip db61fc6 做了 md5 比对:StructureBlueprintFiles.javaBuildingRodObstructions.javaSmartBlockPlacerItemRenderer.javaComradeAmuletItem.javaPocketEffectLayout.javaAncientSeaReefBlock.javaItemTooltipManager.javaEquipmentAbilities.java 全部字节相同
  • 但 PR 的基线 SHA 是 4f77cc7(该 commit 上这些新文件返回 404),GitHub 侧仍未标记 merged(merge_commit_sha: 0d0696b)。

建议: 确认这批改动是否已通过其他途径合入;若是,请关闭本 PR,避免后续重复合并/回滚混乱。下面所有问题按"即使已合入、也可作为后续修复"的方式给出。

✅ Mixin 目标核验(用 1.21.1 client_mappings + 混淆客户端字节码实核)

Mixin 目标 结果
ItemInHandRendererMixin renderItem ✅ 该类只有 1 个 renderItem(LivingEntity, ItemStack, ItemDisplayContext, boolean, PoseStack, MultiBufferSource, int)@WrapMethod 名解析不会歧义;handler 非静态 ✓
GameRendererMixin getNightVisionScale ✅ 存在于 GameRenderer,且字节码 access flag 为 staticprivate static + @ModifyReturnValue 合法
EntityMixin onInsideBubbleColumn / onAboveBubbleCol ✅ 1.21.1 两个方法均存在((boolean)
LivingEntityMixin setLastHurtByMob(LivingEntity)
PocketEffectScreenMixin renderEffects/renderBackgrounds/renderIcons/getEffectName ✅ 签名与 @Shadow 完全一致
CreativeModeInventoryScreenMixin selectedTab / CONTAINER / renderLabels ✅ 静态字段与 final 修饰符匹配
SpiderMixinCreativePocketPacketMixinItemStackMixinMinecraftClientMixin registerGoals / handleSetCreativeModeSlot / finishUsingItem / shouldEntityAppearGlowing ✅ 均存在

⚠️ 警告(建议修复/确认)

  1. block/entity/ProcessingTableBlockEntity.java — 未在描述中声明的行为变更
    proxy.extractItem() 改为恒返回 ItemStack.EMPTY,自动化(漏斗/管道/AE2 等)从此无法从加工台原料槽取出物品。GUI 走 getInput() 不受影响,所以不会卡物品,但这是一个明确的接口语义反转,PR 描述里没有提到。请确认是有意为之(若有意,建议在描述/提交信息里写明)。

  2. 双语手册未同步(与描述中"同步生成资源与双语手册"不符)
    本次护符/装备改动很重,但手册页一个都没动:

    • ageratum/{en_us,zh_cn}/006_prop/100_amulet.mditems/<row>/复制配方列表都缺 anvilcraft:armadillo_amulet;效果表仍是旧文案(羽毛=仅免摔伤、猫狗=仅驱离、绿宝石=仅折扣、红宝石=仅防火、沉默=仅无振动、异常=仅异常物品),未反映新增的缓降/驯服/抗性/力量/夜视免疫/食物有害效果免疫等。
    • 005_tool/301_weatherproof_armor.md:头盔只有"Provides clear vision in lava",无新夜视开关;靴子无蓄力跳开关说明。
    • 230_muti_amulet.md(自然护符组成由 羽毛→犰狳)文字未变(该页只引用配方,影响较小)。
    • 反而是与本 PR 主体无关001_spawner.md 标题("强制刷怪笼工作"→"立即尝试刷怪")和 210_spawner.md 被改了 —— 范围有点跑偏。
  3. i18n:提示键改为英文原句,中文译文变孤儿键
    ItemTooltipLang 删除了 tooltip.anvilcraft.equipment.*tooltip.anvilcraft.resonator.mining_desctooltip.anvilcraft.heavy_halberd.desctooltip.anvilcraft.item.power_converter 等稳定键,ItemTooltipManager 现在直接用英文句子当键。实测 zh_cn.json:旧键全部还在(如 tooltip.anvilcraft.equipment.breathing = 在水下和真空中供氧…),而 tooltip.anvilcraft.keyitem_countindentedcountcomrade_amulet.playerresin_block.mobthought.progressfluid_tank.fluid.valuescreen.anvilcraft.equipment.*screen.anvilcraft.structure_scanner.open_folderscreen.anvilcraft.storage.category.setting.tooltiptooltip.anvilcraft.property.night_vision/charged_jump 全部缺失。结果:中文玩家在装备/重戟/共振器/能量转换器/复合罐矿车等提示上会看到英文,直到 Weblate 补齐。建议至少把"装备与工具"类提示保留在 tooltip.anvilcraft.* 命名空间下(%s/%d 参数形式已具备,成本很低)。

  4. BlueprintRenderView.getBlockState 撤销了带注释的旧修复,但 diff 里没有补偿机制
    被删代码的注释明确说明"把非实心方块(流体/红石粉等)藏成空气会导致流体连接高度、红石下方顶面渲染错误"。现在 getBlockState 直接返回真实状态、hideNonOccludingNeighbors 字段与方法整体删除(确认无其他调用点)。这属于"反向修正",请确认预览中阶梯状流体/内部水面/红石顶面问题没有回归——建议附一张放置预览截图作为验证证据。

  5. IonocraftBackpackItem 删掉了装备状态整表重同步
    删除的 EQUIPPED_TRACKER + inventoryMenu.sendAllDataToRemote() 正是此前为"护腿等槽位出现幻影物品(穿戴只走 setItemSlot/onEquipItem,不经 inventoryMenu 广播)"加的 workaround;本次新增的 ClientboundUpdateAttributesPacket 只同步飞行属性,不涉及槽位。仓储菜单的槽位同步修复(StorageMenu 复用 inventoryMenu.slots 映射)是另一条路径。如果幻影物品的根因仍在,收敛点需要重新确认。

  6. NearestAttackableTargetGoalMixin 新增分支与相邻分支的 isAssignableFrom 方向相反
    新增:Spider.class.isAssignableFrom(clazz)(正确,可覆盖 CaveSpider);相邻两行却是 clazz.isAssignableFrom(AbstractSkeleton.class) / clazz.isAssignableFrom(Creeper.class)。对具体怪物类而言,clazz 不可能是 AbstractSkeleton 的父类,所以 DOG(骷髅驱离)分支疑似死代码(CAT 分支只在恰好是 Creeper 时命中)。建议三个分支统一成与 Spider 相同的方向。

💡 建议

  • BaseChuteBlockEntity.tick:有 source handler 时若 importFromTarget 未成功,现在会继续走掉落物拾取分支(原来直接跳过)。这看起来是有意修复(否则仓储端口下方的溜槽永远不吸掉落物),但请补一句说明/注释,便于排查行为变化。
  • StructureScannerFiles EXPORT:导出改为只写服务端存档目录后,多人游戏里玩家本机不再得到文件,openDirectory() 也被 hasSingleplayerServer() 关掉,反馈只有一条聊天信息。建议在导出成功提示里带上服务端相对路径(或在 MP 下禁用导出按钮/提示管理员),否则玩家容易以为失败。
  • FluidTankMinecartItem:把 "Tank" / "Fluid" 硬编码写死,原文用的是 FluidTankItemTooltip 里的常量;既然同 PR 刚清理过该类,建议抽成公共常量避免两处漂移。
  • BlockPlacementUtil.BlueprintLayout.getLayoutFacingscannerFacing.opposite + targetFacing − this.targetFacing (mod 4) 依赖"记录里存的是原始 targetFacing"这一隐含前提,且 autoRotate=true 时直接短路返回,建议补注释 + 单测(4 朝向 × autoRotate 开关 × upsideDown)。
  • AmuletAbilities.onTick / SpiderMixin 的护符查询AmuletManager.get(...).getAmuletsFromInventory(player) 每次都会 post 2 个 NeoForge 事件并全背包扫描;目前 tick 内只调一次、GravityManager 已把 ignoresCelestialGravity 提到循环外(这点做得不错),但 SpiderMixinAvoidEntityGoal 谓词会按蜘蛛×玩家每 tick 求值。蜘蛛农场场景建议加一层每 tick 缓存。

🟢 做得不错

  • StructureBlueprintFiles 的安全加固:isSafeName + 目录归一化 + 拒绝符号链接 + NOFOLLOW_LINKS + MAX_BYTES 双端限制 + 临时文件 ATOMIC_MOVE + 写入前二次 resolve 校验,比原先的客户端本地文件方案扎实得多。
  • StructureScannerFilePacket.handleOnServer 校验 containerMenu instanceof StructureScannerMenu && containerId 一致 && stillValid —— 补齐了 LIST/IMPORT/EXPORT 三个新动作的入口鉴权。
  • OverworldLikeGenerationBootstrapList.copyOf 快照修复遍历中移除监听器的 CME;BlockPointer 保留 POWERED 并在就位后主动 neighborChanged,红石搬运问题的定位是对的。
  • Ferocious / Merciless 按物品类型(重戟不加强度效率、共振器不加攻击力)收敛属性适用范围,方向正确且与提示文案一致。
  • 生成的 lang/recipe/tag/advancement 资源与数据生成器改动同步一致(nature_amulet 四合一/permutation 配方、tag、JEI 特殊配方 ↔ ItemCompressRecipeLoader 已交叉核对)。

📋 声称验证表

声称 状态 对应实现
犰狳护符 + 配方 + 驱离蜘蛛 + 潜行抗性 + 自然护符调整 ModItems / ModAmulets / ModAmuletDefinitions / AmuletAbilities / SpiderMixin / NearestAttackableTargetGoalMixin / EntityTypeTagLoader / jewel_crafting·four_to_one_smithing·permutation 配方 / tag / item model
扩展护符增益、伤害防护、猫狼驯服、铁傀儡友好 AmuletAbilities(onTick/onEffect/onInteract/onKnockback)/ LivingEntityMixin / GravityManager / ItemStackMixin
耐候头盔稳定夜视 ✅(+⚠️ 手册) EquipmentAbilities.updateNightVision / GameRendererMixin / ModComponents + wheel
耐候靴气泡柱下沉 EntityMixin @ModifyVariable 强制 downwards + EquipmentAbilities.shouldSinkInFluid
蓝图导入导出迁移服务端存档 + 单人 Shift 打开目录 ✅(+💡 MP 反馈) StructureBlueprintFiles / BlueprintClientFiles / StructureScannerFiles / StructureScannerScreen / StructureScannerFilePacket / StructureLoadUtil
结构磁盘自动旋转、智能放置器布局、蓝图预览 ✅ / ⚠️ BlockPlacementUtil / SmartBlockPlacerBlockEntity / SmartBlockPlacerScreen / StructureDiskPreviewSupport / BlueprintRenderView(⚠️)
建筑杖实体阻挡检测 + 3 秒高亮 + 放置交互兼容 BuildingRodObstructions / BuildingRodObstructionHighlight·Packet / BuildingRodService / PlacementInteractions / LargeBlockPlacePreviewEventListener / MinecraftClientMixin
搬运后红石信号更新 + 世界边界监听器遍历 BlockPointer / OverworldLikeGenerationBootstrap
仓储菜单盔甲/口袋槽位同步、创造模式口袋校验、效果布局与 JEI 避让 StorageMenu / CreativePocketPacketMixin / PocketEffectLayout / PocketEffectScreenMixin / JeiPocketEffectAreaMixin
分类一键重置、创造变体标记、仓储端口与溜槽交互 ✅ / 💡 CategoryList / CreativeModeInventoryScreenMixin / StoragePortBlockEntity / ChuteBlockItem / BaseChuteBlockEntity
余烬/寒霜金属块时移配方 + 提高寒霜产量 TimeWarpRecipeLoader(8 个新 recipe,frost ingot 3→4、4→8)
超电容与多相超限物质配方 + 永恒属性 ItemCompressRecipeLoader / ItemCompressCategory / RegistrumItemRecipeLoader / ModBlocks(ETERNAL)
远古海礁含水 + 伐木默认 4 ✅(+⚠️ 手册仅改了伐木) AncientSeaReefBlock / AnvilCraftServerConfig / amethyst_tools.md
重戟与共振器属性加成范围、提示与翻译参数统一 ✅(+⚠️ i18n) Ferocious / Merciless / HeavyHalberdItem / ResonatorItem / ItemTooltipManager / ItemTooltipLang / ToolPropertyLang / ScreenLang / CategoryLang
resolved/fixed #2468 #4841 … #4949(24 个 issue) ⏳ 未逐一核对 匿名 API 配额已用尽,未逐 issue 校验状态与对应提交;如需可下一轮单独核对

🧪 测试建议

被测目标 推荐场景 优先级
AmuletAbilities.onTick/onEffect/onInteract 普通护符 vs 自然/宝石护符 canActLike 包装路径;潜行开关(犰狳/羽毛);移除护符后效果 2 tick 内消失;异常护符 ↔ 食物有害效果(香甜/毒马铃薯/河豚) 🔴
EquipmentAbilities.updateNightVision 头盔开关关闭 → 效果被移除;外部夜视(他人给药水/信标)不被误删;死亡/换维度后恢复 🔴
BlockPlacementUtil.BlueprintLayout.getLayoutFacing 4 朝向 × autoRotate 开/关 × upsideDown 的坐标/朝向等价性(纯函数,单测最划算) 🔴
StructureBlueprintFiles 路径穿越(../、绝对路径)、符号链接、MAX_BYTES±1、导出目录被替换、原子写入后文件完整 🟡
StorageMenu 槽位映射 带 1/2 级口袋护腿时盔甲与口袋索引 ↔ 服务端 containerId 0 广播一致;屏幕打开期间穿脱护腿 🟡
BuildingRodObstructions.find/reject 实体 AABB 与非满方块碰撞形状相交;blocksBuilding=false 实体忽略;3 秒高亮到期 🟡
BaseChuteBlockEntity.tick 上方为仓储端口且无货可导入时,是否仍能拾取掉落物(新行为) 🟡

结论: COMMENT — 未发现必须阻塞的编译/注入错误(Mixin 目标已用 mappings + 字节码实核通过),但存在 5 处需确认的行为变更/文档与 i18n 缺口(第 1–6 条);且本 PR 内容已存在于目标分支 dev/1.21/1.6,请先确认是否应关闭本 PR。

标题建议(本次未自动修改:gh auth status 显示 /opt/data/home/.config/gh/hosts.yml token 无效,按流程跳过):
Expand amulet/equipment abilities, refine blueprint & storage interactions, and rebalance recipes 扩展护符与装备能力、完善蓝图建造与仓储交互并调整配方平衡


由 Hermes Agent 审查

@Gugle2308

Copy link
Copy Markdown
Collaborator

💾 Self-improvement review: Patched SKILL.md in skill 'minecraft-lang-pipeline-review' (1 replacement).

@Gugle2308

Copy link
Copy Markdown
Collaborator

已完成全部核对。以下是审查结论(直接输出,未执行任何 gh 评论命令)。

代码审查摘要 — PR #4951

操作: synchronize(dev/1.21/fix3dev/1.21/1.6
范围: 138 个文件(95 Java、35 新增、0 删除)/ 6255 行 diff;无幽灵文件;No newline 21 处(均为 generated JSON,符合本仓库 datagen 惯例)

✅ 本次做的独立核实(非仅读 diff)

核实项 手段 结果
全部 mixin 目标与签名 MC 1.21.1 官方 client_mappings EffectRenderingInventoryScreen.renderBackgrounds/renderIcons/getEffectName/renderEffectsItemInHandRenderer.renderItem(LivingEntity,ItemStack,ItemDisplayContext,boolean,PoseStack,MultiBufferSource,int)CreativeModeInventoryScreen.selectedTab/CONTAINERMinecraft.shouldEntityAppearGlowingEntity.onInsideBubbleColumn/onAboveBubbleCol(boolean)LivingEntity.setLastHurtByMobItemStack.finishUsingItem(Level,LivingEntity)→ItemStackMobEffectUtil.formatDuration(MobEffectInstance,float,float)GuiGraphics.renderTooltip(Font,List,Optional,int,int)GameRenderer.getNightVisionScale(LivingEntity,float) 全部 ✅
IronGolem.stopBeingAngry() mappings:该方法定义在 NeutralMob(有方法体=default),IronGolem 覆写了 startPersistentAngerTimer/setPersistentAngerTarget 等 ⇒ 确实 implements NeutralMob ✅ 可编译
withWearer 是否真会被触发 mappings:CustomHeadLayer 持有 ItemInHandRenderer 且渲染非头颅头部物品 ⇒ renderItem 会以 ItemDisplayContext.HEAD 调用 ✅ 动画路径成立
anvillib(版本未变 2.0.0+snapshot.530,jar 实探) 常量池解析 CreativeVariantPickerRegistry.isCreativePickerEnabled(ItemStack) ✅ public static;StreamCodecUtil.enumStreamCodec(Class) ✅ public static
Java loader ↔ generated JSON 对账 逐值比对 ember/frost 方块配方 = 锭配方严格 ×9 等比(含 consume 9000 = 1000×9、earth_core_shard_block/silver/titanium 加成同步);frost_metal_ingot_2/3(3→4、4→8)与 block_2/3 一致;超电容 #c:plates/ironcopper_block(JEI 用 Blocks.COPPER_BLOCK 与 loader Items.COPPER_BLOCK 等价);多相超限物质 shaped 9 粒 ✅
删除/改名残留 git grep on PR head hideNonOccludingNeighborsappendFixedTankacceptUploadBlueprintClientFiles.listFiles/directory、旧 StructureScannerFilePacket 构造器 零残留;3 个新 mixin 全部登记于 anvilcraft.mixins.json#anvilcraft:amulet 已含 armadillo_amulet(否则护符完全失效)✅

⚠️ 需要作者确认(非阻塞但影响行为)

  1. BlueprintRenderView 删除了 hideNonOccludingNeighbors 全部逻辑(回退了一处有记录原因的修复) — 基线里该字段默认为 truegetBlockState 用它把「非流体、非 isSolidRender 的邻格」当空气返回,注释明确写着这是为了不让熔岩/含水方块画出阶梯与内部水面、不让红石粉切掉下方顶面。该 setter 在基线无任何调用者 ⇒ 逻辑一直是生效的,本次删除是行为变化,不是死代码清理。若渲染已由别处(如新 renderWorldModel)解决,请在描述中说明;否则预览会重新出现上述伪影。
  2. 蓝图目录与结构盘目录分裂 — 导入导出改为 <world>/anvilcraft/blueprints,而结构盘/建造杖用的 .nbt 仍在 <world>/anvilcraft/structuresStructureSaveUtilStructureLoadUtil.readStructureFileOnServer),旧客户端目录 <gameDir>/anvilcraft/structures 的文件不迁移:扫描器导入下拉里看不到已记录的结构文件,用户需手动拷贝。建议统一目录或补迁移/手册说明。
  3. IonocraftBackpackItem 删除了装备状态变化时的 inventoryMenu.sendAllDataToRemote() 兜底(原注释描述的是 setItemSlot/onEquipItem 不经 inventoryMenu 广播 ⇒ 护腿等槽位幻影物品)。本次的槽位修复只覆盖 StorageMenu 的镜像槽位;若根因仍在,普通背包界面会复现。请确认已用「装备/卸下背包」实测验证(同时新增的属性包同步本身没问题)。
  4. BaseChuteBlockEntity.tickresetCD 重构顺带改了语义 — 原来「上方存在容器(source != null)」就跳过地面 ItemEntity 拾取;现在只有「真的导入成功」才跳过,导入失败会继续走拾取分支。看起来是有意的改进,但 PR 描述未提及,请确认。
  5. NearestAttackableTargetGoalMixinisAssignableFrom 方向不统一 — 新行 Spider.class.isAssignableFrom(clazz) ✅ 正确(覆盖 CaveSpider);但相邻两行 clazz.isAssignableFrom(AbstractSkeleton.class) 是反的:只有类恰好等于 AbstractSkeleton 才命中,Skeleton/Stray/Bogged/WitherSkeleton 都不命中。既然本 PR 已改这段 switch,建议顺手统一(或改用 #anvilcraft:amulet_valid/dog 标签)。
  6. 热路径背包扫描AmuletAbilities.onTick 每 tick 对每个玩家(即使没有任何护符)都会 getAmuletsFromInventory + 建 HashSet + getAmulet()SpiderMixin 又给所有蜘蛛无条件加了 AvoidEntityGoal,其判定回调在蜘蛛搜索附近玩家时逐玩家做一次背包扫描(多人服蜘蛛群会放大)。建议复用 AmuletManager 的 tick 级快照/缓存。
  7. StructureLoadUtil.getClientStructureDirectory 从「返回兜底路径」改为抛 IllegalStateException — 当前所有可达调用点都在服务端(SmartBlockPlacerBlockEntity!isClientSide 守卫、readStructureFileOnServerServerLevel),暂安全;但纯客户端误调用就会崩,建议返回空 Optional/记录警告而非抛异常。
  8. BuildingRodObstructions.find 逐 cell 做 level.getEntities(null, aabb)(大蓝图 = 上千次查询 + 每实体一次 Shapes.create);建议按连通区域合并 AABB 或先做整体预筛。
  9. BlockPointer 的 POWERED 保留sourcePart.state().getValue(POWERED) 只在目标 state 有该属性时被守卫。当前 applyToPos(..., requiredState)matches() 保证同方块故安全;但若日后 BlockPlacementRules 数据允许换方块就会抛 IllegalArgumentException。建议补 sourcePart.state().hasProperty(...) 或用 getOptionalValue(...).orElse(false)

💡 建议

  • #anvilcraft:amulet_valid/armadillo 已可被数据包扩展,但 LivingEntityEventListener 用硬编码 instanceof Spider(CAT/DOG 走的 EntityTypeTags.SKELETONS 是标签)⇒ 建议统一走标签,便于附属模组/整合包扩展。
  • BuildingRodRenderTypes.ghost 删掉了 DoubleSided(原本仅在 setup 时 disableCull)⇒ 幽灵预览背面不再可见;若属有意的渲染修正,建议在描述中点明。
  • getEquipmentWheel((EquipmentArmorItem) holding.getItem()) 强转依赖 abilityComponent 只对 EquipmentArmorItem 返回非 null;建议改为 instanceof 判断 + 早退,避免以后新增物品时 CCE。
  • refreshEffect 用 2 tick 时长:已用 visible=false 免粒子 ✅,但 HUD 图标会长期以极短倒计时存在,若要避免观感异常可考虑 200 tick 或 showIcon=false
  • 未在描述中说明的变更BURNING_HEATER 光照由「恒 15」改为 LEVEL>0 才发光、模型 ambientocclusion false→true;手册「强制刷怪笼工作」→「立即尝试刷怪」。建议补进 PR 描述。
  • 标题gh auth status 显示 active account token 已失效(未导出 token,本次未自动修改)。现标题未覆盖配方/平衡、i18n 统一、含水方块、世界边界与溜槽等大量内容,建议:
    Expand amulets & equipment, move blueprint files server-side, plus recipe/balance, storage and redstone fixes 扩展护符与装备、服务端蓝图文件、配方平衡与仓储/红石修复

🟢 看起来不错

  • 护符链路自洽:Armadillo 定义(obtainEntity 标签:spider+cave_spider)→ 物品/宝石合成配方/创造栏 → #anvilcraft:amulet 标签 → 效果(Shift 抗性 II、驱离蜘蛛)→ 工具提示 → 自然护符替换(四合一 smithing + permutation 配方、lang、tooltip 全同步);FEATHER 退出自然护符后文案 "Combines Silence, Cat, Dog, and Armadillo" 与代码一致;canActLike() 组合路径正确。
  • 装备能力组件默认 true(旧存档物品不丢能力),SwitchEquipmentAbilityPacket 校验 hand/slot 后再写组件;工具提示显示的按键与真正绑定键(SWITCH_TOOL_MODE一致(已核对 onKeyInput/onMouse 门控)。
  • 夜视生命周期细节到位:外部药水夜视经 preserveExternalNightVision 让位、只移除自己施加的实例(addEffect 后回读实例、实例同一性比较),摘头盔/关能力/退出都能正确清理;GameRendererMixin 提供稳定亮度,showIcon=true/visible=false 搭配合理。
  • 蓝图文件服务端化安全设计扎实:名字白名单+长度上限、normalize 后父目录比对、拒绝符号链接、大小上限、临时文件 + ATOMIC_MOVE、容器 containerId+stillValid 校验、导出后自动刷新列表 —— 相比原先客户端读写是明显收紧。
  • 仓储菜单槽位映射改为复用 inventoryMenu 槽位(含 InventoryMenuMixin 注入的 PocketSlot)修掉了旧代码 36+iInventoryMenu39-i 顺序相反造成的索引错位(盔甲/口袋同步的根因);创造模式口袋校验改为按真实槽位判定(isActive()),比原先 45 + capacity 更严格,负槽位分支也做了短路保护。
  • 生成资源与 Java datagen 一致(无 runData 漂移);fellingBlockPerLevel 2→4 与双语手册同步;ItemTooltipManager 的下标算术(AQUA 尾行 size-previousSize、LENS 三色落位 1/2/3)与占位符数量(%s/%d 均有 NORMAL_ARGUMENTS)经手工核对全部正确。

📋 声称验证表

声称 状态 对应文件
犰狳护符及配方、驱离蜘蛛、潜行抗性、自然护符调整 ModAmulets/ModAmuletDefinitions/ModItems/AmuletAbilities/SpiderMixin/TagLoader + 生成配方
扩展护符增益、伤害防护、猫狼驯服、铁傀儡友好 AmuletAbilities/LivingEntityEventListener/ItemTooltipManager
耐候头盔稳定夜视、靴子气泡柱下沉 EquipmentAbilities/GameRendererMixin/EntityMixin/ModComponents
蓝图导入导出迁移服务端 + Shift 开目录 ⚠️ StructureBlueprintFiles/BlueprintClientFiles/StructureScannerFiles/Screen(目录与结构盘不一致,见 ⚠️2
磁盘自动旋转、放置器布局、预览渲染 ✅/⚠️ BlueprintLayout.autoRotate/StructureDiskPreviewSupport/SmartBlockPlacerScreen(预览邻格隐藏被回退,见 ⚠️1
建筑杖实体阻挡 + 3 秒高亮 BuildingRodObstructions/Packet/Highlight/MinecraftClientMixin(message.anvilcraft.building_rod.blocked 键已存在)
搬运红石更新、世界边界监听器遍历 BlockPointer(+POWERED 保留)/OverworldLikeGenerationBootstrap(List.copyOf
仓储菜单同步、创造口袋校验、效果布局、JEI 避让 ✅/⚠️ StorageMenu/CreativePocketPacketMixin/PocketEffectLayout+ScreenMixin/JeiPocketEffectAreaMixin(背包底兜底被删,见 ⚠️3
分类筛选重置、创造变体标记、端口与溜槽交互 CategoryList/CreativeModeInventoryScreenMixin/PlacementInteractions/ChuteBlockItem/StoragePortBlockEntity
余烬/寒霜金属块时移配方、产量提升 TimeWarpRecipeLoader + 生成 JSON(严格 ×9 等比)
超电容/多相超限配方、永恒属性 ItemCompressRecipeLoader/RegistrumItemRecipeLoader/ItemCompressCategory/ModBlocks
远古海礁含水、伐木每级 4 原木 AncientSeaReefBlock/ModBlocks(blockstate "" 变体覆盖全部状态)/AnvilCraftServerConfig
重戟/共振器属性范围、提示与翻译统一、双语手册 Ferocious/Merciless/ItemTooltipManager/ToolPropertyLang/ageratum
20 个 issue 的 resolved/fixed 无法逐条核实(issue 状态需 API),但对应改动在上述文件中均有落点

🧪 测试建议

被测目标 推荐场景 优先级
StorageMenu 槽位索引 穿戴全套盔甲+口袋,逐一与 inventoryMenu 比对 index→(容器,槽位);装备/卸下飞行背包后重开界面 🔴
AmuletAbilities 夜视生命周期 戴头盔→喝夜视药水→药水到期→摘头盔;确认只移除自身实例 🔴
StructureBlueprintFiles.read/write ../、绝对路径、大小写 .NBT、符号链接、超 MAX_BYTES、空文件 🔴
BlueprintLayout.getLayoutFacing autoRotate=false 下 4 个朝向 × 4 个目标朝向的坐标/朝向对照表 🟡
BuildingRodObstructions 实体占用单格/多格、被方块遮挡、大蓝图(性能) 🟡
BaseChuteBlockEntity 输入 上方容器满/空 + 地面掉落物同时存在(验证新 else 分支) 🟡

结论: COMMENT — 未发现编译级/资源级硬伤:mixin 目标、依赖 API(anvillib snapshot.530)、datagen↔Java 对账、残留引用、注册清单均已独立核实通过。但 ⚠️ 1/3/4 属于需要作者确认的行为回退/静默语义变更⚠️ 2 影响用户可见的文件位置迁移,建议澄清(或补说明)后再合并。

@Gugle2308

Copy link
Copy Markdown
Collaborator

💾 Self-improvement review: Patched references/authoritative-vanilla-verification.md in skill 'mixin-injection-verification' (1 replacement). · Patched SKILL.md in skill 'mixin-injection-verification' (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

4 participants