User Tools

Site Tools


zh_cn:tutorial:blockstate

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:blockstate [2022/12/16 01:43] solidblockzh_cn:tutorial:blockstate [2025/04/01 09:21] (current) solidblock
Line 1: Line 1:
 ====== 赋予方块状态 ======= ====== 赋予方块状态 =======
-Minecraft 中的每种类型的方块都由一个单独的 ''Block'' 实例表示。这样就无法仅通过更改 ''Block'' 实例的状态来更改特定方块的状态,因为该类型的其他所有方块都会受到影响!但是,如果您想给出一个单一的方块状态,以便它可以根据某些条件改变,该怎么办?+Minecraft 中的每种类型的方块都由一个单独的 ''Block'' 实例表示。这样就无法仅通过更改 ''Block'' 实例的状态来更改特定方块的状态,因为该类型的其他所有方块都会受到影响!但是,如果您想给出一个单一的方块状态,以便它可以根据某些条件改变,该怎么办?这就是方块状态的目的。
  
-是 ''BlockState''假设我们希望一个方块仅在充能后能够召唤闪电。+===== 方块状态属性 ===== 
 + 
 +每个方块都可以有 0 个、1 个或更多个**方块状态属性**,每个方块状态属性都可以有至少 2 个值。原版已有的属性,可以在 ''Properties''(''net.minecraft.state.property.Properties'')中找到。当然,许多方块比较简单,没有方块状态属性,因此些方块的方块状态是唯一的。 
 + 
 +我们来看几个例子: 
 +  * [[directionalblock|制作带朝向的方块]],使用的方块状态属性是 ''Properties.HORIZONTAL_FACING'',其值可以是 4 个水平方向 
 +  * [[waterloggable|制作可含水方块]],使用方块状态属性是 ''Properties.WATERLOGGED'',其值可以是 true 和 false 
 + 
 +===== 自定义方块状态属性:以可充能方块为例 ===== 
 + 
 +假设我们希望一个方块仅在充能后能够召唤闪电。
      
-首先,我们定义方块的布尔值属性——是否充能(小心不要导入错误的BooleanProperty):+首先,我们定义方块的布尔值属性——是否充能(小心不要导入错误的 ''BooleanProperty'',并在模组初始化的地方将其注册。(如果你直接在 ''ChargeableBlock'' 类的静态字段中注册,模组初始化器可能会忽略它,如果这个类没有被初始化的话。) 
 + 
 +如果你需要定义其他类型的属性,可以使用 ''IntProperty'' 或 ''EnumProperty''。 
 + 
 +先创建类
 <code java> <code java>
 public class ChargeableBlock extends Block { public class ChargeableBlock extends Block {
     public static final BooleanProperty CHARGED = BooleanProperty.of("charged");     public static final BooleanProperty CHARGED = BooleanProperty.of("charged");
-  +     
-    /方块实例。可以放在任何地方。 +    public ChargeableBlock(Settings settings) { 
-    public static final ChargeableBlock CHARGEABLE_BLOCK = Registry.register( +      super(settings); 
-        Registries.BLOCK, +    } 
-        new Identifier("tutorial", "chargeable_block"), +
-        new ChargeableBlock( /* 在这里写合适的东西 */ ));+</code> 
 +然后按照 [[blocks]] 中说的那样注册方块: 
 +<code java> 
 +public final class TutorialBlocks { 
 +    // 对于 1.21.2 之前的版本: 
 +    public static final ChargeableBlock CHARGEABLE_BLOCK = register("chargeable_block", new ChargeableBlock(Block.Settings.copy(Blocks.STONE))); 
 + 
 +    // 对于 1.21.2 以及之后的版本: 
 +    public static final Block CHARGEABLE_BLOCK = register("chargeable_block", ChargeableBlock::new, Block.Settings.copy(Blocks.STONE)); 
 +     
 +    // [...]
 } }
 </code> </code>
Line 29: Line 53:
 } }
 </code> </code>
