LogoArcartX Doc

玩家 UI 协议

SystemMail 收件箱与新邮件 HUD 的 AXUI 通讯契约

玩家 UI 协议

本页用于修改 ui/inbox.ymlui/hud.yml 或重做玩家邮件界面。

其他服务端插件要发送邮件时,请使用公开 API

基本规则

  • UI 文件目录:plugins/SystemMail/ui/
  • 收件箱默认 ID:systemmail_inbox
  • HUD 默认 ID:systemmail_hud
  • 页码从 0 开始,0 是最新一页;
Packet.send('getlist', 0, '全部', '')
Packet.send('sel', mailId)

服务端接受的动作:

动作参数用途
getlistpage, filter, search获取邮件列表
selmailId获取详情并标记已读
getattachmailId领取整封邮件附件
deletemailId删除邮件

主要服务端 handler:

handler内容
systemmail_list邮件列表
systemmail_detail邮件详情
systemmail_attach_result领取结果
systemmail_delete_result删除结果
systemmail_new_mail新邮件 HUD 数据
systemmail_error通用错误

邮件列表

Packet.send('getlist', page, filter, search)
位置类型内容
0Int页码,从 0 开始
1String全部未读含附件
2String标题/发件人搜索;'' 表示不搜索

每页数量由 mail.inbox-page-size 决定,默认 20。

成功回包使用 systemmail_list,内容为 List<Map>

[
  {
    "id": "67c3bf3b-2885-4ea1-b977-94cd1dc53e9e",
    "title": "维护补偿",
    "from": "运营中心",
    "head": "",
    "texts": "感谢您的耐心等待...",
    "attach": 3,
    "time": "2026/07/28",
    "expired": "1天",
    "read": false
  }
]
字段类型内容
idString邮件 UUID
titleString标题
fromString发件人名称;字段名不是 form
headString头像路径;未设置时为 ""
textsString正文前 15 个 Unicode 字符,超出后追加 ...
attachInt可领取的附件数量
timeString投递日期,格式 yyyy/MM/dd
expiredString剩余时间;永不过期时为 ""
readBoolean是否已读

无结果时返回 []含附件 只匹配有附件的邮件。

systemmail_page_count 是未筛选收件箱的总页数,不代表当前搜索结果的页数。当前回包少于每页数量时可以确定没有下一页;刚好等于每页数量时,应结合该变量或允许用户继续翻页。

邮件详情

Packet.send('sel', mailId)

成功回包使用 systemmail_detail

{
  "id": "67c3bf3b-2885-4ea1-b977-94cd1dc53e9e",
  "texts": [
    "完整邮件正文第一行",
    "",
    "第三行;中间空字符串代表空行"
  ],
  "hasAttachments": true,
  "claimed": false,
  "attach": [
    {
      "name": "钻石礼包",
      "type": "item",
      "content": "物品序列化字符串"
    },
    {
      "name": "金币",
      "type": "eco",
      "content": "500 金币",
      "icon": "mail/currency/coin.png"
    },
    {
      "name": "活动称号",
      "type": "command",
      "content": "活动称号",
      "icon": "mail/command/title.png"
    }
  ]
}
  • textsList<String>,每项对应正文一行;保留中间与末尾空行,空正文返回空列表;
  • hasAttachments 表示邮件原本是否含附件;
  • claimed 表示邮件的附件是否已经领取;
  • attach[].typeitemecocommand
  • 物品 content 是完整的物品序列化内容;
  • 货币和命令的 icon 未设置时为 "",UI 应准备默认贴图;
  • 命令附件只下发展示标题,不会泄露真实命令。

UI 只应提供一个“领取全部”按钮。无附件邮件同时返回 hasAttachments: falseclaimed: true,因此按钮逻辑要先判断 hasAttachments

成功读取详情会把邮件标为已读、刷新未读数。

领取附件

Packet.send('getattach', mailId)

结果使用 systemmail_attach_result

{
  "id": "67c3bf3b-2885-4ea1-b977-94cd1dc53e9e",
  "success": true,
  "code": "COMPLETED",
  "claimed": true,
  "msg": "附件领取成功"
}
codesuccess含义
COMPLETEDtrue全部附件领取完成
INVENTORY_FULLfalse背包空槽不足,所有附件均未开始领取
NOTHING_CLAIMABLEfalse没有可领取附件
PARTIALfalse外部附件部分失败
QUARANTINEDfalse外部奖励结果无法确认,转入人工处理
PLAYER_OFFLINEfalse处理时玩家已离线
NOT_FOUNDfalse邮件不存在或不可见
EXPIREDfalse邮件已过期,且没有有效的当前 UI 宽限资格

客户端请勿自动重试 getattach。只有在服务端明确允许重试,并由玩家再次操作时才能重新发送。

删除邮件

Packet.send('delete', mailId)

结果使用 systemmail_delete_result

{
  "id": "67c3bf3b-2885-4ea1-b977-94cd1dc53e9e",
  "success": true,
  "code": "SUCCESS",
  "msg": "邮件已删除"
}

通用错误

systemmail_error 回包:

{
  "action": "getlist",
  "code": "INVALID_PAGE",
  "retry": false,
  "msg": "页码超出服务端允许范围"
}
  • 向玩家显示 msg
  • 使用 code 做逻辑分支;
  • retry: true 只表示可以让玩家手动重试,不表示客户端自动重放;
  • 文案来自服务端 lang.ymlfailure.*

可能出现的通用 code:

ACTION_NOT_ALLOWED
EXPIRED
INTERNAL_ERROR
INVALID_ARGUMENT
INVALID_FILTER
INVALID_ID
INVALID_PAGE
INVALID_SEARCH
NOT_FOUND
PERMISSION_DENIED
QUERY_IN_PROGRESS
RATE_LIMITED
RESPONSE_TOO_LARGE
SERVER_BUSY
SERVICE_UNAVAILABLE

领取和删除的业务失败优先通过各自结果 handler 返回;无法进入对应流程时才使用通用错误。

服务端变量

默认变量内容
systemmail_unread_count当前未读邮件数
systemmail_page_count未筛选收件箱总页数;0 封邮件时为 0

未读数会在玩家进入服务器、收到新邮件、读取邮件或附件状态变化后刷新;总页数会在打开收件箱后刷新。

新邮件 HUD

新邮件使用handler systemmail_new_mail

{
  "id": "67c3bf3b-2885-4ea1-b977-94cd1dc53e9e",
  "title": "维护补偿",
  "from": "运营中心",
  "head": "",
  "texts": "感谢您的耐心等待...",
  "attach": 3
}

请求频率

  • getlist 最短间隔 250 ms;
  • getattach 最短间隔 750 ms;
  • 其余动作最短间隔 100 ms;
  • 同一玩家的相同查询仍在处理时返回 QUERY_IN_PROGRESS
  • 普通回包超过 security.max-ui-response-bytes 时返回 RESPONSE_TOO_LARGE

On this page