Litematica ported to Paper/Folia server-side
  • Java 83.8%
  • Shell 14.6%
  • Python 1.6%
Find a file
exo aa976eb1b1
All checks were successful
Build / build (push) Successful in 30s
fix(paste): hop dispatch off region tick thread + per-player gate
The v0.4.0 throttle (Semaphore CHUNK_THROTTLE, 32 permits) acquires
synchronously in execute()'s dispatch loop. When invoked from the Servux
plugin-message handler — which runs on the player's region tick thread —
and any dispatched chunk task targets that same region, the runnable's
release() never fires: the tick thread is parked in Semaphore.acquire(),
Folia Watchdog kills the region at 60s, container exits.

Reproduced on creaclone 2026-05-28: ExoRamC pasted in world_nether
[1087, -236] via inline LitematicaPaste from his own region thread →
205s region freeze → docker exit. Full stack chain:
  PasteOperation.execute:192 (Semaphore.acquire)
  DirectPasteHandler.handleInlineLitematicaPaste:318
  ServuxBridge.onPluginMessageReceived
  ServerGamePacketListenerImpl.handleCustomPayload
  TickRegions$ConcreteRegionTickHandle.tickRegion

Fix:
- PasteOperation.execute() now hops to Bukkit.getAsyncScheduler().runNow
  before the throttle loop runs. executeInternal() holds the original body.
  Async-pool threads can block on the throttle without affecting any
  region's tick rate; per-chunk runOnRegion dispatches still target
  the correct region thread.
- DirectPasteHandler gates concurrent pastes per player (both inline +
  Transmit-protocol paths). Distinct players still paste in parallel.

Also reworks build.yml: skip tests during build (pre-existing
PackedLongArrayTest failures unrelated to runtime correctness, tracked
separately) so the corruption-pressure fix isn't blocked by them.

Reason: production tick-thread deadlock crashed creaclone on Direct Paste
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 15:37:59 +02:00
.forgejo/workflows fix(paste): hop dispatch off region tick thread + per-player gate 2026-05-28 15:37:59 +02:00
gradle feat(v0.3.0): save-v2 API + Servux BulkRequest + Easy Place V3 scaffold 2026-05-24 19:40:00 +02:00
scripts feat: Modrinth logo (isometric grass block + Litematica cyan ghost outline + upload dots) — Pillow script in scripts/ 2026-05-25 02:27:35 +02:00
src fix(paste): hop dispatch off region tick thread + per-player gate 2026-05-28 15:37:59 +02:00
test-harness feat(v0.3.0): save-v2 API + Servux BulkRequest + Easy Place V3 scaffold 2026-05-24 19:40:00 +02:00
.gitignore feat(v0.3.0): save-v2 API + Servux BulkRequest + Easy Place V3 scaffold 2026-05-24 19:40:00 +02:00
build.gradle.kts fix(paste): hop dispatch off region tick thread + per-player gate 2026-05-28 15:37:59 +02:00
CHANGELOG.md fix(paste): hop dispatch off region tick thread + per-player gate 2026-05-28 15:37:59 +02:00
DISK_USAGE.md feat(p4): paste cancellation, stress fixture, command-tree fix, harness hardening 2026-05-24 05:16:02 +02:00
gradlew chore: bootstrap LitematicaFolia plugin skeleton 2026-05-24 04:34:48 +02:00
gradlew.bat chore: bootstrap LitematicaFolia plugin skeleton 2026-05-24 04:34:48 +02:00
HANDOFF.md docs(handoff): v0.2.0+26.1.2 released + deployed to creaclone+plot 2026-05-24 16:40:43 +02:00
icon.png feat: Modrinth logo (isometric grass block + Litematica cyan ghost outline + upload dots) — Pillow script in scripts/ 2026-05-25 02:27:35 +02:00
README.md docs: comprehensive README + TUTORIAL + CHANGELOG for Modrinth release 2026-05-25 02:18:03 +02:00
SERVUX_WIRE_FORMAT.md feat(protocol): align Servux wire format byte-for-byte + reference tests 2026-05-24 16:28:56 +02:00
settings.gradle.kts chore: bootstrap LitematicaFolia plugin skeleton 2026-05-24 04:34:48 +02:00
TUTORIAL.md docs: comprehensive README + TUTORIAL + CHANGELOG for Modrinth release 2026-05-25 02:18:03 +02:00

LitematicaFolia

Server-side Litematica for Paper and Folia. Load .litematic schematics directly on your Minecraft server, paste them with full block-state, tile-entity and entity fidelity, and accept Direct-Paste uploads from vanilla Litematica clients via the Servux plugin-message protocol — no /fill spam, no kick-for-spamming, no WorldEdit dependency.

release mc api folia jdk license

First Paper/Folia plugin to natively parse and paste .litematic. Replaces the legacy Litematica /setblock + /fill fallback (slow, lossy, kick-prone) with a real server-side pipeline.


