Table of Contents

物品组

这是 1.20+ 版本的教程,对于 1.19 版本,请阅读创建物品组(1.19)(英文)

现在,你可以使用命令 /give @s tutorial:custom_item 来获得你的物品。但是,不像原版物品,它还不存在于任何物品组中,你不能在创造模式轻易获取!有两种方式实现:

添加到任何物品组的物品都可以在创造模式物品栏中搜索到、

将物品添加到已存在的物品组

首先,先决定需要将物品添加到哪个物品组。例如,添加到建筑方块物品组。原版物品组存储在 ItemGroups 类中。

然后,需要为修改物品组创建事件处理器。

  1. public class ExampleMod implements ModInitializer {
  2. @Override
  3. public void onInitialize() {
  4. ItemGroupEvents.modifyEntriesEvent(ItemGroups.BUILDING_BLOCKS).register(content -> {
  5. content.add(TutorialItems.CUSTOM_ITEM);
  6. });
  7. }
  8. }

这个 modification event 也能够进行更加精细化的控制,例如将你的自定义物品放在特定的位置(例如,在 OAK_DOOR 的后面)或者其他的高级修改。每个你需要修改的物品组都需要自己的事件处理器,当然,同一个事件处理器可以用于给一个物品组添加多个物品。

物品可以添加到一个相对于原版物品的位置。仔细思考你的模组的用户会期望物品出现在哪里。例如,如果你添加一种新的类型的木头,那么将其添加到已有木头的后面或许是最合理的。

例如,以下这个事件监听器会将你的模组中的物品放在建筑方块物品组中的橡木门后面:

  1. public class ExampleMod implements ModInitializer {
  2. @Override
  3. public void onInitialize() {
  4. ItemGroupEvents.modifyEntriesEvent(ItemGroups.BUILDING_BLOCKS).register(content -> {
  5. content.addAfter(Items.OAK_DOOR, TutorialItems.CUSTOM_ITEM);
  6. });
  7. }
  8. }
在实践中,考虑到你注册的物品可能有很多,所以建议放在专门的方法中,而不是直接在你的 ModInitializer 里面。请看下面这个例子(如果这么写,记得撤销上面的代码):

  1. public final class TutorialItems {
  2. // [...]
  3.  
  4. public static void registerToVanillaItemGroups() {
  5. ItemGroupEvents.modifyEntriesEvent(ItemGroups.BUILDING_BLOCKS).register(content -> {
  6. content.addAfter(Items.OAK_DOOR, CUSTOM_ITEM);
  7. });
  8. }
  9. }
然后,记得在你的 ModInitializer 中引用那个方法。
  1. public class ExampleMod implements ModInitializer {
  2. @Override
  3. public void onInitialize() {
  4. TutorialItems.registerToVanillaItemGroups();
  5. }
  6. }

创建自定义物品组

创建物品组之前,先决定是否有足够多的内容以至于需要自己的物品组。你的物品组会放置在单独的标签页中,影响可见性。

如果你认为需要自己的物品组,可以使用 FabricItemGroup.builder 方法来创建物品组的构建器,并调用 build 方法来完成:

  1. public final class TutorialItemGroups {
  2. public static final ItemGroup TEST_GROUP = FabricItemGroup.builder()
  3. .icon(() -> new ItemStack(TutorialItems.CUSTOM_ITEM))
  4. .displayName(Text.translatable("itemGroup.tutorial.test_group"))
  5. .entries((context, entries) -> {
  6. entries.add(TutorialItems.CUSTOM_ITEM);
  7. })
  8. .build();
  9. }

你可以在 entries 方法中,将物品添加到你的物品组中。注意,不像原版的物品组,当你添加与已存在的物品相对位置的物品时,必须往你自己的物品组添加物品,因为没有原版的物品可以用来做为相对位置。

必须设置显示名称,否则会导致崩溃。

下一部是注册你的物品组。

  1. public final class TutorialItemGroups {
  2. // ....
  3.  
  4. public static void initialize() {
  5. // 自从 1.21:
  6. Registry.register(Registries.ITEM_GROUP, Identifier.of("tutorial", "test_group"), ITEM_GROUP);
  7.  
  8. // 在 1.21 之前:
  9. Registry.register(Registries.ITEM_GROUP, new Identifier("tutorial", "test_group"), ITEM_GROUP);
  10. }
  11. }

当然,也可以在给字段赋值时,直接注册:

  1. public final class TutorialItemGroups {
  2. public static final ItemGroup TEST_GROUP = Registry.register(Registries.ITEM_GROUP, new Identifier("tutorial", "test_group"), FabricItemGroup.builder()
  3. .icon(() -> new ItemStack(CUSTOM_ITEM))
  4. .displayName(Text.translatable("itemGroup.tutorial.test_group"))
  5. .entries((context, entries) -> {
  6. entries.add(TutorialItems.CUSTOM_ITEM);
  7. })
  8. .build());
  9.  
  10. public static void initialize() {
  11. }
  12. }

记得在你的 ModInitializer 中静态加载类。

  1. public class ExampleMod implements ModInitializer {
  2. @Override
  3. public void onInitialize() {
  4. TutorialItemGroups.initialize();
  5. }
  6. }

:!: 下面的截图已过时。