User Tools

Site Tools


zh_cn:tutorial:colorprovider

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:colorprovider [2024/08/27 03:13] solidblockzh_cn:tutorial:colorprovider [2025/04/01 12:11] (current) solidblock
Line 27: Line 27:
   [...]   [...]
  
 +  // 1.21.2 之前:
   public static final Block COLOR_BLOCK = register("color_block", new Block(AbstractBlock.Settings.create()));   public static final Block COLOR_BLOCK = register("color_block", new Block(AbstractBlock.Settings.create()));
 +  
 +  // 1.21.2 及之后:
 +  public static final Block COLOR_BLOCK = register("color_block", Block::new, AbstractBlock.Settings.create());
 } }
 </code> </code>
Line 33: Line 37:
 简单添加个方块状态文件: 简单添加个方块状态文件:
  
-Then add a simple block states file: 
 <code javascript src/main/resources/assets/tutorial/blockstates/color_block.json> <code javascript src/main/resources/assets/tutorial/blockstates/color_block.json>
 { {
Line 72: Line 75:
  
 然后创建带有 //tintindex// 的模型:模型也很重要,这里需要注意的是,你//一定要//为模型的每一个你需要着色的部分定义tintindex。如要查看这个的例子,请参考 ''leaves.json'',这是原版树叶使用的基本模型。这里是我们方块使用的模型: 然后创建带有 //tintindex// 的模型:模型也很重要,这里需要注意的是,你//一定要//为模型的每一个你需要着色的部分定义tintindex。如要查看这个的例子,请参考 ''leaves.json'',这是原版树叶使用的基本模型。这里是我们方块使用的模型:
-【【 
-我们在这里所做的只是说:“Hi,''MY_BLOCK'' 应被着色为 0x3495eb”,也就是蓝色。你有 BlockState、World 和 BlockPos 的环境,基于这些环境的生物群系或者位置等来改变颜色。最终的 int 是 tintIndex,每个都会单独为颜色获取一个,但是在此例中,我们只返回蓝色。 
  
-如果你需要在颜色提供器中访问 ''BlockEntity'' 数据,你需要实现 ''RenderAttachmentBlockEntity'' 以返回你需要的数据。这是因为方块可以在单独的线程渲染,所以直接访问数据并不安全。而且,如果使用 ''getBlockState'' 查询方块,你无法查看整个世界——确保你只查询当前位置的 ±2 方块范围内的位置。 
-】】 
 <code javascript src/main/resources/assets/tutorial/models/block/color_block.json> <code javascript src/main/resources/assets/tutorial/models/block/color_block.json>
 { {
Line 100: Line 99:
 </code> </code>
  
-在这个实例里面,我们添加了单一的 tintindex,出现在 ''tintIndex'' 参数中(着色索引 0)。事实上,特准可以直接继承 ''minecraft:block/leaves'' 模型,因为也使用的带有 tintindex 的方块。所以可以将上面的模型替换为:+在这个实例里面,我们添加了单一的 tintindex,出现在 ''tintIndex'' 参数中(着色索引 0)。事实上,方块可以直接继承 ''minecraft:block/leaves'' 模型,因为也使用的带有 tintindex 的方块。所以可以将上面的模型替换为:
 <code javascript src/main/resources/assets/tutorial/models/block/color_block.json> <code javascript src/main/resources/assets/tutorial/models/block/color_block.json>
 { {
Line 118: Line 117:
 ===== 带有颜色提供器的方块实体 ===== ===== 带有颜色提供器的方块实体 =====
  
-If you need to access ''BlockEntity'' data in the color provider, you'll want to override ''getRenderData()'' method from the ''RenderDataBlockEntity'', which is an interface of Fabric API but [[interface_injection|injected]] to ''BlockEntity''. If you're using old versions, try implementing ''RenderAttachmentBlockEntity'' and returning the data you need.+如果你需要在颜色提供器中访问 ''BlockEntity'' 数据,你需要实现来自 ''RenderDataBlockEntity'' 的 ''getRenderData()'' 方法,这是 Fabric API 的接口,不过[[interface_injection|注入]]到的 ''BlockEntity'' 中。如果使用的是旧版本,尝试实现 ''RenderAttachmentBlockEntity'' 并返回你需要的数据。
  
-This is because blocks can be rendered on separate threads, so accessing the data directly is not safe. Additionally, if you query blocks with ''getBlockState'' you won't be able to view the entire world - make sure you only query within ±2 blocks x/y/z of the current position.+这是因为方块可以在单独的线程渲染,所以直接访问数据并不安全。而且,如果使用 ''getBlockState'' 查询方块,你无法查看整个世界——确保你只查询当前位置的 ±2 方块范围内的位置。
  
-In this case, we create a ''ColorBlock'' class and a ''ColorBlockEntity'' class, and connect the block with block entity (more information see [[blockentity]]).+在这个例子中,我们创建一个 ''ColorBlock'' 类和 ''ColorBlockEntity'' 类,并连接方块与方块实体(更多信息见[[blockentity|方块实体]]教程)。
  
 <code java ColorBlock.java> <code java ColorBlock.java>
Line 141: Line 140:
   }   }
  
 +  // 自从 1.21.4 开始,不再需要这个方法,因为所有方块实体都默认使用方块模型。
   @Override   @Override
   protected BlockRenderType getRenderType(BlockState state) {   protected BlockRenderType getRenderType(BlockState state) {
Line 156: Line 156:
   }   }
      
-  // The following two methods specify serialization of color data.+  // 以下两个方块指定了颜色数据的序列化。
  
   @Override   @Override
   protected void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup) {   protected void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup) {
     super.readNbt(nbt, registryLookup);     super.readNbt(nbt, registryLookup);
-    color = nbt.getInt("color"); 
          
-    // When the data is modified through "/datacommand+    // 对于 1.21.5 之前的版本,请直接使用 nbt.getInt("color"); 
-    // or placed by an item with "block_entity_data" component, +    color = nbt.getInt("color", 0); 
-    // the render color will be updated.+     
 +    // 当数据通过“/data”命令修改,或者放置了有“block_entity_data”组件的物品时, 
 +    // 需要同步更新。
     if (world != null) {     if (world != null) {
       world.updateListeners(pos, getCachedState(), getCachedState(), 0);       world.updateListeners(pos, getCachedState(), getCachedState(), 0);
Line 190: Line 191:
   @Override   @Override
   public @Nullable Object getRenderData() {   public @Nullable Object getRenderData() {
-    // this is the method from `RenderDataBlockEntity` class.+    // 这是来自 `RenderDataBlockEntity` 类的方法。
     return color;     return color;
   }   }
Line 196: Line 197:
 </code> </code>
  
-In the ''TutorialBlocks'' class, replace ''new Block'' with ''new ColorBlock'':+在 ''TutorialBlocks'' 类中,将 ''new Block'' 替换为 ''new ColorBlock''
 <code java> <code java>
 +  // 1.21.2 之前:
   public static final ColorBlock COLOR_BLOCK = register("color_block", new ColorBlock(AbstractBlock.Settings.create()));   public static final ColorBlock COLOR_BLOCK = register("color_block", new ColorBlock(AbstractBlock.Settings.create()));
 +  
 +  // 1.21.2 及之后:
 +  public static final Block COLOR_BLOCK = register("color_block", ColorBlock::new, AbstractBlock.Settings.create());
 </code> </code>
  
-In the ''TutorialBlockEntityTypes'' class:+在 ''TutorialBlockEntityTypes'' 类中:
 <code java> <code java>
   public static final BlockEntityType<ColorBlockEntity> COLOR_BLOCK = register("color_block",   public static final BlockEntityType<ColorBlockEntity> COLOR_BLOCK = register("color_block",
Line 207: Line 212:
 </code> </code>
  
-Now we modify ''onUseWithItem'' method so that the color changes when you interact the block with a dye:+> 不要忘了在你的模组初始化器中,静态加载 ''TutorialBlocks'' 和 ''TutorialBlockEntityTypes'' 类。 
 + 
 +现在我们修改 ''onUseWithItem'' 方法,这样颜色会在我们使用染料与方块接触时改变:
 <code java ColorBlock.java> <code java ColorBlock.java>
 public class ColorBlock extends BlockWithEntity { public class ColorBlock extends BlockWithEntity {
Line 213: Line 220:
      
   @Override   @Override
-  protected ItemActionResult onUseWithItem(ItemStack stack, BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {+  protected ActionResult onUseWithItem(ItemStack stack, BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
     if (stack.getItem() instanceof DyeItem dyeItem) {     if (stack.getItem() instanceof DyeItem dyeItem) {
       if (world.getBlockEntity(pos) instanceof ColorBlockEntity colorBlockEntity) {       if (world.getBlockEntity(pos) instanceof ColorBlockEntity colorBlockEntity) {
         final int newColor = dyeItem.getColor().getEntityColor();         final int newColor = dyeItem.getColor().getEntityColor();
         final int originalColor = colorBlockEntity.color;         final int originalColor = colorBlockEntity.color;
-        colorBlockEntity.color = ColorHelper.Argb.averageArgb(newColor, originalColor);+        colorBlockEntity.color = ColorHelper.average(newColor, originalColor);
         stack.decrementUnlessCreative(1, player);         stack.decrementUnlessCreative(1, player);
         colorBlockEntity.markDirty();         colorBlockEntity.markDirty();
Line 231: Line 238:
 </code> </code>
  
-Finally, modify the color provider to use the render data. We call ''FabricBlockView.getBlockEntityRenderData'' to ensure thread-safety and data-consistency.+最后,修改颜色提供器以使用渲染数据。我们调用 ''FabricBlockView.getBlockEntityRenderData'' 以确保线程安全和数据连贯。
 <code java ExampleModClient.java> <code java ExampleModClient.java>
 @Environment(EnvType.CLIENT) @Environment(EnvType.CLIENT)
Line 245: Line 252:
 </code> </code>
  
-Now done! Then you can check whether the following work correctly: +搞定!现在你可以检查下面这些是否都正常起作用: 
-  * When you interact the block with a dye, the color should change. +  * 使用染料交互,颜色应该改变。 
-  * When you modify the color through ''/data'' command, the color should change. +  * 通过 ''/data'' 命令修改颜色时,颜色应该改变。 
-  * When you pick (press mouse wheel) the block with ''Ctrl'' pressed, and place the block, it should display as the expected color. +  * 按下 ''Ctrl'' 同时拾取(按下鼠标中键)并放置方块,应该显示为预期的颜色。 
-  * When you leave the world and re-enter, the color should be kept.+  * 离开世界重进,颜色应该保留。
  
-===== 物品颜色提供器 ===== +===== 自定义物品着色(1.21.4 及之后) ===== 
-物品是类似的,区别在于提供的上下文不访问状态、世界和位置,而是访问 ''ItemStack''+从 1.21.4 开始,物品的着色是由物品模型映射指定的。原版提供了几种常见的着色来源的类型,参见 [[https://zh.minecraft.wiki/w/物品模型映射|Minecraft Wiki]]。在这个例子中,我们需要直接指定物品的颜色,因此可以将物品模型映射像这样写: 
 +<code javascript /resources/assets/tutorial/items/color_block.json> 
 +
 +  "model":
 +    "type": "model", 
 +    "model": "tutorial:block/color_block", 
 +    "tints":
 +      { 
 +        "type": "constant", 
 +        "value": 3446251 
 +      } 
 +    ] 
 +  } 
 +
 +</code> 
 + 
 +如果需要指定自定义的着色来源,可以使用原版提供的 ''TintResourceTypes.//ID_MAPPER//.put(...)'' 进行注册。注意是在客户端环境下完成的。注册时使用的 ID 将是上面的物品模型映射中的 ''%%"tints"%%'' 中的 ''%%"type"%%'' 的值。 
 + 
 +> 如果着色不生效,检查下使用的模型中的 tintindex 的值,应该与物品模型映射中的 ''%%"tints"%%'' 列表中的元素下标对应。例如,如果 tintindex 为 2,表示将使用物品模型映射中的第三个着色来源。 
 + 
 +===== 物品颜色提供器(1.21.4 之前) ===== 
 +在 1.21.3 以及之前的版本,物品的颜色提供器也可通过 Fabric API 注册。与方块不同物品的颜色提供器提供的上下文不访问状态、世界和位置,而是访问 ''ItemStack''
  
 物品模型可以直接继承使用 tintindex 的方块模型: 物品模型可以直接继承使用 tintindex 的方块模型:
 +
 +首先,物品需要一个直接继承方块模型的物品模型:
 +<code javascript /resources/assets/tutorial/models/item/color_block.json>
 +{
 +  "parent": "tutorial:block/color_block"
 +}
 +</code>
 +
 +然后,再在客户端环境中,注册颜色提供器。
  
 <code java ExampleModClient.java> <code java ExampleModClient.java>
zh_cn/tutorial/colorprovider.1724728430.txt.gz · Last modified: 2024/08/27 03:13 by solidblock