Перейти к основному содержимому

API и руководство разработчика FreeMinecraftModels

FreeMinecraftModels — это одновременно автономный плагин и API-поверхность для других плагинов.

Репозиторий Maven

<repository>
<id>magmaguy-repo-releases</id>
<name>MagmaGuy's Repository</name>
<url>https://repo.magmaguy.com/releases</url>
</repository>
<repository>
<id>magmaguy-repo-snapshots</id>
<name>MagmaGuy's Snapshot Repository</name>
<url>https://repo.magmaguy.com/snapshots</url>
</repository>

Зависимость

<dependency>
<groupId>com.magmaguy</groupId>
<artifactId>FreeMinecraftModels</artifactId>
<version>LATEST.VERSION.HERE</version>
<scope>provided</scope>
</dependency>

Используйте как compileOnly/provided. Не включайте плагин в свой jar через shade.

Основные точки входа

  • ModeledEntityManager.modelExists(String)
  • ModeledEntityManager.reload()
  • ModeledEntityManager.getAllEntities()
  • ModeledEntityManager.getDynamicEntities()
  • ModeledEntityManager.propEntities()

Основные типы среды выполнения

  • ModeledEntity
  • StaticEntity
  • DynamicEntity
  • PropEntity

Создание сущностей

StaticEntity preview = StaticEntity.create("example_model", location);
DynamicEntity mobModel = DynamicEntity.create("example_model", livingEntity);
DynamicEntity mount = DynamicEntity.createWithInvisibility("example_model", livingEntity);
PropEntity prop = PropEntity.spawnPropEntity("example_model", location);

Все пути создания возвращают null, если запрашиваемый идентификатор модели не загружен.

createWithInvisibility — вариант, который применяет зелье невидимости вместо скрытия сущности от клиентов. Это сохраняет отслеживание сущности на стороне клиента, что необходимо для управления транспортом (используется внутренне командой /fmm mount).

Полезные методы среды выполнения

  • ModeledEntity#setDisplayName(String)
  • ModeledEntity#setDisplayNameVisible(boolean)
  • ModeledEntity#setLeftClickCallback(...)
  • ModeledEntity#setRightClickCallback(...)
  • ModeledEntity#setHitboxContactCallback(...)
  • ModeledEntity#setModeledEntityHitByProjectileCallback(...)
  • ModeledEntity#playAnimation(String, boolean, boolean)
  • ModeledEntity#stopCurrentAnimations()
  • ModeledEntity#hasAnimation(String)
  • DynamicEntity#setSyncMovement(boolean)
  • Bone#getBoneLocation()

Поверхность событий

Общие события взаимодействия:

  • ModeledEntityLeftClickEvent
  • ModeledEntityRightClickEvent
  • ModeledEntityHitboxContactEvent
  • ModeledEntityHitByProjectileEvent

Также существуют типизированные варианты для StaticEntity, DynamicEntity и PropEntity.

ModeledEntityHitByProjectileEvent и OBB-обнаружение снарядов

FMM использует OBB (ориентированный ограничивающий параллелепипед) для обнаружения попадания снарядов в моделированные сущности. Когда снаряд пересекает OBB-хитбокс моделированной сущности, FMM генерирует ModeledEntityHitByProjectileEvent. Это стандартное отменяемое событие Bukkit.

Ключевые детали:

  • Урон от стрел рассчитывается с поддержкой бонуса от чар POWER
  • Чары PIERCING учитываются — стрелы могут проходить сквозь к дополнительным целям
  • Отмена события предотвращает урон и полностью блокирует попадание
@EventHandler
public void onProjectileHitModel(ModeledEntityHitByProjectileEvent event) {
ModeledEntity target = event.getModeledEntity();
Projectile projectile = event.getProjectile();
// Отмена для предотвращения урона
event.setCancelled(true);
}

Утилиты предметов и моделей

ModelItemFactory

Фабричный класс для программного создания ItemStack, связанных с моделями.

// Создание предмета для размещения пропса (использует PDC-ключ "model_id")
ItemStack placementItem = ModelItemFactory.createModelItem("lamp_post", Material.STICK);

// Создание пользовательского предмета из конфига (использует PDC-ключ "fmm_item_id")
PropScriptConfigFields config = ItemScriptManager.getItemDefinitions().get("magic_sword");
ItemStack customItem = ModelItemFactory.createCustomItem("magic_sword", config);
  • createModelItem(String modelId, Material material) — создаёт предмет для размещения пропсов. На 1.21.4+ автоматически применяет рендеринг отображаемой модели, если существует display JSON.
  • createCustomItem(String itemId, PropScriptConfigFields config) — создаёт пользовательский предмет с именем, описанием, чарами и отображаемой моделью из унифицированного конфига.
  • formatModelName(String modelId) — утилита, преобразующая ID модели вида 01_em_flame_sword в Flame Sword.

