# @ferret/platform: API

One interface over OS Beroun and the browser: saved state, suspend, exit, screen size, device class, render scale and quality tiers.

24 exports. Generated from the source (`packages/platform/src`), so it matches the code.

## Classes

### BerounPlatform

*class* · `packages/platform/src/platform.ts:67`

```ts
class BerounPlatform extends DomPlatform implements FerretPlatform
```

OS Beroun: the global `Platform` object that /platform.js provides.

- `readonly kind: "beroun"`
- `constructor(api: any = (globalThis as any).Platform)`
- `async loadState<T>()` — Saved state of the game (null when there is none).
- `async saveState(state: unknown)`
- `exit()` — Leave the game: OS Beroun closes the app; a browser goes back to the game's start page.
- `async capabilities()`
- `log(msg: string)` — Plain text to the host's log (the OS Beroun shell's log; the browser console).

### BrowserPlatform

*class* · `packages/platform/src/platform.ts:87`

```ts
class BrowserPlatform extends DomPlatform implements FerretPlatform
```

An ordinary desktop or mobile browser.

- `readonly kind: "browser"`
- `constructor(private key = 'ferret', private startPage = './')`
- `async loadState<T>(): Promise<T | null>` — Saved state of the game (null when there is none).
- `async saveState(state: unknown)`
- `exit()` — Leave the game: OS Beroun closes the app; a browser goes back to the game's start page.
- `async capabilities()`
- `async requestFullscreen()`
- `log(msg: string)` — Plain text to the host's log (the OS Beroun shell's log; the browser console).

### Display

*class* · `packages/platform/src/display.ts:77`

```ts
class Display
```

Keeps an engine's canvas, hardware scaling, quality and cameras in step with the screen.
Resize, rotation, fullscreen and a move to an external screen are handled without reloading anything.

- `quality: QualitySettings`
- `renderScale: number`
- `xrActive: boolean` — a VR session owns the render target and the field of view: the screen scaling and FOV are left alone while it runs
- `onChange?: (d: Display) => void`
- `constructor(readonly engine: BABYLON.AbstractEngine, readonly platform: { screen(): ScreenInfo; onResize(fn: (s: ScreenInfo) => void): () => void; kind: string }, opts: { tier?: QualityTier; baseVerticalFov?: number; minHorizontalFov?: number } = {})`
- `setTier(tier: QualityTier)`
- `setXr(on: boolean)` — Enter or leave VR: the `xr` tier while a session runs, the screen's tier after.
- `trackCamera(cam: BABYLON.Camera)`
- `get aspect(): number`
- `apply()`
- `applyFov()`
- `dispose()`

### HeadlessPlatform

*class* · `packages/platform/src/platform.ts:135`

```ts
class HeadlessPlatform implements FerretPlatform
```

Tests: everything in memory, nothing needs a DOM.

- `readonly kind: "headless"`
- `state: unknown`
- `exited: boolean`
- `logs: string[]`
- `size: ScreenInfo`
- `async loadState<T>()` — Saved state of the game (null when there is none).
- `async saveState(s: unknown)`
- `onSuspend(fn: (reason: string) => void | Promise<void>)` — Called before the page goes away (OS Beroun: the app is closed, ~2 s to save; browser: hidden/closed).
- `async suspend(reason = 'closed')`
- `exit()` — Leave the game: OS Beroun closes the app; a browser goes back to the game's start page.
- `async capabilities()`
- `screen()`
- `onResize(fn: (s: ScreenInfo) => void)`
- `resize(w: number, h: number, density = 1, deviceClass?: DeviceClass)`
- `log(msg: string)` — Plain text to the host's log (the OS Beroun shell's log; the browser console).

## Functions

### classifyDevice

*function* · `packages/platform/src/platform.ts:37`

```ts
function classifyDevice(width: number, height: number, kind: PlatformKind, coarse: boolean): DeviceClass
```

### detectLevelTier

*function* · `packages/platform/src/tier.ts:69`

```ts
function detectLevelTier(o: TierOptions = {}): TierChoice
```

The level tier for this browser, with the reason (for the log and for a debug line):
 - a software renderer, little memory, data saving or a slow network -> `low`;
 - phones and tablets -> `mobile`;
 - a desktop with its own graphics card (NVIDIA, AMD, Apple M, Intel Arc) -> `desktop`;
 - an old integrated card or few cores / little memory -> `mobile`;
 - nothing known -> `desktop` on a desktop, `mobile` on a touch device.
The page can still give the player a switch; this is only the first choice.

### detectPlatform

*function* · `packages/platform/src/platform.ts:159`

```ts
function detectPlatform(opts: { key?: string; startPage?: string } = {}): FerretPlatform
```

Pick the implementation: OS Beroun when /platform.js is present, else the browser.

### fovFor

*function* · `packages/platform/src/display.ts:55`

```ts
function fovFor(aspect: number, baseVertical = 0.9, minHorizontal = 1.0): number
```

Vertical field of view for an aspect ratio: fixed vertical FOV, so the view widens with the aspect; on tall (portrait)
screens it grows so that the horizontal FOV does not fall below `minHorizontal` (the playable view stays the same).

### initialTier

*function* · `packages/platform/src/display.ts:34`

```ts
function initialTier(deviceClass: DeviceClass, kind: 'beroun' | 'browser' | 'headless'): QualityTier
```

