用户:MashKJo/1.12.2模组开发教程/6.ItemStack和Meta-hack

MashKJo留言 | 贡献2024年12月6日 (五) 15:48的版本 (创建页面,内容为“前文说过,Item这一类型遵循享元设计模式——由此可以看出,每一个Item实例代表的其实是一个特定的物品类型。 那么读者肯定就要问了:那我们在游戏里,跟背包里的物品打交道的时候,不仅能得到背包里每个格子里的物品的种类信息,还能得到数量的信息啊!但是Item类中似乎没有代表堆叠数量的字段,这是什么回事呢?所以由此可见,Item实例所…”)
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)

前文说过,Item这一类型遵循享元设计模式——由此可以看出,每一个Item实例代表的其实是一个特定的物品类型。

那么读者肯定就要问了:那我们在游戏里,跟背包里的物品打交道的时候,不仅能得到背包里每个格子里的物品的种类信息,还能得到数量的信息啊!但是Item类中似乎没有代表堆叠数量的字段,这是什么回事呢?所以由此可见,Item实例所能提供的信息还是不够多。因此,实际上玩家在世界中,在99%的情况下,是和ItemStack对象而非Item打交道。

ItemStack包含的信息

一个ItemStack中所包含的信息有:物品种类(Item)、堆叠数量(int)、meta值(int)和附加NBT(NBTTagCompound)。物品种类和堆叠数量都不难理解,至于这个meta到底什么含义?这会在本节的最后一部分揭晓的,还请读者耐心看下去。至于附加NBT,这个熟悉原版命令的读者应该比较了解,在游戏中它一般是以一种类似JSON文件的格式出现的,即字符串形式的数组,这块的内容可以参考Minecraft Wiki的有关条目;但在代码层面,NBT的有着另一套用法。关于NBT的知识,后面会有专门一节来进行讲解。

ItemStack有着8种构造方法,其中有4种是我们会经常用到的:(Item item)(Item item, int count)(Item item, int count, int meta)(Item item, int count, int meta, @Nullable NBTTagCompound nbt)。还有3种构造方法是把刚才所述的前3种构造方法的第1个形参换成了Block,实际上这3种含Block的构造方法会自动获取传入的方块的物品形式(ItemBlock),再调用那3个含Item的构造方法——没错,我们认知中的拿在玩家手中的方块,实际上是方块的物品形式;被放置在世界中的方块,才是真正的方块。

还有个构造方法,只传入一个NBTTagCompound,这是怎么回事呢?实际上MC在序列化(Serialize)物品数据时,会先把ItemStack的物品类型、堆叠数量、meta值和附加NBT汇总起来,形成一个新的最终NBT,再进行存储操作;而这个构造器实际上就是执行了把最终NBT解成ItemStack的流程。

警告:ItemStack的附加NBT有可能为null,除非你调用含附加NBT的构造方法构造ItemStack,或调用setTagCompound显式指定附加NBT。所以用附加NBT前要先判空,否则大概率会抛NullPointerException崩游戏。

ItemStack对象的使用

ItemStack对象和Item不同,它是随建随用的。永远不要尝试去继承ItemStack类,因为这么做没有意义——事实上你也不可能去继承它,因为它是一个final class。