Поставщики моделей используются для динамического изменения модели элементов на основе данных из ItemStack
. Распространенным примером является лук, который имеет разную текстуру в зависимости от того, как долго был натянут лук. Затем все поставщики используются в файле модели для элемента в разделе overrides
.
Для этого примера предположим, что у нас есть пользовательский предмет лука с именем EXAMPLE_BOW
.
Внутри метода мы регистрируем ModelPredicateProvider
с нашим предметом и Identifier
. Для использования Identifier
вам не нужно указывать пространство имен, так как ни одно из них не должно конфликтовать с поставщиками Minecraft. Это должно быть сделано в методе onInitializeClient
вашего ClientModInitializer
. Если у вас нет ClientModInitializer
, посмотрите страницу Точки входа - руководство о том, как его добавить.
FabricModelPredicateProviderRegistry.register(EXAMPLE_BOW, new Identifier("pull"), (itemStack, clientWorld, livingEntity) -> { if (livingEntity == null) { return 0.0F; } return livingEntity.getActiveItem() != itemStack ? 0.0F : (itemStack.getMaxUseTime() - livingEntity.getItemUseTimeLeft()) / 20.0F; }); FabricModelPredicateProviderRegistry.register(EXAMPLE_BOW, new Identifier("pulling"), (itemStack, clientWorld, livingEntity) -> { if (livingEntity == null) { return 0.0F; } return livingEntity.isUsingItem() && livingEntity.getActiveItem() == itemStack ? 1.0F : 0.0F; });
ModelPredicateProvider
- это функциональный интерфейс, который принимает ItemStack
для текущего отображаемого стака, ClientWorld
для текущего мира, в котором находится клиент, и LivingEntity
в качестве пользователя этого предмета (В 1.17+ он также принимает int
).
Все ModelPredicateProvider
возвращают значение в виде float
, которое может использоваться для представления различных состояний модели, или значение true/false, возвращая 1.0f
и 0f
соответственно.
Присмотревшись повнимательнее к предикату pull
, мы видим, что сначала мы проверяем, является ли сущность null, поскольку предметы могут отображаться вне контекста, в котором они используются (т.е. сбрасываться на землю). Затем мы удостоверяемся, что сущность использует наш предмет, в противном случае предмет может иметь предикат модели, применяемый, когда он не используется. Наконец, мы вычитаем livingEntity.getItemUseTimeLeft()
из itemStack.getMaxUseTime()
, который сообщает нам, сколько тиков удерживался элемент. Поскольку для полной зарядки лука требуется 20 тиков или одна секунда, мы затем делим это число на 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
.