mojira.dev
MC-265807

Mobs don't drown if their Air NBT is less than -19

The Bug

Change the air of creepers which values are less than -19 makes them no longer drown.

How to Reproduce

  1. Summon a creeper in water:

    /fill -1 -1 -1 1 2 1 glass
    /fill 0 0 0 0 1 0 water
    /summon creeper 0 0 0
    /fill -1 -1 -1 1 2 1 glass
    /fill 0 0 0 0 1 0 water
    /summon creeper 0 0 0
  2. Modify the air of the creeper to be -20:

    /data modify entity <uuid of the creeper> Air set value -20s
    /data modify entity <uuid of the creeper> Air set value -20s

Expected Behavior:

The creeper would drown immediately.

Observed Behavior:

The creeper didn't take damage and the air is keeping reducing.

This also affects villagers, pigs, and squids suffocate in air as well.

Code Analysis

This was due to the strict comparison (decompiled 1.20.2 using vanilla mapping:

net.minecraft.world.entity.LivingEntity.class

public void baseTick() {
    ...
    if (getAirSupply() == -20) {
        setAirSupply(0);
        Vec3 $$4 = getDeltaMovement();
        for (int $$5 = 0; $$5 < 8; $$5++) {
            double $$6 = this.random.nextDouble() - this.random.nextDouble();
            double $$7 = this.random.nextDouble() - this.random.nextDouble();
            double $$8 = this.random.nextDouble() - this.random.nextDouble();
            level().addParticle((ParticleOptions)ParticleTypes.BUBBLE, getX() + $$6, getY() + $$7, getZ() + $$8, $$4.x, $$4.y, $$4.z);
        }
        hurt(damageSources().drown(), 2.0F);
    }
    ...
}
public void baseTick() {
    ...
    if (getAirSupply() == -20) {
        setAirSupply(0);
        Vec3 $$4 = getDeltaMovement();
        for (int $$5 = 0; $$5 < 8; $$5++) {
            double $$6 = this.random.nextDouble() - this.random.nextDouble();
            double $$7 = this.random.nextDouble() - this.random.nextDouble();
            double $$8 = this.random.nextDouble() - this.random.nextDouble();
            level().addParticle((ParticleOptions)ParticleTypes.BUBBLE, getX() + $$6, getY() + $$7, getZ() + $$8, $$4.x, $$4.y, $$4.z);
        }
        hurt(damageSources().drown(), 2.0F);
    }
    ...
}

net.minecraft.world.entity.animal.WaterAnimal.class

protected void handleAirSupply(int $$0) {
    if (isAlive() && !isInWaterOrBubble()) {
        setAirSupply($$0 - 1);
        if (getAirSupply() == -20) {
            setAirSupply(0);
            hurt(damageSources().drown(), 2.0F);
        }
    } else {
        setAirSupply(300);
    }
}
protected void handleAirSupply(int $$0) {
    if (isAlive() && !isInWaterOrBubble()) {
        setAirSupply($$0 - 1);
        if (getAirSupply() == -20) {
            setAirSupply(0);
            hurt(damageSources().drown(), 2.0F);
        }
    } else {
        setAirSupply(300);
    }
}

Attachments

Comments 0

No comments.

ccJerrycc

bl4ckscor3

Confirmed

Platform

Low

Mob behaviour

1.20.2, 1.21, 1.21.8 Release Candidate 1

25w36a

Retrieved