Skip to content

分解规则

分解规则用于判断输入物品是否可以分解,并定义匹配后生成的产物与执行的命令。

规则文件位于插件数据目录的 rule 文件夹。可以在该目录及其子目录中创建 .yml 文件,插件重载时会递归读取全部规则文件,并按文件完整路径排序后加载。

每个规则文件的最外层直接填写规则 ID。规则 ID 在全部规则文件中必须唯一。出现重复 ID 或其它阻止加载的问题时,本次重载不会替换当前正在运行的规则。

完整规则示例

yaml
'分解规则示例':
  condition:
    - "name('&a额外规则示例') || name('额外规则', contains)"
    - "lore('武器', contains) || lore('防具', contains)"
    - "!lore('已绑定', contains)"
    - "material('276:0')"

  commands:
    - '[console]say %player_name% 触发了分解规则示例'
    - '[op]say %player_name% 触发了分解规则示例'
    - 'say %player_name% 触发了分解规则示例'

  give-item: true

  result:
    - 'MythicMobs@分解产物1 1-2 0.5 {[console]say %player_name% 获得了分解产物1}'
    - 'MythicMobs@分解产物2 2 1'

规则字段

每条规则只允许使用以下字段。填写其它字段会导致本次重载失败。

配置项类型默认值说明
condition字符串列表物品与玩家需要满足的条件,必须至少填写一行
commands字符串列表空列表当前规则成功执行后依次执行的规则命令
give-item布尔值true是否生成并发放 result 中的产物
result字符串列表空列表当前规则的产物、数量、概率与产物命令

give-itemfalse 时,插件不会解析、生成或发放该规则的 result 产物,但仍会执行 commands

如果 give-itemtrue,但没有配置任何 result,插件会输出警告,不会阻止规则加载。这类规则仍可执行 commands

规则匹配机制

全局条件

主配置中的 global-condition 会在所有规则之前判断。物品只有先满足全部全局条件,才会继续匹配 rule 文件中的规则。

全局条件与规则的 condition 使用相同语法。全局条件不满足时,该物品不会匹配任何分解规则。

多规则叠加

一个物品可以同时匹配多条规则。插件会按规则加载顺序收集全部匹配规则,不会在匹配到第一条规则后停止。

执行单个物品的分解时:

  • 所有匹配规则中 give-item: true 的产物都会分别参与概率判断。
  • 所有匹配规则的 commands 都会加入规则命令列表。
  • 界面预览会汇总所有匹配规则中能够创建的产物。
  • give-item: false 的规则不会提供产物预览,但其规则命令仍会执行。
  • 任意实际抽中的产物无法创建时,本次单个物品的分解会失败,输入物品不会被扣除。

界面只预览输入区域内第一个可分解物品的产物,最多显示预览区域能够容纳的前 18 项产物。

条件组合

