Funnel pre-allowed events too.

Fixes WORLDGUARD-3308.
This commit is contained in:
sk89q 2015-01-16 15:43:13 -08:00
parent a03aaa45b1
commit 2f3f76c8cf
9 changed files with 156 additions and 63 deletions

View File

@ -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.
*
* <p>By default, bulk events will cancel itself if the number of affected
* objects drops to zero. This method returns the true cancellation
* status.</p>
* <p>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.</p>
*
* @return true if really cancelled
* @return the explicit result
*/
boolean isExplicitlyCancelled();
Result getExplicitResult();
}

View File

@ -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<StateFlag> relevantFlags = Lists.newArrayList();
private boolean cancelled;
private Result result = Result.DEFAULT;
private boolean silent;
/**
@ -85,12 +85,24 @@ public List<StateFlag> 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;
}
}

View File

@ -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 extends DelegateEvent> 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 <T> the type of event
* @return the same event
*/
public static <T extends Handleable> T setAllowed(T event, boolean allowed) {
if (allowed) {
event.setResult(Result.ALLOW);
}
return event;
}
}

View File

@ -0,0 +1,30 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* 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 <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.event;
import org.bukkit.event.Event.Result;
public interface Handleable {
Result getResult();
void setResult(Result result);
}

View File

@ -70,16 +70,6 @@ private static List<Block> 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<Location> 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();
}
}

View File

@ -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());
}

View File

@ -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));
}

View File

@ -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

View File

@ -110,7 +110,7 @@ public static <T extends Event & Cancellable> boolean fireItemEventToCancel(Play
*/
public static <T extends Event & Cancellable & BulkEvent> boolean fireBulkEventToCancel(Cancellable original, T eventToFire) {
Bukkit.getServer().getPluginManager().callEvent(eventToFire);
if (eventToFire.isExplicitlyCancelled()) {
if (eventToFire.getExplicitResult() == Result.DENY) {
original.setCancelled(true);
return true;
}