完善后端联调链路与模拟器多通道支持
This commit is contained in:
@@ -12,6 +12,8 @@ import {
|
||||
type GameLaunchEnvelope,
|
||||
type MapPageLaunchOptions,
|
||||
} from '../../utils/gameLaunch'
|
||||
import { finishSession, startSession, type BackendSessionFinishSummaryPayload } from '../../utils/backendApi'
|
||||
import { loadBackendBaseUrl } from '../../utils/backendAuth'
|
||||
import { loadRemoteMapConfig, type RemoteMapConfig } from '../../utils/remoteMapConfig'
|
||||
import { type H5ExperienceFallbackPayload, type H5ExperienceRequest } from '../../game/experience/h5Experience'
|
||||
import { type TrackColorPreset } from '../../game/presentation/trackStyleConfig'
|
||||
@@ -173,6 +175,8 @@ let lastPunchHintHapticAt = 0
|
||||
let currentSystemSettingsConfig: SystemSettingsConfig | undefined
|
||||
let currentRemoteMapConfig: RemoteMapConfig | undefined
|
||||
let systemSettingsLockLifetimeActive = false
|
||||
let syncedBackendSessionStartId = ''
|
||||
let syncedBackendSessionFinishId = ''
|
||||
let lastCenterScaleRulerStablePatch: Pick<
|
||||
MapPageData,
|
||||
| 'centerScaleRulerVisible'
|
||||
@@ -441,6 +445,37 @@ function hasExplicitLaunchOptions(options?: MapPageLaunchOptions | null): boolea
|
||||
)
|
||||
}
|
||||
|
||||
function getCurrentBackendSessionContext(): { sessionId: string; sessionToken: string } | null {
|
||||
const business = currentGameLaunchEnvelope.business
|
||||
if (!business || !business.sessionId || !business.sessionToken) {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
sessionId: business.sessionId,
|
||||
sessionToken: business.sessionToken,
|
||||
}
|
||||
}
|
||||
|
||||
function getBackendSessionContextFromLaunchEnvelope(envelope: GameLaunchEnvelope | null | undefined): { sessionId: string; sessionToken: string } | null {
|
||||
if (!envelope || !envelope.business || !envelope.business.sessionId || !envelope.business.sessionToken) {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
sessionId: envelope.business.sessionId,
|
||||
sessionToken: envelope.business.sessionToken,
|
||||
}
|
||||
}
|
||||
|
||||
function getCurrentBackendBaseUrl(): string {
|
||||
const app = getApp<IAppOption>()
|
||||
if (app.globalData && app.globalData.backendBaseUrl) {
|
||||
return app.globalData.backendBaseUrl
|
||||
}
|
||||
return loadBackendBaseUrl()
|
||||
}
|
||||
|
||||
function buildSideButtonVisibility(mode: SideButtonMode) {
|
||||
return {
|
||||
sideButtonMode: mode,
|
||||
@@ -871,6 +906,8 @@ Page({
|
||||
|
||||
onLoad(options: MapPageLaunchOptions) {
|
||||
clearSessionRecoveryPersistTimer()
|
||||
syncedBackendSessionStartId = ''
|
||||
syncedBackendSessionFinishId = ''
|
||||
currentGameLaunchEnvelope = resolveGameLaunchEnvelope(options)
|
||||
if (!hasExplicitLaunchOptions(options)) {
|
||||
const recoverySnapshot = loadSessionRecoverySnapshot()
|
||||
@@ -991,6 +1028,8 @@ Page({
|
||||
const nextAnimationLevel = typeof nextPatch.animationLevel === 'string'
|
||||
? nextPatch.animationLevel
|
||||
: this.data.animationLevel
|
||||
let shouldSyncBackendSessionStart = false
|
||||
let backendSessionFinishStatus: 'finished' | 'failed' | null = null
|
||||
|
||||
if (nextAnimationLevel === 'lite') {
|
||||
clearHudFxTimer('timer')
|
||||
@@ -1055,6 +1094,7 @@ Page({
|
||||
nextData.showGameInfoPanel = false
|
||||
nextData.showSystemSettingsPanel = false
|
||||
clearGameInfoPanelSyncTimer()
|
||||
backendSessionFinishStatus = nextPatch.gameSessionStatus === 'finished' ? 'finished' : 'failed'
|
||||
} else if (
|
||||
nextPatch.gameSessionStatus !== this.data.gameSessionStatus
|
||||
&& nextPatch.gameSessionStatus === 'idle'
|
||||
@@ -1064,6 +1104,11 @@ Page({
|
||||
shouldSyncRuntimeSystemSettings = true
|
||||
clearSessionRecoverySnapshot()
|
||||
clearSessionRecoveryPersistTimer()
|
||||
} else if (
|
||||
nextPatch.gameSessionStatus !== this.data.gameSessionStatus
|
||||
&& nextPatch.gameSessionStatus === 'running'
|
||||
) {
|
||||
shouldSyncBackendSessionStart = true
|
||||
} else if (nextPatch.gameSessionStatus === 'running' || nextPatch.gameSessionStatus === 'idle') {
|
||||
nextData.showResultScene = false
|
||||
}
|
||||
@@ -1077,6 +1122,12 @@ Page({
|
||||
if (typeof nextPatch.gameSessionStatus === 'string') {
|
||||
this.syncSessionRecoveryLifecycle(nextPatch.gameSessionStatus)
|
||||
}
|
||||
if (shouldSyncBackendSessionStart) {
|
||||
this.syncBackendSessionStart()
|
||||
}
|
||||
if (backendSessionFinishStatus) {
|
||||
this.syncBackendSessionFinish(backendSessionFinishStatus)
|
||||
}
|
||||
if (shouldSyncRuntimeSystemSettings) {
|
||||
this.applyRuntimeSystemSettings(nextLockLifetimeActive)
|
||||
}
|
||||
@@ -1088,6 +1139,12 @@ Page({
|
||||
if (typeof nextPatch.gameSessionStatus === 'string') {
|
||||
this.syncSessionRecoveryLifecycle(nextPatch.gameSessionStatus)
|
||||
}
|
||||
if (shouldSyncBackendSessionStart) {
|
||||
this.syncBackendSessionStart()
|
||||
}
|
||||
if (backendSessionFinishStatus) {
|
||||
this.syncBackendSessionFinish(backendSessionFinishStatus)
|
||||
}
|
||||
if (shouldSyncRuntimeSystemSettings) {
|
||||
this.applyRuntimeSystemSettings(nextLockLifetimeActive)
|
||||
}
|
||||
@@ -1283,6 +1340,8 @@ Page({
|
||||
onUnload() {
|
||||
this.persistSessionRecoverySnapshot()
|
||||
clearSessionRecoveryPersistTimer()
|
||||
syncedBackendSessionStartId = ''
|
||||
syncedBackendSessionFinishId = ''
|
||||
clearGameInfoPanelSyncTimer()
|
||||
clearCenterScaleRulerSyncTimer()
|
||||
clearCenterScaleRulerUpdateTimer()
|
||||
@@ -1332,6 +1391,114 @@ Page({
|
||||
return true
|
||||
},
|
||||
|
||||
syncBackendSessionStart() {
|
||||
const sessionContext = getCurrentBackendSessionContext()
|
||||
if (!sessionContext || syncedBackendSessionStartId === sessionContext.sessionId) {
|
||||
return
|
||||
}
|
||||
|
||||
startSession({
|
||||
baseUrl: getCurrentBackendBaseUrl(),
|
||||
sessionId: sessionContext.sessionId,
|
||||
sessionToken: sessionContext.sessionToken,
|
||||
})
|
||||
.then(() => {
|
||||
syncedBackendSessionStartId = sessionContext.sessionId
|
||||
})
|
||||
.catch((error) => {
|
||||
const message = error && error.message ? error.message : '未知错误'
|
||||
this.setData({
|
||||
statusText: `session start 上报失败: ${message}`,
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
syncBackendSessionFinish(statusOverride?: 'finished' | 'failed' | 'cancelled') {
|
||||
const sessionContext = getCurrentBackendSessionContext()
|
||||
if (!sessionContext || syncedBackendSessionFinishId === sessionContext.sessionId || !mapEngine) {
|
||||
return
|
||||
}
|
||||
|
||||
const finishSummary = mapEngine.getSessionFinishSummary(statusOverride)
|
||||
if (!finishSummary) {
|
||||
return
|
||||
}
|
||||
|
||||
const summaryPayload: BackendSessionFinishSummaryPayload = {}
|
||||
if (typeof finishSummary.finalDurationSec === 'number') {
|
||||
summaryPayload.finalDurationSec = finishSummary.finalDurationSec
|
||||
}
|
||||
if (typeof finishSummary.finalScore === 'number') {
|
||||
summaryPayload.finalScore = finishSummary.finalScore
|
||||
}
|
||||
if (typeof finishSummary.completedControls === 'number') {
|
||||
summaryPayload.completedControls = finishSummary.completedControls
|
||||
}
|
||||
if (typeof finishSummary.totalControls === 'number') {
|
||||
summaryPayload.totalControls = finishSummary.totalControls
|
||||
}
|
||||
if (typeof finishSummary.distanceMeters === 'number') {
|
||||
summaryPayload.distanceMeters = finishSummary.distanceMeters
|
||||
}
|
||||
if (typeof finishSummary.averageSpeedKmh === 'number') {
|
||||
summaryPayload.averageSpeedKmh = finishSummary.averageSpeedKmh
|
||||
}
|
||||
|
||||
finishSession({
|
||||
baseUrl: getCurrentBackendBaseUrl(),
|
||||
sessionId: sessionContext.sessionId,
|
||||
sessionToken: sessionContext.sessionToken,
|
||||
status: finishSummary.status,
|
||||
summary: summaryPayload,
|
||||
})
|
||||
.then(() => {
|
||||
syncedBackendSessionFinishId = sessionContext.sessionId
|
||||
})
|
||||
.catch((error) => {
|
||||
const message = error && error.message ? error.message : '未知错误'
|
||||
this.setData({
|
||||
statusText: `session finish 上报失败: ${message}`,
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
reportAbandonedRecoverySnapshot(snapshot: SessionRecoverySnapshot) {
|
||||
const sessionContext = getBackendSessionContextFromLaunchEnvelope(snapshot.launchEnvelope)
|
||||
if (!sessionContext) {
|
||||
clearSessionRecoverySnapshot()
|
||||
return
|
||||
}
|
||||
|
||||
finishSession({
|
||||
baseUrl: getCurrentBackendBaseUrl(),
|
||||
sessionId: sessionContext.sessionId,
|
||||
sessionToken: sessionContext.sessionToken,
|
||||
status: 'cancelled',
|
||||
summary: {},
|
||||
})
|
||||
.then(() => {
|
||||
syncedBackendSessionFinishId = sessionContext.sessionId
|
||||
clearSessionRecoverySnapshot()
|
||||
wx.showToast({
|
||||
title: '已放弃上次对局',
|
||||
icon: 'none',
|
||||
duration: 1400,
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
clearSessionRecoverySnapshot()
|
||||
const message = error && error.message ? error.message : '未知错误'
|
||||
this.setData({
|
||||
statusText: `放弃恢复已生效,后端取消上报失败: ${message}`,
|
||||
})
|
||||
wx.showToast({
|
||||
title: '已放弃上次对局',
|
||||
icon: 'none',
|
||||
duration: 1400,
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
syncSessionRecoveryLifecycle(status: MapPageData['gameSessionStatus']) {
|
||||
if (status === 'running') {
|
||||
this.persistSessionRecoverySnapshot()
|
||||
@@ -1368,7 +1535,7 @@ Page({
|
||||
cancelText: '放弃',
|
||||
success: (result) => {
|
||||
if (!result.confirm) {
|
||||
clearSessionRecoverySnapshot()
|
||||
this.reportAbandonedRecoverySnapshot(snapshot)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1385,15 +1552,19 @@ Page({
|
||||
return
|
||||
}
|
||||
|
||||
this.setData({
|
||||
showResultScene: false,
|
||||
showDebugPanel: false,
|
||||
showGameInfoPanel: false,
|
||||
showSystemSettingsPanel: false,
|
||||
})
|
||||
this.syncSessionRecoveryLifecycle('running')
|
||||
},
|
||||
})
|
||||
this.setData({
|
||||
showResultScene: false,
|
||||
showDebugPanel: false,
|
||||
showGameInfoPanel: false,
|
||||
showSystemSettingsPanel: false,
|
||||
})
|
||||
const sessionContext = getCurrentBackendSessionContext()
|
||||
if (sessionContext) {
|
||||
syncedBackendSessionStartId = sessionContext.sessionId
|
||||
}
|
||||
this.syncSessionRecoveryLifecycle('running')
|
||||
},
|
||||
})
|
||||
},
|
||||
|
||||
compileCurrentRuntimeProfile(lockLifetimeActive = isSystemSettingsLockLifetimeActive()) {
|
||||
@@ -1537,7 +1708,10 @@ Page({
|
||||
return
|
||||
}
|
||||
|
||||
const errorMessage = error && error.message ? error.message : '未知错误'
|
||||
const rawErrorMessage = error && error.message ? error.message : '未知错误'
|
||||
const errorMessage = rawErrorMessage.indexOf('404') >= 0
|
||||
? `release manifest 不存在或未发布 (${configLabel})`
|
||||
: rawErrorMessage
|
||||
this.setData({
|
||||
configStatusText: `载入失败: ${errorMessage}`,
|
||||
statusText: `远程地图配置载入失败: ${errorMessage} (${INTERNAL_BUILD_VERSION})`,
|
||||
@@ -1939,18 +2113,19 @@ Page({
|
||||
return
|
||||
}
|
||||
|
||||
wx.showModal({
|
||||
title: '确认退出',
|
||||
content: '确认强制结束当前对局并返回开始前状态?',
|
||||
confirmText: '确认退出',
|
||||
cancelText: '取消',
|
||||
success: (result) => {
|
||||
if (result.confirm && mapEngine) {
|
||||
systemSettingsLockLifetimeActive = false
|
||||
mapEngine.handleForceExitGame()
|
||||
}
|
||||
},
|
||||
})
|
||||
wx.showModal({
|
||||
title: '确认退出',
|
||||
content: '确认强制结束当前对局并返回开始前状态?',
|
||||
confirmText: '确认退出',
|
||||
cancelText: '取消',
|
||||
success: (result) => {
|
||||
if (result.confirm && mapEngine) {
|
||||
this.syncBackendSessionFinish('cancelled')
|
||||
systemSettingsLockLifetimeActive = false
|
||||
mapEngine.handleForceExitGame()
|
||||
}
|
||||
},
|
||||
})
|
||||
},
|
||||
|
||||
handleSkipAction() {
|
||||
|
||||
Reference in New Issue
Block a user