Skip to main content
Version: 1.21.4

工具(Tools)

工具(Tools)是指主要用于破坏 方块物品。许多模组会添加新的工具套装(例如铜制工具)或新的工具类型(例如锤子)。

自定义工具套装(Custom Tool Sets)

一个工具套装通常包含五种物品:镐(pickaxe)、斧头(axe)、铲子(shovel)、锄头(hoe)和剑(sword)。(剑虽然严格来说不属于工具,但为了保持一致性也包含在内。)这些物品分别对应以下类:PickaxeItemAxeItemShovelItemHoeItemSwordItem。工具的类层级结构如下:

Item
- DiggerItem
- AxeItem
- HoeItem
- PickaxeItem
- ShovelItem
- SwordItem

工具几乎完全通过七个 数据组件 实现:

  • DataComponents#MAX_DAMAGE#DAMAGE 控制耐久度
  • #MAX_STACK_SIZE 将堆叠数量设置为 1
  • #REPAIRABLE 用于在铁砧中修复工具
  • #ENCHANTABLE 控制最大 附魔
  • #ATTRIBUTE_MODIFIERS 控制攻击伤害与攻击速度
  • #TOOL 提供挖掘信息

对于 DiggerItemSwordItem,它们本质上只是通过工具类 ToolMaterial 工具材料(utility record)来设置这些组件的委托。注意,其他通常被认为是工具的物品,比如剪刀(shears),并不属于这个类层级。它们直接继承自 Item,并自行实现破坏逻辑。

要使用 DiggerItemSwordItem 创建一套标准工具,首先需要定义一个 ToolMaterial。你可以参考 ToolMaterial 中的常量来设置参数。下面的示例以铜制工具为例,你可以根据需要替换为自己的材料,并调整参数。

// 我们将铜的属性设定在石头和铁之间。
public static final ToolMaterial COPPER_MATERIAL = new ToolMaterial(
// 决定该材料无法破坏哪些方块的标签。更多信息见下文。
MyBlockTags.INCORRECT_FOR_COPPER_TOOL,
// 决定该材料的耐久度。
// 石头为 131,铁为 250。
200,
// 决定该材料的挖掘速度。剑不使用此参数。
// 石头为 4,铁为 6。
5f,
// 决定攻击伤害加成。不同工具的用法不同。例如,剑的伤害为 (getAttackDamageBonus() + 4)。
// 石头为 1,铁为 2,分别对应剑的 5 和 6 点伤害;我们的剑现在造成 5.5 点伤害。
1.5f,
// 决定该材料的可附魔性。数值越高,附魔效果越好。
// 金为 22,我们将铜略低于此值。
20,
// 决定哪些物品可以修复该材料的标签。
Tags.Items.INGOTS_COPPER
);

现在我们已经有了自己的 ToolMaterial,接下来可以用它来注册工具。所有工具的构造函数都有相同的四个参数。

// ITEMS 是一个 DeferredRegister.Items
public static final DeferredItem<SwordItem> COPPER_SWORD = ITEMS.registerItem(
"copper_sword",
props -> new SwordItem(
// 要使用的材料。
COPPER_MATERIAL,
// 类型特定的攻击伤害加成。剑为 3,铲为 1.5,镐为 1,斧和锄有不同的值。
3,
// 类型特定的攻击速度修正。玩家默认攻击速度为 4,所以如果想要 1.6f,需要使用 -2.4f。剑为 -2.4f,铲为 -3f,镐为 -2.8f,斧和锄有不同的值。
-2.4f,
// 物品属性。
props
)
);

public static final DeferredItem<AxeItem> COPPER_AXE = ITEMS.registerItem("copper_axe", props -> new AxeItem(...));
public static final DeferredItem<PickaxeItem> COPPER_PICKAXE = ITEMS.registerItem("copper_pickaxe", props -> new PickaxeItem(...));
public static final DeferredItem<ShovelItem> COPPER_SHOVEL = ITEMS.registerItem("copper_shovel", props -> new ShovelItem(...));
public static final DeferredItem<HoeItem> COPPER_HOE = ITEMS.registerItem("copper_hoe", props -> new HoeItem(...));

标签(Tags)

当你创建一个 ToolMaterial(工具材料)时,它会被分配一个方块 标签,其中包含了用该工具破坏时不会掉落任何物品的方块。例如,minecraft:incorrect_for_stone_tool 标签包含了像钻石矿石这样的方块,而 minecraft:incorrect_for_iron_tool 标签包含了黑曜石和远古残骸等方块。为了方便地分配需要某种工具等级才能挖掘的方块,还存在一个标签,专门标记哪些方块需要这种工具。例如,minecraft:needs_iron_tool 标签包含了钻石矿石,而 minecraft:needs_diamond_tool 标签包含了黑曜石和远古残骸。

如果你觉得可以接受,也可以直接复用某个已有的错误标签(incorrect tag)给你的工具。例如,如果我们希望铜工具只是更耐用的石制工具,可以直接传入 BlockTags#INCORRECT_FOR_STONE_TOOL

当然,你也可以像下面这样自定义属于你自己的标签:

