package io.github.bedwarsrel.shop; import io.github.bedwarsrel.BedwarsRel; import io.github.bedwarsrel.game.Game; import io.github.bedwarsrel.utils.ChatWriter; import io.github.bedwarsrel.utils.SoundMachine; import io.github.bedwarsrel.utils.Utils; import io.github.bedwarsrel.villager.MerchantCategory; import io.github.bedwarsrel.villager.VillagerTrade; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map.Entry; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; 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.PlayerInventory; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.PotionMeta; public class NewItemShop { private List<MerchantCategory> categories = null; private MerchantCategory currentCategory = null; public NewItemShop(List<MerchantCategory> categories) { this.categories = categories; } @SuppressWarnings("deprecation") private void addCategoriesToInventory(Inventory inventory, Player player, Game game) { for (MerchantCategory category : this.categories) { if (category.getMaterial() == null) { BedwarsRel.getInstance().getServer().getConsoleSender() .sendMessage(ChatWriter.pluginMessage(ChatColor.RED + "Careful: Not supported material in shop category '" + category.getName() + "'")); continue; } if (player != null && !player.hasPermission(category.getPermission())) { continue; } ItemStack is = new ItemStack(category.getMaterial(), 1); ItemMeta im = is.getItemMeta(); if (Utils.isColorable(is)) { is.setDurability(game.getPlayerTeam(player).getColor().getDyeColor().getWoolData()); } if (this.currentCategory != null && this.currentCategory.equals(category)) { im.addEnchant(Enchantment.DAMAGE_ALL, 1, true); im.addItemFlags(ItemFlag.HIDE_ENCHANTS); } im.setDisplayName(category.getName()); im.setLore(category.getLores()); im.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_POTION_EFFECTS); is.setItemMeta(im); inventory.addItem(is); } } @SuppressWarnings("unchecked") private boolean buyItem(VillagerTrade trade, ItemStack item, Player player) { PlayerInventory inventory = player.getInventory(); boolean success = true; int item1ToPay = trade.getItem1().getAmount(); Iterator<?> stackIterator = inventory.all(trade.getItem1().getType()).entrySet().iterator(); int firstItem1 = inventory.first(trade.getItem1()); if (firstItem1 > -1) { inventory.clear(firstItem1); } else { // pay while (stackIterator.hasNext()) { Entry<Integer, ? extends ItemStack> entry = (Entry<Integer, ? extends ItemStack>) stackIterator.next(); ItemStack stack = (ItemStack) entry.getValue(); int endAmount = stack.getAmount() - item1ToPay; if (endAmount < 0) { endAmount = 0; } item1ToPay = item1ToPay - stack.getAmount(); stack.setAmount(endAmount); inventory.setItem(entry.getKey(), stack); if (item1ToPay <= 0) { break; } } } if (trade.getItem2() != null) { int item2ToPay = trade.getItem2().getAmount(); stackIterator = inventory.all(trade.getItem2().getType()).entrySet().iterator(); int firstItem2 = inventory.first(trade.getItem2()); if (firstItem2 > -1) { inventory.clear(firstItem2); } else { // pay item2 while (stackIterator.hasNext()) { Entry<Integer, ? extends ItemStack> entry = (Entry<Integer, ? extends ItemStack>) stackIterator.next(); ItemStack stack = (ItemStack) entry.getValue(); int endAmount = stack.getAmount() - item2ToPay; if (endAmount < 0) { endAmount = 0; } item2ToPay = item2ToPay - stack.getAmount(); stack.setAmount(endAmount); inventory.setItem(entry.getKey(), stack); if (item2ToPay <= 0) { break; } } } } ItemStack addingItem = item.clone(); ItemMeta meta = addingItem.getItemMeta(); List<String> lore = meta.getLore(); if (lore.size() > 0) { lore.remove(lore.size() - 1); if (trade.getItem2() != null) { lore.remove(lore.size() - 1); } } meta.setLore(lore); addingItem.setItemMeta(meta); HashMap<Integer, ItemStack> notStored = inventory.addItem(addingItem); if (notStored.size() > 0) { ItemStack notAddedItem = notStored.get(0); int removingAmount = addingItem.getAmount() - notAddedItem.getAmount(); addingItem.setAmount(removingAmount); inventory.removeItem(addingItem); // restore inventory.addItem(trade.getItem1()); if (trade.getItem2() != null) { inventory.addItem(trade.getItem2()); } success = false; } player.updateInventory(); return success; } private void changeToOldShop(Game game, Player player) { game.getPlayerSettings(player).setUseOldShop(true); player.playSound(player.getLocation(), SoundMachine.get("CLICK", "UI_BUTTON_CLICK"), Float.valueOf("1.0"), Float.valueOf("1.0")); // open old shop MerchantCategory.openCategorySelection(player, game); } private int getBuyInventorySize(int sizeCategories, int sizeOffers) { return this.getInventorySize(sizeCategories) + this.getInventorySize(sizeOffers); } public List<MerchantCategory> getCategories() { return this.categories; } private int getCategoriesSize(Player player) { int size = 0; for (MerchantCategory cat : this.categories) { if (cat.getMaterial() == null) { continue; } if (player != null && !player.hasPermission(cat.getPermission())) { continue; } size++; } return size; } private MerchantCategory getCategoryByMaterial(Material material) { for (MerchantCategory category : this.categories) { if (category.getMaterial() == material) { return category; } } return null; } private int getInventorySize(int itemAmount) { int nom = (itemAmount % 9 == 0) ? 9 : (itemAmount % 9); return itemAmount + (9 - nom); } private VillagerTrade getTradingItem(MerchantCategory category, ItemStack stack, Game game, Player player) { for (VillagerTrade trade : category.getOffers()) { if (trade.getItem1().getType() == Material.AIR && trade.getRewardItem().getType() == Material.AIR) { continue; } ItemStack iStack = this.toItemStack(trade, player, game); if (iStack.getType() == Material.ENDER_CHEST && stack.getType() == Material.ENDER_CHEST) { return trade; } else if ((iStack.getType() == Material.POTION || (!BedwarsRel.getInstance().getCurrentVersion().startsWith("v1_8") && (iStack.getType().equals(Material.valueOf("TIPPED_ARROW")) || iStack.getType().equals(Material.valueOf("LINGERING_POTION")) || iStack.getType().equals(Material.valueOf("SPLASH_POTION")))))) { if (BedwarsRel.getInstance().getCurrentVersion().startsWith("v1_8")) { if (iStack.getItemMeta().equals(stack.getItemMeta())) { return trade; } } else { PotionMeta iStackMeta = (PotionMeta) iStack.getItemMeta(); PotionMeta stackMeta = (PotionMeta) stack.getItemMeta(); if (iStackMeta.getBasePotionData().equals(stackMeta.getBasePotionData()) && iStackMeta .getCustomEffects().equals(stackMeta.getCustomEffects())) { return trade; } } } else if (iStack.equals(stack)) { return trade; } } return null; } private void handleBuyInventoryClick(InventoryClickEvent ice, Game game, Player player) { int sizeCategories = this.getCategoriesSize(player); List<VillagerTrade> offers = this.currentCategory.getOffers(); int sizeItems = offers.size(); int totalSize = this.getBuyInventorySize(sizeCategories, sizeItems); ItemStack item = ice.getCurrentItem(); boolean cancel = false; int bought = 0; boolean oneStackPerShift = game.getPlayerSettings(player).oneStackPerShift(); if (this.currentCategory == null) { player.closeInventory(); return; } if (ice.getRawSlot() < sizeCategories) { // is category click ice.setCancelled(true); if (item == null) { return; } if (item.getType().equals(this.currentCategory.getMaterial())) { // back to default category view this.currentCategory = null; this.openCategoryInventory(player); } else { // open the clicked buy inventory this.handleCategoryInventoryClick(ice, game, player); } } else if (ice.getRawSlot() < totalSize) { // its a buying item ice.setCancelled(true); if (item == null || item.getType() == Material.AIR) { return; } MerchantCategory category = this.currentCategory; VillagerTrade trade = this.getTradingItem(category, item, game, player); if (trade == null) { return; } player.playSound(player.getLocation(), SoundMachine.get("ITEM_PICKUP", "ENTITY_ITEM_PICKUP"), Float.valueOf("1.0"), Float.valueOf("1.0")); // enough ressources? if (!this.hasEnoughRessource(player, trade)) { player .sendMessage( ChatWriter.pluginMessage(ChatColor.RED + BedwarsRel ._l(player, "errors.notenoughress"))); return; } if (ice.isShiftClick()) { while (this.hasEnoughRessource(player, trade) && !cancel) { cancel = !this.buyItem(trade, ice.getCurrentItem(), player); if (!cancel && oneStackPerShift) { bought = bought + item.getAmount(); cancel = ((bought + item.getAmount()) > 64); } } bought = 0; } else { this.buyItem(trade, ice.getCurrentItem(), player); } } else { if (ice.isShiftClick()) { ice.setCancelled(true); } else { ice.setCancelled(false); } return; } } private void handleCategoryInventoryClick(InventoryClickEvent ice, Game game, Player player) { int catSize = this.getCategoriesSize(player); int sizeCategories = this.getInventorySize(catSize) + 9; int rawSlot = ice.getRawSlot(); if (rawSlot >= this.getInventorySize(catSize) && rawSlot < sizeCategories) { ice.setCancelled(true); if (ice.getCurrentItem().getType() == Material.SLIME_BALL) { this.changeToOldShop(game, player); return; } if (ice.getCurrentItem().getType() == Material.BUCKET) { game.getPlayerSettings(player).setOneStackPerShift(false); player.playSound(player.getLocation(), SoundMachine.get("CLICK", "UI_BUTTON_CLICK"), Float.valueOf("1.0"), Float.valueOf("1.0")); this.openCategoryInventory(player); return; } else if (ice.getCurrentItem().getType() == Material.LAVA_BUCKET) { game.getPlayerSettings(player).setOneStackPerShift(true); player.playSound(player.getLocation(), SoundMachine.get("CLICK", "UI_BUTTON_CLICK"), Float.valueOf("1.0"), Float.valueOf("1.0")); this.openCategoryInventory(player); return; } } if (rawSlot >= sizeCategories) { if (ice.isShiftClick()) { ice.setCancelled(true); return; } ice.setCancelled(false); return; } MerchantCategory clickedCategory = this.getCategoryByMaterial(ice.getCurrentItem().getType()); if (clickedCategory == null) { if (ice.isShiftClick()) { ice.setCancelled(true); return; } ice.setCancelled(false); return; } this.openBuyInventory(clickedCategory, player, game); } public void handleInventoryClick(InventoryClickEvent ice, Game game, Player player) { if (!this.hasOpenCategory()) { this.handleCategoryInventoryClick(ice, game, player); } else { this.handleBuyInventoryClick(ice, game, player); } } private boolean hasEnoughRessource(Player player, VillagerTrade trade) { ItemStack item1 = trade.getItem1(); ItemStack item2 = trade.getItem2(); PlayerInventory inventory = player.getInventory(); if (item2 != null) { if (!inventory.contains(item1.getType(), item1.getAmount()) || !inventory.contains(item2.getType(), item2.getAmount())) { return false; } } else { if (!inventory.contains(item1.getType(), item1.getAmount())) { return false; } } return true; } public boolean hasOpenCategory() { return (this.currentCategory != null); } public boolean hasOpenCategory(MerchantCategory category) { if (this.currentCategory == null) { return false; } return (this.currentCategory.equals(category)); } private void openBuyInventory(MerchantCategory category, Player player, Game game) { List<VillagerTrade> offers = category.getOffers(); int sizeCategories = this.getCategoriesSize(player); int sizeItems = offers.size(); int invSize = this.getBuyInventorySize(sizeCategories, sizeItems); player.playSound(player.getLocation(), SoundMachine.get("CLICK", "UI_BUTTON_CLICK"), Float.valueOf("1.0"), Float.valueOf("1.0")); this.currentCategory = category; Inventory buyInventory = Bukkit .createInventory(player, invSize, BedwarsRel._l(player, "ingame.shop.name")); this.addCategoriesToInventory(buyInventory, player, game); for (int i = 0; i < offers.size(); i++) { VillagerTrade trade = offers.get(i); if (trade.getItem1().getType() == Material.AIR && trade.getRewardItem().getType() == Material.AIR) { continue; } int slot = (this.getInventorySize(sizeCategories)) + i; ItemStack tradeStack = this.toItemStack(trade, player, game); buyInventory.setItem(slot, tradeStack); } player.openInventory(buyInventory); } public void openCategoryInventory(Player player) { int catSize = this.getCategoriesSize(player); int nom = (catSize % 9 == 0) ? 9 : (catSize % 9); int size = (catSize + (9 - nom)) + 9; Inventory inventory = Bukkit.createInventory(player, size, BedwarsRel ._l(player, "ingame.shop.name")); Game game = BedwarsRel.getInstance().getGameManager().getGameOfPlayer(player); this.addCategoriesToInventory(inventory, player, game); ItemStack slime = new ItemStack(Material.SLIME_BALL, 1); ItemMeta slimeMeta = slime.getItemMeta(); slimeMeta.setDisplayName(BedwarsRel._l(player, "ingame.shop.oldshop")); slimeMeta.setLore(new ArrayList<String>()); slime.setItemMeta(slimeMeta); ItemStack stack = null; if (game != null) { if (game.getPlayerSettings(player).oneStackPerShift()) { stack = new ItemStack(Material.BUCKET, 1); ItemMeta meta = stack.getItemMeta(); meta.setDisplayName( ChatColor.AQUA + BedwarsRel._l(player, "default.currently") + ": " + ChatColor.WHITE + BedwarsRel._l(player, "ingame.shop.onestackpershift")); meta.setLore(new ArrayList<String>()); stack.setItemMeta(meta); } else { stack = new ItemStack(Material.LAVA_BUCKET, 1); ItemMeta meta = stack.getItemMeta(); meta.setDisplayName( ChatColor.AQUA + BedwarsRel._l(player, "default.currently") + ": " + ChatColor.WHITE + BedwarsRel._l(player, "ingame.shop.fullstackpershift")); meta.setLore(new ArrayList<String>()); stack.setItemMeta(meta); } if (stack != null) { inventory.setItem(size - 4, stack); } } if (stack == null) { inventory.setItem(size - 5, slime); } else { inventory.setItem(size - 6, slime); } player.openInventory(inventory); } public void setCurrentCategory(MerchantCategory category) { this.currentCategory = category; } @SuppressWarnings("deprecation") private ItemStack toItemStack(VillagerTrade trade, Player player, Game game) { ItemStack tradeStack = trade.getRewardItem().clone(); Method colorable = Utils.getColorableMethod(tradeStack.getType()); ItemMeta meta = tradeStack.getItemMeta(); ItemStack item1 = trade.getItem1(); ItemStack item2 = trade.getItem2(); if (Utils.isColorable(tradeStack)) { tradeStack.setDurability(game.getPlayerTeam(player).getColor().getDyeColor().getWoolData()); } else if (colorable != null) { colorable.setAccessible(true); try { colorable.invoke(meta, new Object[]{game.getPlayerTeam(player).getColor().getColor()}); } catch (Exception e) { BedwarsRel.getInstance().getBugsnag().notify(e); e.printStackTrace(); } } List<String> lores = meta.getLore(); if (lores == null) { lores = new ArrayList<String>(); } lores.add(ChatColor.WHITE + String.valueOf(item1.getAmount()) + " " + item1.getItemMeta().getDisplayName()); if (item2 != null) { lores.add(ChatColor.WHITE + String.valueOf(item2.getAmount()) + " " + item2.getItemMeta().getDisplayName()); } meta.setLore(lores); tradeStack.setItemMeta(meta); return tradeStack; } }