Random Item display in Inventory

Discussion in 'Plugin Development' started by mmautzz, Feb 16, 2024.

Thread Status:
Not open for further replies.
  1. Offline

    mmautzz

    I coded two different java classes.
    In one the game picks a random Item from the config.yml, while in the other one, it creates an inventory with 9 Slots and puts an Iron Ore inside of it (placeholder). Now I want to combine those two by first picking a random item from the list in the config and then displaying it into the inventory when executing the command /bingo. The Inventory should be generated one time and is always the same when the player opens it. How do I do this?
    This is my code for now

    Code:
    package me.mmautzz.bingo;
    
    import java.util.List;
    import java.util.Random;
    
    import me.mmautzz.bingo.commands.BingoCommand;
    import me.mmautzz.bingo.commands.DoCommand;
    import me.mmautzz.bingo.commands.TestCommand;
    import me.mmautzz.bingo.listeners.BingoListener;
    import me.mmautzz.bingo.listeners.BlockListeners;
    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.Material;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.player.PlayerCommandSendEvent;
    import org.bukkit.inventory.Inventory;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.plugin.PluginManager;
    import org.bukkit.plugin.java.JavaPlugin;
    
    import java.util.List;
    
    public final class MinecraftBingo extends JavaPlugin implements Listener {
    
        @Override
        public void onEnable() {
            getCommand("test").setExecutor(new TestCommand());
            getCommand("do").setExecutor(new DoCommand());
            getCommand("bingo").setExecutor(new BingoCommand());
    
            PluginManager pluginManager = Bukkit.getPluginManager();
            pluginManager.registerEvents(new BlockListeners(), this);
            getServer().getPluginManager().registerEvents(new BingoListener(), this);
    
            loadconfig();
            this.getServer().getPluginManager().registerEvents(this, this);
        }
    
        private void loadconfig() {
            getConfig().options().copyDefaults(true);
            saveConfig();
        }
    
    
        private void setupbingo(Player player) {
            List<String> configitems = this.getConfig().getStringList("items");
    
            int index = new Random().nextInt(configitems.size());
            String items = configitems.get(index);
    
            ItemStack newItem = new ItemStack(Material.getMaterial(items.toUpperCase()));
    
        }
    
        @Override
        public void onDisable() {
            // Plugin shutdown logic
        }
    }
    ^ Code for choosing random item from the config.yml

    Code:
    package me.mmautzz.bingo.commands;
    
    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.event.Listener;
    import org.bukkit.inventory.Inventory;
    import org.bukkit.inventory.InventoryHolder;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.meta.ItemMeta;
    import org.bukkit.plugin.java.JavaPlugin;
    
    public class BingoCommand implements CommandExecutor{
        @Override
        public boolean onCommand(CommandSender commandSender, Command command, String s, String[] strings) {
    
            Player p = (Player) commandSender;
    
            Inventory inventory = Bukkit.createInventory(p, 9, ChatColor.LIGHT_PURPLE + "Bingo");
    
            ItemStack item = new ItemStack(Material.IRON_ORE, 1);
    
            inventory.addItem(item);
    
            p.openInventory(inventory);
    
            return false;
        }
    }
    
    ^ Code for creating an inventory, which the player can acces when executing /bingo

    I' new to java so pls help!
     
  2. Offline

    KarimAKL

    @mmautzz First, the 'setupbingo' method does not need the player parameter. It also needs to return the item. Currently, it's a void method (doesn't return a value) and you're just creating a local variable (a variable inside of a method) which is not being used.
    Second, you can use dependency injection, more specifically constructor injection, to get the item in the 'BingoCommand' class (pass the required arguments through the constructor). You can then create the inventory in the constructor and assign it to an instance variable (a non-static variable in the class scope) which you can later reference when the player uses the command to open the inventory.
     
  3. Offline

    mmautzz

    I don't really get it, but rn I'm also unable to fix this. I don't get how a constructor injection works either . I'm sorry
     
  4. Offline

    KarimAKL

    @mmautzz Why are you unable to fix it? Also, constructor injection works like the following:
    Code:Java
    1. // class A
    2. public class A {
    3. // Inside of some method
    4. public void someMethod() {
    5. // Create new instance of the B class and assign it to a local variable
    6. // We're passing the message "Hello world" through the constructor
    7. B b = new B("Hello world");
    8.  
    9. // Call the sendMessage method on the newly-created object
    10. b.sendMessage();
    11. }
    12. }
    13.  
    14. // class B
    15. public class B {
    16. // We declare a private instance variable
    17. private String message;
    18.  
    19. // Constructor method for class B
    20. // This has a parameter of type String
    21. public B(String message) {
    22. // We initialize the instance variable with the message passed through the constructor
    23. this.message = message;
    24. }
    25.  
    26. // Inside of some method
    27. public void sendMessage() {
    28. // We send the message contained in the instance variable to the standard output stream
    29. System.out.println(message);
    30. }
    31. }

    This is an example of dependency injection.
     
  5. Offline

    mmautzz

    It's because I'm not home for a few days but thanks
     
    Last edited: Feb 17, 2024
    KarimAKL likes this.
  6. Offline

    mmautzz

    So I figured it out, but how do I add 9 different items?
     
  7. Offline

    KarimAKL

    @mmautzz You would have to make a for-loop that loops 9 times, then pick a new random number in each iteration and get an item from that. Make sure the config you're getting the materials from actually contains 9 items in the list.
     
  8. Offline

    mmautzz

    I get the error null when performing the command ingame, this is my code:

    Code:
    package me.mmautzz.bingo.commands;
    
    import me.mmautzz.bingo.MinecraftBingo;
    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.event.Listener;
    import org.bukkit.inventory.Inventory;
    import org.bukkit.inventory.InventoryHolder;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.meta.ItemMeta;
    import org.bukkit.plugin.java.JavaPlugin;
    
    public class BingoCommand implements CommandExecutor {
        private final ItemStack[] bingoItems;
    
        public BingoCommand(ItemStack[] bingoItems) {
            this.bingoItems = bingoItems;
        }
    
        @Override
        public boolean onCommand(CommandSender commandSender, Command command, String s, String[] strings) {
            Player player = (Player) commandSender;
            ItemStack[] items = new MinecraftBingo().setupbingo();
    
            Inventory inventory = Bukkit.createInventory(player, 9, ChatColor.LIGHT_PURPLE + "Bingo");
    
            for (ItemStack item : items) {
                inventory.addItem(item);
            }
    
            player.openInventory(inventory);
    
            return true;
        }
    }
    
    Code:
    package me.mmautzz.bingo;
    
    import java.util.*;
    
    import me.mmautzz.bingo.commands.BingoCommand;
    import me.mmautzz.bingo.commands.DoCommand;
    import me.mmautzz.bingo.commands.TestCommand;
    import me.mmautzz.bingo.listeners.BingoListener;
    import me.mmautzz.bingo.listeners.BlockListeners;
    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.Material;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.player.PlayerCommandSendEvent;
    import org.bukkit.inventory.Inventory;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.plugin.PluginManager;
    import org.bukkit.plugin.java.JavaPlugin;
    
    import java.util.List;
    
    public final class MinecraftBingo extends JavaPlugin implements Listener {
    
        @Override
        public void onEnable() {
            getCommand("test").setExecutor(new TestCommand());
            getCommand("do").setExecutor(new DoCommand());
    
            ItemStack[] bingoItem = setupbingo();
            getCommand("bingo").setExecutor(new BingoCommand(bingoItem));
    
            PluginManager pluginManager = Bukkit.getPluginManager();
            pluginManager.registerEvents(new BlockListeners(), this);
            getServer().getPluginManager().registerEvents(new BingoListener(), this);
    
            loadconfig();
            this.getServer().getPluginManager().registerEvents(this, this);
        }
    
        private void loadconfig() {
            getConfig().options().copyDefaults(true);
            saveConfig();
        }
    
    
        public ItemStack[] setupbingo() {
    
            List<String> configItems = this.getConfig().getStringList("items");
            Set<String> selectedItems = new HashSet<>();
            Random random = new Random();
            ItemStack[] items = new ItemStack[9];
    
            for (int i = 0; i < 9; i++) {
                String itemName;
                do {
                    int index = random.nextInt(configItems.size());
                    itemName = configItems.get(index);
                } while (selectedItems.contains(itemName));
    
                selectedItems.add(itemName);
                items[i] = new ItemStack(Material.valueOf(itemName.toUpperCase()));
    
            }
    
            return items;
    
        }
    
    
    
    
        @Override
        public void onDisable() {
            // Plugin shutdown logic
        }
    }
    
     
  9. Online

    timtower Administrator Administrator Moderator

    @mmautzz
    new MinecraftBingo().setupbingo();
    That will not throw a null error, won't work either though
     
  10. Offline

    mmautzz

    I made it work, somehow....
    I save all the items in the config.yml, but I have to manually copy and paste them into the config... How can I make it so they're automatically there?

    It should look like this:

    items:
    - EXAMPLE_1
    - EXAMPLE_2
    - EXAMPLE_3
     
  11. Offline

    KarimAKL

    @mmautzz You can create a "config.yml" file in the same directory as your "plugin.yml" file, then use the saveDefaultConfig() method to copy the contents of that file into the data folder.
     
  12. Offline

    mmautzz

    Thanks, that worked!

    Now the last question and it will be completed. To check if the item has been received in the players inventory i can probably use a listener. But how can the listener understand if one item is completed (in the players inventory) when they were created with a loop, so they're all the same variable?

    Example:

    I get 9 Items in the inventory:
    1,2,3,4,5,6,7,8,9

    Now if I acquire item 2, it will display a green glass pain where the item 2 was placed in the Inventory. So the 2nd spot in the Bingo inventory will be a green glass pane because the player obtained it. Otherwise it stays item 2

    How do I accomplish that?
     
    Last edited: Feb 20, 2024
  13. Offline

    KarimAKL

    There is no event for a player receiving an item, but you'd be adding the item to their inventory yourself, so you can handle it when you do that.

    To accomplish that, you could save the item's slot whenever you select the item you want to give to the player.
    Assuming you want each player to be able to get the same item, you can map the player to a list of acquired slots.
    For example, the player got the item in slot 2, so you map the player (their UUID) to a list containing the number 2. Later, the player also acquired the item in slot 5, so you get the list of acquired slots and add 5 to the list. The player will now be mapped to a list containing the numbers 2 and 5.
    Whenever you open the inventory for that player, you will replace the items at those slots with green glass pane.
    If you want this data to persist through server restarts, you'll have to save it to the disk before the server shuts down, then load it upon startup.

    I hope this answers your question.
     
  14. Offline

    mmautzz

    I didnt mean receive, i meant... how do I check if the players inventory contains the item. Sry for the misunderstanding
     
  15. Offline

    KarimAKL

    @mmautzz No worries. The Inventory interface has the contains(ItemStack) method; you can use that to check if the player has the item. Additionally, if you want to check for a sum of items rather than a specific item stack, you can use the containsAtLeast(ItemStack, int) method. Read the description of each to determine which fits your use case.
     
Thread Status:
Not open for further replies.

Share This Page