工具材料触发药水效果

基本信息

属性 值
核心类 com.Zoko061602.SuperTic.PotionEventHandler(package-private,getInstance() 单例,PotionEventHandler.java:17-21)
触发事件 AttackEntityEvent(SuperEventHandler.java:12-15,无优先级指定即 NORMAL)
生效条件 目标为 EntityLivingBase 且攻击者为 EntityPlayerMP(PotionEventHandler.java:24)
注册时机 preInit,MinecraftForge.EVENT_BUS.register(new SuperEventHandler())(SuperTic.java:47)

判定的四个前置检查

按源码顺序(PotionEventHandler.java:24-78):

顺序 检查 失败后果 源码
1 event.target instanceof EntityLivingBase && event.entityPlayer instanceof EntityPlayerMP 直接返回 PotionEventHandler.java:24
2 player.getCurrentEquippedItem() == null 直接返回 PotionEventHandler.java:27-29
3 目标是 EntityPlayer 且 player.canAttackPlayer(tar) 直接返回(PVP 保护 / 队友判定时不给buff) PotionEventHandler.java:31-33
4 手持物 getItem() instanceof ToolCore 且 getTagCompound() != null 直接返回 PotionEventHandler.java:35-41

注意第 3 条的语义:canAttackPlayer 返回 false 才不发效果。也就是说 可以攻击时才发效果,是正向判断而非"禁止 PVP 时生效"。

读取的四个部件位置

从 InfiTool NBT 复合标签读(PotionEventHandler.java:43-55):

NBT 键 读取条件
Head 无条件
Handle 无条件
Accessory tool.getPartAmount() >= 3
Extra tool.getPartAmount() >= 4

未读取的位置保持 -1(PotionEventHandler.java:46-47)。之后每个位置都查 Config.id_eff.containsKey(位置),命中后按符号分派(PotionEventHandler.java:57-76):

if (Config.id_eff.get(head) > 0) addEffect(target, head);
else if (Config.id_eff.get(head) < 0) addEffect(player, head);

正数 → 施加给被攻击的目标;负数 → 施加给攻击者自己。 这与 effects.cfg 里 “Effect id (if negative gets applied to player)” 的注释一致(Config.java:35)。

实际施加

private void addEffect(EntityLivingBase e, int id) {
    int r = new Random().nextInt(Config.id_prob.get(id));
    if (r == 0) e.addPotionEffect(
        new PotionEffect(Math.abs(Config.id_eff.get(id)), Config.id_dur.get(id), Config.id_amp.get(id)));
}

(PotionEventHandler.java:82-86)

项目 来源 effects.cfg 默认值
触发概率 Config.id_prob(nextInt(prob) == 0,即 1/prob 命中) 1(100% 触发)
药水 ID Math.abs(Config.id_eff) 0(无效果)
时长 Config.id_dur(tick) 200 tick
等级 Config.id_amp(即 amplifier,getLatin 里的罗马数字) 1(即效果 I)

⚠️ 每次调用都 new Random()(PotionEventHandler.java:83),不使用实体/世界已有的 RNG。 在高频攻击下这会持续构造新 Random 对象,且结果是时间种子驱动——不保证同一攻击的 可复现性。

物品部件提示(Tooltip)

TooltipEventHandler(TooltipEventHandler.java,@SideOnly(Side.CLIENT))被 SuperEventHandler.Tooltip(@SideOnly(Side.CLIENT),SuperEventHandler.java:17-22) 在 ItemTooltipEvent 时调用,一次做三件事(TooltipEventHandler.java:43-47):

1. 材料部件提示 addPartTooltips

对 instanceof IToolPart 的物品(材料本身 / 未组装的工具部件),用 item.getMaterialID(e.itemStack) 查 Config.id_eff;为 0 则不显示 (TooltipEventHandler.java:50-52)。显示为 药水名 + 罗马数字,并用聊天色区分方向 (TooltipEventHandler.java:53-56):

效果 ID 符号 颜色 含义
负 EnumChatFormatting.AQUA 给自己
正 EnumChatFormatting.DARK_AQUA 给目标

2. 组装工具提示 addPotionTooltips

对 instanceof ToolCore 的成品工具,按 Head → Handle → Binding(Accessory) → Extra 顺序输出(TooltipEventHandler.java:110、124、138、152),规则:

  • 每行只显示一种药水;若多个部件是同一种药水,取其中最高等级并只显示一行 (TooltipEventHandler.java:102-115 等处逐段比较 c < xxx.getAmplifier())
  • 后面的部件若药水与前面已显示的重复,则跳过
  • Binding 行要求 getPartAmount() >= 3,Extra 行要求 getPartAmount() == 4 (TooltipEventHandler.java:132、148)
  • 整段包在 try { ... } catch (Exception ex) { ex.printStackTrace(); } 里 (TooltipEventHandler.java:163-165)

3. TGregworks 材料提示 addGregTooltips

对 IToolPart 且 GameRegistry.findUniqueIdentifierFor(item).modId.equals("TGregworks") 的材料,显示 mat.stonebound(TooltipEventHandler.java:170-182):

mat.stonebound 显示
> 0 Stonebound: x + 正值
< 0 Jagged: x + 取负后的绝对值
== 0 不显示

罗马数字映射

getLatin(TooltipEventHandler.java:27-41):0/1 → " I"、2 → " II" …、 10 → " X"、其他 → " X+"。所以 Amplifier = 1 显示为「I」, Amplifier = 0 也显示为「I」(两者不可区分)。

配置来源

Config.id_eff / id_dur / id_amp / id_prob 四个 HashMap<Integer,Integer> 在 postInit 由 Config.idConfig(effects.cfg) 填充(SuperTic.java:52)。 详见 配置项。