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

Lua-скриптинг: Начало работы

Эта страница научит вас написать первый Lua-скрипт для пропса FreeMinecraftModels — от пустого файла до работающего интерактивного пропса. К концу вы поймёте хуки, context, API пропсов и общую структуру каждого файла скрипта пропса.

Когда освоите основы, переходите к сопутствующим страницам:

Экспериментальная функция

Lua-скрипты пропсов в настоящее время являются экспериментальными. Имена хуков, вспомогательные методы и поведение ещё могут измениться по мере развития FreeMinecraftModels, поэтому тщательно тестируйте перед использованием на продакшн-сервере.

Связь с Lua в EliteMobs

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 одинаковы в обоих плагинах. Эта страница охватывает только то, что специфично для пропсов FMM.


Что такое скрипты пропсов

Скрипты пропсов — это отдельные файлы .lua, которые находятся в папке plugins/FreeMinecraftModels/scripts/. Они указываются в YAML-конфиге, расположенном рядом с файлом модели, и запускаются при каждом спавне пропса в мире.

Для чего хороши скрипты пропсов

Скрипты пропсов отлично подходят, когда вам нужны:

  • Интерактивные пропсы, реагирующие на клики игроков (двери, рычаги, кнопки)
  • Неуязвимые декоративные пропсы, которые не могут быть сломаны игроками
  • Триггеры приближения, определяющие, когда игроки входят или покидают область
  • Анимированные пропсы, воспроизводящие анимации при взаимодействии или по таймеру
  • Звуковые пропсы, воспроизводящие звуки при клике или приближении
  • Любое поведение пропса, требующее логики помимо статичного украшения

Если ваш пропс чисто декоративный и не требует взаимодействия, скрипт вам не нужен.


Для кого эта страница

Эта страница написана для трёх категорий читателей:

  • Тех, кто уже знает Lua-скриптинг EliteMobs и хочет изучить хуки и API, специфичные для FMM
  • Тех, кто новичок в Lua-скриптинге и нуждается в полном, точном справочнике имён для пропсов
  • Тех, кто использует ИИ для создания скриптов пропсов и нуждается в достаточных деталях, чтобы понять, когда ИИ придумал что-то несуществующее

Вам не нужно становиться полноценным Lua-разработчиком, чтобы писать полезные скрипты пропсов. Для большинства практических скриптов вам действительно нужно только:

  • Как разместить валидный хук в возвращаемой таблице
  • Как читать значения из context
  • Как прервать выполнение с помощью if ... then return end
  • Как точно вызвать несколько вспомогательных методов

Краткий курс Lua

Если вы совершенно новичок в Lua, вот минимальный синтаксис, который вам нужен.

Переменные

Используйте local для хранения значения:

local animation_name = "open"
local sound_volume = 1.0

Функции

Функции — это многоразовые блоки логики:

local function log_click(context)
context.log:info("Prop was clicked!")
end

Проверки if

Используйте if, когда что-то должно происходить только иногда:

if context.event == nil then
return
end

nil

nil означает «нет значения». Вы будете часто проверять на nil:

if context.event ~= nil then
context.event.cancel()
end

Таблицы

Lua использует таблицы для объектов с именованными ключами и для возвращаемого определения скрипта:

return {
api_version = 1,

on_spawn = function(context)
end
}

Комментарии

Используйте -- для заметок:

-- Отменяем событие урона, чтобы пропс нельзя было сломать
context.event.cancel()
подсказка

Для более подробного введения в Lua см. страницу Начало работы с EliteMobs. Основы синтаксиса идентичны.


Расположение файлов

Файлы скриптов

Размещайте файлы .lua в центральной папке скриптов:

plugins/
FreeMinecraftModels/
scripts/
invulnerable.lua
interactive_door.lua
proximity_sound.lua

FMM обнаруживает все файлы .lua в plugins/FreeMinecraftModels/scripts/ при запуске.

Файлы моделей и конфигурации

Каждый файл модели может иметь соседний файл конфигурации .yml в той же директории:

plugins/
FreeMinecraftModels/
models/
torch_01.fmmodel
torch_01.yml <-- конфиг скрипта для torch_01
scripts/
invulnerable.lua <-- указан в torch_01.yml

