Sharing an interesting email
I briefly talked to the crazy engineers over at Bat Country Entertainment about mods that alter the height limit in Minecraft. Ryan send me this interesting email about what different tradeoffs there are, and his experiences working with it:
Very cool! Off the top of my head, here’s a list of the main points:
Implications behind changing height:
- Memory Implications: Due to the way chunks are architected internally, the only relatively-easy way of increasing level height is to double it. As a result, memory usage can spiral out of control very quickly when increasing the number of bits available to the Y axis. A somewhat short-sighted view would be to point out that this is wholly manageable in SSP, but pragmatically, SMP is already a hornet’s nest when it comes to RAM usage, and the only way to increase the level height would be to neatly double the memory footprint. Ouch!
- CPU Implications: Chunk terrain generation occurs in pieces on the X/Z plane, but expects the chunk to be fully populated along the Y axis, from bedrock to sky. To be fair, much of this can be mitigated by the fact that any terrain above a certain cutoff can be assumed to be completely air, and any terrain below a certain cutoff can be assumed to be completely stone, thus eliminating the need for temperature / humidity / biome calculations far down in the level or high up in the level. Nonetheless, it’s still a cache-thrashing memory-fill operation. Worse still, due to the fact that subterranean features are populated per-chunk, to maintain a consistent distribution of ore you would need to double the number of calls made to any given feature generator as well for each doubling of the Y axis. While this is relatively cheap for things like ore, it’s eclipsed by the idea that cave generation would need to occur along the entire Y axis, and being a recursive function, this has the potential to get very costly very quickly.
- Storage Implications: Anything stored in memory needs to be serialized to disk and read back from disk. Given the fact that in SSP, the number-one performance killer - even on my beastly computer - is disk I/O, it would be a highly questionable idea to double the amount of data that needs to be written out to disk. I’m not completely sure if chunks are gzipped before being written to disk, or if that only occurs to chunks when transmitted over the network, but if they are, this simply robs from Peter to pay Paul - it mitigates the disk I/O issue while increasing the enormity of the CPU issue.
- Network Implications: On SMP, Chunks need to be sent to many more people many times more often than in SSP. It can be taken for granted, from a client’s perspective, just how much data needs to be shoved around by the server, and although network packets are gzipped, it’s still an additional networking load, and still an additional CPU load as well.
Regarding changing the level height, it was “easy” to the extent that it took me around 4 hours yesterday morning to do it, but only because I’ve been poking around the engine internals since January and have been mentally keeping track of all of the assumptions in the code on exactly that topic. From top to bottom:
- Search through the codebase for « 11 and « 7, replace with « 12 and « 8 as necessary.
- Search through the codebase for 128, this will hit the majority of places that assume the map height as being 128, such as tile height checks.
- When changing the above locations, save yourself a recompile and make sure to change any variables from bytes to shorts or ints if you’re increasing them past 128. Being a C++ engineer, I keep forgetting that everything is implied as signed in Java.
- Search through the codebase for 127, this will hit the remainder of places that assume the map height as being 128.
- Search through the codebase for 64 and 63, this will hit the places that assume sea level is at 64, as well as Iron’s ore generator height cutoff. Personally, I dialed sea level up to 96 from 64, rather than fully double it up to 128, in order to have 32 additional tiles’ worth of water height, but have an entire 96 additional tiles’ worth of land height.
- Fix up the level feature generators for Redstone, diamond, gold et al.
- Visually grep through all of the level feature generator classes, doubling the RNG baseline and spread for each one.
- Change a few instances of 32768 to 65536 to accommodate 16*256*16 rather than 16*128*16.
- I’m not sure how much of this is a result of JAD and how much of it is actual code, but there are a few instances of “char whatever = ‘\200’;” in the MCP codebase, change it to a short or int containing 256 instead of 128.
I have to say that the game was *remarkably* performant with the Y height pushed up to 256. I imagine 512 might not be too bad on my beast of a machine, either, though 1024 would be pushing it. That said, one of my short-term “just for fun” goals is to see if I can’t get the Nether to populate from 0-127, the main world from 128-255, your Sky dimension from 256-383, and then that one group of modders’ new dimension, the Aether, from 384-511. That would be epic.
Additionally, there’s a mod that some guy made that re-works chunks to be 16x16x16 (it appears), but I’m rather nonplused by it. The bug list is as long as my arm, and it doesn’t actually rescale any of the terrain-generation features, so you don’t get neat things like this: http://moogle-tech.com/bce/gorge.png
As a result, I’m in the process of just trying to re-do what he did on my own. I’m filling all chunks above Y=256 entirely with air, filling all chunks below 0 with stone, manually invoking the cave generator, and theoretically things should just work. In principle, theory is a flimsy thing to go on, and to that end I’ve been chasing down bugs for the past 4-5 hours. At present I’m able to get in-game, but the chunks are horribly mis-arranged, so I suspect I’ve missed an important hashing function somewhere, since that would also explain why it’s spitting out reams of “Wrong location!” exceptions that it’s spitting out whenever it tries to spawn animals - the level provider is providing the wrong chunk.