我正在尝试将Dye颜色应用到现有的ItemStack中,如何在不使用弃用方法和创建新堆栈的情况下执行此操作?
我尝试了以下代码,但这导致了正常的墨水袋。
ps:我只在第一行创建一个堆栈作为示例。
final ItemStack stack = new ItemStack(Material.INK_SACK);
Dye dye = new Dye();
dye.setColor(DyeColor.LIME);
stack.setData(dye);
编辑:在堆栈变量中添加了final,以表明它不能被新堆栈替换。
答案 0 :(得分:6)
我找到了一种方法来做到这一点,但它远不如使用弃用的方法那么高效。这是我自己的个人思考过程。
您当前尝试的问题是setData(MaterialData)
方法的内部。
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());
}
}
}
此方法用作处理空值并防止不正确数据类型的简单setter。这里的问题应该是非常明显的。羊毛和染料不会将它们的信息存储在MaterialData
中,它们会将其存储在耐久性中。 Colorable
对象的持久性决定了它的颜色。因为这种情况,你需要修改耐久性,以便对颜色做任何事情。您可以在构造函数之外设置持久性的唯一位置是setDurability
方法。这不是MaterialData
,只是short
。因此,我们的选项如下:构造新的ItemStack,或获得对可用short
值的不推荐访问。根据您的标准,我们转向后者。
第一个入口点,DyeColor
类。如果我们在这里找不到short
值,它至少会从这里提供给另一个类。查看来源给我们一个严峻的提醒,就是问题是如何根深蒂固地弃用。
有一个hacky解决方案单独使用DyeColor
,但它不是版本证明变更。 Enum.ordinal()
方法将返回枚举的序数值。这是它定义的顺序的数值。从索引零开始,它将匹配羊毛数据值,但需要针对染料进行反转,这是您试图普及的东西。但是可以选择。
所以DyeColor
是不可能的,但它让我思考。使用Dye
方法时,MaterialData
作为toItemStack()
的作品完全正常。也许我们可以使用它。事实证明你可以!它需要创建一个新的Itemstack
,但我们将使用新的ItemStack
来访问原始MaterialData
的数据。首先,我们像您上面那样创建Dye dye = new Dye();
dye.setColor(DyeColor.LIME);
。
Dye
接下来,使用Itemstack
方法将toItemStack()
转换为ItemStack tempStack = dye.toItemStack();
。
Dye.setColor(DyeColor)
现在坚持,为什么这样做?嗯,你看,public void setColor(DyeColor color) {
setData(color.getDyeData());
}
方法有一个内部实现如下:
Material
它使用了一种不推荐使用的方法,但因为它包含在DyeColor调用中,所以它不会被弃用给插件用户。请注意:这是完全可以接受的!使用setData(byte)
作为参数的许多Bukkit调用实际上只调用与其关联的类型id的已弃用方法。尽管调用这些方法完全有效。另请注意,toItemStack()
方法只是一个简单的设置器。
接下来是public ItemStack toItemStack(int amount) {
return new ItemStack(type, amount, data);
}
方法。
DyeColor
我们在这里可以看到转换为字节的ItemStack
现在作为持久性发送到ItemStack(Material, int, short)
构造函数short
(它会自动转换为tempStack
)。这意味着,我们现在有我们要求的简短!它存储在stack.setDurability(tempStack.getDurability());
stack.setData(dye);
的持久性中。最重要的是,我们采取以下措施。
ItemStack
结束了。您有一个修改过的ItemStack.setData(MaterialData)
,没有公开的弃用方法。您可能会问为什么我仍然会拨打DyeColor
。这只是确保如果有人试图从ItemStack的MaterialData
访问{{1}},它将与耐久性相匹配。
我希望您对可行的事实感到满意,但我仍然建议使用弃用的方法,直到它们被列为已损坏的方式(通常不会发生在Bukkit中)。
答案 1 :(得分:1)
DyeColor.*
实际上使用羊毛颜色,Mojang决定改变染料颜色和羊毛颜色。所以,DyeColor.LIME.getData()
返回5,这是石灰色,但是石灰染料是10.所以你需要使用byte data = (byte) (15 - DyeColor.COLOR.getData());
所以,这就是你的代码应该是什么样子:
DyeColor color = DyeColor.LIME //or whatever dye color you want
byte data = (byte) (15 - color.getData()); //use byte data = (byte) (color.getData()) if you're coloring wool
ItemStack itm = new ItemStack(Material.INK_SACK, 1, data);
这会给你一个含有1种石灰染料的ItemStack。
如果你真的想使用一种不推荐的方法,你可以使用他们的ID创建自己的枚举:
public enum CustomDyeColor{
BLACK(0), //ink sack
RED(1),
GREEN(2),
BROWN(3),
BLUE(4), //lapis lazuli
PURPLE(5),
CYAN(6),
LIGHT_GRAY(7),
GRAY(8),
PINK(9),
LIME(10),
YELLOW(11),
LIGHT_BLUE(12),
MAGENTA(13),
ORANGE(14),
WHITE(15); //bonemeal
private byte data;
CustomDyeColor(int i){
this.data = (byte) i;
}
public byte getData(){
return this.data;
}
}
然后您可以使用新的,未展开的自定义代码来获取如下数据值:
CustomDyeColor color = CustomDyeColor.LIME;
byte customData = color.getData();
ItemStack item = new ItemStack(Material.INK_SACK, 1, customData)l
答案 2 :(得分:1)
您可以尝试使用Dye(Material)构造函数,然后应用DyeColor,并将Material转换为ItemStack。
Dye dye = new Dye(Material.INK_SACK);
dye.setColor(...);
ItemStack coloredInkSack = dye.toItemStack();
答案 3 :(得分:0)
我是这样做的:
new ItemStack(Material.STAINED_GLASS_PANE, 1, DyeColor.BLACK.getData()));
使用1.8.8 Spigot,它实际上创建了1个黑色玻璃窗格,尽管它表示颜色上的getData()
已被弃用。
我认为它也适用于羊毛和粘土。