Skip to content

Commit

Permalink
Switch to useInteractedBlock/useItemInHand for PlayerInteractEvent.
Browse files Browse the repository at this point in the history
Bukkit has very odd behavior regarding cancelling this event.

Fixes WORLDGUARD-4090.
  • Loading branch information
wizjany committed May 22, 2019
1 parent c4b31cf commit 4871752
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 49 deletions.
Expand Up @@ -36,10 +36,23 @@ public LoggingPlayerInteractEvent(Player who, Action action, ItemStack item, Blo
super(who, action, item, clickedBlock, clickedFace);
}

@Override
public List<CancelAttempt> getCancels() {
return logger.getCancels();
}

@Override
public void setUseInteractedBlock(Result useInteractedBlock) {
this.logger.log(useInteractedBlock() == Result.DENY, useInteractedBlock == Result.DENY, new Exception().getStackTrace());
super.setUseInteractedBlock(useInteractedBlock);
}

@Override
public void setUseItemInHand(Result useItemInHand) {
this.logger.log(useItemInHand() == Result.DENY, useItemInHand == Result.DENY, new Exception().getStackTrace());
super.setUseItemInHand(useItemInHand);
}

@Override
public void setCancelled(boolean cancel) {
this.logger.log(isCancelled(), cancel, new Exception().getStackTrace());
Expand Down
Expand Up @@ -384,7 +384,7 @@ public void onBlockDamage(BlockDamageEvent event) {
}
}

