Авторские зачарования
EliteMobs и FreeMinecraftModels предоставляют собственные зачарования через общую систему MagmaCore. Каждый плагин хранит свои определения и Lua-эффекты в собственной папке enchantments/. Обычные зачарования Minecraft остаются в пространстве имён minecraft:.
Обновление встроенных определений
Каталог восстанавливает недостающие встроенные YAML- и Lua-файлы и добавляет отсутствующие стандартные поля в существующие встроенные определения. Уже настроенные значения и существующий Lua-код сохраняются. Это работает и при уже существующей папке enchantments/.
Плагин-владелец может сначала архивировать файлы устаревшего формата. Например, EliteMobs сохраняет YAML зачарований с maxLevelV2, прежде чем создавать актуальные стандартные определения. EliteMobs также архивирует неотредактированные копии прежних встроенных скриптов зачарований, например старый grappling_hook.lua, чтобы на их место записалась актуальная версия по умолчанию; отредактированный вами скрипт остаётся. Проверьте свои настройки в архиве конфигурации и перенесите их с использованием актуальных полей. Обновлённому DLC или собственному эффекту по-прежнему нужны соответствующие определение и Lua-код.
Ссылки в предметах
Собственные эффекты используют ID с пространством имён в нижнем регистре и положительный целый уровень. Пример определения предмета FMM:
enchantments:
- "minecraft:unbreaking,3"
- "elitemobs:critical_strikes,2"
Например, critical_strikes.yml в каталоге зачарований EliteMobs определяет elitemobs:critical_strikes. Определение FMM использует freeminecraftmodels:. Подпапки не становятся частью ID; имена файлов контента должны быть уникальными.
YAML собственных предметов EliteMobs сохраняет имена Bukkit, например UNBREAKING,3, для обычных зачарований, но требует ID с пространством имён для собственных эффектов. Не копируйте синтаксис обычных зачарований FMM в другой плагин без проверки его формата предметов.
Установленный поставщик должен распознавать ID. Совместимость, тип предмета, слот, конфликты и необходимые возможности задаются определением. Удаление поставщика не превращает его эффект в обычное зачарование Minecraft.
Формат определения
Это встроенное определение FMM Ignition, работающее вместе с ignition.lua из того же каталога зачарований:
isEnabled: true
name: Ignition
description: Sets surviving targets on fire after a staff fireball hits.
maxLevel: 3
curse: false
validSlots: [MAINHAND]
itemTypes: [STAFF]
attackKinds: [STAFF_FIREBALL]
requires: []
conflicts: []
stacking: source_item
script: ignition.lua
parameters:
base_ticks: 20
ticks_per_level: 20
return {
api_version = 1,
on_ignition_ticks = function(context)
return math.max(0, math.min(200, context.parameters.base_ticks
+ context.parameters.ticks_per_level * context.enchantment.level))
end
}
Запрос возвращает FMM длительность горения. Он не выполняется как скрипт декоративного объекта или экипированного предмета.
| Поле | Значение |
|---|---|
isEnabled | По умолчанию true; отключённые определения не попадают в каталог |
name | Обязательное простое отображаемое имя |
description | Необязательное описание, по умолчанию пустое |
maxLevel | Положительный предел уровня зачарования; явно созданные автором предметы могут его превышать |
curse | Является ли зачарование проклятием; по умолчанию false |
validSlots | Слоты экипировки: HEAD, CHEST, LEGS, FEET, MAINHAND, OFFHAND |
itemTypes | Допустимые категории: SWORD, AXE, PICKAXE, SHOVEL, HOE, BOW, CROSSBOW, TRIDENT, MACE, SPEAR, HELMET, CHESTPLATE, LEGGINGS, BOOTS, SHIELD, FISHING_ROD, SHEARS, ELYTRA, WAND, STAFF, OTHER |
attackKinds | Необязательный фильтр магических атак: WAND_MISSILE, STAFF_MELEE, STAFF_FIREBALL |
requires | Требования к возможностям поставщика |
conflicts | ID других зачарований с пространством имён в нижнем регистре |
stacking | По умолчанию source_item, либо sum_equipped_levels |
script | Обязательное имя .lua-файла в нижнем регистре без папки |
parameters | Именованные скалярные значения или списки таких значений по уровням |
set | Необязательно. Превращает это зачарование в набор предметов |
Список по уровням должен содержать ровно maxLevel элементов. Выше этого уровня используется последнее значение списка, но скрипт всё равно получает фактический уровень зачарования. Параметры относятся к конкретному эффекту; произвольный ключ здесь не создаёт новую механику.
Неизвестные поля верхнего уровня, повторяющиеся ID, отсутствующие скрипты и неподдерживаемые обработчики отклоняют весь новый каталог. Исправьте файл, указанный в ошибке, перед перезагрузкой. Неудачный кандидат не заменяет действующий каталог.
Владелец эффекта
Начните с эффекта, поставляемого плагином, которому будет принадлежать новое определение. Его поддерживаемые обработчики и операции определяют доступное поведение. Обработчики запросов возвращают значения, например число снарядов, шанс критического удара или бонус угрозы. Обработчики действий реагируют на принятый ввод предмета и могут управлять длительными эффектами.
Старый FMM API context.item и его жизненный цикл экипировки и снятия здесь не применяются. Скрипты зачарований используют собственные context.enchantment, context.parameters, сохранённые сведения об источнике и операции действий. Простое переименование старого скрипта предмета не делает его контекст совместимым.
Книги и наковальни
Книги с собственными зачарованиями используют те же определения поставщика, что и экипированные предметы. Наковальня проверяет исходный предмет, книгу и полный результат, включая обычные зачарования. Равные собственные уровни объединяются в следующий; при разных остаётся больший. Каждое изменённое собственное зачарование добавляет свой итоговый уровень к обычной стоимости ремонта. Итог должен пройти проверки предела уровня на наковальне, слота, типа, возможностей и конфликтов из определения.
Смешанные книги должны переносить все принимаемые сервером обычные зачарования вместе с собственными. Если сервер отвергает обычную запись, собственная операция отклоняется целиком вместо молчаливого удаления этой части книги. Недопустимые или недоступные определения тоже отклоняют предпросмотр. При получении результата входные предметы и состояние поставщика проверяются повторно; показанный результат не гарантируется после изменения каталога.
Справочник Lua-запросов
Числовые запросы запускают новый экземпляр скрипта и закрывают его сразу после получения результата. Возвращайте одно конечное число или nil, если вклада нет. Состояние и отложенные задачи не переживают запрос. Ошибочное определение изолируется до успешной перезагрузки каталога; исчерпание оставшегося бюджета вызывающего кода само по себе не изолирует определение.
| Контекст | Содержимое |
|---|---|
context.enchantment | id и фактический level |
context.parameters | Значения этого определения, рассчитанные для уровня |
context.input | Скалярные сведения от механики-владельца; точные ключи смотрите во встроенном эффекте |
context.target | Таблица целевой Entity или Living Entity либо nil |
context.player | Игрок-инициатор, если запрос связан с игроком |
FMM предоставляет on_missile_count, on_missile_damage_factor, on_blast_radius_factor и on_ignition_ticks. Другие поставщики предоставляют свои числовые обработчики. Определение может объявлять только обработчики, принимаемые его поставщиком.
Справочник Lua-действий
Скрипты действий используют общие таблицы планировщика, перезарядок, мира, зон, игрока и событий. Они запускаются для одного принятого ввода или атаки и используют сохранённый источник в последующих обратных вызовах. Чат сохраняет текст во время события, затем захватывает экипировку при обработке в потоке сервера. Необязательный parameters.lifetime_ticks должен быть положительным целым числом; без него активация живёт один тик. Для отложенных эффектов задайте время жизни, достаточное для их завершения.
Активации останавливаются по истечении времени жизни, при смерти, отключении или смене мира исполнителя, выгрузке мира-владельца, выгрузке чанка с одной из принадлежащих активации сущностей, а также при перезагрузке или отключении поставщика. Они могут завершиться раньше, когда после последнего ввода больше не осталось принадлежащей им работы. parameters.stop_on_unequip: true также останавливает активацию, когда сохранённый предмет больше не экипирован. Локальные перезарядки принадлежат игроку и ID зачарования; глобальные принадлежат игроку внутри поставщика. Обе сохраняются при смене экипировки, завершении активаций, смене мира и корректной перезагрузке и очищаются при отключении игрока или остановке поставщика.
| Обработчик | Принимаемый ввод |
|---|---|
on_attack_entity | Успешный положительный обычный урон в ближнем бою предметом основной руки либо явная атака плагина |
on_projectile_hit | Успешный урон живой цели сохранённым снарядом лука, один раз для каждой пары снаряда и цели, либо явное попадание плагина |
on_take_damage | Положительный урон игроку; проверяются подходящие слоты экипировки |
on_right_click, on_left_click | Взаимодействие рукой без приседания |
on_shift_right_click, on_shift_left_click | Взаимодействие рукой при приседании; заменяет соответствующий обычный обработчик нажатия |
on_break_block | Принятое разрушение блока игроком с предметом основной руки |
on_chat | Принятый чат, обработанный в потоке сервера с сохранённым текстом |
on_sneak | Начало приседания; вклад экипировки собирается по определениям |
on_projectile_launch | Израсходованный зачарованный боеприпас выпускается стрелой из события лука |
on_game_tick | Тик, пока эта активация работает |
on_zone_enter, on_zone_leave | Игрок пересекает границу зоны, наблюдаемой этой активацией |
Эти обработчики не создают среду скриптов экипировки и снятия. Определению только с обработкой тиков всё равно нужен обработчик ввода для запуска активации. Обычные обработчики атак, урона, чата и добычи наблюдают уже принятый ввод и не могут отменить исходное событие. Четыре обработчика взаимодействия предоставляют синхронный флаг отмены: context.event:cancel() запрещает соответствующее взаимодействие с предметом и блоком. Отложенные обратные вызовы не могут отменять ввод задним числом.
| Контекст | Содержимое |
|---|---|
context.enchantment | id, level |
context.parameters | Параметры определения с учётом уровня |
context.player | Player Table текущего исполнителя |
context.target | Living Entity Table текущей затронутой цели либо nil |
context.source | Сохранённые сведения: item, slot, inventory_slot, equipment, attack_kind, providers; некоторые входы также предоставляют ammunition, projectile, message, block, drop_items, sneaking или equipped_levels |
context.item | Методы прочности и расходования сохранённого слота, пока предмет инвентаря доступен; см. методы предмета |
context.action | id (UUID атаки), instance (токен активации), actor (UUID), world (UUID мира) и методы ниже |
context.set | Для набора предметов: id, name, level и pieces; иначе nil |
Снимки предметов содержат material, amount и enchantments. Это данные, а не действующие объекты инвентаря. UUID в сведениях об источнике представлены строками. При добыче source.block содержит x, y, z и material в нижнем регистре.
| Метод действия | Возвращает | Поведение |
|---|---|---|
stop() | nil | Останавливает активацию и очищает принадлежащую ей работу |
has_previous() | bool | Проверяет наличие другого активного экземпляра этого зачарования у того же игрока |
replace_previous() | nil | Останавливает предыдущие экземпляры, сохраняя текущий |
damage_target(target_uuid, amount) | bool | Просит поставщика применить конечный положительный урон с сохранённым источником; false при отказе |
own_entity(uuid) | bool | Регистрирует допустимую сущность того же мира, кроме игрока, для удаления при очистке; используйте после создания |
launch_projectile(location, direction, speed, range, ticks, impact, visual?, protected_path?=false) | bool | Запускает принадлежащий действию скриптовый снаряд; скорость и дальность конечные и положительные, ticks не меньше 1 |
attribute_projectile(uuid, callback, protect?=false) | bool | Связывает урон принадлежащего действию обычного снаряда с авторским обратным вызовом |
place_block(x, y, z, expected_material, block_data) | bool | Ставит блок через проверку действий игрока, только если текущий материал совпадает |
break_block(x, y, z, expected_material, drop_material?, amount?=1) | bool | Ломает блок через проверку действий игрока с необязательным авторским дропом |
break_naturally(x, y, z, expected_material) | bool | Ломает блок сохранённым инструментом с правилами дропа исходного события разрушения |
temporary_block(x, y, z, block_data, ticks?=0) | bool | Временно управляет загруженным блоком и восстанавливает его при очистке или через положительное число ticks; ноль означает до очистки |
can_own_block(x, y, z) | bool | Проверяет загрузку координат и доступность временного владения |
temporary_gravity(uuid, enabled) | bool | Временно меняет гравитацию с восстановлением при очистке |
restore_gravity(uuid) | bool | Досрочно восстанавливает гравитацию, временно изменённую этой активацией |
temporary_scale(uuid, scale) | bool | Временно меняет масштаб живой сущности до очистки |
temporary_potion(uuid, type, ticks, amplifier) | bool | Временно накладывает эффект зелья с положительным ticks и неотрицательным amplifier |
restore_potion(uuid, type) | bool | Досрочно восстанавливает эффект зелья, временно изменённый этой активацией |
ride_rails(speed) | bool | Сажает игрока в вагонетку, которую видят только клиенты, и ведёт её по соединённым рельсам в блоке игрока к тому концу, куда он смотрит, со скоростью speed блоков за тик (больше 0, не больше 2); false, если там нет рельсов, игрок уже едет или адаптер NMS сервера недоступен |
Поездка по рельсам — это работа, принадлежащая её активации. Приседание, конец путей, телепортация, смерть, выход или любое другое перемещение игрока дальше чем на блок от вагонетки завершают поездку, а затем и активацию; игрок оказывается там, где остановилась вагонетка, кроме случаев телепортации, смерти или выхода. Остановка активации, в том числе через replace_previous(), тоже высаживает игрока. Значение lifetime_ticks активации по-прежнему действует, поэтому задайте достаточно времени для самого длинного пути.
Обратные вызовы попадания снаряда получают (fresh_context, target_or_nil, location), визуальные получают (fresh_context, location). Обратные вызовы урона обычного снаряда получают (fresh_context, target, native_damage) на следующем тике. Они заменяют обычное применение урона и должны явно наносить нужный урон, обычно через fresh_context.action:damage_target(target.uuid, amount). При protect=true у обычного снаряда защищённые блоки взрыва и поджигание фильтруются. Скриптовый protected_path=true поглощает снаряды, пересекающие защищённые или незагруженные позиции.
Очистка ограничена операциями, регистрирующими владение. Обычные world:spawn_entity, entity:set_gravity и world:set_block_at не получают автоматическую очистку действия. Методы временного состояния управляют восстановлением, но не заменяют проверку разрешения на враждебный эффект или изменение блока.
Наборы предметов
Раздел set превращает зачарование в набор предметов. Поместите одно и то же зачарование на каждую часть набора. Набор считается собранным, пока в каждом слоте, перечисленном в pieces, находится предмет с этим зачарованием. Собранный набор запускает свои обработчики один раз на событие. Если не хватает любой части, ничего не запускается.
name: Crooked's Full Set
maxLevel: 1
validSlots: [HEAD, CHEST, LEGS, FEET]
itemTypes: [HELMET, CHESTPLATE, LEGGINGS, BOOTS]
script: crooked_set.lua
parameters:
lifetime_ticks: 620
stop_on_unequip: true
set:
pieces:
HEAD: Crooked's Hex-Brim
CHEST: Crooked's Warded Wrap
LEGS: Crooked's Bent Hosen
FEET: Crooked's Wayward Soles
lore:
- "&5Crooked's Full Set &7($equippedPieces/$totalPieces)"
- "$setPieces"
- "&7When damaged, has a 5% chance to grant Regeneration I."
return {
api_version = 1,
on_take_damage = function(context)
-- Runs only while all four pieces are worn, once per hit.
context.action:temporary_potion(context.player.uuid, "REGENERATION", 100, 0)
end
}
| Поле set | Значение |
|---|---|
pieces | Обязательное. Сопоставляет слоты экипировки с названиями частей. Если задан validSlots, он должен включать слот каждой части |
name | Название, используемое в $setName. По умолчанию — name зачарования; принимает цветовые коды & |
lore | Строки описания набора. По умолчанию — название набора с числом частей, затем по одной строке на каждую часть |
equippedPiece | Строка для надетой части. По умолчанию &a✔ $pieceName |
missingPiece | Строка для отсутствующей части. По умолчанию &c✘ $pieceName |
Описание набора принимает такие плейсхолдеры:
| Плейсхолдер | Показывает |
|---|---|
$setName | Название набора |
$equippedPieces | Сколько частей надето на игроке |
$totalPieces | Сколько частей в наборе |
$setPieces | По одной строке на часть в порядке слотов, из equippedPiece или missingPiece. Текст вокруг плейсхолдера повторяется в каждой строке |
$pieceName, $pieceSlot | Внутри equippedPiece и missingPiece: название части и её слот, например Head или Main Hand |
$ifSetComplete | Показывает строку, только пока надеты все части |
$ifSetIncomplete | Показывает строку, только пока не хватает части |
Предметы набора показывают этот раздел вместо строки в списке пользовательских зачарований. В EliteMobs поместите $itemSet в itemLoreStructureV2 в ItemSettings.yml или в собственное lore кастомного предмета. Если нет ни того, ни другого, набор показывается после пользовательского описания предмета. $ifItemSet показывает строку структуры только на предметах набора. Кастомные предметы FMM показывают набор в строке описания, содержащей $itemSet, или после своего описания.
Раздел показывает, что надето на игроке, который несёт предмет, и перерисовывается, когда он надевает или снимает часть. Предмет, хранящийся вне инвентаря игрока, сохраняет состояние, которое показывал, когда покинул его.
Обработчики набора отличаются от обычных обработчиков зачарований несколькими особенностями:
- Каждый обработчик действия из таблицы выше доходит до собранного набора независимо от того, какие слоты используют его части. Набор брони может отвечать на
on_attack_entityилиon_break_block. - Собранность проверяется в момент события. Снаряд проверяет наборы, надетые на момент его попадания, причём считается любой снаряд, а не только стрелы лука.
on_take_damageзадаётcontext.targetравным атакующему, если он есть.context.source.itemиcontext.item— первая часть в порядке слотов:HEAD,CHEST,LEGS,FEET,MAINHAND,OFFHAND. Для удерживаемого оружия или инструмента читайтеcontext.source.equipment.MAINHAND.context.set.level— наименьший уровень среди частей.context.set.piecesиндексируется по слоту и содержитnameиinventory_slotкаждой части.stop_on_unequip: trueостанавливает активацию набора, когда снимается любая часть.- Числовые запросы, например угроза и шанс крита EliteMobs или модификаторы каста FMM, учитывают набор один раз и только пока он собран.
Обновление существующего контента
FMM пропускает собственные предметы с непустым scripts: или устаревшими зачарованиями без пространства имён. Замените их определения на зачарования с пространствами имён; скрипты декоративных объектов остаются поддерживаемыми.
Собственные эффекты EliteMobs теперь используют maxLevel и специфичные для эффекта parameters в YAML поставщика. Настройки обычных и элитных уровневых зачарований имеют отдельный формат. Следуйте справочнику зачарований EliteMobs, а не копируйте старый файл maxLevelV2 в определение поставщика.