You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Minecraft Bukkit插件InventoryClickEvent失效问题求助

解决Minecraft InventoryClickEvent无响应的问题

我仔细看了你的代码,发现几个导致GUI点击没反应的关键问题,咱们一步步来修复:

核心问题:事件监听器未正确注册

你的CommandRtp类里写了@EventHandler注解的onClick方法,但这个类没有实现Listener接口,再加上主类里的事件注册代码有错误,导致Bukkit根本没把这个方法当成事件监听器来处理。

修复步骤:

1. 让CommandRtp类实现Listener接口

修改CommandRtp的类定义,加上implements Listener——这是Bukkit识别事件监听器的必要条件:

public class CommandRtp implements CommandExecutor, Listener {

2. 修正主类Main中的事件注册代码

你的主类里有一行完全错误的注册代码:

Bukkit.getPluginManager().registerEvents((Listener) this, Bukkit.getPluginManager().getPlugins()[0]);

这行不仅没必要,还会抛出ClassCastException(因为Main类没实现Listener),直接删掉就行。

保留正确的注册代码,而且现在不需要强制类型转换了(因为CommandRtp已经实现了Listener):

Bukkit.getPluginManager().registerEvents(new CommandRtp(), this);

这里第二个参数this是对的,它代表你的插件实例(Main是JavaPlugin子类)。

3. 优化InventoryClickEvent的判断逻辑

为了避免误触发(比如玩家点击自己的背包也会触发这个事件),建议加上额外判断,确保点击的是咱们创建的GUI:

@EventHandler
public void onClick(InventoryClickEvent event) {
    // 先判断点击者是不是玩家
    if (!(event.getWhoClicked() instanceof Player)) return;
    Player player = (Player) event.getWhoClicked();
    ItemStack current = event.getCurrentItem();
    
    // 过滤空物品、点击的不是GUI的情况
    if (current == null || event.getClickedInventory() == null || !event.getClickedInventory().equals(event.getInventory())) return;
    
    // 确认是咱们的GUI
    if (event.getInventory().getTitle().equals("Menu de tp aléatoire")) {
        event.setCancelled(true); // 取消默认行为,防止物品被移动
        
        if (current.getType() == Material.GOLD_BLOCK) {
            player.closeInventory();
            player.performCommand("rtpPlayer"); // 用performCommand比chat更规范,不会在聊天框发消息
        }
        if (current.getType() == Material.DIAMOND_BLOCK) {
            player.closeInventory();
            player.setFlying(true);
        }
    }
}

另外,执行命令的时候用player.performCommand("rtpPlayer")比player.chat("/rtpPlayer")更合适,前者是直接执行命令,不会在聊天框显示内容,更符合插件的逻辑。

4. 检查控制台错误

启动服务器时看看控制台,如果有ClassCastException或者IllegalArgumentException之类的错误,说明还有遗漏的问题。确保所有导入的类都是正确的,比如Listener是org.bukkit.event.Listener。

完整修正后的代码片段

CommandRtp类:

package can.evilestvirus.randomtp;
import java.util.Arrays;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;

public class CommandRtp implements CommandExecutor, Listener {
    @Override
    public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
        if (sender instanceof Player) {
            Player player = (Player) sender;
            Inventory inv = Bukkit.createInventory(null, 9, "Menu de tp aléatoire");
            ItemStack goldBlock = new ItemStack(Material.GOLD_BLOCK, 1);
            ItemMeta goldBlockM = goldBlock.getItemMeta();
            goldBlockM.setDisplayName("§8[§a+§8] §aRandomTP Normal §8[§a+§8]");
            goldBlockM.setLore(Arrays.asList("§b- §6Distance de TP: 2500 Blocks", "§b- §6Prix: $0", "§b- §6Cooldown de 60 secondes", "§a§lCliquez ici pour utiliser"));
            goldBlockM.addEnchant(Enchantment.DURABILITY, 10, true);
            goldBlockM.addItemFlags(ItemFlag.HIDE_ENCHANTS);
            goldBlock.setItemMeta(goldBlockM);
            inv.setItem(3, goldBlock);

            ItemStack diamondBlock = new ItemStack(Material.DIAMOND_BLOCK, 1);
            ItemMeta diamondBlockM = diamondBlock.getItemMeta();
            diamondBlockM.setDisplayName("§8[§a+§8] §aRandomTP §6§lVIP §8[§a+§8]");
            diamondBlockM.setLore(Arrays.asList("§b- §6Distance de TP: 5000 Blocks", "§b- §6Prix: $1000", "§b- §6Cooldown de 5 minutes", "§a§lCliquez ici pour utiliser"));
            diamondBlockM.addEnchant(Enchantment.DURABILITY, 10, true);
            diamondBlockM.addItemFlags(ItemFlag.HIDE_ENCHANTS);
            diamondBlock.setItemMeta(diamondBlockM);
            inv.setItem(5, diamondBlock);

            player.openInventory(inv);
        }
        return true;
    }

    @EventHandler
    public void onClick(InventoryClickEvent event) {
        if (!(event.getWhoClicked() instanceof Player)) return;
        Player player = (Player) event.getWhoClicked();
        ItemStack current = event.getCurrentItem();
        
        if (current == null || event.getClickedInventory() == null || !event.getClickedInventory().equals(event.getInventory())) return;
        
        if (event.getInventory().getTitle().equals("Menu de tp aléatoire")) {
            event.setCancelled(true);
            if (current.getType() == Material.GOLD_BLOCK) {
                player.closeInventory();
                player.performCommand("rtpPlayer");
            }
            if (current.getType() == Material.DIAMOND_BLOCK) {
                player.closeInventory();
                player.setFlying(true);
            }
        }
    }
}

Main类:

package can.evilestvirus.randomtp;
import org.bukkit.plugin.java.JavaPlugin;
import can.evilestvirus.randomtp.CommandRtpPlayer;

public class Main extends JavaPlugin {
    @Override
    public void onEnable() {
        System.out.println("HELLO PEOPLE!");
        this.getCommand("rtpplayer").setExecutor(new CommandRtpPlayer());
        this.getCommand("rtp").setExecutor(new CommandRtp());
        // 正确注册CommandRtp作为事件监听器
        getServer().getPluginManager().registerEvents(new CommandRtp(), this);
    }
}

额外提示

  • 确保你的plugin.yml文件里正确声明了rtp和rtpplayer这两个命令,否则命令会无法被Bukkit识别。
  • 如果你的CommandRtpPlayer类也需要处理事件,记得也要让它实现Listener接口并在主类里注册。

内容的提问来源于stack exchange,提问作者nat.laliberte

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 16:07:36