diff --git a/pages-game/game/minesweeper/index.vue b/pages-game/game/minesweeper/index.vue index 55bd0f3..5cf4b37 100644 --- a/pages-game/game/minesweeper/index.vue +++ b/pages-game/game/minesweeper/index.vue @@ -5,9 +5,6 @@ - - - 动物扫雷大作战 @@ -73,9 +70,7 @@ export default { this.loadTickets() }, methods: { - goBack() { - uni.navigateBack() - }, + async loadTickets() { this.loading = true try { @@ -151,25 +146,7 @@ export default { padding-top: calc(80rpx + env(safe-area-inset-top)); } -.back-btn { - width: 80rpx; - height: 80rpx; - background: white; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - box-shadow: $shadow-sm; - - &:active { - transform: scale(0.95); - } -} -.back-icon { - font-size: 40rpx; - color: $text-main; -} .title { flex: 1; diff --git a/pages-game/game/minesweeper/play.vue b/pages-game/game/minesweeper/play.vue index f663843..1a1b73c 100644 --- a/pages-game/game/minesweeper/play.vue +++ b/pages-game/game/minesweeper/play.vue @@ -441,7 +441,7 @@ export default { console.log('=== 匹配成功事件 ==='); console.log('[匹配时间]', new Date().toLocaleString()); console.log('[Match ID]', matched.match_id); - console.log('[Match Token]', matched.token ? '存在' : '不存在'); + console.log('[Match Token]', matched.token ? '存在' : '不存在 (权威模式通常不需要)'); console.log('[完整匹配对象]', JSON.stringify(matched, null, 2)); console.log('=================='); @@ -497,7 +497,9 @@ export default { }, onmatchdata: (matchData) => { const opCode = matchData.op_code; - const data = JSON.parse(new TextDecoder().decode(matchData.data)); + // NakamaManager 已内部处理了 utf8 解码,直接 parse 即可 + // const data = JSON.parse(new TextDecoder().decode(matchData.data)); + const data = typeof matchData.data === 'string' ? JSON.parse(matchData.data) : matchData.data; // ========== 控制台日志 - 接收游戏数据 ========== console.log('=== 接收游戏数据 ==='); diff --git a/utils/nakamaManager.js b/utils/nakamaManager.js index c668a15..e47dd6b 100644 --- a/utils/nakamaManager.js +++ b/utils/nakamaManager.js @@ -207,7 +207,12 @@ class NakamaManager { } else if (message.match_data) { // 解码 base64 数据 if (message.match_data.data) { - message.match_data.data = this._base64ToUint8Array(message.match_data.data); + // 原生 Base64 -> Unit8Array + const uint8arr = this._base64ToUint8Array(message.match_data.data); + // !!!关键修复:移除不可用的 TextDecoder,直接传输 Unit8Array,或在业务层处理 + // 由于 play.vue 中还在使用 TextDecoder,这里我们需要提供一个方法来转字符串 + // 为了兼容性,我们直接在这里转成字符串传出去,修改 onmatchdata 的约定 + message.match_data.data = this._utf8Decode(uint8arr); } message.match_data.op_code = parseInt(message.match_data.op_code); if (this.listeners.onmatchdata) { @@ -421,6 +426,24 @@ class NakamaManager { return bytes; } + _utf8Decode(bytes) { + let out = ""; + let i = 0; + while (i < bytes.length) { + let c = bytes[i++]; + if (c >> 7 == 0) { + out += String.fromCharCode(c); + } else if (c >> 5 == 0x06) { + out += String.fromCharCode(((c & 0x1F) << 6) | (bytes[i++] & 0x3F)); + } else if (c >> 4 == 0x0E) { + out += String.fromCharCode(((c & 0x0F) << 12) | ((bytes[i++] & 0x3F) << 6) | (bytes[i++] & 0x3F)); + } else { + out += String.fromCharCode(((c & 0x07) << 18) | ((bytes[i++] & 0x3F) << 12) | ((bytes[i++] & 0x3F) << 6) | (bytes[i++] & 0x3F)); + } + } + return out; + } + _parseUserIdFromToken(token) { try { const parts = token.split('.');