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

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

ps:我仅在第一行中创建一个堆栈作为示例。

final ItemStack stack = new ItemStack(Material.INK_SACK);
Dye dye = new Dye();
dye.setColor(DyeColor.LIME);
stack.setData(dye);

编辑:将final添加到堆栈变量以显示它不能被新堆栈替换。

最佳答案

我找到了一种方法来执行此操作,但是它远不如使用不推荐使用的方法有效。这就是我个人的思考过程。

您当前尝试的问题在于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());
        }
    }
}

此方法用作处理空值并防止错误数据类型的简单设置器。虽然这里的问题应该很明显。羊毛和染料不会将其信息存储在MaterialData中,而是将其存储在持久性中。 Colorable对象的持久性决定了它的颜色。既然是这种情况,您将需要修改耐久性才能对颜色进行任何处理。可以在构造函数之外设置持久性的唯一地方是setDurability方法。这不需要MaterialData,只需要short。因此,我们的选择如下:构造一个新的ItemStack,或获得对不可用的short值的不建议使用的访问。根据您的标准,我们转向后者。

第一个入口点是DyeColor类。如果我们在这里找不到short值,那么它将至少从此处提供给另一个类。查看源代码可以使我们对问题的根源有一个严峻的提醒。

有一种仅使用DyeColor的hacky解决方案,但如果发生更改,则不能提供版本证明。 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());
}

它使用了不推荐使用的方法,但是由于它包装在DyeColor调用中,因此不建议插件用户使用。请注意:这完全可以接受! Bukkit的许多使用Material作为参数的调用实际上只是调用了与该ID相关联的不赞成使用的方法。不过,调用这些方法是完全有效的。还要注意,setData(byte)方法只是一个简单的设置方法。

接下来,使用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)。这只是确保如果有人尝试从ItemStack的DyeColor中访问MaterialData,它将与耐久性相匹配。

我希望您对可能的事实感到满意,但是我仍然建议您使用不推荐使用的方法,直到它们被列为已损坏(Bukkit通常不会发生)为止。

07-24 09:46