Search code examples
javabukkit

How do I call a InventoryClickEvent in a boolean?


I first created the inventory that will be opened:

private void openGUI(Player player) {
    Inventory inv = Bukkit.createInventory(null, 9, ChatColor.DARK_RED + "[" + ChatColor.DARK_GREEN + "DuelRequest" + ChatColor.DARK_RED + "]");

    ItemStack accept = new ItemStack(Material.EMERALD_BLOCK);
    ItemMeta acceptMeta = accept.getItemMeta();

    ItemStack decline = new ItemStack(Material.REDSTONE_BLOCK);
    ItemMeta declineMeta = decline.getItemMeta();

    acceptMeta.setDisplayName(ChatColor.GREEN + "Accept!");
    accept.setItemMeta(acceptMeta);

    declineMeta.setDisplayName(ChatColor.RED + "Decline!");
    decline.setItemMeta(declineMeta);

    inv.setItem(3, accept);
    inv.setItem(5, decline);

    player.openInventory(inv);
}

Then I created the command that will be run:

if (cmd.getName().equalsIgnoreCase("duel")) {
        if (!(args.length == 1)) {
            sender.sendMessage(ChatColor.DARK_RED + "[" + ChatColor.DARK_GREEN + "HuntsCraft" + ChatColor.DARK_RED + "]" + ChatColor.RED + " Usage: /duel <Player>");
            return true;
        } else if (args.length == 1) {

            Player p = Bukkit.getServer().getPlayer(args[0]);
            if (p != null) {
                if (p.equals(sender)) {
                    sender.sendMessage(ChatColor.DARK_RED + "[" + ChatColor.DARK_GREEN + "HuntsCraft" + ChatColor.DARK_RED + "]" + ChatColor.RED + " You cannot duel yourself!");
                    return true;
                } else {
                    sender.sendMessage(ChatColor.DARK_RED + "[" + ChatColor.DARK_GREEN + "HuntsCraft" + ChatColor.DARK_RED + "]" + ChatColor.GREEN + " You sent a duel request to " + ChatColor.BLUE + p.getName());
                    p.sendMessage(ChatColor.DARK_RED + "[" + ChatColor.DARK_GREEN + "HuntsCraft" + ChatColor.DARK_RED + "]" + ChatColor.GREEN + " You recieved a duel request from " + ChatColor.BLUE + sender.getName());
                    openGUI(p);
                }
            }
        } else {
            sender.sendMessage(ChatColor.DARK_RED + "[" + ChatColor.DARK_GREEN + "HuntsCraft" + ChatColor.DARK_RED + "]" + ChatColor.RED + " Player not found!");
        }
    }
    return true;

I Then created an event that is called when a players clicks their inventory.

@SuppressWarnings("deprecation")
@EventHandler
private void onClick(InventoryClickEvent e) {

    if (!ChatColor.stripColor(e.getInventory().getName()).equalsIgnoreCase("[DuelRequest]"))
        return;

    Player player = (Player) e.getWhoClicked();
    e.setCancelled(true);

    switch (e.getCurrentItem().getType()) {
    case EMERALD_BLOCK:
        player.closeInventory();
        player.sendMessage(ChatColor.DARK_RED + "[" + ChatColor.DARK_GREEN + "HuntsCraft" + ChatColor.DARK_RED + "]" + ChatColor.GREEN + " You accepted the request");
        player.getInventory().setItem(0, new ItemStack(Material.DIAMOND_SWORD));
        player.getInventory().setItem(1, new ItemStack(Material.BOW));
        player.getInventory().setItem(2, new ItemStack(Material.GOLDEN_APPLE, 2));
        player.getInventory().setItem(3, new ItemStack(Material.ARROW, 32));
        player.getInventory().setHelmet(new ItemStack(Material.DIAMOND_HELMET));
        player.getInventory().setChestplate(new ItemStack(Material.DIAMOND_CHESTPLATE));
        player.getInventory().setLeggings(new ItemStack(Material.DIAMOND_LEGGINGS));
        player.getInventory().setBoots(new ItemStack(Material.DIAMOND_BOOTS));
        break;
    case REDSTONE_BLOCK:
        player.closeInventory();
        player.sendMessage(ChatColor.DARK_RED + "[" + ChatColor.DARK_GREEN + "HuntsCraft" + ChatColor.DARK_RED + "]" + ChatColor.RED + " You denied the request!");
        break;
    default:
        player.closeInventory();
        break;
    }
}

So, what i want to happen is..

When a player types /duel , the (target) will have an inventory opened in front of them with an option to accept or decline the duel request. I have tested this and it works as expected. If they decline they will receive a message telling them they rejected it, if they accept they will be given a Kit to duel with. This also works as expected. However, i need to be able to give the sender of the /duel command the same kit, but i don't know how to. So... When the (target) accepts the duel, both players will receive a kit so they can both fight.

Is there a way of calling for the onClick event inside the onCommand? Or is there a way to contact the sender of the command from inside the onClick event?

I am average with Bukkit coding but obviously still have a lot to learn so any help/constructive criticism is always helpful!


