Skip to content

Commit

Permalink
添加client客户端
Browse files Browse the repository at this point in the history
  • Loading branch information
v_jiangxinyu01 committed May 16, 2020
1 parent 7b25dc2 commit f292d32
Show file tree
Hide file tree
Showing 7 changed files with 1,439 additions and 0 deletions.
93 changes: 93 additions & 0 deletions public/client/Const.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/** 主命令字定义 **/
var MainCmd = {
CMD_SYS : 1, /** 系统类(主命令字)- 客户端使用 **/
CMD_GAME : 2, /** 游戏类(主命令字)- 客户端使用 **/
}

/** 子命令字定义 **/
var SubCmd = {
//系统子命令字,对应MainCmd.CMD_SYS
LOGIN_FAIL_RESP : 100,
HEART_ASK_REQ : 101,
HEART_ASK_RESP : 102,
BROADCAST_MSG_REQ : 103,
BROADCAST_MSG_RESP : 104,

//游戏逻辑子命令字,对应MainCmd.CMD_GAME
SUB_GAME_START_REQ : 1, //游戏开始---> CGameStart
SUB_GAME_START_RESP : 2, //游戏开始---> CGameStart
SUB_USER_INFO_RESP : 3, //用户信息 ------> CUserInfo
SUB_GAME_SEND_CARD_RESP : 4, //发牌 ------> CGameSendCard
SUB_GAME_CALL_TIPS_RESP : 5, //叫地主提示(广播) --> CGameCall
SUB_GAME_CALL_REQ : 6, //叫地主请求 --> CGameCallReq
SUB_GAME_CALL_RESP : 7, //叫地主请求返回--CGameCallResp
SUB_GAME_DOUBLE_TIPS_RESP : 8, //加倍提示(广播) --> CGameDouble
SUB_GAME_DOUBLE_REQ : 9, //加倍请求--> CGameDoubleReq
SUB_GAME_DOUBLE_RESP : 10, //加倍请求返回----> CGameDoubleResp
SUB_GAME_CATCH_BASECARD_RESP : 11, //摸底牌 ---> CGameCatchBaseCard
SUB_GAME_OUT_CARD : 12, //出牌提示 --> CGameOutCard
SUB_GAME_OUT_CARD_REQ : 13, //出牌请求 --> CGameOutCardReq
SUB_GAME_OUT_CARD_RESP : 14, //出牌返回 --> CGameOutCardResp

CHAT_MSG_REQ : 213, //聊天消息请求,客户端使用
CHAT_MSG_RESP : 214, //聊天消息响应,服务端使用
}


/**
* 路由规则,key主要命令字=》array(子命令字对应策略类名)
* 每条客户端对应的请求,路由到对应的逻辑处理类上处理
*
*/
var Route = {
1 : {
100 : 'loginFail', //登陆失败
105 : 'loginSuccess', //登陆成功
102 : 'heartAsk', //心跳处理
104 : 'broadcast', //广播消息
106 : 'enterRoomFail', //进入房间失败
107 : 'enterRoomSucc', //进入房间成功
},
2 : {
2 : 'gameStart', //获取卡牌
214 : 'chatMsg',
3 : 'userInfo', //显示用户信息
5 : 'gameCallTips', //叫地主广播
7 : 'gameCall', //叫地主返回
11 : 'gameCatchCardTips', //摸底牌
12 : 'gameOutCard', //出牌广播
14 : 'gameOutCardResp', //出牌响应
},
}

/**
* 花色类型
*/
var CardType = {
HEITAO : 0, //黑桃
HONGTAO : 1, //红桃
MEIHUA : 2, //梅花
FANGKUAI : 3, //方块
XIAOWANG : 4, //小王
DAWANG : 5, //大王
}
/**
* 牌显示出来的值
*/
var CardVal = {
CARD_SAN : '3', //牌值3
CARD_SI : '4', //牌值4
CARD_WU : '5', //牌值5
CARD_LIU : '6', //牌值6
CARD_QI : '7', //牌值7
CARD_BA : '8', //牌值8
CARD_JIU : '9', //牌值9
CARD_SHI : '10', //牌值10
CARD_J : 'J', //牌值J
CARD_Q : 'Q', //牌值Q
CARD_K : 'K', //牌值K
CARD_A : 'A', //牌值A
CARD_ER : '2', //牌值2
CARD_XIAOWANG : 'w', //牌值小王
CARD_DAWANG : 'W', //牌值大王
}
118 changes: 118 additions & 0 deletions public/client/Init.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/**
* 初始化类,websock服务器类
*/

