用户:MashKJo/1.12.2模组开发教程/6.ItemStack和Meta-hack:修订间差异

→‎ItemStack对象的使用:​ // Edit via Wikiplus
无编辑摘要
→‎ItemStack对象的使用:​ // Edit via Wikiplus
 
在设计物品的功能时,我们自然而然地会有给物品添加附加数据的需求。首先先明确一点——永远不要让附加数据以Item实例的实例变量的形式存在,因为Item代表的是物品类型,牵一发而动全身,数据的变化会影响所有物品类型为该Item实例的ItemStack——所以你应该把目光放在ItemStack的那几个字段上。能存储额外信息的字段,其实只有两个:Meta和附加NBT。但是除非你要存储的数据是该物品的损害值/耐久值,否则,通常不推荐用meta存储额外数据,因为它本身不是什么复杂的引用类型变量,只是一个int整数罢了,而且它的使用颇有些hack的味道(甚至于1.13开始它直接被抹去了)。因此,还是把目光放在附加NBT上为好。
 
另外,读者如果翻阅过ItemStack类的源代码,可能会发现该类中有个特殊的静态字段:EMPTY。它其实是代表“空”的ItemStack,即对应的Item为null的情况——实际上它被赋予的值就是<code>new ItemStack((Item)null)</code>,如果对ItemStack.EMPTY调用getItem方法的话,却不会返回null,而是会返回Items.AIR(没错,这其中有一个三目运算符在判空)。
 
那么,Items.AIR又是何方神圣呢?望文生义,它似乎是空气方块的物品形式?唔,这个解释,对,也不对。因为所有作为方块的物品形式的物品,都是ItemBlock类的实例,但Items.AIR是ItemAir类的实例,ItemAir类却是直接继承了Item,并未继承ItemBlock——所以我们可以说,空气方块不存在对应的物品——这也是为什么在几乎所有Minecraft版本中我们均不能获得空气物品(除了极个别快照版本)。但另一方面,ItemAir类的构造方法接受一个Block参数,在Item类的registerItems这一静态方法中,Items.AIR又被这样赋了值:
registerItemBlock(Blocks.AIR, new ItemAir(Blocks.AIR));
 
Mojang的意思似乎又是:Items.AIR就是Blocks.AIR的物品形式,着实让人大惑不解。更何况既然都给ItemAir取名为“空气物品”了,又何必多此一举让一个Block传入进去呢?笔者对此属实是不能理解,只能理解为Items.AIR纯粹是Mojang用于占位的一个Item罢了,恰巧“无”的概念在Minecraft中和空气是相近的。
 
此外,下面列出了一些ItemStack类常用的方法,这些方法在实际开发中通常会很实用:
* <code>void addEnchantment(Enchantment ench, int level)</code>:用于给某个ItemStack添加一个固定等级的附魔,注意ItemStack类中并没有一个非静态的Map<Enchantment, Integer>字段来保存ItemStack对象的附魔情况,所以这个方法是怎么实际发挥作用的呢?答案是附魔信息存在了附加NBT里。
* <code>ItemStack copy()</code>:用于构造出一个各方面都与该ItemStack对象一样的另一个不同的ItemStack对象——只要读者懂得Java中关于变量、引用、对象的知识,就知道这个方法是用来干啥的
* <code>ItemStack setStackDisplayName(String displayName)</code>和<code>void clearCustomName()</code>:设定或移除某个ItemStack的自定义名称——实际效果跟把某个ItemStack放在铁砧里重命名是一样的,自定义展示名这个参数同样是储存在附加NBT中的。注意!这里不能做本地化处理——实际上你做了也没用,比如你给这个自定义名称设定一个本地化键名“tutorial_mod.custom_name”,并在语言文件中写好相应的本地化文本,你在游戏中看到的这个ItemStack只会显示未本地化的原始键名
* <code>boolean isEmpty()</code>:判断该ItemStack是否为空,即是否和ItemStack.EMPTY“相等”——实际上这个词用得不好,因为ItemStack类并未覆写equals方法,实际上这里实际的判断是先判断<code>this == ItemStack.EMPTY</code>,再判断当前对象的物品类型
 
此外我们也可以看看Item类中那些未讲到的getter了。实际上这些getter很多都有传入一个ItemStack参数,所以如果你想实现Item属性的高级控制,你可以不用那些简单的setter,而是通过覆写这些getter,结合传入的ItemStack的信息来操作返回结果,借此我们可以实现一些很酷炫的效果。
 
以及你可能已经发现了,ItemStack类中有很多方法是和Item重合的,这些方法一般都通过getItem方法来代理给ItemStack对象对应的Item来做。
行政员、​优秀编辑者、​界面管理员、​监督员、​管理员、​小部件编辑者
3,334

个编辑