Skip to content

Add civilization catalyst and magnet recipes 添加文明催化器与磁铁相关配方 - #5125

Merged
PigeonNian merged 2 commits into
Anvil-Dev:dev/1.21/1.6from
WhereisFff:feat/civilization-catalyst-magnet-recipes
Oct 2, 2026
Merged

PigeonNian merged 2 commits into
Anvil-Dev:dev/1.21/1.6from
WhereisFff:feat/civilization-catalyst-magnet-recipes

Conversation

@WhereisFff

Copy link
Copy Markdown
Contributor

feat(celestial): 添加文明催化器与石碑投放器 (#5073)

  • 新增文明催化器及合成配方,使用一个催化器建造石碑投放器。
  • 十秒后使符合条件的星球产生原始文明,已有文明则各有 50% 概率成为废土或消失。
  • 保留天体基础资源并替换文明资源,更新搜索历史防止恢复旧状态,消失时为附近玩家授予新轮回隐藏挑战。

feat(recipe): 补充磁铁块转换与充电配方 (#5090)

新增文明催化器合成配方及石碑投放器巨构,十秒后催生原始文明或随机产生废土与消失结局。

保留天体基础资源并替换文明资源,更新搜索历史防止恢复旧状态,为附近玩家授予新轮回隐藏挑战。
添加八个磁铁块与九个空心磁铁块的双向合成,以及铁芯磁铁块消耗四千瓦、两秒充电为磁铁块的配方。
@Gugle2308

Copy link
Copy Markdown
Collaborator

⚠️ Dangerous command requires approval:

cd /tmp && curl -s "https://api.github.com/repos/Anvil-Dev/AnvilCraft/issues/5073" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('title')); print('---BODY---'); print(d.get('body'...

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

操作: opened(当前 draft: true,state: open,merged: false,mergeable: true)
范围: 28 文件(15 Java / 13 JSON;11 新增 / 0 删除),+505 −3,46 个 hunk,2 commits
对齐: API changed_files=28 / additions=505 / deletions=3 与本地 diff 完全一致;无 ghost 文件、无 EOF 缺失异常(10 处,与既有生成文件风格一致)
核对基线: 目标分支 dev/1.21/1.6 = 956c11b4e0(git ls-remote 权威对齐),所有 API 均在目标分支上逐个核对,非本地 26.1 克隆

📋 与 Issue 规格的逐项对账(#5073 / #5090 仍为 open,合并后才会自动关闭)

规格条目 状态 证据
新增岩石行星巨构「石碑投放器」monolith deployer ✅ ModMegastructures.MONOLITH_DEPLOYER(.ring(1)、.material(CIVILIZATION_CATALYST,1))+ MonolithDeployerHandler
只能建在「≥3 种生物掉落物」或「已有原始文明」的岩石行星 ✅ canDeploy()(!isWasteland && (hasCivilization || 生物物品 distinct≥3, weight>0))+ 前置 isPlanet && !isErrorPlanet
束星环内层模型 = celestial_forging_anvil_ring_1_monolith ✅ ringModel(1,"monolith");该模型已在目标分支存在
建造后 10 秒生效并删除巨构 ✅ DEPLOYMENT_TICKS = 200;两条分支都经 clearMegastructure()(材料不退,符合"消耗")
①有生物资源→产生原始文明,资源变为文明资源 ✅ advanceCivilization → OFFERING + setHasCivilization() + generateOfferings()(沿用 offering 配方条目)
②已有文明→50% 变废土 / 50% 从锻星砧中消失 ✅ hasCivilization() && nextBoolean() → completeMonolithDeployment(null)(天体置空)/ else WASTELAND + setWasteland()
消失时附近玩家得隐藏挑战「新轮回」,图标=文明催化器,经验≈0→30 级,接在锻星砧进度后 ✅ awardNewCycle(半径 16)+ new_cycle.json(frame: challenge、hidden: true、图标 civilization_catalyst)+ parent = anvilcraft:anvilcraft/the_start;奖励 1395 XP 正是原版 0→30 级所需总量(352 + 1043),数字正确
建材:文明催化器 ×1 ✅ .material(ModItems.CIVILIZATION_CATALYST.get(), 1)
催化器配方 石碑/精华/石碑、石碑/腐化信标/石碑、石碑/精华/石碑 → 4 个 ✅ RegistrumItemRecipeLoader.civilizationCatalyst:MEM/MBM/MEM → count 4
8 磁铁块 = 9 空心磁铁块 ✅ hollow_magnet_block_from_magnet_block(AAA/A A/AAA,count 9)
9 空心磁铁块 = 8 磁铁块 ✅ magnet_block_from_hollow_magnet_block(AAA/AAA/AAA,count 8)
铁芯磁铁块充电→磁铁块,4 kW / 2 s ✅ power(-4)、time(20*2);生成 json "power":-4,"time":40

🔴 关键问题

无。未发现阻塞合并的正确性、崩溃或存档兼容问题(详见下方"看起来不错"的核对项)。

⚠️ 警告

  1. PlanetResourceGenerator.advanceCivilization()(新增)只按 category() 过滤后 findFirst(),没有像 generate() 那样走 recipe.matches(input, level)(generate() 第 ~63 行有 if (!recipe.matches(...)) continue;)。当前数据包 OFFERING/WASTELAND 各只有 1 条,结果确定、行为正确;但有两点脆弱性:① 附属/数据包一旦增加第二条同类别配方,RecipeManager 按 ID 排序返回,findFirst() 会静默挑走属于别的天体类型的配方内容(例如把 A 型星球的废土产物塞给 B 型);② 该路径天然绕过 offering 的 liquidCoverage==MEDIUM/ageMin~ageMax 与 wasteland 的 liquidCoverage!=HIGH/ageMin/wastelandChance 门槛。②与 [TODO] 文明催化器 #5073 规格一致(石碑只看"生物掉落物≥3 种"),应属有意为之,建议在 advanceCivilization 的 javadoc 里显式写明"石碑无视天体参数门槛",①则建议加一层稳健性:把 body/ageAnvilCount 传进来复用 matches(),或在多条命中时改为确定性地拒绝(返回原集合)而不是任取一条。

  2. 配方缺失时静默消耗投放器,玩家零反馈:若数据包删掉 OFFERING/WASTELAND 配方,或 offeringData()/wastelandData()==null,advanceCivilization 直接 return current,但 serverTick 仍走 completeMonolithDeployment(current) → clearMegastructure(),1 个文明催化器(=石碑×4+精华×2+腐化信标)无声蒸发且界面无任何提示。原版数据包两条都在,风险低;建议这种"无变化"结局退还材料或至少给一条提示(ScreenLang 里已有大量类似提示位可复用)。

💡 建议

  1. 资源保留范围:advanceCivilization 只复制 getMinerals() + getFluids(),giantItems/giantFluids 与 biologicalItems/biologicalFluids 都被丢弃。丢生物资源符合既有模型(hasCivilization ⟺ offerings,见 isEcoStationEligible/Temple 前置),也符合"资源变为文明/废土资源"的规格;但①岩石行星上 giant 资源一般恒空(generate() 只在 GiantPlanetData 分支写入),仍建议顺手一并复制或注释说明"有意不复制",避免日后附属往岩石行星投放 giant 资源时被静默清空。②顺带提醒一个玩家可感的设计后果:石碑文明化后该星球不能再建生态站(isEcoStationEligible 要求"无文明 + 有生物资源"),换来神殿路线——建议在 usage 文案里点明"文明化会替换生物资源并关闭生态站"。

  2. sendBlockUpdated(..., 3) 与 Block.UPDATE_CLIENTS 混用:新 handler 内用字面量 3,而同 PR 的 completeMonolithDeployment 用 Block.UPDATE_CLIENTS。两者在本文件中都有先例,但同一 PR 内不统一,建议统一为常量。

  3. 成就 ID 拼接:AnvilCraft.of("anvilcraft/new_cycle") 可用现成的 AnvilCraft.advancementOf("new_cycle")(该 helper 目前全仓库无人使用,正是为此场景而留);另外 criterion key "new_cycle" 与 ID 在 datagen 和 handler 各写一次,建议提成常量避免漂移。

  4. zh_cn.json 新条目未按字母序插入:en_us/en_ud 是生成物、顺序正确,但手工维护的 zh_cn.json 本身是字母序排布的,本次 item.anvilcraft.civilization_catalyst 插在 legacy_essence 之后、screen...monolith_deployer 插在 temple 之后、advancements...new_cycle 插在 the_start 之后,都跳出了排序位置。若仓库对 lang 排序有约定(Weblate 回写时可能被重排),建议挪到正确位置。

  5. MonolithDeployerHandler.onClear 未 be.setChanged()(未持久化 ticksRemaining=0)。实际无影响——巨构清除后 handler 不再 tick,且 clearMegastructure() 的调用方都会 setChanged()——仅为一致性可选修正。

🟢 看起来不错

  • 重构等价性:tryCivilization→generateOfferings、tryWasteland→generateWasteland 是纯抽取,循环体逐行未变(仅 od/wd → data),return true 的语义位置保持不变;pickRandomGemAmulet/Block 的旧 pseudo-entry 兼容分支仍在。
  • Handler 生命周期与持久化完整:name/onBuild/onClear/serverTick/saveAdditional/loadAdditional 全部覆盖 IMegastructureHandler 签名;monolithDeploymentTicks 经 CfaMegastructureManager.saveAdditional(遍历所有 handler 写同一 tag)落盘,key 唯一;loadAdditional 用 Math.clamp(..., 0, DEPLOYMENT_TICKS) 防越界。handler 实例是 per-BE(CfaMegastructureManager 是 BE 字段,definition.createHandler() 每次 new),不存在多台锻星砧共享 ticksRemaining 的状态串台。
  • 判定时机正确:结束那一刻重新校验 planet && canDeploy(...)(而非只在建造时判定),倒计时期间天体被换掉/资源变化时安全清除,不会误作用到新天体;body 为 null 时 instanceof 直接为 false,无 NPE。
  • 状态同步与既有路径一致:completeMonolithDeployment 尾部 = setChanged() + sendBlockUpdated(..., Block.UPDATE_CLIENTS),与 CfaSearchController.sync()→markSearchStateChanged() 完全同构;getUpdateTag 携带 celestialBody/planetaryResources,标签缺 celestialBody 时客户端 handleUpdateTag 置 null → "天体消失"能正确同步(含既有天体出现/消失动画过渡分支)。
  • 不污染旧存档索引:新巨构只注册进 ModMegastructures(新的可扩展注册表),没有往 CelestialRefactorRegistry.getOptionsForRing 那份硬编码 legacy 列表里插条目——否则会整体位移旧存档的 legacyActiveMegastructureIndex 映射,这点处理正确。CfaMegastructureManager.registerLegacyHandlers() 的 putIfAbsent 兜底也不会覆盖注册表实例的运行时状态。
  • 配方/进度/资源 ID 与生成物一一对应:charger_charging/magnet_block_from_ferrite_core_magnet_block、hollow_magnet_block_from_magnet_block、magnet_block_from_hollow_magnet_block、civilization_catalyst 四处 save(...) 名与生成的 recipe/advancement 路径、RecipeCategory(REDSTONE/MISC)全部吻合;新充电配方与既有 charger_charging/magnet_block.json(iron_block→magnet_block,−20kW)材料不同,无配方冲突。
  • 数值无套利:8 磁铁块 ⇄ 9 空心磁铁块为等值往返(8×9=72 磁铁锭 ↔ 9×8=72),与既有"8 铁锭→1 空心""9 铁锭→1 磁铁块"的换算自洽;铁芯磁铁块(9 磁铁锭+1 铁锭)→磁铁块(9 磁铁锭)等价于把中心那颗铁锭充电(−4kW/2s vs 单充铁锭 −4kW/2s),无净收益。
  • 创造栏:现代 items 分节 tab 的 "produced" 段与旧版 ingredients tab 都加了,与其它组件(戴森球组件等)一致;"produced" 段 13→14 项,其它段最多 62 项,分节布局无溢出(分节由 CreativeTabSections 按内容计算)。
  • 成就链路完整:隐藏挑战 + minecraft:impossible 触发器 + 代码 award(holder, "new_cycle"),criterion key 与生成 json 一致;parent/sends_telemetry_event/frame/rewards 均由生成物体现。
  • 资源齐全:textures/item/civilization_catalyst.png、models/block/celestial_forging_anvil_ring_1_monolith.json 在目标分支已存在;lang 三处(生成 en_us/en_ud + 手写 zh_cn)新增 6 个键(item ×1、advancement ×2、megastructure 标题/描述/usage ×3)完全对齐,无英文残留、无占位符缺失。

🧪 测试建议

被测目标 推荐场景 优先级
PlanetResourceGenerator.advanceCivilization ① 文明星球→废土:矿物/流体保留、offerings 清空、isWasteland=true;② 生物星球→文明:hasCivilization=true、offerings 非空;③ 无同类配方/offeringData==null → 返回同一实例且不变异 🔴
MonolithDeployerHandler.serverTick 200 tick 边界(0/1/199/200);倒计时期内换天体→清除且不消耗于错误天体;loadAdditional 的 clamp(负值/超 200) 🔴
50/50 分支 用固定 RandomSource 断言"文明星球"两路各半、"无文明星球"必走 OFFERING 🟡
CelestialSearchHistory.remove 同天体多条历史被全删、其它天体保留、browseIndex/originalEntry 重置;CompoundTag 等值(playerHeadProfile 等嵌套 tag)比对 🟡
canDeploy null / wasteland / 恰好 3 种(含 weight=0 的重复 id)/ 2 种 → false 🟡
awardNewCycle 16 格边界(16/16.01 格)、跨维度玩家不获奖、成就已解锁时不重复 🟢
配方往返 8 磁铁块→9 空心→8 磁铁块恒等;充电配方 power<0 ⇒ CHARGER 🟢

结论: COMMENT — Draft 阶段未发现阻塞项,实现与 #5073/#5090 规格逐条吻合且持久化/同步/存档迁移处理得比较扎实。建议在转 ready 前确认两点:⚠️1 的"多配方时 findFirst() 选错"是否要加稳健性(或明确文档化为"石碑无视门槛")、⚠️2 的"配方缺失仍消耗投放器"是否给反馈。另:本次 gh token 已失效(gh auth status 报 invalid,按流程未尝试导出凭据修复),故未自动改标题——建议标题:Add civilization catalyst, monolith deployer and magnet recipes 添加文明催化器、石碑投放器与磁铁配方(现标题只提了催化器与磁铁配方,漏掉了本 PR 主体的石碑投放器巨构与新轮回进度)。


由 Hermes Agent 审查

@Gugle2308

Copy link
Copy Markdown
Collaborator

💾 Self-improvement review: Skill 'anvilcraft-megastructure-handler-review' created. · Patched SKILL.md in skill 'advancement-criterion-pr-review' (1 replacement).

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

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

代码审查摘要 — PR #5125

操作: ready_for_review(PR 当前 data-status="pullOpened",未合并;base dev/1.21/1.6 = 956c11b4,与 git ls-remote 权威一致)
范围: 25 个文件(12 Java / 11 新增 / 0 删除)/ 840 行 diff,无截断、无 ghost 文件、无 EOF 批量缺失异常
核对基准: 除 diff 外,已在 rvbase1216(目标分支源码)上交叉验证 API 与既有约定,并抓取 issue #5073 / #5090 原文逐条对账。

📋 需求核对表(对照 #5073 / #5090 原文)

需求 状态 证据
新岩石行星巨构:石碑投放器 monolith_deployer ✅ ModMegastructures.MONOLITH_DEPLOYER(ring 1、ringModel(1,"monolith");models/block/celestial_forging_anvil_ring_1_monolith.json 已存在)
只能建在「生物掉落物 ≥3 种」或「已有原始文明」的星球 ✅ MonolithDeployerHandler.canDeploy():!isWasteland && (hasCivilization || distinct(biological itemId) ≥3),同时用于建前 prerequisite 与 10 秒后复检
建后等待 10 秒 ✅ DEPLOYMENT_TICKS = 200;saveAdditional/loadAdditional 持久化(Math.clamp(…,0,200)),区块卸载可续
有生物资源 → 产生原始文明(资源替换为文明资源) ✅ advanceCivilization → OFFERING + setHasCivilization() + generateOfferings();矿物/流体保留
已有文明 → 50% 废土 / 50% 消失 ✅ getRandom().nextBoolean();废土走 WASTELAND + setWasteland() + generateWasteland()
消失时附近玩家获得隐藏挑战「新轮回」 ✅ awardNewCycle() 半径 16 格;advancement parent=anvilcraft:anvilcraft/the_start、frame=challenge、hidden=true、icon=civilization_catalyst(生成 JSON 一致)
经验「约 0→30 级」 ✅ AdvancementRewards.Builder.experience(1395)、生成 JSON "experience":1395 —— 1395 正是原版 0→30 级累计经验,与 issue 细节吻合
建材:文明催化器 ×1 ✅ .material(ModItems.CIVILIZATION_CATALYST.get(), 1)
催化器配方 = 石碑/精华/石碑 ×2 行(中为腐化信标),产 4 ✅ MEM / MBM / MEM,M=MONOLITH、E=LEGACY_ESSENCE、B=CORRUPTED_BEACON,count 4
#5090 8 磁铁块 → 9 空心磁铁块 ✅ hollowMagnetBlock:AAA/A A/AAA
#5090 9 空心磁铁块 → 8 磁铁块 ✅ magnetBlock:3×3 空心 → 8(双向回环净产出为 0,无刷物品漏洞)
#5090 铁芯磁铁块 4 kW / 2 s 充电为磁铁块 ✅ power(-4)(负=耗电,getProcessingBlock() 选 CHARGER)、time(20*2)

✅ 已实做的交叉验证

  • IMegastructureHandler.serverTick 只对 active handler 派发;handler 实例随 BE 独立(definition.createHandler()),ticksRemaining 为实例字段,不会跨 BE 串扰。
  • be.clearMegastructure() 会走 BE 版(重置 materialFilter/materialLimit + PowerGrid.addComponent),失败分支与完成分支都做了全量清理。
  • 消失分支 celestialBodyData=null / stellarMass=0 / locked=false / removeGravitySource() 后 sendBlockUpdated(Block.UPDATE_CLIENTS),而 writeUpdateTag 已含 body / resources / megastructureId / history,客户端状态能同步。
  • CelestialSearchHistory.remove() 用的 body.toTag().equals() 与既有 add() 去重判据同源,非新引入的等值假设;remove 先于 add 调用,借助「首条去重」语义把历史刷新为最新资源 → 浏览历史不会复活已消失星球。
  • 唯一新引入的原版 API 已用 Mojang 1.21 mappings 核对:CriteriaTriggers.IMPOSSIBLE 类型为 ImpossibleTrigger、ImpossibleTrigger$TriggerInstance 有公开无参构造;PlayerAdvancements.award(AdvancementHolder,String)、ServerAdvancementManager.get(ResourceLocation)、Math.clamp(long,int,int) 均存在(Java 21 项目)→ 无编译风险。
  • 创造栏:Ingredients(ingredients 页)与 ItemsSections(items 页 materials 分区)是两个不同 Tab,同时加入不构成重复。
  • 纹理 textures/item/civilization_catalyst.png 已在 base 分支(16×16、8-bit 调色板、274B、PNG 头合法),模型 JSON 引用一致 → 不存在缺纹理坑。
  • 生成资源与 datagen 源逐项一致(4 个 recipe/advancement 的 id、recipes/misc、recipes/charger_charging 目录、charger 配方仅带 has_the_recipe 判据,与既有 8 个 charger 配方完全同构)。

⚠️ 建议合并前处理 / 确认

  1. 新增了巨构却未同步游戏内手册。 src/main/resources/assets/anvilcraft/ageratum/{en_us,zh_cn}/004_block/402_mega_structure.md 逐条记载了全部巨构(含最近的 Temple / Penrose Sphere / Matter Decompressor),建议按同样格式补 ## Monolith Deployer / ## 石碑投放器(需求、10 秒后两种结果、建材、消耗后消失),文案与 ScreenLang 的 usage 保持一致。

  2. PlanetResourceGenerator.advanceCivilization 选配方时未过 recipe.matches(input, level):

level.getRecipeManager().getAllRecipesFor(...).stream()
    .map(RecipeHolder::value).filter(c -> c.category() == category).findFirst().orElse(null);

内置数据只有 1 个 offering + 1 个 wasteland,所以当前结果正确;但这里绕过了全局生成器唯一遵守的天体类型守卫(matches() 对 OFFERING/WASTELAND 要求 body instanceof RockyPlanetData)。后果有两处需要作者确认:

  • ModMegastructures 的 prerequisite 与 SpecialCelestialBodyData 判定都明确允许特殊天体(SpecialCelestialBodyRecipe.generateResources() 确实会带矿物/流体/生物/供奉资源,所以该分支是可达的)→ 特殊天体推进文明时会套用全局 offering 表,并把该天体独一无二的生物资源组整体丢弃。若这是有意为之,请在代码注释/手册里写明「特殊天体使用全局 OFFERING/WASTELAND 表」;若非本意,建议按天体分流。
  • 数据包/附属若注册多条同类别配方(OfferingData 带 ageMin/ageMax/civilizationChance、WastelandData 带 ageMin/wastelandChance,语义上完全支持多条),findFirst() 就依赖配方 map 的迭代顺序,与生成原始资源时选中的那条可能不是同一条,出现「文明资源与星球设定不符」。建议抽出与 generate() 共用的 selectRecipe(category, input, level)(若要保留特殊天体行为,可让特殊天体走显式的 fallback 分支而不是隐式 findFirst)。
  1. 不可逆副作用请确认预期: 推进文明/废土会丢弃 getBiologicalItems()/getBiologicalFluids(),只保留矿物+流体。这与 issue「其星球资源变为对应的原始文明资源」一致,但意味着该星球此后永久不再满足 isEcoStationEligible(生态站需要「无文明 + 有生物资源」)。建议在 PR 描述或手册中明确这条不可逆后果。

💡 小项(可选)

  • MonolithDeployerHandler.serverTick 失败分支用字面量 3,同 PR 的 completeMonolithDeployment 用 Block.UPDATE_CLIENTS,同一 PR 内两种写法建议统一。
  • canDeploy 里 .filter(entry -> entry.weight() > 0) 是恒真过滤(两条写入路径都不会产生 ≤0 权重),可省。
  • RegisterAdditionalEventListener 的「注册表未填充」兜底清单列了其余全部 1.21 内置巨构模型,建议补一行 standaloneBlock("celestial_forging_anvil_ring_1_monolith")(正常路径已由 ModRegistries.MEGASTRUCTURE 通用注册覆盖)。
  • ticksRemaining 未同步客户端(无倒计时 UI);若日后想在 CFA 界面显示进度,可参照 TempleHandler 补 writeUpdateTag/readUpdateTag。

🟢 看起来不错

  • 计时器仅服务端 tick + NBT 持久化(TempleHandler 同款模式),区块卸载/重进可续且不跨 BE 串扰。
  • 10 秒后复检 canDeploy 而非只信任建造时判定,避免中途天体条件变化造成错误推进。
  • 三条结果路径统一由 completeMonolithDeployment() 收口,且都成对 setChanged() + sendBlockUpdated;clearMegastructure() 先于 body 清空,legacy 身份解析仍安全。
  • 磁铁双向配方净产出为 0 环(8→9→8),充电配方沿用 power<0=耗电、time=tick 既有约定;#5090 的回收诉求被正确满足。
  • 生成资源(en_us/en_ud/模型/配方/进度)与 datagen 源一致,lang 键在 AdvancementLang/ScreenLang/ModItems.lang 三处齐全,zh_cn 同步补译文。

🧪 测试建议

被测目标 场景 优先级
MonolithDeployerHandler.serverTick 建造后第 199 tick 卸载区块再加载 → 计时继续、不重复结算 🔴
同上 计时期间解锁星球/清空天体 → 失败分支清巨构且建材不返还 🟡
PlanetResourceGenerator.advanceCivilization 无文明 + ≥3 种生物掉落 → 得到 hasCivilization + offerings,矿物/流体保留、生物组被替换 🔴
同上 已有文明两分支(废土 / 消失)产出形态与 generate() 一致 🔴
同上 特殊天体(SpecialCelestialBodyData)路径与多条同类别配方的选中结果(覆盖 ⚠️2) 🟡
awardNewCycle 16 格内/外玩家是否精确获授;隐藏挑战不出现在正常进度树 🟡
磁铁配方 8→9→8 双向可合成、配方书解锁 🟢

结论: COMMENT(可合并,建议先补手册文档并确认 ⚠️2 意图) —— 代码层面未发现功能性缺陷:12 项需求与 #5073/#5090 原文逐条吻合(连「1395 经验 = 0→30 级」这种细节都对得上),持久化、同步、清理、注册与 datagen 链路均自洽。实质建议集中在「新巨构手册条目」与「advanceCivilization 选配方的天体类型守卫/多配方顺序依赖」两点。

关于标题: gh auth status 显示 /opt/data/home/.config/gh/hosts.yml 中 token 已失效(gh pr edit 返回 HTTP 401 Bad credentials),本次未能自动修改。建议标题(现标题只提 recipes,未覆盖本 PR 主体——石碑投放器巨构与 10 秒演化机制、新轮回挑战进度):

Add civilization catalyst, monolith deployer and magnet block recipes 添加文明催化器、石碑投放器与磁铁方块配方


由 Hermes Agent 审查

@Gugle2308

Copy link
Copy Markdown
Collaborator

代码审查摘要 — PR #5125

操作: review_requested(PR 状态:pullOpened,未合并)
范围: 28 个文件 / +505 −3(46 hunks)/ 15 Java(11 新增 + 4 修改)/ 0 删除 / 无 ghost 文件,diff 完整

本环境无构建/运行条件;下述 API 结论均来自对目标分支源码(dev/1.21/1.6 @ 956c11b4)、官方 1.21.1 client_mappings + 混淆客户端字节码、以及 anvillib 2.0.0+snapshot.534 -sources.jar 的静态核对。

✅ PR 声称验证表

声称 状态 对应实现
新增文明催化器及合成配方 ✅ ModItems.CIVILIZATION_CATALYST(5 巨石 + 2 传承精华 + 1 腐化信标 → ×4)、生成资源齐全(recipe / advancement / model / en_us / en_ud / zh_cn);ingredients + ItemsSections 双处同步
用一个催化器建造石碑投放器 ✅ ModMegastructures.MONOLITH_DEPLOYER(.ring(1)、.material(CIVILIZATION_CATALYST,1))、CfaMegastructureManager.registerLegacy 补齐
十秒后生效 ✅ DEPLOYMENT_TICKS = 200(20 tps = 10 s)
已有文明各 50% 废土 / 消失 ✅ hasCivilization() && nextBoolean() → 消失;否则 advanceCivilization → 废土
保留基础资源、替换文明资源 ✅ advanceCivilization 复制 minerals + fluids 到新集合
更新搜索历史防恢复旧状态 ✅ CelestialSearchHistory.remove() + completeMonolithDeployment 中 remove → add 顺序
消失时给附近玩家隐藏挑战 ✅ awardNewCycle(半径 16)、hidden: true、minecraft:impossible 触发器 + 手动 award
8 磁铁块 ↔ 9 空心磁铁块双向合成 ✅ RegistrumBlockRecipeLoader 中 8→9(AAA/A A/AAA)与 9→8(满 3×3)
铁芯磁铁块 4 kW / 2 s 充电为磁铁块 ✅ power(-4)(负 = 充电,单位 kW)、time(40),与描述完全一致
resolved #5073 / #5090 ✅ 标题匹配:「[TODO] 文明催化器」「[Feature] 添加磁铁相关配方」

🔴 关键问题

无。未发现阻塞性缺陷。

⚠️ 需确认(1 项,非阻塞)

  • 创建文明时生物资源被静默丢弃 — PlanetResourceGenerator.advanceCivilization(PlanetResourceGenerator.java:127+)只复制 minerals / fluids,未复制 biologicalItems / biologicalFluids。因此对「≥3 种生物掉落物但尚无文明」的星球,投放器生效后该星球的生物资源(生态站 EcoStationHandler 采集的 getBiologicalItems()/getBiologicalFluids())会永久消失,且 isEcoStationEligible 因 hasCivilization() 变为不可再建生态站。
    这与 generate() 的互斥语义一致(自然生成的文明星球本就没有生物资源),所以很可能是有意设计;但现有 usage 文本只写「使具有生物资源的星球产生原始文明」,没有说明生物资源会被替换掉。建议要么在 usage 里补一句(「生物资源将被文明资源替换」),要么确认这是预期。同理,废土分支丢弃旧文明 offerings 已由「替换文明资源」覆盖,无异议。

💡 建议(3 项,可选)

  1. advanceCivilization 未复用 recipe.matches(input, level)(PlanetResourceGenerator.java:129-136)— 直接用 findFirst() 按 category 取配方。当前 matches() 对 OFFERING/WASTELAND 仅等价于 body instanceof RockyPlanetData,且特殊天体资源集为空 ⇒ 现状不会误用;但一旦后续给这两类增加匹配条件(如 planetType、liquidMin),本路径会绕过过滤。建议改为构造 PlanetResourceInput(body, ageAnvilCount) 并复用 matches(),与 generate() 保持一致。
  2. 未实现 writeUpdateTag/readUpdateTag — 基础类提供空实现,monolithDeploymentTicks 只进存档、不进客户端同步包,因此 10 s 倒计时在 GUI 上完全不可见(15 个 handler 中有 6 个实现了该钩子)。若希望界面显示进度,把 ticksRemaining 加进 update tag 即可;否则可忽略。
  3. 经验奖励 1395 — 这是全 mod 唯一一处 advancement 经验奖励(其它挑战为 0 或无奖励,原版挑战为 50)。数值看着不像笔误但很特殊,建议确认是有意取值。

🟢 看起来不错(已逐项核验)

  • 提取重构保真:generateOfferings / generateWasteland 逐行对照旧内联循环,变量重命名(od/wd → data)与 return true 位置迁移均等价,legacy pseudo entries 分支完整保留,无守卫丢失(全 diff 仅 3 行删除,均为被搬移行)。
  • 搜索历史顺序正确:add() 有「首条同 body 则跳过」的去重守卫,PR 先 remove(body) 再 add(body, resources),正确绕开了该守卫;CompoundTag.equals 确认是值比较(混淆字节码 code=37 的非默认实现),CelestialBodyData.toTag() 为内容序列化 ⇒ 按 body 身份移除有效。
  • 旧存档无回归(重点核验):新巨构没有被加进 CelestialRefactorRegistry.getOptionsForRing 的硬编码 legacy 列表(这一点很关键,加进去会平移旧存档的数字索引);resolveLegacyIdentity 解析顺序为 id → name → legacy-index,且 legacy-index 走未改动的旧列表 ⇒ 在 ModMegastructures 中间插入定义不会让已存档的巨构错位。
  • 持久化接线正确:CfaMegastructureManager.saveAdditional 遍历全部 handler 写入同一个 compound,monolithDeploymentTicks 键全局唯一,无冲突;loadAdditional 的 Math.clamp(…,0,200) 边界安全。
  • API/资产静态核对全部通过(无编译风险):
    • challenge(ItemLike,String,boolean) / rewards(AdvancementRewards.Builder) / addCriterion(String,Criterion<?>) 均存在于 AdvancementLineHelper;ImpossibleTrigger.TriggerInstance 在 1.21.1 是 record 且有 public 无参构造(<init>()V public,已对官方 mappings 验证);ServerAdvancementManager.get(ResourceLocation)、PlayerAdvancements.award(AdvancementHolder,String)、ServerLevel.getPlayers(Predicate) 签名均匹配;
    • civilization_catalyst.png(item 贴图)与 celestial_forging_anvil_ring_1_monolith.json(巨构环模型)在 base 分支已存在 ⇒ 无缺失资源;
    • Checkstyle LineLength max=140,新增文件最长行 135 ✅;javax.annotation.Nullable 与本分支惯例一致(全分支 347 个文件使用,非 jspecify 迁移分支);
    • 配方无循环套利:8 磁铁块 → 9 空心 → 8 磁铁块往返净收益为 0。
  • 玩法协同良好:文明化后 TEMPLE 前置条件(resources == null || hasCivilization())自动解锁神殿,形成「投放器 → 文明 → 神殿供奉」链路;clearMegastructure() 不退还材料,「生效后石碑投放器消失」的 usage 描述与实际一致。

🧪 测试建议

被测目标 推荐场景 优先级
PlanetResourceGenerator.advanceCivilization 无匹配配方 / wastelandData()==null / offeringData()==null ⇒ 返回同一 current 实例;有文明 → wasteland 且 hasCivilization()==false;无文明 → offering 且 hasCivilization()==true;minerals/fluids 逐项守恒 🔴
CelestialSearchHistory.remove + add 移除后 add 不被去重守卫吞掉;同 body 多条历史全部被清理;browseIndex 复位 🟡
MonolithDeployerHandler 序列化往返 saveAdditional→loadAdditional:0 / 200 / 负值 / 超界值的 clamp;世界重载中途恢复倒计时 🟡
MonolithDeployerHandler.canDeploy resources==null、废土、hasCivilization、恰好 3 种 / 2 种生物物品、weight==0 条目被过滤 🟡
awardNewCycle 半径 16 边界(distanceToSqr <= 256)内外玩家、多玩家同时授予、new_cycle criterion 名与 JSON 一致 🟢
游戏内集成 建造 → 10 s 三结局分支;拆除 CFA / chunk unload 中途取消与恢复;确认倒计时期间 locked==true 使历史浏览/搜索被服务端拒绝(body 不会被换掉) 🟡

📌 标题建议

PR 标题目前只写了 "…and magnet recipes",实际还包含石碑投放器巨构 + 新轮回挑战成就,建议改为:

Add civilization catalyst, monolith deployer and magnet recipes 添加文明催化器、石碑投放器与磁铁相关配方

本次未能自动修改:gh auth status 显示 token 失效(The token in /opt/data/home/.config/gh/hosts.yml is invalid),按约定不导出任何凭据,故在此给出建议标题。

结论: APPROVE — 声称的 5 项功能均已落地且实现正确,API/资产/持久化/旧存档兼容性经静态核验无风险,提取重构保真;仅 1 项行为请在合并前确认(文明化时生物资源被替换,建议补 usage 说明)及 3 项非阻塞建议。


由 Hermes Agent 审查

@Gugle2308

Copy link
Copy Markdown
Collaborator

💾 Self-improvement review: Patched SKILL.md in skill 'anvilcraft-megastructure-handler-review' (1 replacement). · Patched SKILL.md in skill 'pr-fix-claim-verification' (1 replacement).

@Gugle2308

Copy link
Copy Markdown
Collaborator

💾 Self-improvement review: Patched SKILL.md in skill 'anvilcraft-megastructure-handler-review' (1 replacement). · Patched references/shell-only-diff-navigation.md in skill 'github-webhook-pr-review' (1 replacement). · Patched SKILL.md in skill 'advancement-criterion-pr-review' (1 replacement).

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

Copy link
Copy Markdown
Collaborator

PR #5125 的状态是 closed。按 webhook 审查约定(closed / labeled 事件直接停止,不发布评论),本次不做审查、不发表任何评论。

  • 事件类型:closed
  • 处置:stop,未下载 diff,未调用 gh pr review/comment,未触碰任何凭据。
  • 若该 PR 后续重新 open 或推送新提交触发 opened / synchronize / ready_for_review,我会再自动跑完整审查。

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.

[Feature] 添加磁铁相关配方 [TODO] 文明催化器

4 participants