Network.ts 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. import { StringMap } from "../Collections/StringMap";
  2. import Gamecfg from "../common/gameCfg";
  3. import { gameMethod } from "../common/gameMethod";
  4. import { HdClubPkFightAll, PlayerLogin, PlayerLoginPlayer, PlayerLoginUser, PlayerReconnect, TaichuWajieMap, UserAdok, ZhangjieDaguai } from "../common/Xyc";
  5. import { SevBack, SevBackType } from "../common/Xys";
  6. import Config from "../Config";
  7. import { GameEvent, NetworkEvent, UserEvent, WindowEvent } from "../data/const/EventConst";
  8. import { InGame, ReportRoleType } from "../data/const/TypeConst";
  9. import GameDataCenter from "../data/GameDataCenter";
  10. import EventMng from "../manager/EventMng";
  11. import HttpRequest, { POST_DATA } from "./HttpRequest";
  12. import SevDataMng from "./SevDataMng";
  13. export default class Network {
  14. private leftSevbacks: { cb: Function, sevback: SevBack }[] = []
  15. stopRequest: boolean = false //后端提示重启后停止发送协议
  16. stopPopEp: boolean = false //处理装备的属性变化不飘字
  17. isEpChange: boolean = false
  18. private isOutClub: boolean = false // 是否退出公会
  19. private isShowTimeben: [number, string] = [0, ""] // 是否打开或刷新福利礼包
  20. cmdCounts: number = 0 //网络请求计数
  21. m_Timers: StringMap<NodeJS.Timer> = new StringMap<NodeJS.Timer>();
  22. reSentTime: number;
  23. private getLoginUrl(url: string): string {
  24. let realUrl = Gamecfg.packageInfo.getItem(Config.pid).wayhttp + url +
  25. "?version=" + Config.appVersion +
  26. "&time=" + GameDataCenter.time.sevTime
  27. return realUrl
  28. }
  29. private getCmdUrl(url: string, cmdId: number): string {
  30. let realUrl = Gamecfg.packageInfo.getItem(Config.pid).wayhttp + url +
  31. "?uuid=" + GameDataCenter.user.uuid +
  32. "&token=" + GameDataCenter.user.token +
  33. "&version=" + Config.appVersion +
  34. "&cmdId=" + cmdId +
  35. "&time=" + GameDataCenter.time.sevTime
  36. return realUrl
  37. }
  38. constructor() {
  39. }
  40. // 不需要处理回调数据的,走这里
  41. static POST_SPECIAL(path: string, body: string, cb: Function = () => { }) {
  42. let r = new XMLHttpRequest()
  43. r.open("POST", path, true)
  44. r.timeout = 15000
  45. r.setRequestHeader("Content-Type", "application/json")
  46. r.onreadystatechange = () => {
  47. if (r.status >= 200 && r.status <= 400 && r.readyState == 4) {
  48. cb()
  49. }
  50. };
  51. r.send(body)
  52. }
  53. sendLogin(url: string, body: Object, callback: Function = () => { }) {
  54. HttpRequest.POST(this.getLoginUrl(url), { uuid: GameDataCenter.user.uuid, version: Config.appVersion, url: url }, body, (result: SevBack) => {
  55. this.updateSevBack(result, callback)
  56. }, true)
  57. }
  58. send(url: string, body: Object, cb1?: (sev: SevBack) => void, cb2?: (sev: SevBack) => void, deal: number = 1, needWait: boolean = false, cmdId: number = -1) {
  59. if (this.stopRequest) {
  60. return
  61. }
  62. //每发送一个消息,消息计数累计,方便服务端做判断
  63. this.cmdCounts++
  64. //先缓存发送的消息,超时重新请求
  65. let postDataTemp: POST_DATA = {
  66. url: url,
  67. body: body,
  68. cb1: cb1,
  69. cb2: cb2,
  70. deal: deal,
  71. cmdId: cmdId == -1 ? this.cmdCounts : cmdId
  72. }
  73. let unErrArr = [PlayerReconnect.url, UserAdok.url, UserAdok.url];
  74. if (unErrArr.indexOf(url) < 0) {
  75. //重连接口,心跳包, 挂机打怪无需重新发送
  76. HttpRequest.errPostMap.Add(url, postDataTemp)
  77. let unArr = [PlayerLogin.url, PlayerLoginPlayer.url, PlayerLoginUser.url, HdClubPkFightAll.url, TaichuWajieMap.url, ZhangjieDaguai.url];
  78. if (unArr.indexOf(url) < 0) {
  79. let postTime = new Date().getTime()
  80. postDataTemp.postTime = postTime
  81. HttpRequest.curPostMap.Add(url, postDataTemp)
  82. }
  83. }
  84. this.AddTimer(url, () => {
  85. let curTime = new Date().getTime()
  86. if (!this.reSentTime) {
  87. this.reSentTime = cc.sys.platform == cc.sys.TAOBAO_MINIGAME ? 3000 : 1500;
  88. }
  89. if (HttpRequest.curPostMap.ContainsKey(url) && curTime - HttpRequest.curPostMap.Value(url).postTime >= this.reSentTime) {
  90. console.log(`1.5s后重新发送:${url}`)
  91. //遮罩计数-1
  92. EventMng.emit(NetworkEvent.WAIT, -1)
  93. this.m_Timers.Remove(url)
  94. let value = HttpRequest.curPostMap.Value(url)
  95. this.send(value.url, value.body, value.cb1, value.cb2, value.deal, false, value.cmdId)
  96. }
  97. }, 500)
  98. if (needWait) EventMng.emit(NetworkEvent.NETWAIT_MASK, true)
  99. let curCmdId = cmdId == -1 ? this.cmdCounts : cmdId
  100. HttpRequest.POST(this.getCmdUrl(url, curCmdId), { uuid: GameDataCenter.user.uuid, version: Config.appVersion, url: url }, body, (result: SevBack) => {
  101. if (needWait) EventMng.emit(NetworkEvent.NETWAIT_MASK, false)
  102. if (result.type == SevBackType.wu) {
  103. //无需处理的消息
  104. return
  105. }
  106. if (cb2) {
  107. cb2(result)
  108. }
  109. if (result.type == SevBackType.fail) {
  110. // 如果出现异常,则直接处理
  111. this.updateSevBack(result, cb1)
  112. return
  113. }
  114. if (deal == 1) {
  115. if (this.leftSevbacks.length > 0) {
  116. this.leftSevbacks.push({ cb: cb1, sevback: result })
  117. } else {
  118. this.updateSevBack(result, cb1)
  119. }
  120. } else if (deal == 2) { // 暂存弹窗信息
  121. if (this.leftSevbacks.length > 0) {
  122. this.leftSevbacks.push({ cb: cb1, sevback: result })
  123. } else {
  124. let tempSevback: SevBack = { type: result.type }
  125. this.leftSevbacks.push({ cb: () => { }, sevback: tempSevback })
  126. this.updateSevBack(result, cb1)
  127. }
  128. } else {
  129. this.leftSevbacks.push({ cb: cb1, sevback: result })
  130. }
  131. }, false)
  132. }
  133. // 处理暂存的后端数据
  134. dealLeftSevback() {
  135. this.leftSevbacks.forEach(element => {
  136. this.updateSevBack(element.sevback, element.cb)
  137. });
  138. this.leftSevbacks = []
  139. }
  140. updateSevBack(result: SevBack, cb1: Function) {
  141. // 刷新后端数据列表
  142. let oldPower: number = GameDataCenter.sevBack?.userInfo?.a?.power ?? 0;
  143. let sevback = SevDataMng.sevBackUpdate(GameDataCenter.sevBack, result)
  144. // 这里去检测通用类数据的前后对比
  145. this.isOutClub = false
  146. this.isShowTimeben = [0, ""]
  147. GameDataCenter.sevBack = sevback;
  148. if ((!gameMethod.isEmpty(result?.userInfo?.a?.power) || (!gameMethod.isEmpty(result?.userInfo?.u?.power)))) {
  149. // 更新战斗力
  150. if (GameDataCenter.zhanLi) GameDataCenter.zhanLi.updateTotalZhanLi(oldPower, sevback?.userInfo?.a?.power);
  151. }
  152. // 业务逻辑自定义参数处理
  153. for (let key in result) {
  154. let rspModels = GameDataCenter._rspModel.get(key)
  155. for (let i = 0; i < rspModels?.length; i++) {
  156. //需要分发事件的模块分发
  157. rspModels[i]?.doSevback(result)
  158. }
  159. }
  160. // 触发事件,刷新UI
  161. this.updateEvent(result, cb1)
  162. // 需要在数据处理后触发
  163. if (this.isOutClub) {
  164. }
  165. }
  166. updateEvent(result: SevBack, cb1: Function) {
  167. let alreadyRspModel = [] //已分发的模块,同个消息同个模块只分发一次
  168. for (let key in result) {
  169. let rspModels = GameDataCenter._rspModel.get(key)
  170. for (let i = 0; i < rspModels?.length; i++) {
  171. if (alreadyRspModel.indexOf(rspModels[i]) >= 0) {
  172. continue
  173. }
  174. //需要分发事件的模块分发
  175. rspModels[i]?.doEvent(result)
  176. alreadyRspModel.push(rspModels[i])
  177. }
  178. }
  179. // 执行各自协议发送者回调
  180. if (cb1) {
  181. cb1(result)
  182. }
  183. }
  184. /**
  185. * 增加定时器
  186. * @param callback
  187. * @param delta 单位毫秒ms
  188. */
  189. AddTimer(key: string, callback: Function, delta: number) {
  190. if (this.m_Timers.ContainsKey(key)) {
  191. return
  192. }
  193. let timer = setInterval(() => {
  194. callback.apply(this);
  195. }, delta);
  196. this.m_Timers.Add(key, timer);
  197. return timer;
  198. }
  199. /** 移除所有定时器 */
  200. RemoveTimers() {
  201. this.m_Timers.Foreach((key: string, value: NodeJS.Timer) => {
  202. clearInterval(value);
  203. });
  204. this.m_Timers.Clear()
  205. }
  206. }