====== 模型谓词提供器 =======
===== 介绍 =====
模型谓词提供器用于给予 ''ItemStack'' 的数据动态改变物品的模型。一个简单的例子是弓,其在不同的拉伸度下会有不同的纹理。所有的提供器都会用在物品的模型文件中,位于 ''overrides'' 部分。
===== 可行示例 =====
在此例中,我们假定有了自定义的弓,叫做 ''TutorialItems.EXAMPLE_BOW''。
在其方法中,使用其物品和一个 ''Identifier'' 注册一个 ''ModelPredicateProvider''。对于 ''Identifier'' 的使用,不需要提供命名空间,因为这些不会与 Minecraft 的提供器冲突。这些必须在你的 ''ClientModInitializer'' 的 ''onInitializeClient'' 方法中完成。如果你没有 ''ClientModInitializer'',可以看看[[zh_cn:documentation:entrypoint|入口点]]教程以添加一个。
@Environment(EnvType.CLIENT)
public class ExampleModClient implements ClientModInitializer {
public static void registerModelPredicateProviders() {
//对于 1.21 之前的版本,将 'Identifier.ofVanilla' 替换为 'new Identifier'。
ModelPredicateProviderRegistry.register(EXAMPLE_BOW, Identifer.ofVanilla("pull"), (itemStack, clientWorld, livingEntity, seed) -> {
if (livingEntity == null) {
return 0.0F;
}
return livingEntity.getActiveItem() != itemStack ? 0.0F : (itemStack.getMaxUseTime(livingEntity) - livingEntity.getItemUseTimeLeft()) / 20.0F;
});
ModelPredicateProviderRegistry.register(EXAMPLE_BOW, Identifier.ofVanilla("pulling"), (itemStack, clientWorld, livingEntity, seed) -> {
if (livingEntity == null) {
return 0.0F;
}
return livingEntity.isUsingItem() && livingEntity.getActiveItem() == itemStack ? 1.0F : 0.0F;
});
}
@Override
public void onInitializeClient() {
// ...
registerModelPredicateProviders();
}
}
如果 ''ModelPredicateProviderRegistry'' 在某些版本不存在,考虑使用 ''FabricModelPredicateProviderRegistry''。
''ModelPredicateProvider'' 是函数型接口,需要一个 ''ItemStack'' 作为当前被渲染的物品堆,一个 ''ClientWorld'' 作为客户端所在的当前世界,以及使用该物品的玩家 ''LivingEntity''(在1.17+,还需要接收一个''int'')。
所有的 ''ModelPredicateProvider'' 返回浮点数,用来代表模型的不同状态,或者通过返回 ''1.0f'' 和 ''0f'' 来分别表示真假值。返回的值会被限制在 0.0f 到 1.0f 之间。
仔细看看 ''pull'' 谓词,我们会看到我们首先检查实体是否为 null,因为物品可以在其使用的环境之外渲染(例如掉落在地上)。我们确保实体使用我们的物品,否则物品会让模型谓词在不被使用的时候应用。最后,我们将 ''itemStack.getMaxUseTime(livingEntity)'' 减去 ''livingEntity.getItemUseTimeLeft()'' 以表示物品所被持有的刻数。因为完全拉满一把弓需要 20 刻即 1 秒的时间,所以我们将这个数字除以 ''20.0f'' 以使其介于 ''0f'' 到 ''1.0f'' 之间来表示正常的拉伸进度。
所有这些都是有用的,但为了让我们的物品改变其模型,我们只需要实现其一部分的特性。
{
// [...]
"overrides": [
{
"predicate": {
"pulling": 1
},
"model": "tutorial:item/example_bow_pulling_0"
},
{
"predicate": {
"pulling": 1,
"pull": 0.65
},
"model": "tutorial:item/example_bow_pulling_1"
},
{
"predicate": {
"pulling": 1,
"pull": 0.9
},
"model": "tutorial:item/example_bow_pulling_2"
}
]
}
Minecraft 运作的方式是,在指定的值中,检查模型大于等于的值的最后一个值。所以拉伸值为 ''0.8'' 时,会使用 ''tutorial:item/example_bow_pulling_1'',而值为 ''0.5'' 时使用''tutorial:item/example_bow_pulling_0''。