博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用cocoscreator + node.js + websocket实现简单的聊天服务
阅读量:5076 次
发布时间:2019-06-12

本文共 38236 字,大约阅读时间需要 127 分钟。

先上个效果图:

使用cocoscreator 1.9.1 + node.js + websocket实现,没有使用socket.io, 全部自己封装,长连接进行封装后可以和短连接使用方法一样,使用简单,方便以后开发网络游戏。

1、客户端:

  主要就是聊天内容的显示,自动换行和背景扩展,代码大概如下:

cc.Class({    extends: cc.Component,    properties: {        msgLabel: cc.Label,        uidLabel: cc.Label,        msgLayout: cc.Layout,        msgBg: cc.Node,        maxLen: 500,    },    // LIFE-CYCLE CALLBACKS:    // onLoad () {},    start () {        this.node.runAction(cc.fadeTo(0.5, 255))    },    initMsg(msg, uid){        this.msgLabel.string = msg;        this.uidLabel.string = uid;        this.msgLabel.overflow = cc.Label.Overflow.NONE;        // this.msgBg.width = this.msgLabel.node.width + 10;        // this.msgBg.height = this.msgLabel.node.height + 10;        // this.node.height = this.msgBg.height + 40;        this.scheduleOnce((dt)=>{            if ( this.msgLabel.node.width >= this.maxLen){                this.msgLabel.overflow = cc.Label.Overflow.RESIZE_HEIGHT;                this.msgLabel.node.width = this.maxLen;            }            this.msgBg.width = this.msgLabel.node.width + 10;            this.msgBg.height = this.msgLabel.node.height + 10;            this.node.height = this.msgBg.height + 40;        }, 0);        this.node.opacity = 0;    }    // update (dt) {},});

  网络部分分成了四层:

    1、socket 封装基础的websocket, 这里是最底层,也是真正链接的开始

    2、network 控制socket链接层,实现各回调接口

    3、netproxy 封装各服务功能,把长连接变成短连接的请求方式

    4、netprotocols 和服务器协商,确定每个请求的请求体格式和回复格式

  各部分代码如下:

  GameWebSocket.js:  

/** * @enum {number} */var GameWebSocketState = cc.Enum({    CONNECTING: 1,    OPEN: 2,    CLOSING: 3,    CLOSED: 4});/** * @interface */var GameWebSocketDelegate = cc.Class({    onSocketOpen: function () {    },    /**     * 收到了消息     * @param {string|Uint8Array} data     */    onSocketMessage: function (data) {    },    onSocketError: function () {    },    /**     * 连接关闭     * @param {string} reason     */    onSocketClosed: function (reason) {    }});/** * @interface */var GameWebSocketInterface = cc.Class({    connect: function () {    },    send: function () {    },    close: function () {    },    getState: function () {    }});var GameWebSocket = cc.Class({    extends: GameWebSocketInterface,    properties: {        /**         * @type {String} 服务器地址         */        _address: null,        /**         * @type {GameWebSocketDelegate}         */        _delegate: null,        /**         * @type {WebSocket}         */        _webSocket: null,    },    /**     * @param {string} address 服务器地址     * @param {GameWebSocketDelegate} delegate 回调接口     */    init: function(address, delegate){        this._address = address;        this._delegate = delegate;        this._webSocket = null;    },    connect: function () {        cc.log('connect to '+ this._address);        var ws = this._webSocket = new WebSocket(this._address);        ws.onopen = this._delegate.onSocketOpen.bind(this._delegate);        ws.onmessage = function (param) {            this._delegate.onSocketMessage(param.data);        }.bind(this);        ws.onerror = this._delegate.onSocketError.bind(this._delegate);        // function({code: Number, reason: String, wasClean: Boolean})}        ws.onclose = function (param) {            this._delegate.onSocketClosed(param.reason);        }.bind(this);    },    /**     * 发送数据     * @param {string|Uint8Array} stringOrBinary     */    send: function (stringOrBinary) {        this._webSocket.send(stringOrBinary);    },    close: function () {        if (!this._webSocket) {            return;        }        try {            this._webSocket.close();        } catch (err) {            cc.log('error while closing webSocket', err.toString());        }        this._webSocket = null;    },    getState: function () {        if (this._webSocket) {            switch(this._webSocket.readyState){                case WebSocket.OPEN:                    return GameWebSocketState.OPEN;                case WebSocket.CONNECTING:                    return GameWebSocketState.CONNECTING;                case WebSocket.CLOSING:                    return GameWebSocketState.CLOSING;                case WebSocket.CLOSED:                    return GameWebSocketState.CLOSED;            }        }        return GameWebSocketState.CLOSED;    }});module.exports = {    GameWebSocketState: GameWebSocketState,    GameWebSocketDelegate: GameWebSocketDelegate,    GameWebSocketInterface: GameWebSocketInterface,    GameWebSocket: GameWebSocket};

  GameNetwork.js

/** * Created by skyxu on 2018/10/9. */"use strict";let GameWebSocket = require("./GameWebSocket");let GameProtocols = require("./GameProtocols");/** * 服务器回复消息状态,判断回复消息的各种问题 */var response_state = {    ERROR_OK : '0'};/** * 请求回调对象,收到服务器回调后的回调方法 */var NetworkCallback = cc.Class({    properties: {        /**         * @type {BaseRequest} request         */        request: null,        /**         * 请求回调对方法         */        callback: null    },    /**     * @param {BaseRequest} request     * @param {function(BaseResponse): boolean} callback     */    init: function (request, callback) {        this.request = request;        this.callback = callback;    }});let GameNetwork = cc.Class({    extends: GameWebSocket.GameWebSocketDelegate,    ctor: function() {        this._socket = null;        this._delegate = null;        /**         * 每次发送请求,都需要有一个唯一的编号         * @type {number}         * @private         */        this._requestSequenceId = 0;        /**         * 接受服务器主动下发的response回调         * key 表示BaseResponse.act         * @type {Object.
)>} */ this.pushResponseCallback = {}; /** * 根据seq保存Request和其callback,以便在收到服务器的响应后回调 * @type {Object.
} * @private */ this._networkCallbacks = {}; }, setDelegate: function (delegate) { this._delegate = delegate; }, /** * 注册服务器主动推送的response 回调 */ registerPushResponseCallback : function(act, callback){ this.pushResponseCallback[act] = callback; }, /** * 判断socket已连接成功,可以通信 * @returns {boolean} */ isSocketOpened: function(){ return (this._socket && this._socket.getState() == GameWebSocket.GameWebSocketState.OPEN); }, isSocketClosed: function () { return this._socket == null; }, /** * 启动连接 */ connect: function (url) { cc.log("webSocketUrls=" + url); this._requestSequenceId = 0; this._socket = new GameWebSocket.GameWebSocket(); this._socket.init(url, this); this._socket.connect(); }, closeConnect: function () { if(this._socket){ this._socket.close(); } }, onSocketOpen: function () { cc.log('Socket:onOpen'); if(this._delegate && this._delegate.onNetworkOpen){ this._delegate.onNetworkOpen(); } }, onSocketError: function () { cc.log('Socket:onError'); }, onSocketClosed: function (reason) { cc.log('Socket:onClose', reason); if (this._socket) { this._socket.close(); } this._socket = null; if(this._delegate && this._delegate.onNetworkClose){ this._delegate.onNetworkClose(); } }, onSocketMessage: function (msg) { this._onResponse(msg); }, _onResponse: function(responseData){ cc.log('response->resp:', responseData); var responseJson = JSON.parse(responseData); var responseClass = GameProtocols.response_classes[responseJson.act]; /** * @type {object.
} */ var response = new responseClass(); response.loadData(responseJson.data); response.act = responseJson.act; response.seq = responseJson.seq; response.err = responseJson.err; response.ts = responseJson.ts; // 如果指定了回调函数,先回调 var ignoreError = false; if(response.seq != -1){ // 处理服务器推送消息 var pushCallback = this.pushResponseCallback[response.act]; if(pushCallback){ pushCallback(response); } // request回调 var callbackObj = this._networkCallbacks[response.seq]; if(callbackObj){ ignoreError = callbackObj.callback(response); // try {
// ignoreError = callbackObj.callback(response); // } catch (err) {
// cc.log(err + " error in response callback of " + response.act); // } finally {
// delete this._networkCallbacks[response.seq]; // } } } //有错,且不忽略,则统一处理错误 if(response.err && response.err != response_state.ERROR_OK && !ignoreError){ if (response.is_async) { // 异步请求,如果出错了,应该需要重新登录 // todo 重新登录?或者重新同步数据? } else { // 同步请求,如果出错了,需要显示错误信息 // todo 显示错误 var msg = responseJson.msg; cc.log('server err ' + msg); } } }, /** * 向服务器发送请求。 * * 如果提供了callback,在收到response后会被回调。如果response是一个错误(status!=ERR_OK),则需要决定由谁来负责处理错误。 * 如果callback中已经对错误进行了处理,应该返回true,这样会忽略该错误。否则应该返回false,则负责处理该错误。 * * 特别注意:如果这是一个异步(is_async)请求,且出错,一般来讲应该重新登录/同步。但是如果callback返回了true,不会进行 * 任何处理,也就是不会重新登录/同步。请小心确定返回值。 * * @param {object.
} * @param {function(BaseResponse): boolean=} opt_callback 回调函数。出错的情况下,如果返回true,则不会再次处理错误。 */ sendRequest: function (request, opt_callback) { // 每个请求的seq应该唯一,且递增 request.seq = ++this._requestSequenceId; //生成NetworkCallback对象,绑定请求seq和回调方法 if(opt_callback){ this._networkCallbacks[request.seq] = new NetworkCallback(); this._networkCallbacks[request.seq].init(request, opt_callback); } this._sendSocketRequest(false, request); }, /** * sendRequest的不发送data字段 */ sendRequestNoData: function (request, opt_callback) { // 每个请求的seq应该唯一,且递增 request.seq = ++this._requestSequenceId; //生成NetworkCallback对象,绑定请求seq和回调方法 if(opt_callback){ this._networkCallbacks[request.seq] = new NetworkCallback(); this._networkCallbacks[request.seq].init(request, opt_callback); } this._sendSocketRequest(true, request); }, /** * @param {Boolean} isNoData * @param {object.
} req */ _sendSocketRequest: function (isNoData, req) { cc.assert(this._socket); if (this.isSocketOpened()){ //通过json的方法生成请求字符串 var msg = null; if(isNoData){ msg = JSON.stringify({seq:req.seq, act:req.act}); }else{ msg = JSON.stringify({seq:req.seq, act:req.act, data:req}); } cc.log("WebSocketDelegate::send->" + msg); this._socket.send(msg); } else{ // todo } }});module.exports = GameNetwork;

  GameProtocols.js

/** * Created by skyxu on 2018/10/9. */"use strict";/** * 消息基类对象,请求消息BaseRequest, 回调消息BaseResponse都继承BaseProtocol */let BaseProtocol = cc.Class({    ctor: function () {        /**         * 请求动作类型         */        this.act = '';        /**         * 每个请求的sequence_id应该唯一         */        this.seq = 0;        /**         * 错误代码,0为正常         */        this.err = 0;        /**         * 是否需要等待服务器回调         */        this.is_async = false;    }});/** * 请求消息基类,客户端的请求都继承这个类 */let BaseRequest = cc.Class({    extends: BaseProtocol});/** * 服务器返回的消息对应的对象,包含返回数据,一般和BaseRequest成对使用 * @class BaseResponse * @extends BaseProtocol */let BaseResponse = cc.Class({    extends: BaseProtocol,    /**     * 读取返回数据,设置BaseResponse对象     */    loadData: function (data) {        var key;        for (key in data) {            if(!this.hasOwnProperty(key)){                continue;            }            if(data[key] !== undefined && data[key] !== null){                this[key] = data[key];            }        }    }});let HeartRequest = cc.Class({    extends: BaseRequest,    ctor(){        this.act = 'heart';        this.t = -1;    // 发送时间    }});let HeartResponse = cc.Class({    extends: BaseResponse,    ctor(){        this.act = 'heart';        this.t = -1;    }});let ChatRequest = cc.Class({    extends: BaseRequest,    ctor(){        this.act = 'chat';        this.msg = '';        this.uid = '';    }});let ChatResponse = cc.Class({    extends: BaseResponse,    ctor(){        this.act = 'chat';        this.msg = '';        this.uid = '';    }});let LoginRequest = cc.Class({    extends: BaseRequest,    ctor: function () {        this.act = 'login';        /**         * facebook用户的accessToken,或游客的UUID         */        this.token = '';        /**         * token来源,默认0:游客,1:facebook         */        this.origin = 0;        /**         * 平台: 必须为以下几种之一:android/ios/winphone/pc         */        this.os = '';        /**         * 平台系统版本         */        this.osVersion = '';        /**         * 设备产品型号, 示例 iPhone8,2, SM-G 9280         */        this.deviceModel = '';        /**         * 渠道ID         */        this.channelId = 0;        /**         * Ios设备广告标示符         */        this.idfa = '';        /**         * 安卓设备id         */        this.androidId = '';        /**         * Google广告平台账号,安装了google play的设备可取到         */        this.googleAid = '';        /**         * 应用版本号         */        this.appVersion = '';        /**         * 取package name或者bundle id         */        this.packName = '';        /**         * 设备语言         * @type {string}         */        this.language = '';        this.locale = "";    }});let LoginResponse = cc.Class({    extends: BaseResponse,    ctor: function () {        this.act = 'login';        /**         * 游客第一次登录时返回的token,需要客户端保存         */        this.token = '';        /**         * 离体力下次恢复点的剩余时间秒数         * @type {number}         */        this.spStepLeftTime = 0;        /**         * 体力恢复周期         * @type {Number}         */        this.spInterval = 0;        /**         * 农场每天产出量,产出未解锁时为-1         * @type {number}         */        this.farmDailyOut = -1;        /**         * 农场已产出量         * @type {number}         */        this.farmCoins = 0;        /**         * 农场产出间隔         * @type {number}         */        this.farmInterval = null;        /**         * 用json object表示的一个player对象,字段说明参见player json对象         */        this.me = {};        /**         * 建筑数据数组         * @type {Array}         */        this.buildings = [];        /**         * 农民数据数组         * @type {Array}         */        this.farms = [];        /**         * 富豪数据         */        this.cashking = {};        /**         * 行星配置         */        this.planetConf = {};        /**         * 农民配置         */        this.farmConfList = [];        /**         * 其他配置         */        this.settingConf = {};        /**         * 好友数据         */        this.friends = [];        /**         * 好友通缉的目标列表         */        this.helpWantList = [];        /**         * 邮件消息列表         */        this.newsList = [];        /**         * 复仇列表         */        this.revengeList = [];        /**         * 商品信息         * @type {Array}         */        this.rechargeConfs = [];        /**         * 总岛数         * @type {Number}         */        this.planetConfListSize = 0;        /**         * 他人行星信息对象,仅在转到fire断线重新登录时有效         * @type {Object}         */        this.fireTarget = null;        /**         * 他人行星信息对象列表,仅在转到steal断线重新登录时有效         * @type {Array}         */        this.stealTarget = null;    }});let LogoutRequest = cc.Class({    extends: BaseRequest,    ctor: function () {        this.act = 'logout';    }});let LogoutResponse = cc.Class({    extends: BaseResponse,    ctor: function () {        this.act = 'logout';    }});/** * 绑定fb账号 * @extends BaseRequest */let BindFacebookRequest = cc.Class({    extends: BaseRequest,    ctor: function () {        this.act = 'bindFb';        /**         * facebook用户的accessToken,或游客的UUID         */        this.token = '';    }});/** * 绑定fb账号 * @extends BaseResponse */let BindFacebookResponse = cc.Class({    extends: BaseResponse,    ctor: function () {        this.act = 'bindFb';        /**         * fb数据         */        this.me = 0;        /**         * fb好友         */        this.friends = 0;    }});let SpinRequest = cc.Class({    extends: BaseRequest,    ctor: function () {        this.act = 'spin';        /**         * 倍数         * @type {Number}         */        this.x = 1;    }});let SpinResponse = cc.Class({    extends: BaseResponse,    ctor: function () {        this.act = 'spin';        /**         * 摇中的转盘ID         */        this.hit = 0;        /**         * 转到护盾,但护盾已满时,存在         * @type {number}         */        this.shieldfull = 0;        /**         * 玩家数据对象         */        this.me = {};        /**         * 他人行星信息对象,仅在转到fire时有效         * @type {*}         */        this.fireTarget = {};        /**         * 偷取对象数据         */        this.stealTarget = [];        /**         * 离体力下次恢复点的剩余时间秒数         * @type {number}         */        this.spStepLeftTime = 0;        /**         * 体力恢复周期         * @type {Number}         */        this.spInterval = 0;        /**         * 倍数         * @type {Number}         */        this.x = 1;    }});/** * 获取排名 * @extends BaseRequest */let RankRequest = cc.Class({    extends: BaseRequest,    ctor: function () {        this.act = 'rankboard';        /**         * 请求动作类型{ 0全部,1本地,2好友 }         * @type {int}         */        this.type = 0;    }});/** * 获取排名 * @extends BaseResponse */let RankResponse = cc.Class({    extends: BaseResponse,    ctor: function () {        this.act = 'rankboard';        /**         *  我的排名         */        this.myRank = 0;        /**         * 排名玩家数据         */        this.men = [];    }});//push------------------------------------------------------------------------------/** * 推送消息 被攻击 * @extends BaseResponse */var PushAttackedResponse = cc.Class({    extends: BaseResponse,    ctor: function () {        this.act = 'attacked';        /**         * 玩家更新数据         */        this.me = null;        /**         * 建筑数据         */        this.building = null;        /**         * 敌人         */        this.hatredman = null;        /**         * 消息         */        this.news = null;    }});/** * 推送消息 推送消息好友已赠送体力 * @extends BaseResponse */var PushSendSpResponse = cc.Class({    extends: BaseResponse,    ctor: function () {        this.act = 'sendSpNotify';        /**         * 好友对象         */        this.friend = null;    }});/** * 推送消息 推送消息好友已领取赠送的体力 * @extends BaseResponse */var PushTakeSpResponse = cc.Class({    extends: BaseResponse,    ctor: function () {        this.act = 'takeSpNotify';        /**         * 好友对象         */        this.friend = null;    }});/** * 推送消息 同步好友信息 * @extends BaseResponse */var PushSyncFriendInfo = cc.Class({    extends: BaseResponse,    ctor: function () {        this.act = 'friendInfoSync';        /**         * 好友         */        this.friend = null;    }});/** * 推送消息 新增好友 * @extends BaseResponse */var PushAddNewFriend = cc.Class({    extends: BaseResponse,    ctor: function () {        this.act = 'newFriend';        /**         * 好友         */        this.friend = null;        /**         * 消息         */        this.news = null;    }});/** * debug回调 * @extends BaseRequest */let DebugChangeMeRequest = cc.Class({    extends: BaseRequest,    ctor: function () {        this.act = "cmdTest";                    //请求动作类型        this.cmd = "";        //  "player coins add 100", cmd格式:player field value 或者 player field add value        //  Building field [add] value where playerId value type value    }});/** * debug回调 * @extends BaseResponse */let DebugChangeMeResponse = cc.Class({    extends: BaseResponse,    ctor: function () {        this.act = "cmdTest";        /**         * 玩家数据         * @type {Object}         */        this.me = {};        /**         * 体力恢复周期         * @type {Number}         */        this.spInterval = null;        /**         * 体力恢复剩余时间         * @type {Number}         */        this.spStepLeftTime = null;        /**         * 存钱罐速度         * @type {Number}         */        this.farmDailyOut = null;        /**         * 存钱罐可回收金币         * @type {Number}         */        this.farmCoins = null;        /**         * 存钱罐回收周期         * @type {Number}         */        this.farmInterval = null;        /**         * 岛屿建筑数据         * @type {Array}         */        this.buildings = null;    }});let response_classes = {    login: LoginResponse,    logout: LogoutResponse,    spin: SpinResponse,    bindFb: BindFacebookResponse,    rankboard: RankResponse,    heart: HeartResponse,    chat: ChatResponse,    //push    attacked: PushAttackedResponse,    sendSpNotify: PushSendSpResponse,    takeSpNotify: PushTakeSpResponse,    newFriend: PushAddNewFriend,    friendInfoSync: PushSyncFriendInfo,    // debug    cmdTest: DebugChangeMeResponse,};module.exports = {    LoginRequest: LoginRequest,    LoginResponse: LoginResponse,    LogoutRequest: LogoutRequest,    LogoutResponse: LogoutResponse,    SpinRequest: SpinRequest,    SpinResponse: SpinResponse,    BindFacebookRequest: BindFacebookRequest,    BindFacebookResponse: BindFacebookResponse,    RankRequest: RankRequest,    RankResponse: RankResponse,    HeartRequest: HeartRequest,    HeartResponse: HeartResponse,    ChatRequest: ChatRequest,    ChatResponse: ChatResponse,    // debug    DebugChangeMeRequest: DebugChangeMeRequest,    DebugChangeMeResponse: DebugChangeMeResponse,    //push消息    PushAttackedResponse: PushAttackedResponse,    PushSendSpResponse: PushSendSpResponse,    PushTakeSpResponse: PushTakeSpResponse,    PushAddNewFriend: PushAddNewFriend,    PushSyncFriendInfo: PushSyncFriendInfo,    response_classes: response_classes};

  NetProxy.js

/**  * Created by skyxu on 2018/10/9.  */ "use strict"; let GameNetwork = require("./GameNetwork"); let GameProtocols = require("./GameProtocols"); let GAME_SERVER_URL = 'ws://127.0.0.1:3000'; // GAME_SERVER_URL = 'wss://echo.websocket.org'; let NetProxy = cc.Class({
ctor: function () {
this.network = null; this._cachePushCallback = []; }, init: function () {
this.network = new GameNetwork(); this.network.setDelegate(this); this.initPushCallback(); }, connect: function () {
this.network.connect(GAME_SERVER_URL); }, closeConnect: function () {
this.network.closeConnect(); }, isNetworkOpened: function () {
return this.network.isSocketOpened(); }, isNetworkClosed: function () {
return this.network.isSocketClosed(); }, onNetworkOpen: function () {
Global.eventMgr.emit(Global.config.EVENT_NETWORK_OPENED); }, onNetworkClose: function () {
Global.eventMgr.emit(Global.config.EVENT_NETWORK_CLOSED); }, /** * 注册push回调接口 */ initPushCallback: function () {
let self = this; let pushCallback = function (resp) {
self.pushCallback(resp); }; this.network.registerPushResponseCallback('chat', pushCallback); // let pushCallback = function(response){
// if(Util.DNN(farm.game) && farm.game.loginSuccess){
// this.dealCachePush(); // this.pushCallback(response); // }else{
// this._cachePushCallback.push(response); // } // }.bind(this); // this.network.registerPushResponseCallback('attacked', pushCallback); // this.network.registerPushResponseCallback('acceptWantHelp', pushCallback); // this.network.registerPushResponseCallback('sendSpNotify', pushCallback); // this.network.registerPushResponseCallback('takeSpNotify', pushCallback); // this.network.registerPushResponseCallback('wanted', pushCallback); // this.network.registerPushResponseCallback('incomplete', pushCallback); // this.network.registerPushResponseCallback('newFriend', pushCallback); // this.network.registerPushResponseCallback('news', pushCallback); // this.network.registerPushResponseCallback('hatredInfoSync', pushCallback); // this.network.registerPushResponseCallback('friendInfoSync', pushCallback); }, /** * 处理缓存push */ dealCachePush: function () {
// if(this._cachePushCallback.length > 0){
// for(var i = 0; i < this._cachePushCallback.length; i++){
// this.pushCallback(this._cachePushCallback[i]); // } // } // this._cachePushCallback = []; }, beatHeart: function (callback) {
let req = new GameProtocols.HeartRequest(); req.t = Date.now(); this.network.sendRequest(req, callback); }, chat: function (msg) {
let req = new GameProtocols.ChatRequest(); let uid = cc.sys.localStorage.getItem("chat_uid"); req.uid = uid; req.msg = msg; this.network.sendRequest(req); }, /** * Facebook或者游客登录接口 * @param {Object.
} origin * @param token */ login: function (origin, token) {
// let req = new GameProtocols.LoginRequest(); // if(token) req.token = token; // req.origin = origin; // req.os = cc.sys.os; // req.osVersion = cc.sys.osVersion; // // req.language = cc.sys.language;//farm.FarmPlatformHelper.jsToOc(farm.FarmPlatformHelper.JSB_EVENT_JTO_GetCurrentLanguage); // /* // req.deviceModel = ''; // req.channelId = 0; // req.idfa = ''; // req.androidId = ''; // req.googleAid = ''; // req.appVersion = ''; // req.packName = ''; // */ // let callback = function (resp) {
// if(resp.err != 0){
// Global.eventMgr.emit(farm.game.gmConst.SP_EVENT_LOGIN_FAILED, resp); // return; // } // if(resp.token && resp.token.length > 0){
// farm.localStorage.setItem(farm.game.gmConst.GLS_KEY_GUEST_TOKEN, resp.token); // } // farm.localStorage.removeItem(farm.game.gmConst.GLS_KEY_IS_LOGOUT); // // // // farm.game.initConfig(resp); // farm.game.initData(resp); // farm.game.loginSuccess = true; // // // js 调取其他平台的sdk,传过去玩家id // farm.FarmPlatformHelper.jsToOc(farm.FarmPlatformHelper.JSB_EVENT_JTO_setSessionWithUid, farm.game.player.id.toString()); // // // // //登录 // farm.eventManager.emit(farm.game.gmConst.SP_EVENT_LOGIN_SUCCESS); // }; // this.network.sendRequest(req, callback); }, /** * Facebook或者游客登出 */ logout: function () {
// let req = new GameProtocols.LogoutRequest(); // this.network.sendRequest(req, function (resp) {
// if(resp.err != 0){
// cc.log("网络请求---LogoutRequest 失败"); // farm.eventManager.emit(farm.game.gmConst.SP_EVENT_LOGOUT_FAILED); // return; // } // cc.log("网络请求---LogoutRequest 成功"); // Global.eventMgr.emit(farm.game.gmConst.SP_EVENT_LOGOUT_SUCCESS); // }); }, /** * 绑定fb账号 * @param {String} token */ bindFacebook: function (token) {
// let req = new GameProtocols.BindFacebookRequest(); // req.token = token; // let callback = function (resp) {
// //绑定过得逻辑 // if(resp.err == farm.game.gmConst.ERROR_USER_HAS_REGISTERED){
// cc.log("网络请求---BindFacebookRequest 已绑定"); // farm.eventManager.emit(farm.game.gmConst.SP_EVENT_HAS_BIND_FACEBOOK); // return; // } // //绑定失败 // if(resp.err != 0){
// cc.log("网络请求---BindFacebookRequest 失败"); // farm.eventManager.emit(farm.game.gmConst.SP_EVENT_BIND_FACEBOOK_FAILED); // return; // } // //绑定成功 // cc.log("网络请求---BindFacebookRequest 成功"); // if(resp.me){
// farm.game.player.parse(resp.me); // } // if(resp.friends){
// farm.game.initFriends(resp.friends); // } // //绑定成功后删除本地token // farm.localStorage.removeItem(farm.game.gmConst.GLS_KEY_GUEST_TOKEN); // farm.eventManager.emit(farm.game.gmConst.SP_EVENT_BIND_FACEBOOK_SUCCESS); // }; // this.network.sendRequest(req, callback); }, /** * 启动转盘 */ spin: function (x) {
// let req = new GameProtocols.SpinRequest(); // if(farm.util.isNumber(x)){
// req.x = x; // } // var callback = function (resp) {
// if(resp.err != 0){
// cc.log("网络请求---spin 失败"); // farm.eventManager.emit(farm.game.gmConst.SP_EVENT_SPIN_FAILED, resp); // return; // } // cc.log("网络请求---spin 成功"); // farm.game.player.parse(resp.me); // farm.game.spTimer.updateSpTime(resp.spStepLeftTime, resp.spInterval); // farm.eventManager.emit(farm.game.gmConst.SP_EVENT_SPIN_SUCCESS, resp); // }; // this.network.sendRequest(req, callback); }, /** * 获取排名 * @param {Number} rankType 0全部,1本地,2好友 */ getRank: function (rankType) {
// let req = new GameProtocols.RankRequest(); // req.type = rankType; // let callback = function (resp) {
// if(resp.err != 0){
// cc.log("网络请求---getRank 失败"); // Global.eventMgr.emit(farm.game.gmConst.SP_EVENT_GET_RANK_FAILED, resp); // return; // } // cc.log("网络请求---getRank 成功"); // // todo 暂定排名类型 // resp._rankType = rankType; // //farm.game.initLeaderBoardArray(rankType, resp.myRank, resp.men); // if(rankType == 2 && resp.men){
// farm.game.updateFriends(resp.men); // resp.men = farm.game.sortFriendsByStar(); // } // Global.eventMgr.emit(farm.game.gmConst.SP_EVENT_GET_RANK_SUCCESS, resp); // }; // this.network.sendRequest(req, callback); }, //push回调------------------------------------------------------------------------------ /** * 推送回调 */ pushCallback: function (response) {
switch (response.act){
case "sendSpNotify": case "takeSpNotify": case "friendInfoSync": this.pushFriendSendTakeSp(response); break; case "stole": this.pushStole(response); break; case "attacked": this.pushAttacked(response); break; case "newFriend": this.pushAddNewFriend(response); break; case "chat": this.pushChat(response); break; } }, /** * 好友间互赠体力推送 * @param {PushSendSpResponse|PushTakeSpResponse} resp */ pushFriendSendTakeSp: function (resp) {
// cc.log("网络请求---push--- pushFriendSendTakeSp 成功"); // if(resp.friend) farm.game.updateFriends(resp.friend); // farm.eventManager.emit(farm.game.gmConst.SP_PUSH_EVENT_UPDATE_FRIEND); }, /** * 被偷 * @param {PushStolenResponse} resp */ pushStole: function (resp) {
// cc.log("网络请求---push--- pushStole 成功"); // if(resp.me) farm.game.player.parse(resp.me); // //if(resp.building) farm.game.buildings[resp.building.type].parse(resp.building); // if(resp.hatredman && !farm.game.getHelpWant(resp.hatredman.id)){
// farm.game.addEnemy(resp.hatredman); // } // if(resp.news){
// resp.news = farm.game.addNews(resp.news); // } // farm.eventManager.emit(farm.game.gmConst.SP_PUSH_EVENT_BE_STOLE_SUCCESS, resp); }, /** * 被攻击 * @param {PushAttackedResponse} resp */ pushAttacked: function (resp) {
// cc.log("网络请求---push--- pushAttacked 成功"); // if(resp.me) {
// farm.game.player.parse(resp.me); // farm.game.dataUpdater.updateStar(); // } // if(resp.building) farm.game.buildings[resp.building.type].parse(resp.building); // if(resp.hatredman){
// farm.game.addBadass(resp.hatredman); // if(!farm.game.getHelpWant(resp.hatredman.id)){
// farm.game.addEnemy(resp.hatredman); // } // } // if(resp.news){
// resp.news = farm.game.addNews(resp.news); // } // farm.eventManager.emit(farm.game.gmConst.SP_PUSH_EVENT_BE_ATTACK_SUCCESS, resp); }, /** * 新增好友 * @param {PushAddNewFriend} resp */ pushAddNewFriend: function (resp) {
// cc.log("网络请求---push--- pushAddNewFriend 成功"); // if(resp.friend){
// resp.friend = farm.game.addFriend(resp.friend); // } // if(resp.news){
// resp.news = farm.game.addNews(resp.news); // } // farm.eventManager.emit(farm.game.gmConst.SP_PUSH_EVENT_ADD_FRIEND_SUCCESS, resp); }, pushChat: function (resp) {
Global.eventMgr.emit(Global.config.EVENT_CHAT, resp); }, /** * debug调试请求 * @param {String} name */ debug_addCoins: function (name) {
var req = new GameProtocols.DebugChangeMeRequest(); if (name === "btnAddCoins") {
req.cmd = "player coins add 100000000"; } else if (name === "btnClearCoins") {
req.cmd = "player coins 0"; } else if (name === "btnAddEnergy") {
req.cmd = "player sp add 10"; } else if (name === "btnClearEnergy") {
req.cmd = "player sp 0"; } else if (name == "btnAddWp") {
req.cmd = "player wp add 10"; } else if (name == "btnClearWp") {
req.cmd = "player wp 0"; } else if (name == "btnUnwrap"){
req.cmd = "player fbuid null"; } else if (name == "btnWizard1"){
req.cmd = "player wizard1 0"; } else if (name == "btnWizard2"){
req.cmd = "player wizard2 0"; } else if (name == "btnClearShield"){
req.cmd = "player shield 0"; } else if (name == "btnSpEc"){
req.cmd = "SpEc stepInterval 60000"; } else if (name == "btnFarmEc"){
req.cmd = "FarmEc stepInterval 60000"; } else if (name == "btnSpEcBack"){
req.cmd = "SpEc stepInterval 3600000"; } else if (name == "btnFarmBack"){
req.cmd = "FarmEc stepInterval 86400000"; } else if (name == "btnUpdateBuild"){
req.cmd = "Building lv 5"; } else {
req.cmd = name; } // var callback = function (resp) {
// if (resp.err != 0) {
// return; // } // farm.game.player.parse(resp.me); // farm.game.spTimer.updateSpTime(resp.spStepLeftTime, resp.spInterval); // farm.game.dataUpdater.updateCoin(); // farm.game.dataUpdater.updateSp(); // farm.game.dataUpdater.updateShield(); // farm.game.dataUpdater.updateStar(); // // // if((req.cmd == "FarmEc stepInterval 60000" || req.cmd == "FarmEc stepInterval 86400000") // && farm.util.isNumber(resp.farmDailyOut) // && farm.util.isNumber(resp.farmCoins)){
// farm.game.piggyBankTimer.init(resp.farmDailyOut, resp.farmCoins, resp.farmInterval); // } // if(req.cmd == "SpEc stepInterval 60000" || req.cmd == "SpEc stepInterval 3600000"){
// farm.game.spTimer.updateSpTime(resp.spStepLeftTime, resp.spInterval); // } // if(resp.buildings){
// for(var i = 0; i < resp.buildings.length; ++i){
// farm.game.buildings[i].parse(resp.buildings[i]); // } // farm.eventManager.emit(farm.game.gmConst.SP_EVENT_UPGRADE_BUILDING_SUCCESS, resp); // farm.eventManager.emit(farm.game.gmConst.SP_DEBUG_EVENT_BUILD_TO_24_SUCCESS, resp); // } // }; // this.network.sendRequest(req, callback); }, }); module.exports = NetProxy;

2、服务端

 使用express + express-ws组件,调用WSRouter的init初始化连接即可,

let expressWS = require('express-ws');let work = require('./work');let wsRouter = null;function WSRouter(app, server){    this.app = app;    this.server = server;    this.clients = [];    expressWS(app, server);    this.listenClientConnection = ()=>{        app.ws('/', (socket, req)=>{            console.log('client connect to server successful.');            this.clients.push(socket);            console.log('clients: ' + this.clients.length);            socket.on('message', (msg)=>{                console.log('on message: ' + msg);                work(this, socket, msg);            });            socket.on('close', (msg)=>{                console.log('on close: ' + msg);                for (let index=0; index
{ console.log('on error: ' + error); }); }) }}module.exports = { init: function(app, server){ if (wsRouter == null){ wsRouter = new WSRouter(app, server); } return wsRouter; }}
module.exports = function(wsRouter, ws, msg){    let msgObj = JSON.parse(msg);    switch (msgObj.act){        case 'heart':{            msgObj.data.t = Date.now();            ws.send(JSON.stringify(msgObj));            break;        }        case 'chat': {            for (let w of wsRouter.clients){                w.send(msg);            }            break;        }        default:            break;    }}

 

转载于:https://www.cnblogs.com/skyxu123/p/9810741.html

你可能感兴趣的文章
我眼中的技术地图
查看>>
lc 145. Binary Tree Postorder Traversal
查看>>
sublime 配置java运行环境
查看>>
在centos上开关tomcat
查看>>
重启rabbitmq服务
查看>>
正则表达式(进阶篇)
查看>>
无人值守安装linux系统
查看>>
【传道】中国首部淘宝卖家演讲公开课:农业本该如此
查看>>
jQuery应用 代码片段
查看>>
MVC+Servlet+mysql+jsp读取数据库信息
查看>>
黑马程序员——2 注释
查看>>
用OGRE1.74搭建游戏框架(三)--加入人物控制和场景
查看>>
转化课-计算机基础及上网过程
查看>>
android dialog使用自定义布局 设置窗体大小位置
查看>>
ionic2+ 基础
查看>>
互联网模式下我们更加应该“专注”
查看>>
myeclipse集成jdk、tomcat8、maven、svn
查看>>
查询消除重复行
查看>>
Sand Making Plant Produced by Red Star
查看>>
Win 10 文件浏览器无法打开
查看>>