diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 217024065..7a26bcaec 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -41,6 +41,7 @@ use pocketmine\event\inventory\CraftItemEvent; use pocketmine\event\inventory\InventoryCloseEvent; use pocketmine\event\inventory\InventoryPickupArrowEvent; use pocketmine\event\inventory\InventoryPickupItemEvent; +use pocketmine\event\player\cheat\PlayerIllegalMoveEvent; use pocketmine\event\player\PlayerAchievementAwardedEvent; use pocketmine\event\player\PlayerAnimationEvent; use pocketmine\event\player\PlayerBedEnterEvent; @@ -236,6 +237,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade protected $allowFlight = false; protected $flying = false; + protected $allowMovementCheats = false; + protected $allowInstaBreak = false; + private $needACK = []; private $batchedPackets = []; @@ -333,6 +337,22 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade return $this->autoJump; } + public function allowMovementCheats() : bool{ + return $this->allowMovementCheats; + } + + public function setAllowMovementCheats(bool $value = false){ + $this->allowMovementCheats = $value; + } + + public function allowInstaBreak() : bool{ + return $this->allowInstaBreak; + } + + public function setAllowInstaBreak(bool $value = false){ + $this->allowInstaBreak = $value; + } + /** * @param Player $player */ @@ -552,6 +572,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $this->rawUUID = null; $this->creationTime = microtime(true); + + $this->allowMovementCheats = (bool) $this->server->getProperty("player.anti-cheat.allow-movement-cheats", false); + $this->allowInstaBreak = (bool) $this->server->getProperty("player.anti-cheat.allow-instabreak", false); } /** @@ -1349,7 +1372,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade } protected function processMovement($tickDiff){ - if(!$this->isAlive() or !$this->spawned or $this->newPosition === null or $this->teleportPosition !== null){ + if(!$this->isAlive() or !$this->spawned or $this->newPosition === null or $this->teleportPosition !== null or $this->isSleeping()){ return; } @@ -1358,7 +1381,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $revert = false; - if(($distanceSquared / ($tickDiff ** 2)) > 100){ + if(($distanceSquared / ($tickDiff ** 2)) > 100 and !$this->allowMovementCheats){ $this->server->getLogger()->warning($this->getName() . " moved too fast, reverting movement"); $revert = true; }else{ @@ -1389,12 +1412,15 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $diff = ($diffX ** 2 + $diffY ** 2 + $diffZ ** 2) / ($tickDiff ** 2); - if($this->isSurvival()){ - if(!$revert and !$this->isSleeping()){ - if($diff > 0.0625){ - $revert = true; - $this->server->getLogger()->warning($this->getServer()->getLanguage()->translateString("pocketmine.player.invalidMove", [$this->getName()])); - } + if($this->isSurvival() and !$revert and $diff > 0.0625){ + $ev = new PlayerIllegalMoveEvent($this, $newPos); + $ev->setCancelled($this->allowMovementCheats); + + $this->server->getPluginManager()->callEvent($ev); + + if(!$ev->isCancelled()){ + $revert = true; + $this->server->getLogger()->warning($this->getServer()->getLanguage()->translateString("pocketmine.player.invalidMove", [$this->getName()])); } } @@ -1442,7 +1468,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $this->checkNearEntities($tickDiff); } - $this->speed = $from->subtract($to); + $this->speed = ($to->subtract($from))->divide($tickDiff); }elseif($distanceSquared == 0){ $this->speed = new Vector3(0, 0, 0); } @@ -1534,9 +1560,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $this->timings->startTiming(); if($this->spawned){ - if(!$this->isSleeping()){ - $this->processMovement($tickDiff); - } + $this->processMovement($tickDiff); $this->entityBaseTick($tickDiff); if(!$this->isSpectator() and $this->speed !== null){ @@ -1935,7 +1959,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade break; case ProtocolInfo::ADVENTURE_SETTINGS_PACKET: //TODO: player abilities, check for other changes - if($packet->isFlying and !$this->allowFlight){ + if($packet->isFlying and !$this->allowFlight and !$this->server->getAllowFlight()){ $this->kick("Flying is not enabled on this server"); break; }else{ diff --git a/src/pocketmine/PocketMine.php b/src/pocketmine/PocketMine.php index 5f776f253..d8b1fdd3c 100644 --- a/src/pocketmine/PocketMine.php +++ b/src/pocketmine/PocketMine.php @@ -75,7 +75,7 @@ namespace pocketmine { use raklib\RakLib; const VERSION = "1.6.2dev"; - const API_VERSION = "3.0.0-ALPHA2"; + const API_VERSION = "3.0.0-ALPHA3"; const CODENAME = "Unleashed"; /* diff --git a/src/pocketmine/event/player/cheat/PlayerCheatEvent.php b/src/pocketmine/event/player/cheat/PlayerCheatEvent.php new file mode 100644 index 000000000..dfeb14164 --- /dev/null +++ b/src/pocketmine/event/player/cheat/PlayerCheatEvent.php @@ -0,0 +1,31 @@ +attemptedPosition = $attemptedPosition; + $this->player = $player; + } + + public function getAttemptedPosition() : Vector3{ + return $this->attemptedPosition; + } + +} \ No newline at end of file diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index 29002aa36..8f6a3e888 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -1497,7 +1497,7 @@ class Level implements ChunkManager, Metadatable{ } if($player !== null){ - $ev = new BlockBreakEvent($player, $target, $item, $player->isCreative() ? true : false); + $ev = new BlockBreakEvent($player, $target, $item, ($player->isCreative() or $player->allowInstaBreak())); if($player->isSurvival() and $item instanceof Item and !$target->isBreakable($item)){ $ev->setCancelled(); diff --git a/src/pocketmine/resources/pocketmine.yml b/src/pocketmine/resources/pocketmine.yml index 27185f79e..f0ecf96d9 100644 --- a/src/pocketmine/resources/pocketmine.yml +++ b/src/pocketmine/resources/pocketmine.yml @@ -99,6 +99,11 @@ debug: player: #Choose whether to enable player data saving. save-player-data: true + anti-cheat: + #If false, will try to prevent speed and noclip cheats. May cause movement issues with some blocks which are not yet properly implemented. + allow-movement-cheats: false + #If false, times block breaks to ensure players are not cheating. May cause issues with some blocks which are not yet properly implemented. + allow-instabreak: false level-settings: #The default format that levels will use when created diff --git a/tests/plugins/PocketMine-DevTools b/tests/plugins/PocketMine-DevTools index ba9f94e4b..268abd409 160000 --- a/tests/plugins/PocketMine-DevTools +++ b/tests/plugins/PocketMine-DevTools @@ -1 +1 @@ -Subproject commit ba9f94e4b040afbc42e17b12e648f496d400cdcb +Subproject commit 268abd40941416bdaea9a029549f3cc12f806e9c