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.
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 trueThe 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.
| Step | d=0 | d=1 | d=2 | d=3..8 |
|---|---|---|---|---|
empty | outside the window | |||
structure_starts | empty | outside | ||
structure_references | structure_starts | structure_starts | structure_starts | structure_starts |
biomes | structure_references | structure_starts | structure_starts | structure_starts |
terrain | biomes | biomes | structure_starts | structure_starts |
features | terrain | terrain | structure_starts | structure_starts |
initialize_light | features | outside | ||
light | initialize_light | initialize_light | outside | |
spawn | light | biomes | outside | |
full | spawn | features | outside |
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.
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.
inbound.receive(-1, 0, patchFromTheWest);
inbound.inMergeOrder(); // ordered by position, not by when each arrivedThe 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.
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 --saveClasses
- CgroupThrottleSampler
- ChunkDependencies
- ChunkHolder
- ChunkHolderMap
- ChunkNotReadyError
- ChunkPyramid
- ChunkReadOutOfWindowError
- ChunkStatusRegressionError
- ChunkStep
- ChunkStepBuilder
- ChunkStepOutOfOrderError
- ConcurrencyGovernor
- DuplicateFeaturePatchError
- FeaturePatchOutOfRangeError
- GenerationCanceledError
- GenerationPool
- GenerationPoolClosedError
- GenerationScheduler
- GenerationStatsRecorder
- HostedGenerationPool
- InboundFeaturePatches
- MissingGenerationLayerError
- ShardedGenerationPool
- StepRegion
- UnknownChunkStatusError
Interfaces
BuiltGenerationTransport
Defined in: createGenerationTransport.ts:20
What was built, and why when it is not what was asked for.
Properties
mode
readonlymode:GenerationHostMode
Defined in: createGenerationTransport.ts:22
reason?
readonlyoptionalreason?:string
Defined in: createGenerationTransport.ts:24
Why the host was not used, when the caller asked for it.
transport
readonlytransport: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?
readonlyoptionaldecrease?:number
Defined in: ConcurrencyGovernor.ts:28
What the limit is multiplied by on pressure. Defaults to 0.5.
holdMs?
readonlyoptionalholdMs?:number
Defined in: ConcurrencyGovernor.ts:30
After pressure, how long before the limit may rise again, in milliseconds. Defaults to 2000.
initial?
readonlyoptionalinitial?: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?
readonlyoptionallateMs?:number
Defined in: ConcurrencyGovernor.ts:24
A tick later than this counts as pressure, in milliseconds. Defaults to 25, half a tick.
max
readonlymax:number
Defined in: ConcurrencyGovernor.ts:18
The most background tasks ever allowed at once: the number of workers.
min?
readonlyoptionalmin?:number
Defined in: ConcurrencyGovernor.ts:20
The fewest allowed. Defaults to 1, so background work always makes some progress.
raiseEveryMs?
readonlyoptionalraiseEveryMs?: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
readonlyperiodUsec:number
Defined in: ConcurrencyGovernor.ts:129
quotaUsec
readonlyquotaUsec: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
readonlynrPeriods:number
Defined in: ConcurrencyGovernor.ts:95
nrThrottled
readonlynrThrottled:number
Defined in: ConcurrencyGovernor.ts:96
throttledUsec
readonlythrottledUsec: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
readonlybuckets: readonlynumber[]
Defined in: GenerationStats.ts:29
One count per DURATION_BUCKET_BOUNDS_MS bound, then one for everything longer.
count
readonlycount:number
Defined in: GenerationStats.ts:25
maxMs
readonlymaxMs:number
Defined in: GenerationStats.ts:27
totalMs
readonlytotalMs:number
Defined in: GenerationStats.ts:26
GenerationPoolOptions
Defined in: GenerationPool.ts:191
How a GenerationPool is built.
Extended by
Properties
inFlight?
readonlyoptionalinFlight?: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?
readonlyoptionalnow?: () =>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?
readonlyoptionalonWorkerExit?: (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
readonlypipeline: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?
readonlyoptionalsetup?:unknown
Defined in: GenerationPool.ts:219
Handed to every worker's WorkerPipelineFactory.
worker?
readonlyoptionalworker?: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?
readonlyoptionalworkerHeapSnapshotDirectory?: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?
readonlyoptionalworkerHeapStats?: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
readonlyworkers: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?
readonlyoptionalworkerStartupStats?: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
readonlypayload:unknown
Defined in: GenerationPool.ts:147
The chunk, flattened into something postMessage moves rather than copies.
transferList
readonlytransferList: readonlyArrayBuffer[]
Defined in: GenerationPool.ts:149
Every ArrayBuffer in the payload, so it is transferred rather than cloned.
workerStats?
readonlyoptionalworkerStats?: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
readonlyholders:ChunkHolderMap<TChunk>
Defined in: GenerationScheduler.ts:16
Where holders live and how long they live, shared by every run on this scheduler.
pyramid?
readonlyoptionalpyramid?:ChunkPyramid
Defined in: GenerationScheduler.ts:20
Defaults to GENERATION_PYRAMID, the table a chunk climbs when it must be generated.
tasks
readonlytasks: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
readonlybyTask: readonlyGenerationTaskStats[]
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
readonlychunkX:number
Defined in: GenerationPool.ts:121
chunkZ
readonlychunkZ:number
Defined in: GenerationPool.ts:122
dimension
readonlydimension: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?
readonlyoptionalinput?: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
readonlystatus:"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
readonlybacklogWaitMs:number
Defined in: GenerationStats.ts:60
failed
readonlyfailed:boolean
Defined in: GenerationStats.ts:59
priority
readonlypriority:"immediate"|"soon"|"idle"
Defined in: GenerationStats.ts:58
status
readonlystatus:"empty"|"structure_starts"|"structure_references"|"biomes"|"terrain"|"features"|"initialize_light"|"light"|"spawn"|"full"
Defined in: GenerationStats.ts:57
turnaroundMs
readonlyturnaroundMs:number
Defined in: GenerationStats.ts:61
workerCpuMs?
readonlyoptionalworkerCpuMs?:number
Defined in: GenerationStats.ts:64
workerWallMs?
readonlyoptionalworkerWallMs?: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
readonlybacklogWait:DurationSummary
Defined in: GenerationStats.ts:41
Time in the pool's backlog before a worker slot was free.
failed
readonlyfailed:number
Defined in: GenerationStats.ts:39
Tasks that settled with an error.
priority
readonlypriority:"immediate"|"soon"|"idle"
Defined in: GenerationStats.ts:35
status
readonlystatus:"empty"|"structure_starts"|"structure_references"|"biomes"|"terrain"|"features"|"initialize_light"|"light"|"spawn"|"full"
Defined in: GenerationStats.ts:34
tasks
readonlytasks:number
Defined in: GenerationStats.ts:37
Tasks that settled, successfully or not.
turnaround
readonlyturnaround:DurationSummary
Defined in: GenerationStats.ts:43
From leaving the backlog to the result arriving on this thread.
workerCpu
readonlyworkerCpu:DurationSummary
Defined in: GenerationStats.ts:47
Thread CPU time inside the worker, in the same sense as workerWall.
workerWall
readonlyworkerWall: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
readonlyinFlight:number
Defined in: GenerationTransport.ts:17
How many tasks the workers are holding right now.
queued
readonlyqueued:number
Defined in: GenerationTransport.ts:19
How many tasks are waiting for a worker.
workers
readonlyworkers: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
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
GenerationTransportOptions
Defined in: createGenerationTransport.ts:14
How createGenerationTransport chooses.
Extends
Properties
host
readonlyhost:GenerationHostMode
Defined in: createGenerationTransport.ts:16
process asks for a host and falls back when one cannot start; in-process never forks.
hostEntry?
readonlyoptionalhostEntry?:string
Defined in: HostedGenerationPool.ts:52
The module the host runs. Defaults to this package's generationHost.
Inherited from
HostedGenerationPoolOptions.hostEntry
hostPriority?
readonlyoptionalhostPriority?: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?
readonlyoptionalinFlight?: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?
readonlyoptionalmaxRestarts?: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?
readonlyoptionalnow?: () =>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?
readonlyoptionalonFallback?: (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?
readonlyoptionalonWorkerExit?: (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
readonlypipeline: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?
readonlyoptionalsetup?:unknown
Defined in: GenerationPool.ts:219
Handed to every worker's WorkerPipelineFactory.
Inherited from
HostedGenerationPoolOptions.setup
worker?
readonlyoptionalworker?: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?
readonlyoptionalworkerHeapSnapshotDirectory?: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?
readonlyoptionalworkerHeapStats?: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
readonlyworkers: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?
readonlyoptionalworkerStartupStats?: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
readonlypipeline:string
Defined in: GenerationPool.ts:179
The module specifier a worker imports to get its WorkerPipelineFactory.
setup
readonlysetup:unknown
Defined in: GenerationPool.ts:181
Handed to the factory. Cloned to each worker, so keep it flat and keep it small.
workerHeapSnapshotDirectory?
readonlyoptionalworkerHeapSnapshotDirectory?:string
Defined in: GenerationPool.ts:187
Optional directory where each worker writes one heap snapshot after its first task.
workerHeapStats?
readonlyoptionalworkerHeapStats?:SharedArrayBuffer
Defined in: GenerationPool.ts:183
Optional benchmark buffer: one shared heap-used byte count per worker after its last task.
workerStartupStats?
readonlyoptionalworkerStartupStats?: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
readonlylatenessMs:number
Defined in: ConcurrencyGovernor.ts:36
How late the latest tick started, in milliseconds.
throttledDelta?
readonlyoptionalthrottledDelta?: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
readonlyexecArgv: readonlystring[]
Defined in: GenerationPool.ts:349
process.execArgv.
nodeOptions
readonlynodeOptions: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?
readonlyoptionalhostEntry?:string
Defined in: HostedGenerationPool.ts:52
The module the host runs. Defaults to this package's generationHost.
hostPriority?
readonlyoptionalhostPriority?: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?
readonlyoptionalinFlight?: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?
readonlyoptionalmaxRestarts?: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?
readonlyoptionalnow?: () =>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
onFallback?
readonlyoptionalonFallback?: (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?
readonlyoptionalonWorkerExit?: (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
readonlypipeline: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?
readonlyoptionalsetup?:unknown
Defined in: GenerationPool.ts:219
Handed to every worker's WorkerPipelineFactory.
Inherited from
worker?
readonlyoptionalworker?: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
workerHeapSnapshotDirectory?
readonlyoptionalworkerHeapSnapshotDirectory?: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?
readonlyoptionalworkerHeapStats?: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
readonlyworkers: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
workerStartupStats?
readonlyoptionalworkerStartupStats?: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?
readonlyoptionalinFlight?: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?
readonlyoptionalnow?: () =>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
onWorkerExit?
readonlyoptionalonWorkerExit?: (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
readonlypipeline: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?
readonlyoptionalregionChunks?:number
Defined in: ShardedGenerationPool.ts:57
How wide one region is, in chunks. Defaults to DEFAULT_REGION_CHUNKS.
setup?
readonlyoptionalsetup?:unknown
Defined in: GenerationPool.ts:219
Handed to every worker's WorkerPipelineFactory.
Inherited from
stealAfter?
readonlyoptionalstealAfter?: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?
readonlyoptionalworker?: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
workerHeapSnapshotDirectory?
readonlyoptionalworkerHeapSnapshotDirectory?: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?
readonlyoptionalworkerHeapStats?: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
readonlyworkers: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
workerStartupStats?
readonlyoptionalworkerStartupStats?: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
readonlychunkX:number
Defined in: StagedChunk.ts:15
chunkZ
readonlychunkZ:number
Defined in: StagedChunk.ts:16
status
readonlystatus:"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
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
readonlycpuUs:number
Defined in: GenerationStats.ts:70
wallUs
readonlywallUs: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
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
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
constCHUNK_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
constDEFAULT_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
constDEFAULT_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
constDURATION_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
constFEATURE_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
constGENERATION_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
constGENERATION_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
constRADIUS_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
constSAFETY_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
Returns
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
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
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
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.