Skip to content

EventPacket 事件引擎

功能定位-ArcartX-Suite的最具有学习意义的模块

通用触发器 + 动作链模块。当指定事件发生时,按顺序执行一组动作(发 UI 包、播字幕、执行命令、派发邮件、授予称号等)。支持多种触发器和结构化动作类型,覆盖服务端事件监听、客户端回包驱动、Chemdah 任务联动和脚本触发四大场景。每条规则还支持与 prop 模块一致的 conditions 条件判断,可先校验条件再决定是否执行动作。此外还内置了实体清理(ClearLag)定时命令两项服务端实用功能。

使用本模块可以提升你对ArcartX运用的上限,避免写脚本的情况下触发更多你想要的事件

注意

本模块已替代 ArcartX 社区的 ArcartXPacketCommand 附属插件功能,并完整覆盖了其权限校验、冷却、参数透传、<argN> / <uuid> / <world> 占位符等特性。具体使用方法请阅读 client-packet — 客户端回包触发

依赖

类型依赖作用缺少时表现
必需ArcartX接收 client-packet 触发器、提供内置 Aria 的 script-aria 触发器,执行 ui-packet / combateffect.play 等动作客户端回包触发、Aria 脚本触发与 UI 发包不可用
可选PlaceholderAPIplaceholder-* / papi-* 触发器这些触发器不生效,其余不受影响
可选MythicMobsmob-kill-count 按 MythicMob ID 过滤MythicMob 击杀过滤不可用
可选Chemdahquest-* / objective-* / chemdah-level-change 触发器Chemdah 相关触发器不生效
可选ArcartX-Suite 其他模块执行模块联动动作或接收模块信号仅影响引用了该模块的动作/信号

启用步骤

yaml
# config.yml
modules:
  eventpacket:
    enabled: true

