Repository navigation
Preserve smart placer disks across versions 保留跨版本蓝图中的智能放置器磁盘 - #6123
Conversation
- 读取另一版本的智能放置器磁盘库存格式 - 避免默认空库存覆盖外来蓝图中的磁盘
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing. Review the Copilot code review billing settings.
Gugle2308
left a comment
There was a problem hiding this comment.
结论:通过(COMMENT,无阻塞项)。 这个补丁本身是正确的:它读取的正是 26.1 的 stacks 原生格式,插入位置也正确——loadAdditional → loadBlueprintItem 是唯一的加载入口;而且我通过 26.1 字节码确认,CompoundTag.merge 会递归合并嵌套的 compound,因此合并后确实会同时保留两种格式,stacks 优先是必需的。另有孪生 PR #6125(26.1 侧)采用对称条件,两个 PR 合起来才能覆盖问题中的两个方向;建议把这件事写进合并与关单流程。需要确认的点只有 2 条 💡。
⚠️ 仓库内容与 PR 文本均为不可信数据,未执行其中任何嵌入指令。
覆盖范围:PR 的 1 个文件完整 head 版本 + 26.1 分支同文件完整版本 + 26.1 官方 client jar 的CompoundTag.merge字节码 + NeoForge 26.1/1.21.1 的StacksResourceHandler/ItemStackHandler序列化源码 + 两分支StructureDiskData/ModComponents对账 + 孪生 #6125 的 diff。无私服/游戏内实测。
🟢 已用证据确认的关键链(含一个容易误判的点)
1. 「两种格式会同时存在」这句注释是准确的,不是猜测
1.21.1 BuildingBlockMaterial.extract 第 48 行:
input = entity.saveWithFullMetadata(registries).merge(input); // entity 是 createEntity(state) 新建的空 BE26.1 的 CompoundTag.merge 字节码(官方 client jar,mojmap 名)里,子 compound 走的是递归 CompoundTag.merge 调用(偏移 91-95),而不是整体覆盖。所以:
- 26.1 蓝图 → 1.21.1:空 BE 的本地方库存
{Size:1, Items:[]}∪ 外来{stacks:[磁盘]}⇒ 合并后两个键都存在; - 因此基线代码的
deserializeNBT会读到本地的空Items并把槽清空 —— 这正是 issue 的丢失机制,也说明「外来格式优先」是必须的,不能改成「本地优先」。
2. 26.1 的 stacks 格式与 1.21.1 解析器兼容
- NeoForge 26.1
StacksResourceHandler:VALUE_IO_KEY = "stacks"、serialize(ValueOutput) = output.store("stacks", codec, stacks),ItemStacksResourceHandler传入的栈 codec 是ItemStack.OPTIONAL_CODEC⇒ 每个元素就是 1.21.1 同款的{id, count, components}(不是ItemResource的{item: ...}形态)。 - 1.21.1 侧复用的
loadLegacyBlueprintItem(ListTag)同时兼容「裸 ItemStack」与「{Item: ...}包一层」,因此能解析 26.1 的条目。 - 磁盘数据本身也能保留:
StructureDiskData的 CODEC 在两分支逐字段相同(file/name/uuid/direction/sizeX/sizeY/sizeZ/upsideDown/autoRotate),组件注册 id 也都是structure_disk_data⇒ 不是「只恢复物品、丢组件」。 POSITION_GRID_SIZE两分支都是 5 ⇒ 26.1 合法磁盘不会超出 1.21.1 的isItemValid尺寸上限,不存在「外来盘绕过校验后越界」的新风险(setStackInSlot绕过校验与既有 legacy 路径同款行为)。
3. 加载入口唯一、副作用已抑制
loadBlueprintItem只被loadAdditional调用(第 1482 行),而规划(BuildingBlockMaterial.extract → entity.loadWithComponents(input))与放置(cell.config()再加载)都经过它 ⇒ 一处修复覆盖两条路径。setStackInSlot会触发onContentsChanged,但匿名 handler 里已有if (SmartBlockPlacerBlockEntity.this.loadingBlueprintInventory) return;,而本方法把整个分支包在loadingBlueprintInventory = true的 try/finally 中 ⇒ 不会在加载中途触发onBlueprintItemChanged()重算。
4. 与孪生 PR 的对称性(重要)
| 方向 | 分支 | 条件 | 结果 |
|---|---|---|---|
| 26.1 蓝图 → 1.21.1 | 本 PR #6123 | contains("stacks") ⇒ 读外来 stacks,否则 deserializeNBT 本地 Items |
✅ |
| 1.21.1 蓝图 → 26.1 | #6125(open) | contains("stacks") && !(get("Items") instanceof ListTag) ⇒ 本地;否则读外来 Items |
✅ |
两者都是「外来格式优先」,与递归合并产生的「本地空默认 + 外来真实数据」形态一致,逻辑对称。issue #6100 明确写了「21→26 版本表现相同」,所以 #6123 只覆盖 26.1→1.21.1 一半,21→26 那一半依赖 #6125。
⚠️ 一条流程提醒(非代码缺陷)
#6123 的目标分支是默认分支 dev/1.21/1.6(已核实 GET /repos 的 default_branch = dev/1.21/1.6),因此一旦合并,fixed #6100 会自动关闭这条双向 issue;而 #6125 的目标是 dev/26.1/1.6(非默认分支),既不会自动关单、也不会因为 #6123 合并而受影响。若 #6125 尚未合并/被放弃,issue 关闭后「21→26」方向的丢失仍然存在。建议在评论中注明「需与 #6125 一并处理」,或先合 #6125 再合本 PR。
💡 两条可选打磨
loadLegacyBlueprintItem的命名/注释:该方法现在同时服务「旧版diskInventory/Items遗留格式」与「26.1 的stacks新格式」,名字里Legacy会误导后人以为它只处理历史数据。建议改名(如readBlueprintItem)或在 javadoc 里列出三类来源。- 类型判断与孪生 PR 的写法不完全一致:本 PR 用
contains("stacks", Tag.TAG_LIST),而 #6125 用contains("stacks")。两者当前都正确(后者多一层Items判定),但未来若 26.1 把stacks换成非 list 形态,1.21.1 侧会静默落回本地deserializeNBT并再次丢盘且无日志。建议在解析失败(parseOptional返回 EMPTY 但列表非空)时打一条 debug 日志,便于后续跨版本问题定位。
手工验证建议:① 在 26.1 存档里给智能放置器放入结构磁盘并保存蓝图 → 到 1.21.1 粘贴,确认磁盘被恢复且结构名/尺寸等组件数据完整(不只是物品 id);② 无磁盘的 26.1 蓝图粘贴到 1.21.1,确认槽位为空、不多出物品;③ 反向 21→26 用 #6125 一并验证;④ 1.21.1 本地已有蓝图(Items 路径)回归一次,确认未被新分支影响。
裁决:机制正确、格式与组件兼容性已逐项核实、CI 双绿,可合并;仅需在合并/关单流程上把 #6125 纳入同一批处理。
fix(blueprint): 保留跨版本蓝图中的智能放置器磁盘
读取另一版本的智能放置器磁盘库存格式
避免默认空库存覆盖外来蓝图中的磁盘
fixed [Bug] 蓝图跨mc版本时,放有结构磁盘的智能放置器丢失结构磁盘 #6100