From 82c8fa696a2e8609d8ae086c52f96abe7c7705b6 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 7 Jan 2021 20:43:31 +0000 Subject: [PATCH] Relocate teleport ACK checks to InGamePacketHandler --- src/network/mcpe/NetworkSession.php | 4 ++ .../mcpe/handler/InGamePacketHandler.php | 19 ++++++++- src/player/Player.php | 41 ++++--------------- 3 files changed, 31 insertions(+), 33 deletions(-) diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index 33db8255d..800869ba9 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -690,6 +690,10 @@ class NetworkSession{ $pk->onGround = $this->player->onGround; $this->sendDataPacket($pk); + + if($this->handler instanceof InGamePacketHandler){ + $this->handler->forceMoveSync = true; + } } } diff --git a/src/network/mcpe/handler/InGamePacketHandler.php b/src/network/mcpe/handler/InGamePacketHandler.php index f2011fac8..2699bf310 100644 --- a/src/network/mcpe/handler/InGamePacketHandler.php +++ b/src/network/mcpe/handler/InGamePacketHandler.php @@ -127,6 +127,9 @@ class InGamePacketHandler extends PacketHandler{ /** @var Vector3|null */ protected $lastRightClickPos = null; + /** @var bool */ + public $forceMoveSync = false; + /** * TODO: HACK! This tracks GUIs for inventories that the server considers "always open" so that the client can't * open them twice. (1.16 hack) @@ -157,7 +160,21 @@ class InGamePacketHandler extends PacketHandler{ } $this->player->setRotation($yaw, $pitch); - $this->player->updateNextPosition($packet->position->round(4)->subtract(0, 1.62, 0)); + + $curPos = $this->player->getLocation(); + $newPos = $packet->position->subtract(0, 1.62, 0); + + if($this->forceMoveSync and $newPos->distanceSquared($curPos) > 1){ //Tolerate up to 1 block to avoid problems with client-sided physics when spawning in blocks + $this->session->syncMovement($curPos, null, null, MovePlayerPacket::MODE_RESET); + $this->session->getLogger()->debug("Got outdated pre-teleport movement, received " . $newPos . ", expected " . $curPos); + //Still getting movements from before teleport, ignore them + return false; + } + + // Once we get a movement within a reasonable distance, treat it as a teleport ACK and remove position lock + $this->forceMoveSync = false; + + $this->player->handleMovement($newPos); return true; } diff --git a/src/player/Player.php b/src/player/Player.php index c60db4b12..4adf1bba1 100644 --- a/src/player/Player.php +++ b/src/player/Player.php @@ -221,8 +221,6 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ protected $moveRateLimit = 10 * self::MOVES_PER_TICK; /** @var float|null */ protected $lastMovementProcess = null; - /** @var Vector3|null */ - protected $forceMoveSync = null; /** @var int */ protected $inAirTicks = 0; @@ -1106,39 +1104,19 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ } } - /** - * Sets the coordinates the player will move to next. This is processed at the end of each tick. Unless you have - * some particularly specialized logic, you probably want to use teleport() instead of this. - * - * This is used for processing movements sent by the player over network. - * - * @param Vector3 $newPos Coordinates of the player's feet, centered horizontally at the base of their bounding box. - * - * @return bool if the - */ - public function updateNextPosition(Vector3 $newPos) : bool{ - //TODO: teleport acks are a network specific thing and shouldn't be here - - $newPos = $newPos->asVector3(); - if($this->forceMoveSync !== null and $newPos->distanceSquared($this->forceMoveSync) > 1){ //Tolerate up to 1 block to avoid problems with client-sided physics when spawning in blocks - $this->sendPosition($this->location, null, null, MovePlayerPacket::MODE_RESET); - $this->logger->debug("Got outdated pre-teleport movement, received " . $newPos . ", expected " . $this->location->asVector3()); - //Still getting movements from before teleport, ignore them - return false; - } - - // Once we get a movement within a reasonable distance, treat it as a teleport ACK and remove position lock - $this->forceMoveSync = null; - - $this->handleMovement($newPos); - return true; - } - public function getInAirTicks() : int{ return $this->inAirTicks; } - protected function handleMovement(Vector3 $newPos) : void{ + /** + * Attempts to move the player to the given coordinates. Unless you have some particularly specialized logic, you + * probably want to use teleport() instead of this. + * + * This is used for processing movements sent by the player over network. + * + * @param Vector3 $newPos Coordinates of the player's feet, centered horizontally at the base of their bounding box. + */ + public function handleMovement(Vector3 $newPos) : void{ $this->moveRateLimit--; if($this->moveRateLimit < 0){ return; @@ -2222,7 +2200,6 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ public function sendPosition(Vector3 $pos, ?float $yaw = null, ?float $pitch = null, int $mode = MovePlayerPacket::MODE_NORMAL) : void{ $this->networkSession->syncMovement($pos, $yaw, $pitch, $mode); - $this->forceMoveSync = $pos->asVector3(); $this->ySize = 0; }