配置结构(ArcartXEventPacket.yml

yaml
settings:
  refresh-interval-ticks: 20   # PAPI 轮询间隔(tick),默认 20(1秒)
  debug: false                 # 开启后每次动作执行会打印日志

storage:                       # 击杀计数 + 规则触发记录的数据库配置
  mode: sqlite                 # sqlite 或 mysql
  sqlite:
    file: "eventpacket.db"     # 位于 plugins/ArcartX-Suite/data/eventpacket/
  mysql:
    host: "127.0.0.1"
    port: 3306
    database: "ArcartX-Suite"
    username: "root"
    password: ""
  pool-size: 2                 # HikariCP 连接池最大连接数

packet-command:
  # 客户端 Packet.send 回包预设入口,随 EventPacket 一起加载。
  # 预设文件字段: type(op/console/player), permission, cooldown(秒, 如 5s/1m), allow-args, args-pattern, commands
  # 可用占位符: <player>, <uuid>, <world>, <arg1>, <arg2> ...
  enabled: true                          # 是否启用 client-packet 预设
  packet-id: "ArcartXEventPacket"        # 客户端发包匹配的 packetId
  presets-directory: "eventpacket/packet-command-presets"  # 预设文件目录

# 规则定义目录,相对模块数据目录。
# 目录下每个 *.yml 文件可包含多个规则,根键即为规则 ID。
rules-directory: "rules"

规则文件位于 data/eventpacket/rules/*.yml,同一文件可包含多条规则:

yaml
# data/eventpacket/rules/join.yml
join_welcome:
  enabled: true
  trigger: join
  repeatable: true
  actions:
    - type: subtitle.play
      group-id: "welcome"

first_join_guide:
  enabled: true
  trigger: first-join
  actions:
    - type: title.grant
      title-id: "newcomer"

规则通用字段

字段类型默认值说明
enabledbooleantrue是否启用该规则
triggerstring必填触发器类型
repeatablebooleanfalse是否可重复触发;false 时每玩家仅触发一次(记录持久化到数据库,重启后仍生效)
cooldownstring冷却时间,格式 10s / 5m / 2h / 1d / 500ms
conditionslist[]规则条件列表;全部通过后才会执行动作,语法见下方
actionslist必填动作列表,每个动作是一个 type + 参数的 Map

规则条件(conditions)

规则执行分为三层:conditions 是动作执行前的布尔门槛,必须全部通过;script-js / script-aria 是独立的脚本触发器,通过轮询结果的 false → true 边沿触发规则;actions 是触发后按顺序执行的结构化动作。EventPacket 没有 Menu 那种 aria: / js: 结构化动作类型,脚本主要用于条件和脚本触发器。语法与 条件系统(PAPI + Aria + JS) 一致。

PAPI 行内示例:

yaml
conditions:
  - "%player_level% >= 30"
  - "%axsloginview_account_type% == microsoft"

Aria 示例:

yaml
conditions:
  - "aria: return player.getLevel() >= 30"
  - type: aria
    script: "return player.hasPermission('eventpacket.boss.reward')"

支持的操作符:

操作符说明
== / !=字符串相等/不等,忽略大小写
> / < / >= / <=优先按数字比较;解析失败时回退到字符串比较
contains忽略大小写的包含判断
regex正则匹配,忽略大小写

执行时机

conditions 在规则匹配到触发器之后、动作执行之前统一检查,所以对 joinfirst-joinquitpapi-*mob-kill-countcommand-signalclient-packet 全部生效。


触发器详解

以下所有示例中的 rules: 前缀仅用于展示字段结构,实际上规则直接写在规则文件的根级(即 data/eventpacket/rules/*.yml 中,去掉 rules: 前缀,规则 ID 为根键)。

1. join — 玩家加入

玩家每次进入服务器时触发。

yaml
rules:
  join_welcome:
    enabled: true
    trigger: join
    repeatable: true
    actions:
      - type: subtitle.play
        group-id: "welcome_back"

无额外字段。


2. first-join — 首次加入

玩家首次进入服务器时触发(!player.hasPlayedBefore())。

yaml
rules:
  first_join_guide:
    enabled: true
    trigger: first-join
    repeatable: false
    actions:
      - type: subtitle.play
        group-id: "welcome_cinematic"
      - type: questgps.offer
        quest-id: "gps_main_newcomer"
        open-menu: true
      - type: command.dispatch
        executor: console
        command: "give {player_name} diamond 5"

无额外字段。通常搭配 repeatable: false 使用。


3. quit — 玩家退出

玩家退出服务器时触发。退出时玩家实体仍有效,可以向其他在线玩家发送 UI 包。

yaml
rules:
  quit_notify:
    enabled: true
    trigger: quit
    repeatable: true
    actions:
      - type: ui-packet
        ui-id: "party_hud"
        packet-handler: "memberQuit"
        recipients:
          - all-online
        pack:
          player: "{player_name}"
          time: "{timestamp_local}"

无额外字段。


4. placeholder-increase / papi-increase — PAPI 数值增长

指定 PAPI 占位符的数值增长时触发。服务端每 refresh-interval-ticks 轮询一次,比较前后值。

专属字段类型说明
placeholderstring完整 PAPI 占位符,如 %player_level%
require-non-emptyboolean是否要求新值非空(默认 false
yaml
rules:
  level_up_notify:
    enabled: true
    trigger: papi-increase
    placeholder: "%player_level%"
    require-non-empty: true
    repeatable: true
    cooldown: "3s"
    actions:
      - type: subtitle.play
        group-id: "level_up"
      - type: command.dispatch
        executor: console
        command: "say {player_name} 升级了!{old_number} → {new_number}"

可用上下文变量: {placeholder}{old_value}{new_value}{old_number}{new_number}{delta_number}{change_direction}(值为 increase)。


5. placeholder-decrease / papi-decrease — PAPI 数值减少

papi-increase 相同,但在数值减少时触发。

专属字段类型说明
placeholderstring完整 PAPI 占位符
require-non-emptyboolean是否要求新值非空
yaml
rules:
  health_drop_warning:
    enabled: true
    trigger: papi-decrease
    placeholder: "%player_health%"
    repeatable: true
    cooldown: "10s"
    actions:
      - type: ui-packet
        ui-id: "combat_hud"
        packet-handler: "healthWarning"
        pack:
          health: "{new_number}"
          delta: "{delta_number}"

可用上下文变量:papi-increase{change_direction} 值为 decrease


6. placeholder-threshold — PAPI 达到阈值

指定 PAPI 值首次从低于阈值升至 ≥ 阈值时触发(仅在跨越阈值时触发一次)。

专属字段类型说明
placeholderstring完整 PAPI 占位符
thresholdnumber目标阈值
require-non-emptyboolean是否要求新值非空
yaml
rules:
  level_30_unlock:
    enabled: true
    trigger: placeholder-threshold
    placeholder: "%player_level%"
    threshold: 30
    require-non-empty: true
    repeatable: false
    actions:
      - type: mail.send
        preset-id: "level_30_gift"
      - type: title.give
        title-id: "advanced_warrior"
        duration: "permanent"

可用上下文变量:papi-increase


7. mob-kill-count — 击杀计数

玩家击杀指定类型怪物(可包括玩家)累积满 N 次后触发。进度持久化到模块数据库(默认 SQLite,可切换 MySQL),重启不丢失。

专属字段类型说明
countint需要累积的击杀次数(默认 1
worldslist限定世界名(留空 = 不限)
entity-typeslist限定原版实体类型如 ZOMBIESKELETONPLAYER(留空 = 不限)
mythic-mob-idslist限定 MythicMobs 的 mob ID(留空 = 不限)
yaml
rules:
  zombie_dungeon_unlock:
    enabled: true
    trigger: mob-kill-count
    count: 50
    entity-types:
      - "ZOMBIE"
    worlds:
      - "world"
    repeatable: false
    actions:
      - type: questgps.offer
        quest-id: "gps_side_silk_trade"
        open-menu: true
      - type: subtitle.play
        group-id: "dungeon_unlock"

可用上下文变量: {rule_id}{kill_count}{required_count}{mob_world}{mob_entity_type}{mythic_mob_id}

过滤逻辑

worldsentity-typesmythic-mob-ids 三个列表是 AND 关系——只要配置了的列表就必须匹配;留空表示不限制。

击杀玩家计数

此触发器同样支持追踪击杀玩家。由于 PlayerDeathEvent 继承自 EntityDeathEvent,当玩家 A 击杀玩家 B 时,B 的实体类型为 PLAYER。只需配置 entity-types: [PLAYER] 即可实现累计击杀玩家 N 次后触发。

示例:累计击杀 10 名玩家授予称号

yaml
rules:
  pvp_hunter_title:
    enabled: true
    trigger: mob-kill-count
    count: 10
    entity-types:
      - "PLAYER"
    repeatable: false
    actions:
      - type: title.give
        title-id: "pvp_hunter"
        duration: "30d"
      - type: subtitle.play
        group-id: "pvp_achievement"

示例:每击杀 5 名玩家循环发送奖励

yaml
rules:
  pvp_streak_reward:
    enabled: true
    trigger: mob-kill-count
    count: 5
    entity-types:
      - "PLAYER"
    worlds:
      - "pvp_arena"
    repeatable: true
    cooldown: "30s"
    actions:
      - type: mail.send
        preset-id: "pvp_streak_reward"
      - type: command.dispatch
        executor: console
        commands:
          - "say {player} 在竞技场累计击杀 {kill_count} 名玩家!"

注意

  • entity-types: [PLAYER] 只追踪被其他玩家击杀的情况(entity.getKiller() 必须非空)。
  • 若同时配置了 mythic-mob-ids,玩家击杀不会匹配任何 MythicMob ID(始终为空),因此不要混用。
  • 进度存储在 EventPacket 模块数据库(默认 data/eventpacket/eventpacket.db SQLite,或 MySQL),表 eventpacket_kill_progress,主键 (player_uuid, rule_id)repeatable: false 的规则触发记录持久化在 eventpacket_fired_rules,服务器重启后不会重置。

8. command-signal — 命令信号

/axs eventpacket fire <信号名> <玩家> [key=value...] 手动触发,或由其他模块自动发射。

专属字段类型说明
signalstring要匹配的信号名称
yaml
rules:
  boss_celebration:
    enabled: true
    trigger: command-signal
    signal: "boss_settlement"
    repeatable: true
    cooldown: "3s"
    actions:
      - type: subtitle.play
        group-id: "boss_victory"
      - type: mail.send
        preset-id: "boss_reward_{boss_id}"
      - type: title.give
        title-id: "boss_slayer"
        duration: "7d"

可用上下文变量: {signal}{command_signal} + 信号携带的所有 key=value 自定义变量。

模块自动发射的信号

信号名来源模块触发时机携带变量
boss_settlementEntityTrackerBoss 死亡结算boss_id, boss_name, settlement_id, rank, damage, total_damage, participant_count
signin_successOnlineRewards签到成功streak, total, date, day_of_month
login_successLoginView登录成功auth_mode, account_type, account_type_display, account_premium
first_registerLoginView首次注册auth_mode, account_type, account_type_display, account_premium
premium_bypassLoginView微软正版 / LittleSkin 免登录进入服务器auth_mode, account_type, account_type_display, account_premium
cdk_redeemedMailCDK 兑换成功cdk_code, preset_id, preset_name

手动触发示例:

bash
/axs eventpacket fire boss_settlement Steve boss_id=dragon boss_name=末影龙 rank=1 damage=50000

9. client-packet — 客户端回包触发

这是 EventPacket 最核心的 UI 交互能力。 客户端 UI 通过 Packet.send(...) 发包到服务端,EventPacket 匹配预设 ID 后执行对应动作链。

工作原理

┌─────────────────────────────────────────────────────────┐
│                      客户端 (UI YAML)                    │
│                                                         │
│  按钮点击 → Packet.send('ArcartXEventPacket', '预设ID')  │
│                          │                              │
└──────────────────────────┼──────────────────────────────┘
                           │ ArcartX 客户端事件

┌──────────────────────────────────────────────────────────┐
│                    服务端 (EventPacket)                   │
│                                                         │
│  1. 收到 packetId = "ArcartXEventPacket"                 │
│  2. data[0] = "预设ID"                                   │
│  3. 在 packet-command-presets/ 目录查找匹配的预设          │
│  4. 执行预设中定义的命令列表                               │
│                                                         │
│  也可在 rules 中配置 trigger: client-packet 来执行         │
│  完整的动作链(ui-packet、subtitle.play 等)              │
└──────────────────────────────────────────────────────────┘

方式一:预设文件(推荐,简单场景)(本方式等同社区ArcartXPacketCommand插件)

plugins/ArcartX-Suite/eventpacket/packet-command-presets/ 目录下创建 YAML 文件,每个顶层键就是一个预设 ID:

yaml
# eventpacket/packet-command-presets/shop.yml

# 顶层键名就是 presetId,客户端通过 Packet.send('ArcartXEventPacket', '预设ID') 触发
open_shop:
  type: op          # 命令执行身份:op / console / player
  permission: ""    # 可选:触发该预设所需的 Bukkit 权限,留空不校验
  cooldown: 0       # 可选:冷却时间,支持数字(秒)或 5s / 1m / 1h / 1d
  allow-args: false # 可选:是否允许客户端透传额外参数
  args-pattern: "[\\w.:-]{1,64}" # 可选:当 allow-args 为 true 时,对每个参数进行正则校验
  commands:
    - say <player> 打开了商店
    - openShop <player>

buy_item:
  type: console
  permission: ""
  cooldown: 0
  allow-args: false
  args-pattern: "[\\w.:-]{1,64}"
  commands:
    - economy take <player> 100
    - give <player> diamond 1
    - say <player> 购买了钻石

give_item:
  type: op
  permission: "eventpacket.preset.give"
  cooldown: "5s"
  allow-args: true
  args-pattern: "[A-Z_0-9]{1,64}"
  commands:
    - give <player> <arg1> <arg2>

UI YAML 中发包:

yaml
# 某个 UI 文件中的按钮
controls:
  shop_button:
    type: Texture
    texture: "ui/btn_shop.png"
    action:
      click: |-
        Packet.send('ArcartXEventPacket', 'open_shop')
  buy_button:
    type: Texture
    texture: "ui/btn_buy.png"
    action:
      click: |-
        Packet.send('ArcartXEventPacket', 'buy_item')

Packet.send 的第一个参数是 packet-command.packet-id(默认 ArcartXEventPacket),第二个参数是预设文件中的顶层键名。

type 说明

  • op:临时给予玩家 OP 权限执行命令,执行后立即恢复
  • console:以控制台身份执行
  • player:以玩家自身身份执行(不提权)

预设文件可用占位符

预设文件中的 commands 支持以下占位符,执行前会被替换为对应值:

占位符说明示例
<player>触发玩家名Steve
<uuid>触发玩家 UUID00000000-0000-0000-0000-000000000000
<world>触发玩家所在世界名world
<arg1> / <arg2> / ...客户端透传的额外参数,需 allow-args: trueDIAMOND_SWORD

对应动作变量为 {player_name}{player_uuid}{player_world}{arg1}{arg2} 等。

参数透传

allow-args: true 时,客户端可以这样调用:

yaml
action:
  click: |-
    Packet.send('ArcartXEventPacket', 'give_item', 'DIAMOND_SWORD', '1')

服务端预设:

yaml
give_item:
  type: op
  allow-args: true
  args-pattern: "[A-Z_0-9]{1,64}"
  commands:
    - give <player> <arg1> <arg2>

args-pattern 会对每个参数单独校验,不匹配则整个预设不会执行。

方式二:rules 配置(完整动作链)

ArcartXEventPacket.ymlrules 中直接定义 client-packet 触发器。比预设文件更强大——可以使用所有 13 种动作类型。

yaml
rules:
  client_open_quest:
    enabled: true
    trigger: client-packet
    signal: "open_quest_menu"       # 匹配的预设 ID
    repeatable: true
    cooldown: "1s"
    actions:
      - type: questgps.open
      - type: subtitle.play
        group-id: "quest_hint"

UI YAML 对应:

yaml
action:
  click: |-
    Packet.send('ArcartXEventPacket', 'open_quest_menu')

注意

rules 中的 client-packet 规则与预设文件共享同一个匹配池。如果预设文件和 rules 中有相同的 ID,预设文件的规则会优先(因为它们先被加载)。建议避免 ID 重名。


10. quest-accept / quest-complete / quest-fail — Chemdah 任务生命周期

需要 Chemdah 插件。当玩家接受、完成或失败一个 Chemdah 任务时触发。

专属字段类型说明
signalstring可选,指定任务 ID 过滤(如 "gps_main_newcomer"
yaml
rules:
  quest_complete_reward:
    enabled: true
    trigger: quest-complete
    signal: "gps_main_newcomer"
    repeatable: false
    actions:
      - type: subtitle.play
        group-id: "quest_done"
      - type: mail.send
        preset-id: "tutorial_reward"

可用上下文变量: {quest_id}{signal}


11. objective-complete / objective-continue / objective-restart — Chemdah 目标事件

需要 Chemdah 插件。当 Chemdah 任务的某个目标完成、继续(进度推进)或重启(进度重置)时触发。

专属字段类型说明
signalstring可选,指定 quest_id(如 "gps_main_newcomer")或 objective_name(如 "player kill")过滤
yaml
# 按 quest_id 过滤
rules:
  objective_done_notify:
    enabled: true
    trigger: objective-complete
    signal: "gps_main_newcomer"
    repeatable: true
    cooldown: "1s"
    actions:
      - type: ui-packet
        ui-id: "quest_hud"
        packet-handler: "objectiveDone"
        recipients:
          - self
        pack:
          quest_id: "{quest_id}"
          task_id: "{task_id}"

# 按 objective 类型过滤(如仅当 "player kill" 目标完成时触发)
rules:
  kill_objective_bonus:
    enabled: true
    trigger: objective-complete
    signal: "player kill"
    repeatable: true
    cooldown: "3s"
    actions:
      - type: subtitle.play
        group-id: "kill_bonus"
      - type: command.dispatch
        executor: console
        command: "give {player_name} emerald 1"

可用上下文变量: {quest_id}{task_id}{objective_type}(Java 类名)、{objective_name}(Chemdah 配置中的名称,如 "player kill")。

signal 过滤说明

signal 字段对 objective 事件支持双重匹配:先按 quest_id 匹配,不匹配时再按 objective_name 匹配。因此可以灵活地按任务或按目标类型过滤。


12. chemdah-level-change — Chemdah 等级变化

需要 Chemdah 插件。当玩家的 Chemdah 等级或经验值发生变化时触发。

专属字段类型说明
signalstring可选,指定等级选项 ID 过滤(如 "adventure"
yaml
rules:
  level_up_celebrate:
    enabled: true
    trigger: chemdah-level-change
    # signal: "adventure"  # 仅匹配冒险等级变化
    repeatable: true
    cooldown: "5s"
    actions:
      - type: subtitle.play
        group-id: "level_up"
      - type: command.dispatch
        executor: console
        command: "say {player_name} 的 {level_option} 等级升到了 {new_level}!"

可用上下文变量: {level_option}(等级选项 ID)、{old_level}{new_level}{old_experience}{new_experience}{level_delta}(变化量)。


13. script-js / script-aria — 脚本条件触发

通过轮询执行 JavaScript 或 Aria 脚本表达式,当结果从 false 变为 true 时触发(边缘检测)。

专属字段类型说明
scriptstring脚本表达式,script-js 写 JavaScript,script-aria 写 Aria
yaml
# JavaScript 触发器:血量低于 25% 时触发
rules:
  low_health_alert:
    enabled: true
    trigger: script-js
    repeatable: true
    cooldown: "30s"
    script: |
      player.getHealth() / player.bukkit().getMaxHealth() < 0.25
    actions:
      - type: subtitle.play
        group-id: "low_health_warning"

# Aria 触发器:Y 坐标高于 200 时触发
rules:
  high_altitude_achievement:
    enabled: true
    trigger: script-aria
    repeatable: true
    cooldown: "1m"
    script: |
      playerY = player.getY()
      playerY > 200
    actions:
      - type: subtitle.play
        group-id: "high_altitude"
      - type: command.dispatch
        executor: console
        command: "say {player_name} 飞到了高空!"

可用上下文变量: {script_result}(脚本最后一次返回的字符串表示)。

执行说明

  • 脚本触发器每 tick 对所有在线玩家评估一次,仅在结果从 falsetrue 时触发,避免重复执行。
  • script-js 需要 classpath 提供 JavaScript ScriptEngine(Java 15+ 默认无 Nashorn,可使用 GraalJS 或 standalone Nashorn);脚本中的 player 是 AXS 的 AriaPlayer 门面,门面未覆盖的原生 API 使用 player.bukkit();JS 不做脚本级 %...% / {player} 预展开,取 PAPI 请使用 player.papi()player.papiNumber()
  • script-aria 使用 ArcartX 内置的 Aria 脚本语言,绑定的 player 是 AXS 的 AriaPlayer 门面;Aria 会在求值前展开脚本文本中的 %...% PAPI 占位符和 {player}
  • 脚本中返回 true / 非零数字 / 非空字符串 均视为真值。

动作类型详解

所有动作的参数值都支持 {变量名} 占位符替换。

command.dispatch — 执行命令

参数类型说明
commandstring要执行的命令(不需要带 /,可用变量)
executorstring执行身份:op(默认)/ console / player
yaml
- type: command.dispatch
  executor: console
  command: "give {player_name} diamond 5"

ui-packet — 发送 UI 包(服务端 → 客户端)

这是 EventPacket 向客户端 UI 发送数据的核心动作。

参数类型说明
ui-idstring目标 UI 的注册 ID
packet-handlerstringUI YAML packetHandler 中的处理器名称
recipientslist接收者:self(默认)/ all-online / others
packmap/string发送给 UI 的数据负载
yaml
- type: ui-packet
  ui-id: "quest_hud"
  packet-handler: "questCompleted"
  recipients:
    - self
  pack:
    player: "{player_name}"
    quest: "{signal}"
    time: "{timestamp_local}"
    level: "{player_level}"

UI YAML 中接收:

yaml
ui:
  packetHandler:
    questCompleted: |-
      var.completedPlayer = packet['player']
      var.completedQuest = packet['quest']
      var.completedTime = packet['time']
      var.showNotification = true

controls:
  notification:
    type: Text
    visible: "var.showNotification == true"
    texts:
      - "{var.completedPlayer} 完成了任务 {var.completedQuest}"

recipients 说明

  • self:仅发送给触发事件的玩家本人
  • all-online / all:发送给所有在线玩家
  • others:发送给除触发者以外的所有在线玩家

subtitle.play — 播放字幕组

参数类型说明
group-idstringAnnouncer 模块中的字幕组 ID
yaml
- type: subtitle.play
  group-id: "welcome_cinematic"

announcer.play — 播放 Announcer 字幕组

subtitle.play 功能相同,是别名。

chat.card — 推送聊天卡片

参数类型说明
card-idstringChat 模块中的卡片 ID
datamap传递给卡片的数据
yaml
- type: chat.card
  card-id: "quest_offer"
  data:
    quest: "gps_main_newcomer"
    title: "新手引导"

title.give — 授予称号

参数类型说明
title-idstringTitle 模块中的称号 ID
durationstring持续时间:permanent / 7d / 30d
yaml
- type: title.give
  title-id: "boss_slayer"
  duration: "7d"

questgps.offer — 提供任务

参数类型说明
quest-idstringChemdah 任务裸 ID(如 gps_main_newcomer
open-menuboolean是否同时打开任务菜单
yaml
- type: questgps.offer
  quest-id: "gps_main_newcomer"
  open-menu: true

questgps.accept — 接受任务

参数类型说明
quest-idstringChemdah 任务裸 ID(须已在 QuestGPS overlay 登记或 discovery.mode=auto)
yaml
- type: questgps.accept
  quest-id: "gps_main_newcomer"

questgps.open — 打开任务菜单

无参数。

yaml
- type: questgps.open

questgps.track — 追踪任务

参数类型说明
quest-idstringChemdah 任务裸 ID(如 gps_main_newcomer
task-idstring可选,具体任务步骤 ID
yaml
- type: questgps.track
  quest-id: "gps_main_newcomer"
  task-id: "0"

mail.send — 发送邮件预设

参数类型说明
preset-idstringMail 模块中的邮件预设 ID
yaml
- type: mail.send
  preset-id: "welcome_gift"

combateffect.play — 播放战斗特效

参数类型说明
ui-idstring可选,CombatEffect UI ID(留空使用模块默认)
packet-handlerstring可选,处理器名(默认 play
packany特效数据负载
yaml
- type: combateffect.play
  pack: "{player_name};cdk_sparkle;{preset_name}"

qq-broadcast — QQ 群广播

向 QQ 群发送消息(需要 QQBot 模块已启用并配置)。

参数类型说明
messagestring要发送的消息内容(支持变量替换)
group-idlong/string可选,指定群号;留空则发送到所有配置的群
yaml
- type: qq-broadcast
  message: "玩家 {player_name} 完成了成就!"
  # group-id: 123456789  # 可选:指定群号

上下文变量一览

所有动作参数中的 {变量名} 会在执行前自动替换。

玩家信息

变量说明
{player_name}触发玩家名
{player_display_name}显示名
{player_uuid}UUID
{player_world}所在世界
{player_x} / {player_y} / {player_z}坐标(整数)
{player_health} / {player_max_health}生命值
{player_level}等级
{player_ping}延迟

{subject_*}{player_*} 等价。

账号信息

由宿主统一账号识别服务提供,可用于所有触发器(join、papi、command-signal 等)。

变量说明
{account_type}账号类型 id:microsoft / littleskin / offline
{account_type_display}账号类型中文名:微软正版 / LittleSkin / 离线
{account_premium}是否正版账号(可免密进服):true / false

接收者信息(仅 ui-packet 动作的 pack 中有效)

变量说明
{receiver_name}接收者玩家名
{receiver_display_name}接收者显示名
{receiver_uuid}接收者 UUID
{receiver_role}接收者类型:self / all-online / others

PAPI 触发器变量

变量说明
{placeholder}监听的占位符
{old_value} / {new_value}变化前后的原始值
{old_number} / {new_number}变化前后的数值
{delta_number}变化量(new - old)
{change_direction}increasedecrease

Chemdah 触发器变量

变量说明
{quest_id}Chemdah 任务 ID
{task_id}目标(Task)ID
{objective_type}Objective Java 类名
{objective_name}Objective 配置名称(如 "player kill""player chat"
{level_option}等级选项 ID
{old_level} / {new_level}变化前后的等级
{old_experience} / {new_experience}变化前后的经验值
{level_delta}等级变化量

脚本触发器变量

变量说明
{script_result}脚本最后一次评估结果的字符串表示

信号变量

变量说明
{signal} / {command_signal}信号名称
自定义 keyfire 命令或模块发射时携带的 key=value 变量

客户端回包预设变量

变量说明
{preset_id}匹配的预设 ID
{arg1} / {arg2} / ...客户端透传的额外参数(仅 allow-args: true 时可用)

时间戳

变量说明
{timestamp_unix}Unix 秒数
{timestamp_local}本地时间字符串

完整教程:client-packet 双向通信

场景说明

实现一个自定义 UI 按钮,点击后:

  1. 客户端发包给服务端(Packet.send
  2. 服务端执行命令 + 向客户端 UI 回发数据(ui-packet
  3. 客户端 UI 接收数据并更新显示(packetHandler

第一步:创建预设或规则

方式 A — 预设文件(仅执行命令):

yaml
# eventpacket/packet-command-presets/my_ui.yml
claim_daily:
  type: console
  commands:
    - give <player> diamond 1
    - say <player> 领取了每日奖励

方式 B — rules 配置(命令 + UI 回包):

yaml
# data/eventpacket/rules/client.yml
claim_daily_with_feedback:
  enabled: true
  trigger: client-packet
  signal: "claim_daily"
  repeatable: true
  cooldown: "86400s"
  actions:
    - type: command.dispatch
      executor: console
      command: "give {player_name} diamond 1"
    - type: ui-packet
      ui-id: "daily_reward_ui"
      packet-handler: "claimResult"
      recipients:
        - self
      pack:
        success: "true"
        reward: "钻石 x1"
        player: "{player_name}"
        time: "{timestamp_local}"

第二步:UI YAML — 发包 + 接包

yaml
# arcartx/ui/daily_reward_ui.yml
ui:
  background: true
  escClose: true
  screenScale: true
  packetHandler:
    # 接收服务端 ui-packet 动作发来的数据
    claimResult: |-
      var.claimSuccess = packet['success']
      var.rewardText = packet['reward']
      var.claimTime = packet['time']
      var.showResult = true

controls:
  root:
    type: Canvas
    width: 300
    height: 200
    center: true
    children:
      # 领取按钮 —— 点击发包给 EventPacket
      claim_button:
        type: Texture
        texture: "ui/btn_claim.png"
        width: 120
        height: 40
        x: 90
        y: 80
        action:
          click: |-
            Packet.send('ArcartXEventPacket', 'claim_daily')

      # 结果显示 —— 接收到服务端回包后显示
      result_text:
        type: Text
        visible: "var.showResult == true"
        x: 50
        y: 140
        fontSize: 14
        color: "#00FF00"
        texts:
          - "领取成功: {var.rewardText}"
          - "时间: {var.claimTime}"

第三步:发包流程图解

   客户端 UI                          服务端 EventPacket
   ──────────                         ─────────────────
   
   [点击按钮]

       │ Packet.send('ArcartXEventPacket', 'claim_daily')
       │────────────────────────────────────►│
       │                                     │ 1. 匹配 packetId + presetId
       │                                     │ 2. 执行 command.dispatch
       │                                     │ 3. 执行 ui-packet
       │                                     │
       │◄────────────────────────────────────│
       │ sendPacket(player, uiId,            │
       │   "claimResult", {success, reward}) │
       │                                     │
   [packetHandler.claimResult 执行]

   var.showResult = true
   var.rewardText = "钻石 x1"

   [UI 自动刷新显示结果]

关键要点

  1. 客户端 → 服务端Packet.send('packetId', 'presetId')packetId 对应 packet-command.packet-id 配置
  2. 服务端 → 客户端ui-packet 动作,通过 ui-id + packet-handler 指定目标 UI 和处理器
  3. UI 接包:在 ui.packetHandler.<handler名> 中用 packet['key'] 读取数据,赋值给 var.* 变量
  4. UI 使用数据:controls 中通过 {var.变量名} 引用,visible 中通过 var.变量名 == 值 控制显示

联动示例

以下示例均为规则文件根级写法(data/eventpacket/rules/*.yml)。

Boss 击杀庆祝

yaml
# data/eventpacket/rules/boss.yml
boss_settlement_celebration:
  enabled: true
  trigger: command-signal
  signal: "boss_settlement"
  repeatable: true
  cooldown: "3s"
  actions:
    - type: subtitle.play
      group-id: "boss_victory"
    - type: mail.send
      preset-id: "boss_reward_{boss_id}"
    - type: title.give
      title-id: "boss_slayer"
      duration: "7d"

新玩家注册引导流

yaml
# data/eventpacket/rules/onboarding.yml
welcome_new_player:
  enabled: true
  trigger: command-signal
  signal: "first_register"
  conditions:
    - "%axsloginview_account_type% == microsoft"
  repeatable: false
  actions:
    - type: subtitle.play
      group-id: "welcome_cinematic"
    - type: questgps.offer
      quest-id: "gps_main_newcomer"
      open-menu: true
    - type: mail.send
      preset-id: "welcome_gift"
    - type: title.give
      title-id: "newcomer"
      duration: "permanent"

按账号来源区分新玩家流程

yaml
# data/eventpacket/rules/onboarding.yml
welcome_littleskin_player:
  enabled: true
  trigger: command-signal
  signal: "first_register"
  conditions:
    - "%axsloginview_account_type% == littleskin"
  repeatable: false
  actions:
    - type: chat.card
      card-id: "quest_offer"
      data:
        title: "LittleSkin 专属欢迎"
        source: "{account_type_display}"

击杀怪物解锁副本

yaml
# data/eventpacket/rules/progression.yml
zombie_dungeon_unlock:
  enabled: true
  trigger: mob-kill-count
  count: 50
  entity-types:
    - "ZOMBIE"
  worlds:
    - "world"
  repeatable: false
  actions:
    - type: questgps.offer
      quest-id: "gps_side_silk_trade"
      open-menu: true
    - type: subtitle.play
      group-id: "dungeon_unlock"

等级提升联动

yaml
# data/eventpacket/rules/progression.yml(同文件可放多条规则)
level_30_unlock:
  enabled: true
  trigger: placeholder-threshold
  placeholder: "%player_level%"
  threshold: 30
  require-non-empty: true
  repeatable: false
  actions:
    - type: mail.send
      preset-id: "level_30_gift"
    - type: title.give
      title-id: "advanced_warrior"
      duration: "permanent"
    - type: questgps.offer
      quest-id: "gps_main_advanced"

CDK 兑换特效

yaml
# data/eventpacket/rules/misc.yml
cdk_redeemed_effect:
  enabled: true
  trigger: command-signal
  signal: "cdk_redeemed"
  repeatable: true
  cooldown: "5s"
  actions:
    - type: combateffect.play
      pack: "{player_name};cdk_sparkle;{preset_name}"
    - type: subtitle.play
      group-id: "cdk_success"

Chemdah 目标完成按类型奖励

yaml
# data/eventpacket/rules/chemdah.yml
# 仅当 "player kill" 类型的目标完成时给予奖励
kill_objective_bonus:
  enabled: true
  trigger: objective-complete
  signal: "player kill"
  repeatable: true
  cooldown: "3s"
  actions:
    - type: subtitle.play
      group-id: "kill_bonus"
    - type: command.dispatch
      executor: console
      command: "give {player_name} emerald 1"

# 仅当 "player chat" 类型的目标完成时提示
chat_objective_done:
  enabled: true
  trigger: objective-complete
  signal: "player chat"
  repeatable: true
  cooldown: "1s"
  actions:
    - type: subtitle.play
      group-id: "chat_objective"

脚本触发器:低血量急救提示

yaml
# data/eventpacket/rules/script.yml
low_health_alert:
  enabled: true
  trigger: script-js
  repeatable: true
  cooldown: "30s"
  script: |
    player.getHealth() / player.bukkit().getMaxHealth() < 0.25
  actions:
    - type: subtitle.play
      group-id: "low_health_warning"
    - type: ui-packet
      ui-id: "combat_hud"
      packet-handler: "healthAlert"
      recipients:
        - self
      pack:
        health: "{player_health}"
        max: "{player_max_health}"

命令

权限:arcartxsuite.admin

命令说明示例
/axs eventpacket status查看规则数量和模块状态
/axs eventpacket reload重载配置和预设文件
/axs eventpacket fire <信号名> <玩家> [key=value...]手动触发信号,用于调试/axs eventpacket fire boss_settlement Steve boss_id=dragon rank=1
/axs eventpacket list列出已加载的客户端回包预设/axs eventpacket list
/axs eventpacket run <玩家> <预设名> [arg...]手动执行某个回包预设(绕过权限与冷却)/axs eventpacket run Steve give_item DIAMOND_SWORD 1
/axs eventpacket clearlag手动执行一次实体清理/axs eventpacket clearlag

实体清理(ClearLag)

EventPacket 模块内置了实体清理功能,定时清理掉落物和怪物,减轻服务器负担。

配置

yaml
# ArcartXEventPacket.yml
entity-cleanup:
  enabled: false
  # 清理间隔(秒)
  interval-seconds: 300
  # 清理前警告倒计时(秒),0 = 不警告
  warning-seconds: 30
  warning-message: '&c[清理] 将在 {seconds} 秒后清理掉落物!'
  cleanup-message: '&a[清理] 已清除 {count} 个实体。'
  # 清理类型
  clear-dropped-items: true
  clear-monsters: false
  clear-animals: false
  # 跳过有自定义名称的实体
  skip-named: true
  # 额外要清理的实体类型(EntityType 枚举名)
  clear-entity-types: []
  # 不清理的实体类型白名单
  entity-whitelist:
    - VILLAGER
    - ARMOR_STAND
  # 限定生效世界,空 = 所有世界
  worlds: []

命令

  • /axs eventpacket clearlag — 立即执行一次清理(不等待定时器),适合手动维护

定时命令

定时在后台执行控制台或玩家命令,适合定时重启、自动广播等场景。

配置

yaml
# ArcartXEventPacket.yml
scheduled-commands:
  # 可定义多个定时任务,键名即任务 ID
  example-save:
    enabled: false
    interval-seconds: 600
    delay-seconds: 600
    as-console: true
    commands:
      - 'save-all'
    broadcast-message: ''
  example-tip:
    enabled: false
    interval-seconds: 1800
    delay-seconds: 60
    as-console: true
    commands:
      - 'say 欢迎加入服务器!输入 /help 查看帮助。'
    broadcast-message: ''
字段说明
键名任务标识(即任务 ID)
enabled是否启用
delay-seconds服务器启动后延迟多久开始(秒)
interval-seconds执行间隔(秒)
as-consoletrue 以控制台身份执行;false 对每个在线玩家执行
permission可选,仅 as-console: false 时生效,限定只有该权限的玩家才会执行命令
commands命令列表,按顺序执行;支持 {player} 占位符(对每个在线玩家替换)
broadcast-message可选,命令执行后广播的消息(支持 & 颜色码)

基于 GPL-3.0 许可发布