fuzzyworld

tower / files / src / terrain / worker.ts

worker.ts

2.0 KB · history · blame

1/**
2 * A terrain worker. See world-generation.md §5.
3 *
4 * Holds one compiled world and answers questions about it: build this tile, render
5 * these rows of the map. The first worker in the pool also compiles, reporting each
6 * step as it starts so the status dialog can say what is being made.
7 */
8import { expose, transfer } from 'comlink'
9import type { World } from '../world/schema.js'
10import { type CompiledWorld, compileWorld } from './compile.js'
11import { type Runtime, prepare } from './field.js'
12import { renderMapRows } from './map-image.js'
13import { type TileData, type TileGrid, type TileKey, buildTile } from './tile.js'
14
15let runtime: Runtime | null = null
16let generation = -1
17
18const api = {
19 /** Answers once the worker's code has loaded: the pool's check that it is alive. */
20 ping(): true {
21 return true
22 },
23
24 compile(world: World, onStep: (label: string) => void): CompiledWorld {
25 return compileWorld(world, onStep)
26 },
27
28 load(world: CompiledWorld, gen: number): void {
29 runtime = prepare(world)
30 generation = gen
31 },
32
33 /** Null when the world has moved on since the request was made: the tile is stale. */
34 tile(gen: number, t: TileKey, n: TileGrid): TileData | null {
35 if (!runtime || gen !== generation) return null
36 const data = buildTile(runtime, t, n)
37 const buffers: Transferable[] = [data.positions.buffer, data.normals.buffer, data.materials.buffer]
38 if (data.water) buffers.push(data.water.positions.buffer, data.water.attrs.buffer, data.water.indices.buffer)
39 if (data.canopy) buffers.push(data.canopy.positions.buffer, data.canopy.attrs.buffer, data.canopy.indices.buffer)
40 return transfer(data, buffers)
41 },
42
43 mapRows(gen: number, width: number, height: number, y0: number, y1: number, origin: number): Uint8ClampedArray | null {
44 if (!runtime || gen !== generation) return null
45 const rows = renderMapRows(runtime, width, height, y0, y1, origin)
46 return transfer(rows, [rows.buffer])
47 },
48}
49
50export type WorkerApi = typeof api
51expose(api)