如何正确地将染料设置为ItemStack?

Jos*_*ior 3 java minecraft bukkit

我正在尝试将Dye颜色应用到现有的ItemStack中,如何在不使用弃用方法和创建新堆栈的情况下执行此操作?

我尝试了以下代码,但这导致了正常的墨水袋.

ps:我只在第一行创建一个堆栈作为示例.

final ItemStack stack = new ItemStack(Material.INK_SACK);
Dye dye = new Dye();
dye.setColor(DyeColor.LIME);
stack.setData(dye);
Run Code Online (Sandbox Code Playgroud)

编辑:添加最终到堆栈变量以显示它不能被新堆栈替换.

Cry*_*orm 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());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

此方法用作处理空值并防止不正确数据类型的简单setter.这里的问题应该是非常明显的.羊毛和染料不存储它们的信息MaterialData,它们存储它们的耐久性.Colorable物体的耐久性决定了它的颜色.因为这种情况,你需要修改耐久性,以便对颜色做任何事情.您可以在构造函数之外设置持久性的唯一setDurability方法是方法.这不需要MaterialData,只需要一个short.因此,我们的选项如下:构造一个新的ItemStack,或获得对可用short值的非弃用访问.根据您的标准,我们转向后者.

第一个入学点,DyeColor全班.如果我们在short这里找不到这个值,它至少会从这里提供给另一个类.查看源代码,让我们对这个问题的根深蒂固提出了一个严峻的提醒.

有一个hacky解决方案DyeColor单独使用,但它不是版本证明的变化.该Enum.ordinal()方法将返回枚举的序数值.这是它定义的顺序的数值.从索引零开始,它将匹配羊毛数据值,但需要针对染料进行反转,这是您试图普及的东西.但是选项就在那里.

所以DyeColor不可能,但它让我思考.使用该方法时,Dye该类作为一个MaterialData完美的工作toItemStack().也许我们可以使用它.事实证明你可以!它需要创建一个新的Itemstack,但我们将使用new ItemStack来访问原始数据.首先,我们创建了MaterialData你上面所做的那样的东西.

Dye dye = new Dye();
dye.setColor(DyeColor.LIME);
Run Code Online (Sandbox Code Playgroud)

接下来,转换DyeItemstack使用toItemStack()方法.

ItemStack tempStack = dye.toItemStack();
Run Code Online (Sandbox Code Playgroud)

现在坚持,为什么这样做?嗯,你看,该Dye.setColor(DyeColor)方法有一个内部实现如下:

public void setColor(DyeColor color) {
    setData(color.getDyeData());
}
Run Code Online (Sandbox Code Playgroud)

它使用了一种不推荐使用的方法,但因为它包含在DyeColor调用中,所以它不会被弃用给插件用户.请注意:这是完全可以接受的!许多Bukkit的调用Material实际上只是使用与之关联的类型id来调用已弃用的方法.尽管调用这些方法完全有效.另请注意,该setData(byte)方法只是一个简单的setter.

接下来,该toItemStack()方法.

public ItemStack toItemStack(int amount) {
    return new ItemStack(type, amount, data);
}
Run Code Online (Sandbox Code Playgroud)

我们可以在这里看到DyeColor转换为字节的那个现在作为持久性发送到ItemStack构造函数ItemStack(Material, int, short)(它自动转换为a short).这意味着,我们现在有我们要求的简短!它存储在耐用性中tempStack.最重要的是,我们采取以下措施.

stack.setDurability(tempStack.getDurability());
stack.setData(dye);
Run Code Online (Sandbox Code Playgroud)

结束了.您已修改ItemStack,没有公开的弃用方法.你可能会问为什么我仍然打电话ItemStack.setData(MaterialData).这只是确保如果有人试图DyeColor从ItemStack中访问MaterialData它,它将与耐久性相匹配.

我希望你对这是可能的事实感到满意,但我仍然建议使用已弃用的方法,直到它们被列为已损坏(这通常不会发生在Bukkit中).