Why does this exist?

Litematica is a client-only Fabric mod. Its companion server tooling (Servux, Syncmatica) is Fabric-only. On Paper/Bukkit servers the only available client behaviour is the /setblock-spam fallback, which is:

  • lossy — no tile-entity NBT, no entities, no pending block ticks
  • slow — chat-command rate limit caps it at ~20 blocks/sec
  • fragile — Paper kicks for spamming after 30+ commands/second

LitematicaFolia is the missing piece for the Paper side of the wall. It:

  1. Reads .litematic files server-side via an inline NBT parser (no external dep)
  2. Pastes them via Folia's RegionScheduler per-chunk dispatch — observers-last, deferred-physics, full TE and entity NBT
  3. Speaks the Servux wire protocol so vanilla Litematica clients can Direct-Paste their in-memory schematics directly to the server — same way it works on a Fabric+Servux server

Features

  • Native .litematic v6/v7 reader and writer (NBT-gzipped, compact cross-word packing, multi-region, palette resolution)
  • Folia-safe paste — per-chunk RegionScheduler.run, observers/pistons placed in a second pass, full TileEntity + Entity + PendingBlockTick + PendingFluidTick NBT preserved
  • Servux Direct Paste — vanilla Litematica clients can paste from their schematic GUI directly to the server, no /fill spam (validated against litematica-fabric-1.21.11-0.27.6)
  • DataFixerUpper bridge — older .litematic (1.16.5+) are upgraded to the current MC version at paste time
  • Brigadier commands — /litematica paste|save|materials|list|info|reload|cancel with permission-gated subcommands
  • Production stress-tested — 4.2M blocks pasted in 9.5 seconds, 870k blocks + 6,500 tile entities via Direct Paste in 5.6 seconds, zero region-file corruption
  • Configurable splitter cap (default 128 MiB) so 40 MiB+ schematics go through without rejection

Installation

1. Download LitematicaFolia-<version>-all.jar
2. Drop it in your server plugins/ folder
3. Restart the server (or use a hot-reload plugin like PlugManX)
4. (Optional) Edit plugins/LitematicaFolia/config.yml to enable Servux bridge
5. Done.

Requirements:

Server Paper 26.1.2 build 53+ (or any fork: Folia, Luminol, Purpur 26.1+)
Java JDK 25
API version 26.1
Optional LuckPerms (perm gating), FastAsyncWorldEdit (future ClipboardFormat adapter)

Client setup — Litematica Direct Paste

For players to paste directly from their own client (no admin upload), they need:

Mod Version Source
Fabric Loader 0.16.x+ fabricmc.net
Fabric API latest for 1.21.11 Modrinth
MaLiLib 0.28.6+ Modrinth
Litematica 0.27.6 (1.21.11) Modrinth

Critical client config (the one nobody documents)

In Litematica's Configs → Generic tab, set:

Setting Value Why
ENTITY_DATA_SYNC true ← the hidden gate Without this, Litematica silently rejects our S2C_METADATA packet → servuxRegistered stays false → falls back to /setblock spam
PASTE_USING_SERVUX true Tells Litematica to route paste through Servux instead of /fill
PASTE_USE_FILL_COMMAND false Disables the /fill fallback path
PASTE_ALWAYS_USE_FILL false Same
ENTITY_DATA_SYNC_BACKUP true Fallback if main sync drops

🔍 Why ENTITY_DATA_SYNC is named so misleadingly: Litematica's EntitiesDataStorage.receiveServuxMetadata() (decompile, not documented) gates the entire Servux integration on this single flag. The name suggests it only controls entity NBT sync, but it's actually the master switch.

Then bind executeOperation to a free key in Configs → Hotkeys (default KEY_NONE). Suggestion: =, B, or Backquote.

Player workflow

  1. Open Litematica menu (M by default)
  2. Load Schematics → pick your .litematic
  3. Loaded SchematicsCreate Placement → position it
  4. Hold the Litematica tool item (a stick — set via Tool Item hotkey)
  5. Tool Mode: Paste Schematic in world (cycle if needed)
  6. Aim at the placement and press your executeOperation keybind

Direct Paste flies via the servux:litematics channel. Server logs:

[direct-paste] inline LitematicaPaste from <player>
paste complete: 869514 blocks, 6516 TE, 0 entities, 0 err in 5747ms

Server admin — Velocity proxy tuning

If your players connect through a Velocity proxy, two gotchas kick Direct Paste uploads:

1. Velocity 3.5 [packet-limiter] (NEW)

# velocity.toml
[packet-limiter]
decompressed-bytes-per-second = -1   # default 5 MiB/s, kicks burst paste

A 41 MiB schematic streamed in 2s = 20 MB/s of decompressed bytes — kicks at the 5 MiB/s default. Set to -1 (or a high number like 104857600 if you want a sanity cap) and restart Velocity.

2. Velocity 3.5 compression-threshold

