FOUNDATION 01 · WORLD GENERATION

The untouched world is a reproducible answer

Give one implementation of the current world algorithm the same canonical seed, bounds, and integer coordinate, and it returns the same base block. Chunk.js draws terrain locally, while the chunk program independently calculates the protocol block it expects when an action needs verification.

7 min read
The villager girl places a seed cube into a coordinate compass while the villager boy compares a generated grass block and records a mined coordinate separately; identical terrain echoes appear across the lattice.

Key points

Same question, same answer

The generators use integer coordinates and fixed integer-style hashing, so each implementation can recalculate an untouched location without accepting the player's claimed block as fact.

Changes are another layer

A mined coordinate is recorded separately. It does not rewrite the formula that defines the original terrain around it.

Trees are spatial structures

Trunks and leaves occupy many voxel coordinates, so trees remain part of the canonical spatial generator rather than the one-face decoration table.

THE MENTAL MODEL

A coordinate is a question to the world

Imagine asking, “What was originally at x, y, z?” In the browser, Chunk.js normalizes the configured seed into 32 bytes and applies the configured canonical bounds. The current Rust program instead uses its own fixed canonical seed, chunk size, build bounds, terrain limit, and sea level rather than reading terrain parameters from the legacy Core account.

Chunk.js builds terrain and fluid arrays for nearby chunks, then generates tree instances separately. Its getBlockAt() query is the complete coordinate answer because it resolves terrain, water, and eligible tree voxels together. The chunk program has an independent Rust implementation that calculates the protocol result used for action checks.

Location unit Integer voxel

Mining verification addresses one exact x, y, z block coordinate.

Current chunk width 16 × 16

Chunk coordinates and local coordinates are converted back into world coordinates.

Base result Block ID

The program recalculates the expected block type before accepting a mine.

HOW IT STAYS REPRODUCIBLE

Seeded integer arithmetic replaces a hidden dice roll

The Chunk.js world engine normalizes the seed to bytes, hashes those bytes with coordinate values and purpose-specific salts, and interpolates fixed-range noise values. A salt lets terrain height, moisture, trees, and other layers use distinct repeatable number streams.

Chunk.js carries a generationVersion field through its configuration, but the current generator does not select alternate algorithms from it. The existing wide golden suite exercises the legacy browser generator and a JavaScript protocol mirror; it neither imports Chunk.js nor runs Rust. The chunk program independently implements fixed canonical constants and block logic, so JavaScript-to-Rust equality is an intended protocol invariant, not a property the current tests directly prove.

  1. Normalize the world input

    In the browser, normalize the configured seed into 32 bytes and apply the canonical bounds. On chain, the current Rust program substitutes the fixed canonical seed and bounds instead of reading terrain values from the legacy Core account.

  2. Hash the location

    Hash the coordinate components needed by each layer. Two-dimensional terrain noise uses x and z with a fixed y component of zero, while ore, tree, and other volume decisions include height where required.

  3. Build the column

    Use repeatable terrain factors to find surface and water levels, then resolve the block at the requested height.

  4. Check stable fixtures

    Golden tests sample wide coordinate ranges in the legacy browser generator and a JavaScript protocol mirror. They can expose changes in those paths, but they are not a direct Chunk.js-to-Rust comparison.

STATE LAYERS

The base answer and the player's edit are kept apart

When a mine is accepted, the program records a compact coordinate in the ChunkBroken PDA for that chunk. The base generator can still say which block originally belonged there; the delta says that this specific block has already been removed.

The play client reads chunk PDAs in batches, decodes their mined-coordinate lists, and applies those deltas over generated terrain. That is why a shared world can preserve player edits without storing a full second copy of every untouched chunk.

  • Base terrain answers what originally exists at a coordinate.
  • ChunkBroken answers which generated coordinates have been mined.
  • The backpack records accepted rewards instead of trusting a local inventory animation.
  • Foundation and building systems keep their own state; they are not implied by the terrain formula.

WHY TREES ARE DIFFERENT

A tree is one generated structure across many blocks

A tree can cross chunk edges and fill a trunk plus a canopy of leaf voxels. The generator therefore derives the tree candidate, height, type, and occupied volume from its spatial rules, then answers every affected coordinate consistently.

