Skip to content

API reference / @jsprismarine/chunkgen

@jsprismarine/chunkgen ​

Java Edition's chunk generation ladder. A chunk is at one of ten named statuses, a step table says what each status may read and how far it may write, and a holder per chunk makes each status body run exactly once.

This package holds no world, no noise and no features. What it gives the server is the shape those things have to run in if the same seed and the same chunk position are to produce the same blocks whatever order chunks are generated in and however many threads do it.

ts
import { GENERATION_PYRAMID } from '@jsprismarine/chunkgen';

const features = GENERATION_PYRAMID.stepTo('features');
features.requireReadable(1, 0, 'terrain'); // 'terrain'
features.requireReadable(1, 0, 'features'); // throws ChunkReadOutOfWindowError
features.canWriteBlocksAt(1, 0); // true, and it is the only step for which that is true

The tables come out of Mojang's 26.3 server jar, read class by class in java-chunk-generation-pipeline.md. The decision to copy them rather than derive something equivalent is ADR 0002.

The ten statuses ​

empty, structure_starts, structure_references, biomes, terrain, features, initialize_light, light, spawn, full. register sets each status's index to its parent's plus one, so the ladder is a chain and isOrAfter is an integer comparison.

26.3 has ten, not the twelve older versions had: noise, surface and carvers are one terrain status whose task runs noise fill, surface materials and carvers back to back.

Three of the ten have no body in this repository yet. Lighting lives in @jsprismarine/lighting and spawning in @jsprismarine/spawning, and neither is sequenced against generation today. They stay on the ladder anyway. Collapsing them would shift every accumulated radius by one, and the step table would stop being something anyone can check against the jar.

The step table ​

Each step declares two windows and one radius.

Direct dependencies. Per Chebyshev distance, the status that ring is guaranteed to have reached. This is what a running body may read, and requireReadable throws rather than returning a chunk at the wrong status, the way WorldGenRegion.getChunk raises a ReportedException. An undeclared read is a crash on the first chunk rather than a wrong block on the thousandth.

Stepd=0d=1d=2d=3..8
emptyoutside the window
structure_startsemptyoutside
structure_referencesstructure_startsstructure_startsstructure_startsstructure_starts
biomesstructure_referencesstructure_startsstructure_startsstructure_starts
terrainbiomesbiomesstructure_startsstructure_starts
featuresterrainterrainstructure_startsstructure_starts
initialize_lightfeaturesoutside
lightinitialize_lightinitialize_lightoutside
spawnlightbiomesoutside
fullspawnfeaturesoutside

The full row is the one that is not the jar's. Java's full declares nothing, because its feature pass has already written through into the neighbor. Ours reads the eight neighbors at features to collect the patches they recorded for it. The accumulated table does not move: full already guaranteed initialize_light at distance 1, which is above features.

Accumulated dependencies. The transitive closure of the above, which is what sizes each layer of a scheduler. Inverting the full row gives the radius each status has to reach before one chunk can become full: 11 for empty and structure_starts, 3 for structure_references and biomes, 2 for terrain, 1 for features and initialize_light, 0 for light and spawn. Generating one chunk from nothing therefore touches 529 chunks at structure_starts and 25 at terrain.

The block write radius. terrain is 0 and features is 1. Every other step is -1, and -1 excludes the step's own chunk, so those steps cannot write a block through the region at all. features is the only status that writes into a neighbor, which is why a tree is whole across a chunk border, and it is the only place two concurrent bodies could collide.

Two numbers in the package exist as arithmetic checks on the table rather than for their own sake. RADIUS_AROUND_FULL_CHUNK is 11 and SAFETY_MARGIN_CHUNKS is 90, and the second needs the accumulated list for full to be exactly 12 long. A transcription slip anywhere in the pyramid moves one of them.

The holder and the scheduler ​

A ChunkHolder is one chunk's place in the ladder: the chunk, and one promise per status. The first caller to ask for a status creates the promise and runs the body; every later caller awaits that same promise. That is what makes a (chunk, status) body run exactly once however many requests overlap. Java needs a compare-and-exchange on startedWork for it, because several pool threads reach applyStep at once; only the thread that owns the holder map touches a holder here, and a map insert cannot be interleaved. startedWork is kept anyway, because it is what catches a layer loop that skips a rung.

ChunkHolderMap decides how long a holder lives, by reference count. A run acquires every chunk inside its radius before it runs a step and releases them all when it finishes, so nothing it depends on can be dropped while it is in flight, and a holder nothing needs goes away. The generator's 128-entry LRU got this wrong in a way that was measurable: preload-radius: 5 is 121 chunks, right at the edge, so a feature pass writing into a neighbor could land on a holder that had already been evicted. A caller that wants a chunk to stay resident past a run acquires its own reference.

GenerationScheduler is the layer loop. To bring a chunk to a status, the neighborhood has to reach that status's dependencies first, so a run walks the ladder from empty upward and applies each step to the square the accumulated dependency table sizes.

ts
const holders = new ChunkHolderMap((chunkX, chunkZ) => new MyChunk(chunkX, chunkZ));
const scheduler = new GenerationScheduler({ holders, tasks: { terrain: buildTerrain } });

scheduler.layersFor('terrain'); // [['empty', 9], ['structure_starts', 9], ..., ['terrain', 0]]
const chunk = await scheduler.generate(0, 0, 'terrain');

A status with no entry in tasks passes its chunk through, which is what every status above terrain does today. The bodies live in the server, because they need the noise, the biome source and the feature registries; the scheduler only knows how to order them and what each one may read.

Two properties follow, and the tests count them rather than assert them in prose. Nine chunks asked for at once at a full target build terrain over the union of their windows, 49 bodies, where DataDrivenGenerator.generateChunk builds a 3 by 3 tile per chunk and so builds 81. And the sixteen chunks of a 4 by 4 area come out identical whether they are asked for row major, reversed, shuffled, one at a time or all sixteen at once.

The feature patch ​

features is the one status that writes outside its own chunk, and the one place two bodies running at once could land on the same block. Nothing writes through. A feature's writes into its own chunk apply as they happen, so features inside a chunk still see each other the way Java's do; a write that lands in a neighbor is recorded and handed to that neighbor's InboundFeaturePatches. The neighbor applies its own post-features state first and the patches after it, in FEATURE_PATCH_ORDER.

ts
inbound.receive(-1, 0, patchFromTheWest);
inbound.inMergeOrder(); // ordered by position, not by when each arrived

The order is (dx, dz) ascending with dx fastest, and storing by source offset rather than appending to a list is the mechanism rather than a detail: a list would record arrival order, and arrival order is what the scheduler chooses. receive refuses the chunk's own offset and anything past radius 1, and refuses a second patch from the same neighbor, which would mean a features body ran twice.

This is ADR 0002's one deliberate deviation from Java. Java writes through a live WorldGenRegion into the neighbor's ProtoChunk, so which of two overlapping features wins depends on which chunk reached features first, which depends on scheduling; Java's border output is therefore not a function of the seed alone, and ours is. The price is one case: a feature whose placement decision reads a block sees the neighbor's terrain and not the neighbor's features, so two features can end up in the same space where Java would have refused the second.

The chunk type ​

The holder, the map and the scheduler take the chunk type as a parameter. All they need of it is StagedChunk: where it is, which rung it is on, and an advanceTo that refuses to go backward with ChunkStatusRegressionError.

The package ships no chunk of its own. A server climbs the ladder with the chunk buffer it already has rather than copying every block into a second representation twice per status. @jsprismarine/prismarine does: its generation stages speak Java block states with properties.

The worker pool ​

GenerationPool runs status bodies in worker threads, over piscina. It knows a chunk position and a status name and nothing else about world generation, so this package does not depend on the server.

