Files
tianshu-engine/engine/systems/ChoiceSystem.ts
cocos02 c7d035bd8f fix: interpret Choice.timeLimit as seconds, convert to ms internally
Previously maxLimit was passed directly to setTimeout/setInterval (ms),
so a JSON value of 10 meant 10ms instead of the intended 10 seconds.
Now timeLimit in JSON represents seconds, engine multiplies by 1000.
2026-06-07 18:56:30 +08:00

74 lines
1.8 KiB
TypeScript

import type { Choice } from '../types'
export interface ChoiceTimerState {
total: number
remaining: number
}
type TimerUpdateCallback = (state: ChoiceTimerState) => void
type TimeoutCallback = (choice: Choice) => void
export class ChoiceSystem {
private timerId: ReturnType<typeof setInterval> | null = null
private timeoutId: ReturnType<typeof setTimeout> | null = null
private timeLimit = 0
private elapsed = 0
private tickMs = 100
private onUpdate: TimerUpdateCallback | null = null
private onTimeout: TimeoutCallback | null = null
start(choices: Choice[], onUpdate: TimerUpdateCallback, onTimeout: TimeoutCallback) {
this.clear()
const timed = choices.filter((c) => c.timeLimit && c.timeLimit > 0)
if (timed.length === 0) return
const maxLimitSec = Math.max(...timed.map((c) => c.timeLimit!))
const maxLimitMs = maxLimitSec * 1000
this.timeLimit = maxLimitMs
this.elapsed = 0
this.onUpdate = onUpdate
this.onTimeout = onTimeout
this.onUpdate({ total: maxLimitSec, remaining: maxLimitSec })
this.timerId = setInterval(() => {
this.elapsed += this.tickMs
const remainingSec = Math.max(0, maxLimitMs - this.elapsed) / 1000
this.onUpdate?.({
total: maxLimitSec,
remaining: Math.ceil(remainingSec * 10) / 10,
})
}, this.tickMs)
this.timeoutId = setTimeout(() => {
this.clear()
if (choices.length > 0) {
this.onTimeout?.(choices[0])
}
}, maxLimitMs)
}
stop() {
this.clear()
}
private clear() {
if (this.timerId !== null) {
clearInterval(this.timerId)
this.timerId = null
}
if (this.timeoutId !== null) {
clearTimeout(this.timeoutId)
this.timeoutId = null
}
}
destroy() {
this.clear()
this.onUpdate = null
this.onTimeout = null
}
}