Skip to main content

1.4 自定义物品组

Part A. 实战

物品组可以形象地理解为创造模式物品栏的分栏。我们在最开始就提到的类 ItemGroup,所以自定义物品组很简单——就写一个继承于 ItemGroup 类的子类就行。

这个继承的类只需要写两个地方,一个是构造函数,直接使用父类的即可,第一个参数是物品组的名称 String。(这个组就以 “ObsidianGroup” 为例)

另一个是重写类里面的 createIcon() 实例方法(实际用途是创建物品栏的图标),要求返回一个 ItemStack 实例(毕竟需要将物品呈现在物品栏中),这个也很简单,用 ItemStack 构造函数构造个实例就行。ItemStack 构造函数的第一参数就是已注册的 Item 实例对象

从哪获取已注册的 Item 实例?简单,之前我们注册完物品后,DeferredRegister::register 方法不是返回了一个 RegisterObject<Item>,它就是包裹了注册信息的 Item,直接用 get() 实例方法就能返回已注册的 Item 实例。

public class ObsidianGroup extends ItemGroup {
public ObsidianGroup() {
// 注意:这里是翻译键,如果需要本地化(后面介绍),请记住它
super("obsidian_group");
}

@Override
public ItemStack createIcon() {
// ItemRegistry.obsidianIngot 对象在 1.1 中定义,忘了回去看
return new ItemStack(ItemRegistry.obsidianIngot.get());
}
}

这个简单的物品组类就做好了。但是想要将它显示在游戏里,还要将它在合适的位置实例化。

我们再定义一个类,专门存放 mod 中实例化的 ItemGroup 的类,就叫 ModGroup

public class ModGroup {
public static final ItemGroup og_group = new ObsidianGroup();
}

这样在物品类初始化的时候,用 Properties::group() 实例方法将物品加入 og_group 这个实例即可。

public class ObsidianIngot extends Item {
public ObsidianIngot() {
super(new Properties().group(ModGroup.og_group));
}
}

Part B. 理论:ItemGroup & ItemStack

对于 MC 中的物品组,创建方法比较简单,就是继承于原版的 ItemGroup 类型即可。

ItemGroup 提供构造方法:

public ItemGroup(String itemGroupName);

开发者可以自定义创建的物品组的属性,常见的是设置物品组的图标:

@Override
public ItemStack createIcon() {
/* do something to get an item stack / create an item stack containing the specific item (to use its icon) */
}

设置方法是重载父类的 createIcon 方法,要求返回一个包含指定 Item(要显示图标的 Item)的 ItemStack 即可,我们一般可以通过新建一个 ItemStack 对象,也可以引用已经存在的 ItemStack 对象来完成。这里涉及 ItemStack 的一个构造方法:

public ItemStack(Item containingItem);

怎么拿到 Item 对象呢?常见的做法是,获取在 mod 中注册过的物品,来作为 ItemStack 的包含对象。

为什么这里可以用我们之前注册的对象呢?因为调用这个方法的时候,一定是已经进入游戏了,也就是说其调用的生命周期一定在 mod 初始化结束后。

只有这种情况才能直接使用自己注册的对象。

回忆一下,deferred register 注册物品后会返回一个 RegisterObject<T>,同时包含了被注册对象和一些注册信息。我们可以使用已注册对象 get 到完整的 Item 信息,然后传给 ItemStack 进行构造。

值得注意的是,ItemGroup 无需手动注册,只要有 Item 或者其他已注册的对象在设置 Properties 时,使用 .group() 指定这个新的 ItemGroup 实例后,这个新的实例就会自动被注册进入程序。