Skip to content

Fix structure construction and preview, adjust fluid network loading and giant anvil collision 修复蓝图建造与预览并调整流体网络加载和巨型铁砧碰撞 - #4957

Merged
PigeonNian merged 1 commit into
Anvil-Dev:dev/1.21/1.6from
WhereisFff:dev/1.21/fix4
Sep 20, 2026

Conversation

@WhereisFff

Copy link
Copy Markdown
Contributor
  • 分离蓝图配置、材料与容器内容,返还材料自带物品,支持缺料确认后放置空容器
  • 校验方块实体与实体数据及操作权限,保留机器配置并转换方向和蓝图内部引用
  • 修正蓝图自动朝向,优化建筑杖半透明预览及扫描仪预览缩放、居中和边框对齐
  • 补充建筑杖放置音效,更新组件不匹配与容器缺料的中英文提示
  • 延后流体容器能力检测,避免加载回调中同步查询其他区块
  • 略微收缩下落巨型铁砧的碰撞箱

- 分离蓝图配置、材料与容器内容,返还材料自带物品,支持缺料确认后放置空容器
- 校验方块实体与实体数据及操作权限,保留机器配置并转换方向和蓝图内部引用
- 修正蓝图自动朝向,优化建筑杖半透明预览及扫描仪预览缩放、居中和边框对齐
- 补充建筑杖放置音效,更新组件不匹配与容器缺料的中英文提示
- 延后流体容器能力检测,避免加载回调中同步查询其他区块
- 略微收缩下落巨型铁砧的碰撞箱
Copilot AI lite review requested due to automatic review settings September 20, 2026 04: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.

@Gugle2308

Copy link
Copy Markdown
Collaborator

⚠️ Dangerous command requires approval:

curl -sL "https://api.github.com/repos/Anvil-Dev/AnvilCraft/pulls/4957" | python3 -c "
import json,sys
d=json.load(sys.stdin)
print('title:',d.get('title'))
print('state:',d.get('state'),'merged:',d.g...

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

操作: review_requested(正常审查)
范围: 23 个文件(19 Java / 3 新增 / 0 删除)/ 1864 行 diff / 61 hunks
核对方式: patch-diff 下载 diff + git fetch fff dev/1.21/fix4:refs/remotes/h4957(head = 2ca45bbd)逐行交叉验证源码(PR 引用的 FilterOnlyContainerEntityBuildAdapter.PlannedonlyOpCanSetNbtLectern/Jukebox NBT 键名等均已确认存在/签名匹配,无编译级问题)。


🔴 关键

1. BlueprintBlockConfiguration.java:317-322 — 镜像蓝图时 layerPositions 被翻转了两次

if (config.contains("layerPositions") && placement.mirror() != Mirror.NONE) {
    byte[] source = Arrays.copyOf(config.getByteArray("layerPositions"), POSITION_COUNT);
    ...  mirrored[i - i % side + side - 1 - i % side] = source[i];   // 逐行反列
    config.putByteArray("layerPositions", mirrored);
}

SmartBlockPlacerBlockEntity.buildOrderedPositions(basePos, targetFacing, layerPositions, upsideDown)(第 722 行起)把网格定义在放置器自身坐标系里:

Direction right = facing.getClockWise();
... basePos.relative(right, column - RADIUS).relative(facing, RADIUS - row)

getFacing() 读的是方块状态的 FACING 属性(第 178-184 行);BlueprintMultiblocks.expand 已经对放置状态做了 placement.stateOf(state) = state.mirror(mirror).rotate(rotation)BlueprintMultiblocks.java:69)。镜像后状态 FACING 变成反方向、right 随之镜像,网格坐标系已经跟着一起镜像了;数组再翻一次等于把选中格翻回原位,与结构其余部分的镜像方向相反(用 N 朝向的例子手算:镜像后 (row0,col0) 的世界格恰好是原位,而不是镜像位)。

