# @ferret/flow: API

wind, fronts, vortices, jets, shelters and channels as one field of moving air and water, without physics.

Flow sources: wind, fronts, vortices, jets, shelters and channels add up to one field
`flowAt(position, time, medium)` that bodies, vessels, the character and the render all read. No physics and no Babylon here:
every source is a pure function of (position, time), so every peer computes the same field and a game without physics can use it.

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

## Classes

### FlowField

*class* · `packages/flow/src/index.ts:123`

```ts
class FlowField
```

- `readonly sources: Map<string, FlowSourceDef>`
- `evaluated: number` — how many sources were evaluated by the last `at` (the reach culling is visible to tests and the budget)
- `maxSources: number` — the most sources the field takes; none by default
- `add(def: FlowSourceDef): void`
- `remove(name: string)`
- `set(name: string, patch: Partial<FlowSourceDef>)`
- `list(): FlowSourceDef[]` — the sources of the level (those published by code, with a `publisher`, are left out: they are not data)
- `centreOf(s: FlowSourceDef, t: number): V3` — where a source is centred at time t (its first reference point, moved along its path)
- `at(p: V3, t: number, medium: Medium = 'air', skipPublisher?: string): FlowSample` — The flow at a point and time, per medium: the sum of the sources, then the shelters reduce it.

### FlowService

*class* · `packages/flow/src/index.ts:262`

```ts
class FlowService implements Service
```

The field as a world service: the clock is the world's, and the commands of the plan section 5 are registered.

- `readonly name: "flow"`
- `readonly field: FlowField`
- `world: World`
- `init(world: World)`
- `unload(): void` — The sources a level's block added go with the level.
- `load(list: unknown): void` — Flow sources of a level's `physics.flow` list.

## Functions

### advectClouds

*function* · `packages/flow/src/view.ts:25`

```ts
function advectClouds(field: FlowField, clouds: V3[], t: number, dt: number): V3[]
```

Move clouds by the wind at their own place for `dt`; returns the new positions (the input is left alone).

### cloudVelocity

*function* · `packages/flow/src/view.ts:20`

```ts
function cloudVelocity(field: FlowField, at: V3, t: number): [number, number]
```

The horizontal velocity at the height of a cloud layer; a cloud drifts with the wind there, a front brings its clouds with it.

### dropVelocity

*function* · `packages/flow/src/view.ts:36`

```ts
function dropVelocity(field: FlowField, at: V3, t: number, fall: number): V3
```

The slant of rain or snow: the velocity of a drop falling at `fall` m/s through the wind there (unit direction and speed).

### flowGrid

*function* · `packages/flow/src/view.ts:77`

```ts
function flowGrid(field: FlowField, centre: V3, half: number, step: number, t: number, medium: Medium = 'air'): FlowArrow[]
```

A grid of samples round a centre for the inspector's arrows: `half` metres each way (x and z) at height `centre[1]`, every `step` metres.

### flowReaches

*function* · `packages/flow/src/view.ts:92`

```ts
function flowReaches(field: FlowField, t: number): FlowReach[]
```

Where each source is now, how far it reaches and (for a vortex) its core: what the inspector draws as rings.

### funnels

*function* · `packages/flow/src/view.ts:43`

```ts
function funnels(field: FlowField, t: number): Funnel[]
```

### gustAt

*function* · `packages/flow/src/index.ts:59`

```ts
function gustAt(t: number, g: Gust): number
```

A deterministic gust, −1..1 in time (the one of `physics-media`).

### netFlow

*function* · `packages/flow/src/net.ts:32`

```ts
function netFlow(field: FlowField, net: FlowNetLike, opts: NetFlowOptions): NetFlow
```

### patchWind

*function* · `packages/flow/src/view.ts:13`

```ts
function patchWind(field: FlowField, centre: V3, t: number, o: { calm?: number; full?: number } = {}): PatchWind
```

### pathAt

*function* · `packages/flow/src/index.ts:85`

```ts
function pathAt(path: V3[], speed: number, start: number, t: number): V3
```

