作物 1.20 Fabric 长线教程计划
本篇教程的视频
本篇教程的源代码
GitHub地址:TutorialMod-Crop-1.20.1
本篇教程目标
- 理解原版的
作物方块
类 - 理解原版的作物方块和
作物种子
注册 - 学会创建自定义的作物方块
- 学会注册作物方块和相关种子
- 学会作物类方块状态文件的编写
查看源代码
民以食为天对吧,那么现在咱们来种田,不过,当然得现有作物
作物方块注册
这里我们先来看看小麦
相关的注册,这里到Blocks
中找到WHEAT
1 | public static final Block WHEAT = register( |
这里我们可以看到,它实例化的是CropBlock
,这个类是原版作物方块类
它的参数就一个方块设置,但方块设置中可以做很多文章
noCollision()
表示无碰撞箱,作物方块是没有碰撞箱的,我们可以自由穿过
,
不过当我们的十字光标移上去后,也还是会显示它的外轮廓线
ticksRandomly()
表示随机刻
,也就是随机更新,作物类方块都会有这个,决定作物的生长
breakInstantly()
表示立刻破坏,也就是破坏速度很快,我们破坏作物并不是像挖其他方块那样,要挖好一会,看着它被破坏,相反,作物可以立即破坏
pistonBehavior(PistonBehavior.DESTROY)
表示活塞行为,也就是活塞推动作物方块时,作物方块会被破坏
作物方块类
接下来我们来看看CropBlock
,当然我们这里就看一部分,因为在后面一篇教程中,我们还会再好好了解
1 | public class CropBlock extends PlantBlock implements Fertilizable { |
CropBlock
继承了PlantBlock
,也就是植物方块,它里面是有一些生长逻辑的
然后又实现了Fertilizable
接口,表示可施肥
,也就是可以施肥的方块,也就是拿骨粉
催熟作物
1 | public static final int MAX_AGE = 7; |
这里的三个变量,分别定义了作物的最大生长阶段
,生长阶段属性
(用在方块状态上),还有每个阶段不同的外框形状
(轮廓线)
生长阶段要注意,它是从0
开始算的,所以这里会有8
个生长阶段,对应的轮廓线也有8
个
1 |
|
这里就是获取作物的轮廓线,根据当前的生长阶段来获取对应的轮廓线
1 |
|
这里就是判断作物方块是否可以种植在当前方块上,默认它是只能种在耕地
方块上的,但我们可以改一下,让它可以像甜浆果
那样直接种在地上
1 | protected IntProperty getAgeProperty() { |
这里就是获取作物的生长阶段属性
、最大生长阶段
和当前生长阶段
不过,我不知道Mojang
为什么定义了一个最大生长阶段,结果这里的getMaxAge
还是直接返回一个7,怪
那么我们在这期教程中会涉及的就大概这一些,后面还有很多方法,这个我们放到下一期的多方块作物里来讲
作物种子注册
作物的种子这里我们也来看一下,我们在Items
中找到WHEAT_SEEDS
1 | public static final Item WHEAT_SEEDS = register("wheat_seeds", new AliasedBlockItem(Blocks.WHEAT, new Item.Settings())); |
这里实例化的是AliasedBlockItem
,其实它也是方块物品,但它有自己的翻译键
,而不是和方块共用翻译键
不过注意一下,我们这里是以小麦
为例,其他的作物像胡萝卜
、马铃薯
这样的,作物和种子都是同一个东西,与小麦这种还是有点区别的
注册作物
创建作物方块
我们创建一个StrawberryCropBlock
,让它继承CropBlock
,然后创建一个构造函数
1 | public class StrawberryCropBlock extends CropBlock { |
对于这个草莓
作物,我们可以重新设置一下最大生长阶段
和它是生长阶段属性
1 | public static final int MAX_AGE = 5; |
原版是正好定义了6
个生长阶段属性的变量,所以我们直接拿过来用就好了
那么再接下来我们重写一些和它有关的方法
1 |
|
这里重写最大生长阶段
,生长阶段属性
,当前生长阶段
,还有方块状态
然后,我们要返回作物的种子
1 |
|
这里我们返回的是ModItems.STRAWBERRY_SEEDS
,也就是我们后面要注册的草莓种子
我们再改写一下这个作物可以种植的位置
1 |
|
这里我们让草莓作物既可以种植在耕地
方块上,也可以种在泥土
类方块上(包括泥土、草方块、砂土)
那么这样,我们完成了自定义作物的编写,接下来就是注册这个作物方块
注册作物方块
1 | public static final Block STRAWBERRY_CROP = Registry.register(Registries.BLOCK, new Identifier(TutorialMod.MOD_ID, "strawberry_crop"), |
注册作物方块我们得直接用Registry.register
,因为我们不需要对应的方块物品,毕竟作物方块是种在地上的,
拿在手里的只是种植或者成熟的果实,而不是植株
这里实例化的是StrawberryCropBlock
,也就是我们前面创建的草莓作物方块,后面的设置我们按照小麦的写就好了
注册作物种子
1 | public static final Item STRAWBERRY_SEEDS = registerItems("strawberry_seeds", |
这里我们注册的是草莓种子
,实例化的是AliasedBlockItem
,也就是我们前面提到的
数据生成
语言文件
1 | translationBuilder.add(ModItems.STRAWBERRY_SEEDS, "Strawberry Seeds"); |
战利品列表
作物的战利品列表
稍微有点复杂,因为它是分成熟
和未成熟
两种状态来决定最终的掉落物的
成熟的时候,会掉落最终的果实和种子,未成熟的时候,只会掉落种子
这里我们要写一个LootCondition
1 | LootCondition.Builder builder = |
这个可以参考原版的BlockLootTableGenerator
中的内容
BlockStatePropertyLootCondition.builder
中写上作物
properties
中写上属性,这里我们写的是StrawberryCropBlock.AGE
,也就是草莓作物的生长阶段属性,根据被破坏的作物当前的生长阶段来决定掉落物
然后就可以写战利品列表了
1 | addDrop(ModBlocks.STRAWBERRY_CROP, cropDrops(ModBlocks.STRAWBERRY_CROP, ModItems.STRAWBERRY, ModItems.STRAWBERRY_SEEDS, builder)); |
作物的战利品列表有cropDrops
方法,里面的参数是作物方块、作物种子和上面写的条件
方块模型
作物模型的数据生成同样有单独的方法
1 | blockStateModelGenerator.registerCrop(ModBlocks.STRAWBERRY_CROP, StrawberryCropBlock.AGE, 0, 1, 2, 3, 4, 5); |
用registerCrop
来生成作物的模型文件、方块状态文件
第一个参数是作物方块
,第二个参数是生长阶段属性
,后面的参数是每个生长阶段的值,一一罗列出来
种子物品同样也不用我们写了,它也会自己生成的
材质文件
那么这里的草莓作物一共6个生长阶段,所以我们需要6个不同的材质文件
注意它的命名方法是作物方块注册名 + _stage + 生长阶段数值 + .png
stage
和数值
之间是没有其他字符的,这里我们要从0
写到5
,一共6
个
测试
跑好数据生成之后,我们就可以进入游戏进行测试了