User Tools

Site Tools


zh_cn:tutorial:items

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
zh_cn:tutorial:items [2021/01/16 06:26] – [创建物品类] solidblockzh_cn:tutorial:items [2024/12/08 14:24] (current) – [创建物品实例] solidblock
Line 1: Line 1:
-====== 添加一个物品 ======+====== 添加物品 ======
  
-==== 介绍 ====+===== 介绍 ====
 + 
 +添加基本的物品是编写模组的第一步。你将需要创建 ''Item'' 对象,注册,并提供纹理。要向物品添加其他行为,你将需要自定义的 ''Item'' 类。在本教程以及以后的所有教程中,均使用 ''tutorial'' 作为命名空间。如果你有单独的模组 ID,那就直接使用它。 
 +===== 创建物品实例 ===== 
 +:!: 如果是使用的 1.21.2 之后的版本,请直接跳到[[#在 1.21.2+ 中创建物品]]。 
 + 
 +首先,创建 ''Item'' 的实例,存储为静态常量字段。''Item'' 的构造方法接受一个 ''Item.Settings''(或 ''FabricItemSettings'',除非是 1.20.5 以上版本)对象,该对象用于设置物品属性,例如耐久和堆叠数量。为了简便,就直接在 ''ExampleMod'' 中做了,然后存为静态字段。 
 + 
 +<yarncode java [enable_line_numbers="true"]> 
 +public class ExampleMod implements ModInitializer {
  
-添加一个基本的物品是编写模组的第一步。 你将需要创建一个''Item''对象,注册它,并赋予它一个材质。要向物品添加其他行为,你将需要一个自定义的''Item''类。 在本教程以及以后的所有教程中,''tutorial''命名空间均用作模组的ID的占位符。如果你有单独的模组ID,则应当使用它。 
-==== 注册物品 ==== 
-首先,创建一个''Item''的实例。我们将其存放在模组主类的顶部。''Item''的构造方法接受一个''Item.Settings''(或''FabricItemSettings'')对象,该对象用于设置物品属性,例如创造模式物品栏中的分类、耐久和堆叠数量。 
-<code java [enable_line_numbers="true"]> 
-public class ExampleMod implements ModInitializer 
-{ 
     // 新物品的实例     // 新物品的实例
-    public static final Item FABRIC_ITEM = new Item(new FabricItemSettings().group(ItemGroup.MISC));+    // 对于 1.20.4 以下版本 
 +    public static final class_1792 CUSTOM_ITEM = new class_1792(new FabricItemSettings()); 
 +    // 对于 1.20.5 之后,1.21.2 之前的版本 
 +    public static final class_1792 CUSTOM_ITEM = new class_1792(new class_1792.class_1793());
     [...]     [...]
 } }
-</code+</yarncode
-这里使用原版注册方式来注册,基本语法''Registry#register(Registry TypeIdentifierContent)''注册表类型存储为''Registry''对象内的静态字段,标识符用来给内容“加标签”Content则添加的东西的一个实例。可以随时调用,只要发生在初始化阶段。 + 
-<code java [enable_line_numbers="true"]> +===== 注册物品 ===== 
-public class ExampleMod implements ModInitializer + 
-{+我们创建了基本的物品,但是在 Minecraft 中还不存在,因为还没有注册。在 Minecraft 中,几乎所有东西都有注册表,物品也不例外。 
 + 
 +注册新的内容使用原版注册,基本语法为 ''<yarn class_2378>.<yarn method_10230>(注册表类型<yarn class_2960>内容)''注册表类型存储为 ''<yarn class_7923>'' 或 ''<yarn class_2378>''的静态字段ID(identifier)则是注你的内容内容添加的东西的实例。对于物品而言,语法就是 ''<yarn class_2378>#<yarn method_10230>(<yarn class_7923>.<yarn field_41178>, <yarn class_2960>, <yarn class_1792>)''可以在初始化过程的任何地方调用它,方法本身会返回物品的实例 
 + 
 +对于 1.21 之后的版本,''Identifier'' 是通过 ''%%Identifier.of("namespace", "path")%%'' 创建的。对于 1.21 之前的版本,是通过 ''%%new Identifier("namespace", "path")%%'' 或 ''%%new Identifier("namespace:path")%%''。当命名空间或路径包含非法字符(例如大写字母、中文)时,会失败。 
 + 
 +<yarncode java [enable_line_numbers="true"]> 
 +public class ExampleMod implements ModInitializer {
     // 新物品的实例     // 新物品的实例
-    public static final Item FABRIC_ITEM = new Item(new FabricItemSettings().group(ItemGroup.MISC)); +    public static final class_1792 CUSTOM_ITEM = new class_1792(new class_1792.class_1793()); 
-      +
     @Override     @Override
-    public void onInitialize() +    public void onInitialize() { 
-    +        // 对于 1.21 之前的版本,请将 ''Identifier.of'' 替换为 ''new Identifier'' 
-        Registry.register(Registry.ITEMnew Identifier("tutorial", "fabric_item"), FABRIC_ITEM); +        class_2378.method_10230(class_7923.field_41178, Identifier.of("tutorial", "custom_item"), CUSTOM_ITEM); 
-    } +    } 
 +</yarncode> 
 + 
 +现在新物品已添加到 Minecraft 中,运行“Minecraft Client”运行配置或者 ''runClient'' Gradle任务以查看它的运行情况,在游戏内执行命令 ''/​give @s tutorial:​custom_item''​。 
 + 
 +===== 注册物品的最佳实践 ===== 
 + 
 +在上面的代码中,简直创建了//一个//物品。但是,如果模组有//许多//物品,则这样并不方块,因为你每次都需要注册、创建一个 ''Identifier''。所以我们创建一个专门的类存储物品对象,例如 ''ModItems'' 或者 ''TutorialItems'',然后简单的 ''register'' 方法便捷地注册物品。这在实际模组开发中很常见。你也可以看看原版的 ''Items'' 类以了解 Minecraft 中如何以类似方式完成的。 
 + 
 +在这个例子中,创建一个 ''TutorialItems'' 类,并在 ''ModInitializer'' 中引用这个类。 
 + 
 +<yarncode java [enable_line_numbers="true"]> 
 +public final class TutorialItems { 
 + 
 +    private TutorialItems() {} 
 +     
 +    // 新物品的实例 
 +    public static final class_1792 CUSTOM_ITEM = register("custom_item", new class_1792(new class_1792.class_1793())); 
 + 
 +    public static <T extends Item> T register(String path, T item) { 
 +        // 对于 1.21 之前的版本,请将 ''Identifier.of'' 替换为 ''new Identifier'' 
 +        return class_2378.method_10230(class_7923.field_41178, Identifier.of("tutorial", path), item); 
 +    } 
 +     
 +    public static void initialize() { 
 +    }
 } }
 +</yarncode>
 +
 +记得在模组初始化过程中引用模组的一些方法或字段,从而静态加载 ''TutorialItems'' 类。
 +<yarncode java [enable_line_numbers="true"]>
 +public class ExampleMod implements ModInitializer {
 +    @Override
 +    public void onInitialize() {
 +        TutorialItems.initialize();
 +    }
 +}
 +</yarncode>
 +
 +> **注意:**一些有经验的用户也可能会决定使用反射来自动注册一个类的所有静态字段。这也可以,但是请小心使用。
 +
 +===== 在 1.21.2+ 中创建物品 =====
 +
 +从 1.21.2 开始,物品注册重写了。你需要把 ''RegistryKey'' 存储到 ''Item.Settings'' 中,这样模型和翻译键才会正确地存储在物品组件中。否则,就会看到下面的异常,Minecraft 也不会运行:
 +
 +<code>
 +java.lang.NullPointerException: Item id not set
 </code> </code>
-现在新物品已添加到Minecraft中,运行''runClient'' Gradle任务以查看它的运行情况。 
  
-{{:tutorial:2019-02-17_16.50.44.png?400|}}+要让它正常运行,就要像下面这样写:
  
-==== 添加物品材质 ====+<code java> 
 +public final class TutorialItems { 
 +  private TutorialItems() { 
 +  }
  
-为物品注册材质需要物品模型.json文件和材质图像文件。 您将需要将它们添加到资源目录中。每个的直接路径是:+  public static final Item CUSTOM_ITEM = register("custom_item", Item::new, new Item.Settings());
  
-    物品模型: <根目录>/resources/assets/tutorial/models/item/fabric_item.json +  public static Item register(String path, Function<Item.Settings, Itemfactory, Item.Settings settings) { 
-    物品材质<根目录>/resources/assets/tutorial/textures/item/fabric_item.png +    final RegistryKey<Item> registryKey = RegistryKey.of(RegistryKeys.ITEM, Identifier.of("tutorial", path)); 
-我们将使用[[https://i.imgur.com/CqLSMEQ.png|个示例材质]]+    return Items.register(registryKey, factory, settings); 
 +  } 
 + 
 +  public static void initialize() { 
 +  } 
 +
 +</code> 
 + 
 +在方法 ''Items.register'' 中,注册表键(registry key)会先写到 ''settings'' 中,然后使用那个 ''settings'' 去创建物品。 
 + 
 +===== 添加物品纹理 ===== 
 + 
 +如果第一步成功注册了你的物品,就可以成输入命令 ''/give @s tutorial:custom_item'' 成功得到你的物品。你会发现纹理缺乏,Minecraft 会像这样报错: 
 + 
 +    [Server-Worker-1/WARN]: Unable to load model: 'tutorial:custom_item#inventory' referenced from: tutorial:custom_item#inventory: java.io.FileNotFoundException: tutorial:models/item/custom_item.json 
 + 
 +这是因为我们还没有给物品提供纹理和模型。所以,你需要定义物品模组并提供纹理图像。你会需要将这些添加到你的资源的目的下,直接路径如下: 
 + 
 +为物品注册纹理需要物品模型.json文件和纹理图像文件。 您将需要将它们添加到资源目录中。每个的直接路径是:
  
-如果您在第一步中正确注册了物品,则游戏将以类似于以下方式的方式抱怨缺少材质文件:+  * 物品模型:''.../resources/assets/tutorial/models/item/custom_item.json'' 
 +  * 物品纹理:''.../resources/assets/tutorial/textures/item/custom_item.png''
  
-    [Server-Worker-1/WARN]: Unable to load model: 'tutorial:fabric_item#inventory' referenced from: tutorial:fabric_item#inventory: java.io.FileNotFoundException: tutorial:models/item/fabric_item.json +我们将使用[[https://i.imgur.com/CqLSMEQ.png|这个示例纹理]]
-游戏能很方便地告诉你它想要的资源路径。遇事不决,日志解决+
  
 一个非常简单的物品模型长这个样子: 一个非常简单的物品模型长这个样子:
 <code JavaScript> <code JavaScript>
 { {
-  "parent": "builtin/generated",+  "parent": "item/generated",
   "textures": {   "textures": {
-    "layer0": "tutorial:item/fabric_item"+    "layer0": "tutorial:item/custom_item"
   }   }
 } }
 </code> </code>
-物品模型会将所有属性继承自父模型,例如对工具、方块等物品十分有用的自定义持模型(''item/handheld'')。这里的''builtin/generated''父模型告诉MC给出材质文件生成一个模型''textures/layer0''材质图像文件的位置。+你的物品模型的 ''parent''改变了物品中以及在物品栏内等情形下的渲染。''item/generated'' 用于许多简单物品。''item/handheld''于手持其纹理左下角物品。在 json 中,''textures/layer0'' 是图像文件的位置。
  
-最终材质的结果:+===== 创建物品类 =====
  
-{{:tutorial:item_texture.png?400|}}+要为物品添加自定义行为,则需要创建一个物品类。其默认的构造方法需要一个 ''Item.Settings'' 对象。
  
-==== 创建物品类 ==== +<yarncode java [enable_line_numbers="true"]> 
-要为物品添加自定义行为,则需要创建一个物品类。其默认的构造方法需要一个Item.Settings对象。 +public class CustomItem extends class_1792 {
-<code java [enable_line_numbers="true"]> +
-public class FabricItem extends Item {+
  
-    public FabricItem(Settings settings) {+    public CustomItem(class_1793 settings) {
         super(settings);         super(settings);
     }     }
 } }
-</code>+</yarncode> 
 自定义物品类的一个实际用例是使该物品在右击时播放声音: 自定义物品类的一个实际用例是使该物品在右击时播放声音:
-<code java [enable_line_numbers="true"]> +<yarncode java [enable_line_numbers="true"]> 
-public class FabricItem extends Item {+public class CustomItem extends class_1792 {
  
-    public FabricItem(Settings settings) {+    public CustomItem(class_1793 settings) {
         super(settings);         super(settings);
     }     }
-      + 
 +    // 1.21.2 之前的版本,请这么写:
     @Override     @Override
-    public TypedActionResult<ItemStackuse(World world, PlayerEntity playerEntityHand hand) { +    public class_1271<class_1799method_7836(class_1937 world, class_1657 userclass_1268 hand) { 
-        playerEntity.playSound(SoundEvents.BLOCK_WOOL_BREAK, 1.0F, 1.0F); +        user.method_5783(class_3417.field_14983, 1.0F, 1.0F); 
-        return TypedActionResult.success(playerEntity.getStackInHand(hand));+        return class_1271.method_22427(playerEntity.method_5998(hand))
 +    }  
 +     
 +    // 1.21.2 以及之后的版本,请这么写: 
 +    @Override 
 +    public ActionResult use(World world, PlayerEntity user, Hand hand) { 
 +        user.playSound(SoundEvents.BLOCK_WOOL_BREAK, 1.0F, 1.0F); 
 +        return ActionResult.SUCCESS;
     }     }
 } }
-</code>+</yarncode>
  
-用新物品类的实例替换旧的Item对象: +用新物品类的实例替换旧的 <yarn class_1792> 对象: 
-<code java [enable_line_numbers="true"]>+<yarncode java [enable_line_numbers="true"]>
 public class ExampleMod implements ModInitializer { public class ExampleMod implements ModInitializer {
-    //创建item的实例 + 
-    public static final FabricItem FABRIC_ITEM = new FabricItem(new FabricItemSettings().group(ItemGroup.MISC));+    // 新物品的实例 
 +     
 +    // 对于 1.21.2 之前的版本: 
 +    public static final CustomItem CUSTOM_ITEM register("custom_item", new CustomItem(new Item.Settings())); 
 +    // 对于 1.21.2 之后的版本: 
 +    public static final CustomItem CUSTOM_ITEM = register("custom_item", CustomItem::new, new Item.Settings());
     [...]     [...]
 } }
-</code>+</yarncode>
 如果你正确执行了所有操作,则使用该物品现在应该会播放声音。 如果你正确执行了所有操作,则使用该物品现在应该会播放声音。
  
-==== 如果我想更改物品的堆叠大小怎么办? ====+====物品组件 ====
 +有时你会想给物品添加一些默认的物品组件,例如最大堆叠数量或防火。可以通过调用 ''Item.Settings'' 的 ''component'' 方法来完成。关于物品组件的详细教程,可见 [[https://docs.fabricmc.net/zh_cn/develop/items/custom-data-components|Fabric Docs 上的教程]]。
  
-使用'FabricItemSettings''内的''maxCount(int size)''来指定最大堆叠数。请注意,如果你的物品是有耐久的(及耐久归零后会被破坏),那么此物品无法设置最大堆叠数,否则游戏将抛出运行时错误(''RuntimeException''。 +这个例子中,物品默认不可破坏,并隐藏关于这一点的物品提示: 
-<code java [enable_line_numbers="true"]>+<yarncode java> 
 +    // For versions below 1.21.2: 
 +    public static final CustomItem CUSTOM_ITEM = register("custom_item", new CustomItem(new class_1792.class_1793() 
 +        .component(DataComponentTypes.UNBREAKABLE, new UnbreakableComponent(true)))); 
 +    // For versions since 1.21.2: 
 +    public static final Item CUSTOM_ITEM = register("custom_item", CustomItem::new, new Item.Settings() 
 +        .component(DataComponentTypes.UNBREAKABLE, new UnbreakableComponent(true))); 
 +</yarncode> 
 + 
 +特别地,最大堆叠数可使用 ''Item.Settings'' 内的 ''maxCount(int size)'' 方法(在 1.20.5 之前也有效)来指定。请注意,如果你的物品是有耐久的,那么无法设置最大堆叠数,否则游戏将抛出 ''RuntimeException'' 
 + 
 +<yarncode java [enable_line_numbers="true"]>
 public class ExampleMod implements ModInitializer { public class ExampleMod implements ModInitializer {
 +    // 我们新物品的实例,最大堆叠数为 16
 +    
 +    // For versions below 1.21.2:
 +    public static final CustomItem CUSTOM_ITEM = register("custom_item", new CustomItem(new class_1792.class_1793().maxCount(16)));
 +    // For versions since 1.21.2:
 +    public static final Item CUSTOM_ITEM = register("custom_item", CustomItem::new, new Item.Settings().maxCount(16));
 +    [...]
 +}
 +</yarncode>
  
-    //我们新物品的实例,最大叠大小16 + 
-    public static final FabricItem FABRIC_ITEM = new FabricItem(new Item.Settings().group(ItemGroup.MISC).maxCount(16));+===== 让物品能作为燃料或者可肥 ===== 
 + 
 +如果需要让物品能作燃料在熔炉中燃烧,可以使用 ''FuelRegistry'',例如: 
 +<code java> 
 +public class ExampleMod implements ModInitializer {
     [...]     [...]
 +    
 +    // 对于 1.21.2 之前的版本
 +    @Override
 +    public void onInitialize() {
 +        [...]
 +        FuelRegistry.INSTANCE.add(CUSTOM_ITEM, 300);
 +    }
 } }
 </code> </code>
-==== 下一步 ====+ 
 +然而,在实践中,你可能有许多要注册的物品,注册大量物品可能会耗费精力而且乱,所以可以考虑把代码放到单独的方法中,而不是上面的写法。 
 + 
 +在 1.21.2 之前的版本,需要使用 Fabric API 的 ''FuelRegistry.INSTANCE''。 
 +<code java> 
 +public final class TutorialItems { 
 +    [...] 
 +     
 +    // 对于 1.21.2 之前的版本 
 +    public static void registerFuels() { 
 +        FuelRegistry.INSTANCE.add(CUSTOM_ITEM, 300); 
 +    } 
 +
 +</code> 
 + 
 +而自从 1.21.2 之后,使用的则是 Fabric API 的 ''FuelRegistryEvents'': 
 +<code java> 
 +public final class TutorialItems { 
 +    [...] 
 +     
 +    // 对于 1.21.2 之后的版本 
 +    public static void registerFuels() { 
 +        FuelRegistryEvents.BUILD.register((builder, context) -> { 
 +            // 可以一次在这个 lambda 中添加多个物品。 
 +            builder.add(CUSTOM_ITEM, 300); 
 +        }); 
 +    } 
 +
 +</code> 
 + 
 +然后在你的 ''ModInitializer'' 中提及此方法: 
 +<code java> 
 +public class ExampleMod implements ModInitializer { 
 +    [...] 
 +     
 +    @Override 
 +    public void onInitialize() { 
 +        [...] 
 +        TutorialItems.registerFuels(); 
 +    } 
 +
 +</code> 
 + 
 +类似地,你也可以使用 ''CompostingChanceRegistry'' 来让物品可以在堆肥桶中堆肥。 
 +===== 下一步 =====
 试着[[zh_cn:tutorial:itemgroup|将你的物品添加到一个物品组中]]。 试着[[zh_cn:tutorial:itemgroup|将你的物品添加到一个物品组中]]。
zh_cn/tutorial/items.1610778376.txt.gz · Last modified: 2021/01/16 06:26 by solidblock