How we ported a world
Our server world, Schnopzo-Bashi, grew for years on All of Fabric 7 (Fabric, Minecraft 1.20.1). We wanted to play on in All the Mods 10 (NeoForge, Minecraft 1.21.1) without leaving anything we built behind. Different loader, different Minecraft version, and more than a hundred of our mods simply don't exist in the new pack. This is how we moved it, and why Tinfoil exists.
The short version: move only what players built, rewrite every id offline before the new game ever sees it, give every block without a home a purpose-made replacement, and turn the seams between old and new terrain into a feature.
1. Find out what was built
The world had 423,742 chunks over 11 dimensions (5.6 GB). Players had built in 1,122 of them, about a quarter of a percent. A census scanned every chunk once and flagged it as player-built when it had been inhabited for a while and contained blocks that never generate naturally (indicator blocks: furniture, machines, crafted building blocks). The flagged chunks fell into nine clusters: the main base (over a thousand chunks), a few outposts, a nether portal hub, two space-station chunks, a moon base and a small train station in a mining dimension (the one cluster left behind).
Each cluster was padded by two chunks (paths and farms on the edges), holes inside were filled, and the result was reviewed on rendered maps. The masks are plain files in the repository, so the whole pipeline can be re-run on a fresh backup.
2. Why chunks, not schematics
Copying chunks keeps everything at once: block positions, biomes, block entities (chests, machines, signs), entities (item frames, armour stands, pets) and lighting hints. Schematics only stay as a fallback for the one base whose dimension doesn't exist in the new pack; see dimensions.
3. Rewrite every id before the game sees it
NeoForge replaces unknown block ids with air when it loads a chunk, and then saves that. So the conversion has to be complete before the new game touches a chunk. Our porter (Python, no game needed) rewrites the chunks offline, one mapping table per kind:
| table | rule |
|---|---|
| blocks | keep blockstate properties (facing, half, shape, axis, waterlogged); stairs stay stairs, slabs stay slabs |
| items | same table where block items match; tools and materials go to the new pack's equivalents |
| biomes | per palette entry; biomes of mods that are gone are mapped by climate and look |
| block entities | contents move along; anything unmappable is sealed in a relic cache with its original data |
| entities | item frames, armour stands, paintings kept; mod mobs and glue dropped |
Every block that was placed by a player and has no exact match got a row, in order of preference: the same id (mods that exist in both packs), a faithful block from the new pack with the same shape and material, or a Tinfoil block designed for that family. Low-confidence guesses ("any slab becomes a stone-brick slab") were never accepted. Around 420 player-placed blocks had no good substitute anywhere; they became Tinfoil's block families and decor.
Nothing is thrown away silently. Items that can't be mapped become relic artifacts that remember the original id and data, and containers become relic caches. An admin can read them later and hand out fair replacements.
4. A safety net in the mod
Whatever the offline pass might miss, Tinfoil carries the same tables as legacy ids: registry aliases from old ids to new ones. A chunk or item with an old id loads as its replacement instead of air. That is why the server pack is the new modpack plus Tinfoil and nothing else. /tinfoil scan compares the loaded chunks with what the porter expected and reports any block that went missing; the target is zero.
5. Make the seams the feature
The old terrain and the new terrain come from different world generators; they will never line up. Instead of hiding the step, every imported base sits on a fold: a plateau or basin with layered cliffs where the land looks like it buckled around the base, with waterfalls pouring over the edges, plunge pools, mist, and ruins reclaimed by greenery. Megalith stone shows in the cliff bands: something was buried here.
The folds are built in three layers: vanilla's own old-chunk blending on the outer ring, pre-generation of the new terrain around each base, then Tinfoil's fold, falls and overgrowth passes. They never write inside a base, can be previewed with particles and can be undone. The details are in folds. The same generators can run as optional worldgen elsewhere (Ancient Islands), so the folds look like part of the land rather than scars of a port.
6. Players come along
Inventories and ender chests go through the item table, advancements and statistics are copied. Waystone networks, land claims, homes and trinket slots are left behind: some things just get lost to time, and the old server stays live. Players whose last position was in a dimension that no longer exists wake up at the world spawn.
7. Rehearse
One command runs the whole conversion (remap, blend, players, report) and is deterministic, so it can be repeated on any later backup. The result is loaded into a copy of the real modpack, scanned, folded and walked through cluster by cluster. The old server stays live; the ported world is a new home next to it, not a replacement.
Status: the conversion pipeline and the mod side are done; the first full rehearsal in the real pack is next, and its results go into the compatibility report.
What we'd tell anyone attempting the same
- Count first. A census of what was really built shrinks the problem from hundreds of thousands of chunks to about a thousand.
- Convert offline and refuse to lose anything: a strict mode that fails on any unmapped id is worth more than any in-game fixer.
- Keep the data you can't place (relic caches and artifacts) instead of guessing.
- Give the replacements a reason to exist. A themed mod makes a hundred "missing block" decisions into one design.
- Embrace the seam.