Lua Scripting & Event SDK

Программирование на Lua: хуки событий мира, регистрация команд, управление инвентарем, песочница и отладка через /lua.

Lua Scripting & Event SDK

Скриптовый слой Metron позволяет писать геймплейную логику на языке Lua 5.4.

Скрипты загружаются из папок datapacks/*/scripts/*.lua при запуске игры и при каждом нажатии F3+T.


Архитектура и ограничения песочницы

Скриптовый хост построен на базе библиотеки mlua 0.12. Чтобы обеспечить стабильные 20 TPS и безопасность игроков, в движке действуют три правила:

  1. Безопасная стандартная библиотека:
    • Разрешены: table, string, math, coroutine, print.
    • Запрещены: io, os, вызовы системных библиотек.
  2. Бюджет 500 микросекунд на тик (SCRIPT_BUDGET_US = 500):
    • Каждый вызов события или команды контролируется счётчиком инструкций.
    • Скрипт, превысивший время выполнения, мгновенно прерывается с ошибкой ScriptError::Timeout, защищая сервер от зависаний.
  3. Изоляция горячих путей:
    • Мешинг, свет и расчёт столкновений выполняются строго на нативном Rust без обращений к скриптам.

Глобальные события (Хуки мира)

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

1. on_block_break(x, y, z, block_id)

Срабатывает, когда игрок или игровая механика разрушает блок в мире.

LUA
function on_block_break(x, y, z, block_id)
    -- block_id: числовой ID сломанного блока (u16)
    print(string.format("[Script] Игрок сломал блок %d на (%d, %d, %d)", block_id, x, y, z))
end

2. on_block_place(x, y, z, block_id)

Срабатывает при установке блока игроком.

LUA
function on_block_place(x, y, z, block_id)
    print(string.format("[Script] Установлен блок %d на (%d, %d, %d)", block_id, x, y, z))
end

3. on_entity_interact(entity_id, action)

Срабатывает при взаимодействии с сущностями. На данный момент активно используется при подборе выпадающих предметов магнитом (action == "use").

LUA
function on_entity_interact(entity_id, action)
    if action == "use" then
        print(string.format("[Script] Поднят предмет от entity #%d", entity_id))
    end
end

Регистрация команд чата (commands)

Движок предоставляет глобальный объект commands для регистрации кастомных команд:

LUA
commands:register("heal", function(sender, args)
    -- sender: имя игрока, вызвавшего команду
    -- args: строка аргументов после имени команды
    return "Игрок " .. sender .. " успешно исцелен!"
end)
  • Команда регистрируется без символа /.
  • Если функция возвращает строку, она выводится игроку в чат в качестве ответа.
  • Если функция возвращает nil, ответ не отправляется.

Работа с инвентарем (metron.inventory)

Моды могут читать и изменять содержимое локального инвентаря игрока.

Нумерация слотов:

  • 0 .. 8: Хотбар (активная панель быстрого доступа)
  • 9 .. 35: Основной инвентарь (3 ряда по 9 ячеек)
  • 36 .. 45: Специальные слоты (крафт, броня)
  • Всего: 46 слотов (TOTAL_PLAYER_SLOTS)

Чтение слота: metron.inventory.get(slot)

Возвращает таблицу { item_id, count, display_name } или nil, если слот пуст.

LUA
local slot_0 = metron.inventory.get(0)
if slot_0 then
    print(string.format("В первом слоте: предмет #%d в количестве %d шт.", slot_0.item_id, slot_0.count))
else
    print("Первый слот пуст!")
end

Запись в слот: metron.inventory.set(slot, item_id, count [, display_name])

Записывает стак предметов в указанный слот:

LUA
-- Выдать 64 единицы камня (ID 1) в первый слот
metron.inventory.set(0, 1, 64)

-- Выдать кирку с кастомным NBT-именем во второй слот
metron.inventory.set(1, 200, 1, "Кирка первопроходца")

-- Очистить слот
metron.inventory.set(2, 0, 0)

Внутриигровой отладчик /lua

В одиночной игре вы можете выполнять любой Lua-код прямо из строки чата:

TEXT
/lua print("Текущий тик жив!")
/lua metron.inventory.set(0, 1, 64)
/lua local s = metron.inventory.get(0); print(s.count)

Результат выполнения и вывод print() сразу отобразятся в консоли разработчика.