Lua-скриптинг: Начало работы
Эта страница научит вас написать первый Lua-скрипт для пропса FreeMinecraftModels — от пустого файла до работающего интерактивного пропса. К концу вы поймёте хуки, context, API пропсов и общую структуру каждого файла скрипта пропса.
Когда освоите основы, переходите к сопутствующим страницам:
- Prop API — API
context.prop,context.event,context.worldи другие - Примеры и паттерны — полные рабочие скрипты для изучения и адаптации
- Устранение неполадок — типичные ошибки, советы по отладке и чеклист контроля качества
Lua-скрипты пропсов в настоящее время являются экспериментальными. Имена хуков, вспомогательные методы и поведение ещё могут измениться по мере развития FreeMinecraftModels, поэтому тщательно тестируйте перед использованием на продакшн-сервере.
FreeMinecraftModels использует тот же Lua-движок (Magmacore), что и EliteMobs. Если вы уже пишете Lua-способности для EliteMobs, основные концепции — хуки, context, api_version, планировщик, зоны и песочница — идентичны. Разница в следующем:
- Скрипты EliteMobs работают на боссах и имеют хуки вроде
on_boss_damaged_by_player,on_enter_combatи т.д. - Скрипты FMM работают на пропсах и имеют хуки вроде
on_right_click,on_left_click,on_projectile_hitи т.д.
API context.world, context.zones, context.scheduler, context.state и context.log, описанные здесь, — это версии FreeMinecraftModels/MagmaCore. Скрипты NPC EliteMobs используют те же общие таблицы MagmaCore плюс context.npc; силы боссов EliteMobs используют специфичные для боссов варианты нескольких таблиц. Эта страница охватывает то, что специфично для пропсов и предметов FMM.
Что такое скрипты пропсов
Скрипты пропсов — это отдельные файлы .lua, которые находятся в папке plugins/FreeMinecraftModels/scripts/. Они указываются в YAML-конфиге, расположенном рядом с файлом модели, и запускаются при каждом спавне пропса в мире.
Для чего хороши скрипты пропсов
Скрипты пропсов отлично подходят, когда вам нужны:
- Интерактивные пропсы, реагирующие на клики игроков (двери, рычаги, кнопки)
- Неуязвимые декоративные пропсы, которые не могут быть сломаны игроками
- Триггеры приближения, определяющие, когда игроки входят или покидают область
- Анимированные пропсы, воспроизводящие анимации при взаимодействии или по таймеру
- Звуковые пропсы, воспроизводящие звуки при клике или приближении
- Любое поведение пропса, требующее логики помимо статичного украшения
Если ваш пропс чисто декоративный и не требует взаимодействия, скрипт вам не нужен.
Что такое скрипты предметов
Скрипты предметов используют тот же формат файлов .lua и ту же папку scripts/, что и скрипты пропсов. Разница в том, что они привязываются к пользовательским предметам — моделям, у которых в YML-конфиге задано поле material:. Если скрипты пропсов запускаются при спавне сущности-пропса в мире, то скрипты предметов запускаются, когда игрок экипирует пользовательский предмет (основная рука, вторая рука или слот брони), и останавливаются, когда предмет снимается.
Как работают скрипты предметов
- Активация: экземпляр скрипта создаётся, когда игрок экипирует пользовательский предмет FMM. Скрипты работают на пару (игрок, тип предмета) — один
ScriptInstanceна каждую пару (player, itemId). - Деактивация: экземпляр скрипта уничтожается, когда предмет снимается (перемещён из активного слота, выброшен, либо игрок отключился).
- Идентификация предмета: пользовательские предметы определяются по PDC-ключу (PersistentDataContainer)
fmm_item_id, который отличается отmodel_idпропса. Чтобы получить корректно помеченный предмет, используйте/fmm giveitem <id>или админ-меню. - Контекст: хуки предметов получают
contextсcontext.player,context.item,context.world,context.state,context.scheduler,context.logи (где применимо)context.event.
Для чего хороши скрипты предметов
Скрипты предметов отлично подходят, когда вам нужны:
- Пользовательское оружие с особыми способностями (морозные мечи, волшебные палочки)
- Инструменты с уникальными действиями по правому клику или shift-клику
- Расходуемые предметы с пользовательскими эффектами
- Броня с пассивными эффектами при ношении
- Предметы, отслеживающие использование или имеющие ограниченную прочность
- Любое поведение удерживаемого предмета за пределами ванильной механики
Для кого эта страница
Эта страница написана для трёх категорий читателей:
- Тех, кто уже знает Lua-скриптинг EliteMobs и хочет изучить хуки и API, специфичные для FMM
- Тех, кто новичок в Lua-скриптинге и нуждается в полном, точном справочнике имён для пропсов
- Тех, кто использует ИИ для создания скриптов пропсов и нуждается в достаточных деталях, чтобы понять, когда ИИ придумал что-то несуществующее
Вам не нужно становиться полноценным Lua-разработчиком, чтобы писать полезные скрипты пропсов. Для большинства практических скриптов вам действительно нужно только:
- Как разместить валидный хук в возвращаемой таблице
- Как читать значения из
context - Как прервать выполнение с помощью
if ... then return end - Как точно вызвать несколько вспомогательных методов
Краткий курс Lua
Чтобы писать скрипты FMM, необязательно быть экспертом по Lua. В большинстве скриптов используется лишь горстка понятий: переменные (local x = 5), функции (function foo() end), проверки if (if x then ... end), таблицы ({key = value}) и nil (значение «ничего» в Lua). Синтаксис лёгкий — ни точек с запятой, ни фигурных скобок, только end для закрытия блоков.
Полное пошаговое введение с примерами см. в Движок Lua-скриптов MagmaCore — краткий курс Lua. Этот курс общий для всех плагинов Nightbreak, поэтому изучив его один раз, вы примените его везде.
Расположение файлов
Файлы скриптов
Размещайте файлы .lua в центральной папке скриптов:
plugins/
FreeMinecraftModels/
scripts/
invulnerable.lua
interactive_door.lua
proximity_sound.lua
FMM обнаруживает все файлы .lua в plugins/FreeMinecraftModels/scripts/ при запуске.
В списке scripts: модели указывайте расширение .lua для наглядности. FMM также принимает записи без расширения и добавляет .lua внутренне. Файл на диске всё равно обязан оканчиваться на .lua, а имена остаются чувствительными к регистру.
Файлы моделей и конфигурации
Каждый файл модели может иметь соседний файл конфигурации .yml в той же директории:
plugins/
FreeMinecraftModels/
models/
torch_01.fmmodel
torch_01.yml <-- конфиг скрипта для torch_01
scripts/
invulnerable.lua <-- указан в torch_01.yml
Файл .yml — это то, что связывает модель с её скриптами.
Формат файла конфигурации
YAML-файл конфигурации, расположенный рядом с файлом модели, имеет следующие поля:
isEnabled: true
voxelize: false
solidify: false
scripts:
- invulnerable.lua
Для пользовательских предметов (моделей, которые игроки могут держать или экипировать) вы также задаёте поле material и при желании name, lore и enchantments:
isEnabled: true
material: DIAMOND_SWORD
name: "&bFrost Blade"
lore:
- "&7A sword forged in eternal ice"
- "&7Slows enemies on hit"
enchantments:
- "SHARPNESS,5"
- "UNBREAKING,3"
scripts:
- frost_sword.lua
| Поле | Тип | По умолчанию | Примечания |
|---|---|---|---|
isEnabled | boolean | true | Активны ли скрипты для этого пропса/предмета |
scripts | список строк | [] | Имена файлов .lua скриптов в папке scripts/ |
voxelize | boolean | false | Привязывает размещение к поворотам на 90 градусов и к сетке блоков |
solidify | boolean | false | Размещает пакетные блоки-барьеры в габаритах пропса (требует voxelize) |
material | string | "" | Валидное имя Bukkit Material (например, DIAMOND_SWORD). Установка этого поля превращает модель в пользовательский предмет, который игроки могут держать или экипировать, что активирует систему скриптов предметов |
name | string | "" | Отображаемое имя пользовательского предмета. Поддерживает цветовые &-коды |
lore | список строк | [] | Строки lore, показываемые в подсказке предмета. Поддерживает цветовые &-коды |
enchantments | список строк | [] | Зачарования, применяемые к предмету. Формат: "ENCHANTMENT_NAME,LEVEL" (например, "SHARPNESS,5") |
Вы можете привязать несколько скриптов к одному пропсу. Каждый скрипт является независимым экземпляром.
- ID предмета выводится из имени YML-файла без расширения. Например,
frost_sword.ymlдаёт ID предметаfrost_sword. Именно этот ID используется командой/fmm giveitemи PDC-ключомfmm_item_id. - Предметы привязывают только один скрипт из списка
scripts:. FMM проверяет записи по порядку и использует первый скрипт, который смог разрешить, а последующие записи игнорирует. В отличие от предметов, пропсы запускают каждый разрешённый скрипт из списка как независимый экземпляр. - Расширение
.luaавтоматически дописывается к именам файлов скриптов, если вы его опустили, поэтомуfrost_swordиfrost_sword.luaв спискеscripts:эквивалентны.
Ленивая генерация конфигурации
Когда пропс спавнится и не существует соседнего файла .yml, FMM автоматически создаёт файл конфигурации по умолчанию с isEnabled: true и пустым списком scripts:. Это происходит асинхронно, поэтому при первом спавне у пропса не будет скриптов — только после создания конфига и добавления имён файлов скриптов.
Это означает:
- Поместите файл модели в
models/ - Заспавните пропс один раз (FMM создаст
.ymlавтоматически) - Отредактируйте сгенерированный
.yml, чтобы добавить имена файлов скриптов - Переспавните пропс или перезагрузите (скрипты теперь активны)
Справочник хуков
Каждый файл Lua-скрипта пропса возвращает таблицу. Каждый ключ в этой таблице (кроме api_version и priority) должен быть одним из хуков, перечисленных ниже. Среда выполнения вызывает соответствующую функцию всякий раз, когда происходит соответствующее игровое событие.
| Хук | Срабатывает когда | Примечания |
|---|---|---|
on_spawn | Пропс появляется в мире | Выполняется один раз при привязке скрипта |
on_game_tick | Каждый серверный тик (50 мс) | Активен только если скрипт определяет этот хук |
on_destroy | Пропс удаляется из мира | Хук очистки |
on_left_click | Игрок кликает левой кнопкой (бьёт) по пропсу | context.event — событие урона |
on_right_click | Игрок кликает правой кнопкой по пропсу | context.event — событие взаимодействия |
on_zone_enter | Игрок входит в наблюдаемую зону | Требует настроенного наблюдения за зоной |
on_zone_leave | Игрок покидает наблюдаемую зону | Требует настроенного наблюдения за зоной |
Текущий валидатор скриптов принимает on_projectile_hit для скриптов пропсов, но текущая среда выполнения пока не рассылает попадания снарядов скриптам пропсов. Используйте хук предмета on_projectile_hit для поведения снарядов, привязанного к скриптуемому предмету, либо Bukkit-API ModeledEntityHitByProjectileEvent для обработки снарядов по моделированным сущностям на стороне плагина.
Справочник хуков предметов
Скрипты предметов возвращают таблицу так же, как и скрипты пропсов, с api_version = 1 и функциями-хуками. Для скриптов предметов доступны следующие хуки. Все хуки предметов получают context с context.player, context.item и (где применимо) context.event.
В столбце примечаний указано имя соответствующего семейства событий Bukkit. Lua-обёртка не предоставляет необработанные поля, специфичные для Bukkit, такие как target, block, projectile или item; используйте context.player, context.event.player и вспомогательные запросы к сущностям/миру, когда вам нужен дополнительный контекст.
Боевые хуки
| Хук | Срабатывает когда | Примечания |
|---|---|---|
on_attack_entity | Игрок атакует сущность, держа предмет | context.event — событие урона |
on_kill_entity | Игрок убивает сущность, держа предмет | context.event — событие смерти |
on_take_damage | Игрок получает урон, когда предмет экипирован | context.event — событие урона |
on_shield_block | Игрок блокирует урон щитом | context.event — событие урона |
on_shoot_bow | Игрок стреляет из лука | context.event — событие выстрела из лука |
on_projectile_hit | Снаряд, выпущенный игроком, во что-то попадает | context.event — событие попадания снаряда |
on_projectile_launch | Игрок запускает снаряд | context.event — событие запуска снаряда |
Хуки взаимодействия
| Хук | Срабатывает когда | Примечания |
|---|---|---|
on_right_click | Игрок кликает правой кнопкой, держа предмет | context.event — событие взаимодействия |
on_left_click | Игрок кликает левой кнопкой, держа предмет | context.event — событие взаимодействия |
on_shift_right_click | Игрок кликает Shift+правая кнопка, держа предмет | context.event — событие взаимодействия |
on_shift_left_click | Игрок кликает Shift+левая кнопка, держа предмет | context.event — событие взаимодействия |
on_interact_entity | Игрок кликает правой кнопкой по сущности, держа предмет | context.event — событие взаимодействия с сущностью |
Хуки экипировки
| Хук | Срабатывает когда | Примечания |
|---|---|---|
on_equip | Предмет экипируется (перемещается в активный слот) | Хорошее место для инициализации состояния |
on_unequip | Предмет снимается (перемещается из активного слота) | Хорошее место для очистки |
on_swap_hands | Игрок перекладывает предмет между основной и второй рукой | context.event — событие перекладывания |
on_drop | Игрок выбрасывает предмет | context.event — событие выбрасывания |
Вспомогательные хуки
| Хук | Срабатывает когда | Примечания |
|---|---|---|
on_break_block | Игрок ломает блок, держа предмет | context.event — событие разрушения блока |
on_consume | Игрок потребляет предмет (еда/зелье) | context.event — событие потребления |
on_item_damage | Предмет теряет прочность | context.event — событие повреждения предмета |
on_fish | Игрок использует удочку | context.event — событие рыбалки |
on_death | Игрок умирает, когда предмет экипирован | context.event — событие смерти |
Хук жизненного цикла
| Хук | Срабатывает когда | Примечания |
|---|---|---|
on_game_tick | Каждый серверный тик, пока предмет экипирован | Используйте осторожно — выполняется 20 раз в секунду |
Минимальный контракт файла
Каждый Lua-скрипт пропса должен возвращать (return) таблицу.
Обязательные и необязательные поля верхнего уровня
| Поле | Обязательно | Тип | Примечания |
|---|---|---|---|
api_version | Да | Number | В настоящее время должно быть 1 |
priority | Нет | Number | Валидируется, если присутствует, но FMM в настоящее время не сортирует по нему скрипты. Пропсы выполняются в порядке списка scripts:; предметы привязывают только первый валидный скрипт |
| поддерживаемые ключи хуков | Нет | Function | Должны использовать одно из точных имён хуков из справочника |
Правила валидации
- Файл должен возвращать таблицу.
api_versionобязателен и в настоящее время должен быть1.priorityдолжен быть числом, если указан.- Каждый дополнительный ключ верхнего уровня должен быть поддерживаемым именем хука.
- Каждый ключ хука должен указывать на функцию.
- Неизвестные ключи верхнего уровня отклоняются.
priority полезен, чтобы скрипты оставались переносимыми между средами выполнения на базе MagmaCore, но текущий порядок выполнения в FreeMinecraftModels задаётся конфигом. Располагайте скрипты пропсов в списке scripts: модели в том порядке, в котором они должны выполняться.
Вспомогательные функции и локальные константы должны располагаться над финальным return, а не внутри возвращаемой таблицы.
Ваш первый рабочий скрипт пропса, пошагово
Перед шагом 1: Настройка конфигурации
- Поместите файл модели (например,
my_prop.fmmodel) вplugins/FreeMinecraftModels/models/ - Заспавните пропс один раз для генерации конфига
.yml - Создайте файл скрипта в
plugins/FreeMinecraftModels/scripts/first_test.lua - Отредактируйте
plugins/FreeMinecraftModels/models/my_prop.yml:
isEnabled: true
scripts:
- first_test.lua
- Переспавните пропс или перезагрузите сервер
Шаг 1: Загрузка файла
return {
api_version = 1,
on_spawn = function(context)
end
}
Если это загружается без ошибок в консоли, вы подтвердили:
- Файл является валидным Lua
- FMM нашёл его в папке
scripts/ - Конфиг правильно на него ссылается
- Структура возвращаемой таблицы корректна
Шаг 2: Пропс делает что-то видимое
return {
api_version = 1,
on_spawn = function(context)
context.log:info("Prop script loaded for: " .. (context.prop.model_id or "unknown"))
end
}
Проверьте консоль сервера. Если вы видите сообщение в логе, ваш хук работает.
Шаг 3: Реакция на клик игрока
return {
api_version = 1,
on_right_click = function(context)
context.log:info("Prop was right-clicked!")
end
}
Кликните правой кнопкой по пропсу в игре. Если консоль показывает сообщение, хук клика работает.
Шаг 4: Отмена урона для неуязвимости пропса
return {
api_version = 1,
on_left_click = function(context)
if context.event then
context.event.cancel()
end
end
}
Это паттерн, используемый готовым скриптом invulnerable.lua. Он отменяет событие урона, чтобы стойку для брони, лежащую в основе пропса, нельзя было уничтожить.
Шаг 5: Воспроизведение анимации по клику
return {
api_version = 1,
on_right_click = function(context)
context.prop:play_animation("open", true, false)
end
}
Это воспроизводит анимацию «open» на модели пропса, с плавным переходом и без зацикливания.
Что такое context?
Каждая функция хука получает один аргумент, называемый context. Думайте о нём как о наборе инструментов, который FMM передаёт вам каждый раз, когда что-то происходит — он содержит всё необходимое для взаимодействия с пропсом, миром, зонами и многим другим.
Вы не создаёте context сами — FMM создаёт его и передаёт в ваш хук. Полные подробности об общих API контекста (context.state, context.log, context.cooldowns, context.scheduler, context.world, context.zones) см. на странице Движок Lua-скриптов MagmaCore.
Ключевые API context
Вот краткое описание доступного. Подробности см. в Prop API.
-
context.prop— (только скрипты пропсов) Сущность пропса. Предоставляетmodel_id,current_location,play_animation()иstop_animation(). -
context.item— (только скрипты предметов) Пользовательский предмет. Предоставляетid,material(),get_amount(),set_amount(),consume(),get_uses(),set_uses(),get_name(),set_name(),get_lore(),set_lore(),get_durability(),get_durability_percentage(),use_durability()иuse_durability_percentage(). Полные подробности см. в API пропсов и предметов. -
context.player— Игрок для хуков, вызванных игроком. Скрипты предметов определяют его по владельцу предмета; хуки кликов по пропсам и общие хуки зон — по игроку, вызвавшему событие. Равенnilв хуках жизненного цикла пропса, в отложенных обратных вызовах пропса и в хуках, не связанных с игроком. -
context.event— Небольшая обёртка для события Bukkit или игрока-актора, вызвавшего этот хук. Доступен в хуках кликов, боя, взаимодействия и в общих хуках зон. Предоставляетevent.player,is_cancelled, а когда базовое событие Bukkit отменяемо —cancel()/uncancel(); он не предоставляет специфичные для Bukkit поля вродеtarget,block,projectileилиitem. Равенnilв хуках без события или игрока-актора (таких какon_spawn,on_game_tickиon_equip). -
context.state— Обычная Lua-таблица, которая сохраняется на протяжении жизни экземпляра скрипта. См. context.state. -
context.cooldowns— Помощники локальных и глобальных перезарядок. Используйтеcontext.cooldowns:check_local("key", ticks)для обычных перезарядок в рамках скрипта. См. context.cooldowns. -
context.log— Логирование в консоль. См. context.log. -
context.scheduler— Отложенные и повторяющиеся задачи. См. context.scheduler. -
context.world— Взаимодействие с миром: частицы, звуки, запросы блоков, молнии, ближайшие сущности. См. context.world. -
context.zones— Создание и наблюдение пространственных зон (сферы, цилиндры, кубоиды). См. context.zones.
Синтаксис методов: : и .
Объяснение синтаксиса методов : и . в Lua см. на странице Движок Lua-скриптов MagmaCore. API FMM принимает обе формы.
Готовые шаблоны для копирования
Минимальный валидный скрипт пропса
return {
api_version = 1,
on_spawn = function(context)
end
}
Шаблон неуязвимого пропса
return {
api_version = 1,
on_left_click = function(context)
if context.event then
context.event.cancel()
end
end
}
Шаблон интерактивного пропса
return {
api_version = 1,
on_spawn = function(context)
context.state.is_active = false
end,
on_right_click = function(context)
context.state.is_active = not context.state.is_active
if context.state.is_active then
context.prop:play_animation("activate", true, true)
else
context.prop:stop_animation()
end
end
}
Минимальный валидный скрипт предмета
return {
api_version = 1,
on_equip = function(context)
end
}
Шаблон предмета с действием по правому клику
return {
api_version = 1,
on_right_click = function(context)
if not context.cooldowns:check_local("activate", 40) then return end
-- Ваше действие здесь
context.player:send_message("&aItem activated!")
end
}
Расширенная структура файла
local ANIMATION_NAME = "idle"
local function do_something(context)
context.log:info("Doing something!")
end
return {
api_version = 1,
priority = 0,
on_spawn = function(context)
context.state.task_id = nil
end,
on_right_click = function(context)
do_something(context)
end,
on_destroy = function(context)
if context.state.task_id ~= nil then
context.scheduler:cancel(context.state.task_id)
end
end
}
Первый реальный рабочий процесс
При создании совершенно нового скрипта пропса используйте этот порядок:
- Создайте файл
.luaи заставьтеon_spawnработать. - Добавьте имя файла скрипта в конфиг
.ymlпропса. - Переключитесь на нужный хук (например,
on_right_click). - Сначала добавьте сообщение в лог, до анимаций и эффектов.
- Добавьте один реальный эффект (анимацию, звук, частицы).
- Только после этого добавляйте вспомогательные функции, состояние, логику планировщика или зоны.
Такой порядок значительно упрощает отладку, потому что меняется только одна вещь за раз.
Готовые скрипты
FMM поставляется с четырьмя готовыми Lua-скриптами:
invulnerable.lua— Отменяет события урона при левом клике, делая пропс неразрушимым. Это простейший полезный скрипт пропса.pickupable.lua— Позволяет игрокам подбирать пропс, ударив его три раза. Каждый удар воспроизводит анимацию повреждения на пропсе, а при третьем ударе пропс удаляется и выбрасывает свой предмет размещения для сбора игроком.storage_double.lua— Превращает пропс в двойной сундук (54 слота). Правый клик открывает постоянный GUI инвентаря. Воспроизводит анимации и звуки открытия/закрытия. Содержимое сохраняется в пропсе и переживает перезапуски сервера. При уничтожении всё содержимое выбрасывается.storage_single.lua— То же, что иstorage_double, но с 3 рядами (27 слотов) вместо 6.
Больше примеров можно найти на странице Примеры и паттерны.
Песочница Lua
Скрипты пропсов и предметов работают в той же изолированной среде LuaJ, что и EliteMobs. Ограничения песочницы идентичны. Полный список удалённых глобальных переменных и доступных функций стандартной библиотеки см. на странице Движок Lua-скриптов MagmaCore.
Следующие шаги
- API пропсов и предметов — полный справочник
context.prop,context.item,context.event,context.world,context.zonesиcontext.scheduler - Примеры и паттерны — полные рабочие скрипты для пропсов и предметов с разбором
- Устранение неполадок — типичные проблемы, советы по отладке и чеклист контроля качества
Если вы также пишете Lua-силы боссов EliteMobs, песочница, api_version, таблица состояния, понятия перезарядок и структура на основе хуков будут вам знакомы, но контекст босса использует специфичные для EliteMobs имена методов. Точные API боссов см. в документации Lua для EliteMobs.