fix: 优化 WebSocket 连接和游戏重连逻辑,并改进回合计时器同步及用户操作反馈。

This commit is contained in:
邹方成 2026-01-04 16:29:57 +08:00
parent 413f7557f1
commit 75b6ef7809
2 changed files with 44 additions and 7 deletions

View File

@ -615,6 +615,9 @@ export default {
// //
try { try {
if (this._isReconnecting) return;
this._isReconnecting = true;
console.log('[重连] 开始重新连接...'); console.log('[重连] 开始重新连接...');
const session = await nakamaManager.authenticateWithGameToken(this.gameToken, this.stableUserId); const session = await nakamaManager.authenticateWithGameToken(this.gameToken, this.stableUserId);
this.myUserId = session.user_id; this.myUserId = session.user_id;
@ -636,6 +639,8 @@ export default {
} catch (e) { } catch (e) {
console.error('[重连] 失败:', e); console.error('[重连] 失败:', e);
this.addLog('system', `❌ 重连失败: ${e.message}`); this.addLog('system', `❌ 重连失败: ${e.message}`);
} finally {
this._isReconnecting = false;
} }
} }
}); });
@ -666,6 +671,8 @@ export default {
if (opCode === 1) { if (opCode === 1) {
this.gameState = data; this.gameState = data;
const limit = data.turnDuration || 15;
this.resetTurnTimer(limit, limit);
this.addLog('system', '战局开始,准备翻格!'); this.addLog('system', '战局开始,准备翻格!');
} else if (opCode === 2) { } else if (opCode === 2) {
// - HP // - HP
@ -691,10 +698,13 @@ export default {
} }
}); });
} }
this.gameState = data; // 使
//
if (data.gameStarted) { if (data.gameStarted) {
this.resetTurnTimer(); const serverTime = data.serverTime || Math.floor(Date.now() / 1000);
const elapsed = serverTime - (data.lastMoveTimestamp || serverTime);
const limit = data.turnDuration || 15;
const remaining = Math.max(0, limit - elapsed);
this.resetTurnTimer(remaining, limit);
} }
} else if (opCode === 5) { } else if (opCode === 5) {
this.handleEvent(data); this.handleEvent(data);
@ -817,9 +827,15 @@ export default {
handleCellClick(idx) { handleCellClick(idx) {
// //
if (this.isSpectator) return; if (this.isSpectator) return;
if (!this.gameState?.gameStarted) return; if (!this.gameState?.gameStarted) {
uni.showToast({ title: '游戏尚未开始', icon: 'none' });
return;
}
if (this.showResultModal || this.showSettlement) return; if (this.showResultModal || this.showSettlement) return;
if (!this.isMyTurn) return; if (!this.isMyTurn) {
uni.showToast({ title: '等待对方行动...', icon: 'none' });
return;
}
if (this.gameState.grid[idx].revealed) return; if (this.gameState.grid[idx].revealed) return;
// //
@ -832,8 +848,9 @@ export default {
closeResultModal() { closeResultModal() {
this.showResultModal = false; this.showResultModal = false;
}, },
resetTurnTimer() { resetTurnTimer(initialTime, limit) {
this.turnTimer = 15; const turnLimit = limit || (this.gameState?.turnDuration) || 15;
this.turnTimer = Math.floor(initialTime !== undefined ? initialTime : turnLimit);
clearInterval(this.turnInterval); clearInterval(this.turnInterval);
this.turnInterval = setInterval(() => { this.turnInterval = setInterval(() => {
if (this.turnTimer > 0) this.turnTimer--; if (this.turnTimer > 0) this.turnTimer--;

View File

@ -15,6 +15,7 @@ class NakamaManager {
this.gameToken = null; this.gameToken = null;
this.socketTask = null; this.socketTask = null;
this.isConnected = false; this.isConnected = false;
this.isConnecting = false; // 正在连接标志位
// 消息 ID 和待处理的 Promise // 消息 ID 和待处理的 Promise
this.nextCid = 1; this.nextCid = 1;
@ -132,7 +133,24 @@ class NakamaManager {
* 建立 WebSocket 连接 * 建立 WebSocket 连接
*/ */
_connectWebSocket() { _connectWebSocket() {
if (this.isConnecting) {
console.log('[Nakama] Already connecting, skipping...');
return Promise.resolve();
}
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// 确保清理旧连接
if (this.socketTask) {
console.log('[Nakama] Closing existing socket before new connection');
try {
this.socketTask.close();
} catch (e) {
console.warn('[Nakama] Error closing old socket:', e);
}
this.socketTask = null;
}
this.isConnecting = true;
const scheme = this.useSSL ? 'wss://' : 'ws://'; const scheme = this.useSSL ? 'wss://' : 'ws://';
const portSuffix = (this.useSSL && this.port === '443') || (!this.useSSL && this.port === '80') ? '' : `:${this.port}`; const portSuffix = (this.useSSL && this.port === '443') || (!this.useSSL && this.port === '80') ? '' : `:${this.port}`;
const wsUrl = `${scheme}${this.host}${portSuffix}/ws?lang=en&status=true&token=${encodeURIComponent(this.session.token)}`; const wsUrl = `${scheme}${this.host}${portSuffix}/ws?lang=en&status=true&token=${encodeURIComponent(this.session.token)}`;
@ -151,6 +169,7 @@ class NakamaManager {
this.socketTask.onOpen(() => { this.socketTask.onOpen(() => {
clearTimeout(connectTimeout); clearTimeout(connectTimeout);
this.isConnected = true; this.isConnected = true;
this.isConnecting = false;
console.log('[Nakama] WebSocket connected'); console.log('[Nakama] WebSocket connected');
this._startHeartbeat(); this._startHeartbeat();
resolve(); resolve();
@ -169,6 +188,7 @@ class NakamaManager {
clearTimeout(connectTimeout); clearTimeout(connectTimeout);
console.error('[Nakama] WebSocket error:', err); console.error('[Nakama] WebSocket error:', err);
this.isConnected = false; this.isConnected = false;
this.isConnecting = false;
if (this.listeners.onerror) { if (this.listeners.onerror) {
this.listeners.onerror(err); this.listeners.onerror(err);
} }