Fix the splash potion flag not working with the other flags.

Fixes WORLDGUARD-3274.
This commit is contained in:
sk89q 2015-01-06 15:00:13 -08:00
parent 37a80338f5
commit da032cb04e
5 changed files with 76 additions and 66 deletions

View File

@ -19,11 +19,14 @@
package com.sk89q.worldguard.bukkit.event;
import com.google.common.collect.Lists;
import com.sk89q.worldguard.bukkit.cause.Cause;
import com.sk89q.worldguard.protection.flags.StateFlag;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import javax.annotation.Nullable;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
@ -36,6 +39,7 @@ public abstract class DelegateEvent extends Event implements Cancellable {
@Nullable
private final Event originalEvent;
private final Cause cause;
private final List<StateFlag> relevantFlags = Lists.newArrayList();
private boolean cancelled;
private boolean silent;
@ -70,6 +74,15 @@ public Cause getCause() {
return cause;
}
/**
* Get a list of relevant flags to consider for this event.
*
* @return A list of relevant flags
*/
public List<StateFlag> getRelevantFlags() {
return relevantFlags;
}
@Override
public boolean isCancelled() {
return cancelled;

View File

@ -28,7 +28,10 @@
import com.sk89q.worldguard.bukkit.event.block.BreakBlockEvent;
import com.sk89q.worldguard.bukkit.event.block.PlaceBlockEvent;
import com.sk89q.worldguard.bukkit.event.block.UseBlockEvent;
import com.sk89q.worldguard.bukkit.event.entity.*;
import com.sk89q.worldguard.bukkit.event.entity.DamageEntityEvent;
import com.sk89q.worldguard.bukkit.event.entity.DestroyEntityEvent;
import com.sk89q.worldguard.bukkit.event.entity.SpawnEntityEvent;
import com.sk89q.worldguard.bukkit.event.entity.UseEntityEvent;
import com.sk89q.worldguard.bukkit.event.inventory.UseItemEvent;
import com.sk89q.worldguard.bukkit.listener.debounce.BlockPistonExtendKey;
import com.sk89q.worldguard.bukkit.listener.debounce.BlockPistonRetractKey;
@ -40,6 +43,7 @@
import com.sk89q.worldguard.bukkit.util.Blocks;
import com.sk89q.worldguard.bukkit.util.Events;
import com.sk89q.worldguard.bukkit.util.Materials;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import org.bukkit.*;
import org.bukkit.block.*;
import org.bukkit.entity.*;
@ -731,7 +735,7 @@ public void onPotionSplash(PotionSplashEvent event) {
Entity entity = event.getEntity();
ThrownPotion potion = event.getPotion();
World world = entity.getWorld();
Cause cause = create(potion.getShooter());
Cause cause = create(potion);
// Fire item interaction event
Events.fireToCancel(event, new UseItemEvent(event, cause, world, potion.getItem()));
@ -746,6 +750,9 @@ public void onPotionSplash(PotionSplashEvent event) {
? new DamageEntityEvent(event, cause, affected) :
new UseEntityEvent(event, cause, affected);
// Consider the potion splash flag
delegate.getRelevantFlags().add(DefaultFlag.POTION_SPLASH);
if (Events.fireAndTestCancel(delegate)) {
event.setIntensity(affected, 0);
blocked++;

View File

@ -32,33 +32,28 @@
import com.sk89q.worldguard.bukkit.event.entity.DestroyEntityEvent;
import com.sk89q.worldguard.bukkit.event.entity.SpawnEntityEvent;
import com.sk89q.worldguard.bukkit.event.entity.UseEntityEvent;
import com.sk89q.worldguard.bukkit.internal.WGMetadata;
import com.sk89q.worldguard.bukkit.permission.RegionPermissionModel;
import com.sk89q.worldguard.bukkit.protection.DelayedRegionOverlapAssociation;
import com.sk89q.worldguard.bukkit.util.Entities;
import com.sk89q.worldguard.bukkit.util.Events;
import com.sk89q.worldguard.bukkit.util.Materials;
import com.sk89q.worldguard.bukkit.internal.WGMetadata;
import com.sk89q.worldguard.domains.Association;
import com.sk89q.worldguard.protection.association.Associables;
import com.sk89q.worldguard.protection.association.RegionAssociable;
import com.sk89q.worldguard.protection.events.DisallowedPVPEvent;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.flags.StateFlag.State;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.ExperienceOrb;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.*;
import org.bukkit.event.EventHandler;
import org.bukkit.event.vehicle.VehicleExitEvent;
import java.util.Arrays;
import java.util.List;
/**
* Handle events that need to be processed by region protection.
*/
@ -112,6 +107,7 @@ private void tellErrorMessage(DelegateEvent event, Cause cause, Location locatio
* Return whether the given cause is whitelist (should be ignored).
*
* @param cause the cause
* @param world the world
* @return true if whitelisted
*/
private boolean isWhitelisted(Cause cause, World world) {
@ -178,12 +174,12 @@ public boolean apply(Location target) {
/* Flint and steel, fire charge, etc. */
if (type == Material.FIRE) {
canPlace = query.testBuild(target, associable, DefaultFlag.BLOCK_PLACE, DefaultFlag.LIGHTER);
canPlace = query.testBuild(target, associable, combine(event, DefaultFlag.BLOCK_PLACE, DefaultFlag.LIGHTER));
what = "place fire";
/* Everything else */
} else {
canPlace = query.testBuild(target, associable, DefaultFlag.BLOCK_PLACE);
canPlace = query.testBuild(target, associable, combine(event, DefaultFlag.BLOCK_PLACE));
what = "place that block";
}
@ -215,12 +211,12 @@ public boolean apply(Location target) {
/* TNT */
if (event.getCause().find(EntityType.PRIMED_TNT, EntityType.PRIMED_TNT) != null) {
canBreak = query.testBuild(target, associable, DefaultFlag.BLOCK_BREAK, DefaultFlag.TNT);
canBreak = query.testBuild(target, associable, combine(event, DefaultFlag.BLOCK_BREAK, DefaultFlag.TNT));
what = "dynamite blocks";
/* Everything else */
} else {
canBreak = query.testBuild(target, associable, DefaultFlag.BLOCK_BREAK);
canBreak = query.testBuild(target, associable, combine(event, DefaultFlag.BLOCK_BREAK));
what = "break that block";
}
@ -252,32 +248,32 @@ public boolean apply(Location target) {
/* Saplings, etc. */
if (Materials.isConsideredBuildingIfUsed(type)) {
canUse = query.testBuild(target, associable);
canUse = query.testBuild(target, associable, combine(event));
what = "use that";
/* Inventory */
} else if (Materials.isInventoryBlock(type)) {
canUse = query.testBuild(target, associable, DefaultFlag.INTERACT, DefaultFlag.CHEST_ACCESS);
canUse = query.testBuild(target, associable, combine(event, DefaultFlag.INTERACT, DefaultFlag.CHEST_ACCESS));
what = "open that";
/* Beds */
} else if (type == Material.BED_BLOCK) {
canUse = query.testBuild(target, associable, DefaultFlag.INTERACT, DefaultFlag.SLEEP);
canUse = query.testBuild(target, associable, combine(event, DefaultFlag.INTERACT, DefaultFlag.SLEEP));
what = "sleep";
/* TNT */
} else if (type == Material.TNT) {
canUse = query.testBuild(target, associable, DefaultFlag.INTERACT, DefaultFlag.TNT);
canUse = query.testBuild(target, associable, combine(event, DefaultFlag.INTERACT, DefaultFlag.TNT));
what = "use explosives";
/* Legacy USE flag */
} else if (Materials.isUseFlagApplicable(type)) {
canUse = query.testBuild(target, associable, DefaultFlag.INTERACT, DefaultFlag.USE);
canUse = query.testBuild(target, associable, combine(event, DefaultFlag.INTERACT, DefaultFlag.USE));
what = "use that";
/* Everything else */
} else {
canUse = query.testBuild(target, associable, DefaultFlag.INTERACT);
canUse = query.testBuild(target, associable, combine(event, DefaultFlag.INTERACT));
what = "use that";
}
@ -307,22 +303,22 @@ public void onSpawnEntity(SpawnEntityEvent event) {
/* Vehicles */
if (Entities.isVehicle(type)) {
canSpawn = query.testBuild(target, associable, DefaultFlag.PLACE_VEHICLE);
canSpawn = query.testBuild(target, associable, combine(event, DefaultFlag.PLACE_VEHICLE));
what = "place vehicles";
/* Item pickup */
} else if (event.getEntity() instanceof Item) {
canSpawn = query.testBuild(target, associable, DefaultFlag.ITEM_DROP);
canSpawn = query.testBuild(target, associable, combine(event, DefaultFlag.ITEM_DROP));
what = "drop items";
/* XP drops */
} else if (event.getEffectiveType() == EntityType.EXPERIENCE_ORB) {
canSpawn = query.testBuild(target, associable, DefaultFlag.EXP_DROPS);
canSpawn = query.testBuild(target, associable, combine(event, DefaultFlag.EXP_DROPS));
what = "drop XP";
/* Everything else */
} else {
canSpawn = query.testBuild(target, associable);
canSpawn = query.testBuild(target, associable, combine(event));
if (event.getEntity() instanceof Item) {
what = "drop items";
@ -352,17 +348,17 @@ public void onDestroyEntity(DestroyEntityEvent event) {
/* Vehicles */
if (Entities.isVehicle(type)) {
canDestroy = query.testBuild(target, associable, DefaultFlag.DESTROY_VEHICLE);
canDestroy = query.testBuild(target, associable, combine(event, DefaultFlag.DESTROY_VEHICLE));
what = "break vehicles";
/* Item pickup */
} else if (event.getEntity() instanceof Item || event.getEntity() instanceof ExperienceOrb) {
canDestroy = query.testBuild(target, associable, DefaultFlag.ITEM_PICKUP);
canDestroy = query.testBuild(target, associable, combine(event, DefaultFlag.ITEM_PICKUP));
what = "pick up items";
/* Everything else */
} else {
canDestroy = query.testBuild(target, associable);
canDestroy = query.testBuild(target, associable, combine(event));
what = "break things";
}
@ -386,22 +382,22 @@ public void onUseEntity(UseEntityEvent event) {
/* Hostile / ambient mob override */
if (Entities.isHostile(event.getEntity()) || Entities.isAmbient(event.getEntity()) || Entities.isNPC(event.getEntity())) {
canUse = true;
canUse = event.getRelevantFlags().isEmpty() || query.testState(target, associable, combine(event));
what = "use that";
/* Paintings, item frames, etc. */
} else if (Entities.isConsideredBuildingIfUsed(event.getEntity())) {
canUse = query.testBuild(target, associable);
canUse = query.testBuild(target, associable, combine(event));
what = "change that";
/* Ridden on use */
} else if (Entities.isRiddenOnUse(event.getEntity())) {
canUse = query.testBuild(target, associable, DefaultFlag.RIDE, DefaultFlag.INTERACT);
canUse = query.testBuild(target, associable, combine(event, DefaultFlag.RIDE, DefaultFlag.INTERACT));
what = "ride that";
/* Everything else */
} else {
canUse = query.testBuild(target, associable, DefaultFlag.INTERACT);
canUse = query.testBuild(target, associable, combine(event, DefaultFlag.INTERACT));
what = "use that";
}
@ -427,20 +423,20 @@ public void onDamageEntity(DamageEntityEvent event) {
/* Hostile / ambient mob override */
if (isWhitelistedEntity(event.getEntity()) || (rootCause instanceof Entity && isWhitelistedEntity((Entity) rootCause))) {
canDamage = true;
canDamage = event.getRelevantFlags().isEmpty() || query.testState(target, associable, combine(event));
what = "hit that";
/* Paintings, item frames, etc. */
} else if (Entities.isConsideredBuildingIfUsed(event.getEntity())) {
canDamage = query.testBuild(target, associable);
canDamage = query.testBuild(target, associable, combine(event));
what = "change that";
/* PVP */
} else if (event.getEntity() instanceof Player && (attacker = event.getCause().getFirstPlayer()) != null && !attacker.equals(event.getEntity())) {
Player defender = (Player) event.getEntity();
canDamage = query.testBuild(target, associable, DefaultFlag.PVP)
&& query.queryState(attacker.getLocation(), attacker, DefaultFlag.PVP) != State.DENY;
canDamage = query.testBuild(target, associable, combine(event, DefaultFlag.PVP))
&& query.queryState(attacker.getLocation(), attacker, combine(event, DefaultFlag.PVP)) != State.DENY;
// Fire the disallow PVP event
if (!canDamage && Events.fireAndTestCancel(new DisallowedPVPEvent(attacker, defender, event.getOriginalEvent()))) {
@ -451,12 +447,12 @@ public void onDamageEntity(DamageEntityEvent event) {
/* Player damage not caused by another player */
} else if (event.getEntity() instanceof Player) {
canDamage = true;
canDamage = event.getRelevantFlags().isEmpty() || query.testState(target, associable, combine(event));
what = "damage that";
/* Everything else */
} else {
canDamage = query.testBuild(target, associable, DefaultFlag.INTERACT);
canDamage = query.testBuild(target, associable, combine(event, DefaultFlag.INTERACT));
what = "hit that";
}
@ -494,4 +490,22 @@ private boolean isWhitelistedEntity(Entity entity) {
return Entities.isNonPlayerCreature(entity);
}
/**
* Combine the flags from a delegate event with an array of flags.
*
* <p>The delegate event's flags appear at the end.</p>
*
* @param event The event
* @param flag An array of flags
* @return An array of flags
*/
private static StateFlag[] combine(DelegateEvent event, StateFlag... flag) {
List<StateFlag> extra = event.getRelevantFlags();
StateFlag[] flags = Arrays.copyOf(flag, flag.length + extra.size());
for (int i = 0; i < extra.size(); i++) {
flags[flag.length + i] = extra.get(i);
}
return flags;
}
}

View File

@ -768,30 +768,6 @@ public void onFoodLevelChange(FoodLevelChangeEvent event) {
}
}
@EventHandler(ignoreCancelled = true)
public void onPotionSplash(PotionSplashEvent event) {
Entity entity = event.getEntity();
ThrownPotion potion = event.getPotion();
World world = entity.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
GlobalRegionManager regionMan = plugin.getGlobalRegionManager();
int blockedEntities = 0;
for (LivingEntity e : event.getAffectedEntities()) {
if (!regionMan.allows(DefaultFlag.POTION_SPLASH, e.getLocation(),
e instanceof Player ? plugin.wrapPlayer((Player) e) : null)) {
event.setIntensity(e, 0);
++blockedEntities;
}
}
if (blockedEntities == event.getAffectedEntities().size()) {
event.setCancelled(true);
}
}
/**
* Check if a player is invincible, via either god mode or region flag. If
* the region denies invincibility, the player must have an extra permission

View File

@ -56,6 +56,7 @@ public final class DefaultFlag {
public static final StateFlag DESTROY_VEHICLE = new StateFlag("vehicle-destroy", false);
public static final StateFlag LIGHTER = new StateFlag("lighter", false);
public static final StateFlag RIDE = new StateFlag("ride", false);
public static final StateFlag POTION_SPLASH = new StateFlag("potion-splash", false);
// These flags are similar to the ones above (used in tandem with BUILD),
// but their defaults are set to TRUE because it is more user friendly.
@ -99,7 +100,6 @@ public final class DefaultFlag {
public static final StateFlag ENDERPEARL = new StateFlag("enderpearl", true);
public static final StateFlag ENTITY_PAINTING_DESTROY = new StateFlag("entity-painting-destroy", true);
public static final StateFlag ENTITY_ITEM_FRAME_DESTROY = new StateFlag("entity-item-frame-destroy", true);
public static final StateFlag POTION_SPLASH = new StateFlag("potion-splash", true);
// Flags that adjust behaviors that aren't state flags
public static final StringFlag DENY_MESSAGE = new StringFlag("deny-message",