1. 村民职业
原版的村民职业是写死进 EntityVillager
的。经过 Forge 一番 patch 后我们可以通过 Forge 的注册表来注册新的村民职业了。
import net.minecraftforge.fml.common.registry.VillagerRegistry;
@SubscribeEvent
public static void onVillagerProfessionRegistration(RegistryEvent.Register<VillagerRegistry.VillagerProfession> event) {
// VillagerRegistry.VillagerProfession 的构造器接受三个 ResourceLocation 作为参数:
// 第一个 ResourceLocation 是注册名。因为某些原因,它的构造器会调用 setRegistryName。
// 第二个 ResourceLocation 指定了有这个职业的村民的纹理。必须指明 png 后缀。
// 第三个 ResourceLocation 指定了有这个职业的僵尸村民的纹理。必须指明 png 后缀。
event.getRegistry().registerAll(new VillagerRegistry.VillagerProfession("my_mod:weird_profession", "my_mod:textures/entity/villagers/weird_profession.png", "my_mod:textures/entity/zombie_villagers/weird_profession.png"));
}
1.1. “子职业”(Career)
每一个村民职业(Profession)又会被细分为各种“子职业”(Career),比如原版农民(Farmer)被细分为了普通农民(Farmer)、渔夫(Fisherman)、牧羊人(Shepherd)和制箭师(Fletcher)。子职业的相关信息是直接存储在对应的职业下的。
import net.minecraftforge.fml.common.registry.VillagerRegistry;
@SubscribeEvent
public static void onVillagerProfessionRegistration(RegistryEvent.Register<VillagerRegistry.VillagerProfession> event) {
VillagerRegistry.VillagerProfession profession = event.getRegistry().getValue(new ResourceLocation("minecraft", "farmer"));
VillagerRegistry.VillagerCareer newCareer = new VillagerRegistry.VillagerCareer(profession, "fisherman");
}
1.2. 村民交易
一个卖鱼给 fisherman 的交易:
newCareer.addTrade(1, new EntityVillager.ListItemForEmeralds(new ItemStack(Items.FISH), new PriceInfo(1, 1)));
注意到 addTrade
方法的第二个参数接受的是 EntityVillager.ITradeList trades...
。在 EntityVillager
下有这些现成的实现可用:
ItemAndEmeraldToItem
,用于沙砾和绿宝石换燧石这样的交易。ListEnchantedBookForEmeralds
,用于图书管理员卖附魔书。ListEnchantedItemForEmeralds
,用户铁匠卖工具和护甲。ListItemForEmeralds
,绝大多数物品换绿宝石或绿宝石换物品的交易都是用的这个。TreasureMapForEmeralds
,地图师卖地图用到了这个。
除此之外我们可以自己实现 ITradeList
来实现更高级的交易。
public final class MyCustomTradeList implements EntityVillager.ITradeList {
public void addMerchantRecipe(IMerchant merchant, MerchantRecipeList trades, Random random) {
// 注意到 MerchantRecipeList 继承了 ArrayList<MerchantRecipe>,
// 所以这个方法的实现其实就是向 trades 这个 List<MerchantRecipe> 中加新元素的操作了。
}
}