Search code examples
javaminecraftspigot

How to open an Inventory with an Item inside an Inventory


By just writing the code in one class and the write:

case "example":
     player.openInventory(exampleInv);
     break;
   

But because I like my things organized and well sorted I wrote the Inventory inside another class as the Inventory Click Event.

Here is the class with the InvClickEvent:

package de.t0x1ccr34t0r.charactertrails.listeners;

import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;

public class InventoryListener implements Listener{

    @EventHandler
    public void onInvClick(InventoryClickEvent event) {
        if(event.getCurrentItem() == null) return;
        if(event.getView().getTitle() == "§5Trails:"){
            Player player = (Player) event.getWhoClicked();
            event.setCancelled(true);
            if(event.getCurrentItem().getItemMeta().hasLocalizedName()) {
                switch (event.getCurrentItem().getItemMeta().getLocalizedName()) {
                    case "Close":
                        player.closeInventory();
                        break;
                    case "Copper":
                        player.closeInventory();
                        break;
                    case "Iron":
                        player.closeInventory();
                        break;
                    case "Gold":
                        player.closeInventory();
                        break;
                    case "Diamond":
                        player.closeInventory();
                        break;
                    case "Emerald":
                        player.closeInventory();
                        break;
                }
            }
        }
    }
}

it all says player.closeinventory() because the player.openInventory() doesn't work yet and with that I need help. I made several classes like the copper_Inventory which I show you here:

package de.t0x1ccr34t0r.charactertrails.inventories;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;

import java.util.ArrayList;

public class Copper_Inventory implements CommandExecutor {

    @Override
    public boolean onCommand(CommandSender sender1, Command cmd1, String s1, String[] strings1) {
        if(!(sender1 instanceof Player)) return false;
        Player player1 = (Player) sender1;

        Inventory copperInventory = Bukkit.createInventory(null , 4 * 9 , "§5Copper Trails:");

        ItemStack ia = new ItemStack(Material.BARRIER);
        ItemMeta ma = ia.getItemMeta();
        ma.setLocalizedName("Close");
        ma.setDisplayName("§cClose");
        ia.setItemMeta(ma);
        copperInventory.setItem(31 , ia);

        ItemStack ib = new ItemStack(Material.ARROW);
        ItemMeta mb = ib.getItemMeta();
        mb.setLocalizedName("Back");
        mb.setDisplayName("§7Back");
        ib.setItemMeta(mb);
        copperInventory.setItem(27 , ib);

        player1.openInventory(copperInventory);

        return false;
    }
}

So that code actually works. But only with an command in-game. In the end, I want something like this:

case "copper":
     player.openInventory(copperInventory);
     break;
   

But this obviously doesn't work of course, because the program cant find "copperInventory".

I use the word copper in case "copper": from another class which looks like this and this already works:

package de.t0x1ccr34t0r.charactertrails.inventories;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;

import java.util.ArrayList;

public class Main_Inventory implements CommandExecutor {
    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        if(!(sender instanceof Player)) return false;
        Player player = (Player) sender;

        Inventory mainInventory = Bukkit.createInventory(null , 3 * 9 , "§5Trails:");

        ItemStack i1 = new ItemStack(Material.COPPER_INGOT);
        ItemMeta m1 = i1.getItemMeta();
        m1.setLocalizedName("Copper");
        m1.setDisplayName(ChatColor.WHITE + "example");
        i1.setItemMeta(m1);
        mainInventory.setItem(11 , i1);

        player.openInventory(mainInventory);

        return false;
    }
}

So my question is now: How do I do define the variable "copperInventory" from public class Copper_Inventory inside the "case "copper": in public class InventoryListener.

Also, I don't know if that is important, you may see these classes are not in the same package. I made multiple subpackages to keep everything smooth.

So in the end, my code should look like this:

case "copper":
     player.openInventory(copperInventory);
     break;

But I just don't know how to do this whilst having the variables inside other classes.

Could you help me with that?


Solution

  • The issue comes because the variable is out of your actual scope. It have been create in another method, and now the variable by itself isn't accessible.

    If you want to keep the same inventory (not specially recommended), you can put into an HashMap<>() and get it after. Exemple:

    
    public class Copper_Inventory implements CommandExecutor {
    
        public static final HashMap<Player, Inventory> INVENTORIES = new HashMap<>();
    
        @Override
        public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
            if(!(sender instanceof Player)) return false;
            Player player = (Player) sender;
    
            Inventory copperInventory = Bukkit.createInventory(null , 4 * 9 , "§5Copper 
    Trails:");
            // fill inventory
            player.openInventory(copperInventory);
            INVENTORIES.put(player, copperInventory);
        }
    }
    

    Then, when closing inventory, use: player.openInventort(Copper_Inventory.INVENTORIES.get(player)).

    But, the most recommended way is not this one.

    You can simply re-open a new one

    You can create a new class which can be like that:

    public class Inventories {
    
        public static Inventory createCopperInventory(Player p) {
            Inventory copperInventory = Bukkit.createInventory(null , 4 * 9 , "§5Copper 
    Trails:");
            // fill inventory
            return copperInventory;
        }
    }
    

    And then, each time use player.openInventory(Inventories.createCopperInventory(player)).