物品属性

物品属性

物品属性将物品的“属性”暴露给模型系统。例如弓最重要的属性是拉开的程度;系统利用它选择模型,形成拉弓动画。

物品属性覆盖示意:examplemod:power 返回 0.80;按顺序列出的阈值 0.25 和 0.75 均匹配,因此最终使用第二项模型;无匹配时使用默认模型。

原创说明图,依据 Forge 1.21.x 官方文档 绘制。

物品属性为注册该属性的每个 ItemStack 指定一个 float 值。原版物品模型定义可以用这些值定义“覆盖”:物品默认使用某个模型,但匹配覆盖条件时改用另一个模型。其主要优势在于值是连续的。例如弓的拉弓动画由浮点数谓词决定,数值不受限制,但通常在 0.0F 到 1.0F 之间。这让资源包可以在该范围内添加任意数量的动画模型,而不局限于四个模型“槽位”。指南针和时钟也是如此。

为物品添加属性

ItemProperties#register 为特定物品添加属性。Item 参数是目标物品(如 ExampleItems#APPLE);ResourceLocation 是属性名称(如 new ResourceLocation("pull"))。ItemPropertyFunction 是函数式接口,接收 ItemStack、所在 ClientLevel(可为 null)、持有它的 LivingEntity(可为 null)和持有实体 ID 的 int(可为 0),返回属性的 float 值。

Mod 属性建议使用 Mod ID 作为命名空间,例如 examplemod:property,而非仅写 property,后者实际表示 minecraft:property。应在 FMLClientSetupEvent 中执行。另有 ItemProperties#registerGeneric,用于给所有物品添加属性,不接收 Item 参数。

重要:使用 FMLClientSetupEvent#enqueueWork 执行任务,因为 ItemProperties 中的数据结构不是线程安全的。

注意:Mojang 已弃用 ItemPropertyFunction,推荐其子接口 ClampedItemPropertyFunction,它将结果限制在 0 到 1 之间。

使用覆盖

覆盖格式见 Minecraft Wiki,model/item/bow.json 也是一个好例子。以下假设物品具有 examplemod:power 属性。没有匹配值时默认使用当前模型;如果多个覆盖项匹配,选择列表中最后一个。

重要:谓词匹配所有大于或等于指定值的值。

带注释和省略号的示例用于说明结构;实际 JSON 文件需移除注释并补全内容。

{
  "parent": "item/generated",
  "textures": {
    // 默认
    "layer0": "examplemod:items/example_partial"
  },
  "overrides": [
    {
      // power >= .75
      "predicate": { "examplemod:power": 0.75 },
      "model": "examplemod:item/example_powered"
    }
  ]
}

下面是假设的配套代码片段。与低于 1.16.x 的旧版本不同,这必须仅在客户端执行,因为服务端不存在 ItemProperties。

private void setup(final FMLClientSetupEvent event) {
  event.enqueueWork(() -> {
    ItemProperties.register(ExampleItems.APPLE,
      ResourceLocation.fromNamespaceAndPath(ExampleMod.MODID, "pulling"), (stack, level, living, id) -> {
        return living != null && living.isUsingItem() && living.getUseItem() == stack ? 1.0F : 0.0F;
      });
  });
}

译注:原文模型使用 examplemod:power,示例代码却注册 pulling;若两者需要配合,须使用同一个属性名称。

原文:Item Properties。