Solution

  • You could use a HashMap, to store the player that sent the duel request to a player:

    Map<UUID, UUID> duels = new HashMap<UUID, UUID>();
    

    HashMaps are used to store a value for another value, it's effectively a large collection of variables.

    When the sender runs the command, you could use:

    duels.put(target.getUniqueId(), sender.getUniqueId());
    

    So, when the target accepts the duel, you could get the sender of the request with:

    duels.get(target.getUniqueId());
    

    Here's what your onCommand() could look like:

    if (cmd.getName().equalsIgnoreCase("duel")) {
        if (!(args.length == 1)) {
            sender.sendMessage(ChatColor.DARK_RED + "[" + ChatColor.DARK_GREEN + "HuntsCraft" + ChatColor.DARK_RED + "]" + ChatColor.RED + " Usage: /duel <Player>");
            return true;
        } else if (args.length == 1) {
    
            Player p = Bukkit.getServer().getPlayer(args[0]);
            if (p != null) {
                if (p.equals(sender)) {
                    sender.sendMessage(ChatColor.DARK_RED + "[" + ChatColor.DARK_GREEN + "HuntsCraft" + ChatColor.DARK_RED + "]" + ChatColor.RED + " You cannot duel yourself!");
                    return true;
                } else {
                    sender.sendMessage(ChatColor.DARK_RED + "[" + ChatColor.DARK_GREEN + "HuntsCraft" + ChatColor.DARK_RED + "]" + ChatColor.GREEN + " You sent a duel request to " + ChatColor.BLUE + p.getName());
                    p.sendMessage(ChatColor.DARK_RED + "[" + ChatColor.DARK_GREEN + "HuntsCraft" + ChatColor.DARK_RED + "]" + ChatColor.GREEN + " You recieved a duel request from " + ChatColor.BLUE + sender.getName());
                    openGUI(p);
    
                    //Put the player in the HashMap here
                    duels.put(p.getUniqueId(), ((Player) sender).getUniqueId());
                }
            }
        } else {
            sender.sendMessage(ChatColor.DARK_RED + "[" + ChatColor.DARK_GREEN + "HuntsCraft" + ChatColor.DARK_RED + "]" + ChatColor.RED + " Player not found!");
        }
    }
    return true;
    

    And your onClick() could look like this:

    @SuppressWarnings("deprecation")
    @EventHandler
    //It's better if you make your events public
    //and not private
    public void onClick(InventoryClickEvent e) {
    
    if (!ChatColor.stripColor(e.getInventory().getName()).equalsIgnoreCase("[DuelRequest]"))
        return;
    
    Player player = (Player) e.getWhoClicked();
    e.setCancelled(true);
    
    //get the UUID stored in the duels HashMap for the player's UUID as a key
    UUID uuid = duels.get(player.getUniqueId());
    
    //Get the challenger from the UUID above
    Player challenger = Bukkit.getPlayer(uuid);
    
    switch (e.getCurrentItem().getType()) {
    case EMERALD_BLOCK:
        player.closeInventory();
        player.sendMessage(ChatColor.DARK_RED + "[" + ChatColor.DARK_GREEN + "HuntsCraft" + ChatColor.DARK_RED + "]" + ChatColor.GREEN + " You accepted the request");
        player.getInventory().setItem(0, new ItemStack(Material.DIAMOND_SWORD));
        player.getInventory().setItem(1, new ItemStack(Material.BOW));
        player.getInventory().setItem(2, new ItemStack(Material.GOLDEN_APPLE, 2));
        player.getInventory().setItem(3, new ItemStack(Material.ARROW, 32));
        player.getInventory().setHelmet(new ItemStack(Material.DIAMOND_HELMET));
        player.getInventory().setChestplate(new ItemStack(Material.DIAMOND_CHESTPLATE));
        player.getInventory().setLeggings(new ItemStack(Material.DIAMOND_LEGGINGS));
        player.getInventory().setBoots(new ItemStack(Material.DIAMOND_BOOTS));
    
        //give the kit to the challenger here
        //Maybe make a method, giveKit(Player p), to clean up your code
        //Then you could run giveKit(challenger) and giveKit(player)
        break;
    case REDSTONE_BLOCK:
        player.closeInventory();
        player.sendMessage(ChatColor.DARK_RED + "[" + ChatColor.DARK_GREEN + "HuntsCraft" + ChatColor.DARK_RED + "]" + ChatColor.RED + " You denied the request!");
    
    
        //tell the challenger that player denied their duel request
        challenger.sendMessage(ChatColor.DARK_RED + "[" + ChatColor.DARK_GREEN + "HuntsCraft" + ChatColor.DARK_RED + "]" + ChatColor.RED + player.getName + " denied your duel request");
        break;
    default:
        player.closeInventory();
        break;
    }
    }
    

    If you wanted to check if a UUID exists in the HashMap, you could use duels.containsKey(uuid)

    Make sure to never store Player objects inside of HashMaps, because it can cause memory leaks if the player leaves the server, for instance. The best way to store player information is by storing their UUID, or by storing their username.