Файл .yml — это то, что связывает модель с её скриптами.


Формат файла конфигурации

YAML-файл конфигурации, расположенный рядом с файлом модели, имеет два поля:

isEnabled: true
scripts:
- invulnerable.lua
ПолеТипПо умолчаниюПримечания
isEnabledbooleantrueАктивны ли скрипты для этого пропса
scriptsсписок строк[]Имена файлов .lua скриптов в папке scripts/

Вы можете привязать несколько скриптов к одному пропсу. Каждый скрипт является независимым экземпляром.

Ленивая генерация конфигурации

Когда пропс спавнится и не существует соседнего файла .yml, FMM автоматически создаёт файл конфигурации по умолчанию с isEnabled: true и пустым списком scripts:. Это происходит асинхронно, поэтому при первом спавне у пропса не будет скриптов — только после создания конфига и добавления имён файлов скриптов.

Это означает:

  1. Поместите файл модели в models/
  2. Заспавните пропс один раз (FMM создаст .yml автоматически)
  3. Отредактируйте сгенерированный .yml, чтобы добавить имена файлов скриптов
  4. Переспавните пропс или перезагрузите (скрипты теперь активны)

Справочник хуков

Каждый файл Lua-скрипта пропса возвращает таблицу. Каждый ключ в этой таблице (кроме api_version и priority) должен быть одним из хуков, перечисленных ниже. Среда выполнения вызывает соответствующую функцию всякий раз, когда происходит соответствующее игровое событие.

ХукСрабатывает когдаПримечания
on_spawnПропс появляется в миреВыполняется один раз при привязке скрипта
on_game_tickКаждый серверный тик (50 мс)Активен только если скрипт определяет этот хук
on_destroyПропс удаляется из мираХук очистки
on_left_clickИгрок кликает левой кнопкой (бьёт) по пропсуcontext.event — событие урона
on_right_clickИгрок кликает правой кнопкой по пропсуcontext.event — событие взаимодействия
on_projectile_hitСнаряд попадает в пропсcontext.event — событие попадания снаряда
on_zone_enterИгрок входит в наблюдаемую зонуТребует настроенного наблюдения за зоной
on_zone_leaveИгрок покидает наблюдаемую зонуТребует настроенного наблюдения за зоной

Минимальный контракт файла

Каждый Lua-скрипт пропса должен возвращать (return) таблицу.

Обязательные и необязательные поля верхнего уровня

ПолеОбязательноТипПримечания
api_versionДаNumberВ настоящее время должно быть 1
priorityНетNumberПриоритет выполнения. Меньшие значения выполняются первыми. По умолчанию 0
поддерживаемые ключи хуковНетFunctionДолжны использовать одно из точных имён хуков из справочника

Правила валидации

  • Файл должен возвращать таблицу.
  • api_version обязателен и в настоящее время должен быть 1.
  • priority должен быть числом, если указан.
  • Каждый дополнительный ключ верхнего уровня должен быть поддерживаемым именем хука.
  • Каждый ключ хука должен указывать на функцию.
  • Неизвестные ключи верхнего уровня отклоняются.

Вспомогательные функции и локальные константы должны располагаться над финальным return, а не внутри возвращаемой таблицы.


Ваш первый рабочий скрипт пропса, пошагово

Перед шагом 1: Настройка конфигурации

  1. Поместите файл модели (например, my_prop.fmmodel) в plugins/FreeMinecraftModels/models/
  2. Заспавните пропс один раз для генерации конфига .yml
  3. Создайте файл скрипта в plugins/FreeMinecraftModels/scripts/first_test.lua
  4. Отредактируйте plugins/FreeMinecraftModels/models/my_prop.yml:
isEnabled: true
scripts:
- first_test.lua
  1. Переспавните пропс или перезагрузите сервер

Шаг 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 передаёт вам каждый раз, когда что-то происходит — он содержит всё необходимое для взаимодействия с пропсом, миром, зонами и многим другим.

on_right_click = function(context)
-- context.prop = пропс, по которому кликнули
-- context.event = событие клика (можно отменить)
-- context.world = инструменты для частиц, звуков, запросов блоков
-- context.state = ваше собственное постоянное хранилище
-- context.log = логирование в консоль
-- context.scheduler = отложенные и повторяющиеся задачи
-- context.zones = создание и наблюдение пространственных зон
end

