Skip to main content

A high-performance Minecraft schematic parser and utility library

Project description

Nucleation for Python

PyPI

Python bindings for Nucleation, a high-performance Minecraft schematic engine. Read, edit, build, simulate, and mesh .schematic, .litematic, .nbt, and .mcstructure files — at native speed.

The core is written in Rust and compiled to a CPython extension via PyO3 (abi3-py38), so a single wheel works on every CPython 3.8+ on your platform — no Rust toolchain required to install.


Install

pip install nucleation

Pre-built wheels are published for:

  • Linux x86_64 and aarch64
  • macOS x86_64 (Intel) and arm64 (Apple Silicon)
  • Windows x86_64

If your platform isn't covered, pip will fall back to the source distribution and build locally (requires a Rust toolchain).


Quick start

from nucleation import Schematic, sign, text

# Three explicit constructors (legacy `Schematic("file.schem")` still works):
schem = Schematic.open("example.litematic")        # load from disk
fresh = Schematic.new("my_schematic")              # blank
templ = Schematic.from_template("ab\ncd")          # ASCII template

# Polished set_block: tuple coords, structured state and NBT, chainable.
schem.set_block((0, 0, 0), "minecraft:repeater",
                state={"delay": 4, "facing": "east"})
schem.set_block((0, 1, 0), "minecraft:oak_sign",
                state={"rotation": 8},
                nbt=sign([text("Hello", color="gold"), "world"]))

# Format inferred from extension.
schem.save("out.litematic")

Hot loops

For placing many blocks, prefer the batch and fast-path APIs:

# 30+ M placements/sec — one native call.
schem.set_blocks([(x, 0, 0) for x in range(1_000_000)], "minecraft:stone")

# 10+ M placements/sec — pre-resolve once, place by index.
stone = schem.prepare_block("minecraft:stone")
place = schem.place
for x, y, z in positions:
    place(x, y, z, stone)

Tile-entity helpers

from nucleation import Schematic, chest, sign, text, Item

schem = Schematic.new("loot_room")

schem.set_block((0, 0, 0), "minecraft:chest",
                state={"facing": "north"},
                nbt=chest([
                    Item("minecraft:diamond", count=64),
                    Item("minecraft:elytra"),
                ]))

schem.set_block((0, 1, 0), "minecraft:oak_sign",
                nbt=sign([text("Loot", color="gold"), "this way →"]))

For lossless, fully-typed reads/writes (64-bit NBT, item components), use the SNBT accessors: get_block_entity_snbt(x, y, z) / set_block_entity(x, y, z, id, snbt) and get_entities_snbt() / add_entity_from_snbt(snbt).

Version conversion (datafixers)

Convert block / block-entity / item / entity data between Minecraft data versions — a Rust port of PaperMC's DataConverter. Forward conversion is lossless; down-converting to an older version returns a JSON loss report so you can warn before saving. Importers capture the source data version (set it manually for versionless formats; classic .schematic1343).

import json

schem = Schematic.open("modern.litematic")
print(schem.get_source_data_version())              # e.g. 3953 (1.21)
print(Schematic.canonical_data_version())           # 4790 (in-memory target)

# Save a copy for 1.16.5 (data version 2586); schem itself is untouched.
data, loss = schem.to_litematic_for_version(2586)
report = json.loads(loss)                            # [] when lossless
for e in report:                                    # {version, kind, severity, path, detail}
    print(f"[{e['severity']}] {e['path']}: {e['detail']}")

# Or convert in place using the captured source version:
loss = schem.convert_to_version(Schematic.canonical_data_version())

Remote storage

Schematic.open and schem.save work transparently against remote backends — no extra object, no manual byte-shuffling. The same calls you use for local files take a scheme'd URI or an explicit Store:

from nucleation import Schematic, Store

# local file (unchanged)
schem = Schematic.open("build.schem")
schem.save("build.litematic")

# transparent remote: a scheme'd URI, no Store object needed
schem = Schematic.open("s3://my-bucket/builds/adder.schem")
schem.save("s3://my-bucket/out/adder.schem")
schem.save("file:///tmp/adder.litematic")   # file:// = local path

# explicit Store + key: works for ANY backend (incl. redis/postgres)
# and reuses a single connection
store = Store.open("redis://localhost:6379")
schem = Schematic.open(store, "builds/adder.schem")
schem.save(store, "out/adder.schem")

The format is inferred from the key/path extension (.schem, .litematic, .mcstructure); pass format="litematic" etc. to save to override it.

The single-string form works for path-like backends — s3://bucket/key (and file:// → local). redis:// and postgres:// single-strings raise ValueError, because their URL path is the database, leaving no slot for the key; open those with an explicit store instead: Schematic.open(Store.open(url), key).

Which backends are reachable depends on the store-* features the extension was built with. The default wheel ships mem:// + file://; for S3/Redis/Postgres rebuild it:

maturin develop --features python,store-s3,store-redis,store-pg

Raw byte store. When you want raw bytes rather than schematics — PNG renders, arbitrary artifacts — use the Store class directly (get/put/exists/delete/list/health).


Diff & Fingerprint

Canonically fingerprint a build, dedup near-duplicates, and compute a structural diff between two builds — all under a configurable equivalence ruleset chosen by preset name:

  • exact — material- and orientation-sensitive (identical blockstates only).
  • shape — occupancy only; palette and orientation ignored.
  • structural — functional shape, rotation- and material-agnostic.
  • redstone_computational (alias redstone) — redstone-logic equivalence, rotation-agnostic, cosmetic-material-agnostic.
  • redstone_survival — like redstone, but keeps survival material constraints.

