BLOXAR Lua API
Скрипты блоков в BLOXAR пишутся на Lua и выполняются в изолированной
виртуальной машине (fengari) — у каждого скрипта своё собственное состояние,
скрипты не видят переменные друг друга напрямую. Общаться между собой блоки
могут только через явные функции движка, описанные в этом документе, или
через события (emit/on).
🔑 Главный принцип
Скрипт не имеет прямого доступа к 3D-объектам движка.
Вместо parent.position.x = 5 используются функции вида
setBlockPosition(id, x, y, z), где id — уникальный
UUID блока.
🚀 Первый скрипт
- Откройте проект в Studio Mode.
- В панели Explorer выберите блок, нажмите
➕и добавьте📜 Script. - Кликните по скрипту — откроется редактор кода.
- Напишите Lua-код и нажмите
Save & Close. - Нажмите Publish, чтобы опубликовать мир на сервер.
Важно: скрипты
сохраняются только через Publish (реальная публикация мира), а не
через локальное сохранение .blxr-файла. После публикации
перезайдите в место, чтобы скрипт применился.
Минимальный пример
function onTick(dt)
if isKeyDown('e') then
say('Привет из скрипта!')
end
end
onTick(dt) — единственная функция, которую движок вызывает
автоматически, каждый кадр, с dt — временем в секундах с прошлого кадра.
Весь остальной код внутри скрипта пишется вокруг неё.
🧬 Переменные блока
Эти функции доступны только внутри скрипта, привязанного к блоку — они возвращают данные именно этого блока, не требуя UUID.
Текущие координаты блока, на котором висит скрипт.
Имя блока, заданное в редакторе.
Уникальный ID этого блока — используй его
в функциях вроде setBlockPosition(id, ...), чтобы двигать сам себя.
⚡ События
Вызывается один раз, когда игрок заходит в радиус ~1.5 от блока. who — ник игрока.
Вызывается один раз, когда игрок вплотную касается блока (радиус ~1.0).
Отправляет событие всем блокам, подписанным на eventName через on().
Подписка/отписка. При срабатывании вызывается глобальная функция скрипта onEvent_<eventName>(data).
-- Блок-кнопка
on('door_toggle')
function onEvent_door_toggle(data)
say('Дверь получила сигнал от ' .. data.from)
end
function onTick(dt)
if isKeyDown('e') then
emit('door_toggle', 'state', 'open')
end
end
❤️ Здоровье и позиция игрока
Текущее и максимальное здоровье игрока.
Жив ли игрок сейчас.
Наносит урон / восстанавливает здоровье. Не выходит за пределы 0..max.
Мгновенно убивает или возрождает игрока на точке спавна.
Проверка/включение временной неуязвимости после спавна.
Позиция игрока. Возвращает три числа: local x, y, z = getPlayerPosition().
Телепортирует игрока или сдвигает его на смещение.
Телепортирует игрока к указанному блоку (чуть выше его позиции).
Поворот игрока вокруг вертикальной оси, в радианах.
Ник и скин локального игрока.
Режим прохождения сквозь стены.
Расстояние от игрока до точки — основа для ловушек и триггеров.
⌨️ Ввод
Зажата ли клавиша сейчас. Строка в нижнем регистре: 'w', 'e', ' ' (пробел), 'shift'.
Хотя бы одна / все перечисленные клавиши зажаты одновременно.
Список всех зажатых клавиш через запятую — для отладки.
🎥 Камера
Текущая позиция камеры.
Дистанция камеры от игрока в режиме третьего лица (1..40).
Выполняется ли скрипт в режиме студии (там события касания не срабатывают).
🌍 Время суток и гравитация
Текущее время суток в радианах (0..2π — полный цикл).
Быстрая установка времени суток по названию.
Читает/меняет силу гравитации в мире, resetGravity() возвращает значение по умолчанию.
Служебные данные об окружении и мире.
Включает/выключает облака, либо запускает генерацию рельефа.
Сканирует размещённые блоки (вода/лава рядом, средняя высота) — полезно для AI-скриптов. Формат: "hasWater:0,hasLava:0,blockCount:12,avgY:3.5,dominantColor:...".
🧱 Блоки
Каждая функция принимает или возвращает uuid — уникальный ID блока
(получить его можно через getBlockUUID() у своего блока, findBlockByName()
у чужого, или как результат spawnBlock()).
Поиск
UUID первого блока с указанным именем.
Все совпавшие UUID через запятую. См. также таблицы данных ниже.
Общая информация по всем блокам в мире.
Чтение свойств
Позиция и масштаб блока.
Имя, цвет (hex) и физическая коллизия блока.
Изменение
Двигает блок в мире.
Перекрашивает, масштабирует, вращает блок (радианы).
Показывает/прячет блок.
Создание / удаление
Создаёт новый блок. shape: 'box', 'sphere', 'cone', 'cylinder'.
Удаляет блок (или все блоки с указанным именем).
📡 Рейкаст
Луч из камеры вперёд. Возвращает UUID первого попавшегося блока.
Луч из произвольной точки в произвольном направлении.
🎒 Инвентарь и очки
Текущий выбранный слот и переключение на другой.
Что лежит в слоте.
Кладёт предмет в слот или очищает его.
Переменные, общие для всех скриптов на время сессии — удобно для счёта очков или простой валюты.
setGlobalVar('score', (getGlobalVar('score') or 0) + 10)
say('Очки: ' .. getGlobalVar('score'))
👥 Мультиплеер
Только чтение — другие игроки управляются сервером напрямую.
Формат: "id:nick:x:y:z;id:nick:x:y:z". Для нормальной таблицы см. getOtherPlayersTable() ниже.
Количество игроков рядом и позиция конкретного по его id.
🔊 Звук и чат
Проигрывает звуковой эффект движка.
Фоновая музыка по ссылке.
Сообщение от лица скрипта в чат + пузырь речи над игроком.
Системное сообщение другим цветом — для предупреждений.
⏱ Таймеры
Выполняет Lua-функцию через указанное количество секунд.
wait(2, function()
say('Прошло 2 секунды')
end)
🖥️ UI и диалоги
Всплывающее уведомление вверху экрана (toast).
Модальное окно с кнопкой OK по центру экрана.
📊 Таблицы данных
Большинство функций API возвращают строку (проще маршалить в Lua), но для списков объектов есть версии, отдающие настоящую Lua-таблицу.
Массив таблиц {id, nickname, x, y, z}.
Массив UUID-строк вместо строки через запятую.
for i, p in ipairs(getOtherPlayersTable()) do
print(p.nickname, p.x, p.y, p.z)
end
🎬 Анимации
Включает/выключает встроенную анимацию блока (например, постоянное вращение).
🧮 Математика и утилиты
Расстояние между двумя точками в 3D.
Стандартные хелперы, которых не хватает в чистом Lua.
Время в секундах с момента загрузки страницы.
Вывод в консоль браузера — основной инструмент отладки скриптов.
💡 Готовые примеры (Copy & Paste)
Лёгкая машина (сесть по E)
local carId = nil
local seated = false
local eWasDown = false
local speed = 6.0
local turnSpeed = 2.2
local enterRadius = 2.5
local rotY = 0
function onTick(dt)
if carId == nil then carId = getBlockUUID() end
local cx, cy, cz = getBlockX(), getBlockY(), getBlockZ()
local eDown = isKeyDown('e')
local ePressed = eDown and not eWasDown
eWasDown = eDown
if not seated then
if ePressed and distanceToPlayer(cx, cy, cz) < enterRadius then
seated = true
say('Сел за руль')
end
return
end
if ePressed then
seated = false
say('Вышел из машины')
setPlayerPosition(cx + 2, cy + 1, cz)
return
end
if isKeyDown('a') then rotY = rotY + turnSpeed * dt end
if isKeyDown('d') then rotY = rotY - turnSpeed * dt end
local moveDir = 0
if isKeyDown('w') then moveDir = 1 end
if isKeyDown('s') then moveDir = -1 end
local nx, nz = cx, cz
if moveDir ~= 0 then
nx = cx + math.sin(rotY) * speed * dt * moveDir
nz = cz + math.cos(rotY) * speed * dt * moveDir
end
setBlockPosition(carId, nx, cy, nz)
setBlockRotation(carId, 0, rotY, 0)
setPlayerPosition(nx, cy + 1.0, nz)
setPlayerRotationY(rotY)
end
Ловушка-шипы (урон при касании)
local cooldown = 0
function onTick(dt)
cooldown = math.max(0, cooldown - dt)
local x, y, z = getBlockX(), getBlockY(), getBlockZ()
if distanceToPlayer(x, y, z) < 1.2 and cooldown <= 0 then
cooldown = 1.5
damagePlayer(20)
playSound('land', 1)
end
end
Интерактивная кнопка
local activated = false
function onTick(dt)
local x, y, z = getBlockX(), getBlockY(), getBlockZ()
if distanceToPlayer(x, y, z) < 3 and not activated then
if isKeyDown('e') then
activated = true
playSound('jump', 1)
setBlockColor(getBlockUUID(), 0x2EE6A6)
announce('Кнопка активирована!')
end
end
end
Портал с задержкой
local used = false
function onPlayerEnter(who)
if used then return end
used = true
say(who .. ' активировал портал')
wait(1, function()
setPlayerPosition(0, 5, 0)
used = false
end)
end