First look at #5512: gameplay permissions

This commit is contained in:
Dylan K. Taylor 2023-01-16 22:12:07 +00:00
parent edb8f19a0c
commit 10a962daa2
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
10 changed files with 98 additions and 36 deletions

View File

@ -38,6 +38,7 @@ use pocketmine\network\mcpe\convert\TypeConverter;
use pocketmine\network\mcpe\protocol\AddItemActorPacket; use pocketmine\network\mcpe\protocol\AddItemActorPacket;
use pocketmine\network\mcpe\protocol\types\entity\EntityIds; use pocketmine\network\mcpe\protocol\types\entity\EntityIds;
use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper; use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper;
use pocketmine\permission\DefaultPermissionNames;
use pocketmine\player\Player; use pocketmine\player\Player;
use function max; use function max;
@ -311,7 +312,7 @@ class ItemEntity extends Entity{
}; };
$ev = new EntityItemPickupEvent($player, $this, $item, $playerInventory); $ev = new EntityItemPickupEvent($player, $this, $item, $playerInventory);
if($player->hasFiniteResources() && $playerInventory === null){ if(($player->hasFiniteResources() && $playerInventory === null) || !$player->hasPermission(DefaultPermissionNames::GAME_ITEM_PICKUP)){
$ev->cancel(); $ev->cancel();
} }

View File

