Сделал простой плагин для действий. У меня одна проблема. Когда игрок нажимает Shift и быстро закрывает инвентарь, он может получить предмет бесплатно. Мне нужно это исправить, что мне делать?
Код ниже:
@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;
}
вы не должны использовать Economy.setMoney для подобных транзакций, в хранилище есть специальный метод приема / передачи денег игроку. А что, если предметы не поместятся в инвентаре игрока?




Трудно сказать, если ваша логика, связанная с проверкой инвентаря, в порядке, я бы сказал, что вы пропустили 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>, где ключ - это индекс элемента из аргумента метода (так как это varargs, в вашем случае ключ может быть только 0, поскольку вы передаете только один аргумент) и элемент, который не поместился в инвентарь. (обратите внимание, что может быть добавлена одна часть стопки, например, 12 из 43 элементов в стопке)
Вау ... это работает, но только с режимом выживания.