挑战系统

基本信息

属性 值 来源
注册类 ModChallenges client/challenge/ModChallenges.java
难度枚举 EnumChallengeLevel:4 级 client/challenge/EnumChallengeLevel.java:13-18
挑战条目 20(6 + 6 + 4 + 4) ModChallenges.init(),20 次 addChallenge
数据类 Challenge client/challenge/Challenge.java
初始化调用 ClientProxy.java:209 纯客户端
展示界面 辞典 GUI 的「挑战」页 client/gui/lexicon/GuiLexiconChallengesList.java、GuiLexiconChallenge.java
持久化 客户端本地文件 PersistentVariableHelper → injectNBTToFile(cmp, getCacheFile())

⚠️ 整个系统位于 client/ 包,不产生任何服务端注册。服务端既不知道有哪些挑战,也不知道玩家完成了哪些挑战。

这是「挑战」而不是「宾果」

.desc 文本里反复出现「奖励积分」(bonus points),但 Botania 源码中没有任何积分 / 计分 / 物品限制代码:

  • 全仓 grep -rlni 'bingo' src/main/java → 无任何命中,模组里没有宾果(Bingo)玩法
  • Challenge 只有 3 个字段 + 1 个布尔:unlocalizedName / icon / level / complete(Challenge.java:18-21)
  • 没有任何类读取「完成状态」来改变物品可获得性

所以 Botania 交付的是挑战定义 + 自查清单 UI,积分判定与奖励由外部整合包 / 宾果封装包负责。描述文本引用积分,只是因为这些挑战最初为宾果卡组设计。读源码时不要期待在本模组内找到计分逻辑。

完成状态如何被设置

Challenge.complete 是 public boolean(Challenge.java:21),唯一的写入点是玩家在辞典界面手动点击按钮:

challenge.complete = !challenge.complete;   // GuiLexiconChallenge.java:113

即玩家自己勾选「这条我做到了」。没有自动检测、没有统计系统。GuiLexiconChallenge.java:171 通过 ModChallenges.challengeLookup.get(challengeName) 按未本地化名取回实例。

持久化

PersistentVariableHelper 把挑战状态与其他辞典数据一起写入本地缓存文件(PersistentVariableHelper.java:59-62):

NBTTagCompound challengesCmp = new NBTTagCompound();
for(Challenge c : ModChallenges.challengeLookup.values())
    c.writeToNBT(challengesCmp);          // cmp.setBoolean(unlocalizedName, complete)
cmp.setTag(TAG_CHALLENGES, challengesCmp);

读取在 PersistentVariableHelper.java:97-99。同一个 NBT 还保存书签(TAG_BOOKMARKS)、辞典笔记(TAG_LEXICON_NOTES)、首载标记与上次 Botania 版本号。

注意:因为存在客户端本地文件,换电脑 / 删 .minecraft 下的缓存目录会丢失所有勾选状态,且多人游戏中各客户端状态独立、不同步。

20 条挑战

难度键为 botania.challengelevel.<level>,条目键为 botania.challenge.<name>。四条难度:EASY / NORMAL / HARD / LUNATIC。

难度 键 名称 图标
EASY flowerFarm 花卉农场 ModBlocks.flower meta 6
EASY recordFarm 唱片农场 Items.record_13
EASY reedFarm 甘蔗农场 Items.reeds
EASY cobbleGen 圆石制造机 Blocks.cobblestone
EASY pureDaisy 自动白雏菊 subtile_puredaisy
EASY battery 魔力电池 ModBlocks.pool
NORMAL apothecaryRefill 药剂台注水器 ModBlocks.altar
NORMAL treeFarm 树场 Blocks.sapling
NORMAL fullCropFarm 齐全的作物农场 Items.wheat_seeds
NORMAL animalFarm 动物农场 Items.leather
NORMAL boneMealFarm 骨粉农场 Items.dye meta 15(骨粉)
NORMAL orechid 自动凝矿 subtile_orechid
HARD mobTower 刷怪塔 Items.bone
HARD entropinnyumSetup 热爆装置 subtile_entropinnyum
HARD spectrolusSetup 斑斓装置 subtile_spectrolus
HARD potionBrewer 自动酿造 ModBlocks.brewery
LUNATIC kekimurusSetup 贪食装置 subtile_kekimurus
LUNATIC autoQuarry 自动采矿 Items.diamond_pickaxe
LUNATIC runeCrafter 符文合成 ModItems.rune

EASY / NORMAL 各 6 条,HARD / LUNATIC 各 4 条 —— 难度越高条目越少,但 LUNATIC 的描述明确写着「你必须非常疯狂才能尝试这个」。

20 条挑战中有 4 条直接考据功能花(pureDaisy、orechid、entropinnyumSetup、spectrolusSetup、kekimurusSetup 共 5 条),即「让某朵花完全自动化」。这与凝矿兰权重表那类内部数据配合阅读效果最好。

注册机制

public static void addChallenge(EnumChallengeLevel level, String name, ItemStack icon) {
    Challenge c = new Challenge("botania.challenge." + name, icon, level);
    challenges.get(level).add(c);              // 按难度分桶
    challengeLookup.put(c.unlocalizedName, c); // 另建按未本地化名的索引
}

init() 先按 EnumChallengeLevel.class.getEnumConstants() 为 4 个难度各建一个空 ArrayList(ModChallenges.java:32-33),所以 challenges 永远是 4 键的 EnumMap,即使某难度没有条目也不会缺键。

注意 challengeLookup 以 unlocalizedName(含 botania.challenge. 前缀)为键,不是裸名。

相关条目

  • 成就系统 - 同一套玩家目标体系的另一部分,服务端注册、49 条
  • 凝矿兰权重表 - orechid 挑战所考据功能花的内部权重数据
  • 功能花 - 挑战涉及的花:puredaisy / entropinnyum / spectrolus / kekimurus / orechid
  • 生成花 - entropinnyum / spectrolus 所属体系
  • 纯雏菊与星辰 - pureDaisy 挑战的主体
  • 祭坛组 - apothecaryRefill 与 runeCrafter 挑战涉及的方块
  • 饮剂系统 - potionBrewer 挑战的主体