zh_cn:tutorial:colorprovider
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
zh_cn:tutorial:colorprovider [2019/12/19 05:48] – lightcolour | zh_cn:tutorial:colorprovider [2025/04/01 12:11] (current) – solidblock | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== | + | ====== 颜色提供器 |
- | 有没有想过,草木和树叶如何根据生物群落而改变色调,或者皮革装甲如何具有看似无限的颜色模式? | + | 有没有想过,草和树叶如何根据生物群系而改变色调的?皮革盔甲如何具有看似无限的颜色模式?答案是**颜色提供器**,这个可以允许你根据位置、NBT、方块状态等属性为方块或物品的模型纹理设置色调或者着色。 |
- | === 现有例子 === | + | ===== 原版例子 |
- | 首先,现有的哪些原版内容使用颜色提供程序? 一些示例包括: | + | 首先,现有的哪些原版内容使用颜色提供器?一些示例包括: |
*草 | *草 | ||
| | ||
- | | + | |
| | ||
- | *瓜类,甘蔗和睡莲等植物 | + | *西瓜、甘蔗和睡莲等植物 |
- | *尖箭头 | + | *药箭 |
- | 颜色提供程序功能强大,但是Mojang选择对混凝土,羊毛和玻璃等有色块坚持使用单独的纹理。 此时的主要用例是针对生物群落阴影块和对现有纹理的细微调整,例如带尖箭头的彩色末端。 | + | 颜色提供器功能强大,但是 Mojang 选择对混凝土、羊毛和玻璃等有色方块坚持使用单独的纹理。此时的主要用例是针对受生物群系的方块,以及对现有纹理的细微调整,例如药箭的彩色末端。 |
- | 颜色提供程序背后的概念很简单。 | + | 颜色提供器背后的概念很简单。你为之注册方块和物品,并在渲染该方块或物品的模型时,颜色提供器对纹理的每一层应用色调调整。两个提供器都可以访问模型的层,这意味着您可以分别对模型的每个部分进行色调设置,皮革盔甲和药箭就是这种情况。当您只想更改几个像素而不是整个纹理时,这很有用。 |
- | 请记住,提供颜色是客户端机制。 确保将与其相关的所有代码放入客户端初始化程序中。 | + | 请记住,颜色提供器是客户端机制。确保将与其相关的所有代码放入客户端初始化器中。 |
- | ===== 注册方块 | + | ===== 方块颜色提供器 |
- | 要将块注册到块颜色提供程序,您需要使用Fabric的'' | + | |
- | <code java [enable_line_numbers=" | + | 要将方块注册到方块颜色提供器,您需要使用 Fabric 的 '' |
- | ColorProviderRegistry.BLOCK.register(new | + | |
- | | + | 首先,先在 '' |
- | public | + | <code java TutorialBlocks.class> |
- | return 0x3495eb; | + | public final class TutorialBlocks { |
- | } | + | |
- | }, MY_BLOCK); | + | |
+ | // 1.21.2 之前: | ||
+ | public static final Block COLOR_BLOCK = register(" | ||
+ | |||
+ | // 1.21.2 及之后: | ||
+ | | ||
+ | } | ||
</ | </ | ||
- | 我们在这里所做的只是说:" | + | 简单添加个方块状态文件: |
- | 该模型也很重要:这里的主要提示是//您需要//为要色调的模型的每个部分定义一个tintindex。 要查看此示例,请查看'' | + | <code javascript src/ |
- | <code json [enable_line_numbers=" | + | { |
+ | " | ||
+ | "": | ||
+ | " | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | 在你的 '' | ||
+ | <code java ExampleModClient.java> | ||
+ | @Environment(EnvType.CLIENT) | ||
+ | public class ExampleModClient implements ClientModInitializer { | ||
+ | @Override | ||
+ | public void onInitializeClient() { | ||
+ | // ... | ||
+ | |||
+ | ColorProviderRegistry.BLOCK.register((state, | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | 如果还没有的话,记得在你的 [[documentation: | ||
+ | <code javascript> | ||
+ | { | ||
+ | // ... | ||
+ | " | ||
+ | // ... | ||
+ | " | ||
+ | " | ||
+ | ] | ||
+ | }, | ||
+ | // ... | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | 然后创建带有 // | ||
+ | |||
+ | < | ||
{ | { | ||
" | " | ||
Line 40: | Line 84: | ||
}, | }, | ||
" | " | ||
- | { | + | { " |
" | " | ||
" | " | ||
Line 54: | Line 98: | ||
} | } | ||
</ | </ | ||
- | 在这种情况下,我们添加了一个单一的tintindex,它会出现在`layer`参数(第0层)中。 | ||
- | 这是最终结果-请注意,原始模型使用了'' | + | 在这个实例里面,我们添加了单一的 tintindex,出现在 '' |
+ | <code javascript src/ | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | > **注意:**方块颜色是有缓存的,如果提供了随时间改变的颜色,这个改变不会直接生效,除非附近有方块更新。 | ||
+ | |||
+ | 这是最终结果——请注意,原始模型使用了 '' | ||
{{https:// | {{https:// | ||
- | ===== 注册颜色提供物品 ===== | + | |
- | 项目相似;区别在于提供的上下文。 您无需访问状态,世界或位置,而可以访问'' | + | ===== 带有颜色提供器的方块实体 ===== |
- | < | + | |
- | ColorProviderRegistry.ITEM.register((itemStack, layer) -> { | + | 如果你需要在颜色提供器中访问 '' |
- | return | + | |
- | }, COLORED_ITEM); | + | 这是因为方块可以在单独的线程渲染,所以直接访问数据并不安全。而且,如果使用 '' |
+ | |||
+ | 在这个例子中,我们创建一个 '' | ||
+ | |||
+ | <code java ColorBlock.java> | ||
+ | public class ColorBlock extends BlockWithEntity { | ||
+ | public ColorBlock(Settings settings) { | ||
+ | super(settings); | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | protected MapCodec<? | ||
+ | return createCodec(ColorBlock:: | ||
+ | } | ||
+ | |||
+ | @Nullable | ||
+ | @Override | ||
+ | public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { | ||
+ | return new ColorBlockEntity(pos, | ||
+ | } | ||
+ | |||
+ | // 自从 1.21.4 开始,不再需要这个方法,因为所有方块实体都默认使用方块模型。 | ||
+ | @Override | ||
+ | protected BlockRenderType getRenderType(BlockState state) { | ||
+ | return BlockRenderType.MODEL; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | <code java ColorBlockEntity.java> | ||
+ | public class ColorBlockEntity extends BlockEntity { | ||
+ | public int color = 0x3495eb; | ||
+ | |||
+ | public ColorBlockEntity(BlockPos pos, BlockState state) { | ||
+ | super(TutorialBlockEntityTypes.COLOR_BLOCK, | ||
+ | } | ||
+ | |||
+ | // 以下两个方块指定了颜色数据的序列化。 | ||
+ | |||
+ | @Override | ||
+ | protected void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup) { | ||
+ | super.readNbt(nbt, | ||
+ | |||
+ | // 对于 1.21.5 之前的版本,请直接使用 nbt.getInt(" | ||
+ | color = nbt.getInt(" | ||
+ | |||
+ | // 当数据通过“/ | ||
+ | // 需要同步更新。 | ||
+ | if (world != null) { | ||
+ | world.updateListeners(pos, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | protected void writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup) { | ||
+ | super.writeNbt(nbt, | ||
+ | nbt.putInt(" | ||
+ | } | ||
+ | |||
+ | @Nullable | ||
+ | @Override | ||
+ | public Packet< | ||
+ | return BlockEntityUpdateS2CPacket.create(this); | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | public NbtCompound toInitialChunkDataNbt(RegistryWrapper.WrapperLookup registryLookup) { | ||
+ | return createNbt(registryLookup); | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | public @Nullable Object getRenderData() { | ||
+ | // 这是来自 `RenderDataBlockEntity` 类的方法。 | ||
+ | return color; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | 在 '' | ||
+ | <code java> | ||
+ | // 1.21.2 之前: | ||
+ | public static final ColorBlock COLOR_BLOCK = register(" | ||
+ | |||
+ | // 1.21.2 及之后: | ||
+ | public static final Block COLOR_BLOCK = register(" | ||
+ | </ | ||
+ | |||
+ | 在 '' | ||
+ | <code java> | ||
+ | public static final BlockEntityType< | ||
+ | BlockEntityType.Builder.create(ColorBlockEntity:: | ||
+ | </ | ||
+ | |||
+ | > 不要忘了在你的模组初始化器中,静态加载 '' | ||
+ | |||
+ | 现在我们修改 '' | ||
+ | <code java ColorBlock.java> | ||
+ | public class ColorBlock extends BlockWithEntity { | ||
+ | [...] | ||
+ | |||
+ | @Override | ||
+ | protected ActionResult onUseWithItem(ItemStack stack, BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { | ||
+ | if (stack.getItem() instanceof DyeItem dyeItem) { | ||
+ | if (world.getBlockEntity(pos) instanceof ColorBlockEntity colorBlockEntity) { | ||
+ | final int newColor = dyeItem.getColor().getEntityColor(); | ||
+ | final int originalColor = colorBlockEntity.color; | ||
+ | colorBlockEntity.color = ColorHelper.average(newColor, | ||
+ | stack.decrementUnlessCreative(1, | ||
+ | colorBlockEntity.markDirty(); | ||
+ | world.updateListeners(pos, | ||
+ | } | ||
+ | } | ||
+ | return super.onUseWithItem(stack, | ||
+ | } | ||
+ | |||
+ | [...] | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | 最后,修改颜色提供器以使用渲染数据。我们调用 '' | ||
+ | <code java ExampleModClient.java> | ||
+ | @Environment(EnvType.CLIENT) | ||
+ | public class ExampleModClient implements ClientModInitializer { | ||
+ | [...] | ||
+ | @Override | ||
+ | public void onInitializeClient() { | ||
+ | [...] | ||
+ | |||
+ | ColorProviderRegistry.BLOCK.register((state, | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | 搞定!现在你可以检查下面这些是否都正常起作用: | ||
+ | * 使用染料交互,颜色应该改变。 | ||
+ | * 通过 ''/ | ||
+ | * 按下 '' | ||
+ | * 离开世界重进,颜色应该保留。 | ||
+ | |||
+ | ===== 自定义物品着色(1.21.4 及之后) | ||
+ | 从 1.21.4 开始,物品的着色是由物品模型映射指定的。原版提供了几种常见的着色来源的类型,参见 [[https:// | ||
+ | <code javascript / | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | ] | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | 如果需要指定自定义的着色来源,可以使用原版提供的 | ||
+ | |||
+ | > 如果着色不生效,检查下使用的模型中的 tintindex 的值,应该与物品模型映射中的 '' | ||
+ | |||
+ | ===== 物品颜色提供器(1.21.4 之前) ===== | ||
+ | 在 1.21.3 以及之前的版本,物品的颜色提供器也是可通过 Fabric API 注册的。与方块不同,物品的颜色提供器提供的上下文不访问状态、世界和位置,而是访问 '' | ||
+ | |||
+ | 物品模型可以直接继承使用 tintindex 的方块模型: | ||
+ | |||
+ | 首先,物品需要一个直接继承方块模型的物品模型: | ||
+ | < | ||
+ | { | ||
+ | | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | 然后,再在客户端环境中,注册颜色提供器。 | ||
+ | |||
+ | <code java ExampleModClient.java> | ||
+ | @Environment(EnvType.CLIENT) | ||
+ | public class ExampleModClient implements ClientModInitializer { | ||
+ | @Override | ||
+ | public void onInitializeClient() { | ||
+ | // ... | ||
+ | |||
+ | | ||
+ | } | ||
+ | } | ||
</ | </ | ||
- | 这将色相相同的方式为块库存量的项目。 | + | 这会以像方块那样的方法为你物品栏中的物品提供色相。 |
- | === 局限性 === | + | ===== 限制 ===== |
- | 使用颜色提供程序的一个关键问题是项目提供程序中缺少上下文。 这就是为什么原版草不会根据您站立的位置改变存货颜色的原因。 为了实现诸如块的颜色变体(混凝土,玻璃,羊毛等)之类的东西,建议您为每个版本简单地提供单独的纹理。 | + | 使用颜色提供器的一个关键问题是物品的提供器中缺少上下文。这就是为什么原版草不会根据您站立的位置改变物品栏中的颜色的原因。为了实现诸如方块的颜色变体(混凝土、玻璃、羊毛等)之类的东西,建议您为每个版本简单地提供单独的纹理。 |
zh_cn/tutorial/colorprovider.1576734501.txt.gz · Last modified: 2019/12/19 05:48 by lightcolour