Table of Contents

Поставщики моделей

Введение

Поставщики моделей используются для динамического изменения модели элементов на основе данных из ItemStack. Распространенным примером является лук, который имеет разную текстуру в зависимости от того, как долго был натянут лук. Затем все поставщики используются в файле модели для элемента в разделе overrides.

Практический пример

Для этого примера предположим, что у нас есть пользовательский предмет лука с именем EXAMPLE_BOW.

Внутри метода мы регистрируем ModelPredicateProvider с нашим предметом и Identifier. Для использования Identifier вам не нужно указывать пространство имен, так как ни одно из них не должно конфликтовать с поставщиками Minecraft. Это должно быть сделано в методе onInitializeClient вашего ClientModInitializer. Если у вас нет ClientModInitializer, посмотрите страницу Точки входа - руководство о том, как его добавить.

  1. FabricModelPredicateProviderRegistry.register(EXAMPLE_BOW, new Identifier("pull"), (itemStack, clientWorld, livingEntity) -> {
  2. if (livingEntity == null) {
  3. return 0.0F;
  4. }
  5. return livingEntity.getActiveItem() != itemStack ? 0.0F : (itemStack.getMaxUseTime() - livingEntity.getItemUseTimeLeft()) / 20.0F;
  6. });
  7.  
  8. FabricModelPredicateProviderRegistry.register(EXAMPLE_BOW, new Identifier("pulling"), (itemStack, clientWorld, livingEntity) -> {
  9. if (livingEntity == null) {
  10. return 0.0F;
  11. }
  12. return livingEntity.isUsingItem() && livingEntity.getActiveItem() == itemStack ? 1.0F : 0.0F;
  13. });

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 для нормального хода натяжения.

Все это полезно, но это только половина функций, которые нам необходимо реализовать, чтобы наш элемент изменил свою модель.

  1. "overrides": [
  2. {
  3. "predicate": {
  4. "pulling": 1
  5. },
  6. "model": "tutorial:item/example_bow_pulling_0"
  7. },
  8. {
  9. "predicate": {
  10. "pulling": 1,
  11. "pull": 0.65
  12. },
  13. "model": "tutorial:item/example_bow_pulling_1"
  14. },
  15. {
  16. "predicate": {
  17. "pulling": 1,
  18. "pull": 0.9
  19. },
  20. "model": "tutorial:item/example_bow_pulling_2"
  21. }
  22. ]

Принцип работы Minecraft заключается в том, что он проверяет, какая модель находится последней в списке, которая либо соответствует, либо имеет значения, превышающие указанные. Таким образом, при значении 0.8, мы бы использовали модель tutorial:item/example_bow_pulling_1. 0.5 будет tutorial:item/example_bow_pulling_0.