探矿器(进阶物品) 1.21 Fabric
本篇教程的视频
本篇教程的源代码
GitHub地址:TutorialMod-Prospector-1.21
介绍
所谓进阶物品,就是一些比较复杂的物品,它们可能需要一些特殊的逻辑,或者是一些特殊的效果
最本质的区别在于它们有自己的类,而不是简单的Item
类,实例化的时候用的也是对应的类
原版中的很多物品都可以去看看,看看它们的实现逻辑,然后再去实现自己的物品
在这篇教程中,我们将制作一个进阶物品——探矿器Prospector
。探矿器是一种可以用来探测矿石的物品,它可以在玩家使用时输出矿石的位置,帮助玩家更快地找到矿石
这篇教程是和后面的Tag
教程配合的,后续我们会使用Tag
来优化探矿器的代码
思路
在开始着手编程之前,我们需要先思考一下探矿器的逻辑,你希望它怎么工作。这个过程是非常重要的,先搭框架再填内容。不要写到哪算哪,这样效率不高,甚至面临推翻重写的风险
那么在这里,我给出我的思路:
探矿器是一种物品,所以我们需要继承
Item
类,以继承物品的基本属性探矿器是一种可以使用的物品,不过要如何使用?我们可以在玩家右键方块的时候使用探矿器,然后输出矿石的位置。这里我们可以重写
useOnBlock
来实现这里说明一下,
Item
类中的那些公共方法是可以重写的,一些方法Fabric也加了注释,可供参考。具体的实现方法参考源代码或者其他的模组其实
使用
物品的方法不只有useOnBlock
,还有use
、finishUsing
等等,其他的方法可以自己尝试那么探矿器是怎么工作的?这个例子在1.20的教程中也有,我们对其进行一个改写。
现在我们让这个探矿器有
两种模式
,分别是精确搜索
和模糊搜索
,精确搜索可以找到具体某一个矿石的确切位置,而模糊搜索一片矿石的位置我们希望玩家正常使用时是
模糊搜索
,而蹲下使用时是精确搜索
,这样就可以实现两种模式的切换了那么这两个模式的范围是多少呢?
模糊搜索
的范围是以右击的方块为起点,向x轴和z轴方向拓展,各拓展5格,这样就得到了一个5*5的范围,外加竖向的搜索而
精确搜索
则就以右击的方块进行竖向搜索,直到找到矿石为止蹲下
这个东西怎么判断?玩Minecraft的人都知道,蹲下是按Shift
,那么我们是否可以判断玩家是否按下了Shift
键呢?嘿,巧了,Screen
类就提供了这样的方法另外则是一些小细节,比如探矿器的
耐久
,矿石的种类
,屏幕输出
等等
编写探矿器
创建Prospector类
首先我们需要创建一个Prospector
类,这个类继承Item
类,实现super
函数
1 | public class Prospector extends Item { |
重写useOnBlock方法
然后我们重写useOnBlock
方法,这个方法是在玩家右键方块时调用的,我们可以在这里实现探矿器的逻辑
我们重写方法时,只要输入对应的方法名,用TAB
补全就可以了
1 |
|
里面要写的东西就是探矿器的逻辑了
咋搜索啊?遍历呗,for
循环,然后判断是不是矿石,是的话就输出
1 |
|
我这里直接放上来了,教程的视频可以看我遍敲遍讲的过程
其逻辑其实就是遍历,找到了就给玩家输出信息,然后返回ActionResult.SUCCESS
,表示成功使用
BlockPos pos
,PlayerEntity player
,World world
这几个变量我是后来拎出来的。
在实际开发过程中,有些时候我们并不知道自己需要什么变量,可以到后期优化的时候,将一些重复的代码提取出来,然后再进行优化
模糊搜索
有三层循环,精确搜索
只有一层循环,这是因为精确搜索
只需要竖向搜索,而模糊搜索
需要横向搜索
Screen.hasShiftDown()
这个方法就是判断玩家是否按下了Shift
键
这里我们只输出找到的第一个矿石,使用break
跳出循环,如果全部输出的话可能有一堆,反倒是不好判断了
player.sendMessage(Text.of("Found" + name + "!"));
这个方法是给玩家输出信息,name
是矿石的名字;同理没找到则输出No ore found!
context.getStack().damage(1, player, EquipmentSlot.MAINHAND);
这个方法是让探矿器的耐久减少1,这条语句和1.20的不太一样,改了一些参数
isRightBlock(blockState)
这个方法是判断这个方块是不是矿石,这个方法我们需要自己实现
1 | private boolean isRightBlock(BlockState blockState) { |
这个方法很简单,就是判断这个方块是不是钻石矿石
或者铁矿石
,是的话就返回true
,否则返回false
虽然这里采用的是硬编码的形式,但再讲解完Tag
之后,我们会使用Tag
来优化这个方法
注册探矿器
和注册物品一样,我们需要在ModItems
类中注册探矿器
1 | public static final Item PROSPECTOR = registerItems("prospector", new Prospector(new Item.Settings().maxDamage(127))); |
这里我们注册了一个PROSPECTOR
物品,即探矿器
,实例化的是我们刚刚写的类,有别于普通的物品,我们还要设置最大耐久,这里设置为127(可以使用128次,0~127)
加入物品栏
1 | entries.add(ModItems.PROSPECTOR); |
数据生成
语言文件
1 | translationBuilder.add(ModItems.PROSPECTOR, "Prospector"); |
模型文件
1 | itemModelGenerator.register(ModItems.PROSPECTOR, Models.GENERATED); |
然后记得跑一遍Data Generation
,生成数据。当然,贴图也别忘了
测试
然后我们就可以测试了,将探矿器放到物品栏中,右键方块,看看是否能找到矿石