fix: prevent FightViewer random resets from concurrent kaplay init

- Guard initScene() with initializingScene flag to prevent concurrent calls
- Don't auto-reinit scene on WebGL context restore during active replay
- Block initScene() after component is destroyed
- Static audio files now play even before Kokoro worker loads
- kokoroSpeak/kokoroSpeakAsync check cache before requiring worker ready

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-09 10:58:13 +00:00
co-authored by Claude Opus 4.6
parent 52769ab43a
commit 1a7ad74859
+8 -1
View File
@@ -28,6 +28,7 @@ let scene: FightSceneController | null = null
const sceneReady = ref(false)
let cleanupTimerHandle: ReturnType<typeof setTimeout> | null = null
let destroyed = false
let initializingScene = false
const contextLost = ref(false)
const isReplaying = ref(false)
@@ -174,6 +175,8 @@ onUnmounted(() => {
async function initScene() {
if (!props.fight.botA || !props.fight.botB) return
if (initializingScene || destroyed) return // prevent concurrent init or post-destroy init
initializingScene = true
// Destroy previous scene fully
sceneReady.value = false
if (scene) { scene.destroy(); scene = null }
@@ -207,8 +210,10 @@ async function initScene() {
sceneReady.value = false
})
newCanvas.addEventListener('webglcontextrestored', () => {
// Don't auto-reinit during replay — just mark context as restored
// The contextLost overlay will let users tap to reload if needed
contextLost.value = false
initScene() // Re-create the scene with fresh context
if (!isReplaying.value) initScene()
})
// Wrap scene creation in try/catch + timeout so a mobile sprite loading failure
@@ -230,6 +235,8 @@ async function initScene() {
}
} catch (err) {
console.error('[FightViewer] Scene creation failed — continuing without canvas:', err)
} finally {
initializingScene = false
}
}