// 这个标签允许我们将这些方块加入不能被该工具挖掘的错误标签中
public static final TagKey<Block> NEEDS_COPPER_TOOL = TagKey.create(BuiltInRegistries.BLOCK.key(), ResourceLocation.fromNamespaceAndPath(MOD_ID, "needs_copper_tool"));

// 这个标签会传递给我们的材料
public static final TagKey<Block> INCORRECT_FOR_COPPER_TOOL = TagKey.create(BuiltInRegistries.BLOCK.key(), ResourceLocation.fromNamespaceAndPath(MOD_ID, "incorrect_for_cooper_tool"));

接下来,我们需要为自定义标签添加内容。例如,我们希望铜工具能够挖掘金矿石、金块和红石矿石,但不能挖掘钻石或绿宝石。(红石块本来石制工具就能挖掘。)标签文件应放在 src/main/resources/data/mod_id/tags/block/needs_copper_tool.json 路径下(其中 mod_id 替换为你的模组 id): 然后,为了让我们的标签(tag)传递给材料(material),我们可以为任何对石质工具(stone tools)不合适、但属于我们的铜工具(copper tools)标签内的工具,提供一个负向约束。该标签文件位于 src/main/resources/data/mod_id/tags/block/incorrect_for_cooper_tool.json

{
"values": [
"#minecraft:incorrect_for_stone_tool"
],
"remove": [
"#mod_id:needs_copper_tool"
]
}

最后,我们就可以像上面那样,将我们的标签传递进材料实例(material instance)中。

如果你想检查某个工具(tool)是否能让某个方块状态(block state)掉落其方块,调用 Tool#isCorrectForDrops 方法即可。可以通过调用 ItemStack#get 并传入 DataComponents#TOOL 来获取 Tool

自定义工具(Custom Tools)

你可以通过向物品(item)的默认组件列表添加一个 Tool 数据组件(通过 DataComponents#TOOL),并使用 Item.Properties#component 实现自定义工具。DiggerItem 是一个实现类,它会如上所述接收一个 ToolMaterial 来构造 Tool,并配合一些基础组件,例如属性(attributes)和耐久度(durability)。

一个 Tool 包含若干个 Tool.Rule,持有该工具时的默认挖掘速度(默认为 1),以及挖掘方块时工具应承受的伤害值(默认为 1)。每个 Tool.Rule 包含三部分信息:一个应用该规则的方块的 HolderSet,一个可选的挖掘这些方块的速度,以及一个可选的布尔值,用于判断这些方块是否可以由该工具掉落。如果可选项未设置,则会检查其他规则。如果所有规则都不适用,则使用默认的挖掘速度,并且该方块无法掉落。

note

可以通过 Registry#getOrThrow,从一个 TagKey 创建一个 HolderSet

创建任何工具或多功能工具类物品(multitool-like item,例如将斧头和镐子合二为一的物品),都不需要继承任何已存在的 DiggerItemSwordItem。你只需结合以下部分来实现即可:

  • 通过设置 Item.Properties#component 中的 DataComponents#TOOL,为物品添加自定义规则的 Tool(工具)。
  • 通过 Item.Properties#attributes 向物品添加 [属性修饰符][attributemodifier](如攻击伤害、攻击速度)。
  • 通过 Item.Properties#durability 为物品添加耐久度。
  • 通过 Item.Properties#repariable 允许物品被修复。
  • 通过 Item.Properties#enchantable 允许物品被附魔。
  • 重写 IItemExtension#canPerformAction 方法,以决定该物品可以执行哪些 ItemAbility(物品能力)
  • 如果你希望物品根据 ItemAbility 在右键点击时修改方块状态,可以调用 IBlockExtension#getToolModifiedState
  • 将你的工具添加到某些 minecraft:enchantable/* ItemTags(物品标签)中,以便该物品可以获得特定附魔。
  • 将你的工具添加到某些 minecraft:*_preferred_weapons 标签中,让生物更倾向于拾取和使用你的武器。

ItemAbility(物品能力)

ItemAbility(物品能力)是对物品可执行和不可执行行为的抽象。这包括左键和右键的行为。NeoForge 在 ItemAbilities 类中提供了默认的 ItemAbility

  • 挖掘能力。对于前面提到的四种 DiggerItem 类型,以及剑和剪刀的挖掘,都有对应的能力。
  • 斧头的右键能力,包括去皮(原木)、刮除(氧化铜)、去蜡(打蜡铜)。
  • 铁锹的右键能力,包括平整(泥土小路)和熄灭(营火)。
  • 剪刀的能力,包括收获(蜂巢)、移除护甲(装备护甲的狼)、雕刻(南瓜)、解除(绊线)、修剪(阻止植物生长)。
  • 其他能力包括剑的横扫、锄头的耕地、盾牌的格挡、鱼竿的抛钩、三叉戟的投掷、刷子的刷洗和火种的点燃。

要创建你自己的 ItemAbility,可以使用 ItemAbility#get —— 如果需要,它会创建一个新的 ItemAbility。然后,在自定义工具类型中,根据需要重写 IItemExtension#canPerformAction

如果你想查询一个 ItemStack 是否能执行某个特定的 ItemAbility,可以调用 IItemStackExtension#canPerformAction。注意,这对任何 Item(物品)都适用,不仅限于工具。

方块
数据组件
附魔
物品
物品能力
注册
标签