mojira.dev
MC-311550

Unable to break instantly breakable blocks with Mining Fatigue 86 or higher

I've used this setup for reproducing MC-311510, MC-311511, MC-311513 and MC-311514, however the fact that this works at all may be a bug in and of itself.

To reproduce: /effect give @s minecraft:mining_fatigue 1 86 then try punching some slime blocks, honey blocks or basic plants

Expected results: since these have zero hardness, they would break instantly regardless of circumstances.

Actual results: in this bizarre edge case, they suddenly become indestructible

Linked issues

Attachments

Comments 3

Thank you for helping us improve Minecraft! We saved your files:

[media]

Some analysis:

As the fix for MC-279819, the speed multipliers for Mining Fatigue are no longer from a lookup table, and are instead calculated directly from the exponential formula.

// net.minecraft.world.entity.player.Player at 26.3-rc-2
    public float getDestroySpeed(BlockState state) {
        float speed = this.inventory.getSelectedItem().getDestroySpeed(state);
        if (speed > 1.0f) {
            speed += (float)this.getAttributeValue(Attributes.MINING_EFFICIENCY);
        }
        if (MobEffectUtil.hasDigSpeed(this)) {
            speed *= 1.0f + (float)(MobEffectUtil.getDigSpeedAmplification(this) + 1) * 0.2f;
        }
        // This is the part in question
        if (this.hasEffect(MobEffects.MINING_FATIGUE)) {
            int amplifier = this.getEffect(MobEffects.MINING_FATIGUE).getAmplifier();
            float scale = (float)Math.pow(0.3, amplifier + 1);
            speed *= scale;
        }
        speed *= (float)this.getAttributeValue(Attributes.BLOCK_BREAK_SPEED);
        if (this.isEyeInFluid(FluidTags.WATER)) {
            speed *= (float)this.getAttribute(Attributes.SUBMERGED_MINING_SPEED).getValue();
        }
        if (!this.onGround()) {
            speed /= 5.0f;
        }
        return speed;
    }

And pow(0.3, 87) underflows to zero when cast to single-precision. Thus the mining speed calculated turns out to be zero under Mining Fatigue 87 or higher.

Well, this speed is not used directly, and is instead used to calculate the mining progress per tick:

// net.minecraft.world.level.block.state.BlockBehaviour at 26.3-rc-2
    protected float getDestroyProgress(BlockState state, Player player, BlockGetter level, BlockPos pos) {
        float destroySpeed = state.getDestroySpeed(level, pos);
        if (destroySpeed == -1.0f) {
            return 0.0f;
        }
        int modifier = player.hasCorrectToolForDrops(state) ? 30 : 100;
        return player.getDestroySpeed(state) / destroySpeed / (float)modifier;
    }

destroySpeed here is just the block hardness. Evidently having both the mining speed and the hardness set to zero incurs Bad Things (a.k.a. NaN), and there seems to be no guarding against either of them being zero (although I haven’t thoroughly scanned the code, so I may be wrong). This is probably why the insta-breakable blocks are now unbreakable.

muzikbike

(Unassigned)

Confirmed

Platform

Low

Player

26.3 Snapshot 10

Retrieved