Заметки по созданию моделей FreeMinecraftModels
Эта страница документирует текущие детали создания моделей, видимые в кодовой базе FreeMinecraftModels. Она намеренно консервативна: сосредоточена на контракте импорта/среды выполнения, а не на каждом предпочтении рабочего процесса Blockbench.
Исходные форматы
FreeMinecraftModels в настоящее время принимает:
- файлы
.bbmodelдля редактируемых исходных импортов - файлы
.fmmodelдля облегчённых данных моделей, готовых к выполнению
Обычный процесс импорта:
- поместите модель в
plugins/FreeMinecraftModels/imports - выполните
/fmm reload - позвольте FreeMinecraftModels импортировать модель в активный набор моделей и пересобрать сгенерированный ресурспак
Роли папок
plugins/FreeMinecraftModels/imports
plugins/FreeMinecraftModels/models
plugins/FreeMinecraftModels/models_disabled
imports— это входная папка для ручного импорта моделей и загрузки официальных пакетов до обработкиmodelsсодержит активный установленный контент моделейmodels_disabledсодержит загруженный или установленный контент пакетов, который в данный момент отключён
В старых установках вместо этого может быть папка Models с заглавной буквы. FreeMinecraftModels решает это, предпочитая каноническую строчную models, когда она существует, и откатываясь на устаревшую Models, только когда её нет. На Windows и macOS это в любом случае один и тот же каталог; на чувствительной к регистру файловой системе Linux старая установка продолжает работать, но если обе директории каким-то образом существуют, читается только строчная models. Если вы нашли обе — сведите их в models.
Идентификаторы моделей
- Идентификаторы моделей в среде выполнения берутся из имени файла без расширения
.bbmodelили.fmmodel - Используйте стабильные, уникальные имена файлов, поскольку идентификатор — это то, к чему обращаются команды и вызовы API
- Ссылки на анимации в Blockbench основаны на именах, поэтому дублирующиеся или неясные имена внутри модели чаще вызывают проблемы, чем чистая, явная схема именования
- Сопоставление расширения не учитывает регистр, поэтому
.BBModelи.FMModelтоже принимаются
Нормализация ID и коллизии
Имя файла нормализуется, прежде чем стать ID модели во время выполнения и именем файла в ресурс-паке:
- приводится к нижнему регистру
- каждый символ вне
a-z,0-9,.,_и-заменяется на_
Поэтому My Table.bbmodel, my table.bbmodel и my_table.bbmodel нормализуются в один и тот же ID, my_table.
Перед запуском любого преобразования FreeMinecraftModels обходит всё дерево моделей и проверяет файлы, нормализующиеся в один ID. Когда коллизия найдена:
- отклоняется каждый конфликтующий файл — ни один из них не загружается, поэтому нет молчаливого «побеждает последний»
- ID модели блокируется на весь оставшийся проход загрузки
- отклонённые модели также исключаются из экспорта комплекта кастомных Bedrock-сущностей
- в консоль выводится:
[FMM Models] Rejected normalized model ID collision '<id>'. These files normalize to the same ID: <paths>. Rename the files so every normalized model ID is unique; no colliding model was loaded.
Решение всегда одно — переименовать файлы так, чтобы нормализованные ID различались. Самая безопасная привычка — с самого начала называть файлы моделей в нижнем регистре с подчёркиваниями (stone_table.bbmodel), что делает имя файла и ID времени выполнения идентичными и полностью убирает шанс неожиданной коллизии.
Совместимость с Blockbench
- FreeMinecraftModels читает
meta.format_versionиз.bbmodelи ветвится по его мажорному номеру - Отсутствующий блок
meta, отсутствующийformat_versionили значение, которое не удаётся разобрать, — всё это откатывается к версии4, с информационной строкой или предупреждением, называющим модель - Отсутствующий массив
texturesпринимается и трактуется как пустой список текстур, а не приводит к падению импортёра. Экспортёр кастомных Bedrock-сущностей затем пропускает такую модель, потому что экспорт в Bedrock требует хотя бы одной текстуры - Имена извлечённых файлов текстур нормализуются к одному расширению
.png. Исходное имя вродеbody.jpg,body.PNGилиbodyзаписывается и указывается какbody.png format_version4.xи старше: кости читаются напрямую из дереваoutliner, которое несёт имена костей внутри себяformat_version5.xи новее: схема outliner изменилась.outlinerтеперь — вложенное дерево из голых строк UUID и словарей{uuid, isOpen, children}без ключа имени, тогда как отдельный плоский массивgroupsсодержит фактические данные костей (включаяname). FMM соединяет их по UUID — каждый узел outliner заменяется соответствующей записьюgroups, затем дочерние узлы объединяются рекурсивно, — поэтому имена костей, origin'ы и повороты разрешаются нормально- Следствия, о которых стоит знать при ручной правке или генерации файлов
.bbmodel:- Файл v5, в котором отсутствует массив
groups, пропускается без объединения, поэтому его кости теряют имена, а зарезервированные префиксы (tag_,h_,b_,m_,hitbox) перестают распознаваться - UUID должны точно совпадать между
outlinerиgroups; узел outliner без соответствующей группы сохраняется как есть, а не отбрасывается - Не смешивайте
format_versionv5 с outliner в форме v4 и наоборот — ветка выбирается по объявленной версии, а не по фактической форме
- Файл v5, в котором отсутствует массив
- Если журналы импорта сообщают, что формат модели несовместим с FreeMinecraftModels, рассматривайте это в первую очередь как проблему формата модели, а не вики или команды
Соглашения об именовании костей, значимые для среды выполнения
Текущий конвертер и конвейер скелета распознают несколько соглашений об именовании:
hitbox- зарезервировано для генерации хитбоксов
- должно чётко определять хитбокс модели, а не использоваться как визуальная кость
- обязана быть костью верхнего уровня в outliner. Импортёр ищет её только на корневом уровне; группа
hitbox, вложенная внутрь другой кости, считается обычной костью - обязана содержать ровно один куб, который задаёт ширину (x), глубину (z) и высоту (y) во время выполнения. Лишние кубы приводят к записи в лог
has more than one value defining a hitbox! Only the first cube will be used; пустая кость hitbox даётhas a hitbox bone but no hitbox cube!, и хитбокс не генерируется - никогда не анимируется (треки анимации, нацеленные на
hitbox, пропускаются), никогда не отрисовывается и исключается из экспорта геометрии Bedrock. На Bedrock модель без костиhitboxоткатывается к1.0x2.0
tag_...- единственный способ, которым модель получает тег имени. См. Для тегов имён нужна кость
tag_ниже
- единственный способ, которым модель получает тег имени. См. Для тегов имён нужна кость
h_...- обрабатывается как кости головы
b_...- неотображаемые кости (скрыты в среде выполнения). Используйте их для структурных или организационных костей, которые не должны рендериться в игре.
m_...- кости точек посадки. Каждая кость с этим префиксом создаёт ездовую позицию для посадки на модели. Игроки или сущности могут быть посажены на эти позиции во время выполнения. Несколько
m_-костей создают несколько мест. Управляется внутренне черезMountPointManager.
- кости точек посадки. Каждая кость с этим префиксом создаёт ездовую позицию для посадки на модели. Игроки или сущности могут быть посажены на эти позиции во время выполнения. Несколько
Это не просто стилистические соглашения; они влияют на конвертацию и поведение среды выполнения.
Для тегов имён нужна кость tag_
Это самая частая причина безымянных мобов в поставляемом контенте, поэтому стоит сказать прямо:
Модель получает тег имени, только если содержит кость, чьё имя начинается с tag_. Запасного варианта нет.
Как это работает:
- При импорте любая кость с именем
tag_...получает параллельную автогенерируемую «мета»-кость (fmm_nametag_bone_<name>), помеченную как кость тега имени. Больше ничто в конвейере этот флаг не выставляет - Во время выполнения скелет собирает эти помеченные кости, и в origin'е кости
tag_спавнится text display. Его позиция и текст следуют за этой костью ModeledEntity.setDisplayName(...)иsetDisplayNameVisible(...)проходят по этой коллекции. Без костиtag_коллекция пуста, и оба вызова молча ничего не делают — ни ошибки, ни предупреждения, ни имени
Почему ванильный тег имени вас не выручает:
- Динамическая модель скрывает от клиентов лежащую в основе живую сущность (
setVisibleByDefault(false)плюс флаг невидимости), поэтому собственный тег имени ванильного моба тоже не отрисовывается - В итоге получается совершенно безымянный моб, хотя вызывающий плагин успешно задал отображаемое имя
Практические правила:
- Если модель представляет именованную сущность (босса EliteMobs, квестового NPC, что угодно, для чего плагин вызывает
setDisplayName), добавьте костьtag_ - Разместите её там, где должен парить тег имени — обычно чуть выше головы
- Кости не нужны кубы; это позиционный якорь. В частности,
tag_nameпропускается при генерации определений моделей предметов, поэтому она никогда не отрисовывается как геометрия - Несколько костей
tag_допустимы; каждая из них получает собственный text display с тем же именем - Если вы видите в консоли
nametag bone did not spawn name tag, кость была распознана, но её text display не смог заспавниться — это другая проблема, чем полное отсутствие костиtag_
Свободно парящие кубы
Кубы, объявленные в верхней части outliner без содержащей их группы, приходят как «голые» строки UUID, а не как записи костей. FreeMinecraftModels присоединяет их к автогенерируемой корневой кости (freeminecraftmodels_autogenerated_root), чтобы они всё же отрисовывались. Анимации к ним обращаться не могут, поэтому всё, что вы собираетесь анимировать, помещайте внутрь настоящей группы.
IK, нулевые объекты и локаторы
Текущий код подтверждает поддержку:
- нулевых объектов Blockbench в качестве контроллеров IK
- чертежей цепей IK и решения IK во время выполнения (FABRIK)
- парсинга локаторов
Нулевой объект становится контроллером IK только тогда, когда его запись в .bbmodel несёт оба поля: ik_source (кость, с которой начинается цепь) и ik_target (кость или локатор, к которому цепь тянется). Также считывается lock_ik_target_rotation. Цепь обнаруживается обходом иерархии костей вверх от цели к источнику, поэтому эти двое должны быть действительно связаны.
Важные практические ограничения:
- Связь источника и цели идёт по UUID, поэтому она переживает переименования — но если какого-то UUID нет в модели, в консоль пишется
IK chain in model <model>: Could not find source bone with UUID .../Could not find target with UUID ..., и эта цепь пропускается - Если обход не находит пути от источника к цели, вы получите
Could not find path from source to target, и цепь пропускается - Поиск анимации для контроллера основан на именах, поэтому именование контроллеров должно оставаться стабильным между структурой модели и данными анимации
- Значение имеют только ключевые кадры позиции на нулевом объекте — они становятся смещением цели IK. Треки поворота и масштаба на нулевом объекте игнорируются
О том, как IK управляется покадрово, см. Анимации.
Разделение вывода для 1.21.4+
FreeMinecraftModels объявляет api-version: 1.21.4, поэтому 1.21.4 — это минимальная версия сервера, и современная раскладка определений моделей предметов — единственная, которую вы получите:
plugins/FreeMinecraftModels/output/FreeMinecraftModels/assets/freeminecraftmodels/items
В коде всё ещё существуют устаревшие (до 1.21.4) ветки с переопределениями через кожаную конскую броню, но ни один сервер, способный загрузить текущий плагин, до них не доходит. Если вы читаете старые заметки или смотрите на старую папку вывода — вот в чём разница.
Отображаемая модель JSON (1.21.4+)
Администраторы могут поместить файл .json рядом с файлом .bbmodel или .fmmodel с тем же базовым именем (например, table.bbmodel + table.json). Этот JSON должен быть экспортирован из Blockbench как модель «Java Block/Item» и определяет, как предмет выглядит при удержании в руке или отображении в инвентаре.
При импорте FMM копирует JSON в вывод ресурспака и автоматически переписывает голые ссылки на текстуры внутри него для указания на извлечённые текстуры модели. Если сопутствующий JSON отсутствует, предмет отображается в игре как обычная бумага.
Настройка пользовательских предметов в YML
Сопутствующий файл конфигурации .yml (с тем же базовым именем, что и модель) теперь поддерживает необязательные поля предметов. Если установлен material:, модель также доступна как пользовательский предмет для удержания в руке. Полный формат YML:
isEnabled: true
scripts:
- my_script.lua
material: DIAMOND_SWORD # optional — if set, model is also a custom item
name: '&b&lMy Custom Sword' # optional — display name
lore: # optional
- '&7A custom weapon'
enchantments: # optional — format: ENCHANTMENT_NAME,LEVEL
- SHARPNESS,5
- FIRE_ASPECT,2
Когда material: присутствует, модель появляется в браузере контента администратора наряду с пропсами и может быть выдана игрокам как функциональный предмет.
Заметки о Bedrock и пути рендеринга
- Поддержка Bedrock зависит от
sendCustomModelsToBedrockClientsV2(по умолчаниюtrue; заменяет более старый ключsendCustomModelsToBedrockClients) и окружающего пути Floodgate/Geyser/ресурспака - Java-клиенты на поддерживаемых версиях могут использовать рендеринг через display-сущности, когда
useDisplayEntitiesWhenPossibleвключен - Не предполагайте, что модель, которая выглядит правильно на Java-клиенте, автоматически безопасна для вашего пути Bedrock
Практические советы по созданию моделей
- сохраняйте стабильные имена файлов, потому что они становятся идентификаторами среды выполнения
- сохраняйте явные имена контроллеров и анимаций, потому что поиск анимаций в Blockbench основан на именах
- используйте зарезервированные имена виртуальных костей осознанно (
hitbox,tag_,h_,b_,m_) — и помните, что любой модели, которая должна показывать имя, нужна костьtag_, иначе она молча останется безымянной - называйте анимации состояний
spawn,idle,walk,attackиdeath, если хотите, чтобы они запускались автоматически; всё остальное — пользовательские анимации, которые вы запускаете сами (см. Анимации) - модель, предназначенная для
/fmm disguise, должна как минимум поставляться сidleи может добавлятьsneakиjump, которые распознаёт только контроллер маскировки (см. Маскировки игроков) - проверяйте импортированный вывод после
/fmm reload, а не только внутри Blockbench - проверяйте содержимое сгенерированного пака для вашей целевой версии Minecraft, особенно на
1.21.4+
Модели состояний лука и арбалета
FMM поддерживает автоматические состояния анимации натяжения для пользовательских предметов-луков и арбалетов. Настройка не требуется — просто назовите файлы моделей с правильными суффиксами, и FMM автоматически обнаружит набор состояний при генерации ресурспака.
Соглашение об именовании
| Суффикс | Назначение | Лук | Арбалет |
|---|---|---|---|
_idle | Предмет в руке, не натягивается и не заряжен | обязательно | обязательно |
_draw_start | Начало натяжения | обязательно | обязательно |
_draw_half | Натянут наполовину | обязательно | обязательно |
_draw_full | Полностью натянут | обязательно | обязательно |
_charged | Заряженный арбалет (стрела или ракета) | -- | обязательно |
Для лука нужны четыре модели (все кроме _charged). Для арбалета нужны все пять.
Пример расположения файлов
plugins/FreeMinecraftModels/imports/
cool_bow_idle.bbmodel
cool_bow_draw_start.bbmodel
cool_bow_draw_half.bbmodel
cool_bow_draw_full.bbmodel
cool_bow.yml <-- config uses the base name, not _idle
Для арбалета добавьте пятый файл cool_bow_charged.bbmodel.
Как работает обнаружение
- Обнаружение происходит автоматически при генерации ресурспака (при запуске или
/fmm reload). - Только модель
_idleполучает JSON-файл определения предмета в выходном паке. Состояния натяжения и зарядки указываются как условные записи внутри этого определения. - Только базовое имя получает файл конфигурации YML. В примере выше конфиг — это
cool_bow.yml, а неcool_bow_idle.yml.
Отображаемая модель JSON
Каждая модель состояния может иметь свой сопутствующий .json файл отображаемой модели (например, cool_bow_idle.json, cool_bow_draw_full.json). FMM автоматически подключает их к сгенерированному определению предмета. Точную JSON-структуру, которая генерируется, см. в Вывод ресурспака.
За рамками данной страницы
Эта страница не пытается гарантировать:
- точные шаги в интерфейсе Blockbench
- предпочтения художественного рабочего процесса
- каждую особенность устаревших
.bbmodel, описанную в более ранних локальных README-материалах
Эти детали меняются быстрее, чем проверенный контракт среды выполнения выше.
Имена текстур нормализуются к нижнему регистру и должны оканчиваться на .png: например, body.PNG и body.jpg разрешаются как textures/body.png. Не используйте имена, различающиеся только регистром.