→ 结论:这里应该完全不动数组(旋转同样不需要,所以“只处理镜像、不处理旋转”的不对称恰好说明翻转是多余的)。反之若数组本意是“世界轴系绝对格”,那旋转和 selectedLayer 的上下翻转也必须处理——两种语义只能选一种,现在是自相矛盾的中间态。


⚠️ 警告

2. PR 声称「更新组件不匹配与容器缺料的中英文提示」,但只改了英文

  • src/generated/.../en_us.json / en_ud.json ✅ 新文案 + 新增 message.anvilcraft.building_rod.contents_missing
  • src/main/resources/assets/anvilcraft/lang/zh_cn.json:2823component_mismatch 仍是旧语义「部分方块的组件不匹配;请在3秒内再次右键点击以确认放置」,且没有 contents_missing —— 新分支 BuildingRodService.java:592-593contents_missing 时,中文客户端只能回退到英文。

建议补 zh_cn(及其他已翻译语言)的 contents_missing,并把 component_mismatch 改成与新英文一致(“使用现有材料及其数据”)。

3. BuildingRodService.java:430-431 / 479-481 — 权限不足复用了 “blocked” 文案

if (blockMaterial.requiresOperator() && !player.canUseGameMasterBlocks()) {
    message(player, "blocked");   // = "Placement area is obstructed or protected"

blocked 描述的是“区域被阻挡/受保护”,与实际原因(该方块实体/实体 NBT 只有管理员可设置)无关,玩家会去检查地形而不是权限。既然本次已经为缺料新增了 key,建议同样加一个 operator_required(中英文)。


💡 建议

4. StructureScannerScreen.java:1177 — 预览边框与方块在 Z 方向差 1 格
扫描数据里 z 存储为 1..rangeZ 对应的局部 0..rangeZ‑1(scanNextLayerfor (z = 1; z < rangeZ + 1; z++) calculateWorldPos(x, layer, z - 1, ...)),预览把方块画在 data.z() + 1(= 世界偏移 1..rangeZ ✅),而边框是 Shapes.create(0, 0, 2, rangeX, rangeY, rangeZ + 2)(Z ∈ 2..rangeZ+2 ❌)。旧代码边框用完全不同的姿态链,看不出错位;现在边框与方块共用同一 applyPreviewTransform 后,这一格错位会直接显形。既然是同一批“边框对齐”改动,建议顺手核对成 1 .. rangeZ + 1

5. BuildingBlockMaterial.java:46-54 — 校验 try 只包住了第一次 load

try { entity.loadWithComponents(input, registries); }
catch (RuntimeException e) { throw new IllegalArgumentException(...); }
BlockEntityContentAdapter.Extracted extracted = ...;
BlockEntity empty = createEntity(state);
empty.loadWithComponents(extracted.config(), registries);   // ← 同一份数据的第二次 load,未受保护

blueprint() 只 catch ConstructionBlueprintException | IllegalArgumentExceptionBuildingRodService.java:517),第二次 load 若因模组 loadAdditional 里的 NPE/AIOOBE 抛别的 RuntimeException 就会穿透到网络包处理层。既然本 PR 的目标是“校验蓝图数据”,建议把两处 load 放进同一 try(separateContents 同理,第 123 行)。

6. BlueprintBlockConfiguration.java:324-337 — 内嵌世界坐标带来的行为变化值得写清楚
StructureScannerBlockEntity 改用 saveWithFullMetadata 后,结构文件里带上了扫描时的绝对 x/y/zsourceOrigin() 靠它反推原点。当原点不可确定(来自其他工具的结构文件、或同一快照里多台机器原点不一致 → 返回 null)时,唯一路径是 remove(config, "Ix", "Iy", "Iz"),即日晷(Heliostats)的目标坐标被静默丢弃(加载后回到默认目标),而不再是旧版“原样复制(但坐标已失效)”。请确认这是期望行为,并在 PR 描述/注释里点明“非扫描器来源的蓝图会丢失日晷目标”。另:StructureSnapshot.java:29 的 javadoc 仍写 “nbt 为方块实体的完整数据(saveWithId 语义)”,与本次改动不符,请同步。

