二七王:补齐 data.success 成败标志与失败回包
此前全仓(除协议文档开头一句说明外)没有任何下发包携带 data.success,且所有失败路径一律裸 return、不回任何包:前端点了 没反应,只能干等倒计时,同时违反 server dev-guide「成败标志唯一 是 data.success,主动推送的 data 必须自带 success」与 client dev-guide「发包只请求、收包才表现」两条硬红线。 本次: - 成功包一律补 data.success=true:fapai、zhunbei(class.desk.js)、 jiaofen、shangzhuang、xuanzhu、maipai、chupai1/2/3、mingpai、 tishi(mod.js),jiesuan 在 get_paiju_account 统一注入(覆盖 正常/投降/解散三种结算来源)。 - 新增 youle_erqiwang.ERR 失败码表与 do_sendfail 统一回包封装: PLAYER/NODESK/STEP/SEAT/PARAM/RULE,失败只回发给请求者 (conmode/fromid 取自请求包),data.success=false + errcode。 - 每个 handler 的每条失败分支都改为「回失败包 + return」,含 check_player 不通过(平台侧只返回 null、不回包,前端会干等)。 tishi 成功时仍按 design §11 只转发给对家、不给发送者回执(该包不 含对局状态,属 fire-and-forget 提示),失败才回给发送者。 test_rpc 中原先以「不发包」表示被拒的断言,同步改为断言「恰好回 1 个 success=false 且 errcode 正确的包」——是随行为修正而加强, 不是软化。新增 test_success.js 29 项覆盖成功包 success 字段与各 handler 失败回包。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,10 @@ const t = require('./_assert')();
|
||||
|
||||
const pack = (seat, extra) => Object.assign({ data: Object.assign({ agentid: 'a', playerid: 1, gameid: 'g', roomcode: 1, seat }, extra), conmode: 0, fromid: seat });
|
||||
|
||||
// 被拒 = 恰好回 1 个失败包给请求者(data.success=false + errcode),不再是"静默不发包"
|
||||
const ERR = mod.ERR;
|
||||
const rej = (c, errcode) => c.sent.length === 1 && c.sent[0].data.success === false && c.sent[0].data.errcode === errcode;
|
||||
|
||||
// ===================== §9 明牌 mingpai =====================
|
||||
const dealMP = [[id(1, 1, 13), 2], [id(1, 1, 12), 3]]; // seat1 主K, seat2 主Q
|
||||
const mkMP = (step, baofu) => ({ step, banker: 0, flower: 1, cards: make108(dealMP), method: { have_baofu: () => baofu } });
|
||||
@@ -14,11 +18,11 @@ mod.mingpai(pack(0));
|
||||
t.eq('明牌 合法 下发1包', ctx.sent.length, 1);
|
||||
t.eq('明牌 others=他家主牌', ctx.sent[0] && ctx.sent[0].data.others, [{ seat: 1, zhucards: [id(1, 1, 13)] }, { seat: 2, zhucards: [id(1, 1, 12)] }]);
|
||||
ctx = setup("00001", mkMP(5, true)); mod.mingpai(pack(0)); // 不查牌(位4=1)
|
||||
t.eq('明牌 不查牌 拒', ctx.sent.length, 0);
|
||||
t.eq('明牌 不查牌 拒(回失败包RULE)', rej(ctx, ERR.RULE), true);
|
||||
ctx = setup("00000", mkMP(5, false)); mod.mingpai(pack(0)); // 未报无主
|
||||
t.eq('明牌 未报无主 拒', ctx.sent.length, 0);
|
||||
t.eq('明牌 未报无主 拒(回失败包RULE)', rej(ctx, ERR.RULE), true);
|
||||
ctx = setup("00000", mkMP(3, true)); mod.mingpai(pack(0)); // 非出牌阶段
|
||||
t.eq('明牌 非出牌阶段 拒', ctx.sent.length, 0);
|
||||
t.eq('明牌 非出牌阶段 拒(回失败包STEP)', rej(ctx, ERR.STEP), true);
|
||||
|
||||
// ===================== §4 投降 touxiang 条件 =====================
|
||||
const mkTX = (step, banker, call) => ({ step, banker, call, method: { get_paiju_account: (type, msg) => { msg.rpc = 'jiesuan'; msg.data = { type }; return msg; } } });
|
||||
@@ -26,11 +30,11 @@ let p = mkTX(2, 0, 70); ctx = setup("00000", p); mod.touxiang(pack(0)); // 70
|
||||
t.eq('投降 70分step2庄家 step→6', p.step, 6);
|
||||
t.eq('投降 下发jiesuan', ctx.sent.length === 1 && ctx.sent[0].rpc, 'jiesuan');
|
||||
p = mkTX(2, 0, 65); ctx = setup("00000", p); mod.touxiang(pack(0));
|
||||
t.eq('投降 65分 拒', ctx.sent.length, 0);
|
||||
t.eq('投降 65分 拒(回失败包RULE)', rej(ctx, ERR.RULE), true);
|
||||
p = mkTX(3, 0, 70); ctx = setup("00000", p); mod.touxiang(pack(0));
|
||||
t.eq('投降 埋牌后step3 拒', ctx.sent.length, 0);
|
||||
t.eq('投降 埋牌后step3 拒(回失败包STEP)', rej(ctx, ERR.STEP), true);
|
||||
p = mkTX(2, 1, 70); ctx = setup("00000", p); mod.touxiang(pack(0));
|
||||
t.eq('投降 非庄家 拒', ctx.sent.length, 0);
|
||||
t.eq('投降 非庄家 拒(回失败包SEAT)', rej(ctx, ERR.SEAT), true);
|
||||
|
||||
// ===================== §9 出牌 chupai 的查牌门控(info/baozhu)=====================
|
||||
// 造真实牌局 → 强制到首出(step5),庄家(0)出一张副牌单张;seat1 已报无主
|
||||
@@ -143,14 +147,14 @@ tp = setup("00000", mkTip(5, 2)); mod.tishi(pack(0, { tip: 2 }));
|
||||
t.eq('提示 banker=2·闲0发→对家1', tp.sent[0] && tp.sent[0].fromid, 1);
|
||||
// 庄家发 → 拒(庄家无对家)
|
||||
tp = setup("00000", mkTip(5, 0)); mod.tishi(pack(0, { tip: 1 }));
|
||||
t.eq('提示 庄家发 拒', tp.sent.length, 0);
|
||||
t.eq('提示 庄家发 拒(回失败包RULE)', rej(tp, ERR.RULE), true);
|
||||
// 非出牌阶段 → 拒
|
||||
tp = setup("00000", mkTip(3, 0)); mod.tishi(pack(1, { tip: 1 }));
|
||||
t.eq('提示 非出牌阶段(step3) 拒', tp.sent.length, 0);
|
||||
t.eq('提示 非出牌阶段(step3) 拒(回失败包STEP)', rej(tp, ERR.STEP), true);
|
||||
// 非法 tip / 缺 tip → 拒
|
||||
tp = setup("00000", mkTip(5, 0)); mod.tishi(pack(1, { tip: 9 }));
|
||||
t.eq('提示 非法tip=9 拒', tp.sent.length, 0);
|
||||
t.eq('提示 非法tip=9 拒(回失败包PARAM)', rej(tp, ERR.PARAM), true);
|
||||
tp = setup("00000", mkTip(5, 0)); mod.tishi(pack(1, {}));
|
||||
t.eq('提示 缺tip 拒', tp.sent.length, 0);
|
||||
t.eq('提示 缺tip 拒(回失败包PARAM)', rej(tp, ERR.PARAM), true);
|
||||
|
||||
process.exit(t.done('rpc') ? 0 : 1);
|
||||
|
||||
Reference in New Issue
Block a user