A caller names a pipeline module. Each worker imports it once, hands it the pool's setup value, and keeps whatever it builds for the life of the worker. That is the whole reason a worker is worth starting: a seed's noise tables cost 55 to 134 ms to build and the 7594-entry climate biome source 145 to 345 ms, so a worker is pinned to one world rather than told which world each task belongs to.

ts
const pool = new GenerationPool({
    pipeline: '/path/to/built/terrainPipeline.js',
    workers: 6,
    setup: { seed: 1234n, registryBundle }
});

const { payload } = await pool.run({ status: 'terrain', chunkX: 3, chunkZ: -14, input: beardPieces });

The pipeline module exports createGenerationPipeline, which answers with an object that has a run. A body hands back a payload and the list of ArrayBuffers inside it, and the pool transfers those rather than copying them: 18 microseconds for a 192 KiB column against 76 cloned and 1370 as a number[].

Two constraints are not negotiable.

Only a status that writes radius 0 belongs in a worker. terrain is one, which is why Java sends it to a thread pool and keeps features, which writes radius 1, on a single executor. Two terrain bodies can never touch the same block, so no two workers can race.

The module has to be something the worker's loader can import(). A worker thread inherits process.execArgv, so the loader the host was started with is already installed in the worker. A published install needs nothing: the specifier is a built .js. A dev checkout runs under node --import tsx, and its workers do too, which is what follows the extensionless @jsprismarine/* imports a .ts pipeline module is full of. Nothing has to be built first. A production workspace start selects the compiled .js exports with the jsprismarine:dist condition, so the pool picks its built pipeline and worker entries without adding a TypeScript loader to either thread.

A host that reads TypeScript through a loader of its own, which is vitest, has no such flag to hand on, and its workers would read the .ts through Node's strip-only loader, which stops at the first extensionless import. When the pipeline or the worker entry is TypeScript source and nothing in process.execArgv or NODE_OPTIONS installs an ES module loader, the pool starts its workers with --import and the tsx resolved from beside the pipeline module, which is the one the package being run from source declares. workerExecArgv(options) is that decision, exported so a caller can see what its workers will get.

Math.random is shadowed inside the worker and throws. It is seeded independently per V8 isolate, so a main thread and six workers produce seven different sequences and a decorator that reached for it would give a different world depending on which worker ran the chunk.

When a pool cannot start ​

GenerationPool.unavailable(options) answers with a sentence or with undefined, and a caller is expected to ask before it builds one. It refuses a single executable, where the modules live in the binary and no worker thread can reach them, and it refuses a worker entry or a pipeline module that is not on disk.

It cannot promise the import succeeds, because that depends on the loader, so the first task is still the real test. A caller that wants a server rather than a fast one catches that rejection, says so once, and runs the body on its own thread.

Running the pool in a host process ​

GenerationPool and HostedGenerationPool both implement GenerationTransport. The hosted one forks a generation host, lowers its operating system priority, and sends it tasks over IPC, which is the portable way to give generation a lower priority than the server: Node cannot lower one worker thread. createGenerationTransport({ ...options, host: 'process' }) builds it and falls back to the in-process pool, calling onFallback with the reason, when no host can start. A host that dies is replaced and the tasks it held are sent again, which returns the same bytes. Shared buffers in the setup are copied to the host once and shared again among its workers. A Bun-compiled executable starts the host by running itself again with --role generation-host (GENERATION_HOST_ROLE from hostRole), so its entry has to hand that role to generationHost, and the build has to define JSP_EMBEDDED_GENERATION_HOST to say it does. A Node single executable cannot start the host yet and keeps the in-process pool. setBackgroundLimit caps how many soon and idle tasks run at once, which is what ConcurrencyGovernor steers; immediate tasks are never limited.

Installation ​

To install @jsprismarine/chunkgen, use the following command:

pnpm install @jsprismarine/chunkgen --save

Classes ​

Interfaces ​

BuiltGenerationTransport ​

Defined in: createGenerationTransport.ts:20

What was built, and why when it is not what was asked for.

Properties ​

mode ​

readonly mode: GenerationHostMode

Defined in: createGenerationTransport.ts:22

reason? ​

readonly optional reason?: string

Defined in: createGenerationTransport.ts:24

Why the host was not used, when the caller asked for it.

transport ​

readonly transport: GenerationTransport

Defined in: createGenerationTransport.ts:21


CgroupFiles ​

Defined in: ConcurrencyGovernor.ts:154

Where throttle counters can be read from. Injectable so a test needs no cgroup.

Methods ​

read() ​

read(path): string | undefined

Defined in: ConcurrencyGovernor.ts:155

Parameters ​
path ​

string

Returns ​

string | undefined


ConcurrencyGovernorOptions ​

Defined in: ConcurrencyGovernor.ts:16

What a governor is built with.

Properties ​

decrease? ​

readonly optional decrease?: number

Defined in: ConcurrencyGovernor.ts:28

What the limit is multiplied by on pressure. Defaults to 0.5.

holdMs? ​

readonly optional holdMs?: number

Defined in: ConcurrencyGovernor.ts:30

After pressure, how long before the limit may rise again, in milliseconds. Defaults to 2000.

initial? ​

readonly optional initial?: number

Defined in: ConcurrencyGovernor.ts:22

Where the limit starts. Defaults to half of max, so a fresh server ramps up rather than bursts.

lateMs? ​

readonly optional lateMs?: number

Defined in: ConcurrencyGovernor.ts:24

A tick later than this counts as pressure, in milliseconds. Defaults to 25, half a tick.

max ​

readonly max: number

Defined in: ConcurrencyGovernor.ts:18

The most background tasks ever allowed at once: the number of workers.

min? ​

readonly optional min?: number

Defined in: ConcurrencyGovernor.ts:20

The fewest allowed. Defaults to 1, so background work always makes some progress.

raiseEveryMs? ​

readonly optional raiseEveryMs?: number

Defined in: ConcurrencyGovernor.ts:26

How long the server must stay calm before the limit rises by one, in milliseconds. Defaults to 1000.


CpuMax ​

Defined in: ConcurrencyGovernor.ts:126

The bandwidth limit of a version 2 control group, from cpu.max.

Properties ​

periodUsec ​

readonly periodUsec: number

Defined in: ConcurrencyGovernor.ts:129

quotaUsec ​

readonly quotaUsec: number | undefined

Defined in: ConcurrencyGovernor.ts:128

Microseconds of CPU per period, or undefined for max, meaning no limit.


CpuThrottleStat ​

Defined in: ConcurrencyGovernor.ts:94

The throttle counters of a control group, as cpu.stat reports them.

Properties ​

nrPeriods ​

readonly nrPeriods: number

Defined in: ConcurrencyGovernor.ts:95

nrThrottled ​

readonly nrThrottled: number

Defined in: ConcurrencyGovernor.ts:96

throttledUsec ​

readonly throttledUsec: number

Defined in: ConcurrencyGovernor.ts:98

Time spent throttled, in microseconds.


DurationSummary ​

Defined in: GenerationStats.ts:24

The count, total, maximum and bucketed distribution of one duration.

Properties ​

buckets ​

readonly buckets: readonly number[]

Defined in: GenerationStats.ts:29

One count per DURATION_BUCKET_BOUNDS_MS bound, then one for everything longer.

count ​

readonly count: number

Defined in: GenerationStats.ts:25

maxMs ​

readonly maxMs: number

Defined in: GenerationStats.ts:27

totalMs ​

readonly totalMs: number

Defined in: GenerationStats.ts:26


GenerationPoolOptions ​

Defined in: GenerationPool.ts:191

How a GenerationPool is built.

Extended by ​

Properties ​

inFlight? ​

readonly optional inFlight?: number

Defined in: GenerationPool.ts:250

How many tasks may be with the workers at once, which defaults to one more than there are workers.

