package me.fromgate.reactions.menu; import me.fromgate.reactions.ReActions; import me.fromgate.reactions.event.EventManager; import me.fromgate.reactions.util.Param; import me.fromgate.reactions.util.item.ItemUtil; import me.fromgate.reactions.util.message.M; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; public class InventoryMenu implements Listener { private static Map<Integer, List<String>> activeMenus = new HashMap<>(); private static Map<String, VirtualInventory> menu = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); public static void init() { load(); save(); } public static void save() { File f = new File(ReActions.instance.getDataFolder() + File.separator + "menu.yml"); if (f.exists()) f.delete(); YamlConfiguration cfg = new YamlConfiguration(); for (String key : menu.keySet()) { menu.get(key).save(cfg, key); } try { cfg.save(f); } catch (Exception e) { M.logMessage("Failed to save menu configuration file"); } } public static void load() { menu.clear(); File f = new File(ReActions.instance.getDataFolder() + File.separator + "menu.yml"); if (!f.exists()) return; YamlConfiguration cfg = new YamlConfiguration(); try { cfg.load(f); for (String key : cfg.getKeys(false)) { VirtualInventory vi = new VirtualInventory(cfg, key); menu.put(key, vi); } } catch (Exception e) { M.logMessage("Failed to load menu configuration file"); } } public static boolean add(String id, int size, String title) { if (menu.keySet().contains(id)) return false; menu.put(id, new VirtualInventory(size, title)); save(); return true; } public static boolean set(String id, Param params) { if (!menu.keySet().contains(id)) return false; VirtualInventory vi = menu.get(id); String title = params.getParam("title", vi.title); int size = params.getParam("size", vi.size); size = (size % 9 == 0) ? size : ((size / 9) + 1) * 9; List<String> activators = vi.execs; if (activators.size() < size) for (int i = activators.size(); i < size; i++) activators.add(""); List<String> slots = vi.slots; if (slots.size() < size) for (int i = slots.size(); i < size; i++) slots.add(""); for (int i = 1; i <= size; i++) { if (params.isParamsExists("activator" + Integer.toString(i))) activators.set(i - 1, params.getParam("activator" + Integer.toString(i), "")); if (params.isParamsExists("item" + Integer.toString(i))) slots.set(i - 1, params.getParam("item" + Integer.toString(i), "")); } vi.title = title; vi.size = size; vi.slots = slots; vi.execs = activators; menu.put(id, vi); save(); return true; } public static boolean remove(String id) { if (!menu.containsKey(id)) return false; menu.remove(id); return true; } public static List<String> getActivators(Param param) { if (param.isParamsExists("menu")) { String id = param.getParam("menu", ""); if (menu.containsKey(id)) return menu.get(id).getActivators(); } else { int size = param.getParam("size", 9); if (size > 0) { List<String> activators = new ArrayList<>(); for (int i = 1; i <= size; i++) activators.add(param.getParam("exec" + Integer.toString(i), "")); return activators; } } return new ArrayList<>(); } public static Inventory getInventory(Param param) { Inventory inv = null; if (param.isParamsExists("menu")) { String id = param.getParam("menu", ""); if (menu.containsKey(id)) inv = menu.get(id).getInventory(); } else { String title = param.getParam("title", "ReActions Menu"); int size = param.getParam("size", 9); if (size <= 0) return null; List<String> activators = new ArrayList<>(); inv = Bukkit.createInventory(null, size, title); for (int i = 1; i <= size; i++) { activators.add(param.getParam("exec" + Integer.toString(i), "")); String slotStr = "slot" + Integer.toString(i); if (!param.isParamsExists(slotStr)) continue; ItemStack slotItem = ItemUtil.parseItemStack(param.getParam(slotStr, "")); if (slotItem == null) continue; inv.setItem(i - 1, slotItem); } } return inv; } public static boolean createAndOpenInventory(Player player, Param params) { Inventory inv = getInventory(params); if (inv == null) return false; activeMenus.put(getInventoryCode(player, inv), getActivators(params)); openInventory(player, inv); return true; } public static void openInventory(final Player player, final Inventory inv) { Bukkit.getScheduler().runTaskLater(ReActions.instance, new Runnable() { @Override public void run() { if (player.isOnline()) player.openInventory(inv); else activeMenus.remove(getInventoryCode(player, inv)); } }, 1); } public static boolean isMenu(Inventory inventory) { return activeMenus.containsKey(getInventoryCode(inventory)); } public static void removeInventory(Inventory inv) { int code = getInventoryCode(inv); if (activeMenus.containsKey(code)) activeMenus.remove(code); } public static List<String> getActivators(Inventory inventory) { if (isMenu(inventory)) return activeMenus.get(getInventoryCode(inventory)); return new ArrayList<>(); } @EventHandler public void onInventoryClick(InventoryClickEvent event) { if (!InventoryMenu.isMenu(event.getInventory())) return; Player player = (Player) event.getWhoClicked(); int clickedSlot = event.getRawSlot(); if (clickedSlot < 0 || clickedSlot >= event.getInventory().getSize()) return; List<String> activators = getActivators(event.getInventory()); if (activators.size() > clickedSlot) { String activator = activators.get(clickedSlot); if (!activator.isEmpty()) { EventManager.raiseExecEvent(player, new Param(activator, "activator")); } } event.setCancelled(true); InventoryMenu.removeInventory(event.getInventory()); player.closeInventory(); } public static List<String> getEmptyList(int size) { List<String> l = new ArrayList<>(); for (int i = 0; i < size; i++) l.add(""); return l; } public static boolean exists(String id) { return menu.containsKey(id); } public static void printMenu(CommandSender sender, String id) { if (menu.containsKey(id)) { VirtualInventory vi = menu.get(id); M.printMSG(sender, "msg_menuinfotitle", 'e', '6', id, vi.size, vi.title); for (int i = 0; i < vi.size; i++) { String exec = vi.execs.get(i); String slot = vi.slots.get(i); if (exec.isEmpty() && slot.isEmpty()) continue; slot = itemToString(slot); M.printMSG(sender, "msg_menuinfoslot", i + 1, exec.isEmpty() ? "N/A" : exec, slot.isEmpty() ? "AIR" : slot); } } else M.printMSG(sender, "msg_menuidfail", id); } public static void printMenuList(CommandSender sender, int pageNum, String mask) { int linesPerPage = (sender instanceof Player) ? 15 : 10000; List<String> menuList = new ArrayList<>(); for (String id : menu.keySet()) { if (mask.isEmpty() || id.toLowerCase().contains(mask.toLowerCase())) { menuList.add(id + " : " + menu.get(id).title); } } M.printPage(sender, menuList, M.MSG_MENULIST, pageNum, linesPerPage); } public static String itemToString(String itemStr) { if (itemStr.isEmpty()) return "AIR"; ItemStack item = ItemUtil.parseItemStack(itemStr); if (item == null || item.getType() == Material.AIR) return "AIR"; String returnStr = item.hasItemMeta() && item.getItemMeta().hasDisplayName() ? item.getItemMeta().getDisplayName() : ""; String itemTypeData = item.getType().name() + (item.getDurability() == 0 ? "" : ":" + item.getDurability()) + (item.getAmount() == 1 ? "" : "*" + item.getAmount()); return ChatColor.stripColor(returnStr.isEmpty() ? itemTypeData : returnStr + "[" + itemTypeData + "]"); } public static int getInventoryCode(InventoryClickEvent event) { if (event.getViewers().size() != 1) return -1; HumanEntity human = event.getViewers().get(0); return getInventoryCode((Player) human, event.getInventory()); } public static int getInventoryCode(Inventory inv) { if (inv.getViewers().size() != 1) return -1; HumanEntity human = inv.getViewers().get(0); return getInventoryCode((Player) human, inv); } public static int getInventoryCode(Player player, Inventory inv) { if (player == null || inv == null) return -1; StringBuilder sb = new StringBuilder(); sb.append(player.getName()); sb.append(inv.getTitle()); for (ItemStack i : inv.getContents()) { String iStr = "emptyslot"; if (i != null && i.getType() != Material.AIR) { if (i.hasItemMeta()) { ItemMeta im = i.getItemMeta(); if (im.hasDisplayName()) sb.append(im.getDisplayName()); if (im.hasLore()) for (String str : im.getLore()) sb.append(str); } sb.append(i.getType().name()); sb.append(":"); sb.append(i.getDurability()); sb.append(":"); sb.append(i.getAmount()); } sb.append(iStr); } return sb.toString().hashCode(); } }