- Java 83.8%
- Shell 14.6%
- Python 1.6%
|
All checks were successful
Build / build (push) Successful in 30s
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> |
||
|---|---|---|
| .forgejo/workflows | ||
| gradle | ||
| scripts | ||
| src | ||
| test-harness | ||
| .gitignore | ||
| build.gradle.kts | ||
| CHANGELOG.md | ||
| DISK_USAGE.md | ||
| gradlew | ||
| gradlew.bat | ||
| HANDOFF.md | ||
| icon.png | ||
| README.md | ||
| SERVUX_WIRE_FORMAT.md | ||
| settings.gradle.kts | ||
| TUTORIAL.md | ||
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.
First Paper/Folia plugin to natively parse and paste
.litematic. Replaces the legacy Litematica/setblock+/fillfallback (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:
- Reads
.litematicfiles server-side via an inline NBT parser (no external dep) - Pastes them via Folia's
RegionSchedulerper-chunk dispatch — observers-last, deferred-physics, full TE and entity NBT - 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
.litematicv6/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
/fillspam (validated againstlitematica-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|cancelwith 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_SYNCis named so misleadingly: Litematica'sEntitiesDataStorage.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
- Open Litematica menu (
Mby default) - Load Schematics → pick your
.litematic - Loaded Schematics → Create Placement → position it
- Hold the Litematica tool item (a stick — set via Tool Item hotkey)
- Tool Mode: Paste Schematic in world (cycle if needed)
- Aim at the placement and press your
executeOperationkeybind
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 saveis blocks-only in v0.3.0. The TileEntity / Entity / PendingTick capture path is wired but the per-chunkgetBlockStatereturns 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
sliceForServuxthreshold 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
UseItemOnpackets requires PacketEvents 2.7+ which fails to parse Luminol's*.local-SNAPSHOTversion string. Code is there, enable at your own risk. - FAWE ClipboardFormat adapter is stubbed. The
mvn.intellectualsites.comrepo 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.
Links
- Source
- Issue tracker
- Releases
- Modrinth (once published)