黑名单 API

基本信息

属性 值
API 基类 buildcraft.oiltweak.api.OilTweakAPI(抽象类)
API 单例 public static OilTweakAPI INSTANCE,在 preInit 里赋为 this
黑名单接口 ItemBlacklistRegistry(注册 provider、查询)
Provider 接口 ItemBlacklistProvider#isBlacklisted(EntityLivingBase, ItemStack)
内置实现 DefaultBlacklistProvider、BlacklistRegistry
API 标记 `@API(owner = “OilTweak”, provides = “OilTweakAPI” / "OilTweakAPI
对外暴露方 BuildCraftOilTweak 继承 OilTweakAPI 并覆写 getItemBlacklistRegistry()

api 与 api.blacklist 两个包各有一个 package-info.java, 用 cpw.mods.fml.common.API 注解声明所有者为 "OilTweak", apiVersion = Tags.VERSION(构建期生成的版本常量)。

为什么 API 基类是抽象类

BuildCraftOilTweak 本身 extends OilTweakAPI(BuildCraftOilTweak.java:30), 于是一个 @Mod 类同时充当 API 实例。preInit 里:

itemBlacklistRegistry = new BlacklistRegistry();
itemBlacklistRegistry.registerItemBlacklistProvider(new DefaultBlacklistProvider());
OilTweakAPI.INSTANCE = this;

OilTweakAPI 只有一个抽象方法 getItemBlacklistRegistry(), BuildCraftOilTweak 直接 return itemBlacklistRegistry;。

⚠️ 字段 INSTANCE 是 public static 且没有 volatile, 其他 mod 必须在 postInit 之后(更稳妥是第一个事件触发后)才访问它—— 在 preInit 阶段读会拿到 null。

内置黑名单:末影珍珠

DefaultBlacklistProvider 只有一个判定:

return stack != null && (stack.getItem() == Items.ender_pearl
                      || stack.getItem() instanceof ItemEnderPearl);

两个条件是 ||,覆盖原版 Items.ender_pearl 与任何 ItemEnderPearl 子类 (如某些 mod 的自定义末影珍珠)。除末影珍珠外没有别的默认条目。

判定语义

BlacklistRegistry#isBlacklisted 是短路 OR:

for (ItemBlacklistProvider provider : providers) {
    if (provider.isBlacklisted(entity, stack)) return true;
}
return false;

任一 provider 返回 true 即整体为黑名单。entity 参数原样透传, 留给 provider 自行判断(内置实现不用它)。 注册时 if (provider != null) 过滤空引用;重复注册同一实例不去重。

消费点只有一处

黑名单只被交互限制的右键规则 B 读取:

|| OilTweakAPI.INSTANCE.getItemBlacklistRegistry().isBlacklisted(player, player.getCurrentEquippedItem())

它与"浸没等级"是 || 关系,且外层已要求 inOil.halfOfFull()—— 所以离开油中时黑名单完全不生效,黑名单不是无条件禁用末影珍珠。

API 的两个调用时机约束

  1. OilTweakAPI.INSTANCE 在 preInit 才被赋值—— 其他 mod 在自己的 preInit(若早于本 mod)访问会拿到 null;
  2. getItemBlacklistRegistry() 返回的是 preInit 里创建的单个实例, 其他 mod 注册的 provider 会真正生效(列表可变,非不可变视图)。

deInit(FMLModDisabledEvent)里不会清空 provider 列表, 但由于 canBeDeactivated = true,mod 被禁用后 INSTANCE 仍指向旧实例—— onRightClick 里的 OilTweakAPI.INSTANCE 在 mod 被禁用后不再被调用 (事件处理器已 unregister),所以不构成问题。

相关条目