getDurability() the Same as data ?

Discussion in 'Plugin Development' started by Jacek, Aug 22, 2011.

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

    Jacek

    So I am a little confused here, ItemStacks have a getDurability() method. but when you create a new ItemStack you pass the damage value to the constructor.

    Does the getDurability() method return the damage ? Or something else ?

    I'm asking because I am working on a plugin that is basically the same as MultiInv (for practice not release really before you moan about people cloning plugins) and people can heal their tools by loading a new inventory.
     
  2. Offline

    bergerkiller

    No. getData() only returns a single byte and does not contain anything related to durability. I believe the Data is used internally and should not be accessed from the outside, although I never looked into getData() before.

    Also, there is a getState().getData() to return the material data from a block. They could be related.
     
  3. Offline

    Jacek

    Isn't data used to identify stuff like the type of wool ?

    So if I store the getDurability() result and then pass that to a new ItemStack() as the damage parameter, home come all the tools and stuff get renewed :s
     
  4. Offline

    CptSausage

    Yes that confuses me as well. My plugin saves the data (itemStack.getData() !! But care, it can return null) and sets the data again (itemStack.setData(new MaterialData( int, byte))). But to be honest, I don't even know why. :/

    If you have a look into the 'original' ItemStack getData() does return the damage?!

    Code:
    public int getData() {
        return this.damage;
    }
     
  5. Offline

    bergerkiller

    Guess it is time for some net.minecraft.server browsing. ;)

    EDIT

    Ok, in native code I found these variables for ItemStack:
    Code:
        public int count;
        public int b;
        public int id;
        public int damage; // CraftBukkit - private -> public
    There is count, id and b/damage. B must be the data, yet damage is also an int. Let's see the usage.

    EDIT

    B is never stored, in other words, it is temporary. Definitely NOT the sub-id:
    Code:
        public NBTTagCompound a(NBTTagCompound nbttagcompound) {
            nbttagcompound.a("id", (short) this.id);
            nbttagcompound.a("Count", (byte) this.count);
            nbttagcompound.a("Damage", (short) this.damage);
            return nbttagcompound;
        }
     
  6. Offline

    Jacek

    Yeah I already ran into it returning null ;)

    So if the MaterialData contains what ever it is that gives a item a health bar, how do you store that in a file ?

    Also, where do you get the int and byte from that you pass to the MaterialData() ?

    Finally, edited 8 times :eek:

    Hmm, this is getting more confusing, now damage and data are both ints but the bukkit methods return short and byte :s

    this is how I am storing the items currently

    Code:
    public class PerWorldInventoriesInventoryItem implements Serializable {
    
        private static final long serialVersionUID = 7454354939402953958L;
    
        public int itemType;
        public int itemAmount;
        public short itemDamage;
        public byte itemData;
    
        public void fromItemStack(ItemStack item){
            if (item != null){
                this.itemType = item.getTypeId();
                this.itemAmount = item.getAmount();
                this.itemDamage = item.getDurability();
    
                if (item.getData() != null){
                    this.itemData = item.getData().getData();
                }
            }
        }
    
        public ItemStack toItemStack(){
            return new ItemStack(this.itemType, this.itemAmount, this.itemDamage, this.itemData);
        }
    
    }
    getData().getData() seemed odd to me, but it returns the correct type ;)

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 18, 2016
  7. Offline

    bergerkiller

    Final. GitHub link
    Code:
        /**
    * Gets the MaterialData for this stack of items
    *
    * @return MaterialData for this item
    */
        public MaterialData getData() {
            if (Material.getMaterial(getTypeId()).getData() != null) {
                data = Material.getMaterial(getTypeId()).getNewData((byte) this.durability);
            }
    
            return data;
        }
    
        /**
    * Sets the MaterialData for this stack of items
    *
    * @param amount New MaterialData for this item
    */
        public void setData(MaterialData data) {
            Material mat = getType();
    
            if ((mat == null) || (mat.getData() == null)) {
                this.data = data;
            } else {
                if ((data.getClass() == mat.getData()) || (data.getClass() == MaterialData.class)) {
                    this.data = data;
                } else {
                    throw new IllegalArgumentException("Provided data is not of type " + mat.getData().getName() + ", found " + data.getClass().getName());
                }
            }
        }
    getData() is a shortening of the material (id) and durability (damage) members. Simply the same.

    But why is it a byte there and MaterialData here...weird.
     
  8. Offline

    Jacek

    So the problem I am seeing is because I am setting the same thing twice ? When I set the damage is it then reset by setting the data ?
     
  9. Offline

    CptSausage

    For blocks yes, but in the inventory as well? :/

    Code:
    location.getBlock().setData(DyeColor.WHITE.getData());
    // Here the .setData needs 'byte'
    
    ItemStack[] contents = player.getInventory().getContents();
    contents[0].setData(DyeColor.WHITE.getData());
    // But that doesn't work, because .setData requires 'Material Data'
    
    Haha yes... now 10 times. Don't know I you saw it. The forum did some crazy stuff.


    EDIT: Damn I'm so slow. Need to read your last posts.
     
  10. Offline

    bergerkiller

    Any chance getData() as byte is simply the durability cast as a byte?
     
  11. Offline

    Jacek

    As cool as this forum software is, it seems a little buggy in placed. Paste a huge chunk of code, then press enter under the [ /CODE] tag, code all dissapears.

    I guess they could be the same thing.

    Either way, removing the data getting / setting seemed to fix the durability issue. :D

    The way the durability is sometimes called the damage really does not help ;)
     
  12. Offline

    Afforess

    It's called durability, but it's not always. For instance, if you get the durability of a partially used pickaxe, it should be a large number, > max byte, but if you get the durability of a stack of red wool, it will be the same data value as the block of red wool.

    Essentially, items can not have damage AND data values at the same time. I guess notch was trying to save mem, but this seems a poor design choice.
     
  13. Offline

    Jacek

    Okay that makes sense (sort of). So in the context of my code above for saving an inventory slot, do I need to do anything with the data ?
     
  14. Offline

    CptSausage

    I guess that's it. :( so I'm saving more data than I need to in my plugin :(
    Thought they can have both, data and dura.

    Code:
    Player player = (Player) sender;
            ItemStack[] contents = player.getInventory().getContents();
            sender.sendMessage("ID: " + contents[0].getTypeId());
            sender.sendMessage("Dura: " + contents[0].getDurability());
            if (contents[0].getData() != null) {
                sender.sendMessage("Item ID: " + contents[0].getData().getItemTypeId());
                sender.sendMessage("Data: " + contents[0].getData().getData());
            } else {
                sender.sendMessage("Is null");
            }
    ID and Dura are always the same as Item ID and Data, as long the MaterialData != null. :(

    @Jacek Looks like you don't have to save it. If want to do it, here are my saving / reloading methods:
    Show Spoiler

    Code:
        public String itemStackToString(ItemStack[] itemStacks) {
            //(final int type, final int amount, final short damage, final Byte data)
            String invString = "";
            for (ItemStack itemStack : itemStacks) {
                if (itemStack != null) {
                    invString = invString
                            + ";" + itemStack.getTypeId()
                            + ":" + itemStack.getAmount()
                            + ":" + itemStack.getDurability();
                    if (itemStack.getData() == null) {
                        invString = invString + ":null";
                    } else {
                        invString = invString
                                //+ "IDZ" + itemStack.getData().getItemTypeId() Das gleiche wie itemStack.getTypeId() s.o.
                                + ":" + itemStack.getData().getData();
                    }
    
                } else {
                    invString = invString + ";" + "null";
                }
            }
            return invString;
        }
    
        /**
         * Converts a String, storing a inventory, into an ItemStack[]
         *
         * @param Inventory as String
         * @return ItemStack[]
         */
        public ItemStack[] stringToItemStack(String invString) {
            //(final int type, final int amount, final short damage, final Byte data)
    
            String[] firstSplit = invString.split("\\;");
            ItemStack[] itemStack = new ItemStack[firstSplit.length - 1];
    
            for (int i = 0; i < (firstSplit.length - 1); i++) {
                if (!firstSplit[i + 1].equals("null")) {
                    String[] secondSplit = firstSplit[i + 1].split("\\:"); //+1, because lenght = 37 and [0] = ""
                    itemStack[i] = new ItemStack(
                            Integer.valueOf(secondSplit[0]),
                            Integer.valueOf(secondSplit[1]),
                            Short.valueOf(secondSplit[2]));
                    if (!secondSplit[3].equals("null")) {
                        itemStack[i].setData(new MaterialData(
                                Integer.valueOf(secondSplit[0]),
                                Byte.valueOf(secondSplit[3])));
                    }
                }
            }
            return itemStack;
        }
     
  15. Offline

    Jacek

    Well looking at your code, we are using the same method basically, except I used an ObjectOutputStream to store the object instead of creating strings.

    If you are setting the data basically like I was, do you have the same problem ?
     
  16. Offline

    CptSausage

    No, it works like a charm.
     
  17. Offline

    Jacek

    Hmm, then what was I doing !
     
Thread Status:
Not open for further replies.

Share This Page