Repository navigation
1.21.1 Blueprint editing and shared previews 完善结构蓝图编辑与共享预览并修复红石及实体交互 - #6128
Conversation
- 为结构扫描仪添加选块、JEI 标记格、facing 轮换、单个及完整状态批量替换、撤回和蓝图区域裁剪扩展 - 调整磁盘界面切换与 overlay 布局,支持导入长名称悬停滚动及扫描仪范围预览 - 将扫描仪、智能方块放置器和磁盘预览迁移至砧库,统一缩放、左键旋转、右键平移及 75% 蓝色扫描效果 - 接入带连线的只读 GUI 浮窗和存储快照,避免事件穿透及磁盘预览与 tooltip 重叠 - 将藿香改为可选集成并取消捆绑,适配 1.21.1 的渲染、注册与存储接口,升级砧库及藿香依赖 - 补齐六面红石导线短拐角模型、信号传递与邻居更新,修复高级比较器记忆恢复 - 支持大红按钮、物品检测器及磁化节点随活塞移动,修正下落方块碰撞目标与速度阈值 - 提升三类溜槽抗爆性并保留金属音效
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)。#6127 到 dev/1.21/1.6 的端口适配面(ItemStack.OPTIONAL_STREAM_CODEC、BlockPos.CODEC、9 参 blit、IGhostIngredientScreen、getStructureBlockEntityData、Entity.collide 注入、AbstractMultiPartBlock#getMainPartPos)逐处对得上,未发现崩溃级路径;CI build / checkstyle 均 success(已核对 check-runs)。建议合入前处理
仓库内容与 PR 描述按不可信数据处理,本次未运行游戏(作者也注明画面/鼠标未实测)。Diff 覆盖:PR 的 77 个文件已全部核对(Java 逐文件、生成资源抽查、
overlay.png尺寸实测)。
已核实
- 红石短拐角资源链:
RedstoneWireBlockStateGenerator现在对 6 个附着方向 × 4 个索引生成CORNER_SP;生成物 = blockstate 24 个corner_sp条目(48 处字符串命中)+ 24 个模型文件(新增 20 + 既有 4 个水平_0),与 datagen 源一一对应。 - 转角信号与邻居更新:
getCornerSignal/hasCornerConnection/notifyCornerTargets/neighborChangedAroundSupport的改名调用点全部同步(RedstoneWireNetworkManager、BlockEventListener、reattach、SignalGetterMixin),axis.ordinal()去重覆盖 12 个对角位置;SignalGetterMixin仍是Math.max追加语义。 - 活塞 + 磁化节点:
PistonBaseBlockMixin在moveBlocks内包裹PistonStructureResolver#getToPush,@Local(argsOnly=true) Level与 1.21.1 签名匹配;节点 tick 在目标格是MOVING_PISTON && !isSourcePiston()时用getMovedState()判活(不会被代理方块误杀),moveWithPiston同时同步支撑格与实体位置。 - 下落方块碰撞定位:1.21.1
Entity.move只调用一次collide;mixin 的轴序|x|<|z| ? {Y,Z,X} : {Y,X,Z}与 1.21.1Entity.collideWithShapes字节码一致(先 Y,再按Math.abs比较决定 Z/X 先后),BlockCollisions5 参构造 +pos.immutable()正确。 - 高级比较器:
loadAdditional里的getBlockState()返回构造期缓存的blockState字段(1.21.1BlockEntity.getBlockState字节码为aload_0; getfield dqh.f; areturn,不读level),重载期不会 NPE;state = POWERED != outputInvert ? HIGH : LOW与isOutputting()恒等,onLoad计划刻 1 tick 重算;tick删除的重复updateBlockAndNeighbours由update(...)末尾执行,changed短路保证幂等。 - 离屏预览:
RenderTarget.clear(boolean)内部先_bindWrite(true)、末尾unbindWrite()(1.21.1 客户端 jar 反汇编确认),因此setClearColor → clear → bindWrite(true)不会误清主帧缓冲;PreviewRenderState保存/恢复 framebuffer、viewport、scissor、depth/color mask、blend、雾、3 个 shader 纹理,submitNative的状态收放顺序正确。 - 扫描后处理:
scan_preview的预乘混合(one/1-srcalpha)与StructurePreviewEffects.blit的反预乘 +ScanOpacity一致;shader.clear()在 finally 中。 TriStateButton的16 → 48:不改变采样 UV(yOffset与texHeight*3同步放大 3 倍,UV 仍是 0 / ⅓ / ⅔),属无害改动,不是回归。- 蓝本 tick 坐标:
buildCachedSnapshot的world - origin + result.offset()与ScannerDiskNormalizer/BlueprintNormalizer的规范化帧一致(四种朝向 + 倒置逐一代入推演),不会把计划刻映射到错误方块;BlueprintTicks.restore还有类型二次校验。 - 存储预览/手册:
StorageStructurePreview用主部件位置取快照 NBT(非主部件在captureBlockEntity提前返回,不写 key,两边一致);StoragePreviewSnapshot的容量常量(2048 / 65536 / 1024 / MAX)与StorageType对得上;overlay.png实测 65×40,与两处 9 参 blit 区域一致;新增 5 个 lang key 在ScreenLang/en_us/en_ud/zh_cn 同步。 - ageratum 可选化:所有
dev.anvilcraft.resource.ageratum引用都落在客户端门控/@Integration/指南渲染路径内(AnvilCraftRecipeComponentFactories仅被AnvilCraftClient的isLoaded分支引用,AgeratumUtil只被 markdown 组件使用,PortalConversionCategory已去掉 ageratum 依赖);mods.toml的[[dependencies."${mod_id}"]]写在[mc-publish]之后仍是根级表(TOML 表头是绝对路径,合法),ageratum_version已加入ProcessResources替换。 - 溜槽与移动通知:
CHUTE/SIMPLE_CHUTE/SIMPLE_MAGNETIC_CHUTE改为END_STONE后覆写METAL音效,MAGNETIC_CHUTE/OVERFLOW_CHUTE经initialProperties(ModBlocks.CHUTE/MAGNETIC_CHUTE)继承,5 个溜槽抗爆一致;ItemDetectorBlock.notifyMoved重算探测范围。
⚠️ 建议处理
StoragePreviewSnapshot.read的getOrThrow(以及captureBlockEntity的 encode):read(约 :123)对结构文件里的anvilcraft:storage_preview直接CODEC.parse(...).getOrThrow(),StorageStructurePreview.create没有捕获;一旦物品/流体来自已卸载的模组、count 为 0、或旧/新 schema 缺items/capacity,打开该结构的手册/扫描仪存储预览会抛DataResult.Error(客户端崩溃)。captureBlockEntity(约 :110)的 encode 也在scanNextLayer的服务端 tick 路径上用了getOrThrow。建议都改成resultOrPartial(...).orElseGet(() -> empty(type))(或flatMap)+ 一条 WARN。- 智能放置器在蓝图模式下每帧重载结构:
SmartBlockPlacerScreen.getOrCreateCachedPreviewLevelLike(约 :1320)每帧调用StructureLoadUtil.loadStructureFromDiskForPreview→BlueprintNormalizer.load的LoadKey以整个CompoundTag为键,record 相等性走CompoundTag的值语义(1.21.1CompoundTag.hashCode()=tags.hashCode(),深层遍历整份结构 NBT;maximumSize(32)一旦淘汰还会整份重解析),随后StructureData.fromSnapshot又复制一遍全部方块条目;另外renderDisplayedBlock(约 :910)每帧new LevelLike+StructurePreviewScene.of(icon)(键是新对象,CACHE必不命中 ⇒ 每帧重建StructureTemplate+StructureSandboxFactory沙盒)。结构越大、蓝本带 NBT 时越明显,建议在 Screen 内按STRUCTURE_DISK_DATA(file+uuid)缓存StructureData/snapshot,图标按BlockState缓存 scene。 - 编辑后保存的方块状态朝向与未编辑保存不一致(需确认):对原始扫描做替换时,
StructureScannerFiles.editBlueprint会把快照旋转到 scanner 预览帧(StructureBlueprintEdit.rotate(snapshot, rotation),rotation 恰为facingPlayer(scannerDir, SOUTH)=ScannerDiskNormalizer的逆),保存时StructureDiskData.direction固定 NORTH;而放置侧StructureLoadUtil.loadStructureFromDisk对未编辑磁盘施加facingPlayer(dir, SOUTH)、对编辑后磁盘施加 NONE —— 位置旋转相消,但该 loader 只旋转位置、方块状态原样使用,于是“编辑后保存”的文件状态被旋转过、“未编辑保存”的文件状态是 canonical。两者放置出来的朝向(楼梯/机器正面等)可能不同。建议用 GameTest 对账“编辑一个方块后保存”与“不编辑直接保存”,断言位置与状态都一致;若不一致,说明保存侧应把状态旋转回 canonical(或在saveImportedStructure记录真实 direction)。 - 碰撞速度阈值边界:
FallingBlockCollisionEventListener:56由config > speed → return改为speed <= config → return,爆炸条件从speed >= 阈值变成speed > 阈值;默认 16 时恰好 16 不再爆炸,而AnvilCraftServerConfig:65的注释仍写 “minimum … explode”、FallingBlockCollisionEventListener:66的配方门仍是speed < recipe.speed()(含端点)。请统一三处语义(要么改回<,要么同步注释与配方门说明)。#6127 同一处也是这个改动,建议两线一起定。
💡 可选清理/确认
StructureDiskPreviewSupport的PENDING_PREVIEW_DATA/receiveStructureData/parsePreviewNbt无任何调用方(真实回填走StructureDiskResponsePacket → StructureLoadUtil.cacheStructureNbt),clearCache()也无人调用(会话级缓存在登出时不清);建议删除或接线。AnvilCraftMixinPlugin.hasAgeratum在本分支没有对应 mixin:mixin包下没有client/Handbook*类,mixins.json也没有任何 ageratum mixin,shouldApplyMixin的该分支永不命中(不影响功能,但与 #6127 的意图不符)。- 编辑入口与磁盘面板互斥:
blueprintVisible = hasDisk && (imported || scanComplete),而选择/替换/撤回都要求!blueprintVisible;常规“插盘→扫描→保存”流程里看不到替换按钮,需要先取出磁盘再编辑。请确认这是预期的操作流(若是,建议在手册/描述里写明)。 DiskItemRenderer:40的末参从blueprint改成suppressFoil后仍传structure;同时scan_preview_item着色器已删,磁盘图标上的扫描效果消失——确认是否有意(若否,末参应传false)。StructureScannerEditPacket无服务端节流:每次编辑都会重建/规范化并压缩整份蓝图回传,客户端isBusy不是服务端限频;建议按玩家加冷却(RedstoneWirePowerRequestPacket式先例)。- 建议保留/补一条 #4325 场景的回归测试(窗口模式:输入在区块卸载期间变化后重载),因为
loadAdditional现在信任存档POWERED而不再用重采样输入重算。 - 三个溜槽硬度由 5.0(IRON_BLOCK)变为 3.0(END_STONE),描述只提到抗爆与音效;若是有意可忽略,否则用
.properties(p -> p.explosionResistance(9))保留原硬度。
声称核对
| 声称 | 结论 |
|---|---|
#6127 功能完整移植到 1.21.1 |
✅ 逐文件核对,API 适配正确 |
build + portCheckstyle 通过 |
✅ CI build/checkstyle success(等价门禁) |
含/不含藿香两套 runData 通过 |
无法离线复现(脚本未提交);生成资源与 datagen 源抽查一致 |
50 项 GameTest(含 -PportWithHandbook) |
无法核实:CI 无 gametest job,测试未提交(作者自述) |
| 成品仅内置砧库、无藿香捆绑 | ✅ dependencies.gradle 已改为 compileClasspath(transitive=false)+runtimeClasspath,无 api/jarJar |
| 游戏内画面/鼠标未实测 | 与本次未覆盖项一致(FBO 预览、输入层、tooltip 对侧布局需实机验证) |
未覆盖
- 游戏内渲染与输入:
StructurePreviewScene的 FBO 合成/范围框/缩放平移旋转、StructureGuiPreview浮窗、tooltip 对侧布局、drawScrolling手感(作者已注明未实测)。 - AnvilLib
2.0.0+snapshot.689的StructureGui*/IntegrationManager运行时行为(本机无该 artifact;GuideEventListener的 COMMON@Integration装载路径按仓库既有 CLIENT/DATA 先例推断)。 - 大型存储快照的实际包体/存档体积;多人并发;Iris/Sodium 兼容。
- 编辑后保存/放置的坐标系只在源码层推演,未跑 GameTest 复现(即
⚠️ 3 的对账项)。
将 #6127 的功能提交
4766d9c30abcffefefd490929f06982fcb74e4c0完整移植到dev/1.21/1.6(Minecraft 1.21.1)。2.0.0+snapshot.689和 Ageratum0.0.1+build.151。验证:
./gradlew.bat compileJava build -I build/port-style.gradle portCheckstyle --console=plain通过;改动文件 Checkstyle 零告警,全仓库检查仅有未改动文件的 15 条既有告警。./gradlew.bat -I build/port-tests.gradle runGameTestServer --console=plain和添加-PportWithHandbook的运行各通过 50 项本地 GameTest,覆盖蓝图编辑、存储快照、可选手册加载、六面红石转角、活塞与碰撞行为。runData均通过;仅保留与本次功能有关的生成资源。git diff --check、git diff --cached --check通过;成品仅内置砧库,无藿香捆绑和本地测试文件。