// VPlay SDK v1 - type declarations for vplay-sdk.js / vplay-sdk.global.js. // Contract: docs/sdk/CONTRACT_v1.md export type VPlayMode = "vplay" | "standalone"; export type Capability = "core" | "score" | "purchase" | "entitlements" | "save" | "milestone" | "leaderboard"; /** `config` fires whenever the platform description changes (theme, switches, tournament). */ export type VPlayEvent = "pause" | "resume" | "mute" | "unmute" | "entitlements" | "vcoins" | "config"; /** Platform switches that can change at any time. Ask each time, or listen for `config`. */ export type FeatureName = "purchases" | "milestones" | "saves" | "leaderboard" | "tournaments"; export interface HostTheme { mode: "dark" | "light"; /** CSS colours by role: bg, surface, surface2, line, text, muted, accent, accent2, danger, warning, positive. More roles may appear. */ colors: Record; } export interface TournamentInfo { id: number; title: string; startsAt: string; endsAt: string; topRewardCoins: number } /** Nothing in here is personal. Fields are additive: ignore ones you don't know. */ export interface HostInfo { revision: number; features: Record & Record; limits: { saveBytes: number; hintsPerSecond: number; minRunMs: number; idLength: number }; theme: HostTheme | null; locale: string; scoreOrder: "high" | "low"; tournament: TournamentInfo | null; } export type LeaderboardScope = "all" | "week" | "day" | "tournament"; export interface LeaderboardEntry { rank: number; name: string; avatarUrl: string | null; score: number; you: boolean } export interface LeaderboardResult { scope: LeaderboardScope; scoreOrder: "high" | "low"; entries: LeaderboardEntry[]; /** The signed-in player's own standing, even outside the listed entries. */ me: { rank: number; score: number } | null; endsAt: string | null; } export interface VPlayPlayer { signedIn: boolean; displayName: string | null; member: boolean } export interface VPlayItem { id: string; label?: string | null; priceVc: number; owned: boolean } export interface VPlayInit { mode: VPlayMode; player: VPlayPlayer; /** Display only. Never use it for game logic. */ vcoins: number; /** Prices come from vplay.gg, never from the game. */ items: VPlayItem[]; entitlements: string[]; /** Cloud save, or null (none yet, or a guest). */ save: unknown | null; /** What this game is allowed to do. Empty in standalone mode. */ capabilities: Capability[]; sdkVersion: number; /** The live platform description; null when standalone or on an older host. */ host: HostInfo | null; } export interface VPlayInitOptions { gameId: string; sdkVersion?: 1; /** Extra host origins to trust (local dev hosts). Adds to the vplay.gg defaults. */ hostOrigins?: string[]; /** Where openOnVplay() sends a standalone player. */ openUrl?: string; /** Mirror the site's colours into --vp-* CSS variables on and keep them current. Default true. */ autoTheme?: boolean; } export type PurchaseResult = | { status: "purchased"; entitlements: string[]; vcoins: number } | { status: "cancelled" | "needs_signin" | "insufficient" | "unavailable" | "error"; message?: string }; export interface GameOverResult { accepted: boolean; flagged: boolean; best: number | null } export interface VPlayApi { readonly version: number; readonly mode: VPlayMode; readonly capabilities: Capability[]; has(capability: Capability): boolean; /** The live platform description, or null (standalone / older host). */ readonly host: HostInfo | null; /** Is this platform feature on right now? Switches change at runtime; ask each time or listen for "config". */ feature(name: FeatureName): boolean; readonly theme: HostTheme | null; /** The tournament running for this game right now, if any. */ readonly tournament: TournamentInfo | null; /** Write the host's colours into --vp-* variables on target (default ). Only needed with autoTheme:false. */ applyTheme(target?: HTMLElement): void; init(opts: VPlayInitOptions): Promise; loading(progress: number): void; gameplayStart(): void; gameplayStop(): void; score(value: number): void; lives(value: number): void; level(value: number): void; gameOver(result: { score: number; level?: number; reason?: string }): Promise; win(result: { score: number; level?: number }): Promise; purchase(itemId: string): Promise; entitlements(): Promise; saveCloud(data: unknown): void; flush(): void; milestone(id: string): void; /** Opens vplay.gg's own leaderboard over the game and pauses it. The game receives nothing. */ showLeaderboard(): void; /** The board as data, for a game that draws its own (needs the "leaderboard" capability). null when unavailable. */ leaderboard(opts?: { scope?: LeaderboardScope; limit?: number }): Promise; openOnVplay(): void; on(event: VPlayEvent, cb: (data?: unknown) => void): () => void; destroy(): void; } export declare const VPlay: VPlayApi; export declare function createVPlay(): VPlayApi;