7. FluidNetworkManager.addContainerAfterLoad / ServerBlockEntityEventListener.onLoad — 每个方块实体加载都会置 dirty
延迟检测本身是对的(见下),但 addContainerAfterLoadaddContainer 会无条件 dirty = true,于是任何带方块实体的区块加载都会触发一次全量 rebuild(含对所有已登记位置的 isContainer 能力查询)。旧代码只有真容器才置脏。可考虑先查一个“已知非容器”的小集合,或在候选位置已登记时跳过置脏。


🟢 看起来不错

  • 延后流体容器能力检测:已核对 FluidNetworkManager.rebuild() —— 非容器/已失效位置会在重建时被注销(isContainer 检查在 tick 中执行),因此加载回调只登记候选位置是安全的,确实避开了加载回调里同步查询其他区块的能力代理。
  • 配置/材料/内容分离的设计自洽:容器物品被消耗时其自带内容进 allocated.returnedconsume() 返还玩家;蓝图记录的内容物单独预留并 insert 进放置后的方块 —— 不会重复获得,也不会丢料。reserveBlockexact 改为比较剥离内容后的 empty 与 expected,语义正确(旧代码用 source.resource 比较,带内容的容器永远匹配不上)。
  • 校验链Blocks ENTITY_TYPE id 与方块不匹配、砲台书架、唱片机、阀门方向(checkValves)、sign 文本非法均抛 IllegalArgumentException,且都落在 blueprint()catch (… | IllegalArgumentException) 内(已逐个确认抛点都在 try 内)→ 表现为 invalid_structure 提示而非崩服。
  • 建筑杖放置音效(蓝图单声 NOTE_BLOCK_PLING / 逐方块 SoundType,按方块去重)实现干净。
  • 扫描仪预览统一了 pose 链,顺带修掉了旧代码里写死的 45 + getFacingYawOffset()(=270) 与方块渲染不同链导致的边框错位;getFacingYawOffset/Mth 残留清理无误(Mth 仍有其他使用,无未用 import)。
  • BlueprintPlacement.facingPlayer 收敛了自动朝向(player.getDirection()getOpposite()),客户端唯一调用点。
  • FallingGiantAnvilEntity.deflate(0.01) 只影响碰撞盒,尺寸未外泄到 EntityDimensions,符合“略微收缩”的意图。

📋 声称验证表

声称 状态 对应实现
分离蓝图配置、材料与容器内容,返还材料自带物品 BuildingBlockMaterial.{extract,separateContents,withConfiguration}BuildingMaterials.reserveBlock/returnedconsume()
支持缺料确认后放置空容器 BuildingMaterials.reserve() cells 分支(HAS_BOOK/HAS_RECORD=false + missingContents)→ contents_missing
校验方块实体与实体数据及操作权限 requiresOperatoronlyOpCanSetNbt 排除 sign/lectern)、probe.onlyOpCanSetNbt()nbt.id 校验;⚠ 拒绝提示复用 blocked
保留机器配置并转换方向和蓝图内部引用 BlueprintBlockConfiguration.take/applytransform(Facing/Valves/Ix…);🔴 layerPositions 镜像翻转两次
修正蓝图自动朝向 BlueprintPlacement.facingPlayer
建筑杖半透明预览 / 扫描仪缩放居中边框对齐 building_rod_ghost fsh+json、BLOCK_GHOST RenderType、applyPreviewTransformrenderLevelBorder 共用 pose;💡 边框 Z 差 1 格
补充建筑杖放置音效 playPlacementSounds
更新组件不匹配与容器缺料的中英文提示 ⚠️ 仅英文 en_us/en_ud ✅;zh_cn ❌ 缺 contents_missing、旧语义未改
延后流体容器能力检测 ServerBlockEntityEventListener.onLoad + addContainerAfterLoad(doc 已更新);💡 每次都置 dirty
略微收缩下落巨型铁砧的碰撞箱 makeBoundingBox().deflate(0.01)

