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

时间:2014-07-13 12:59:04

标签: 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);

编辑:在堆栈变量中添加了final,以表明它不能被新堆栈替换。

4 个答案:

答案 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()已被弃用。 我认为它也适用于羊毛和粘土。