Uploaded image for project: 'Minecraft: Java Edition'
  1. Minecraft: Java Edition
  2. MC-265807

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

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • None
    • 1.20.2
    • None
    • Confirmed
    • Mob behaviour
    • Low
    • Platform

      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
        
      2. Modify the air of the creeper to be -20:
        /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);
          }
          ...
      }
      
      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);
          }
      }
      

            Unassigned Unassigned
            ccJerrycc ccJerrycc
            Votes:
            1 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              CHK: