package me.fromgate.reactions.util.item; import me.fromgate.reactions.util.BukkitCompatibilityFix; import me.fromgate.reactions.util.Param; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; import java.util.regex.Pattern; public class ItemUtil { private static Random random = new Random(); private static boolean itemVersion = determineVersion(); // false - old, true - new; private final static Pattern INT_GZ = Pattern.compile("[1-9]+[0-9]*"); private final static Pattern D = Pattern.compile("\\d+"); private final static Pattern ITEM_D = Pattern.compile("item\\d+|ITEM\\d+"); private final static Pattern SET_D = Pattern.compile("set\\d+|SET\\d+"); private static boolean determineVersion() { String versionStr = Bukkit.getBukkitVersion().replaceAll("[^0-9]", ""); return versionStr.matches("15\\d*|16\\d*|17\\d*"); } public static void giveItemOrDrop(Player player, ItemStack item) { for (ItemStack itemDrop : player.getInventory().addItem(item).values()) { player.getWorld().dropItemNaturally(player.getLocation(), itemDrop); } } public static VirtualItem itemFromString(String itemStr) { return itemVersion ? VirtualItem.fromString(itemStr) : VirtualItem18.fromString(itemStr); } public static void giveItemOrDrop(Player player, String itemStr) { VirtualItem vi = itemFromString(itemStr); if (vi == null) return; giveItemOrDrop(player, vi); } public static boolean removeItemInHand(Player player, String itemStr) { ItemStack inHand = BukkitCompatibilityFix.getItemInHand(player); if (inHand == null || inHand.getType() == Material.AIR) return false; VirtualItem hand = VirtualItem.fromItemStack(inHand); VirtualItem vi = removeItemFromStack(hand, itemStr); if (vi == null) return false; BukkitCompatibilityFix.setItemInHand(player, vi.getType() == Material.AIR ? null : vi); return true; } public static boolean removeItemInOffHand(Player player, String itemStr) { ItemStack inHand = BukkitCompatibilityFix.getItemInOffHand(player); if (inHand == null || inHand.getType() == Material.AIR) return false; VirtualItem hand = VirtualItem.fromItemStack(inHand); VirtualItem vi = removeItemFromStack(hand, itemStr); if (vi == null) return false; BukkitCompatibilityFix.setItemInOffHand(player, vi.getType() == Material.AIR ? null : vi); return true; } public static boolean removeItemInInventory(Inventory inventory, String itemStr) { Map<String, String> itemParams = VirtualItem.parseParams(itemStr); return removeItemInInventory(inventory, itemParams); } private static boolean removeItemInInventory(Inventory inventory, Map<String, String> itemParams) { int amountToRemove = Integer.parseInt(VirtualItem.getParam(itemParams, "amount", "1")); //int countItems = countItemsInventory (inventory, itemParams); //if (amountToRemove>countItems) return false; for (int i = 0; i < inventory.getSize(); i++) { if (inventory.getItem(i) == null || inventory.getItem(i).getType() == Material.AIR) continue; VirtualItem vi = ItemUtil.itemFromItemStack(inventory.getItem(i)); if (!vi.compare(itemParams, 1)) continue; if (vi.getAmount() <= amountToRemove) { amountToRemove -= vi.getAmount(); inventory.setItem(i, null); } else { vi.setAmount(vi.getAmount() - amountToRemove); inventory.setItem(i, vi); amountToRemove = 0; } if (amountToRemove == 0) return true; } return false; } private static int countItemsInventory(Inventory inventory, Map<String, String> itemParams) { int count = 0; for (ItemStack slot : inventory) { if (slot == null || slot.getType() == Material.AIR) continue; VirtualItem vi = ItemUtil.itemFromItemStack(slot); if (!vi.compare(itemParams, 1)) continue; count += slot.getAmount(); } return count; } /** * @param stack - source item * @param itemStr - item description to remove * @return - item stack contained left items (if all items removed - remove */ private static VirtualItem removeItemFromStack(VirtualItem stack, String itemStr) { if (!ItemUtil.compareItemStr(stack, itemStr)) return null; int amountToRemove = getAmount(itemStr); if (amountToRemove <= 0) return null; int leftAmount = stack.getAmount() - amountToRemove; if (leftAmount < 0) return null; VirtualItem result = VirtualItem.fromItemStack(stack); if (leftAmount == 0) result.setType(Material.AIR); else result.setAmount(leftAmount); return result; } private static int getAmount(String itemStr) { Map<String, String> itemMap = VirtualItem.parseParams(itemStr); String amountStr = VirtualItem.getParam(itemMap, "amount", "1"); if (D.matcher(amountStr).matches()) return Integer.parseInt(amountStr); return 1; } public static boolean hasItemInInventory(Player player, String itemStr) { return hasItemInInventory(player.getInventory(), itemStr); } public static boolean hasItemInInventory(Inventory inventory, String itemStr) { int countAmount = countItemsInInventory(inventory, itemStr); int amount = getAmount(itemStr); return countAmount >= amount; } public static int countItemsInInventory(Inventory inventory, String itemStr) { Map<String, String> itemMap = VirtualItem.parseParams(itemStr); return countItemsInventory(inventory, itemMap); } public static VirtualItem itemFromItemStack(ItemStack item) { return itemVersion ? VirtualItem.fromItemStack(item) : VirtualItem18.fromItemStack(item); } public static ItemStack parseItemStack(String string) { return itemFromString(string); } public static boolean compareItemStr(ItemStack item, String itemStr) { if (item == null || item.getType() == Material.AIR) return false; return itemFromItemStack(item).compare(itemStr); } public static boolean compareItemStr(ItemStack item, String itemStr, boolean allowHand) { if (item != null && item.getType() != Material.AIR) return compareItemStr(item, itemStr); if (!allowHand) return false; return (itemStr.equalsIgnoreCase("HAND") || itemStr.equalsIgnoreCase("AIR")); } public static boolean removeItemInInventory(Player player, String itemStr) { return removeItemInInventory(player.getInventory(), itemStr); } public static ItemStack getRndItem(String str) { if (str.isEmpty()) return new ItemStack(Material.AIR); String[] ln = str.split(","); if (ln.length == 0) return new ItemStack(Material.AIR); ItemStack item = ItemUtil.parseItemStack(ln[tryChance(ln.length)]); if (item == null) return new ItemStack(Material.AIR); item.setAmount(1); return item; } /* * <item>;<item>;<item>[%<chance>]/<item>;<item>;<item>[%<chance>] * */ public static List<ItemStack> parseItemStacksOld(String items) { List<ItemStack> stacks = new ArrayList<>(); String[] ln = items.split(";"); // ВОТ ЭТО ЛОМАЕТ К ЧЕРТЯМ НОВЫЙ ФОРМАТ!!! for (String item : ln) { VirtualItem vi = itemFromString(item); if (vi != null) stacks.add(vi); } return stacks; } public static String itemToString(ItemStack item) { VirtualItem vi = itemFromItemStack(item); return vi == null ? "" : vi.toString(); } public static String toDisplayString(List<ItemStack> items) { StringBuilder sb = new StringBuilder(); for (ItemStack i : items) { VirtualItem vi = VirtualItem.fromItemStack(i); if (sb.length() > 0) sb.append(", "); sb.append(vi.toDisplayString()); } return sb.toString(); } //item:{item1:{[...] chance:50} item2:{} item3:{} public static VirtualItem itemFromMap(Param params) { return itemVersion ? VirtualItem.fromMap(params.getMap()) : VirtualItem18.fromMap(params.getMap()); } public static List<ItemStack> parseItemsSet(Param params) { List<ItemStack> items = new ArrayList<>(); for (String key : params.keySet()) { if (ITEM_D.matcher(key).matches()) { String itemStr = params.getParam(key, ""); VirtualItem vi = itemFromString(itemStr); if (vi != null) items.add(vi); } } if (items.isEmpty()) { VirtualItem item = itemFromMap(params); if (item != null) items.add(item); } return items; } /* * set1:{item1:{} item2:{} item3:{} chance:50} set2:{item1:{} item2:{} item3:{} chance:50} * * */ public static List<ItemStack> parseRandomItemsStr(String items) { Param params = new Param(items); if (params.matchAnyParam(SET_D)) { Map<List<ItemStack>, Integer> sets = new HashMap<>(); int maxChance = 0; int nochcount = 0; for (String key : params.keySet()) { if (!SET_D.matcher(key).matches()) continue; Param itemParams = new Param(params.getParam(key)); List<ItemStack> itemList = parseItemsSet(itemParams); if (itemList == null || itemList.isEmpty()) continue; int chance = itemParams.getParam("chance", -1); if (chance > 0) maxChance += chance; else nochcount++; sets.put(itemList, chance); } int eqperc = (nochcount * 100) / sets.size(); maxChance = maxChance + eqperc * nochcount; int rnd = tryChance(maxChance); int curchance = 0; for (List<ItemStack> stack : sets.keySet()) { curchance = curchance + (sets.get(stack) < 0 ? eqperc : sets.get(stack)); if (rnd <= curchance) return stack; } } else if (params.matchAnyParam("item\\d+|ITEM\\d+")) { return parseItemsSet(params); } else { VirtualItem vi = itemFromString(items); if (vi != null) { List<ItemStack> iList = new ArrayList<>(); iList.add(vi); return iList; } } return null; } //id:data*amount@enchant:level,color;id:data*amount%chance/id:data*amount@enchant:level,color;id:data*amount%chance public static String parseRandomItemsStrOld(String items) { if (items.isEmpty()) return ""; String[] loots = items.split("/"); Map<String, Integer> drops = new HashMap<>(); int maxchance = 0; int nochcount = 0; for (String loot : loots) { String[] ln = loot.split("%"); if (ln.length > 0) { String stacks = ln[0]; if (stacks.isEmpty()) continue; int chance = -1; if ((ln.length == 2) && (INT_GZ.matcher(ln[1]).matches())) { chance = Integer.parseInt(ln[1]); maxchance += chance; } else nochcount++; drops.put(stacks, chance); } } if (drops.isEmpty()) return ""; int eqperc = (nochcount * 100) / drops.size(); maxchance = maxchance + eqperc * nochcount; int rnd = tryChance(maxchance); int curchance = 0; for (String stack : drops.keySet()) { curchance = curchance + (drops.get(stack) < 0 ? eqperc : drops.get(stack)); if (rnd <= curchance) return stack; } return ""; } private static int tryChance(int chance) { return random.nextInt(chance); } public static String toDisplayString(String itemStr) { VirtualItem vi = itemFromString(itemStr); if (vi != null) return vi.toDisplayString(); Map<String, String> itemMap = VirtualItem.parseParams(itemStr); String name = itemMap.containsKey("name") ? itemMap.get("name") : itemMap.containsKey("type") ? itemMap.get("type") : null; if (name == null) return itemStr; int amount = getAmount(itemStr); String data = VirtualItem.getParam(itemMap, "data", "0"); StringBuilder sb = new StringBuilder(name); if (!itemMap.containsKey("name") && !data.equals("0")) sb.append(":").append(data); if (amount > 1) sb.append("*").append(amount); return ChatColor.stripColor(ChatColor.translateAlternateColorCodes('&', sb.toString())); } }