🧪 测试建议

被测目标 建议场景 优先级
BlueprintBlockConfiguration.transform 同一蓝图分别以 rotation=NONE/90/180/270、mirror=LEFT_RIGHT/FRONT_BACK 放置含「智能方块放置器(POSITION 模式)」+「日晷」+「控制阀门」的结构,逐格比对选中格/日晷目标/阀门方向 🔴
BuildingMaterials.reserveBlock 玩家提供「带内容物的箱子」+ 蓝图要求该箱子的内容物;断言内容物返还一次、放置后的箱子内容正确(不重复不丢失);take 跨多个同种容器时返还数量 = 内容数 × 取用数 🔴
BuildingBlockMaterial.separateContents/withConfiguration 打包机/熔炉/唱片机/砲台等含遗留数据的机器:exact 与 mismatch 两段匹配是否按预期触发 component_mismatch,遗留数据是否来自实际消耗的物品 🟡
BlockEntityContentAdapter.extract(lectern/jukebox 分支) 非法 Book(非成书/书与笔)、LootTable 箱子、非法 sign 文本 → 应得到 invalid_structure 而非异常穿透 🟡
BlueprintBlockConfiguration.sourceOrigin 单台机器蓝图 / 多台机器蓝图 / 手工删除 x/y/z 的结构文件(期望 null → 丢弃 Ix/Iy/Iz) 🟡
FluidNetworkManager 加载含大量方块实体的区块后,网络重建次数与非容器注销正确性(避免每 tick 重建) 🟢

结论: REQUEST_CHANGES — 整体方向与实现质量都不错(能力检测延后、内容物分离、校验链都站得住),但需要先确认 layerPositions 的坐标系语义(🔴 疑似二次镜像),并补齐 PR 自己声称的中文提示文案(⚠️)。其余为预览边框 1 格错位、校验 try 范围、坐标来源行为与文档同步等小改。

