触发节点
触发节点用于定义事件触发条件、物品槽位、名称与 Lore 匹配、权限条件、触发几率、物品扣除、冷却、指令和提示消息。节点可以绑定一个或多个槽位,也可以不绑定物品,仅根据事件、权限和变量条件触发。
插件会读取主配置文件 config.yml 中的 config 节点,并递归读取插件目录 extra 文件夹及其子文件夹内的全部 .yml 文件。
每个触发节点都使用以下结构:
yaml
config:
节点ID:
event:
- "right"节点 ID 在全部配置文件中共用。出现重复 ID 时,后加载的节点会覆盖此前注册的同名节点,因此应保证每个节点 ID 唯一。
触发流程
节点收到事件后,按以下流程进行判断:
- 检查节点是否存在,并确认玩家冷却数据已经加载。
- 检查当前事件是否匹配节点的
event;强制触发事件force会跳过此项限制。 - 按
plugin-slot顺序查找第一个名称和 Lore 均匹配的物品。 - 检查
permission、nopermission和condition。 - 检查
cd-team对应的冷却时间。 - 根据
fail-take决定先扣除物品还是先进行几率判定。 - 几率成功后写入冷却,执行普通指令和权重指令,并发送成功消息。
- 同一次事件中,将成功节点的
mutual-exclusion-group标记为已触发,跳过后续同组节点。
当 plugin-slot 未配置或为空列表时,插件不会检查物品,节点可以只使用事件、权限和 PlaceholderAPI 条件触发。此时没有可扣除的物品,take 和 take-all 不会产生效果。
槽位来源
yaml
plugin-slot:
- "Origin#MainHand"插件会按照列表顺序检查槽位,并使用第一个同时满足名称与 Lore 条件的槽位。后续的 Lore 数值提取和物品扣除也以该槽位为准。
| 格式 | 说明 |
|---|---|
DragonCore#槽位名 | DragonCore 槽位 |
GermPlugin#槽位名 | GermPlugin 槽位 |
APInventory#分页ID#槽位ID | APInventory 分页槽位 |
LyInventory#背包ID#类型 | LyInventory 背包槽位 |
LyInventoryReload#背包ID#类型 | LyInventoryReload 背包槽位 |
YeeJewelry#背包ID#槽位ID | YeeJewelry 饰品背包槽位 |
PXRPG#类型#背包ID#槽位 | PXRPG 装备容器槽位 |
Origin#MainHand | 原版主手 |
Origin#OffHand | 原版副手 |
Origin#Helmet | 原版头盔 |
Origin#ChestPlate | 原版胸甲 |
Origin#Legging | 原版护腿 |
Origin#Boots | 原版靴子 |
Origin2#MainHand | 使用旧版 Bukkit 接口读取主手 |
Minecraft#槽位ID | 原版玩家背包槽位 |
使用外部背包槽位时,必须安装对应插件并确保其接口可用。plugin.yml 仅将 GermPlugin 和 DragonCore 声明为软依赖,其他槽位来源同样依赖项目中对应插件提供的 API。
PXRPG 槽位可以用于物品读取和数量获取,但现有扣除代码没有调用装备容器的写回接口,不应依赖 take 或 take-all 修改 PXRPG 槽位中的物品。
名称与 Lore 匹配
yaml
name: "equals@名称"
lore:
- "contain@特殊说明"名称与 Lore 配置中的 & 会在节点加载时转换为 Minecraft 颜色符号。
名称匹配
| 写法 | 匹配方式 |
|---|---|
equals@文本 | 物品显示名称必须与文本完全相同 |
contain@文本 | 物品显示名称必须包含文本 |
文本 | 默认按照包含文本处理 |
未配置 name 或配置为空字符串时,不限制物品名称。没有自定义显示名称的物品会使用空字符串参与匹配。
Lore 匹配
| 写法 | 匹配方式 |
|---|---|
equals@文本 | 任意一行 Lore 与文本完全相同 |
contain@文本 | 任意一行 Lore 包含文本 |
文本 | 默认检查任意一行 Lore 是否包含文本 |
lore 中的配置项是“任意匹配”关系:任意一项规则匹配任意一行 Lore,整个 Lore 条件就会通过,并不要求配置的全部 Lore 同时存在。
未配置 lore 或配置为空列表时,不限制物品 Lore。
Lore 数值提取
lore-placeholder 可以从匹配物品的 Lore 中提取数字。规则中的 <value> 表示数字所在位置,必须放在行内代码或 YAML 字符串中。
yaml
lore-placeholder:
力量: "力量+<value>"
暴击率: "暴击率:<value>%"例如物品 Lore 包含 力量+25 时,会生成名为 力量、值为 25 的节点内部变量。
| 写法 | 说明 |
|---|---|
{v.力量} | 默认按无小数格式输出 |
{v.力量~%.1f} | 使用 Java String.format 格式输出,此处保留一位小数 |
提取规则如下:
<value>左侧文本必须出现在 Lore 行中。<value>右侧存在文本时,提取左右文本之间的内容。<value>位于规则末尾时,提取左侧文本之后直到 Lore 行末尾的内容。- 提取内容必须能够转换为数字。
- 某个变量没有成功提取时,其默认值为
0。 - 同一变量匹配到多行有效 Lore 时,现有实现会保留最后一次成功解析的值,不会累加。
- 只从第一个通过槽位、名称和 Lore 检查的物品中提取数值。
Lore 变量可以用于 commands、weight-command、condition 和 cd。格式化写法 {v.变量名~格式} 仅用于指令和条件;cd 应使用普通写法 {v.变量名}。
权限条件
yaml
permission:
- "lilc.use"
nopermission:
- "lilc.block"| 配置项 | 说明 |
|---|---|
permission | 玩家必须拥有列表内全部权限 |
nopermission | 玩家不能拥有列表内任意权限 |
permission、nopermission 未配置或为空列表时,不执行对应检查。
当任意权限条件不满足时,节点停止执行,并发送 condition-or-permission-match-failed-message。
变量条件
yaml
condition:
- "%player_level% > 0"
- "{v.力量} >= 20"每项条件会先替换 Lore 变量,再通过 PlaceholderAPI 处理占位符。列表内全部条件都成立时才会继续触发。
| 类型 | 示例 |
|---|---|
| 大于 | %player_level% > 10 |
| 大于等于 | %player_level% >= 10 |
| 小于 | %player_level% < 10 |
| 小于等于 | %player_level% <= 10 |
| 相等 | %player_level% == 10 |
| 不相等 | %player_level% != 10 |
| 逻辑与 | %player_level% > 0 && %player_health% > 0 |
| 逻辑或 | `%player_level% > 10 |
| 数学运算 | %player_level% + 5 > 10 |
| 字符串相等 | "%player_world%" == "world" |
| 字符串不等 | "%player_world%" != "world_nether" |
| 布尔值 | %某个变量% 替换后为 true |
数学表达式支持整数、小数、+、-、*、/ 和括号。字符串比较建议给两侧都添加单引号或双引号。
Lore 变量可以参与运算:
yaml
condition:
- "{v.力量} + %player_level% > 30"
- "{v.暴击率~%.1f} >= 12.5"未配置 condition 或配置为空列表时,不执行变量条件检查。条件失败时发送 condition-or-permission-match-failed-message。
触发事件
yaml
event:
- "right"节点只有在 event 列表中包含当前事件时才会触发。事件字符串比较不区分大小写。未配置事件或配置为空列表时,节点只能通过 API 或 /lilc use 使用 force 事件强制尝试触发。
基础事件
| 事件 | 触发时机 |
|---|---|
move | 玩家移动到另一格方块时;仅改变视角或在同一方块内移动不会触发 |
attack | 玩家对实体造成伤害时 |
damaged | 玩家受到实体伤害时 |
tick | 定时检测在线玩家,重载后每 20 Tick 执行一次 |
sprint | 玩家开始奔跑时 |
sneak | 玩家开始蹲下时 |
death | 玩家死亡时 |
respawn | 玩家重生时 |
kill | 玩家击杀实体时 |
break | 玩家破坏任意方块时 |
place | 玩家放置任意方块时 |
consume | 玩家完成食用或饮用物品时 |
left | 玩家未蹲下时左键点击空气或方块 |
right | 玩家未蹲下时右键点击空气或方块 |
shiftlet | 玩家蹲下时左键点击空气或方块 |
shiftright | 玩家蹲下时右键点击空气或方块 |
psd_cast | PxSkillDrive 技能释放事件 |
配置示例的注释使用 shiftleft,但当前监听代码实际发送的蹲下左键事件是 shiftlet。需要配置 shiftlet 才能匹配该事件;event-trigger-interval 中对应的间隔键仍然是 shiftleft。
普通 right 和 shiftright 由方块或空气交互事件触发。右键实体时,实体监听器只发送带目标名称或类型的事件,不会同时发送普通 right 或 shiftright。
指定方块事件
yaml
event:
- "break:STONE"
- "place:CHEST"| 写法 | 说明 |
|---|---|
break:方块类型 | 破坏指定类型的方块 |
place:方块类型 | 放置指定类型的方块 |
方块类型使用 Bukkit 的类型名称,例如 STONE、CHEST。插件会同时发送普通事件和指定方块事件,因此 break 与 break:STONE 可以分别匹配。
指定目标名称事件
yaml
event:
- "attack:僵尸王"
- "kill:僵尸王"
- "right:商店管理员"| 写法 | 说明 |
|---|---|
attack:目标名称 | 攻击指定名称的实体 |
damaged:目标名称 | 被指定名称的实体攻击 |
kill:目标名称 | 击杀指定名称的实体 |
right:目标名称 | 未蹲下时右键指定名称的实体 |
shiftright:目标名称 | 蹲下时右键指定名称的实体 |
实体存在自定义名称时优先使用自定义名称。没有自定义名称时,通常使用 Bukkit 实体类型名称;在 Bukkit 1.7.10 环境中会通过对应的旧版实体名称接口读取。
事件使用完整字符串匹配,不支持名称包含匹配。实体名称中的颜色符号也属于名称内容,配置时需要保持一致。
指定实体类型事件
yaml
event:
- "attack_type:ZOMBIE"
- "kill_type:PLAYER"| 写法 | 说明 |
|---|---|
attack_type:类型 | 攻击指定实体类型 |
kill_type:类型 | 击杀指定实体类型 |
right_type:类型 | 未蹲下时右键指定实体类型 |
shiftright_type:类型 | 蹲下时右键指定实体类型 |
damaged_type:PLAYER | 玩家受到实体伤害时匹配当前实现传入的类型 |
实体类型使用 Bukkit 类型名称,例如 PLAYER、PIG、ZOMBIE。
当前 damaged_type 的实现读取的是受伤玩家自身类型,而不是攻击者类型,因此实际传入值为 PLAYER。不要使用 damaged_type:ZOMBIE 等配置判断攻击者类型;需要判断攻击者时使用 damaged:目标名称,或等待插件修正此行为。
外部按键事件
yaml
register-keys:
- "KEY_Z"
config:
按键节点:
event:
- "GermPlugin#KEY_Z"| 事件写法 | 说明 |
|---|---|
GermPlugin#按键 | GermPlugin 松开按键事件 |
DragonCore#按键 | DragonCore 按键事件 |
只有对应插件已经启用时,相关监听器才会注册。
插件会把 register-keys 中的每一项同时交给 DragonCore 和 GermPlugin 的注册接口。GermPlugin 使用 KEY_Z 一类的 KeyType 名称;DragonCore 事件则按其返回的按键名称组成 DragonCore#按键。同时安装两个按键插件时,应确保注册列表中的值能够被对应接口接受。
psd_cast 监听器仅在 PxSkillDrive 已启用时注册。
强制触发
插件 API 和 /lilc use 命令可以使用 force 事件强制尝试触发节点。
text
/lilc use 玩家 节点IDforce 只会跳过节点的 event 列表限制,以下检查仍然执行:
- 玩家冷却数据是否已经加载。
- 槽位、物品名称和 Lore 是否匹配。
permission和nopermission。condition。- 冷却、几率与扣除逻辑。
- 互斥组仅在通过统一节点遍历器触发时生效;直接调用单个节点 API 不处理其他节点的互斥关系。
/lilc use 只能由 OP 执行,目标玩家必须在线,节点必须已经成功加载。
执行指令
yaml
commands:
- "[console]tell %p 触发成功"
- "[op]say %player_name% 使用了道具"
- "[player]spawn"节点成功触发后,会执行 commands 列表中的全部指令。
| 前缀 | 执行身份 |
|---|---|
[console] | 控制台执行 |
[op] | 临时赋予玩家 OP 后执行,完成后恢复玩家原有 OP 状态 |
[player] | 玩家身份执行 |
只有包含以上前缀之一的配置项才会进入对应的指令执行分支。前缀会从整条字符串中移除,不需要在指令开头添加 /。
指令替换内容
| 内容 | 说明 |
|---|---|
%p | 当前玩家名称 |
| PlaceholderAPI 变量 | 例如 %player_name%,需要 PlaceholderAPI 提供对应变量 |
{amount} | 本次通过 take-all 取得的匹配槽位物品数量 |
{v.变量名} | Lore 数值变量,默认按无小数格式输出 |
{v.变量名~格式} | Lore 数值变量,按照指定的 String.format 格式输出 |
替换顺序为 {amount}、Lore 数值变量、PlaceholderAPI 变量、%p,之后再根据身份前缀执行。
未使用 take-all、没有匹配槽位或槽位数量读取失败时,{amount} 为 0。普通 take: true 扣除一个物品时不会把扣除数量写为 1。
权重指令
yaml
weight-command:
权重组1:
- "30#[console]tell %player_name% 抽中了第一项"
- "70#[console]tell %player_name% 抽中了第二项"每个权重组会独立随机选择一项。配置格式为:
text
整数权重#带身份前缀的指令同一结果中可以使用多个 # 串联指令:
yaml
weight-command:
权重组1:
- "100#[console]tell %p 第一条#[player]spawn"权重指令支持与普通指令相同的 {amount}、Lore 变量、PlaceholderAPI 变量、%p 和身份前缀。
注意事项:
- 权重必须是能够解析为整数的文本。
- 每个权重组独立抽取一次结果。
- 每项的实际概率由该项权重占组内总权重的比例决定,不要求总和为
100。 - 同一结果中的每条指令都要携带自己的执行身份前缀。
- 普通
commands会先加入执行流程,随后处理各个权重组。
几率与物品扣除
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
chance | 小数 | 1 | 触发几率,配置示例约定使用 0 至 1 |
take | 布尔值 | false | 扣除匹配槽位中的一个物品 |
take-all | 布尔值 | false | 扣除匹配槽位中的全部物品,并记录原数量到 {amount} |
fail-take | 布尔值 | true | 是否在几率判定之前执行扣除 |
take-all 和 take 同时为 true 时,优先执行 take-all。
fail-take: true
执行顺序为:
- 扣除物品。
- 进行
chance几率判定。 - 几率失败时发送
fail-message并结束。 - 几率成功时写入冷却、执行指令并发送成功消息。
因此,fail-take: true 表示几率失败也会保留已经发生的物品扣除。
fail-take: false
执行顺序为:
- 进行
chance几率判定。 - 几率失败时发送
fail-message,不扣除物品。 - 几率成功时写入冷却。
- 扣除物品、执行指令并发送成功消息。
冷却
yaml
cd: "10"
cd-team: "冷却组"
cd-message: "还有%time秒才可以使用该物品!"| 配置项 | 默认值 | 说明 |
|---|---|---|
cd | 0 | 冷却秒数,支持 PlaceholderAPI、Lore 变量和数学表达式 |
cd-team | 默认 | 冷却组名称,同一玩家的相同冷却组共享结束时间 |
cd-message | 空字符串 | 冷却未结束时发送的消息,支持 %time |
message | 空列表 | 成功触发后发送的消息列表 |
fail-message | 空字符串 | 几率判定失败时发送的单条消息 |
condition-or-permission-match-failed-message | 空字符串 | 权限或条件不满足时发送的单条消息 |
fail-message 和 condition-or-permission-match-failed-message 在代码中按照单个字符串读取,不应配置为 YAML 列表。
cd 支持 +、-、*、/ 和括号:
yaml
cd: "%player_level% / 2 + {v.力量}"冷却时间会先处理 PlaceholderAPI 变量,再将普通 Lore 变量 {v.变量名} 替换为保留一位小数的数值,最后计算表达式。
消息替换内容如下:
| 消息配置 | 可用内容 | 说明 |
|---|---|---|
cd-message | %time | 当前剩余冷却时间 |
message | %cd-team | 当前节点的冷却组名称 |
message | %time | 本次写入的冷却时间 |
fail-message | %cd-team | 当前节点的冷却组名称 |
countdown-format 决定 %time 的输出格式:
| 配置值 | 格式 |
|---|---|
true | mm:ss,秒数会截取为整数 |
false | 保留一位小数的秒数 |
冷却按照玩家 UUID 和 cd-team 存储。不同节点填写相同 cd-team 时会共享冷却;填写不同冷却组时互不影响。
互斥组
yaml
mutual-exclusion-group: "技能组"同一次事件遍历中,同一互斥组只允许第一个成功触发的节点继续生效。某个节点成功后,后续属于相同互斥组的节点会跳过本次触发尝试。
| 配置值 | 效果 |
|---|---|
| 未配置或空字符串 | 不参与互斥 |
| 多个节点填写相同字符串 | 同一次事件中相互排斥 |
| 节点填写不同字符串 | 不同组之间互不影响 |
只有成功完成节点流程的节点才会阻止后续同组节点。因物品、权限、条件、冷却或几率失败的节点不会锁定互斥组。
节点存储使用并发映射,遍历顺序没有明确保证。不要依赖配置文件中的书写顺序决定同一互斥组中哪个节点优先成功,应通过互不重叠的条件控制节点匹配范围。
互斥状态只在当前一次事件处理中有效,不会写入数据文件,也不会影响下一次事件。
事件触发间隔
主配置中的 event-trigger-interval 用于限制部分点击事件的触发频率,单位为毫秒:
yaml
event-trigger-interval:
left: 200
right: 200
shiftleft: 200
shiftright: 200| 配置项 | 实际限制的事件 |
|---|---|
left | 未蹲下左键空气或方块 |
right | 未蹲下右键空气或方块 |
shiftleft | 蹲下左键空气或方块,实际触发事件名为 shiftlet |
shiftright | 蹲下右键空气或方块 |
插件会加载 event-trigger-interval 下的任意键,但当前只有上述四个键在事件监听器中执行间隔检查。
默认配置中存在 move: 500,但当前移动事件监听器没有调用间隔检查,因此该配置不会限制 move。右键实体事件同样不经过此间隔检查。
间隔计时会在点击事件尝试触发节点之前写入。即使本次没有节点成功,下一次相同点击事件仍需等待间隔结束。
当任意点击节点成功时,对应 Bukkit 交互事件会被取消。右键事件建议配置触发间隔或节点冷却,避免一次交互产生重复尝试。
冷却数据保存
未启用 MySQL 时,玩家冷却数据保存在:
text
plugins/LyItemLoreCommand/data/玩家UUID.yml数据以 cd-group 保存各冷却组的结束时间。玩家加入时异步读取,退出时异步保存。保存过程会使用临时文件、上一份稳定数据备份和原子替换;主文件损坏时会尝试从 .bak 备份恢复。
玩家冷却数据尚未加载时,节点不会触发。
启用 MySQL 后,冷却组改为从数据库读取和保存,可用于跨服共享冷却状态:
yaml
mysql:
enable: true
databasename: mc2
username: mc2
password: mc1234
port: 3306
ip: 127.0.0.1MySQL 模式必须安装 LyMySQLCore,并且成功连接数据库后相关功能才会生效。启用 MySQL 但数据库尚未连接时,插件会阻止玩家进入服务器。
完整节点结构
以下示例汇总当前触发节点支持的配置项。未使用的配置可以删除,列表配置也可以设置为空列表。
yaml
config:
节点ID:
plugin-slot:
- "Minecraft#8"
name: "equals@名称"
lore:
- "contain@特殊说明"
lore-placeholder:
力量: "力量+<value>"
permission:
- "lilc.use"
nopermission:
- "lilc.block"
condition:
- "%player_level% > 0"
chance: 1
take: false
take-all: false
fail-take: true
event:
- "right"
commands:
- "[console]tell %p 触发成功"
weight-command:
权重组1:
- "100#[console]tell %p 权重触发"
message:
- "&7冷却组%cd-team进入了%time冷却"
fail-message: "&7本次几率判定失败"
condition-or-permission-match-failed-message: "&7权限或条件不满足"
cd-message: "&7还有%time才可以再次使用"
cd: "10"
cd-team: "冷却组"
mutual-exclusion-group: "技能组"配置项速查
| 配置项 | 类型 | 默认值 | 用途 |
|---|---|---|---|
plugin-slot | 字符串列表 | 空列表 | 指定物品检测槽位 |
name | 字符串 | 空字符串 | 匹配物品显示名称 |
lore | 字符串列表 | 空列表 | 匹配物品 Lore,任意规则成立即可 |
lore-placeholder | 键值映射 | 空映射 | 从 Lore 中提取数字变量 |
permission | 字符串列表 | 空列表 | 要求玩家拥有全部权限 |
nopermission | 字符串列表 | 空列表 | 要求玩家不拥有列表中的任何权限 |
condition | 字符串列表 | 空列表 | PlaceholderAPI 与 Lore 变量条件 |
chance | 小数 | 1 | 节点成功几率 |
take | 布尔值 | false | 扣除一个匹配物品 |
take-all | 布尔值 | false | 扣除匹配槽位中的全部物品 |
fail-take | 布尔值 | true | 是否在几率判定前扣除物品 |
event | 字符串列表 | 空列表 | 允许触发节点的事件 |
commands | 字符串列表 | 空列表 | 成功后执行的普通指令 |
weight-command | 分组列表 | 空 | 成功后按组随机执行的权重指令 |
message | 字符串列表 | 空列表 | 成功后发送的消息 |
fail-message | 字符串 | 空字符串 | 几率失败消息 |
condition-or-permission-match-failed-message | 字符串 | 空字符串 | 权限或条件失败消息 |
cd-message | 字符串 | 空字符串 | 冷却未结束消息 |
cd | 字符串 | 0 | 冷却秒数或计算表达式 |
cd-team | 字符串 | 默认 | 共享冷却的分组名称 |
mutual-exclusion-group | 字符串 | 空字符串 | 当前事件内的节点互斥分组 |