Need help with this Backpack plugin I made

Discussion in 'Plugin Development' started by shablombiiii, Apr 28, 2023.

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

    shablombiiii

    for some reason the items are being saved into the data.yml however when the player opens the gui after closing it the items are gone.

    I am still new to plugin dev so please lend a helping hand that I could under stand thank you.
    Best regards - shablombi

    P.S I would like to add a feature to where you cannot put the backpack into the backpack.
    here is a clip of the two problems I am encountering:
    https://youtu.be/0T98mYOprDA

    Code:
    package org.stick.ugh;
    
    import org.bukkit.Bukkit;
    import org.bukkit.Material;
    import org.bukkit.block.Block;
    import org.bukkit.block.ShulkerBox;
    import org.bukkit.configuration.file.FileConfiguration;
    import org.bukkit.configuration.file.YamlConfiguration;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.Action;
    import org.bukkit.event.inventory.InventoryClickEvent;
    import org.bukkit.event.inventory.InventoryCloseEvent;
    import org.bukkit.event.inventory.InventoryType;
    import org.bukkit.event.player.PlayerInteractEvent;
    import org.bukkit.inventory.Inventory;
    import org.bukkit.inventory.ItemStack;
    import org.jetbrains.annotations.NotNull;
    
    import java.io.File;
    import java.io.IOException;
    import java.io.StringReader;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import static org.bukkit.Bukkit.getServer;
    
    public class backpack implements Listener {
        private Inventory gui;
    
        Ugh plugin;
    
        public backpack(Ugh instance) {
            plugin = instance;
            dataFile = new File("plugins/Ugh", "data.yml");
            data = YamlConfiguration.loadConfiguration(dataFile);
    
        }
    
        private File dataFile;
        private YamlConfiguration data;
    
        public void update() {
            dataFile = new File(plugin.getDataFolder(), "data.yml");
            data = YamlConfiguration.loadConfiguration(dataFile);
        }
    
        @EventHandler
        public void onPlayerInteract(PlayerInteractEvent event) {
            Player player = event.getPlayer();
            if (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) {
                ItemStack itemInHand = player.getInventory().getItemInMainHand();
                if (itemInHand.getType() == Material.PLAYER_HEAD) {
                    if (event.getItem().getItemMeta().getDisplayName().equals("Backpack")) {
                        gui = Bukkit.createInventory(player, 9, "Backpack");
                        // player.openInventory(gui);
                        createGUI(player);
                        event.setCancelled(true);
                    }
                }
    
            }
        }
    
        private void createGUI(Player player) {
            Inventory inventory = getServer().createInventory(player, 9, "Backpack");
    
            // Load data from file
            List<Map<?, ?>> items = data.getMapList(player.getUniqueId().toString());
            if (items != null) {
                for (Map<?, ?> item : items) {
                    Integer slot = (Integer) item.get("slot");
                    ItemStack stack = (ItemStack) item.get("item");
                    if (slot != null && stack != null) {
                        inventory.setItem(slot, stack);
                    }
                }
            }
            player.openInventory(inventory);
        }
    
    
        private void saveInventory(Inventory inventory, String playerName) {
            FileConfiguration config = plugin.getConfig();
            List<Map<?, ?>> items = new ArrayList<>();
            ItemStack[] contents = inventory.getContents();
            for (int i = 0; i < contents.length; i++) {
                ItemStack item = contents[i];
                if (item != null && item.getType() != Material.AIR && item.getType() != null) { // Check if item and material are not null
                    Map<String, Object> map = new HashMap<>();
                    map.put("slot", i);
                    map.put("item", item);
                    items.add(map);
                }
            }
            config.set(playerName, items);
            plugin.saveConfig();
        }
    
        @EventHandler
        public void onInventoryClick(InventoryClickEvent event) {
            Player player = (Player) event.getWhoClicked();
            Inventory clickedInventory = event.getClickedInventory();
            ItemStack clickedItem = event.getCurrentItem();
    
            if (clickedInventory != null && clickedInventory.getHolder() instanceof Player && player.getOpenInventory().getTopInventory().equals(clickedInventory) && clickedItem != null) {
                // Save inventory when an item is clicked
                saveInventory(clickedInventory, player.getUniqueId().toString());
            }
        }
    
        @EventHandler
        public void onInventoryClose(InventoryCloseEvent event) {
            Player player = (Player) event.getPlayer();
            Inventory inventory = event.getInventory();
    
            if (inventory != null && inventory.getHolder() instanceof Player && player.getOpenInventory().getTopInventory().equals(inventory)) {
                // Save inventory when the GUI is closed
                saveInventory(inventory, player.getUniqueId().toString());
            }
        }
    }
     
    Last edited: Apr 28, 2023
  2. Offline

    mehboss

    Hello! Instead of saving the inventory items from the GUI every single time it is closed, I would simply hold an instance of the inventory and only save them to data.yml when the plugin is disabled. This will be more efficient for you and will save your server some stress from looping through multiple inventories every time a backpack is opened and closed.

    1. Create a hashmap<Player, Inventory>
    2. Add the entire inventory to it mapped with the player (hashmap#put(e.getPlayer(), inventory)
    3. Upon opening the inventory grab the hashmap#get(e.getPlayer()) which will return the entire inventory and its contents.
    4. onDisable loop through the hashmap and save the inventories to the data.yml
    5. onEnable load the inventories back into the hashmap.
    It would look something like this psuedo code here, which is only intended to give you an idea of how to do it, rather than copy and pasting.

    Code:
    import org.bukkit.entity.Player;
    import org.bukkit.inventory.Inventory;
    import org.bukkit.plugin.java.JavaPlugin;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class MyBackpackPlugin extends JavaPlugin {
    
        private Map<Player, Inventory> backpacks;
    
        @Override
        public void onEnable() {
            backpacks = new HashMap<>();
            // Register an event listener to handle inventory open and close events
            getServer().getPluginManager().registerEvents(new BackpackListener(), this);
            loadBackpacks();
        }
    
        @Override
        public void onDisable() {
            // Save the backpacks to data.yml or any other persistent storage
            saveBackpacks();
        }
    
        private void loadBackpacks() {
            // Load the backpacks from data.yml or any other persistent storage
        }
    
        private void saveBackpacks() {
            // Save the backpacks to data.yml or any other persistent storage
        }
    
        private class BackpackListener implements Listener {
    
            @EventHandler
            public void onInventoryOpen(InventoryOpenEvent event) {
                Player player = (Player) event.getPlayer();
                Inventory inventory = event.getInventory();
    
                // Check if the inventory is the player's own inventory and is not a backpack
                if (inventory.getType() == InventoryType.PLAYER && !backpacks.containsValue(inventory)) {
                    // Get the player's backpack inventory from the map, or create a new one if it doesn't exist
                    Inventory backpack = backpacks.getOrDefault(player, Bukkit.createInventory(player, 27, "Backpack"));
    
                    // Set the inventory for the event to the backpack inventory
                    event.setInventory(backpack);
    
                    // Put the backpack inventory into the map if it wasn't already there
                    backpacks.putIfAbsent(player, backpack);
                }
            }
    
            @EventHandler
            public void onInventoryClose(InventoryCloseEvent event) {
                Player player = (Player) event.getPlayer();
                Inventory inventory = event.getInventory();
    
                // Check if the inventory is a backpack
                if (backpacks.containsValue(inventory)) {
                    // Store the backpack inventory in the map
                    backpacks.put(player, inventory);
                }
            }
    
            @EventHandler
            public void onPlayerInteract(PlayerInteractEvent event) {
                Player player = event.getPlayer();
    
                // Check if the player right-clicked with an empty hand
                if (event.getAction() == Action.RIGHT_CLICK_AIR && player.getInventory().getItemInMainHand().getType() == Material.PLAYER_HEAD) {
                    // Get the player's backpack inventory from the map, or create a new one if it doesn't exist
                    Inventory backpack = backpacks.getOrDefault(player, Bukkit.createInventory(player, 27, "Backpack"));
    
                    // Set the player's open inventory to the backpack inventory
                    player.openInventory(backpack);
                }
            }
        }
    }
    As far as not allowing a backpack to be put inside a backpack, you would simply check if the item is being moved into a backpack inventory && if the item being moved IS a backpack. You can check out this thread here for more info on how to do it using InventoryDragEvent and InventoryClickEvent:

    https://www.spigotmc.org/threads/enderchest-item-blacklist.592939/#post-4550816

    This thread here shows the basic principles that should definitely point you in the correct direction as it did for me when I had a similar question.
     
    Last edited: Apr 28, 2023
    shablombiiii likes this.
  3. Offline

    shablombiiii




    Perfect this worked amazingly, however im having another issue that I just can seam to figure out. when I move the backpack within my inventory and then move it back to my hotbar and try to open it nothing happens, its almost like it turns into a player head again. please any help with this would be great!


    Here is a video of the issue:


    This is my main class code:

    Code:
    package org.stick.ugh;
    
    import org.bukkit.Bukkit;
    import org.bukkit.Material;
    import org.bukkit.block.Block;
    import org.bukkit.block.ShulkerBox;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.Action;
    import org.bukkit.event.player.PlayerInteractEvent;
    import org.bukkit.inventory.Inventory;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.plugin.Plugin;
    import org.bukkit.plugin.PluginManager;
    import org.bukkit.plugin.java.JavaPlugin;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public final class Ugh extends JavaPlugin {
        public static Plugin instance;
    
        private Map<Player, Inventory> backpacks = new HashMap<>();
    
        @Override
        public void onEnable() {
            instance = this;
    
            PluginManager pm = getServer().getPluginManager();
            pm.registerEvents(new InventorySaveLoad(this), this);
            pm.registerEvents(new backpack(this), this);
    
        }
    
        @Override
        public void onDisable() {
            // Plugin shutdown logic
        }
    
    }
    
    and this is my backpack code:


    Code:
    package org.stick.ugh;
    
    import org.bukkit.Bukkit;
    import org.bukkit.Material;
    import org.bukkit.block.Block;
    import org.bukkit.block.ShulkerBox;
    import org.bukkit.configuration.ConfigurationSection;
    import org.bukkit.configuration.file.FileConfiguration;
    import org.bukkit.configuration.file.YamlConfiguration;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.Action;
    import org.bukkit.event.inventory.InventoryClickEvent;
    import org.bukkit.event.inventory.InventoryCloseEvent;
    import org.bukkit.event.inventory.InventoryOpenEvent;
    import org.bukkit.event.inventory.InventoryType;
    import org.bukkit.event.player.PlayerInteractEvent;
    import org.bukkit.event.player.PlayerJoinEvent;
    import org.bukkit.event.player.PlayerQuitEvent;
    import org.bukkit.inventory.Inventory;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.meta.SkullMeta;
    import org.jetbrains.annotations.NotNull;
    
    import java.io.File;
    import java.io.IOException;
    import java.io.StringReader;
    import java.util.*;
    
    import static org.bukkit.Bukkit.getServer;
    
    public class backpack implements Listener {
        private Map<Player, Inventory> backpacks;
        private Inventory gui;
    
        Ugh plugin;
    
        public backpack(Ugh instance) {
            plugin = instance;
            dataFile = new File("plugins/Ugh", "data.yml");
            data = YamlConfiguration.loadConfiguration(dataFile);
            backpacks = new HashMap<>();
            // loads backpacks from data.yml
            loadbackpacks();
    
        }
    
        private void loadbackpacks() {
            FileConfiguration config = plugin.getConfig();
    
            if (!config.contains("Backpacks")) {
                return;
            }
    
            ConfigurationSection backpacksSection = config.getConfigurationSection("Backpacks");
            Set<String> backpackKeys = backpacksSection.getKeys(false);
    
            for (String backpackKey : backpackKeys) {
                ConfigurationSection backpackSection = backpacksSection.getConfigurationSection(backpackKey);
    
                Player player = Bukkit.getPlayerExact(backpackKey);
                if (player == null) {
                    continue;
                }
                List<?> itemList = backpackSection.getList("items");
                ItemStack[] items = new ItemStack[itemList.size()];
                for (int i = 0; i < itemList.size(); i++) {
                    Map<?, ?> map = (Map<?, ?>) itemList.get(i);
                    items[i] = ItemStack.deserialize((Map<String, Object>) map);
                }
                Inventory backpack = Bukkit.createInventory(player, 27, "Backpack");
                backpack.setContents(items);
                backpacks.put(player, backpack);
            }
        }
    
    
        private void savebackpacks() {
            if (backpacks == null || backpacks.isEmpty()) {
                return;
            }
            FileConfiguration config = plugin.getConfig();
            ConfigurationSection backpacksSection = config.createSection("Backpacks");
            for (Player uuid : backpacks.keySet()) {
                String uuidString = uuid.toString();
                backpacksSection.set(uuidString, backpacks.get(uuid));
            }
            plugin.saveConfig();
        }
    
    
        private File dataFile;
        private YamlConfiguration data;
    
        public void update() {
            dataFile = new File(plugin.getDataFolder(), "data.yml");
            data = YamlConfiguration.loadConfiguration(dataFile);
        }
    
        @EventHandler
        public void onPlayerInteract(PlayerInteractEvent event) {
            Player player = event.getPlayer();
            if (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) {
                ItemStack itemInHand = player.getInventory().getItemInMainHand();
                if (itemInHand.getType() == Material.PLAYER_HEAD && itemInHand.getItemMeta().getDisplayName().equals("Backpack")) {
                    // Check if the player right-clicked with an empty hand
    
                    // Get the player's backpack inventory from the map, or create a new one if it doesn't exist
                    if (player != null && backpacks != null) {
                        Inventory backpack = backpacks.getOrDefault(player, Bukkit.createInventory(player, 27, "Backpack"));
                        if (backpack.getType() != InventoryType.PLAYER) {
                            // Add or remove items from the backpack inventory
                            // ...
    
                            // Open the backpack inventory for the player
                            openBackpack(player);
                        }
                    }
    
                    // Set the player's open inventory to the backpack inventory
                    event.setCancelled(true);
                } else {
                    // Check if the player has a backpack item in their inventory
                    Inventory playerInventory = player.getInventory();
                    for (int i = 0; i < playerInventory.getSize(); i++) {
                        ItemStack itemInInventory = playerInventory.getItem(i);
                        if (itemInInventory != null && itemInInventory.getType() == Material.PLAYER_HEAD && itemInInventory.getItemMeta().getDisplayName().equals("Backpack")) {
                            // Get the player's backpack inventory from the map, or create a new one if it doesn't exist
                            if (player != null && backpacks != null) {
                                Inventory backpack = backpacks.getOrDefault(player, Bukkit.createInventory(player, 27, "Backpack"));
                                if (backpack.getType() != InventoryType.PLAYER) {
                                    // Add or remove items from the backpack inventory
                                    // ...
    
                                    // Open the backpack inventory for the player
                                    openBackpack(player);
                                }
                            }
    
                            // Set the player's open inventory to the backpack inventory
                            event.setCancelled(true);
                            break;
                        }
                    }
                }
            }
        }
    
        private ItemStack createBackpack() {
            ItemStack backpack = new ItemStack(Material.PLAYER_HEAD);
            SkullMeta meta = (SkullMeta) backpack.getItemMeta();
            meta.setOwningPlayer(Bukkit.getOfflinePlayer(UUID.fromString("8667ba71-b85a-4004-af54-457a9734eed7"))); // set the texture to the backpack texture
            meta.setDisplayName("Backpack");
            meta.setLore(Arrays.asList("A convenient way to carry extra items!"));
            backpack.setItemMeta(meta);
            return backpack;
        }
    
    
        // Open the backpack inventory
        public void openBackpack(Player player) {
            Inventory backpack = backpacks.getOrDefault(player, Bukkit.createInventory(player, 27, "Backpack"));
    
            // Add an inventory click listener to update the backpacks map
            plugin.getServer().getPluginManager().registerEvents(new InventoryClickEventListener(player, backpack, backpacks), plugin);
    
            player.openInventory(backpack);
        }
    
    
    
        private void createGUI(Player player) {
            Inventory inventory = getServer().createInventory(player, 27, "Backpack");
    
            // Load data from file
            List<Map<?, ?>> items = data.getMapList(player.getUniqueId().toString());
            if (items != null) {
                for (Map<?, ?> item : items) {
                    Integer slot = (Integer) item.get("slot");
                    ItemStack stack = (ItemStack) item.get("item");
                    if (slot != null && stack != null) {
                        inventory.setItem(slot, stack);
                    }
                }
            }
            player.openInventory(inventory);
        }
    
    
        private void saveInventory(Inventory inventory, String playerName) {
            FileConfiguration config = plugin.getConfig();
            List<Map<?, ?>> items = new ArrayList<>();
            ItemStack[] contents = inventory.getContents();
            for (int i = 0; i < contents.length; i++) {
                ItemStack item = contents[i];
                if (item != null && item.getType() != Material.AIR && item.getType() != null) { // Check if item and material are not null
                    Map<String, Object> map = new HashMap<>();
                    map.put("slot", i);
                    map.put("item", item);
                    items.add(map);
                }
            }
            config.set(playerName, items);
            plugin.saveConfig();
        }
    
    
        @EventHandler
        public void onInventoryClick(InventoryClickEvent event) {
            Player player = (Player) event.getWhoClicked();
            Inventory clickedInventory = event.getClickedInventory();
            ItemStack clickedItem = event.getCurrentItem();
    
            if (clickedInventory != null && clickedInventory.getHolder() instanceof Player && player.getOpenInventory().getTopInventory().equals(clickedInventory) && clickedItem != null) {
                // Save inventory when an item is clicked
                saveInventory(clickedInventory, player.getUniqueId().toString());
            }
        }
    
    
        @EventHandler
        public void onInventoryClose(InventoryCloseEvent event) {
            Player player = (Player) event.getPlayer();
            Inventory inventory = event.getInventory();
    
            if (inventory != null && inventory.getHolder() instanceof Player && player.getOpenInventory().getTopInventory().equals(inventory)) {
                saveInventory(inventory, player.getUniqueId().toString());
                backpacks.put(player, inventory);
            }
        }
    
        @EventHandler
        public void onInventoryOpen(InventoryOpenEvent event) {
            Player player = (Player) event.getPlayer();
            Inventory inventory = event.getInventory();
    
            // Initialize the backpacks map if it is null
            if (backpacks == null) {
                backpacks = new HashMap<>();
            }
    
            // Check if the inventory is the player's own inventory and is not a backpack
    
            if (player.getInventory().getItemInMainHand().getType() == Material.AIR) {
                // Get the player's backpack inventory from the map, or create a new one if it doesn't exist
                Inventory backpack = backpacks.getOrDefault(player, Bukkit.createInventory(player, 27, "Backpack"));
    
                // Debug statement to verify that items are being added to the backpack inventory
                // player.sendMessage("Added item to backpack: " + player.getInventory().getItemInMainHand().getType().name());
    
                // Add the item to the backpack inventory
                backpack.addItem(player.getInventory().getItemInMainHand());
    
                // Update the backpack inventory in the map
                backpacks.put(player, backpack);
            }
    
        }
    }

     
    Last edited: May 1, 2023
  4. Offline

    mehboss

    Well, what have you done to try and solve the issue? Have you ran any debug code to see what is stopping the code?
     
Thread Status:
Not open for further replies.

Share This Page