Everything above this waits in the pool's own queue, where GenerationPriority still orders it; everything below it has already been handed to piscina, which dispatches in arrival order and cannot be re-ordered afterwards. So this is the trade: at the worker count exactly, a worker that finishes waits a microtask for its next task, and at a large multiple the bands stop meaning anything because the whole backlog is already downstream.

One spare is what keeps both: every worker has work, one task is staged behind them, and the worst a newly arrived immediate can wait is the one staged chunk.

now? ​

readonly optional now?: () => number

Defined in: GenerationPool.ts:252

The clock task timings are read from, in milliseconds. Defaults to performance.now; a test names its own.

Returns ​

number

onWorkerExit? ​

readonly optional onWorkerExit?: (threadId) => void

Defined in: GenerationPool.ts:236

Called with a worker thread ID after that worker exits, including pool shutdown.

Parameters ​
threadId ​

number

Returns ​

void

pipeline ​

readonly pipeline: string

Defined in: GenerationPool.ts:204

The module each worker imports to get its status bodies.

A path or a file: URL, exporting createGenerationPipeline, a WorkerPipelineFactory. TypeScript is as good as JavaScript here: a worker thread inherits process.execArgv, so whatever loader the host was started with is already installed in the worker, and a host running under --import tsx hands its workers a loader that follows the extensionless @jsprismarine/* imports a dev checkout is full of. A host that reads TypeScript through its own loader instead, which is vitest, has no such flag to hand on, so the pool names the tsx beside the module itself; see workerExecArgv.

setup? ​

readonly optional setup?: unknown

Defined in: GenerationPool.ts:219

Handed to every worker's WorkerPipelineFactory.

worker? ​

readonly optional worker?: string

Defined in: GenerationPool.ts:209

The worker entry, which defaults to defaultGenerationWorker. A data: URL uses the embedded worker message protocol; file paths and URLs use piscina.

workerHeapSnapshotDirectory? ​

readonly optional workerHeapSnapshotDirectory?: string

Defined in: GenerationPool.ts:234

Optional diagnostics directory. Each worker writes one .heapsnapshot after its first completed task, so the snapshot contains the initialized pipeline and one task's result.

workerHeapStats? ​

readonly optional workerHeapStats?: SharedArrayBuffer

Defined in: GenerationPool.ts:224

Optional benchmark sink with one Int32 slot per worker plus a leading worker counter. Each worker stores its isolate heap usage in bytes after its most recent task.

workers ​

readonly workers: number

Defined in: GenerationPool.ts:217

How many workers to start.

Five or six on this machine. Aggregate throughput peaks at 4.7 times one thread there and declines past six, because six of the eight cores are performance cores and each worker is a whole V8 isolate with its own garbage collector.

workerStartupStats? ​

readonly optional workerStartupStats?: SharedArrayBuffer

Defined in: GenerationPool.ts:229

Optional BigInt64Array sink with one leading worker counter and three slots per worker: first-task elapsed wall microseconds, thread CPU microseconds, and heap-used bytes.


GenerationResult ​

Defined in: GenerationPool.ts:145

What a status body in a worker hands back.

Properties ​

payload ​

readonly payload: unknown

Defined in: GenerationPool.ts:147

The chunk, flattened into something postMessage moves rather than copies.

transferList ​

readonly transferList: readonly ArrayBuffer[]

Defined in: GenerationPool.ts:149

Every ArrayBuffer in the payload, so it is transferred rather than cloned.

workerStats? ​

readonly optional workerStats?: WorkerTaskStats

Defined in: GenerationPool.ts:154

What the worker measured about this task. Set by the worker entries; a runner or a test double that leaves it out simply contributes nothing to the worker columns of the stats.


GenerationSchedulerOptions ​

Defined in: GenerationScheduler.ts:14

What a scheduler is built over.

Type Parameters ​

TChunk ​

TChunk extends StagedChunk

Properties ​

holders ​

readonly holders: ChunkHolderMap<TChunk>

Defined in: GenerationScheduler.ts:16

Where holders live and how long they live, shared by every run on this scheduler.

pyramid? ​

readonly optional pyramid?: ChunkPyramid

Defined in: GenerationScheduler.ts:20

Defaults to GENERATION_PYRAMID, the table a chunk climbs when it must be generated.

tasks ​

readonly tasks: StepTasks<TChunk>

Defined in: GenerationScheduler.ts:18

The status bodies. A status with no entry passes its chunk through.


GenerationStatsSnapshot ​

Defined in: GenerationStats.ts:51

A point-in-time copy of everything a pool recorded.

Properties ​

byTask ​

readonly byTask: readonly GenerationTaskStats[]

Defined in: GenerationStats.ts:52


GenerationTask ​

Defined in: GenerationPool.ts:118

What a worker is asked to do: advance one chunk to one status.

Properties ​

chunkX ​

readonly chunkX: number

Defined in: GenerationPool.ts:121

chunkZ ​

readonly chunkZ: number

Defined in: GenerationPool.ts:122

dimension ​

readonly dimension: number

Defined in: GenerationPool.ts:132

The Bedrock id of the dimension the chunk is in: 0 for the Overworld, 1 for the Nether, 2 for the End, 1000 and up for a custom dimension.

Part of the task so a pool shared between dimensions can tell their chunks apart. ShardedGenerationPool mixes it into the shard hash, so chunk (0, 0) of two dimensions does not always land on the same worker. The body is free to ignore it: a worker pinned to one world builds what it was set up for, whatever the task names.

input? ​

readonly optional input?: unknown

Defined in: GenerationPool.ts:141

Anything else the body needs, structured-cloned to the worker.

The inputs a status reads that the worker cannot derive from the seed and the position. A terrain body is handed the structure pieces that push its terrain around, because laying structures out is the main thread's job and reading them is not worth duplicating six times.

status ​

readonly status: "empty" | "structure_starts" | "structure_references" | "biomes" | "terrain" | "features" | "initialize_light" | "light" | "spawn" | "full"

Defined in: GenerationPool.ts:120

The status the body being run produces.


GenerationTaskSample ​

Defined in: GenerationStats.ts:56

One settled task, as the pool saw it.

Properties ​

backlogWaitMs ​

readonly backlogWaitMs: number

Defined in: GenerationStats.ts:60

failed ​

readonly failed: boolean

Defined in: GenerationStats.ts:59

priority ​

readonly priority: "immediate" | "soon" | "idle"

Defined in: GenerationStats.ts:58

status ​

readonly status: "empty" | "structure_starts" | "structure_references" | "biomes" | "terrain" | "features" | "initialize_light" | "light" | "spawn" | "full"

Defined in: GenerationStats.ts:57

turnaroundMs ​

readonly turnaroundMs: number

Defined in: GenerationStats.ts:61

workerCpuMs? ​

readonly optional workerCpuMs?: number

Defined in: GenerationStats.ts:64

workerWallMs? ​

readonly optional workerWallMs?: number

Defined in: GenerationStats.ts:63

Absent when the worker did not say, which is every runner that predates the field.


GenerationTaskStats ​

Defined in: GenerationStats.ts:33

Tasks of one status in one priority band.

Properties ​

backlogWait ​

readonly backlogWait: DurationSummary

Defined in: GenerationStats.ts:41

Time in the pool's backlog before a worker slot was free.

failed ​

readonly failed: number

Defined in: GenerationStats.ts:39

Tasks that settled with an error.

priority ​

readonly priority: "immediate" | "soon" | "idle"

Defined in: GenerationStats.ts:35

status ​

readonly status: "empty" | "structure_starts" | "structure_references" | "biomes" | "terrain" | "features" | "initialize_light" | "light" | "spawn" | "full"

Defined in: GenerationStats.ts:34

tasks ​

readonly tasks: number

Defined in: GenerationStats.ts:37

Tasks that settled, successfully or not.

turnaround ​

readonly turnaround: DurationSummary

Defined in: GenerationStats.ts:43

From leaving the backlog to the result arriving on this thread.

workerCpu ​

readonly workerCpu: DurationSummary

Defined in: GenerationStats.ts:47

Thread CPU time inside the worker, in the same sense as workerWall.

workerWall ​

readonly workerWall: DurationSummary

Defined in: GenerationStats.ts:45

The task's own wall time inside the worker. Only tasks that reported it count here.


GenerationTransport ​

Defined in: GenerationTransport.ts:13

The surface a generation pool offers its callers.

Properties ​

inFlight ​

readonly inFlight: number

Defined in: GenerationTransport.ts:17

How many tasks the workers are holding right now.

queued ​

readonly queued: number

Defined in: GenerationTransport.ts:19

How many tasks are waiting for a worker.

workers ​

readonly workers: number

Defined in: GenerationTransport.ts:15

How many workers are up.

Methods ​

cancel() ​

cancel(wanted): number

Defined in: GenerationTransport.ts:31

Drops every waiting task a predicate rejects.

Parameters ​
wanted ​

(task) => boolean

Returns ​

number

How many went.

destroy() ​

destroy(): Promise<void>

Defined in: GenerationTransport.ts:49

Stops every worker and refuses what is waiting.

Returns ​

Promise<void>

promote() ​

promote(wanted, to): number

Defined in: GenerationTransport.ts:34

Moves waiting tasks up into a band.

Parameters ​
wanted ​

(task) => boolean

to ​

"immediate" | "soon" | "idle"

Returns ​

number

How many moved.

resetStats() ​

resetStats(): void

Defined in: GenerationTransport.ts:40

Forgets the recorded stats.

Returns ​

void

run() ​

run(task, priority?): Promise<GenerationResult>

Defined in: GenerationTransport.ts:28

Runs one task in a worker.

Parameters ​
task ​

GenerationTask

The status, the position and whatever else the body reads.

priority? ​

"immediate" | "soon" | "idle"

Which band the task waits in. Defaults to immediate.

Returns ​

Promise<GenerationResult>

What the body produced.

setBackgroundLimit() ​

setBackgroundLimit(limit): void

Defined in: GenerationTransport.ts:46

Limits how many soon and idle tasks may be with workers at once, which is what the concurrency governor steers. immediate tasks are never limited.

Parameters ​
limit ​

number | undefined

Returns ​

void

statsSnapshot() ​

statsSnapshot(): GenerationStatsSnapshot

Defined in: GenerationTransport.ts:37

What the transport recorded about the tasks it ran.

Returns ​

GenerationStatsSnapshot


GenerationTransportOptions ​

Defined in: createGenerationTransport.ts:14

How createGenerationTransport chooses.

Extends ​

Properties ​

host ​

readonly host: GenerationHostMode

Defined in: createGenerationTransport.ts:16

process asks for a host and falls back when one cannot start; in-process never forks.

hostEntry? ​

readonly optional hostEntry?: string

Defined in: HostedGenerationPool.ts:52

The module the host runs. Defaults to this package's generationHost.

Inherited from ​

HostedGenerationPoolOptions.hostEntry

hostPriority? ​

readonly optional hostPriority?: number

Defined in: HostedGenerationPool.ts:48

The operating system priority to give the host, as os.setPriority takes it. Defaults to os.constants.priority.PRIORITY_LOW. Failing to set it is not an error: the host runs at the priority it started with.

Inherited from ​

HostedGenerationPoolOptions.hostPriority

inFlight? ​

readonly optional inFlight?: number

Defined in: GenerationPool.ts:250

How many tasks may be with the workers at once, which defaults to one more than there are workers.

Everything above this waits in the pool's own queue, where GenerationPriority still orders it; everything below it has already been handed to piscina, which dispatches in arrival order and cannot be re-ordered afterwards. So this is the trade: at the worker count exactly, a worker that finishes waits a microtask for its next task, and at a large multiple the bands stop meaning anything because the whole backlog is already downstream.

One spare is what keeps both: every worker has work, one task is staged behind them, and the worst a newly arrived immediate can wait is the one staged chunk.

Inherited from ​

HostedGenerationPoolOptions.inFlight

maxRestarts? ​

readonly optional maxRestarts?: number

Defined in: HostedGenerationPool.ts:50

How many times a host that exits is replaced before the pool gives up on hosts. Defaults to 3.

Inherited from ​

HostedGenerationPoolOptions.maxRestarts

now? ​

readonly optional now?: () => number

Defined in: GenerationPool.ts:252

The clock task timings are read from, in milliseconds. Defaults to performance.now; a test names its own.

Returns ​

number

Inherited from ​

HostedGenerationPoolOptions.now

onFallback? ​

readonly optional onFallback?: (reason) => void

Defined in: HostedGenerationPool.ts:54

Told when the pool runs its tasks in process instead, and why.

Parameters ​
reason ​

string

Returns ​

void

Inherited from ​

HostedGenerationPoolOptions.onFallback

onWorkerExit? ​

readonly optional onWorkerExit?: (threadId) => void

Defined in: GenerationPool.ts:236

Called with a worker thread ID after that worker exits, including pool shutdown.

Parameters ​
threadId ​

number

Returns ​

void

Inherited from ​

HostedGenerationPoolOptions.onWorkerExit

pipeline ​

readonly pipeline: string

Defined in: GenerationPool.ts:204

The module each worker imports to get its status bodies.

A path or a file: URL, exporting createGenerationPipeline, a WorkerPipelineFactory. TypeScript is as good as JavaScript here: a worker thread inherits process.execArgv, so whatever loader the host was started with is already installed in the worker, and a host running under --import tsx hands its workers a loader that follows the extensionless @jsprismarine/* imports a dev checkout is full of. A host that reads TypeScript through its own loader instead, which is vitest, has no such flag to hand on, so the pool names the tsx beside the module itself; see workerExecArgv.

Inherited from ​

HostedGenerationPoolOptions.pipeline

setup? ​

readonly optional setup?: unknown

Defined in: GenerationPool.ts:219

Handed to every worker's WorkerPipelineFactory.

Inherited from ​

HostedGenerationPoolOptions.setup

worker? ​

readonly optional worker?: string

Defined in: GenerationPool.ts:209

The worker entry, which defaults to defaultGenerationWorker. A data: URL uses the embedded worker message protocol; file paths and URLs use piscina.

Inherited from ​

HostedGenerationPoolOptions.worker

workerHeapSnapshotDirectory? ​

readonly optional workerHeapSnapshotDirectory?: string

Defined in: GenerationPool.ts:234

Optional diagnostics directory. Each worker writes one .heapsnapshot after its first completed task, so the snapshot contains the initialized pipeline and one task's result.

Inherited from ​

HostedGenerationPoolOptions.workerHeapSnapshotDirectory

workerHeapStats? ​

readonly optional workerHeapStats?: SharedArrayBuffer

Defined in: GenerationPool.ts:224

Optional benchmark sink with one Int32 slot per worker plus a leading worker counter. Each worker stores its isolate heap usage in bytes after its most recent task.

Inherited from ​

HostedGenerationPoolOptions.workerHeapStats

workers ​

readonly workers: number

Defined in: GenerationPool.ts:217

How many workers to start.

Five or six on this machine. Aggregate throughput peaks at 4.7 times one thread there and declines past six, because six of the eight cores are performance cores and each worker is a whole V8 isolate with its own garbage collector.

Inherited from ​

HostedGenerationPoolOptions.workers

workerStartupStats? ​

readonly optional workerStartupStats?: SharedArrayBuffer

Defined in: GenerationPool.ts:229

Optional BigInt64Array sink with one leading worker counter and three slots per worker: first-task elapsed wall microseconds, thread CPU microseconds, and heap-used bytes.

Inherited from ​

HostedGenerationPoolOptions.workerStartupStats


GenerationWorkerData ​

Defined in: GenerationPool.ts:177

What the worker entry is told when it starts, through workerData.

Properties ​

pipeline ​

readonly pipeline: string

Defined in: GenerationPool.ts:179

The module specifier a worker imports to get its WorkerPipelineFactory.

setup ​

readonly setup: unknown

Defined in: GenerationPool.ts:181

Handed to the factory. Cloned to each worker, so keep it flat and keep it small.

workerHeapSnapshotDirectory? ​

readonly optional workerHeapSnapshotDirectory?: string

Defined in: GenerationPool.ts:187

Optional directory where each worker writes one heap snapshot after its first task.

workerHeapStats? ​

readonly optional workerHeapStats?: SharedArrayBuffer

Defined in: GenerationPool.ts:183

Optional benchmark buffer: one shared heap-used byte count per worker after its last task.

workerStartupStats? ​

readonly optional workerStartupStats?: SharedArrayBuffer

Defined in: GenerationPool.ts:185

Optional benchmark buffer: a leading slot count, then first-task wall/CPU microseconds and heap bytes per worker.


GovernorSignal ​

Defined in: ConcurrencyGovernor.ts:34

What the server reports to the governor.

Properties ​

latenessMs ​

readonly latenessMs: number

Defined in: ConcurrencyGovernor.ts:36

How late the latest tick started, in milliseconds.

throttledDelta? ​

readonly optional throttledDelta?: number

Defined in: ConcurrencyGovernor.ts:38

How many times the control group was throttled since the previous signal, when known.


HostFlags ​

Defined in: GenerationPool.ts:347

What a thread was started with, which is what its workers inherit.

Properties ​

execArgv ​

readonly execArgv: readonly string[]

Defined in: GenerationPool.ts:349

process.execArgv.

nodeOptions ​

readonly nodeOptions: string

Defined in: GenerationPool.ts:351

NODE_OPTIONS, which Node applies to every thread of the process.


HostedGenerationPoolOptions ​

Defined in: HostedGenerationPool.ts:42

How a HostedGenerationPool is built.

Extends ​

Extended by ​

Properties ​

hostEntry? ​

readonly optional hostEntry?: string

Defined in: HostedGenerationPool.ts:52

The module the host runs. Defaults to this package's generationHost.

hostPriority? ​

readonly optional hostPriority?: number

Defined in: HostedGenerationPool.ts:48

The operating system priority to give the host, as os.setPriority takes it. Defaults to os.constants.priority.PRIORITY_LOW. Failing to set it is not an error: the host runs at the priority it started with.

inFlight? ​

readonly optional inFlight?: number

Defined in: GenerationPool.ts:250

How many tasks may be with the workers at once, which defaults to one more than there are workers.

Everything above this waits in the pool's own queue, where GenerationPriority still orders it; everything below it has already been handed to piscina, which dispatches in arrival order and cannot be re-ordered afterwards. So this is the trade: at the worker count exactly, a worker that finishes waits a microtask for its next task, and at a large multiple the bands stop meaning anything because the whole backlog is already downstream.

One spare is what keeps both: every worker has work, one task is staged behind them, and the worst a newly arrived immediate can wait is the one staged chunk.

Inherited from ​

GenerationPoolOptions.inFlight

maxRestarts? ​

readonly optional maxRestarts?: number

Defined in: HostedGenerationPool.ts:50

How many times a host that exits is replaced before the pool gives up on hosts. Defaults to 3.

now? ​

readonly optional now?: () => number

Defined in: GenerationPool.ts:252

The clock task timings are read from, in milliseconds. Defaults to performance.now; a test names its own.

Returns ​

number

Inherited from ​

GenerationPoolOptions.now

onFallback? ​

readonly optional onFallback?: (reason) => void

Defined in: HostedGenerationPool.ts:54

Told when the pool runs its tasks in process instead, and why.

Parameters ​
reason ​

string

Returns ​

void

onWorkerExit? ​

readonly optional onWorkerExit?: (threadId) => void

Defined in: GenerationPool.ts:236

Called with a worker thread ID after that worker exits, including pool shutdown.

Parameters ​
threadId ​

number

Returns ​

void

Inherited from ​

GenerationPoolOptions.onWorkerExit

pipeline ​

readonly pipeline: string

Defined in: GenerationPool.ts:204

The module each worker imports to get its status bodies.

A path or a file: URL, exporting createGenerationPipeline, a WorkerPipelineFactory. TypeScript is as good as JavaScript here: a worker thread inherits process.execArgv, so whatever loader the host was started with is already installed in the worker, and a host running under --import tsx hands its workers a loader that follows the extensionless @jsprismarine/* imports a dev checkout is full of. A host that reads TypeScript through its own loader instead, which is vitest, has no such flag to hand on, so the pool names the tsx beside the module itself; see workerExecArgv.

Inherited from ​

GenerationPoolOptions.pipeline

setup? ​

readonly optional setup?: unknown

Defined in: GenerationPool.ts:219

Handed to every worker's WorkerPipelineFactory.

Inherited from ​

GenerationPoolOptions.setup

worker? ​

readonly optional worker?: string

Defined in: GenerationPool.ts:209

The worker entry, which defaults to defaultGenerationWorker. A data: URL uses the embedded worker message protocol; file paths and URLs use piscina.

Inherited from ​

GenerationPoolOptions.worker

workerHeapSnapshotDirectory? ​

readonly optional workerHeapSnapshotDirectory?: string

Defined in: GenerationPool.ts:234

Optional diagnostics directory. Each worker writes one .heapsnapshot after its first completed task, so the snapshot contains the initialized pipeline and one task's result.

Inherited from ​

GenerationPoolOptions.workerHeapSnapshotDirectory

workerHeapStats? ​

readonly optional workerHeapStats?: SharedArrayBuffer

Defined in: GenerationPool.ts:224

Optional benchmark sink with one Int32 slot per worker plus a leading worker counter. Each worker stores its isolate heap usage in bytes after its most recent task.

Inherited from ​

GenerationPoolOptions.workerHeapStats

workers ​

readonly workers: number

Defined in: GenerationPool.ts:217

How many workers to start.

Five or six on this machine. Aggregate throughput peaks at 4.7 times one thread there and declines past six, because six of the eight cores are performance cores and each worker is a whole V8 isolate with its own garbage collector.

Inherited from ​

GenerationPoolOptions.workers

workerStartupStats? ​

readonly optional workerStartupStats?: SharedArrayBuffer

Defined in: GenerationPool.ts:229

Optional BigInt64Array sink with one leading worker counter and three slots per worker: first-task elapsed wall microseconds, thread CPU microseconds, and heap-used bytes.

Inherited from ​

GenerationPoolOptions.workerStartupStats


ShardedGenerationPoolOptions ​

Defined in: ShardedGenerationPool.ts:55

How a ShardedGenerationPool is built.

Extends ​

Properties ​

inFlight? ​

readonly optional inFlight?: number

Defined in: GenerationPool.ts:250

How many tasks may be with the workers at once, which defaults to one more than there are workers.

Everything above this waits in the pool's own queue, where GenerationPriority still orders it; everything below it has already been handed to piscina, which dispatches in arrival order and cannot be re-ordered afterwards. So this is the trade: at the worker count exactly, a worker that finishes waits a microtask for its next task, and at a large multiple the bands stop meaning anything because the whole backlog is already downstream.

One spare is what keeps both: every worker has work, one task is staged behind them, and the worst a newly arrived immediate can wait is the one staged chunk.

Inherited from ​

GenerationPoolOptions.inFlight

now? ​

readonly optional now?: () => number

Defined in: GenerationPool.ts:252

The clock task timings are read from, in milliseconds. Defaults to performance.now; a test names its own.

Returns ​

number

Inherited from ​

GenerationPoolOptions.now

onWorkerExit? ​

readonly optional onWorkerExit?: (threadId) => void

Defined in: GenerationPool.ts:236

Called with a worker thread ID after that worker exits, including pool shutdown.

Parameters ​
threadId ​

number

Returns ​

void

Inherited from ​

GenerationPoolOptions.onWorkerExit

pipeline ​

readonly pipeline: string

Defined in: GenerationPool.ts:204

The module each worker imports to get its status bodies.

A path or a file: URL, exporting createGenerationPipeline, a WorkerPipelineFactory. TypeScript is as good as JavaScript here: a worker thread inherits process.execArgv, so whatever loader the host was started with is already installed in the worker, and a host running under --import tsx hands its workers a loader that follows the extensionless @jsprismarine/* imports a dev checkout is full of. A host that reads TypeScript through its own loader instead, which is vitest, has no such flag to hand on, so the pool names the tsx beside the module itself; see workerExecArgv.

Inherited from ​

GenerationPoolOptions.pipeline

regionChunks? ​

readonly optional regionChunks?: number

Defined in: ShardedGenerationPool.ts:57

How wide one region is, in chunks. Defaults to DEFAULT_REGION_CHUNKS.

setup? ​

readonly optional setup?: unknown

Defined in: GenerationPool.ts:219

Handed to every worker's WorkerPipelineFactory.

Inherited from ​

GenerationPoolOptions.setup

stealAfter? ​

readonly optional stealAfter?: number

Defined in: ShardedGenerationPool.ts:64

How far behind a region's owner has to fall before its work is given away.

Defaults to DEFAULT_STEAL_AFTER. Zero sends every task to the least loaded worker, which is GenerationPool with extra steps.

worker? ​

readonly optional worker?: string

Defined in: GenerationPool.ts:209

The worker entry, which defaults to defaultGenerationWorker. A data: URL uses the embedded worker message protocol; file paths and URLs use piscina.

Inherited from ​

GenerationPoolOptions.worker

workerHeapSnapshotDirectory? ​

readonly optional workerHeapSnapshotDirectory?: string

Defined in: GenerationPool.ts:234

Optional diagnostics directory. Each worker writes one .heapsnapshot after its first completed task, so the snapshot contains the initialized pipeline and one task's result.

Inherited from ​

GenerationPoolOptions.workerHeapSnapshotDirectory

workerHeapStats? ​

readonly optional workerHeapStats?: SharedArrayBuffer

Defined in: GenerationPool.ts:224

Optional benchmark sink with one Int32 slot per worker plus a leading worker counter. Each worker stores its isolate heap usage in bytes after its most recent task.

Inherited from ​

GenerationPoolOptions.workerHeapStats

workers ​

readonly workers: number

Defined in: GenerationPool.ts:217

How many workers to start.

Five or six on this machine. Aggregate throughput peaks at 4.7 times one thread there and declines past six, because six of the eight cores are performance cores and each worker is a whole V8 isolate with its own garbage collector.

Inherited from ​

GenerationPoolOptions.workers

workerStartupStats? ​

readonly optional workerStartupStats?: SharedArrayBuffer

Defined in: GenerationPool.ts:229

Optional BigInt64Array sink with one leading worker counter and three slots per worker: first-task elapsed wall microseconds, thread CPU microseconds, and heap-used bytes.

Inherited from ​

GenerationPoolOptions.workerStartupStats


StagedChunk ​

Defined in: StagedChunk.ts:14

All a holder needs of the thing it drives up the ladder.

The package ships no chunk of its own: the holder, the map and the scheduler take the chunk type as a parameter, so a server climbs the ladder with the chunk buffer it already has rather than copying every block into a second representation twice per status. @jsprismarine/prismarine does exactly that: its generation stages speak Java block states with properties.

The contract is the whole of what the ladder relies on. A chunk knows which rung it is on, and it refuses to move to a rung at or below that one, because each (chunk, status) body runs once.

Properties ​

chunkX ​

readonly chunkX: number

Defined in: StagedChunk.ts:15

chunkZ ​

readonly chunkZ: number

Defined in: StagedChunk.ts:16

status ​

readonly status: "empty" | "structure_starts" | "structure_references" | "biomes" | "terrain" | "features" | "initialize_light" | "light" | "spawn" | "full"

Defined in: StagedChunk.ts:19

The status this chunk has reached.

Methods ​

advanceTo() ​

advanceTo(status): void

Defined in: StagedChunk.ts:26

Records that the chunk has reached a higher status.

Parameters ​
status ​

"empty" | "structure_starts" | "structure_references" | "biomes" | "terrain" | "features" | "initialize_light" | "light" | "spawn" | "full"

Returns ​

void

Throws ​

ChunkStatusRegressionError when the target is not above the current status.


WorkerPipeline ​

Defined in: GenerationPool.ts:158

The status bodies a pipeline module builds for one world.

Methods ​

run() ​

run(task): GenerationResult | Promise<GenerationResult>

Defined in: GenerationPool.ts:165

Runs one status body.

Parameters ​
task ​

GenerationTask

Returns ​

GenerationResult | Promise<GenerationResult>

Throws ​

Whatever the body throws. The pool reports it as a rejection on the task rather than leaving the caller waiting, which is the failure mode a pool has to get right.


WorkerTaskStats ​

Defined in: GenerationStats.ts:68

What a worker reports about one task it ran, in microseconds.

Properties ​

cpuUs ​

readonly cpuUs: number

Defined in: GenerationStats.ts:70

wallUs ​

readonly wallUs: number

Defined in: GenerationStats.ts:69

Type Aliases ​

ChunkStatus ​

ChunkStatus = typeof CHUNK_STATUSES[number]

Defined in: ChunkStatus.ts:26

One rung of the generation ladder. A chunk is at exactly one of these at any moment.


ChunkStepBody ​

ChunkStepBody<TChunk> = (chunk) => TChunk | Promise<TChunk>

Defined in: ChunkHolder.ts:13

Runs one status over a chunk and hands back the chunk at that status.

The holder supplies the chunk the status below left and takes whatever comes back, so a body that ran in a worker may return a chunk adopted from a transferred payload rather than the one it was given.

Type Parameters ​

TChunk ​

TChunk extends StagedChunk

Parameters ​

chunk ​

TChunk

Returns ​

TChunk | Promise<TChunk>


ChunkStorageKind ​

ChunkStorageKind = "proto_chunk" | "level_chunk"

Defined in: ChunkStatus.ts:29

The storage a chunk uses at a status: a proto chunk below full, a finished chunk at full.


FeaturePatchOffset ​

FeaturePatchOffset = typeof FEATURE_PATCH_ORDER[number]

Defined in: FeaturePatch.ts:28

One of the eight offsets in FEATURE_PATCH_ORDER.


GenerationHostMode ​

GenerationHostMode = "process" | "in-process"

Defined in: createGenerationTransport.ts:11

Where a transport's workers run.


GenerationPriority ​

GenerationPriority = typeof GENERATION_PRIORITIES[number]

Defined in: GenerationPool.ts:115

One of GENERATION_PRIORITIES.


NeighborReader ​

NeighborReader<TChunk> = (chunkX, chunkZ, status) => TChunk

Defined in: StepTasks.ts:11

Reads a neighbor's chunk, having already been told the read is inside the step's window.

The scheduler supplies this over its holder map. It raises ChunkNotReadyError when the chunk has not reached the status, which means a layer ran before the layer below it finished.

Type Parameters ​

TChunk ​

TChunk extends StagedChunk

Parameters ​

chunkX ​

number

chunkZ ​

number

status ​

ChunkStatus

Returns ​

TChunk


StepTask ​

StepTask<TChunk> = (region) => TChunk | Promise<TChunk>

Defined in: StepTasks.ts:76

One status's body: a pure function of the seed, the chunk position and the frozen outputs below.

It returns the chunk at the new status. Returning the chunk it was handed is the ordinary case; a body that ran in a worker returns one adopted from the payload that came back, which is why the return value is used rather than ignored. The holder records the new status, so a body should not call advanceTo itself.

Type Parameters ​

TChunk ​

TChunk extends StagedChunk

Parameters ​

region ​

StepRegion<TChunk>

Returns ​

TChunk | Promise<TChunk>


StepTasks ​

StepTasks<TChunk> = Partial<Readonly<Record<ChunkStatus, StepTask<TChunk>>>>

Defined in: StepTasks.ts:85

The bodies, by status. This is the seam the server's generation code plugs into.

A status with no entry passes its chunk through unchanged, which is what initialize_light, light and spawn do today and what every status above terrain does until slice 7. A pass-through still climbs the rung, so the accumulated radii and the retention stay Java's.

Type Parameters ​

TChunk ​

TChunk extends StagedChunk


TaskRunnerFactory ​

TaskRunnerFactory = (options) => TaskRunner

Defined in: GenerationPool.ts:281

Builds the task runner. Separated so a test can drive the pool without starting threads.

Parameters ​

options ​

GenerationPoolOptions

Returns ​

TaskRunner


WorkerPipelineFactory ​

WorkerPipelineFactory = (setup) => Promise<WorkerPipeline> | WorkerPipeline

Defined in: GenerationPool.ts:174

What a pipeline module exports.

Called once per worker, with the setup value the pool was built with. Everything expensive that depends only on the seed belongs inside it.

Parameters ​

setup ​

unknown

Returns ​

Promise<WorkerPipeline> | WorkerPipeline

Variables ​

CHUNK_STATUSES ​

const CHUNK_STATUSES: readonly ["empty", "structure_starts", "structure_references", "biomes", "terrain", "features", "initialize_light", "light", "spawn", "full"]

Defined in: ChunkStatus.ts:12

The ten chunk statuses Java Edition 26.3 registers, in registration order.

ChunkStatus's static initializer in the 26.3 server jar registers exactly these names, and each register(name, parent, ...) call sets index = parent.index + 1. The list is therefore a chain rather than a graph, which is what lets isOrAfter be an integer comparison.

26.3 has ten statuses, not the twelve older versions had. noise, surface and carvers were merged into one terrain status whose task runs noise fill, surface materials and carvers back to back.


DEFAULT_REGION_CHUNKS ​

const DEFAULT_REGION_CHUNKS: 8 = 8

Defined in: ShardedGenerationPool.ts:42

How wide one region is, in chunks.

Eight. A region of 64 chunks needs terrain for the 12 by 12 around it, so it builds 2.25 tiles per chunk against the one a single thread would; four would build 4 and sixteen 1.6. Against that, a 10 chunk view distance is 21 by 21, which falls across about nine regions - enough to keep six workers busy, which four hundred chunks in two regions would not.


DEFAULT_STEAL_AFTER ​

const DEFAULT_STEAL_AFTER: 2 = 2

Defined in: ShardedGenerationPool.ts:52

How much longer a worker's queue may be than the shortest before work is sent elsewhere.

Without a limit, one player exploring alone would keep one worker busy and five idle, because every chunk they walk into belongs to the same region. With it, the overflow goes to a worker that will have to build the neighborhood itself - slower per chunk, faster in total, and only once the owner is far enough behind for that to be true.


DURATION_BUCKET_BOUNDS_MS ​

const DURATION_BUCKET_BOUNDS_MS: readonly [1, 2, 5, 10, 20, 50, 100, 250, 1000]

Defined in: GenerationStats.ts:21

Upper bounds of the duration buckets, in milliseconds. A final bucket past the last bound holds everything longer. The 10 ms bound is deliberate: tasks longer than it are the ones that can make an arriving immediate task wait noticeably.


FEATURE_PATCH_ORDER ​

const FEATURE_PATCH_ORDER: readonly [readonly [-1, -1], readonly [0, -1], readonly [1, -1], readonly [-1, 0], readonly [1, 0], readonly [-1, 1], readonly [0, 1], readonly [1, 1]]

Defined in: FeaturePatch.ts:16

The eight neighbors a feature pass can reach, in the order their writes are merged.

(dx, dz) ascending with dx fastest, which is row major from the northwest corner. The order is the reason a chunk border is a function of the seed and the position: two features from different chunks that land on the same block always resolve the same way, whichever chunk was asked for first and however many were in flight.

Java has no such order. Its feature pass writes straight into the live neighbor through a WorldGenRegion, so which of two overlapping features wins depends on which chunk reached features first, which depends on scheduling. ADR 0002 takes the deviation deliberately and names its one cost: a feature that reads a block before placing sees the neighbor's terrain and not the neighbor's features, so two features can occupy the same space where Java would have refused the second.


GENERATION_PRIORITIES ​

const GENERATION_PRIORITIES: readonly ["immediate", "soon", "idle"]

Defined in: GenerationPool.ts:112

How badly a caller wants a chunk, highest first.

The pool holds back everything it is not already running, so this is the order the backlog is drained in rather than a hint. Three bands rather than a number, because the three are the three questions a server actually asks:

  • immediate: somebody is waiting. A player stood on it, or a command has to answer.
  • soon: it is wanted inside the next few seconds. The chunks a player is walking towards.
  • idle: it would be nice to have. The outer rim of a large view distance, a preload running behind a world that is already open.

GENERATION_PYRAMID ​

const GENERATION_PYRAMID: ChunkPyramid

Defined in: ChunkPyramid.ts:82

The pyramid a chunk climbs when it has to be generated rather than read from disk.


RADIUS_AROUND_FULL_CHUNK ​

const RADIUS_AROUND_FULL_CHUNK: number

Defined in: ChunkPyramid.ts:90

The widest ring a chunk reaching full drags in, which is 11, so a 23 by 23 neighborhood.

Java derives ChunkLevel.RADIUS_AROUND_FULL_CHUNK from the same place, and its MAX_LEVEL = 33 + 11 = 44 follows from it.


SAFETY_MARGIN_CHUNKS ​

const SAFETY_MARGIN_CHUNKS: number

Defined in: ChunkPyramid.ts:100

How far inside the world border generation has to stop, in chunks.

Java's ChunkPyramid.SAFETY_MARGIN_CHUNKS, (32 + accumulatedDependencies(full).size() + 1) * 2, which is 90 and is what MAX_CHUNK_COORDINATE_VALUE subtracts from the border. It is quoted here because it is an arithmetic check on the table: a transcription slip anywhere in the pyramid moves the accumulated length and therefore moves this number.

Functions ​

cgroupV2PathOf() ​

cgroupV2PathOf(procCgroup): string | undefined

Defined in: ConcurrencyGovernor.ts:148

The version 2 control group of a process, from the 0::$PATH line of /proc/$PID/cgroup.

Parameters ​

procCgroup ​

string

Returns ​

string | undefined


createGenerationTransport() ​

createGenerationTransport(options): BuiltGenerationTransport

Defined in: createGenerationTransport.ts:34

Builds the transport for a generation pool.

Parameters ​

options ​

GenerationTransportOptions

Returns ​

BuiltGenerationTransport

The transport and the mode it runs in. A host that starts and later cannot be kept alive is replaced by an in-process pool inside the transport, which reports it through options.onFallback.


decodeShared() ​

decodeShared(value): unknown

Defined in: hostProtocol.ts:82

The inverse of encodeShared: puts each copied buffer back into shared memory.

Parameters ​

value ​

unknown

Returns ​

unknown


defaultGenerationHost() ​

defaultGenerationHost(): string

Defined in: HostedGenerationPool.ts:70

This package's host entry, beside this file.

Returns ​

string


defaultGenerationWorker() ​

defaultGenerationWorker(): string

Defined in: GenerationPool.ts:298

This package's own worker entry, beside this file or embedded in a packaged executable.

.js in a built package and .ts in a dev checkout, which a worker thread can import either way because Node strips types. Single executables load their embedded worker from a data URL. Resolved rather than configured, so a caller does not have to know which is running.

Returns ​

string


encodeShared() ​

encodeShared(value): unknown

Defined in: hostProtocol.ts:69

Replaces every SharedArrayBuffer in a value with a copy of its bytes.

Shared memory cannot be sent to another process. The value may nest buffers in plain objects, arrays and maps, which is what a pipeline's setup looks like. Anything else passes through.

Parameters ​

value ​

unknown

Returns ​

unknown


indexOfStatus() ​

indexOfStatus(status): number

Defined in: ChunkStatus.ts:50

The position of a status on the ladder, with empty at 0 and full at 9.

This is Java's ChunkStatus.getIndex(), and it is the only ordering this package uses.

Parameters ​

status ​

"empty" | "structure_starts" | "structure_references" | "biomes" | "terrain" | "features" | "initialize_light" | "light" | "spawn" | "full"

Returns ​

number

Throws ​

UnknownChunkStatusError when the value is not one of the ten statuses.


isChunkStatus() ​

isChunkStatus(value): value is "empty" | "structure_starts" | "structure_references" | "biomes" | "terrain" | "features" | "initialize_light" | "light" | "spawn" | "full"

Defined in: ChunkStatus.ts:68

Narrows an unvalidated value, such as a persisted status read back from disk.

Parameters ​

value ​

unknown

Returns ​

value is "empty" | "structure_starts" | "structure_references" | "biomes" | "terrain" | "features" | "initialize_light" | "light" | "spawn" | "full"


isOrAfter() ​

isOrAfter(status, other): boolean

Defined in: ChunkStatus.ts:76

True when status is other or any status above it.

Parameters ​

status ​

"empty" | "structure_starts" | "structure_references" | "biomes" | "terrain" | "features" | "initialize_light" | "light" | "spawn" | "full"

other ​

"empty" | "structure_starts" | "structure_references" | "biomes" | "terrain" | "features" | "initialize_light" | "light" | "spawn" | "full"

Returns ​

boolean


isOrBefore() ​

isOrBefore(status, other): boolean

Defined in: ChunkStatus.ts:80

True when status is other or any status below it.

Parameters ​

status ​

"empty" | "structure_starts" | "structure_references" | "biomes" | "terrain" | "features" | "initialize_light" | "light" | "spawn" | "full"

other ​

"empty" | "structure_starts" | "structure_references" | "biomes" | "terrain" | "features" | "initialize_light" | "light" | "spawn" | "full"

Returns ​

boolean


maxStatus() ​

maxStatus(a, b): "empty" | "structure_starts" | "structure_references" | "biomes" | "terrain" | "features" | "initialize_light" | "light" | "spawn" | "full"

Defined in: ChunkStatus.ts:84

The higher of two statuses. This is how the step builder merges overlapping requirements.

Parameters ​

a ​

"empty" | "structure_starts" | "structure_references" | "biomes" | "terrain" | "features" | "initialize_light" | "light" | "spawn" | "full"

b ​

"empty" | "structure_starts" | "structure_references" | "biomes" | "terrain" | "features" | "initialize_light" | "light" | "spawn" | "full"

Returns ​

"empty" | "structure_starts" | "structure_references" | "biomes" | "terrain" | "features" | "initialize_light" | "light" | "spawn" | "full"


mergeGenerationStats() ​

mergeGenerationStats(snapshots): GenerationStatsSnapshot

Defined in: GenerationStats.ts:169

Adds snapshots together, so a pool made of shards reports as one.

Parameters ​

snapshots ​

readonly GenerationStatsSnapshot[]

Returns ​

GenerationStatsSnapshot


parentOfStatus() ​

parentOfStatus(status): "empty" | "structure_starts" | "structure_references" | "biomes" | "terrain" | "features" | "initialize_light" | "light" | "spawn" | "full" | undefined

Defined in: ChunkStatus.ts:72

The status a chunk must have reached before this one can run, or undefined for empty.

Parameters ​

status ​

"empty" | "structure_starts" | "structure_references" | "biomes" | "terrain" | "features" | "initialize_light" | "light" | "spawn" | "full"

Returns ​

"empty" | "structure_starts" | "structure_references" | "biomes" | "terrain" | "features" | "initialize_light" | "light" | "spawn" | "full" | undefined


parseCpuMax() ​

parseCpuMax(text): CpuMax | undefined

Defined in: ConcurrencyGovernor.ts:136

Reads cpu.max, whose format is $MAX $PERIOD with max standing for no limit and the period defaulting to 100000 microseconds.

Parameters ​

text ​

string

Returns ​

CpuMax | undefined


parseCpuStat() ​

parseCpuStat(text): CpuThrottleStat | undefined

Defined in: ConcurrencyGovernor.ts:112

Reads the throttle counters out of a cpu.stat file.

Both layouts are flat keyed files of KEY VALUE lines. Version 2 reports throttled_usec in microseconds (cgroup-v2); version 1 reports throttled_time in nanoseconds (sched-bwc). A group with no CPU controller has none of the three keys.

Parameters ​

text ​

string

Returns ​

CpuThrottleStat | undefined

The counters, or undefined when the file has no throttle keys.


shareLongerThan() ​

shareLongerThan(duration, boundMs): number

Defined in: GenerationStats.ts:197

The share of a duration's samples longer than a bucket bound, or 0 with no samples.

Parameters ​

duration ​

DurationSummary

boundMs ​

1 | 2 | 5 | 10 | 20 | 50 | 100 | 250 | 1000

Returns ​

number


statusAtIndex() ​

statusAtIndex(index): "empty" | "structure_starts" | "structure_references" | "biomes" | "terrain" | "features" | "initialize_light" | "light" | "spawn" | "full"

Defined in: ChunkStatus.ts:61

The status at a ladder position, for walking the ladder by index.

Parameters ​

index ​

number

Returns ​

"empty" | "structure_starts" | "structure_references" | "biomes" | "terrain" | "features" | "initialize_light" | "light" | "spawn" | "full"

Throws ​

UnknownChunkStatusError when no status sits at that index.


storageKindOf() ​

storageKindOf(status): ChunkStorageKind

Defined in: ChunkStatus.ts:92

Which storage a chunk at this status lives in.

Every status below full operates on a proto chunk. full promotes it, reusing the same section storage rather than copying it.

Parameters ​

status ​

"empty" | "structure_starts" | "structure_references" | "biomes" | "terrain" | "features" | "initialize_light" | "light" | "spawn" | "full"

Returns ​

ChunkStorageKind


workerExecArgv() ​

workerExecArgv(options, host?): string[] | undefined

Defined in: GenerationPool.ts:532

The flags the workers start with, or undefined when inheriting this thread's is right.

A worker thread is a second module loader and reads the pipeline off disk through Node's own resolution. It inherits process.execArgv, so a host started with --import tsx hands its workers the loader that follows a dev checkout's extensionless imports, and a built package needs none. A host whose own loader is not Node's has nothing to hand on: under vitest this thread reads TypeScript through Vite while a worker would read it through Node's strip-only loader, which stops at the first extensionless relative import and rejects the parameter properties and enums the source uses anyway. So when the pipeline or the worker entry is TypeScript source and nothing in the host's flags installs a loader, the workers get the tsx the pipeline's own package declares.

Parameters ​

options ​

Pick<GenerationPoolOptions, "pipeline" | "worker">

The pipeline module and the worker entry.

host? ​

HostFlags = ...

This thread's flags. Defaults to the process's; a test names its own.

Returns ​

string[] | undefined

The worker flags, or undefined to inherit.