DisplayModelRegistry

Простой реестр, отслеживающий, какие модели имеют доступный display JSON.

// Проверка, есть ли у модели зарегистрированный display model JSON
boolean has3D = DisplayModelRegistry.hasDisplayModel("magic_sword");
  • register(String modelId) — регистрирует ID модели (вызывается внутренне при перезагрузке)
  • hasDisplayModel(String modelId) — возвращает true, если для этой модели существует .json отображаемая модель
  • shutdown() — очищает все регистрации

ItemScriptManager

Управляет жизненным циклом Lua-скриптов для каждого игрока для пользовательских предметов (моделей с установленным material: в YML-конфиге).

// Получение всех зарегистрированных определений пользовательских предметов
Map<String, PropScriptConfigFields> items = ItemScriptManager.getItemDefinitions();

// Получение активного экземпляра Lua-скрипта для игрока + предмета
ScriptInstance instance = ItemScriptManager.getActiveScript(playerUUID, "magic_sword");

// Получение всех активных скриптов для игрока
Map<String, ScriptInstance> scripts = ItemScriptManager.getActiveScripts(playerUUID);
  • scanForCustomItems(File modelsFolder) — сканирует YML-конфиги моделей для поиска пользовательских предметов
  • updateEquippedScripts(Player player) — сравнивает экипированные предметы с запущенными скриптами, вызывая хуки equip/unequip
  • removePlayer(Player player) — завершает все скрипты для игрока (вызывайте при выходе)
  • getItemDefinitions() — возвращает карту ID предмета к PropScriptConfigFields

ScriptedItemAPI

Публичный API для внешних плагинов для интеграции со скриптовой системой предметов FMM. Позволяет другим плагинам ставить свои собственные ItemStack данные скриптовых предметов FMM (PDC-тег + модель предмета), чтобы Lua-скрипт хуки FMM срабатывали для этих предметов, без перезаписи имени, описания или чар предмета.

// Проверка существования определения скриптового предмета
boolean exists = ScriptedItemAPI.isValidItemId("flame_blade");

// Применение данных скриптового предмета FMM к существующему ItemStack
// Устанавливает:
// - PDC-тег fmm_item_id (чтобы система скриптов FMM распознавала предмет)
// - Модель предмета (1.21.4+) из реестра отображаемых моделей FMM
// НЕ изменяет имя, описание, чары или другие свойства предмета.
boolean success = ScriptedItemAPI.applyScriptedItemData(itemStack, "flame_blade");

// Получение конфига скриптового предмета
PropScriptConfigFields config = ScriptedItemAPI.getItemConfig("flame_blade");
  • isValidItemId(String itemId) — возвращает true, если ID предмета зарегистрирован в определениях предметов FMM
  • applyScriptedItemData(ItemStack itemStack, String itemId) — ставит PDC-тег и модель предмета на существующий ItemStack. Возвращает true при успехе, false если ID предмета недействителен или ItemStack не имеет мета. Примечание по лукам/арбалетам: если у данного itemId нет отображаемой модели, но у itemId + "_idle" есть (т.е. предмет имеет модели состояний лука/арбалета), метод автоматически использует модель _idle как отображаемую модель
  • getItemConfig(String itemId) — возвращает PropScriptConfigFields для данного ID предмета или null, если не найден
Интеграция с EliteMobs

EliteMobs использует этот API внутренне через поле конфигурации scriptedItem. Когда пользовательский предмет EliteMobs устанавливает scriptedItem: flame_blade, EliteMobs создаёт предмет обычным образом (имя, описание, чары, уровень), а затем вызывает ScriptedItemAPI.applyScriptedItemData() для добавления модели и скриптового поведения FMM.

PropScriptConfigFields

Унифицированный класс конфигурации для YML-файлов конфигурации моделей. Используется как скриптами пропсов, так и пользовательскими предметами.

# Пример: torch_01.yml
isEnabled: true
scripts:
- torch_glow.lua
material: STICK # Если задано, модель становится пользовательским предметом
name: "&eMagic Torch" # Пользовательское отображаемое имя (необязательно)
lore: # Пользовательские строки описания (необязательно)
- "&7Glows in the dark"
enchantments: # Чары (необязательно, формат: NAME,LEVEL)
- "FIRE_ASPECT,1"

Ключевые методы: isCustomItem(), getParsedMaterial(), getParsedEnchantments(), getScripts().

Lua-скриптинг

FreeMinecraftModels поддерживает Lua-скрипты как для пропсов, так и для пользовательских предметов через скриптовый движок MagmaCore 2.0. Файлы скриптов размещаются в plugins/FreeMinecraftModels/scripts/ и привязываются к моделям через сопутствующий YML-конфиг рядом с файлом модели.

