自定义村民 1.20 Fabric 长线教程计划
本篇教程的视频
本篇教程的源代码
GitHub地址:TutorialMod-Villagers-1.20.1
本篇教程目标
- 理解原版村民的注册
- 学会为模组添加自定义村民
查看源代码
那么这里我们也还是来看看源代码
村民职业注册
原版的村民是在VillagerProfession
中注册的
1 | public record VillagerProfession( |
它是一个record
类,我们再来看看里面的东西
1 | public static final VillagerProfession ARMORER = register("armorer", PointOfInterestTypes.ARMORER, SoundEvents.ENTITY_VILLAGER_WORK_ARMORER); |
可以看到,register
是它的注册方法,不过也一样的,也是有好几个重载方法的
1 | private static VillagerProfession register(String id, RegistryKey<PointOfInterestType> heldWorkstation, { SoundEvent workSound) |
不过最终调用的,其实就是最后一个方法中的Registry.register
,这个和我们之前注册方块或者物品类似
接下来我们看看其中的参数
id
,注册的id,也就是村民的名称
heldWorkstatio
n,村民的工作站,比如铁匠
对应的是铁砧
,图书管理员
对应讲台
等等
acquirableWorkstation
,村民可以获取的工作站,一般与上面的那个一样
gatherableItems
,村民可以收集的物品,比如农民
可以收集小麦、小麦种子等等
secondaryJobSites
,村民的次要工作地点,比如农民
可以在耕地
上进行工作,除了农民其他职业的也没有第二个工作站点了
workSound
,村民工作的声音
村民工作站注册
那么接下来我们看看村民的工作站
是怎么注册的,不难发现,它与PointOfInterestTypes
这个类有关
这个工作站的话,也可以称为兴趣点
,因为这个不是村民独有的
1 | public static final RegistryKey<PointOfInterestType> FARMER = of("farmer"); |
这是它其中的一个注册语句和注册方法,这个是注册键
那么问题来了,对应的方块呢?接着往下翻,翻到一个registerAndGetDefault
的方法
1 | public static PointOfInterestType registerAndGetDefault(Registry<PointOfInterestType> registry) { |
那么在这里我们就能够发现注册键对应的方块了
这里的register
方法是下面这个
1 | private static PointOfInterestType register( |
不过呢,这个方法是private
的,我们自己写的时候得另寻他法
接下来我们看看它的参数
registry
,注册表
key
,注册键,也就是上面注册的那个注册键
states
,注册键对应的方块,比如这里的农民对应的就是堆肥箱
ticketCount
,这个工作站能够容纳的村民数量,一般而言,每一个工作站只能容纳一个村民
searchDistance
,村民搜索这个工作站的距离,比如这里的农民就是1
,这个单位估计是一个区块
不过,我们也可以看到其他的那些工作站或者兴趣点,比如床
、蜂巢
、钟
等等,而像蜂巢这种并不是给人使用的兴趣点,
它的ticketCount
是0
,毕竟它是给蜜蜂用的
好了,村民注册相关的内容就这一些,村民的交易内容也是按照我们之前的教程来写就好了
注册村民
注册工作站注册键
这里我们先创建一个ModPointOfInterestTypes
类,用于注册这些兴趣点的注册键
1 | public class ModPointOfInterestTypes { |
然后我们搬一下原版的注册方法,改一下命名空间
1 | private static RegistryKey<PointOfInterestType> of(String id) { |
最后就可以注册兴趣点的注册键了
1 | public static final RegistryKey<PointOfInterestType> ICE_ETHER_KEY = of("ice_ether_poi"); |
为了加以区分,这里加上了poi
,指代这个兴趣点
注册村民职业
接下来我们创建一个ModVillagers
类,用于注册村民职业
1 | public class ModVillagers { |
随后我们按照原版的注册方法来定义我们自己的注册方法
1 | public static VillagerProfession register(String id, RegistryKey<PointOfInterestType> heldWorkstation, { SoundEvent workSound) |
这里的两个ImmutableSet.of()
,指的就是村民可以收集的物品和第二个工作站点,因为这里我们不需要,所以就让它直接空着好了
不要忘了将命名空间改成我们模组的
随后我们就可以注册村民职业了
1 | public static final VillagerProfession ICE_ETHER_MASTER = register("ice_ether_master", |
第二个参数的兴趣点注册键就是上面注册好的
村民工作的声音我们直接用原版的就好了
那么还有一个,就是兴趣点注册键对应的方块我们还没写,由于原版是private
的方法,
所以这里我们也还是使用Fabric
提供的API
来实现
先写一个注册方法
1 | public static PointOfInterestType registerPoints(String name, Block block) { |
这里我们使用了PointOfInterestHelper.register
方法,这个方法就是用来注册兴趣点注册键对应的方块的
第一个参数是注册键名称
,第二个参数是村民数量
,第三个参数是搜索距离
,第四个参数就是方块
了
村民数量和搜索距离就与原版的一致,直接设置为1
而后,我们就可以来写对应的方块了
1 | public static final PointOfInterestType ICE_ETHER_POI = registerPoints("ice_ether_poi", ModBlocks.ICE_ETHER_BLOCK); |
注意这里的注册键名称
,它要和我们注册的注册键名字一致,不然对应不上
最后,还有一个用于初始化的方法
1 | public static void registerModVillagers() { |
同样不要忘记在主类
调用
1 | ModVillagers.registerModVillagers(); |
注册村民交易
那么接下来就是村民交易
了
写法和前面一篇一样,这里就不再赘述了
1 | TradeOfferHelper.registerVillagerOffers(ModVillagers.ICE_ETHER_MASTER, 1, factories -> { |
同样也是用TradeOfferHelper
来新增村民交易
数据生成
语言文件
这个语言文件写的是在交易的GUI
上,显示的村民职业的名字
1 | translationBuilder.add("entity.minecraft.villager.ice_ether_master", "Ice Ether Master"); |
注意它的翻译键是entity.minecraft.villager. + 村民职业的id
兴趣点标签
兴趣点或者说工作站,它也是有标签的,我们得写一下
但是兴趣点标签与以往的物品或者方块的标签不一样,它们是另一种标签,所以这里我们要新建一个ModPointTagProvider
,
让它继承TagProvider<PointOfInterestType>
创建一个构造函数,同时重写方法
1 | public class ModPointTagProvider extends TagProvider<PointOfInterestType> { |
然后我们就得在configure
里面写标签了
1 | getOrCreateTagBuilder(PointOfInterestTypeTags.ACQUIRABLE_JOB_SITE) |
不过,万变不离其宗的还是使用getOrCreateTagBuilder
这里使用addOptional
加入我们的命名空间和兴趣点的注册键名称,名字不要搞错
最后也不要忘了在数据生成类中调用这个类
1 | pack.addProvider(ModPointTagProvider::new); |
贴图
这个贴图也是展开图,要放在textures/entity/villager/profession
目录下
文件名是注册的村民职业名称id
,不要写错了
测试
那么最后我们就可以进入游戏进行测试了