Skip to content

Fix spectral anvil undo refund 修复幻灵铁砧撤销返还 - #5134

Merged
PigeonNian merged 1 commit into
Anvil-Dev:dev/1.21/1.6from
WhereisFff:fix/5133-spectral-anvil-refund
Oct 2, 2026
Merged

PigeonNian merged 1 commit into
Anvil-Dev:dev/1.21/1.6from
WhereisFff:fix/5133-spectral-anvil-refund

Conversation

@WhereisFff

Copy link
Copy Markdown
Contributor

- 撤销无掉落幻灵铁砧虚影时不再结算基础物品
- 保留实体铁砧与其他下落方块的资源结算

fixed Anvil-Dev#5133
@Gugle2308

Copy link
Copy Markdown
Collaborator

代码审查摘要 — PR #5134

操作: opened(PR 当前为 draft,mergeable_state: unstable)
范围: 1 个文件(1 Java,+6 行 / 0 删除 / 1 commit 94b89d1 fix(building): 修复幻灵铁砧虚影撤销时重复返还物品)
目标分支: dev/1.21/1.6(base 5c9ee48)← head 94b89d1(refs/pull/5134/head 与 fork 分支一致)

🔍 根因验证(已用 1.21.1 official mappings + 混淆客户端字节码取证)

结论 证据
falling.dropItem 跨包可访问 cjg(FallingBlockEntity) 字段 c(dropItem) 访问标志 = public;t()(getBlockState) = public,故 building 包内可直接读 ✅
vanilla 会持久化 DropItem cjg.b(Lub;)V(addAdditionalSaveData) 写入 DropItem/CancelDrop;cjg.a(Lub;)V(readAdditionalSaveData) 含 DropItem 的 contains(key,99)+getBoolean ✅(dropItem 能随 NBT 往返)
state.is(ModBlocks.SPECTRAL_ANVIL) 合法 该写法在仓库中有 125 处,且 base 分支 DynamicBuildingEntities.java:120 是同一表达式,BlockEntry 即 Holder<Block> ✅
复现链成立 幻灵虚影有两条 免费 生成路径:SpectralAnvilBlock.tick(fall(..., false, true),不消耗方块)与 GiantAnvilShockEventListener:121(同样 isGhostEntity=true,仅限 SPECTRAL_ANVIL)。虚影在快照之后生成 → 快照的 Block 仍返还铁砧,虚影实体又返还一个 ⇒ 2 变 1,可刷 ✅ 与 #5133 描述吻合
「不返还」是正确语义(非玩家损失) 建造侧 BuildingRodService:658 已把此类实体的材料归入 group.tools,而 BuildingMaterials.reserveTool()(269) 只置 retainedTool=true、不增加 reserved ⇒ 玩家从未消耗该铁砧。撤销侧不返还 = 消除重复,不是吞材料 ✅
作用域完整 全仓库仅上述两个 fall(...) 调用点,都传 isGhostEntity=true,且都被 SPECTRAL_ANVIL 限定 ⇒ 只可能产出「虚影 + 幻灵铁砧」这一种组合,state.is(...) && ghost 的窄守卫已覆盖全部现网路径 ✅
反向不行破坏 material = EMPTY 只会短路 this.item(material);contents()/fluids()/Leash 结算保持不变,与 PR 描述一致。守卫写在 BuildingUndoResources.entity() 内,recovered/required 两侧共用 ⇒ cancel() 的净额对消仍然自洽 ✅
风格门禁 style.xml LineLength max 140,新增两行 119 / 92;git diff --check 干净;import 有序无冗余 ✅

