二七王协议文档:补齐 success/errcode 约定并同步本轮字段变更

协议文档开头一直写着「成败判定只看推送包里的 data.success」,但下
面没有任何一个包定义过该字段,代码里也没有——文档自相矛盾且与实
现不符。本轮代码补齐后同步文档:

- 新增「0. 通用约定」:0.1 所有服务器→客户端包必带 data.success;
  0.2 失败回包(rpc 与请求同名、只回请求者、success=false+errcode)
  与 errcode 取值表,另附 cards 牌id 入参约束(非空数组、0~107 整
  数、不重复,不做类型兜底)与 tishi 成功不回执的例外;0.3 说明
  deskinfo 的 success 归平台填写。
- 6 处 multiple 描述改为 get_base_bycall(call, climb),列出爬坡与
  常规两套取值,并注明与结算包 aset.multiple 同源。
- chupai1 补 shuai 字段;cardtype 补完整取值说明与「甩牌会被压平、
  真实结构读 shuai」的告警。
- 3 处 info 描述补「有人报无主后三个座位同时刷新」。
- PushCards.pushlist 描述补「内层恒 3 个座位、按本局主牌花色排序」。
- mingpai / tishi 的「否则忽略」改为按 0.2 回对应 errcode 的失败包。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-12 04:22:53 +08:00
co-authored by Claude Opus 5
parent 8948a2950f
commit a049498f2c
@@ -4,6 +4,51 @@
--- ---
## 0. 通用约定(所有包适用,下文各表不再逐一重复)
### 0.1 成败标志 `data.success`
**每一个「服务器 → 客户端」的包,`data` 都必带 `success`**(布尔):
- `success: true` —— 操作成功 / 正常推送。下文各包的字段表描述的都是这种情况,表里不再重复列 `success` 这一行。
- `success: false` —— 操作失败,见 0.2。
前端一律 `if (!data.success)` 判成败,**不看 `status` / `code`,也不写 `status` 兼容兜底**。
### 0.2 失败回包
服务端受理请求时,任一校验不通过都会**回一个失败包**(此前是静默丢弃、前端只能干等倒计时):
- **rpc 与请求包同名**(如 `chupai` 失败回 `chupai`,而不是 `chupai1/2/3`);
- **只回发给请求者**(`conmode`/`fromid` 取自请求包),其他两家收不到;
- `data` 只含 `success: false` 与 `errcode`,无业务字段。
| 参数名 | 类型 | 说明 |
| --- | --- | --- |
| success | 布尔 | 恒为 `false` |
| errcode | 整数 | 失败原因,见下表 |
`errcode` 取值(服务端 `youle_erqiwang.ERR`,`mod.js`):
| 值 | 名称 | 含义 |
| --- | --- | --- |
| 1 | PLAYER | 玩家/房间/座位校验不通过(平台 `check_player` 返回 null) |
| 2 | NODESK | 牌桌或牌局不存在 |
| 3 | STEP | 当前阶段不允许该操作(如非出牌阶段发 `chupai`) |
| 4 | SEAT | 位置不符,或还没轮到该玩家操作 |
| 5 | PARAM | 参数非法:类型/范围/张数不对、牌不在手上、牌id 重复 |
| 6 | RULE | 规则不允许:叫分未更低、出牌不合法、投降条件不满足、房间模式禁止等 |
> **牌id 列表的入参约束**(`cards` 字段,`maipai`/`chupai`):必须是**非空数组**,元素必须是 `0 ~ 107` 的**整数**牌id,且**互不重复**。字符串形式的数字(如 `"5"`)、小数、越界值、重复值一律按 `PARAM` 拒绝,服务端不做类型兜底转换。
> **例外:`tishi` 成功时不回执**。该包是闲家给对家的主观提示、不含任何对局状态,服务端只转发给对家(design §11),发送者收不到成功包;只有失败才回给发送者。
### 0.3 断线重连包不在此约定内
`deskinfo` 由平台组装在 `pack.data.deskinfo` 下(见文末「断线重连」),`data.success` 由**平台**填写,子游戏不注入。
---
## 1. 发牌(fapai) ## 1. 发牌(fapai)
发包者:服务器 收包者:游戏 app:youle route:erqiwang rpc:fapai 发包者:服务器 收包者:游戏 app:youle route:erqiwang rpc:fapai
@@ -42,7 +87,7 @@
| seat | 整数 | 叫分者的位置序号 | | seat | 整数 | 叫分者的位置序号 |
| call | 整数 | 分数,0表示不叫 | | call | 整数 | 分数,0表示不叫 |
| currcall | 整数 | 当前叫到的分数 | | currcall | 整数 | 当前叫到的分数 |
| multiple | 整数 | 叫分对应的基础子数(`get_multiple_bycall`,按常规算子取值:65→2 60→3 55→4 50及以下→6 70→2 无叫分→0)| | multiple | 整数 | 叫分对应的基础子数 `get_base_bycall(call, climb)`,**随房间「爬坡」开关取值**(roomtype 位3):常规算子 65→2 60→3 55→4 50及以下→6;爬坡 65→2 60→3 55→4 50→6 45→7 40→8 35→9 30→10 25→11 20→12 15→13 10→14 5→15;两种模式下 70→2;无叫分→0。与结算包 `aset.multiple` 同源同值(design §7.1/§7.3.1)|
| nextseat | 整数 | 下一个叫分者的位置序号 | | nextseat | 整数 | 下一个叫分者的位置序号 |
| countdown | 整数 | 叫分倒计时 | | countdown | 整数 | 叫分倒计时 |
@@ -58,7 +103,7 @@
| call | 整数 | 分数,0表示不叫 | | call | 整数 | 分数,0表示不叫 |
| banker | 整数 | 庄家的位置序号 | | banker | 整数 | 庄家的位置序号 |
| grade | 整数 | 庄家的叫分 | | grade | 整数 | 庄家的叫分 |
| multiple | 整数 | 叫分对应的基础子数(`get_multiple_bycall`,按常规算子取值:65→2 60→3 55→4 50及以下→6 70→2 无叫分→0)| | multiple | 整数 | 叫分对应的基础子数 `get_base_bycall(call, climb)`,**随房间「爬坡」开关取值**(roomtype 位3):常规算子 65→2 60→3 55→4 50及以下→6;爬坡 65→2 60→3 55→4 50→6 45→7 40→8 35→9 30→10 25→11 20→12 15→13 10→14 5→15;两种模式下 70→2;无叫分→0。与结算包 `aset.multiple` 同源同值(design §7.1/§7.3.1)|
| bottomcards | 数组 | 8 张暗牌。**庄家恒有**;**闲家仅当 70 分坐庄时才有**(供 3 秒亮牌用),非 70 分时闲家没有该属性(暗牌只有庄家可见,design §4)| | bottomcards | 数组 | 8 张暗牌。**庄家恒有**;**闲家仅当 70 分坐庄时才有**(供 3 秒亮牌用),非 70 分时闲家没有该属性(暗牌只有庄家可见,design §4)|
| ancard3s | 整数 | 仅 70 分坐庄时出现且为 `1`:表示庄家把暗牌摸入手前,需将 `bottomcards` 这 8 张暗牌向所有玩家亮出 3 秒(design §4/§7.1);非 70 分无此属性 | | ancard3s | 整数 | 仅 70 分坐庄时出现且为 `1`:表示庄家把暗牌摸入手前,需将 `bottomcards` 这 8 张暗牌向所有玩家亮出 3 秒(design §4/§7.1);非 70 分无此属性 |
| cards | 数组 | 拿了暗牌后手上的牌(36 张,含暗牌),庄家才有此属性,闲家没有该属性 | | cards | 数组 | 拿了暗牌后手上的牌(36 张,含暗牌),庄家才有此属性,闲家没有该属性 |
@@ -162,10 +207,11 @@
| seat | 整数 | 出牌者的位置序号 | | seat | 整数 | 出牌者的位置序号 |
| cards | 数组 | 实际打出的牌id列表;**甩错时**(见 `shuaicuo`)为被强制打出的那一张最小主牌单张 | | cards | 数组 | 实际打出的牌id列表;**甩错时**(见 `shuaicuo`)为被强制打出的那一张最小主牌单张 |
| shuaicuo | 整数 | 甩错标志,仅甩错时出现且为 `1`(design §5.4.5:甩牌未通过最大性判定,整套甩牌收回,本轮只强制打出最小一张、失去本轮甩牌资格);正常出牌无此属性 | | shuaicuo | 整数 | 甩错标志,仅甩错时出现且为 `1`(design §5.4.5:甩牌未通过最大性判定,整套甩牌收回,本轮只强制打出最小一张、失去本轮甩牌资格);正常出牌无此属性 |
| info | 数组 | 出牌者的座位牌况 `o_paiju.seatlist[seat]`,**仅可查牌模式下发**(不查牌无此属性,design §9)。5 元素数组:前 4 个对应花色1~4 的 `[无该花色标志, 该花色无对标志]`(0/1),第 5 个为报副情况 `[剩余主牌数, 剩余主对数]`(初始 `[-1,-1]`,报无主后为实际数量) | | info | 数组 | 出牌者的座位牌况 `o_paiju.seatlist[seat]`,**仅可查牌模式下发**(不查牌无此属性,design §9)。5 元素数组:前 4 个对应花色1~4 的 `[无该花色标志, 该花色无对标志]`(0/1),第 5 个为报副情况 `[剩余主牌数, 剩余主对数]`(初始 `[-1,-1]`)。**一旦全场有人报无主,服务端会按各家实际手牌同时刷新三个座位**的这一格(design §9「为全体三人显示另外两家」);但本包只带出牌者这一个座位的,另两家的最新值可从后续出牌包或重连包 `PushCards.seatlist` 取 |
| count | 整数 | 出牌数量(甩错时为 1) | | count | 整数 | 出牌数量(甩错时为 1) |
| flower | 整数 | 出牌花色 | | flower | 整数 | 出牌花色 |
| cardtype | 整数 | 出牌牌型 | | cardtype | 整数 | 出牌牌型:`>100` 单张(101 一张、102 两张…)、`>200` 对子(201 一对、202 两对…)、`>300` 拖拉机(302 两连对、303 三连对…),见 `class.pai.js` 顶部注释。**注意:cardtype 只能表达单一牌型**,而甩牌是单张/对子/拖拉机自由混搭(design §5.4.3),会被牌型推导压平成 1xx 或 2xx(例如「主K对 + 主5」得 103、「两连对 + 一散对」得 203)。**甩牌的真实结构请读 `shuai`,不要据 cardtype 反推** |
| shuai | json | 甩牌分量构成,**仅本次出牌是合法甩牌时才有**(非甩牌、以及甩错退化为单张时都没有该属性)。结构 `{ tractors: [连对数...], pairs: 独立对子数, singles: 单张数 }`,例如「主K对 + 主5」为 `{tractors:[],pairs:1,singles:1}`。与服务端跟牌时逐分量强制匹配用的 `shuai_demand` 同源(design §5.4.3/§5.4.4)|
| nextseat | 整数 | 下一个出牌者的位置序号 | | nextseat | 整数 | 下一个出牌者的位置序号 |
| countdown | 整数 | 下一个出牌者的出牌倒计时 | | countdown | 整数 | 下一个出牌者的出牌倒计时 |
| baozhu | 整数 | 是否已有玩家报无主(主牌出空)0否 1是;对应服务端 `have_baofu()`(任一玩家 `seatlist[seat][4][0]==0`)。**仅可查牌模式**下才可能为 1,供客户端展示他家主牌数量/对子结构并出现"明牌"按钮;**不查牌模式恒为 0**(design §9)| | baozhu | 整数 | 是否已有玩家报无主(主牌出空)0否 1是;对应服务端 `have_baofu()`(任一玩家 `seatlist[seat][4][0]==0`)。**仅可查牌模式**下才可能为 1,供客户端展示他家主牌数量/对子结构并出现"明牌"按钮;**不查牌模式恒为 0**(design §9)|
@@ -181,7 +227,7 @@
| --- | --- | --- | | --- | --- | --- |
| seat | 整数 | 出牌者的位置序号 | | seat | 整数 | 出牌者的位置序号 |
| cards | 数组 | 出的牌id列表 | | cards | 数组 | 出的牌id列表 |
| info | 数组 | 出牌者的座位牌况 `o_paiju.seatlist[seat]`,**仅可查牌模式下发**(不查牌无此属性,design §9)。5 元素数组:前 4 个对应花色1~4 的 `[无该花色标志, 该花色无对标志]`(0/1),第 5 个为报副情况 `[剩余主牌数, 剩余主对数]`(初始 `[-1,-1]`,报无主后为实际数量) | | info | 数组 | 出牌者的座位牌况 `o_paiju.seatlist[seat]`,**仅可查牌模式下发**(不查牌无此属性,design §9)。5 元素数组:前 4 个对应花色1~4 的 `[无该花色标志, 该花色无对标志]`(0/1),第 5 个为报副情况 `[剩余主牌数, 剩余主对数]`(初始 `[-1,-1]`)。**一旦全场有人报无主,服务端会按各家实际手牌同时刷新三个座位**的这一格(design §9「为全体三人显示另外两家」);但本包只带出牌者这一个座位的,另两家的最新值可从后续出牌包或重连包 `PushCards.seatlist` 取 |
| nextseat | 整数 | 下一个出牌者的位置序号 | | nextseat | 整数 | 下一个出牌者的位置序号 |
| countdown | 整数 | 出牌倒计时 | | countdown | 整数 | 出牌倒计时 |
| baozhu | 整数 | 是否已有玩家报无主(主牌出空)0否 1是;对应服务端 `have_baofu()`(任一玩家 `seatlist[seat][4][0]==0`)。**仅可查牌模式**下才可能为 1,供客户端展示他家主牌数量/对子结构并出现"明牌"按钮;**不查牌模式恒为 0**(design §9)| | baozhu | 整数 | 是否已有玩家报无主(主牌出空)0否 1是;对应服务端 `have_baofu()`(任一玩家 `seatlist[seat][4][0]==0`)。**仅可查牌模式**下才可能为 1,供客户端展示他家主牌数量/对子结构并出现"明牌"按钮;**不查牌模式恒为 0**(design §9)|
@@ -197,7 +243,7 @@
| --- | --- | --- | | --- | --- | --- |
| seat | 整数 | 出牌者的位置序号 | | seat | 整数 | 出牌者的位置序号 |
| cards | 数组 | 出的牌id列表 | | cards | 数组 | 出的牌id列表 |
| info | 数组 | 出牌者的座位牌况 `o_paiju.seatlist[seat]`,**仅可查牌模式下发**(不查牌无此属性,design §9)。5 元素数组:前 4 个对应花色1~4 的 `[无该花色标志, 该花色无对标志]`(0/1),第 5 个为报副情况 `[剩余主牌数, 剩余主对数]`(初始 `[-1,-1]`,报无主后为实际数量) | | info | 数组 | 出牌者的座位牌况 `o_paiju.seatlist[seat]`,**仅可查牌模式下发**(不查牌无此属性,design §9)。5 元素数组:前 4 个对应花色1~4 的 `[无该花色标志, 该花色无对标志]`(0/1),第 5 个为报副情况 `[剩余主牌数, 剩余主对数]`(初始 `[-1,-1]`)。**一旦全场有人报无主,服务端会按各家实际手牌同时刷新三个座位**的这一格(design §9「为全体三人显示另外两家」);但本包只带出牌者这一个座位的,另两家的最新值可从后续出牌包或重连包 `PushCards.seatlist` 取 |
| nextseat | 整数 | 下一个出牌者的位置序号 | | nextseat | 整数 | 下一个出牌者的位置序号 |
| countdown | 整数 | 出牌倒计时 | | countdown | 整数 | 出牌倒计时 |
| baozhu | 整数 | 是否已有玩家报无主(主牌出空)0否 1是;对应服务端 `have_baofu()`(任一玩家 `seatlist[seat][4][0]==0`)。**仅可查牌模式**下才可能为 1,供客户端展示他家主牌数量/对子结构并出现"明牌"按钮;**不查牌模式恒为 0**(design §9)| | baozhu | 整数 | 是否已有玩家报无主(主牌出空)0否 1是;对应服务端 `have_baofu()`(任一玩家 `seatlist[seat][4][0]==0`)。**仅可查牌模式**下才可能为 1,供客户端展示他家主牌数量/对子结构并出现"明牌"按钮;**不查牌模式恒为 0**(design §9)|
@@ -211,7 +257,7 @@
发包者:游戏 收包者:服务器 app:youle route:erqiwang rpc:mingpai 发包者:游戏 收包者:服务器 app:youle route:erqiwang rpc:mingpai
查看另外两家手中全部主牌的具体牌面(design §9)。服务端仅在**可查牌模式、出牌阶段(step5)、且已有玩家报无主**(`have_baofu()`)时受理;否则忽略。 查看另外两家手中全部主牌的具体牌面(design §9)。服务端仅在**可查牌模式、出牌阶段(step5)、且已有玩家报无主**(`have_baofu()`)时受理;不满足时按 0.2 回 `mingpai` 失败包(不查牌 / 未报无主 → `RULE`,非出牌阶段 → `STEP`)。
| 参数名 | 类型 | 说明 | | 参数名 | 类型 | 说明 |
| --- | --- | --- | | --- | --- | --- |
@@ -236,7 +282,7 @@
发包者:游戏 收包者:服务器 app:youle route:erqiwang rpc:tishi 发包者:游戏 收包者:服务器 app:youle route:erqiwang rpc:tishi
闲家在出牌阶段向对家(另一闲家)发"踩/没分/有分"提示(design §11)。服务端仅在**出牌阶段(step5)、且发起者为闲家**(`seat != banker`)、**tip 合法(1/2/3)** 时受理;**不校验提示真实性**(玩家可主观发送);庄家无对家,不受理。 闲家在出牌阶段向对家(另一闲家)发"踩/没分/有分"提示(design §11)。服务端仅在**出牌阶段(step5)、且发起者为闲家**(`seat != banker`)、**tip 合法(1/2/3)** 时受理;**不校验提示真实性**(玩家可主观发送);庄家无对家,不受理。不满足时按 0.2 回 `tishi` 失败包给发送者(庄家发 → `RULE`,非出牌阶段 → `STEP`,tip 非法或缺失 → `PARAM`)。**成功时不给发送者回执**,只转发给对家。
| 参数名 | 类型 | 说明 | | 参数名 | 类型 | 说明 |
| --- | --- | --- | | --- | --- | --- |
@@ -362,7 +408,7 @@
## 断线重连(deskinfo) ## 断线重连(deskinfo)
> 由平台在玩家进入房间/断线重连时回调 `youle_erqiwang.export.get_deskinfo(o_room, seat)` 生成并下发(服务器→客户端);下发的 app/route/rpc 由平台的进房/重连流程决定,不在本子游戏代码内固定。下列字段即该函数返回的 `deskinfo` 对象结构,按当前 `paiju.step` 只带对应阶段的分组。 > 由平台在玩家进入房间/断线重连时回调 `youle_erqiwang.export.get_deskinfo(o_room, seat)` 生成并下发(服务器→客户端);下发的 app/route/rpc 由平台的进房/重连流程决定,不在本子游戏代码内固定。平台把它挂在 `pack.data.deskinfo` 下,**`data.success` 由平台填写、子游戏不注入**(见 0.3)。下列字段即该函数返回的 `deskinfo` 对象结构,按当前 `paiju.step` 只带对应阶段的分组。
| 参数名 | 类型 | 说明 | | 参数名 | 类型 | 说明 |
| --- | --- | --- | | --- | --- | --- |
@@ -379,7 +425,7 @@
| seat | 整数 | 当前叫分位置 | | seat | 整数 | 当前叫分位置 |
| countdown | 整数 | 叫分倒计时 | | countdown | 整数 | 叫分倒计时 |
| nowcall | 整数 | 当前叫分 | | nowcall | 整数 | 当前叫分 |
| multiple | 整数 | 叫分对应的基础子数(`get_multiple_bycall`,按常规算子取值:65→2 60→3 55→4 50及以下→6 70→2 无叫分→0)| | multiple | 整数 | 叫分对应的基础子数 `get_base_bycall(call, climb)`,**随房间「爬坡」开关取值**(roomtype 位3):常规算子 65→2 60→3 55→4 50及以下→6;爬坡 65→2 60→3 55→4 50→6 45→7 40→8 35→9 30→10 25→11 20→12 15→13 10→14 5→15;两种模式下 70→2;无叫分→0。与结算包 `aset.multiple` 同源同值(design §7.1/§7.3.1)|
| call | 数组 | 三家叫分 `[null,0,65]`,null还未叫分,0不叫,>0叫了多少分 | | call | 数组 | 三家叫分 `[null,0,65]`,null还未叫分,0不叫,>0叫了多少分 |
**ChooseMain(step 2 选主/投降阶段,不在此阶段无此属性)** **ChooseMain(step 2 选主/投降阶段,不在此阶段无此属性)**
@@ -388,7 +434,7 @@
| --- | --- | --- | | --- | --- | --- |
| banker | 整数 | 庄家 | | banker | 整数 | 庄家 |
| call | 整数 | 叫分 | | call | 整数 | 叫分 |
| multiple | 整数 | 叫分对应的基础子数(`get_multiple_bycall`,按常规算子取值:65→2 60→3 55→4 50及以下→6 70→2 无叫分→0)| | multiple | 整数 | 叫分对应的基础子数 `get_base_bycall(call, climb)`,**随房间「爬坡」开关取值**(roomtype 位3):常规算子 65→2 60→3 55→4 50及以下→6;爬坡 65→2 60→3 55→4 50→6 45→7 40→8 35→9 30→10 25→11 20→12 15→13 10→14 5→15;两种模式下 70→2;无叫分→0。与结算包 `aset.multiple` 同源同值(design §7.1/§7.3.1)|
| countdown | 整数 | 选主倒计时 | | countdown | 整数 | 选主倒计时 |
| bottomcards | 数组 | 8 张暗牌,**只有庄家有此属性**(暗牌仅庄家可见;70 分的 3 秒亮牌是上庄时的一次性事件,重连不重放)| | bottomcards | 数组 | 8 张暗牌,**只有庄家有此属性**(暗牌仅庄家可见;70 分的 3 秒亮牌是上庄时的一次性事件,重连不重放)|
| touxiang | 整数 | 是否允许投降 0:不允许 1:允许(仅 70 分坐庄为 1)。投降与选主互斥、同一决策点,见 touxiang 包与 design §4 | | touxiang | 整数 | 是否允许投降 0:不允许 1:允许(仅 70 分坐庄为 1)。投降与选主互斥、同一决策点,见 touxiang 包与 design §4 |
@@ -401,7 +447,7 @@
| --- | --- | --- | | --- | --- | --- |
| banker | 整数 | 庄家 | | banker | 整数 | 庄家 |
| call | 整数 | 叫分 | | call | 整数 | 叫分 |
| multiple | 整数 | 叫分对应的基础子数(`get_multiple_bycall`,按常规算子取值:65→2 60→3 55→4 50及以下→6 70→2 无叫分→0)| | multiple | 整数 | 叫分对应的基础子数 `get_base_bycall(call, climb)`,**随房间「爬坡」开关取值**(roomtype 位3):常规算子 65→2 60→3 55→4 50及以下→6;爬坡 65→2 60→3 55→4 50→6 45→7 40→8 35→9 30→10 25→11 20→12 15→13 10→14 5→15;两种模式下 70→2;无叫分→0。与结算包 `aset.multiple` 同源同值(design §7.1/§7.3.1)|
| flower | 整数 | 主牌花色 | | flower | 整数 | 主牌花色 |
| countdown | 整数 | 埋牌倒计时 | | countdown | 整数 | 埋牌倒计时 |
| bottomcards | 数组 | 8 张暗牌,**只有庄家有此属性**(暗牌仅庄家可见;70 分的 3 秒亮牌是上庄时的一次性事件,重连不重放)| | bottomcards | 数组 | 8 张暗牌,**只有庄家有此属性**(暗牌仅庄家可见;70 分的 3 秒亮牌是上庄时的一次性事件,重连不重放)|
@@ -414,7 +460,7 @@
| --- | --- | --- | | --- | --- | --- |
| banker | 整数 | 庄家 | | banker | 整数 | 庄家 |
| call | 整数 | 叫分 | | call | 整数 | 叫分 |
| multiple | 整数 | 叫分对应的基础子数(`get_multiple_bycall`,按常规算子取值:65→2 60→3 55→4 50及以下→6 70→2 无叫分→0)| | multiple | 整数 | 叫分对应的基础子数 `get_base_bycall(call, climb)`,**随房间「爬坡」开关取值**(roomtype 位3):常规算子 65→2 60→3 55→4 50及以下→6;爬坡 65→2 60→3 55→4 50→6 45→7 40→8 35→9 30→10 25→11 20→12 15→13 10→14 5→15;两种模式下 70→2;无叫分→0。与结算包 `aset.multiple` 同源同值(design §7.1/§7.3.1)|
| flower | 整数 | 主牌花色 | | flower | 整数 | 主牌花色 |
| countdown | 整数 | 出牌倒计时 | | countdown | 整数 | 出牌倒计时 |
| bottomcards | 数组 | 埋的牌,只有庄家有此属性 | | bottomcards | 数组 | 埋的牌,只有庄家有此属性 |
@@ -423,7 +469,7 @@
| playproc | json | 当前出牌情况 `o_paiju.playproc`:`round` 第几轮、`start` 本轮首出位置、`currseat` 当前出牌位置、`startcount` 首出张数、`startflower` 首出花色、`starttype` 首出牌型、`maxseat` 本轮最大者位置、`maxcard` 最大牌编码、`cards` 本轮三家各自出的牌(数组下标=位置序号)、`shuai_demand` 首家甩牌的分量需求 `{tractors:[连对数...],pairs,singles}`(非甩牌为 null,供跟牌逐分量强制匹配,design §5.4.4)| | playproc | json | 当前出牌情况 `o_paiju.playproc`:`round` 第几轮、`start` 本轮首出位置、`currseat` 当前出牌位置、`startcount` 首出张数、`startflower` 首出花色、`starttype` 首出牌型、`maxseat` 本轮最大者位置、`maxcard` 最大牌编码、`cards` 本轮三家各自出的牌(数组下标=位置序号)、`shuai_demand` 首家甩牌的分量需求 `{tractors:[连对数...],pairs,singles}`(非甩牌为 null,供跟牌逐分量强制匹配,design §5.4.4)|
| seatlist | 数组 | 三家座位牌况,元素结构同上文 chupai 包的 `info`(每个玩家一个 5 元素数组:4 个花色的 `[无该花色,无对]` + 报副 `[剩余主牌数,剩余主对数]`)。**仅可查牌模式下有此属性**(design §9)| | seatlist | 数组 | 三家座位牌况,元素结构同上文 chupai 包的 `info`(每个玩家一个 5 元素数组:4 个花色的 `[无该花色,无对]` + 报副 `[剩余主牌数,剩余主对数]`)。**仅可查牌模式下有此属性**(design §9)|
| liangpai | json | 庄家亮牌信息,结构同 maipai 包的 `liangpai`;**仅可查牌模式、且请求者为闲家、且庄家达标时有**(供闲家重连后仍能看到亮牌,design §8.2)| | liangpai | json | 庄家亮牌信息,结构同 maipai 包的 `liangpai`;**仅可查牌模式、且请求者为闲家、且庄家达标时有**(供闲家重连后仍能看到亮牌,design §8.2)|
| pushlist | 数组 | 出牌历史 `[[[], [], []], [[], [], []], ...]`,外层下标=轮次,内层 3 个数组按位置序号存该轮各家出的牌id(已按大小排序) | | pushlist | 数组 | 出牌历史 `[[[], [], []], [[], [], []], ...]`,外层下标=轮次(从第 1 轮起,含进行中的当前轮),内层**恒为 3 个数组**、按位置序号存该轮各家出的牌id,各自已按**本局主牌花色**从大到小排序 |
**Balance(不在结算阶段无此属性)** **Balance(不在结算阶段无此属性)**