chore: sync latest changes

This commit is contained in:
2026-06-09 17:21:54 +08:00
parent bca137535b
commit 451c6ea025
12 changed files with 503 additions and 28 deletions

View File

@@ -0,0 +1,81 @@
import type { AchievementDef } from '../types'
type UnlockCallback = (achievement: AchievementDef) => void
export class AchievementSystem {
private definitions: AchievementDef[] = []
private unlockedIds: Set<string> = new Set()
private onUnlock: UnlockCallback | null = null
private toastQueue: string[] = []
private toastActive = false
init(defs: AchievementDef[], alreadyUnlocked: string[]) {
this.definitions = defs
this.unlockedIds = new Set(alreadyUnlocked)
this.toastQueue = []
this.toastActive = false
}
setUnlockCallback(cb: UnlockCallback) {
this.onUnlock = cb
}
check(variables: Record<string, number>) {
for (const def of this.definitions) {
if (this.unlockedIds.has(def.id)) continue
const cond = def.condition
const val = variables[cond.variable] ?? 0
let matched = false
switch (cond.op) {
case '==': matched = val === cond.value; break
case '!=': matched = val !== cond.value; break
case '>': matched = val > (cond.value as number); break
case '<': matched = val < (cond.value as number); break
case '>=': matched = val >= (cond.value as number); break
case '<=': matched = val <= (cond.value as number); break
}
if (matched) {
this.unlockedIds.add(def.id)
this.onUnlock?.(def)
this.enqueueToast(def.id)
}
}
}
private enqueueToast(id: string) {
this.toastQueue.push(id)
if (!this.toastActive) {
this.showNextToast()
}
}
private showNextToast() {
if (this.toastQueue.length === 0) {
this.toastActive = false
return
}
this.toastActive = true
// toast is shown by the UI layer watching toastQueue
// UI calls toastDismissed() when the toast animation finishes
}
getToastQueue(): string[] {
return [...this.toastQueue]
}
toastDismissed(id: string) {
this.toastQueue = this.toastQueue.filter((i) => i !== id)
this.showNextToast()
}
getUnlockedIds(): string[] {
return [...this.unlockedIds]
}
getDefinitions(): AchievementDef[] {
return this.definitions
}
}