⚠️ 警告

  • BuildingUndoResources.java:155-156 — 守卫依赖 !falling.dropItem,与 Ghost 是两个独立持久化信号,存在静默失效面。
    FallingSpectralBlockEntity.readAdditionalSaveData 只同步 isGhostEntity(且 缺 Ghost 时默认为 true),从不回写 dropItem/cancelDrop(它们由 vanilla 从 DropItem/CancelDrop 恢复)。因此若某份 NBT 含 Ghost:true 但 没有 DropItem 键,加载后 isGhostEntity=true 而 dropItem 保持 vanilla 初始值 true → !falling.dropItem 为假 → 守卫静默不触发,刷物复现。
    当前仓库内所有生产者都同时写了两个键(DynamicBuildingEntities:122),故尚未可达;但蓝图 NBT 是可流转/可跨版本的数据,建议把守卫改为以 Ghost 标签为准(代码本身已读了 copy.getBoolean("Ghost")),或在 readAdditionalSaveData 里同步 this.dropItem = !this.isGhostEntity;。
    附带:!copy.contains("Ghost") 这一「旧格式」分支因 && !falling.dropItem 的存在而实际不可达(缺 Ghost 的旧 NBT 同时也缺 DropItem,dropItem 为 true),属死条件,建议一并澄清。

  • 谓词不对称:建造侧与撤销侧的判据形状不一致。
    建造侧(BuildingRodService:658)只判 instanceof FallingSpectralBlockEntity && material 是幻灵铁砧,不看 ghost;撤销侧要求 state==SPECTRAL_ANVIL && (Ghost 或缺失) && !dropItem。今天因「所有幻灵下落实体都是虚影」而等价,但一旦将来出现 isGhostEntity=false 的生成路径(或 Ghost=false 的蓝图 NBT),建造侧不收费、撤销侧却返还 → 同一种刷物会以另一形态回归。建议抽一个共享判定(如 BlueprintSpectral.isToolOnly(Entity, CompoundTag)),BuildingRodService:658 与本次守卫同时引用。

💡 建议

  • 守卫与 DynamicBuildingEntities:120 的 falling.getBlockState().is(ModBlocks.SPECTRAL_ANVIL) 完全重复,可加一行注释互相指向,避免两处日后漂移。
  • 若采纳上条「以 Ghost 为准」的写法,!falling.dropItem 可直接去掉,判据单一化也顺便消掉警告一。

🟢 看起来不错

  • 根因定位准确:不是「少扣材料」而是「免费虚影 + 方块返还」的叠加重复,修在返还侧是正确落点。
  • 改动最小(6 行 / 1 文件),无越界改动、无 EOF/空白问题,符合仓库既有惯例。
  • 与建造侧的 group.tools(不消耗工具)语义对齐——修复后玩家既不会白得铁砧,也不会凭空少一个铁砧。
  • 未触碰 DynamicBuildingEntities 中已存在的 Ghost/DropItem 写入,改动面可控。

📋 声称验证表

PR 声称 状态 证据
撤销无掉落幻灵铁砧虚影时不再返还幻灵铁砧 ✅ 守卫命中后 material = EMPTY,item(EMPTY) 无操作
保留实体铁砧、其他下落方块及独立内容物的资源结算 ✅ 仅短路 base material;其他 FallingBlockEntity/方块走 block() 路径不变;plan.contents()/fluids()/leash 仍结算
fixed #5133 ✅ #5133 现为 open;复现链(SpectralAnvilBlock.tick 免费虚影)已核实,本修复确实封堵该路径

🧪 测试建议

被测目标 推荐场景 优先级
BuildingUndoResources.entity() 世界内放置幻灵铁砧方块 → tick 生成虚影 → 圈选快照后撤销:断言回收列表不含幻灵铁砧,且方块本身的铁砧仍返还(正好 1 个) 🔴
同上 虚影携带独立内容物/流体/拴绳时,撤销仍完整结算 🟡
守卫鲁棒性 构造 Ghost:true 但缺 DropItem 的实体 NBT 走撤销 → 当前应复现「仍返还」以确认警告一;修好后应不返还 🟡
建造↔撤销对称性 Ghost=false 的蓝图 NBT 建造+撤销净额应为 0(暴露警告二的潜在回归) 🟢

结论: APPROVE(comment 级) — 根因正确、改动最小、作用域完整,且与建造侧「工具不消耗」语义自洽,未发现阻塞问题。两条警告均为鲁棒性/未来回归面,建议随手加固但不阻塞合并。另:PR 目前仍是 draft,请作者确认已准备好再转 ready_for_review。

关于标题:当前标题 Fix spectral anvil undo refund 修复幻灵铁砧撤销返还 尚可接受但偏含糊(未点出「重复返还/刷物」)。建议标题:Fix spectral anvil ghost refunded on undo 修复撤销幻灵铁砧虚影时重复返还。本次因 gh auth status 显示 token 失效(The token in /opt/data/home/.config/gh/hosts.yml is invalid)而未自动修改,故仅给出建议。
另:本 PR 仅需落在 dev/1.21/1.6——已核实 dev/26.1/1.6 上不存在 building/ 撤销子系统(无 BuildingRod*/Blueprint*/Undo 相关文件),无需前向移植。


