Маскировки игроков
FreeMinecraftModels умеет маскировать любого онлайн-игрока под загруженную модель. Маскировки управляются через команды, публичный DisguiseAPI и PlayerDisguiseEntity на каждого игрока, который отвечает за невидимость и отрисовку модели для замаскированного игрока.
Команды
| Команда | Право | Заметки |
|---|---|---|
/fmm disguise <modelID> | freeminecraftmodels.disguise.self | Маскирует отправителя. Только для игрока |
/fmm disguise <modelID> <player> | freeminecraftmodels.disguise.self + freeminecraftmodels.disguise.others | Маскирует указанного игрока. Работает из консоли |
/fmm undisguise | freeminecraftmodels.disguise.self | Снимает маскировку с отправителя. Только для игрока |
/fmm undisguise <player> | freeminecraftmodels.disguise.self + freeminecraftmodels.disguise.others | Снимает маскировку с указанного игрока. Работает из консоли |
/fmm disguiselist | freeminecraftmodels.disguise.others | Перечисляет всех замаскированных игроков и их модели |
Wildcard freeminecraftmodels.* выдаёт admin, deleteall, disguise.self и disguise.others при дефолте OP. Он также выдаёт отдельно зарегистрированное право freeminecraftmodels.bypassregionprotection.
Поведение
- Маскировка игрока, который уже замаскирован, аккуратно заменяет предыдущую маскировку — снимать её сначала не нужно.
- FMM скрывает игрока от других наблюдателей через
setVisibleByDefault(false)и добавляет эффект зелья невидимости, если его ещё нет. Подмена отображения экипировки скрывает броню и предметы в руках от других наблюдателей, не меняя инвентарь. Собственный вид игрока исключён из этой подмены; отображение его тела по-прежнему зависит от обработки видимости клиентом. - FMM повторно применяет невидимость через один тик после соответствующих событий удаления или изменения эффекта либо возрождения, только если эта маскировка изначально добавила эффект. Эффект невидимости, существовавший до начала маскировки, не сохраняется и не восстанавливается. Снятие маскировки возвращает видимость по умолчанию в
true, удаляет добавленный FMM эффект и повторно отправляет текущую экипировку игрока. - Скрытие экипировки повторно отправляется для подключающихся наблюдателей и при смене мира. Реальная броня и предметы в руках игрока не заменяются.
- Хитбокс игрока не меняется. Декоративная маскировка не создаёт пакетную сущность взаимодействия, а её обработчики кликов ничего не делают, поэтому отдельной цели для атак или посадки она не предоставляет. Невидимость может влиять на поведение вне FMM; неизменность выбора целей мобами не гарантируется.
- Маскировки не переживают перезапуск сервера,
/fmm reloadили выход игрока из игры — они отслеживаются в памяти, и обработчикDisguiseListeners.onQuitснимает маскировку поPlayerQuitEvent. Смерть и смена мира не снимают маскировку. - Успешный
/fmm reloadудаляет активные маскировки при выключении; после него их нужно применить заново. Если перезагрузка отклонена на этапе подготовки нового содержимого, активное состояние сохраняется.
Анимации маскировки
У каждой маскировки есть контроллер, выбирающий анимации по состоянию игрока перед запуском общего механизма воспроизведения моделируемых сущностей. Он не обходит этот механизм. Зарезервированные имена должны быть в нижнем регистре, поскольку проверка наличия анимаций учитывает регистр.
Распознаются пять зарезервированных имён анимаций, в следующем порядке приоритета (от высшего к низшему):
| Приоритет | Анимация | Тип | Что запускает |
|---|---|---|---|
| 1 | attack | одноразовая | Игрок взмахнул рукой |
| 2 | jump | одноразовая | Игрок оторвался от земли, двигаясь вверх |
| 3 | sneak | цикл | Игрок крадётся |
| 4 | walk | цикл | Позиция игрока изменилась более чем на 0,01 блока с прошлого тика, включая вертикальное движение |
| 5 | idle | цикл | Ничто другое не подходит |
Что стоит знать о поведении:
-
Учитываются только те анимации, которые действительно есть у модели. Модель без анимации
sneakпросто проваливается кwalkилиidle. -
Одноразовая анимация запрашивает немедленное воспроизведение без цикла и приостанавливает любой новый выбор на фиксированные 20 тиков (1 секунда при 20 TPS). Этот отсчёт не измеряет длительность анимации. Более длинная анимация может прерваться следующим выбором, а короткая — завершиться до возобновления выбора. Взмахи рукой во время паузы объединяются в одну ожидающую атаку, а переходы к прыжку не ставятся в очередь.
-
Циклы перезапускаются только тогда, когда выбранная анимация действительно меняется, поэтому ровная ходьба не начинается заново каждый тик.
-
jumpдействительно подключён для маскировок, в отличие от (сейчас неактивного) состояния прыжка у обычных моделируемых сущностей. См. Анимации. -
Модель маскировки без анимации
idleвыводит предупреждение при каждой маскировке:Disguise model '<model>' has no 'idle' animation — disguised players using this model will freeze on the last animation frame whenever no other action is active.Поставляйте анимацию
idleс любой моделью, которую собираетесь использовать как маскировку.
Клиенты Bedrock
Маскировки зависят от отрисовки пользовательской модели средствами FMM. Значение по умолчанию sendCustomModelsToBedrockClientsV2: true в config.yml включает отправку моделей Bedrock. При false модель не поступает наблюдателям Bedrock, а замаскированный игрок остаётся невидимым. Устаревший ключ sendCustomModelsToBedrockClients больше не читается. Даже при включённом V2 клиенту нужны преобразованный ресурс-пак и работающая интеграция Geyser/Floodgate.
DisguiseAPI
Сторонние плагины могут управлять маскировками программно через com.magmaguy.freeminecraftmodels.api.DisguiseAPI.
import com.magmaguy.freeminecraftmodels.api.DisguiseAPI;
// Disguise (returns false if the model ID is not loaded)
boolean ok = DisguiseAPI.disguise(player, "dragon");
// Undisguise (returns true if a disguise was removed)
DisguiseAPI.undisguise(player);
// Queries
boolean isDisguised = DisguiseAPI.isDisguised(player);
String modelID = DisguiseAPI.getDisguiseModelID(player); // null if not disguised
// Unmodifiable snapshot of all disguised players
Collection<Player> all = DisguiseAPI.getDisguisedPlayers();
Этот API — публичная, безопасная при рефакторингах точка входа. Плагинам следует обращаться к DisguiseAPI, а не к внутреннему DisguiseManager.
API не проверяет права команд и не нормализует ID моделей. Передавайте онлайн-игрока и точный ID загруженной модели. disguise удаляет существующую маскировку до попытки создать замену, поэтому неизвестный ID возвращает false уже после удаления прежней маскировки. Команда сначала проверяет модель и при неверном ID сохраняет старую маскировку. Успешный результат API подтверждает создание, а не отрисовку клиентом или принятие ресурс-пака.
Типичные сценарии
- Ролевые и RPG-серверы: маскировка игроков под модели боссов для синематиков или квестовых скриптов.
- Проведение событий: маскировка ведущего под гигантскую пользовательскую модель.
- Маунты и транспорт: комбинируйте
/fmm mountс/fmm disguiseдля креативных схем передвижения. - Интеграция с EliteMobs: скрипты боссов могут маскировать игрока, инициировавшего событие, для временного эффекта трансформации.
Решение проблем
Ничего не происходит после /fmm disguise dragon.
ID модели должен в точности совпадать с загруженной моделью. Проверьте имя модели через /fmm admin или автодополнение команды. Форма с указанием игрока проверяет freeminecraftmodels.disguise.others до того, как разрешает модель или игрока, и сообщает об отсутствии этого права напрямую.
Моя маскировка исчезла после /fmm reload.
Это ожидаемо после успешной полной перезагрузки. Для автоматического повторного применения маскировок слушайте FmmReloadedEvent, запланированное на основном потоке через 40 тиков после инициализации. Отклонённая подготовка не удаляет активное состояние.
Bedrock-игроки не видят маскировку. См. Клиенты Bedrock выше.
Замаскированный игрок всё ещё виден другим. Проверьте, был ли игрок невидимым до начала маскировки: FMM не берёт этот эффект под управление и не восстанавливает его после исчезновения. Также проверьте плагины, меняющие видимость игроков, эффекты или пакеты экипировки. FMM использует видимость игрока, реальный эффект зелья и подмену отображения экипировки; подтвердите конфликт, прежде чем менять настройки другого плагина.