Player: Move rollback responsibility to network for interact/break block

Custom player implementations might not need rollbacks (f.e. Specter).
This commit is contained in:
Dylan K. Taylor 2019-05-09 14:54:56 +01:00
parent ca7c23c137
commit 51a8c2be9d
2 changed files with 36 additions and 29 deletions

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine; namespace pocketmine;
use pocketmine\block\Bed; use pocketmine\block\Bed;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory; use pocketmine\block\BlockFactory;
use pocketmine\block\BlockLegacyIds; use pocketmine\block\BlockLegacyIds;
use pocketmine\block\UnknownBlock; use pocketmine\block\UnknownBlock;
@ -117,7 +116,6 @@ use pocketmine\world\format\Chunk;
use pocketmine\world\Position; use pocketmine\world\Position;
use pocketmine\world\World; use pocketmine\world\World;
use function abs; use function abs;
use function array_merge;
use function assert; use function assert;
use function ceil; use function ceil;
use function count; use function count;
@ -1952,7 +1950,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
* *
* @param Vector3 $pos * @param Vector3 $pos
* *
* @return bool if the block was successfully broken. * @return bool if the block was successfully broken, false if a rollback needs to take place.
*/ */
public function breakBlock(Vector3 $pos) : bool{ public function breakBlock(Vector3 $pos) : bool{
$this->doCloseInventory(); $this->doCloseInventory();
@ -1969,16 +1967,6 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
} }
} }
$this->inventory->sendContents($this);
$this->inventory->sendHeldItem($this);
$target = $this->world->getBlock($pos);
/** @var Block[] $blocks */
$blocks = $target->getAllSides();
$blocks[] = $target;
$this->world->sendBlocks([$this], $blocks);
return false; return false;
} }
@ -2005,20 +1993,6 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
} }
} }
$this->inventory->sendHeldItem($this);
if($pos->distanceSquared($this) > 10000){
return true;
}
$target = $this->world->getBlock($pos);
$block = $target->getSide($face);
/** @var Block[] $blocks */
$blocks = array_merge($target->getAllSides(), $block->getAllSides()); //getAllSides() on each of these will include $target and $block because they are next to each other
$this->world->sendBlocks([$this], $blocks);
return false; return false;
} }

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\network\mcpe\handler; namespace pocketmine\network\mcpe\handler;
use pocketmine\block\Block;
use pocketmine\block\ItemFrame; use pocketmine\block\ItemFrame;
use pocketmine\block\Sign; use pocketmine\block\Sign;
use pocketmine\block\utils\SignText; use pocketmine\block\utils\SignText;
@ -78,6 +79,7 @@ use pocketmine\network\mcpe\protocol\types\ReleaseItemTransactionData;
use pocketmine\network\mcpe\protocol\types\UseItemOnEntityTransactionData; use pocketmine\network\mcpe\protocol\types\UseItemOnEntityTransactionData;
use pocketmine\network\mcpe\protocol\types\UseItemTransactionData; use pocketmine\network\mcpe\protocol\types\UseItemTransactionData;
use pocketmine\Player; use pocketmine\Player;
use function array_push;
use function base64_encode; use function base64_encode;
use function fmod; use function fmod;
use function implode; use function implode;
@ -267,10 +269,17 @@ class SimpleSessionHandler extends SessionHandler{
return true; return true;
} }
//TODO: end hack for client spam bug //TODO: end hack for client spam bug
$this->player->interactBlock($data->getBlockPos(), $data->getFace(), $clickPos);
$blockPos = $data->getBlockPos();
if(!$this->player->interactBlock($blockPos, $data->getFace(), $clickPos)){
$this->onFailedBlockAction($blockPos, $data->getFace());
}
return true; return true;
case UseItemTransactionData::ACTION_BREAK_BLOCK: case UseItemTransactionData::ACTION_BREAK_BLOCK:
$this->player->breakBlock($data->getBlockPos()); $blockPos = $data->getBlockPos();
if(!$this->player->breakBlock($blockPos)){
$this->onFailedBlockAction($blockPos, null);
}
return true; return true;
case UseItemTransactionData::ACTION_CLICK_AIR: case UseItemTransactionData::ACTION_CLICK_AIR:
$this->player->useHeldItem(); $this->player->useHeldItem();
@ -280,6 +289,30 @@ class SimpleSessionHandler extends SessionHandler{
return false; return false;
} }
/**
* Internal function used to execute rollbacks when an action fails on a block.
*
* @param Vector3 $blockPos
* @param int|null $face
*/
private function onFailedBlockAction(Vector3 $blockPos, ?int $face) : void{
$this->player->getInventory()->sendHeldItem($this->player);
if($blockPos->distanceSquared($this->player) < 10000){
$target = $this->player->getWorld()->getBlock($blockPos);
$blocks = $target->getAllSides();
if($face !== null){
$sideBlock = $target->getSide($face);
/** @var Block[] $blocks */
array_push($blocks, ...$sideBlock->getAllSides()); //getAllSides() on each of these will include $target and $sideBlock because they are next to each other
}else{
$blocks[] = $target;
}
$this->player->getWorld()->sendBlocks([$this->player], $blocks);
}
}
private function handleUseItemOnEntityTransaction(UseItemOnEntityTransactionData $data) : bool{ private function handleUseItemOnEntityTransaction(UseItemOnEntityTransactionData $data) : bool{
$target = $this->player->getWorld()->getEntity($data->getEntityRuntimeId()); $target = $this->player->getWorld()->getEntity($data->getEntityRuntimeId());
if($target === null){ if($target === null){