写法逻辑
同一行顶层使用 `
多行 conditionAND,每一行都必须成立
表达式前添加 !对当前表达式结果取反
连续添加多个 !每个 ! 依次取反,偶数个等于不取反
yaml
condition:
  # 名称包含“武器”或“防具”时,本行成立
  - "name('武器', contains) || name('防具', contains)"

  # Lore不存在“已绑定”时,本行成立
  - "!lore('已绑定', contains)"

  # 玩家拥有指定权限时,本行成立
  - "permission('lydecomposition.use')"

条件表达式建议使用双引号包裹,函数中的文本参数使用单引号包裹。需要在字符串参数中表示单引号时,可以连续填写两个单引号。

yaml
condition:
  - "name('冒险者''的长剑')"

函数名与选项匹配时不区分英文大小写,建议统一使用文档中的写法。

条件函数

插件支持以下条件函数:

函数用途
hasname()判断物品是否存在自定义名称
name()匹配物品自定义名称
haslore()判断物品是否存在 Lore
lore()匹配物品任意一行 Lore
material()匹配物品材质、数字 ID 或 Data
permission()判断玩家是否拥有指定权限
papi()替换 PlaceholderAPI 变量并判断表达式
hasnbt()判断物品是否存在指定 NBT 节点
nbt()匹配指定 NBT 节点的值

名称条件

判断名称是否存在

yaml
condition:
  - "hasname()"

取反后表示物品不能存在自定义名称:

yaml
condition:
  - "!hasname()"

hasname() 不接受参数。

匹配名称内容

name() 的第一个参数是目标名称,后续可以填写一种匹配方式和 ignoreColor

写法说明
name('&a普通装备')完整匹配名称,颜色参与比较
name('&a普通装备', equals)显式使用完整匹配
name('普通装备', contains)名称包含指定内容
name('&a', startsWith)名称以指定内容开头
name('装备', endsWith)名称以指定内容结尾
name('普通装备', ignoreColor)忽略颜色后完整匹配
name('普通', contains, ignoreColor)忽略颜色后进行包含匹配

equals 是默认匹配方式。未填写 ignoreColor 时,颜色代码会参与比较,条件中的 & 颜色代码会先转换为服务端颜色符号。

yaml
condition:
  - "name('&a普通装备')"
  - "!name('绑定', contains)"

物品没有自定义名称时,name() 返回不匹配。

Lore 条件

判断 Lore 是否存在

yaml
condition:
  - "haslore()"

取反后表示物品不能存在 Lore:

yaml
condition:
  - "!haslore()"

haslore() 不接受参数。

匹配 Lore 内容

lore() 会逐行检查物品 Lore,只要任意一行符合要求,当前函数就会成立。

写法说明
lore('&7品质: &a一般')完整匹配任意一行 Lore,颜色参与比较
lore('&7品质: &a一般', equals)显式完整匹配任意一行 Lore
lore('品质:', contains)任意一行 Lore 包含指定内容
lore('&7', startsWith)任意一行 Lore 以指定内容开头
lore('装备', endsWith)任意一行 Lore 以指定内容结尾
lore('品质: 一般', ignoreColor)忽略颜色后完整匹配任意一行
lore('品质', contains, ignoreColor)忽略颜色后进行包含匹配
yaml
condition:
  - "lore('&7品质: &a一般')"
  - "!lore('已绑定', contains)"

!lore('已绑定', contains) 表示没有任何一行 Lore 可以包含“已绑定”。物品没有 Lore 时,原始 lore() 结果为不匹配,取反后结果为匹配。

材质条件

material() 只接受一个单引号字符串参数,可以使用数字 ID、数字 ID 与 Data,或材质枚举名称。

写法说明
material('276')匹配数字 ID 为 276 的物品,不检查 Data
material('276:0')同时匹配数字 ID 与 Data
material('DIAMOND_SWORD')匹配材质枚举名称
material('minecraft:diamond_sword')去除 minecraft: 命名空间后匹配材质名称
yaml
condition:
  - "material('DIAMOND_SWORD')"

材质名称匹配不区分英文大小写。数字 ID 与 Data 主要用于仍使用旧版物品体系的服务端配置。

权限条件

permission() 用于判断执行分解的玩家是否拥有指定权限节点。它只读取服务端当前的权限结果,不代表插件内置了同名权限。

yaml
condition:
  - "permission('lydecomposition.use')"

取反后可以要求玩家没有某个权限:

yaml
condition:
  - "!permission('lydecomposition.bypass')"

permission() 只接受一个单引号字符串参数。

PlaceholderAPI 条件

papi() 会先替换括号内的 PlaceholderAPI 变量,再判断替换后的完整表达式。

使用 papi() 条件时必须安装并启用 PlaceholderAPI,否则包含该条件的全局条件、规则或额外按钮会导致本次重载失败。

比较与逻辑运算符

运算符说明
==相等
!=不相等
>大于,仅支持数字
>=大于等于,仅支持数字
<小于,仅支持数字
<=小于等于,仅支持数字
&&AND,同组表达式全部成立
`

papi() 内部先按 || 划分 OR 组,再按 && 判断每个 OR 组中的表达式,因此 && 优先于 ||