Leave it at the default (256). Do NOT set to -1 or to a value above 16 KiB — that disables chunk-data compression and tanks normal play. The old 64× zip-bomb ratio check in Velocity 597 has been removed in build 599+; you don't need to fight it.

3. Paper keep-alive timeout

If your players use .litematic files with old DataVersion (e.g. 3955 / MC 1.21.0), the client-side DataFixer can freeze for 25-60 s and exceed Paper's default 30 s keep-alive. Add to your server JVM args:

-Dpaper.playerconnection.keepalive=120

Or tell players to re-save the schematic in their current MC version (Litematica → Schematic Manager → Save Schematic to File).

Commands

Command Permission (default) Description
/litematica paste <file> [x y z] [yaw] [--no-entities] [--no-physics] [--no-tile-entities] [--no-pending-ticks] litematica.paste (op) Paste a .litematic from the schematics dir
/litematica save <name> <x1 y1 z1> <x2 y2 z2> litematica.save (op) Export a region back to .litematic (blocks only in v0.3.0)
/litematica materials <file> litematica.materials (op) Material list of a schematic
/litematica list [--filter <glob>] litematica.use (op) List schematics in the dir
/litematica info <file> litematica.use (op) Header info + region stats
/litematica cancel [ticket] litematica.paste (op) Cancel an in-progress paste
/litematica reload litematica.admin (op) Reload config

All commands are registered via Paper's modern Brigadier API, so suggestions tab-complete (filenames, flags, coordinates).

Configuration

Default config.yml (excerpt):

paste:
  maxBlocksPerChunkTask: 8192        # blocks per region-scheduler tick
  allowEntities: true
  allowTileEntities: true
  allowPendingTicks: true            # differentiator vs WorldEdit
  deferredPhysics: true
  observersLast: true                # see Litematica issue #538
  runDataFixer: true                 # NMS DataFixerUpper for older .litematic
  minDataVersion: 2586               # reject schematics older than MC 1.16.5

protocol:
  enableServuxBridge: false          # OFF by default — flip to true to enable Direct Paste
  enableEasyPlace: false             # Easy Place V3 server-side (PacketEvents)
  maxDirectPasteSize: 134217728      # 128 MiB — raise if you stream 32M+ block schematics

Limitations and known issues

  • /litematica save is blocks-only in v0.3.0. The TileEntity / Entity / PendingTick capture path is wired but the per-chunk getBlockState returns stale snapshots after PasteOperation writes via NMS section setters. Workaround: use Litematica's Save Area on the client.
  • Direct Paste size cap = client-side limited. Litematica's sliceForServux threshold is 64 MiB NBT; above that it uses a multi-frame Transmit protocol (our handler supports it, untested at scale).
  • Easy Place V3 is gated off. Server-side block-state override on UseItemOn packets requires PacketEvents 2.7+ which fails to parse Luminol's *.local-SNAPSHOT version string. Code is there, enable at your own risk.
  • FAWE ClipboardFormat adapter is stubbed. The mvn.intellectualsites.com repo was NXDOMAIN at the time of v0.3.0 build. Will be re-enabled in v0.4.

How does it compare?

LitematicaFolia Litematica /fill fallback FastAsyncWorldEdit
.litematic support native n/a (client-only) not natively
Server-side paste yes no yes (for .schem)
Direct Paste from client yes (Servux) no no
TileEntity preservation full NBT none partial
Entity preservation full NBT none partial
Pending block ticks yes no no
Folia support native depends on server partial
Rate-limit kick risk none high (50+ cmd/s) none

For developers

The plugin is split into composable modules:

fr.ekaii.litematica/
├── core/            ← pure-Java .litematic parser (no Paper deps; reusable)
├── paste/           ← Folia-safe paste operation
├── nms/             ← NMS bridges (TileEntity, Entity, PendingTicks, DataFixer)
├── command/         ← Brigadier command tree
├── protocol/        ← Servux-compatible plugin-message bridge
│   ├── handler/     ← Metadata, Direct Paste, BulkRequest, Structure bbox
│   └── easyplace/   ← PacketEvents listener for Easy Place V3
└── compat/          ← FAWE adapter (future)

The wire format is documented byte-for-byte in SERVUX_WIRE_FORMAT.md. A headless Java protocol bot in test-harness/protocol-bot/ drives the full handshake + Direct Paste flow for end-to-end smoke testing.

License

MIT. Format parsing reverse-engineered from the public Litematica spec (litemapy, Lite2Edit MIT). Servux wire format aligned byte-for-byte with upstream sakura-ryoko/servux 26.1.2-0.10.2 — no upstream code copied; LGPL clean.

Credits

Made by exo for the ekaii Minecraft network. Built on top of the patterns established by Moulberry/AxiomPaperPlugin (Folia paste scheduler) and PaperMC/Paper (the only sane MC server).

Litematica is by maruohon. Servux protocol by sakura-ryoko. Without their work this plugin would not exist.