创造模式物品栏 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 | { |
启动游戏测试
那么,现在我们就可以启动游戏测试了
在物品栏的第二页
,我们就能看到我们加入的两个物品栏了