The Bug:
The levitation effect doesn't work while entities are inside water.
Steps to Reproduce:
Enter some water and give yourself the levitation effect by using the command provided below.
/effect give @s minecraft:levitation
Wait for a couple of seconds and observe if you levitate.
Take note as to whether or not the levitation effect works while entities are inside water.
Observed Behavior:
The levitation effect doesn't work.
Expected Behavior:
The levitation effect would work.
Code Analysis:
Code analysis by @unknown can be found in this comment.
Linked issues
is duplicated by 10
Attachments
Comments 19
I don't think it's supposed towork under water. It doesn't work when you are flying, and it doesn't work on squids. I don't think this is a bug.
I am able to confirm this in 21w40a. The expected behavior would be that the levitation effect works whilst in water.
Code analysis (Mojang mappings, 22w18a): in LivingEntity#travel(Vec3)
, the effects of Levitation are only calculated if three conditionals are false: the first one is
this.isInWater() && this.isAffectedByFluids() && !this.canStandOnFluid($$3)
which means that, for Levitation to take effect, the entity cannot be simultaneously in water, be affected by fluids, and be unable to stand on the fluid it is on. For nearly all entities inside water, the first conditional is already true, so the effects of Levitation are not calculated. Same thing happens with entities that are inside lava (except striders, because striders can stand on lava).
net.minecraft.world.entity.LivingEntity.java
...
public void travel(Vec3 $$0) {
if (this.isEffectiveAi() || this.isControlledByLocalInstance()) {
...
FluidState $$3 = this.level.getFluidState(this.blockPosition());
if (this.isInWater() && this.isAffectedByFluids() && !this.canStandOnFluid($$3)) {
...
} else if (this.isInLava() && this.isAffectedByFluids() && !this.canStandOnFluid($$3)) {
...
} else if (this.isFallFlying()) {
...
} else {
BlockPos $$25 = this.getBlockPosBelowThatAffectsMyMovement();
float $$26 = this.level.getBlockState($$25).getBlock().getFriction();
float $$27 = this.onGround ? $$26 * 0.91f : 0.91f;
Vec3 $$28 = this.handleRelativeFrictionAndCalculateMovement($$0, $$26);
double $$29 = $$28.y;
if (this.hasEffect(MobEffects.LEVITATION)) {
$$29 += (0.05 * (double)(this.getEffect(MobEffects.LEVITATION).getAmplifier() + 1) - $$28.y) * 0.2;
this.resetFallDistance();
} else if (!this.level.isClientSide || this.level.hasChunkAt($$25)) {
if (!this.isNoGravity()) {
$$29 -= $$1;
}
} else {
$$29 = this.getY() > (double)this.level.getMinBuildHeight() ? -0.1 : 0.0;
}
if (this.shouldDiscardFriction()) {
this.setDeltaMovement($$28.x, $$29, $$28.z);
} else {
this.setDeltaMovement($$28.x * (double)$$27, $$29 * (double)0.98f, $$28.z * (double)$$27);
}
}
}
this.calculateEntityAnimation(this, this instanceof FlyingAnimal);
}
...
indeed