The tier chosen from the device class. The console is always `low`; a benchmark may refine the others later.

### probeDevice

*function* · `packages/platform/src/tier.ts:21`

```ts
function probeDevice(): DeviceProbe
```

Reads the device from the browser. The graphics card is read from a throw-away canvas that is released at once.

### renderScaleFor

*function* · `packages/platform/src/display.ts:45`

```ts
function renderScaleFor(screen: ScreenInfo, tier: QualityTier, requested = 1): number
```

The render scale (<= 1) that keeps the frame within the tier's pixel budget.

### uiScaleFor

*function* · `packages/platform/src/display.ts:63`

```ts
function uiScaleFor(screen: ScreenInfo): number
```

UI scale from the screen's physical size, not its pixels: text stays readable on a console and on a phone.

## Interfaces

### DeviceProbe

*interface* · `packages/platform/src/tier.ts:8`

```ts
interface DeviceProbe
```

What the browser tells about the machine. Every field is optional: a browser may hide any of them.

- `renderer?: string` — the graphics card (WEBGL_debug_renderer_info): `ANGLE (NVIDIA, NVIDIA GeForce RTX 3050 ...)`
- `memoryGB?: number` — navigator.deviceMemory, GB, rounded down to a power of two and capped at 8
- `cores?: number`
- `saveData?: boolean` — the user asked the browser to save data
- `connection?: string` — navigator.connection.effectiveType

### FerretPlatform

*interface* · `packages/platform/src/platform.ts:20`

```ts
interface FerretPlatform
```

One interface, two implementations (plus a headless one for tests).
OS Beroun: Platform.state / onClose / exit / capabilities of /platform.js.
Browser: IndexedDB/localStorage state, visibilitychange/pagehide as suspend, fullscreen, orientation.

- `readonly kind: PlatformKind`
- `loadState<T = any>(): Promise<T | null>` — Saved state of the game (null when there is none).
- `saveState(state: unknown): Promise<void>`
- `onSuspend(fn: (reason: string) => void | Promise<void>): () => void` — Called before the page goes away (OS Beroun: the app is closed, ~2 s to save; browser: hidden/closed).
- `exit(): void` — Leave the game: OS Beroun closes the app; a browser goes back to the game's start page.
- `capabilities(): Promise<string[]>`
- `screen(): ScreenInfo`
- `onResize(fn: (s: ScreenInfo) => void): () => void`
- `requestFullscreen?(): Promise<void>`
- `log(msg: string): void` — Plain text to the host's log (the OS Beroun shell's log; the browser console).

### QualitySettings

*interface* · `packages/platform/src/display.ts:5`

```ts
interface QualitySettings
```

- `tier: QualityTier`
- `renderScale: number` — 1 = native size x density; lower renders fewer pixels (hardware scaling = 1 / renderScale)
- `shadowMapSize: number`
- `shadowCascades: number`
- `lodBias: number`
- `maxTextureSize: number`
- `fxaa: boolean`
- `msaa: number`
- `postProcessing: boolean`
- `drawDistance: number`
- `foveation?: number` — VR: fixed foveation 0..1 (the headset renders the edges of the view at lower resolution)
- `framebufferScale?: { min: number; max: number; start: number }` — VR: the range the framebuffer scale may move in, and where it starts
- `streaming?: { radius: number; budget: number }` — VR: scale of the streaming radii and of the per-frame instantiation work

### ScreenInfo

*interface* · `packages/platform/src/platform.ts:6`

```ts
interface ScreenInfo
```

- `width: number`
- `height: number`
- `density: number` — devicePixelRatio
- `portrait: boolean`
- `deviceClass: DeviceClass`

### TierChoice

*interface* · `packages/platform/src/tier.ts:48`

```ts
interface TierChoice
```

- `tier: LevelTier`
- `reason: string`

### TierOptions

*interface* · `packages/platform/src/tier.ts:50`

```ts
interface TierOptions
```

- `override?: string | null` — the tier asked for in the address (`?tier=`) or in a setting: wins when it is one of the tiers and the level has it
- `screen?: Pick<ScreenInfo, 'deviceClass'>`
- `probe?: DeviceProbe` — default: probeDevice()
- `available?: readonly LevelTier[]` — the tiers the level package has (default: all three). A tier that is not there gives way to the nearest one.

## Types

### DeviceClass

*type* · `packages/platform/src/platform.ts:4`

```ts
type DeviceClass = 'console' | 'phone' | 'tablet' | 'desktop'
```

### LevelTier

*type* · `packages/platform/src/tier.ts:4`

```ts
type LevelTier = 'desktop' | 'mobile' | 'low'
```

The quality variants a level package comes in (`tiers.json` of the exporter): a folder per tier, `desktop` the richest.

### PlatformKind

*type* · `packages/platform/src/platform.ts:3`

```ts
type PlatformKind = 'beroun' | 'browser' | 'headless'
```

### QualityTier

*type* · `packages/platform/src/display.ts:3`

```ts
type QualityTier = 'low' | 'medium' | 'high' | 'xr'
```

## Constants

### LEVEL_TIERS

*const* · `packages/platform/src/tier.ts:5`

```ts
const LEVEL_TIERS: readonly LevelTier[]
```

### QUALITY

*const* · `packages/platform/src/display.ts:25`

```ts
const QUALITY: Record<QualityTier, QualitySettings>
```

