燃烧物 1.21 Fabric
本篇教程的视频
本篇教程的源代码
GitHub地址:TutorialMod-FuelItem-1.21
介绍
燃烧物是一种特殊的物品,它可以作为游戏中熔炉、高炉等方块实体的燃料,用于烧炼各种物品
当然,除了物品,还有方块也可以作为燃烧物,比如各种原木,而它们本身是可以作为可燃物的(可以被点燃,火会蔓延)。不过,可燃物的教程我们将在添加自定义的木头
这一篇教程中讲解
在这篇教程中,我会提供两种添加燃烧物的方法,一种是提供Fabric API的方法,另一种是使用Mixin的方法
为何使用Mixin
这里我们先讲解Mixin的方法,配合着前一篇教程的内容,我们可以很容易地添加燃烧物
查看源代码
不过在用Mixin之前,我们需要先查看源代码,找到我们需要的方法,然后再进行Mixin
我们查找Items
中的一些燃烧物,以COAL
为例
1 | public static final Item COAL = register("coal", new Item(new Item.Settings())); |
遗憾的是,这里的注册方法并没有提供燃烧时间,所以我们需要进一步查找
按住Ctrl
键,点击COAL
这个字段,我们可以查找所有引用这个字段的地方(范围为所有位置)
查找这些引用的地方也是有技巧的,首先看类名,再看后面的具体引用的语句,就可以缩小范围了
1 | public static Map<Item, Integer> createFuelTimeMap() { |
我们找到AbstractFurnaceBlockEntity
中的createFuelTimeMap
方法,这个方法顾名思义,是用来创建燃烧时间的
在它的方法体中,我们可以看到addFuel(map2, Items.COAL, 1600);
这一行,这就是添加燃烧物的方法
看到这里你应该知道为什么要用Mixin了,因为原版的燃烧物的燃烧时间是直接写在这个熔炉类中的,我们无法直接修改,然后我们再讲讲其他的
addFuel
方法的参数是Map<Item, Integer> map
、Item item
和int fuelTime
,我们可以看到COAL
的燃烧时间是1600
,单位自然是tick
,那么对应80s
1 | private static void addFuel(Map<Item, Integer> fuelTimes, ItemConvertible item, int fuelTime) { |
至于这其中的isNonFlammableWood
方法对我们这期教程来说并不重要,感兴趣可以自行研究。我们现在只看else
里的东西
结合着上面的addFuel(map2, Items.COAL, 1600);
,不难理解,这个方法就是将COAL
这个物品和它的燃烧时间1600
放到fuelTimes
这个Map
中
1 |
|
这个fuelTimes
是一个Map
类型的一个私有字段
所以本质上吧,其实就是折腾这个Map
类型的变量,所以我们直接使用Mixin来折腾这个Map
就可以了
在不考虑使用API的情况下,我们得把我们自己的物品和燃烧时间塞到这个字段中(当然,你翻Fabric API的那个方法,也是Mixin,只是别人帮你把轮子造好了,咱们后面再说)
注册物品
在写Mixin或者使用Fabric API之前,我们先注册物品
注册
1 | public static final Item ANTHRACITE = registerItems("anthracite", new Item(new Item.Settings())); |
这里我们注册了一个ANTHRACITE
物品,即无烟煤
加入物品栏
1 | entries.add(ModItems.ANTHRACITE); |
数据生成
语言文件
1 | translationBuilder.add(ModItems.ANTHRACITE, "Anthracite"); |
模型文件
1 | itemModelGenerator.register(ModItems.ANTHRACITE, Models.GENERATED); |
然后记得跑一遍Data Generation
,生成数据。当然,贴图也别忘了
Mixin
前面也讲过为什么要使用Mixin了,那么现在我们就来将燃烧物的注册方法塞到AbstractFurnaceBlockEntity
中
创建AbstractFurnaceBlockEntityMixin类
和目标类一样,我们将其声明为abstract
1 |
|
并记得将这个类加入到tutorialmod.mixins.json
中(插件可以自动加入)
1 | { |
编写方法
随后,我们就开始写里面的方法
1 | private static volatile Map<Item, Integer> fuelTimes; |
这里我们使用@Shadow
注解,为fuelTimes
这个字段创建一个影子
,这样我们就可以直接使用目标类中的这个字段了
1 |
|
而后,我们使用@Inject
注解,创建addFuelItems
方法,方法的参数由Minecraft Development
插件修正
method
是我们前面看到的那个方法,注入的位置at
是这个方法的尾部TAIL
(不要给它写在头部HEAD
,一旦写在了头部就会导致原版其他的燃烧物失效了(你可以尝试一下,原因自行研究,教程视频中也讲了))
在这个方法下的语句就是要注入的代码,因为Map
类型可以使用put
方法,这里我们就直接塞我们的物品和时间
这样我们的物品就成为燃烧物了,我们可以启动游戏,只要没有出问题,我们就可以使用这个新的物品熔炼东西了
PS:其实这个Mixin类并不是很严谨,但能够实现我们所需。Mixin的写法多种多样,也可以去参考Fabric API里的那些方法
Fabric API
可能一些同学还是搞不清Mixin的东西,没关系,Fabric API
早已提供了燃烧物的注册,这里我们就来使用
我们在主类初始化方法中加入以下语句即可
1 | FuelRegistry.INSTANCE.add(ModItems.ANTHRACITE, 1600); |
嗯,就这么简单。一个物品
再加一个时间
即可
而如果你想知道这背后到底是什么,那么可以挖一挖,它对应的实例类是FuelRegistryImpl
,该类在Fabric的AbstractFurnaceBlockEntityMixin
类中被调用