MatchMaster/assets/Script/module/Config/BattlePassSettlementCheck.ts

55 lines
2.0 KiB
TypeScript

import { PASS_PERIOD } from './BattlePassModel';
/** Memory-only login cache; scene destruction must not reset a completed check. */
export default class BattlePassSettlementCheck {
private static player: any;
private static identity = '';
private static current: BattlePassSettlementCheck;
static forPlayer(player: any): BattlePassSettlementCheck {
const identity = String(player.uid || '') + ':' + String(player.token || '');
if (this.player !== player || this.identity !== identity || !this.current) {
this.player = player;
this.identity = identity;
this.current = new BattlePassSettlementCheck();
}
return this.current;
}
static resetLogin() { this.current = null; }
private periodEnd = 0;
private checkedAt = 0;
private checkedVersion = -1;
private offset = 0;
version = 0;
readonly reviewOrders = new Set<string>();
hasSchedule(): boolean { return this.periodEnd > 0; }
observeStart(start: number) {
if (Number.isFinite(start) && start > 0) this.periodEnd = start + PASS_PERIOD;
}
syncClock(serverTime: number) {
if (Number.isFinite(serverTime) && serverTime > 0) this.offset = serverTime - Date.now();
}
invalidate() { this.version++; }
needsCheck(orders: any[] = []): boolean {
if (orders.some(order => /^battlepass(?:_30|_12)?$/.test(order.itemid) && !this.reviewOrders.has(order.outTradeNo))) return true;
if (!this.checkedAt || this.checkedVersion !== this.version) return true;
if (!this.periodEnd) return false;
// Derive the first boundary after the last read, even if another API has
// already advanced the global season while we were in GameScene.
const nextEnd = this.periodEnd + (Math.floor((this.checkedAt - this.periodEnd) / PASS_PERIOD) + 1) * PASS_PERIOD;
return Date.now() + this.offset >= nextEnd;
}
complete(serverTime: number, version: number) {
this.checkedAt = serverTime;
this.checkedVersion = version;
}
}