This is a good one. As someone who has been writing tooling for interfacing with the game for several years, the flaws of how the game stores its level data stick out all the time.
History
Back before The Nether was added, in 2010, the game stored the Overworld in the level’s root folder, as a collection of dozens of folders and subfolders. When The Nether ended up being added, the game created an additional folder called DIM-1 to hold its dimension data. Annoyingly, though, it didn’t also move the overworld folders into its own subfolder called DIM0.
At some point months later, the game switched from using dozens of folders and subfolders, to using Region files. Great! More compact file traversal. These new files were stored in a subfolder called region. Not DIM0/region, but region. This was a perfect time to organize dimensions! And it didn’t happen! Why??
When The End was added, in 1.0, a new subfolder called DIM1 was inserted to house its data, solidifying a standard to have dimensions store their stuff in folders named DIM<id>. But again, the overworld’s level data didn’t get moved. So you have the file tree like this:
root├ level.dat├ region├ DIM-1| └ region└ DIM1 └ region
In 19w11a for 1.14, a sister folder to region was added: poi. It being tied to each dimension, it was underneath the root of the dimension. Then, in 20w45a, another sister folder called entities was added to hold entities. Both poi and entities have the same idea as region: hold that dimension’s objects (somewhat) like chunks in Region files. The data folder for each dimension holds specific data regarding that dimension, such as world_border.dat.
Because the overworld didn’t move to a subdirectory, its files are littered around alongside non-dimension-specific files, like the lockfile, icon, and player data folder. Plus, dimension-specific data (e.g. chunks.dat) sat alongside world-specific data (e.g. scoreboard.dat) in the data folder. It’s a mess! Look:
root├ level.dat├ region├ poi├ entities├ data├ DIM-1| ├ region| ├ poi| ├ entities| └ data└ DIM1 ├ region ├ poi ├ entities └ data
The April Fool’s Day snapshot 20w14infinity added a ton more dimensions. Each dimension warped to created a new folder in the level’s root directory, with the format DIM<id>. Warping to many dimensions cluttered up the root folder of the level.
New level format
But in 26.1-snapshot-6, what you have is streamlined. Simple, refined. Dimension data goes into the “dimension” folder, where each entry is namespaced! <root>/dimensions/<namespace>/<name>. Easy. Now the level looks like this:
root├ level.dat└ dimensions └ minecraft ├ overworld | ├ data | ├ entities | ├ poi | └ region ├ the_nether | ├ data | ├ entities | ├ poi | └ region └ the_end ├ data ├ entities ├ poi └ region
Flat. Elegant. Expansive.
Euclid Editor, the world editor I’m making, had to change a little to, for its goal, accommodate every version since 1.2.0. The creation of the level object (called World) actually parses and saves the level data NBT now, rather than just being a wrapper around a java.nio.file.Path object. The level data object is important because it has the DataVersion number, which will instruct methods on the object on what to return based on different level versions.
I’ll do more of a technical breakdown at some other point of how the API expects others to load and store NBT files, but for now, I can smile.