The bug
There is a hardcoded limit imposed by the game to restrict entities being pushed by 0.51 blocks per direction per gametick. It's an arbitrary restriction that is unintuitive when multiple pistons attempt to push an entity in the same tick, especially when it involves mobs "stepping up" (0.5m for most mobs, 1m for player/llama/horse), and becomes glitched inside blocks (example
[media]).
Code analysis
Originally by Myren Eario
Based on 1.12.2 decompiled using MCP 9.40
net.minecraft.entity.Entity.move(MoverType, double, double, double)
uses the attribute pistonDeltasGameTime
to store the offset by which an entity has been moved by pistons in a tick.
Entity.move(MoverType, double, double, double)
...
if (type == MoverType.PISTON)
{
long i = this.world.getTotalWorldTime();
if (i != this.pistonDeltasGameTime)
{
Arrays.fill(this.pistonDeltas, 0.0D);
this.pistonDeltasGameTime = i;
}
if (x != 0.0D)
{
int j = EnumFacing.Axis.X.ordinal();
double d0 = MathHelper.clamp(x + this.pistonDeltas[j], -0.51D, 0.51D);
x = d0 - this.pistonDeltas[j];
this.pistonDeltas[j] = d0;
if (Math.abs(x) <= 9.999999747378752E-6D)
{
return;
}
}
else if (y != 0.0D)
{
int l4 = EnumFacing.Axis.Y.ordinal();
double d12 = MathHelper.clamp(y + this.pistonDeltas[l4], -0.51D, 0.51D);
y = d12 - this.pistonDeltas[l4];
this.pistonDeltas[l4] = d12;
if (Math.abs(y) <= 9.999999747378752E-6D)
{
return;
}
}
else
{
if (z == 0.0D)
{
return;
}
int i5 = EnumFacing.Axis.Z.ordinal();
double d13 = MathHelper.clamp(z + this.pistonDeltas[i5], -0.51D, 0.51D);
z = d13 - this.pistonDeltas[i5];
this.pistonDeltas[i5] = d13;
if (Math.abs(z) <= 9.999999747378752E-6D)
{
return;
}
}
}
...
Here´s a less obfuscated version of the relevant part of the code. It´s the beginning of the moveEntity() method in the Entity class in 1.12 MCP, except that I renamed some variables.
and then there´s the rest of the moveEntity method.
While I don´t like this behavior, it looks intentional, so I don´t think this bug report will go very far.