diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index 7fa48f392..3a6f4e4ef 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -258,7 +258,7 @@ class NetworkSession{ } public function isConnected() : bool{ - return $this->connected; + return $this->connected && !$this->disconnectGuard; } public function getIp() : string{ @@ -503,7 +503,7 @@ class NetworkSession{ public function disconnect(string $reason, bool $notify = true) : void{ $this->tryDisconnect(function() use ($reason, $notify) : void{ if($this->player !== null){ - $this->player->disconnect($reason, null, $notify); + $this->player->onPostDisconnect($reason, null); } $this->doServerDisconnect($reason, $notify); }, $reason); @@ -518,7 +518,7 @@ class NetworkSession{ $this->tryDisconnect(function() use ($ip, $port, $reason) : void{ $this->sendDataPacket(TransferPacket::create($ip, $port), true); if($this->player !== null){ - $this->player->disconnect($reason, null, false); + $this->player->onPostDisconnect($reason, null); } $this->doServerDisconnect($reason, false); }, $reason); @@ -527,9 +527,9 @@ class NetworkSession{ /** * Called by the Player when it is closed (for example due to getting kicked). */ - public function onPlayerDestroyed(string $reason, bool $notify = true) : void{ - $this->tryDisconnect(function() use ($reason, $notify) : void{ - $this->doServerDisconnect($reason, $notify); + public function onPlayerDestroyed(string $reason) : void{ + $this->tryDisconnect(function() use ($reason) : void{ + $this->doServerDisconnect($reason, true); }, $reason); } @@ -551,7 +551,7 @@ class NetworkSession{ public function onClientDisconnect(string $reason) : void{ $this->tryDisconnect(function() use ($reason) : void{ if($this->player !== null){ - $this->player->disconnect($reason, null, false); + $this->player->onPostDisconnect($reason, null); } }, $reason); } diff --git a/src/player/Player.php b/src/player/Player.php index e9635d2d2..3d4171683 100644 --- a/src/player/Player.php +++ b/src/player/Player.php @@ -1986,15 +1986,31 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ * Note for plugin developers: Prefer kick() instead of this method. * That way other plugins can have a say in whether the player is removed or not. * + * Note for internals developers: Do not call this from network sessions. It will cause a feedback loop. + * * @param string $reason Shown to the player, usually this will appear on their disconnect screen. * @param TranslationContainer|string|null $quitMessage Message to broadcast to online players (null will use default) */ - public function disconnect(string $reason, $quitMessage = null, bool $notify = true) : void{ + public function disconnect(string $reason, $quitMessage = null) : void{ if(!$this->isConnected()){ return; } - $this->networkSession->onPlayerDestroyed($reason, $notify); + $this->networkSession->onPlayerDestroyed($reason); + $this->onPostDisconnect($reason, $quitMessage); + } + + /** + * @internal + * This method executes post-disconnect actions and cleanups. + * + * @param string $reason Shown to the player, usually this will appear on their disconnect screen. + * @param TranslationContainer|string|null $quitMessage Message to broadcast to online players (null will use default) + */ + public function onPostDisconnect(string $reason, $quitMessage) : void{ + if($this->isConnected()){ + throw new \InvalidStateException("Player is still connected"); + } //prevent the player receiving their own disconnect message PermissionManager::getInstance()->unsubscribeFromPermission(Server::BROADCAST_CHANNEL_USERS, $this);