子co,库存

时间:2018-07-27 04:33:54

标签: java minecraft

我做了一个简单的动作插件。我有一个问题。 当玩家按下换档并快速关闭库存时,他可以免费获得物品。我需要解决此问题,该怎么办?

下面的代码:

@EventHandler public void inventoryHandler(InventoryClickEvent e) throws Exception {
    for (AuctionInventory[] inventories : inventoryMap.values()){
        for (AuctionInventory inventory : inventories){
            if (inventory.getInventoryType().equals(AuctionInventoryType.MAIN)) {
                if (e.getClickedInventory().equals(inventory.getSource())) {
                    e.setResult(Event.Result.DENY);
                    e.setCancelled(true);
                    if (e.getCurrentItem().getType() != Material.AIR) {
                        Player p = (Player) e.getWhoClicked();
                        for (Button button : buttonList){
                            if (button.getItem().equals(e.getCurrentItem())){
                                button.doLogic(inventory.getSource(), p);
                                e.setResult(Event.Result.DENY);
                            }
                        }
                        IProduct product = InventoryUtil.getProductByItem(getProducts().values(), e.getCurrentItem());
                        if ((product != null)) {
                            buyProduct(p, product);
                        }
                    }
                }
            }
        }
    }
}

@Override @Deprecated @SuppressWarnings("all")
public boolean buyProduct(Player p, IProduct product) throws Exception {
    if (!product.getSeller().equals(p.getUniqueId())) {
        if (Economy.getMoney(p.getName()) < product.getPrice()) {
            return false;
        }
        p.getInventory().addItem(product.getItem());
        removeProduct(product);
        Economy.setMoney(p.getName(), Economy.getMoney(p.getName()) - product.getPrice());            Economy.setMoney(Bukkit.getOfflinePlayer(product.getSeller()).getName(), Economy.getMoney(Bukkit.getOfflinePlayer(product.getSeller()).getName()) + product.getPrice());
        return true;
    }
    return false;
}

1 个答案:

答案 0 :(得分:0)

很难说,如果您与检查库存有关的逻辑很好,我会说您错过了InventoryDragEvent。您还需要实施该事件,并阻止与库存相关的任何互动。
同样,如果您的库存处于打开状态,则在ClickEvent中您应该阻止交互-包括播放器库存中的单击,因为有些交互可以通过单击内部库存来移动已打开库存中的项目。
另外getClickedInventory()可以返回null。
因此,您应该只检查event.getView().getTopInventory(),检查它是否不是空值,以及是否是您的库存。

带按钮的for循环也不会中断/返回,因此即使玩家按下按钮,您仍然会尝试寻找要出售的物品,这也会引起一些问题。
另外我在这里注意到了其他一些问题,如果您使用.setMoney,则不应该使用Vault API函数,因为这可能会破坏与其他插件的兼容性,就像通过getMoney支票一样。
有一种特殊的public boolean has(OfflinePlayer player, double amount);方法可以检查玩家是否有足够的钱,因为此功能可以与允许负数或以其他方式付款的插件配合使用。
然后,您应该通过public EconomyResponse withdrawPlayer(OfflinePlayer player, double amount);从玩家那里获利,然后您还应该检查响应以确保成功。

p.getInventory().addItem(product.getItem());如果播放器的库存空间不足怎么办?请注意,此方法返回Map<Integer, ItemStack>,其中key是方法参数中项目的索引(因为它是varargs,在您的情况下,key只能是0,因为您仅传递单个参数),并且不适合库存。 (请注意,可能会添加堆栈的一部分,例如堆栈中43个项中的12个)