为什么我的 Minecraft(我的世界)图形用户界面在设置时不能清除剑和弓?

Why does my GUI for Minecraft not clear the sword and set the bow when it is set to do so?

我是 Minecraft 上服务器的插件开发人员,我 运行 遇到了一个问题,当我点击 "Accept." 我最终需要它做的是拿起那把钻石剑,在交易被接受后清除它,然后将弓添加到相应的槽中供玩家拿走。

private Inventory i = Bukkit.createInventory(null, 9, ChatColor.BOLD + "Trade-Up"); //Creating an inventory for everything to work around

public void onEnable() {
    getServer().getPluginManager().registerEvents(this, this);
}//Registering the event

private void openGUI(Player player) {
    player.closeInventory();

    ItemStack Anvil = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 3);
    ItemMeta AnvilMeta = Anvil.getItemMeta();

    AnvilMeta.setDisplayName(ChatColor.DARK_AQUA + "Trade Up");
    Anvil.setItemMeta(AnvilMeta);

    ItemStack AnvilAccept = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 5);
    ItemMeta AnvilAcceptMeta = AnvilAccept.getItemMeta();

    AnvilAcceptMeta.setDisplayName(ChatColor.GREEN + "Accept");
    AnvilAccept.setItemMeta(AnvilAcceptMeta);

    ItemStack AnvilFirst = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 7);
    ItemMeta AnvilFirstMeta = AnvilFirst.getItemMeta();

    AnvilFirstMeta.setDisplayName(ChatColor.GRAY + "Input Items Here");
    AnvilFirst.setItemMeta(AnvilFirstMeta);

    ItemStack AnvilSecond = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 7);
    ItemMeta AnvilSecondMeta = AnvilSecond.getItemMeta();

    AnvilSecondMeta.setDisplayName(ChatColor.GRAY + "Output Items Here");
    AnvilSecond.setItemMeta(AnvilSecondMeta);

    i.setItem(0, Anvil);
    i.setItem(1, Anvil);
    i.setItem(3, AnvilFirst);
    i.setItem(4, AnvilAccept);
    i.setItem(5, AnvilSecond);
    i.setItem(7, Anvil);
    i.setItem(8, Anvil);

    player.openInventory(i);
}//Opens the trade-up inventory when the player type the command

public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
    if(sender instanceof Player) {
        if(cmd.getName().equalsIgnoreCase("trade-up")) {
            Player player = (Player) sender;
            openGUI(player);
        }//GUI openning command
    }
    return false;
}

@EventHandler
public void inventoryClickEvent(InventoryClickEvent e) {

    ItemStack Anvil = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 3);
    ItemMeta AnvilMeta = Anvil.getItemMeta();

    AnvilMeta.setDisplayName(ChatColor.DARK_AQUA + "Trade Up");
    Anvil.setItemMeta(AnvilMeta);

    ItemStack AnvilAccept = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 5);
    ItemMeta AnvilAcceptMeta = AnvilAccept.getItemMeta();

    AnvilAcceptMeta.setDisplayName(ChatColor.GREEN + "Accept");
    AnvilAccept.setItemMeta(AnvilAcceptMeta);

    ItemStack AnvilFirst = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 7);
    ItemMeta AnvilFirstMeta = AnvilFirst.getItemMeta();

    AnvilFirstMeta.setDisplayName(ChatColor.GRAY + "Input Items Here");
    AnvilFirst.setItemMeta(AnvilFirstMeta);

    ItemStack AnvilSecond = new ItemStack(Material.STAINED_GLASS_PANE, 1, (short) 7);
    ItemMeta AnvilSecondMeta = AnvilSecond.getItemMeta();

    AnvilSecondMeta.setDisplayName(ChatColor.GRAY + "Output Items Here");
    AnvilSecond.setItemMeta(AnvilSecondMeta);

    ItemStack is = e.getCurrentItem();

    if(is.equals(Anvil) || is.equals(AnvilFirst) || is.equals(AnvilSecond)) {
        e.setCancelled(true);//Making sure that the player doesn't take the glass panes
    }

    if(is.equals(AnvilAccept)) {
        Player p = (Player) e.getWhoClicked();

        ItemStack air = new ItemStack(Material.AIR);

        ItemStack chests = new ItemStack(Material.DIAMOND_SWORD);
        ItemStack chestsConvert = new ItemStack(Material.BOW);

        if(i.contains(chests, 2)) {
            i.setItem(6, chestsConvert);
            i.clear(2);
            i.setItem(0, Anvil);
            i.setItem(1, Anvil);
            i.setItem(3, AnvilFirst);
            i.setItem(4, AnvilAccept);
            i.setItem(5, AnvilSecond);
            i.setItem(7, Anvil);
            i.setItem(8, Anvil);
            p.closeInventory();
            p.openInventory(i);
            p.sendMessage(ChatColor.GREEN + "Your items have been Traded-Up!");//Removes the sword and gives them a bow instead
        }else if(i.contains(air, 2)) {
            p.sendMessage("There is no items to trade up!");
        } //Makes sure there is an item to trade-up

    e.setCancelled(true);//Makes so the player can't take the "Accept" pane.
    }
}

插件不会记录插槽中有任何东西,也不会移除钻石剑并将其替换为弓。

contains(ItemStack, int) 方法不检查那种 ItemStack 是否在插槽 int 中(我看到你使用它的方式)但检查它的全部内容库存至少包含 ItemStack 的整数。您的代码正在检查自定义库存是否包含两把钻石剑(如果您将它们放在插槽 2 和 6 中就可以完成),而不是检查插槽 2 中是否放置了一把钻石剑(这是我假设的正在尝试做)。

要解决此问题,请使用 inventory.getItem(2).equals(chests) 检查插槽二是否包含剑。请注意,在空插槽的情况下,上述方法不会 return 类型 Material.AIRItemStack 而是 return null.

下面是一些示例代码:

ItemStack input = i.getItem(2); // Get the ItemStack at slot two

if (input == null) { // If there is nothing in that slot
    player.sendMessage("There are no items to trade up!");
} else if (input.equals(chests)) { // If it contains the sword
    // Execute the trade
}
// Optionally send message if it is the wrong item

您定义和初始化自定义 InventoryItemStack 的方式可以颠倒过来。请注意,多个人可以查看同一个库存并与之交互,因此按照您现在编写插件的方式,使用 "trade-up" 界面的每个人都将看到相同的库存,并且能够拿走其他人的物品。但是,您为每个事件和 openGUI(Player) 方法调用新创建的 ItemStack 不是唯一的,并且可以代替清单,只创建一次以节省资源(换句话说,您可以每次调用 openGUI(Player) 方法时创建一个新的 Inventory,但始终引用相同的 ItemStacks).