Baubles Expanded 兼容

基本信息

属性 值
目标 modid Baubles|Expanded(带竖线)
门控位置 mixins/Mixins.java:53 .addRequiredMod(TargetedMod.BAUBLES_EXPANDED)
枚举定义 mixins/TargetedMod.java:10 BAUBLES_EXPANDED("Baubles|Expanded")
运行时检测 WitcheryExtras.java:63 Loader.isModLoaded("Baubles|Expanded")
编译依赖 compileOnly('com.github.GTNewHorizons:Baubles-Expanded:2.2.22-GTNH:dev')(dependencies.gradle)
涉及的 Mixin 3 个

✅ Baubles Expanded 在本 wiki 收录范围内(分类 baubles-expanded), 跨分类链接见 分类页。 相对地,Witchery 本体不在收录范围(见 分类页)。

⚠️ modid 陷阱

Baubles|Expanded 是 GTNH 版 Baubles-Expanded 的父 modid, 不是 Baubles,也不是 BaublesExpanded。

字符串 出现在 含义
Baubles|Expanded TargetedMod.java:10、WitcheryExtras.java:63 父 modid,本 mod 门控用的就是它
Baubles —— 主 mod 自己的 modid(见 baubles-expanded 分类页)

本 mod 里没有出现 Baubles 这个字符串——若哪天看到 Loader.isModLoaded("Baubles") 就说明门控写错了。

preInit 阶段的槽位申请

if (Loader.isModLoaded("Baubles|Expanded")) {
    BaubleExpandedSlots.tryAssignSlotsUpToMinimum(BaubleExpandedSlots.beltType, 1);
    BaubleExpandedSlots.tryAssignSlotsUpToMinimum(BaubleExpandedSlots.charmType, 1);
}

(WitcheryExtras.java:63-66)

在 preInit 里申请腰带(belt)与挂饰(charm)各至少 1 个槽位。 用 tryAssignSlotsUpToMinimum(类型, 1)——只保证至少 1 个, 具体分配到哪几个槽由 Baubles Expanded 决定。

3 个 Mixin

1. BlockWitchDoorMixin_Bauble —— 女巫门钥匙

@WrapMethod 包住 hasKeyForDoor(BlockWitchDoorMixin_Bauble.java:23-26), 让挂在饰品栏里的门钥匙也能开女巫门。

关键实现(BlockWitchDoorMixin_Bauble.java:28-45):

// func_150012_g == getFullMetadata with MCP mappings. We use it to get the Y coord of the bottom door block,
// which has the NBT data we want, even if the player clicks on the top block.
final int doorBaseY = (((BlockWitchDoor) (Object) this).func_150012_g(world, x, y, z) & 8) == 0 ? y : y - 1;

IInventory baubles = BaublesApi.getBaubles(player);
for (int slot = 0; slot < baubles.getSizeInventory(); slot++) {
    ItemStack bauble = baubles.getStackInSlot(slot);
    if (Witchery.Items.GENERIC.itemDoorKey.isMatch(bauble)) {
        if (witcheryExtras$keyNBTMatchesDoor(bauble.getTagCompound(), x, doorBaseY, z, world.provider.dimensionId))
            return true;
        continue;
    }
    ...
}
  • 用 func_150012_g(getFullMetadata)的 & 8 位判断点击的是上半还是下半门, 换成下半门的 Y 坐标——注释明确说明「即使玩家点的是上半门」
  • 匹配条件是 witcheryExtras$keyNBTMatchesDoor(baubleNBT, x, doorBaseY, z, dimensionId) ——钥匙 NBT 里绑定的坐标与维度必须完全一致

2. ItemGeneralMixin_Bauble —— 罗温钥匙 / 钥匙串

ItemGeneral(Witchery 的通用物品容器类)通过 implements IBaubleExpanded(ItemGeneralMixin_Bauble.java:29) 让其中 2 个子物品成为饰品:

@Unique
private static final String[] witcheryExtras$rowanKeyBaubleTypes = { BaubleExpandedSlots.amuletType,
        BaubleExpandedSlots.beltType, BaubleExpandedSlots.charmType };

(ItemGeneralMixin_Bauble.java:32-33)

匹配的 2 个子物品(通过 @Final @Shadow 取用,ItemGeneralMixin_Bauble.java:37-40):

字段 物品
itemDoorKey 罗温钥匙
itemDoorKeyring 钥匙串

可用槽位类型:护符(amulet)、腰带(belt)、挂饰(charm)。

补丁 行 作用
@Inject addInformation(TAIL,仅客户端) ItemGeneralMixin_Bauble.java:45-52 BaubleItemHelper.addSlotInformation(tooltip, 类型数组),tooltip 追加可用的饰品槽类型
@WrapMethod onItemRightClick ItemGeneralMixin_Bauble.java:53-58 右键时走 BaubleItemHelper.onBaubleRightClick(stack, world, player) 装到饰品栏;不匹配则 original.call(...) 走原版逻辑
getBaubleTypes(ItemStack) ItemGeneralMixin_Bauble.java:62-64 匹配则返回 3 个槽类型,否则返回 null
getBaubleType(ItemStack) ItemGeneralMixin_Bauble.java:66-68 直接 return null(该接口方法未实现)

3. ItemPoppetMixin_Bauble —— 附魔人偶

同样 implements IBaubleExpanded(ItemPoppetMixin_Bauble.java:33), 但可用槽位只有挂饰(charm)一种:

@Unique
private static final String[] witcheryExtras$poppetBaubleTypes = { BaubleExpandedSlots.charmType };

(ItemPoppetMixin_Bauble.java:36)

9 种人偶类型(全部 @Final @Shadow,ItemPoppetMixin_Bauble.java:40-66): earthPoppet、waterPoppet、firePoppet、foodPoppet、toolPoppet、 deathPoppet、antiVoodooPoppet、vampiricPoppet、poppetProtectionPoppet、 armorPoppet(源码共 10 个 @Shadow 字段,含上列 10 项)。

补丁 行 作用
@Inject addInformation(TAIL,仅客户端) ItemPoppetMixin_Bauble.java:78-84 同样用 BaubleItemHelper.addSlotInformation
@WrapMethod onItemRightClick ItemPoppetMixin_Bauble.java:86-89 有效人偶 → 装入饰品栏;否则 original.call(...)
@WrapMethod(static)findBoundPoppetInInventory ItemPoppetMixin_Bauble.java:93-99 源码注释:// Prioritize player inventory over baubles when checking for poppets ——优先搜玩家背包,再搜饰品栏

@SideOnly(Side.CLIENT) 标在方法上(ItemPoppetMixin_Bauble.java:77、 ItemGeneralMixin_Bauble.java:44),因此 tooltip 补丁只在客户端存在。

门控的双重性

层次 机制 位置
Mixin 是否应用 .addRequiredMod(TargetedMod.BAUBLES_EXPANDED) Mixins.java:53
槽位是否申请 Loader.isModLoaded("Baubles|Expanded") WitcheryExtras.java:63

没装 Baubles Expanded 时这 3 个 Mixin 完全不加载, Witchery 的钥匙/人偶就只能放背包,与原版行为一致。

📌 dependencies.gradle 里 Baubles-Expanded 是 compileOnly—— 编译需要,运行时可选。文件末尾两行 // Uncomment to test baubles compat 与 //devOnlyNonPublishable('com.github.GTNewHorizons:Baubles-Expanded:2.2.22-GTNH:dev') 是注释掉的开发期依赖(dependencies.gradle:13-14),不参与构建。

关联