-然后,我们需要在方块构造器中设置属性的默认状态(要设置多个属性请通过调用 ''with()'' 来连接)+ 
 +然后需要注册属性的默认状态。到刚刚创建的类的构造方块像这样修改
 <code java> <code java>
 public class ChargeableBlock extends Block { public class ChargeableBlock extends Block {
Line 41: Line 66:
 </code> </code>
  
-现在,我们需要能够通过 ''onUse'' 方法充能方块,在该方法中调用 ''world.setBlockState()''(这个 ''playSound'' 是可的,只是让我们知道方块充能了)。+现在,我们需要能够通过 ''onUse'' 方法充能方块,在该方法中调用 ''world.setBlockState()''(这个 ''playSound'' 是可的,只是让我们知道方块充能了)。
  
 <code java> <code java>
Line 47: Line 72:
     [...]     [...]
     @Override     @Override
-    public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {+    public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) {
         player.playSound(SoundEvents.BLOCK_RESPAWN_ANCHOR_CHARGE, 1, 1);         player.playSound(SoundEvents.BLOCK_RESPAWN_ANCHOR_CHARGE, 1, 1);
         world.setBlockState(pos, state.with(CHARGED, true));         world.setBlockState(pos, state.with(CHARGED, true));
Line 63: Line 88:
         if (world.getBlockState(pos).get(CHARGED)){         if (world.getBlockState(pos).get(CHARGED)){
             // 在方块的位置召唤闪电             // 在方块的位置召唤闪电
-            LightningEntity lightningEntity = (LightningEntity) EntityType.LIGHTNING_BOLT.create(world);+            LightningEntity lightningEntity = EntityType.LIGHTNING_BOLT.create(world, SpawnReason.MOB_SUMMONED);
             lightningEntity.refreshPositionAfterTeleport(Vec3d.ofBottomCenter(pos));             lightningEntity.refreshPositionAfterTeleport(Vec3d.ofBottomCenter(pos));
             world.spawnEntity(lightningEntity);             world.spawnEntity(lightningEntity);
Line 74: Line 99:
 </code> </code>
  
-==== 为方块状态添加模型 ====+==== 为方块状态添加模型和方块状态映射 ====
  
-你可能还需要使得纹理和模型能够根据状态来改变,这是通过一个叫做“方块状态 JSON”的 JSON 来完成的。所有的方块都需要一个方块状态 JSON,无论它是否有多个方块状态,但其内容可以简单也可以复杂。如果需要根据方块状态来改变纹理,我们需要添加多个模型。+你可能还需要使得纹理和模型能够根据状态来改变,这是通过一个叫做“**方块状态映射**(block states definitions)”的 JSON 来完成的。所有的方块都需要一个方块状态映射,无论它是否有多个方块状态,但其内容可以简单也可以复杂。如果需要根据方块状态来改变纹理,我们需要添加多个模型。
  
-比如说,你为 ''ChargeableBlock'' 注册了 ID 为 ''tutorial:chargeable_block''。Minecraft 会加载地址 ''src/main/resources/assets/tutorial/blockstates/chargeable_block.json'' 并从加载方块状态。如果你不需要让方块根据状态更改模型,方块状态 JSON 可以非常简单,就像这样:+比如说,你为 ''ChargeableBlock'' 注册了 ID 为 ''tutorial:chargeable_block''。Minecraft 会加载地址 ''src/main/resources/assets/tutorial/blockstates/chargeable_block.json''方块状态映射,并根据方块状态映射分配方块模型。如果你不需要让方块根据状态更改模型,方块状态映射可以非常简单,就像这样:
  
 <code JavaScript resources/assets/tutorial/blockstates/chargeable_block.json> <code JavaScript resources/assets/tutorial/blockstates/chargeable_block.json>
 { {
-    +    "variants":
-        "variants":+        "": { "model": "tutorial:block/chargeable_block" }
-            "": { "model": "tutorial:block/chargeable_block" +
-        }+
     }     }
- 
 } }
 </code> </code>
 +
 让我们分解一下这个简单的例子。JSON 有几个重要的部分: 让我们分解一下这个简单的例子。JSON 有几个重要的部分:
  
-''"variants"'' 定义了每个方块状态应该使用什么模型。我们将稍作探讨。 +  * The ''%%"variants"%%'' 定义了每个方块状态应该使用什么模型。我们将稍作探讨。 
-名为 ''""'' 的变种将应用于//每个//方块状态。如果你有 ''""'' 变种,则 JSON 中不应包含任何其他变种,否则 Minecraft 会出问题。 +  名为 ''%%""%%''(空字符串)的变种将应用于//每个//方块状态。如果你有 ''%%""%%'' 变种,则 JSON 中不应包含任何其他变种,否则 Minecraft 会出问题。 
-分配给 ''""'' 变种的对象可以添加各种属性,例如旋转或纹理操作。请查看下面的链接的“模型”页面,以获取有关可以添加哪些属性的更多文档。所有变种都//必须//包含 ''"model"''属性。 +  分配给 ''%%""%%'' 变种的对象可以添加各种属性,例如旋转或纹理操作。请查看下面的链接的“模型”页面,以获取有关可以添加哪些属性的更多文档。所有变种都//必须//包含 ''%%"model"%%'' 属性。 
-''"model"'' 属性总是传递模型的 ID。在这个例子中,游戏将查看位置 ''src/main/resources/assets/tutorial/models/block/chargeable_block.json''。这里的ID可以是任何东西,//不需要//与方块的ID相同,但是如果只有一个变种,则应当要相同。方块模型具有自己的设置,在下面链接的 Minecraft Wiki 页面上有很好的记录。您可以手动编写 JSON,也可以使用[[https://blockbench.net|Blockbench]]之类的程序更轻松地生成它。+  ''%%"model"%%'' 属性总是传递模型的 ID。在这个例子中,游戏将查看位置 ''src/main/resources/assets/tutorial/models/block/chargeable_block.json''。这里的 ID 可以是任何东西,//不需要//与方块的ID相同,但是如果只有一个变种,则应当要相同。方块模型具有自己的设置,在下面链接的 Minecraft Wiki 页面上有很好的记录。您可以手动编写 JSON,也可以使用 [[https://blockbench.net|Blockbench]] 之类的程序更轻松地生成它。
  
 如果//确实//想要为每个方块状态使用不同的模型,则需要添加多个变种。对于我们上面使用的同一个 ''src/main/resources/assets/tutorial/blockstates/chargeable_block.json'' 位置,你可能需要这样子: 如果//确实//想要为每个方块状态使用不同的模型,则需要添加多个变种。对于我们上面使用的同一个 ''src/main/resources/assets/tutorial/blockstates/chargeable_block.json'' 位置,你可能需要这样子:
  
 <code JavaScript resources/assets/tutorial/blockstates/chargeable_block.json> <code JavaScript resources/assets/tutorial/blockstates/chargeable_block.json>
-    +
-        "variants":+    "variants":
-            "charged=false": { "model": "tutorial:block/chargeable_block" }, +        "charged=false": { "model": "tutorial:block/chargeable_block" }, 
-            "charged=true": { "model": "tutorial:block/chargeable_block_charged" +        "charged=true": { "model": "tutorial:block/chargeable_block_charged" }
-        }+
     }     }
 +}
 </code> </code>
  
