Inventory holders can be used to register own types, handlers and data to a opened GUI for a player.
To start, we need to create our menu class that implemetns InventoryHolder and any other functions we may want. For this example, we are gonna fill the inventory and open it for player, then save the player for later ussage with our handler.
It will look something like this
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
public class MyMenu implements InventoryHolder {
private Inventory inventory = Bukkit.createInventory(this, 6 * 9, "My menu");
private Player target;
public MyMenu(Player player) {
//set the player, for later used
this.target = player;
//fill it with one stone
inventory.setItem(4, new ItemStack(Material.STONE, 1));
//open the menu
player.openInventory(inventory);
}
public Boolean trigger(ItemStack itemStack) {
//check if the clicked item is stone
if (itemStack.getType() == Material.STONE) {
target.sendMessage("No, you may not steal my fancy stone. It is my only friend.");
//cancel the event
return true;
}
//dont cancel the event
return false;
}
@Override
public Inventory getInventory() {
return this.inventory;
}
}
Then, to handle it We use the bukkit event like normal, but this time we check if it is an instance of our menu, and cast/call it if this is the case.
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
public class MyListener implements Listener {
@EventHandler
public void onInventoryClick(InventoryClickEvent event) {
//filter out bad events
if (event.getInventory() == null
|| event.getCurrentItem() == null) return;
//check if the inventory is an instance of our menu
if (event.getInventory().getHolder() instanceof MyMenu) {
//call teh function and hold its state
Boolean cancel = ((MyMenu) event.getInventory().getHolder()).trigger(event.getCurrentItem());
//set the event cancelled based on the return state
event.setCancelled(cancel);
}
}
}
To open the menu and register the handler, all we have to do is
new MyMenu(Bukkit.getPlayer("Mindgamesnl");
And that's all, we now have
- a menu that builds itself
- a menu that is linked to a player
- one lister that handles our menu like a callback function
- a simpler and cleaner inventory system
- a stone block in our gui, that the player cannot interact of based on our handler
That's all folks