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 发包不可用 |
| 可选 | PlaceholderAPI | placeholder-* / papi-* 触发器 | 这些触发器不生效,其余不受影响 |
| 可选 | MythicMobs | mob-kill-count 按 MythicMob ID 过滤 | MythicMob 击杀过滤不可用 |
| 可选 | Chemdah | quest-* / objective-* / chemdah-level-change 触发器 | Chemdah 相关触发器不生效 |
| 可选 | ArcartX-Suite 其他模块 | 执行模块联动动作或接收模块信号 | 仅影响引用了该模块的动作/信号 |
启用步骤
# config.yml
modules:
eventpacket:
enabled: true配置结构(ArcartXEventPacket.yml)
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,同一文件可包含多条规则:
# 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"规则通用字段
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
enabled | boolean | true | 是否启用该规则 |
trigger | string | 必填 | 触发器类型 |
repeatable | boolean | false | 是否可重复触发;false 时每玩家仅触发一次(记录持久化到数据库,重启后仍生效) |
cooldown | string | 无 | 冷却时间,格式 10s / 5m / 2h / 1d / 500ms |
conditions | list | [] | 规则条件列表;全部通过后才会执行动作,语法见下方 |
actions | list | 必填 | 动作列表,每个动作是一个 type + 参数的 Map |
规则条件(conditions)
规则执行分为三层:conditions 是动作执行前的布尔门槛,必须全部通过;script-js / script-aria 是独立的脚本触发器,通过轮询结果的 false → true 边沿触发规则;actions 是触发后按顺序执行的结构化动作。EventPacket 没有 Menu 那种 aria: / js: 结构化动作类型,脚本主要用于条件和脚本触发器。语法与 条件系统(PAPI + Aria + JS) 一致。
PAPI 行内示例:
conditions:
- "%player_level% >= 30"
- "%axsloginview_account_type% == microsoft"Aria 示例:
conditions:
- "aria: return player.getLevel() >= 30"
- type: aria
script: "return player.hasPermission('eventpacket.boss.reward')"支持的操作符:
| 操作符 | 说明 |
|---|---|
== / != | 字符串相等/不等,忽略大小写 |
> / < / >= / <= | 优先按数字比较;解析失败时回退到字符串比较 |
contains | 忽略大小写的包含判断 |
regex | 正则匹配,忽略大小写 |
执行时机
conditions 在规则匹配到触发器之后、动作执行之前统一检查,所以对 join、first-join、quit、papi-*、mob-kill-count、command-signal、client-packet 全部生效。
触发器详解
以下所有示例中的
rules:前缀仅用于展示字段结构,实际上规则直接写在规则文件的根级(即data/eventpacket/rules/*.yml中,去掉rules:前缀,规则 ID 为根键)。
1. join — 玩家加入
玩家每次进入服务器时触发。
rules:
join_welcome:
enabled: true
trigger: join
repeatable: true
actions:
- type: subtitle.play
group-id: "welcome_back"无额外字段。
2. first-join — 首次加入
玩家首次进入服务器时触发(!player.hasPlayedBefore())。
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 包。
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 轮询一次,比较前后值。
| 专属字段 | 类型 | 说明 |
|---|---|---|
placeholder | string | 完整 PAPI 占位符,如 %player_level% |
require-non-empty | boolean | 是否要求新值非空(默认 false) |
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 相同,但在数值减少时触发。
| 专属字段 | 类型 | 说明 |
|---|---|---|
placeholder | string | 完整 PAPI 占位符 |
require-non-empty | boolean | 是否要求新值非空 |
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 值首次从低于阈值升至 ≥ 阈值时触发(仅在跨越阈值时触发一次)。
| 专属字段 | 类型 | 说明 |
|---|---|---|
placeholder | string | 完整 PAPI 占位符 |
threshold | number | 目标阈值 |
require-non-empty | boolean | 是否要求新值非空 |
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),重启不丢失。
| 专属字段 | 类型 | 说明 |
|---|---|---|
count | int | 需要累积的击杀次数(默认 1) |
worlds | list | 限定世界名(留空 = 不限) |
entity-types | list | 限定原版实体类型如 ZOMBIE、SKELETON、PLAYER(留空 = 不限) |
mythic-mob-ids | list | 限定 MythicMobs 的 mob ID(留空 = 不限) |
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}。
过滤逻辑
worlds、entity-types、mythic-mob-ids 三个列表是 AND 关系——只要配置了的列表就必须匹配;留空表示不限制。
击杀玩家计数
此触发器同样支持追踪击杀玩家。由于 PlayerDeathEvent 继承自 EntityDeathEvent,当玩家 A 击杀玩家 B 时,B 的实体类型为 PLAYER。只需配置 entity-types: [PLAYER] 即可实现累计击杀玩家 N 次后触发。
示例:累计击杀 10 名玩家授予称号
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 名玩家循环发送奖励
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.dbSQLite,或 MySQL),表eventpacket_kill_progress,主键(player_uuid, rule_id)。repeatable: false的规则触发记录持久化在eventpacket_fired_rules,服务器重启后不会重置。
8. command-signal — 命令信号
由 /axs eventpacket fire <信号名> <玩家> [key=value...] 手动触发,或由其他模块自动发射。
| 专属字段 | 类型 | 说明 |
|---|---|---|
signal | string | 要匹配的信号名称 |
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_settlement | EntityTracker | Boss 死亡结算 | boss_id, boss_name, settlement_id, rank, damage, total_damage, participant_count |
signin_success | OnlineRewards | 签到成功 | streak, total, date, day_of_month |
login_success | LoginView | 登录成功 | auth_mode, account_type, account_type_display, account_premium |
first_register | LoginView | 首次注册 | auth_mode, account_type, account_type_display, account_premium |
premium_bypass | LoginView | 微软正版 / LittleSkin 免登录进入服务器 | auth_mode, account_type, account_type_display, account_premium |
cdk_redeemed | CDK 兑换成功 | cdk_code, preset_id, preset_name |
手动触发示例:
/axs eventpacket fire boss_settlement Steve boss_id=dragon boss_name=末影龙 rank=1 damage=500009. 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:
# 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 中发包:
# 某个 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> | 触发玩家 UUID | 00000000-0000-0000-0000-000000000000 |
<world> | 触发玩家所在世界名 | world |
<arg1> / <arg2> / ... | 客户端透传的额外参数,需 allow-args: true | DIAMOND_SWORD |
对应动作变量为 {player_name}、{player_uuid}、{player_world}、{arg1}、{arg2} 等。
参数透传
当 allow-args: true 时,客户端可以这样调用:
action:
click: |-
Packet.send('ArcartXEventPacket', 'give_item', 'DIAMOND_SWORD', '1')服务端预设:
give_item:
type: op
allow-args: true
args-pattern: "[A-Z_0-9]{1,64}"
commands:
- give <player> <arg1> <arg2>args-pattern 会对每个参数单独校验,不匹配则整个预设不会执行。
方式二:rules 配置(完整动作链)
在 ArcartXEventPacket.yml 的 rules 中直接定义 client-packet 触发器。比预设文件更强大——可以使用所有 13 种动作类型。
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 对应:
action:
click: |-
Packet.send('ArcartXEventPacket', 'open_quest_menu')注意
rules 中的 client-packet 规则与预设文件共享同一个匹配池。如果预设文件和 rules 中有相同的 ID,预设文件的规则会优先(因为它们先被加载)。建议避免 ID 重名。
10. quest-accept / quest-complete / quest-fail — Chemdah 任务生命周期
需要 Chemdah 插件。当玩家接受、完成或失败一个 Chemdah 任务时触发。
| 专属字段 | 类型 | 说明 |
|---|---|---|
signal | string | 可选,指定任务 ID 过滤(如 "gps_main_newcomer") |
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 任务的某个目标完成、继续(进度推进)或重启(进度重置)时触发。
| 专属字段 | 类型 | 说明 |
|---|---|---|
signal | string | 可选,指定 quest_id(如 "gps_main_newcomer")或 objective_name(如 "player kill")过滤 |
# 按 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 等级或经验值发生变化时触发。
| 专属字段 | 类型 | 说明 |
|---|---|---|
signal | string | 可选,指定等级选项 ID 过滤(如 "adventure") |
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 时触发(边缘检测)。
| 专属字段 | 类型 | 说明 |
|---|---|---|
script | string | 脚本表达式,script-js 写 JavaScript,script-aria 写 Aria |
# 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 对所有在线玩家评估一次,仅在结果从
false→true时触发,避免重复执行。 script-js需要 classpath 提供 JavaScriptScriptEngine(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 — 执行命令
| 参数 | 类型 | 说明 |
|---|---|---|
command | string | 要执行的命令(不需要带 /,可用变量) |
executor | string | 执行身份:op(默认)/ console / player |
- type: command.dispatch
executor: console
command: "give {player_name} diamond 5"ui-packet — 发送 UI 包(服务端 → 客户端)
这是 EventPacket 向客户端 UI 发送数据的核心动作。
| 参数 | 类型 | 说明 |
|---|---|---|
ui-id | string | 目标 UI 的注册 ID |
packet-handler | string | UI YAML packetHandler 中的处理器名称 |
recipients | list | 接收者:self(默认)/ all-online / others |
pack | map/string | 发送给 UI 的数据负载 |
- 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 中接收:
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-id | string | Announcer 模块中的字幕组 ID |
- type: subtitle.play
group-id: "welcome_cinematic"announcer.play — 播放 Announcer 字幕组
与 subtitle.play 功能相同,是别名。
chat.card — 推送聊天卡片
| 参数 | 类型 | 说明 |
|---|---|---|
card-id | string | Chat 模块中的卡片 ID |
data | map | 传递给卡片的数据 |
- type: chat.card
card-id: "quest_offer"
data:
quest: "gps_main_newcomer"
title: "新手引导"title.give — 授予称号
| 参数 | 类型 | 说明 |
|---|---|---|
title-id | string | Title 模块中的称号 ID |
duration | string | 持续时间:permanent / 7d / 30d 等 |
- type: title.give
title-id: "boss_slayer"
duration: "7d"questgps.offer — 提供任务
| 参数 | 类型 | 说明 |
|---|---|---|
quest-id | string | Chemdah 任务裸 ID(如 gps_main_newcomer) |
open-menu | boolean | 是否同时打开任务菜单 |
- type: questgps.offer
quest-id: "gps_main_newcomer"
open-menu: truequestgps.accept — 接受任务
| 参数 | 类型 | 说明 |
|---|---|---|
quest-id | string | Chemdah 任务裸 ID(须已在 QuestGPS overlay 登记或 discovery.mode=auto) |
- type: questgps.accept
quest-id: "gps_main_newcomer"questgps.open — 打开任务菜单
无参数。
- type: questgps.openquestgps.track — 追踪任务
| 参数 | 类型 | 说明 |
|---|---|---|
quest-id | string | Chemdah 任务裸 ID(如 gps_main_newcomer) |
task-id | string | 可选,具体任务步骤 ID |
- type: questgps.track
quest-id: "gps_main_newcomer"
task-id: "0"mail.send — 发送邮件预设
| 参数 | 类型 | 说明 |
|---|---|---|
preset-id | string | Mail 模块中的邮件预设 ID |
- type: mail.send
preset-id: "welcome_gift"combateffect.play — 播放战斗特效
| 参数 | 类型 | 说明 |
|---|---|---|
ui-id | string | 可选,CombatEffect UI ID(留空使用模块默认) |
packet-handler | string | 可选,处理器名(默认 play) |
pack | any | 特效数据负载 |
- type: combateffect.play
pack: "{player_name};cdk_sparkle;{preset_name}"qq-broadcast — QQ 群广播
向 QQ 群发送消息(需要 QQBot 模块已启用并配置)。
| 参数 | 类型 | 说明 |
|---|---|---|
message | string | 要发送的消息内容(支持变量替换) |
group-id | long/string | 可选,指定群号;留空则发送到所有配置的群 |
- 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} | increase 或 decrease |
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} | 信号名称 |
| 自定义 key | fire 命令或模块发射时携带的 key=value 变量 |
客户端回包预设变量
| 变量 | 说明 |
|---|---|
{preset_id} | 匹配的预设 ID |
{arg1} / {arg2} / ... | 客户端透传的额外参数(仅 allow-args: true 时可用) |
时间戳
| 变量 | 说明 |
|---|---|
{timestamp_unix} | Unix 秒数 |
{timestamp_local} | 本地时间字符串 |
完整教程:client-packet 双向通信
场景说明
实现一个自定义 UI 按钮,点击后:
- 客户端发包给服务端(
Packet.send) - 服务端执行命令 + 向客户端 UI 回发数据(
ui-packet) - 客户端 UI 接收数据并更新显示(
packetHandler)
第一步:创建预设或规则
方式 A — 预设文件(仅执行命令):
# eventpacket/packet-command-presets/my_ui.yml
claim_daily:
type: console
commands:
- give <player> diamond 1
- say <player> 领取了每日奖励方式 B — rules 配置(命令 + UI 回包):
# 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 — 发包 + 接包
# 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 自动刷新显示结果]关键要点
- 客户端 → 服务端:
Packet.send('packetId', 'presetId'),packetId对应packet-command.packet-id配置 - 服务端 → 客户端:
ui-packet动作,通过ui-id+packet-handler指定目标 UI 和处理器 - UI 接包:在
ui.packetHandler.<handler名>中用packet['key']读取数据,赋值给var.*变量 - UI 使用数据:controls 中通过
{var.变量名}引用,visible中通过var.变量名 == 值控制显示
联动示例
以下示例均为规则文件根级写法(
data/eventpacket/rules/*.yml)。
Boss 击杀庆祝
# 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"新玩家注册引导流
# 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"按账号来源区分新玩家流程
# 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}"击杀怪物解锁副本
# 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"等级提升联动
# 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 兑换特效
# 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 目标完成按类型奖励
# 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"脚本触发器:低血量急救提示
# 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 模块内置了实体清理功能,定时清理掉落物和怪物,减轻服务器负担。
配置
# 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— 立即执行一次清理(不等待定时器),适合手动维护
定时命令
定时在后台执行控制台或玩家命令,适合定时重启、自动广播等场景。
配置
# 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-console | true 以控制台身份执行;false 对每个在线玩家执行 |
permission | 可选,仅 as-console: false 时生效,限定只有该权限的玩家才会执行命令 |
commands | 命令列表,按顺序执行;支持 {player} 占位符(对每个在线玩家替换) |
broadcast-message | 可选,命令执行后广播的消息(支持 & 颜色码) |