==!= 两侧都能解析为数字时,插件按数字比较;否则按区分大小写的文本进行完整比较。文本可以使用单引号包裹。

如果表达式中没有比较运算符,只有文本 true 会被判断为成立,英文大小写不受限制。

yaml
condition:
  - "papi(%player_level% >= 5)"
  - "papi(%player_level% >= 5 && %player_level% <= 10)"
  - "papi(%player_class% == '战士')"
  - "papi(%player_class% != '法师')"
  - "papi(%player_class% == '战士' || %player_class% == '骑士')"
  - "papi(%some_boolean_placeholder%)"

PlaceholderAPI 替换后的内容直接参与表达式判断。对应变量必须返回能够与目标值正确比较的文本。

NBT 条件

NBT 键使用点号表示节点路径。例如 lyfj.a.b.c 表示根 NBT 中 lyfj 节点下的 a.b.c 节点。

使用 hasnbt()nbt() 时,当前服务端版本必须存在可用的 NBT 适配器,否则包含 NBT 条件的配置会导致本次重载失败。

项目中提供 NBT 适配的服务端版本包括:

  • 1.7.10
  • 1.8.8
  • 1.11.2
  • 1.12.2
  • 1.13.2
  • 1.14.4
  • 1.15.2
  • 1.16.5
  • 1.17.1
  • 1.18.2
  • 1.19.2
  • 1.19.4
  • 1.20.1
  • 1.20.2
  • 1.20.3

判断 NBT 节点是否存在

yaml
condition:
  - "hasnbt('lyfj.a.b.c')"

取反后表示该节点不能存在:

yaml
condition:
  - "!hasnbt('lyfj.a.b.c')"

hasnbt() 只接受一个单引号字符串参数。

匹配 NBT 值

nbt() 的 NBT 节点必须存在,否则条件不会成立。读取到的最终节点值会以字符串形式参与比较。

写法说明
nbt('lyfj.a.b.c', 'sword')完整匹配字符串,默认使用 equals
nbt('lyfj.attribute.level', 5)将节点值作为字符串与数字文本 5 完整匹配
nbt('lyfj.a.b.c', 'sword', equals)显式完整匹配
nbt('lyfj.a.b.c', 'bound', !=)节点值不等于指定内容
nbt('lyfj.a.b.c', 'swo', contains)节点值包含指定内容
nbt('lyfj.a.b.c', 'sword', startsWith)节点值以指定内容开头
nbt('lyfj.a.b.c', 'sword', endsWith)节点值以指定内容结尾
nbt('lyfj.a.b.c', 'SWORD', equals, ignoreCase)忽略英文大小写完整匹配
nbt('lyfj.attribute.level', 5, >)节点数值大于 5
nbt('lyfj.attribute.level', 5, >=)节点数值大于等于 5
nbt('lyfj.attribute.level', 10, <)节点数值小于 10
nbt('lyfj.attribute.level', 10, <=)节点数值小于等于 10

>>=<<= 只有在实际值和目标值都能转换为数字时才会成立。

字符串目标值必须使用单引号包裹。不加引号的目标值必须是有效数字。

yaml
condition:
  - "hasnbt('lyfj.attribute.level')"
  - "nbt('lyfj.attribute.level', 5, >=)"
  - "nbt('lyfj.attribute.type', 'SWORD', equals, ignoreCase)"

分解产物

基础格式

每条产物至少包含物品标识、数量和概率:

text
物品库@物品ID 数量 概率
部分说明
物品库@物品ID指定产物来源物品库及其内部物品 ID
数量正整数固定数量,或 最小值-最大值
概率01 之间的出现概率
yaml
result:
  - 'MythicMobs@分解产物1 1-2 0.5'
  - 'MythicMobs@分解产物2 2 1'

上例中:

  • 分解产物10.5 的概率生成,数量在 12 之间随机。
  • 分解产物2 必定生成,固定数量为 2
  • 每条产物独立进行概率判断。
  • 概率为 0 时不会生成,概率为 1 时必定生成。

