跳到主要内容
版本:1.21.5

物品(Items)

与方块一起,物品是Minecraft的关键组成部分。虽然方块构成了你周围的世界,但物品存在于库存中。

什么是物品?

在我们进一步创建物品之前,重要的是要理解物品实际上是什么,以及它与方块(block)的区别。让我们用一个例子来说明:

  • 在世界中,你遇到一个泥土方块并想要挖掘它。这是一个方块,因为它被放置在世界中。(实际上,它不是方块,而是方块状态。有关更详细的信息,请参见方块状态文章(Blockstates article)。)
  • 一旦你挖掘了方块,它被移除(=被空气方块替换)并掉落泥土。掉落的泥土是一个物品**实体(entity)**。这意味着像其他实体(猪、僵尸、箭等)一样,它本质上可以被水推动或火和熔岩燃烧。
  • 一旦你捡起泥土物品实体,它就成为你库存中的物品堆栈。物品堆栈简单来说就是具有一些额外信息的物品实例,例如堆叠大小。
  • 物品堆栈由其对应的物品支持(这就是我们正在创建的)。物品持有数据组件(data components),其中包含所有物品堆栈初始化的默认信息(例如,每把铁剑的最大耐久度为250),而物品堆栈可以修改这些数据组件,允许同一物品的两个不同堆栈具有不同的信息(例如,一把铁剑剩余100次使用,而另一把铁剑剩余200次使用)。有关通过物品完成什么和通过物品堆栈完成什么的更多信息,请继续阅读。
    • 物品和物品堆栈之间的关系大致与方块(blocks)方块状态(blockstates)之间的关系相同,因为方块状态总是由方块支持。这不是一个非常准确的比较(例如,物品堆栈不是单例),但它很好地基本概念。

创建物品

现在我们已经理解了物品是什么,让我们创建一个!

