Fixed recovery upon reconnection.

This commit is contained in:
genxium 2022-11-13 11:37:30 +08:00
parent 2d080ad134
commit 4369729d9c
4 changed files with 75 additions and 55 deletions

View File

@ -537,7 +537,8 @@ func (pR *Room) StartBattle() {
2. reconnection 2. reconnection
*/ */
shouldResync1 := (MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED == player.LastSentInputFrameId) shouldResync1 := (MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED == player.LastSentInputFrameId)
shouldResync2 := (0 < unconfirmedMask) // This condition is critical, if we don't send resync upon this condition, the might never get its input synced // shouldResync2 := (0 < (unconfirmedMask & uint64(1 << uint32(player.JoinIndex-1)))) // This condition is critical, if we don't send resync upon this condition, the "reconnected or slowly-clocking player" might never get its input synced
shouldResync2 := (0 < unconfirmedMask) // An easier version of the above, might keep sending "refRenderFrame"s to still connected players when any player is disconnected
if pR.BackendDynamicsEnabled && (shouldResync1 || shouldResync2) { if pR.BackendDynamicsEnabled && (shouldResync1 || shouldResync2) {
tmp := pR.RenderFrameBuffer.GetByFrameId(refRenderFrameId) tmp := pR.RenderFrameBuffer.GetByFrameId(refRenderFrameId)
if nil == tmp { if nil == tmp {
@ -970,11 +971,12 @@ func (pR *Room) OnPlayerBattleColliderAcked(playerId int32) bool {
playerMetas := make(map[int32]*PlayerDownsyncMeta, 0) playerMetas := make(map[int32]*PlayerDownsyncMeta, 0)
for _, eachPlayer := range pR.Players { for _, eachPlayer := range pR.Players {
playerMetas[eachPlayer.Id] = &PlayerDownsyncMeta{ playerMetas[eachPlayer.Id] = &PlayerDownsyncMeta{
Id: eachPlayer.Id, Id: eachPlayer.Id,
Name: eachPlayer.Name, Name: eachPlayer.Name,
DisplayName: eachPlayer.DisplayName, DisplayName: eachPlayer.DisplayName,
Avatar: eachPlayer.Avatar, Avatar: eachPlayer.Avatar,
JoinIndex: eachPlayer.JoinIndex, JoinIndex: eachPlayer.JoinIndex,
ColliderRadius: eachPlayer.ColliderRadius,
} }
} }
@ -1251,6 +1253,8 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
if 0 < encodedInput { if 0 < encodedInput {
Logger.Debug(fmt.Sprintf("Checking collision for playerId=%v: virtual (%d, %d) -> (%d, %d), now playerShape=%v", playerId, currPlayerDownsync.VirtualGridX, currPlayerDownsync.VirtualGridY, newVx, newVy, ConvexPolygonStr(playerCollider.Shape.(*resolv.ConvexPolygon)))) Logger.Debug(fmt.Sprintf("Checking collision for playerId=%v: virtual (%d, %d) -> (%d, %d), now playerShape=%v", playerId, currPlayerDownsync.VirtualGridX, currPlayerDownsync.VirtualGridY, newVx, newVy, ConvexPolygonStr(playerCollider.Shape.(*resolv.ConvexPolygon))))
nextRenderFramePlayers[playerId].Dir.Dx = decodedInput[0]
nextRenderFramePlayers[playerId].Dir.Dy = decodedInput[1]
} }
} }

View File

@ -86,8 +86,8 @@ cc.Class({
self.smsLoginCaptchaLabel.active = true; self.smsLoginCaptchaLabel.active = true;
self.loginButton.active = true; self.loginButton.active = true;
self.onLoginButtonClicked = self.onLoginButtonClicked.bind(self); self.onLoginButtonClicked = self.onLoginButtonClicked.bind(self);
self.onSMSCaptchaGetButtonClicked = self.onSMSCaptchaGetButtonClicked.bind(self); self.onSMSCaptchaGetButtonClicked = self.onSMSCaptchaGetButtonClicked.bind(self);
self.smsLoginCaptchaButton.on('click', self.onSMSCaptchaGetButtonClicked); self.smsLoginCaptchaButton.on('click', self.onSMSCaptchaGetButtonClicked);
self.loadingNode = cc.instantiate(this.loadingPrefab); self.loadingNode = cc.instantiate(this.loadingPrefab);
@ -98,6 +98,17 @@ cc.Class({
if (null != qDict && qDict["expectedRoomId"]) { if (null != qDict && qDict["expectedRoomId"]) {
window.clearBoundRoomIdInBothVolatileAndPersistentStorage(); window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
} }
self.checkIntAuthTokenExpire().then(
(intAuthToken) => {
console.log("Successfully found `intAuthToken` in local cache");
self.useTokenLogin(intAuthToken);
},
() => {
console.warn("Failed to find `intAuthToken` in local cache");
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
}
);
}, },
getRetCodeList() { getRetCodeList() {
@ -185,28 +196,28 @@ cc.Class({
checkIntAuthTokenExpire() { checkIntAuthTokenExpire() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!cc.sys.localStorage.getItem('selfPlayer')) { if (!cc.sys.localStorage.getItem('selfPlayer')) {
console.warn("Couldn't find selfPlayer key in local cache"); console.warn("Couldn't find selfPlayer key in local cache");
reject(); reject();
return; return;
} }
const selfPlayer = JSON.parse(cc.sys.localStorage.getItem('selfPlayer')); const selfPlayer = JSON.parse(cc.sys.localStorage.getItem('selfPlayer'));
if (null == selfPlayer) { if (null == selfPlayer) {
console.warn("Couldn't find selfPlayer object in local cache"); console.warn("Couldn't find selfPlayer object in local cache");
reject(); reject();
return; return;
}
if (null == selfPlayer.intAuthToken) {
console.warn("Couldn't find selfPlayer object with key `intAuthToken` in local cache");
reject();
return;
}
if (new Date().getTime() > selfPlayer.expiresAt) {
console.warn("Couldn't find unexpired selfPlayer `intAuthToken` in local cache");
reject();
return;
} }
resolve(selfPlayer.intAuthToken);
if (null == selfPlayer.intAuthToken) {
console.warn("Couldn't find selfPlayer object with key `intAuthToken` in local cache");
reject();
return;
}
if (new Date().getTime() > selfPlayer.expiresAt) {
console.warn("Couldn't find unexpired selfPlayer `intAuthToken` in local cache");
reject();
return;
}
resolve(selfPlayer.intAuthToken);
}) })
}, },
@ -343,7 +354,7 @@ cc.Class({
); );
cc.director.loadScene('default_map'); cc.director.loadScene('default_map');
} else { } else {
console.log("OnLoggedIn failed, about to remove `selfPlayer` in local cache.") console.log("OnLoggedIn failed, about to remove `selfPlayer` in local cache.")
cc.sys.localStorage.removeItem("selfPlayer"); cc.sys.localStorage.removeItem("selfPlayer");
window.clearBoundRoomIdInBothVolatileAndPersistentStorage(); window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
self.enableInteractiveControls(true); self.enableInteractiveControls(true);

View File

@ -479,32 +479,34 @@ cc.Class({
const dx = boundaryObj[i].x - x0; const dx = boundaryObj[i].x - x0;
const dy = boundaryObj[i].y - y0; const dy = boundaryObj[i].y - y0;
pts.push([dx, dy]); pts.push([dx, dy]);
if (self.showCriticalCoordinateLabels) { /*
const barrierVertLabelNode = new cc.Node(); if (self.showCriticalCoordinateLabels) {
switch (i % 4) { const barrierVertLabelNode = new cc.Node();
case 0: switch (i % 4) {
barrierVertLabelNode.color = cc.Color.RED; case 0:
break; barrierVertLabelNode.color = cc.Color.RED;
case 1: break;
barrierVertLabelNode.color = cc.Color.GRAY; case 1:
break; barrierVertLabelNode.color = cc.Color.GRAY;
case 2: break;
barrierVertLabelNode.color = cc.Color.BLACK; case 2:
break; barrierVertLabelNode.color = cc.Color.BLACK;
default: break;
barrierVertLabelNode.color = cc.Color.MAGENTA; default:
break; barrierVertLabelNode.color = cc.Color.MAGENTA;
} break;
barrierVertLabelNode.setPosition(cc.v2(x0+0.95*dx, y0+0.5*dy));
const barrierVertLabel = barrierVertLabelNode.addComponent(cc.Label);
barrierVertLabel.fontSize = 20;
barrierVertLabel.lineHeight = 22;
barrierVertLabel.string = `(${boundaryObj[i].x.toFixed(1)}, ${boundaryObj[i].y.toFixed(1)})`;
safelyAddChild(self.node, barrierVertLabelNode);
setLocalZOrder(barrierVertLabelNode, 5);
barrierVertLabelNode.active = true;
} }
barrierVertLabelNode.setPosition(cc.v2(x0+0.95*dx, y0+0.5*dy));
const barrierVertLabel = barrierVertLabelNode.addComponent(cc.Label);
barrierVertLabel.fontSize = 20;
barrierVertLabel.lineHeight = 22;
barrierVertLabel.string = `(${boundaryObj[i].x.toFixed(1)}, ${boundaryObj[i].y.toFixed(1)})`;
safelyAddChild(self.node, barrierVertLabelNode);
setLocalZOrder(barrierVertLabelNode, 5);
barrierVertLabelNode.active = true;
}
*/
} }
const newBarrier = self.collisionSys.createPolygon(x0, y0, pts); const newBarrier = self.collisionSys.createPolygon(x0, y0, pts);
// console.log("Created barrier: ", newBarrier); // console.log("Created barrier: ", newBarrier);
@ -797,8 +799,8 @@ cc.Class({
newPlayerNode.active = true; newPlayerNode.active = true;
const playerScriptIns = newPlayerNode.getComponent("SelfPlayer"); const playerScriptIns = newPlayerNode.getComponent("SelfPlayer");
playerScriptIns.scheduleNewDirection({ playerScriptIns.scheduleNewDirection({
dx: 0, dx: playerRichInfo.dir.dx,
dy: 0 dy: playerRichInfo.dir.dy
}, true); }, true);
return [newPlayerNode, playerScriptIns]; return [newPlayerNode, playerScriptIns];
@ -943,10 +945,13 @@ cc.Class({
setLocalZOrder(toShowNode, 10); setLocalZOrder(toShowNode, 10);
}, },
hideFindingPlayersGUI() { hideFindingPlayersGUI(rdf) {
const self = this; const self = this;
if (null == self.findingPlayerNode.parent) return; if (null == self.findingPlayerNode.parent) return;
self.findingPlayerNode.parent.removeChild(self.findingPlayerNode); self.findingPlayerNode.parent.removeChild(self.findingPlayerNode);
if (null != rdf) {
self._initPlayerRichInfoDict(rdf.players, rdf.playerMetas);
}
}, },
onBattleReadyToStart(rdf) { onBattleReadyToStart(rdf) {

View File

@ -156,7 +156,7 @@ window.initPersistentSessionClient = function(onopenCb, expectedRoomId) {
break; break;
case window.DOWNSYNC_MSG_ACT_PLAYER_READDED_AND_ACKED: case window.DOWNSYNC_MSG_ACT_PLAYER_READDED_AND_ACKED:
// Deliberately left blank for now // Deliberately left blank for now
mapIns.hideFindingPlayersGUI(); mapIns.hideFindingPlayersGUI(resp.rdf);
break; break;
case window.DOWNSYNC_MSG_ACT_BATTLE_READY_TO_START: case window.DOWNSYNC_MSG_ACT_BATTLE_READY_TO_START:
mapIns.onBattleReadyToStart(resp.rdf); mapIns.onBattleReadyToStart(resp.rdf);