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

Авторские зачарования

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Требования к возможностям поставщика
conflictsID других зачарований с пространством имён в нижнем регистре
stackingПо умолчанию source_item, либо sum_equipped_levels
scriptОбязательное имя .lua-файла в нижнем регистре без папки
parametersИменованные скалярные значения или списки таких значений по уровням
setНеобязательно. Превращает это зачарование в набор предметов

Список по уровням должен содержать ровно maxLevel элементов. Выше этого уровня используется последнее значение списка, но скрипт всё равно получает фактический уровень зачарования. Параметры относятся к конкретному эффекту; произвольный ключ здесь не создаёт новую механику.

Неизвестные поля верхнего уровня, повторяющиеся ID, отсутствующие скрипты и неподдерживаемые обработчики отклоняют весь новый каталог. Исправьте файл, указанный в ошибке, перед перезагрузкой. Неудачный кандидат не заменяет действующий каталог.

Владелец эффекта​

Начните с эффекта, поставляемого плагином, которому будет принадлежать новое определение. Его поддерживаемые обработчики и операции определяют доступное поведение. Обработчики запросов возвращают значения, например число снарядов, шанс критического удара или бонус угрозы. Обработчики действий реагируют на принятый ввод предмета и могут управлять длительными эффектами.

Старый FMM API context.item и его жизненный цикл экипировки и снятия здесь не применяются. Скрипты зачарований используют собственные context.enchantment, context.parameters, сохранённые сведения об источнике и операции действий. Простое переименование старого скрипта предмета не делает его контекст совместимым.

Книги и наковальни​

Книги с собственными зачарованиями используют те же определения поставщика, что и экипированные предметы. Наковальня проверяет исходный предмет, книгу и полный результат, включая обычные зачарования. Равные собственные уровни объединяются в следующий; при разных остаётся больший. Каждое изменённое собственное зачарование добавляет свой итоговый уровень к обычной стоимости ремонта. Итог должен пройти проверки предела уровня на наковальне, слота, типа, возможностей и конфликтов из определения.

Смешанные книги должны переносить все принимаемые сервером обычные зачарования вместе с собственными. Если сервер отвергает обычную запись, собственная операция отклоняется целиком вместо молчаливого удаления этой части книги. Недопустимые или недоступные определения тоже отклоняют предпросмотр. При получении результата входные предметы и состояние поставщика проверяются повторно; показанный результат не гарантируется после изменения каталога.

Справочник Lua-запросов​

Числовые запросы запускают новый экземпляр скрипта и закрывают его сразу после получения результата. Возвращайте одно конечное число или nil, если вклада нет. Состояние и отложенные задачи не переживают запрос. Ошибочное определение изолируется до успешной перезагрузки каталога; исчерпание оставшегося бюджета вызывающего кода само по себе не изолирует определение.

КонтекстСодержимое
context.enchantmentid и фактический 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.enchantmentid, level
context.parametersПараметры определения с учётом уровня
context.playerPlayer Table текущего исполнителя
context.targetLiving 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.actionid (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 в определение поставщика.