建议标题(本次 gh token 已失效,未自动修改:gh auth statusThe token ... is invalid

Fix blueprint building & preview; separate blueprint settings from contents; defer fluid container detection; shrink giant anvil hitbox 修复蓝图建造与预览:分离蓝图设置与容器内容、延后流体容器检测、收缩巨型铁砧碰撞箱


由 Hermes Agent 审查

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

Copy link
Copy Markdown
Collaborator

跳过审查 — PR #4957 已关闭(closed)

操作: closed
原因: 按 webhook 审查规则,closed / labeled 事件不触发审查流程,本次不发表任何评论(避免对已关闭 PR 留噪音)。

等待该 PR 重新打开(reopened)或推送新提交(synchronize)后,再按标准流程下载 diff 并输出完整审查意见。


由 Hermes Agent 处理

@Gugle2308

Copy link
Copy Markdown
Collaborator

💾 Self-improvement review: Patched SKILL.md in skill 'building-rod-blueprint-review' (1 replacement). · Patched SKILL.md in skill 'coordinate-transform-pr-review' (1 replacement). · Patched SKILL.md in skill 'minecraft-modding' (1 replacement). · Patched references/blueprint-block-configuration-and-placement-frame.md in skill 'building-rod-blueprint-review' (1 replacement).

@Gugle2308

Copy link
Copy Markdown
Collaborator

分析完成。以下是审查意见(将直接由 webhook 发布到 PR 评论区)。


代码审查摘要 — PR #4957

操作: opened(dev/1.21/fix4dev/1.21/1.6
范围: 23 个文件(19 Java、3 新增、0 删除)/ 1864 行 diff / 100 KB,diff 完整(尾部 JSON 收尾正常,无 ghost 文件,无 EOF 缺换行)
基线核对: 本地 git fetch 到具名 ref 与远端一致(base 0b2f54774c = 当前 dev/1.21/1.6;head 2ca45bbd07 = dev/1.21/fix4),所有交叉引用都在 head 树上核对,未用陈旧本地分支。


⚠️ 警告(建议合并前处理)

1. 流体网络:任意方块实体加载都会置脏并推迟重建 —— 全量 rebuild 触发频率大幅上升

ServerBlockEntityEventListener.onLoad(diff 1703-1707)现在对所有非 IFluidHandlerHolder 的方块实体无条件调用 addContainerAfterLoad,而该方法内部是:

addContainer(level, pos);          // d.containers.add(pos); d.dirty = true;
data(level).deferRebuild = true;
  • 原实现先做 FluidNetworkScanner.isContainer(level, pos, blockEntity) 过滤,只有真容器才会 dirty = true;现在每加载一个箱子/熔炉/告示牌都会置脏 → 下一 tick 走完整 rebuild()(清空 networks/partIndex,对每个容器重新 flood-fill 整张管网)。在存在较大管网且区块持续加载(跑图、区块加载器)时,相当于每 tick 一次 O(管道数) 重建
  • deferRebuild 每 tick 只消费一次,dirty 保持 true;区块连续加载时该标志会被反复置位 → 重建可被无限推迟(饿死),期间放置的管道/容器不会被索引,流体停摆。
  • 候选集合虽然会在 rebuild 中被 d.containers.remove(...) 剪枝,但瞬时集合 = 全level方块实体,剪枝前每个都要做一次能力查询。

建议(保留「加载回调不做能力查询」这个正确方向的前提下):a) 候选位置放入待检队列,每 tick 限量处理,确认是容器后才 dirty = true;b) 重建合并/限频(最小间隔或最大推迟次数上限);c) 加载侧只做零成本判断(getBlockState() 级别/已知容器类型),把能力查询留在延后阶段。注释里担心的「能力代理同步跨区块回查」只发生在能力查询上,登记本身可以继续做廉价过滤。


💡 建议(非阻塞)

2. BuildingEntityTransform.sanitize 白名单作用于核心路径,会静默裁剪扩展模组的实体数据

它被放在 BuildingRodService.blueprint 里、adapter.plan(...) 之后统一执行,而白名单只认识原版键。EntityBuildAdapters.register(...) 是公开注册点,第三方适配器 plan 出来的自定义 NBT 会被无声剥掉(其 spawn() 只会拿到 id/Pos/Rotation/CustomName…)。建议白名单下沉到各适配器,或让适配器自己声明允许的键,并在文档/注释中写明该契约。
另外两处原版键未列入白名单、会随蓝图丢失:ArmorStandDisabledSlots(盔甲架锁定槽位)、ItemFrameItemDropChance。其余键集核对无误(船 Type、矿车显示属性/Command、盔甲架姿态组、画/展示框 variant/Facing/TileX-Y-Z/ItemRotation),且实体自带内容物(盔甲架装备、展示框物品、容器物品)已正确拆到 contents 并由各 insertContents 还原。

3. 定日镜内部引用(Ix/Iy/Iz)静默丢弃的两条路径

Ix/Iy/Iz 语义已核对:HeliostatsBlockEntity 存的确实是 irritatePos绝对世界坐标,因此 local = target - sourceOriginplacement.worldOf(local) 的换算方向是对的,越界目标丢弃也是有意设计。但以下两种情况用户完全无提示:a) sourceOrigin(snapshot) == null(本 PR 之前扫描的旧磁盘没有 x/y/z;litematica 导入同理);b) 目标落在结构外。建议像 unsupported 那样给一条 lang 提示。

