成就

基本信息

属性 值
成就条目数 24
成就页数 1(Blood Magic)
注册方法 ModAchievements.init()(common/achievements/ModAchievements.java:40-73)
调用点 AlchemicalWizardry.preInit → ModAchievements.init()(AlchemicalWizardry.java:692)
成就类 common/achievements/AchievementsMod.java(继承原版 Achievement)
成就页类 net.minecraftforge.common.AchievementPage(Forge 提供)
语言键前缀 achievement.alchemicalwizardry:(统计名)/ alchemicalwizardry:(展示名)
道具触发 AchievementsRegistry.getAchievementForItem(Item) / getAchievementForBlock(Block)
事件触发 AchievementTrigger(注册于 :72)

粒度选择

24 条成就在字段结构上完全同构(id / 网格 x,y / 图标 / 父成就),共用同一个类与同一个注册方法,彼此无独立行为代码。按惯例合并为一页表格,不拆成 24 个文件。

AchievementsMod 的构造函数把 this 追加进静态列表 AchievementsMod.achievements 并调用 registerStat(),因此每 new 一个就自动完成一次注册 —— 不存在「构造了但没注册」的可能。

成就表

「父」列为源码中传入的父成就字段;— 表示该字段是 null,即根成就。

网格 x,y id 图标 父 特殊
0, 0 firstPrick ModItems.sacrificialDagger —(根) ✅ setSpecial()
3, 0 weakOrb ModItems.weakBloodOrb firstPrick
3, 2 bloodLettersPack ModItems.itemBloodPack weakOrb
6, 2 waterSigil ModItems.waterSigil weakOrb
4, -2 blankRunes ModBlocks.bloodRune weakOrb
4, -4 apprenticeOrb ModItems.apprenticeBloodOrb blankRunes
6, 1 airSigil ModItems.airSigil apprenticeOrb
4, -5 daggerSacrifice ModItems.daggerOfSacrifice apprenticeOrb
6, -3 brewingPotions ModBlocks.blockWritingTable apprenticeOrb
2, -2 magicianOrb ModItems.magicianBloodOrb apprenticeOrb
6, 0 sigilHolding ModItems.sigilOfHolding magicianOrb
0, -2 boundBlade ModItems.energySword magicianOrb
1, -1 boundArmor ModItems.boundPlate magicianOrb
1, -4 complexSpells ModItems.itemComplexSpellCrystal magicianOrb
1, -3 ritualDiviner ModItems.itemRitualDiviner magicianOrb
-2, -1 masterOrb ModItems.masterBloodOrb boundBlade
-3, -2 demonSpawn ModItems.demonPlacer masterOrb
6, -1 phantomBridgeSigil ModItems.sigilOfTheBridge masterOrb
-4, -1 teleposer ModBlocks.blockTeleposer masterOrb
6, -2 suppressionSigil ModItems.itemSigilOfSupression masterOrb
-1, 2 archmageOrb ModItems.archmageBloodOrb masterOrb
-3, 2 energyBazooka ModItems.energyBazooka archmageOrb
0, 3 demons ModItems.baseItems meta 29 archmageOrb ✅ setSpecial()
0, 5 transcendentOrb ModItems.transcendentBloodOrb demons

⚠️ 字段名与 id 不一致(源码既有):daggerSacrifice 成就的字段叫 daggerOfSacrifice(ModAchievements.java:22),而传入的 id 字符串是 "daggerSacrifice"(:48)。语言键因此是 achievement.alchemicalwizardry:daggerSacrifice,不是字段名。AchievementsRegistry(:72)按字段 ModItems.daggerOfSacrifice 查找,两侧指向同一个物品,不影响功能。

成就页

alchemicalWizardryPage = new AchievementPage(
        "Blood Magic",
        AchievementsMod.achievements.toArray(new Achievement[AchievementsMod.achievements.size()]));
AchievementPage.registerAchievementPage(alchemicalWizardryPage);

