From 727e66787f61b92410c7dfa1d38a507556966509 Mon Sep 17 00:00:00 2001 From: genxium Date: Tue, 20 Dec 2022 16:01:44 +0800 Subject: [PATCH] Added inactive watchdog hint in frontend. --- battle_srv/common/constants.json | 59 ++++++++-------- battle_srv/common/constants_struct.go | 18 ++--- battle_srv/models/room.go | 18 ++--- battle_srv/ws/serve.go | 2 +- frontend/assets/plugin_scripts/constants.js | 64 +++++++++-------- frontend/assets/scenes/login.fire | 2 +- frontend/assets/scripts/Map.js | 27 ++++---- frontend/assets/scripts/WsSessionMgr.js | 76 ++++++++------------- 8 files changed, 130 insertions(+), 136 deletions(-) diff --git a/battle_srv/common/constants.json b/battle_srv/common/constants.json index 51c4ca0..01545fc 100644 --- a/battle_srv/common/constants.json +++ b/battle_srv/common/constants.json @@ -1,28 +1,28 @@ { "RET_CODE": { - "__comment__":"基础", - "OK": 9000, - "UNKNOWN_ERROR": 9001, - "INVALID_REQUEST_PARAM": 9002, - "IS_TEST_ACC": 9003, - "MYSQL_ERROR": 9004, - "NONEXISTENT_ACT": 9005, - "LACK_OF_DIAMOND": 9006, - "LACK_OF_GOLD": 9007, - "LACK_OF_ENERGY": 9008, - "NONEXISTENT_ACT_HANDLER": 9009, - "LOCALLY_NO_AVAILABLE_ROOM": 9010, - "LOCALLY_NO_SPECIFIED_ROOM": 9011, - "PLAYER_NOT_ADDABLE_TO_ROOM": 9012, - "PLAYER_NOT_READDABLE_TO_ROOM": 9013, - "PLAYER_NOT_FOUND": 9014, - "PLAYER_CHEATING": 9015, - "WECHAT_SERVER_ERROR": 9016, - "IS_BOT_ACC": 9017, + "__comment__": "Websocket", + "OK": 3000, + "UNKNOWN_ERROR": 3001, + "INVALID_REQUEST_PARAM": 3002, + "IS_TEST_ACC": 3003, + "MYSQL_ERROR": 3004, + "NONEXISTENT_ACT": 3005, + "LACK_OF_DIAMOND": 3006, + "LACK_OF_GOLD": 3007, + "LACK_OF_ENERGY": 3008, + "NONEXISTENT_ACT_HANDLER": 3009, + "LOCALLY_NO_AVAILABLE_ROOM": 3010, + "LOCALLY_NO_SPECIFIED_ROOM": 3011, + "PLAYER_NOT_ADDABLE_TO_ROOM": 3012, + "PLAYER_NOT_READDABLE_TO_ROOM": 3013, + "PLAYER_NOT_FOUND": 3014, + "PLAYER_CHEATING": 3015, + "WECHAT_SERVER_ERROR": 3016, + "IS_BOT_ACC": 3017, + "ACTIVE_WATCHDOG": 3018, + "BATTLE_STOPPED": 3019, - "__comment__":"SMS", - "SMS_CAPTCHA_REQUESTED_TOO_FREQUENTLY": 5001, - "SMS_CAPTCHA_NOT_MATCH": 5002, + "__comment__": "OTHERS", "INVALID_TOKEN": 2001, "DUPLICATED": 2002, @@ -39,12 +39,15 @@ "FAILED_TO_DELETE": 2015, "FAILED_TO_CREATE": 2016, "INCORRECT_PHONE_NUMBER": 2018, - "INSUFFICIENT_MEM_TO_ALLOCATE_CONNECTION": 3001, - "PASSWORD_RESET_CODE_GENERATION_PER_EMAIL_TOO_FREQUENTLY": 4000, - "TRADE_CREATION_TOO_FREQUENTLY": 4002, - "MAP_NOT_UNLOCKED": 4003, + "INSUFFICIENT_MEM_TO_ALLOCATE_CONNECTION": 2019, + "PASSWORD_RESET_CODE_GENERATION_PER_EMAIL_TOO_FREQUENTLY": 2020, + "TRADE_CREATION_TOO_FREQUENTLY": 2021, + "MAP_NOT_UNLOCKED": 2022, + + "GET_SMS_CAPTCHA_RESP_ERROR_CODE": 2023, + "SMS_CAPTCHA_REQUESTED_TOO_FREQUENTLY": 2024, + "SMS_CAPTCHA_NOT_MATCH": 2025, - "GET_SMS_CAPTCHA_RESP_ERROR_CODE": 5003, "NOT_IMPLEMENTED_YET": 65535 }, "AUTH_CHANNEL": { @@ -62,6 +65,6 @@ }, "WS": { "INTERVAL_TO_PING": 2000, - "WILL_KICK_IF_INACTIVE_FOR": 6000 + "WILL_KICK_IF_INACTIVE_FOR": 4000 } } diff --git a/battle_srv/common/constants_struct.go b/battle_srv/common/constants_struct.go index 570e26b..a17380c 100644 --- a/battle_srv/common/constants_struct.go +++ b/battle_srv/common/constants_struct.go @@ -15,10 +15,13 @@ type constants struct { SmsValidResendPeriodSeconds int `json:"SMS_VALID_RESEND_PERIOD_SECONDS"` } `json:"PLAYER"` RetCode struct { + ActiveWatchdog int `json:"ACTIVE_WATCHDOG"` + BattleStopped int `json:"BATTLE_STOPPED"` Duplicated int `json:"DUPLICATED"` FailedToCreate int `json:"FAILED_TO_CREATE"` FailedToDelete int `json:"FAILED_TO_DELETE"` FailedToUpdate int `json:"FAILED_TO_UPDATE"` + GetSmsCaptchaRespErrorCode int `json:"GET_SMS_CAPTCHA_RESP_ERROR_CODE"` IncorrectCaptcha int `json:"INCORRECT_CAPTCHA"` IncorrectHandle int `json:"INCORRECT_HANDLE"` IncorrectPassword int `json:"INCORRECT_PASSWORD"` @@ -28,27 +31,26 @@ type constants struct { InvalidEmailLiteral int `json:"INVALID_EMAIL_LITERAL"` InvalidRequestParam int `json:"INVALID_REQUEST_PARAM"` InvalidToken int `json:"INVALID_TOKEN"` - IsTestAcc int `json:"IS_TEST_ACC"` IsBotAcc int `json:"IS_BOT_ACC"` + IsTestAcc int `json:"IS_TEST_ACC"` LackOfDiamond int `json:"LACK_OF_DIAMOND"` LackOfEnergy int `json:"LACK_OF_ENERGY"` LackOfGold int `json:"LACK_OF_GOLD"` + LocallyNoAvailableRoom int `json:"LOCALLY_NO_AVAILABLE_ROOM"` + LocallyNoSpecifiedRoom int `json:"LOCALLY_NO_SPECIFIED_ROOM"` MapNotUnlocked int `json:"MAP_NOT_UNLOCKED"` MysqlError int `json:"MYSQL_ERROR"` - GetSmsCaptchaRespErrorCode int `json:"GET_SMS_CAPTCHA_RESP_ERROR_CODE"` NewHandleConflict int `json:"NEW_HANDLE_CONFLICT"` NonexistentAct int `json:"NONEXISTENT_ACT"` NonexistentActHandler int `json:"NONEXISTENT_ACT_HANDLER"` - LocallyNoAvailableRoom int `json:"LOCALLY_NO_AVAILABLE_ROOM"` - LocallyNoSpecifiedRoom int `json:"LOCALLY_NO_SPECIFIED_ROOM"` - PlayerNotAddableToRoom int `json:"PLAYER_NOT_ADDABLE_TO_ROOM"` - PlayerNotReAddableToRoom int `json:"PLAYER_NOT_READDABLE_TO_ROOM"` - PlayerNotFound int `json:"PLAYER_NOT_FOUND"` - PlayerCheating int `json:"PLAYER_CHEATING"` NotImplementedYet int `json:"NOT_IMPLEMENTED_YET"` NoAssociatedEmail int `json:"NO_ASSOCIATED_EMAIL"` Ok int `json:"OK"` PasswordResetCodeGenerationPerEmailTooFrequently int `json:"PASSWORD_RESET_CODE_GENERATION_PER_EMAIL_TOO_FREQUENTLY"` + PlayerCheating int `json:"PLAYER_CHEATING"` + PlayerNotAddableToRoom int `json:"PLAYER_NOT_ADDABLE_TO_ROOM"` + PlayerNotFound int `json:"PLAYER_NOT_FOUND"` + PlayerNotReaddableToRoom int `json:"PLAYER_NOT_READDABLE_TO_ROOM"` SendEmailTimeout int `json:"SEND_EMAIL_TIMEOUT"` SmsCaptchaNotMatch int `json:"SMS_CAPTCHA_NOT_MATCH"` SmsCaptchaRequestedTooFrequently int `json:"SMS_CAPTCHA_REQUESTED_TOO_FREQUENTLY"` diff --git a/battle_srv/models/room.go b/battle_srv/models/room.go index b9a28de..02d588e 100644 --- a/battle_srv/models/room.go +++ b/battle_srv/models/room.go @@ -170,9 +170,10 @@ type Room struct { LastAllConfirmedInputList []uint64 JoinIndexBooleanArr []bool - BackendDynamicsEnabled bool - LastRenderFrameIdTriggeredAt int64 - PlayerDefaultSpeed int32 + BackendDynamicsEnabled bool + ForceAllResyncOnAnyActiveSlowTicker bool + LastRenderFrameIdTriggeredAt int64 + PlayerDefaultSpeed int32 BulletBattleLocalIdCounter int32 dilutedRollbackEstimatedDtNanos int64 @@ -210,7 +211,7 @@ func (pR *Room) AddPlayerIfPossible(pPlayerFromDbInit *Player, session *websocke pR.PlayerSignalToCloseDict[playerId] = signalToCloseConnOfThisPlayer newWatchdog := NewWatchdog(ConstVals.Ws.WillKickIfInactiveFor, func() { Logger.Warn("Conn inactive watchdog triggered#1:", zap.Any("playerId", playerId), zap.Any("roomId", pR.Id), zap.Any("roomState", pR.State), zap.Any("roomEffectivePlayerCount", pR.EffectivePlayerCount)) - signalToCloseConnOfThisPlayer(Constants.RetCode.UnknownError, "") + signalToCloseConnOfThisPlayer(Constants.RetCode.ActiveWatchdog, "") }) newWatchdog.Stop() pR.PlayerActiveWatchdogDict[playerId] = newWatchdog @@ -247,7 +248,7 @@ func (pR *Room) ReAddPlayerIfPossible(pTmpPlayerInstance *Player, session *webso pR.PlayerSignalToCloseDict[playerId] = signalToCloseConnOfThisPlayer pR.PlayerActiveWatchdogDict[playerId] = NewWatchdog(ConstVals.Ws.WillKickIfInactiveFor, func() { Logger.Warn("Conn inactive watchdog triggered#2:", zap.Any("playerId", playerId), zap.Any("roomId", pR.Id), zap.Any("roomState", pR.State), zap.Any("roomEffectivePlayerCount", pR.EffectivePlayerCount)) - signalToCloseConnOfThisPlayer(Constants.RetCode.UnknownError, "") + signalToCloseConnOfThisPlayer(Constants.RetCode.ActiveWatchdog, "") }) // For ReAdded player the new watchdog starts immediately Logger.Warn("ReAddPlayerIfPossible finished.", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("joinIndex", pEffectiveInRoomPlayerInstance.JoinIndex), zap.Any("playerBattleState", pEffectiveInRoomPlayerInstance.BattleState), zap.Any("roomState", pR.State), zap.Any("roomEffectivePlayerCount", pR.EffectivePlayerCount), zap.Any("AckingFrameId", pEffectiveInRoomPlayerInstance.AckingFrameId), zap.Any("AckingInputFrameId", pEffectiveInRoomPlayerInstance.AckingInputFrameId), zap.Any("LastSentInputFrameId", pEffectiveInRoomPlayerInstance.LastSentInputFrameId)) @@ -776,7 +777,8 @@ func (pR *Room) OnDismissed() { pR.InputFrameUpsyncDelayTolerance = (pR.NstDelayFrames >> pR.InputScaleFrames) - 1 // this value should be strictly smaller than (NstDelayFrames >> InputScaleFrames), otherwise "type#1 forceConfirmation" might become a lag avalanche pR.MaxChasingRenderFramesPerUpdate = 12 // Don't set this value too high to avoid exhausting frontend CPU within a single frame - pR.BackendDynamicsEnabled = true // [WARNING] When "false", recovery upon reconnection wouldn't work! + pR.BackendDynamicsEnabled = true // [WARNING] When "false", recovery upon reconnection wouldn't work! + pR.ForceAllResyncOnAnyActiveSlowTicker = false // See tradeoff discussion in "downsyncToAllPlayers" punchSkillId := int32(1) pR.MeleeSkillConfig = make(map[int32]*MeleeBullet, 0) pR.MeleeSkillConfig[punchSkillId] = &MeleeBullet{ @@ -1769,7 +1771,7 @@ func (pR *Room) downsyncToAllPlayers(inputsBufferSnapshot *InputsBufferSnapshot) break } /* - [WARNING] There's a tradeoff here, if the `ACTIVE SLOW TICKER` doesn't resume for a long period of time, the current approach is to kick it out by "connWatchdog" instead of forcing resync of all players in the same battle all the way along. + [WARNING] There's a tradeoff for setting/unsetting "ForceAllResyncOnAnyActiveSlowTicker" here, if the `ACTIVE SLOW TICKER` doesn't resume for a long period of time, the current approach is to kick it out by "connWatchdog" instead of forcing resync of all players in the same battle all the way along. [FIXME] In practice, I tested in internet environment by toggling player#1 "CPU throttling: 1x -> 4x -> 1x -> 6x -> 1x" and checked the logs of all players which showed that "all received inputFrameIds are consecutive for all players", yet not forcing resync of all players here still result in occasional inconsistent graphics for the `ACTIVE NORMAL TICKER`s. @@ -1778,7 +1780,7 @@ func (pR *Room) downsyncToAllPlayers(inputsBufferSnapshot *InputsBufferSnapshot) */ thatPlayerJoinMask := uint64(1 << uint32(player.JoinIndex-1)) isActiveSlowTicker := (0 < (thatPlayerJoinMask & inputsBufferSnapshot.UnconfirmedMask)) && (PlayerBattleStateIns.ACTIVE == playerBattleState) - if isActiveSlowTicker { + if pR.ForceAllResyncOnAnyActiveSlowTicker && isActiveSlowTicker { inputsBufferSnapshot.ShouldForceResync = true break } diff --git a/battle_srv/ws/serve.go b/battle_srv/ws/serve.go index e8de933..8299428 100644 --- a/battle_srv/ws/serve.go +++ b/battle_srv/ws/serve.go @@ -373,7 +373,7 @@ func Serve(c *gin.Context) { // TODO: Is there any potential edge-trigger improvement like the epoll approach mentioned above for the following statement? See discussion in https://github.com/gorilla/websocket/issues/122 _, bytes, err := conn.ReadMessage() if nil != err { - Logger.Error("About to `signalToCloseConnOfThisPlayer`", zap.Any("roomId", pRoom.Id), zap.Any("playerId", playerId), zap.Error(err)) + Logger.Error("About to `signalToCloseConnOfThisPlayer` due to conn.ReadMessage err", zap.Any("roomId", pRoom.Id), zap.Any("playerId", playerId), zap.Error(err)) signalToCloseConnOfThisPlayer(Constants.RetCode.UnknownError, "") return nil } diff --git a/frontend/assets/plugin_scripts/constants.js b/frontend/assets/plugin_scripts/constants.js index c615bab..82875d6 100644 --- a/frontend/assets/plugin_scripts/constants.js +++ b/frontend/assets/plugin_scripts/constants.js @@ -23,9 +23,9 @@ var constants = { FILE_NAME: { TREASURE_PICKEDUP: "TreasurePicked", CRASHED_BY_TRAP_BULLET: "CrashedByTrapBullet", - HIGH_SCORE_TREASURE_PICKED:"HighScoreTreasurePicked", - COUNT_DOWN_10SEC_TO_END:"countDown10SecToEnd", - BGM: "BGM" + HIGH_SCORE_TREASURE_PICKED: "HighScoreTreasurePicked", + COUNT_DOWN_10SEC_TO_END: "countDown10SecToEnd", + BGM: "BGM" } }, ROUTE_PATH: (_ROUTE_PATH = { @@ -55,39 +55,40 @@ var constants = { }, RET_CODE: { /** - * NOTE: The "RET_CODE"s from 1000-1015 are reserved for the websocket "WebsocketStdCloseCode"s. + * NOTE: The "RET_CODE"s from 1000-1015 are reserved for the websocket "WebsocketStdCloseCode"s, custom codes should be between 3000-4999 * * References * - https://tools.ietf.org/html/rfc6455#section-7.4 * - https://godoc.org/github.com/gorilla/websocket#pkg-constants. */ - "__comment__": "基础", - "OK": 9000, - "UNKNOWN_ERROR": 9001, - "INVALID_REQUEST_PARAM": 9002, - "IS_TEST_ACC": 9003, - "MYSQL_ERROR": 9004, - "NONEXISTENT_ACT": 9005, - "LACK_OF_DIAMOND": 9006, - "LACK_OF_GOLD": 9007, - "LACK_OF_ENERGY": 9008, - "NONEXISTENT_ACT_HANDLER": 9009, - "LOCALLY_NO_AVAILABLE_ROOM": 9010, - "LOCALLY_NO_SPECIFIED_ROOM": 9011, - "PLAYER_NOT_ADDABLE_TO_ROOM": 9012, - "PLAYER_NOT_READDABLE_TO_ROOM": 9013, - "PLAYER_NOT_FOUND": 9014, - "PLAYER_CHEATING": 9015, - + "__comment__": "Websocket", + "OK": 3000, + "UNKNOWN_ERROR": 3001, + "INVALID_REQUEST_PARAM": 3002, + "IS_TEST_ACC": 3003, + "MYSQL_ERROR": 3004, + "NONEXISTENT_ACT": 3005, + "LACK_OF_DIAMOND": 3006, + "LACK_OF_GOLD": 3007, + "LACK_OF_ENERGY": 3008, + "NONEXISTENT_ACT_HANDLER": 3009, + "LOCALLY_NO_AVAILABLE_ROOM": 3010, + "LOCALLY_NO_SPECIFIED_ROOM": 3011, + "PLAYER_NOT_ADDABLE_TO_ROOM": 3012, + "PLAYER_NOT_READDABLE_TO_ROOM": 3013, + "PLAYER_NOT_FOUND": 3014, + "PLAYER_CHEATING": 3015, + "WECHAT_SERVER_ERROR": 3016, + "IS_BOT_ACC": 3017, + "ACTIVE_WATCHDOG": 3018, + "BATTLE_STOPPED": 3019, - "__comment__": "SMS", - "SMS_CAPTCHA_REQUESTED_TOO_FREQUENTLY": 5001, - "SMS_CAPTCHA_NOT_MATCH": 5002, + "__comment__": "OTHERS", "INVALID_TOKEN": 2001, "DUPLICATED": 2002, "INCORRECT_HANDLE": 2004, - "NONEXISTENT_HANDLE": 2005, + "INCORRECT_PASSWORD": 2006, "INCORRECT_CAPTCHA": 2007, "INVALID_EMAIL_LITERAL": 2008, @@ -99,9 +100,14 @@ var constants = { "FAILED_TO_DELETE": 2015, "FAILED_TO_CREATE": 2016, "INCORRECT_PHONE_NUMBER": 2018, - "PASSWORD_RESET_CODE_GENERATION_PER_EMAIL_TOO_FREQUENTLY": 4000, - "TRADE_CREATION_TOO_FREQUENTLY": 4002, - "MAP_NOT_UNLOCKED": 4003, + "INSUFFICIENT_MEM_TO_ALLOCATE_CONNECTION": 2019, + "PASSWORD_RESET_CODE_GENERATION_PER_EMAIL_TOO_FREQUENTLY": 2020, + "TRADE_CREATION_TOO_FREQUENTLY": 2021, + "MAP_NOT_UNLOCKED": 2022, + + "GET_SMS_CAPTCHA_RESP_ERROR_CODE": 2023, + "SMS_CAPTCHA_REQUESTED_TOO_FREQUENTLY": 2024, + "SMS_CAPTCHA_NOT_MATCH": 2025, "NOT_IMPLEMENTED_YET": 65535 }, diff --git a/frontend/assets/scenes/login.fire b/frontend/assets/scenes/login.fire index 76a6bfa..740ec4a 100644 --- a/frontend/assets/scenes/login.fire +++ b/frontend/assets/scenes/login.fire @@ -440,7 +440,7 @@ "array": [ 0, 0, - 216.50635094610968, + 215.95961841836203, 0, 0, 0, diff --git a/frontend/assets/scripts/Map.js b/frontend/assets/scripts/Map.js index 9d6b0b0..3dcc0aa 100644 --- a/frontend/assets/scripts/Map.js +++ b/frontend/assets/scripts/Map.js @@ -11,6 +11,7 @@ window.ALL_MAP_STATES = { }; window.ALL_BATTLE_STATES = { + NONE: -1, WAITING: 0, IN_BATTLE: 1, IN_SETTLEMENT: 2, @@ -222,15 +223,19 @@ cc.Class({ onDestroy() { const self = this; console.warn("+++++++ Map onDestroy()"); - if (null == self.battleState || ALL_BATTLE_STATES.WAITING == self.battleState) { + if (null == self.battleState || ALL_BATTLE_STATES.IN_BATTLE != self.battleState) { window.clearBoundRoomIdInBothVolatileAndPersistentStorage(); } if (null != window.handleBattleColliderInfo) { window.handleBattleColliderInfo = null; } - if (null != window.handleClientSessionError) { - window.handleClientSessionError = null; - } + }, + + onManualRejoinRequired(labelString) { + const self = this; + self.battleState = ALL_BATTLE_STATES.NONE; // Effectively stops "update(dt)" + self.showPopupInCanvas(self.gameRuleNode); + self.popupSimplePressToGo(labelString, false); }, popupSimplePressToGo(labelString, hideYesButton) { @@ -334,16 +339,6 @@ cc.Class({ self.showCriticalCoordinateLabels = false; console.warn("+++++++ Map onLoad()"); - window.handleClientSessionError = function() { - console.warn('+++++++ Common handleClientSessionError()'); - - if (ALL_BATTLE_STATES.IN_SETTLEMENT == self.battleState) { - console.log("Battled ended by settlement"); - } else { - console.warn("Connection lost, going back to login page"); - window.clearLocalStorageAndBackToLoginScene(true); - } - }; const mapNode = self.node; const canvasNode = mapNode.parent; @@ -759,6 +754,8 @@ cc.Class({ if (ALL_BATTLE_STATES.IN_BATTLE != self.battleState) { return; } + window.closeWSConnection(constants.RET_CODE.BATTLE_STOPPED); + self.battleState = ALL_BATTLE_STATES.IN_SETTLEMENT; self.countdownNanos = null; self.logBattleStats(); if (self.musicEffectManagerScriptIns) { @@ -769,7 +766,6 @@ cc.Class({ const resultPanelScriptIns = resultPanelNode.getComponent("ResultPanel"); resultPanelScriptIns.showPlayerInfo(self.playerRichInfoDict); window.clearBoundRoomIdInBothVolatileAndPersistentStorage(); - self.battleState = ALL_BATTLE_STATES.IN_SETTLEMENT; self.showPopupInCanvas(resultPanelNode); // Clear player info @@ -945,6 +941,7 @@ cc.Class({ showPopupInCanvas(toShowNode) { const self = this; + toShowNode.active = true; self.disableInputControls(); self.transitToState(ALL_MAP_STATES.SHOWING_MODAL_POPUP); safelyAddChild(self.widgetsAboveAllNode, toShowNode); diff --git a/frontend/assets/scripts/WsSessionMgr.js b/frontend/assets/scripts/WsSessionMgr.js index e797ae9..93079f1 100644 --- a/frontend/assets/scripts/WsSessionMgr.js +++ b/frontend/assets/scripts/WsSessionMgr.js @@ -12,7 +12,6 @@ window.DOWNSYNC_MSG_ACT_INPUT_BATCH = 2; window.DOWNSYNC_MSG_ACT_BATTLE_STOPPED = 3; window.DOWNSYNC_MSG_ACT_FORCED_RESYNC = 4; - window.sendSafely = function(msgStr) { /** * - "If the data can't be sent (for example, because it needs to be buffered but the buffer is full), the socket is closed automatically." @@ -28,10 +27,13 @@ window.sendUint8AsBase64Safely = function(msgUint8Arr) { window.clientSession.send(_uint8ToBase64(msgUint8Arr)); } -window.closeWSConnection = function() { - if (null == window.clientSession || window.clientSession.readyState != WebSocket.OPEN) return; +window.closeWSConnection = function(code, reason) { + if (null == window.clientSession || window.clientSession.readyState != WebSocket.OPEN) { + console.log(`"window.clientSession" is already closed or destroyed.`); + return; + } console.log(`Closing "window.clientSession" from the client-side.`); - window.clientSession.close(); + window.clientSession.close(code, reason); } window.getBoundRoomIdFromPersistentStorage = function() { @@ -184,39 +186,33 @@ window.initPersistentSessionClient = function(onopenCb, expectedRoomId) { clientSession.onerror = function(evt) { console.error("Error caught on the WS clientSession: ", evt); - if (window.handleClientSessionError) { - window.handleClientSessionError(); - } + window.clearLocalStorageAndBackToLoginScene(true); }; clientSession.onclose = function(evt) { // [WARNING] The callback "onclose" might be called AFTER the webpage is refreshed with "1001 == evt.code". - console.warn("The WS clientSession is closed: ", evt, clientSession); - if (false == evt.wasClean) { - /* - Chrome doesn't allow the use of "CustomCloseCode"s (yet) and will callback with a "WebsocketStdCloseCode 1006" and "false == evt.wasClean" here. See https://tools.ietf.org/html/rfc6455#section-7.4 for more information. - */ - if (window.handleClientSessionError) { - window.handleClientSessionError(); - } - } else { - switch (evt.code) { - case constants.RET_CODE.PLAYER_NOT_ADDABLE_TO_ROOM: - case constants.RET_CODE.PLAYER_NOT_READDABLE_TO_ROOM: - window.clearBoundRoomIdInBothVolatileAndPersistentStorage(); - break; - case constants.RET_CODE.UNKNOWN_ERROR: - case constants.RET_CODE.MYSQL_ERROR: - case constants.RET_CODE.PLAYER_NOT_FOUND: - case constants.RET_CODE.PLAYER_CHEATING: - case 1006: // Peer(i.e. the backend) gone unexpectedly - if (window.handleClientSessionError) { - window.handleClientSessionError(); - } - break; - default: - break; - } + console.warn(`The WS clientSession is closed: evt=${JSON.stringify(evt)}, evt.code=${evt.code}`); + switch (evt.code) { + case constants.RET_CODE.BATTLE_STOPPED: + // deliberately do nothing + break; + case constants.RET_CODE.PLAYER_NOT_ADDABLE_TO_ROOM: + case constants.RET_CODE.PLAYER_NOT_READDABLE_TO_ROOM: + window.clearBoundRoomIdInBothVolatileAndPersistentStorage(); // To favor the player to join other rooms + mapIns.onManualRejoinRequired("Couldn't join any room at the moment, please retry"); + break; + case constants.RET_CODE.ACTIVE_WATCHDOG: + mapIns.onManualRejoinRequired("Disconnected due to long-time inactivity, please rejoin"); + break; + case constants.RET_CODE.UNKNOWN_ERROR: + case constants.RET_CODE.MYSQL_ERROR: + case constants.RET_CODE.PLAYER_NOT_FOUND: + case constants.RET_CODE.PLAYER_CHEATING: + case 1006: // Peer(i.e. the backend) gone unexpectedly + window.clearLocalStorageAndBackToLoginScene(true); + break; + default: + break; } }; }; @@ -227,19 +223,7 @@ window.clearLocalStorageAndBackToLoginScene = function(shouldRetainBoundRoomIdIn if (window.mapIns && window.mapIns.musicEffectManagerScriptIns) { window.mapIns.musicEffectManagerScriptIns.stopAllMusic(); } - /** - * Here I deliberately removed the callback in the "common `handleClientSessionError` callback" - * within which another invocation to `clearLocalStorageAndBackToLoginScene` will be made. - * - * It'll be re-assigned to the common one upon reentrance of `Map.onLoad`. - * - * -- YFLu 2019-04-06 - */ - window.handleClientSessionError = () => { - console.warn("+++++++ Special handleClientSessionError() assigned within `clearLocalStorageAndBackToLoginScene`"); - // TBD. - window.handleClientSessionError = null; // To ensure that it's called at most once. - }; + window.closeWSConnection(); window.clearSelfPlayer(); if (true != shouldRetainBoundRoomIdInBothVolatileAndPersistentStorage) {