mojira.dev
MCPE-142292

Iron golems and cats cannot spawn in many underground/roofed villages

The new iron golem/cat spawning mechanics in 1.17.30 make iron golems and cats unable to spawn at an otherwise spawnable X, Z location if there is any block above that spot up to Y + 6 of the village center. At the extreme, a spawn attempt can be blocked by a ceiling 12 blocks above where the spawn is attempted. This makes iron golems and cats unable to spawn in many underground villages and iron farms with ceilings/roofs above them.

Steps to reproduce

  1. Load

[media]
  1. . It contains two villages that meet the minimum conditions for iron golem spawning. Each village has command blocks that mark iron golem spawns within the village with a gold block and then teleport the golems into lava. Each village also has command blocks that can be used to toggle a stone roof at Y + 6 of the village center. The western village has a spawning platform that leaves 4 blocks of air under the stone roof where golems should be able to spawn. The eastern village has a spawning platform at the lowest possible Y-level where golems should be able to spawn.

  2. Stand on the gold block between the villages and wait 5-10 minutes.

  3. Go to each village and toggle the stone roof off.

  4. Stand on the gold block between the villages and wait 5-10 minutes.

Expected results

Iron golem and cats spawn in both village in steps (2) and (4).

Actual results.

Iron golems and cats do not spawn in step (2). They do spawn in step (4).

Linked issues

Attachments

Comments 2

According to code digging by Reed Cartwright, the bug here is in the check for air or water above the block chosen to spawn a golem. The game actually only checks the block at the top of the column (Y + 6 from the village center) instead of the block directly above the potentially spawnable block being checked. In other words, the Y value passed to the air-or-liquid-checking function does not update as the algorithm searches down the vertical column for a spawnable block.

This means that the stone ceilings in the test world can be changed to tripwire, leaves, hanging roots, anything, and the villages will not spawn golems or cats.

After reverse engineering iron golem spawning mechanics in 1.17.30. And testing different designs in 1.17.40+ betas, I have developed the following improvement to the iron golem spawning mechanics.

In this algorithm, iron golems will spawn on top of the highest solid block in the search column that is below an air or liquid block also in the search column. If the spawn location is obstructed by blocks or entities, the spawn will fail and another attempt will be made.

// C++ style psuedocode to improve MobSpawnUtils::trySpawnMob()

for(int i = 0; i < num_attempts; ++i) {
    auto current_pos = village_center;
    // Draw a random x and z offsets uniformly between -xz_offset and xz_offset.
    // The lower and upper limits are inclusive.
    current_pos.x += random_int_inclusive(-xz_offset, xz_offset);
    current_pos.z += random_int_inclusive(-xz_offset, xz_offset);

    // Look for the highest gap block in spawning area.
    // A gap block is a air block or a liquid block.
    int y_off = y_offset;
    for(; y_off > -y_offset; --y_off) {
        current_pos.y = village_center.y + y_off;
        auto current_block = block_source.getBlock(current_pos);
        if(current_block == mAir || current_block.getMaterial().isLiquid()) {
            break;
        }
    }
    // No gap block found. Search failed, try again
    if(y_off <= -y_offset) {
        continue;
    }
    
    // Look for highest solid block below the gap block
    for(; y_off > -y_offset; --y_off) {
        current_pos.y = village_center.y + y_off;
        auto platform_block = block_source.getBlock(current_pos.below());
        if(current_block.isSolid()) {
            break;
        }
    }
    // No solid block found. Search failed, try again
    if(y_off <= -y_offset) {
        continue;
    }
    // Try creating a golem.
    auto mob = create_golem(current_pos);
    if(mob->checkSpawnRules() && mob->checkSpawnObstruction()) {
        // golem successfully spawned
        return mob;
    }
    // Golem spawning is blocked. Destroy golem and try again.
    destroy_golem(mob);
}
return null;

 

 

GoldenHelmet

(Unassigned)

624197

Community Consensus

Windows

1.17.30, 1.17.40, 1.18.2 Hotfix

1.18.30.23 Preview, 1.18.30.22 Beta, 1.18.30

Retrieved