How can I correctly set a Dye into an ItemStack?
bukkit, java, minecraft
Solution
I've found a way to do this, but it is nowhere near as efficient as using a deprecated method. Here it is with my own personal thought process along the way.
The problem with your current attempt is the interior of the `setData(MaterialData)` method.
public void setData(MaterialData data) {
Material mat = getType();
if (data == null || 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());
}
}
}
This method works as a simple setter that handles null values and prevents incorrect data types. The problem here should be quite visible though. Wools and dyes don't store their info in `MaterialData`, they store it in their durability. The durability of a `Colorable` object determines its color. Being that this is the case, you will need to modify the durability in order to do anything to the color. The only place you can set the durability outside of the constructor is the `setDurability` method. This doesn't take a `MaterialData`, only a `short`. Thus our options are the following: Construct a new ItemStack, or gain non-deprecated access to a usable `short` value. By your criteria, we move to the latter.
First point of entry, the `DyeColor` class. If we can't find the `short` value here, it will at least be supplied from here to another class. Looking at the source gives us a grim reminder of just how rooted in deprecation the problem is.
There is one hacky solution using `DyeColor` alone, but it's not version proof incase of changes. The `Enum.ordinal()` method will return the ordinal value of an enum. This is the numerical value of the order it was defined. Starting from index zero, it will match the wool data values, but needs to be inverted for dyes, something you are trying to make universal. The option is there though.
So `DyeColor` is out of the question, but it got me thinking. The `Dye` class as a `MaterialData` works perfectly fine when using the `toItemStack()` method. Maybe we could use that. Turns out you can! It will require creating a new `Itemstack`, but we will use the new `ItemStack` to access data for the original one. Firstly, we create the `MaterialData` like you did above.
Dye dye = new Dye();
dye.setColor(DyeColor.LIME);
Next, convert the `Dye` into an `Itemstack` using the `toItemStack()` method.
ItemStack tempStack = dye.toItemStack();
Now hold on, why does this work? Well you see, the `Dye.setColor(DyeColor)` method has an internal implementation of the following:
public void setColor(DyeColor color) {
setData(color.getDyeData());
}
It uses a deprecated method, but because it's wrapped in a DyeColor call, it's not deprecated to the plugin user. Please note: THIS IS PERFECTLY ACCEPTABLE! Many of Bukkit's calls using `Material` as a parameter actually just call the deprecated method with the type id associated to it. It's perfectly valid to call those methods though. Also note that the `setData(byte)` method is just a simple setter.
Next up, the `toItemStack()` method.
public ItemStack toItemStack(int amount) {
return new ItemStack(type, amount, data);
}
We can see here that the `DyeColor` that was converted to a byte is now sent to the `ItemStack` constructor `ItemStack(Material, int, short)` as the durability (it automatically casts to a `short`). This means, we now have the short we require! It's stored in the durability of `tempStack`. To top it all off, we do the following.
stack.setDurability(tempStack.getDurability());
stack.setData(dye);
It's over. You have a modified `ItemStack` with no exposed deprecated methods. You may be asking though why I still call `ItemStack.setData(MaterialData)`. This just ensures that if someone tries to access the `DyeColor` from the ItemStack's `MaterialData` it will match up with the durability.
I hope you are satisfied with the fact that it is possible, but I still just recommend using the deprecated methods until they are listed as broken (which usually doesn't happen with Bukkit).
Problem
I'm trying to apply a Dye color into an existing ItemStack, how can I do this without using deprecated methods and creating an new stack? I tried the following code but it's resulting in a normal ink sack. ps: I'm creating an stack in the first line only as example. ``` final ItemStack stack = new ItemStack(Material.INK_SACK); Dye dye = new Dye(); dye.setColor(DyeColor.LIME); stack.setData(dye); ``` edit: Added final to stack variable to show that it cannot be replaced by a new stack.