627 lines
18 KiB
JavaScript
627 lines
18 KiB
JavaScript
|
|
"use strict";
|
||
|
|
cc._RF.push(module, 'a4cf66+FXxG5rd4h8TtCXqZ', 'socket');
|
||
|
|
// Scripts/client/socket/socket.js
|
||
|
|
|
||
|
|
"use strict";
|
||
|
|
|
||
|
|
/*-----------------------------------------------------+
|
||
|
|
* socket相关处理
|
||
|
|
* @author whjing2012@163.com
|
||
|
|
+-----------------------------------------------------*/
|
||
|
|
|
||
|
|
var Proto = require("proto_mate");
|
||
|
|
var SocketSvr = require("SocketService");
|
||
|
|
var _require = require("config"),
|
||
|
|
SSL = _require.SSL;
|
||
|
|
|
||
|
|
// 心跳间隔&超时次数
|
||
|
|
var HEARTBEAT_ID = 1199;
|
||
|
|
var HEARTBEAT_PERIOD = 10000;
|
||
|
|
var HEARTBEAT_LIMIT = 2;
|
||
|
|
|
||
|
|
// 数据类型
|
||
|
|
var DataType = cc.Enum({
|
||
|
|
None: 0,
|
||
|
|
Int8: 1,
|
||
|
|
UInt8: 2,
|
||
|
|
Int16: 3,
|
||
|
|
UInt16: 4,
|
||
|
|
Int32: 5,
|
||
|
|
UInt32: 6,
|
||
|
|
String: 7,
|
||
|
|
Byte: 8,
|
||
|
|
Array: 9,
|
||
|
|
Float: 10,
|
||
|
|
Int64: 11,
|
||
|
|
UInt64: 12
|
||
|
|
});
|
||
|
|
var fmtNow = function fmtNow() {
|
||
|
|
var dt = new Date();
|
||
|
|
var date = dt.getHours() + ":" + dt.getMinutes() + ":" + dt.getSeconds();
|
||
|
|
return date;
|
||
|
|
};
|
||
|
|
var output = function output(_content) {
|
||
|
|
if (window.nx) {
|
||
|
|
nx.info("" + _content);
|
||
|
|
} else {
|
||
|
|
cc.log("" + fmtNow() + _content);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
var invoke = function invoke(_fn) {
|
||
|
|
if (!!_fn && typeof _fn == 'function') {
|
||
|
|
_fn.apply(null, Array.prototype.slice.call(arguments, 1));
|
||
|
|
}
|
||
|
|
};
|
||
|
|
var CliSocket = {
|
||
|
|
getTime: function getTime() {
|
||
|
|
return this.diff_time + parseInt(cc.sys.now() / 1000);
|
||
|
|
},
|
||
|
|
getMsTime: function getMsTime() {
|
||
|
|
return this.diff_time * 1000 + cc.sys.now();
|
||
|
|
},
|
||
|
|
setTime: function setTime(time) {
|
||
|
|
this.diff_time = time - parseInt(cc.sys.now() / 1000);
|
||
|
|
},
|
||
|
|
init: function init() {
|
||
|
|
this.net_connect = null;
|
||
|
|
this.buffer = null;
|
||
|
|
this.listeners = {};
|
||
|
|
this.msg_list = [];
|
||
|
|
this.diff_time = 0;
|
||
|
|
this.connecting = false;
|
||
|
|
this.check_time = 0;
|
||
|
|
|
||
|
|
//初始化网络接口
|
||
|
|
SocketSvr.InitWebSocket(WebSocket);
|
||
|
|
|
||
|
|
//创建一个连接实例: 支持wss/ws
|
||
|
|
this.net_connect = SocketSvr.CreateConnect(SSL);
|
||
|
|
|
||
|
|
// 初始化网络事件
|
||
|
|
this.net_connect.Init(this, this.on_open, this.on_message, this.on_close, this.on_error);
|
||
|
|
|
||
|
|
// 网络协议转换,当前不使用
|
||
|
|
//this.net_connect.AttachMessage(fn_on_receive,fn_on_send);
|
||
|
|
|
||
|
|
// 注册心跳
|
||
|
|
this.readyHeartBeat();
|
||
|
|
if (!Uint8Array.prototype.slice) {
|
||
|
|
Uint8Array.prototype.slice = Array.prototype.slice;
|
||
|
|
}
|
||
|
|
},
|
||
|
|
// ======================================================================
|
||
|
|
// 心跳处理
|
||
|
|
// ======================================================================
|
||
|
|
|
||
|
|
// 心跳监听
|
||
|
|
readyHeartBeat: function readyHeartBeat() {
|
||
|
|
var _this = this;
|
||
|
|
// cc.log( "$心跳:开始" );
|
||
|
|
this.hb_caches = 0;
|
||
|
|
this.bindCmd(HEARTBEAT_ID, this.on1199.bind(this), "hb");
|
||
|
|
this.net_connect.AttachBeartbeat(HEARTBEAT_PERIOD, function () {
|
||
|
|
_this.tickHeartBeat();
|
||
|
|
return _this.structMsg(HEARTBEAT_ID, {});
|
||
|
|
});
|
||
|
|
},
|
||
|
|
// 心跳检查
|
||
|
|
tickHeartBeat: function tickHeartBeat() {
|
||
|
|
// cc.log( "$心跳:触发, 次数: %s -> %s", this.hb_caches, this.hb_caches + 1 );
|
||
|
|
// let old = nx.bridge.vget( "connFlag" );
|
||
|
|
// if( old != "good" ) {
|
||
|
|
// return;
|
||
|
|
// }
|
||
|
|
|
||
|
|
// 缓存未回复次数
|
||
|
|
this.hb_caches += 1;
|
||
|
|
if (this.hb_caches >= HEARTBEAT_LIMIT) {
|
||
|
|
cc.log("$心跳:超时,主动断开网络!");
|
||
|
|
this.breakws();
|
||
|
|
}
|
||
|
|
},
|
||
|
|
// 心跳 5发1收
|
||
|
|
on1199: function on1199(data) {
|
||
|
|
// cc.log( "$心跳:有效回复, 当前:", this.hb_caches );
|
||
|
|
this.hb_caches = 0;
|
||
|
|
},
|
||
|
|
// ======================================================================
|
||
|
|
// 连接处理
|
||
|
|
// ======================================================================
|
||
|
|
|
||
|
|
// 连接网络
|
||
|
|
connect: function connect(host, port, ws, _cb) {
|
||
|
|
output(cc.js.formatStr("$网络:连接开始... 地址:%s,端口:%s,SSL:%s", host, port, ws || "ws"));
|
||
|
|
this.buffer = null;
|
||
|
|
this.hb_caches = 0;
|
||
|
|
this.closeFlag = "";
|
||
|
|
|
||
|
|
// 连接开始
|
||
|
|
this.net_connect.SetSSL(ws == "wss");
|
||
|
|
var code = this.net_connect.Connect(host, port);
|
||
|
|
if (code == SocketSvr.ErrCode().SUCC) {
|
||
|
|
this.setConnecting(true);
|
||
|
|
this.setLinkFlag("linking");
|
||
|
|
this.cbConnect = _cb;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 重复连接
|
||
|
|
if (code == SocketSvr.ErrCode().ERR_ALREADY_CONNECTED) {
|
||
|
|
invoke(_cb, true, "repeat");
|
||
|
|
this.setConnecting(true);
|
||
|
|
this.setLinkFlag("good");
|
||
|
|
this.cbConnect = null;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 连接失败
|
||
|
|
invoke(_cb, false, "TipConnectFailed");
|
||
|
|
this.setConnecting(false);
|
||
|
|
this.setLinkFlag("close");
|
||
|
|
this.cbConnect = null;
|
||
|
|
},
|
||
|
|
// 关闭网络
|
||
|
|
close: function close(_flag) {
|
||
|
|
if (_flag === void 0) {
|
||
|
|
_flag = "close";
|
||
|
|
}
|
||
|
|
output(cc.js.formatStr("$网络:连接关闭... %s", this._curInfo()));
|
||
|
|
this.closeFlag = _flag;
|
||
|
|
if (this.net_connect) {
|
||
|
|
this.net_connect.DisConnect();
|
||
|
|
}
|
||
|
|
},
|
||
|
|
// 断开websocket
|
||
|
|
breakws: function breakws() {
|
||
|
|
output(cc.js.formatStr("$网络:连接断开... %s", this._curInfo()));
|
||
|
|
this.close();
|
||
|
|
},
|
||
|
|
// 发送消息
|
||
|
|
send: function send(cmd, data) {
|
||
|
|
// 完整日志
|
||
|
|
output(cc.js.formatStr("[send] >>>[%d]:%s", cmd, JSON.stringify(data || {})));
|
||
|
|
|
||
|
|
// 参数封装
|
||
|
|
var p_data = this.structMsg(cmd, data);
|
||
|
|
if (!p_data) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return this.net_connect.Send(p_data);
|
||
|
|
},
|
||
|
|
// 协议监听
|
||
|
|
bindCmd: function bindCmd(cmd, func, key) {
|
||
|
|
if (!func) {
|
||
|
|
cc.error("$Socket:无效监听函数!", cmd, key);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (!this.listeners[cmd]) {
|
||
|
|
this.listeners[cmd] = [];
|
||
|
|
}
|
||
|
|
|
||
|
|
// 重复判定
|
||
|
|
var flag = key || "none";
|
||
|
|
if (CC_DEBUG) {
|
||
|
|
for (var i in this.listeners[cmd]) {
|
||
|
|
var tm = this.listeners[cmd][i];
|
||
|
|
if (tm && tm.key == flag) {
|
||
|
|
cc.error("$Socket:重复监听!", cmd, flag);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 加入列表
|
||
|
|
this.listeners[cmd].push({
|
||
|
|
cb: func,
|
||
|
|
key: flag
|
||
|
|
});
|
||
|
|
},
|
||
|
|
// 协议监听解除
|
||
|
|
unbindCmd: function unbindCmd(_cmd, _key) {
|
||
|
|
var arr = this.listeners[_cmd];
|
||
|
|
if (!arr || arr.length == 0) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
var flag = _key || "none";
|
||
|
|
var i = arr.length;
|
||
|
|
while (i--) {
|
||
|
|
if (arr[i].key == flag) {
|
||
|
|
arr.splice(i, 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
// 发送消息组装
|
||
|
|
structMsg: function structMsg(cmd, data) {
|
||
|
|
try {
|
||
|
|
var bytes = this.packData(cmd, data);
|
||
|
|
var buffer = new ArrayBuffer(bytes.length + 4);
|
||
|
|
var view = new DataView(buffer);
|
||
|
|
view.setUint32(0, bytes.length);
|
||
|
|
for (var i = 0; i < bytes.length; i++) {
|
||
|
|
view.setUint8(i + 4, bytes[i]);
|
||
|
|
}
|
||
|
|
return view.buffer;
|
||
|
|
} catch (error) {
|
||
|
|
cc.error("[send] send_msg_error:" + error.message, error.stack);
|
||
|
|
if (error && cc.sys.isNative && window && window.__errorHandler) {
|
||
|
|
window.__errorHandler(error.message, "", "", error.stack);
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
},
|
||
|
|
handleMsg: function handleMsg() {
|
||
|
|
//这里不需要,网络层自驱动,如需特殊处理,打开即可
|
||
|
|
//
|
||
|
|
// if( this.msg_list.length == 0 ) return;
|
||
|
|
// for( var i = 0; i < 5; i++ ) {
|
||
|
|
// var msg = this.msg_list.shift();
|
||
|
|
// this.onCmdCallback( msg.cmd, msg.data );
|
||
|
|
// if( this.msg_list.length == 0 ) return;
|
||
|
|
// }
|
||
|
|
},
|
||
|
|
// ======================================================================
|
||
|
|
// 监听处理
|
||
|
|
// ======================================================================
|
||
|
|
|
||
|
|
// 事件:网络打开准备就绪
|
||
|
|
on_open: function on_open(self, is_reconnect, e) {
|
||
|
|
cc.log("$网络监听:已打开... %s", self._curInfo());
|
||
|
|
self.setConnecting(false);
|
||
|
|
gcore.GlobalEvent.fire_x(gcore.GlobalEvent, gcore.GlobalEvent.EVT_SOCKET_CONNECT);
|
||
|
|
|
||
|
|
// 视图标记
|
||
|
|
self.setLinkFlag("good");
|
||
|
|
|
||
|
|
// 回调
|
||
|
|
if (self.cbConnect) {
|
||
|
|
invoke(self.cbConnect, true);
|
||
|
|
self.cbConnect = null;
|
||
|
|
}
|
||
|
|
},
|
||
|
|
// 事件:网络接收消息
|
||
|
|
on_message: function on_message(self, msg, data) {
|
||
|
|
self.doRecv(data, self);
|
||
|
|
},
|
||
|
|
// 事件:网络关闭
|
||
|
|
on_close: function on_close(self) {
|
||
|
|
cc.log("$网络监听:已关闭... %s", self._curInfo());
|
||
|
|
self.setConnecting(false);
|
||
|
|
gcore.GlobalEvent.fire_x(gcore.GlobalEvent, gcore.GlobalEvent.EVT_SOCKET_DISCONNECT, self.closeFlag);
|
||
|
|
|
||
|
|
// 视图标记
|
||
|
|
self.setLinkFlag(self.closeFlag);
|
||
|
|
return true;
|
||
|
|
},
|
||
|
|
// 事件:网络错误
|
||
|
|
on_error: function on_error(self, e) {
|
||
|
|
cc.error("$网络监听:错误... %s", self._curInfo());
|
||
|
|
console.error(e);
|
||
|
|
|
||
|
|
// 回调
|
||
|
|
if (self.cbConnect) {
|
||
|
|
invoke(self.cbConnect, false, "TipConnectFailed");
|
||
|
|
self.cbConnect = null;
|
||
|
|
}
|
||
|
|
},
|
||
|
|
onCmdCallback: function onCmdCallback(cmd, data) {
|
||
|
|
if (!window.nx) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
try {
|
||
|
|
var arr = this.listeners[cmd];
|
||
|
|
if (arr && arr.length > 0) {
|
||
|
|
arr.forEach(function (_hook) {
|
||
|
|
if (_hook.cb) {
|
||
|
|
invoke(_hook.cb, data, cmd);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
cc.error("handle_msg_error:" + cmd + ", err=" + error.message + ", data=" + data, error, error.stack);
|
||
|
|
if (error && cc.sys.isNative && window && window.__errorHandler) {
|
||
|
|
window.__errorHandler(error.message, "", "", error.stack);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
// 设置连接状态
|
||
|
|
setConnecting: function setConnecting(_doing) {
|
||
|
|
this.connecting = _doing;
|
||
|
|
},
|
||
|
|
// ======================================================================
|
||
|
|
// 设置连接状态
|
||
|
|
// ======================================================================
|
||
|
|
|
||
|
|
// 设置
|
||
|
|
setLinkFlag: function setLinkFlag(_flag) {
|
||
|
|
if (!window.nx) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
var flag = _flag || "close";
|
||
|
|
var old = nx.bridge.vget("connFlag");
|
||
|
|
if (old == flag) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
output(cc.js.formatStr("$SOCKET: %s -> %s", old, flag));
|
||
|
|
nx.bridge.vset("connFlag", flag);
|
||
|
|
},
|
||
|
|
// ======================================================================
|
||
|
|
// 数据处理
|
||
|
|
// ======================================================================
|
||
|
|
|
||
|
|
doRecv: function doRecv(buffer, self) {
|
||
|
|
// 重置心跳包
|
||
|
|
this.check_time = 0;
|
||
|
|
if (typeof buffer == "string")
|
||
|
|
//服务器传过来的可能是字符串,判断是不是
|
||
|
|
{
|
||
|
|
output("[recv] =text= " + buffer);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (self.buffer == null) {
|
||
|
|
buffer = new Uint8Array(buffer);
|
||
|
|
} else {
|
||
|
|
var a = Array.from(new Uint8Array(buffer));
|
||
|
|
var b = Array.from(new Uint8Array(self.buffer));
|
||
|
|
buffer = b.concat(a);
|
||
|
|
}
|
||
|
|
this.unpackBuffer(buffer);
|
||
|
|
},
|
||
|
|
unpackBuffer: function unpackBuffer(buffer) {
|
||
|
|
if (buffer.length < 6) {
|
||
|
|
this.buffer = buffer;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
var dataview = new DataView(new Uint8Array(buffer).buffer);
|
||
|
|
var len = dataview.getUint32(0, false);
|
||
|
|
//cc.log("======= " + len);
|
||
|
|
if (len > 80000) {
|
||
|
|
cc.error("[recv] data_to_long:" + len);
|
||
|
|
this.net_connect.DisConnec();
|
||
|
|
}
|
||
|
|
var data_len = buffer.length;
|
||
|
|
if (len + 4 > data_len) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
var cmd = 0;
|
||
|
|
try {
|
||
|
|
cmd = dataview.getUint16(4, false);
|
||
|
|
this.unpackData(dataview, cmd, buffer, len);
|
||
|
|
} catch (error) {
|
||
|
|
cc.error("[recv] " + cmd + ": unpackData_error:" + error.message, buffer, error.stack);
|
||
|
|
if (error && cc.sys.isNative && window && window.__errorHandler) {
|
||
|
|
window.__errorHandler(error.message, "", "", error.stack);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (data_len > len + 4) {
|
||
|
|
// cc.log( "data_length==", cmd, len );
|
||
|
|
this.unpackBuffer(buffer.slice(len + 4));
|
||
|
|
} else {
|
||
|
|
this.buffer = null;
|
||
|
|
// if( cmd != HEARTBEAT_ID ) {
|
||
|
|
// cc.error( "协议空内容:" + cmd );
|
||
|
|
// }
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
unpackData: function unpackData(dataview, cmd, buffer, len) {
|
||
|
|
if (!Proto.recv.hasOwnProperty(cmd)) {
|
||
|
|
throw new Error("[recv] unpackData查找不到协议定义:" + cmd);
|
||
|
|
}
|
||
|
|
var data = {};
|
||
|
|
var mate = Proto.recv[cmd];
|
||
|
|
this.unpackData_(dataview, buffer, data, mate, 6, len);
|
||
|
|
|
||
|
|
// 屏蔽心跳
|
||
|
|
if (cmd != '1199') {
|
||
|
|
output(cc.js.formatStr("[recv] <<<[%d]:%s", cmd, JSON.stringify(data || {}, function (key, value) {
|
||
|
|
return typeof value === 'bigint' ? value.toString() : value;
|
||
|
|
} // return everything else unchanged
|
||
|
|
)));
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!this.listeners[cmd]) {
|
||
|
|
cc.warn("[recv] 协议处理函数未定义:" + cmd);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this.onCmdCallback(cmd, data);
|
||
|
|
return data;
|
||
|
|
},
|
||
|
|
unpackData_: function unpackData_(dataview, buffer, data, mate, pos, len) {
|
||
|
|
for (var i = 0, n = mate.length; i < n; i++) {
|
||
|
|
var field = mate[i];
|
||
|
|
//cc.log("field=" +field.s +" i=" + i + " t=" + field.t + " n=" +n + " pos=" + pos);
|
||
|
|
switch (field.t) {
|
||
|
|
case DataType.Int8:
|
||
|
|
{
|
||
|
|
data[field.s] = dataview.getInt8(pos, false);
|
||
|
|
pos += 1;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case DataType.UInt8:
|
||
|
|
{
|
||
|
|
data[field.s] = dataview.getUint8(pos, false);
|
||
|
|
pos += 1;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case DataType.Int16:
|
||
|
|
{
|
||
|
|
data[field.s] = dataview.getInt16(pos, false);
|
||
|
|
pos += 2;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case DataType.UInt16:
|
||
|
|
{
|
||
|
|
data[field.s] = dataview.getUint16(pos, false);
|
||
|
|
pos += 2;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case DataType.Int32:
|
||
|
|
{
|
||
|
|
data[field.s] = dataview.getInt32(pos, false);
|
||
|
|
pos += 4;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case DataType.UInt32:
|
||
|
|
{
|
||
|
|
data[field.s] = dataview.getUint32(pos, false);
|
||
|
|
pos += 4;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case DataType.String:
|
||
|
|
{
|
||
|
|
var s_len = dataview.getUint16(pos, false);
|
||
|
|
pos += 2;
|
||
|
|
var unit8Arr = new Uint8Array(buffer.slice(pos, pos + s_len));
|
||
|
|
var encodedString = String.fromCharCode.apply(null, unit8Arr);
|
||
|
|
data[field.s] = decodeURIComponent(escape(encodedString)); //没有这一步中文会乱码
|
||
|
|
pos += s_len;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case DataType.Byte:
|
||
|
|
{
|
||
|
|
var s_len = dataview.getUint32(pos, false);
|
||
|
|
pos += 4;
|
||
|
|
data[field.s] = buffer.slice(pos, pos + s_len); //没有这一步中文会乱码
|
||
|
|
pos += s_len;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case DataType.Array:
|
||
|
|
{
|
||
|
|
var s_len = dataview.getUint16(pos, false);
|
||
|
|
pos += 2;
|
||
|
|
var arr = [];
|
||
|
|
data[field.s] = arr;
|
||
|
|
for (var j = 0; j < s_len; j++) {
|
||
|
|
var data1 = {};
|
||
|
|
arr[j] = data1;
|
||
|
|
pos = this.unpackData_(dataview, buffer, data1, field.f, pos, len);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case DataType.Float:
|
||
|
|
{
|
||
|
|
data[field.s] = dataview.getFloat64(pos, false);
|
||
|
|
pos += 8;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case DataType.Int64:
|
||
|
|
{
|
||
|
|
data[field.s] = dataview.getInt64(pos, false);
|
||
|
|
pos += 8;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case DataType.UInt64:
|
||
|
|
{
|
||
|
|
data[field.s] = dataview.getUint64(pos, false);
|
||
|
|
pos += 8;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
{
|
||
|
|
cc.warn("无效数据类型:" + field.t);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
//cc.log("unpack_data:" + field.s + ", val=" + data[field.s]);
|
||
|
|
}
|
||
|
|
|
||
|
|
return pos;
|
||
|
|
},
|
||
|
|
packData: function packData(cmd, data) {
|
||
|
|
if (!Proto.send.hasOwnProperty(cmd)) {
|
||
|
|
throw new Error("unpackData查找不到协议定义:" + cmd);
|
||
|
|
}
|
||
|
|
// cc.log( "pack_data2:" + cmd );
|
||
|
|
var mate = Proto.send[cmd];
|
||
|
|
var bytes = [];
|
||
|
|
this.i16ToBytes(bytes, cmd);
|
||
|
|
this.packData_(bytes, mate, data);
|
||
|
|
return bytes;
|
||
|
|
},
|
||
|
|
packData_: function packData_(bytes, mate, data) {
|
||
|
|
for (var i = 0, n = mate.length; i < n; i++) {
|
||
|
|
var field = mate[i];
|
||
|
|
var val = data[field.s];
|
||
|
|
// cc.log("pack_data2:" + field.s + ", val=" + val);
|
||
|
|
switch (field.t) {
|
||
|
|
case 1:
|
||
|
|
case 2:
|
||
|
|
bytes.push(new Uint8Array([val]));
|
||
|
|
break;
|
||
|
|
case 3:
|
||
|
|
case 4:
|
||
|
|
this.i16ToBytes(bytes, val);
|
||
|
|
break;
|
||
|
|
case 5:
|
||
|
|
case 6:
|
||
|
|
this.i32ToBytes(bytes, val);
|
||
|
|
break;
|
||
|
|
case 7:
|
||
|
|
this.strToBytes(bytes, val);
|
||
|
|
break;
|
||
|
|
case 8:
|
||
|
|
var s_len = val.length;
|
||
|
|
this.i32ToBytes(bytes, s_len);
|
||
|
|
for (var j = 0; j < s_len; j++) {
|
||
|
|
bytes.push(val[j]);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case 9:
|
||
|
|
var s_len = val.length;
|
||
|
|
// cc.log("pack_data2:" + field.s + ", val=" + val + ", len:" + s_len);
|
||
|
|
this.i16ToBytes(bytes, s_len);
|
||
|
|
for (var j = 0; j < s_len; j++) {
|
||
|
|
if (val[0] == null && val.length > 0) {
|
||
|
|
j = j + 1;
|
||
|
|
}
|
||
|
|
this.packData_(bytes, field.f, val[j]);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
strToBytes: function strToBytes(bytes, string) {
|
||
|
|
var str = unescape(encodeURIComponent(string));
|
||
|
|
var len = str.length;
|
||
|
|
this.i16ToBytes(bytes, len);
|
||
|
|
for (var i = 0; i < len; i++) {
|
||
|
|
bytes.push(str.charCodeAt(i));
|
||
|
|
}
|
||
|
|
},
|
||
|
|
i16ToBytes: function i16ToBytes(bytes, num) {
|
||
|
|
var a = new Uint8Array(new Uint16Array([num]).buffer);
|
||
|
|
bytes.push(a[1]);
|
||
|
|
bytes.push(a[0]);
|
||
|
|
},
|
||
|
|
i32ToBytes: function i32ToBytes(bytes, num) {
|
||
|
|
var a = new Uint8Array(new Uint32Array([num]).buffer);
|
||
|
|
bytes.push(a[3]);
|
||
|
|
bytes.push(a[2]);
|
||
|
|
bytes.push(a[1]);
|
||
|
|
bytes.push(a[0]);
|
||
|
|
},
|
||
|
|
// 格式化当前连接信息
|
||
|
|
_curInfo: function _curInfo(_self) {
|
||
|
|
var txt = "无连接";
|
||
|
|
var self = _self || this;
|
||
|
|
if (self.net_connect) {
|
||
|
|
var ip = self.net_connect.GetIp();
|
||
|
|
var port = self.net_connect.GetPort();
|
||
|
|
txt = cc.js.formatStr("连接地址:%s,端口号: %d", ip, port);
|
||
|
|
}
|
||
|
|
return txt;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
// 载入
|
||
|
|
var install = function install() {
|
||
|
|
CliSocket.init();
|
||
|
|
client.socket = CliSocket;
|
||
|
|
};
|
||
|
|
|
||
|
|
// 导出
|
||
|
|
module.exports = {
|
||
|
|
install: install
|
||
|
|
};
|
||
|
|
|
||
|
|
cc._RF.pop();
|