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 [2022/07/17 11:59] – 更改了无法正常运作的代码 luo_tian_wyzh_cn:tutorial:blocks [2024/04/15 01:52] (current) – [自定义形状] solidblock
Line 1: Line 1:
-====== 添加一个方块 ======+====== 添加方块 ======
  
-将方块添加到你的模组过程与[[zh_cn:tutorial:items|添加物品]]类似。你可以创建''Block''或自定义类的实例,然后将其注册到''Registry.BLOCK''注册表。你还需要提供纹理和方块状态或模型文件以提供方块外观。如需了解方块模型格式的更多信息,请参考[[https://minecraft-zh.gamepedia.com/模型|Minecraft Wiki模型页面]]。+将方块添加到你的模组过程与[[zh_cn:tutorial:items|添加物品]]类似。你可以创建 ''Block'' 或自定义类的实例,然后将其注册到 ''Registries.BLOCK''(1.19.3 以上版本)或 ''Registry.BLOCK'' (1.19.2 以下)注册表。你还需要提供纹理和方块状态或模型文件以提供方块外观。如需了解方块模型格式的更多信息,请参考[[https://zh.minecraft.wiki/模型|Minecraft Wiki模型页面]]。
  
-===== 创建一个方块 =====+===== 创建方块 =====
  
-首先创建''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"]>
Line 11: Line 11:
  
     /* 声明和初始化我们的自定义方块实例。     /* 声明和初始化我们的自定义方块实例。
-       我们将方块材质(material)设置为METAL(金属),需要镐来高效挖掘+       我们将方块材质(material)设置为 METAL(金属)。
                
-       `strength`会将方块的硬度和抗性设为同一个值。+       `strength` 会将方块的硬度和抗性设为同一个值。
        硬度决定了方块需要多久挖掘,抗性决定了方块抵御爆破伤害(如爆炸)的能力。        硬度决定了方块需要多久挖掘,抗性决定了方块抵御爆破伤害(如爆炸)的能力。
-       石头的硬度为1.5f,抗性为6.0f,黑曜石的硬度为50.0f,抗性为1200.0f。+       石头的硬度为 1.5f,抗性为 6.0f,黑曜石的硬度为 50.0f,抗性为 1200.0f。
                
-       可以在`Blocks`类中查找所有原版方块的统计+       可以在`Blocks`类中查找所有原版方块,你可以以此作为参考
     */     */
-    public static final Block EXAMPLE_BLOCK = new Block(FabricBlockSettings.of(Material.METAL).hardness(4.0f));+     
 +    // 对于 1.20 以下版本: 
 +    // public static final Block EXAMPLE_BLOCK = new Block(FabricBlockSettings.of(Material.METAL).strength(4.0f)); 
 +    // 对于 1.20.5 以下版本: 
 +    // public static final Block EXAMPLE_BLOCK = new Block(FabricBlockSettings.create().strength(4.0f)); 
 +    // 对于自 1.20.5 之后的版本: 
 +    public static final Block EXAMPLE_BLOCK = new Block(Block.Settings.create().strength(4.0f));
          
     @Override     @Override
Line 29: Line 35:
 ==== 注册方块 ==== ==== 注册方块 ====
  
-方块应该注册在''Block.REGISTRY''注册表。调用//Registry.register//并传递适当的参数。+方块应该注册在 ''Registries.BLOCK'' 注册表。调用 ''Registry.//register//'' 并传递适当的参数。你可以直接在 ''onInitialize'' 方法中注册方块,也可以在静态部分创建方块实例时将其注册,因为 ''register'' 方法会返回这个方块实例自身
  
-<code java [enable_line_numbers="true"]>+如果你使用的是 1.19.2 以下的版本,请将 ''Registries.BLOCK'' 替换为 ''Registry.BLOCK''。 
 + 
 +<code java [enable_line_numbers="true",highlight_lines_extra="11"]>
 public class ExampleMod implements ModInitializer { public class ExampleMod implements ModInitializer {
  
-    public static final Block EXAMPLE_BLOCK = new Block(FabricBlockSettings.of(Material.METAL).hardness(4.0f));+    // 对于 1.20 以下版本: 
 +    // public static final Block EXAMPLE_BLOCK = new Block(FabricBlockSettings.of(Material.METAL).strength(4.0f)); 
 +    // 对于 1.20.5 以下版本: 
 +    // public static final Block EXAMPLE_BLOCK = new Block(FabricBlockSettings.create().strength(4.0f)); 
 +    // 对于自 1.20.5 之后的版本: 
 +    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);
-        Registry.register(Registry.BLOCK, new Identifier("tutorial", "example_block"), EXAMPLE_BLOCK);+
     }     }
 } }
 </code> </code>
  