相关文档/兼容点:saveWithFullMetadata 把扫描点绝对坐标写进了蓝图 NBT —— 结构文件现在携带建造地点;同时 StructureSnapshotCodec 类注释声称「同一内容无论来源如何都会产生相同的规范 NBT 与内容哈希」,而 hash() 目前树内无调用者,位置相关这一点最好在注释里说明。StructureSnapshot.BlockEntry 的注释仍写「saveWithId 语义」,请与已更新的扫描器注释一并对齐。

4. 小项清理

  • BlueprintBlockConfigurationimport net.minecraft.world.item.Items; 未使用(只用了 ModItems.CHECK_VALVE 与字符串字面量 "Items")。
  • 同文件 filterSamples 内联全限定名 dev.dubhe.anvilcraft.inventory.container.FilterOnlyContainer,建议改为 import。
  • StructureScannerScreen.applyPreviewTransformprojectedWidth/Height 作除数,空预览(bounds 为 0)会得到 Infinity/NaN scale,建议 Math.max(1.0e-4F, …) 兜底。

5. 文案:本次只重新生成了 en_us/en_ud,而 src/main/resources/assets/anvilcraft/lang/zh_cn.json 仍在仓库内且仍是旧的 component_mismatch 中文、且没有 contents_missing 键。若「更新中英文提示」要求一起落地,请补 zh_cn(或注明由 Crowdin 后续同步)。


🟢 已验证正确的部分(便于作者知道哪些已被交叉核对)

  • 配置/材料/内容分离reserveBlock 的 exact 比较已改为「剥掉内容后的物品」对 expectedreturnedconsume()placeItemBackInInventory 返还,材料自带内容物既不丢失也不重复;缺料确认分支正确复位 HAS_BOOK/HAS_RECORD 并置 componentMismatch|missingContents(对应新键 contents_missing),二次确认会重新核对 cells/entities/supplied
  • 配置白名单键集已与 FilteredItemStackHandler.serializeNBT/deserializeNBTFilterEnabled/Size/Inventory + 槽位 Disabled/SlotLimit/SlotFilterEnabled/SlotFilterItem)、FilterOnlyContainerItems/Size,交易站 3 槽、物品探测器 9 槽)逐一对照,并通过 ChargerBlockEntity/DischargerBlockEntityDepository 键验证 filtering() 拿到的是嵌套 handler 复合标签 —— 过滤设置能正确保留、库存内容被正确剥离。
  • layerPositions 镜像:litematic 推演确认 LEFT_RIGHTFRONT_BACK 两种镜像下只需翻转列索引(i % 5,即放置器的 right 轴):放置器网格是朝向相对的,stateOf 的镜像与 getClockWise 的关系保证右向项恒取负、深度项恒不变;并已兼容旧 positionMarks 与 compound layer_N 格式。
  • 唱片机/讲台JukeboxBlockEntity 确实实现 ContainerContainerSingleItem extends Container,用 1.21.1 client_mappings 核对 eyn → bqk),所以 insertContainer 分支能还原唱片,不存在「抽取了内容却没有回填」的丢失;讲台额外分支 + afterContents 处理了「先放书后设页」的顺序。
  • 坐标/引用链路StructureSnapshotCodec.parseBlocks 原样保留 nbtBlueprintMultiblocks.expand 只传引用不改 NBT,BuildingBlockMaterial.extractcopy() 再改 —— 磁盘/预览快照不会被污染;transformFacing 旋转在设置项里只有控制阀的 Facing,不存在误旋转。
  • 巨型铁砧 deflate(0.01):对 anvilcraft$hasBlockCollision 的 0.001 面探测是安全的(静止位置本身由收缩后的 getBoundingBox() 决定,探测仍与邻块重叠 0.001);方块判定走 anvilcraft$getBlockingFacePos 的 ±1 循环,不依赖 AABB。
  • 预览重构applyPreviewTransform 的投影尺寸公式与 scale(-s,-s,-s) × 旋转 的合成一致;旧 renderLevelLikeWithFixedSize 内部隐含的 +45° 已并入统一的 +315°(朝向与旧观感一致),方块与边框终于共用同一 pose;renderLevelLikeBlocks 抽取后 push/pop 平衡未变;facingPlayer 成为唯一实现且只由客户端使用、朝向随包发给服务端,客户端/服务端不存在朝向分歧。
  • 着色器building_rod_ghost.fsh/json 是原版 rendertype_translucent 的忠实拷贝(vertex 复用、uniform/sampler 齐全),仅增加 alpha<0.1 的镂空 discard;BLOCK_GHOST 使用原版半透明的 786432 缓冲与 createCompositeState(true)ModShaders@Getter/方法引用可用。
  • API 存在性抽查(head 树 / 1.21.1 mappings):EntityType.create(Level)Entity.onlyOpCanSetNbt()BlockEntity.saveWithFullMetadataMath.clamp(Java 21)、TeslaFilter.getFilter 不会返回 null(emptyFilter)、POSITION_*/FilterOnlyContainer(@Nullable,int)/setLiquidLevel/loadBlueprint/ModItems.CHECK_VALVE.asStack(n) 均存在;除 Items 外无未使用 import。

