Скриптовый движок Lua в MagmaCore
MagmaCore предоставляет общий скриптовый движок Lua, используемый несколькими плагинами Nightbreak. Движок отвечает за песочницу, планирование задач, управление зонами, взаимодействие с миром, таблицы сущностей и пользовательский интерфейс игрока — всё это с единым API во всех плагинах.
На данный момент этот движок используют следующие плагины:
- EliteMobs — Lua-силы для кастомных боссов (хуки вроде
on_boss_damaged_by_player,on_enter_combatи т.д.) - FreeMinecraftModels — Lua-скрипты для пропсов и кастомных предметов (хуки вроде
on_right_click,on_left_click,on_equipи т.д.)
Эта страница описывает общие возможности движка. Для специфичных для плагина хуков, API и рабочих процессов смотрите страницы плагинов, указанные выше.
Краткое введение в Lua
Если вы совсем не знакомы с Lua, вот минимум синтаксиса, необходимый для написания скриптов для любого плагина Nightbreak.
Переменные
Используйте local для хранения значения:
local cooldown_key = "fire_burst"
local damage_multiplier = 1.5
local означает, что переменная принадлежит только этому файлу или блоку.
Функции
Функции — это переиспользуемые блоки логики:
local function warn_player(player)
player:send_message("&cMove!")
end
Позже её можно вызвать:
warn_player(some_player)
Проверки if
Используйте if, когда что-то должно происходить только иногда:
if context.player == nil then
return
end
Это означает «если для этого хука нет игрока — остановись здесь».
nil
nil означает «нет значения». Это вариант «ничего здесь нет» в Lua.
Вы часто будете проверять nil так:
if context.event ~= nil then
-- что-то делаем с событием
end
~= означает «не равно».
Таблицы
Lua использует таблицы для нескольких задач:
- Списки
- Объекты с именованными ключами
- Итоговое возвращаемое определение скрипта
Пример таблицы с именованными ключами:
local particle = {
particle = "FLAME",
amount = 1,
speed = 0.05
}
Возврат определения скрипта
В конце каждого файла скрипта вы возвращаете одну таблицу:
return {
api_version = 1,
on_spawn = function(context)
end
}
Эта возвращённая таблица и есть файл скрипта.
Комментарии
Используйте --, чтобы оставить заметку для людей:
-- Этот кулдаун не даёт атаке срабатывать при каждом ударе
context.cooldowns:set_local(60, "fire_burst")
Lua-песочница
Все Lua-скрипты выполняются в песочнице среды LuaJ. Несколько глобальных переменных, которые могли бы получить доступ к файловой системе или Java-рантайму, удалены. Правила песочницы одинаковы во всех плагинах, использующих MagmaCore.
Удалённые глобальные переменные
Следующие стандартные глобальные переменные Lua установлены в nil и не могут быть использованы:
| Удалено | Почему |
|---|---|
debug | Раскрывает внутреннее состояние VM |
dofile | Доступ к файловой системе |
io | Доступ к файловой системе |
load | Загрузка произвольного кода |
loadfile | Доступ к файловой системе |
luajava | Прямой доступ к классам Java |
module | Модульная система (не требуется) |
os | Доступ к операционной системе |
package | Модульная система (не требуется) |
require | Модульная система / доступ к файловой системе |
Доступная стандартная библиотека
Всё остальное из стандартной библиотеки Lua работает обычным образом:
| Категория | Функции |
|---|---|
| Math | math.abs, math.ceil, math.floor, math.max, math.min, math.random, math.sin, math.cos, math.sqrt, math.pi и все остальные функции math.* |
| String | string.byte, string.char, string.find, string.format, string.gsub, string.len, string.lower, string.match, string.rep, string.sub, string.upper и все остальные функции string.* |
| Table | table.insert, table.remove, table.sort, table.concat и все остальные функции table.* |
| Итераторы | pairs, ipairs, next |
| Тип | type, tostring, tonumber, select, unpack |
| Обработка ошибок | pcall, xpcall, error, assert |
| Прочее | print, rawget, rawset, rawequal, rawlen, setmetatable, getmetatable |
os недоступнаБиблиотека os полностью удалена из песочницы. Если вам нужна информация о времени, используйте context.world:get_time() для времени мира или храните метки времени в context.state, применяя счётчики тиков через хук on_game_tick.
print пишет в консоль сервера, но предпочтительнее использовать context.log:info(msg) для вывода. Сообщения лога снабжаются префиксом — именем файла скрипта, благодаря чему легче отследить, какой скрипт создал сообщение.
Контракт файла
Каждый Lua-скрипт обязан return возвращать таблицу. Эта таблица намеренно строгая.
Обязательные и необязательные поля верхнего уровня
| Поле | Обязательно | Тип | Примечания |
|---|---|---|---|
api_version | Да | Number | Сейчас должно быть 1 |
priority | Нет | Number | Приоритет выполнения. Меньшие значения выполняются раньше. По умолчанию 0 |
| ключи поддерживаемых хуков | Нет | Function | Должны использовать одно из точных имён хуков, поддерживаемых плагином |
Правила валидации
- Файл обязан вернуть таблицу.
api_versionобязательно и сейчас должно быть1.priorityдолжен быть числом, если присутствует.- Каждый дополнительный ключ верхнего уровня должен быть именем поддерживаемого хука.
- Каждый ключ хука должен указывать на функцию.
- Неизвестные ключи верхнего уровня отклоняются.
Вспомогательные функции и локальные константы должны располагаться над финальным return, а не внутри возвращаемой таблицы, если только это не настоящие хуки.
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)
do_something(context)
end
}
Общие хуки движка
Следующие хуки доступны всем плагинам, использующим скриптовый движок MagmaCore. Отдельные плагины добавляют свои хуки поверх них.
| Хук | Когда срабатывает |
|---|---|
on_spawn | Вызывается один раз при создании экземпляра скрипта (сущность спавнится или пропс размещается) |
on_game_tick | Вызывается каждый серверный тик, пока сущность жива/активна |
on_zone_enter | Вызывается, когда игрок входит в отслеживаемую зону |
on_zone_leave | Вызывается, когда игрок покидает отслеживаемую зону |
Синтаксис методов: : против .
В Lua object:method(arg) — это сокращение для object.method(object, arg). API MagmaCore принимает обе формы, так что оба варианта работают:
context.log:info("hello")
context.log.info("hello") -- то же самое
Вся документация последовательно использует :.
Бюджет выполнения
Каждый вызов хука и каждый вызов колбэка засекается по времени. Если один вызов занимает больше 50 миллисекунд, скрипт отключается с предупреждением в консоли:
[Lua] my_script.lua took 73ms in 'on_game_tick' (limit: 50ms) -- script disabled to prevent lag.
Чтобы оставаться в рамках бюджета:
- Избегайте неограниченных циклов внутри хуков.
- Делайте обработчики
on_game_tickлёгкими — они выполняются каждый тик. - Используйте
context.scheduler:run_repeating(...), чтобы распределить работу по тикам. - Перенесите дорогую работу за кулдаун на основе состояния или разумный интервал.
Если Lua-скрипт выбрасывает ошибку выполнения в любом хуке или запланированном колбэке, экземпляр скрипта немедленно и навсегда отключается для этой сущности. Исправьте ошибку в файле скрипта — скрипт будет переинициализирован при следующем спавне сущности.
context.state
Обычная Lua-таблица, живущая всё время существования экземпляра скрипта. Используйте её для хранения флагов, счётчиков, ID задач, состояний переключателей и любых данных, которые нужно разделять между хуками.
on_spawn = function(context)
context.state.is_open = false
context.state.click_count = 0
context.state.task_id = nil
end,
on_right_click = function(context)
context.state.click_count = (context.state.click_count or 0) + 1
end
Только context.state сохраняется между вызовами хуков. Все остальные таблицы контекста (context.prop, context.world, context.event и т.д.) пересоздаются заново каждый раз. context.state не пересоздаётся — она существует с момента создания экземпляра скрипта и до его уничтожения.
context.log
Методы логирования в консоль. Сообщения снабжаются префиксом — именем файла скрипта в консоли сервера.
| Метод | Примечания |
|---|---|
log:info(message) | Информационное сообщение |
log:warn(message) | Предупреждающее сообщение |
log:error(message) | Сообщение уровня предупреждения (логируется на уровне WARN, так же как log:warn) |
context.log в EliteMobs регистрирует debug вместо error. Используйте log:debug(message) для отладочного вывода (появляется на уровне info с префиксом debug).
context.log:info("Script loaded!")
context.log:warn("Something unexpected happened")
context.log:error("Critical failure in zone setup")
context.cooldowns
Таблица cooldowns управляет временными кулдаунами для ваших скриптов. Есть две области:
- Локальные кулдауны привязаны к экземпляру скрипта и идентифицируются строковым ключом. Если ключ не указан, в качестве ключа по умолчанию используется имя файла скрипта.
- Глобальные кулдауны общие для всех скриптов на одной сущности-владельце (например, всех скриптов на одном пропсе или всех Lua-сил на одном боссе).
cooldowns:check_local(key?, duration)
Наиболее часто используемый метод. Проверяет, готов ли кулдаун, и если да — запускает его и возвращает true. Если не готов, возвращает false. Это атомарная операция check-and-set — гонок данных не возникает.
| Параметр | Тип | Примечания |
|---|---|---|
key | string (опционально) | Идентификатор кулдауна. По умолчанию — имя файла скрипта. |
duration | int | Длительность кулдауна в тиках (20 = 1 секунда) |
on_right_click = function(context)
-- Разрешать это действие только раз в 3 секунды
if not context.cooldowns:check_local("interact", 60) then
return
end
-- ... выполнить действие
end
cooldowns:local_ready(key?)
Возвращает true, если локальный кулдаун истёк (или никогда не устанавливался), false, если ещё активен.
cooldowns:local_remaining(key?)
Возвращает количество оставшихся тиков локального кулдауна, или 0, если он готов.
cooldowns:set_local(duration, key?)
Устанавливает локальный кулдаун без проверки, активен ли он уже. Используйте это для безусловного сброса кулдауна.
| Параметр | Тип | Примечания |
|---|---|---|
duration | int | Длительность в тиках. Передайте 0 или отрицательное значение для очистки. |
key | string (опционально) | Идентификатор кулдауна. По умолчанию — имя файла скрипта. |
cooldowns:global_ready()
Возвращает true, если глобальный кулдаун (общий для всех скриптов на одной сущности) истёк.
cooldowns:set_global(duration)
Устанавливает глобальный кулдаун.
| Параметр | Тип | Примечания |
|---|---|---|
duration | int | Длительность в тиках |
«Владелец» глобального кулдауна зависит от типа скрипта:
- Lua-силы EliteMobs — общий на
EliteEntity(один блок на босса).global_ready()/set_global()используют встроенную систему кулдаунов сил босса; локальные кулдауны также общие для всех сил на одном боссе. - Скрипты пропсов FMM — общий на
PropEntity(один блок на размещённый пропс). - Скрипты предметов FMM — общий на UUID игрока (один блок на игрока). Локальные кулдауны для предметов сохраняются между циклами надевания/снятия, ключуясь как
playerUUID → "itemId:scriptFile" → key, так что кулдаун переживёт смену предмета в хотбаре игрока и обратно.
context.scheduler
Планировщик позволяет вам запускать отложенные и повторяющиеся задачи. Все задачи принадлежат экземпляру скрипта и автоматически отменяются, когда экземпляр уничтожается (например, когда пропс удаляется или босс умирает).
scheduler:run_later(ticks, callback)
Запускает колбэк один раз после задержки. Возвращает числовой ID задачи.
| Параметр | Тип | Примечания |
|---|---|---|
ticks | int | Задержка в серверных тиках (20 тиков = 1 секунда) |
callback | function | Вызывается со свежим context, когда задержка истекает |
context.scheduler:run_later(40, function(delayed_context)
delayed_context.log:info("2 seconds have passed!")
end)
scheduler:run_repeating(delay, interval, callback)
Запускает колбэк повторно с фиксированным интервалом. Возвращает числовой ID задачи.
| Параметр | Тип | Примечания |
|---|---|---|
delay | int | Начальная задержка в тиках перед первым запуском |
interval | int | Тики между каждым последующим запуском |
callback | function | Вызывается со свежим context каждый интервал |
context.state.particle_task = context.scheduler:run_repeating(0, 20, function(tick_context)
tick_context.log:info("Another second passed!")
end)
scheduler:cancel(taskId)
Отменяет запланированную задачу по её ID.
| Параметр | Тип | Примечания |
|---|---|---|
taskId | int | ID задачи, возвращённый из run_later или run_repeating |
Если вы запустили повторяющуюся задачу, всегда отменяйте её в хуке очистки (on_destroy для пропсов, on_exit_combat / on_death для боссов, on_unequip для предметов). Невыполнение отмены оставит фоновую задачу запущенной до уничтожения экземпляра скрипта, что тратит производительность и может вызывать ошибки.
Запланированные колбэки получают свежий контекст в качестве своего параметра. Всегда используйте собственный аргумент контекста колбэка, а не внешний context из хука, создавшего колбэк. Внешний контекст может содержать устаревшие ссылки.
context.world
Таблица world предоставляет методы для запросов и взаимодействия с миром Minecraft. Она строится из текущего мира сущности.
EliteMobs расширяет context.world дополнительными методами для спавна боссов, подкреплений, падающих блоков, фейерверков, взрывных зелий и временных блоков. Полный расширенный API смотрите в EliteMobs World & Environment. Методы, описанные здесь, доступны во всех плагинах.
world.name
Строковое поле, содержащее имя мира.
world:get_block_at(x, y, z)
Возвращает имя материала блока в указанных координатах в виде строки в нижнем регистре (например, "stone", "air").
| Параметр | Тип | Примечания |
|---|---|---|
x | int | Координата блока X |
y | int | Координата блока Y |
z | int | Координата блока Z |
world:set_block_at(x, y, z, material)
Устанавливает блок в указанных координатах. Выполняется в главном потоке.
| Параметр | Тип | Примечания |
|---|---|---|
x | int | Координата блока X |
y | int | Координата блока Y |
z | int | Координата блока Z |
material | string | Имя Bukkit Material в нижнем регистре (например, "stone", "air", "oak_planks") |
Возвращает true, если блок был установлен успешно, иначе false.
world:spawn_particle(particle, x, y, z, count, dx, dy, dz, speed)
Создаёт частицы в локации.
| Параметр | Тип | По умолчанию | Примечания |
|---|---|---|---|
particle | string | обязательно | Имя перечисления Bukkit Particle в ВЕРХНЕМ_РЕГИСТРЕ (например, "FLAME", "DUST") |
x | number | обязательно | Координата X |
y | number | обязательно | Координата Y |
z | number | обязательно | Координата Z |
count | int | 1 | Количество частиц |
dx | number | 0 | Разброс/смещение по X |
dy | number | 0 | Разброс/смещение по Y |
dz | number | 0 | Разброс/смещение по Z |
speed | number | 0 | Скорость частиц |
Некоторые типы частиц требуют данных блока или предмета, которые не поддерживаются этим простым API. BLOCK_CRACK, FALLING_DUST, BLOCK_DUST и ITEM_CRACK потерпят неудачу или не дадут видимого эффекта. Используйте альтернативы без данных: CLOUD, SMOKE, CAMPFIRE_COSY_SMOKE, SNOWFLAKE, FLAME, DUST и т.д.
world:play_sound(sound, x, y, z, volume, pitch)
Воспроизводит звук в локации.
| Параметр | Тип | По умолчанию | Примечания |
|---|---|---|---|
sound | string | обязательно | Имя перечисления Bukkit Sound в ВЕРХНЕМ_РЕГИСТРЕ (например, "ENTITY_EXPERIENCE_ORB_PICKUP") |
x | number | обязательно | Координата X |
y | number | обязательно | Координата Y |
z | number | обязательно | Координата Z |
volume | number | 1.0 | Громкость |
pitch | number | 1.0 | Высота тона |
world:strike_lightning(x, y, z)
Бьёт молнией в локации (визуальная и наносящая урон).
| Параметр | Тип | Примечания |
|---|---|---|
x | number | Координата X |
y | number | Координата Y |
z | number | Координата Z |
world:get_time()
Возвращает текущее время мира в тиках.
world:set_time(ticks)
Устанавливает время мира.
| Параметр | Тип | Примечания |
|---|---|---|
ticks | int | Время мира (0 = рассвет, 6000 = полдень, 13000 = ночь, 18000 = полночь) |
world:get_nearby_entities(x, y, z, radius)
Возвращает массив таблиц-обёрток сущностей для всех сущностей в ограничивающем боксе с центром в указанных координатах.
| Параметр | Тип | Примечания |
|---|---|---|
x | number | Центр X |
y | number | Центр Y |
z | number | Центр Z |
radius | number | Радиус поиска (используется как полуразмер по всем трём осям) |
Это возвращает ВСЕ сущности в радиусе, включая не-живые сущности (armor stands, выпавшие предметы и т.д.). Всегда проверяйте через if entity.damage then, прежде чем вызывать методы живых сущностей.
world:get_nearby_players(x, y, z, radius)
Возвращает массив таблиц-обёрток игроков для всех игроков в ограничивающем боксе с центром в указанных координатах.
| Параметр | Тип | Примечания |
|---|---|---|
x | number | Центр X |
y | number | Центр Y |
z | number | Центр Z |
radius | number | Радиус поиска |
world:spawn_entity(entity_type, x, y, z)
Спавнит ванильную сущность Minecraft в указанной локации.
| Параметр | Тип | Примечания |
|---|---|---|
entity_type | string | Имя типа сущности Bukkit в нижнем регистре (например, "zombie", "skeleton", "pig") |
x | number | Координата X |
y | number | Координата Y |
z | number | Координата Z |
Возвращает таблицу сущности для заспавненной сущности (с методами живой сущности, если применимо), либо nil, если тип сущности недопустим.
world:get_highest_block_y(x, z)
Возвращает координату Y самого верхнего не-воздушного блока в указанной позиции X/Z.
| Параметр | Тип | Примечания |
|---|---|---|
x | int | Координата блока X |
z | int | Координата блока Z |
world:raycast(from_x, from_y, from_z, dir_x, dir_y, dir_z, [max_distance])
Бросает луч из точки в направлении и возвращает информацию о том, что он попал.
| Параметр | Тип | По умолчанию | Примечания |
|---|---|---|---|
from_x | number | обязательно | Origin X |
from_y | number | обязательно | Origin Y |
from_z | number | обязательно | Origin Z |
dir_x | number | обязательно | Компонент направления X |
dir_y | number | обязательно | Компонент направления Y |
dir_z | number | обязательно | Компонент направления Z |
max_distance | number | 50 | Максимальная дистанция луча |
Возвращает таблицу со следующими полями:
| Поле | Тип | Примечания |
|---|---|---|
hit_entity | entity table или nil | Первая сущность, в которую попал луч, или nil, если ни одной |
hit_location | location table или nil | Точка, где луч во что-то попал |
hit_block | table или nil | {x, y, z, material} блока, в который попал луч, или nil, если ни один блок не задет |
world:spawn_firework(x, y, z, colors, [type], [power])
Запускает фейерверочную ракету в указанной локации.
| Параметр | Тип | По умолчанию | Примечания |
|---|---|---|---|
x | number | обязательно | Координата X |
y | number | обязательно | Координата Y |
z | number | обязательно | Координата Z |
colors | table | обязательно | Массив строк цветов, например, {"RED", "BLUE", "WHITE"} |
type | string | "BALL" | Форма фейерверка: "BALL", "BALL_LARGE", "STAR", "BURST", "CREEPER" |
power | int | 1 | Сила полёта, 0-127 |
-- Пример: красно-золотой залп фейерверка
context.world:spawn_firework(loc.x, loc.y, loc.z, {"RED", "GOLD"}, "BURST", 2)
world:place_temporary_block(x, y, z, material, [ticks], [require_air])
Устанавливает блок, который автоматически возвращается в исходное состояние через задержку.
| Параметр | Тип | По умолчанию | Примечания |
|---|---|---|---|
x | int | обязательно | Координата блока X |
y | int | обязательно | Координата блока Y |
z | int | обязательно | Координата блока Z |
material | string | обязательно | Имя Bukkit Material (например, "stone", "ice") |
ticks | int | 0 | Длительность в тиках до возврата блока. 0 означает постоянный. |
require_air | boolean | false | Если true, ставит блок только при условии, что цель — воздух |
Возвращает true, если блок был установлен, false, если материал был недопустим или требование воздуха не выполнено.
world:drop_item(x, y, z, material, [amount])
Бросает сущность-предмет в указанной локации с естественным разбросом.
| Параметр | Тип | По умолчанию | Примечания |
|---|---|---|---|
x | number | обязательно | Координата X |
y | number | обязательно | Координата Y |
z | number | обязательно | Координата Z |
material | string | обязательно | Имя Bukkit Material |
amount | int | 1 | Размер стака |
Возвращает таблицу сущности выроненного предмета, или nil, если материал был недопустим.
context.zones
Таблица zones позволяет создавать пространственные зоны и отслеживать их на предмет событий входа/выхода игрока. Зоны привязаны к экземпляру скрипта и очищаются автоматически при уничтожении экземпляра.
zones:create_sphere(x, y, z, radius)
Создаёт сферическую зону с центром в указанных координатах. Возвращает числовой дескриптор зоны.
| Параметр | Тип | Примечания |
|---|---|---|
x | number | Центр X |
y | number | Центр Y |
z | number | Центр Z |
radius | number | Радиус сферы |
zones:create_cylinder(x, y, z, radius, height)
Создаёт цилиндрическую зону. Возвращает числовой дескриптор зоны.
| Параметр | Тип | Примечания |
|---|---|---|
x | number | Центр X |
y | number | Центр Y (основание) |
z | number | Центр Z |
radius | number | Радиус цилиндра |
height | number | Высота цилиндра |
zones:create_cuboid(x, y, z, xSize, ySize, zSize)
Создаёт кубоидную зону. Возвращает числовой дескриптор зоны.
| Параметр | Тип | Примечания |
|---|---|---|
x | number | Центр X |
y | number | Центр Y |
z | number | Центр Z |
xSize | number | Полуразмер по X |
ySize | number | Полуразмер по Y |
zSize | number | Полуразмер по Z |
zones:watch(handle, onEnterCallback, onLeaveCallback)
Запускает отслеживание зоны на предмет событий входа/выхода игрока. Параметры колбэков действуют как булевы сигналы — передача не-nil значения (например, функции или true) активирует соответствующий хук на скрипте. Сами колбэки не вызываются напрямую. Вместо этого логика входа/выхода срабатывает через хуки скрипта on_zone_enter / on_zone_leave.
| Параметр | Тип | Примечания |
|---|---|---|
handle | int | Дескриптор зоны из вызова create_* |
onEnterCallback | any non-nil или nil | Не-nil активирует хук on_zone_enter для этой зоны |
onLeaveCallback | any non-nil или nil | Не-nil активирует хук on_zone_leave для этой зоны |
Возвращает true, если отслеживание было настроено успешно, nil, если дескриптор зоны недопустим.
Отслеживание зон проверяется каждый серверный тик против всех игроков в том же мире. Сохраняйте количество зон разумным, чтобы избежать накладных расходов на производительность.
zones:unwatch(handle)
Прекращает отслеживание зоны и очищает её ресурсы.
| Параметр | Тип | Примечания |
|---|---|---|
handle | int | Дескриптор зоны, отслеживание которой нужно прекратить |
Пример: триггерная зона по близости
return {
api_version = 1,
on_spawn = function(context)
local loc = context.prop.current_location -- или context.boss:get_location()
if loc == nil then return end
local handle = context.zones:create_sphere(loc.x, loc.y, loc.z, 5)
-- Передайте не-nil значения, чтобы активировать хуки on_zone_enter и on_zone_leave.
-- Это булевы сигналы, а не колбэки — реальная логика идёт в хуках ниже.
context.zones:watch(handle, true, true)
context.state.zone_handle = handle
end,
on_zone_enter = function(context)
context.log:info("Player entered zone!")
end,
on_zone_leave = function(context)
context.log:info("Player left zone!")
end,
on_destroy = function(context)
if context.state.zone_handle then
context.zones:unwatch(context.state.zone_handle)
end
end
}
context.event
Таблица event присутствует, когда текущий хук был вызван игровым событием (например, on_right_click, on_zone_enter). Она не присутствует во время on_game_tick или запланированных колбэков.
| Поле / Метод | Тип | Примечания |
|---|---|---|
is_cancelled | boolean | Отменено ли событие |
cancel() | method | Отменяет событие (предотвращает поведение по умолчанию) |
uncancel() | method | Снимает отмену с ранее отменённого события |
player | entity table | Игрок, участвующий в событии, если есть |
on_right_click = function(context)
if context.event then
context.event:cancel() -- предотвратить обычное взаимодействие правым кликом
end
end
Скрипты сил EliteMobs имеют более подробную таблицу событий с количеством урона, причинами урона, ссылками на наносящего урон и методами модификации урона. Полные поля события EliteMobs смотрите в Справочнике API Lua.
Вспомогательное пространство имён em
Таблица em доступна на момент загрузки файла (до запуска любого хука). Она предоставляет вспомогательные конструкторы для построения таблиц локаций, таблиц векторов и определений зон, используемых по всему API.
| Функция | Назначение |
|---|---|
em.create_location(x, y, z [, world, yaw, pitch]) | Создать таблицу локации с опциональными именем мира, yaw и pitch. У возвращённой таблицы также есть метод .add(dx, dy, dz), смещающий локацию на месте и возвращающий саму себя для построения цепочки. |
em.create_vector(x, y, z) | Создать таблицу вектора |
em.zone.create_sphere_zone(radius) | Создать определение сферической зоны |
em.zone.create_dome_zone(radius) | Создать определение купольной зоны |
em.zone.create_cylinder_zone(radius, height) | Создать определение цилиндрической зоны |
em.zone.create_cuboid_zone(x, y, z) | Создать определение кубоидной зоны |
em.zone.create_cone_zone(length, radius) | Создать определение конусной зоны |
em.zone.create_static_ray_zone(length, thickness) | Создать определение статической лучевой зоны |
em.zone.create_rotating_ray_zone(length, point_radius, animation_duration) | Создать определение вращающейся лучевой зоны |
em.zone.create_translating_ray_zone(length, point_radius, animation_duration) | Создать определение перемещающейся лучевой зоны |
em.location.is_in_dungeon(loc) | Проверить, находится ли локация внутри любого зарегистрированного региона данжа |
em.location.is_protected(loc) | Проверить, находится ли локация в любом защищённом регионе (WorldGuard, GriefPrevention, регионы EM и т.д.) |
em.location.owned_by(loc, namespace) | Проверить, владеет ли конкретный namespace плагина локацией (например, "EliteMobs") |
em.location.owners(loc) | Массив строк-неймспейсов, владеющих локацией |
em.location.kinds_at(loc) | Массив тегов вида в локации ("elitemobs", "world_package", "open_world_dungeon", категория размера данжа) |
em.location.has_kind(loc, kind) | Проверить, помечена ли локация указанным видом |
Конструкторы зон возвращают цепочечные таблицы с :set_center(loc) (или :set_origin(loc) / :set_destination(loc) в зависимости от типа зоны):
-- На уровне файла: создать переиспользуемую форму зоны
local blast_zone = em.zone.create_sphere_zone(5)
return {
api_version = 1,
on_spawn = function(context)
-- Привязать зону на момент вызова
blast_zone:set_center(context.boss:get_location())
local entities = context.zones:get_entities_in_zone(blast_zone)
-- ...
end
}
Пространство имён em особенно полезно в EliteMobs, где определения зон используются с context.zones:get_entities_in_zone() и context.script. В FreeMinecraftModels чаще применяются методы context.zones:create_sphere(...) / create_cylinder(...) / create_cuboid(...) для простых отслеживаемых зон.
Таблицы сущностей
Таблицы сущностей возвращаются из запросов мира, данных событий и колбэков зон. Они предоставляют слоёный набор полей и методов в зависимости от типа сущности.
Базовые поля сущности
| Поле | Тип | Примечания |
|---|---|---|
uuid | string | UUID сущности |
entity_type | string | Тип сущности (например, "player", "zombie", "skeleton", "villager") |
is_valid | boolean | Действительна ли ещё ссылка на сущность |
is_dead | boolean | Мертва ли сущность |
is_player | boolean | Является ли сущность игроком |
is_hostile | boolean | Является ли сущность враждебным мобом (зомби, скелет и т.д.) |
is_passive | boolean | Является ли сущность пассивным мобом (корова, свинья, курица и т.д.) |
current_location | location table | Текущая позиция сущности (x, y, z, world, yaw, pitch) |
world | string | Имя мира, в котором находится сущность |
Базовые методы сущности
| Метод | Возвращает | Примечания |
|---|---|---|
teleport(location_table) | void | Телепортирует сущность. Таблица локации должна иметь поля x, y, z, world; yaw и pitch опциональны. |
remove() | void | Удаляет сущность из мира. Действует только если сущность ещё валидна. |
set_silent(flag) | void | Заглушает или включает звуки сущности. |
set_invulnerable(flag) | void | Делает сущность неуязвимой или уязвимой к урону. |
set_gravity(flag) | void | Включает или отключает гравитацию для сущности. |
set_glowing(flag) | void | Переключает эффект светящегося контура у сущности. |
Поля живой сущности
Живые сущности (игроки, мобы и т.д.) имеют все базовые поля сущности плюс:
| Поле | Тип | Примечания |
|---|---|---|
health | number | Текущее здоровье |
maximum_health | number | Максимальное здоровье |
name | string | Отображаемое имя |
is_alive | boolean | Жива ли сущность |
Методы живой сущности
| Метод | Возвращает | Примечания |
|---|---|---|
damage(amount) | void | Наносит сущности указанный урон |
push(x, y, z) | void | Применяет импульс скорости |
set_facing(x, y, z) | void | Задаёт направление, куда смотрит сущность |
add_potion_effect(effect, duration, amplifier) | void | Добавляет эффект зелья. effect — строка (например, "speed", "slowness", "regeneration"). duration в тиках. amplifier — уровень эффекта минус 1 (0 = уровень I). |
remove_potion_effect(effect) | void | Удаляет эффект зелья по имени |
get_scale() | number | Возвращает текущий масштаб сущности (по умолчанию 1.0 на серверах без атрибута generic.scale) |
set_scale(value) | void | Устанавливает масштаб сущности через атрибут generic.scale. На серверах ниже 1.20.5 не работает. |
Не все сущности, возвращаемые get_nearby_entities(), являются живыми сущностями. Можно использовать entity.is_player, entity.is_hostile или entity.is_passive для фильтрации по категории, либо проверять if entity.damage then перед вызовом методов живой сущности, таких как damage(), push() или add_potion_effect().
Поля интеграции с плагинами
Таблицы сущностей автоматически включают поля для обнаружения и взаимодействия с сущностями, управляемыми другими плагинами Nightbreak. Эти поля заполняются только когда соответствующий плагин установлен — иначе они равны false / nil без накладных расходов.
Поля EliteMobs
Доступны, когда установлен EliteMobs.
| Поле | Тип | Примечания |
|---|---|---|
is_elite | boolean | Является ли сущность элитой EliteMobs |
is_custom_boss | boolean | Является ли сущность кастомным боссом EliteMobs (также доступно внутри подтаблицы elite) |
is_significant_boss | boolean | Является ли сущность кастомным боссом с множителем здоровья больше 1 (то есть продуманное столкновение, а не элита-наполнитель) |
elite | table или nil | Подтаблица информации об элите (см. ниже). nil, если сущность не элита. |
Подтаблица elite содержит:
| Поле | Тип | Примечания |
|---|---|---|
elite.level | int | Уровень элиты |
elite.name | string | Отображаемое имя элиты |
elite.health | number | Текущее здоровье |
elite.max_health | number | Максимальное здоровье |
elite.is_custom_boss | boolean | Является ли это кастомным боссом (в отличие от естественной элиты) |
elite.health_multiplier | number | Множитель здоровья, заданный в конфиге |
elite.damage_multiplier | number | Множитель урона, заданный в конфиге |
elite:remove() | void | Удаляет элиту через корректный пайплайн удаления EliteMobs (очищает отслеживание, лут и т.д.) |
Пример: разный урон элитам
local entities = context.world:get_nearby_entities(x, y, z, 5)
for _, entity in ipairs(entities) do
if entity.is_elite then
-- Двойной урон элитам
entity:damage(20)
context.log:info("Hit elite: " .. entity.elite.name .. " (level " .. entity.elite.level .. ")")
elseif entity.is_hostile then
entity:damage(10)
end
end
Поля FreeMinecraftModels
Доступны, когда установлен FreeMinecraftModels.
| Поле | Тип | Примечания |
|---|---|---|
is_modeled | boolean | Прикреплена ли к сущности FMM-модель (DynamicEntity или PropEntity) |
is_prop | boolean | Является ли сущность FMM-пропсом (статической декоративной сущностью) |
model | table или nil | Подтаблица информации о модели (см. ниже). nil, если сущность не смоделирована. |
Подтаблица model содержит:
| Поле | Тип | Примечания |
|---|---|---|
model.model_id | string | ID чертежа модели (например, "torch_01") |
model.is_dynamic | boolean | Является ли смоделированная сущность DynamicEntity (модель моба/босса), а не статичным пропсом |
model:play_animation(name, [blend], [loop]) | boolean | Воспроизводит именованную анимацию. blend по умолчанию false, loop по умолчанию false. Возвращает true, если анимация была найдена. |
model:stop_animations() | void | Останавливает все воспроизводящиеся анимации на модели. |
model:remove() | void | Удаляет смоделированную сущность через корректный пайплайн удаления FMM. |
Мост модели (доступный у любой сущности) задаёт blend и loop по умолчанию в false. У таблицы пропса prop table play_animation задаёт оба по умолчанию в true, потому что пропсы обычно используют плавные зацикленные анимации.
Пример: фильтрация сущностей по типу
local entities = context.world:get_nearby_entities(x, y, z, 10)
for _, entity in ipairs(entities) do
if entity.is_prop then
-- Пропускаем пропсы
elseif entity.is_player then
entity:damage(5)
elseif entity.entity_type == "villager" then
-- Не трогаем жителей
elseif entity.is_elite then
entity:damage(20)
elseif entity.is_hostile then
entity:damage(10)
end
end
Поля, специфичные для игрока
Сущности-игроки имеют все поля сущности и живой сущности плюс:
| Поле | Тип | Примечания |
|---|---|---|
game_mode | string | Игровой режим игрока ("creative", "survival", "adventure", "spectator") |
Методы, специфичные для игрока
| Метод | Возвращает | Примечания |
|---|---|---|
send_message(msg) | void | Отправляет игроку сообщение в чат. Поддерживает цветовые коды &. |
get_held_item() | table или nil | Возвращает {type, amount, display_name} для предмета в основной руке игрока, либо nil, если рука пуста |
consume_held_item(amount?) | void | Расходует предметы из основной руки игрока. amount по умолчанию 1 |
has_item(material, amount?) | boolean | Возвращает true, если у игрока есть как минимум amount (по умолчанию 1) указанного материала где-либо в инвентаре |
get_target_entity([range]) | entity table или nil | Возвращает сущность, на которую смотрит игрок, через лучевую трассировку, либо nil, если её нет. Дистанция по умолчанию — 50. |
get_eye_location() | location table | Возвращает таблицу локации на высоте глаз игрока |
get_look_direction() | table | Возвращает вектор направления {x, y, z}, куда смотрит игрок |
send_block_change(x, y, z, material, [ticks]) | boolean | Отправляет фальшивый блок, видимый только этому игроку. Если задан ticks, фальшивый блок автоматически сбрасывается через эту длительность. Возвращает true при успехе, false, если материал недопустим. |
reset_block(x, y, z) | boolean | Сбрасывает фальшивый блок обратно к настоящему блоку для этого игрока. Всегда возвращает true. |
sleep(x, y, z) | void | Заставляет игрока войти в анимацию сна в кровати в указанных координатах. Блок автоматически восстанавливается, когда игрок перестаёт спать. |
wake_up() | void | Будит спящего игрока. |
Методы UI для игрока
Эти методы доступны на любой таблице сущности-игрока и предоставляют способы отображения информации игроку через встроенные UI-элементы Minecraft.
player:show_boss_bar(text, [color], progress, [ticks])
Показывает полосу босса игроку.
| Параметр | Тип | По умолчанию | Примечания |
|---|---|---|---|
text | string | обязательно | Отображаемый текст. Поддерживает цветовые коды &. |
color | string | "WHITE" | Цвет полосы. Один из: "RED", "BLUE", "GREEN", "YELLOW", "PURPLE", "PINK", "WHITE" |
progress | number | обязательно | Заполнение от 0.0 (пусто) до 1.0 (полно) |
ticks | int | nil | Опциональная задержка автоскрытия в тиках. Если опущено, полоса остаётся до ручного скрытия. |
player:hide_boss_bar()
Убирает полосу босса с экрана игрока. Параметров не принимает.
player:show_action_bar(text, [ticks])
Показывает текст в области панели действий (над хотбаром).
| Параметр | Тип | По умолчанию | Примечания |
|---|---|---|---|
text | string | обязательно | Отображаемый текст. Поддерживает цветовые коды &. |
ticks | int | nil | Опциональная длительность в тиках. Если задана, сообщение пересылается каждые 40 тиков, чтобы оставаться видимым в течение всей длительности. |
player:show_title(title, [subtitle], fade_in, stay, fade_out)
Показывает игроку экранный заголовок.
| Параметр | Тип | По умолчанию | Примечания |
|---|---|---|---|
title | string | обязательно | Основной текст заголовка. Поддерживает цветовые коды &. |
subtitle | string | "" | Подзаголовок под основным заголовком. Опционально. |
fade_in | int | обязательно | Длительность появления в тиках |
stay | int | обязательно | Сколько заголовок остаётся на экране в тиках |
fade_out | int | обязательно | Длительность исчезновения в тиках |
Что дальше
Для специфичных для плагина хуков, API и рабочих процессов:
- EliteMobs: Getting Started | Hooks & Lifecycle | Boss & Entities | World & Environment | Zones & Targeting
- FreeMinecraftModels: Getting Started | Prop & Item API | Examples