Skip to content

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 变量声明

将载荷对象的属性映射为脚本变量。

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 直接引用载荷对象

getter 查找优先级

  1. getXxx() — 标准 Java Bean getter
  2. isXxx() — boolean getter
  3. xxx() — Record 风格 accessor

flow 流程节点

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

完整示例

示例 1:伤害指示器

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}"]

示例 2:复合条件与失败回退

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"]

示例 3:数学计算与分支

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}"]

示例 4:集合筛选

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} 个稀有物品"]

Clone this wiki locally