创造模式物品栏 1.20 Fabric 长线教程计划
本篇教程的视频
本篇教程的源代码
GitHub地址:TutorialMod-ItemGroup-1.20.1
本篇教程目标
- 理解原版物品栏的注册
- 使用
Fabric API将模组物品加入原版的创造模式物品栏 - 创建模组的创造模式物品栏,并加入物品
查看源代码
那么在前一篇教程中,我们添加了第一个物品,但现在只能通过give来获得我们的物品,这有些麻烦
所以在这一篇教程中,我们将学习如何将物品加入的创造模式物品栏中
同样的,我们来看看原版的物品栏是怎么写的
与Items一样,这一次要找的是ItemGroups这个类
那么,先问大家一个问题,就1.20.1这个版本而言,原版有多少个物品栏?也就是标签页有多少个
1 | public static final RegistryKey<ItemGroup> BUILDING_BLOCKS = register("building_blocks"); |
答案是14个,也就是这里罗列的14个物品栏注册键
不过,一般我们可见的只有13个物品栏,其中的OPERATOR是管理员物品栏,
在设置中可以将其打开,里面是放了命令方块、结构方块、光源方块等特殊的物品
注册键注册方法
这里我们先看看它们注册键的注册方法
1 | private static RegistryKey<ItemGroup> register(String id) { |
可以看到,这里调用了RegistryKey.of方法,传入了一个RegistryKeys.ITEM_GROUP和Identifier
这与我们之前看到物品注册中的注册键类似
那么同样,如果搬到我们自己的类中,Identifier还要传入我们模组的modid
物品栏注册
上面是注册键的注册,再接下来我们看看真正的物品栏是这么注册的
挑一个BUILDING_BLOCKS,我们可以看到下面有一个registerAndGetDefault方法,
在这个方法里面定义了原版的14个创造模式物品栏,也定义了每个物品栏中有什么东西
1 | Registry.register( |
这里的Registry.register很熟悉吧,前面的物品注册用的就是它
第一个参数是registerAndGetDefault方法的形参,其类型为Registry<ItemGroup>,其实就是之前说过的注册表
我们可以在Registries类中找到这个注册表
1 | public static final Registry<ItemGroup> ITEM_GROUP = create(RegistryKeys.ITEM_GROUP, ItemGroups::registerAndGetDefault); |
这个注册表调用的也是ItemGroups的registerAndGetDefault方法,我们自己注册物品栏时,直接用这个注册表就可以
Fabric的底层会将我们模组的物品栏塞进这个注册表中,具体的实现感兴趣的同学可以自己去研究Fabric的那些Mixin类
第二个参数是注册键,也就是上面注册好的BUILDING_BLOCKS
第三个参数是物品栏的定义,从ItemGroup.create方法开始,一直到最后的build方法
物品栏定义
那么现在,我们重点来看看物品栏的定义
1 | ItemGroup.create(ItemGroup.Row.TOP, 0) |
create方法传入两个参数,第一个是物品栏的标签页位置,这里的Row.Top表示在上面那行;
第二个是物品栏的标签页的索引值,从0开始
displayName方法传入一个Text对象,用于定义物品栏的标签页名称,这里使用了Text.translatable方法,
即可以用语言文件来翻译填的内容,我们可以在原版的en_us.json中找到对应的翻译
icon方法传入一个lambda表达式,用于定义物品栏的标签页图标,这里使用了new ItemStack(Blocks.BRICKS),
也就是用原版的砖块作为图标
先提一嘴,ItemStack这个概念与未来讲到的BlockEntity类似。
在游戏中,物品本身是不能存储任何数据的,而像物品图标、堆叠数量、耐久度等,
都是由ItemStack来存储的。所以在这里我们获取物品栏的图标,
也是实例化一个ItemStack来实现的
entries方法传入一个lambda表达式,用于定义物品栏中有什么物品,这里使用了displayContext和entries两个参数。
不过绝大多数情况下,我们只会使用entries
entries.add方法传入一个物品(也可以是方块),将物品加入物品栏,这里加入的是橡木原木
build方法用于构建物品栏,返回一个ItemGroup对象
这就是其中一个物品栏的注册,剩下的13个也是类似的,不过有些物品栏不太一样,比如快捷栏、玩家的生存模式物品栏等,
具体的可以大家自己研究
使用Fabric API将物品加入原版物品栏
那么现在,我们已经知道了该如何去创建物品栏,可以开始写我们模组的物品栏了
不过,在此之前,我们先讲讲如何使用Fabric API将物品加入原版物品栏
大家也看到了,上面一堆的entries.add都已经写好了,原版没有提供给我们将自己物品加入到原版物品栏的方法
这个时候,如果你想把之前添加的物品加到原版某个物品栏中时,就得使用Mixin了,将我们的物品塞进原版物品栏中
不过,Fabric已经将这个Mixin封装好了,我们拿过来用就好了,不用我们自己去写Mixin了
添加方法
这里我们到ModItems中,写上一个返回值为空的方法,形参为FabricItemGroupEntries entries
1 | private static void addItemToItemGroup(FabricItemGroupEntries entries) { |
这个FabricItemGroupEntries是Fabric的一个API,先将模组物品加入到Fabric的物品栏
初始化
随后,我们在之前写的,用来初始化的注册方法中写上
1 | ItemGroupEvents.modifyEntriesEvent(ItemGroups.NATURAL).register(ModItems::addItemToItemGroup); |
这里我们调用了ItemGroupEvents.modifyEntriesEvent方法,
传入了一个ItemGroups.NATURAL,也就是原版自然方块物品栏
后面的regsiter再调用刚刚写的方法
举一反三
我们还有一个物品对吧,我想将它加入到原版原材料物品栏,该怎么做呢?很简单,把上面步骤再重复一遍就好了
1 | private static void addItemToItemGroup2(FabricItemGroupEntries entries) { |
并且初始化
1 | ItemGroupEvents.modifyEntriesEvent(ItemGroups.INGREDIENTS).register(ModItems::addItemToItemGroup2); |
随后,我们进入游戏,再到原版的物品栏中,就可以看到我们模组的物品了
创建模组的物品栏
我们已经知道了如何使用Fabric API将物品加入原版物品栏,接下来就按照原版的方法来写我们模组的物品吧
这里我们创建一个ModItemGroups类,用于注册我们的物品栏
1 | public class ModItemGroups { |
注册键注册方法
我们先写一个注册键注册方法,把原版的搬过来改一下就可以了
1 | private static RegistryKey<ItemGroup> register(String id) { |
这里我们将Identifier加上我们模组的modid
注册注册键
随后,我们注册物品栏的注册键
1 | public static final RegistryKey<ItemGroup> TUTORIAL_GROUP = register("tutorial_group"); |
和原版的一样,一句话搞定
物品栏注册
那么最后,就是物品栏的注册
这里我们先写一个初始化注册方法,和前面物品注册里的一样
1 | public static void registerGroups() { |
随后我们在这个初始化注册方法中写上物品栏注册语句
1 | Registry.register( |
那么,这里面的参数基本上都解释过了,这里就不再赘述
第一个参数是物品栏的注册表,Registries中的直接拿过来用即可
create中的参数,注意不要和原版的重合,不然会出问题,原版已经将第一页排满了,使用我们模组的物品栏会从第二页开始
另外,如果说像这里的create写上8,在你只有这一个物品栏的情况下,它也还是在第二页的第一个,前面缺省那么后面还是会顶上去的
不过,好像Fabric的物品栏是默认以物品栏的开头字母排序的,也许与这个索引没有关系,Fabric也没有提供像Forge和NeoForge那样可以改变物品栏顺序的方法
调用初始化方法
不要忘了在模组主类的onInitialize方法调用上面的初始化方法
1 |
|
举一反三 & 简化
那么,联想到我们之前注册物品,哎?能不能用static final来像物品注册那样写呢?
能的兄弟,能的
ItemGroups中的registerAndGetDefault,其返回值是ItemGroup,返回的其实是第14个物品栏
那么现在,我们就可以直接定义一个ItemGroup类型的静态字段
1 | public static final ItemGroup TUTORIAL_GROUP2 = Registry.register( |
这里也直接省去了注册键的写法,直接将第二个参数换为Identifier,也就是我们在注册物品时提到的简化写法
这里的create,直接写成null和-1,交给Fabric来处理模组的物品栏(按照物品栏名称的首字母排序)
如果你按照它Wiki的方法,用FabricItemGroup来注册物品栏,那么其实这里面写的就是null和-1
不过,这倒是有一个缺点,在未来的数据生成中会讲
语言文件
最后,别忘了在语言文件中添加物品栏的翻译
1 | { |
启动游戏测试
那么,现在我们就可以启动游戏测试了
在物品栏的第二页,我们就能看到我们加入的两个物品栏了











