Solved [Custome Inventory] Make lore Change while using the inventory

Discussion in 'Spigot Plugin Development' started by Sn0wFl4ke, Mar 16, 2020.

  1. Hello,
    I am pretty new to Plugin Programming and I currently work on a Plugin that uses Skills to Improve some stats.
    These can be leveled in a Inventory. I first made a small test with a int that changes its Value by time.
    Now i want that the Value also Changes in the Item Lore while the Inventory is open. Is that actually Possible or do i have to get another way ?
    Aditionaly: How does Player Exhaution Impact on Saturation in terms of Values ?

    Here is my current Code for the Inventory:
    Code (Java):
        @Override
        public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
            if (sender instanceof Player) {
                PlayerProperties valuestest = Main.PlayerS.get(sender);
                if (label.equalsIgnoreCase("sg")) {
                    if (args.length == 0) {
                        Inventory SkillInv = Bukkit.createInventory(null, 9 * x, "Skills");
                        createInvContent(Material.DIAMOND_ORE ,SkillInv,2,"TestName","test lore", String.valueOf(valuestest.SkillPonts));
                        ((Player) sender).openInventory(SkillInv);
                    }
                }

            }
            return false;
        }
    Code (Java):
        public void createInvContent(Material mat, Inventory inv, int Slot, String Name, String lore, String lore2){
            ItemStack item = new ItemStack(mat);
            ItemMeta meta = item.getItemMeta();
            meta.setDisplayName(Name);
            ArrayList<String> Lore = new ArrayList();
            Lore.add(lore);
            Lore.add("Points: " + lore2);
            Lore.add("test3");
            meta.setLore(Lore);
            item.setItemMeta(meta);
            inv.setItem(Slot, item);
        }
     
  2. I'm assuming that menu with skills is same for all the players if so you can create it once for example when the plugin starts, store it somewhere and the just update it after making changes to the items in the inventory. Players that currently have that inventory open should see changes after inventory is updated.
     
  3. @TheNesko its not really the same for everyone since the Lore is different for each Player depending how many Skillpoints the Player got left.

    //Edit:
    I kinda made it work like this:
    Code (Java):
        @Override
        public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
            if (sender instanceof Player) {
                PlayerProperties valuestest = Main.PlayerS.get(sender);
                if (label.equalsIgnoreCase("sg")) {
                    if (args.length == 0) {
                        Inventory SkillInv = Bukkit.createInventory(null, 9 * x, "Skills");
                        createInvContent(Material.DIAMOND_ORE ,SkillInv,2,"TestName","test lore", String.valueOf(valuestest.SkillPonts));
                        ((Player) sender).openInventory(SkillInv);

                        new BukkitRunnable() {
                            public void run() {
                                createInvContent(Material.DIAMOND_ORE ,SkillInv,2,"TestName","test lore", String.valueOf(valuestest.SkillPonts));//loop through the online players, get their helm, check if it isn't null, check if it has an itemmeta and lore, and then check the lore for your string and if so, give regen
                                ((Player) sender).updateInventory();
                            }
                        }.runTaskTimer(Main.getInstance(), 0L, 20L);
                    }
                }

            }
            return false;
        }
     
    In main
    Code (Text):
         public static Main instance;

        @Override
        public void onEnable() {
            SetupPlugin();
            instance = this;
    }

       public static Main getInstance(){
            return instance;
        }
    BUT: is there a way (Thats now really new to me) to get the PluginInstance without having a static funktion in the main class ? Also is there actually a better way to realise this in general ?
     
    #3 Sn0wFl4ke, Mar 16, 2020
    Last edited: Mar 16, 2020
  4. I would just create a new ItemStack and set all the MetaData as they were before but change the lore to whatever you want to. Then I would just set the new ItemStack on the slot where the old one was.
     
  5. @KonTux Yeah thats what i actually tried there. But now when i close the Inventory Ingame it reopens again xD but atleast it changes what it needs to change
     
  6. You could look into dependency injection for getting the main instance in a non static way. Here is a short example.

    As for your code you have a problem there and that is every time someone types that command you will run a new repeating task while the previous one is still running they will just pile up which is not the best practice.
     
    #6 TheNesko, Mar 16, 2020
    Last edited: Mar 16, 2020
    • Agree Agree x 1
  7. @TheNesko That was actually a Problem i managed to solve
    I just made it change on a Click Event now i only got to change the way the Items gets placed since i dont want to have 2 Functions for it but thats sth i might be able to figure out on my own. Might be realisable with a Hashmap or sth.

    The ClickEvent:
    Code (Java):
       @EventHandler
        public void SkillClickEvent(InventoryClickEvent e){
            Player player = (Player)e.getWhoClicked();
            Integer SlotClicked = e.getSlot();
            PlayerProperties valuestest = Main.PlayerS.get(player);
            Inventory inv = e.getInventory();
            InventoryView viewedonv = e.getView();
            if(viewedonv.getTitle().equals("Skills")){
                createInvContent(Material.DIAMOND_ORE, inv, 2, "TestName", "test lore", String.valueOf(valuestest.SkillPonts));
                player.updateInventory();
            }
        }

        public void createInvContent(Material mat, Inventory inv, int Slot, String Name, String lore, String lore2){
            ItemStack item = new ItemStack(mat);
            ItemMeta meta = item.getItemMeta();
            meta.setDisplayName(Name);
            ArrayList<String> Lore = new ArrayList();
            Lore.add(lore);
            Lore.add("Points Left: " + lore2);
            Lore.add("test3");
            meta.setLore(Lore);
            item.setItemMeta(meta);
            inv.setItem(Slot, item);
        }
    Code where Command gets Triggered:
    Code (Java):
        @Override
        public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
            if (sender instanceof Player) {
                PlayerProperties valuestest = Main.PlayerS.get(sender);
                if (label.equalsIgnoreCase("sg")) {
                    if (args.length == 0) {
                        Inventory SkillInv = Bukkit.createInventory(null, 9 * x, "Skills");
                        createInvContent(Material.DIAMOND_ORE, SkillInv, 2, "TestName", "test lore", String.valueOf(valuestest.SkillPonts));
                        ((Player) sender).openInventory(SkillInv);
                    }
                }

            }
            return false;
        }


        public void createInvContent(Material mat, Inventory inv, int Slot, String Name, String lore, String lore2){
            ItemStack item = new ItemStack(mat);
            ItemMeta meta = item.getItemMeta();
            meta.setDisplayName(Name);
            ArrayList<String> Lore = new ArrayList();
            Lore.add(lore);
            Lore.add("Points Left: " + lore2);
            Lore.add("test3");
            meta.setLore(Lore);
            item.setItemMeta(meta);
            inv.setItem(Slot, item);
        }
    //Update:
    Works now how it should added the createInvContent as private Method in the Player class and made it get called by this Method:
    Code (Java):
        public void UpdateInv(Inventory inv){
            createInvContent(Material.DIAMOND_ORE, inv, 2, "TestName", "test lore", String.valueOf(SkillPonts));
        }
    now it works Exactly how it should and is less Redundant.

    Thx for all your help guys learned alot right now ^^
     
    #7 Sn0wFl4ke, Mar 16, 2020
    Last edited: Mar 16, 2020