与基本方块一样,对于不需要特殊功能的基本物品(想想木棍、糖等),可以直接使用Item类。为此,在注册期间,使用Item.Properties参数实例化Item。这个Item.Properties参数可以使用Item.Properties#of创建,并可以通过调用其方法进行自定义:

  • setId - 设置物品的资源键。
    • 必须在每个物品上设置;否则,将抛出异常。
  • overrideDescription - 设置物品的翻译键。创建的Component存储在DataComponents#ITEM_NAME中。
  • useBlockDescriptionPrefix - 便利助手,使用翻译键block.<modid>.<registry_name>调用overrideDescription。这应在任何BlockItem上调用。
  • requiredFeatures - 设置此物品所需的特性标志。这主要用于原版在次要版本中的特性锁定系统。不鼓励使用此功能,除非你正在集成到由原版锁定在特性标志后面的系统。
  • stacksTo - 设置此物品的最大堆叠大小(通过DataComponents#MAX_STACK_SIZE)。默认为64。例如,末影珍珠或其他仅堆叠到16的物品使用此功能。
  • durability - 设置此物品的耐久度(通过DataComponents#MAX_DAMAGE)并将初始伤害设置为0(通过DataComponents#DAMAGE)。默认为0,表示"无耐久度"。例如,铁工具在此处使用250。请注意,设置耐久度会自动将最大堆叠大小锁定为1。
  • fireResistant - 使使用此物品的物品实体对火和熔岩免疫(通过DataComponents#FIRE_RESISTANT)。各种下界合金物品使用此功能。
  • rarity - 设置此物品的稀有度(通过DataComponents#RARITY)。目前,这只是改变物品的颜色。Rarity是一个枚举,由四个值组成:COMMON(白色,默认)、UNCOMMON(黄色)、RARE(水色)和EPIC(浅紫色)。请注意,模组可能会添加更多稀有度类型。
  • setNoCombineRepair - 禁用此物品的砂轮和合成网格修复。原版中未使用。
  • jukeboxPlayable - 设置插入唱片机时播放的数据包JukeboxSong的资源键。
  • food - 设置此物品的FoodProperties(通过DataComponents#FOOD)。

有关示例,或查看Minecraft使用的各种值,请查看Items类。

剩余物和冷却时间

物品在使用的可能有其他属性,或在一段时间内阻止物品被使用:

  • craftRemainder - 设置此物品的合成剩余物。原版使用此功能用于合成后留下空桶的装满的桶。
  • usingConvertsTo - 设置通过Item#useIItemExtension#finishUsingItemItem#releaseUsing完成使用物品后返回的物品。ItemStack存储在DataComponents#USE_REMAINDER上。
  • useCooldown - 设置物品可以再次使用之前的秒数(通过DataComponents#USE_COOLDOWN)。

工具和盔甲

一些物品像[工具(tools)]和[盔甲(armor)]一样工作。这些通过一系列物品属性构建,只有一些使用委托给其关联类:

  • enchantable - 设置堆栈的最大[附魔(enchantment)]值,允许物品被附魔(通过DataComponents#ENCHANTABLE)。
  • repairable - 设置可用于修复此物品耐久度的物品或标签(通过DataComponents#REPAIRABLE)。必须具有耐久度组件且没有DataComponents#UNBREAKABLE
  • equippable - 设置物品可以装备到的槽位(通过DataComponents#EQUIPPABLE)。
  • equippableUnswappable - 与equippable相同,但禁用通过使用物品按钮(默认右键单击)的快速交换。

更多信息可以在其相关页面上找到。

更多功能

直接使用Item只允许非常基本的物品。如果你想添加功能,例如右键单击交互,需要一个扩展Item的自定义类。Item类有许多可以重写以执行不同操作的方法;有关更多信息,请参见类ItemIItemExtension

物品的两个最常见用例是左键单击和右键单击。由于它们的复杂性以及它们涉及其他系统,它们在单独的交互文章(Interaction article)中解释。

DeferredRegister.Items

所有注册表都使用DeferredRegister来注册其内容,物品也不例外。然而,由于添加新物品是绝大多数模组的基本功能,NeoForge提供了DeferredRegister.Items辅助类,它扩展DeferredRegister<Item>并提供一些特定于物品的辅助方法:

public static final DeferredRegister.Items ITEMS = DeferredRegister.createItems(ExampleMod.MOD_ID);

public static final DeferredItem<Item> EXAMPLE_ITEM = ITEMS.registerItem(
"example_item",
Item::new, // 属性将传递到的工厂。
new Item.Properties() // 要使用的属性。
);

在内部,这将简单地调用ITEMS.register("example_item", registryName -> new Item(new Item.Properties().setId(ResourceKey.create(Registries.ITEM, registryName)))),通过将属性参数应用于提供的物品工厂(通常是构造函数)。id在属性上设置。

如果你想使用Item::new,可以完全省略工厂并使用simple方法变体:

public static final DeferredItem<Item> EXAMPLE_ITEM = ITEMS.registerSimpleItem(
"example_item",
new Item.Properties() // 要使用的属性。
);

这与前一个示例完全相同,但稍微短一些。当然,如果你想使用Item的子类而不是Item本身,你将不得不使用前一个方法。

这两种方法也有省略new Item.Properties()参数的重载:

public static final DeferredItem<Item> EXAMPLE_ITEM = ITEMS.registerItem("example_item", Item::new);

// 也省略Item::new参数的变体
public static final DeferredItem<Item> EXAMPLE_ITEM = ITEMS.registerSimpleItem("example_item");

最后,还有方块物品的快捷方式。与setId一起,这些也调用useBlockDescriptionPrefix将翻译键设置为用于方块的翻译键:

public static final DeferredItem<BlockItem> EXAMPLE_BLOCK_ITEM = ITEMS.registerBlockItem(
"example_block",
BlockItem::new, // 属性将传递到的工厂。
new Item.Properties() // 要使用的属性。
);

// 使用BlockItem::new的简单变体
public static final DeferredItem<BlockItem> EXAMPLE_BLOCK_ITEM = ITEMS.registerSimpleBlockItem(
"example_block",
new Item.Properties() // 要使用的属性。
);

物品堆栈

如前所述,物品堆栈是物品的实例。它们包含有关特定物品堆栈的信息,例如其堆叠大小、耐久度、附魔等。物品堆栈通过ItemStack类表示。

创建物品堆栈

创建物品堆栈的最简单方法是使用其构造函数:

// 从物品创建物品堆栈
ItemStack stack = new ItemStack(EXAMPLE_ITEM.get());

// 从物品创建具有特定数量的物品堆栈
ItemStack stack = new ItemStack(EXAMPLE_ITEM.get(), 16);

// 从物品创建具有特定数量和数据的物品堆栈
ItemStack stack = new ItemStack(EXAMPLE_ITEM.get(), 16, new CompoundTag());

修改物品堆栈

物品堆栈可以通过各种方法修改:

// 设置堆叠大小
stack.setCount(32);

// 设置耐久度
stack.setDamageValue(50);

// 设置附魔
stack.enchant(Enchantments.SHARPNESS, 3);

// 设置自定义名称
stack.setHoverName(Component.literal("自定义物品"));

// 设置自定义数据组件
stack.set(DataComponents.CUSTOM_DATA, new CompoundTag());

查询物品堆栈

你可以查询物品堆栈的各种属性:

// 获取物品
Item item = stack.getItem();

// 获取堆叠大小
int count = stack.getCount();

// 获取最大堆叠大小
int maxStackSize = stack.getMaxStackSize();

// 检查是否为空
boolean isEmpty = stack.isEmpty();

// 检查是否损坏
boolean isDamaged = stack.isDamaged();

// 检查是否可修复
boolean isRepairable = stack.isRepairable();

// 检查是否可附魔
boolean isEnchantable = stack.isEnchantable();

物品实体

当物品掉落在地面上时,它成为一个物品实体。物品实体是ItemEntity类的实例,它扩展Entity

创建物品实体

创建物品实体相对简单:

// 在世界中创建物品实体
ItemEntity itemEntity = new ItemEntity(
level, // 世界
x, y, z, // 位置
stack // 物品堆栈
);

// 可选:设置速度
itemEntity.setDeltaMovement(dx, dy, dz);

// 可选:设置拾取延迟
itemEntity.setPickUpDelay(20); // 20刻 = 1秒

// 将实体添加到世界
level.addFreshEntity(itemEntity);

物品实体属性

物品实体具有各种属性:

  • pickupDelay - 实体可以被捡起之前的刻数。
  • thrower - 抛出实体的玩家的UUID。
  • owner - 实体所有者的UUID(用于防止其他玩家捡起)。
  • age - 实体已存在的刻数。超过6000刻(5分钟)后,实体将消失。

最佳实践

  1. 使用适当的物品属性:根据物品的用途设置适当的属性(耐久度、最大堆叠大小等)。
  2. 考虑性能:避免在每刻检查物品堆栈,因为这会严重影响性能。
  3. 使用数据组件:对于自定义数据,使用数据组件而不是NBT标签。
  4. 正确处理物品实体:确保物品实体有适当的拾取延迟,以防止立即被捡起。
  5. 本地化:为所有物品提供适当的翻译键。

通过遵循这些指南,你可以有效地在模组中创建和使用物品。