本篇教程的视频

本篇教程的源代码

GitHub地址:TutorialMod-Tools-1.20.1

本篇教程目标

  • 理解原版工具注册
  • 理解原版工具材料的编写
  • 学会添加自定义工具材料和自定义工具

查看源代码

本期教程我们来写原版那些工具,也就是

同样的我们先来看源代码

物品注册

我们先到Items这个类中来看看原版的工具是怎么注册的

1
2
3
4
5
public static final Item WOODEN_SWORD = register("wooden_sword", new SwordItem(ToolMaterials.WOOD, 3, -2.4F, new Item.Settings()));
public static final Item WOODEN_SHOVEL = register("wooden_shovel", new ShovelItem(ToolMaterials.WOOD, 1.5F, -3.0F, new Item.Settings()));
public static final Item WOODEN_PICKAXE = register("wooden_pickaxe", new PickaxeItem(ToolMaterials.WOOD, 1, -2.8F, new Item.Settings()));
public static final Item WOODEN_AXE = register("wooden_axe", new AxeItem(ToolMaterials.WOOD, 6.0F, -3.2F, new Item.Settings()));
public static final Item WOODEN_HOE = register("wooden_hoe", new HoeItem(ToolMaterials.WOOD, 0, -3.0F, new Item.Settings()));

这里就是这5个工具,我们可以看到它们实例化的是各自对应的物品类

不过,它们类似的是,第一个参数都是ToolMaterial,也就是工具材料,这里是木制的WOOD

第二个参数是额外攻击力,第三个是额外攻击速度,这个我们在自己写物品注册的时候再详细解释

最后一个参数是物品的设置,这里都是new Item.Settings(),也就是默认设置

工具材料类

那么接下来我们就来看看原版的这些工具材料,我们跳转到ToolMaterials这个类

工具材料决定了以这些材料为基础的工具的基本属性,像采集等级耐久度

这个类是一个枚举类,里面定义了原版所有的工具材料,我们来看一下

1
2
3
4
5
6
7
8
9
10
11
WOOD(MiningLevels.WOOD, 59, 2.0F, 0.0F, 15, () -> Ingredient.fromTag(ItemTags.PLANKS)),
...

private ToolMaterials(int miningLevel, int itemDurability, float miningSpeed, float attackDamage, int enchantability, Supplier<Ingredient> repairIngredient) {
this.miningLevel = miningLevel;
this.itemDurability = itemDurability;
this.miningSpeed = miningSpeed;
this.attackDamage = attackDamage;
this.enchantability = enchantability;
this.repairIngredient = new Lazy<>(repairIngredient);
}

我们直接来看其中的WOOD和这个类的构造方法,可以看到这里有很多参数

itemDurability是工具的耐久度

miningSpeed是基础挖掘速度

attackDamage是基础攻击伤害

enchantability是附魔等级,数值越高则可能获得的附魔效果越好

repairIngredient是工具的修复材料,也就是你在铁砧上修复工具用到的材料

后面的话就是一堆重写方法,那个是实现ToolMaterial接口必须重写的方法,
其实也就是返回上面的这些参数

1
2
3
4
5
6
WOOD(MiningLevels.WOOD, 59, 2.0F, 0.0F, 15, () -> Ingredient.fromTag(ItemTags.PLANKS)),
STONE(MiningLevels.STONE, 131, 4.0F, 1.0F, 5, () -> Ingredient.fromTag(ItemTags.STONE_TOOL_MATERIALS)),
IRON(MiningLevels.IRON, 250, 6.0F, 2.0F, 14, () -> Ingredient.ofItems(Items.IRON_INGOT)),
DIAMOND(MiningLevels.DIAMOND, 1561, 8.0F, 3.0F, 10, () -> Ingredient.ofItems(Items.DIAMOND)),
GOLD(MiningLevels.WOOD, 32, 12.0F, 0.0F, 22, () -> Ingredient.ofItems(Items.GOLD_INGOT)),
NETHERITE(MiningLevels.NETHERITE, 2031, 9.0F, 4.0F, 15, () -> Ingredient.ofItems(Items.NETHERITE_INGOT));

我们回过头来看看这些不同的工具材料对应的属性

自然,下界合金耐久度是最高的,但金质工具的采集速度是最高的(当然耐久也是最低的)

物品注册

自定义工具材料

那么接下来我们就来写我们的工具,首先是写工具材料

这里呢,为了与之前的ICE ETHER相区分,我已先行添加了一个新物品FIRE ETHER和它相关的各类文件

大家写的时候呢可以按照自己的实际情况来

1
public static final Item FIRE_ETHER = registerItems("fire_ether", new Item(new Item.Settings()));

接下去创建ModToolMaterials类,注意是枚举类,同时实现ToolMaterial这个接口

1
2
3
public enum ModToolMaterials implements ToolMaterial {
;
}

那么随后就是重写那些实现ToolMaterial要重写的方法

不过,在此之前,先从原版类中搬些参数过来

1
2
3
4
5
6
private final int miningLevel;
private final int itemDurability;
private final float miningSpeed;
private final float attackDamage;
private final int enchantability;
private final Supplier<Ingredient> repairIngredient;

