User Tools

Site Tools


zh_cn:tutorial:blocks

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:blocks [2024/04/15 01:44] – 更新 solidblockzh_cn:tutorial:blocks [2024/12/08 14:23] (current) – [下一步] solidblock
Line 1: Line 1:
 ====== 添加方块 ====== ====== 添加方块 ======
  
-将方块添加到你的模组过程与[[zh_cn:tutorial:items|添加物品]]类似。你可以创建 ''Block'' 或自定义类的实例,然后将其注册到 ''Registries.BLOCK''(1.19.3 以上版本)或 ''Registry.BLOCK'' (1.19.2 以下)注册表。你还需要提供纹理和方块状态或模型文件以提供方块外观。如需了解方块模型格式的更多信息,请参考[[https://zh.minecraft.wiki/模型|Minecraft Wiki模型页面]]。+将方块添加到你的模组过程与[[zh_cn:tutorial:items|添加物品]]类似。你可以创建 ''Block'' 或自定义类的实例,然后将其注册到 ''Registries.BLOCK''(1.19.3 以上版本)或 ''Registry.BLOCK''(1.19.2 以下)注册表。你还需要提供纹理和方块状态或模型文件以提供方块外观。如需了解方块模型格式的更多信息,请参考[[https://zh.minecraft.wiki/模型|Minecraft Wiki 模型页面]]。
  
 ===== 创建方块 ===== ===== 创建方块 =====
 +:!: 使用你使用的是 1.21.2 或者之后的版本,请直接看 [[#在 1.21.2+ 中注册方块]]。
  
 首先创建 ''Block'' 的实例。该实例可以存储在任何地方,但是我们会在 ''ModInitializer'' 的顶部开始。''Block'' 构造器函数需要一个 ''AbstractBlock.Settings'' 实例,也就是用于配置方块属性的构造器。Fabric 提供一个 ''FabricBlockSettings'' 构造器类以及更多可用的选项。 首先创建 ''Block'' 的实例。该实例可以存储在任何地方,但是我们会在 ''ModInitializer'' 的顶部开始。''Block'' 构造器函数需要一个 ''AbstractBlock.Settings'' 实例,也就是用于配置方块属性的构造器。Fabric 提供一个 ''FabricBlockSettings'' 构造器类以及更多可用的选项。
  
-<code java [enable_line_numbers="true"]>+<code java [enable_line_numbers="true"ExampleMod.java>
 public class ExampleMod implements ModInitializer { public class ExampleMod implements ModInitializer {
  
Line 24: Line 25:
     // 对于 1.20.5 以下版本:     // 对于 1.20.5 以下版本:
     // public static final Block EXAMPLE_BLOCK = new Block(FabricBlockSettings.create().strength(4.0f));     // public static final Block EXAMPLE_BLOCK = new Block(FabricBlockSettings.create().strength(4.0f));
-    // 对于自 1.20.5 之后的版本:+    // 对于自 1.20.5 之后、1.21.2 以前的版本:
     public static final Block EXAMPLE_BLOCK = new Block(Block.Settings.create().strength(4.0f));     public static final Block EXAMPLE_BLOCK = new Block(Block.Settings.create().strength(4.0f));
          
Line 33: Line 34:
 } }
 </code> </code>
-==== 注册方块 ====+===== 注册方块 =====
  
-方块应该注册在 ''Registries.BLOCK'' 注册表中。调用 ''Registry.//register//'' 并传递适当的参数。你可以直接在 ''onInitialize'' 方法中注册方块,也可以在静态部分创建方块实例时将其注册,因为 ''register'' 方法会返回这个方块实例自身。+方块应该注册在 ''Registries.BLOCK'' 注册表中。和 [[items|物品]] 类似,调用 ''Registry.//register//'' 并传递适当的参数。你可以直接在 ''onInitialize'' 方法中注册方块,也可以在静态部分创建方块实例时将其注册,因为 ''register'' 方法会返回这个方块实例自身。
  
 如果你使用的是 1.19.2 以下的版本,请将 ''Registries.BLOCK'' 替换为 ''Registry.BLOCK'' 如果你使用的是 1.19.2 以下的版本,请将 ''Registries.BLOCK'' 替换为 ''Registry.BLOCK''
  
-<code java [enable_line_numbers="true",highlight_lines_extra="11"]>+<code java [enable_line_numbers="true",highlight_lines_extra="11"ExampleMod.java>
 public class ExampleMod implements ModInitializer { public class ExampleMod implements ModInitializer {
  
Line 46: Line 47:
     // 对于 1.20.5 以下版本:     // 对于 1.20.5 以下版本:
     // public static final Block EXAMPLE_BLOCK = new Block(FabricBlockSettings.create().strength(4.0f));     // public static final Block EXAMPLE_BLOCK = new Block(FabricBlockSettings.create().strength(4.0f));
-    // 对于自 1.20.5 之后的版本:+    // 对于自 1.20.5 之后、1.21.2 以前的版本:
     public static final Block EXAMPLE_BLOCK = new Block(Block.Settings.create().strength(4.0f));     public static final Block EXAMPLE_BLOCK = new Block(Block.Settings.create().strength(4.0f));
          
     @Override     @Override
     public void onInitialize() {     public void onInitialize() {
-        Registry.register(Registries.BLOCK, new Identifier("tutorial", "example_block"), EXAMPLE_BLOCK);+        // 对于 1.21 以下版本: 
 +        // Registry.register(Registries.BLOCK, new Identifier("tutorial", "example_block"), EXAMPLE_BLOCK); 
 +        // 对于 1.21 之后的版本: 
 +        Registry.register(Registries.BLOCK, Identifier.of("tutorial", "example_block"), EXAMPLE_BLOCK);
     }     }
 } }
 </code> </code>
  
-的方块不能作为物品存入背包,但可以通过使用 ''/setblock <位置> tutorial:example_block'' 在游戏中看到。+自定义方块不能作为物品存入背包,但可以通过使用 ''/setblock <位置> tutorial:example_block'' 在游戏中看到。
  
 ==== 为方块注册物品 ==== ==== 为方块注册物品 ====
Line 62: Line 66:
 在大多数情况下,您希望能够拿着物品放置方块。为此,您需要在物品注册表中注册一个相应的物品。您可以通过在 ''Registries.ITEM'' 下注册 ''BlockItem'' 的实例来执行此操作。该物品的注册表名称通常应与该方块的注册表名称相同。 在大多数情况下,您希望能够拿着物品放置方块。为此,您需要在物品注册表中注册一个相应的物品。您可以通过在 ''Registries.ITEM'' 下注册 ''BlockItem'' 的实例来执行此操作。该物品的注册表名称通常应与该方块的注册表名称相同。
  
-<code java [enable_line_numbers="true",highlight_lines_extra="12"]>+<code java [enable_line_numbers="true",highlight_lines_extra="12"ExampleMod.java>
 public class ExampleMod implements ModInitializer { public class ExampleMod implements ModInitializer {
  
Line 69: Line 73:
     // 对于 1.20.5 以下版本:     // 对于 1.20.5 以下版本:
     // public static final Block EXAMPLE_BLOCK = new Block(FabricBlockSettings.create().strength(4.0f));     // public static final Block EXAMPLE_BLOCK = new Block(FabricBlockSettings.create().strength(4.0f));
-    // 对于自 1.20.5 之后的版本:+    // 对于自 1.20.5 之后、1.21.2 之前的版本:
     public static final Block EXAMPLE_BLOCK = new Block(Block.Settings.create().strength(4.0f));     public static final Block EXAMPLE_BLOCK = new Block(Block.Settings.create().strength(4.0f));
          
Line 76: Line 80:
         Registry.register(Registries.BLOCK, new Identifier("tutorial", "example_block"), EXAMPLE_BLOCK);         Registry.register(Registries.BLOCK, new Identifier("tutorial", "example_block"), EXAMPLE_BLOCK);
         // 对于 1.20.5 以下版本:         // 对于 1.20.5 以下版本:
-        Registry.register(Registries.ITEM, new Identifier("tutorial", "example_block"), new BlockItem(EXAMPLE_BLOCK, new FabricItemSettings())); +        // Registry.register(Registries.ITEM, new Identifier("tutorial", "example_block"), new BlockItem(EXAMPLE_BLOCK, new FabricItemSettings())); 
-        // 对于自 1.20.之后的版本: +        // 对于 1.21 以下版本: 
-        Registry.register(Registries.ITEM, new Identifier("tutorial", "example_block"), new BlockItem(EXAMPLE_BLOCK, new Item.Settings()));+        // Registry.register(Registries.ITEM, new Identifier("tutorial", "example_block"), new BlockItem(EXAMPLE_BLOCK, new Item.Settings())); 
 +        // 对于 1.21 之后的版本: 
 +        Registry.register(Registries.ITEM, Identifier.of("tutorial", "example_block"), new BlockItem(EXAMPLE_BLOCK, new Item.Settings()));
     }     }
 } }
 </code> </code>
 +
 +===== 注册方块的最佳实践 =====
 +:!: 本段不适用于 1.21.2 之后的版本。
 +
 +有时你的模组有许多方块。如果这样注册,你会为每个方块都写这样复杂的代码,代码就会显乱。所以,类似于注册物品,我们为方块创建单独的类,以及一个实用方法以注册方块和物品。
 +
 +<code java TutorialBlocks.java>
 +public final class TutorialBlocks {
 +    public static final Block EXAMPLE_BLOCK = register("example_block", new Block(Block.Settings.create().strength(4.0f)));
 +    
 +    private static <T extends Block> T register(String path, T block) {
 +        Registry.register(Registries.BLOCK, Identifier.of("tutorial", path), block);
 +        Registry.register(Registries.ITEM, Identifier.of("tutorial", path), new BlockItem(block, new Item.Settings()));
 +        return block;
 +    }
 +    
 +    public static void initialize() {
 +    }
 +}
 +</code>
 +
 +记得要在 ''ModInitializer'' 类中初始化 ''TutorialBlocks'' 类。
 +<code java ExampleMod.java>
 +public class ExampleMod implements ModInitializer {
 +    @Override
 +    public void onInitialize() {
 +        TutorialBlocks.initialize();
 +    }
 +}
 +</code>
 +
 +===== 在 1.21.2+ 中注册方块 =====
 +在 1.21.2+ 中,要把 ''RegistryKey'' 添加到方块的 ''AbstractBlock.Settings'' 中,和物品的 ''Item.Settings'' 一起。看上去有点麻烦,不过好在 Minecraft 的 ''Blocks.//register//'' 和 ''Items.//register//'' 可以帮你做这些。
 +
 +<code java>
 +public class ExampleMod implements ModInitializer {
 +  public static final Block EXAMPLE_BLOCK = register("example_block", Block::new, Block.Settings.create().strength(4.0f));
 +
 +  private static Block register(String path, Function<AbstractBlock.Settings, Block> factory, AbstractBlock.Settings settings) {
 +    final Identifier identifier = Identifier.of("tutorial", path);
 +    final RegistryKey<Block> registryKey = RegistryKey.of(RegistryKeys.BLOCK, identifier);
 +
 +    final Block block = Blocks.register(registryKey, factory, settings);
 +    Items.register(block);
 +    return block;
 +  }
 +}
 +</code>
 +
 +上面的代码中,''Blocks.//register//'' 会帮助你将注册表键先写到 ''AbstractBlock.Settings'' 中,然后创建方块实例再注册。''Items.//register//'' 会直接创建简单的 ''BlockItem'' 实例,使用和方块一样的 ID,然后注册。如果需要更加复杂的制作,例如创建 ''BlockItem'' 的子类,可以调用其他一些也叫做 ''Items.//register//'' 但是有不同方法签名的方法。
  
 ===== 给予方块外观 ===== ===== 给予方块外观 =====
  
-你可能已经注意到,新的方块只是游戏中紫色和黑色棋盘格图案。这表明Minecraft加载方块资源或外观时出错。运行客户端时,完整的问题列表会输出在你的日志中。你需要以下文件来给予方块外观:+你可能已经注意到,新的方块只是游戏中紫色和黑色棋盘格图案。这表明 Minecraft 加载方块资源或外观时出错。运行客户端时,完整的问题列表会输出在你的日志中。你需要以下文件来给予方块外观:
  
   * 方块状态文件   * 方块状态文件
Line 134: Line 190:
 该方块必须有//战利品表//,以便在该方块被破坏时掉落物品。以下文件会使方块被破坏时掉落其本身。 该方块必须有//战利品表//,以便在该方块被破坏时掉落物品。以下文件会使方块被破坏时掉落其本身。
  
-<code JavaScript src/main/resources/data/tutorial/loot_tables/blocks/example_block.json>+对于 1.21 之后的版本,路径为 ''src/main/resources/data/tutorial/**loot_table**/blocks/example_block.json''(注意是单数)。对于 1.21 之前的版本,路径为 ''src/main/resources/data/tutorial/**loot_tables**/blocks/example_block.json''(复数)。 
 + 
 +<code JavaScript src/main/resources/data/tutorial/loot_table/blocks/example_block.json>
 { {
   "type": "minecraft:block",   "type": "minecraft:block",
Line 158: Line 216:
 条件 ''minecraft:survives_explosion'' 的意思是,如果方块是在带有损耗的爆炸(例如苦力怕的爆炸,而非 TNT 的爆炸)中破坏的,//有可能//不会掉落。如果没有这个条件,那么方块在带有损耗的爆炸中总是会掉落。 条件 ''minecraft:survives_explosion'' 的意思是,如果方块是在带有损耗的爆炸(例如苦力怕的爆炸,而非 TNT 的爆炸)中破坏的,//有可能//不会掉落。如果没有这个条件,那么方块在带有损耗的爆炸中总是会掉落。
  
-在1.17,破坏方块有所改变,定义采集工具和采集等级需要使用标签,请参考[[zh_cn:tutorial:tags|标签教程]]。我们需要将方块添加到以下标签:+在 1.17,破坏方块有所改变,定义采集工具和采集等级需要使用标签,请参考[[zh_cn:tutorial:tags|标签教程]]。我们需要将方块添加到以下标签:
  
- * 采集工具:''src/main/resources/data/minecraft/tags/blocks/mineable/<tooltype>.json'',其中 ''<tooltype>'' 可以是 ''axe''、''pickaxe''、''shovel''、''hoe'' +  * 采集工具:''src/main/resources/data/minecraft/tags/**block**/mineable/<tooltype>.json'',其中 ''<tooltype>'' 可以是 ''axe''、''pickaxe''、''shovel''、''hoe''(对于 1.21 以下的版本,把“//**block**//”替换为“//**blocks**//”) 
- * 采集等级:''src/main/resources/data/minecraft/tags/blocks/needs_<tier>_tool.json'',其中 ''<tier>'' 可以是:''stone''、''iron''、''diamond''(//不包括// ''netherite''+  * 采集等级:''src/main/resources/data/minecraft/tags/**block**/needs_<tier>_tool.json'',其中 ''<tier>'' 可以是:''stone''、''iron''、''diamond''(//不包括// ''netherite'')(对于 1.21 以下的版本,把“//**block**//”替换为“//**blocks**//
  
 <code JavaScript src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json> <code JavaScript src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json>
Line 167: Line 225:
   "replace": false,   "replace": false,
   "values": [   "values": [
-    "example:example_block"+    "tutorial:example_block"
   ]   ]
 } }
Line 176: Line 234:
   "replace": false,   "replace": false,
   "values": [   "values": [
-    "example:example_block"+    "tutorial:example_block"
   ]   ]
 } }
 </code> </code>
  
-对于采集等级标签(''needs_stone_tool''、''needs_iron_tool'' 和 ''needs_diamond_tool'')生效,在方块定义中将 ''requiresTool()'' 到 ''Block.Settings''(以 1.20.5 以上版本为例):+采集等级标签(''needs_stone_tool''、''needs_iron_tool'' 和 ''needs_diamond_tool'')生效,在方块定义中将 ''requiresTool()'' 到 ''Block.Settings''(以 1.20.5 以上版本为例):
  
 <code java [enable_line_numbers="true"]> <code java [enable_line_numbers="true"]>
Line 191: Line 249:
 当创建一个简单的方块时,上述方法效果很好,但是有时您想要一个具有//独特//机制的方块。我们将创建一个//单独//的继承 ''Block'' 的类来执行此操作。该类需要一个带有 ''AbstractBlock.Settings'' 参数的构造器: 当创建一个简单的方块时,上述方法效果很好,但是有时您想要一个具有//独特//机制的方块。我们将创建一个//单独//的继承 ''Block'' 的类来执行此操作。该类需要一个带有 ''AbstractBlock.Settings'' 参数的构造器:
  
-<code java [enable_line_numbers="true"]>+<code java [enable_line_numbers="true"ExampleBlock.java>
 public class ExampleBlock extends Block { public class ExampleBlock extends Block {
- 
     public ExampleBlock(Settings settings) {     public ExampleBlock(Settings settings) {
         super(settings);         super(settings);
Line 202: Line 259:
 你可以在方块类中覆盖方法以实现特殊功能。这里是 ''onUse'' 方法的实现,右键单击方块时会调用此方法。我们检查交互是否在服务器进行,并向玩家发送消息,//"Hello, world!"// 你可以在方块类中覆盖方法以实现特殊功能。这里是 ''onUse'' 方法的实现,右键单击方块时会调用此方法。我们检查交互是否在服务器进行,并向玩家发送消息,//"Hello, world!"//
  
-<code java [enable_line_numbers="true",highlight_lines_extra="8,9,10,11,12,13,14,15"]>+<code java [enable_line_numbers="true",highlight_lines_extra="8,9,10,11,12,13,14,15"ExampleBlock.java>
 public class ExampleBlock extends Block { public class ExampleBlock extends Block {
  
Line 223: Line 280:
 要使用自定义方块类,请在注册时将 ''new Block'' 替换为 ''new ExampleBlock'' 要使用自定义方块类,请在注册时将 ''new Block'' 替换为 ''new ExampleBlock''
  
-<code java [enable_line_numbers="true",highlight_lines_extra="3"]> +<code java [enable_line_numbers="true",highlight_lines_extra="3"TutorialBlocks.java
-public class ExampleMod implements ModInitializer {+public final class TutorialBlocks {
  
-    public static final ExampleBlock EXAMPLE_BLOCK = new ExampleBlock(Block.Settings.create().strength(4.0f));+    public static final Block EXAMPLE_BLOCK = register("example_block", new ExampleBLock(Block.Settings.create().strength(4.0f)));
          
-    @Override +    // ...
-    public void onInitialize() { +
-        Registry.register(Registries.BLOCK, new Identifier("tutorial", "example_block"), EXAMPLE_BLOCK); +
-        Registry.register(Registries.ITEM, new Identifier("tutorial", "example_block"), new BlockItem(EXAMPLE_BLOCK, new Item.Settings())); +
-    }+
 } }
 </code> </code>
Line 244: Line 297:
 要解决这个问题,我们需要定义方块的 ''VoxelShape'' 要解决这个问题,我们需要定义方块的 ''VoxelShape''
  
-<code java>+<code java ExampleBlock.java>
 public class ExambleBlock extends Block { public class ExambleBlock extends Block {
     [...]     [...]
Line 258: Line 311:
 {{:tutorial:voxelshape_fixed.png?200|}} {{:tutorial:voxelshape_fixed.png?200|}}
  
-You can also define other types of shapes for the block. The type of shapes of blocks include: +你也可以定义其他几类方块形状,方块形状的类型包括: 
-  * **outline shape**: the shape used as default value for most type of shapes. In the worlds, when you points to the shape, the translucent black outline is displayed according to this shape. Most times it should not be empty. +  * **外观形状(outline shape**:方块大多数类型的形状都使用这个值作为默认。在世界中,当你指向这个形状时,会根据此形状绘制道明的黑色边框。大多数时候,这个形状不应该是空的。 
-  * **collision shape**: the shape used to calculate collisions. When entities (including players) are moving, their collision box usually cannot intersect the collision shape of blocks. Some blocks, such as fences and walls, may have a collision shape higher than one block. Some blocks, such as flowers, have an empty collision shape. Apart from modifying ''getCollisionShape'' method, you can also call ''noCollision'' in the ''FabricBlockSettings'' when creating the block. +  * **碰撞形状(collision shape**:用于计算碰撞的形状。实体(包括玩家)移动时,其碰撞箱通常不能与方块的碰撞形状重合。一些方块,例如栅栏和墙,碰撞形状高于一格。一些方块,例如花,碰撞形状是空的。除了修改 ''getCollisionShape'' 方法外,你也可以在创建方块时调用 ''Block.Settings'' 中的 ''noCollision'' 
-  * **raycasting shape**: the shape used to calculate raycasting (the process judging which block you are pointing to). You usually do not need to specify it. +  * **raycasting shape**:用于计算视线投射(判断你正在指向哪个方块的过程)的形状。通过不需要指定。 
-  * **camera collision shape**: the shape used to calculate the position of camera in third-party view. Glass and powder snow have an empty camera collision shape. +  * **相机碰撞形状(camera collision shape**:用于计算第三人称视角的相机的位置的形状。玻璃和细雪的相机碰撞形状为空。 
 +  
 ===== 下一步 ===== ===== 下一步 =====
 [[zh_cn:tutorial:blockstate|向方块添加简单状态,例如整数和布尔值]]。 [[zh_cn:tutorial:blockstate|向方块添加简单状态,例如整数和布尔值]]。
  
-[[zh_cn:tutorial:blockentity|给块一个方块实体,使它们可以具有物品栏之类的高级状态]]。此外,还需要像 GUI 和自定义方块渲染。+[[zh_cn:tutorial:blockentity|给块方块实体,使之能有物品栏之类的高级状态]]。此外,还需要像 GUI 和自定义方块渲染。
  
 要让方块可燃(也就是说,可以被火燃烧),可使用 ''FlammableBlockRegistry'' 要让方块可燃(也就是说,可以被火燃烧),可使用 ''FlammableBlockRegistry''
zh_cn/tutorial/blocks.1713145453.txt.gz · Last modified: 2024/04/15 01:44 by solidblock