Хуки скриптов пропсов

ХукТриггер
on_spawnПропс появляется в мире
on_game_tickКаждый тик, пока пропс активен
on_zone_enterИгрок входит в зону пропса
on_zone_leaveИгрок покидает зону пропса
on_destroyПропс удаляется
on_left_clickИгрок кликает левой кнопкой по пропсу
on_right_clickИгрок кликает правой кнопкой по пропсу
on_projectile_hitСнаряд попадает в пропс

Хуки скриптов предметов

Пользовательские предметы (модели с установленным material:) поддерживают 22 Lua-хука:

ХукТриггер
on_equipПредмет попадает в отслеживаемый слот экипировки
on_unequipПредмет покидает отслеживаемый слот экипировки
on_game_tickКаждый тик, пока предмет экипирован
on_attack_entityИгрок атакует сущность, держа предмет
on_kill_entityИгрок убивает сущность, держа предмет
on_take_damageИгрок получает урон при экипированном предмете
on_shield_blockИгрок блокирует щитом
on_shoot_bowИгрок стреляет из лука
on_projectile_hitСнаряд, выпущенный игроком, попадает в цель
on_projectile_launchИгрок запускает снаряд
on_right_clickИгрок кликает правой кнопкой с предметом
on_left_clickИгрок кликает левой кнопкой с предметом
on_shift_right_clickИгрок кликает Shift+ПКМ с предметом
on_shift_left_clickИгрок кликает Shift+ЛКМ с предметом
on_interact_entityИгрок кликает правой кнопкой по сущности с предметом
on_swap_handsИгрок меняет предмет между руками
on_dropИгрок выбрасывает предмет
on_break_blockИгрок ломает блок, держа предмет
on_consumeИгрок потребляет предмет
on_item_damageПредмет получает урон прочности
on_fishИгрок использует удочку
on_deathИгрок умирает при экипированном предмете

Скрипты предметов получают context.item (с ID предмета и информацией об игроке) вместо context.prop.

Таблица context скриптов пропсов

Скрипты пропсов получают таблицу context. Вот краткое описание ключевых API — подробности см. в Lua Prop API.

context.prop:

  • model_id — имя модели-чертежа
  • current_location — текущее местоположение пропса
  • play_animation(name, blend, loop) — воспроизводит указанную анимацию (blend и loop по умолчанию true)
  • stop_animation() — останавливает все текущие анимации
  • hurt_visual() — воспроизводит визуальный эффект повреждения (красная вспышка) на пропсе
  • pickup() — удаляет пропс и выбрасывает его предмет размещения
  • mount(player) — сажает игрока на пропс
  • dismount(player) — снимает игрока с пропса
  • get_passengers() — возвращает список игроков, которые сейчас сидят на пропсе
  • spawn_elitemobs_boss(filename, x, y, z) — спавнит босса EliteMobs относительно пропса

context.event:

  • Доступен в on_left_click, on_right_click и on_projectile_hit
  • cancel(), uncancel(), is_cancelled
  • player — игрок, вызвавший событие

context.world:

  • spawn_entity(entity_type, location) — спавнит ванильную сущность
  • set_block_at(location, material) — устанавливает блок в мире
  • А также частицы, звуки, запросы блоков, молнии и поиск ближайших сущностей

Объекты игрока (из context.event.player):

  • get_held_item() — возвращает предмет, который держит игрок
  • consume_held_item() — убирает один предмет из руки
  • has_item(material) — проверяет, есть ли у игрока предмет
  • send_message(text) — отправляет сообщение в чат игроку
  • game_mode — текущий режим игры игрока

Пример скрипта пропса

function on_spawn(context)
context.prop.play_animation("idle", true, true)
end

function on_right_click(context)
context.prop.play_animation("activate", false, false)
end

Пример скрипта предмета

function on_equip(context)
context.event.player.send_message("&6You equipped the Flame Blade!")
end

function on_attack_entity(context)
-- Огненный эффект при попадании
context.event.player.send_message("&cBurn!")
end

function on_unequip(context)
context.event.player.send_message("&7Flame Blade sheathed.")
end

Примечания

  • FreeMinecraftModels — это зависимость в виде установленного плагина, а не встраиваемая библиотека.
  • Если вашему плагину нужны свежеимпортированные модели, вызывайте ModeledEntityManager.reload() вместо попытки самостоятельно пересобрать состояние FreeMinecraftModels.
  • Все плагины в экосистеме Nightbreak теперь зависят от MagmaCore 2.0.0-SNAPSHOT, который включает общий Lua-скриптовый движок, используемый скриптами пропсов FreeMinecraftModels и Lua-способностями EliteMobs.