From 2f3f76c8cfa89fb204250c5804ead5f97edc17a3 Mon Sep 17 00:00:00 2001 From: sk89q Date: Fri, 16 Jan 2015 15:43:13 -0800 Subject: [PATCH] Funnel pre-allowed events too. Fixes WORLDGUARD-3308. --- .../worldguard/bukkit/event/BulkEvent.java | 13 +++-- .../bukkit/event/DelegateEvent.java | 38 ++++++++++-- .../bukkit/event/DelegateEvents.java | 17 ++++++ .../worldguard/bukkit/event/Handleable.java | 30 ++++++++++ .../event/block/AbstractBlockEvent.java | 24 ++++---- .../bukkit/listener/DebuggingListener.java | 29 +++++----- .../listener/EventAbstractionListener.java | 58 ++++++++++--------- .../listener/RegionProtectionListener.java | 8 +++ .../sk89q/worldguard/bukkit/util/Events.java | 2 +- 9 files changed, 156 insertions(+), 63 deletions(-) create mode 100644 src/main/java/com/sk89q/worldguard/bukkit/event/Handleable.java diff --git a/src/main/java/com/sk89q/worldguard/bukkit/event/BulkEvent.java b/src/main/java/com/sk89q/worldguard/bukkit/event/BulkEvent.java index 20df01b2..5675a743 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/event/BulkEvent.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/event/BulkEvent.java @@ -19,20 +19,21 @@ package com.sk89q.worldguard.bukkit.event; +import org.bukkit.event.Event.Result; + /** * A bulk event contains several affected objects in a list. */ public interface BulkEvent { /** - * Return whether the event is explicitly cancelled. + * Get the actual result. * - *

By default, bulk events will cancel itself if the number of affected - * objects drops to zero. This method returns the true cancellation - * status.

+ *

By default, bulk events will set the result to DENY if the number of + * affected objects drops to zero. This method returns the true result.

* - * @return true if really cancelled + * @return the explicit result */ - boolean isExplicitlyCancelled(); + Result getExplicitResult(); } diff --git a/src/main/java/com/sk89q/worldguard/bukkit/event/DelegateEvent.java b/src/main/java/com/sk89q/worldguard/bukkit/event/DelegateEvent.java index 2e3eb9fe..65b12d94 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/event/DelegateEvent.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/event/DelegateEvent.java @@ -34,13 +34,13 @@ * This event is an internal event. We do not recommend handling or throwing * this event or its subclasses as the interface is highly subject to change. */ -public abstract class DelegateEvent extends Event implements Cancellable { +public abstract class DelegateEvent extends Event implements Cancellable, Handleable { @Nullable private final Event originalEvent; private final Cause cause; private final List relevantFlags = Lists.newArrayList(); - private boolean cancelled; + private Result result = Result.DEFAULT; private boolean silent; /** @@ -85,12 +85,24 @@ public List getRelevantFlags() { @Override public boolean isCancelled() { - return cancelled; + return getResult() == Result.DENY; } @Override public void setCancelled(boolean cancel) { - this.cancelled = cancel; + if (cancel) { + setResult(Result.DENY); + } + } + + @Override + public Result getResult() { + return result; + } + + @Override + public void setResult(Result result) { + this.result = result; } /** @@ -106,9 +118,25 @@ public boolean isSilent() { * Set whether this should be a silent check. * * @param silent true if silent + * @return the same event */ - void setSilent(boolean silent) { + public DelegateEvent setSilent(boolean silent) { this.silent = silent; + return this; + } + + /** + * Set the event to {@link Result#ALLOW} if {@code allowed} is true. + * + * @param allowed true to set the result + * @return the same event + */ + public DelegateEvent setAllowed(boolean allowed) { + if (allowed) { + setResult(Result.ALLOW); + } + + return this; } } diff --git a/src/main/java/com/sk89q/worldguard/bukkit/event/DelegateEvents.java b/src/main/java/com/sk89q/worldguard/bukkit/event/DelegateEvents.java index d526e129..92379cf2 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/event/DelegateEvents.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/event/DelegateEvents.java @@ -19,6 +19,8 @@ package com.sk89q.worldguard.bukkit.event; +import org.bukkit.event.Event.Result; + /** * Utility methods for dealing with delegate events. */ @@ -52,4 +54,19 @@ public static T setSilent(T event, boolean silent) { return event; } + /** + * Set an event as handled as {@link Result#ALLOW} if {@code allowed} is + * true, otherwise do nothing. + * + * @param event the event + * @param the type of event + * @return the same event + */ + public static T setAllowed(T event, boolean allowed) { + if (allowed) { + event.setResult(Result.ALLOW); + } + return event; + } + } diff --git a/src/main/java/com/sk89q/worldguard/bukkit/event/Handleable.java b/src/main/java/com/sk89q/worldguard/bukkit/event/Handleable.java new file mode 100644 index 00000000..f521287a --- /dev/null +++ b/src/main/java/com/sk89q/worldguard/bukkit/event/Handleable.java @@ -0,0 +1,30 @@ +/* + * WorldGuard, a suite of tools for Minecraft + * Copyright (C) sk89q + * Copyright (C) WorldGuard team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldguard.bukkit.event; + +import org.bukkit.event.Event.Result; + +public interface Handleable { + + Result getResult(); + + void setResult(Result result); + +} diff --git a/src/main/java/com/sk89q/worldguard/bukkit/event/block/AbstractBlockEvent.java b/src/main/java/com/sk89q/worldguard/bukkit/event/block/AbstractBlockEvent.java index 7a3a52c4..f40564e0 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/event/block/AbstractBlockEvent.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/event/block/AbstractBlockEvent.java @@ -70,16 +70,6 @@ private static List createList(Block block) { return blocks; } - @Override - public boolean isCancelled() { - return super.isCancelled() || blocks.isEmpty(); - } - - @Override - public boolean isExplicitlyCancelled() { - return super.isCancelled(); - } - /** * Get the world. * @@ -153,4 +143,18 @@ public boolean filter(Predicate predicate) { public Material getEffectiveMaterial() { return effectiveMaterial; } + + @Override + public Result getResult() { + if (blocks.isEmpty()) { + return Result.DENY; + } + return super.getResult(); + } + + @Override + public Result getExplicitResult() { + return super.getResult(); + } + } diff --git a/src/main/java/com/sk89q/worldguard/bukkit/listener/DebuggingListener.java b/src/main/java/com/sk89q/worldguard/bukkit/listener/DebuggingListener.java index 3f527b4c..94ec49b5 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/listener/DebuggingListener.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/listener/DebuggingListener.java @@ -30,6 +30,7 @@ import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.event.Event; +import org.bukkit.event.Event.Result; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -67,8 +68,8 @@ public void onPlaceBlock(PlaceBlockEvent event) { builder.append("[").append(event.getCause()).append("]"); builder.append(" "); builder.append(":").append(getEventName(event.getOriginalEvent())); - if (event.isCancelled()) { - builder.append(" [CANCELLED]"); + if (event.getResult() != Result.DEFAULT) { + builder.append(" [").append(event.getResult()).append("]"); } logger.info(builder.toString()); } @@ -85,8 +86,8 @@ public void onBreakBlock(BreakBlockEvent event) { builder.append("@").append(toBlockString(event.getBlocks())); builder.append(" "); builder.append(":").append(getEventName(event.getOriginalEvent())); - if (event.isCancelled()) { - builder.append(" [CANCELLED]"); + if (event.getResult() != Result.DEFAULT) { + builder.append(" [").append(event.getResult()).append("]"); } logger.info(builder.toString()); } @@ -103,8 +104,8 @@ public void onUseBlock(UseBlockEvent event) { builder.append("@").append(toBlockString(event.getBlocks())); builder.append(" "); builder.append(":").append(getEventName(event.getOriginalEvent())); - if (event.isCancelled()) { - builder.append(" [CANCELLED]"); + if (event.getResult() != Result.DEFAULT) { + builder.append(" [").append(event.getResult()).append("]"); } logger.info(builder.toString()); } @@ -121,8 +122,8 @@ public void onSpawnEntity(SpawnEntityEvent event) { builder.append("@").append(toBlockString(event.getTarget())); builder.append(" "); builder.append(":").append(getEventName(event.getOriginalEvent())); - if (event.isCancelled()) { - builder.append(" [CANCELLED]"); + if (event.getResult() != Result.DEFAULT) { + builder.append(" [").append(event.getResult()).append("]"); } logger.info(builder.toString()); } @@ -139,8 +140,8 @@ public void onDestroyEntity(DestroyEntityEvent event) { builder.append("@").append(toBlockString(event.getTarget())); builder.append(" "); builder.append(":").append(getEventName(event.getOriginalEvent())); - if (event.isCancelled()) { - builder.append(" [CANCELLED]"); + if (event.getResult() != Result.DEFAULT) { + builder.append(" [").append(event.getResult()).append("]"); } logger.info(builder.toString()); } @@ -157,8 +158,8 @@ public void onUseEntity(UseEntityEvent event) { builder.append("@").append(toBlockString(event.getTarget())); builder.append(" "); builder.append(":").append(getEventName(event.getOriginalEvent())); - if (event.isCancelled()) { - builder.append(" [CANCELLED]"); + if (event.getResult() != Result.DEFAULT) { + builder.append(" [").append(event.getResult()).append("]"); } logger.info(builder.toString()); } @@ -175,8 +176,8 @@ public void onUseItem(UseItemEvent event) { builder.append("@").append(event.getWorld().getName()); builder.append(" "); builder.append(":").append(getEventName(event.getOriginalEvent())); - if (event.isCancelled()) { - builder.append(" [CANCELLED]"); + if (event.getResult() != Result.DEFAULT) { + builder.append(" [").append(event.getResult()).append("]"); } logger.info(builder.toString()); } diff --git a/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java b/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java index 5d2c5ca7..46e06c2f 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java @@ -24,7 +24,6 @@ import com.sk89q.worldguard.bukkit.WorldGuardPlugin; import com.sk89q.worldguard.bukkit.cause.Cause; import com.sk89q.worldguard.bukkit.event.DelegateEvent; -import com.sk89q.worldguard.bukkit.event.DelegateEvents; import com.sk89q.worldguard.bukkit.event.block.BreakBlockEvent; import com.sk89q.worldguard.bukkit.event.block.PlaceBlockEvent; import com.sk89q.worldguard.bukkit.event.block.UseBlockEvent; @@ -304,6 +303,7 @@ public void onPlayerInteract(PlayerInteractEvent event) { Block clicked = event.getClickedBlock(); Block placed; boolean silent = false; + boolean modifiesWorld; Cause cause = create(player); switch (event.getAction()) { @@ -313,9 +313,8 @@ public void onPlayerInteract(PlayerInteractEvent event) { silent = true; } - if (!hasInteractBypass(clicked)) { - interactDebounce.debounce(clicked, event.getPlayer(), event, DelegateEvents.setSilent(new UseBlockEvent(event, cause, clicked), silent)); - } + interactDebounce.debounce(clicked, event.getPlayer(), event, + new UseBlockEvent(event, cause, clicked).setSilent(silent).setAllowed(hasInteractBypass(clicked))); break; case RIGHT_CLICK_BLOCK: @@ -328,17 +327,17 @@ public void onPlayerInteract(PlayerInteractEvent event) { placed = clicked.getRelative(event.getBlockFace()); // Only fire events for blocks that are modified when right clicked - if (isBlockModifiedOnClick(clicked, event.getAction() == Action.RIGHT_CLICK_BLOCK) || (item != null && isItemAppliedToBlock(item, clicked))) { - if (Events.fireAndTestCancel(new UseBlockEvent(event, cause, clicked))) { - event.setUseInteractedBlock(Result.DENY); - } + 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))) { - event.setUseInteractedBlock(Result.DENY); - break; - } + if (Events.fireAndTestCancel(new UseBlockEvent(event, cause, clicked).setAllowed(!modifiesWorld))) { + event.setUseInteractedBlock(Result.DENY); + } + + // 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; } } @@ -377,9 +376,8 @@ public void onPlayerInteract(PlayerInteractEvent event) { @EventHandler(ignoreCancelled = true) public void onEntityInteract(org.bukkit.event.entity.EntityInteractEvent event) { - if (!hasInteractBypass(event.getBlock())) { - interactDebounce.debounce(event.getBlock(), event.getEntity(), event, new UseBlockEvent(event, create(event.getEntity()), event.getBlock())); - } + interactDebounce.debounce(event.getBlock(), event.getEntity(), event, + new UseBlockEvent(event, create(event.getEntity()), event.getBlock()).setAllowed(hasInteractBypass(event.getBlock()))); } @EventHandler(ignoreCancelled = true) @@ -420,15 +418,18 @@ public void onBedEnter(PlayerBedEnterEvent event) { public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event) { Player player = event.getPlayer(); Block blockAffected = event.getBlockClicked().getRelative(event.getBlockFace()); + boolean allowed = false; // Milk buckets can't be emptied as of writing - if (event.getBucket() != Material.MILK_BUCKET) { - ItemStack item = new ItemStack(event.getBucket(), 1); - Material blockMaterial = Materials.getBucketBlockMaterial(event.getBucket()); - Events.fireToCancel(event, new PlaceBlockEvent(event, create(player), blockAffected.getLocation(), blockMaterial)); - Events.fireToCancel(event, new UseItemEvent(event, create(player), player.getWorld(), item)); + if (event.getBucket() == Material.MILK_BUCKET) { + allowed = true; } + ItemStack item = new ItemStack(event.getBucket(), 1); + Material blockMaterial = Materials.getBucketBlockMaterial(event.getBucket()); + Events.fireToCancel(event, new PlaceBlockEvent(event, create(player), blockAffected.getLocation(), blockMaterial).setAllowed(allowed)); + Events.fireToCancel(event, new UseItemEvent(event, create(player), player.getWorld(), item).setAllowed(allowed)); + playDenyEffect(event.getPlayer(), blockAffected.getLocation().add(0.5, 0.5, 0.5)); } @@ -436,14 +437,17 @@ public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event) { public void onPlayerBucketFill(PlayerBucketFillEvent event) { Player player = event.getPlayer(); Block blockAffected = event.getBlockClicked().getRelative(event.getBlockFace()); + boolean allowed = false; - // Milk buckets can't be filled by right clicking the ground as of writing - if (event.getBucket() != Material.MILK_BUCKET) { - ItemStack item = new ItemStack(event.getBucket(), 1); - Events.fireToCancel(event, new BreakBlockEvent(event, create(player), blockAffected)); - Events.fireToCancel(event, new UseItemEvent(event, create(player), player.getWorld(), item)); + // Milk buckets can't be emptied as of writing + if (event.getBucket() == Material.MILK_BUCKET) { + allowed = true; } + ItemStack item = new ItemStack(event.getBucket(), 1); + Events.fireToCancel(event, new BreakBlockEvent(event, create(player), blockAffected).setAllowed(allowed)); + Events.fireToCancel(event, new UseItemEvent(event, create(player), player.getWorld(), item).setAllowed(allowed)); + playDenyEffect(event.getPlayer(), blockAffected.getLocation().add(0.5, 1, 0.5)); } diff --git a/src/main/java/com/sk89q/worldguard/bukkit/listener/RegionProtectionListener.java b/src/main/java/com/sk89q/worldguard/bukkit/listener/RegionProtectionListener.java index 26b9dd28..af1b6f37 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/listener/RegionProtectionListener.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/listener/RegionProtectionListener.java @@ -48,6 +48,7 @@ import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.entity.*; +import org.bukkit.event.Event.Result; import org.bukkit.event.EventHandler; import org.bukkit.event.vehicle.VehicleExitEvent; @@ -153,6 +154,7 @@ private RegionAssociable createRegionAssociable(Cause cause) { @EventHandler(ignoreCancelled = true) public void onPlaceBlock(final PlaceBlockEvent event) { + if (event.getResult() == Result.ALLOW) return; // Don't care about events that have been pre-allowed if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled if (isWhitelisted(event.getCause(), event.getWorld(), false)) return; // Whitelisted cause @@ -196,6 +198,7 @@ public boolean apply(Location target) { @EventHandler(ignoreCancelled = true) public void onBreakBlock(final BreakBlockEvent event) { + if (event.getResult() == Result.ALLOW) return; // Don't care about events that have been pre-allowed if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled if (isWhitelisted(event.getCause(), event.getWorld(), false)) return; // Whitelisted cause @@ -234,6 +237,7 @@ public boolean apply(Location target) { @EventHandler(ignoreCancelled = true) public void onUseBlock(final UseBlockEvent event) { + if (event.getResult() == Result.ALLOW) return; // Don't care about events that have been pre-allowed if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled if (isWhitelisted(event.getCause(), event.getWorld(), false)) return; // Whitelisted cause @@ -290,6 +294,7 @@ public boolean apply(Location target) { @EventHandler(ignoreCancelled = true) public void onSpawnEntity(SpawnEntityEvent event) { + if (event.getResult() == Result.ALLOW) return; // Don't care about events that have been pre-allowed if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled if (isWhitelisted(event.getCause(), event.getWorld(), false)) return; // Whitelisted cause @@ -336,6 +341,7 @@ public void onSpawnEntity(SpawnEntityEvent event) { @EventHandler(ignoreCancelled = true) public void onDestroyEntity(DestroyEntityEvent event) { + if (event.getResult() == Result.ALLOW) return; // Don't care about events that have been pre-allowed if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled if (isWhitelisted(event.getCause(), event.getWorld(), false)) return; // Whitelisted cause @@ -371,6 +377,7 @@ public void onDestroyEntity(DestroyEntityEvent event) { @EventHandler(ignoreCancelled = true) public void onUseEntity(UseEntityEvent event) { + if (event.getResult() == Result.ALLOW) return; // Don't care about events that have been pre-allowed if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled if (isWhitelisted(event.getCause(), event.getWorld(), false)) return; // Whitelisted cause @@ -410,6 +417,7 @@ public void onUseEntity(UseEntityEvent event) { @EventHandler(ignoreCancelled = true) public void onDamageEntity(DamageEntityEvent event) { + if (event.getResult() == Result.ALLOW) return; // Don't care about events that have been pre-allowed if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled // Whitelist check is below diff --git a/src/main/java/com/sk89q/worldguard/bukkit/util/Events.java b/src/main/java/com/sk89q/worldguard/bukkit/util/Events.java index 0feee09f..a42d75a5 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/util/Events.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/util/Events.java @@ -110,7 +110,7 @@ public static boolean fireItemEventToCancel(Play */ public static boolean fireBulkEventToCancel(Cancellable original, T eventToFire) { Bukkit.getServer().getPluginManager().callEvent(eventToFire); - if (eventToFire.isExplicitlyCancelled()) { + if (eventToFire.getExplicitResult() == Result.DENY) { original.setCancelled(true); return true; }