数量范围的最小值必须大于 0,最大值必须大于等于最小值。

产物命令

可以从第四段开始为产物追加命令。每条命令必须分别放在一组 {} 中:

text
物品库@物品ID 数量 概率 {命令1} {命令2}
yaml
result:
  - 'MythicMobs@分解产物1 1-2 0.5 {[console]say %player_name% 获得了分解产物1} {say 产物已经发放}'

产物命令具有以下规则:

  • 只有当前产物通过概率判断并完成发放后才会执行。
  • 同一产物的多条命令按填写顺序执行。
  • 支持 [console][op] 和无前缀玩家身份。
  • 支持 PlaceholderAPI 变量替换。
  • 单条产物未抽中时,其产物命令不会执行。
  • 产物命令执行异常会记录为警告,不会撤回已经发放的产物。

产物命令与规则级 commands 的触发范围不同。产物命令只属于当前抽中的产物,规则命令属于整条匹配规则。

可用物品库前缀

规则产物支持以下物品库名称:

前缀对应物品库
MythicMobsMythicMobs 4 或 MythicMobs 5
LyItemSaveLyItemSave 提供的 MythicMobs 4 兼容接口
AzureFlowAzureFlow
NeonFlashNeonFlash
SX-ItemSX-Item
NeigeItemsNeigeItems
OriginAttributeOriginAttribute

MythicMobsLyItemSave 两个名称互通。当 MythicMobs 或 LyItemSave 任意一个可用时,这两个前缀都会指向当前实际连接的兼容物品库。

如果 MythicMobs 已启用,插件会根据其版本选择 MythicMobs 4 或 MythicMobs 5 适配器。如果 MythicMobs 不可用但 LyItemSave 已启用,则使用 LyItemSave 提供的 MythicMobs 4 兼容接口。

物品库名称查找不区分英文大小写。

如果产物 ID 没有填写 物品库@ 前缀,插件会使用主配置中的 item-provider。当 item-provider 为空或缺失时,默认使用 MythicMobs

yaml
result:
  # 使用主配置指定的默认物品库
  - '分解材料 1 1'

  # 明确指定物品库
  - 'NeigeItems@分解材料 1-3 0.25'

规则重载时会检查产物对应的物品库适配器是否可用。物品库未安装、未启用或初始化失败时,本次重载不会替换当前运行数据。

物品库可用不代表内部物品 ID 一定存在。产物 ID 无法创建时,预览会跳过或报告该产物,实际抽中该产物时分解执行会失败。

产物发放顺序

产物生成后,会按照主配置 delivery-order 中的顺序依次尝试发放:

配置值发放目标
inventory玩家背包
LyLootsWarehouseLyLootsWareHouse 战利品仓库
LyWarehouseLyWarehouse
SpaceRingPlusYeeCore 提供的灵魂空间
StarStorageStarStorage

当前目标不能完全接收时,剩余数量会继续尝试下一个目标。未安装或未启用的外部仓库无法接收物品。全部目标处理后仍有剩余时,剩余产物会掉落在玩家位置。

delivery-order 留空时仅尝试玩家背包,背包无法容纳的剩余产物会掉落在玩家位置。

产物的具体入库顺序由主配置管理,不需要写入规则文件。

规则命令

commands 中的规则命令会在全部产物生成和发放流程后,按照规则加载顺序与列表配置顺序执行。

格式执行身份
[console]命令控制台
[op]命令玩家临时获得 OP 后执行,完成后恢复原状态
命令玩家
yaml
commands:
  - '[console]say %player_name% 完成了一次分解'
  - '[op]say %player_name% 触发了临时OP命令'
  - 'say 我完成了一次分解'

命令支持 PlaceholderAPI 变量替换。未安装或未启用 PlaceholderAPI 时,非 papi() 条件中的命令仍可执行,但其中的变量会保留原文。

[console][op] 前缀匹配时不区分英文大小写。命令中不要填写开头的 /