📋 声称验证表

PR 声称 状态 对应实现
分离蓝图配置、材料与容器内容,返还材料自带物品 BuildingBlockMaterialcontents/Separated/withConfiguration)、BuildingMaterials.BlockSupply+returnedconsume()
缺料确认后放置空容器 reserve 逐 cell 预留;hasProperty(HAS_BOOK/HAS_RECORD)→false;新键 contents_missing
校验方块实体数据 + 操作权限 id 比对、loadWithComponents try/catch、requiresOperator+onlyOpCanSetNbt、命令方块矿车拦截
保留机器配置、转换方向与蓝图内部引用 BlueprintBlockConfiguration.take/strip/transform(阀门 Face/Flow、layerPositionsIx/Iy/Iz 重定位)
修正蓝图自动朝向 BlueprintPlacement.facingPlayer(客户端 + 共享;注意相较旧客户端实现朝向翻转 180°,属预期修正,且经包同步)
建筑杖半透明预览 / 扫描仪缩放·居中·边框对齐 BLOCK_GHOST+新着色器、applyPreviewTransformcachedPreviewBoundsrenderScannerBorder 重构、renderLevelLikeBlocks 抽取
补充放置音效 playPlacementSounds(蓝图 PLING / 非蓝图按方块音效去重)
更新中英文提示 ⚠️ en_us/en_ud 与生成器已更新;zh_cn.json 未同步(旧文案 + 缺新键)
延后流体容器能力检测 addContainerAfterLoad 注释+实现、事件监听器、LevelChunkMixin 注释(代价见警告 1)
略微收缩巨型铁砧碰撞箱 makeBoundingBox().deflate(0.01)

结论: COMMENT(Approved with suggestions) — 未发现会阻塞合并的正确性缺陷;核心「配置/内容分离 + 数据校验 + 引用重定位」链路自洽且防御性不错。唯一建议合并前处理的是警告 1(流体网络脏标记语义变化带来的重建频率与饿死风险),其余为可选清理。


说明:本次 gh auth status 显示 token 已失效(hosts.yml 中 account Gugle2308 invalid),按约束执行 gh pr edit(也严禁 export GITHUB_TOKEN),因此未自动改标题。建议标题:
Fix blueprint build/preview: split configs & container contents, validate BE/entity data, defer fluid capability checks, shrink giant anvil hitbox 修复蓝图建造与预览:分离配置与容器内容、校验方块实体/实体数据、延后流体能力检测、收缩巨型铁砧碰撞箱

由 Hermes Agent 审查

@Gugle2308

Copy link
Copy Markdown
Collaborator

💾 Self-improvement review: Patched SKILL.md in skill 'minecraft-modding' (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.

4 participants