-您的方块不能作为物品存入背包,但可以通过使用''/setblock tutorial:example_block''在游戏中看到。+您的方块不能作为物品存入背包,但可以通过使用 ''/setblock <位置> tutorial:example_block'' 在游戏中看到。
  
 ==== 为方块注册物品 ==== ==== 为方块注册物品 ====
  
-在大多数情况下,您希望能够拿着物品放置方块。为此,您需要在物品注册表中注册一个相应的BlockItem。您可以通过在Registry.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"]>
 public class ExampleMod implements ModInitializer { public class ExampleMod implements ModInitializer {
  
-    /* Declare and initialize our custom block instance+    // 对于 1.20 以下版本: 
-       We set out block material to METAL, which requires a pickaxe to efficiently break. +    // public static final Block EXAMPLE_BLOCK = new Block(FabricBlockSettings.of(Material.METAL).strength(4.0f)); 
-       Hardness represents how long the break takes to breakStone has a hardness of 1.5f, while Obsidian has a hardness of 50.0f+    // 对于 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.of(Material.METAL));+    // 对于自 1.20.5 之后的版本: 
 +    public static final Block EXAMPLE_BLOCK = new Block(Block.Settings.create().strength(4.0f));
          
     @Override     @Override
     public void onInitialize() {     public void onInitialize() {
-        Registry.register(Registry.BLOCK, new Identifier("tutorial", "example_block"), EXAMPLE_BLOCK); +        Registry.register(Registries.BLOCK, new Identifier("tutorial", "example_block"), EXAMPLE_BLOCK); 
-        Registry.register(Registry.ITEM, new Identifier("tutorial", "example_block"), new BlockItem(EXAMPLE_BLOCK, new Item.Settings().group(ItemGroup.MISC)));+        // 对于 1.20.5 以下版本: 
 +        // Registry.register(Registries.ITEM, new Identifier("tutorial", "example_block"), new BlockItem(EXAMPLE_BLOCK, new FabricItemSettings())); 
 +        // 对于自 1.20.5 之后的版本: 
 +        Registry.register(Registries.ITEM, new Identifier("tutorial", "example_block"), new BlockItem(EXAMPLE_BLOCK, new Item.Settings()));
     }     }
 } }
 </code> </code>
  
-===== 给您的方块一个外观 =====+===== 给方块外观 =====
  
-可能已经注意到,新的方块只是游戏中紫色和黑色棋盘格图案。这表明Minecraft加载方块资源或外观时出错。运行客户端时,完整的问题列表会输出在你的日志中。你需要以下文件来给予方块外观:+可能已经注意到,新的方块只是游戏中紫色和黑色棋盘格图案。这表明Minecraft加载方块资源或外观时出错。运行客户端时,完整的问题列表会输出在你的日志中。你需要以下文件来给予方块外观:
  
   * 方块状态文件   * 方块状态文件
Line 78: Line 94:
 这些文件位于: 这些文件位于:
  
-  方块状态:src/main/resources/assets/tutorial/blockstates/example_block.json +  方块状态:''src/main/resources/assets/tutorial/blockstates/example_block.json'' 
-  方块模型:src/main/resources/assets/tutorial/models/block/example_block.json +  方块模型:''src/main/resources/assets/tutorial/models/block/example_block.json'' 
-  物品模型:src/main/resources/assets/tutorial/models/item/example_block.json +  物品模型:''src/main/resources/assets/tutorial/models/item/example_block.json'' 
-  方块纹理:src/main/resources/assets/tutorial/textures/block/example_block.png+  方块纹理:''src/main/resources/assets/tutorial/textures/block/example_block.png''
  
 方块状态文件根据其方块装填确定该方块应使用的模型。由于我们的方块没有所谓状态,所以我们用空字符串表示所有: 方块状态文件根据其方块装填确定该方块应使用的模型。由于我们的方块没有所谓状态,所以我们用空字符串表示所有:
Line 116: Line 132:
 ===== 配置方块掉落物 ===== ===== 配置方块掉落物 =====
  
-该方块必须有一个//战利品表//,以便在该方块被破坏时掉落物品。以下文件会使方块被破坏时掉落其本身。+该方块必须有//战利品表//,以便在该方块被破坏时掉落物品。以下文件会使方块被破坏时掉落其本身。
  
 <code JavaScript src/main/resources/data/tutorial/loot_tables/blocks/example_block.json> <code JavaScript src/main/resources/data/tutorial/loot_tables/blocks/example_block.json>
Line 139: Line 155:
 } }
 </code> </code>
 +
 +条件 ''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/blocks/mineable/<tooltype>.json'',其中 ''<tooltype>'' 可以是 ''axe''、''pickaxe''、''shovel''、''hoe'
-  采集等级:src/main/resources/data/minecraft/tags/blocks/needs_<tier>_tool.json,其中'tier'可以是:'stone'、'iron'、'diamond'+ 采集等级:''src/main/resources/data/minecraft/tags/blocks/needs_<tier>_tool.json'',其中 ''<tier>'' 可以是:''stone''、''iron''、''diamond''(//不包括// ''netherite''
  
 <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 163: Line 181:
 </code> </code>
  
-对于采集等级标签(needs_stone_tool、needs_iron_tool和needs_diamond_tool)生效,在方块定义中将requiresTool()到FabricToolSettings+对于采集等级标签(''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"]>
-    public static final Block EXAMPLE_BLOCK = new ExampleBlock(FabricBlockSettings.of(Material.METAL).strength(4.0f).requiresTool());+    public static final Block EXAMPLE_BLOCK = new ExampleBlock(Block.Settings.create().strength(4.0f).requiresTool());
 </code> </code>
  
 ===== 创建自定义方块类 ===== ===== 创建自定义方块类 =====
  
-当创建一个简单的方块时,上述方法效果很好,但是有时您想要一个具有//一无二//机制的方块。我们将创建一个//单独//扩展''Block''的类来执行此操作。该类需要一个带有''AbstractBlock.Settings''参数的构造器:+当创建一个简单的方块时,上述方法效果很好,但是有时您想要一个具有////机制的方块。我们将创建一个//单独//继承 ''Block'' 的类来执行此操作。该类需要一个带有 ''AbstractBlock.Settings'' 参数的构造器:
  
 <code java [enable_line_numbers="true"]> <code java [enable_line_numbers="true"]>
Line 182: Line 200:
 </code> </code>
  
-你可以在方块类中覆盖方法以实现特殊功能。这里是''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"]>
Line 191: Line 209:
     }     }
  
 +    // 对于 1.20.5 以下版本,方法参数应该是“BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit”
     @Override     @Override
-    public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {+    public ActionResult onUse(World world, PlayerEntity player, BlockHitResult hit) {
         if (!world.isClient) {         if (!world.isClient) {
-            player.sendMessage(Text.of("Hello, world!"), false);+            player.sendMessage(Text.literal("Hello, world!"), false);
         }         }
  
Line 202: Line 221:
 </code> </code>
  
-要使用自定义方块类,请在注册时将//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"]>
 public class ExampleMod implements ModInitializer { public class ExampleMod implements ModInitializer {
  
-    public static final ExampleBlock EXAMPLE_BLOCK = new ExampleBlock(Block.Settings.of(Material.STONE).hardness(4.0f));+    public static final ExampleBlock EXAMPLE_BLOCK = new ExampleBlock(Block.Settings.create().strength(4.0f));
          
     @Override     @Override
     public void onInitialize() {     public void onInitialize() {
-        Registry.register(Registry.BLOCK, new Identifier("tutorial", "example_block"), EXAMPLE_BLOCK); +        Registry.register(Registries.BLOCK, new Identifier("tutorial", "example_block"), EXAMPLE_BLOCK); 
-        Registry.register(Registry.ITEM, new Identifier("tutorial", "example_block"), new BlockItem(EXAMPLE_BLOCK, new Item.Settings().group(ItemGroup.MISC)));+        Registry.register(Registries.ITEM, new Identifier("tutorial", "example_block"), new BlockItem(EXAMPLE_BLOCK, new Item.Settings()));
     }     }
 } }
 </code> </code>
  
-==== 自定义VoxelShape ====+==== 自定义形状 ====
  
-当使用不能''完整''填充一个方块的方块模型(例如铁砧、台阶、楼梯)时,邻近的方块隐藏面:+当使用不能完整填充一个方块的方块模型(例如铁砧、台阶、楼梯)而其形状却仍是完整的时,邻近的方块隐藏面就会暴露
  
 {{:tutorial:voxelshape_wrong.png?200|}} {{:tutorial:voxelshape_wrong.png?200|}}
  
-要解决这个问题,我们需要定义方块的''VoxelShape''+要解决这个问题,我们需要定义方块的 ''VoxelShape''
  
-<code> +<code java
- @Override +public class ExambleBlock extends Block { 
- public VoxelShape getOutlineShape(BlockState state, BlockView view, BlockPos pos, ShapeContext context) { +    [...] 
-     return VoxelShapes.cuboid(0f, 0f, 0f, 1f, 1.0f, 0.5f); +    @Override 
- }+    public VoxelShape getOutlineShape(BlockState state, BlockView view, BlockPos pos, ShapeContext context) { 
 +        return VoxelShapes.cuboid(0f, 0f, 0f, 1f, 1.0f, 0.5f); 
 +    } 
 +}
 </code> </code>
  
-注意方块的//collision shape//默认为其描边形状,如果未被指定。+注意方块的//碰撞形状//默认为其描边形状,如果未被指定。
  
 {{:tutorial:voxelshape_fixed.png?200|}} {{:tutorial:voxelshape_fixed.png?200|}}
  
-==== 下一步 ====+你也可以定义其他几类方块形状,方块形状的类型包括: 
 +  * **外观形状(outline shape)**:方块大多数类型的形状都使用这个值作为默认。在世界中,当你指向这个形状时,会根据此形状绘制道明的黑色边框。大多数时候,这个形状不应该是空的。 
 +  * **碰撞形状(collision shape)**:用于计算碰撞的形状。实体(包括玩家)移动时,其碰撞箱通常不能与方块的碰撞形状重合。一些方块,例如栅栏和墙,碰撞形状高于一格。一些方块,例如花,碰撞形状是空的。除了修改 ''getCollisionShape'' 方法外,你也可以在创建方块时调用 ''Block.Settings'' 中的 ''noCollision''。 
 +  * **raycasting shape**:用于计算视线投射(判断你正在指向哪个方块的过程)的形状。通过不需要指定。 
 +  * **相机碰撞形状(camera collision shape)**:用于计算第三人称视角的相机的位置的形状。玻璃和细雪的相机碰撞形状为空。 
 +===== 下一步 =====
 [[zh_cn:tutorial:blockstate|向方块添加简单状态,例如整数和布尔值]]。 [[zh_cn:tutorial:blockstate|向方块添加简单状态,例如整数和布尔值]]。
  
-[[zh_cn:tutorial:blockentity|给块一个方块实体,使它们可以具有物品栏之类的的高级状态]]。此外,还需要像GUI和自定义块渲染很多东西+[[zh_cn:tutorial:blockentity|给块一个方块实体,使它们可以具有物品栏之类的的高级状态]]。此外,还需要像 GUI 和自定义块渲染。 
 + 
 +要让方块可燃(也就是说,可以被火燃烧),可使用 ''FlammableBlockRegistry''
zh_cn/tutorial/blocks.1658059163.txt.gz · Last modified: 2022/07/17 11:59 by luo_tian_wy