mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-04 00:55:14 +00:00
PlayerInteractEvent: added APIs to independently control reaction of item and block (#4683)
This allows, for example, banning the usage of spawn eggs, without preventing opening of doors, without the need for item ID whitelists. It also allows customizing the behaviour of item and block interactions when sneaking - it's now possible to force spawn eggs to work when sneaking, or force containers to open. Finally, this also allows preventing any interaction at all without preventing block placement (by setting both to false). Since cancelling the event will typically prevent placement too (which might not be desired). Side note: Blocks are now always synced when right-clicking on a block. This differs from the previous behaviour, where the blocks were only synced when the action "failed". However, since this change introduces a situation where the action may succeed but have different results than the client expects, it's best to just always sync blocks in this situation. Fixes #3267
This commit is contained in:
@ -493,15 +493,18 @@ class InGamePacketHandler extends PacketHandler{
|
||||
|
||||
$blockPos = $data->getBlockPosition();
|
||||
$vBlockPos = new Vector3($blockPos->getX(), $blockPos->getY(), $blockPos->getZ());
|
||||
if(!$this->player->interactBlock($vBlockPos, $data->getFace(), $clickPos)){
|
||||
$this->onFailedBlockAction($vBlockPos, $data->getFace());
|
||||
}
|
||||
$this->player->interactBlock($vBlockPos, $data->getFace(), $clickPos);
|
||||
//always sync this in case plugins caused a different result than the client expected
|
||||
//we *could* try to enhance detection of plugin-altered behaviour, but this would require propagating
|
||||
//more information up the stack. For now I think this is good enough.
|
||||
//if only the client would tell us what blocks it thinks changed...
|
||||
$this->syncBlocksNearby($vBlockPos, $data->getFace());
|
||||
return true;
|
||||
case UseItemTransactionData::ACTION_BREAK_BLOCK:
|
||||
$blockPos = $data->getBlockPosition();
|
||||
$vBlockPos = new Vector3($blockPos->getX(), $blockPos->getY(), $blockPos->getZ());
|
||||
if(!$this->player->breakBlock($vBlockPos)){
|
||||
$this->onFailedBlockAction($vBlockPos, null);
|
||||
$this->syncBlocksNearby($vBlockPos, null);
|
||||
}
|
||||
return true;
|
||||
case UseItemTransactionData::ACTION_CLICK_AIR:
|
||||
@ -529,9 +532,9 @@ class InGamePacketHandler extends PacketHandler{
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal function used to execute rollbacks when an action fails on a block.
|
||||
* Syncs blocks nearby to ensure that the client and server agree on the world's blocks after a block interaction.
|
||||
*/
|
||||
private function onFailedBlockAction(Vector3 $blockPos, ?int $face) : void{
|
||||
private function syncBlocksNearby(Vector3 $blockPos, ?int $face) : void{
|
||||
if($blockPos->distanceSquared($this->player->getLocation()) < 10000){
|
||||
$blocks = $blockPos->sidesArray();
|
||||
if($face !== null){
|
||||
@ -682,7 +685,7 @@ class InGamePacketHandler extends PacketHandler{
|
||||
case PlayerAction::START_BREAK:
|
||||
self::validateFacing($face);
|
||||
if(!$this->player->attackBlock($pos, $face)){
|
||||
$this->onFailedBlockAction($pos, $face);
|
||||
$this->syncBlocksNearby($pos, $face);
|
||||
}
|
||||
|
||||
break;
|
||||
@ -998,7 +1001,7 @@ class InGamePacketHandler extends PacketHandler{
|
||||
$lectern = $world->getBlockAt($pos->getX(), $pos->getY(), $pos->getZ());
|
||||
if($lectern instanceof Lectern && $this->player->canInteract($lectern->getPosition(), 15)){
|
||||
if(!$lectern->onPageTurn($packet->page)){
|
||||
$this->onFailedBlockAction($lectern->getPosition(), null);
|
||||
$this->syncBlocksNearby($lectern->getPosition(), null);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
Reference in New Issue
Block a user