本篇教程的视频

本篇教程的源代码

GitHub地址:TutorialMod-Trades-1.20.1

本篇教程目标

  • 理解原版村民交易内容
  • 增加现有村民的交易内容

查看源代码

原版的村民交易我们可以在TradeOffers这个类中找到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static final Map<VillagerProfession, Int2ObjectMap<TradeOffers.Factory[]>> PROFESSION_TO_LEVELED_TRADE = Util.make(
Maps.<VillagerProfession, Int2ObjectMap<TradeOffers.Factory[]>>newHashMap(),
map -> {
map.put(
VillagerProfession.FARMER,
copyToFastUtilMap(
ImmutableMap.of(
1,
new TradeOffers.Factory[]{
new TradeOffers.BuyForOneEmeraldFactory(Items.WHEAT, 20, 16, 2),
new TradeOffers.BuyForOneEmeraldFactory(Items.POTATO, 26, 16, 2),
new TradeOffers.BuyForOneEmeraldFactory(Items.CARROT, 22, 16, 2),
new TradeOffers.BuyForOneEmeraldFactory(Items.BEETROOT, 15, 16, 2),
new TradeOffers.SellItemFactory(Items.BREAD, 1, 6, 16, 1)
},
...

这里我们可以发现一个Map类型的变量PROFESSION_TO_LEVELED_TRADE,它存储了村民职业和对应的村民交易内容

比如这里的VillagerProfession.FARMER是农民职业的村民

里面的ImmutableMap.of()方法就是存储了村民交易等级和内容,第一个数字就是交易的等级,后面的TradeOffers.Factory[]就是交易内容

现在我们来看看这里面有什么方法

BuyForOneEmeraldFactory

1
new TradeOffers.BuyForOneEmeraldFactory(Items.WHEAT, 20, 16, 2)

这个方法是村民向玩家购买物品,即玩家给村民物品,村民给玩家绿宝石

其参数为交易物交易数量最大交易次数每次交易村民获得的经验

不过,从这个方法名字中我们就可以看出来了,每次交易只有一个绿宝石,不过在1.21中是有了另外的重载方法,可以写多个绿宝石

而要在1.20里面写的话,得用另外的方法,我们之后再说

SellItemFactory

1
new TradeOffers.SellItemFactory(Items.BREAD, 1, 6, 16, 1)

这个方法是村民向玩家出售物品,即玩家给村民绿宝石,村民给玩家物品

其参数为交易物交易价格绿宝石数量)、交易数量最大交易次数每次交易村民获得的经验

ProcessItemFactory

1
new TradeOffers.ProcessItemFactory(Items.COD, 6, Items.COOKED_COD, 6, 16, 1)

这个是村民向玩家出售加工好的物品,也就是玩家给村民绿宝石和原料,村民给玩家加工好的产品

其参数为原料原料数量、(价格,绿宝石数量)、产品产品数量最大交易次数每次交易村民获得的经验

其中的价格缺省则默认为1,要自己修改的话是写在原料数量和产品之间的

其他还有一些方法可以自己研究研究,这里就不一一列举了

添加交易内容

好,那么现在我们来添加新的交易内容,将我们模组的内容加入到村民交易中

但是,或许你也发现了,上面的那些村民交易是一个Map类型的变量,然后它的各个交易内容在更里面的Map里

所以我们要想添加村民交易,就得用Mixin

不过好在,Fabric已经为我们封装好了相关的API,我们直接拿过来用就好了

ModTrades

我们创建一个ModTrades类,用来添加交易内容

1
2
3
public class ModTrades {

}

然后我们创建一个用来初始化的方法

1
2
3
public static void registerTrades() {

}

然后在这里面,我们使用TradeOfferHelper.registerVillagerOffers来添加自定义的交易内容

这个TradeOfferHelper类就是Fabric为我们封装好的API,我们直接拿过来用就好了

1
2
3
4
5
6
7
8
9
TradeOfferHelper.registerVillagerOffers(VillagerProfession.FARMER, 1, factories -> {
factories.add(new TradeOffers.BuyForOneEmeraldFactory(ModItems.CORN, 2, 12, 5));
factories.add(new TradeOffers.SellItemFactory(ModItems.STRAWBERRY_SEEDS.getDefaultStack(), 1, 12, 5, 2, 0.5f));
factories.add((entity, random) -> new TradeOffer(
new ItemStack(ModItems.STRAWBERRY, 5),
new ItemStack(Items.EMERALD, 6),
2, 7, 0.5f
));
});

这个方法有三个参数,第一个是村民职业,第二个是交易等级,第三个是交易内容

我们使用factories.add()方法来添加交易内容

前两个我们是用了上面提到的方法,而第三个是自定义的交易内容,这是一个以物易物的交易,不用绿宝石

其参数分别是用于购买的物品和数量村民出售的物品和数量最大交易次数每次交易村民获得的经验打折系数

当然,实际的打折原版也就只有0.05,也就是95折,我们这里直接给它打骨折

同样的,你将这里面的第二个物品换成绿宝石,就可以实现获得多个绿宝石了

然后我们举一反三

1
2
3
TradeOfferHelper.registerVillagerOffers(VillagerProfession.FARMER, 2, factories -> {
factories.add(new TradeOffers.ProcessItemFactory(Items.MILK_BUCKET, 1, 2, ModItems.CHEESE, 3, 16, 5));
});

比如说这里我们使用ProcessItemFactory方法,来添加一个制作奶酪的交易

不过,村民交易有的一个bug是,Mojang没有为带个桶的这种物品设置单独的判断方法,
所以每次交易我们会消耗一个桶,确实有点消耗桶

另外,在1.20中,附魔还没有变成数据驱动的,这里我们可以指定图书管理员出售特定种类和等级的附魔书

1
2
3
4
5
6
7
TradeOfferHelper.registerVillagerOffers(VillagerProfession.LIBRARIAN, 1, factories -> {
factories.add((entity, random) -> new TradeOffer(
new ItemStack(ModItems.ICE_ETHER, 16),
EnchantedBookItem.forEnchantment(new EnchantmentLevelEntry(Enchantments.SHARPNESS, 2)),
3, 12, 0.5F
));
});

同样也是直接用TradeOffer类来创建交易内容

EnchantmentLevelEntry类来指定附魔类型和等级

后面的就是最大交易次数每次交易村民获得的经验打折系数

那么现在村民交易就写完了,下一篇教程是添加自定义的村民,也是通过这里的方法来添加村民交易的

主类调用

最后,我们在主类中调用这个方法

1
ModTrades.registerTrades();

测试

最后我们就可以进入游戏进行测试了,当然,因为原版交易内容的存在,我们添加的不一定会显示出来,看运气