Nucleation
Nucleation is a high-performance Minecraft schematic engine written in Rust, with generated bindings for C, C++, JavaScript/TypeScript (WASM), Kotlin/JVM, Python, and PHP.
What it does
- Schematic formats: read and write
.litematic, Sponge.schem, WorldEdit.schematic, Bedrock.mcstructure, structure.nbt, and a fast binary snapshot format (.nusn), with format auto-detection. - World import and export: parse whole worlds (Anvil
.mcaregion files, zipped or on-disk world folders, optionally bounded to a coordinate box) into a schematic, and export schematics back out as playable worlds. A streaming API processes worlds chunk by chunk in constant memory. - Cross-version conversion: convert block, block-entity, item, and entity data between Minecraft data versions (a Rust port of PaperMC's DataConverter), with loss reports on lossy down-converts.
- Schematic building: a template system for building schematics from ASCII or Unicode layer art, a procedural building tool (spheres, cuboids, cylinders, bezier curves, and more, filled by solid, gradient, or shaded brushes), and SDF-based shape and terrain generation.
- Redstone simulation: tick circuits headlessly via MCHPRS, inject and read signals at arbitrary positions, and drive circuits through a typed executor with named, typed inputs and outputs (booleans, integers, floats, ASCII).
- Meshing and rendering: turn schematics into GLB/glTF or USDZ meshes using any resource pack, and render PNG previews on the GPU, headlessly.
- Diffing and fingerprinting: structural diffs between schematics (added, removed, changed, swapped views), translation-invariant fingerprints, signatures, and duplicate detection.
- Auto-stack: detect the repeating lattice in a build and re-stamp it to a new size, for example a 4-bit adder to 8-bit, or a 32x32 screen to 64x64.
- Storage: a pluggable byte store (in-memory, filesystem, and S3, Redis, or Postgres behind feature flags) for moving schematics and renders around with a single URI.
- Embedded scripting: generate schematics from Lua or JavaScript scripts.
- Block database: a vendored copy of blockpedia (
nucleation::blockpedia) — Minecraft block facts with texture-derived colors, palette and gradient generation, block-state queries and transforms, and Java-Bedrock blockstate and block-entity translation via Geyser mappings.
One API, seven languages
Since v0.3.0 every language binding is generated from a single annotated-Rust source of truth
(src/bridge/) using Diplomat. The bindings are
committed under bindings/, regenerated and diffed in CI so they can never go stale, and every
language exposes the same types and methods with per-language casing and idioms:
| Language | Package | Errors | Naming |
|---|---|---|---|
| Rust | nucleation crate (native API) |
Result |
snake_case |
| C | Release archive (include/ + library) |
result structs | Schematic_set_block |
| C++ | Release archive (header-only over C ABI) | diplomat::result |
set_block |
| JavaScript | npm install nucleation |
exceptions | setBlock |
| Kotlin/JVM | Release JAR (JNA) | kotlin.Result |
setBlock |
| Python | pip install nucleation |
exceptions | set_block |
| PHP | Release archive (php/ + FFI) |
DiplomatError |
setBlock |
Installation
# Rust
# JavaScript / TypeScript (Node >= 18 or a bundler)
# Python (CPython 3.12+)
For C, C++, Kotlin, and PHP, download the platform archive or JAR from Releases, or build locally:
What ships in the published packages
Published artifacts (npm, PyPI, release archives, JAR) contain the core feature set: schematics, formats, world import/export and streaming, builder, building tool, definition regions, diff/fingerprint, autostack, NBT helpers, SDF, and the in-memory/filesystem store.
Meshing, rendering, simulation, and scripting are compiled in when you build the native library
yourself with --features bridge-full (or any subset, for example --features bridge,simulation).
Simulation and meshing also work on WASM. See the per-language docs for details.
Quick start
Rust
use UniversalSchematic;
JavaScript
import from "nucleation";
const schematic = ;
schematic.;
console.log; // "minecraft:stone"
// Serialize to litematic bytes (base64 across the WASM boundary)
const bytes = Uint8Array.;
const loaded = ;
Python
=
# "minecraft:stone"
=
Kotlin
import at.schem.nucleation.*
val schematic = Schematic.create("demo")
schematic.setBlock(1, 2, 3, "minecraft:stone").getOrThrow()
println(schematic.getBlockName(1, 2, 3).getOrThrow()) // "minecraft:stone"
PHP
C
int
Documentation
Full documentation lives in docs/:
- Documentation index
- Per-language references: Rust, JavaScript, Python, Kotlin, PHP, C, C++
- Feature guides (concepts, data models, and JSON schemas shared by all bindings)
Development
# Regenerate the committed bindings from src/bridge/ (requires the diplomat-tool fork)
# End-to-end smoke tests for the generated bindings
CI regenerates the bindings and fails on any diff, checks coverage of the full pre-0.3.0 FFI surface, and runs the smoke tests on every push.
Minecraft block data
The block database (formerly the standalone blockpedia crate) lives in-tree at
src/blockpedia/. Its data ships as gzipped snapshots in data/blockpedia/ — currently pinned
to Minecraft 26.2 (Java block states from Mojang's own data generator, official block
semantics — kind/base-block/tags/full-cube geometry, Bedrock block states, Geyser blockstate
mappings, and a color cache derived from the vanilla texture pack) — and build.rs bakes them
into static PHF tables at compile time. Normal builds never touch the network.
To refresh the Java data for a new Minecraft version (needs a JRE new enough for the server
jar on PATH; MC 26.x wants Java 25+):
# 1. Vanilla report converter: downloads the server jar, runs Mojang's data
# generator (--reports), and rebuilds prismarinejs_blocks.json.gz — the
# report is authoritative for the block list, properties and state ids;
# enrichment fields (transparency, hardness, light, ...) carry forward
# from the previous snapshot, and blocks new in the version are enriched
# from an analogue block or a model-shape heuristic over the client jar
# (the run prints the added/removed diff and every derived fact).
# Also rebuilds block_semantics.json.gz from official data only:
# - kind + base block: the report's definition.type / definition.base_state
# (stairs), plus a model-texture linkage for the other shape variants
# (oak_slab renders with block/oak_planks, owned by oak_planks)
# - tags: every data/minecraft/tags/block/** tag from the server jar's
# inner (bundler) jar, nested #tag refs resolved
# - full_cube: blockstate models root in a cube-family template or carry
# a full 16x16x16 element
# These drive BlockFacts::{kind, base_block, has_tag, is_full_cube},
# blocks_by_tag/variants_of, and the BlockFilter/only_solid classifiers
# (which no longer guess from name substrings).
# 2. Texture colors: downloads the client jar, extracts block textures,
# regenerates color_cache.json.gz (alpha-weighted averages + biome tints).
Both tools take the version as an optional trailing arg (-- 26.2) and default to the
manifest's latest release, so a routine bump needs no code edits. A normal cargo build
afterwards bakes the new tables in.
The PrismarineJS blocks.json schema is kept as the on-disk format (PrismarineJS itself has
no 26.x data). tests/blockpedia_data_refresh.rs guards data currency.
The refresh is also automated: .github/workflows/data-refresh.yml runs weekly (and on
manual dispatch, optionally with an explicit version), compares the version manifest's
latest.release against data/blockpedia/DATA_VERSION (a plain-text marker
refresh-block-data rewrites on every run), and — when Mojang has shipped a new release —
regenerates the snapshots and opens/updates a PR on data-refresh/<version>. The PR body
carries the added/removed-block diff, file size deltas, and color coverage. Two failure
modes are tolerated by design: refresh-bedrock-mappings may fail while GeyserMC's
mappings lag the Java release (noted in the PR, previous mappings kept), and cargo test
may fail because new blocks need human test updates (the PR is still opened, marked
failing, with the failure tail).
Java ↔ Bedrock mappings
-
geyser_mappings.json.gz— regenerated from GeyserMC/mappings (blocks.nbt@efe0f2c, "Mappings for Minecraft Java 26.2"). GeyserMC retired the oldmappings-generatorJSON dumps; the canonical data is now gzipped NBT: abedrock_mappingslist with one compound per Java blockstate in runtime state-id order (java side implicit by index;bedrock_identifierabsent ⇒ same name as Java,stateabsent ⇒ bedrock default state).refresh-bedrock-mappingsconverts that back into the JSON schemabuild.rsconsumes, reconstructing the java side fromprismarinejs_blocks.json.gz(state-id enumeration validated 32,366/32,366 against the vanilla 26.2 report). All 32,366 Java 26.2 states are mapped (was 29,671 at the 1.21.x pin; all carried-over entries identical, +2,695 gained, none lost), so the identity fallback for unmapped blocks is currently unused: -
bedrock_block_states.json.gz— PrismarineJSdata/bedrock/1.26.30/blockStates.jsongzipped verbatim (content-identical to the previous snapshot; the per-stateversionfield1.21.60.33is Bedrock's state-format version, which hasn't bumped since — the palette content is current and includes the 26.x cinnabar/sulfur blocks). Everybedrock_identifieremitted by the mappings exists in this palette.
License
MIT. See LICENSE.