[op] 会临时修改玩家的 OP 状态,并在执行完成后恢复玩家原来的状态。能够使用控制台或普通玩家身份完成时,不建议使用该方式。

单条规则命令执行异常会作为警告记录,不会撤回已经发放的产物,也不会将成功结果改为失败。

执行顺序

单个输入物品匹配成功后的主要执行顺序如下:

  1. 收集全部匹配规则。
  2. 触发分解前置事件,外部插件可以取消本次分解。
  3. 对所有启用产物的匹配规则逐条进行概率判断并生成产物。
  4. delivery-order 发放每项实际生成的产物。
  5. 每项产物发放后执行该产物配置的 {命令}
  6. 全部产物处理后执行所有匹配规则的 commands
  7. 触发分解完成事件。
  8. 调用方确认执行成功后扣除一个输入物品。

如果产物配置或物品创建在生成阶段失败,本次执行不会成功,界面不会扣除当前输入物品。产物发放开始后的命令异常只会记录警告,不会回滚已经完成的发放。

纯命令规则

如果规则只需要执行命令,不需要发放物品,可以关闭 give-item 并省略 result

yaml
'纯命令规则':
  condition:
    - "name('&e特殊物品')"
  give-item: false
  commands:
    - '[console]say %player_name% 分解了特殊物品'

condition 仍然必须至少填写一行。物品匹配成功后,这类规则可以与其它产物规则叠加执行。

旧版规则转换说明

插件包含从旧版 LyDecompositionReload 配置转换为当前规则格式的功能。转换来源包括:

  • plugins/LyDecompositionReload/config.yml 中的 decomposition-set
  • plugins/LyDecompositionReload/extra 目录及子目录中的 .yml 文件。

转换结果会写入当前插件的:

text
rule/旧版转换/旧版配置转换.yml

转换时会进行以下处理:

  • 转换后的规则 ID 添加 旧版_ 前缀。
  • 规则 ID 中的英文点 . 会替换为全角点 ,避免被 YAML 配置路径拆分。
  • 旧版无物品库前缀的产物会补充 MythicMobs@
  • 旧版百分比概率会转换为 01 的概率。
  • 旧版 %p 玩家变量会转换为 %player_name%
  • 旧版 [player] 规则命令会转换为无前缀玩家命令。
  • 旧版无执行身份前缀的产物命令会按旧行为转换为 [console] 命令。
  • 覆盖已有转换文件前会创建固定 .bak 备份。
  • 转换文件明确使用 UTF-8 无 BOM 写入。

旧版转换生成的规则仍需要通过当前规则的完整校验后才能生效。

严格校验

插件重载时会校验主配置、全局条件、规则、产物、额外按钮和外部适配器。存在阻止加载的错误时,本次重载不会替换当前正在运行的数据。

以下问题会导致规则重载失败:

  • YAML 格式错误或文件无法读取。
  • 不同文件中存在重复的规则 ID。
  • 规则包含 conditiongive-itemcommandsresult 之外的字段。
  • 规则没有至少一行 condition
  • 条件函数名称、括号、单引号或基础格式错误。
  • 使用 papi(),但 PlaceholderAPI 未安装或未启用。
  • 使用 NBT 条件,但当前服务端没有可用的 NBT 适配器。
  • result 的物品标识、数量、概率或产物命令格式无效。
  • 产物使用的物品库未安装、未启用或适配器初始化失败。

以下情况只会产生警告或运行时结果:

  • give-item: true 但没有配置 result,重载时只输出警告。
  • 物品库已连接但具体产物 ID 不存在,通常在预览或实际生成产物时发现。
  • 产物最终无法进入任何配置目标,剩余物品会掉落在玩家位置并记录警告。
  • 产物命令或规则命令执行异常,会记录警告,不会回滚已经完成的产物发放。

重载失败后,需要根据控制台输出修正规则,再执行插件重载指令。旧的运行数据会继续保留,不会被本次失败的配置覆盖。