The point of a path at time t (moving at `speed` from `start`); the last point after the end.

### plumeLean

*function* · `packages/flow/src/view.ts:30`

```ts
function plumeLean(field: FlowField, base: V3, t: number, riseSpeed: number): [number, number]
```

How far a plume of smoke or steam leans: the horizontal offset per metre of rise, for a rise speed (wind speed over rise speed).

### turbulenceNoise

*function* · `packages/flow/src/view.ts:56`

```ts
function turbulenceNoise(seed: number, p: V3, t: number): number
```

Seeded turbulence for the picture only (D9): a smooth value noise of position and time, in -1..1, the same everywhere for one seed. The
physics never reads it; the render adds `amplitude * noise` to the flow it draws, so a gale looks ragged without peers disagreeing.

### validateFlowSource

*function* · `packages/flow/src/index.ts:98`

```ts
function validateFlowSource(d: unknown, path = 'flow'): string[]
```

### waterCurrent

*function* · `packages/flow/src/index.ts:293`

```ts
function waterCurrent(field: FlowField, y = 0, t = 0): (x: number, z: number) => [number, number]
```

A current for a liquid surface (`SurfaceDef.current`) taken from the water flow at height `y` and time `t`.

## Interfaces

### ChannelSource

*interface* · `packages/flow/src/index.ts:45`

```ts
interface ChannelSource extends Base
```

A flow along a polyline (a river, a mill race, a canyon wind) with a parabolic cross profile of half-width `width`.

- `kind: 'channel'`
- `points: V3[]`
- `velocity: number`
- `width: number`

### CurveSource

*interface* · `packages/flow/src/index.ts:47`

```ts
interface CurveSource extends Base
```

A sampled field (baked from a tool): `size` cells of `cell` metres from `origin`, `data` holds vx, vy, vz per cell (x fastest, then y, then z); trilinear inside, nothing outside.

- `kind: 'curve'`
- `origin: V3`
- `cell: number`
- `size: [number, number, number]`
- `data: number[]`

### FlowArrow

*interface* · `packages/flow/src/view.ts:75`

```ts
interface FlowArrow
```

- `at: V3`
- `velocity: V3`
- `speed: number`
- `updraft?: number`

### FlowNetLike

*interface* · `packages/flow/src/net.ts:8`

```ts
interface FlowNetLike
```

The weather over the net. The flow field is a pure function of position and time, so only its *changes* travel:
the authority of the level (one machine) sends each change with an effect time `now() + delay`, and every machine, the authority included,
applies it when the shared clock reaches that time. Nothing else is replicated, so a storm costs a message per change, not per step.

- `send(name: string, data: unknown): void`
- `on(name: string, fn: (data: any, from: string) => void): () => void`

### FlowReach

*interface* · `packages/flow/src/view.ts:90`

```ts
interface FlowReach
```

- `name: string`
- `kind: FlowSourceDef['kind']`
- `on: boolean`
- `centre: V3`
- `reach?: number`
- `core?: number`

### FlowSample

*interface* · `packages/flow/src/index.ts:11`

```ts
interface FlowSample
```

- `velocity: V3`
- `updraft?: number`
- `turbulence?: number`

### FrontSource

*interface* · `packages/flow/src/index.ts:37`

```ts
interface FrontSource extends Base
```

A plane that travels along `direction` (horizontal) at `speed`; behind it the flow goes from `before` to `after` over `width`.

- `kind: 'front'`
- `origin: V3`
- `direction: V3`
- `speed: number`
- `width: number`
- `before?: V3`
- `after: V3`

### Funnel

*interface* · `packages/flow/src/view.ts:42`

```ts
interface Funnel
```

A funnel to draw: the vortices of the field with their core, height and where they are now.

- `name: string`
- `centre: V3`
- `core: number`
- `height: number`
- `updraft: number`
- `circulation: number`

### Gust

*interface* · `packages/flow/src/index.ts:34`

```ts
interface Gust
```

- `amplitude: number`
- `period: number`
- `seed?: number`

### JetSource

