The bug
Tnt, Falling blocks, and Xp orbs (only those that I know of currently, might be more) don't bounce on slime blocks when falling into them. This is due to the order or events in the entities tick phase where the onGround
tag perpetuates downward motion instead of upwards.
How to reproduce
Place four slime blocks in a 2x2 pattern on the floor.
Go in the middle of the 4 slime blocks and fly up 5 blocks
Use the following command above the slime blocks
/summon minecraft:tnt ~ ~ ~ {fuse:100,Motion:[0.0,-9.0,0.0]}
→ ❌ It will not bounce
Code analysis
Using Fabric mapping 1.16.5
Here, we will look at the tnt entity for this example. We will start in the tick phase where it handles its motion and velocity as well as other important stuff not related to this ticket. We will say that this entity is moving down in this example (negative velocity y). We are first going to go into the move method as that is called first:
public void tick() {
REMOVED code as it was not needed
this.move(MovementType.SELF, this.getVelocity());
REMOVED code as it was not needed
if (this.onGround) {
this.setVelocity(this.getVelocity().multiply(0.7, -0.5, 0.7));
}
REMOVED code as it was not needed
}
In the move
method of the Entity class:
public void move(MovementType type, Vec3d movement) {
REMOVE code above as it was not needed
BlockPos lv2 = this.getLandingPos();
BlockState lv3 = this.world.getBlockState(lv2);
REMOVED code here as it was not needed
this.fall(lv.y, this.onGround, lv3, lv2);
Vec3d lv4 = this.getVelocity();
Block lv5 = lv3.getBlock();
if (movement.y != lv.y) {
lv5.onEntityLand(this.world, this);
}
REMOVED code here as it was not needed
}
In the move
method, the entity will try to go to it's final location using the velocity supplied in the parameters. If the y position hits a block, movement.y != lv.y
, will be set to true
and call onEntityLand
, supplying a block, which in this case, that is a slime block.
Now looking in the onEnitiyLand
code
@Override
public void onEntityLand(BlockView world, Entity entity) {
if (entity.bypassesLandingEffects()) {
super.onEntityLand(world, entity);
} else {
this.bounce(entity);
}
}
As the tnt can't bypassesLandingEffects
, it will call this.bounce(entity)
.
Now looking at the bounce
:
private void bounce(Entity entity) {
Vec3d lv = entity.getVelocity();
if (lv.y < 0.0) {
double d = entity instanceof LivingEntity ? 1.0 : 0.8;
entity.setVelocity(lv.x, -lv.y * d, lv.z);
}
}
As the tnt is being shot down, it has negative y velocity. Thus, the entities velocity will be set to a positive as it has its sign changed by -lv.y
As the move
method is now done, we are back in the tick
method
public void tick() { REMOVED code as it was not needed
this.move(MovementType.SELF, this.getVelocity());
REMOVED code as it was not needed
if (this.onGround) {
this.setVelocity(this.getVelocity().multiply(0.7, -0.5, 0.7));
}
REMOVED code as it was not needed
}
We came out of the move
method with a positive velocity. Now, as it hit a block going down, the onGround
check was set to true
. As the onGround
check was set to true
, the y velocity will be multiplied by -0.5, thus making it negative. When the tick
is called again, the slime blocks will just keep smacking into the slime block, thus never bouncing up.
Below is an MCP print statement to show the same thing above.
[Player268: Summoned new Primed TNT]
-9.04 before move in tick
-9.04 pre move
-9.04 Pre onLanded
-9.04 enter bounce
7.231999999999999 return from bounce
7.231999999999999 Post onlanded
7.231999999999999 Pre ground and stepping
7.231999999999999 post ground and stepping
7.231999999999999 post move
7.231999999999999 after move in tick
7.087359999999999 before ground in tick
-3.5436799999999997 after ground in tick
Solution
Like MC-207866,
If an entity has collided with a slime block in the "bounce", set the OnGround
tag to false
. This may have unforeseen consequences, but I can't think of any as of now.
Linked issues
Attachments
Comments 10
Relates to MC-207866
Can confirm in 1.17. Relates to MC-227382.
Relates to MC-61542
I can confirm.