@ -36,6 +36,7 @@ use pocketmine\nbt\tag\CompoundTag;
use pocketmine\network\mcpe\protocol\types\entity\EntityIds; use pocketmine\network\mcpe\protocol\types\entity\EntityIds;
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataCollection; use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataCollection;
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataFlags; use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataFlags;
use pocketmine\permission\DefaultPermissionNames;
use pocketmine\player\Player; use pocketmine\player\Player;
use pocketmine\world\sound\ArrowHitSound; use pocketmine\world\sound\ArrowHitSound;
use function ceil; use function ceil;
@ -184,7 +185,7 @@ class Arrow extends Projectile{
}; };
$ev = new EntityItemPickupEvent($player, $this, $item, $playerInventory); $ev = new EntityItemPickupEvent($player, $this, $item, $playerInventory);
if($player->hasFiniteResources() && $playerInventory === null){ if(($player->hasFiniteResources() && $playerInventory === null) || !$player->hasPermission(DefaultPermissionNames::GAME_ITEM_PICKUP)){
$ev->cancel(); $ev->cancel();
} }
if($this->pickupMode === self::PICKUP_NONE || ($this->pickupMode === self::PICKUP_CREATIVE && !$player->isCreative())){ if($this->pickupMode === self::PICKUP_NONE || ($this->pickupMode === self::PICKUP_CREATIVE && !$player->isCreative())){

View File

@ -27,6 +27,7 @@ use pocketmine\inventory\CreativeInventory;
use pocketmine\inventory\transaction\TransactionValidationException; use pocketmine\inventory\transaction\TransactionValidationException;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\item\VanillaItems; use pocketmine\item\VanillaItems;
use pocketmine\permission\DefaultPermissionNames;
use pocketmine\player\Player; use pocketmine\player\Player;
/** /**

View File

@ -27,6 +27,7 @@ use pocketmine\event\player\PlayerDropItemEvent;
use pocketmine\inventory\transaction\TransactionValidationException; use pocketmine\inventory\transaction\TransactionValidationException;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\item\VanillaItems; use pocketmine\item\VanillaItems;
use pocketmine\permission\DefaultPermissionNames;
use pocketmine\player\Player; use pocketmine\player\Player;
/** /**
@ -49,7 +50,7 @@ class DropItemAction extends InventoryAction{
public function onPreExecute(Player $source) : bool{ public function onPreExecute(Player $source) : bool{
$ev = new PlayerDropItemEvent($source, $this->targetItem); $ev = new PlayerDropItemEvent($source, $this->targetItem);
if($source->isSpectator()){ if(!$source->hasPermission(DefaultPermissionNames::GAME_ITEM_DROP)){
$ev->cancel(); $ev->cancel();
} }
$ev->call(); $ev->call();

View File

@ -854,16 +854,16 @@ class NetworkSession{
UpdateAbilitiesPacketLayer::ABILITY_OPERATOR => $isOp, UpdateAbilitiesPacketLayer::ABILITY_OPERATOR => $isOp,
UpdateAbilitiesPacketLayer::ABILITY_TELEPORT => $for->hasPermission(DefaultPermissionNames::COMMAND_TELEPORT_SELF), UpdateAbilitiesPacketLayer::ABILITY_TELEPORT => $for->hasPermission(DefaultPermissionNames::COMMAND_TELEPORT_SELF),
UpdateAbilitiesPacketLayer::ABILITY_INVULNERABLE => $for->isCreative(), UpdateAbilitiesPacketLayer::ABILITY_INVULNERABLE => $for->isCreative(),
UpdateAbilitiesPacketLayer::ABILITY_MUTED => false, UpdateAbilitiesPacketLayer::ABILITY_MUTED => !$for->hasPermission(DefaultPermissionNames::GAME_CHAT),
UpdateAbilitiesPacketLayer::ABILITY_WORLD_BUILDER => false, UpdateAbilitiesPacketLayer::ABILITY_WORLD_BUILDER => false,
UpdateAbilitiesPacketLayer::ABILITY_INFINITE_RESOURCES => !$for->hasFiniteResources(), UpdateAbilitiesPacketLayer::ABILITY_INFINITE_RESOURCES => !$for->hasFiniteResources(),
UpdateAbilitiesPacketLayer::ABILITY_LIGHTNING => false, UpdateAbilitiesPacketLayer::ABILITY_LIGHTNING => false,
UpdateAbilitiesPacketLayer::ABILITY_BUILD => !$for->isSpectator(), UpdateAbilitiesPacketLayer::ABILITY_BUILD => $for->hasPermission(DefaultPermissionNames::GAME_BLOCK_PLACE),
UpdateAbilitiesPacketLayer::ABILITY_MINE => !$for->isSpectator(), UpdateAbilitiesPacketLayer::ABILITY_MINE => $for->hasPermission(DefaultPermissionNames::GAME_BLOCK_BREAK),
UpdateAbilitiesPacketLayer::ABILITY_DOORS_AND_SWITCHES => !$for->isSpectator(), UpdateAbilitiesPacketLayer::ABILITY_DOORS_AND_SWITCHES => $for->hasPermission(DefaultPermissionNames::GAME_BLOCK_INTERACT),
UpdateAbilitiesPacketLayer::ABILITY_OPEN_CONTAINERS => !$for->isSpectator(), UpdateAbilitiesPacketLayer::ABILITY_OPEN_CONTAINERS => $for->hasPermission(DefaultPermissionNames::GAME_BLOCK_INTERACT) || $for->hasPermission(DefaultPermissionNames::GAME_ENTITY_INTERACT), //not perfect, but this is a pain to implement right now
UpdateAbilitiesPacketLayer::ABILITY_ATTACK_PLAYERS => !$for->isSpectator(), UpdateAbilitiesPacketLayer::ABILITY_ATTACK_PLAYERS => $for->hasPermission(DefaultPermissionNames::GAME_PLAYER_ATTACK),
UpdateAbilitiesPacketLayer::ABILITY_ATTACK_MOBS => !$for->isSpectator(), UpdateAbilitiesPacketLayer::ABILITY_ATTACK_MOBS => $for->hasPermission(DefaultPermissionNames::GAME_ENTITY_ATTACK),
]; ];
$this->sendDataPacket(UpdateAbilitiesPacket::create( $this->sendDataPacket(UpdateAbilitiesPacket::create(

View File

@ -91,7 +91,24 @@ final class DefaultPermissionNames{
public const COMMAND_WHITELIST_LIST = "pocketmine.command.whitelist.list"; public const COMMAND_WHITELIST_LIST = "pocketmine.command.whitelist.list";
public const COMMAND_WHITELIST_RELOAD = "pocketmine.command.whitelist.reload"; public const COMMAND_WHITELIST_RELOAD = "pocketmine.command.whitelist.reload";
public const COMMAND_WHITELIST_REMOVE = "pocketmine.command.whitelist.remove"; public const COMMAND_WHITELIST_REMOVE = "pocketmine.command.whitelist.remove";
public const GAME_BLOCK_BREAK = "pocketmine.game.block.break";
public const GAME_BLOCK_INTERACT = "pocketmine.game.block.interact";
public const GAME_BLOCK_PLACE = "pocketmine.game.block.place";
public const GAME_CHAT = "pocketmine.game.chat";
public const GAME_ENTITY_ATTACK = "pocketmine.game.entity.attack";
public const GAME_ENTITY_INTERACT = "pocketmine.game.entity.interact";
public const GAME_FLIGHT = "pocketmine.game.flight";
public const GAME_ITEM_CREATE = "pocketmine.game.item.create";
public const GAME_ITEM_DROP = "pocketmine.game.item.drop";
public const GAME_ITEM_PICKUP = "pocketmine.game.item.pickup";
public const GAME_ITEM_USE = "pocketmine.game.item.use";
public const GAME_PLAYER_ATTACK = "pocketmine.game.player.attack";
public const GAME_PLAYER_INTERACT = "pocketmine.game.player.interact";
public const GROUP_CONSOLE = "pocketmine.group.console"; public const GROUP_CONSOLE = "pocketmine.group.console";
public const GROUP_GAMEMODE_ADVENTURE = "pocketmine.group.gamemode.adventure";
public const GROUP_GAMEMODE_CREATIVE = "pocketmine.group.gamemode.creative";
public const GROUP_GAMEMODE_SPECTATOR = "pocketmine.group.gamemode.spectator";
public const GROUP_GAMEMODE_SURVIVAL = "pocketmine.group.gamemode.survival";
public const GROUP_OPERATOR = "pocketmine.group.operator"; public const GROUP_OPERATOR = "pocketmine.group.operator";
public const GROUP_USER = "pocketmine.group.user"; public const GROUP_USER = "pocketmine.group.user";
} }

View File

@ -136,5 +136,26 @@ abstract class DefaultPermissions{
self::registerPermission(new Permission(Names::COMMAND_WHITELIST_LIST, "Allows the user to list all players on the server whitelist"), [$operatorRoot]); self::registerPermission(new Permission(Names::COMMAND_WHITELIST_LIST, "Allows the user to list all players on the server whitelist"), [$operatorRoot]);
self::registerPermission(new Permission(Names::COMMAND_WHITELIST_RELOAD, "Allows the user to reload the server whitelist"), [$operatorRoot]); self::registerPermission(new Permission(Names::COMMAND_WHITELIST_RELOAD, "Allows the user to reload the server whitelist"), [$operatorRoot]);
self::registerPermission(new Permission(Names::COMMAND_WHITELIST_REMOVE, "Allows the user to remove a player from the server whitelist"), [$operatorRoot]); self::registerPermission(new Permission(Names::COMMAND_WHITELIST_REMOVE, "Allows the user to remove a player from the server whitelist"), [$operatorRoot]);
self::registerPermission(new Permission(Names::GAME_CHAT, "Allows the user to chat"), [$everyoneRoot]);
$survivalRoot = self::registerPermission(new Permission(Names::GROUP_GAMEMODE_SURVIVAL));
$creativeRoot = self::registerPermission(new Permission(Names::GROUP_GAMEMODE_CREATIVE));
$adventureRoot = self::registerPermission(new Permission(Names::GROUP_GAMEMODE_ADVENTURE));
self::registerPermission(new Permission(Names::GROUP_GAMEMODE_SPECTATOR)); //not currently used, but will be in the future
self::registerPermission(new Permission(Names::GAME_BLOCK_BREAK, "Allows the user to break blocks"), [$survivalRoot, $creativeRoot, $adventureRoot]);
self::registerPermission(new Permission(Names::GAME_BLOCK_INTERACT, "Allows the user to interact with blocks"), [$survivalRoot, $creativeRoot, $adventureRoot]);
self::registerPermission(new Permission(Names::GAME_BLOCK_PLACE, "Allows the user to place blocks"), [$survivalRoot, $creativeRoot, $adventureRoot]);
self::registerPermission(new Permission(Names::GAME_ENTITY_ATTACK, "Allows the user to attack entities"), [$survivalRoot, $creativeRoot, $adventureRoot]);
self::registerPermission(new Permission(Names::GAME_ENTITY_INTERACT, "Allows the user to interact with entities"), [$survivalRoot, $creativeRoot, $adventureRoot]);
self::registerPermission(new Permission(Names::GAME_ITEM_DROP, "Allows the user to drop items"), [$survivalRoot, $creativeRoot, $adventureRoot]);
self::registerPermission(new Permission(Names::GAME_ITEM_PICKUP, "Allows the user to pick up items"), [$survivalRoot, $creativeRoot, $adventureRoot]);
self::registerPermission(new Permission(Names::GAME_ITEM_USE, "Allows the user to use items such as snowballs"), [$survivalRoot, $creativeRoot, $adventureRoot]);
self::registerPermission(new Permission(Names::GAME_PLAYER_ATTACK, "Allows the user to attack other players"), [$survivalRoot, $creativeRoot, $adventureRoot]);
self::registerPermission(new Permission(Names::GAME_PLAYER_INTERACT, "Allows the user to interact with other players"), [$survivalRoot, $creativeRoot, $adventureRoot]);
self::registerPermission(new Permission(Names::GAME_ITEM_CREATE, "Allows the user to use the creative inventory"), [$creativeRoot]);
self::registerPermission(new Permission(Names::GAME_FLIGHT, "Allows the user to toggle flight mode"), [$creativeRoot]);
} }
} }

View File

@ -25,6 +25,7 @@ namespace pocketmine\player;
use pocketmine\lang\KnownTranslationFactory; use pocketmine\lang\KnownTranslationFactory;
use pocketmine\lang\Translatable; use pocketmine\lang\Translatable;
use pocketmine\permission\DefaultPermissionNames;
use pocketmine\utils\EnumTrait; use pocketmine\utils\EnumTrait;
use function mb_strtolower; use function mb_strtolower;
@ -50,10 +51,10 @@ final class GameMode{
protected static function setup() : void{ protected static function setup() : void{
self::registerAll( self::registerAll(
new self("survival", "Survival", KnownTranslationFactory::gameMode_survival(), ["survival", "s", "0"]), new self("survival", "Survival", KnownTranslationFactory::gameMode_survival(), DefaultPermissionNames::GROUP_GAMEMODE_SURVIVAL, ["survival", "s", "0"]),
new self("creative", "Creative", KnownTranslationFactory::gameMode_creative(), ["creative", "c", "1"]), new self("creative", "Creative", KnownTranslationFactory::gameMode_creative(), DefaultPermissionNames::GROUP_GAMEMODE_CREATIVE, ["creative", "c", "1"]),
new self("adventure", "Adventure", KnownTranslationFactory::gameMode_adventure(), ["adventure", "a", "2"]), new self("adventure", "Adventure", KnownTranslationFactory::gameMode_adventure(), DefaultPermissionNames::GROUP_GAMEMODE_ADVENTURE, ["adventure", "a", "2"]),
new self("spectator", "Spectator", KnownTranslationFactory::gameMode_spectator(), ["spectator", "v", "view", "3"]) new self("spectator", "Spectator", KnownTranslationFactory::gameMode_spectator(), DefaultPermissionNames::GROUP_GAMEMODE_SPECTATOR, ["spectator", "v", "view", "3"])
); );
} }
@ -76,6 +77,7 @@ final class GameMode{
string $enumName, string $enumName,
private string $englishName, private string $englishName,
private Translatable $translatableName, private Translatable $translatableName,
private string $permissionGroupName,
private array $aliases = [] private array $aliases = []
){ ){
$this->Enum___construct($enumName); $this->Enum___construct($enumName);
@ -87,6 +89,8 @@ final class GameMode{
public function getTranslatableName() : Translatable{ return $this->translatableName; } public function getTranslatableName() : Translatable{ return $this->translatableName; }
public function getPermissionGroupName() : string{ return $this->permissionGroupName; }
/** /**
* @return string[] * @return string[]
*/ */

View File

@ -261,7 +261,6 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
//TODO: Abilities //TODO: Abilities
protected bool $autoJump = true; protected bool $autoJump = true;
protected bool $allowFlight = false;
protected bool $blockCollision = true; protected bool $blockCollision = true;
protected bool $flying = false; protected bool $flying = false;
@ -436,12 +435,16 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
* *
* Note: Setting this to false DOES NOT change whether the player is currently flying. Use * Note: Setting this to false DOES NOT change whether the player is currently flying. Use
* {@link Player::setFlying()} for that purpose. * {@link Player::setFlying()} for that purpose.
*
* Note: As of 4.13, this will override any game mode flight restrictions for the duration of the game session.
* This differs from previous behaviour, where the flag would get overwritten by game mode changes.
*
* @deprecated This is now controlled by setting a permission, which allows more fine-tuned control.
* @see DefaultPermissionNames::GAME_FLIGHT
*/ */
public function setAllowFlight(bool $value) : void{ public function setAllowFlight(bool $value) : void{
if($this->allowFlight !== $value){ $this->setBasePermission(DefaultPermissionNames::GAME_FLIGHT, $value);
$this->allowFlight = $value; $this->getNetworkSession()->syncAbilities($this);
$this->getNetworkSession()->syncAbilities($this);
}
} }
/** /**
@ -451,7 +454,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
* enter or exit flight mode will be prevented. * enter or exit flight mode will be prevented.
*/ */
public function getAllowFlight() : bool{ public function getAllowFlight() : bool{
return $this->allowFlight; return $this->hasPermission(DefaultPermissionNames::GAME_FLIGHT);
} }
/** /**
@ -1056,9 +1059,13 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
} }
protected function internalSetGameMode(GameMode $gameMode) : void{ protected function internalSetGameMode(GameMode $gameMode) : void{
if(isset($this->gamemode)){
$this->unsetBasePermission($this->gamemode->getPermissionGroupName());
}
$this->gamemode = $gameMode; $this->gamemode = $gameMode;
$this->allowFlight = $this->gamemode->equals(GameMode::CREATIVE()); $this->setBasePermission($this->gamemode->getPermissionGroupName(), true);
$this->hungerManager->setEnabled($this->isSurvival()); $this->hungerManager->setEnabled($this->isSurvival());
if($this->isSpectator()){ if($this->isSpectator()){
@ -1071,7 +1078,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
//this is a yucky hack but we don't have any other options :( //this is a yucky hack but we don't have any other options :(
$this->sendPosition($this->location, null, null, MovePlayerPacket::MODE_TELEPORT); $this->sendPosition($this->location, null, null, MovePlayerPacket::MODE_TELEPORT);
}else{ }else{
if($this->isSurvival()){ if(!$this->hasPermission(DefaultPermissionNames::GAME_FLIGHT)){
$this->setFlying(false); $this->setFlying(false);
} }
$this->setHasBlockCollision(true); $this->setHasBlockCollision(true);
@ -1140,11 +1147,8 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
return $this->gamemode->equals(GameMode::SPECTATOR()); return $this->gamemode->equals(GameMode::SPECTATOR());
} }
/**
* TODO: make this a dynamic ability instead of being hardcoded
*/
public function hasFiniteResources() : bool{ public function hasFiniteResources() : bool{
return $this->gamemode->equals(GameMode::SURVIVAL()) || $this->gamemode->equals(GameMode::ADVENTURE()); return !$this->hasPermission(DefaultPermissionNames::GAME_ITEM_CREATE);
} }
public function isFireProof() : bool{ public function isFireProof() : bool{
@ -1452,6 +1456,9 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
Timings::$playerCommand->stopTiming(); Timings::$playerCommand->stopTiming();
}else{ }else{
$ev = new PlayerChatEvent($this, $ev->getMessage(), $this->server->getBroadcastChannelSubscribers(Server::BROADCAST_CHANNEL_USERS)); $ev = new PlayerChatEvent($this, $ev->getMessage(), $this->server->getBroadcastChannelSubscribers(Server::BROADCAST_CHANNEL_USERS));
if(!$this->hasPermission(DefaultPermissionNames::GAME_CHAT)){
$ev->cancel();
}
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$this->server->broadcastMessage($this->getServer()->getLanguage()->translateString($ev->getFormat(), [$ev->getPlayer()->getDisplayName(), $ev->getMessage()]), $ev->getRecipients()); $this->server->broadcastMessage($this->getServer()->getLanguage()->translateString($ev->getFormat(), [$ev->getPlayer()->getDisplayName(), $ev->getMessage()]), $ev->getRecipients());
@ -1494,7 +1501,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
$oldItem = clone $item; $oldItem = clone $item;
$ev = new PlayerItemUseEvent($this, $item, $directionVector); $ev = new PlayerItemUseEvent($this, $item, $directionVector);
if($this->hasItemCooldown($item) || $this->isSpectator()){ if($this->hasItemCooldown($item) || !$this->hasPermission(DefaultPermissionNames::GAME_ITEM_USE)){
$ev->cancel(); $ev->cancel();
} }
@ -1565,7 +1572,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
public function releaseHeldItem() : bool{ public function releaseHeldItem() : bool{
try{ try{
$item = $this->inventory->getItemInHand(); $item = $this->inventory->getItemInHand();
if(!$this->isUsingItem() || $this->hasItemCooldown($item)){ if(!$this->isUsingItem() || $this->hasItemCooldown($item) || !$this->hasPermission(DefaultPermissionNames::GAME_ITEM_USE)){
return false; return false;
} }
@ -1599,7 +1606,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
$ev = new PlayerBlockPickEvent($this, $block, $item); $ev = new PlayerBlockPickEvent($this, $block, $item);
$existingSlot = $this->inventory->first($item); $existingSlot = $this->inventory->first($item);
if($existingSlot === -1 && ($this->hasFiniteResources() || $this->isSpectator())){ if($existingSlot === -1 && $this->hasFiniteResources()){
$ev->cancel(); $ev->cancel();
} }
$ev->call(); $ev->call();
@ -1641,7 +1648,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
$target = $this->getWorld()->getBlock($pos); $target = $this->getWorld()->getBlock($pos);
$ev = new PlayerInteractEvent($this, $this->inventory->getItemInHand(), $target, null, $face, PlayerInteractEvent::LEFT_CLICK_BLOCK); $ev = new PlayerInteractEvent($this, $this->inventory->getItemInHand(), $target, null, $face, PlayerInteractEvent::LEFT_CLICK_BLOCK);
if($this->isSpectator()){ if(!$this->hasPermission(DefaultPermissionNames::GAME_BLOCK_INTERACT)){
$ev->cancel(); $ev->cancel();
} }
$ev->call(); $ev->call();
@ -1759,7 +1766,11 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
if(!$this->canInteract($entity->getLocation(), self::MAX_REACH_DISTANCE_ENTITY_INTERACTION)){ if(!$this->canInteract($entity->getLocation(), self::MAX_REACH_DISTANCE_ENTITY_INTERACTION)){
$this->logger->debug("Cancelled attack of entity " . $entity->getId() . " due to not currently being interactable"); $this->logger->debug("Cancelled attack of entity " . $entity->getId() . " due to not currently being interactable");
$ev->cancel(); $ev->cancel();
}elseif($this->isSpectator() || ($entity instanceof Player && !$this->server->getConfigGroup()->getConfigBool("pvp"))){ }elseif(!$this->hasPermission($entity instanceof Player ? DefaultPermissionNames::GAME_PLAYER_ATTACK : DefaultPermissionNames::GAME_ENTITY_ATTACK)){
$this->logger->debug("Cancelled attack of entity " . $entity->getId() . " due to lack of attack permission");
$ev->cancel();
}elseif($entity instanceof Player && !$this->server->getConfigGroup()->getConfigBool("pvp")){
$this->logger->debug("Cancelled attack of player " . $entity->getId() . " due to PvP being disabled globally");
$ev->cancel(); $ev->cancel();
} }
@ -1825,6 +1836,10 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
$this->logger->debug("Cancelled interaction with entity " . $entity->getId() . " due to not currently being interactable"); $this->logger->debug("Cancelled interaction with entity " . $entity->getId() . " due to not currently being interactable");
$ev->cancel(); $ev->cancel();
} }
if(!$this->hasPermission($entity instanceof Player ? DefaultPermissionNames::GAME_PLAYER_INTERACT : DefaultPermissionNames::GAME_ENTITY_INTERACT)){
$this->logger->debug("Cancelled interaction with entity " . $entity->getId() . " due to lack of permission");
$ev->cancel();
}
$ev->call(); $ev->call();
@ -1875,7 +1890,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
return true; return true;
} }
$ev = new PlayerToggleFlightEvent($this, $fly); $ev = new PlayerToggleFlightEvent($this, $fly);
if(!$this->allowFlight){ if(!$this->getAllowFlight()){
$ev->cancel(); $ev->cancel();
} }
$ev->call(); $ev->call();
@ -2373,7 +2388,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
&& $source->getCause() !== EntityDamageEvent::CAUSE_SUICIDE && $source->getCause() !== EntityDamageEvent::CAUSE_SUICIDE
){ ){
$source->cancel(); $source->cancel();
}elseif($this->allowFlight && $source->getCause() === EntityDamageEvent::CAUSE_FALL){ }elseif($this->getAllowFlight() && $source->getCause() === EntityDamageEvent::CAUSE_FALL){
$source->cancel(); $source->cancel();
} }

View File

@ -69,6 +69,7 @@ use pocketmine\network\mcpe\protocol\BlockActorDataPacket;
use pocketmine\network\mcpe\protocol\ClientboundPacket; use pocketmine\network\mcpe\protocol\ClientboundPacket;
use pocketmine\network\mcpe\protocol\types\BlockPosition; use pocketmine\network\mcpe\protocol\types\BlockPosition;
use pocketmine\network\mcpe\protocol\UpdateBlockPacket; use pocketmine\network\mcpe\protocol\UpdateBlockPacket;
use pocketmine\permission\DefaultPermissionNames;
use pocketmine\player\ChunkSelector; use pocketmine\player\ChunkSelector;
use pocketmine\player\Player; use pocketmine\player\Player;
use pocketmine\promise\Promise; use pocketmine\promise\Promise;
@ -1869,7 +1870,7 @@ class World implements ChunkManager{
if($player !== null){ if($player !== null){
$ev = new BlockBreakEvent($player, $target, $item, $player->isCreative(), $drops, $xpDrop); $ev = new BlockBreakEvent($player, $target, $item, $player->isCreative(), $drops, $xpDrop);
if($target instanceof Air || ($player->isSurvival() && !$target->getBreakInfo()->isBreakable()) || $player->isSpectator()){ if($target instanceof Air || ($player->isSurvival() && !$target->getBreakInfo()->isBreakable()) || !$player->hasPermission(DefaultPermissionNames::GAME_BLOCK_BREAK)){
$ev->cancel(); $ev->cancel();
} }
@ -1966,7 +1967,7 @@ class World implements ChunkManager{
if($player !== null){ if($player !== null){
$ev = new PlayerInteractEvent($player, $item, $blockClicked, $clickVector, $face, PlayerInteractEvent::RIGHT_CLICK_BLOCK); $ev = new PlayerInteractEvent($player, $item, $blockClicked, $clickVector, $face, PlayerInteractEvent::RIGHT_CLICK_BLOCK);
if($player->isSpectator()){ if(!$player->hasPermission(DefaultPermissionNames::GAME_BLOCK_INTERACT)){
$ev->cancel(); //set it to cancelled so plugins can bypass this $ev->cancel(); //set it to cancelled so plugins can bypass this
} }
@ -2020,7 +2021,7 @@ class World implements ChunkManager{
if($player !== null){ if($player !== null){
$ev = new BlockPlaceEvent($player, $hand, $blockReplace, $blockClicked, $item); $ev = new BlockPlaceEvent($player, $hand, $blockReplace, $blockClicked, $item);
if($player->isSpectator()){ if(!$player->hasPermission(DefaultPermissionNames::GAME_BLOCK_PLACE)){
$ev->cancel(); $ev->cancel();
} }