*interface* · `packages/flow/src/index.ts:41`

```ts
interface JetSource extends Base
```

A cone of flow from a point (a fan, a vent, the wash of a propeller) with exponential decay over distance.

- `kind: 'jet'`
- `origin: V3`
- `direction: V3`
- `velocity: number`
- `halfAngle?: number`
- `decay?: number`

### LevelCurve

*interface* · `packages/flow/src/index.ts:14`

```ts
interface LevelCurve
```

A level of a source in time: keys [[t, v], ...] (linear, held at the ends); `loop` repeats over the last key.

- `curve: Array<[number, number]>`
- `loop?: boolean`

### NetFlow

*interface* · `packages/flow/src/net.ts:22`

```ts
interface NetFlow
```

- `add(def: FlowSourceDef): void`
- `set(name: string, patch: Partial<FlowSourceDef>): void`
- `remove(name: string): void`
- `step(): void` — call every fixed step
- `pending(): number`
- `dispose(): void`

### NetFlowOptions

*interface* · `packages/flow/src/net.ts:12`

```ts
interface NetFlowOptions
```

- `authority: boolean` — is this machine the authority of the level's weather (default false: it only receives)
- `authorityPeer?: string` — the peer id of the authority, when known (otherwise the first sender is taken for it)
- `now: () => number`
- `delay?: number`

### PatchWind

*interface* · `packages/flow/src/view.ts:12`

```ts
interface PatchWind
```

One wind uniform for a patch of grass or trees: the direction (unit, horizontal), the speed and a 0..1 sway amount.

- `dir: [number, number]`
- `speed: number`
- `sway: number`
- `gust: number`

### ShelterSource

*interface* · `packages/flow/src/index.ts:43`

```ts
interface ShelterSource extends Base
```

A sphere in the lee of an obstacle where the flow of the other sources is reduced by `strength` (0..1) and made turbulent.

- `kind: 'shelter'`
- `centre: V3`
- `radius: number`
- `strength: number`

### SolvedSource

*interface* · `packages/flow/src/index.ts:53`

```ts
interface SolvedSource extends Base
```

A region where the flow is **solved** (a flow box, `@ferret/flow-solver`): inside it the solver's field replaces the analytic sum, blended over a margin.
Code only (it has a function); the box publishes it and the readers see the wake without any change on their side. `sampler` gets the point, the time and the
analytic velocity there and returns the replaced velocity and its weight 0..1, or null outside the region (or while the box sleeps).

- `kind: 'solved'`
- `sampler: (p: V3, t: number, analytic: V3) => { velocity: V3; weight: number } | null`

### UniformSource

*interface* · `packages/flow/src/index.ts:35`

```ts
interface UniformSource extends Base
```

- `kind: 'uniform'`
- `velocity: V3`
- `profile?: { power: number; refHeight: number; seaLevel?: number }`
- `gust?: Gust`

### VortexSource

*interface* · `packages/flow/src/index.ts:39`

```ts
interface VortexSource extends Base
```

A Rankine vortex about a vertical axis: solid rotation inside `core`, Γ/(2πr) outside; inflow near the ground, an updraft in the core.

- `kind: 'vortex'`
- `centre: V3`
- `core: number`
- `circulation: number`
- `inflow?: number`
- `updraft?: number`
- `height?: number`

## Types

### FlowSourceDef

*type* · `packages/flow/src/index.ts:54`

```ts
type FlowSourceDef = SolvedSource | CurveSource | UniformSource | FrontSource | VortexSource | JetSource | ShelterSource | ChannelSource
```

### Medium

*type* · `packages/flow/src/index.ts:10`

```ts
type Medium = 'air' | 'water'
```

### V3

*type* · `packages/flow/src/index.ts:9`

```ts
type V3 = [number, number, number]
```

Flow sources: wind, fronts, vortices, jets, shelters and channels add up to one field
`flowAt(position, time, medium)` that bodies, vessels, the character and the render all read. No physics and no Babylon here:
every source is a pure function of (position, time), so every peer computes the same field and a game without physics can use it.

