Save and load a GUI to the config

Discussion in 'Plugin Development' started by Teotia444, Jan 11, 2022.

  1. Offline

    Teotia444

    Hello,
    I am currently making a plugin for our SMP. The goal would be to share enderchests. I managed to do the system where you chose with who you share the ender chest but not the saving stuff. I use a different GUI for the enderchest as it's 54 blocks. So I here is my code :
    For the onEnderChestOpen
    Code:
    package com.teotia444.customsmp.events;
    
    import com.teotia444.customsmp.CustomSMP;
    import com.teotia444.customsmp.inventories.SharedEC;
    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.Material;
    import org.bukkit.Sound;
    import org.bukkit.entity.HumanEntity;
    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.*;
    import org.bukkit.event.player.PlayerInteractEvent;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.scheduler.BukkitRunnable;
    
    import java.util.List;
    
    public class EnderChestOpenEvent implements Listener{
    
        static CustomSMP plugin;
    
        public EnderChestOpenEvent(CustomSMP plugin){
            this.plugin = plugin;
        }
    
        @EventHandler
        public static void onEnderChestOpened(PlayerInteractEvent event){
            Player player = event.getPlayer();
            String root = plugin.getConfig().getString("ec.team." + player.getName());
            SharedEC ec = new SharedEC(plugin, root);
            if(event.getAction() == Action.RIGHT_CLICK_BLOCK && event.getClickedBlock().getType() == Material.ENDER_CHEST){
                new BukkitRunnable() {
                    @Override
                    public void run() {
                        player.closeInventory();
                        player.playSound(player.getLocation(), Sound.BLOCK_ANVIL_LAND, 1, 1);
                    }
                }.runTaskLater(plugin, 1);
                new BukkitRunnable() {
                    @Override
                    public void run() {
                        player.openInventory(ec.getInventory());
                    }
                }.runTaskLater(plugin, 1);
            }
        }
        @EventHandler
        public static void onEnderChestClosed(InventoryCloseEvent event){
            new BukkitRunnable(){
                @Override
                public void run() {
                        Player player = (Player) event.getView().getPlayer();
                        String root = plugin.getConfig().getString("ec.team." + player.getName()); //root is the team name of the player
                        if(event.getView().getTitle().equals("Shared Ender Chest")){ //saving the gui in config here
                        }}
            }.runTaskLaterAsynchronously(plugin, 2);
        }
    }
    
    
    and here is the enderchest gui code :
    Code:
    package com.teotia444.customsmp.inventories;
    
    import com.teotia444.customsmp.CustomSMP;
    import org.bukkit.Bukkit;
    import org.bukkit.inventory.Inventory;
    import org.bukkit.inventory.InventoryHolder;
    import org.bukkit.inventory.ItemStack;
    
    import java.util.*;
    
    
    public class SharedEC implements InventoryHolder {
    
        private Inventory ec;
    
        public SharedEC(CustomSMP plugin, String team){
            ec = Bukkit.createInventory(this, 54, "Shared Ender Chest");
            setEc(plugin, team);
        }
    
        public SharedEC(){
            ec = Bukkit.createInventory(this, 54, "Shared Ender Chest");
        }
    
        public void setEc(CustomSMP plugin, String root){
    // here would be the load by config stuff
        }
    
    
        @Override
        public Inventory getInventory() {
            return ec;
        }
    }
    
    I would want an idea on how I can do it, on even maybe some code showing how to do it.
    Thank you
     
  2. Offline

    The_Spaceman

    Code:java
    1. //to save inventory content
    2. getConfig().set(path + ".content", inventory.getContents());
    3.  
    4. //this is an implementation to get the content I've used a long time ago (should still work)
    5. private Inventory getInventory(String path) {
    6. Inventory inv = Bukkit.createInventory(null, 18, NAME);
    7.  
    8. if (!getConfig().contains(path)) {
    9. return inv;
    10. }
    11.  
    12. List<?> content = getConfig().getList(path + ".content");
    13. if (content != null) {
    14. for (int i = 0; i < content.size(); i++) {
    15. Object o = content.get(i);
    16. if (o != null) {
    17. if (o instanceof ItemStack item) {
    18. inv.setItem(i, item);
    19. }
    20. }
    21. }
    22. }
    23. return inv;
    24. }


    Its better to cancel the PlayerInteractEvent than using the Runnables. Something like this:
    Code:java
    1. @EventHandler
    2. public static void onEnderChestOpened(PlayerInteractEvent event) {
    3. Player player = event.getPlayer();
    4. if(event.getAction() == Action.RIGHT_CLICK_BLOCK && event.getClickedBlock().getType() == Material.ENDER_CHEST) {
    5. Inventory inv = Bukkit.createInventory(null, 54, "Shared Ender Chest");
    6. inv.addItem(new ItemStack(Material.STONE));
    7.  
    8. player.playSound(player.getLocation(), Sound.BLOCK_ANVIL_LAND, 1, 1);
    9. player.openInventory(inv);
    10. event.setCancelled(true);
    11. }
    12. }
    13.  
     
  3. Offline

    Teotia444

    Thanks for the advice. It really helped me out. I still have problems to load : First time I load it's loading correctly but then the content list is null. This happens whenever I save using the GUI, and then re-open it
    Any advice?
    thanks
     
  4. Offline

    The_Spaceman

    at the end do you use 'saveConfig()'? If not, try that. Otherwise I don't know why its set to null.
    Can you post what you have?
     
  5. Offline

    Teotia444

    Ok, then here is in detail what I did : When I open the ender chest, it shows correctly the chest and it's content. Then I pick up some stuff, get off of the chest (where it saves AND use saveConfig) and try to re-open it I got this error :
    Code:
    [14:41:12] [Server thread/ERROR]: Could not pass event PlayerInteractEvent to CustomSMP v0.1
    java.lang.NullPointerException: Cannot invoke "java.util.List.size()" because "content" is null
        at com.teotia444.customsmp.events.EnderChestOpenEvent.getInventory(EnderChestOpenEvent.java:65) ~[CustomSMP.jar:?]
        at com.teotia444.customsmp.events.EnderChestOpenEvent.onEnderChestOpened(EnderChestOpenEvent.java:39) ~[CustomSMP.jar:?]
        at com.destroystokyo.paper.event.executor.StaticMethodHandleEventExecutor.execute(StaticMethodHandleEventExecutor.java:38) ~[paper-api-1.18.1-R0.1-SNAPSHOT.jar:?]
        at co.aikar.timings.TimedEventExecutor.execute(TimedEventExecutor.java:80) ~[paper-api-1.18.1-R0.1-SNAPSHOT.jar:git-Paper-140]
        at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:70) ~[paper-api-1.18.1-R0.1-SNAPSHOT.jar:?]
        at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:628) ~[paper-api-1.18.1-R0.1-SNAPSHOT.jar:?]
        at org.bukkit.craftbukkit.v1_18_R1.event.CraftEventFactory.callPlayerInteractEvent(CraftEventFactory.java:543) ~[paper-1.18.1.jar:git-Paper-140]
        at net.minecraft.server.level.ServerPlayerGameMode.useItemOn(ServerPlayerGameMode.java:540) ~[?:?]
        at net.minecraft.server.network.ServerGamePacketListenerImpl.handleUseItemOn(ServerGamePacketListenerImpl.java:1838) ~[?:?]
        at net.minecraft.network.protocol.game.ServerboundUseItemOnPacket.handle(ServerboundUseItemOnPacket.java:33) ~[?:?]
        at net.minecraft.network.protocol.game.ServerboundUseItemOnPacket.a(ServerboundUseItemOnPacket.java:9) ~[?:?]
        at net.minecraft.network.protocol.PacketUtils.lambda$ensureRunningOnSameThread$1(PacketUtils.java:56) ~[?:?]
        at net.minecraft.server.TickTask.run(TickTask.java:18) ~[paper-1.18.1.jar:git-Paper-140]
        at net.minecraft.util.thread.BlockableEventLoop.doRunTask(BlockableEventLoop.java:149) ~[?:?]
        at net.minecraft.util.thread.ReentrantBlockableEventLoop.doRunTask(ReentrantBlockableEventLoop.java:23) ~[?:?]
        at net.minecraft.server.MinecraftServer.doRunTask(MinecraftServer.java:1413) ~[paper-1.18.1.jar:git-Paper-140]
        at net.minecraft.server.MinecraftServer.c(MinecraftServer.java:189) ~[paper-1.18.1.jar:git-Paper-140]
        at net.minecraft.util.thread.BlockableEventLoop.pollTask(BlockableEventLoop.java:122) ~[?:?]
        at net.minecraft.server.MinecraftServer.pollTaskInternal(MinecraftServer.java:1391) ~[paper-1.18.1.jar:git-Paper-140]
        at net.minecraft.server.MinecraftServer.pollTask(MinecraftServer.java:1384) ~[paper-1.18.1.jar:git-Paper-140]
        at net.minecraft.util.thread.BlockableEventLoop.managedBlock(BlockableEventLoop.java:132) ~[?:?]
        at net.minecraft.server.MinecraftServer.waitUntilNextTick(MinecraftServer.java:1362) ~[paper-1.18.1.jar:git-Paper-140]
        at net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:1268) ~[paper-1.18.1.jar:git-Paper-140]
        at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:317) ~[paper-1.18.1.jar:git-Paper-140]
        at java.lang.Thread.run(Thread.java:833) ~[?:?]
    along with the regular ender chesr, and for the code :
    Code:
    package com.teotia444.customsmp.events;
    
    import com.teotia444.customsmp.CustomSMP;
    import com.teotia444.customsmp.inventories.SharedEC;
    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.Material;
    import org.bukkit.Sound;
    import org.bukkit.entity.HumanEntity;
    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.*;
    import org.bukkit.event.player.PlayerInteractEvent;
    import org.bukkit.inventory.Inventory;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.scheduler.BukkitRunnable;
    
    import java.util.List;
    import java.util.Objects;
    
    public class EnderChestOpenEvent implements Listener{
    
        static CustomSMP plugin;
    
        public EnderChestOpenEvent(CustomSMP plugin){
            this.plugin = plugin;
        }
    
        @EventHandler
        public static void onEnderChestOpened(PlayerInteractEvent event){
            Player player = event.getPlayer();
    
            if(event.getAction() == Action.RIGHT_CLICK_BLOCK && event.getClickedBlock().getType() == Material.ENDER_CHEST){
                String root = plugin.getConfig().getString("ec.team." + player.getName());
    
                player.playSound(player.getLocation(), Sound.BLOCK_ENDER_CHEST_OPEN, 1, 1);
                Inventory inv = getInventory("ec." + root);
    
                player.openInventory(inv);
                event.setCancelled(true);
            }
        }
        @EventHandler
        public static void onEnderChestClosed(InventoryCloseEvent event){
            Player player = (Player) event.getView().getPlayer();
            String root = plugin.getConfig().getString("ec.team." + player.getName());
            if(event.getView().getTitle().equals("Shared Ender Chest")){
                plugin.getConfig().set("ec."+ root + ".content", event.getInventory().getContents());
                plugin.saveConfig();
                player.playSound(player.getLocation(), Sound.BLOCK_ENDER_CHEST_CLOSE, 1, 1);
            }
        }
    
        private static Inventory getInventory(String path) {
            plugin.getServer().getConsoleSender().sendMessage(path);
            Inventory inv = Bukkit.createInventory(null, 54, "Shared Ender Chest");
    
            if (!plugin.getConfig().contains(path)) {
                return inv;
            }
    
            List<?> content = plugin.getConfig().getList(path + ".content");
            if (content != null) {
                for (int i = 0; i < content.size(); i++) {
                    Object o = content.get(i);
                    if (o != null) {
                        if (o instanceof ItemStack item) {
                            inv.setItem(i, item);
                        }
                    }
                }
            }
            return inv;
        }
    }
    
    
    I tried to tweak some things with no success...
    Thanks for the help
     
  6. Offline

    The_Spaceman

    That's weird.
    You get a NullPointerException after you check if that object is not null. You sure this error log is from this code?
     

Share This Page