跳到主要内容

内容附魔

EliteMobs 与 FreeMinecraftModels 通过共享的 MagmaCore 系统提供自定义附魔。每个插件在自己的 enchantments/ 目录中管理定义和 Lua 效果。Minecraft 原版附魔仍使用 minecraft: 命名空间。

更新内置定义​

目录会恢复缺失的内置 YAML 和 Lua 文件,并向现有内置定义添加缺少的默认字段。已有配置值和 Lua 源码会保留。即使 enchantments/ 目录已经存在,此机制也会生效。

所属插件可能先归档符合已废弃格式的文件。例如,EliteMobs 会先保留含有 maxLevelV2 的附魔 YAML,再生成当前默认内容。EliteMobs 还会归档较早内置附魔脚本中未经编辑的副本(例如旧的 grappling_hook.lua),以便在原处写入当前默认版本;你编辑过的脚本会保留。在配置归档中检查自定义设置,并使用当前字段重新应用。更新的 DLC 或自定义效果仍需要各自匹配的定义和 Lua 源码。

物品引用​

自定义效果使用小写的命名空间 ID 和正整数等级。以下是 FMM 物品定义示例:

enchantments:
- "minecraft:unbreaking,3"
- "elitemobs:critical_strikes,2"

例如,EliteMobs 附魔目录中的 critical_strikes.yml 定义 elitemobs:critical_strikes。FMM 定义使用 freeminecraftmodels:。子目录不会成为 ID 的一部分;内容文件应使用唯一文件名。

EliteMobs 自定义物品 YAML 对原版附魔保留 UNBREAKING,3 等 Bukkit 名称,对自定义效果则要求命名空间 ID。不要在未检查其他插件物品格式的情况下,直接复制 FMM 的原版附魔语法。

已安装的提供方必须识别该 ID。兼容性、物品类型、栏位、冲突和必需能力都来自定义。移除提供方不会把其自定义效果变成原版附魔。

定义格式​

以下是 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 context.item API 及其装备、卸下生命周期不适用于这里。附魔脚本使用自己的 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.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.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)的速度,沿玩家所在方块中相连的铁轨、朝其面向的一端驱动它;当那里没有铁轨、玩家已在骑乘,或服务器的 NMS 适配器不可用时返回 false

铁轨骑行属于其激活实例所管理的工作。潜行、到达轨道尽头、传送、死亡、离开,或任何其他使玩家离开矿车超过一格的情况,都会结束骑行,随后结束该激活实例;玩家会被放在矿车停下的位置,传送、死亡或离开的情况除外。停止该激活实例(包括通过 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
}
套装字段含义
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 放进 ItemSettings.yml 的 itemLoreStructureV2,或放进自定义物品自己的 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 自定义效果现在在提供方 YAML 中使用 maxLevel 和效果专属的 parameters。原版及精英等级附魔配置是另一种格式。请遵循 EliteMobs 附魔参考,不要将旧 maxLevelV2 文件复制到提供方定义中。