Seed is immutable information about the world, like its generator type, generator options, name, etc. We don't allow changing any of those things, so why the fuck would we allow changing the seed? This makes no sense at all.
I'm removing this because a) its existence makes no sense, and b) it will not produce the behaviour expected from such a function (what even is the expected behaviour???)
It checks for the existence of (and creates) the world directory if it doesn't exist. But what sense does this make when the world obviously doesn't exist in this case and must be generated first?
This now removes logging from the level providers (for the most part) and replaces it with exception throws and catches. The implementation using the providers should catch these exceptions if they are thrown.
Level providers are now cut back to just an interface to a world's data. They don't keep their own chunk registries or any stupid shit like that because the Level already does that.
This furthers the goal of being able to move level I/O off the main thread, and also drastically decreases the complication of implementing level providers.
The remaining methods, constants and fields in the NBT class now pertain to generic NBT functionality (except for the matchList()/matchTree() methods, but that's a job for another time). All NBT I/O specific logic has now been moved to NBTStream and its descendents.
Refactored level\format\generic\GenericChunk -> level\format\Chunk.
Re-added support for async chunk sending
Refactored most Level IO into new namespaces for more organisation
Removed LevelDB loader completely (will be re-added at a later date)