我做了一个简单的动作插件。我有一个问题。 当玩家按下换档并快速关闭库存时,他可以免费获得物品。我需要解决此问题,该怎么办?
下面的代码:
@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;
}
答案 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个)