-
Notifications
You must be signed in to change notification settings - Fork 0
Script Engine
Noogear edited this page Mar 11, 2026
·
4 revisions
GloomLib Script — 高性能声明式 YAML 脚本引擎。
| 节点 | 说明 |
|---|---|
| 条件判断 check | 条件判断,满足则继续,不满足执行 on_fail
|
| 动作调用 action | 调用已注册的动作 |
| 返回值 return | 返回值并终止脚本 |
| 多分支 switch | 按变量值选择执行分支 |
| 数学运算 math | 数学表达式求值并存储结果 |
| 复合条件 any / all | OR / AND 复合条件组合 |
| 集合操作 collect | 集合遍历、筛选与聚合 |
| 操作符参考 | 所有操作符的完整列表 |
| 数学表达式 | 表达式语法、函数与运算符优先级 |
id: "my-script" # 脚本标识符(可选,默认 AnonymousScript)
event: "com.example.MyEvent" # 必填,事件/载荷类的全限定名
priority: 0 # 可选,事件优先级(默认 0)
ignore-cancelled: true # 可选,已取消事件是否跳过(默认 true)
variables:
# ...
flow:
# ...| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
id |
String | 否 | AnonymousScript |
脚本唯一标识,用于日志和错误追踪 |
event |
String | 是 | — | 载荷类全限定名 |
priority |
Integer | 否 | 0 |
事件监听优先级 |
ignore-cancelled |
boolean | 否 | true |
true 时已被取消的事件不触发脚本 |
variables |
Map | 否 | {} |
变量声明映射 |
flow |
List | 否 | [] |
流程节点列表 |
将载荷对象的属性映射为脚本变量。
variables:
# 简单属性:调用 event.getDamage()
damage: "damage"
# 链式属性:event.getEntity().getName()
entityName: "entity.name"
# 集合索引:event.getPlayer().getInventory().get(0)
firstItem: "player.inventory[0]"
# Map 索引:event.getMetadata().get("key")
metaValue: "metadata[key]"
quotedKey: "metadata['damage_all']"
# payload 别名:直接引用载荷对象本身
event: "$self"| 语法 | 示例 | 解析方式 |
|---|---|---|
| 简单属性 | damage |
调用 getDamage() 或 damage()
|
| 链式属性 | entity.name |
依次调用 getEntity() → getName()
|
| List 索引 | inventory[0] |
调用 getInventory() → List.get(0)
|
| Map 索引 | metadata[key] |
调用 getMetadata() → Map.get("key")
|
| payload 别名 | $self |
直接引用载荷对象 |
-
getXxx()— 标准 Java Bean getter -
isXxx()— boolean getter -
xxx()— Record 风格 accessor
flow 是一个有序列表,引擎按顺序执行每个节点。共支持 8 种节点类型:
| 类型 | YAML 触发键 | 说明 | 详细参考 |
|---|---|---|---|
| CHECK | check |
条件判断 | 详情 |
| ACTION |
action 或动态推断 |
调用已注册动作 | 详情 |
| RETURN | return |
返回值并终止 | 详情 |
| SWITCH | switch |
多分支选择 | 详情 |
| MATH | math |
数学表达式求值 | 详情 |
| ANY | any |
OR 复合条件 | 详情 |
| ALL | all |
AND 复合条件 | 详情 |
| COLLECT | collect |
集合遍历与筛选 | 详情 |
节点类型通过触发键自动推断,无需显式声明 type 字段。
使用 {变量名} 语法在字符串中插入变量值。
# 单变量引用
args: ["{damage}"]
# 多变量模板
args: ["玩家 {playerName} 受到 {damage} 点伤害"]
# 链式属性引用
args: ["{entity.name}"]
# return 中使用模板
- return: "HP:{hp} DMG:{damage}"属性路径支持多级嵌套:
player.inventory[0].amount
│ │ │ └── getAmount() → int
│ │ └──────── List.get(0) → ItemStack
│ └─────────────── getInventory() → List<ItemStack>
└─────────────────────── getPlayer() → Player
| 类型 | 语法 | 说明 |
|---|---|---|
| 属性访问 | property |
标准 getter 调用 |
| List 索引 | list[index] |
List.get(int) |
| Map 索引 | map[key] |
Map.get(String),支持引号包裹 key |
id: "damage-indicator"
event: "org.bukkit.event.entity.EntityDamageByEntityEvent"
priority: 3
variables:
target: "entity"
source: "damager"
value: "finalDamage"
cause: "cause"
critical: "critical"
flow:
- check: target
op: "instanceof"
value: "org.bukkit.entity.LivingEntity"
- check: value
op: ">"
value: 0
- check: critical
op: "!="
value: true
on_fail:
- showIndicator: ["{target}", "{source}", "{value}", "CRITICAL"]
- return
- showIndicator: ["{target}", "{source}", "{value}", "{cause.name}"]id: "pvp-guard"
event: "org.bukkit.event.entity.EntityDamageByEntityEvent"
variables:
damage: "damage"
entity: "entity"
weapon: "damager.itemInMainHand.type.name"
flow:
- all:
- check: damage
op: ">"
value: 5
- check: weapon
op: "in"
value: ["DIAMOND_SWORD", "IRON_SWORD", "NETHERITE_SWORD"]
- check: entity
op: "!null"
on_fail:
- return
- any:
- check: damage
op: "between"
value: [100, 999]
- check: weapon
op: "starts_with"
value: "NETHERITE"
- showIndicator: ["{entity}", "{entity}", "{damage}", "SPECIAL"]id: "rpg-damage"
event: "com.example.CombatEvent"
variables:
attack: "attacker.attack"
defense: "target.defense"
level: "attacker.level"
weaponType: "weapon.type"
flow:
- math: "clamp({attack} * (1 + {level} * 0.05) - {defense} * 0.3, 1, 99999)"
store: "finalDmg"
- switch: weaponType
cases:
SWORD:
- math: "{finalDmg} * 1.2"
store: "finalDmg"
BOW:
- math: "{finalDmg} * 0.9"
store: "finalDmg"
- action: "applyDamage"
args: ["{finalDmg}"]id: "inventory-check"
event: "com.example.TradeEvent"
variables:
items: "player.inventory"
flow:
# 必须存在稀有物品
- collect: items
op: exists
match:
- check: "$it"
op: "contains"
value: "rare"
on_fail:
- action: "sendMessage"
args: ["背包中没有稀有物品"]
- return
# 统计匹配数量
- collect: items
op: count
store: "rareCount"
match:
- check: "$it"
op: "contains"
value: "rare"
- action: "log"
args: ["找到 {rareCount} 个稀有物品"]