var Init = {
ws : null,
url : "",
timer : 0,
reback_times : 100, //断线重连次数
dubug : true,

//启动websocket
webSock: function (url) {
this.url = url;
ws = new WebSocket(url);
ws.binaryType = "arraybuffer"; //设置为2进制类型 webSocket.binaryType = "blob" ;
var obj = this;
//连接回调
ws.onopen = function(evt) {
Req.heartBeat(obj);
//清除定时器
clearInterval(obj.timer);
//获取用户状态
obj.log('系统提示: 连接服务器成功');
};

//消息回调
ws.onmessage = function(evt) {
if(!evt.data) return ;
var total_data = new DataView(evt.data);
var total_len = total_data.byteLength;
if(total_data.byteLength < 4){
obj.log('系统提示: 数据格式有问题');
ws.close();
return ;
}

//进行粘包处理
var off = 0;
var guid = body = '';
while(total_len > off) {
var len = total_data.getUint32(off);
var data = evt.data.slice(off, off + len + 4);
//解析body
body = Packet.msgunpack(data);
//转发响应的请求
obj.recvCmd(body);
off += len + 4;
}

};
//关闭回调
ws.onclose = function(evt) {
//断线重新连接
obj.timer = setInterval(function () {
if(obj.reback_times == 0) {
clearInterval(obj.timer);
clearInterval(Req.timer);
} else {
obj.reback_times--;
obj.webSock(obj.url);
}
},5000);
obj.log('系统提示: 连接断开');
};
//socket错误回调
ws.onerror = function(evt) {
obj.log('系统提示: 服务器错误'+evt.type);
};
this.ws = ws;
return this;
},

//处理消息回调命令字
recvCmd: function(body) {
console.log('debub data'+body);
console.log(body);
var len = body['len'];
var cmd = body['cmd'];
var scmd = body['scmd'];
var data = body['data'];
this.log('websocket Recv <<< len='+len+" cmd="+cmd+" scmd="+scmd);
//路由到处理地方
var func = Route[cmd][scmd];
var str = 'Resp.'+func;
if(func) {
if(typeof(eval(str)) == 'function') {
eval("Resp."+func+"(data)");
} else {
document.getElementById('msgText').innerHTML += func+':'+JSON.stringify(data) + '\n';
}
} else {
this.log('func is valid');
}

this.log("websocket Recv body <<< func="+func);
this.log(body);
},

//打印日志方法
log: function(msg) {
if(this.dubug) {
console.log(msg);
}
},

//发送数据
send: function(data, cmd, scmd) {
//this.ws.close();
this.log("websocket Send >>> cmd="+cmd+" scmd="+scmd+" data=");
this.log(data);
var pack_data = Packet.msgpack(data, cmd, scmd);
//组装数据
if(this.ws.readyState == this.ws.OPEN) {
this.ws.send(pack_data);
}
}
}
95 changes: 95 additions & 0 deletions public/client/Packet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
var Packet = {
//jons数据打包成二进制数据
encode : function(data, cmd, scmd) {
var data = JSON.stringify(data);
var len = data.length + 6;
var buf = new ArrayBuffer(len); // 每个字符占用1个字节
var buff_data = new DataView(buf, 0, len);
var str_len = data.length;
buff_data.setUint32(0, str_len+2);
buff_data.setUint8(4, cmd);
buff_data.setUint8(5, scmd);
for (var i = 0; i < str_len; i++) {
buff_data.setInt8(i+6, data.charCodeAt(i));
}
return buf;
},

//二进制数据解包成二进制数据
decode : function(buff) {
var body = '';
var len = new DataView(buff, 0, 4).getUint32(0);
var body_data = new DataView(buff, 4, len);
//解析cmd
var cmd = body_data.getUint8(0);
var scmd = body_data.getUint8(1);

//解析body
for(var i = 2; i < body_data.byteLength; i++) {
body += String.fromCharCode(body_data.getUint8(i));
}
//console.log("data decode >>> len="+len+" cmd="+cmd+" scmd="+scmd+" data="+body);
var body = JSON.parse(body);
body["cmd"] = cmd;
body["scmd"] = scmd;
return body;
},

encodeUTF8: function(str){
var temp = "",rs = "";
for( var i=0 , len = str.length; i < len; i++ ){
temp = str.charCodeAt(i).toString(16);
rs += "\\u"+ new Array(5-temp.length).join("0") + temp;
}
return rs;
},

decodeUTF8: function(str){
return str.replace(/(\\u)(\w{4}|\w{2})/gi, function($0,$1,$2){
return String.fromCharCode(parseInt($2,16));
});
},

//使用msgpack解包arraybuf数据
msgunpack: function(buff) {
var body = '';
var len = new DataView(buff, 0, 4).getUint32(0);
var body_data = new DataView(buff, 4, len);
//解析cmd
var cmd = body_data.getUint8(0);
var scmd = body_data.getUint8(1);

//解析body
for(var i = 2; i < body_data.byteLength; i++) {
body += String.fromCharCode(body_data.getUint8(i));
}
//console.log("data msgpack decode >>> cmd="+cmd+" scmd="+scmd+" len="+len+" data="+body);
var body = msgpack.unpack(body);
body["cmd"] = cmd;
body["scmd"] = scmd;
body["len"] = len;
return body;
},

//使用packmsg打包object数据对象
msgpack: function(data, cmd, scmd) {
//var dt = {};
//dt.data = data;
var data_buff = msgpack.pack(data);
var str_buff = String.fromCharCode.apply(null, new Uint8Array(data_buff));
var len = str_buff.length + 6;
var buf = new ArrayBuffer(len); // 每个字符占用1个字节
var buff_data = new DataView(buf, 0, len);
var str_len = str_buff.length;
buff_data.setUint32(0, str_len + 2);
buff_data.setUint8(4, cmd);
buff_data.setUint8(5, scmd);

for (var i = 0; i < str_len; i++) {
buff_data.setInt8(i+6, str_buff.charCodeAt(i));
}
//console.log("data msgpack encode >>> cmd="+cmd+" scmd="+scmd+" len="+len+" data=");
//console.log(data);
return buf;
}
}
42 changes: 42 additions & 0 deletions public/client/Req.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**发请求命令字处理类*/

var Req = {
//定时器
timer : 0,

//发送心跳
heartBeat:function(obj) {
this.timer = setInterval(function () {
if(obj.ws.readyState == obj.ws.OPEN) {
var data = {};
data['time'] = (new Date()).valueOf()
obj.send(data, MainCmd.CMD_SYS, SubCmd.HEART_ASK_REQ);
} else {
clearInterval(this.timer);
}
}, 600000);
},

//游戏开始
GameStart: function(obj,data) {
var data = {};
obj.send(data, MainCmd.CMD_GAME, SubCmd.SUB_GAME_START_REQ);
},

//抢地主
GameCall: function(obj,status) {
var data = {"type": status};
obj.send(data, MainCmd.CMD_GAME, SubCmd.SUB_GAME_CALL_REQ);
},

//玩游戏
PlayGame: function(obj,data) {
obj.send(data, MainCmd.CMD_GAME, SubCmd.SUB_GAME_OUT_CARD_REQ);
},

//聊天消息
ChatMsg: function(obj, data) {
var data = {data};
obj.send(data, MainCmd.CMD_GAME, SubCmd.CHAT_MSG_REQ);
},
}
Loading

0 comments on commit f292d32

Please sign in to comment.