3,417
个编辑
MCBBS Wiki欢迎您共同参与编辑!在参与编辑之前请先阅读Wiki方针。
如果在编辑的过程中遇到了什么问题,可以去讨论板提问。
为了您能够无阻碍地参与编辑 未验证/绑定过邮箱的用户,请尽快绑定/验证。
MCBBS Wiki GitHub群组已上线!
您可以在回声洞中发表吐槽!
服务器状态监控。点击进入
本站由MCBBS用户自行搭建,与MCBBS及东银河系漫游指南(北京)科技有限公司没有从属关系。点此了解 MCBBS Wiki 不是什么>>
(→ItemStack对象的使用: // Edit via Wikiplus) |
(→Meta-hack: // Edit via Wikiplus) |
||
| (未显示同一用户的1个中间版本) | |||
| 第33行: | 第33行: | ||
以及你可能已经发现了,ItemStack类中有很多方法是和Item重合的,这些方法一般都通过getItem方法来代理给ItemStack对象对应的Item来做。 | 以及你可能已经发现了,ItemStack类中有很多方法是和Item重合的,这些方法一般都通过getItem方法来代理给ItemStack对象对应的Item来做。 | ||
== Meta-hack == | |||
那么,笔者终于要给读者解惑:ItemStack的meta字段,到底是什么意思?? | |||
好,这个字段,它的实际名称,为<code>itemDamage</code>,意思为“物品的损害值”,什么叫损害值?举个例子,一个满耐久的铁镐,其损害值为0;而如果用了它一次,且它挖掉的这个方块具有让它损耗耐久的功能(不能是TNT这种方块),那么它之后的损害值就变为了1——这下明白了吧?一个物品的最大损害值,实际上数值上等于它的最大耐久值。通过Item类的setMaxDamage方法可以控制物品的最大损害值。 | |||
然而,事情远没有这么简单。itemDamage这一字段,它的含义是会变的——由对应Item实例的<code>boolean hasSubtypes</code>字段控制,该字段默认为false。 | |||
但如果,我们用setHasSubtypes(true)来改变了这一字段呢?那么itemDamage,也即meta,它就不能用于指代损害值了,而是用于区分共享同一个Item实例的不同种物品了。这个技巧,有什么好处呢?一是为了防止物品占用过多的数字ID——虽然Forge的注册表不要求我们显式指定数字ID,但不代表数字ID就不存在了,它仍然存在于Minecraft底层之中,直到1.13它才彻底消失;而在1.12.2时期,数字ID是会被Forge动态分配的。二是在某些实现中它确实很符合人的惯常思维,也确实很好用,比如MC中有很多与颜色相关的物品,先写一个辅助类EnumDyeColor,再通过meta的值进行统筹分配颜色,确实是个不错的设计。然而为什么这玩意叫“Meta-hack”呢?那是因为Mojang不知道怎么想的,非得把物品的损害值和类型序数这两个概念耦合在一个字段中——这不是吃饱了撑的吗?所以实际上一个Item实例并不能同时拥有类型序数和耐久值,除非其中有一个被存在附加NBT中(实际上最好把itemDamage设定为类型序数,这样在设定物品模型的时候方便——setCustomModelResourceLocation那块正好传入一个meta值,不过把类型序数存进附加NBT也不是不行,写个Property Override就可以,这个内容后面会讲到的)。实际上meta这个概念在1.13直接被废除了,物品的耐久也被并入了附加NBT中。 | |||
而且,使用Meta-hack时,通常需要覆写Item类的一些getter,通过<code>switch(stack.getMetadata())</code>来控制同一个Item实例不同meta的ItemStack的各自的unlocalizedName、maxStackSize等参数。 | |||
而且还有一个问题:如何让带合适meta的ItemStack体现在创造模式物品栏中呢?答案是覆写Item类的getSubItems方法,向传入的NonNullList<ItemStack>中添加特定的ItemStack即可。注意这个方法不需要设定hasSubtypes为true才能起效果,因此这个方法也不是专门为meta-hack准备的——因为ItemStack里除了meta还有附加NBT啊,所以理论上你可以让陈列在创造模式物品栏中的ItemStack带上一定的附魔——暮色森林中的迷宫破坏者,在创造模式物品栏中,就是自带附魔的,原理就是这个。 | |||
另外,由于ItemStack对象的使用方法是随建随用,因此你甚至可以往这个NonNullList<ItemStack>中塞2个各方面都完全相同的2个ItemStack。 | |||
说教得差不多了,来段示例代码吧(这里笔者设定了:在创造模式物品栏中展示meta为0 - 3的该物品。 | |||
<code>src/main/java/net/tutorial_mod/item/ItemMultiMetadata.java:</code> | |||
package net.tutorial_mod.item; | |||
import net.minecraft.creativetab.CreativeTabs; | |||
import net.minecraft.item.Item; | |||
import net.minecraft.item.ItemStack; | |||
import net.minecraft.util.NonNullList; | |||
import net.tutorial_mod.TutorialMod; | |||
public class ItemMultiMetadata extends Item{ | |||
public ItemMultiMetadata(){ | |||
this.setRegistryName(TutorialMod.MODID, "multimetadata_item"); | |||
this.setCreativeTab(CreativeTabs.MISC); | |||
this.setHasSubtypes(true); | |||
this.setNoRepair(); | |||
} | |||
@Override | |||
public String getUnlocalizedName(ItemStack stack){ | |||
return "item.multimetadata_item_" + stack.getMetadata(); | |||
} | |||
@Override | |||
public void getSubItems(CreativeTabs tab, NonNullList<ItemStack> items) | |||
{ | |||
if (this.isInCreativeTab(tab)) | |||
{ | |||
for(int i = 0; i < 4; i ++) | |||
{ | |||
items.add(new ItemStack(this, 1, i)); | |||
} | |||
} | |||
} | |||
} | |||
最后,再说两点吧: | |||
# 对于物品而言(猜猜看笔者为什么要特意强调“对于物品”),meta值最大为short类型的上限:65535。 | |||
# 除非你真的有特殊需求,否则,不要轻易用这个Meta-hack,因为它的实现莫名其妙的,且在1.13就会失效。那么有什么代替的方案吗?也简单,实际上原版就有这样的案例——ItemBucket类,原版的空桶、水桶、岩浆桶都是通过new这个类构造出来的(注意牛奶桶不在此列),因为ItemBucket的构造方法中有个Block参数,借此控制桶中到底装的是啥——空桶在被构造时,传入的是空气方块——合理吧?所以你更应该修改你的Item子类的构造方法,加点形参用于控制不同的变种,再多new几次这个类就行了,犯不着一定要用Meta-hack。 | |||