diff additionally accepts opt-in overrides: per-edit cost weights (cost_add / cost_delete / cost_change / cost_swap) and a symmetry group.

from nucleation import Schematic

a = Schematic.open("a.litematic")
b = Schematic.open("b.litematic")

# 32-hex canonical hash (rotation/translation/palette-agnostic per preset).
print(a.fingerprint("structural"))

# Cheap exact-equivalence dedup, and fuzzy FFT shape distance (0.0 == same shape).
if a.is_duplicate_of(b, "structural"):
    print("duplicate build")
print("footprint distance:", a.footprint_distance(b, "structural"))

# Dims + token histogram as JSON.
print(a.signature("structural"))

# Structural diff (optionally pass cost_*/symmetry overrides).
d = a.diff(b, "redstone")
print("distance:", d.distance())
# support = fraction of cells that aligned: (matched+changed+swapped)/max(|A|,|B|).
# Edited/re-paletted cells count as aligned; only added/removed are unaligned, so
# a pure re-palette scores 1.0. Alignment confidence, NOT a similarity %.
print("support:", d.support())

# Each delta as its own Schematic.
d.added(); d.removed(); d.changed(); d.swapped(); d.markers()

# Lossless JSON round-trips via Diff.from_json; summary_json() is compact.
from nucleation import Diff
full = d.to_json()
restored = Diff.from_json(full)
print(d.summary_json())

The glowing-overlay GLB requires the meshing feature in your wheel:

# `after_glb` is the meshed "after" build (bytes); returns a new GLB.
glb = d.to_overlay_glb(after_glb)
with open("diff_overlay.glb", "wb") as f:
    f.write(glb)

Documentation

Full reference, including simulation, meshing, and resource-pack rendering, lives in the main repository:


Why Rust?

Nucleation's core is shared across Rust, WebAssembly/JS, Python, and C/PHP — one engine, one set of behaviour, one set of tests. The Python package you install is the same engine that powers the JS and Rust libraries; you get native throughput for free.

License

MIT. See the main repository for details.

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nucleation-0.2.18.tar.gz (5.6 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

nucleation-0.2.18-cp38-abi3-win_amd64.whl (6.9 MB view details)

Uploaded CPython 3.8+Windows x86-64

nucleation-0.2.18-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.1 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ x86-64

nucleation-0.2.18-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (7.1 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ ARM64

nucleation-0.2.18-cp38-abi3-macosx_11_0_arm64.whl (6.0 MB view details)

Uploaded CPython 3.8+macOS 11.0+ ARM64

nucleation-0.2.18-cp38-abi3-macosx_10_12_x86_64.whl (6.4 MB view details)

Uploaded CPython 3.8+macOS 10.12+ x86-64

File details

Details for the file nucleation-0.2.18.tar.gz.

File metadata

  • Download URL: nucleation-0.2.18.tar.gz
  • Upload date:
  • Size: 5.6 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for nucleation-0.2.18.tar.gz
Algorithm Hash digest
SHA256 cca51097491e706297eecc2813b171c17ba24340ed4299590b4ebddd7b73226b
MD5 f1c55e19aee946fd4084748cf48fe0ee
BLAKE2b-256 682c3c311d30a080ab8c3642ecbe25975854e5ea8b3a33a8abc0112e63df9872

See more details on using hashes here.

File details

Details for the file nucleation-0.2.18-cp38-abi3-win_amd64.whl.

File metadata

  • Download URL: nucleation-0.2.18-cp38-abi3-win_amd64.whl
  • Upload date:
  • Size: 6.9 MB
  • Tags: CPython 3.8+, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for nucleation-0.2.18-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 a40ef23dcd17e11729fdbfaefad8a1aa8bda5adca02d1e0a45251dc6b0650900
MD5 7aa19e8ef424face36ace8bdcca56efa
BLAKE2b-256 d303c06f168be793b410ca26a17ced317b025d25837b8f3d73cf5a7c268ed08f

See more details on using hashes here.

File details

Details for the file nucleation-0.2.18-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for nucleation-0.2.18-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 dc1c871400865cd0b7d5e28c086866ccdb52b1a6a71cc1587fd60feac2682be7
MD5 03137c7ab323335a960afc04c5fd7e55
BLAKE2b-256 8e49556aa1357917bb46b829117b9853e2088235352cfd58acf60e34c75e94e5

See more details on using hashes here.

File details

Details for the file nucleation-0.2.18-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for nucleation-0.2.18-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 cf7b6fae8307b6b6d8810abf8e6a7aada767f9fd8a55247d63afb73070b55a2e
MD5 aa081b1cbe6837b17ac2994438c3cd23
BLAKE2b-256 e638f757e55011308eda5cfaf6712b48500de7452bb23ee8de5c5bcaf1a1357a

See more details on using hashes here.

File details

Details for the file nucleation-0.2.18-cp38-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for nucleation-0.2.18-cp38-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 90f3a46dbae3e32345180785dde1a936b99b4452b54bb40090147a8b29ca1d5a
MD5 38c90a6c2ee354806cf742d4ec7341c0
BLAKE2b-256 5a7f76fdd7a52e95eb4e85711f0c064b41f351674a36dab6f00c193b56f8e295

See more details on using hashes here.

File details

Details for the file nucleation-0.2.18-cp38-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for nucleation-0.2.18-cp38-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 528b0fce3eed3da18cbe80f7b86c3d446ead97ebc3db17c2445793fd0f7027d0
MD5 c58e5a1a05da147bd6b6e90a024a00c3
BLAKE2b-256 4c5712366d330964859b2403ae6b79609b34240016a3ecee672604dadde19b9e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page