Trees are the only natural decoration family resolved by canonical spatial generation. Plants, flowers, shrubs, cactus models, moss, lichen, mushrooms, and pebbles must be resolved from a fetched and valid SurfaceDecorationTable PDA and bound to their supporting terrain face. When no valid table is installed, those non-tree surface decorations remain disabled.

IMPLEMENTATION BOUNDARY

Reproducibility belongs to one implementation; parity needs a direct test

The equations separate two claims that are easy to confuse. A fixed implementation can reproduce its own answer, while agreement between Chunk.js and Rust remains a protocol invariant that must be exercised across both implementations.

Determinism inside one implementation

B_impl(p) = G_impl(S, p, C), where p = (x, y, z) in Z^3

For one fixed implementation, the same 32-byte seed, integer coordinate, and canonical constants produce the same base-block answer. This equation does not by itself prove that two independent implementations agree.

B_impl(p)
The base block returned by one particular generator implementation at coordinate p.
G_impl
One fixed JavaScript or Rust world-generation implementation.
S
The normalized 32-byte world seed used by that implementation.
p
An integer voxel coordinate in three-dimensional space.
C
The chunk size, build bounds, sea level, terrain limit, and other canonical constants.

Cross-implementation parity requirement

Parity(P) = true iff for every p in P: G_JS(S, p, C) = G_Rust(S, p, C)

Parity is established only for coordinates exercised by a fixture that runs both implementations with the same canonical inputs. The current golden suite imports neither Chunk.js nor Rust, so this remains a protocol requirement rather than a property those tests directly prove.

P
The set of coordinates covered by a direct cross-language parity fixture.
G_JS
The Chunk.js coordinate query under canonical inputs.
G_Rust
The chunk program's independent Rust calculation under the corresponding canonical inputs.

Chunk.js normalizes the coordinate query

JavaScript chunk.js/world/world-generator.js
export function getBlockAt(worldSeed, worldX, worldY, worldZ, ruleVersion = DEFAULT_GENERATION_VERSION, options = {}) {
  const config = createWorldGeneratorConfig({ ...options, worldSeed, generationVersion: ruleVersion });
  const x = Math.trunc(worldX);
  const y = Math.trunc(worldY);
  const z = Math.trunc(worldZ);
  return blockAtConfig(config, x, y, z);
}

The public query converts every component to an integer and resolves terrain, fluid, and eligible generated-tree voxels through the complete coordinate path. The generationVersion field is carried in the configuration, but the current generator does not use it to select a different algorithm.

Rust rejects a mismatched generated block

Rust programs/nicechunk_chunk/src/lib.rs
    let surface = generated_surface_height(global_config_view, args.world_x, args.world_z);
    let block_id = generated_block_id_at_surface(global_config_view, &generated_args, surface);
    if args.expected_block_id != block_id {
        return Err(NicechunkChunkError::GeneratedBlockMismatch.into());
    }

The chunk program independently recalculates the block ID and rejects the action when the player's expected block does not match its result.

IMPLEMENTATION EVIDENCE

Where these claims come from

Each claim is intentionally scoped to a concrete implementation path. These references are for verification, not decoration.

chunk.js/world/world-generator.js

Defines the current seeded chunk generator, canonical defaults, terrain profiles, water, and generated tree instances.

chunk.js/core/hash.js

Implements seed normalization, coordinate hashing, and fixed-range noise interpolation used by the shared engine.

programs/nicechunk_chunk/src/state.rs

Contains the chunk program's canonical block, surface, water, tree, and coordinate calculations plus compact ChunkBroken state.

programs/nicechunk_chunk/src/lib.rs

Recalculates the generated block during mining and records accepted mined coordinates and backpack rewards.

play/play-chain-chunk-deltas.js

Fetches, validates, decodes, caches, and incrementally applies ChunkBroken PDA snapshots to the rendered world.

tests/worldgen_golden.ts

Pins representative and wide-range results from the legacy JavaScript generation paths; it is compatibility evidence, not a direct Chunk.js-to-Rust parity proof.