-
Bug
-
Resolution: Won't Fix
-
None
-
1.20.6, 24w18a
-
None
-
Community Consensus
-
Mob spawning
What happens
During natural mob spawnings for nether fortress mobs:
- For packed spawning for fortress mob whose spawner data is picked on netherbricks blocks, its spawn attempts cannot spawn mobs in inner fortress bounding box on non-netherbricks block
- For packed spawning for fortress mob whose spawner data is picked on non-netherbricks blocks, its spawn attempts cannot spawn mobs in outer fortress bounding box on netherbricks block
Here "spawner data" means net.minecraft.world.level.biome.MobSpawnSettings.SpawnerData
Affected versions: from 1.18.2 release, to the current latest release and snapshot
Analyze
Let's have a look at class net.minecraft.world.level.NaturalSpawner#getRandomSpawnMobAt
During natural mob spawning, NaturalSpawner#getRandomSpawnMobAt is used to get the
SpawnerData for the current pack spawning, and NaturalSpawner#canSpawnMobAt is used to check if the mob can still be spawned at the current pos.
Both getRandomSpawnMobAt and canSpawnMobAt invoke mobsAt method to get the list of SpawnerData for the given pos
For nether fortress mobs, mobsAt method could return 2 different list:
return isInNetherFortressBounds(blockPos, serverLevel, mobCategory, structureManager) ? NetherFortressStructure.FORTRESS_ENEMIES : chunkGenerator.getMobsAt(holder != null ? holder : serverLevel.getBiome(blockPos), structureManager, mobCategory, blockPos);
- Case A: If the pos is inside the outer bounding box of the fortress, and is on the top of a nether bricks block, then NetherFortressStructure.FORTRESS_ENEMIES is returned
- Case B: Otherwise, the return value of chunkGenerator.getMobsAt is used. If the pos is inside the inner bounding box of the fortress, then a list with the same value of NetherFortressStructure.FORTRESS_ENEMIES is returned
Since 1.18.2-pre1, the returned list of case A will be a different object with case B, and the list elements will be different as well. Notes that canSpawnMobAt uses java.util.List#contains to check if the spawner data is inside the list, and class MobSpawnSettings.SpawnerData does not implements the equals methods.
As the result, canSpawnMobAt will return false, if a pack spawning picks the spawner data on a netherbricks block (pick from case A list), and trying to spawn a fortress mob on non-nether bricks (check with case B list), vice versa
For the 1.18.2-pre1 change, 1.18.2-pre1 makes the spawn data list data-driven, resulting in spawner data list for fortress mobs are serialized and deserialized (i.e. deep copied) during the creation of the current level's RegistryAccess
How this affects the game
Wither skeleton farms built at fortress crossroads, using dirt + wither rose as the spawning platform, will have its rate decreased, if nether bricks floor is built around the spawning platform (see attachment wiskefarm.png). For MC version < 1.18.2, the rate will increase instead
The reason is, with extended netherbricks floors built, for pack spawning that picks its spawner data on inner bounding box structure (e.g. fortress bridges) adjacent to the intersection spawning platform, it can no longer spawns wither skeleton on the spawning platform, due to the described issue
Possible solution
- Implements the equals method on MobSpawnSettings.SpawnerData
- Replace the java.util.List#contains call in canSpawnMobAt with something else