由 Hermes Agent 审查

@Gugle2308

Copy link
Copy Markdown
Collaborator

💾 Self-improvement review: Patched SKILL.md in skill 'offline-pr-evidence-verification' (1 replacement). · Patched SKILL.md in skill 'building-rod-blueprint-review' (1 replacement).

@WhereisFff
WhereisFff marked this pull request as ready for review October 2, 2026 10:13
Copilot AI balanced review requested due to automatic review settings October 2, 2026 10:13

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

⏳ Retrying in 2.9s (attempt 1/3)...

@Gugle2308

Copy link
Copy Markdown
Collaborator

⏳ Retrying in 5.1s (attempt 2/3)...

@Gugle2308

Copy link
Copy Markdown
Collaborator

❌ API failed after 3 retries — HTTP 503: Service temporarily unavailable

@Gugle2308

Copy link
Copy Markdown
Collaborator

API call failed after 3 retries: HTTP 503: Service temporarily unavailable

@Gugle2308

Copy link
Copy Markdown
Collaborator

⏳ Retrying in 2.5s (attempt 1/3)...

@Gugle2308

Copy link
Copy Markdown
Collaborator

⏳ Retrying in 5.0s (attempt 2/3)...

@Gugle2308

Copy link
Copy Markdown
Collaborator

❌ API failed after 3 retries — HTTP 503: Service temporarily unavailable

@Gugle2308

Copy link
Copy Markdown
Collaborator

API call failed after 3 retries: HTTP 503: Service temporarily unavailable

@PigeonNian
PigeonNian merged commit 94dd46d into Anvil-Dev:dev/1.21/1.6 Oct 2, 2026
2 checks passed
@Gugle2308

Copy link
Copy Markdown
Collaborator

PR #5134 的 webhook 事件为 closed(已关闭/已合并),按审查流程约定(action 为 closed/labeled → 停止,不发布审查评论),本次不产出审查意见,也不再发表任何评论。

(gh 认证当前失效,无需修改标题;如后续该 PR 重新开启或以 opened/synchronize/ready_for_review 事件再次触发,可重新提交完整审查。)