这里的repairIngredient的类型我们改为Supplier类型的,原版是Lazy类型

然后创建构造函数,初始化这些参数

1
2
3
4
5
6
7
8
ModToolMaterials(int miningLevel, int itemDurability, float miningSpeed, float attackDamage, int enchantability, Supplier<Ingredient> repairIngredient) {
this.miningLevel = miningLevel;
this.itemDurability = itemDurability;
this.miningSpeed = miningSpeed;
this.attackDamage = attackDamage;
this.enchantability = enchantability;
this.repairIngredient = repairIngredient;
}

随后,后面的那些要重写的方法就可以写了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Override
public int getDurability() {
return this.itemDurability;
}

@Override
public float getMiningSpeedMultiplier() {
return this.miningSpeed;
}

@Override
public float getAttackDamage() {
return this.attackDamage;
}

@Override
public int getMiningLevel() {
return this.miningLevel;
}

@Override
public int getEnchantability() {
return this.enchantability;
}

@Override
public Ingredient getRepairIngredient() {
return this.repairIngredient.get();
}

好,那么最后就是写我们自己的工具材料了,写法与原版的类似

1
2
FIRE_ETHER(4, 2031, 12.0F, 4.0F, 50,
() -> Ingredient.ofItems(ModItems.FIRE_ETHER));

这里的采集等级我们就直接定义为4,与下界合金是同一个等级的

后面的参数根据你自己的需求去写就可以了,只是这里的修复材料是我前面预先写好的FIRE ETHER

大家根据你自己模组的实际编写即可

物品注册

那么接下来就是物品的注册

1
2
3
4
5
6
7
8
9
10
public static final Item FIRE_ETHER_SWORD = registerItems("fire_ether_sword", new SwordItem(ModToolMaterials.FIRE_ETHER,
3, -2.0F, new Item.Settings()));
public static final Item FIRE_ETHER_SHOVEL = registerItems("fire_ether_shovel", new ShovelItem(ModToolMaterials.FIRE_ETHER,
1.5f, -3.0F, new Item.Settings()));
public static final Item FIRE_ETHER_PICKAXE = registerItems("fire_ether_pickaxe", new PickaxeItem(ModToolMaterials.FIRE_ETHER,
2, -2.8F, new Item.Settings()));
public static final Item FIRE_ETHER_AXE = registerItems("fire_ether_axe", new AxeItem(ModToolMaterials.FIRE_ETHER,
6.0f, -3.2F, new Item.Settings()));
public static final Item FIRE_ETHER_HOE = registerItems("fire_ether_hoe", new HoeItem(ModToolMaterials.FIRE_ETHER,
-4, 0.0F, new Item.Settings()));

一共是5个工具,实例化的类不要搞错了

这里我们来讲一下中间的两个数字,上面也提到了,一个是额外攻击伤害,另一个是额外攻击速度

工具的最终攻击伤害攻击速度是由材料提供的基础伤害攻速,加上这里的额外属性得到的

相对而言,的额外伤害是比较高的,原版是石斧有着最高的额外伤害,但同样,攻速会比较低,CD长

的话,还相对平均一点,有比较高的攻击伤害和攻速

呢,你要拿它来当武器,那就不太现实了,因为它的额外攻击伤害一般都是的,还是老老实实拿它锄地吧

其他的可以参考原版的那些工具来写

加入物品栏

完成物品注册之后,不要忘了将物品加入物品栏

1
2
3
4
5
entries.add(ModItems.FIRE_ETHER_SWORD);
entries.add(ModItems.FIRE_ETHER_SHOVEL);
entries.add(ModItems.FIRE_ETHER_PICKAXE);
entries.add(ModItems.FIRE_ETHER_AXE);
entries.add(ModItems.FIRE_ETHER_HOE);

数据生成

语言文件

1
2
3
4
5
translationBuilder.add(ModItems.FIRE_ETHER_SWORD, "Fire Ether Sword");
translationBuilder.add(ModItems.FIRE_ETHER_SHOVEL, "Fire Ether Shovel");
translationBuilder.add(ModItems.FIRE_ETHER_PICKAXE, "Fire Ether Pickaxe");
translationBuilder.add(ModItems.FIRE_ETHER_AXE, "Fire Ether Axe");
translationBuilder.add(ModItems.FIRE_ETHER_HOE, "Fire Ether Hoe");

模型文件

工具类的模型文件与一般的物品模型有所区别

1
2
3
4
5
itemModelGenerator.register(ModItems.FIRE_ETHER_SWORD, Models.HANDHELD);
itemModelGenerator.register(ModItems.FIRE_ETHER_SHOVEL, Models.HANDHELD);
itemModelGenerator.register(ModItems.FIRE_ETHER_PICKAXE, Models.HANDHELD);
itemModelGenerator.register(ModItems.FIRE_ETHER_AXE, Models.HANDHELD);
itemModelGenerator.register(ModItems.FIRE_ETHER_HOE, Models.HANDHELD);

这里我们使用是父模型是HANDHELD,也就是手持物品的父模型

测试

那么跑好数据生成之后,放好对应的贴图文件,我们就可以进入游戏进行测试了