AchievementPage 的列表不是硬编码的 24 个字段,而是把静态列表 AchievementsMod.achievements 整体转成数组 —— 该列表在 AchievementsMod 构造函数里累加,因此页内条目数与 new AchievementsMod( 的调用数恒等(24)。页面标题 "Blood Magic" 与成就页内部键由 Forge 自行管理。

触发机制

成就全部通过 AchievementTrigger(common/achievements/AchievementTrigger.java,注册于 ModAchievements.java:72)的两个 Forge 事件触发,没有第三条路径:

事件 遍历列表 判定函数 列表长度
PlayerEvent.ItemPickupEvent AchievementsRegistry.pickupList getAchievementForItem(Item) 12
PlayerEvent.ItemCraftedEvent AchievementsRegistry.craftinglist getAchievementForItem(Item) 9

getAchievementForItem(AchievementsRegistry.java:65-88)是一串 if (item == ModItems.x) return ModAchievements.y;,19 个分支,含两条类型判定而非等值判定:

判定 成就 依据
item instanceof BoundArmour boundArmor AchievementsRegistry.java:76
item instanceof ItemRitualDiviner ritualDiviner AchievementsRegistry.java:78

方块成就走 getAchievementForBlock(Block)(:89-95,3 个分支:bloodRune、blockWritingTable、blockTeleposer),由 onItemCrafted 里的 event.crafting.getItem() instanceof ItemBlock 分支调用,把 ItemBlock.field_150939_a 反查回方块。

⚠️ 2 条成就不可达

pickupList(12)与 craftinglist(9)均不含 ModItems.demonPlacer 与 ModItems.baseItems,因此以下 2 条成就在正常游戏流程中无法解锁:

id 图标 说明
demonSpawn ModItems.demonPlacer 图标物品从未被加入任何触发列表
demons ModItems.baseItems meta 29 同上;且它是 setSpecial() 成就

即 24 条成就中 22 条可达、2 条不可达。两条的字段、统计名与父子关系都已正确注册并显示在成就页上,只是缺少触发入口 —— 属于未完成而非注册错误。

⚠️ blockCraftingList 是死列表

AchievementsRegistry 用 addBlocksToCraftingList()(:41-45)向 blockCraftingList 填了 3 个方块,但全仓无任何读取点 —— 该标识符只在声明处与 3 次 .add() 出现。

方块成就之所以仍能触发,靠的是 onItemCrafted 中与 craftinglist 循环并列的 instanceof ItemBlock 分支,它按实际合成物的方块反查,与 blockCraftingList 无关。该列表是重构残留:早期版本大概是靠遍历它判定方块成就的。

数值

数值名 值
成就条目数 24
成就页数 1
根成就数(父为 null) 1(firstPrick)
标记 setSpecial() 的成就 2(firstPrick、demons)
以物品为图标的成就 21
以方块为图标的成就 3(blankRunes bloodRune、brewingPotions blockWritingTable、teleposer blockTeleposer)
以 ItemStack(带 meta)为图标的成就 1(demons = ModItems.baseItems meta 29)
网格 x 范围 -4 – 6
网格 y 范围 -5 – 5
最深成就链 firstPrick → weakOrb → blankRunes → apprenticeOrb → magicianOrb → boundBlade → masterOrb → archmageOrb → demons → transcendentOrb(10 层)
叶子成就(无子成就) 15
成就树形态 单根树(仅 firstPrick 无父),24 条全部挂在这一棵树下
由道具判定解锁的条目 22(19 个道具分支 + 3 个方块分支,减去未进入触发列表的 2 条)
不可达的成就 2(demonSpawn、demons)
死列表 blockCraftingList 1(填 3 项,无读取点)

相关条目

  • 气血宝珠 - 6 个宝珠对应 6 条宝珠成就
  • 印记 - waterSigil、airSigil、sigilHolding、phantomBridgeSigil、suppressionSigil 五条印记成就
  • 约束装甲 - boundArmor(instanceof BoundArmour 判定)
  • 其他物品 - 牺牲匕首、法术水晶、仪式推测杖的成就
  • 方块实体总览 - blockWritingTable、blockTeleposer 两个成就图标方块
  • 血之祭坛配方 - demons 成就图标 baseItems meta 29 所指物品