PigeonNian added a commit that referenced this pull request Oct 3, 2026
…修复到26.1 (#5143)

* The text regarding celestial death has been corrected, and some progress has been made. 修正了天体死亡文本,增加了一些进度 (#5129)

* feat(advancement): 添加天体进化挑战成就及触发器

- 新增 CelestialEvolutionTrigger 用于天体质量进化判定
- 在触发 util 中添加 celestialEvolution 方法,触发成就判定
- 在加速器逻辑中调用触发方法进行成就检测
- 添加无残留(no_remnant)挑战成就,要求64质量铁砧的天体进化至终局
- 将成就文本翻译添加至英文语言文件和特殊字符文件
- 在成就数据中注册无残留成就及其触发条件

* feat(advancement): 添加行星毁灭成就及触发器支持

- 新增PlanetDetonationTrigger用于行星毁灭事件的判定
- 在ExcavatorHandler中增加触发行星毁灭触发器的逻辑
- 在AdvancementLineHelper中集成planetDetonation方法方便创建该成就
- 在AnvilCraftAdvancement中添加efficiency成就分支,绑定行星毁灭触发器
- 更新语言文件,添加行星毁灭成就的标题与描述
- 注册PlanetDetonationTrigger触发器并完善其触发实现
- 新增efficiency成就JSON配置文件,定义触发条件及显示信息

* feat(advancement): 新增因行星坍缩死亡的成就触发器

- 添加了 PlanetaryCollapseDeathTrigger 触发器类及其数据结构
- 在 ModCriterionTriggers 中注册 planetary_collapse_death 触发器
- 在 AdvancementLineHelper 中新增 planetaryCollapseDeath 方法便于调用
- 在 AnvilCraftAdvancement 中添加 Cannon Fodder 成就,绑定行星坍缩死亡触发器
- 在语言文件中添加 Cannon Fodder 成就标题与描述的多语言支持
- 在 OverworldLikeEventListener 中监听行星坍缩死亡事件并触发相应成就
- 在 TriggerUtil 中实现 planetaryCollapseDeath 方法来触发成就判定
- 新增 Cannon Fodder 成就的 JSON 配置文件,包含父级与图标等信息
- 修改效率成就添加隐藏属性,改善游戏内成就展示体验

* feat(advancement): 新增黑洞和中子星终局星体成就

- TriggerUtil新增支持根据StellarTerminal.Kind触发星体演化成就
- CelestialEvolutionTrigger增加对终局类型的判定和对应触发方法
- AdvancementLineHelper新增celestialEvolution重载方法支持终局类型参数
- AnvilCraftAdvancement中增加黑洞和中子星分支成就定义和保存
- AdvancementLang添加黑洞与中子星成就名称及描述多语言支持
- 语言文件(en_us, en_ud)增加对应成就的描述和标题
- 新增黑洞和中子星成就JSON数据文件,定义触发条件和显示信息

* feat(damage): 新增天体接触伤害类型及独立标签支持

- 添加黑洞接触、恒星接触及行星接触三种新伤害类型
- 天体接触伤害采用独立类型以实现专属死亡提示
- 更新伤害标签,支持新伤害类型绕过护甲、抗性、击退等效果
- 修改重力控制器中伤害来源,替换为对应新天体接触伤害类型
- 保持星体及行星接触伤害原版燃烧和摔落效果表现不变
- 增加对应的语言文本显示新伤害的死亡描述信息
- 修正玩家攻击混入对行星接触伤害的判定,保持原摔落伤害一致性
- 新增相关资源数据文件,完善伤害类型和标签配置

* feat(advancement): 添加“夜晚来访”星接触死亡进度条件

- 新增 StarContactDeathTrigger 实现星接触死亡触发器
- 注册并初始化星接触死亡触发条件 ModCriterionTriggers.STAR_CONTACT_DEATH
- AdvancementLineHelper 新增 starContactDeath 方法支持该触发器
- AnvilCraftAdvancement 新增“come_at_night”任务,使用星接触死亡触发器
- AdvancementLang 中添加“come_at_night”进度名称及描述文本
- OverworldLikeEventListener 监听星接触死亡事件触发进度
- TriggerUtil 新增 starContactDeath 方法简化触发调用

* feat(locale): 添加“come_at_night”成就的中英文描述

- 新增“advancements.anvilcraft.come_at_night”标题的本地化文本
- 新增“advancements.anvilcraft.come_at_night”描述的本地化文本
- 中文描述内容为“被星光笼罩”
- 英文标题内容为“Showdown at Night”倒转样式

* feat(advancement): 添加“come_at_night”隐藏成就

- 创建新的隐藏成就“come_at_night”
- 设置成就触发器为“star_contact_death”
- 指定成就图标为“celestial_forging_anvil”
- 定义成就的父级为“the_start”
- 启用成就的遥测事件发送

---------

Co-authored-by: Pigeon_Nian <adove2005@163.com>

* fix(celestial): 修复演化音效衰减与锻造界面恢复 (#5131) (#5132)

- 将演化音乐归入唱片音量分类,并以单声道音源实现 64 格原生距离衰减。
- 保持音效与字幕的听距一致。
- 通过实时同步入口恢复锻造状态,避免重开界面时丢失正在锻造的进度。

* fix(building): 修复幻灵铁砧虚影撤销时重复返还物品 (#5134)

- 撤销无掉落幻灵铁砧虚影时不再结算基础物品
- 保留实体铁砧与其他下落方块的资源结算

fixed #5133

* fix(item-splitter): 修复物品分配器掉落物超出堆叠上限 (#5136)

按物品实际堆叠上限拆分每个目标位置的掉落物,保留均分份额、余数、零动量和拾取延迟。

修复 #5135

* fix(button): 修复大红按钮遮挡边缘交互与按压动画 (#5141)

- 使用实际命中位置进行服务端射线校验,修复按钮可见但底座中心被遮挡时无法按下的问题。
- 按住按钮后等待服务端确认再播放手部动画,并忽略已释放或已切换目标的过期确认。
- fixed #5138

* fix(storage-port): 修复服务端扫描仓储端口时崩溃 (#5140)

- 优先使用原版 includeData 标志控制数据复制,避免服务端扫描读取客户端按键状态
- 保留 26.1 服务端中键克隆时的缓存、标记与流体数据

(cherry picked from commit d7c2f74)

---------

Co-authored-by: PigeonNian <78527064+PigeonNian@users.noreply.github.com>
Co-authored-by: Pigeon_Nian <adove2005@163.com>
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.

[Bug] 建筑杖撤回幻灵铁砧实体返还幻灵铁砧物品

4 participants