#Check if a player can build in a specific location

1 messages · Page 1 of 1 (latest)

final sundial
#

How can I check if a player can build in a specific location? I have a block.setType(material) method and I want to only execute it if at the location of the block the player is able to build.

modest plaza
#

i guess you have some kind of protection plugin like worldguard?

final sundial
#

I don't have a specific one, no

modest plaza
#

would be easier to have such a plugin that will block it for you only let your blockplace event have a lower priority than wordguard

#

so it wont run if worldguard says no

final sundial
#

If a server has other plugins that don't use worldguard and still cancel block place event in specific regions, would I still be able to check with worldguard if a player cannot place in those regions?

modest plaza
#

well the listeners with the higher priority will decide what finally happens

#

actually just having a monitor priority and blocking the listener when the event is cancelled will work too

#
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onBlockPlace() {}```
final sundial
#

is there a way to call the event? because i don't think that block.setType() triggers the event, and the player is not actually the one placing the block.

modest plaza
#

wdym call the event?

#

ah i understand

final sundial
#

to call the event from code (instead of Bukkit calling it)

modest plaza
#

maybe thats the easiest way

#

hoping other plugins dont do weird stuff with it

bitter dagger
modest plaza
#

i k

final sundial
#

The point is not to change event, just to check if it is cancelled or not

bitter dagger
#

It was for molioron, if one day he need to

bitter dagger
final sundial
#

BlockPlaceEvent(Block placedBlock, BlockState replacedBlockState, Block placedAgainst, ItemStack itemInHand, Player thePlayer, boolean canBuild, EquipmentSlot hand)
Btw, if I want to create an instance of an event (in order to call it to check if a different plugin cancels it or not), I need to pass it the placedBlock. Problem is that the block has yet to be placed (I want to call the event before block.setType). is there a way to create a Block instance that does not actually exist in a world?

final sundial
#

the actual block that is the literal block placed in the world

final sundial
#

Welp, I think I have managed to do it. for anyone wondering:

    /**
     * Whether a given player can place a block in a certain location
     * @param player the given player
     * @param block the block where to place
     * @param newMaterial the new material to replace the old one
     * @return true if the player can place a block there, otherwise false.
     */
    public boolean canPlaceBlock(Player player, Block block, Material newMaterial)
    {
        // the old material before "placing"
        Material oldMaterial = block.getType();
        // the state of the block before it was placed
        BlockState replacedState = block.getState();
        // the location under the block
        Location blockUnderLocation = block.getLocation(); // currently, not under
        blockUnderLocation.add(0,-1,0); // make the block, under
        // the block that the given block was "placed against" (not really because it was never placed)
        Block placedAgainst = blockUnderLocation.getBlock();
        block.setType(newMaterial); // *temporarily* set material

        // the place event
        BlockPlaceEvent placeEvent = new BlockPlaceEvent(block, replacedState, placedAgainst,
                new ItemStack(newMaterial, 1), player, true, EquipmentSlot.HAND);
        Bukkit.getServer().getPluginManager().callEvent(placeEvent);
        // whether the event got cancelled or not
        boolean isCancelled = placeEvent.isCancelled();
        block.setType(oldMaterial); // return old material

        return !isCancelled;
    }