@EventHandler(ignoreCancelled = true)
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
Player player = event.getPlayer();
@Nullable ItemStack item = event.getItem();
Expand All @@ -396,59 +396,66 @@ public void onPlayerInteract(PlayerInteractEvent event) {

switch (event.getAction()) {
case PHYSICAL:
DelegateEvent firedEvent = new UseBlockEvent(event, cause, clicked).setAllowed(hasInteractBypass(clicked));
if (clicked.getType() == Material.REDSTONE_ORE) {
silent = true;
}
if (clicked.getType() == Material.FARMLAND || clicked.getType() == Material.TURTLE_EGG) {
silent = true;
firedEvent.getRelevantFlags().add(Flags.TRAMPLE_BLOCKS);
if (event.useInteractedBlock() != Result.DENY) {
DelegateEvent firedEvent = new UseBlockEvent(event, cause, clicked).setAllowed(hasInteractBypass(clicked));
if (clicked.getType() == Material.REDSTONE_ORE) {
silent = true;
}
if (clicked.getType() == Material.FARMLAND || clicked.getType() == Material.TURTLE_EGG) {
silent = true;
firedEvent.getRelevantFlags().add(Flags.TRAMPLE_BLOCKS);
}
firedEvent.setSilent(silent);
interactDebounce.debounce(clicked, event.getPlayer(), event, firedEvent);
}
firedEvent.setSilent(silent);
interactDebounce.debounce(clicked, event.getPlayer(), event, firedEvent);
break;

case RIGHT_CLICK_BLOCK:
placed = clicked.getRelative(event.getBlockFace());
if (event.useInteractedBlock() != Result.DENY) {
placed = clicked.getRelative(event.getBlockFace());

// Re-used for dispensers
handleBlockRightClick(event, create(event.getPlayer()), item, clicked, event.getBlockFace(), placed);
// Re-used for dispensers
handleBlockRightClick(event, create(event.getPlayer()), item, clicked, event.getBlockFace(), placed);
}

case LEFT_CLICK_BLOCK:
placed = clicked.getRelative(event.getBlockFace());

// Only fire events for blocks that are modified when right clicked
modifiesWorld = isBlockModifiedOnClick(clicked, event.getAction() == Action.RIGHT_CLICK_BLOCK) || (item != null && isItemAppliedToBlock(item, clicked));
if (event.useInteractedBlock() != Result.DENY) {
placed = clicked.getRelative(event.getBlockFace());

if (Events.fireAndTestCancel(new UseBlockEvent(event, cause, clicked).setAllowed(!modifiesWorld))) {
event.setUseInteractedBlock(Result.DENY);
}
// Only fire events for blocks that are modified when right clicked
modifiesWorld = isBlockModifiedOnClick(clicked, event.getAction() == Action.RIGHT_CLICK_BLOCK) || (item != null && isItemAppliedToBlock(item, clicked));

// Handle connected blocks (i.e. beds, chests)
for (Block connected : Blocks.getConnected(clicked)) {
if (Events.fireAndTestCancel(new UseBlockEvent(event, create(event.getPlayer()), connected).setAllowed(!modifiesWorld))) {
if (Events.fireAndTestCancel(new UseBlockEvent(event, cause, clicked).setAllowed(!modifiesWorld))) {
event.setUseInteractedBlock(Result.DENY);
break;
}
}

// Special handling of putting out fires
if (event.getAction() == Action.LEFT_CLICK_BLOCK && placed.getType() == Material.FIRE) {
if (Events.fireAndTestCancel(new BreakBlockEvent(event, create(event.getPlayer()), placed))) {
event.setUseInteractedBlock(Result.DENY);
break;
// Handle connected blocks (i.e. beds, chests)
for (Block connected : Blocks.getConnected(clicked)) {
if (Events.fireAndTestCancel(new UseBlockEvent(event, create(event.getPlayer()), connected).setAllowed(!modifiesWorld))) {
event.setUseInteractedBlock(Result.DENY);
break;
}
}
}

if (event.isCancelled()) {
playDenyEffect(event.getPlayer(), clicked.getLocation().add(0.5, 1, 0.5));
// Special handling of putting out fires
if (event.getAction() == Action.LEFT_CLICK_BLOCK && placed.getType() == Material.FIRE) {
if (Events.fireAndTestCancel(new BreakBlockEvent(event, create(event.getPlayer()), placed))) {
event.setUseInteractedBlock(Result.DENY);
break;
}
}

if (event.isCancelled()) {
playDenyEffect(event.getPlayer(), clicked.getLocation().add(0.5, 1, 0.5));
}
}

case LEFT_CLICK_AIR:
case RIGHT_CLICK_AIR:
if (item != null && !item.getType().isBlock() && Events.fireAndTestCancel(new UseItemEvent(event, cause, player.getWorld(), item))) {
event.setUseItemInHand(Result.DENY);
event.setCancelled(true); // The line above does not appear to work with spawn eggs
if (event.useItemInHand() != Result.DENY) {
if (item != null && !item.getType().isBlock() && Events.fireAndTestCancel(new UseItemEvent(event, cause, player.getWorld(), item))) {
event.setUseItemInHand(Result.DENY);
}
}

// Check for items that the administrator has configured to
Expand All @@ -457,7 +464,7 @@ public void onPlayerInteract(PlayerInteractEvent event) {
// throw events
if (item != null && ((BukkitWorldConfiguration) getWorldConfig(BukkitAdapter.adapt(player.getWorld()))).blockUseAtFeet.test(item)) {
if (Events.fireAndTestCancel(new UseBlockEvent(event, cause, player.getLocation().getBlock()))) {
event.setCancelled(true);
event.setUseInteractedBlock(Result.DENY);
}
}

Expand Down
Expand Up @@ -26,6 +26,7 @@
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.event.player.ProcessPlayerEvent;
import com.sk89q.worldguard.bukkit.util.Events;
import com.sk89q.worldguard.bukkit.util.Materials;
import com.sk89q.worldguard.config.ConfigurationManager;
import com.sk89q.worldguard.config.WorldConfiguration;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
Expand All @@ -47,6 +48,7 @@
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
Expand Down Expand Up @@ -249,7 +251,7 @@ public void onPlayerInteract(PlayerInteractEvent event) {
* @param event Thrown event
*/
private void handleBlockRightClick(PlayerInteractEvent event) {
if (event.isCancelled()) {
if (event.useItemInHand() == Event.Result.DENY) {
return;
}

Expand All @@ -263,14 +265,7 @@ private void handleBlockRightClick(PlayerInteractEvent event) {
WorldConfiguration wcfg = cfg.get(BukkitAdapter.adapt(world));

// Infinite stack removal
if ((type == Material.CHEST
|| type == Material.JUKEBOX
|| type == Material.DISPENSER
|| type == Material.FURNACE
|| type == Material.DROPPER
|| type == Material.BREWING_STAND
|| type == Material.TRAPPED_CHEST
|| type == Material.ENCHANTING_TABLE)
if (Materials.isInventoryBlock(type)
&& wcfg.removeInfiniteStacks
&& !plugin.hasPermission(player, "worldguard.override.infinite-stack")) {
for (int slot = 0; slot < 40; slot++) {
Expand Down Expand Up @@ -301,12 +296,12 @@ private void handleBlockRightClick(PlayerInteractEvent event) {
}
}

localPlayer.print("Applicable regions: " + str.toString());
localPlayer.print("Applicable regions: " + str);
} else {
localPlayer.print("WorldGuard: No defined regions here!");
}

event.setCancelled(true);
event.setUseItemInHand(Event.Result.DENY);
}
}
}
Expand All @@ -317,7 +312,7 @@ private void handleBlockRightClick(PlayerInteractEvent event) {
* @param event Thrown event
*/
private void handlePhysicalInteract(PlayerInteractEvent event) {
if (event.isCancelled()) return;
if (event.useInteractedBlock() == Event.Result.DENY) return;

Player player = event.getPlayer();
Block block = event.getClickedBlock(); //not actually clicked but whatever
Expand Down

0 comments on commit 4871752

Please sign in to comment.