Bukkit中点击方块时PlayerInteractEvent触发两次问题问询
问题分析与解决方案
1. 主手判断逻辑错误
你的代码中用event.getHand().name() != "HAND"过滤副手事件的写法是错误的:
- Java中字符串比较必须使用
equals()方法,!=比较的是对象引用而非内容,即便字符串内容相同,也可能因引用不同导致判断失效,无法过滤副手事件。 - 更规范的方式是直接比较
EquipmentSlot枚举常量,无需转换为字符串。
修正后的判断代码:
// 先导入EquipmentSlot类 import org.bukkit.inventory.EquipmentSlot; // 替换原判断行 if (event.getHand() != EquipmentSlot.HAND) return;
2. 事件处理器重复注册
如果你的插件主类中多次实例化WandHandler(比如调用了两次new WandHandler(this)),会导致同一个事件处理器被注册多次。每次触发PlayerInteractEvent时,所有注册的处理器都会执行一次,表现为代码逻辑运行两次。
检查主类的onEnable()方法,确保仅实例化一次WandHandler:
public class Jtest extends JavaPlugin { @Override public void onEnable() { new WandHandler(this); // 仅实例化一次 } }
3. 可选:过滤多余的交互动作类型
点击方块时,PlayerInteractEvent可能触发不同的Action类型(比如RIGHT_CLICK_BLOCK和PHYSICAL),如果不需要响应这些动作,可以添加过滤逻辑:
import org.bukkit.event.block.Action; // 在主手判断后添加 if (!event.getAction().equals(Action.RIGHT_CLICK_BLOCK) && !event.getAction().equals(Action.RIGHT_CLICK_AIR)) { return; }
修正后的完整处理器代码
package me.ronking159.jtest.handlers; import me.ronking159.jtest.items.ItemManager; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.plugin.Plugin; public class WandHandler implements Listener { public WandHandler(Plugin Jtest) { Bukkit.getPluginManager().registerEvents(this, Jtest); } @EventHandler public void WandHandler(PlayerInteractEvent event) { // 过滤副手事件 if (event.getHand() != EquipmentSlot.HAND) return; // 过滤非右键动作(可选,根据需求调整) if (!event.getAction().equals(Action.RIGHT_CLICK_BLOCK) && !event.getAction().equals(Action.RIGHT_CLICK_AIR)) { return; } if (event.getItem() == null) return; // 用isSimilar()替代ItemMeta比较,更可靠地判断物品一致性 if (!event.getItem().isSimilar(ItemManager.wand)) return; Player p = event.getPlayer(); p.getWorld().createExplosion(p.getLocation(), 2.0f); p.sendMessage("You don't know how to use a wand yet!"); p.sendMessage(event.getAction().name()); p.sendMessage(event.getHand().name()); p.sendMessage(event.getMaterial().name()); } }
注:代码中用isSimilar()替代了ItemMeta.equals(),因为isSimilar()会直接比较两个ItemStack的类型、数据、Meta等核心属性,比单独比较Meta更可靠。
内容的提问来源于stack exchange,提问作者Ron Caspi
相关产品推荐
相关产品推荐

