Anti-cheat fixes, settings and API (#287)

* Added options to disable movement checks and anti-instabreak and API methods to control this
* Fixed anti-flight false positives
* Fix flight toggle kick cannot be disabled
* Added PlayerIllegalMoveEvent
This commit is contained in:
Dylan K. Taylor 2017-01-25 09:40:48 +00:00 committed by GitHub
parent 77456702e9
commit 661f17b6e0
7 changed files with 121 additions and 16 deletions

View File

@ -41,6 +41,7 @@ use pocketmine\event\inventory\CraftItemEvent;
use pocketmine\event\inventory\InventoryCloseEvent; use pocketmine\event\inventory\InventoryCloseEvent;
use pocketmine\event\inventory\InventoryPickupArrowEvent; use pocketmine\event\inventory\InventoryPickupArrowEvent;
use pocketmine\event\inventory\InventoryPickupItemEvent; use pocketmine\event\inventory\InventoryPickupItemEvent;
use pocketmine\event\player\cheat\PlayerIllegalMoveEvent;
use pocketmine\event\player\PlayerAchievementAwardedEvent; use pocketmine\event\player\PlayerAchievementAwardedEvent;
use pocketmine\event\player\PlayerAnimationEvent; use pocketmine\event\player\PlayerAnimationEvent;
use pocketmine\event\player\PlayerBedEnterEvent; use pocketmine\event\player\PlayerBedEnterEvent;
@ -236,6 +237,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
protected $allowFlight = false; protected $allowFlight = false;
protected $flying = false; protected $flying = false;
protected $allowMovementCheats = false;
protected $allowInstaBreak = false;
private $needACK = []; private $needACK = [];
private $batchedPackets = []; private $batchedPackets = [];
@ -333,6 +337,22 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return $this->autoJump; 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 * @param Player $player
*/ */
@ -552,6 +572,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->rawUUID = null; $this->rawUUID = null;
$this->creationTime = microtime(true); $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){ 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; return;
} }
@ -1358,7 +1381,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$revert = false; $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"); $this->server->getLogger()->warning($this->getName() . " moved too fast, reverting movement");
$revert = true; $revert = true;
}else{ }else{
@ -1389,12 +1412,15 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$diff = ($diffX ** 2 + $diffY ** 2 + $diffZ ** 2) / ($tickDiff ** 2); $diff = ($diffX ** 2 + $diffY ** 2 + $diffZ ** 2) / ($tickDiff ** 2);
if($this->isSurvival()){ if($this->isSurvival() and !$revert and $diff > 0.0625){
if(!$revert and !$this->isSleeping()){ $ev = new PlayerIllegalMoveEvent($this, $newPos);
if($diff > 0.0625){ $ev->setCancelled($this->allowMovementCheats);
$revert = true;
$this->server->getLogger()->warning($this->getServer()->getLanguage()->translateString("pocketmine.player.invalidMove", [$this->getName()])); $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->checkNearEntities($tickDiff);
} }
$this->speed = $from->subtract($to); $this->speed = ($to->subtract($from))->divide($tickDiff);
}elseif($distanceSquared == 0){ }elseif($distanceSquared == 0){
$this->speed = new Vector3(0, 0, 0); $this->speed = new Vector3(0, 0, 0);
} }
@ -1534,9 +1560,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->timings->startTiming(); $this->timings->startTiming();
if($this->spawned){ if($this->spawned){
if(!$this->isSleeping()){ $this->processMovement($tickDiff);
$this->processMovement($tickDiff);
}
$this->entityBaseTick($tickDiff); $this->entityBaseTick($tickDiff);
if(!$this->isSpectator() and $this->speed !== null){ if(!$this->isSpectator() and $this->speed !== null){
@ -1935,7 +1959,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
break; break;
case ProtocolInfo::ADVENTURE_SETTINGS_PACKET: case ProtocolInfo::ADVENTURE_SETTINGS_PACKET:
//TODO: player abilities, check for other changes //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"); $this->kick("Flying is not enabled on this server");
break; break;
}else{ }else{

View File

@ -75,7 +75,7 @@ namespace pocketmine {
use raklib\RakLib; use raklib\RakLib;
const VERSION = "1.6.2dev"; const VERSION = "1.6.2dev";
const API_VERSION = "3.0.0-ALPHA2"; const API_VERSION = "3.0.0-ALPHA3";
const CODENAME = "Unleashed"; const CODENAME = "Unleashed";
/* /*

View File

@ -0,0 +1,31 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
/**
* Events called when a player attempts to cheat
*/
namespace pocketmine\event\player\cheat;
use pocketmine\event\player\PlayerEvent;
abstract class PlayerCheatEvent extends PlayerEvent{
}

View File

@ -0,0 +1,45 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
/**
* Events called when a player attempts to perform movement cheats such as clipping through blocks.
*/
namespace pocketmine\event\player\cheat;
use pocketmine\event\Cancellable;
use pocketmine\Player;
use pocketmine\math\Vector3;
class PlayerIllegalMoveEvent extends PlayerCheatEvent implements Cancellable{
public static $handlerList = null;
private $attemptedPosition;
public function __construct(Player $player, Vector3 $attemptedPosition){
$this->attemptedPosition = $attemptedPosition;
$this->player = $player;
}
public function getAttemptedPosition() : Vector3{
return $this->attemptedPosition;
}
}

View File

@ -1497,7 +1497,7 @@ class Level implements ChunkManager, Metadatable{
} }
if($player !== null){ 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)){ if($player->isSurvival() and $item instanceof Item and !$target->isBreakable($item)){
$ev->setCancelled(); $ev->setCancelled();

View File

@ -99,6 +99,11 @@ debug:
player: player:
#Choose whether to enable player data saving. #Choose whether to enable player data saving.
save-player-data: true 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: level-settings:
#The default format that levels will use when created #The default format that levels will use when created

@ -1 +1 @@
Subproject commit ba9f94e4b040afbc42e17b12e648f496d400cdcb Subproject commit 268abd40941416bdaea9a029549f3cc12f806e9c