此前全仓(除协议文档开头一句说明外)没有任何下发包携带 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>
198 lines
6.0 KiB
JavaScript
198 lines
6.0 KiB
JavaScript
///////////////////////////////////////////////////
|
||
////////// cls_youle_erqiwang_desk: 牌桌 //////////
|
||
///////////////////////////////////////////////////
|
||
//跨模块依赖:Node 走 require 守卫;友乐/浏览器由 min_loadJsFile 加载为同名全局(dev-guide 01 §1)
|
||
if (typeof require !== "undefined"){
|
||
var cls_youle_erqiwang_paiju = require("./class.paiju.js");
|
||
}
|
||
|
||
var cls_youle_erqiwang_desk = cls_youle_erqiwang_desk || {
|
||
|
||
countdown_jiaofen: 15, //叫分倒计时
|
||
countdown_xuanzhu: 20, //选主倒计时
|
||
countdown_maipai: 25, //埋牌倒计时
|
||
countdown_chupai: 30, //出牌倒计时
|
||
|
||
//创建牌桌对象
|
||
new: function(o_room){
|
||
|
||
var desk = {};
|
||
|
||
desk.o_room = o_room; //桌所属的房间对象
|
||
desk.seatlist = []; //玩家得分
|
||
desk.seatlist.push([0, []]); //第一位为累积得分,第二位为每局得分
|
||
desk.seatlist.push([0, []]);
|
||
desk.seatlist.push([0, []]);
|
||
desk.prepare = [0,0,0]; //玩家准备状态
|
||
desk.paiju_list = []; //牌局列表
|
||
|
||
//方法
|
||
desk.method = {};
|
||
|
||
//当前牌局
|
||
desk.method.curr_paiju = function(){
|
||
return desk.paiju_list[desk.paiju_list.length - 1];
|
||
}
|
||
|
||
//新牌局
|
||
desk.method.do_new_paiju = function(firstseat){
|
||
cls_youle_erqiwang_desk.do_new_paiju(desk, firstseat);
|
||
}
|
||
|
||
//叫分倒计时
|
||
desk.method.get_countdown_jiaofen = function(){
|
||
return cls_youle_erqiwang_desk.countdown_jiaofen;
|
||
}
|
||
|
||
//叫主倒计时
|
||
desk.method.get_countdown_xuanzhu = function(){
|
||
return cls_youle_erqiwang_desk.countdown_xuanzhu;
|
||
}
|
||
|
||
//埋牌倒计时
|
||
desk.method.get_countdown_maipai = function(){
|
||
return cls_youle_erqiwang_desk.countdown_maipai;
|
||
}
|
||
|
||
//出牌倒计时
|
||
desk.method.get_countdown_chupai = function(){
|
||
return cls_youle_erqiwang_desk.countdown_chupai;
|
||
}
|
||
|
||
//准备
|
||
desk.method.do_prepare = function(seat){
|
||
return cls_youle_erqiwang_desk.do_prepare(desk, seat);
|
||
}
|
||
|
||
//获取大局结算包
|
||
desk.method.get_desk_account = function(msg){
|
||
return cls_youle_erqiwang_desk.get_desk_account(desk, msg);
|
||
}
|
||
|
||
return desk;
|
||
},
|
||
|
||
//新开一局
|
||
do_new_paiju: function(o_desk, firstseat){
|
||
//恢复玩家准备状态
|
||
o_desk.prepare = [0,0,0];
|
||
|
||
if (o_desk.paiju_list.length > 0){
|
||
delete o_desk.paiju_list[o_desk.paiju_list.length - 1].tmp_jiesuan_aset;
|
||
}
|
||
|
||
//新开一局
|
||
cls_youle_erqiwang_paiju.new(o_desk, firstseat);
|
||
|
||
var msg = {};
|
||
msg.app = "youle";
|
||
msg.route = "erqiwang";
|
||
msg.rpc = "fapai";
|
||
msg.data = {};
|
||
msg.data.success = true;
|
||
msg.data.asetidx = o_desk.paiju_list.length;
|
||
msg.data.asetcount = o_desk.o_room.asetcount;
|
||
msg.data.seat = o_desk.method.curr_paiju().method.get_callgrade_seat();
|
||
msg.data.countdown = o_desk.method.get_countdown_jiaofen();
|
||
for (var i = 0; i < o_desk.o_room.seatlist.length; i++) {
|
||
msg.conmode = o_desk.o_room.seatlist[i].conmode;
|
||
msg.fromid = o_desk.o_room.seatlist[i].fromid;
|
||
msg.data.cards = o_desk.method.curr_paiju().method.get_seat_cards(i);
|
||
youle_erqiwang.app.SendPack(msg);
|
||
}
|
||
},
|
||
|
||
//准备
|
||
do_prepare: function(o_desk, seat){
|
||
o_desk.prepare[seat] = 1;
|
||
if (o_desk.prepare[0] && o_desk.prepare[1] && o_desk.prepare[2]){
|
||
//新开一局
|
||
var paiju = o_desk.method.curr_paiju();
|
||
var firstseat = paiju.banker;
|
||
if (paiju.result == 1 || paiju.result == 2){
|
||
firstseat = (firstseat + 1) % 3;
|
||
}
|
||
cls_youle_erqiwang_desk.do_new_paiju(o_desk, firstseat);
|
||
} else {
|
||
var msg = {};
|
||
msg.app = "youle";
|
||
msg.route = "erqiwang";
|
||
msg.rpc = "zhunbei";
|
||
msg.data = {};
|
||
msg.data.success = true;
|
||
msg.data.seat = seat;
|
||
o_desk.o_room.method.sendpack_toother(msg, -1);
|
||
}
|
||
},
|
||
|
||
//大局结算包
|
||
get_desk_account: function(o_desk, msg){
|
||
//保存战绩
|
||
var do_save_grade = function(){
|
||
var o_gameinfo1 = {};
|
||
o_gameinfo1.roomcode = o_desk.o_room.roomcode;
|
||
o_gameinfo1.asetcount = o_desk.paiju_list.length;
|
||
o_gameinfo1.createtime = o_desk.o_room.createtime;
|
||
o_gameinfo1.makewartime = o_desk.o_room.makewartime;
|
||
o_gameinfo1.players = [];
|
||
for (var i = 0; i < o_desk.o_room.seatlist.length; i++){
|
||
var _player = {};
|
||
_player.seat = i;
|
||
_player.playerid = o_desk.o_room.seatlist[i].playerid;
|
||
_player.name = o_desk.o_room.seatlist[i].nickname;
|
||
_player.avatar = o_desk.o_room.seatlist[i].avatar;
|
||
_player.score = o_desk.seatlist[i][0];
|
||
o_gameinfo1.players.push(_player);
|
||
}
|
||
|
||
var o_gameinfo2 = [];
|
||
for (var i = 0; i < o_desk.paiju_list.length; i++) {
|
||
var _paiju = {};
|
||
_paiju.starttime = o_desk.paiju_list[i].starttime;
|
||
_paiju.endtime = o_desk.paiju_list[i].endtime;
|
||
_paiju.seatlist = [0, 0, 0];
|
||
_paiju.seatlist[0] = o_desk.seatlist[0][1][i];
|
||
_paiju.seatlist[1] = o_desk.seatlist[1][1][i];
|
||
_paiju.seatlist[2] = o_desk.seatlist[2][1][i];
|
||
_paiju.callproc = o_desk.paiju_list[i].callproc;
|
||
_paiju.banker = o_desk.paiju_list[i].banker;
|
||
_paiju.call = o_desk.paiju_list[i].call;
|
||
_paiju.flower = o_desk.paiju_list[i].flower;
|
||
_paiju.result = o_desk.paiju_list[i].result;
|
||
//数据量太多,json转数组后进行存储
|
||
_paiju.cards = [];
|
||
for (var j = 0; j < o_desk.paiju_list[i].cards.length; j++) {
|
||
var _pai = o_desk.paiju_list[i].cards[j];
|
||
var _card = [];
|
||
_card.push(_pai.id);
|
||
_card.push(_pai.flower);
|
||
_card.push(_pai.number);
|
||
_card.push(_pai.score);
|
||
_card.push(_pai.dealowner);
|
||
_card.push(_pai.playround);
|
||
_card.push(_pai.playindex);
|
||
_card.push(_pai.playowner);
|
||
_paiju.cards.push(_card);
|
||
}
|
||
o_gameinfo2.push(_paiju);
|
||
}
|
||
|
||
//累积游戏得分
|
||
for (var i = 0; i < o_desk.o_room.seatlist.length; i++) {
|
||
o_desk.o_room.seatlist[i].gameinfo.grade = o_desk.seatlist[i][0];
|
||
}
|
||
//保存战绩
|
||
youle_erqiwang.import.save_grade(o_desk.o_room, o_gameinfo1, o_gameinfo2, 1);
|
||
}
|
||
min_ontimeout(do_save_grade, 1000);
|
||
|
||
msg.data.account = o_desk.seatlist;
|
||
return msg;
|
||
}
|
||
}
|
||
|
||
//Node 导出;友乐/浏览器无 module 时跳过(dev-guide 01 §1)。SendPack/youle_erqiwang.* 为平台全局
|
||
if (typeof module !== "undefined"){
|
||
module.exports = cls_youle_erqiwang_desk;
|
||
}
|