changing durability issues?

Discussion in 'Plugin Development' started by BeastyBoo, Sep 4, 2016.

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

    BeastyBoo

    Hello, as many of you know I earlier needed help with making a grapple plugin. Still thankful for that one. I've moved on to ItemStacks and want to name the Fishing_Rod Grapple Hook. So I made this:


    Code:
    public ItemStack createGrapplingHook(int uses) {
            Short g = 50;
            ItemStack Grapple = new ItemStack (Material.FISHING_ROD);
            ItemMeta GrappleMeta = Grapple.getItemMeta();
            Grapple.setDurability(g);
            GrappleMeta.setDisplayName(ChatColor.GOLD + "Grapple Hook");
            ArrayList<String> Grapple1 = new ArrayList<String>();
            Grapple1.add(ChatColor.GREEN + "Uses left: " + g);
            GrappleMeta.setLore(Grapple1);
            Grapple.setItemMeta(GrappleMeta);
            return Grapple;
          
        }
    I havent tested it yet, because I cant figure out how to give a player this itemstack on a command.

    Code:
    public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
            if (!(sender instanceof Player)) {
                sender.sendMessage("§cOnly players can use this command");
                return true;
            }
            if(label.equalsIgnoreCase("Grapple")) {
                Player p = (Player) sender;
                if (p.hasPermission("Grapple.Grapple")) {
                    p.getInventory().addItem(ItemStack(createGrapplingHook));
                } else {
                    p.sendMessage("§cYou dont have permission to use this command");
                }
            }
        }
    I cant use "createGrapplingHook" as the ItemStack. so, anyone know where I did wrong? And I'm not sure if I made the GrappleHook durability worked. Not that big on an issue as of now, but if someone could comment on that too that would be lovley.


    -------------------------EDIT-----------------------------

    I had a huge brain fart while making this, I forgot to do this instead:
    Code:
    p.getInventory().addItem(createGrapplingHook(50));
    Anyways, The Durability didnt work. I was trying to make it so for every use the durability went down. and it would be displayed in the lore how many uses left.

    any ideas?
     
    Last edited: Sep 4, 2016
  2. Offline

    Zombie_Striker

    @BeastyBoo
    1. Get the lore.
    2. Find the line that displays the durability
    3. Use Itemstack#getDurability to get the durability.
    4. Change that line to contain the new durability.
     
  3. Offline

    InstanceofDeath

    So you made, that the ItemStack gets the Lore one time with the current Durability, but it didnt get autoupdated ... is that correct?

    I would say, that you should use the PlayerInteractEvent, test if the player has the rod in his hand and then you just need to replace the Lore
     
  4. Offline

    BeastyBoo

    So if I use ItemMeta.setDurability(Short 50)
    Then wont it be 50? WHen I use the command to give myself this ItemStack I just get 14 dura Fishing_Rods. The Displayname and Lore works. It just wont countdown. Ive tried to look up but everyone have done the same as me?


    --------------------------------------EDIT-----------------------------------------
    I rememberd I could use the enums and make a switch statement to make it more organized:

    Code:
        public enum Items {
              Fishing_Rod
       
          }
      
        public ItemStack getCustomItem(Items item) {
              ItemStack is = null;
              ItemMeta im;
              ArrayList<String> lore;
              switch (item) {
              case Fishing_Rod:
                  is = new ItemStack(Material.FISHING_ROD, 1);
                  im = is.getItemMeta();
                  im.setDisplayName(ChatColor.GOLD + "Grapple Hook");
                  lore = new ArrayList<String>();
                  lore.add(ChatColor.GREEN + "Uses left: " + is.getDurability());
                  im.setLore(lore);
                  is.setItemMeta(im); 
               
              }
            return is;   
             
          }
    I Still dont understand how to add the new lore from the playerInteractEvent though
    Code:
    @EventHandler
        public void Check(PlayerInteractEvent e) {
            Player p = e.getPlayer();
           
            if(p.getItemInHand().equals(getCustomItem(Items.Fishing_Rod))) {
                short durability = getCustomItem(Items.Fishing_Rod).getDurability();
                int maximum = Material.FISHING_ROD.getMaxDurability() - 14;
                short result = (short) (durability - maximum);
                getCustomItem(Items.Fishing_Rod).setDurability(result);
               
            } else {
                return;
            }
        }
     
    Last edited: Sep 4, 2016
  5. Offline

    BeastyBoo

    Im sorry for double post but i have tried my best for the last 5 days and I cant figure it out. It most likly a small little line i have missed or something. My code is still the same as the post above..
     
  6. Offline

    Zombie_Striker

    This will almost never be true. This checks for if all values are the same, including durability. Check for material types and names.
    What is this meant to do? ......
    This line here sets the durability equal to the "result". Result is equal to the durability - the maximum.The thing is, this only allow for two clicks.

    Lets assume the fishing rod is at the maximum damage. For the first time result = 64-(64-14)=14. The second time, result = 14-(64-14)= -36.

    If you want to allow for a constant decrease of a value, I recommend using the following format.
    Code:
    float damagePerUse = PercentTakenAway/100 * Maximum value;
    //Example: If PTA is 33, this will have three uses. If you set it to 25, it will have four.
    setDamage(getDamage-damagePerUse);
     
  7. Offline

    BeastyBoo

    Will this work ?
    Code:
    if(p.getItemInHand().equals(Material.FISHING_ROD) && getCustomItem(Items.Fishing_Rod).getItemMeta().getDisplayName().equals(ChatColor.GOLD + "Grapple Hook")) {
    What do you mean with it only allow for two clicks?

    My InteractEvent, the dura didnt set. Should I set the dura inside the event or inside the ItemStack getCustomItems?
    Code:
    @EventHandler
        public void Check(PlayerInteractEvent e) {
            Player p = e.getPlayer();
           
           
           
            if(p.getItemInHand().equals(Material.FISHING_ROD) && getCustomItem(Items.Fishing_Rod).getItemMeta().getDisplayName().equals(ChatColor.GOLD + "Grapple Hook")) {
               
                short getDamage = 50;
                float damagePerUse = 1/64 * 50;
               
                getCustomItem(Items.Fishing_Rod).setDurability((short) (getDamage-damagePerUse));
            } else {
                return;
            }
        }
    My ItemStack:
    Code:
    public ItemStack getCustomItem(Items item) {
              ItemStack is = null;
              ItemMeta im;
              ArrayList<String> lore;
              switch (item) {
              case Fishing_Rod:
                  is = new ItemStack(Material.FISHING_ROD, 1);
                  im = is.getItemMeta();
                  im.setDisplayName(ChatColor.GOLD + "Grapple Hook");
                  lore = new ArrayList<String>();
                  lore.add(ChatColor.GREEN + "Uses left: " + is.getDurability());
                  im.setLore(lore);
                  is.setItemMeta(im);
                
              }
            return is;    
              
          }
     
  8. Offline

    Zombie_Striker

    @BeastyBoo
    Since you do not want the durability to be 64 (the actual durability), you will have to convert the numbers when changing durability.

    First, change this line:
    to:
    Since you want to have 50 durability.

    After this, use the following formula to get the next Displayed durability:
    Code:
     int displayUses = ACTUAL_DURABILITY / 64 * 50;
    When adding damage, add the following damage to the fishing rod
    Code:
    int damage = 1/64*50;
    ....setDurability(getDurability-damage+1);
    //REMEBER: ADD+1 TO CANCEL OUT THE DAMAGE THAT BASE MC ADDS
     
  9. Offline

    BeastyBoo

    Thanks, The last bit of code, What do you mean by "ADD". That I should add the durability?
    This is what I've made out of what you told me. Please tell me if anything is wrong:



    Code:
    @EventHandler
        public void Check(PlayerInteractEvent e) {
            Player p = e.getPlayer();
          
          
          
            if(p.getItemInHand().equals(Material.FISHING_ROD) && getCustomItem(Items.Fishing_Rod).getItemMeta().getDisplayName().equals(ChatColor.GOLD + "Grapple Hook")) {
              
                int damage = 1/64*50;
                getCustomItem(Items.Fishing_Rod).setDurability((short) (getCustomItem(Items.Fishing_Rod).getDurability()-damage+1));
                //REMEBER: ADD
              
            } else {
                return;
            }
        }
    Code:
    public ItemStack getCustomItem(Items item) {
            ItemStack is = null;
            ItemMeta im;
            ArrayList<String> lore;
            switch (item) {
            case Fishing_Rod:
                is = new ItemStack(Material.FISHING_ROD, 1);
                im = is.getItemMeta();
                im.setDisplayName(ChatColor.GOLD + "Grapple Hook");
                lore = new ArrayList<String>();
                lore.add(ChatColor.GREEN + "Uses left: 50");
                int displayUses = 64 / 64 * 50;
                lore.add(ChatColor.GREEN + "Uses left: " + displayUses);
                im.setLore(lore);
                is.setItemMeta(im);
                break;
            case Compass:
                is = new ItemStack(Material.COMPASS, 1);
                im = is.getItemMeta();
                im.setDisplayName(ChatColor.GOLD + "GUI");
                lore = new ArrayList<String>();
                lore.add(ChatColor.GREEN + "Click me to open the GUI");
                im.setLore(lore);
                is.setItemMeta(im);
                break;
            }
          return is;   
           
        }
     
  10. Offline

    Zombie_Striker

    @BeastyBoo
    That is correct. Whenever you cast a fishing rod, minecraft will automatically take 1 away from the durability (will subtract 1). What you want to do is add +1 so it cancels out the subtraction and add your own damage (which would be the 'damage').
     
  11. Offline

    BeastyBoo

    I didnt follow on the last part, im from norway and my english isnt the best, so sorry. Will this code work? I havent tested it yet because im not on my original pc. Im setting up a local server to test it on though. But will it work?

    Thanks for keeping up with me ;P I know Im nooby. this community is really good for beginners and pros.
     
  12. Offline

    Zombie_Striker

    @BeastyBoo
    Yes.
     
  13. Offline

    BeastyBoo

    I just tested it and unfortantly it didnt work. The lore was displayed twice, which I thought would happend and the durability or uses left didnt change. Any ideas? the code is the same as above.
     
  14. Offline

    Zombie_Striker

    The reason it does not work may be because you are not getting the existing durability, but instead the max durability.
    If you look at the bold part, that represents the Maximum value. This will never change. That means the durability will never change. Replace that line with

    Edit: The reason why the lore was displayed twice was because you added the line twice.
    Remove this from that method and only add this line when a player uses the fishing rod.
     
  15. Offline

    BeastyBoo

    Now it shows "Usesleft 0".
    and displayuses are unused.
    This is my code now:

    Code:
    ItemStack is = null;
            ItemMeta im;
            ArrayList<String> lore;
            switch (item) {
            case Fishing_Rod:
                is = new ItemStack(Material.FISHING_ROD, 1);
                im = is.getItemMeta();
                im.setDisplayName(ChatColor.GOLD + "Grapple Hook");
                lore = new ArrayList<String>();
                lore.add(ChatColor.GREEN + "Uses left: " + is.getDurability());
               
                im.setLore(lore);
                is.setItemMeta(im);
                break;
    Code:
    @EventHandler
        public void Check(PlayerInteractEvent e) {
            Player p = e.getPlayer();
          
          
          
            if(p.getItemInHand().equals(Material.FISHING_ROD) && getCustomItem(Items.Fishing_Rod).getItemMeta().getDisplayName().equals(ChatColor.GOLD + "Grapple Hook")) {
              
               
                ArrayList<String> lore;
                ItemMeta im = getCustomItem(Items.Fishing_Rod).getItemMeta();
                lore = new ArrayList<String>();
                int damage = 1/64*50;
                getCustomItem(Items.Fishing_Rod).setDurability((short) (p.getItemInHand().getDurability()-damage+1));
                int displayUses = 64 / 64 * 50;
                lore.add(ChatColor.GREEN + "Uses left: " + getCustomItem(Items.Fishing_Rod).getDurability());
              
            } else {
                return;
            }
        }
     
  16. Offline

    Zombie_Striker

    @BeastyBoo
    In the top bit of code, you are display the actual durability, not what should be displayed. Use the conversion method I provided to get the displayed uses.

    Here's your issue: I don't think you have any idea what you're actually doing. A lot of your code is incomplete, has a lot of redundant lines, and has a lot of code that should not work the way you want. Because of this, it seems you are struggling understanding what I am telling you to do.

    Because of this, I will provide the bit of code needed in order to properly display the uses. Please read the comments for each line to understand what I am doing.
    Code:
    @EventHandler
    public void Check(PlayerInteractEvent e) {
      Player p = e.getPlayer();
      if(p.getItemInHand() != null && p.getItemInHand().getType() == Material.FISHING_ROD &&  p.getItemInHand().getItemMeta().getDisplayName().equals(ChatColor.GOLD + "Grapple Hook")) {
    //The above is all the same
    
    //This changes the lore to "uses-1"
      Itemstack copy = DamageFishingRod( p.getItemInHand());
    
    //This gets the DISPLAYED durability and converts it into the actual durability.
      int durability = Integer.parseInt(p.getItemInHand().getItemMeta().getLore().get(0).split(":")[1]);
      copy.setDurability((short)(((double)durability)/50*64));
    
    //This resets the item in the player's hand.
      p.getInventory().setItemInHand(copy);
      }
     }
    
    public ItemStack DamageFishingRod(ItemStack is){
     //Setting values.
     ItemMeta im = is.getItemMeta();
     List<String> lore = new ArrayList<String>();
    
    //This gets the uses left and adds it to the lore
     int currentUses = (int)(((double)is.getDurability())/64*50);
     lore.add(0,"Uses Left:"+currentUses);
     im.setLore(lore);
     is.setItemMeta(im);
    
    //Returns the item stack.
     return is;
    }
     
  17. Offline

    BeastyBoo

    Hey thanks for understand my struggles. I did everything here and yet it still says usesleft 0.

    Code:
    public ItemStack DamageFishingRod(ItemStack is){
             is = new ItemStack(Material.FISHING_ROD, 1);
             ItemMeta im = is.getItemMeta();
             im.setDisplayName(ChatColor.GOLD + "Grapple Hook");
             List<String> lore = new ArrayList<String>();
    
            //This gets the uses left and adds it to the lore
             int currentUses = (int)(((double)is.getDurability())/64*50);
             lore.add(0,"Uses Left: "+ currentUses);
             im.setLore(lore);
             is.setItemMeta(im);
    
            //Returns the item stack.
             return is;
            }
    
    
    @EventHandler
        public void Check(PlayerInteractEvent e) {
            Player p = e.getPlayer();
        
        
        
            if(p.getItemInHand().equals(Material.FISHING_ROD) && DamageFishingRod(null).getItemMeta().getDisplayName().equals(ChatColor.GOLD + "Grapple Hook")) {
          
            
              //This changes the lore to "uses-1"
                ItemStack copy = DamageFishingRod( p.getItemInHand());
    
              //This gets the DISPLAYED durability and converts it into the actual durability.
                int durability = Integer.parseInt(p.getItemInHand().getItemMeta().getLore().get(0).split(":")[1]);
                copy.setDurability((short)(((double)durability)/50*64));
    
              //This resets the item in the player's hand.
                p.getInventory().setItemInHand(copy);
              
            } else {
                return;
            }
        }
    And in my boolean where I get the grapples uses the command "/grapple" I use this line, if that have anything to do with it:
    p.getInventory().addItem(DamageFishingRod(null));
     
    Last edited: Sep 11, 2016
  18. Offline

    Zombie_Striker

    Since the method does not expect null items, This line will break your plugin. Replace "null" with "new ItemStack(Material.FISHING_ROD)"

    If you click anywhere, the durability should equal 50. If not, debug what "currentUses" is equal to.
     
  19. Offline

    BeastyBoo

    I debugged it and in the consol it says that currentUses are equal to 0. this is how I debugged it incase i did it wrong :p.

    Code:
    public ItemStack DamageFishingRod(ItemStack is){
             is = new ItemStack(Material.FISHING_ROD, 1);
             ItemMeta im = is.getItemMeta();
             im.setDisplayName(ChatColor.GOLD + "Grapple Hook");
             List<String> lore = new ArrayList<String>();
    
            //This gets the uses left and adds it to the lore
             int currentUses = (int)(((double)is.getDurability())/64*50);
             lore.add(0, "Uses Left: "+ currentUses);
             System.out.println("currentUses: " + currentUses);
             im.setLore(lore);
             is.setItemMeta(im);
    
            //Returns the item stack.
             return is;
            }
     
  20. Offline

    Zombie_Striker

    @BeastyBoo
    1. Print out what durability is equal to.
    2. Print out what ((double)is.getDurability())/64 is equal to
    3. Print out what (int)((((double)is.getDurability())/64)*50)
    If #1 is equal to 0, then that means the durability is broken for the fishing rod.

    if#2 is equal to 0, but not #1, that means the double conversion is converting the durability to 0.

    if #3 is equal to 0, but #2 and #1 are not, then it may be the int conversion that is setting the durability to 0.

    Please, post what these values are equal to. After that, I will try to figure out a "workaround " for this issue.
     
  21. Offline

    BeastyBoo


    My consol. I get all the durability test when i use my command.
    Code:
    [22:50:32 INFO]: Thorbie issued server command: /grapple
    [22:50:32 INFO]: Durability 2: 0.0
    [22:50:32 INFO]: Durability 3: 0
    [22:50:32 INFO]: currentUses: 0
    [22:50:32 INFO]: Durability 2: 0.0
    [22:50:32 INFO]: Durability 3: 0
    [22:50:32 INFO]: currentUses: 0
    [22:50:32 INFO]: durability: 0
    Code:
    public ItemStack DamageFishingRod(ItemStack is){
             is = new ItemStack(Material.FISHING_ROD, 1);
             ItemMeta im = is.getItemMeta();
             im.setDisplayName(ChatColor.GOLD + "Grapple Hook");
             List<String> lore = new ArrayList<String>();
    
            //This gets the uses left and adds it to the lore
             int currentUses = (int)(((double)is.getDurability())/64*50);
       //Dura 2
             System.out.println("Durability 2: " + ((double)is.getDurability())/64);
      // Dura 3
             System.out.println("Durability 3: " + (int)((((double)is.getDurability())/64)*50));
             lore.add(0, "Uses Left: "+ currentUses);
             System.out.println("currentUses: " + currentUses);
             im.setLore(lore);
             is.setItemMeta(im);
    
            //Returns the item stack.
             return is;
            }
       
        public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
            if (!(sender instanceof Player)) {
                sender.sendMessage("§cOnly players can use this command");
                return true;
            }
            if(label.equalsIgnoreCase("Grapple")) {
                Player p = (Player) sender;
                if (p.hasPermission("Grapple.Grapple")) {
                    p.getInventory().addItem(DamageFishingRod(new ItemStack(Material.FISHING_ROD)));
                    //Durability 1
                    System.out.println("durability: " + DamageFishingRod(new ItemStack(Material.FISHING_ROD)).getDurability());
                } else {
                    p.sendMessage("§cYou dont have permission to use this command.");
                }
            }
            return false;
        }
       
        @EventHandler
        public void Check(PlayerInteractEvent e) {
            Player p = e.getPlayer();
         
         
         
            if(p.getItemInHand().equals(Material.FISHING_ROD) && DamageFishingRod(new ItemStack(Material.FISHING_ROD)).getItemMeta().getDisplayName().equals(ChatColor.GOLD + "Grapple Hook")) {
           
             
              //This changes the lore to "uses-1"
                ItemStack copy = DamageFishingRod( p.getItemInHand());
    
              //This gets the DISPLAYED durability and converts it into the actual durability.
                int durability = Integer.parseInt(p.getItemInHand().getItemMeta().getLore().get(0).split(":")[1]);
                copy.setDurability((short)(((double)durability)/50*64));
    
              //This resets the item in the player's hand.
                p.getInventory().setItemInHand(copy);
                System.out.println("currentUsesInter: " + copy.getDurability());
               
            } else {
                return;
            }
        }
     
  22. Offline

    ShaneCraftDev

    ItemStack#setDurability(0) fully restores the durability uses of an itemstack, all your equations return 0 because the durability of the newly created itemstack is 0, and we all know 0/x= 0. To set the durability you have to add instead of subtract. In other words, if an Item has 50 uses, but you wished it had 10, you'd have to set the durability to 40. From the top of my head, I am not sure if there is a method to fetch the maximum durability/uses of an itemstack/material.
     
    Zombie_Striker likes this.
  23. Offline

    BeastyBoo

    @Zombie_Striker

    Hey, Im starting to give up. I cant figure this out. I've spent maybe 20 hours the last 3 days reading oracles java tutorial and tutorialpoint over and over again. And the spigot docs. I just cant figure this out... I've tried everything I have learned and nothing seem to work. I've tried adding durability to the item when they recive it. I've tried adding it to the itemstack, but it just dont work... Any last ideas before I give up completly?
     
  24. Offline

    Zombie_Striker

    @BeastyBoo
    I just tested it, and it seems bukkit messed something up when they were making item durability. Now, durability acounts for the damage done to an object, not it's actual durability.

    To fix this issue, use this new method for convertting items durability below:
     
  25. Offline

    BeastyBoo

    Isnt that my old code? I just tested it. Only difference now is that it says Uses 50. It doesnt go down and the dura is still the default 64.
     
  26. Offline

    Zombie_Striker

    @BeastyBoo
    What if you try using the line below into the event for the durability
    Code:
    copy.setDurability(((short)64-(((double)durability)/50*64)));
    The issue was that '64-' was in the wrong place. This should now update the durability correctly.

    [edit] Also, it seems there was a missing double cast in the DamageFioshingRod method. Replace the "current uses" line with
    Code:
    int currentUses = (int)((((double)64)-((double)is.getDurability()))/64*50);
     
  27. Offline

    BeastyBoo

    Still doesnt update. I had to add another short cast into the first line you sent me to remove a redline.
    This is my code, where did I go wrong?
    Code:
    public ItemStack DamageFishingRod(ItemStack is){
            is = new ItemStack(Material.FISHING_ROD, 1);
            ItemMeta im = is.getItemMeta();
            im.setDisplayName(ChatColor.GOLD + "Grapple Hook");
            List<String> lore = new ArrayList<String>();
    
            //This gets the uses left and adds it to the lore
            int currentUses = (int)((((double)64)-((double)is.getDurability()))/64*50);
            lore.add(0, "Uses Left: "+ currentUses);
            System.out.println("currentUses: " + currentUses);
            im.setLore(lore);
            is.setItemMeta(im);
    
            //Returns the item stack.
            return is;
            }
    
            public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
            if (!(sender instanceof Player)) {
            sender.sendMessage("§cOnly players can use this command");
            return true;
            }
            if(label.equalsIgnoreCase("Grapple")) {
            Player p = (Player) sender;
            if (p.hasPermission("Grapple.Grapple")) {
            p.getInventory().addItem(DamageFishingRod(new ItemStack(Material.FISHING_ROD)));
            } else {
            p.sendMessage("§cYou dont have permission to use this command.");
            }
            }
            return false;
            }
    
            @EventHandler
            public void Check(PlayerInteractEvent e) {
            Player p = e.getPlayer();
    
    
    
            if(p.getItemInHand().equals(Material.FISHING_ROD) && p.getItemInHand().getItemMeta().getDisplayName().equals(ChatColor.GOLD + "Grapple Hook")) {
    
    
            ItemStack copy = DamageFishingRod( p.getItemInHand());
    
            //This gets the DISPLAYED durability and converts it into the actual durability.
            int durability = Integer.parseInt(p.getItemInHand().getItemMeta().getLore().get(0).split(":")[1]);
            copy.setDurability((short) ((short)64-(double)durability/50*64));
    
            //This resets the item in the player's hand.
            p.getInventory().setItemInHand(copy);
            System.out.println("currentUsesInter: " + copy.getDurability());
    
            } else {
            return;
            }
            }
     
  28. Offline

    Zombie_Striker

    @BeastyBoo
    Maybe you have to update the player's inventory after you set the item in hand. Add the following line after the "setItemInHand(copy)" line
    Code:
    p.updateInventory();
     
  29. Offline

    BeastyBoo

    @Zombie_Striker
    Still doesnt work :/

    Maybe i need to do something with PlayerItemDamageEvent? idk
     
  30. Offline

    ArsenArsen

    @BeastyBoo
    Try making a BukkitRunnable and invoking a runTask(plugin) on it so it runs a tick later.
     
Thread Status:
Not open for further replies.

Share This Page