-在此 JSON中,有两个变种,一种针对我们上面定义的 ''CHARGED'' 属性的每种可能性。由于我们在 Java 中为属性指定了字符串 ''charged'',因此我们在这里使用它。布尔值只有两种状态,但是如果您使用基于整数或枚举的属性,则会有更多的变种。+在此方块状态映射中,有两个变种,一种针对我们上面定义的 ''CHARGED'' 属性的每种可能性。由于我们在 Java 中为属性指定了字符串 ''charged'',因此我们在这里使用它。布尔值只有两种状态,但是如果您使用基于整数或枚举的属性,则会有更多的变种。
  
 变种基于添加到方块中的属性的可能排列。如果需要,可以在方块状态 JSON 中完全忽略某个属性,例如在第一个方块状态 JSON 中我们忽略了 ''charged'' 属性,但如果要在一个变种中包含属性,则必须将其包含在//所有//变种。如果 ''tutorial:chargeable_block'' 还具有一个称为 ''glowing'' 的布尔属性,并且您想根据模型是否发光以及是否经过充能来更改模型,则需要四个变种:充能发光,充能不发光,不充能但发光,不充能不发光。如果需要,可以将同一模型分配给多个变种。 变种基于添加到方块中的属性的可能排列。如果需要,可以在方块状态 JSON 中完全忽略某个属性,例如在第一个方块状态 JSON 中我们忽略了 ''charged'' 属性,但如果要在一个变种中包含属性,则必须将其包含在//所有//变种。如果 ''tutorial:chargeable_block'' 还具有一个称为 ''glowing'' 的布尔属性,并且您想根据模型是否发光以及是否经过充能来更改模型,则需要四个变种:充能发光,充能不发光,不充能但发光,不充能不发光。如果需要,可以将同一模型分配给多个变种。
  
-这只是对方块状态 JSON 的简单介绍。[[https://minecraft-zh.gamepedia.com/模型|Minecraft Wiki]]中记录了有关方块状态和模型 JSON 的所有技巧,以及在原版游戏中使用这些功能的示例。祝你好运!+这只是对方块状态映射的简单介绍。[[https://zh.minecraft.wiki/模型|Minecraft Wiki]] 中记录了有关方块模型和方块状态映射的所有技巧,以及在原版游戏中使用这些功能的示例。你也可以使用[[datagen_model|数据生成器生成模型]]。祝你好运!
  
-==== 关于性能的注意事项 ====+===== 关于性能的注意事项 =====
  
-游戏开始时会注册方块的所有可能状态。这意味着,如果具有14个布尔属性,则该方块具有2 ^ 14 = 16384个不同的状态,并且会注册这2 ^ 14个状态。因此,方块不应包含太多的方块状态属性。相反,方块状态应主要保留用于视觉效果,需要使用更高级的状态应使用[[zh_cn:tutorial:blockentity|方块实体]]。+游戏开始时会注册方块的所有可能状态。这意味着,如果具有14个布尔属性,则该方块具有2 ^ 14 = 16384个不同的状态,并且会注册这2 ^ 14个状态。因此,方块不应包含太多的方块状态属性。相反,方块状态应主要保留用于视觉效果,需要使用更高级的状态应使用[[blockentity|方块实体]]。
  
 由于所有的可能的方块状态都已经构建好了,因此相等的方块状态是同一个对象,''with'' 方法会返回一个存在的对象,而不是创建一个新对象——例如,''CHARGEABLE_BLOCK.getDefaultState().with(CHARGED, true) == CHARGEABLE_BLOCK.getDefaultState().with(CHARGED, true)'' 会返回 ''true'' 由于所有的可能的方块状态都已经构建好了,因此相等的方块状态是同一个对象,''with'' 方法会返回一个存在的对象,而不是创建一个新对象——例如,''CHARGEABLE_BLOCK.getDefaultState().with(CHARGED, true) == CHARGEABLE_BLOCK.getDefaultState().with(CHARGED, true)'' 会返回 ''true''
zh_cn/tutorial/blockstate.1671155004.txt.gz · Last modified: 2022/12/16 01:43 by solidblock