So, if you're willing to put in the effort to spawn proof the area you're better off building a mob farm as low as possible and removing any solid blocks higher up in the chunk.
I've verified that for myself in an all bedrock superflat world, I built a spawning platform up at Y = 250 or so, it never had more than about 15 mobs at a time, they were despawning as fast as they spawned. Then I teleported 1000 blocks away and built one directly on the bedrock and the joint was hopping, a real mob party!
So, as I understand it, that's because the game keeps track of the highest solid block in each chunk and spreads the spawn attempts out between level 1 and the highest block.
So, ignoring the mob cap and other mobs getting in the way, my first test platform would have had only 1 in every 250 or so attempts succeed for that chunk and my second platform would have had every other attempt succeed (or every one if I replaced the bedrock with spawnable blocks)?
So far it all makes sense.
However, I'm pretty sure it's been claimed that a single platform as low as possible is better than having multiple platforms?
(It used to be as many platforms as you could fit into the lowest subchunk.)
Is that the case? And if so, why exactly?
I can clearly understand that the very best case scenario is removing the bedrock and putting a single platform at Y = 1 with every block in the chunk being spawnable.
But, with my limited knowledge, it would seem that in survival on a normal world a single platform at y=6, on top of the bedrock, would have only 1 out of every 6 blocks spawnable while squeezing in 84 spawning platforms from Y=6 to Y=255 would give you close to every third block being spawnable?
Multiple platforms will increase spawn rates but the spawn rate per platform will be reduced as the height of the highest platform (or roof) increases; the game always does one spawn attempt per chunk per tick (provided that the cap isn't met), so for a single platform the rate is 1 / (20 / height) and for multiple platforms it is 1 / (20 / height * platforms) seconds per successful pack spawn attempt; for example, a platform at y=63 (sea level) would have one spawn attempt every 3.15 seconds while 85 platforms over the entire height range (ignoring bedrock) would have one attempt every 0.15 seconds, but each platform would only see one attempt every 12.75 seconds.
Also, the thing about subchunks only applied to versions prior to 1.8, where instead of using the actual height the game used the height of the highest loaded chunk section. Also, once a chunk section is created it is never removed, meaning that you wouldn't actually benefit from digging down to bedrock; not only that, prior to 1.7 the Superflat world generator always generated every subchunk (I've always noticed that Superflat worlds paradoxically used significantly more memory than default worlds, and world generation was actually slower than a normal world, except, even odder, for presets like Tunneler's Dream (this is because the game calculates sky light across the entire height range up to the highest loaded chunk section, so a default Superflat world has far more air blocks to light); the server doesn't send empty subchunks to the client so this wasn't immediately apparent until I fixed MC-80966, which then showed the "lc" value as always being 255, and likewise when removing blocks it never decreased, until I added a "garbage collector" that periodically deletes sections with no block or light data):
Vanilla 1.6.4; note that the game uses the highest loaded chunk section to determine the altitude range for spawning:
protected static ChunkPosition getRandomSpawningPointInChunk(World par0World, int par1, int par2)
Chunk var3 = par0World.getChunkFromChunkCoords(par1, par2);
int var4 = par1 * 16 + par0World.rand.nextInt(16);
int var5 = par2 * 16 + par0World.rand.nextInt(16);
int var6 = par0World.rand.nextInt(var3 == null ? par0World.getActualHeight() : var3.getTopFilledSegment() + 16);
return new ChunkPosition(var4, var6, var5);
This is from my own mod, which is similar to what 1.8 does (I use a fixed range for the Nether since it will normally always be y=0-127; this also means I don't need to check for bedrock when spawning mobs since they can never spawn above y=127, while I do want them to spawn on the single layer of bedrock at y=0):
protected void getRandomSpawningPointInChunk(World par0World, int par1, int par2, boolean nether)
int x = this.nextInt16();
int z = this.nextInt16();
this.randomSpawnPoint = par1 << 4 | x;
this.randomSpawnPoint = par2 << 4 | z;
// Fixed to a range of 1-125
this.randomSpawnPoint = this.nextInt(125) + 1;
// Uses actual height instead of LC (not affected by empty sections loaded above ground)
Chunk chunk = par0World.getChunkFromChunkCoords(par1, par2);
this.randomSpawnPoint = this.nextInt(Math.max(1, chunk == null ? par0World.getActualHeight() : chunk.getHeightValue(x, z))) + 1;
Of note, the vanilla code actually has (had) a bug; Random.nextInt(16) gives a range of 0-15, while for mobs to spawn on top of the lowest chunk section (where getTopFilledSegment returns 0) a range of up to 16 is required (this bug was fixed in vanilla in a later version; normally it was only apparent in Superflat worlds with a height that was a multiple of 16, and no other blocks; the Overworld preset is 64 layers deep but has tall grass which loads the next section up). Technically, there is also no need to ever attempt to spawn mobs at y=0 since there are no blocks below, so I add 1 to the randomized value (getHeightValue returns the block above the highest solid block); e.g. a height of 63 (sea level) results in a range of 1-63 (unless it has changed in a more recent version vanilla 1.8+ still uses the full range, so the actual best-case spawn rate is 1/2 for a platform at y=0, since it chooses either 0 or 1. I've hear of changes to the mob spawning code in 1.13 and/or 1.14 so I don't know if this is still the case).
Also, you may have heard that the game doesn't save empty chunk sections; in reality, it does save them, never deleting sections for any reason, but prior to 1.13 it didn't send them to the client, resulting in lighting errors along section boundaries; this is because the game only counted the blocks present in a section and used that to determine if it was empty when sending data to the client (I just changed this to always return false, and added code that checks for and removes sections with only air blocks, 0 block light, and 15 sky light (the default values for empty/null sections):
public boolean isEmpty()
return this.blockRefCount == 0;
I'm not actually interested in building a maxed out mob farm, I just like to understand how the game works and the inconsistency in the information I had was bugging me.
I have dug out a slime chunk in connection with my mine, no automation, I just run up and down the stairs killing the slimes when I happen to pass and hear them bouncing around.
I have removed all the rock above level 30, more as a project than because I really care about the spawn rates.
I'm considering removing all except the bottom floor just because I'm getting tired of running up and down the stairs.
And just to clear things out in my mind,
a single platform at level 6 (with everything above removed) should then have 1/(20/6) = 0.3 seconds between successful attempts (so theoretically the 85 platforms would be twice as good) and I figure a platform at level 5 (with some bedrock intruding) would be about as good as level 6. (I've only checked 1 chunk for bedrock in layer 4 so I don't know how evenly it's distributed, I found 51 bedrock leaving 201 spawnable blocks or 78.5% spawnable. I get that to be 0.318 seconds per success, so slightly worse than level 6 (in that chunk.))
And a single platform at level 1 would have the absolute minimum of 0.05 seconds between successes.