Hello Spigot Community! I have an issue with InventoryActions in InventoryClickEvent, I'm trying to make a custom Anvil with a GUI, but the problem is how can I verify the recipe is correct by the InventoryClickEvent like the plugin AdvancedCraftingTable. My code: Spoiler: Code Code (Java): package me.RandomSurvival.Listeners; import me.RandomSurvival.MClass; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockState; import org.bukkit.block.Skull; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryAction; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.scheduler.BukkitRunnable; import java.util.HashMap; import java.util.Map; import java.util.UUID; import static me.RandomSurvival.Utils.chatManager.Chat; public class AnvilRecipeListener implements Listener { private Map<UUID, Inventory> inventories = new HashMap(); private boolean renameBoolean = false; private String rename = ""; @EventHandler public void onJoin(PlayerJoinEvent event) { Player player = event.getPlayer(); inventories.put(player.getUniqueId(), customAnvil(player)); } @EventHandler(priority = EventPriority.HIGHEST) public void interactEvent(PlayerInteractEvent event) { if (event.getClickedBlock() == null) return; Player player = event.getPlayer(); Block block = event.getClickedBlock(); if (block.getType().equals(Material.PLAYER_HEAD)) { BlockState state = block.getState(); Skull skull = (Skull) state; if (skull.getOwner().equalsIgnoreCase("fin95")) { player.openInventory(inventories.get(player.getUniqueId())); } } } @EventHandler public void clickInventory(InventoryClickEvent event) { Player player = (Player) event.getWhoClicked(); InventoryView inv = event.getView(); if (inv.getTitle().equals(Chat("&b&lRandom &e&lAnvil"))) { Inventory inventory = inventories.get(player.getUniqueId()); if (event.getCurrentItem() == null || event.getCurrentItem().getType() == Material.AIR) return; ItemStack itemClicked = event.getCurrentItem(); Material itemType = itemClicked.getType(); if (itemType.equals(Material.BLACK_STAINED_GLASS_PANE) || itemType.equals(Material.LIME_STAINED_GLASS_PANE))event.setCancelled(true); InventoryAction action = event.getAction(); /*new BukkitRunnable() { @Override public void run() { Player player = (Player) event.getWhoClicked(); if (event.getView().getTitle().equals(Chat("&b&lRandom &e&lYAnvil"))) { try { checkRecipes(player); } catch (NullPointerException e) { e.printStackTrace(); } } } }.runTask(MClass.plugin);*/ ///////// //RENAME if (event.getSlot() == 18 && itemClicked.getType().equals(Material.NAME_TAG)) { event.setCancelled(true); player.closeInventory(); player.sendMessage(Chat("&aSet a name for your item...", true)); this.renameBoolean = true; } /////// //GET RESULT if (event.getSlot() == 15 && itemClicked != null) { inventory.clear(11); inventory.clear(13); new BukkitRunnable() { @Override public void run() { player.updateInventory(); } }.runTask(MClass.plugin); } } } @EventHandler public void setRename(AsyncPlayerChatEvent event) { Player player = event.getPlayer(); if (this.renameBoolean == true) { this.rename = event.getMessage(); player.sendMessage(Chat("&aSaved Name! &f" + this.rename, true)); this.renameBoolean = false; event.setCancelled(true); if (this.rename != null) { Inventory inv = inventories.get(player.getUniqueId()); ItemStack item = inv.getItem(18); ItemMeta itemMeta = item.getItemMeta(); itemMeta.setDisplayName(Chat("&bRename &7= &f" + this.rename)); item.setItemMeta(itemMeta); } } } public void checkRecipes(Player player) { Inventory inventory = inventories.get(player.getUniqueId()); ItemStack item1 = inventory.getItem(11); ItemStack item2 = inventory.getItem(13); if (item2.getType().equals(Material.CYAN_DYE)) { if (item1 == null) return; ItemStack itemR = item1.clone(); ItemMeta itemMeta = itemR.getItemMeta(); itemMeta.setDisplayName(Chat("&b" + this.rename)); itemR.setItemMeta(itemMeta); inventory.setItem(15, itemR); } else return; player.updateInventory(); } public Inventory customAnvil(Player player) { Inventory customAnvil = Bukkit.createInventory(player, 27, Chat("&b&lRandom &e&lAnvil")); for (int i = 0; i <= 26; i++) { if ((i == 14)) { ItemStack glassG = new ItemStack(Material.LIME_STAINED_GLASS_PANE); ItemMeta glassGMeta = glassG.getItemMeta(); glassGMeta.setDisplayName(Chat("&a&n->")); glassG.setItemMeta(glassGMeta); customAnvil.setItem(i, glassG); } else if ((i == 18)) { ItemStack nametag = new ItemStack(Material.NAME_TAG); ItemMeta nametagMeta = nametag.getItemMeta(); nametagMeta.setDisplayName(Chat("&bRename")); nametag.setItemMeta(nametagMeta); customAnvil.setItem(i, nametag); } else if ((i == 11) || (i == 13) || (i == 15)) { ItemStack air = new ItemStack(Material.AIR); customAnvil.setItem(i, air); } else { ItemStack glass = new ItemStack(Material.BLACK_STAINED_GLASS_PANE); ItemMeta glassMeta = glass.getItemMeta(); glassMeta.setDisplayName(""); glass.setItemMeta(glassMeta); customAnvil.setItem(i, glass); } } return customAnvil; } }
You will have a lot of problems when multiple people use your custom anvil GUI. The will rename each others items. private boolean renameBoolean = false; private String rename = ""; those are defined in the wrong scope. However... In order to implement custom recipes with two items that should be combined (or a item with a matrix) i would create a new abstract class CustomAnvilRecipe. with a method that takes (ItemStack, ItemStack) and returns a boolean. Like this: Then you just need some classes that implement your custom recipe and manage them a bit like this: Then you get the two items from the InventoryClickEvent call customAnvilRecipeHandler.getRecipeForInput(left, right); check if optional.isPresent(); optional.get().getResult(left, right); remove items left and right; set the output slot with the getResult() item. There are easier ways but this one is clean, pretty fast (you could implement interesting hash methods and use those) and very modular.
I'll try thanks bro. It's really useful, and the problem with the private boolean I'll already now that, I was thinking to saved into a hashmap, but I like your idea. But this doesn't fix my problem with the result, I need to make it appear into the GUI when you put the items into the slots. Something needs to detect that the recipe is correct.