/** * tsrpc连接管理 */ import { HttpClient as HttpClient_Browser, WsClient as WsClient_Browser } from 'tsrpc-browser'; import { HttpClient as HttpClient_Miniapp, WsClient as WsClient_Miniapp } from 'tsrpc-miniapp'; import { serviceProto as ServiceProtoRoom, ServiceType, ServiceType as ServiceTypeRoom } from "../shared/protocols/ServiceProtoRoom"; import { GameServerConfig } from './GameServerConfig'; import { ShareConfig } from './ShareConfig'; import { Security } from './Security'; import { BaseResponse } from './base'; /** TSRPC网络模块 */ export class TsrpcNet { /** 连接房间服务器 Websocket 客户端 */ wscRoom: WsClient_Browser = null!; private static instance: TsrpcNet; static getInstance(): TsrpcNet { if (this.instance == null) { this.instance = new TsrpcNet(); //@ts-ignore window.TsrpcNet = this; } return this.instance; } constructor() { } /** * 创建连接房间服务器 Websocket 客户端 * @param serverUrl 服务器地址 * @returns WsClient */ createWscRoom(serverUrl: string) { // 创建客户端与房间服务器的 WebSocket 连接 serverUrl = serverUrl.replace(/[\u0000\x00]/g, ""); this.wscRoom = new (cc.sys.platform == cc.sys.WECHAT_GAME ? WsClient_Miniapp : WsClient_Browser)(ServiceProtoRoom, { // server: serverUrl + "?" + Date.now(), server: serverUrl, heartbeat: { interval: GameServerConfig.heartbeat_interval, timeout: GameServerConfig.heartbeat_timeout }, json: ShareConfig.json, // logger: console, logMsg: true, }); this.flowClientApi(this.wscRoom); this.flowAuth(this.wscRoom); return this.wscRoom; } /** HTTP 客户端协议数据加密、解密 */ private flowClientApi(hc: any) { if (!ShareConfig.security) return; hc.flows.preSendDataFlow.push(v => { if (v.data instanceof Uint8Array) { v.data = Security.encrypt(v.data); } return v; }); // 在处理接收到的数据之前,通常要进行加密/解密 hc.flows.preRecvDataFlow.push(v => { if (v.data instanceof Uint8Array) { v.data = Security.decrypt(v.data); } return v; }); } /** 帐号登录令牌验证是否逻辑(帐号中加入登录令牌,服务器通过令牌解析玩家数据,如果存在就是已登录) */ private flowAuth(client: any) { // HttpClient WsClient // 执行 callApi 之前协议中插入登录令牌 client.flows.preCallApiFlow.push(v => { // 请求前插入登录令牌 let ssoToken = cc.sys.localStorage.getItem('SSO_TOKEN'); if (ssoToken) { v.req.__ssoToken = ssoToken; } return v; }) // 将 callApi 的结果返回给调用方之后将登录令牌存到本地(收到协议时将登录令牌存到本地) client.flows.postApiReturnFlow.push(v => { if (v.return.isSucc) { let res = v.return.res as BaseResponse; // 请求成功后刷新登录令牌 if (res.__ssoToken !== undefined) { cc.sys.localStorage.setItem('SSO_TOKEN', res.__ssoToken); } } // 登录令牌过期时删除客户端登录令牌(可跳转到登录界面) else if (v.return.err.code === 'NEED_LOGIN') { cc.sys.localStorage.setItem('SSO_TOKEN', ''); } return v; }); } /** http请求api */ public async callApi(apiName: T, req: ServiceType['api'][T]['req']) { let ret = await this.wscRoom.callApi('RoomJoin', req); return ret; } /** ws发送消息 */ public sendMsg(msgName: T, msg: ServiceType['msg'][T]) { this.wscRoom.sendMsg(msgName, msg); } /** 监听消息 */ public listenMsg(msgName: T | RegExp, callback: Function) { this.wscRoom.listenMsg(msgName, v => { callback(v); }); } }