前端一致性测试(同一局真包:逐包增量回放 vs 一次性 deskinfo 重连)暴露的四处
服务端缺陷,均属「同一份数据两条路径给的不一样 / 有一条根本没给」:
① chupai1/2/3 补发 playproc(本轮进行态)
与 deskinfo.PushCards 共用新增的 get_playproc() 快照函数,结构取值完全一致。
playproc 是全程复用的活对象(new_playround 就地重置),故快照做逐字段深拷贝,
避免已发出的包被后续出牌回改。可见性:全部字段由桌面公开信息推出,
与既有 PushCards.playproc 一样三家无差别下发。
② deskinfo ChooseMain(step2)/BuryCards(step3) 补发 curmultiple
与 shangzhuang 推送同源同值;此刻一张牌未出、捡分恒 0,必为 +3(大光)。
原先重连重建为 0,顶部「抓分」角标掉档。
③ maipai 补发 seatlist
与 chupai/PushCards 同一张表、同一道查牌模式门控;埋牌完成时为初始化空表。
④ bottomcards / burycards 收敛到单一权威源(SSOT)
- burycards:maipai 原样回显了客户端请求包里 cards 的顺序,改取 get_burycard()
权威快照,与 PushCards.burycards 同一函数。请求包只承载「意图」,其顺序不可信。
- bottomcards:get_bottomcards 按「调用时的 flower」排序,导致上庄推送(flower=-1)
与重连 BuryCards(flower 已定) 两种顺序。底牌是选主【之前】就翻给玩家看的、
发牌结束即固定的快照,故改为发牌时算一次并冻结,get_bottomcards 返回其副本
(order_cards 是原地排序,交出本体会被调用方就地重排)。三个调用点无需改动。
协议文档同步 7 处(新增 playproc/seatlist/curmultiple 字段说明与两处排序口径)。
新增 test_rpc.js「下发面一致性」用例组 21 checks,含 28 轮真实牌局逐包逐座位比对
(249 次、0 不一致)与深拷贝守卫;每条均已用「退回修复必转红」反向验证。
既有 649 checks 未改一条断言,全绿(17 脚本 / 670 checks)。未涉及 shared/。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
47 KiB
二七王协议包列表
说明:data 均为发送方与接收方之间约定的 JSON 内容;成败判定只看推送包里的 data.success。
0. 通用约定(所有包适用,下文各表不再逐一重复)
0.0 术语:底牌 vs 埋牌底牌(先读这一条)
本项目于 2026-08-25 修订了这两个术语(design.md §1 已同步,本文亦已改用新称):
| 术语 | 指哪 8 张 | 旧称 |
|---|---|---|
| 底牌 | 发牌时没有发给玩家、扣在桌面的 8 张 | |
| 埋牌底牌 | 庄家埋牌时从手里扣下的 8 张 |
两批牌的字段名已拆分(2026-08-25,原先共用 bottomcards):
| 字段名 | 含义 | 出现在 |
|---|---|---|
bottomcards |
底牌 | shangzhuang、deskinfo.ChooseMain、deskinfo.BuryCards |
burycards |
埋牌底牌 | maipai、deskinfo.PushCards |
bottom.cards |
埋牌底牌 | 结算包的 bottom 分组(分组名已表明是抠底相关,字段未改名) |
同一个包里不会同时出现这两个字段。下发面:burycards 与 bottomcards(非 70 分时)都只发给庄家,闲家两者皆无——已由 test/test_leak.js 的泄露审计覆盖。
0.0b 四类「公开信息」术语(都带亮/明字,别读混)
| 术语 | 谁公开给谁 | 给的是什么 | 触发 | 本文相关字段 |
|---|---|---|---|---|
| 亮牌 | 庄家 → 两个闲家 | 具体牌面(庄家全部固定主牌) | 庄家埋牌后固定主牌达门槛(design §8.2) | liangpai.cards |
| 余主公示 | 全体 → 全体 | 只有数量(剩余主牌数、主对数) | 任一玩家报无主(design §9) | seatlist[seat][4]、baozhu |
| 明牌 | 他家 → 请求者 | 具体牌面(他家全部未出主牌) | 可查牌 + 任一玩家报无主 → 三家均可点、随时可查(design §9) | mingpai.others[].zhucards |
| 开底 | 桌面 → 所有玩家 | 具体牌面(8 张底牌) | 70 分坐庄,摸底之前 3 秒(design §4) | ancard3s + bottomcards |
一句话记:只有「余主公示」是统计类(给数字),「亮牌」「明牌」「开底」都给具体牌面——区别在给谁的牌:亮牌给庄家自己的、明牌给他家的、开底给桌上那 8 张。
另有一组「底」字族专管发牌留桌的那 8 张:摸底(庄家摸起看,仅庄家)、开底(70 分时全场看 3 秒)、查底牌(对局中随时回看)、扣底(末轮翻开埋牌底牌计分)。 (「亮主」不是术语,是前端选主界面的标题文案,与上表无关。)
0.0c 算奖 = 冲关 + 傍王
| 术语 | 范围 | 相关字段 |
|---|---|---|
| 冲关 | design §8.1,只计庄家。旧称"常规算奖",现统一叫冲关 | chongguan(奖数)、cards(冲关牌型) |
| 傍王 | design §8.3,可选规则,勾选后庄闲都算,每张王 1 奖 | wang(王数)、bangwang(开关) |
| 算奖 | 上位概念 = 冲关 + 傍王 | naward(总奖数 N)、grade_aw(算奖得分) |
说「冲关」指庄家那一份,说「算奖」指两者合计。界面上小局结算显示「冲关分」、按钮叫「冲关牌型」。
⚠️
grade_aw是按合计后的N算出来的,冲关与傍王的贡献事后无法拆分。大局结算若要分别显示「冲关分」「傍王分」,须服务端在算钱时就分开代入公式——见前端清单 §7.5 S-6。
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 countdown 只是展示用的秒数
多个包带 countdown(叫分 / 选主 / 埋牌 / 出牌倒计时,取自 class.desk.js 的四个常量)。它只供客户端显示提醒,服务端不据此做任何事:
- 服务端没有对应的定时器,倒计时归零后不会自动叫分 / 选主 / 埋牌 / 出牌,也不判负、不跳过该玩家;
- 轮到谁而谁不操作,牌局就停在该阶段一直等,
step与playproc都不变; - 这是 design §11 确认过的规则(无超时托管),不是未实现的功能。牌局因此停住时,由玩家走平台的房间解散流程收场(平台回调子游戏
get_disbandRoom→ 解散结算,见 §14)。
因此客户端不要在倒计时归零时做任何乐观的界面推进(不要自行跳阶段、不要清控制权),一切仍以收到服务端推送为准。
0.4 断线重连包不在此约定内
deskinfo 由平台组装在 pack.data.deskinfo 下(见文末「断线重连」),data.success 由平台填写,子游戏不注入。
0.5 roomtype 房间选项位串(建房参数,下文多处引用「位2 / 位3」)
roomtype 是建房时由客户端拼好、经平台建房流程存在 o_room.roomtype 上的定长数字位串(字符串),每一位(charAt)一个开关 '0'/'1',便于前端逐项勾选。它不是某个 erqiwang 收发包的字段,但下文多个包的 multiple / bangwang / climb / baozhu / seatlist / liangpai / pushlist 都按它取值或门控,故在此给出唯一定义。服务端解析入口是 class.config.js 的 parse()(SSOT,不得在别处按下标硬解析)。
| 位 | 含义 | '0' |
'1' |
design |
|---|---|---|---|---|
| 0 | 局数 | 6 局(缺省) | 12 局 | §10.1 |
| 1 | 扣卡方式 | 房主扣卡(缺省) | AA 每人扣卡 | §10.1 |
| 2 | 傍王 | 关(缺省) | 开 | §8.3 / §10.3 |
| 3 | 爬坡 | 常规算子(缺省) | 爬坡 | §7.3 / §10.3 |
| 4 | 查牌模式 | 可查牌(缺省) | 不查牌 | §9 / §10.2 |
缺省 "00000" = 6局 / 房主扣卡 / 无傍王 / 常规算子 / 可查牌。示例 "10100" = 12局 / 房主扣卡 / 傍王开 / 常规算子 / 可查牌。解析对缺失、非字符串、过短的 roomtype 一律按 '0' 处理。
对应的房卡与局数(export.get_asetcount / get_needroomcard / get_needroomcard_joinroom,design §10.1):
| 扣卡方式(位1) | 局数(位0) | 房主开房扣 | 加入者扣 |
|---|---|---|---|
房主扣卡 '0' |
6 局 | 2 张 | 0 |
房主扣卡 '0' |
12 局 | 4 张 | 0 |
AA 每人 '1' |
6 局 | 1 张 | 1 张 |
AA 每人 '1' |
12 局 | 2 张 | 2 张 |
1. 发牌(fapai)
发包者:服务器 收包者:游戏 app:youle route:erqiwang rpc:fapai
| 参数名 | 类型 | 说明 |
|---|---|---|
| asetidx | 整数 | 当前局数 |
| asetcount | 整数 | 总局数 |
| cards | 数组 | 自己得到的牌id列表 |
| seat | 整数 | 当前等待叫分者的位置 |
| countdown | 整数 | 叫分倒计时 |
2. 叫分或不叫(jiaofen,客户端→服务器)
发包者:游戏 收包者:服务器 app:youle route:erqiwang rpc:jiaofen
| 参数名 | 类型 | 说明 |
|---|---|---|
| agentid | 字符 | 代理id |
| playerid | 整数 | 玩家id |
| gameid | 字符 | 游戏id |
| roomcode | 整数 | 房间号 |
| seat | 整数 | 叫分者的位置序号 |
| call | 整数 | 分数,0表示不叫 |
3. 叫分或不叫(jiaofen,服务器→客户端)
发包者:服务器 收包者:游戏 app:youle route:erqiwang rpc:jiaofen
| 参数名 | 类型 | 说明 |
|---|---|---|
| seat | 整数 | 叫分者的位置序号 |
| call | 整数 | 分数,0表示不叫 |
| currcall | 整数 | 当前叫到的分数 |
| 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 | 整数 | 下一个叫分者的位置序号 |
| countdown | 整数 | 叫分倒计时 |
4. 上庄(shangzhuang)
发包者:服务器 收包者:游戏 app:youle route:erqiwang rpc:shangzhuang
| 参数名 | 类型 | 说明 |
|---|---|---|
| seat | 整数 | 叫分者的位置序号 |
| call | 整数 | 分数,0表示不叫 |
| banker | 整数 | 庄家的位置序号 |
| grade | 整数 | 庄家的叫分 |
| 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 张底牌(发牌时没发给玩家、扣在桌面的 8 张)。庄家恒有;闲家仅当 70 分坐庄时才有(供 3 秒亮牌用),非 70 分时闲家没有该属性(底牌只有庄家可见,design §4)。 顺序在发牌结束时即冻结(服务端 paiju.bottomcards,按「还没有主牌」的口径排一次):底牌是在选主之前翻给庄家看的,那时主牌花色尚不存在,故不按主牌花色排。本包与重连包 ChooseMain.bottomcards / BuryCards.bottomcards 三处同序,客户端存一次即可全程复用(含「查底牌」回看) |
| ancard3s | 整数 | 开底标志。仅 70 分坐庄时出现且为 1:表示庄家摸底之前,需将 bottomcards 这 8 张底牌向所有玩家翻开 3 秒(design §4/§7.1);非 70 分无此属性 |
| cards | 数组 | 拿了底牌后手上的牌(36 张,含底牌),庄家才有此属性,闲家没有该属性 |
| countdown | 整数 | 选主倒计时 |
| touxiang | 整数 | 是否允许投降 0:不允许 1:允许(仅 70 分坐庄为 1)。投降与选主互斥、同为选主阶段(step2)的决策,见 touxiang 包与 design §4 |
| curmultiple | 整数 | 当前抓分倍数(design §7.2.0):按此刻累计捡分实时算出的判定倍率,带符号,与结算包 aset.upgrade 同口径——3/2/1 = 庄家 大光/小光/过庄,-N = 闲家升 N 级,0 = 叫分未定。上庄时捡分恒为 0,故必为 3。三家同值(捡分本就公开)。不含扣底——扣底要到末轮才产生。顶部「抓分」角标只关心倍数大小,取 Math.abs 即可;符号供客户端的判定动画分辨该播哪个(不能取绝对值,否则 3 大光与 -3 升3级会撞在一起) |
5. 投降(touxiang,客户端→服务器)
发包者:游戏 收包者:服务器 app:youle route:erqiwang rpc:touxiang
| 参数名 | 类型 | 说明 |
|---|---|---|
| agentid | 字符 | 代理id |
| playerid | 整数 | 玩家id |
| gameid | 字符 | 游戏id |
| roomcode | 整数 | 房间号 |
| seat | 整数 | 庄家的位置序号。投降是选主阶段(step 2)与选主互斥的选择:mod.touxiang 仅在 step==2、banker==seat、call==70 时受理;点投降即直接结算,不选主、不埋牌、不出牌(design §4) |
6. 选主(xuanzhu,客户端→服务器)
发包者:游戏 收包者:服务器 app:youle route:erqiwang rpc:xuanzhu
| 参数名 | 类型 | 说明 |
|---|---|---|
| agentid | 字符 | 代理id |
| playerid | 整数 | 玩家id |
| gameid | 字符 | 游戏id |
| roomcode | 整数 | 房间号 |
| seat | 整数 | 选主者的位置序号 |
| flower | 整数 | 花色 1方块 2梅花 3红心 4黑桃 |
7. 选主(xuanzhu,服务器→客户端)
发包者:服务器 收包者:游戏 app:youle route:erqiwang rpc:xuanzhu
| 参数名 | 类型 | 说明 |
|---|---|---|
| banker | 整数 | 庄家的位置序号 |
| flower | 整数 | 花色 1方块 2梅花 3红心 4黑桃 |
| countdown | 整数 | 埋牌倒计时 |
| cards | 数组 | 选主后自己手上的牌id列表 |
8. 埋牌(maipai,客户端→服务器)
发包者:游戏 收包者:服务器 app:youle route:erqiwang rpc:maipai
| 参数名 | 类型 | 说明 |
|---|---|---|
| agentid | 字符 | 代理id |
| playerid | 整数 | 玩家id |
| gameid | 字符 | 游戏id |
| roomcode | 整数 | 房间号 |
| seat | 整数 | 埋牌者的位置序号 |
| cards | 数组 | 埋牌的id列表 |
9. 埋牌(maipai,服务器→客户端)
发包者:服务器 收包者:游戏 app:youle route:erqiwang rpc:maipai
| 参数名 | 类型 | 说明 |
|---|---|---|
| cards | 数组 | 埋牌后手上的牌,去掉了埋牌,庄家才有此属性,闲家没有该属性 |
| burycards | 数组 | 埋牌底牌(庄家埋下的 8 张),庄家才有此属性,闲家没有该属性。注意与 shangzhuang.bottomcards(底牌,发牌留桌 8 张)是两批不同的牌,见 §0.0。取服务端权威快照 get_burycard(),不是客户端请求包里 cards 的原序:按本局主牌花色从大到小排好,与重连包 PushCards.burycards 同源同序 |
| seatlist | 数组 | 三家座位牌况,仅可查牌模式下发(不查牌无此属性,design §9),结构与门控同 chupai1/2/3.seatlist 与重连包 PushCards.seatlist。埋牌完成时它是刚初始化的空表(每家 [[0,0],[0,0],[0,0],[0,0],[-1,-1]])——下发它是为了让「埋牌完成 → 庄家首出」这段窗口内,增量路径与重连路径拿到同一张表,客户端无需为这段窗口特判 |
| seat | 整数 | 出牌者的位置序号(即将首出的庄家) |
| countdown | 整数 | 出牌倒计时 |
| liangpai | json | 亮牌(design §8.2)。只有闲家、且可查牌模式、且庄家达门槛时才有;不达标或不查牌则无此属性。结构:{ cards: [牌id...] }——庄家手中全部固定主牌的具体牌面,按本局主牌序从大到小排好。固定主牌 = 双王 + 全部花色的 2 + 全部花色的 7,不含主花色的普通牌 A/K/Q/J/10/9/8/6/5。 门槛(任一满足即下发):固定主牌总数 ≥10 / 王 ≥3 / 7 ≥6 / 2 ≥6。不限叫分。 亮出的是固定的一份,不随被哪条门槛触发而增减;也不给数量统计——数量前端自己数 cards.length 即可。口径是庄家埋牌后的静态快照(排除已埋的 8 张,但包含之后已打出的牌),全局固定不随出牌缩水,故重连包里取值一致 |
10. 出牌(chupai,客户端→服务器)
发包者:游戏 收包者:服务器 app:youle route:erqiwang rpc:chupai
| 参数名 | 类型 | 说明 |
|---|---|---|
| agentid | 字符 | 代理id |
| playerid | 整数 | 玩家id |
| gameid | 字符 | 游戏id |
| roomcode | 整数 | 房间号 |
| seat | 整数 | 出牌者的位置序号 |
| cards | 数组 | 出牌的id列表 |
11. 第一个玩家出牌(chupai1)
发包者:服务器 收包者:游戏 app:youle route:erqiwang rpc:chupai1
| 参数名 | 类型 | 说明 |
|---|---|---|
| seat | 整数 | 出牌者的位置序号 |
| cards | 数组 | 实际打出的牌id列表;甩错时(见 shuaicuo)为被强制打出的那一张最小主牌单张 |
| shuaicuo | 整数 | 甩错标志,仅甩错时出现且为 1(design §5.4.5:甩牌未通过最大性判定,整套甩牌收回,本轮只强制打出最小一张、失去本轮甩牌资格);正常出牌无此属性 |
| seatlist | 数组 | 三家座位牌况 o_paiju.seatlist(长度 3,下标 = 座位序号),仅可查牌模式下发(不查牌无此属性,design §9)。每个座位为 5 元素数组:前 4 个对应花色1~4 的 [无该花色标志, 该花色无对标志](0/1),第 5 个为余主公示数据 [剩余主牌数, 剩余主对数](初始 [-1,-1],代码内旧称「报副」)。一旦全场有人报无主,服务端会按各家实际手牌同时刷新三个座位并整表下发(design §9「为全体三人显示另外两家」),无需等另两家各自出牌才补。字段名与结构同重连包 PushCards.seatlist |
| count | 整数 | 出牌数量(甩错时为 1) |
| flower | 整数 | 出牌花色 |
| 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 | 整数 | 下一个出牌者的位置序号 |
| countdown | 整数 | 下一个出牌者的出牌倒计时 |
| baozhu | 整数 | 是否已有玩家报无主(主牌出空)0否 1是;对应服务端 have_baofu()(任一玩家 seatlist[seat][4][0]==0)。仅可查牌模式下才可能为 1,是余主公示与"明牌"按钮的开关;不查牌模式恒为 0(design §9) |
| cardsinhand | 数组 | 出牌者出牌后手上剩下的牌id列表,只有出牌者才有此属性 |
| curmultiple | 整数 | 当前抓分倍数(design §7.2.0):带符号,与结算包 aset.upgrade 同口径(3/2/1 庄家大光/小光/过庄,-N 闲家升 N 级,0 叫分未定)。同源同算法,差别仅在此处不含扣底。三家同值,随本包下发、不另开推送。符号是「谁赢」的区分,客户端判定动画靠它分辨 |
| playproc | json | 本轮进行态(design §5.1)。chupai1/2/3 三个包恒有,三家同值;结构与重连包 PushCards.playproc 完全一致(服务端同一个快照函数 get_playproc(),前端增量回放与重连重建复用同一份解析)。字段: round 第几轮、start 本轮首出位置、currseat 当前该谁出、startcount 首出张数、startflower 首出花色、starttype 首出牌型、maxseat 本轮暂时最大者、maxcard 其牌编码、cards 本轮三家各自出的牌(定长 3,下标 = 座位序号,未出的位置为 null)、shuai_demand 首家甩牌的分量需求 {tractors:[连对数...],pairs,singles}(非甩牌为 null)。⚠️ chupai3 带的是【下一轮】的进行态(round+1、cards 全空、currseat == nextseat == maxseat):本轮第三家一出完,服务端就地开了新一轮。这与「此刻断线重连拿到的 PushCards.playproc」完全相同——本轮那三手牌客户端已由 chupai1/2/3 各自的 seat+cards 收到,收牌动画后即清台。唯一例外:chupai3 打完最后一张牌时本包会转成 jiesuan(见 §14),那种情况下不带 playproc。可见性:全部字段都由桌面公开信息推出( cards 就是已摊在桌上的牌,shuai_demand 与 chupai1.shuai 等价且甩出的牌本身已公开),故三家整体下发、不逐座位裁剪 |
| mustcard | 数组 | 下一个出牌者本轮跟牌的必出牌(design §5.2),供其客户端自动选中。只发给 nextseat 那一家,其余两家无此属性——它是该玩家自己手牌的子集,整表下发会泄露他家手牌结构。以下情形不下发:nextseat 是本轮首家、首家为甩牌(甩牌跟牌走逐分量匹配,见 design §5.4.4)、或算出的必出牌为空 |
12. 第二个玩家出牌(chupai2)
发包者:服务器 收包者:游戏 app:youle route:erqiwang rpc:chupai2
| 参数名 | 类型 | 说明 |
|---|---|---|
| seat | 整数 | 出牌者的位置序号 |
| cards | 数组 | 出的牌id列表 |
| seatlist | 数组 | 三家座位牌况 o_paiju.seatlist(长度 3,下标 = 座位序号),仅可查牌模式下发(不查牌无此属性,design §9)。每个座位为 5 元素数组:前 4 个对应花色1~4 的 [无该花色标志, 该花色无对标志](0/1),第 5 个为余主公示数据 [剩余主牌数, 剩余主对数](初始 [-1,-1],代码内旧称「报副」)。一旦全场有人报无主,服务端会按各家实际手牌同时刷新三个座位并整表下发(design §9「为全体三人显示另外两家」),无需等另两家各自出牌才补。字段名与结构同重连包 PushCards.seatlist |
| nextseat | 整数 | 下一个出牌者的位置序号 |
| countdown | 整数 | 出牌倒计时 |
| baozhu | 整数 | 是否已有玩家报无主(主牌出空)0否 1是;对应服务端 have_baofu()(任一玩家 seatlist[seat][4][0]==0)。仅可查牌模式下才可能为 1,是余主公示与"明牌"按钮的开关;不查牌模式恒为 0(design §9) |
| cardsinhand | 数组 | 出牌后出牌者手上剩下的牌id列表,只有出牌者才有此属性 |
| playproc | json | 本轮进行态,恒有、三家同值,结构见 §11 playproc。此时 cards 已含首家与本家两手牌,currseat 指向第三家 |
| mustcard | 数组 | 下一个出牌者本轮跟牌的必出牌(design §5.2),供其客户端自动选中。只发给 nextseat 那一家,其余两家无此属性——它是该玩家自己手牌的子集,整表下发会泄露他家手牌结构。以下情形不下发:nextseat 是本轮首家、首家为甩牌、或算出的必出牌为空 |
13. 第三个玩家出牌(chupai3)
发包者:服务器 收包者:游戏 app:youle route:erqiwang rpc:chupai3
| 参数名 | 类型 | 说明 |
|---|---|---|
| seat | 整数 | 出牌者的位置序号 |
| cards | 数组 | 出的牌id列表 |
| seatlist | 数组 | 三家座位牌况 o_paiju.seatlist(长度 3,下标 = 座位序号),仅可查牌模式下发(不查牌无此属性,design §9)。每个座位为 5 元素数组:前 4 个对应花色1~4 的 [无该花色标志, 该花色无对标志](0/1),第 5 个为余主公示数据 [剩余主牌数, 剩余主对数](初始 [-1,-1],代码内旧称「报副」)。一旦全场有人报无主,服务端会按各家实际手牌同时刷新三个座位并整表下发(design §9「为全体三人显示另外两家」),无需等另两家各自出牌才补。字段名与结构同重连包 PushCards.seatlist |
| nextseat | 整数 | 下一个出牌者的位置序号 |
| countdown | 整数 | 出牌倒计时 |
| baozhu | 整数 | 是否已有玩家报无主(主牌出空)0否 1是;对应服务端 have_baofu()(任一玩家 seatlist[seat][4][0]==0)。仅可查牌模式下才可能为 1,是余主公示与"明牌"按钮的开关;不查牌模式恒为 0(design §9) |
| cardsinhand | 数组 | 出牌后出牌者手上剩下的牌id列表,只有出牌者才有此属性 |
| maxseat | 整数 | 本轮出牌谁最大,只有本轮最后一个玩家出牌后才有此属性 |
| grade | 整数 | 本轮闲家得分,只有本轮最后一个玩家出牌后且闲家有得分才有此属性 |
| curmultiple | 整数 | 当前抓分倍数(design §7.2.0):带符号,口径同 aset.upgrade。同源同算法,差别仅在此处不含扣底。三家同值,随本包下发、不另开推送 |
| playproc | json | 本轮进行态,三家同值,结构见 §11 playproc。⚠️ 本包带的是下一轮的进行态(round+1、cards 全空、currseat == nextseat == maxseat),与此刻重连拿到的 PushCards.playproc 一致。牌局在本包打完(转为 jiesuan)时不带此属性 |
13.5 明牌(mingpai,客户端→服务器)
发包者:游戏 收包者:服务器 app:youle route:erqiwang rpc:mingpai
查看另外两家手中全部主牌的具体牌面(design §9)。服务端仅在可查牌模式、出牌阶段(step5)、且已有【任一】玩家报无主(have_baofu())时受理——注意判定的是「场上有人报无主」而非「请求者本人报无主」,报无主那位与另外两位同样有权查看(design §9.3);不满足时按 0.2 回 mingpai 失败包(不查牌 / 未报无主 → RULE,非出牌阶段 → STEP)。
| 参数名 | 类型 | 说明 |
|---|---|---|
| agentid | 字符 | 代理id |
| playerid | 整数 | 玩家id |
| gameid | 字符 | 游戏id |
| roomcode | 整数 | 房间号 |
| seat | 整数 | 请求者的位置序号 |
13.6 明牌(mingpai,服务器→客户端)
发包者:服务器 收包者:游戏 app:youle route:erqiwang rpc:mingpai (只回发给请求者)
| 参数名 | 类型 | 说明 |
|---|---|---|
| seat | 整数 | 请求者的位置序号 |
| others | 数组 | 另外两家各自未出的全部主牌,元素 { seat: 位置序号, zhucards: [主牌id列表] } |
"再点一次取消查看"是客户端的显示开关,无需再请求服务端。
13.7 出牌提示(tishi,客户端→服务器)
发包者:游戏 收包者:服务器 app:youle route:erqiwang rpc:tishi
闲家在出牌阶段向对家(另一闲家)发"踩/没分/有分"提示(design §11)。服务端仅在出牌阶段(step5)、且发起者为闲家(seat != banker)、tip 合法(1/2/3) 时受理;不校验提示真实性(玩家可主观发送);庄家无对家,不受理。不满足时按 0.2 回 tishi 失败包给发送者(庄家发 → RULE,非出牌阶段 → STEP,tip 非法或缺失 → PARAM)。成功时不给发送者回执,只转发给对家。
| 参数名 | 类型 | 说明 |
|---|---|---|
| agentid | 字符 | 代理id |
| playerid | 整数 | 玩家id |
| gameid | 字符 | 游戏id |
| roomcode | 整数 | 房间号 |
| seat | 整数 | 发出提示的闲家位置序号 |
| tip | 整数 | 提示类型:1=踩(我能大过庄家)、2=没分(我手上没分了)、3=有分(我手上有分) |
13.8 出牌提示(tishi,服务器→客户端)
发包者:服务器 收包者:游戏 app:youle route:erqiwang rpc:tishi (只转发给对家,即另一闲家 3 - banker - seat)
| 参数名 | 类型 | 说明 |
|---|---|---|
| seat | 整数 | 发出提示的闲家位置序号 |
| tip | 整数 | 提示类型:1=踩、2=没分、3=有分 |
14. 结算(jiesuan)
发包者:服务器 收包者:游戏 app:youle route:erqiwang rpc:jiesuan
结算包由以下几个子结构拼装而成。三种结算来源的组成不同:
- 正常出牌结算(
mod.chupai中最后一张牌出完,get_paiju_account(0, ...)):含chupai+bottom+aset(末局再加account)。 - 投降结算(
mod.touxiang,get_paiju_account(1, ...)):只含aset(末局再加account),无chupai、无bottom。 - 解散结算(
export.get_disbandRoom,get_paiju_account(2, ...)):只含aset+account,无chupai、无bottom。投递方式与上面两种不同,见 §14.1。
上面这张表头(route: erqiwang / rpc: jiesuan)只适用于前两种——正常出牌结算与投降结算,由子游戏自己 sendpack_toother 广播,客户端在 rpc == "jiesuan" 的分支里按 data.aset 取值。
14.1 解散结算的投递方式(与前两种不同,客户端需单独处理)
解散不是由子游戏发包,而是平台在解散流程里回调 youle_erqiwang.export.get_disbandRoom(o_room),把返回值整个对象塞进房间路由的解散包里下发(平台 server_room/rpc.js、server_room/class.room.js)。因此客户端收到的是:
{
"app": "youle", "route": "room", "rpc": "free_room",
"data": {
"seats": [],
"deskfree": {
"rpc": "jiesuan",
"data": { "success": true, "aset": {}, "account": [] }
}
}
}
要点(照 §14 的表去 data.aset 取值会取空):
- rpc 是平台的
free_room(route 也是room),不是erqiwang/jiesuan;子游戏返回的rpc: "jiesuan"只是嵌在deskfree里的一个普通字段。 - 多一层
data包装:真实取值路径是data.deskfree.data.aset与data.deskfree.data.account。 - 本包的成败标志有两层:外层
data.success由平台填写(解散流程本身成功与否),子游戏结算自带的success在data.deskfree.data.success。§0.1「每个包data必带success」说的是子游戏自己发的包;本包外层归平台。 aset/account的字段结构与下面 §14 的表完全一致(aset.multiple = 0、upgrade = 0、各家grade = 0,即解散局不结算子数与算奖;account恒有,见 design §12.2「按当前累计分结算」)。- 若解散发生在开战后、首局牌发出前的窗口内(本游戏首局由
makewar延迟 1 秒创建),get_disbandRoom返回null,平台走「不带deskfree」分支——客户端需容忍data.deskfree缺失。
chupai(出牌包,仅正常出牌结算存在)
| 参数名 | 类型 | 说明 |
|---|---|---|
| seat | 整数 | 出牌者的位置序号,投降和解散无此属性 |
| cards | 数组 | 出的牌id列表,投降和解散无此属性 |
| maxseat | 整数 | 本轮出牌谁最大,投降和解散无此属性 |
| grade | 整数 | 本轮闲家得分,投降和解散无此属性 |
| gradecards | 数组 | 本轮闲家得分分牌列表,投降和解散无此属性。注意:当前源码中赋值语句被注释(class.paiju.js/mod.js 中相关行均被注释掉),该字段实际永远不会出现在下发的包里,属于失效字段 |
bottom(抠底包,仅正常出牌结算存在;cards 恒有,其余仅闲家抠底时有)
本分组的
cards是埋牌底牌(庄家埋下的 8 张),不是发牌留桌的底牌。
| 参数名 | 类型 | 说明 |
|---|---|---|
| cards | 数组 | 埋牌底牌(庄家埋下的 8 张),投降和解散无此属性 |
| multiple | 整数 | 闲家抠底倍数,闲家没抠底无此属性,投降和解散无此属性 |
| grade1 | 整数 | 埋牌底牌的分数,闲家没抠底无此属性,投降和解散无此属性 |
| grade2 | 整数 | 闲家抠底得分,闲家没抠底无此属性,投降和解散无此属性 |
aset(单局结算包)
| 参数名 | 类型 | 说明 |
|---|---|---|
| banker | 整数 | 庄家的位置序号,-1:无庄 |
| call | 整数 | 庄家叫分,-1:无叫分 |
| multiple | 整数 | 基础子数 get_base_bycall(call, climb)(design §7.1/§7.3.1):常规算子 65→2、60→3、55→4、50 及以下→6、70打牌→2;投降固定 1、解散 0;无叫分 0 |
| flower | 整数 | 主牌花色,-1:无主牌花色 |
| grade | 整数 | 闲家捡分(含抠底) |
| upgrade | 整数 | 判定倍率(带符号,design §7.2.0):3大光 / 2小光 / 1过庄 / -N升N级(倒庄)/ -99投降 / 0解散或无判定 |
| bangwang | 整数 | 本局是否启用傍王规则 0否 1是(roomtype 位2) |
| climb | 整数 | 本局是否启用爬坡规则 0否 1是(roomtype 位3) |
| seatlist | 数组 | 玩家列表,元素结构见下 |
seatlist 数组元素结构:
{
"cards": [], // 冲关牌型:参与冲关的牌(王 + 冲关组合牌)列表,供「冲关牌型」界面展示
"chongguan": 0, // 冲关奖数(design §8.1,旧称"常规算奖";只有庄家才计入自己的 N)
"wang": 0, // 手牌中的王数(傍王按此计奖)
"naward": 0, // 该家总奖数 N =(庄家?冲关奖数:0)+(傍王?王数:0)
"grade_aw": 0, // 算奖得分 = X×(2Ni−Nj−Nk),X 为每对子子数。= grade_cg + grade_bw
"grade_cg": 0, // 其中的【冲关】分量(design §8.1,不含傍王)
"grade_bw": 0, // 其中的【傍王】分量(design §8.3;未勾傍王时恒 0)
"grade_jf": 0, // 捡分子数得分
"grade": 0, // 本局总分 = grade_aw + grade_jf
"score": 0 // 累计得分
}
结算数值模型(design §7~§8):每「庄–闲」对子的基础金额
X = multiple × |upgrade|(投降 X=1、解散 X=0)。捡分子数:庄赢时两闲家各付庄家 X、庄家收 2X;闲赢(升级)时庄家各付两闲家 X。算奖:持有 N 奖的玩家从另外两人各多收X×N,三家两两独立叠加(含闲–闲),即grade_aw = X×(2Ni−Nj−Nk)。算奖的两个分量(供大局结算分项展示):
N = N_冲关 + N_傍王(冲关只计庄家、傍王勾选后庄闲都算)。 服务端把两个分量分别代入同一公式各算一次,得到grade_cg与grade_bw。 公式对N是线性的,因此恒有grade_cg + grade_bw == grade_aw,且两个分量各自零和。 之所以必须在算钱时就拆,是因为两个N一旦相加就再也分不开——事后无法从grade_aw反推各自占比。
account(大局结算包)
仅当打到最后一局(
o_paiju.idx >= o_room.asetcount)或房间中途解散(解散结算)时,jiesuan包才会带上此分组;普通的中间局结算包没有account字段(class.paiju.jsget_paiju_account)。
| 参数名 | 类型 | 说明 |
|---|---|---|
| account | 数组 | 玩家列表(长度 3,下标 = 座位序号),元素结构见下 |
[
{ "score": 0, "grades": [], "grade_jf_total": 0, "grade_cg_total": 0, "grade_bw_total": 0 },
{ "score": 0, "grades": [], "grade_jf_total": 0, "grade_cg_total": 0, "grade_bw_total": 0 },
{ "score": 0, "grades": [], "grade_jf_total": 0, "grade_cg_total": 0, "grade_bw_total": 0 }
]
| 字段 | 类型 | 说明 |
|---|---|---|
| score | 整数 | 累积总分(全部小局 aset.seatlist[i].grade 之和) |
| grades | 数组 | 每局总分列表,按局序 |
| grade_jf_total | 整数 | 基础分累计:各局 grade_jf(捡分子数得分)之和 |
| grade_cg_total | 整数 | 冲关分累计:各局 grade_cg 之和(design §8.1,不含傍王) |
| grade_bw_total | 整数 | 傍王分累计:各局 grade_bw 之和(design §8.3;未勾傍王时恒 0) |
恒等式:
grade_jf_total + grade_cg_total + grade_bw_total == score,供大局结算面板分项展示(基础分 / 冲关分 / 傍王分 / 总分)。⚠️ 结构变更(2026-08-26):原为
[[累积得分, [每局得分...]], ...]的二元数组,现改为对象数组并增加三项分解。数组下标语义不清,且前端尚未开工,此时改代价最小。
15. 准备(zhunbei,客户端→服务器)
发包者:游戏 收包者:服务器 app:youle route:erqiwang rpc:zhunbei
| 参数名 | 类型 | 说明 |
|---|---|---|
| agentid | 字符 | 代理id |
| playerid | 整数 | 玩家id |
| gameid | 字符 | 游戏id |
| roomcode | 整数 | 房间号 |
| seat | 整数 | 位置序号 |
16. 准备(zhunbei,服务器→客户端)
发包者:服务器 收包者:游戏 app:youle route:erqiwang rpc:zhunbei
| 参数名 | 类型 | 说明 |
|---|---|---|
| seat | 整数 | 位置序号 |
断线重连(deskinfo)
由平台在玩家进入房间/断线重连时回调
youle_erqiwang.export.get_deskinfo(o_room, seat)生成并下发(服务器→客户端);下发的 app/route/rpc 由平台的进房/重连流程决定,不在本子游戏代码内固定。平台把它挂在pack.data.deskinfo下,data.success由平台填写、子游戏不注入(见 0.4)。下列字段即该函数返回的deskinfo对象结构,按当前paiju.step只带对应阶段的分组。
| 参数名 | 类型 | 说明 |
|---|---|---|
| count | 整数 | 总局数 |
| idx | 整数 | 当前局数 |
| PlayerInfo | 数组 | 三个玩家目前的总积分 [0,0,0] |
| step | 整数 | 牌桌状态:1发完牌叫分 2选主/投降 3埋牌 5出牌 6结算(无独立投降阶段——投降在 step2 与选主互斥;埋牌后直接进入 step5 出牌) |
| MyCards | 数组 | 自己手上的牌 |
CallRun(不在叫分阶段无此属性)
| 参数名 | 类型 | 说明 |
|---|---|---|
| seat | 整数 | 当前叫分位置 |
| countdown | 整数 | 叫分倒计时 |
| nowcall | 整数 | 当前叫分 |
| 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叫了多少分 |
ChooseMain(step 2 选主/投降阶段,不在此阶段无此属性)
| 参数名 | 类型 | 说明 |
|---|---|---|
| banker | 整数 | 庄家 |
| call | 整数 | 叫分 |
| 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 | 整数 | 选主倒计时 |
| bottomcards | 数组 | 8 张底牌(发牌留桌的 8 张),只有庄家有此属性(底牌仅庄家可见;70 分的 3 秒亮牌是上庄时的一次性事件,重连不重放)。顺序取发牌时冻结的快照,与 shangzhuang.bottomcards、BuryCards.bottomcards 完全同序(见 §4) |
| touxiang | 整数 | 是否允许投降 0:不允许 1:允许(仅 70 分坐庄为 1)。投降与选主互斥、同一决策点,见 touxiang 包与 design §4 |
| curmultiple | 整数 | 当前抓分倍数(design §7.2.0):带符号,与 shangzhuang.curmultiple 同源同值。选主阶段一张牌都还没出、捡分恒为 0,故必为 3(大光)。三家同值。有此字段,重连后顶部「抓分」角标才不会掉回 0 |
选主阶段前端需在每个花色按钮上显示"该花色在庄家手中的对子数"(design §4/§11)——庄家的完整手牌由
MyCards提供(庄家为 36 张),对子数由前端据此计算,服务端不额外下发。
BuryCards(step 3 埋牌阶段,不在此阶段无此属性)
| 参数名 | 类型 | 说明 |
|---|---|---|
| banker | 整数 | 庄家 |
| call | 整数 | 叫分 |
| 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 | 整数 | 主牌花色 |
| countdown | 整数 | 埋牌倒计时 |
| bottomcards | 数组 | 8 张底牌(发牌留桌的 8 张),只有庄家有此属性(底牌仅庄家可见;70 分的 3 秒亮牌是上庄时的一次性事件,重连不重放)。顺序取发牌时冻结的快照,与 shangzhuang.bottomcards、ChooseMain.bottomcards 完全同序——不按本局主牌花色重排(见 §4) |
| curmultiple | 整数 | 当前抓分倍数(design §7.2.0):带符号,与 shangzhuang.curmultiple 同源同值。埋牌阶段同样一张牌未出、捡分恒为 0,故必为 3(大光)。三家同值 |
埋牌阶段无投降(投降是 step2 与选主互斥的选择,选主后即不可再投降)。
PushCards(step 5 出牌阶段,不在此阶段无此属性)
| 参数名 | 类型 | 说明 |
|---|---|---|
| banker | 整数 | 庄家 |
| call | 整数 | 叫分 |
| 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 | 整数 | 主牌花色 |
| countdown | 整数 | 出牌倒计时 |
| burycards | 数组 | 埋牌底牌(庄家埋下的 8 张),只有庄家有此属性。注意与 ChooseMain/BuryCards.bottomcards(底牌)是两批不同的牌,见 §0.0。与 maipai.burycards 同源同序(同一个 get_burycard(),按本局主牌花色从大到小) |
| grade | 整数 | 当前的捡分分数 |
| gradecards | 数组 | 当前的捡分分牌,只有闲家有此属性 |
| playproc | json | 本轮进行态,与 chupai1/2/3.playproc 同源同结构(服务端同一个 get_playproc() 快照函数,见 §11 playproc):round 第几轮、start 本轮首出位置、currseat 当前出牌位置、startcount 首出张数、startflower 首出花色、starttype 首出牌型、maxseat 本轮最大者位置、maxcard 最大牌编码、cards 本轮三家各自出的牌(定长 3,下标=位置序号,未出为 null)、shuai_demand 首家甩牌的分量需求 {tractors:[连对数...],pairs,singles}(非甩牌为 null,供跟牌逐分量强制匹配,design §5.4.4)。两种查牌模式下恒有此属性——cards 是当前这一轮桌面上的牌,不属于「查牌」,屏蔽了后出的人就无从跟牌(design §9 末尾) |
| seatlist | 数组 | 三家座位牌况,与上文 maipai / chupai1/2/3 包的 seatlist 同名同结构(每个玩家一个 5 元素数组:4 个花色的 [无该花色,无对] + 报副 [剩余主牌数,剩余主对数])。仅可查牌模式下有此属性(design §9) |
| liangpai | json | 亮牌,结构同 maipai 包的 liangpai({ cards: [牌id...] });仅可查牌模式、且请求者为闲家、且庄家达标时有(供闲家重连后仍能看到,design §8.2) |
| pushlist | 数组 | 出牌历史 [[[], [], []], [[], [], []], ...],外层下标=轮次(从第 1 轮起,含进行中的当前轮),内层恒为 3 个数组、按位置序号存该轮各家出的牌id,各自已按本局主牌花色从大到小排序。仅可查牌模式下有此属性——往轮打出、已被收走的牌属于「查牌」范畴,不查牌模式一律不下发(design §9)。注意当前这一轮桌面上的牌由 playproc.cards 恢复,两种模式下都有,否则后出的人无从跟牌 |
| curmultiple | 整数 | 当前抓分倍数(design §7.2.0):带符号,与 chupai1/2/3 同源同值,供重连后顶部「抓分」角标与判定动画状态立即正确 |
| mustcard | 数组 | 本轮跟牌的必出牌(design §5.2)。仅当 playproc.currseat == 请求者座位 时才有,且只算请求者自己的手牌;未轮到本家、本轮首家、甩牌局面、必出牌为空时均无此属性 |
Balance(不在结算阶段无此属性)
| 参数名 | 类型 | 说明 |
|---|---|---|
| readystate | 数组 | 所有玩家的准备状态 |
| aset | json | 单局结算包,同上面结算包中的 aset,只有当自己的准备状态为0时才有此属性 |
战绩(大局列表)gameinfo1
非客户端收发包:大局结束/解散时由
class.desk.jsget_desk_account组装,经import.save_grade(o_room, o_gameinfo1, o_gameinfo2, 1)传给平台战绩服务持久化(服务器→平台)。
| 参数名 | 类型 | 说明 |
|---|---|---|
| roomcode | 整数 | 房号 |
| asetcount | 整数 | 实际局数 |
| createtime | 字符 | 开房时间 |
| makewartime | 字符 | 开战时间 |
| players | 数组 | 玩家列表,元素结构见下 |
players 数组元素结构:
{
"seat": 0, // 座位
"playerid": 100001, // 玩家ID
"name": "", // 昵称
"avatar": "", // 头像
"score": 0 // 成绩
}
战绩(大局)gameinfo2
非客户端收发包:与 gameinfo1 同批,由
import.save_grade的第 3 个参数传给平台战绩服务(服务器→平台)。
牌局列表,数组元素结构:
{
"starttime": "", // 开始时间
"endtime": "", // 结束时间
"seatlist": [6, -6, 0], // 玩家成绩
"callproc": [], // 叫分过程,详情见代码中的注释
"banker": 0, // 庄
"call": 0, // 叫分
"flower": 0, // 主牌花色
"result": 0, // 牌局结果
"cards": [] // 发牌出牌情况,详情见代码中的注释
}