Entity: workaround teleport client bug #4394 by despawning and respawning the entity (#4870)

this is a sucky solution but it works well enough for this scenario.

From my research it appears that while the client-side MovementInterpolator is active on the client and hasn't yet reached its target, any teleport sent during the lerp will get overridden by the lerp.
This appears to last 3-4 ticks (about 150-200 ms) which explains why this can be reproduced by stopping movement just before the ender pearl lands (human reaction times would make the reproduction unreliable otherwise).

Things to note:
- All entities are affected by this bug.
- MovePlayerPacket appears not to have the problem, but we can't use it because it doesn't work for non-players.
- MoveActorAbsolute and MoveActorDelta are both handled by the same code and will have the same lerping bug.

This is the cleanest solution I could come up with.
This commit is contained in:
Dylan T 2022-04-08 23:12:01 +01:00 committed by GitHub
parent 1aee5b1ed8
commit d1dfbd95e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -768,17 +768,29 @@ abstract class Entity{
} }
protected function broadcastMovement(bool $teleport = false) : void{ protected function broadcastMovement(bool $teleport = false) : void{
$this->server->broadcastPackets($this->hasSpawned, [MoveActorAbsolutePacket::create( if($teleport){
$this->id, //TODO: HACK! workaround for https://github.com/pmmp/PocketMine-MP/issues/4394
$this->getOffsetPosition($this->location), //this happens because MoveActor*Packet doesn't clear interpolation targets on the client, so the entity
$this->location->pitch, //snaps to the teleport position, but then lerps back to the original position if a normal movement for the
$this->location->yaw, //entity was recently broadcasted. This can be seen with players throwing ender pearls.
$this->location->yaw, //TODO: remove this if the bug ever gets fixed (lol)
( foreach($this->hasSpawned as $player){
($teleport ? MoveActorAbsolutePacket::FLAG_TELEPORT : 0) | $this->despawnFrom($player);
($this->onGround ? MoveActorAbsolutePacket::FLAG_GROUND : 0) $this->spawnTo($player);
) }
)]); }else{
$this->server->broadcastPackets($this->hasSpawned, [MoveActorAbsolutePacket::create(
$this->id,
$this->getOffsetPosition($this->location),
$this->location->pitch,
$this->location->yaw,
$this->location->yaw,
(
//TODO: if the above hack for #4394 gets removed, we should be setting FLAG_TELEPORT here
($this->onGround ? MoveActorAbsolutePacket::FLAG_GROUND : 0)
)
)]);
}
} }
protected function broadcastMotion() : void{ protected function broadcastMotion() : void{