Вы не создаёте context сами — FMM создаёт его и передаёт в ваш хук.

к сведению

context создаётся заново для каждого вызова хука, за исключением context.state, который сохраняется на протяжении всего времени жизни пропса. Это означает, что вы можете хранить данные в context.state и считывать их позже в другом хуке.


Ключевые API context

Вот краткое описание доступного. Подробности см. в Prop API.

  • context.prop — Сущность пропса. Предоставляет model_id, current_location, play_animation() и stop_animation().

  • context.event — Событие Bukkit, вызвавшее этот хук. Доступен в on_left_click, on_right_click и on_projectile_hit. Предоставляет cancel(), uncancel() и is_cancelled. Равен nil в хуках без события (например, on_spawn и on_game_tick).

  • context.state — Обычная Lua-таблица, которая сохраняется на протяжении жизни пропса. Используйте для хранения флагов, состояний переключения, идентификаторов задач и всего, что нужно запоминать между хуками.

  • context.log — Логирование в консоль с log:info(msg), log:warn(msg) и log:error(msg).

  • context.scheduler — Отложенные и повторяющиеся задачи с scheduler:run_later(ticks, callback) и scheduler:run_repeating(delay, interval, callback). Обратные вызовы получают новый context. Отмена задач через scheduler:cancel(taskId).

  • context.world — Взаимодействие с миром: частицы, звуки, запросы блоков, молнии, ближайшие сущности. Полный список методов см. в Prop API.

  • context.zones — Создание и наблюдение пространственных зон (сферы, цилиндры, кубоиды). Полный список методов см. в Prop API.


Синтаксис методов: : и .

В Lua object:method(arg) — это сокращение для object.method(object, arg). API FMM принимает обе формы:

context.log:info("hello")
context.log.info("hello") -- то же самое

Вся документация последовательно использует :.


Готовые шаблоны для копирования

Минимальный валидный скрипт пропса

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
}

Расширенная структура файла

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
}

Первый реальный рабочий процесс

При создании совершенно нового скрипта пропса используйте этот порядок:

  1. Создайте файл .lua и заставьте on_spawn работать.
  2. Добавьте имя файла скрипта в конфиг .yml пропса.
  3. Переключитесь на нужный хук (например, on_right_click).
  4. Сначала добавьте сообщение в лог, до анимаций и эффектов.
  5. Добавьте один реальный эффект (анимацию, звук, частицы).
  6. Только после этого добавляйте вспомогательные функции, состояние, логику планировщика или зоны.

Такой порядок значительно упрощает отладку, потому что меняется только одна вещь за раз.


Готовые скрипты

FMM поставляется с двумя готовыми Lua-скриптами:

  • invulnerable.lua — Отменяет события урона при левом клике, делая пропс неразрушимым. Это простейший полезный скрипт пропса.
  • pickupable.lua — Позволяет игрокам подбирать пропс, ударив его три раза. Каждый удар воспроизводит анимацию повреждения на пропсе, а при третьем ударе пропс удаляется и выбрасывает свой предмет размещения для сбора игроком.

Больше примеров можно найти на странице Примеры и паттерны.


Песочница Lua

Скрипты пропсов работают в той же песочнице LuaJ, что и EliteMobs. Ограничения песочницы идентичны. Полный список удалённых глобальных переменных и доступных функций стандартной библиотеки см. на странице Хуки и жизненный цикл EliteMobs.

Вкратце:

  • Удалены: debug, dofile, io, load, loadfile, luajava, module, os, package, require
  • Доступны: Все функции math.*, string.*, table.*, pairs, ipairs, type, tostring, tonumber, pcall, print и другие
подсказка

print выводит в консоль сервера, но предпочтительнее использовать context.log:info(msg) для вывода. Сообщения логов имеют префикс с именем файла скрипта, что облегчает определение того, какой скрипт произвёл сообщение.


Следующие шаги

Если вы также пишете Lua-способности для EliteMobs, общие API (context.world, context.zones, context.scheduler, context.state, context.log) работают идентично. См. документацию Lua для EliteMobs для API, специфичных для боссов.