diff --git a/src/main/java/com/sk89q/worldguard/bukkit/BukkitUtil.java b/src/main/java/com/sk89q/worldguard/bukkit/BukkitUtil.java index 16aa971d..b483b9a9 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/BukkitUtil.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/BukkitUtil.java @@ -42,6 +42,7 @@ import org.bukkit.entity.Tameable; import org.bukkit.inventory.ItemStack; +import javax.annotation.Nullable; import java.util.List; import static com.google.common.base.Preconditions.checkNotNull; @@ -303,7 +304,7 @@ public static > T tryEnum(Class enumType, String ... values /** * Get a blacklist target for the given block. - * + * * @param block the block * @return a target */ @@ -312,6 +313,22 @@ public static Target createTarget(Block block) { return new MaterialTarget(block.getTypeId(), block.getData()); } + /** + * Get a blacklist target for the given block. + * + * @param block the block + * @param material a fallback material + * @return a target + */ + public static Target createTarget(@Nullable Block block, Material material) { + checkNotNull(material); + if (block != null) { + return new MaterialTarget(block.getTypeId(), block.getData()); + } else { + return new MaterialTarget(material.getId(), (short) 0); + } + } + /** * Get a blacklist target for the given item. * diff --git a/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardHangingListener.java b/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardHangingListener.java deleted file mode 100644 index 8c906b71..00000000 --- a/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardHangingListener.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * 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; - -import com.sk89q.worldedit.blocks.ItemID; -import com.sk89q.worldguard.blacklist.event.BlockBreakBlacklistEvent; -import com.sk89q.worldguard.blacklist.event.ItemUseBlacklistEvent; -import com.sk89q.worldguard.blacklist.target.MaterialTarget; -import com.sk89q.worldguard.protection.flags.DefaultFlag; -import org.bukkit.ChatColor; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.entity.Creeper; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Hanging; -import org.bukkit.entity.ItemFrame; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Painting; -import org.bukkit.entity.Player; -import org.bukkit.entity.Projectile; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.hanging.HangingBreakByEntityEvent; -import org.bukkit.event.hanging.HangingBreakEvent; -import org.bukkit.event.hanging.HangingBreakEvent.RemoveCause; -import org.bukkit.event.hanging.HangingPlaceEvent; -import org.bukkit.event.player.PlayerInteractEntityEvent; -import org.bukkit.projectiles.ProjectileSource; - -import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector; - -/** - * Listener for painting related events. - * - * @author BangL - */ -public class WorldGuardHangingListener implements Listener { - - private WorldGuardPlugin plugin; - - /** - * Construct the object; - * - * @param plugin The plugin instance - */ - public WorldGuardHangingListener(WorldGuardPlugin plugin) { - this.plugin = plugin; - } - - /** - * Register events. - */ - public void registerEvents() { - plugin.getServer().getPluginManager().registerEvents(this, plugin); - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onHangingingBreak(HangingBreakEvent event) { - Hanging hanging = event.getEntity(); - World world = hanging.getWorld(); - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - - if (event instanceof HangingBreakByEntityEvent) { - HangingBreakByEntityEvent entityEvent = (HangingBreakByEntityEvent) event; - Entity removerEntity = entityEvent.getRemover(); - if (removerEntity instanceof Projectile) { - Projectile projectile = (Projectile) removerEntity; - ProjectileSource remover = projectile.getShooter(); - removerEntity = (remover instanceof LivingEntity ? (LivingEntity) remover : null); - } - - if (removerEntity instanceof Player) { - Player player = (Player) removerEntity; - - if (wcfg.getBlacklist() != null) { - if (hanging instanceof Painting - && !wcfg.getBlacklist().check( - new BlockBreakBlacklistEvent(plugin.wrapPlayer(player), - toVector(player.getLocation()), new MaterialTarget(ItemID.PAINTING, (short) 0)), false, false)) { - event.setCancelled(true); - return; - } else if (hanging instanceof ItemFrame - && !wcfg.getBlacklist().check( - new BlockBreakBlacklistEvent(plugin.wrapPlayer(player), - toVector(player.getLocation()), new MaterialTarget(ItemID.ITEM_FRAME, (short) 0)), false, false)) { - event.setCancelled(true); - return; - } - } - - if (wcfg.useRegions) { - if (!plugin.getGlobalRegionManager().canBuild(player, hanging.getLocation())) { - player.sendMessage(ChatColor.DARK_RED + "You don't have permission for this area."); - event.setCancelled(true); - return; - } - } - } else { - if (removerEntity instanceof Creeper) { - if (wcfg.blockCreeperBlockDamage || wcfg.blockCreeperExplosions) { - event.setCancelled(true); - return; - } - if (wcfg.useRegions && !plugin.getGlobalRegionManager().allows(DefaultFlag.CREEPER_EXPLOSION, hanging.getLocation())) { - event.setCancelled(true); - return; - } - } - - // this now covers dispensers as well, if removerEntity is null above, - // due to a non-LivingEntity ProjectileSource - if (hanging instanceof Painting - && (wcfg.blockEntityPaintingDestroy - || (wcfg.useRegions - && !plugin.getGlobalRegionManager().allows(DefaultFlag.ENTITY_PAINTING_DESTROY, hanging.getLocation())))) { - event.setCancelled(true); - } else if (hanging instanceof ItemFrame - && (wcfg.blockEntityItemFrameDestroy - || (wcfg.useRegions - && !plugin.getGlobalRegionManager().allows(DefaultFlag.ENTITY_ITEM_FRAME_DESTROY, hanging.getLocation())))) { - event.setCancelled(true); - } - } - } else { - // Explosions from mobs are not covered by HangingBreakByEntity - if (hanging instanceof Painting && wcfg.blockEntityPaintingDestroy - && event.getCause() == RemoveCause.EXPLOSION) { - event.setCancelled(true); - } else if (hanging instanceof ItemFrame && wcfg.blockEntityItemFrameDestroy - && event.getCause() == RemoveCause.EXPLOSION) { - event.setCancelled(true); - } - } - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onHangingPlace(HangingPlaceEvent event) { - Block placedOn = event.getBlock(); - Player player = event.getPlayer(); - World world = placedOn.getWorld(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - - if (wcfg.getBlacklist() != null) { - - if (event.getEntity() instanceof Painting - && !wcfg.getBlacklist().check( - new ItemUseBlacklistEvent(plugin.wrapPlayer(player), - toVector(player.getLocation()), new MaterialTarget(ItemID.PAINTING, (short) 0)), false, false)) { - event.setCancelled(true); - return; - } else if (event.getEntity() instanceof ItemFrame - && !wcfg.getBlacklist().check( - new ItemUseBlacklistEvent(plugin.wrapPlayer(player), - toVector(player.getLocation()), new MaterialTarget(ItemID.ITEM_FRAME, (short) 0)), false, false)) { - event.setCancelled(true); - return; - } - } - - if (wcfg.useRegions) { - if (!plugin.getGlobalRegionManager().canBuild(player, placedOn.getRelative(event.getBlockFace()))) { - player.sendMessage(ChatColor.DARK_RED + "You don't have permission for this area."); - event.setCancelled(true); - return; - } - } - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onEntityInteract(PlayerInteractEntityEvent event) { - Player player = event.getPlayer(); - Entity entity = event.getRightClicked(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(entity.getWorld()); - - if (wcfg.useRegions && (entity instanceof ItemFrame || entity instanceof Painting)) { - if (!plugin.getGlobalRegionManager().canBuild(player, entity.getLocation())) { - player.sendMessage(ChatColor.DARK_RED + "You don't have permission for this area."); - event.setCancelled(true); - return; - } - -// if (entity instanceof ItemFrame -// && ((!plugin.getGlobalRegionManager().allows( -// DefaultFlag.ENTITY_ITEM_FRAME_DESTROY, entity.getLocation())))) { -// event.setCancelled(true); -// } else if (entity instanceof Painting -// && ((!plugin.getGlobalRegionManager().allows( -// DefaultFlag.ENTITY_PAINTING_DESTROY, entity.getLocation())))) { -// event.setCancelled(true); -// } - } - } -} diff --git a/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardPlayerListener.java b/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardPlayerListener.java deleted file mode 100644 index 50146b8a..00000000 --- a/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardPlayerListener.java +++ /dev/null @@ -1,1435 +0,0 @@ -/* - * 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; - -import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.blocks.BlockID; -import com.sk89q.worldedit.blocks.BlockType; -import com.sk89q.worldedit.blocks.ItemID; -import com.sk89q.worldguard.LocalPlayer; -import com.sk89q.worldguard.blacklist.event.BlockBreakBlacklistEvent; -import com.sk89q.worldguard.blacklist.event.BlockInteractBlacklistEvent; -import com.sk89q.worldguard.blacklist.event.BlockPlaceBlacklistEvent; -import com.sk89q.worldguard.blacklist.event.ItemAcquireBlacklistEvent; -import com.sk89q.worldguard.blacklist.event.ItemDropBlacklistEvent; -import com.sk89q.worldguard.blacklist.event.ItemUseBlacklistEvent; -import com.sk89q.worldguard.bukkit.FlagStateManager.PlayerFlagState; -import com.sk89q.worldguard.internal.Events; -import com.sk89q.worldguard.internal.cause.Causes; -import com.sk89q.worldguard.internal.event.Interaction; -import com.sk89q.worldguard.internal.event.ItemInteractEvent; -import com.sk89q.worldguard.protection.ApplicableRegionSet; -import com.sk89q.worldguard.protection.flags.DefaultFlag; -import com.sk89q.worldguard.protection.managers.RegionManager; -import com.sk89q.worldguard.protection.regions.ProtectedRegion; -import com.sk89q.worldguard.util.command.CommandFilter; -import org.bukkit.ChatColor; -import org.bukkit.GameMode; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Item; -import org.bukkit.entity.Player; -import org.bukkit.event.Event.Result; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.block.Action; -import org.bukkit.event.player.AsyncPlayerChatEvent; -import org.bukkit.event.player.PlayerBedEnterEvent; -import org.bukkit.event.player.PlayerBucketEmptyEvent; -import org.bukkit.event.player.PlayerBucketFillEvent; -import org.bukkit.event.player.PlayerCommandPreprocessEvent; -import org.bukkit.event.player.PlayerDropItemEvent; -import org.bukkit.event.player.PlayerFishEvent; -import org.bukkit.event.player.PlayerGameModeChangeEvent; -import org.bukkit.event.player.PlayerInteractEntityEvent; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerItemHeldEvent; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerLoginEvent; -import org.bukkit.event.player.PlayerMoveEvent; -import org.bukkit.event.player.PlayerPickupItemEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.event.player.PlayerRespawnEvent; -import org.bukkit.event.player.PlayerTeleportEvent; -import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; -import org.bukkit.inventory.ItemStack; -import org.bukkit.plugin.PluginManager; - -import java.util.Iterator; -import java.util.Set; -import java.util.logging.Level; -import java.util.regex.Pattern; - -import static com.sk89q.worldguard.bukkit.BukkitUtil.createTarget; -import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector; - -/** - * Handles all events thrown in relation to a player. - */ -public class WorldGuardPlayerListener implements Listener { - - private Pattern opPattern = Pattern.compile("^/op(?:\\s.*)?$", Pattern.CASE_INSENSITIVE); - private WorldGuardPlugin plugin; - - /** - * Construct the object; - * - * @param plugin - */ - public WorldGuardPlayerListener(WorldGuardPlugin plugin) { - this.plugin = plugin; - } - - /** - * Register events. - */ - public void registerEvents() { - final PluginManager pm = plugin.getServer().getPluginManager(); - pm.registerEvents(this, plugin); - - if (plugin.getGlobalStateManager().usePlayerMove) { - pm.registerEvents(new PlayerMoveHandler(), plugin); - } - } - - // unsure if anyone actually started using this yet, but just in case... - @Deprecated - public static boolean checkMove(WorldGuardPlugin plugin, Player player, World world, Location from, Location to) { - return checkMove(plugin, player, from, to); // drop world since it used to be mishandled - } - - /** - * Handles movement related events, including changing gamemode, sending - * greeting/farewell messages, etc. - * A reference to WorldGuardPlugin is required to keep this method static - * although WGBukkit.getPlugin() may be used. - * @return true if the movement should not be allowed - */ - public static boolean checkMove(WorldGuardPlugin plugin, Player player, Location from, Location to) { - PlayerFlagState state = plugin.getFlagStateManager().getState(player); - - //Flush states in multiworld scenario - if (state.lastWorld != null && !state.lastWorld.equals(to.getWorld())) { - plugin.getFlagStateManager().forget(player); - state = plugin.getFlagStateManager().getState(player); - } - - World world = from.getWorld(); - World toWorld = to.getWorld(); - - LocalPlayer localPlayer = plugin.wrapPlayer(player); - boolean hasBypass = plugin.getGlobalRegionManager().hasBypass(player, world); - boolean hasRemoteBypass; - if (world.equals(toWorld)) { - hasRemoteBypass = hasBypass; - } else { - hasRemoteBypass = plugin.getGlobalRegionManager().hasBypass(player, toWorld); - } - - RegionManager mgr = plugin.getGlobalRegionManager().get(toWorld); - Vector pt = new Vector(to.getBlockX(), to.getBlockY(), to.getBlockZ()); - ApplicableRegionSet set = mgr.getApplicableRegions(pt); - - /* - // check if region is full - // get the lowest number of allowed members in any region - boolean regionFull = false; - String maxPlayerMessage = null; - if (!hasBypass) { - for (ProtectedRegion region : set) { - if (region instanceof GlobalProtectedRegion) { - continue; // global region can't have a max - } - // get the max for just this region - Integer maxPlayers = region.getFlag(DefaultFlag.MAX_PLAYERS); - if (maxPlayers == null) { - continue; - } - int occupantCount = 0; - for(Player occupant : world.getPlayers()) { - // each player in this region counts as one toward the max of just this region - // A person with bypass doesn't count as an occupant of the region - if (!occupant.equals(player) && !plugin.getGlobalRegionManager().hasBypass(occupant, world)) { - if (region.contains(BukkitUtil.toVector(occupant.getLocation()))) { - if (++occupantCount >= maxPlayers) { - regionFull = true; - maxPlayerMessage = region.getFlag(DefaultFlag.MAX_PLAYERS_MESSAGE); - // At least one region in the set is full, we are going to use this message because it - // was the first one we detected as full. In reality we should check them all and then - // resolve the message from full regions, but that is probably a lot laggier (and this - // is already pretty laggy. In practice, we can't really control which one we get first - // right here. - break; - } - } - } - } - } - } - */ - - boolean entryAllowed = set.allows(DefaultFlag.ENTRY, localPlayer); - if (!hasRemoteBypass && (!entryAllowed /*|| regionFull*/)) { - String message = /*maxPlayerMessage != null ? maxPlayerMessage :*/ "You are not permitted to enter this area."; - - player.sendMessage(ChatColor.DARK_RED + message); - return true; - } - - // Have to set this state - if (state.lastExitAllowed == null) { - state.lastExitAllowed = plugin.getGlobalRegionManager().get(world) - .getApplicableRegions(toVector(from)) - .allows(DefaultFlag.EXIT, localPlayer); - } - - boolean exitAllowed = set.allows(DefaultFlag.EXIT, localPlayer); - if (!hasBypass && exitAllowed && !state.lastExitAllowed) { - player.sendMessage(ChatColor.DARK_RED + "You are not permitted to leave this area."); - return true; - } - -// WorldGuardRegionMoveEvent event = new WorldGuardRegionMoveEvent(plugin, player, state, set, from, to); -// Bukkit.getPluginManager().callEvent(event); - - String greeting = set.getFlag(DefaultFlag.GREET_MESSAGE);//, localPlayer); - String farewell = set.getFlag(DefaultFlag.FAREWELL_MESSAGE);//, localPlayer); - Boolean notifyEnter = set.getFlag(DefaultFlag.NOTIFY_ENTER);//, localPlayer); - Boolean notifyLeave = set.getFlag(DefaultFlag.NOTIFY_LEAVE);//, localPlayer); - GameMode gameMode = set.getFlag(DefaultFlag.GAME_MODE); - - if (state.lastFarewell != null && (farewell == null - || !state.lastFarewell.equals(farewell))) { - String replacedFarewell = plugin.replaceMacros( - player, BukkitUtil.replaceColorMacros(state.lastFarewell)); - player.sendMessage(replacedFarewell.replaceAll("\\\\n", "\n").split("\\n")); - } - - if (greeting != null && (state.lastGreeting == null - || !state.lastGreeting.equals(greeting))) { - String replacedGreeting = plugin.replaceMacros( - player, BukkitUtil.replaceColorMacros(greeting)); - player.sendMessage(replacedGreeting.replaceAll("\\\\n", "\n").split("\\n")); - } - - if ((notifyLeave == null || !notifyLeave) - && state.notifiedForLeave != null && state.notifiedForLeave) { - plugin.broadcastNotification(ChatColor.GRAY + "WG: " - + ChatColor.LIGHT_PURPLE + player.getName() - + ChatColor.GOLD + " left NOTIFY region"); - } - - if (notifyEnter != null && notifyEnter && (state.notifiedForEnter == null - || !state.notifiedForEnter)) { - StringBuilder regionList = new StringBuilder(); - - for (ProtectedRegion region : set) { - if (regionList.length() != 0) { - regionList.append(", "); - } - regionList.append(region.getId()); - } - - plugin.broadcastNotification(ChatColor.GRAY + "WG: " - + ChatColor.LIGHT_PURPLE + player.getName() - + ChatColor.GOLD + " entered NOTIFY region: " - + ChatColor.WHITE - + regionList); - } - - if (!hasBypass && gameMode != null) { - if (player.getGameMode() != gameMode) { - state.lastGameMode = player.getGameMode(); - player.setGameMode(gameMode); - } else if (state.lastGameMode == null) { - state.lastGameMode = player.getServer().getDefaultGameMode(); - } - } else { - if (state.lastGameMode != null) { - GameMode mode = state.lastGameMode; - state.lastGameMode = null; - player.setGameMode(mode); - } - } - - state.lastGreeting = greeting; - state.lastFarewell = farewell; - state.notifiedForEnter = notifyEnter; - state.notifiedForLeave = notifyLeave; - state.lastExitAllowed = exitAllowed; - state.lastWorld = to.getWorld(); - state.lastBlockX = to.getBlockX(); - state.lastBlockY = to.getBlockY(); - state.lastBlockZ = to.getBlockZ(); - return false; - } - - class PlayerMoveHandler implements Listener { - @EventHandler(priority = EventPriority.HIGH) - public void onPlayerMove(PlayerMoveEvent event) { - Player player = event.getPlayer(); - World world = player.getWorld(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - - if (player.getVehicle() != null) { - return; // handled in vehicle listener - } - if (wcfg.useRegions) { - // Did we move a block? - if (event.getFrom().getBlockX() != event.getTo().getBlockX() - || event.getFrom().getBlockY() != event.getTo().getBlockY() - || event.getFrom().getBlockZ() != event.getTo().getBlockZ()) { - boolean result = checkMove(plugin, player, event.getFrom(), event.getTo()); - if (result) { - Location newLoc = event.getFrom(); - newLoc.setX(newLoc.getBlockX() + 0.5); - newLoc.setY(newLoc.getBlockY()); - newLoc.setZ(newLoc.getBlockZ() + 0.5); - event.setTo(newLoc); - } - } - } - } - } - - @EventHandler - public void onPlayerGameModeChange(PlayerGameModeChangeEvent event) { - Player player = event.getPlayer(); - WorldConfiguration wcfg = plugin.getGlobalStateManager().get(player.getWorld()); - if (wcfg.useRegions && !plugin.getGlobalRegionManager().hasBypass(player, player.getWorld())) { - GameMode gameMode = plugin.getGlobalRegionManager().get(player.getWorld()) - .getApplicableRegions(player.getLocation()).getFlag(DefaultFlag.GAME_MODE); - if (plugin.getFlagStateManager().getState(player).lastGameMode != null - && gameMode != null && event.getNewGameMode() != gameMode) { - event.setCancelled(true); - } - } - } - - @EventHandler - public void onPlayerJoin(PlayerJoinEvent event) { - Player player = event.getPlayer(); - World world = player.getWorld(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - - if (cfg.activityHaltToggle) { - player.sendMessage(ChatColor.YELLOW - + "Intensive server activity has been HALTED."); - - int removed = 0; - - for (Entity entity : world.getEntities()) { - if (BukkitUtil.isIntensiveEntity(entity)) { - entity.remove(); - removed++; - } - } - - if (removed > 10) { - plugin.getLogger().info("Halt-Act: " + removed + " entities (>10) auto-removed from " - + player.getWorld().toString()); - } - } - - if (wcfg.fireSpreadDisableToggle) { - player.sendMessage(ChatColor.YELLOW - + "Fire spread is currently globally disabled for this world."); - } - - if (!cfg.hasCommandBookGodMode() && cfg.autoGodMode && (plugin.inGroup(player, "wg-invincible") - || plugin.hasPermission(player, "worldguard.auto-invincible"))) { - plugin.getLogger().log(Level.INFO, "Enabled auto-god mode for " + player.getName()); - cfg.enableGodMode(player); - } - - if (plugin.inGroup(player, "wg-amphibious")) { - plugin.getLogger().log(Level.INFO, "Enabled no-drowning mode for " + player.getName() + " (player is in group 'wg-amphibious')"); - cfg.enableAmphibiousMode(player); - } - - if (wcfg.useRegions) { - PlayerFlagState state = plugin.getFlagStateManager().getState(player); - Location loc = player.getLocation(); - state.lastWorld = loc.getWorld(); - state.lastBlockX = loc.getBlockX(); - state.lastBlockY = loc.getBlockY(); - state.lastBlockZ = loc.getBlockZ(); - } - } - - @EventHandler(ignoreCancelled = true) - public void onPlayerChat(AsyncPlayerChatEvent event) { - Player player = event.getPlayer(); - WorldConfiguration wcfg = plugin.getGlobalStateManager().get(player.getWorld()); - if (wcfg.useRegions) { - if (!plugin.getGlobalRegionManager().allows(DefaultFlag.SEND_CHAT, player.getLocation())) { - player.sendMessage(ChatColor.RED + "You don't have permission to chat in this region!"); - event.setCancelled(true); - return; - } - - for (Iterator i = event.getRecipients().iterator(); i.hasNext();) { - if (!plugin.getGlobalRegionManager().allows(DefaultFlag.RECEIVE_CHAT, i.next().getLocation())) { - i.remove(); - } - } - if (event.getRecipients().size() == 0) { - event.setCancelled(true); - } - } - } - - @EventHandler(ignoreCancelled = true) - public void onPlayerLogin(PlayerLoginEvent event) { - Player player = event.getPlayer(); - ConfigurationManager cfg = plugin.getGlobalStateManager(); - - String hostKey = cfg.hostKeys.get(player.getName().toLowerCase()); - if (hostKey != null) { - String hostname = event.getHostname(); - int colonIndex = hostname.indexOf(':'); - if (colonIndex != -1) { - hostname = hostname.substring(0, colonIndex); - } - - if (!hostname.equals(hostKey)) { - event.disallow(PlayerLoginEvent.Result.KICK_OTHER, - "You did not join with the valid host key!"); - plugin.getLogger().warning("WorldGuard host key check: " + - player.getName() + " joined with '" + hostname + - "' but '" + hostKey + "' was expected. Kicked!"); - return; - } - } - - if (cfg.deopOnJoin) { - player.setOp(false); - } - } - - @EventHandler - public void onPlayerQuit(PlayerQuitEvent event) { - Player player = event.getPlayer(); - World world = player.getWorld(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - - // This is to make the enter/exit flags accurate -- move events are not - // sent constantly, so it is possible to move just a little enough to - // not trigger the event and then rejoin so that you are then considered - // outside the border. This should work around that. - if (wcfg.useRegions) { - boolean hasBypass = plugin.getGlobalRegionManager().hasBypass(player, world); - PlayerFlagState state = plugin.getFlagStateManager().getState(player); - - if (state.lastWorld != null && !hasBypass) { - LocalPlayer localPlayer = plugin.wrapPlayer(player); - RegionManager mgr = plugin.getGlobalRegionManager().get(world); - Location loc = player.getLocation(); - Vector pt = new Vector(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); - ApplicableRegionSet set = mgr.getApplicableRegions(pt); - - if (state.lastExitAllowed == null) { - state.lastExitAllowed = set.allows(DefaultFlag.EXIT, localPlayer); - } - - if (!state.lastExitAllowed || !set.allows(DefaultFlag.ENTRY, localPlayer)) { - // Only if we have the last location cached - if (state.lastWorld.equals(world)) { - Location newLoc = new Location(world, state.lastBlockX + 0.5, - state.lastBlockY, state.lastBlockZ + 0.5); - player.teleport(newLoc); - } - } - } - } - - cfg.forgetPlayer(plugin.wrapPlayer(player)); - plugin.forgetPlayer(player); - } - - @EventHandler(priority = EventPriority.HIGH) - public void onPlayerInteractEntity(PlayerInteractEntityEvent event) { - // TODO reduce duplication with right-click-air - Player player = event.getPlayer(); - World world = player.getWorld(); - ItemStack item = player.getItemInHand(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - - if (wcfg.getBlacklist() != null) { - if (!wcfg.getBlacklist().check( - new ItemUseBlacklistEvent(plugin.wrapPlayer(player), toVector(player.getLocation()), createTarget(item)), false, false)) { - event.setCancelled(true); - return; - } - } - } - - @EventHandler(priority = EventPriority.HIGH) - public void onPlayerInteract(PlayerInteractEvent event) { - Player player = event.getPlayer(); - World world = player.getWorld(); - ItemStack item = event.getItem(); - - if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { - handleBlockRightClick(event); - } else if (event.getAction() == Action.RIGHT_CLICK_AIR) { - handleAirRightClick(event); - } else if (event.getAction() == Action.LEFT_CLICK_BLOCK) { - handleBlockLeftClick(event); - } else if (event.getAction() == Action.LEFT_CLICK_AIR) { - handleAirLeftClick(event); - } else if (event.getAction() == Action.PHYSICAL) { - handlePhysicalInteract(event); - } - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - - if (wcfg.removeInfiniteStacks - && !plugin.hasPermission(player, "worldguard.override.infinite-stack")) { - int slot = player.getInventory().getHeldItemSlot(); - ItemStack heldItem = player.getInventory().getItem(slot); - if (heldItem != null && heldItem.getAmount() < 0) { - player.getInventory().setItem(slot, null); - player.sendMessage(ChatColor.RED + "Infinite stack removed."); - } - } - - if (item != null) { - Events.fireItemEventToCancel(event, new ItemInteractEvent(event, Causes.create(event.getPlayer()), Interaction.INTERACT, world, item)); - } - } - - /** - * Called when a player left clicks air. - * - * @param event Thrown event - */ - private void handleAirLeftClick(PlayerInteractEvent event) { - // I don't think we have to do anything here yet. - return; - } - - /** - * Called when a player left clicks a block. - * - * @param event Thrown event - */ - private void handleBlockLeftClick(PlayerInteractEvent event) { - if (event.isCancelled()) return; - - Player player = event.getPlayer(); - Block block = event.getClickedBlock(); - int type = block.getTypeId(); - World world = player.getWorld(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - - if (wcfg.useRegions) { - Vector pt = toVector(block); - RegionManager mgr = plugin.getGlobalRegionManager().get(world); - ApplicableRegionSet set = mgr.getApplicableRegions(pt); - LocalPlayer localPlayer = plugin.wrapPlayer(player); - - /*if (type == BlockID.STONE_BUTTON - || type == BlockID.LEVER - || type == BlockID.WOODEN_DOOR - || type == BlockID.TRAP_DOOR - || type == BlockID.NOTE_BLOCK) { - if (!plugin.getGlobalRegionManager().hasBypass(player, world) - && !set.allows(DefaultFlag.USE, localPlayer) - && !set.canBuild(localPlayer)) { - player.sendMessage(ChatColor.DARK_RED + "You don't have permission to use that in this area."); - event.setUseInteractedBlock(Result.DENY); - event.setCancelled(true); - return; - } - }*/ - - if (type == BlockID.DRAGON_EGG) { - if (!plugin.getGlobalRegionManager().hasBypass(player, world) - && !set.canBuild(localPlayer)) { - player.sendMessage(ChatColor.DARK_RED + "You're not allowed to move dragon eggs here!"); - event.setUseInteractedBlock(Result.DENY); - event.setCancelled(true); - return; - } - } - - if (block.getRelative(event.getBlockFace()).getTypeId() == BlockID.FIRE) { - if (!plugin.getGlobalRegionManager().hasBypass(player, world) - && !mgr.getApplicableRegions(block.getRelative(event.getBlockFace()) - .getLocation()).canBuild(localPlayer)) { - event.setUseInteractedBlock(Result.DENY); - event.setCancelled(true); - return; - } - } - - } - - if (type == BlockID.TNT && player.getItemInHand().getTypeId() == ItemID.FLINT_AND_TINDER) { - if (wcfg.getBlacklist() != null) { - if (!wcfg.getBlacklist().check( - new BlockBreakBlacklistEvent(plugin.wrapPlayer(player), toVector(event.getClickedBlock()), createTarget(event.getClickedBlock())), false, false)) { - event.setUseInteractedBlock(Result.DENY); - event.setUseItemInHand(Result.DENY); - event.setCancelled(true); - return; - } - } - } - } - - /** - * Called when a player right clicks air. - * - * @param event Thrown event - */ - private void handleAirRightClick(PlayerInteractEvent event) { - Player player = event.getPlayer(); - World world = player.getWorld(); - ItemStack item = player.getItemInHand(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - - if (wcfg.getBlacklist() != null) { - if (!wcfg.getBlacklist().check( - new ItemUseBlacklistEvent(plugin.wrapPlayer(player), toVector(player.getLocation()), createTarget(item)), false, false)) { - event.setCancelled(true); - event.setUseItemInHand(Result.DENY); - return; - } - } - } - - /** - * Called when a player right clicks a block. - * - * @param event Thrown event - */ - private void handleBlockRightClick(PlayerInteractEvent event) { - if (event.isCancelled()) { - return; - } - - Block block = event.getClickedBlock(); - World world = block.getWorld(); - int type = block.getTypeId(); - Player player = event.getPlayer(); - ItemStack item = player.getItemInHand(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - - // Infinite stack removal - if ((type == BlockID.CHEST - || type == BlockID.JUKEBOX - || type == BlockID.DISPENSER - || type == BlockID.FURNACE - || type == BlockID.BURNING_FURNACE - || type == BlockID.BREWING_STAND - || type == BlockID.ENCHANTMENT_TABLE) - && wcfg.removeInfiniteStacks - && !plugin.hasPermission(player, "worldguard.override.infinite-stack")) { - for (int slot = 0; slot < 40; slot++) { - ItemStack heldItem = player.getInventory().getItem(slot); - if (heldItem != null && heldItem.getAmount() < 0) { - player.getInventory().setItem(slot, null); - player.sendMessage(ChatColor.RED + "Infinite stack in slot #" + slot + " removed."); - } - } - } - - if (wcfg.useRegions) { - Vector pt = toVector(block); - RegionManager mgr = plugin.getGlobalRegionManager().get(world); - Block placedIn = block.getRelative(event.getBlockFace()); - ApplicableRegionSet set = mgr.getApplicableRegions(pt); - ApplicableRegionSet placedInSet = mgr.getApplicableRegions(placedIn.getLocation()); - LocalPlayer localPlayer = plugin.wrapPlayer(player); - - if (item.getTypeId() == wcfg.regionWand && plugin.hasPermission(player, "worldguard.region.wand")) { - if (set.size() > 0) { - player.sendMessage(ChatColor.YELLOW + "Can you build? " - + (set.canBuild(localPlayer) ? "Yes" : "No")); - - StringBuilder str = new StringBuilder(); - for (Iterator it = set.iterator(); it.hasNext();) { - str.append(it.next().getId()); - if (it.hasNext()) { - str.append(", "); - } - } - - player.sendMessage(ChatColor.YELLOW + "Applicable regions: " + str.toString()); - } else { - player.sendMessage(ChatColor.YELLOW + "WorldGuard: No defined regions here!"); - } - - event.setCancelled(true); - return; - } - - if (item.getTypeId() == BlockID.TNT) { - // workaround for a bug that allowed tnt to trigger instantly if placed - // next to redstone, without plugins getting the block place event - // (not sure if this actually still happens) - if (!plugin.getGlobalRegionManager().hasBypass(player, world) - && !placedInSet.allows(DefaultFlag.TNT, localPlayer)) { - event.setUseItemInHand(Result.DENY); - event.setCancelled(true); - } - } - - // hacky workaround for craftbukkit bug - // has since been fixed, but leaving for legacy - if (item.getTypeId() == BlockID.STEP - || item.getTypeId() == BlockID.WOODEN_STEP) { - if (!plugin.getGlobalRegionManager().hasBypass(localPlayer, world)) { - boolean cancel = false; - if ((block.getTypeId() == item.getTypeId()) - && !set.canBuild(localPlayer)) { - // if we are on a step already, the new block will end up in the same block as the interact - cancel = true; - } else if (!placedInSet.canBuild(localPlayer)) { - // if we are on another block, the half-slab in hand will be pushed to the adjacent block - cancel = true; - } - if (cancel) { - player.sendMessage(ChatColor.DARK_RED + "You don't have permission for this area."); - event.setCancelled(true); - return; - } - } - } - - if (item.getTypeId() == ItemID.BED_ITEM) { - // this is mojang-level code, it had better give us the right direction - double yaw = (player.getLocation().getYaw() * 4.0F / 360.0F) + 0.5D; - int i = (int) yaw; - int i1 = (yaw < i ? i - 1 : i) & 3; - byte b0 = 0; - byte b1 = 0; - if (i1 == 0) { - b1 = 1; - } - if (i1 == 1) { - b0 = -1; - } - if (i1 == 2) { - b1 = -1; - } - if (i1 == 3) { - b0 = 1; - } - // end mojang-level code - Location headLoc = placedIn.getRelative(b0, 0, b1).getLocation(); - if (!plugin.getGlobalRegionManager().hasBypass(localPlayer, world) - && !mgr.getApplicableRegions(headLoc).canBuild(localPlayer)) { - // note that normal block placement is handled later, this is just a workaround - // for the location of the head block of the bed - player.sendMessage(ChatColor.DARK_RED + "You don't have permission for this area."); - event.setCancelled(true); - return; - } - } - - if (block.getTypeId() == BlockID.PISTON_MOVING_PIECE) { - if (!plugin.getGlobalRegionManager().hasBypass(player, world) - && !set.canBuild(localPlayer)) { - event.setUseInteractedBlock(Result.DENY); - } - } - - if (item.getTypeId() == ItemID.WOODEN_DOOR_ITEM || item.getTypeId() == ItemID.IRON_DOOR_ITEM) { - if (!plugin.getGlobalRegionManager().hasBypass(localPlayer, world) - && !placedInSet.canBuild(localPlayer)) { - // note that normal block placement is handled later, this is just a workaround - // for the location of the top block of the door - player.sendMessage(ChatColor.DARK_RED + "You don't have permission for this area."); - event.setCancelled(true); - return; - } - } - - if (item.getTypeId() == ItemID.FIRE_CHARGE || item.getTypeId() == ItemID.FLINT_AND_TINDER) { - if (!plugin.getGlobalRegionManager().hasBypass(localPlayer, world) - && !plugin.canBuild(player, placedIn) - && !placedInSet.allows(DefaultFlag.LIGHTER)) { - event.setCancelled(true); - event.setUseItemInHand(Result.DENY); - player.sendMessage(ChatColor.DARK_RED + "You're not allowed to use that here."); - return; - } - } - - if (item.getTypeId() == ItemID.EYE_OF_ENDER && block.getTypeId() == BlockID.END_PORTAL_FRAME) { - if (!plugin.getGlobalRegionManager().hasBypass(player, world) - && !set.canBuild(localPlayer)) { - event.setCancelled(true); - event.setUseItemInHand(Result.DENY); - player.sendMessage(ChatColor.DARK_RED + "You're not allowed to use that here."); - return; - } - } - - if (item.getTypeId() == ItemID.INK_SACK - && item.getData() != null) { - if (item.getData().getData() == 15 // bonemeal - && (type == BlockID.GRASS - || type == BlockID.SAPLING - || type == BlockID.CROPS - || type == BlockID.BROWN_MUSHROOM - || type == BlockID.RED_MUSHROOM - || type == BlockID.PUMPKIN_STEM - || type == BlockID.MELON_STEM - || type == BlockID.POTATOES - || type == BlockID.CARROTS - || type == BlockID.COCOA_PLANT - || type == BlockID.LONG_GRASS)) { - if (!plugin.getGlobalRegionManager().hasBypass(player, world) - && !set.canBuild(localPlayer)) { - event.setCancelled(true); - event.setUseItemInHand(Result.DENY); - player.sendMessage(ChatColor.DARK_RED + "You're not allowed to use that here."); - return; - } - } else if (item.getData().getData() == 3) { // cocoa beans - // craftbukkit doesn't throw a block place for this, so workaround - if (!plugin.getGlobalRegionManager().hasBypass(player, world) - && !set.canBuild(localPlayer)) { - if (!(event.getBlockFace() == BlockFace.DOWN || event.getBlockFace() == BlockFace.UP)) { - event.setCancelled(true); - event.setUseItemInHand(Result.DENY); - player.sendMessage(ChatColor.DARK_RED + "You're not allowed to plant that here."); - return; - } - } - } - } - - if (type == BlockID.FLOWER_POT) { // no api for this atm - if (item.getTypeId() == BlockID.RED_FLOWER - || item.getTypeId() == BlockID.YELLOW_FLOWER - || item.getTypeId() == BlockID.SAPLING - || item.getTypeId() == BlockID.RED_MUSHROOM - || item.getTypeId() == BlockID.BROWN_MUSHROOM - || item.getTypeId() == BlockID.CACTUS - || item.getTypeId() == BlockID.LONG_GRASS - || item.getTypeId() == BlockID.DEAD_BUSH) { - if (!plugin.getGlobalRegionManager().hasBypass(player, world) - && !set.canBuild(localPlayer)) { - event.setUseItemInHand(Result.DENY); - event.setCancelled(true); - player.sendMessage(ChatColor.DARK_RED + "You're not allowed to plant that here."); - return; - } - } - } - - if (type == BlockID.BED) { - if (!plugin.getGlobalRegionManager().hasBypass(player, world) - && !set.allows(DefaultFlag.SLEEP, localPlayer)) { - player.sendMessage(ChatColor.DARK_RED + "You're not allowed to use that bed."); - event.setUseInteractedBlock(Result.DENY); - event.setCancelled(true); - return; - } - } - - if (type == BlockID.CHEST - || type == BlockID.JUKEBOX //stores the (arguably) most valuable item - || type == BlockID.DISPENSER - || type == BlockID.FURNACE - || type == BlockID.BURNING_FURNACE - || type == BlockID.BREWING_STAND - || type == BlockID.TRAPPED_CHEST - || type == BlockID.HOPPER - || type == BlockID.DROPPER) { - if (!plugin.getGlobalRegionManager().hasBypass(player, world) - && !set.canBuild(localPlayer) - && !set.allows(DefaultFlag.CHEST_ACCESS, localPlayer)) { - player.sendMessage(ChatColor.DARK_RED + "You don't have permission to open that in this area."); - event.setUseInteractedBlock(Result.DENY); - event.setCancelled(true); - return; - } - } - - if (type == BlockID.DRAGON_EGG) { - if (!plugin.getGlobalRegionManager().hasBypass(player, world) - && !set.canBuild(localPlayer)) { - player.sendMessage(ChatColor.DARK_RED + "You're not allowed to move dragon eggs here!"); - event.setUseInteractedBlock(Result.DENY); - event.setCancelled(true); - return; - } - } - - if (type == BlockID.LEVER - || type == BlockID.STONE_BUTTON - || type == BlockID.WOODEN_BUTTON - || type == BlockID.NOTE_BLOCK - || type == BlockID.REDSTONE_REPEATER_OFF - || type == BlockID.REDSTONE_REPEATER_ON - || type == BlockID.WOODEN_DOOR - || type == BlockID.TRAP_DOOR - || type == BlockID.FENCE_GATE - || type == BlockID.JUKEBOX //stores the (arguably) most valuable item - || type == BlockID.DISPENSER - || type == BlockID.FURNACE - || type == BlockID.BURNING_FURNACE - || type == BlockID.WORKBENCH - || type == BlockID.BREWING_STAND - || type == BlockID.ENCHANTMENT_TABLE - || type == BlockID.CAULDRON - || type == BlockID.ENDER_CHEST // blah - || type == BlockID.BEACON - || type == BlockID.ANVIL - || type == BlockID.HOPPER - || type == BlockID.DROPPER) { - if (!plugin.getGlobalRegionManager().hasBypass(player, world) - && !set.canBuild(localPlayer) - && !set.allows(DefaultFlag.USE, localPlayer)) { - player.sendMessage(ChatColor.DARK_RED + "You don't have permission to use that in this area."); - event.setUseInteractedBlock(Result.DENY); - event.setCancelled(true); - return; - } - } - - if (type == BlockID.REDSTONE_REPEATER_OFF - || type == BlockID.REDSTONE_REPEATER_ON - || type == BlockID.COMPARATOR_OFF - || type == BlockID.COMPARATOR_ON) { - if (!plugin.getGlobalRegionManager().hasBypass(player, world) - && !set.canBuild(localPlayer)) { - // using build and not use because it can potentially damage a circuit and use is more general-purposed - player.sendMessage(ChatColor.DARK_RED + "You don't have permission to use that in this area."); - event.setUseInteractedBlock(Result.DENY); - event.setCancelled(true); - return; - } - } - - if (type == BlockID.CAKE_BLOCK) { - if (!plugin.getGlobalRegionManager().hasBypass(player, world) - && !set.canBuild(localPlayer) - && !set.allows(DefaultFlag.USE, localPlayer)) { - player.sendMessage(ChatColor.DARK_RED + "You're not invited to this tea party!"); - event.setUseInteractedBlock(Result.DENY); - event.setCancelled(true); - return; - } - } - - if (BlockType.isRailBlock(type) - && (item.getTypeId() == ItemID.MINECART - || item.getTypeId() == ItemID.POWERED_MINECART - || item.getTypeId() == ItemID.STORAGE_MINECART - || item.getTypeId() == ItemID.TNT_MINECART - || item.getTypeId() == ItemID.HOPPER_MINECART)) { - if (!plugin.getGlobalRegionManager().hasBypass(player, world) - && !placedInSet.canBuild(localPlayer) - && !placedInSet.allows(DefaultFlag.PLACE_VEHICLE, localPlayer)) { - player.sendMessage(ChatColor.DARK_RED + "You don't have permission to place vehicles here."); - event.setUseItemInHand(Result.DENY); - event.setCancelled(true); - return; - } - } - - if (item.getTypeId() == ItemID.WOOD_BOAT) { - if (!plugin.getGlobalRegionManager().hasBypass(player, world) - && !placedInSet.canBuild(localPlayer) - && !placedInSet.allows(DefaultFlag.PLACE_VEHICLE, localPlayer)) { - player.sendMessage(ChatColor.DARK_RED + "You don't have permission to place vehicles here."); - event.setUseItemInHand(Result.DENY); - event.setCancelled(true); - return; - } - } - } - - if (wcfg.getBlacklist() != null) { - if (player.isSneaking() // sneak + right clicking no longer opens guis as of some recent version - || (type != BlockID.CHEST - && type != BlockID.DISPENSER - && type != BlockID.FURNACE - && type != BlockID.BURNING_FURNACE - && type != BlockID.BREWING_STAND - && type != BlockID.ENCHANTMENT_TABLE - && type != BlockID.ANVIL - && type != BlockID.ENDER_CHEST - && type != BlockID.TRAPPED_CHEST - && type != BlockID.HOPPER - && type != BlockID.DROPPER)) { - if (!wcfg.getBlacklist().check( - new ItemUseBlacklistEvent(plugin.wrapPlayer(player), toVector(block), createTarget(item)), false, false)) { - event.setUseItemInHand(Result.DENY); - event.setCancelled(true); - return; - } - } - - if (!wcfg.getBlacklist().check( - new BlockInteractBlacklistEvent(plugin.wrapPlayer(player), toVector(block), createTarget(block)), false, false)) { - event.setUseInteractedBlock(Result.DENY); - event.setCancelled(true); - return; - } - - // Workaround for http://leaky.bukkit.org/issues/1034 - if (item.getTypeId() == BlockID.TNT) { - Block placedOn = block.getRelative(event.getBlockFace()); - if (!wcfg.getBlacklist().check( - new BlockPlaceBlacklistEvent(plugin.wrapPlayer(player), toVector(placedOn), createTarget(item)), false, false)) { - event.setUseItemInHand(Result.DENY); - event.setCancelled(true); - return; - } - } - } - - if ((type == BlockID.CHEST - || type == BlockID.DISPENSER - || type == BlockID.FURNACE - || type == BlockID.BURNING_FURNACE - || type == BlockID.ENCHANTMENT_TABLE - || type == BlockID.BREWING_STAND - || type == BlockID.TRAPPED_CHEST - || type == BlockID.HOPPER - || type == BlockID.DROPPER)) { - - if (wcfg.isChestProtected(block, player)) { - player.sendMessage(ChatColor.DARK_RED + "The chest is protected."); - event.setUseInteractedBlock(Result.DENY); - event.setCancelled(true); - return; - } - } - - /*if (wcfg.useRegions && wcfg.useiConomy && cfg.getiConomy() != null - && (type == BlockID.SIGN_POST || type == ItemID.SIGN || type == BlockID.WALL_SIGN)) { - BlockState block = blockClicked.getState(); - - if (((Sign)block).getLine(0).equalsIgnoreCase("[WorldGuard]") - && ((Sign)block).getLine(1).equalsIgnoreCase("For sale")) { - String regionId = ((Sign)block).getLine(2); - //String regionComment = ((Sign)block).getLine(3); - - if (regionId != null && regionId != "") { - RegionManager mgr = cfg.getWorldGuardPlugin().getGlobalRegionManager().get(player.getWorld().getName()); - ProtectedRegion region = mgr.getRegion(regionId); - - if (region != null) { - RegionFlags flags = region.getFlags(); - - if (flags.getBooleanFlag(DefaultFlag.BUYABLE).getValue(false)) { - if (iConomy.getBank().hasAccount(player.getName())) { - Account account = iConomy.getBank().getAccount(player.getName()); - double balance = account.getBalance(); - double regionPrice = flags.getDoubleFlag(DefaultFlag.PRICE).getValue(); - - if (balance >= regionPrice) { - account.subtract(regionPrice); - player.sendMessage(ChatColor.YELLOW + "You have bought the region " + regionId + " for " + - iConomy.getBank().format(regionPrice)); - DefaultDomain owners = region.getOwners(); - owners.addPlayer(player.getName()); - region.setOwners(owners); - flags.getBooleanFlag(DefaultFlag.BUYABLE).setValue(false); - account.save(); - } else { - player.sendMessage(ChatColor.YELLOW + "You have not enough money."); - } - } else { - player.sendMessage(ChatColor.YELLOW + "You have not enough money."); - } - } else { - player.sendMessage(ChatColor.RED + "Region: " + regionId + " is not buyable"); - } - } else { - player.sendMessage(ChatColor.DARK_RED + "The region " + regionId + " does not exist."); - } - } else { - player.sendMessage(ChatColor.DARK_RED + "No region specified."); - } - } - }*/ - } - - /** - * Called when a player steps on a pressure plate or tramples crops. - * - * @param event Thrown event - */ - private void handlePhysicalInteract(PlayerInteractEvent event) { - if (event.isCancelled()) return; - - Player player = event.getPlayer(); - Block block = event.getClickedBlock(); //not actually clicked but whatever - int type = block.getTypeId(); - World world = player.getWorld(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - - if (block.getTypeId() == BlockID.SOIL && wcfg.disablePlayerCropTrampling) { - event.setCancelled(true); - return; - } - - if (wcfg.useRegions) { - Vector pt = toVector(block); - RegionManager mgr = plugin.getGlobalRegionManager().get(world); - ApplicableRegionSet set = mgr.getApplicableRegions(pt); - LocalPlayer localPlayer = plugin.wrapPlayer(player); - - if (type == BlockID.STONE_PRESSURE_PLATE || type == BlockID.WOODEN_PRESSURE_PLATE - || type == BlockID.TRIPWIRE || type == BlockID.PRESSURE_PLATE_LIGHT - || type == BlockID.PRESSURE_PLATE_HEAVY) { - if (!plugin.getGlobalRegionManager().hasBypass(player, world) - && !set.canBuild(localPlayer) - && !set.allows(DefaultFlag.USE, localPlayer)) { - event.setUseInteractedBlock(Result.DENY); - event.setCancelled(true); - return; - } - } - } - } - - /** - * Called when a player uses an item. - *//* - @Override - public void onPlayerItem(PlayerItemEvent event) { - - if (event.isCancelled()) { - return; - } - - Player player = event.getPlayer(); - Block block = event.getBlockClicked(); - ItemStack item = event.getItem(); - int itemId = item.getTypeId(); - - GlobalConfiguration cfg = plugin.getGlobalConfiguration(); - WorldConfiguration wcfg = cfg.getWorldConfig(player.getWorld().getName()); - - if (wcfg.useRegions - && (itemId == 322 || itemId == 320 || itemId == 319 || itemId == 297 || itemId == 260 - || itemId == 350 || itemId == 349 || itemId == 354) ) { - return; - } - - if (!wcfg.itemDurability) { - // Hoes - if (item.getTypeId() >= 290 && item.getTypeId() <= 294) { - item.setDurability((byte) -1); - player.setItemInHand(item); - } - } - - if (wcfg.useRegions && !event.isBlock() && block != null) { - Vector pt = toVector(block.getRelative(event.getBlockFace())); - if (block.getTypeId() == BlockID.WALL_SIGN) { - pt = pt.subtract(0, 1, 0); - } - - if (!cfg.canBuild(player, pt)) { - player.sendMessage(ChatColor.DARK_RED - + "You don't have permission for this area."); - event.setCancelled(true); - return; - } - } - - if (wcfg.getBlacklist() != null && item != null && block != null) { - if (!wcfg.getBlacklist().check( - new ItemUseBlacklistEvent(plugin.wrapPlayer(player), - toVector(block.getRelative(event.getBlockFace())), - item.getTypeId()), false, false)) { - event.setCancelled(true); - return; - } - } - - if (wcfg.useRegions && item != null && block != null && item.getTypeId() == 259) { - Vector pt = toVector(block.getRelative(event.getBlockFace())); - RegionManager mgr = plugin.getGlobalRegionManager().get(player.getWorld().getName()); - - if (!mgr.getApplicableRegions(pt).isStateFlagAllowed(DefaultFlag.LIGHTER)) { - event.setCancelled(true); - return; - } - } - }*/ - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onPlayerDropItem(PlayerDropItemEvent event) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(event.getPlayer().getWorld()); - Player player = event.getPlayer(); - - if (wcfg.useRegions) { - if (!plugin.getGlobalRegionManager().hasBypass(player, player.getWorld()) - && !plugin.getGlobalRegionManager().allows(DefaultFlag.ITEM_DROP, player.getLocation())) { - event.setCancelled(true); - player.sendMessage(ChatColor.RED + "You don't have permission to do that in this area."); - } - } - - if (wcfg.getBlacklist() != null) { - Item ci = event.getItemDrop(); - - if (!wcfg.getBlacklist().check( - new ItemDropBlacklistEvent(plugin.wrapPlayer(event.getPlayer()), - toVector(ci.getLocation()), createTarget(ci.getItemStack())), false, false)) { - event.setCancelled(true); - return; - } - } - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onPlayerPickupItem(PlayerPickupItemEvent event) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(event.getPlayer().getWorld()); - - if (wcfg.getBlacklist() != null) { - Item ci = event.getItem(); - - if (!wcfg.getBlacklist().check( - new ItemAcquireBlacklistEvent(plugin.wrapPlayer(event.getPlayer()), - toVector(ci.getLocation()), createTarget(ci.getItemStack())), false, true)) { - event.setCancelled(true); - return; - } - } - } - - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onPlayerBucketFill(PlayerBucketFillEvent event) { - Player player = event.getPlayer(); - World world = player.getWorld(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - - if (!plugin.getGlobalRegionManager().canBuild( - player, event.getBlockClicked().getRelative(event.getBlockFace())) - && !(event.getItemStack().getTypeId() == ItemID.MILK_BUCKET)) { - player.sendMessage(ChatColor.DARK_RED + "You don't have permission for this area."); - event.setCancelled(true); - return; - } - - if (wcfg.getBlacklist() != null) { - if (!wcfg.getBlacklist().check( - new ItemUseBlacklistEvent(plugin.wrapPlayer(player), - toVector(player.getLocation()), createTarget(event.getBucket())), false, false)) { - event.setCancelled(true); - return; - } - } - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onPlayerFish(PlayerFishEvent event) { - WorldConfiguration wcfg = plugin.getGlobalStateManager().get(event.getPlayer().getWorld()); - - if (wcfg.disableExpDrops || !plugin.getGlobalRegionManager().allows(DefaultFlag.EXP_DROPS, - event.getPlayer().getLocation())) { - event.setExpToDrop(0); - } - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event) { - Player player = event.getPlayer(); - World world = player.getWorld(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - - if (!plugin.getGlobalRegionManager().canBuild( - player, event.getBlockClicked().getRelative(event.getBlockFace()))) { - player.sendMessage(ChatColor.DARK_RED + "You don't have permission for this area."); - event.setCancelled(true); - return; - } - - if (wcfg.getBlacklist() != null) { - if (!wcfg.getBlacklist().check( - new ItemUseBlacklistEvent(plugin.wrapPlayer(player), - toVector(player.getLocation()), createTarget(event.getBucket())), false, false)) { - event.setCancelled(true); - return; - } - } - } - - @EventHandler(priority = EventPriority.HIGHEST) - public void onPlayerRespawn(PlayerRespawnEvent event) { - Player player = event.getPlayer(); - Location location = player.getLocation(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(player.getWorld()); - - if (wcfg.useRegions) { - Vector pt = toVector(location); - RegionManager mgr = plugin.getGlobalRegionManager().get(player.getWorld()); - ApplicableRegionSet set = mgr.getApplicableRegions(pt); - - LocalPlayer localPlayer = plugin.wrapPlayer(player); - com.sk89q.worldedit.Location spawn = set.getFlag(DefaultFlag.SPAWN_LOC, localPlayer); - - if (spawn != null) { - event.setRespawnLocation(com.sk89q.worldedit.bukkit.BukkitUtil.toLocation(spawn)); - } - } - } - - @EventHandler(priority = EventPriority.HIGH) - public void onItemHeldChange(PlayerItemHeldEvent event) { - Player player = event.getPlayer(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(player.getWorld()); - - if (wcfg.removeInfiniteStacks - && !plugin.hasPermission(player, "worldguard.override.infinite-stack")) { - int newSlot = event.getNewSlot(); - ItemStack heldItem = player.getInventory().getItem(newSlot); - if (heldItem != null && heldItem.getAmount() < 0) { - player.getInventory().setItem(newSlot, null); - player.sendMessage(ChatColor.RED + "Infinite stack removed."); - } - } - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onPlayerBedEnter(PlayerBedEnterEvent event) { - Player player = event.getPlayer(); - Location location = player.getLocation(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(player.getWorld()); - - if (wcfg.useRegions) { - Vector pt = toVector(location); - RegionManager mgr = plugin.getGlobalRegionManager().get(player.getWorld()); - ApplicableRegionSet set = mgr.getApplicableRegions(pt); - - if (!plugin.getGlobalRegionManager().hasBypass(player, player.getWorld()) - && !set.allows(DefaultFlag.SLEEP, plugin.wrapPlayer(player))) { - event.setCancelled(true); - player.sendMessage("This bed doesn't belong to you!"); - return; - } - } - } - - @EventHandler(priority= EventPriority.LOW, ignoreCancelled = true) - public void onPlayerTeleport(PlayerTeleportEvent event) { - World world = event.getFrom().getWorld(); - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - - if (wcfg.useRegions) { - RegionManager mgr = plugin.getGlobalRegionManager().get(event.getFrom().getWorld()); - Vector pt = new Vector(event.getTo().getBlockX(), event.getTo().getBlockY(), event.getTo().getBlockZ()); - Vector ptFrom = new Vector(event.getFrom().getBlockX(), event.getFrom().getBlockY(), event.getFrom().getBlockZ()); - ApplicableRegionSet set = mgr.getApplicableRegions(pt); - ApplicableRegionSet setFrom = mgr.getApplicableRegions(ptFrom); - LocalPlayer localPlayer = plugin.wrapPlayer(event.getPlayer()); - - if (cfg.usePlayerTeleports) { - boolean result = checkMove(plugin, event.getPlayer(), event.getFrom(), event.getTo()); - if (result) { - event.setCancelled(true); - return; - } - } - - if (event.getCause() == TeleportCause.ENDER_PEARL) { - if (!plugin.getGlobalRegionManager().hasBypass(localPlayer, world) - && !(set.allows(DefaultFlag.ENDERPEARL, localPlayer) - && setFrom.allows(DefaultFlag.ENDERPEARL, localPlayer))) { - event.getPlayer().sendMessage(ChatColor.DARK_RED + "You're not allowed to go there."); - event.setCancelled(true); - return; - } - } - } - } - - @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) - public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { - Player player = event.getPlayer(); - LocalPlayer localPlayer = plugin.wrapPlayer(player); - World world = player.getWorld(); - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - - if (wcfg.useRegions && !plugin.getGlobalRegionManager().hasBypass(player, world)) { - Vector pt = toVector(player.getLocation()); - RegionManager mgr = plugin.getGlobalRegionManager().get(world); - ApplicableRegionSet set = mgr.getApplicableRegions(pt); - - Set allowedCommands = set.getFlag(DefaultFlag.ALLOWED_CMDS, localPlayer); - Set blockedCommands = set.getFlag(DefaultFlag.BLOCKED_CMDS, localPlayer); - CommandFilter test = new CommandFilter(allowedCommands, blockedCommands); - - if (!test.apply(event.getMessage())) { - player.sendMessage(ChatColor.RED + event.getMessage() + " is not allowed in this area."); - event.setCancelled(true); - return; - } - } - - if (cfg.blockInGameOp) { - if (opPattern.matcher(event.getMessage()).matches()) { - player.sendMessage(ChatColor.RED + "/op can only be used in console (as set by a WG setting)."); - event.setCancelled(true); - return; - } - } - } -} diff --git a/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardPlugin.java b/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardPlugin.java index a6ad15d9..1b2fcc15 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardPlugin.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardPlugin.java @@ -48,10 +48,21 @@ import com.sk89q.worldguard.bukkit.commands.GeneralCommands; import com.sk89q.worldguard.bukkit.commands.ProtectionCommands; import com.sk89q.worldguard.bukkit.commands.ToggleCommands; -import com.sk89q.worldguard.internal.listener.BlacklistListener; -import com.sk89q.worldguard.internal.listener.BlockedPotionsListener; -import com.sk89q.worldguard.internal.listener.ChestProtectionListener; -import com.sk89q.worldguard.internal.listener.RegionProtectionListener; +import com.sk89q.worldguard.bukkit.listener.BlacklistListener; +import com.sk89q.worldguard.bukkit.listener.BlockedPotionsListener; +import com.sk89q.worldguard.bukkit.listener.ChestProtectionListener; +import com.sk89q.worldguard.bukkit.listener.DebuggingListener; +import com.sk89q.worldguard.bukkit.listener.EventAbstractionListener; +import com.sk89q.worldguard.bukkit.listener.RegionProtectionListener; +import com.sk89q.worldguard.bukkit.listener.WorldGuardBlockListener; +import com.sk89q.worldguard.bukkit.listener.WorldGuardCommandBookListener; +import com.sk89q.worldguard.bukkit.listener.WorldGuardEntityListener; +import com.sk89q.worldguard.bukkit.listener.WorldGuardHangingListener; +import com.sk89q.worldguard.bukkit.listener.WorldGuardPlayerListener; +import com.sk89q.worldguard.bukkit.listener.WorldGuardServerListener; +import com.sk89q.worldguard.bukkit.listener.WorldGuardVehicleListener; +import com.sk89q.worldguard.bukkit.listener.WorldGuardWeatherListener; +import com.sk89q.worldguard.bukkit.listener.WorldGuardWorldListener; import com.sk89q.worldguard.protection.GlobalRegionManager; import com.sk89q.worldguard.protection.util.migrator.MigrationException; import com.sk89q.worldguard.protection.util.migrator.UUIDMigrator; @@ -218,6 +229,8 @@ public void run() { (new ChestProtectionListener(this)).registerEvents(); (new RegionProtectionListener(this)).registerEvents(); (new BlockedPotionsListener(this)).registerEvents(); + (new EventAbstractionListener(this)).registerEvents(); + (new DebuggingListener(this, getLogger())).registerEvents(); configuration.updateCommandBookGodMode(); diff --git a/src/main/java/com/sk89q/worldguard/bukkit/cause/Cause.java b/src/main/java/com/sk89q/worldguard/bukkit/cause/Cause.java new file mode 100644 index 00000000..c9adfe32 --- /dev/null +++ b/src/main/java/com/sk89q/worldguard/bukkit/cause/Cause.java @@ -0,0 +1,132 @@ +/* + * 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.cause; + +import com.google.common.base.Joiner; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * An instance of this object describes the actors that played a role in + * causing an event, with the ability to describe a situation where one actor + * controls several other actors to create the event. + * + *

For example, if a player fires an arrow that hits an item frame, the player + * is the initiator, while the arrow is merely controlled by the player to + * hit the item frame.

+ */ +public class Cause { + + private static final Cause UNKNOWN = new Cause(Collections.emptyList()); + + private final List causes; + + /** + * Create a new instance. + * + * @param causes a list of causes + */ + private Cause(List causes) { + checkNotNull(causes); + this.causes = causes; + } + + /** + * Return whether a cause is known. + * + * @return true if known + */ + public boolean isKnown() { + return !causes.isEmpty(); + } + + @Nullable + public Player getPlayerRootCause() { + for (Object object : causes) { + if (object instanceof Player) { + return (Player) object; + } + } + + return null; + } + + @Override + public String toString() { + return Joiner.on(" | ").join(causes); + } + + /** + * Expand an cause object. + * + * @param list the list to add elements to + * @param element an array of objects + */ + private static void expand(List list, @Nullable Object ... element) { + if (element != null) { + for (Object o : element) { + if (o == null) { + continue; + } + + if (o instanceof Projectile) { + expand(list, ((Projectile) o).getShooter()); + } else { + list.add(o); + } + } + } + } + + /** + * Create a new instance with the given objects as the cause, + * where the first-most object is the initial initiator and those + * following it are controlled by the previous entry. + * + * @param cause an array of causing objects + * @return a cause + */ + public static Cause create(@Nullable Object ... cause) { + if (cause != null) { + List causes = new ArrayList(cause.length); + expand(causes, cause); + return new Cause(causes); + } else { + return UNKNOWN; + } + } + + /** + * Create a new instance that indicates that the cause is not known. + * + * @return a cause + */ + public static Cause unknown() { + return UNKNOWN; + } + +} diff --git a/src/main/java/com/sk89q/worldguard/internal/event/AbstractInteractEvent.java b/src/main/java/com/sk89q/worldguard/bukkit/event/AbstractInteractEvent.java similarity index 58% rename from src/main/java/com/sk89q/worldguard/internal/event/AbstractInteractEvent.java rename to src/main/java/com/sk89q/worldguard/bukkit/event/AbstractInteractEvent.java index f0142d4f..0c4aa410 100644 --- a/src/main/java/com/sk89q/worldguard/internal/event/AbstractInteractEvent.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/event/AbstractInteractEvent.java @@ -17,38 +17,31 @@ * along with this program. If not, see . */ -package com.sk89q.worldguard.internal.event; +package com.sk89q.worldguard.bukkit.event; -import com.sk89q.worldguard.internal.cause.Cause; +import com.sk89q.worldguard.bukkit.cause.Cause; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; -import java.util.Collections; -import java.util.List; - import static com.google.common.base.Preconditions.checkNotNull; -abstract class AbstractInteractEvent extends Event implements Cancellable { +public abstract class AbstractInteractEvent extends Event implements Cancellable { private final Event originalEvent; - private final List> causes; - private final Interaction interaction; + private final Cause cause; private boolean cancelled; /** * Create a new instance * * @param originalEvent the original event - * @param causes a list of causes, where the originating causes are at the beginning - * @param interaction the action that is being taken + * @param cause the cause */ - protected AbstractInteractEvent(Event originalEvent, List> causes, Interaction interaction) { + protected AbstractInteractEvent(Event originalEvent, Cause cause) { checkNotNull(originalEvent); - checkNotNull(causes); - checkNotNull(interaction); + checkNotNull(cause); this.originalEvent = originalEvent; - this.causes = causes; - this.interaction = interaction; + this.cause = cause; } /** @@ -61,22 +54,12 @@ public Event getOriginalEvent() { } /** - * Return an unmodifiable list of causes, where the originating causes are - * at the beginning of the list. + * Return the cause. * - * @return a list of causes + * @return the cause */ - public List> getCauses() { - return Collections.unmodifiableList(causes); - } - - /** - * Get the action that is being taken. - * - * @return the action - */ - public Interaction getInteraction() { - return interaction; + public Cause getCause() { + return cause; } @Override 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 new file mode 100644 index 00000000..1d01971d --- /dev/null +++ b/src/main/java/com/sk89q/worldguard/bukkit/event/block/AbstractBlockEvent.java @@ -0,0 +1,84 @@ +/* + * 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.block; + +import com.sk89q.worldguard.bukkit.cause.Cause; +import com.sk89q.worldguard.bukkit.event.AbstractInteractEvent; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.event.Event; + +import javax.annotation.Nullable; + +import static com.google.common.base.Preconditions.checkNotNull; + +abstract class AbstractBlockEvent extends AbstractInteractEvent { + + private final Location target; + @Nullable + private final Block block; + private final Material effectiveMaterial; + + protected AbstractBlockEvent(Event originalEvent, Cause cause, Block block) { + super(originalEvent, cause); + checkNotNull(block); + this.target = block.getLocation(); + this.block = block; + this.effectiveMaterial = block.getType(); + } + + protected AbstractBlockEvent(Event originalEvent, Cause cause, Location target, Material effectiveMaterial) { + super(originalEvent, cause); + this.target = target; + this.block = null; + this.effectiveMaterial = effectiveMaterial; + } + + /** + * Get the target block being affected. + * + * @return a block + */ + public Location getTarget() { + return target; + } + + /** + * Get the block. + * + * @return the block + */ + @Nullable + public Block getBlock() { + return block; + } + + /** + * Get the effective material of the block, regardless of what the block + * currently is. + * + * @return the effective material + */ + public Material getEffectiveMaterial() { + return effectiveMaterial; + } + +} diff --git a/src/main/java/com/sk89q/worldguard/internal/cause/BlockCause.java b/src/main/java/com/sk89q/worldguard/bukkit/event/block/BreakBlockEvent.java similarity index 52% rename from src/main/java/com/sk89q/worldguard/internal/cause/BlockCause.java rename to src/main/java/com/sk89q/worldguard/bukkit/event/block/BreakBlockEvent.java index d19d2fd0..e3647c62 100644 --- a/src/main/java/com/sk89q/worldguard/internal/cause/BlockCause.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/event/block/BreakBlockEvent.java @@ -17,32 +17,34 @@ * along with this program. If not, see . */ -package com.sk89q.worldguard.internal.cause; +package com.sk89q.worldguard.bukkit.event.block; +import com.sk89q.worldguard.bukkit.cause.Cause; +import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.block.Block; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; -/** - * A cause that is a block. - */ -import static com.google.common.base.Preconditions.checkNotNull; +public class BreakBlockEvent extends AbstractBlockEvent { -public class BlockCause implements Cause { + private static final HandlerList handlers = new HandlerList(); - private final Block block; + public BreakBlockEvent(Event originalEvent, Cause cause, Block block) { + super(originalEvent, cause, block); + } - /** - * Create a new instance. - * - * @param block the block - */ - public BlockCause(Block block) { - checkNotNull(block); - this.block = block; + public BreakBlockEvent(Event originalEvent, Cause cause, Location target, Material effectiveMaterial) { + super(originalEvent, cause, target, effectiveMaterial); } @Override - public Block get() { - return block; + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; } } diff --git a/src/main/java/com/sk89q/worldguard/bukkit/event/block/PlaceBlockEvent.java b/src/main/java/com/sk89q/worldguard/bukkit/event/block/PlaceBlockEvent.java new file mode 100644 index 00000000..7a02a876 --- /dev/null +++ b/src/main/java/com/sk89q/worldguard/bukkit/event/block/PlaceBlockEvent.java @@ -0,0 +1,50 @@ +/* + * 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.block; + +import com.sk89q.worldguard.bukkit.cause.Cause; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class PlaceBlockEvent extends AbstractBlockEvent { + + private static final HandlerList handlers = new HandlerList(); + + public PlaceBlockEvent(Event originalEvent, Cause cause, Block block) { + super(originalEvent, cause, block); + } + + public PlaceBlockEvent(Event originalEvent, Cause cause, Location target, Material effectiveMaterial) { + super(originalEvent, cause, target, effectiveMaterial); + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } + +} diff --git a/src/main/java/com/sk89q/worldguard/bukkit/event/block/UseBlockEvent.java b/src/main/java/com/sk89q/worldguard/bukkit/event/block/UseBlockEvent.java new file mode 100644 index 00000000..bd22dbf0 --- /dev/null +++ b/src/main/java/com/sk89q/worldguard/bukkit/event/block/UseBlockEvent.java @@ -0,0 +1,53 @@ +/* + * 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.block; + +import com.sk89q.worldguard.bukkit.cause.Cause; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * Fired when a block is interacted with. + */ +public class UseBlockEvent extends AbstractBlockEvent { + + private static final HandlerList handlers = new HandlerList(); + + public UseBlockEvent(Event originalEvent, Cause cause, Block block) { + super(originalEvent, cause, block); + } + + public UseBlockEvent(Event originalEvent, Cause cause, Location target, Material effectiveMaterial) { + super(originalEvent, cause, target, effectiveMaterial); + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } + +} diff --git a/src/main/java/com/sk89q/worldguard/bukkit/event/entity/AbstractEntityEvent.java b/src/main/java/com/sk89q/worldguard/bukkit/event/entity/AbstractEntityEvent.java new file mode 100644 index 00000000..093325e8 --- /dev/null +++ b/src/main/java/com/sk89q/worldguard/bukkit/event/entity/AbstractEntityEvent.java @@ -0,0 +1,72 @@ +/* + * 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.entity; + +import com.sk89q.worldguard.bukkit.cause.Cause; +import com.sk89q.worldguard.bukkit.event.AbstractInteractEvent; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.event.Event; + +import javax.annotation.Nullable; + +import static com.google.common.base.Preconditions.checkNotNull; + +abstract class AbstractEntityEvent extends AbstractInteractEvent { + + private final Location target; + @Nullable + private final Entity entity; + + protected AbstractEntityEvent(Event originalEvent, Cause cause, Entity entity) { + super(originalEvent, cause); + checkNotNull(entity); + this.target = entity.getLocation(); + this.entity = entity; + } + + protected AbstractEntityEvent(Event originalEvent, Cause cause, Location target) { + super(originalEvent, cause); + checkNotNull(target); + this.target = target; + this.entity = null; + } + + /** + * Get the target location being affected. + * + * @return a location + */ + public Location getTarget() { + return target; + } + + + /** + * Get the target entity being affected. + * + * @return a entity + */ + @Nullable + public Entity getEntity() { + return entity; + } + +} diff --git a/src/main/java/com/sk89q/worldguard/internal/cause/EntityCause.java b/src/main/java/com/sk89q/worldguard/bukkit/event/entity/DestroyEntityEvent.java similarity index 57% rename from src/main/java/com/sk89q/worldguard/internal/cause/EntityCause.java rename to src/main/java/com/sk89q/worldguard/bukkit/event/entity/DestroyEntityEvent.java index f24774b7..db53d8eb 100644 --- a/src/main/java/com/sk89q/worldguard/internal/cause/EntityCause.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/event/entity/DestroyEntityEvent.java @@ -17,32 +17,38 @@ * along with this program. If not, see . */ -package com.sk89q.worldguard.internal.cause; +package com.sk89q.worldguard.bukkit.event.entity; +import com.sk89q.worldguard.bukkit.cause.Cause; import org.bukkit.entity.Entity; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import javax.annotation.Nonnull; import static com.google.common.base.Preconditions.checkNotNull; -/** - * A cause that is an entity. - */ -public class EntityCause implements Cause { +public class DestroyEntityEvent extends AbstractEntityEvent { - private final Entity entity; + private static final HandlerList handlers = new HandlerList(); - /** - * Create a new instance. - * - * @param entity the entity - */ - public EntityCause(Entity entity) { - checkNotNull(entity); - this.entity = entity; + public DestroyEntityEvent(Event originalEvent, Cause cause, Entity target) { + super(originalEvent, cause, checkNotNull(target)); } @Override - public Entity get() { - return entity; + @Nonnull + public Entity getEntity() { + return super.getEntity(); + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; } } diff --git a/src/main/java/com/sk89q/worldguard/internal/event/BlockInteractEvent.java b/src/main/java/com/sk89q/worldguard/bukkit/event/entity/SpawnEntityEvent.java similarity index 56% rename from src/main/java/com/sk89q/worldguard/internal/event/BlockInteractEvent.java rename to src/main/java/com/sk89q/worldguard/bukkit/event/entity/SpawnEntityEvent.java index 5f21d854..05fee2f7 100644 --- a/src/main/java/com/sk89q/worldguard/internal/event/BlockInteractEvent.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/event/entity/SpawnEntityEvent.java @@ -17,46 +17,40 @@ * along with this program. If not, see . */ -package com.sk89q.worldguard.internal.event; +package com.sk89q.worldguard.bukkit.event.entity; -import com.sk89q.worldguard.internal.cause.Cause; -import org.bukkit.block.Block; +import com.sk89q.worldguard.bukkit.cause.Cause; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; -import java.util.List; - import static com.google.common.base.Preconditions.checkNotNull; -/** - * Fired when a block is interacted with. - */ -public class BlockInteractEvent extends AbstractInteractEvent { +public class SpawnEntityEvent extends AbstractEntityEvent { private static final HandlerList handlers = new HandlerList(); - private final Block target; + private final EntityType effectiveType; - /** - * Create a new instance. - * - * @param originalEvent the original event - * @param causes a list of causes, where the originating causes are at the beginning - * @param interaction the action that is being taken - * @param target the target block being affected - */ - public BlockInteractEvent(Event originalEvent, List> causes, Interaction interaction, Block target) { - super(originalEvent, causes, interaction); - checkNotNull(target); - this.target = target; + public SpawnEntityEvent(Event originalEvent, Cause cause, Entity target) { + super(originalEvent, cause, checkNotNull(target)); + this.effectiveType = target.getType(); + } + + public SpawnEntityEvent(Event originalEvent, Cause cause, Location location, EntityType type) { + super(originalEvent, cause, location); + checkNotNull(type); + this.effectiveType = type; } /** - * Get the target block being affected. + * Get the effective entity type of the spawned entity. * - * @return a block + * @return the effective type */ - public Block getTarget() { - return target; + public EntityType getEffectiveType() { + return effectiveType; } @Override diff --git a/src/main/java/com/sk89q/worldguard/internal/event/EntityInteractEvent.java b/src/main/java/com/sk89q/worldguard/bukkit/event/entity/UseEntityEvent.java similarity index 59% rename from src/main/java/com/sk89q/worldguard/internal/event/EntityInteractEvent.java rename to src/main/java/com/sk89q/worldguard/bukkit/event/entity/UseEntityEvent.java index bc924ee0..66b34282 100644 --- a/src/main/java/com/sk89q/worldguard/internal/event/EntityInteractEvent.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/event/entity/UseEntityEvent.java @@ -17,46 +17,32 @@ * along with this program. If not, see . */ -package com.sk89q.worldguard.internal.event; +package com.sk89q.worldguard.bukkit.event.entity; -import com.sk89q.worldguard.internal.cause.Cause; +import com.sk89q.worldguard.bukkit.cause.Cause; import org.bukkit.entity.Entity; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; -import java.util.List; +import javax.annotation.Nonnull; import static com.google.common.base.Preconditions.checkNotNull; /** * Fired when an entity is interacted with. */ -public class EntityInteractEvent extends AbstractInteractEvent { +public class UseEntityEvent extends AbstractEntityEvent { private static final HandlerList handlers = new HandlerList(); - private final Entity target; - /** - * Create a new instance. - * - * @param originalEvent the original event - * @param causes a list of causes, where the originating causes are at the beginning - * @param interaction the action that is being taken - * @param target the target entity being affected - */ - public EntityInteractEvent(Event originalEvent, List> causes, Interaction interaction, Entity target) { - super(originalEvent, causes, interaction); - checkNotNull(target); - this.target = target; + public UseEntityEvent(Event originalEvent, Cause cause, Entity target) { + super(originalEvent, cause, checkNotNull(target)); } - /** - * Get the target entity. - * - * @return the target entity - */ - public Entity getTarget() { - return target; + @Override + @Nonnull + public Entity getEntity() { + return super.getEntity(); } @Override @@ -67,4 +53,5 @@ public HandlerList getHandlers() { public static HandlerList getHandlerList() { return handlers; } + } diff --git a/src/main/java/com/sk89q/worldguard/internal/event/ItemInteractEvent.java b/src/main/java/com/sk89q/worldguard/bukkit/event/inventory/UseItemEvent.java similarity index 72% rename from src/main/java/com/sk89q/worldguard/internal/event/ItemInteractEvent.java rename to src/main/java/com/sk89q/worldguard/bukkit/event/inventory/UseItemEvent.java index 163cd53a..acd0185e 100644 --- a/src/main/java/com/sk89q/worldguard/internal/event/ItemInteractEvent.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/event/inventory/UseItemEvent.java @@ -17,38 +17,28 @@ * along with this program. If not, see . */ -package com.sk89q.worldguard.internal.event; +package com.sk89q.worldguard.bukkit.event.inventory; -import com.sk89q.worldguard.internal.cause.Cause; +import com.sk89q.worldguard.bukkit.cause.Cause; +import com.sk89q.worldguard.bukkit.event.AbstractInteractEvent; import org.bukkit.World; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; import org.bukkit.inventory.ItemStack; -import java.util.List; - import static com.google.common.base.Preconditions.checkNotNull; /** * Fired when an item is interacted with. */ -public class ItemInteractEvent extends AbstractInteractEvent { +public class UseItemEvent extends AbstractInteractEvent { private static final HandlerList handlers = new HandlerList(); private final World world; private final ItemStack itemStack; - /** - * Create a new instance. - * - * @param originalEvent the original event - * @param causes a list of causes, where the originating causes are at the beginning - * @param interaction the action that is being taken - * @param world the world - * @param itemStack the item - */ - public ItemInteractEvent(Event originalEvent, List> causes, Interaction interaction, World world, ItemStack itemStack) { - super(originalEvent, causes, interaction); + public UseItemEvent(Event originalEvent, Cause cause, World world, ItemStack itemStack) { + super(originalEvent, cause); checkNotNull(world); checkNotNull(itemStack); this.world = world; diff --git a/src/main/java/com/sk89q/worldguard/internal/listener/AbstractListener.java b/src/main/java/com/sk89q/worldguard/bukkit/listener/AbstractListener.java similarity index 98% rename from src/main/java/com/sk89q/worldguard/internal/listener/AbstractListener.java rename to src/main/java/com/sk89q/worldguard/bukkit/listener/AbstractListener.java index f8845c5b..bce1e6ac 100644 --- a/src/main/java/com/sk89q/worldguard/internal/listener/AbstractListener.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/listener/AbstractListener.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldguard.internal.listener; +package com.sk89q.worldguard.bukkit.listener; import com.sk89q.worldguard.bukkit.WorldConfiguration; import com.sk89q.worldguard.bukkit.WorldGuardPlugin; diff --git a/src/main/java/com/sk89q/worldguard/bukkit/listener/BlacklistListener.java b/src/main/java/com/sk89q/worldguard/bukkit/listener/BlacklistListener.java new file mode 100644 index 00000000..549981fe --- /dev/null +++ b/src/main/java/com/sk89q/worldguard/bukkit/listener/BlacklistListener.java @@ -0,0 +1,258 @@ +/* + * 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.listener; + +import com.sk89q.worldguard.LocalPlayer; +import com.sk89q.worldguard.blacklist.event.BlockBreakBlacklistEvent; +import com.sk89q.worldguard.blacklist.event.BlockDispenseBlacklistEvent; +import com.sk89q.worldguard.blacklist.event.BlockInteractBlacklistEvent; +import com.sk89q.worldguard.blacklist.event.BlockPlaceBlacklistEvent; +import com.sk89q.worldguard.blacklist.event.ItemAcquireBlacklistEvent; +import com.sk89q.worldguard.blacklist.event.ItemDestroyWithBlacklistEvent; +import com.sk89q.worldguard.blacklist.event.ItemDropBlacklistEvent; +import com.sk89q.worldguard.blacklist.event.ItemUseBlacklistEvent; +import com.sk89q.worldguard.bukkit.ConfigurationManager; +import com.sk89q.worldguard.bukkit.WorldConfiguration; +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +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.DestroyEntityEvent; +import com.sk89q.worldguard.bukkit.event.entity.SpawnEntityEvent; +import com.sk89q.worldguard.bukkit.event.inventory.UseItemEvent; +import com.sk89q.worldguard.bukkit.util.Materials; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.BlockDispenseEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerPickupItemEvent; +import org.bukkit.inventory.ItemStack; + +import static com.sk89q.worldguard.bukkit.BukkitUtil.createTarget; +import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector; + +/** + * Handle events that need to be processed by the blacklist. + */ +public class BlacklistListener extends AbstractListener { + + /** + * Construct the listener. + * + * @param plugin an instance of WorldGuardPlugin + */ + public BlacklistListener(WorldGuardPlugin plugin) { + super(plugin); + } + + @EventHandler(ignoreCancelled = true) + public void onBreakBlock(BreakBlockEvent event) { + Player player = event.getCause().getPlayerRootCause(); + + if (player == null) { + return; + } + + LocalPlayer localPlayer = getPlugin().wrapPlayer(player); + Block target = event.getBlock(); + WorldConfiguration wcfg = getWorldConfig(player); + + // Blacklist guard + if (wcfg.getBlacklist() == null) { + return; + } + + if (!wcfg.getBlacklist().check( + new BlockBreakBlacklistEvent(localPlayer, toVector(event.getTarget()), createTarget(target, event.getEffectiveMaterial())), false, false)) { + event.setCancelled(true); + } else if (!wcfg.getBlacklist().check( + new ItemDestroyWithBlacklistEvent(localPlayer, toVector(event.getTarget()), createTarget(player.getItemInHand())), false, false)) { + event.setCancelled(true); + } + } + + @EventHandler(ignoreCancelled = true) + public void onPlaceBlock(PlaceBlockEvent event) { + Player player = event.getCause().getPlayerRootCause(); + + if (player == null) { + return; + } + + LocalPlayer localPlayer = getPlugin().wrapPlayer(player); + Block target = event.getBlock(); + WorldConfiguration wcfg = getWorldConfig(player); + + // Blacklist guard + if (wcfg.getBlacklist() == null) { + return; + } + + if (!wcfg.getBlacklist().check(new BlockPlaceBlacklistEvent( + localPlayer, toVector(event.getTarget()), createTarget(target, event.getEffectiveMaterial())), false, false)) { + event.setCancelled(true); + } + } + + @EventHandler(ignoreCancelled = true) + public void onUseBlock(UseBlockEvent event) { + Player player = event.getCause().getPlayerRootCause(); + + if (player == null) { + return; + } + + LocalPlayer localPlayer = getPlugin().wrapPlayer(player); + Block target = event.getBlock(); + WorldConfiguration wcfg = getWorldConfig(player); + + // Blacklist guard + if (wcfg.getBlacklist() == null) { + return; + } + + if (!wcfg.getBlacklist().check(new BlockInteractBlacklistEvent( + localPlayer, toVector(event.getTarget()), createTarget(target, event.getEffectiveMaterial())), false, false)) { + event.setCancelled(true); + } + } + + @EventHandler(ignoreCancelled = true) + public void onSpawnEntity(SpawnEntityEvent event) { + Player player = event.getCause().getPlayerRootCause(); + + if (player == null) { + return; + } + + LocalPlayer localPlayer = getPlugin().wrapPlayer(player); + WorldConfiguration wcfg = getWorldConfig(player); + + // Blacklist guard + if (wcfg.getBlacklist() == null) { + return; + } + + Material material = Materials.getRelatedMaterial(event.getEffectiveType()); + if (material != null) { + if (!wcfg.getBlacklist().check(new ItemUseBlacklistEvent(localPlayer, toVector(event.getTarget()), createTarget(material)), false, false)) { + event.setCancelled(true); + } + } + } + + @EventHandler(ignoreCancelled = true) + public void onDestroyEntity(DestroyEntityEvent event) { + Player player = event.getCause().getPlayerRootCause(); + + if (player == null) { + return; + } + + LocalPlayer localPlayer = getPlugin().wrapPlayer(player); + Entity target = event.getEntity(); + WorldConfiguration wcfg = getWorldConfig(player); + + // Blacklist guard + if (wcfg.getBlacklist() == null) { + return; + } + + Material material = Materials.getRelatedMaterial(target.getType()); + if (material != null) { + // Not really a block but we only have one on-break blacklist event + if (!wcfg.getBlacklist().check(new BlockBreakBlacklistEvent(localPlayer, toVector(event.getTarget()), createTarget(material)), false, false)) { + event.setCancelled(true); + } + } + } + + @EventHandler(ignoreCancelled = true) + public void onUseItem(UseItemEvent event) { + Player player = event.getCause().getPlayerRootCause(); + + if (player == null) { + return; + } + + LocalPlayer localPlayer = getPlugin().wrapPlayer(player); + ItemStack target = event.getItemStack(); + WorldConfiguration wcfg = getWorldConfig(player); + + // Blacklist guard + if (wcfg.getBlacklist() == null) { + return; + } + + if (!wcfg.getBlacklist().check(new ItemUseBlacklistEvent(localPlayer, toVector(player.getLocation()), createTarget(target)), false, false)) { + event.setCancelled(true); + } + } + + @EventHandler(ignoreCancelled = true) + public void onPlayerDropItem(PlayerDropItemEvent event) { + ConfigurationManager cfg = getPlugin().getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(event.getPlayer().getWorld()); + + if (wcfg.getBlacklist() != null) { + Item ci = event.getItemDrop(); + + if (!wcfg.getBlacklist().check( + new ItemDropBlacklistEvent(getPlugin().wrapPlayer(event.getPlayer()), + toVector(ci.getLocation()), createTarget(ci.getItemStack())), false, false)) { + event.setCancelled(true); + } + } + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onPlayerPickupItem(PlayerPickupItemEvent event) { + ConfigurationManager cfg = getPlugin().getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(event.getPlayer().getWorld()); + + if (wcfg.getBlacklist() != null) { + Item ci = event.getItem(); + + if (!wcfg.getBlacklist().check( + new ItemAcquireBlacklistEvent(getPlugin().wrapPlayer(event.getPlayer()), + toVector(ci.getLocation()), createTarget(ci.getItemStack())), false, true)) { + event.setCancelled(true); + } + } + } + + @EventHandler(ignoreCancelled = true) + public void onBlockDispense(BlockDispenseEvent event) { + ConfigurationManager cfg = getPlugin().getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld()); + + if (wcfg.getBlacklist() != null) { + if (!wcfg.getBlacklist().check(new BlockDispenseBlacklistEvent(null, toVector(event.getBlock()), createTarget(event.getItem())), false, false)) { + event.setCancelled(true); + } + } + } + +} diff --git a/src/main/java/com/sk89q/worldguard/internal/listener/BlockedPotionsListener.java b/src/main/java/com/sk89q/worldguard/bukkit/listener/BlockedPotionsListener.java similarity index 91% rename from src/main/java/com/sk89q/worldguard/internal/listener/BlockedPotionsListener.java rename to src/main/java/com/sk89q/worldguard/bukkit/listener/BlockedPotionsListener.java index 93a9e01a..96c32236 100644 --- a/src/main/java/com/sk89q/worldguard/internal/listener/BlockedPotionsListener.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/listener/BlockedPotionsListener.java @@ -17,14 +17,13 @@ * along with this program. If not, see . */ -package com.sk89q.worldguard.internal.listener; +package com.sk89q.worldguard.bukkit.listener; import com.sk89q.worldguard.bukkit.BukkitUtil; import com.sk89q.worldguard.bukkit.ConfigurationManager; import com.sk89q.worldguard.bukkit.WorldConfiguration; import com.sk89q.worldguard.bukkit.WorldGuardPlugin; -import com.sk89q.worldguard.internal.cause.Causes; -import com.sk89q.worldguard.internal.event.ItemInteractEvent; +import com.sk89q.worldguard.bukkit.event.inventory.UseItemEvent; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.entity.Player; @@ -49,9 +48,9 @@ public BlockedPotionsListener(WorldGuardPlugin plugin) { } @EventHandler - public void onItemInteract(ItemInteractEvent event) { + public void onItemInteract(UseItemEvent event) { // We only care about player caused events - if (!Causes.mayInvolvePlayer(event.getCauses())) { + if (event.getCause().getPlayerRootCause() == null) { return; } @@ -84,7 +83,7 @@ public void onItemInteract(ItemInteractEvent event) { } if (blockedEffect != null) { - Player player = Causes.getInvolvedPlayer(event.getCauses()); + Player player = event.getCause().getPlayerRootCause(); if (player != null) { if (getPlugin().hasPermission(player, "worldguard.override.potions")) { diff --git a/src/main/java/com/sk89q/worldguard/bukkit/listener/ChestProtectionListener.java b/src/main/java/com/sk89q/worldguard/bukkit/listener/ChestProtectionListener.java new file mode 100644 index 00000000..9f8536c0 --- /dev/null +++ b/src/main/java/com/sk89q/worldguard/bukkit/listener/ChestProtectionListener.java @@ -0,0 +1,177 @@ +/* + * 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.listener; + +import com.sk89q.worldedit.blocks.BlockID; +import com.sk89q.worldguard.bukkit.WorldConfiguration; +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +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 org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.block.SignChangeEvent; + +/** + * Handle events that need to be processed by the chest protection. + */ +public class ChestProtectionListener extends AbstractListener { + + /** + * Construct the listener. + * + * @param plugin an instance of WorldGuardPlugin + */ + public ChestProtectionListener(WorldGuardPlugin plugin) { + super(plugin); + } + + @EventHandler(ignoreCancelled = true) + public void onPlaceBlock(PlaceBlockEvent event) { + Player player = event.getCause().getPlayerRootCause(); + Location target = event.getTarget(); + + if (player != null) { + WorldConfiguration wcfg = getWorldConfig(player); + + // Early guard + if (!wcfg.signChestProtection) { + return; + } + + if (wcfg.getChestProtection().isChest(event.getEffectiveMaterial().getId()) && wcfg.isChestProtected(target.getBlock(), player)) { + player.sendMessage(ChatColor.DARK_RED + "This spot is for a chest that you don't have permission for."); + event.setCancelled(true); + } + } + } + + @EventHandler(ignoreCancelled = true) + public void onBreakBlock(BreakBlockEvent event) { + Player player = event.getCause().getPlayerRootCause(); + Location target = event.getTarget(); + + WorldConfiguration wcfg = getWorldConfig(target.getWorld()); + + // Early guard + if (!wcfg.signChestProtection) { + return; + } + + if (player != null) { + if (wcfg.isChestProtected(target.getBlock(), player)) { + player.sendMessage(ChatColor.DARK_RED + "This chest is protected."); + event.setCancelled(true); + } + } else { + if (wcfg.isChestProtected(target.getBlock())) { + // No player? Deny anyway + event.setCancelled(true); + } + } + } + + @EventHandler(ignoreCancelled = true) + public void onUseBlock(UseBlockEvent event) { + Player player = event.getCause().getPlayerRootCause(); + Location target = event.getTarget(); + + WorldConfiguration wcfg = getWorldConfig(target.getWorld()); + + // Early guard + if (!wcfg.signChestProtection) { + return; + } + + if (player != null) { + if (wcfg.isChestProtected(target.getBlock(), player)) { + player.sendMessage(ChatColor.DARK_RED + "This chest is protected."); + event.setCancelled(true); + } + } else { + if (wcfg.isChestProtected(target.getBlock())) { + // No player? Deny anyway + event.setCancelled(true); + } + } + } + + @EventHandler(ignoreCancelled = true) + public void onSignChange(SignChangeEvent event) { + Player player = event.getPlayer(); + WorldConfiguration wcfg = getWorldConfig(player); + + if (wcfg.signChestProtection) { + if (event.getLine(0).equalsIgnoreCase("[Lock]")) { + if (wcfg.isChestProtectedPlacement(event.getBlock(), player)) { + player.sendMessage(ChatColor.DARK_RED + "You do not own the adjacent chest."); + event.getBlock().breakNaturally(); + event.setCancelled(true); + return; + } + + if (event.getBlock().getTypeId() != BlockID.SIGN_POST) { + player.sendMessage(ChatColor.RED + + "The [Lock] sign must be a sign post, not a wall sign."); + + event.getBlock().breakNaturally(); + event.setCancelled(true); + return; + } + + if (!event.getLine(1).equalsIgnoreCase(player.getName())) { + player.sendMessage(ChatColor.RED + + "The first owner line must be your name."); + + event.getBlock().breakNaturally(); + event.setCancelled(true); + return; + } + + int below = event.getBlock().getRelative(0, -1, 0).getTypeId(); + + if (below == BlockID.TNT || below == BlockID.SAND + || below == BlockID.GRAVEL || below == BlockID.SIGN_POST) { + player.sendMessage(ChatColor.RED + + "That is not a safe block that you're putting this sign on."); + + event.getBlock().breakNaturally(); + event.setCancelled(true); + return; + } + + event.setLine(0, "[Lock]"); + player.sendMessage(ChatColor.YELLOW + + "A chest or double chest above is now protected."); + } + } else if (!wcfg.disableSignChestProtectionCheck) { + if (event.getLine(0).equalsIgnoreCase("[Lock]")) { + player.sendMessage(ChatColor.RED + + "WorldGuard's sign chest protection is disabled."); + + event.getBlock().breakNaturally(); + event.setCancelled(true); + } + } + } + +} diff --git a/src/main/java/com/sk89q/worldguard/bukkit/listener/DebuggingListener.java b/src/main/java/com/sk89q/worldguard/bukkit/listener/DebuggingListener.java new file mode 100644 index 00000000..4943be13 --- /dev/null +++ b/src/main/java/com/sk89q/worldguard/bukkit/listener/DebuggingListener.java @@ -0,0 +1,162 @@ +/* + * 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.listener; + +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +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.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 org.bukkit.Location; +import org.bukkit.event.EventHandler; + +import java.util.logging.Logger; + +import static com.google.common.base.Preconditions.checkNotNull; + +public class DebuggingListener extends AbstractListener { + + private final Logger logger; + + /** + * Construct the listener. + * + * @param plugin an instance of WorldGuardPlugin + * @param logger the logger + */ + public DebuggingListener(WorldGuardPlugin plugin, Logger logger) { + super(plugin); + checkNotNull(logger); + this.logger = logger; + } + + @EventHandler + public void onPlaceBlock(PlaceBlockEvent event) { + StringBuilder builder = new StringBuilder(); + builder.append("PLACE"); + builder.append(" "); + builder.append("").append(event.getEffectiveMaterial()); + builder.append(" "); + builder.append("@").append(toBlockString(event.getTarget())); + builder.append(" "); + builder.append("[").append(event.getCause()).append("]"); + builder.append(" "); + builder.append(":").append(event.getOriginalEvent().getEventName()); + logger.info(builder.toString()); + } + + @EventHandler + public void onBreakBlock(BreakBlockEvent event) { + StringBuilder builder = new StringBuilder(); + builder.append("DIG"); + builder.append(" "); + builder.append("").append(event.getEffectiveMaterial()); + builder.append(" "); + builder.append("[").append(event.getCause()).append("]"); + builder.append(" "); + builder.append("@").append(toBlockString(event.getTarget())); + builder.append(" "); + builder.append(":").append(event.getOriginalEvent().getEventName()); + logger.info(builder.toString()); + } + + @EventHandler + public void onUseBlock(UseBlockEvent event) { + StringBuilder builder = new StringBuilder(); + builder.append("INTERACT"); + builder.append(" "); + builder.append("").append(event.getEffectiveMaterial()); + builder.append(" "); + builder.append("[").append(event.getCause()).append("]"); + builder.append(" "); + builder.append("@").append(toBlockString(event.getTarget())); + builder.append(" "); + builder.append(":").append(event.getOriginalEvent().getEventName()); + logger.info(builder.toString()); + } + + @EventHandler + public void onSpawnEntity(SpawnEntityEvent event) { + StringBuilder builder = new StringBuilder(); + builder.append("SPAWN"); + builder.append(" "); + builder.append("").append(event.getEffectiveType()); + builder.append(" "); + builder.append("[").append(event.getCause()).append("]"); + builder.append(" "); + builder.append("@").append(toBlockString(event.getTarget())); + builder.append(" "); + builder.append(":").append(event.getOriginalEvent().getEventName()); + logger.info(builder.toString()); + } + + @EventHandler + public void onDestroyEntity(DestroyEntityEvent event) { + StringBuilder builder = new StringBuilder(); + builder.append("DESTROY"); + builder.append(" "); + builder.append("").append(event.getEntity().getType()); + builder.append(" "); + builder.append("[").append(event.getCause()).append("]"); + builder.append(" "); + builder.append("@").append(toBlockString(event.getTarget())); + builder.append(" "); + builder.append(":").append(event.getOriginalEvent().getEventName()); + logger.info(builder.toString()); + } + + @EventHandler + public void onUseEntity(UseEntityEvent event) { + StringBuilder builder = new StringBuilder(); + builder.append("INTERACT"); + builder.append(" "); + builder.append("").append(event.getEntity().getType()); + builder.append(" "); + builder.append("[").append(event.getCause()).append("]"); + builder.append(" "); + builder.append("@").append(toBlockString(event.getTarget())); + builder.append(" "); + builder.append(":").append(event.getOriginalEvent().getEventName()); + logger.info(builder.toString()); + } + + @EventHandler + public void onUseItem(UseItemEvent event) { + StringBuilder builder = new StringBuilder(); + builder.append("USE"); + builder.append(" "); + builder.append("").append(event.getItemStack().getType()); + builder.append(" "); + builder.append("[").append(event.getCause()).append("]"); + builder.append(" "); + builder.append("@").append(event.getWorld().getName()); + builder.append(" "); + builder.append(":").append(event.getOriginalEvent().getEventName()); + logger.info(builder.toString()); + } + + private static String toBlockString(Location location) { + return location.getBlockX() + "," + location.getBlockY() + "," + location.getBlockZ(); + } + +} diff --git a/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java b/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java new file mode 100644 index 00000000..c4e83da4 --- /dev/null +++ b/src/main/java/com/sk89q/worldguard/bukkit/listener/EventAbstractionListener.java @@ -0,0 +1,578 @@ +/* + * 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.listener; + +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import com.sk89q.worldguard.bukkit.cause.Cause; +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.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.util.Blocks; +import com.sk89q.worldguard.bukkit.util.Events; +import com.sk89q.worldguard.bukkit.util.Materials; +import com.sk89q.worldguard.bukkit.util.WGMetadata; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.ThrownPotion; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.Event.Result; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockBurnEvent; +import org.bukkit.event.block.BlockDamageEvent; +import org.bukkit.event.block.BlockDispenseEvent; +import org.bukkit.event.block.BlockFromToEvent; +import org.bukkit.event.block.BlockIgniteEvent; +import org.bukkit.event.block.BlockIgniteEvent.IgniteCause; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.SignChangeEvent; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.event.entity.EntityCombustByBlockEvent; +import org.bukkit.event.entity.EntityCombustByEntityEvent; +import org.bukkit.event.entity.EntityCombustEvent; +import org.bukkit.event.entity.EntityDamageByBlockEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityTameEvent; +import org.bukkit.event.entity.EntityUnleashEvent; +import org.bukkit.event.entity.PotionSplashEvent; +import org.bukkit.event.hanging.HangingBreakByEntityEvent; +import org.bukkit.event.hanging.HangingBreakEvent; +import org.bukkit.event.hanging.HangingPlaceEvent; +import org.bukkit.event.player.PlayerBedEnterEvent; +import org.bukkit.event.player.PlayerBucketEmptyEvent; +import org.bukkit.event.player.PlayerBucketFillEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerPickupItemEvent; +import org.bukkit.event.player.PlayerShearEntityEvent; +import org.bukkit.event.player.PlayerUnleashEntityEvent; +import org.bukkit.event.vehicle.VehicleDamageEvent; +import org.bukkit.event.vehicle.VehicleDestroyEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.material.Dispenser; +import org.bukkit.material.MaterialData; + +import javax.annotation.Nullable; + +import static com.sk89q.worldguard.bukkit.cause.Cause.create; +import static com.sk89q.worldguard.bukkit.util.Materials.isBlockModifiedOnClick; +import static com.sk89q.worldguard.bukkit.util.Materials.isItemAppliedToBlock; + +public class EventAbstractionListener implements Listener { + + /** + * Abstract {@link BlockFromToEvent}s into break and place events. + * Currently disabled as it creates a lot of new events. + */ + public static final boolean ABSTRACT_FROM_TO_EVENTS = false; + private static final String FALLING_SOURCE_KEY = "worldguard.fallingSource"; + + private final WorldGuardPlugin plugin; + + public EventAbstractionListener(WorldGuardPlugin plugin) { + this.plugin = plugin; + } + + public void registerEvents() { + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + //------------------------------------------------------------------------- + // Block break / place + //------------------------------------------------------------------------- + + @EventHandler + public void onBlockBreak(BlockBreakEvent event) { + Events.fireToCancel(event, new BreakBlockEvent(event, create(event.getPlayer()), event.getBlock())); + } + + @EventHandler + public void onBlockPlace(BlockPlaceEvent event) { + BlockState previousState = event.getBlockReplacedState(); + + // Some blocks, like tall grass and fire, get replaced + if (previousState.getType() != Material.AIR) { + Events.fireToCancel(event, new BreakBlockEvent(event, create(event.getPlayer()), previousState.getLocation(), previousState.getType())); + } + + Events.fireToCancel(event, new PlaceBlockEvent(event, create(event.getPlayer()), event.getBlock())); + } + + @EventHandler + public void onBlockBurn(BlockBurnEvent event) { + Events.fireToCancel(event, new UseBlockEvent(event, Cause.unknown(), event.getBlock())); + } + + // TODO: Handle EntityCreatePortalEvent? + + @EventHandler + public void onEntityChangeBlock(EntityChangeBlockEvent event) { + Block block = event.getBlock(); + Entity entity = event.getEntity(); + Material to = event.getTo(); + + // Fire two events: one as BREAK and one as PLACE + if (event.getTo() != Material.AIR && event.getBlock().getType() != Material.AIR) { + Events.fireToCancel(event, new BreakBlockEvent(event, create(entity), block)); + Events.fireToCancel(event, new PlaceBlockEvent(event, create(entity), block.getLocation(), to)); + } else { + if (event.getTo() == Material.AIR) { + // Track the source so later we can create a proper chain of causes + if (entity instanceof FallingBlock) { + WGMetadata.put(entity, FALLING_SOURCE_KEY, block); + + // Switch around the event + Events.fireToCancel(event, new SpawnEntityEvent(event, create(block), entity)); + } else { + Events.fireToCancel(event, new BreakBlockEvent(event, create(entity), event.getBlock())); + } + } else { + Cause cause; + + // Return the source for falling blocks + if (entity instanceof FallingBlock) { + Block source = WGMetadata.getIfPresent(entity, FALLING_SOURCE_KEY, Block.class); + cause = create(source, entity); + } else { + cause = create(entity); + } + + Events.fireToCancel(event, new PlaceBlockEvent(event, cause, event.getBlock().getLocation(), to)); + } + } + } + + // TODO: Handle pistons + // TODO: Handle EntityExplodeEvent + + //------------------------------------------------------------------------- + // Block external interaction + //------------------------------------------------------------------------- + + @EventHandler + public void onBlockDamage(BlockDamageEvent event) { + Block target = event.getBlock(); + + // Previously, and perhaps still, the only way to catch cake eating + // events was through here + if (target.getType() == Material.CAKE_BLOCK) { + Events.fireToCancel(event, new UseBlockEvent(event, create(event.getPlayer()), target)); + } + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + Player player = event.getPlayer(); + @Nullable ItemStack item = player.getItemInHand(); + Block clicked = event.getClickedBlock(); + Block placed; + Cause cause = create(player); + + switch (event.getAction()) { + case PHYSICAL: + if (Events.fireAndTestCancel(new UseBlockEvent(event, cause, clicked))) { + event.setUseInteractedBlock(Result.DENY); + event.setCancelled(true); + } + break; + + case RIGHT_CLICK_BLOCK: + placed = clicked.getRelative(event.getBlockFace()); + + // Re-used for dispensers + handleBlockRightClick(event, create(event.getPlayer()), item, clicked, event.getBlockFace(), placed); + + case LEFT_CLICK_BLOCK: + placed = clicked.getRelative(event.getBlockFace()); + + // As of MC ~1.6, sneaking blocks the use of blocks with right click + if (!player.isSneaking() || event.getAction() == Action.LEFT_CLICK_BLOCK) { + // Only fire events for blocks that are modified when right clicked + if (isBlockModifiedOnClick(clicked.getType()) || (item != null && isItemAppliedToBlock(item.getType(), clicked.getType()))) { + if (Events.fireAndTestCancel(new UseBlockEvent(event, cause, clicked))) { + 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))) { + event.setUseInteractedBlock(Result.DENY); + break; + } + } + } + + // Special handling of flint and steel on TNT + if (clicked.getType() == Material.TNT && item != null && item.getType() == Material.FLINT_AND_STEEL) { + if (Events.fireAndTestCancel(new BreakBlockEvent(event, create(event.getPlayer()), clicked))) { + 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; + } + } + + 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); + } + + break; + } + } + + @EventHandler + public void onEntityInteract(org.bukkit.event.entity.EntityInteractEvent event) { + Events.fireToCancel(event, new UseBlockEvent(event, create(event.getEntity()), event.getBlock())); + } + + @EventHandler + public void onBlockIgnite(BlockIgniteEvent event) { + Block block = event.getBlock(); + Cause cause; + + // Find the cause + if (event.getPlayer() != null) { + cause = create(event.getPlayer()); + } else if (event.getIgnitingEntity() != null) { + cause = create(event.getIgnitingEntity()); + } else if (event.getIgnitingBlock() != null) { + cause = create(event.getIgnitingBlock()); + } else { + cause = Cause.unknown(); + } + + if (block.getType() != Material.AIR) { + Events.fireToCancel(event, new BreakBlockEvent(event, cause, event.getBlock())); + } + + // This is also handled in the PlayerInteractEvent listener + if (event.getCause() == IgniteCause.FLINT_AND_STEEL || event.getCause() == IgniteCause.FIREBALL) { + // TODO: Test location of block + Events.fireToCancel(event, new PlaceBlockEvent(event, cause, event.getBlock().getLocation(), Material.FIRE)); + } + } + + @EventHandler + public void onSignChange(SignChangeEvent event) { + Events.fireToCancel(event, new UseBlockEvent(event, create(event.getPlayer()), event.getBlock())); + } + + @EventHandler + public void onBedEnter(PlayerBedEnterEvent event) { + Events.fireToCancel(event, new UseBlockEvent(event, create(event.getPlayer()), event.getBed())); + } + + @EventHandler + public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event) { + Player player = event.getPlayer(); + Block blockAffected = event.getBlockClicked().getRelative(event.getBlockFace()); + + // 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)); + } + } + + @EventHandler + public void onPlayerBucketFill(PlayerBucketFillEvent event) { + Player player = event.getPlayer(); + Block blockAffected = event.getBlockClicked().getRelative(event.getBlockFace()); + + // 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)); + } + } + + // TODO: Handle EntityPortalEnterEvent + + //------------------------------------------------------------------------- + // Block self-interaction + //------------------------------------------------------------------------- + + @EventHandler + public void onBlockFromTo(BlockFromToEvent event) { + if (ABSTRACT_FROM_TO_EVENTS) { + Block from = event.getBlock(); + Block to = event.getToBlock(); + + // Liquids pass this event when flowing to solid blocks + if (to.getType().isSolid() && Materials.isLiquid(from.getType())) { + return; + } + + Cause cause = create(from); + + if (from.getType() != Material.AIR) { + Events.fireToCancel(event, new BreakBlockEvent(event, cause, to)); + } + + Events.fireToCancel(event, new PlaceBlockEvent(event, cause, to.getLocation(), from.getType())); + } + } + + //------------------------------------------------------------------------- + // Entity break / place + //------------------------------------------------------------------------- + + @EventHandler + public void onCreatureSpawn(CreatureSpawnEvent event) { + Events.fireToCancel(event, new SpawnEntityEvent(event, Cause.unknown(), event.getEntity())); + } + + @EventHandler + public void onHangingPlace(HangingPlaceEvent event) { + Events.fireToCancel(event, new SpawnEntityEvent(event, create(event.getPlayer()), event.getEntity())); + } + + @EventHandler + public void onHangingBreak(HangingBreakEvent event) { + if (event instanceof HangingBreakByEntityEvent) { + Events.fireToCancel(event, new DestroyEntityEvent(event, create(((HangingBreakByEntityEvent) event).getRemover()), event.getEntity())); + } else { + Events.fireToCancel(event, new DestroyEntityEvent(event, Cause.unknown(), event.getEntity())); + } + } + + @EventHandler + public void onVehicleDestroy(VehicleDestroyEvent event) { + Events.fireToCancel(event, new DestroyEntityEvent(event, create(event.getAttacker()), event.getVehicle())); + } + + // TODO: XP pickup is an entity destroy event + + //------------------------------------------------------------------------- + // Entity external interaction + //------------------------------------------------------------------------- + + @EventHandler + public void onPlayerInteractEntity(PlayerInteractEntityEvent event) { + Player player = event.getPlayer(); + World world = player.getWorld(); + ItemStack item = player.getItemInHand(); + Entity entity = event.getRightClicked(); + + Events.fireToCancel(event, new UseItemEvent(event, create(player), world, item)); + Events.fireToCancel(event, new UseEntityEvent(event, create(player), entity)); + } + + @EventHandler + public void onEntityDamage(EntityDamageEvent event) { + if (event instanceof EntityDamageByBlockEvent) { + Events.fireToCancel(event, new UseEntityEvent(event, create(((EntityDamageByBlockEvent) event).getDamager()), event.getEntity())); + + } else if (event instanceof EntityDamageByEntityEvent) { + EntityDamageByEntityEvent entityEvent = (EntityDamageByEntityEvent) event; + Entity damager = entityEvent.getDamager(); + Events.fireToCancel(event, new UseEntityEvent(event, create(damager), event.getEntity())); + + // Item use event with the item in hand + // Older blacklist handler code used this, although it suffers from + // race problems + if (damager instanceof Player) { + ItemStack item = ((Player) damager).getItemInHand(); + + if (item != null) { + Events.fireToCancel(event, new UseItemEvent(event, create(damager), event.getEntity().getWorld(), item)); + } + } + + } else { + Events.fireToCancel(event, new UseEntityEvent(event, Cause.unknown(), event.getEntity())); + } + } + + @EventHandler + public void onEntityCombust(EntityCombustEvent event) { + if (event instanceof EntityCombustByBlockEvent) { + Events.fireToCancel(event, new UseEntityEvent(event, create(((EntityCombustByBlockEvent) event).getCombuster()), event.getEntity())); + + } else if (event instanceof EntityCombustByEntityEvent) { + Events.fireToCancel(event, new UseEntityEvent(event, create(((EntityCombustByEntityEvent) event).getCombuster()), event.getEntity())); + + } else { + Events.fireToCancel(event, new UseEntityEvent(event, Cause.unknown(), event.getEntity())); + } + } + + @EventHandler + public void onEntityUnleash(EntityUnleashEvent event) { + if (event instanceof PlayerUnleashEntityEvent) { + PlayerUnleashEntityEvent playerEvent = (PlayerUnleashEntityEvent) event; + Events.fireToCancel(playerEvent, new UseEntityEvent(playerEvent, create(playerEvent.getPlayer()), event.getEntity())); + } else { + // TODO: Raise anyway? + } + } + + @EventHandler + public void onEntityTame(EntityTameEvent event) { + Events.fireToCancel(event, new UseEntityEvent(event, create(event.getOwner()), event.getEntity())); + } + + @EventHandler + public void onPlayerShearEntity(PlayerShearEntityEvent event) { + Events.fireToCancel(event, new UseEntityEvent(event, create(event.getPlayer()), event.getEntity())); + } + + @EventHandler + public void onPlayerPickupItem(PlayerPickupItemEvent event) { + Events.fireToCancel(event, new DestroyEntityEvent(event, create(event.getPlayer()), event.getItem())); + } + + @EventHandler + public void onPlayerDropItem(PlayerDropItemEvent event) { + Events.fireToCancel(event, new SpawnEntityEvent(event, create(event.getPlayer()), event.getItemDrop())); + } + + @EventHandler + public void onVehicleDamage(VehicleDamageEvent event) { + Events.fireToCancel(event, new DestroyEntityEvent(event, create(event.getAttacker()), event.getVehicle())); + } + + @EventHandler + public void onVehicleEnter(VehicleDamageEvent event) { + Events.fireToCancel(event, new UseEntityEvent(event, create(event.getAttacker()), event.getVehicle())); + } + + //------------------------------------------------------------------------- + // Composite events + //------------------------------------------------------------------------- + + @EventHandler + public void onPotionSplash(PotionSplashEvent event) { + Entity entity = event.getEntity(); + ThrownPotion potion = event.getPotion(); + World world = entity.getWorld(); + Cause cause = create(potion.getShooter()); + + // Fire item interaction event + Events.fireToCancel(event, new UseItemEvent(event, cause, world, potion.getItem())); + + // Fire entity interaction event + if (!event.isCancelled()) { + int blocked = 0; + + for (LivingEntity affected : event.getAffectedEntities()) { + if (Events.fireAndTestCancel(new UseEntityEvent(event, cause, affected))) { + event.setIntensity(affected, 0); + blocked++; + } + } + + if (blocked == event.getAffectedEntities().size()) { + event.setCancelled(true); + } + } + } + + @EventHandler + public void onBlockDispense(BlockDispenseEvent event) { + Cause cause = create(event.getBlock()); + Block dispenserBlock = event.getBlock(); + ItemStack item = event.getItem(); + MaterialData materialData = dispenserBlock.getState().getData(); + + Events.fireToCancel(event, new UseItemEvent(event, cause, dispenserBlock.getWorld(), item)); + + // Simulate right click event as players have it + if (materialData instanceof Dispenser) { + Dispenser dispenser = (Dispenser) materialData; + Block placed = dispenserBlock.getRelative(dispenser.getFacing()); + Block clicked = placed.getRelative(dispenser.getFacing()); + handleBlockRightClick(event, cause, item, clicked, dispenser.getFacing().getOppositeFace(), placed); + } + } + + /** + * Handle the right click of a block while an item is held. + * + * @param event the original event + * @param cause the list of cause + * @param item the item + * @param clicked the clicked block + * @param faceClicked the face of the clicked block + * @param placed the placed block + * @param the event type + */ + private static void handleBlockRightClick(T event, Cause cause, @Nullable ItemStack item, Block clicked, BlockFace faceClicked, Block placed) { + if (item != null && item.getType() == Material.TNT) { + // Workaround for a bug that allowed TNT to trigger instantly if placed + // next to redstone, without plugins getting the clicked place event + // (not sure if this actually still happens) + Events.fireToCancel(event, new UseBlockEvent(event, cause, clicked.getLocation(), Material.TNT)); + } + + // Handle created Minecarts + if (item != null && Materials.isMinecart(item.getType())) { + // TODO: Give a more specific Minecart type + Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.MINECART)); + } + + // Handle cocoa beans + if (item != null && item.getType() == Material.INK_SACK && Materials.isDyeColor(item.getData(), DyeColor.BROWN)) { + // CraftBukkit doesn't or didn't throw a clicked place for this + if (!(faceClicked == BlockFace.DOWN || faceClicked == BlockFace.UP)) { + Events.fireToCancel(event, new PlaceBlockEvent(event, cause, placed.getLocation(), Material.COCOA)); + } + } + + // Workaround for http://leaky.bukkit.org/issues/1034 + if (item != null && item.getType() == Material.TNT) { + Events.fireToCancel(event, new PlaceBlockEvent(event, cause, placed.getLocation(), Material.TNT)); + } + } + + // TODO: Inventory events? + +} diff --git a/src/main/java/com/sk89q/worldguard/bukkit/listener/RegionProtectionListener.java b/src/main/java/com/sk89q/worldguard/bukkit/listener/RegionProtectionListener.java new file mode 100644 index 00000000..ee6bc082 --- /dev/null +++ b/src/main/java/com/sk89q/worldguard/bukkit/listener/RegionProtectionListener.java @@ -0,0 +1,202 @@ +/* + * 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.listener; + +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +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.DestroyEntityEvent; +import com.sk89q.worldguard.bukkit.event.entity.SpawnEntityEvent; +import com.sk89q.worldguard.bukkit.event.entity.UseEntityEvent; +import com.sk89q.worldguard.bukkit.util.Entities; +import com.sk89q.worldguard.bukkit.util.Materials; +import com.sk89q.worldguard.bukkit.util.RegionQuery; +import com.sk89q.worldguard.protection.flags.DefaultFlag; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; + +/** + * Handle events that need to be processed by region protection. + */ +public class RegionProtectionListener extends AbstractListener { + + /** + * Construct the listener. + * + * @param plugin an instance of WorldGuardPlugin + */ + public RegionProtectionListener(WorldGuardPlugin plugin) { + super(plugin); + } + + private void tellErrorMessage(CommandSender sender, Object subject) { + sender.sendMessage(ChatColor.DARK_RED + "You don't have permission for this area."); + } + + @EventHandler(ignoreCancelled = true) + public void onPlaceBlock(PlaceBlockEvent event) { + Player player = event.getCause().getPlayerRootCause(); + Location target = event.getTarget(); + Material type = event.getEffectiveMaterial(); + + if (player != null) { + RegionQuery query = new RegionQuery(getPlugin(), player); + boolean canPlace; + + // Flint and steel, fire charge + if (type == Material.FIRE) { + canPlace = query.allows(DefaultFlag.LIGHTER, target) || (query.canBuild(target) && query.canConstruct(target)); + + } else { + canPlace = query.canBuild(target) && query.canConstruct(target); + } + + if (!canPlace) { + tellErrorMessage(player, target); + event.setCancelled(true); + } + } + } + + @EventHandler(ignoreCancelled = true) + public void onBreakBlock(BreakBlockEvent event) { + Player player = event.getCause().getPlayerRootCause(); + Location target = event.getTarget(); + + if (player != null) { + if (!getPlugin().getGlobalRegionManager().canBuild(player, target)) { + tellErrorMessage(player, target); + event.setCancelled(true); + } else if (!getPlugin().getGlobalRegionManager().canConstruct(player, target)) { + tellErrorMessage(player, target); + event.setCancelled(true); + } + } + } + + @EventHandler(ignoreCancelled = true) + public void onUseBlock(UseBlockEvent event) { + Player player = event.getCause().getPlayerRootCause(); + Location target = event.getTarget(); + Material type = event.getEffectiveMaterial(); + + if (player != null) { + RegionQuery query = new RegionQuery(getPlugin(), player); + boolean canUse; + + // Inventory blocks (CHEST_ACCESS) + if (Materials.isInventoryBlock(type)) { + canUse = query.canBuild( target) + || query.allows(DefaultFlag.CHEST_ACCESS, target) + || query.allows(DefaultFlag.USE, target); + + // Beds (SLEEP) + } else if (type == Material.BED) { + canUse = query.canBuild(target) + || query.allows(DefaultFlag.SLEEP, target) + || query.allows(DefaultFlag.USE, target); + + // TNT (TNT) + } else if (type == Material.TNT) { + canUse = query.canBuild(target) + || query.allows(DefaultFlag.TNT, target); + + // Everything else + } else { + canUse = query.canBuild(target) + || query.allows(DefaultFlag.USE, target); + } + + if (!canUse) { + tellErrorMessage(player, target); + event.setCancelled(true); + } + } + } + + @EventHandler(ignoreCancelled = true) + public void onSpawnEntity(SpawnEntityEvent event) { + Player player = event.getCause().getPlayerRootCause(); + Location target = event.getTarget(); + EntityType type = event.getEffectiveType(); + + if (player != null) { + RegionQuery query = new RegionQuery(getPlugin(), player); + boolean canSpawn; + + if (Entities.isVehicle(type)) { + canSpawn = query.canBuild(target) || query.allows(DefaultFlag.PLACE_VEHICLE, target); + } else { + canSpawn = query.canBuild(target); + } + + if (!canSpawn) { + tellErrorMessage(player, target); + event.setCancelled(true); + } + } + } + + @EventHandler(ignoreCancelled = true) + public void onDestroyEntity(DestroyEntityEvent event) { + Player player = event.getCause().getPlayerRootCause(); + Location target = event.getTarget(); + EntityType type = event.getEntity().getType(); + + if (player != null) { + RegionQuery query = new RegionQuery(getPlugin(), player); + boolean canDestroy; + + if (Entities.isVehicle(type)) { + canDestroy = query.canBuild(target) || query.allows(DefaultFlag.DESTROY_VEHICLE, target); + } else { + canDestroy = query.canBuild(target); + } + + if (!canDestroy) { + tellErrorMessage(player, target); + event.setCancelled(true); + } + } + } + + @EventHandler(ignoreCancelled = true) + public void onUseEntity(UseEntityEvent event) { + Player player = event.getCause().getPlayerRootCause(); + Location target = event.getTarget(); + + if (player != null) { + RegionQuery query = new RegionQuery(getPlugin(), player); + boolean canUse = query.canBuild(target) || query.allows(DefaultFlag.USE, target); + + if (!canUse) { + tellErrorMessage(player, target); + event.setCancelled(true); + } + } + } + +} diff --git a/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardBlockListener.java b/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardBlockListener.java similarity index 79% rename from src/main/java/com/sk89q/worldguard/bukkit/WorldGuardBlockListener.java rename to src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardBlockListener.java index f8dc373a..ef0c69cf 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardBlockListener.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardBlockListener.java @@ -1,858 +1,732 @@ -/* - * 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; - -import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.blocks.BlockID; -import com.sk89q.worldedit.blocks.BlockType; -import com.sk89q.worldedit.blocks.ItemType; -import com.sk89q.worldguard.LocalPlayer; -import com.sk89q.worldguard.blacklist.event.BlockDispenseBlacklistEvent; -import com.sk89q.worldguard.internal.Events; -import com.sk89q.worldguard.internal.cause.Causes; -import com.sk89q.worldguard.internal.event.BlockInteractEvent; -import com.sk89q.worldguard.internal.event.Interaction; -import com.sk89q.worldguard.internal.event.ItemInteractEvent; -import com.sk89q.worldguard.protection.ApplicableRegionSet; -import com.sk89q.worldguard.protection.flags.DefaultFlag; -import com.sk89q.worldguard.protection.managers.RegionManager; -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.entity.Player; -import org.bukkit.entity.Snowman; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.block.BlockBurnEvent; -import org.bukkit.event.block.BlockDamageEvent; -import org.bukkit.event.block.BlockDispenseEvent; -import org.bukkit.event.block.BlockExpEvent; -import org.bukkit.event.block.BlockFadeEvent; -import org.bukkit.event.block.BlockFormEvent; -import org.bukkit.event.block.BlockFromToEvent; -import org.bukkit.event.block.BlockIgniteEvent; -import org.bukkit.event.block.BlockIgniteEvent.IgniteCause; -import org.bukkit.event.block.BlockPhysicsEvent; -import org.bukkit.event.block.BlockPistonExtendEvent; -import org.bukkit.event.block.BlockPistonRetractEvent; -import org.bukkit.event.block.BlockPlaceEvent; -import org.bukkit.event.block.BlockRedstoneEvent; -import org.bukkit.event.block.BlockSpreadEvent; -import org.bukkit.event.block.EntityBlockFormEvent; -import org.bukkit.event.block.LeavesDecayEvent; -import org.bukkit.event.block.SignChangeEvent; -import org.bukkit.inventory.ItemStack; - -import static com.sk89q.worldguard.bukkit.BukkitUtil.createTarget; -import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector; - -/** - * The listener for block events. - * - * @author sk89q - */ -public class WorldGuardBlockListener implements Listener { - - private WorldGuardPlugin plugin; - - /** - * Construct the object. - * - * @param plugin The plugin instance - */ - public WorldGuardBlockListener(WorldGuardPlugin plugin) { - this.plugin = plugin; - } - - /** - * Register events. - */ - public void registerEvents() { - plugin.getServer().getPluginManager().registerEvents(this, plugin); - } - - /** - * Get the world configuration given a world. - * - * @param world The world to get the configuration for. - * @return The configuration for {@code world} - */ - protected WorldConfiguration getWorldConfig(World world) { - return plugin.getGlobalStateManager().get(world); - } - - /** - * Get the world configuration given a player. - * - * @param player The player to get the wold from - * @return The {@link WorldConfiguration} for the player's world - */ - protected WorldConfiguration getWorldConfig(Player player) { - return getWorldConfig(player.getWorld()); - } - - /* - * Called when a block is damaged. - */ - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onBlockDamage(BlockDamageEvent event) { - Block target = event.getBlock(); - - // Cake are damaged and not broken when they are eaten, so we must - // handle them a bit separately - if (target.getType() == Material.CAKE_BLOCK) { - Events.fireToCancel(event, new BlockInteractEvent(event, Causes.create(event.getPlayer()), Interaction.INTERACT, target)); - } - } - - /* - * Called when a block is broken. - */ - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onBlockBreak(BlockBreakEvent event) { - Player player = event.getPlayer(); - Block target = event.getBlock(); - WorldConfiguration wcfg = getWorldConfig(player); - - if (!wcfg.itemDurability) { - ItemStack held = player.getItemInHand(); - if (held.getType() != Material.AIR && !(ItemType.usesDamageValue(held.getTypeId())|| BlockType.usesData(held.getTypeId()))) { - held.setDurability((short) 0); - player.setItemInHand(held); - } - } - - Events.fireToCancel(event, new BlockInteractEvent(event, Causes.create(event.getPlayer()), Interaction.BREAK, target)); - } - - /* - * Called when fluids flow. - */ - @EventHandler(ignoreCancelled = true) - public void onBlockFromTo(BlockFromToEvent event) { - World world = event.getBlock().getWorld(); - Block blockFrom = event.getBlock(); - Block blockTo = event.getToBlock(); - - boolean isWater = blockFrom.getTypeId() == 8 || blockFrom.getTypeId() == 9; - boolean isLava = blockFrom.getTypeId() == 10 || blockFrom.getTypeId() == 11; - boolean isAir = blockFrom.getTypeId() == 0; - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld()); - - if (cfg.activityHaltToggle) { - event.setCancelled(true); - return; - } - - if (wcfg.simulateSponge && isWater) { - int ox = blockTo.getX(); - int oy = blockTo.getY(); - int oz = blockTo.getZ(); - - for (int cx = -wcfg.spongeRadius; cx <= wcfg.spongeRadius; cx++) { - for (int cy = -wcfg.spongeRadius; cy <= wcfg.spongeRadius; cy++) { - for (int cz = -wcfg.spongeRadius; cz <= wcfg.spongeRadius; cz++) { - Block sponge = world.getBlockAt(ox + cx, oy + cy, oz + cz); - if (sponge.getTypeId() == 19 - && (!wcfg.redstoneSponges || !sponge.isBlockIndirectlyPowered())) { - event.setCancelled(true); - return; - } - } - } - } - } - - /*if (plugin.classicWater && isWater) { - int blockBelow = blockFrom.getRelative(0, -1, 0).getTypeId(); - if (blockBelow != 0 && blockBelow != 8 && blockBelow != 9) { - blockFrom.setTypeId(9); - if (blockTo.getTypeId() == 0) { - blockTo.setTypeId(9); - } - return; - } - }*/ - - // Check the fluid block (from) whether it is air. - // If so and the target block is protected, cancel the event - if (wcfg.preventWaterDamage.size() > 0) { - int targetId = blockTo.getTypeId(); - - if ((isAir || isWater) && - wcfg.preventWaterDamage.contains(targetId)) { - event.setCancelled(true); - return; - } - } - - if (wcfg.allowedLavaSpreadOver.size() > 0 && isLava) { - int targetId = blockTo.getRelative(0, -1, 0).getTypeId(); - - if (!wcfg.allowedLavaSpreadOver.contains(targetId)) { - event.setCancelled(true); - return; - } - } - - if (wcfg.highFreqFlags && isWater - && !plugin.getGlobalRegionManager().allows(DefaultFlag.WATER_FLOW, - blockFrom.getLocation())) { - event.setCancelled(true); - return; - } - - if (wcfg.highFreqFlags && isLava - && !plugin.getGlobalRegionManager().allows(DefaultFlag.LAVA_FLOW, - blockFrom.getLocation())) { - event.setCancelled(true); - return; - } - - if (wcfg.disableObsidianGenerators && (isAir || isLava) - && (blockTo.getTypeId() == BlockID.REDSTONE_WIRE - || blockTo.getTypeId() == BlockID.TRIPWIRE)) { - blockTo.setTypeId(BlockID.AIR); - return; - } - } - - /* - * Called when a block gets ignited. - */ - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onBlockIgnite(BlockIgniteEvent event) { - IgniteCause cause = event.getCause(); - Block block = event.getBlock(); - World world = block.getWorld(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - - if (cfg.activityHaltToggle) { - event.setCancelled(true); - return; - } - boolean isFireSpread = cause == IgniteCause.SPREAD; - - if (wcfg.preventLightningFire && cause == IgniteCause.LIGHTNING) { - event.setCancelled(true); - return; - } - - if (wcfg.preventLavaFire && cause == IgniteCause.LAVA) { - event.setCancelled(true); - return; - } - - if (wcfg.disableFireSpread && isFireSpread) { - event.setCancelled(true); - return; - } - - if (wcfg.blockLighter && (cause == IgniteCause.FLINT_AND_STEEL || cause == IgniteCause.FIREBALL) - && event.getPlayer() != null - && !plugin.hasPermission(event.getPlayer(), "worldguard.override.lighter")) { - event.setCancelled(true); - return; - } - - if (wcfg.fireSpreadDisableToggle && isFireSpread) { - event.setCancelled(true); - return; - } - - if (wcfg.disableFireSpreadBlocks.size() > 0 && isFireSpread) { - int x = block.getX(); - int y = block.getY(); - int z = block.getZ(); - - if (wcfg.disableFireSpreadBlocks.contains(world.getBlockTypeIdAt(x, y - 1, z)) - || wcfg.disableFireSpreadBlocks.contains(world.getBlockTypeIdAt(x + 1, y, z)) - || wcfg.disableFireSpreadBlocks.contains(world.getBlockTypeIdAt(x - 1, y, z)) - || wcfg.disableFireSpreadBlocks.contains(world.getBlockTypeIdAt(x, y, z - 1)) - || wcfg.disableFireSpreadBlocks.contains(world.getBlockTypeIdAt(x, y, z + 1))) { - event.setCancelled(true); - return; - } - } - - if (wcfg.useRegions) { - Vector pt = toVector(block); - Player player = event.getPlayer(); - RegionManager mgr = plugin.getGlobalRegionManager().get(world); - ApplicableRegionSet set = mgr.getApplicableRegions(pt); - - if (player != null && !plugin.getGlobalRegionManager().hasBypass(player, world)) { - LocalPlayer localPlayer = plugin.wrapPlayer(player); - - // this is preliminarily handled in the player listener under handleBlockRightClick - // why it's handled here too, no one knows - if (cause == IgniteCause.FLINT_AND_STEEL || cause == IgniteCause.FIREBALL) { - if (!set.allows(DefaultFlag.LIGHTER) - && !set.canBuild(localPlayer) - && !plugin.hasPermission(player, "worldguard.override.lighter")) { - event.setCancelled(true); - return; - } - } - } - - if (wcfg.highFreqFlags && isFireSpread - && !set.allows(DefaultFlag.FIRE_SPREAD)) { - event.setCancelled(true); - return; - } - - if (wcfg.highFreqFlags && cause == IgniteCause.LAVA - && !set.allows(DefaultFlag.LAVA_FIRE)) { - event.setCancelled(true); - return; - } - - if (cause == IgniteCause.FIREBALL && event.getPlayer() == null) { - // wtf bukkit, FIREBALL is supposed to be reserved to players - if (!set.allows(DefaultFlag.GHAST_FIREBALL)) { - event.setCancelled(true); - return; - } - } - - if (cause == IgniteCause.LIGHTNING && !set.allows(DefaultFlag.LIGHTNING)) { - event.setCancelled(true); - return; - } - } - } - - /* - * Called when a block is destroyed from burning. - */ - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onBlockBurn(BlockBurnEvent event) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld()); - - if (cfg.activityHaltToggle) { - event.setCancelled(true); - return; - } - - if (wcfg.disableFireSpread) { - event.setCancelled(true); - return; - } - - if (wcfg.fireSpreadDisableToggle) { - Block block = event.getBlock(); - event.setCancelled(true); - checkAndDestroyAround(block.getWorld(), block.getX(), block.getY(), block.getZ(), BlockID.FIRE); - return; - } - - if (wcfg.disableFireSpreadBlocks.size() > 0) { - Block block = event.getBlock(); - - if (wcfg.disableFireSpreadBlocks.contains(block.getTypeId())) { - event.setCancelled(true); - checkAndDestroyAround(block.getWorld(), block.getX(), block.getY(), block.getZ(), BlockID.FIRE); - return; - } - } - - if (wcfg.isChestProtected(event.getBlock())) { - event.setCancelled(true); - return; - } - - if (wcfg.useRegions) { - Block block = event.getBlock(); - int x = block.getX(); - int y = block.getY(); - int z = block.getZ(); - Vector pt = toVector(block); - RegionManager mgr = plugin.getGlobalRegionManager().get(block.getWorld()); - ApplicableRegionSet set = mgr.getApplicableRegions(pt); - - if (!set.allows(DefaultFlag.FIRE_SPREAD)) { - checkAndDestroyAround(block.getWorld(), x, y, z, BlockID.FIRE); - event.setCancelled(true); - return; - } - - } - } - - private void checkAndDestroyAround(World world, int x, int y, int z, int required) { - checkAndDestroy(world, x, y, z + 1, required); - checkAndDestroy(world, x, y, z - 1, required); - checkAndDestroy(world, x, y + 1, z, required); - checkAndDestroy(world, x, y - 1, z, required); - checkAndDestroy(world, x + 1, y, z, required); - checkAndDestroy(world, x - 1, y, z, required); - } - - private void checkAndDestroy(World world, int x, int y, int z, int required) { - if (world.getBlockTypeIdAt(x, y, z) == required) { - world.getBlockAt(x, y, z).setTypeId(BlockID.AIR); - } - } - - /* - * Called when block physics occurs. - */ - @EventHandler(ignoreCancelled = true) - public void onBlockPhysics(BlockPhysicsEvent event) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld()); - - if (cfg.activityHaltToggle) { - event.setCancelled(true); - return; - } - - int id = event.getChangedTypeId(); - - if (id == 13 && wcfg.noPhysicsGravel) { - event.setCancelled(true); - return; - } - - if (id == 12 && wcfg.noPhysicsSand) { - event.setCancelled(true); - return; - } - - if (id == 90 && wcfg.allowPortalAnywhere) { - event.setCancelled(true); - return; - } - - if (wcfg.ropeLadders && event.getBlock().getType() == Material.LADDER) { - if (event.getBlock().getRelative(0, 1, 0).getType() == Material.LADDER) { - event.setCancelled(true); - return; - } - } - } - - /* - * Called when a player places a block. - */ - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onBlockPlace(BlockPlaceEvent event) { - Block target = event.getBlock(); - World world = target.getWorld(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - - Events.fireToCancel(event, new BlockInteractEvent(event, Causes.create(event.getPlayer()), Interaction.PLACE, target)); - - if (wcfg.simulateSponge && target.getType() == Material.SPONGE) { - if (wcfg.redstoneSponges && target.isBlockIndirectlyPowered()) { - return; - } - - int ox = target.getX(); - int oy = target.getY(); - int oz = target.getZ(); - - SpongeUtil.clearSpongeWater(plugin, world, ox, oy, oz); - } - } - - /* - * Called when redstone changes. - */ - @EventHandler(priority = EventPriority.HIGH) - public void onBlockRedstoneChange(BlockRedstoneEvent event) { - Block blockTo = event.getBlock(); - World world = blockTo.getWorld(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - - if (wcfg.simulateSponge && wcfg.redstoneSponges) { - int ox = blockTo.getX(); - int oy = blockTo.getY(); - int oz = blockTo.getZ(); - - for (int cx = -1; cx <= 1; cx++) { - for (int cy = -1; cy <= 1; cy++) { - for (int cz = -1; cz <= 1; cz++) { - Block sponge = world.getBlockAt(ox + cx, oy + cy, oz + cz); - if (sponge.getTypeId() == 19 - && sponge.isBlockIndirectlyPowered()) { - SpongeUtil.clearSpongeWater(plugin, world, ox + cx, oy + cy, oz + cz); - } else if (sponge.getTypeId() == 19 - && !sponge.isBlockIndirectlyPowered()) { - SpongeUtil.addSpongeWater(plugin, world, ox + cx, oy + cy, oz + cz); - } - } - } - } - - return; - } - } - - /* - * Called when a sign is changed. - */ - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onSignChange(SignChangeEvent event) { - Player player = event.getPlayer(); - WorldConfiguration wcfg = getWorldConfig(player); - - if (wcfg.signChestProtection) { - if (event.getLine(0).equalsIgnoreCase("[Lock]")) { - if (wcfg.isChestProtectedPlacement(event.getBlock(), player)) { - player.sendMessage(ChatColor.DARK_RED + "You do not own the adjacent chest."); - event.getBlock().breakNaturally(); - event.setCancelled(true); - return; - } - - if (event.getBlock().getTypeId() != BlockID.SIGN_POST) { - player.sendMessage(ChatColor.RED - + "The [Lock] sign must be a sign post, not a wall sign."); - - event.getBlock().breakNaturally(); - event.setCancelled(true); - return; - } - - if (!event.getLine(1).equalsIgnoreCase(player.getName())) { - player.sendMessage(ChatColor.RED - + "The first owner line must be your name."); - - event.getBlock().breakNaturally(); - event.setCancelled(true); - return; - } - - int below = event.getBlock().getRelative(0, -1, 0).getTypeId(); - - if (below == BlockID.TNT || below == BlockID.SAND - || below == BlockID.GRAVEL || below == BlockID.SIGN_POST) { - player.sendMessage(ChatColor.RED - + "That is not a safe block that you're putting this sign on."); - - event.getBlock().breakNaturally(); - event.setCancelled(true); - return; - } - - event.setLine(0, "[Lock]"); - player.sendMessage(ChatColor.YELLOW - + "A chest or double chest above is now protected."); - } - } else if (!wcfg.disableSignChestProtectionCheck) { - if (event.getLine(0).equalsIgnoreCase("[Lock]")) { - player.sendMessage(ChatColor.RED - + "WorldGuard's sign chest protection is disabled."); - - event.getBlock().breakNaturally(); - event.setCancelled(true); - return; - } - } - - if (!plugin.getGlobalRegionManager().canBuild(player, event.getBlock())) { - player.sendMessage(ChatColor.DARK_RED + "You don't have permission for this area."); - event.setCancelled(true); - return; - } - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onLeavesDecay(LeavesDecayEvent event) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld()); - - if (cfg.activityHaltToggle) { - event.setCancelled(true); - return; - } - - if (wcfg.disableLeafDecay) { - event.setCancelled(true); - return; - } - - if (wcfg.useRegions) { - if (!plugin.getGlobalRegionManager().allows(DefaultFlag.LEAF_DECAY, - event.getBlock().getLocation())) { - event.setCancelled(true); - } - } - } - - /* - * Called when a block is formed based on world conditions. - */ - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onBlockForm(BlockFormEvent event) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld()); - - if (cfg.activityHaltToggle) { - event.setCancelled(true); - return; - } - - int type = event.getNewState().getTypeId(); - - if (event instanceof EntityBlockFormEvent) { - if (((EntityBlockFormEvent) event).getEntity() instanceof Snowman) { - if (wcfg.disableSnowmanTrails) { - event.setCancelled(true); - return; - } - } - return; - } - - if (type == BlockID.ICE) { - if (wcfg.disableIceFormation) { - event.setCancelled(true); - return; - } - if (wcfg.useRegions && !plugin.getGlobalRegionManager().allows( - DefaultFlag.ICE_FORM, event.getBlock().getLocation())) { - event.setCancelled(true); - return; - } - } - - if (type == BlockID.SNOW) { - if (wcfg.disableSnowFormation) { - event.setCancelled(true); - return; - } - if (wcfg.allowedSnowFallOver.size() > 0) { - int targetId = event.getBlock().getRelative(0, -1, 0).getTypeId(); - - if (!wcfg.allowedSnowFallOver.contains(targetId)) { - event.setCancelled(true); - return; - } - } - if (wcfg.useRegions && !plugin.getGlobalRegionManager().allows( - DefaultFlag.SNOW_FALL, event.getBlock().getLocation())) { - event.setCancelled(true); - return; - } - } - } - - /* - * Called when a block spreads based on world conditions. - */ - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onBlockSpread(BlockSpreadEvent event) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld()); - - if (cfg.activityHaltToggle) { - event.setCancelled(true); - return; - } - - int fromType = event.getSource().getTypeId(); - - if (fromType == BlockID.RED_MUSHROOM || fromType == BlockID.BROWN_MUSHROOM) { - if (wcfg.disableMushroomSpread) { - event.setCancelled(true); - return; - } - if (wcfg.useRegions && !plugin.getGlobalRegionManager().allows( - DefaultFlag.MUSHROOMS, event.getBlock().getLocation())) { - event.setCancelled(true); - return; - } - } - - if (fromType == BlockID.GRASS) { - if (wcfg.disableGrassGrowth) { - event.setCancelled(true); - return; - } - if (wcfg.useRegions && !plugin.getGlobalRegionManager().allows( - DefaultFlag.GRASS_SPREAD, event.getBlock().getLocation())) { - event.setCancelled(true); - return; - } - } - - if (fromType == BlockID.MYCELIUM) { - if (wcfg.disableMyceliumSpread) { - event.setCancelled(true); - return; - } - - if (wcfg.useRegions - && !plugin.getGlobalRegionManager().allows( - DefaultFlag.MYCELIUM_SPREAD, event.getBlock().getLocation())) { - event.setCancelled(true); - return; - } - } - - if (fromType == BlockID.VINE) { - if (wcfg.disableVineGrowth) { - event.setCancelled(true); - return; - } - - if (wcfg.useRegions - && !plugin.getGlobalRegionManager().allows( - DefaultFlag.VINE_GROWTH, event.getBlock().getLocation())) { - event.setCancelled(true); - return; - } - } - } - - /* - * Called when a block fades. - */ - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onBlockFade(BlockFadeEvent event) { - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld()); - - switch (event.getBlock().getTypeId()) { - case BlockID.ICE: - if (wcfg.disableIceMelting) { - event.setCancelled(true); - return; - } - - if (wcfg.useRegions && !plugin.getGlobalRegionManager().allows( - DefaultFlag.ICE_MELT, event.getBlock().getLocation())) { - event.setCancelled(true); - return; - } - break; - - case BlockID.SNOW: - if (wcfg.disableSnowMelting) { - event.setCancelled(true); - return; - } - - if (wcfg.useRegions && !plugin.getGlobalRegionManager().allows( - DefaultFlag.SNOW_MELT, event.getBlock().getLocation())) { - event.setCancelled(true); - return; - } - break; - - case BlockID.SOIL: - if (wcfg.disableSoilDehydration) { - event.setCancelled(true); - return; - } - if (wcfg.useRegions && !plugin.getGlobalRegionManager().allows( - DefaultFlag.SOIL_DRY, event.getBlock().getLocation())) { - event.setCancelled(true); - return; - } - break; - } - - } - - /* - * Called when a piston extends - */ - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onBlockPistonExtend(BlockPistonExtendEvent event) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld()); - - if (wcfg.useRegions) { - if (!plugin.getGlobalRegionManager().allows(DefaultFlag.PISTONS, event.getBlock().getLocation())) { - event.setCancelled(true); - return; - } - for (Block block : event.getBlocks()) { - if (!plugin.getGlobalRegionManager().allows(DefaultFlag.PISTONS, block.getLocation())) { - event.setCancelled(true); - return; - } - } - } - } - - /* - * Called when a piston retracts - */ - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onBlockPistonRetract(BlockPistonRetractEvent event) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld()); - - if (wcfg.useRegions && event.isSticky()) { - if (!(plugin.getGlobalRegionManager().allows(DefaultFlag.PISTONS, event.getRetractLocation())) - || !(plugin.getGlobalRegionManager().allows(DefaultFlag.PISTONS, event.getBlock().getLocation()))) { - event.setCancelled(true); - return; - } - } - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onBlockDispense(BlockDispenseEvent event) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld()); - - if (wcfg.getBlacklist() != null) { - if (!wcfg.getBlacklist().check(new BlockDispenseBlacklistEvent(null, toVector(event.getBlock()), createTarget(event.getItem())), false, false)) { - event.setCancelled(true); - return; - } - } - - Events.fireToCancel(event, new ItemInteractEvent(event, Causes.create(event.getBlock()), Interaction.INTERACT, event.getBlock().getWorld(), event.getItem())); - } - - /* - * Called when a block yields exp - */ - @EventHandler(priority = EventPriority.HIGH) - public void onBlockExp(BlockExpEvent event) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld()); - if (wcfg.disableExpDrops || !plugin.getGlobalRegionManager().allows(DefaultFlag.EXP_DROPS, - event.getBlock().getLocation())) { - event.setExpToDrop(0); - } - } - -} +/* + * 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.listener; + +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.blocks.BlockID; +import com.sk89q.worldedit.blocks.BlockType; +import com.sk89q.worldedit.blocks.ItemType; +import com.sk89q.worldguard.bukkit.ConfigurationManager; +import com.sk89q.worldguard.bukkit.SpongeUtil; +import com.sk89q.worldguard.bukkit.WorldConfiguration; +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import com.sk89q.worldguard.protection.ApplicableRegionSet; +import com.sk89q.worldguard.protection.flags.DefaultFlag; +import com.sk89q.worldguard.protection.managers.RegionManager; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.entity.Snowman; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockBurnEvent; +import org.bukkit.event.block.BlockExpEvent; +import org.bukkit.event.block.BlockFadeEvent; +import org.bukkit.event.block.BlockFormEvent; +import org.bukkit.event.block.BlockFromToEvent; +import org.bukkit.event.block.BlockIgniteEvent; +import org.bukkit.event.block.BlockIgniteEvent.IgniteCause; +import org.bukkit.event.block.BlockPhysicsEvent; +import org.bukkit.event.block.BlockPistonExtendEvent; +import org.bukkit.event.block.BlockPistonRetractEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.BlockRedstoneEvent; +import org.bukkit.event.block.BlockSpreadEvent; +import org.bukkit.event.block.EntityBlockFormEvent; +import org.bukkit.event.block.LeavesDecayEvent; +import org.bukkit.inventory.ItemStack; + +import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector; + +/** + * The listener for block events. + * + * @author sk89q + */ +public class WorldGuardBlockListener implements Listener { + + private WorldGuardPlugin plugin; + + /** + * Construct the object. + * + * @param plugin The plugin instance + */ + public WorldGuardBlockListener(WorldGuardPlugin plugin) { + this.plugin = plugin; + } + + /** + * Register events. + */ + public void registerEvents() { + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + /** + * Get the world configuration given a world. + * + * @param world The world to get the configuration for. + * @return The configuration for {@code world} + */ + protected WorldConfiguration getWorldConfig(World world) { + return plugin.getGlobalStateManager().get(world); + } + + /** + * Get the world configuration given a player. + * + * @param player The player to get the wold from + * @return The {@link WorldConfiguration} for the player's world + */ + protected WorldConfiguration getWorldConfig(Player player) { + return getWorldConfig(player.getWorld()); + } + + /* + * Called when a block is broken. + */ + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onBlockBreak(BlockBreakEvent event) { + Player player = event.getPlayer(); + Block target = event.getBlock(); + WorldConfiguration wcfg = getWorldConfig(player); + + if (!wcfg.itemDurability) { + ItemStack held = player.getItemInHand(); + if (held.getType() != Material.AIR && !(ItemType.usesDamageValue(held.getTypeId())|| BlockType.usesData(held.getTypeId()))) { + held.setDurability((short) 0); + player.setItemInHand(held); + } + } + } + + /* + * Called when fluids flow. + */ + @EventHandler(ignoreCancelled = true) + public void onBlockFromTo(BlockFromToEvent event) { + World world = event.getBlock().getWorld(); + Block blockFrom = event.getBlock(); + Block blockTo = event.getToBlock(); + + boolean isWater = blockFrom.getTypeId() == 8 || blockFrom.getTypeId() == 9; + boolean isLava = blockFrom.getTypeId() == 10 || blockFrom.getTypeId() == 11; + boolean isAir = blockFrom.getTypeId() == 0; + + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld()); + + if (cfg.activityHaltToggle) { + event.setCancelled(true); + return; + } + + if (wcfg.simulateSponge && isWater) { + int ox = blockTo.getX(); + int oy = blockTo.getY(); + int oz = blockTo.getZ(); + + for (int cx = -wcfg.spongeRadius; cx <= wcfg.spongeRadius; cx++) { + for (int cy = -wcfg.spongeRadius; cy <= wcfg.spongeRadius; cy++) { + for (int cz = -wcfg.spongeRadius; cz <= wcfg.spongeRadius; cz++) { + Block sponge = world.getBlockAt(ox + cx, oy + cy, oz + cz); + if (sponge.getTypeId() == 19 + && (!wcfg.redstoneSponges || !sponge.isBlockIndirectlyPowered())) { + event.setCancelled(true); + return; + } + } + } + } + } + + /*if (plugin.classicWater && isWater) { + int blockBelow = blockFrom.getRelative(0, -1, 0).getTypeId(); + if (blockBelow != 0 && blockBelow != 8 && blockBelow != 9) { + blockFrom.setTypeId(9); + if (blockTo.getTypeId() == 0) { + blockTo.setTypeId(9); + } + return; + } + }*/ + + // Check the fluid block (from) whether it is air. + // If so and the target block is protected, cancel the event + if (wcfg.preventWaterDamage.size() > 0) { + int targetId = blockTo.getTypeId(); + + if ((isAir || isWater) && + wcfg.preventWaterDamage.contains(targetId)) { + event.setCancelled(true); + return; + } + } + + if (wcfg.allowedLavaSpreadOver.size() > 0 && isLava) { + int targetId = blockTo.getRelative(0, -1, 0).getTypeId(); + + if (!wcfg.allowedLavaSpreadOver.contains(targetId)) { + event.setCancelled(true); + return; + } + } + + if (wcfg.highFreqFlags && isWater + && !plugin.getGlobalRegionManager().allows(DefaultFlag.WATER_FLOW, + blockFrom.getLocation())) { + event.setCancelled(true); + return; + } + + if (wcfg.highFreqFlags && isLava + && !plugin.getGlobalRegionManager().allows(DefaultFlag.LAVA_FLOW, + blockFrom.getLocation())) { + event.setCancelled(true); + return; + } + + if (wcfg.disableObsidianGenerators && (isAir || isLava) + && (blockTo.getTypeId() == BlockID.REDSTONE_WIRE + || blockTo.getTypeId() == BlockID.TRIPWIRE)) { + blockTo.setTypeId(BlockID.AIR); + return; + } + } + + /* + * Called when a block gets ignited. + */ + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onBlockIgnite(BlockIgniteEvent event) { + IgniteCause cause = event.getCause(); + Block block = event.getBlock(); + World world = block.getWorld(); + + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(world); + + if (cfg.activityHaltToggle) { + event.setCancelled(true); + return; + } + boolean isFireSpread = cause == IgniteCause.SPREAD; + + if (wcfg.preventLightningFire && cause == IgniteCause.LIGHTNING) { + event.setCancelled(true); + return; + } + + if (wcfg.preventLavaFire && cause == IgniteCause.LAVA) { + event.setCancelled(true); + return; + } + + if (wcfg.disableFireSpread && isFireSpread) { + event.setCancelled(true); + return; + } + + if (wcfg.blockLighter && (cause == IgniteCause.FLINT_AND_STEEL || cause == IgniteCause.FIREBALL) + && event.getPlayer() != null + && !plugin.hasPermission(event.getPlayer(), "worldguard.override.lighter")) { + event.setCancelled(true); + return; + } + + if (wcfg.fireSpreadDisableToggle && isFireSpread) { + event.setCancelled(true); + return; + } + + if (wcfg.disableFireSpreadBlocks.size() > 0 && isFireSpread) { + int x = block.getX(); + int y = block.getY(); + int z = block.getZ(); + + if (wcfg.disableFireSpreadBlocks.contains(world.getBlockTypeIdAt(x, y - 1, z)) + || wcfg.disableFireSpreadBlocks.contains(world.getBlockTypeIdAt(x + 1, y, z)) + || wcfg.disableFireSpreadBlocks.contains(world.getBlockTypeIdAt(x - 1, y, z)) + || wcfg.disableFireSpreadBlocks.contains(world.getBlockTypeIdAt(x, y, z - 1)) + || wcfg.disableFireSpreadBlocks.contains(world.getBlockTypeIdAt(x, y, z + 1))) { + event.setCancelled(true); + return; + } + } + + if (wcfg.useRegions) { + Vector pt = toVector(block); + RegionManager mgr = plugin.getGlobalRegionManager().get(world); + ApplicableRegionSet set = mgr.getApplicableRegions(pt); + + if (wcfg.highFreqFlags && isFireSpread + && !set.allows(DefaultFlag.FIRE_SPREAD)) { + event.setCancelled(true); + return; + } + + if (wcfg.highFreqFlags && cause == IgniteCause.LAVA + && !set.allows(DefaultFlag.LAVA_FIRE)) { + event.setCancelled(true); + return; + } + + if (cause == IgniteCause.FIREBALL && event.getPlayer() == null) { + // wtf bukkit, FIREBALL is supposed to be reserved to players + if (!set.allows(DefaultFlag.GHAST_FIREBALL)) { + event.setCancelled(true); + return; + } + } + + if (cause == IgniteCause.LIGHTNING && !set.allows(DefaultFlag.LIGHTNING)) { + event.setCancelled(true); + return; + } + } + } + + /* + * Called when a block is destroyed from burning. + */ + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onBlockBurn(BlockBurnEvent event) { + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld()); + + if (cfg.activityHaltToggle) { + event.setCancelled(true); + return; + } + + if (wcfg.disableFireSpread) { + event.setCancelled(true); + return; + } + + if (wcfg.fireSpreadDisableToggle) { + Block block = event.getBlock(); + event.setCancelled(true); + checkAndDestroyAround(block.getWorld(), block.getX(), block.getY(), block.getZ(), BlockID.FIRE); + return; + } + + if (wcfg.disableFireSpreadBlocks.size() > 0) { + Block block = event.getBlock(); + + if (wcfg.disableFireSpreadBlocks.contains(block.getTypeId())) { + event.setCancelled(true); + checkAndDestroyAround(block.getWorld(), block.getX(), block.getY(), block.getZ(), BlockID.FIRE); + return; + } + } + + if (wcfg.isChestProtected(event.getBlock())) { + event.setCancelled(true); + return; + } + + if (wcfg.useRegions) { + Block block = event.getBlock(); + int x = block.getX(); + int y = block.getY(); + int z = block.getZ(); + Vector pt = toVector(block); + RegionManager mgr = plugin.getGlobalRegionManager().get(block.getWorld()); + ApplicableRegionSet set = mgr.getApplicableRegions(pt); + + if (!set.allows(DefaultFlag.FIRE_SPREAD)) { + checkAndDestroyAround(block.getWorld(), x, y, z, BlockID.FIRE); + event.setCancelled(true); + return; + } + + } + } + + private void checkAndDestroyAround(World world, int x, int y, int z, int required) { + checkAndDestroy(world, x, y, z + 1, required); + checkAndDestroy(world, x, y, z - 1, required); + checkAndDestroy(world, x, y + 1, z, required); + checkAndDestroy(world, x, y - 1, z, required); + checkAndDestroy(world, x + 1, y, z, required); + checkAndDestroy(world, x - 1, y, z, required); + } + + private void checkAndDestroy(World world, int x, int y, int z, int required) { + if (world.getBlockTypeIdAt(x, y, z) == required) { + world.getBlockAt(x, y, z).setTypeId(BlockID.AIR); + } + } + + /* + * Called when block physics occurs. + */ + @EventHandler(ignoreCancelled = true) + public void onBlockPhysics(BlockPhysicsEvent event) { + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld()); + + if (cfg.activityHaltToggle) { + event.setCancelled(true); + return; + } + + int id = event.getChangedTypeId(); + + if (id == 13 && wcfg.noPhysicsGravel) { + event.setCancelled(true); + return; + } + + if (id == 12 && wcfg.noPhysicsSand) { + event.setCancelled(true); + return; + } + + if (id == 90 && wcfg.allowPortalAnywhere) { + event.setCancelled(true); + return; + } + + if (wcfg.ropeLadders && event.getBlock().getType() == Material.LADDER) { + if (event.getBlock().getRelative(0, 1, 0).getType() == Material.LADDER) { + event.setCancelled(true); + return; + } + } + } + + /* + * Called when a player places a block. + */ + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onBlockPlace(BlockPlaceEvent event) { + Block target = event.getBlock(); + World world = target.getWorld(); + + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(world); + + if (wcfg.simulateSponge && target.getType() == Material.SPONGE) { + if (wcfg.redstoneSponges && target.isBlockIndirectlyPowered()) { + return; + } + + int ox = target.getX(); + int oy = target.getY(); + int oz = target.getZ(); + + SpongeUtil.clearSpongeWater(plugin, world, ox, oy, oz); + } + } + + /* + * Called when redstone changes. + */ + @EventHandler(priority = EventPriority.HIGH) + public void onBlockRedstoneChange(BlockRedstoneEvent event) { + Block blockTo = event.getBlock(); + World world = blockTo.getWorld(); + + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(world); + + if (wcfg.simulateSponge && wcfg.redstoneSponges) { + int ox = blockTo.getX(); + int oy = blockTo.getY(); + int oz = blockTo.getZ(); + + for (int cx = -1; cx <= 1; cx++) { + for (int cy = -1; cy <= 1; cy++) { + for (int cz = -1; cz <= 1; cz++) { + Block sponge = world.getBlockAt(ox + cx, oy + cy, oz + cz); + if (sponge.getTypeId() == 19 + && sponge.isBlockIndirectlyPowered()) { + SpongeUtil.clearSpongeWater(plugin, world, ox + cx, oy + cy, oz + cz); + } else if (sponge.getTypeId() == 19 + && !sponge.isBlockIndirectlyPowered()) { + SpongeUtil.addSpongeWater(plugin, world, ox + cx, oy + cy, oz + cz); + } + } + } + } + + return; + } + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onLeavesDecay(LeavesDecayEvent event) { + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld()); + + if (cfg.activityHaltToggle) { + event.setCancelled(true); + return; + } + + if (wcfg.disableLeafDecay) { + event.setCancelled(true); + return; + } + + if (wcfg.useRegions) { + if (!plugin.getGlobalRegionManager().allows(DefaultFlag.LEAF_DECAY, + event.getBlock().getLocation())) { + event.setCancelled(true); + } + } + } + + /* + * Called when a block is formed based on world conditions. + */ + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onBlockForm(BlockFormEvent event) { + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld()); + + if (cfg.activityHaltToggle) { + event.setCancelled(true); + return; + } + + int type = event.getNewState().getTypeId(); + + if (event instanceof EntityBlockFormEvent) { + if (((EntityBlockFormEvent) event).getEntity() instanceof Snowman) { + if (wcfg.disableSnowmanTrails) { + event.setCancelled(true); + return; + } + } + return; + } + + if (type == BlockID.ICE) { + if (wcfg.disableIceFormation) { + event.setCancelled(true); + return; + } + if (wcfg.useRegions && !plugin.getGlobalRegionManager().allows( + DefaultFlag.ICE_FORM, event.getBlock().getLocation())) { + event.setCancelled(true); + return; + } + } + + if (type == BlockID.SNOW) { + if (wcfg.disableSnowFormation) { + event.setCancelled(true); + return; + } + if (wcfg.allowedSnowFallOver.size() > 0) { + int targetId = event.getBlock().getRelative(0, -1, 0).getTypeId(); + + if (!wcfg.allowedSnowFallOver.contains(targetId)) { + event.setCancelled(true); + return; + } + } + if (wcfg.useRegions && !plugin.getGlobalRegionManager().allows( + DefaultFlag.SNOW_FALL, event.getBlock().getLocation())) { + event.setCancelled(true); + return; + } + } + } + + /* + * Called when a block spreads based on world conditions. + */ + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onBlockSpread(BlockSpreadEvent event) { + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld()); + + if (cfg.activityHaltToggle) { + event.setCancelled(true); + return; + } + + int fromType = event.getSource().getTypeId(); + + if (fromType == BlockID.RED_MUSHROOM || fromType == BlockID.BROWN_MUSHROOM) { + if (wcfg.disableMushroomSpread) { + event.setCancelled(true); + return; + } + if (wcfg.useRegions && !plugin.getGlobalRegionManager().allows( + DefaultFlag.MUSHROOMS, event.getBlock().getLocation())) { + event.setCancelled(true); + return; + } + } + + if (fromType == BlockID.GRASS) { + if (wcfg.disableGrassGrowth) { + event.setCancelled(true); + return; + } + if (wcfg.useRegions && !plugin.getGlobalRegionManager().allows( + DefaultFlag.GRASS_SPREAD, event.getBlock().getLocation())) { + event.setCancelled(true); + return; + } + } + + if (fromType == BlockID.MYCELIUM) { + if (wcfg.disableMyceliumSpread) { + event.setCancelled(true); + return; + } + + if (wcfg.useRegions + && !plugin.getGlobalRegionManager().allows( + DefaultFlag.MYCELIUM_SPREAD, event.getBlock().getLocation())) { + event.setCancelled(true); + return; + } + } + + if (fromType == BlockID.VINE) { + if (wcfg.disableVineGrowth) { + event.setCancelled(true); + return; + } + + if (wcfg.useRegions + && !plugin.getGlobalRegionManager().allows( + DefaultFlag.VINE_GROWTH, event.getBlock().getLocation())) { + event.setCancelled(true); + return; + } + } + } + + /* + * Called when a block fades. + */ + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onBlockFade(BlockFadeEvent event) { + + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld()); + + switch (event.getBlock().getTypeId()) { + case BlockID.ICE: + if (wcfg.disableIceMelting) { + event.setCancelled(true); + return; + } + + if (wcfg.useRegions && !plugin.getGlobalRegionManager().allows( + DefaultFlag.ICE_MELT, event.getBlock().getLocation())) { + event.setCancelled(true); + return; + } + break; + + case BlockID.SNOW: + if (wcfg.disableSnowMelting) { + event.setCancelled(true); + return; + } + + if (wcfg.useRegions && !plugin.getGlobalRegionManager().allows( + DefaultFlag.SNOW_MELT, event.getBlock().getLocation())) { + event.setCancelled(true); + return; + } + break; + + case BlockID.SOIL: + if (wcfg.disableSoilDehydration) { + event.setCancelled(true); + return; + } + if (wcfg.useRegions && !plugin.getGlobalRegionManager().allows( + DefaultFlag.SOIL_DRY, event.getBlock().getLocation())) { + event.setCancelled(true); + return; + } + break; + } + + } + + /* + * Called when a piston extends + */ + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onBlockPistonExtend(BlockPistonExtendEvent event) { + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld()); + + if (wcfg.useRegions) { + if (!plugin.getGlobalRegionManager().allows(DefaultFlag.PISTONS, event.getBlock().getLocation())) { + event.setCancelled(true); + return; + } + for (Block block : event.getBlocks()) { + if (!plugin.getGlobalRegionManager().allows(DefaultFlag.PISTONS, block.getLocation())) { + event.setCancelled(true); + return; + } + } + } + } + + /* + * Called when a piston retracts + */ + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onBlockPistonRetract(BlockPistonRetractEvent event) { + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld()); + + if (wcfg.useRegions && event.isSticky()) { + if (!(plugin.getGlobalRegionManager().allows(DefaultFlag.PISTONS, event.getRetractLocation())) + || !(plugin.getGlobalRegionManager().allows(DefaultFlag.PISTONS, event.getBlock().getLocation()))) { + event.setCancelled(true); + return; + } + } + } + + /* + * Called when a block yields exp + */ + @EventHandler(priority = EventPriority.HIGH) + public void onBlockExp(BlockExpEvent event) { + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld()); + if (wcfg.disableExpDrops || !plugin.getGlobalRegionManager().allows(DefaultFlag.EXP_DROPS, + event.getBlock().getLocation())) { + event.setExpToDrop(0); + } + } + +} diff --git a/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardCommandBookListener.java b/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardCommandBookListener.java similarity index 96% rename from src/main/java/com/sk89q/worldguard/bukkit/WorldGuardCommandBookListener.java rename to src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardCommandBookListener.java index 7727ba6d..40fa77eb 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardCommandBookListener.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardCommandBookListener.java @@ -17,10 +17,11 @@ * along with this program. If not, see . */ -package com.sk89q.worldguard.bukkit; +package com.sk89q.worldguard.bukkit.listener; import com.sk89q.commandbook.InfoComponent; import com.sk89q.worldguard.LocalPlayer; +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; import com.sk89q.worldguard.protection.ApplicableRegionSet; import com.sk89q.worldguard.protection.regions.ProtectedRegion; import org.bukkit.entity.Player; diff --git a/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardEntityListener.java b/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardEntityListener.java similarity index 93% rename from src/main/java/com/sk89q/worldguard/bukkit/WorldGuardEntityListener.java rename to src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardEntityListener.java index 24ababb6..b052f72f 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardEntityListener.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardEntityListener.java @@ -1,1042 +1,1009 @@ -/* - * 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; - -import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.blocks.BlockID; -import com.sk89q.worldguard.LocalPlayer; -import com.sk89q.worldguard.blacklist.event.ItemUseBlacklistEvent; -import com.sk89q.worldguard.internal.Events; -import com.sk89q.worldguard.internal.cause.Causes; -import com.sk89q.worldguard.internal.event.Interaction; -import com.sk89q.worldguard.internal.event.ItemInteractEvent; -import com.sk89q.worldguard.protection.ApplicableRegionSet; -import com.sk89q.worldguard.protection.GlobalRegionManager; -import com.sk89q.worldguard.protection.events.DisallowedPVPEvent; -import com.sk89q.worldguard.protection.flags.DefaultFlag; -import com.sk89q.worldguard.protection.managers.RegionManager; -import org.bukkit.ChatColor; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.entity.Creeper; -import org.bukkit.entity.EnderDragon; -import org.bukkit.entity.EnderPearl; -import org.bukkit.entity.Enderman; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Fireball; -import org.bukkit.entity.ItemFrame; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.entity.Projectile; -import org.bukkit.entity.TNTPrimed; -import org.bukkit.entity.Tameable; -import org.bukkit.entity.ThrownPotion; -import org.bukkit.entity.Wither; -import org.bukkit.entity.WitherSkull; -import org.bukkit.entity.Wolf; -import org.bukkit.entity.minecart.ExplosiveMinecart; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.CreatureSpawnEvent; -import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; -import org.bukkit.event.entity.CreeperPowerEvent; -import org.bukkit.event.entity.EntityBreakDoorEvent; -import org.bukkit.event.entity.EntityChangeBlockEvent; -import org.bukkit.event.entity.EntityCombustEvent; -import org.bukkit.event.entity.EntityCreatePortalEvent; -import org.bukkit.event.entity.EntityDamageByBlockEvent; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityDamageEvent; -import org.bukkit.event.entity.EntityDamageEvent.DamageCause; -import org.bukkit.event.entity.EntityDeathEvent; -import org.bukkit.event.entity.EntityExplodeEvent; -import org.bukkit.event.entity.EntityInteractEvent; -import org.bukkit.event.entity.EntityRegainHealthEvent; -import org.bukkit.event.entity.ExpBottleEvent; -import org.bukkit.event.entity.ExplosionPrimeEvent; -import org.bukkit.event.entity.FoodLevelChangeEvent; -import org.bukkit.event.entity.PigZapEvent; -import org.bukkit.event.entity.PlayerDeathEvent; -import org.bukkit.event.entity.PotionSplashEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.projectiles.ProjectileSource; - -import java.util.Set; - -import static com.sk89q.worldguard.bukkit.BukkitUtil.createTarget; -import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector; - -/** - * Listener for entity related events. - * - * @author sk89q - */ -public class WorldGuardEntityListener implements Listener { - - private WorldGuardPlugin plugin; - - /** - * Construct the object; - * - * @param plugin The plugin instance - */ - public WorldGuardEntityListener(WorldGuardPlugin plugin) { - this.plugin = plugin; - } - - /** - * Register events. - */ - public void registerEvents() { - plugin.getServer().getPluginManager().registerEvents(this, plugin); - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onEntityInteract(EntityInteractEvent event) { - Entity entity = event.getEntity(); - Block block = event.getBlock(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(entity.getWorld()); - - if (block.getTypeId() == BlockID.SOIL) { - if (/* entity instanceof Creature && // catch for any entity (not thrown for players) */ - wcfg.disableCreatureCropTrampling) { - event.setCancelled(true); - } - } - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onExpBottle(ExpBottleEvent event) { - WorldConfiguration wcfg = plugin.getGlobalStateManager().get(event.getEntity().getWorld()); - - if (wcfg.disableExpDrops || !plugin.getGlobalRegionManager().allows(DefaultFlag.EXP_DROPS, - event.getEntity().getLocation())) { - event.setExperience(0); - // event.setShowEffect(false); // don't want to cancel the bottle entirely I suppose, just the exp - } - } - - @EventHandler(priority = EventPriority.HIGH) - public void onEntityDeath(EntityDeathEvent event) { - WorldConfiguration wcfg = plugin.getGlobalStateManager().get(event.getEntity().getWorld()); - - if (wcfg.disableExpDrops || !plugin.getGlobalRegionManager().allows(DefaultFlag.EXP_DROPS, - event.getEntity().getLocation())) { - event.setDroppedExp(0); - } - - if (event instanceof PlayerDeathEvent && wcfg.disableDeathMessages) { - ((PlayerDeathEvent) event).setDeathMessage(""); - } - } - - private void onEntityDamageByBlock(EntityDamageByBlockEvent event) { - Entity defender = event.getEntity(); - DamageCause type = event.getCause(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(defender.getWorld()); - - if (defender instanceof Wolf && ((Wolf) defender).isTamed()) { - if (wcfg.antiWolfDumbness && !(type == DamageCause.VOID)) { - event.setCancelled(true); - return; - } - } else if (defender instanceof Player) { - Player player = (Player) defender; - - if (isInvincible(player)) { - event.setCancelled(true); - return; - } - - if (wcfg.disableLavaDamage && type == DamageCause.LAVA) { - event.setCancelled(true); - player.setFireTicks(0); - return; - } - - if (wcfg.disableContactDamage && type == DamageCause.CONTACT) { - event.setCancelled(true); - return; - } - - if (wcfg.teleportOnVoid && type == DamageCause.VOID) { - BukkitUtil.findFreePosition(player); - event.setCancelled(true); - return; - } - - if (wcfg.disableVoidDamage && type == DamageCause.VOID) { - event.setCancelled(true); - return; - } - - if (type == DamageCause.BLOCK_EXPLOSION - && (wcfg.disableExplosionDamage || wcfg.blockOtherExplosions - || (wcfg.explosionFlagCancellation - && !plugin.getGlobalRegionManager().allows(DefaultFlag.OTHER_EXPLOSION, player.getLocation())))) { - event.setCancelled(true); - return; - } - } else { - - // for whatever reason, plugin-caused explosions with a null entity count as block explosions and aren't - // handled anywhere else - if (type == DamageCause.BLOCK_EXPLOSION - && (wcfg.blockOtherExplosions - || (wcfg.explosionFlagCancellation - && !plugin.getGlobalRegionManager().allows(DefaultFlag.OTHER_EXPLOSION, defender.getLocation())))) { - event.setCancelled(true); - return; - } - } - } - - private void onEntityDamageByEntity(EntityDamageByEntityEvent event) { - - if (event.getDamager() instanceof Projectile) { - onEntityDamageByProjectile(event); - return; - } - - Entity attacker = event.getDamager(); - Entity defender = event.getEntity(); - - if (attacker instanceof Player) { - Player player = (Player) attacker; - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(player.getWorld()); - - ItemStack held = player.getInventory().getItemInHand(); - - if (held != null) { - if (wcfg.getBlacklist() != null) { - if (!wcfg.getBlacklist().check( - new ItemUseBlacklistEvent(plugin.wrapPlayer(player), - toVector(player.getLocation()), createTarget(held)), false, false)) { - event.setCancelled(true); - return; - } - } - } - } - - if (defender instanceof ItemFrame) { - if (checkItemFrameProtection(attacker, (ItemFrame) defender)) { - event.setCancelled(true); - return; - } - } - - if (defender instanceof Player) { - Player player = (Player) defender; - LocalPlayer localPlayer = plugin.wrapPlayer(player); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(player.getWorld()); - - if (isInvincible(player)) { - if (wcfg.regionInvinciblityRemovesMobs - && attacker instanceof LivingEntity && !(attacker instanceof Player) - && !(attacker instanceof Tameable && ((Tameable) attacker).isTamed())) { - attacker.remove(); - } - - event.setCancelled(true); - return; - } - - if (wcfg.disableLightningDamage && event.getCause() == DamageCause.LIGHTNING) { - event.setCancelled(true); - return; - } - - if (wcfg.disableExplosionDamage) { - switch (event.getCause()) { - case BLOCK_EXPLOSION: - case ENTITY_EXPLOSION: - event.setCancelled(true); - return; - } - } - - if (attacker != null) { - if (attacker instanceof Player) { - if (wcfg.useRegions) { - Vector pt = toVector(defender.getLocation()); - Vector pt2 = toVector(attacker.getLocation()); - RegionManager mgr = plugin.getGlobalRegionManager().get(player.getWorld()); - - if (!mgr.getApplicableRegions(pt2).allows(DefaultFlag.PVP, plugin.wrapPlayer((Player) attacker))) { - tryCancelPVPEvent((Player) attacker, player, event, true); - } else if (!mgr.getApplicableRegions(pt).allows(DefaultFlag.PVP ,localPlayer)) { - tryCancelPVPEvent((Player) attacker, player, event, false); - } - } - } - - if (attacker instanceof TNTPrimed || attacker instanceof ExplosiveMinecart) { - - // The check for explosion damage should be handled already... But... What ever... - if (wcfg.blockTNTExplosions) { - event.setCancelled(true); - return; - } - if (wcfg.useRegions && wcfg.explosionFlagCancellation) { - Vector pt = toVector(defender.getLocation()); - RegionManager mgr = plugin.getGlobalRegionManager().get(player.getWorld()); - ApplicableRegionSet set = mgr.getApplicableRegions(pt); - if (!set.allows(DefaultFlag.TNT, localPlayer)) { - event.setCancelled(true); - return; - } - } - } - - if (attacker instanceof Fireball) { - if (attacker instanceof WitherSkull) { - if (wcfg.blockWitherSkullExplosions) { - event.setCancelled(true); - return; - } - } else { - if (wcfg.blockFireballExplosions) { - event.setCancelled(true); - return; - } - } - if (wcfg.useRegions) { - Fireball fireball = (Fireball) attacker; - Vector pt = toVector(defender.getLocation()); - RegionManager mgr = plugin.getGlobalRegionManager().get(player.getWorld()); - ApplicableRegionSet set = mgr.getApplicableRegions(pt); - if (fireball.getShooter() instanceof Player) { - Vector pt2 = toVector(((Player) fireball.getShooter()).getLocation()); - if (!mgr.getApplicableRegions(pt2).allows(DefaultFlag.PVP, plugin.wrapPlayer((Player) fireball.getShooter()))) { - tryCancelPVPEvent((Player) fireball.getShooter(), player, event, true); - } else if (!set.allows(DefaultFlag.PVP, localPlayer)) { - tryCancelPVPEvent((Player) fireball.getShooter(), player, event, false); - } - } else { - if (!set.allows(DefaultFlag.GHAST_FIREBALL, localPlayer) && wcfg.explosionFlagCancellation) { - event.setCancelled(true); - return; - } - } - - } - } - - if (attacker instanceof LivingEntity && !(attacker instanceof Player)) { - if (attacker instanceof Creeper && wcfg.blockCreeperExplosions) { - event.setCancelled(true); - return; - } - - if (wcfg.disableMobDamage) { - event.setCancelled(true); - return; - } - - if (wcfg.useRegions) { - Vector pt = toVector(defender.getLocation()); - RegionManager mgr = plugin.getGlobalRegionManager().get(player.getWorld()); - ApplicableRegionSet set = mgr.getApplicableRegions(pt); - - if (!set.allows(DefaultFlag.MOB_DAMAGE, localPlayer) && !(attacker instanceof Tameable)) { - event.setCancelled(true); - return; - } - - if (attacker instanceof Creeper) { - if (!set.allows(DefaultFlag.CREEPER_EXPLOSION, localPlayer) && wcfg.explosionFlagCancellation) { - event.setCancelled(true); - return; - } - } - if (attacker instanceof Tameable) { - if (((Tameable) attacker).getOwner() == null) { - if (!set.allows(DefaultFlag.MOB_DAMAGE, localPlayer)) { - event.setCancelled(true); - return; - } - } - if (!(((Tameable) attacker).getOwner() instanceof Player)) { - return; - } - Player beastMaster = (Player) ((Tameable) attacker).getOwner(); - Vector pt2 = toVector(attacker.getLocation()); - if (!mgr.getApplicableRegions(pt2).allows(DefaultFlag.PVP, plugin.wrapPlayer(beastMaster))) { - tryCancelPVPEvent(beastMaster, player, event, true); - } else if (!set.allows(DefaultFlag.PVP, localPlayer)) { - tryCancelPVPEvent(beastMaster, player, event, false); - } - } - } - } - } - } - } - - private void onEntityDamageByProjectile(EntityDamageByEntityEvent event) { - Entity defender = event.getEntity(); - Entity attacker; - ProjectileSource source = ((Projectile) event.getDamager()).getShooter(); - if (source instanceof LivingEntity) { - attacker = (LivingEntity) source; - } else { - return; - } - - if (defender instanceof Player) { - Player player = (Player) defender; - LocalPlayer localPlayer = plugin.wrapPlayer(player); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(player.getWorld()); - - // Check Invincible - if (isInvincible(player)) { - event.setCancelled(true); - return; - } - - // Check Mob - if (attacker != null && !(attacker instanceof Player)) { - if (wcfg.disableMobDamage) { - event.setCancelled(true); - return; - } - if (wcfg.useRegions) { - Vector pt = toVector(defender.getLocation()); - RegionManager mgr = plugin.getGlobalRegionManager().get(player.getWorld()); - - if (!mgr.getApplicableRegions(pt).allows(DefaultFlag.MOB_DAMAGE, localPlayer)) { - event.setCancelled(true); - return; - } - } - } - - // Check Player - // if (event.getDamager() instanceof EnderPearl || event.getDamager() instanceof Snowball) return; - if (attacker != null && attacker instanceof Player) { - if (event.getDamager() instanceof EnderPearl && attacker == player) return; - if (wcfg.useRegions) { - Vector pt = toVector(defender.getLocation()); - Vector pt2 = toVector(attacker.getLocation()); - RegionManager mgr = plugin.getGlobalRegionManager().get(player.getWorld()); - - if (!mgr.getApplicableRegions(pt2).allows(DefaultFlag.PVP, plugin.wrapPlayer((Player) attacker))) { - tryCancelPVPEvent((Player) attacker, player, event, true); - } else if (!mgr.getApplicableRegions(pt).allows(DefaultFlag.PVP, localPlayer)) { - tryCancelPVPEvent((Player) attacker, player, event, false); - } - } - } - } else if (defender instanceof ItemFrame) { - if (checkItemFrameProtection(attacker, (ItemFrame) defender)) { - event.setCancelled(true); - return; - } - } - - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onEntityDamage(EntityDamageEvent event) { - - if (event instanceof EntityDamageByEntityEvent) { - this.onEntityDamageByEntity((EntityDamageByEntityEvent) event); - return; - } else if (event instanceof EntityDamageByBlockEvent) { - this.onEntityDamageByBlock((EntityDamageByBlockEvent) event); - return; - } - - Entity defender = event.getEntity(); - DamageCause type = event.getCause(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(defender.getWorld()); - - if (defender instanceof Wolf && ((Wolf) defender).isTamed()) { - if (wcfg.antiWolfDumbness) { - event.setCancelled(true); - return; - } - } else if (defender instanceof Player) { - Player player = (Player) defender; - - if (isInvincible(player)) { - event.setCancelled(true); - player.setFireTicks(0); - return; - } - - if (type == DamageCause.WITHER) { - // wither boss DoT tick - if (wcfg.disableMobDamage) { - event.setCancelled(true); - return; - } - - if (wcfg.useRegions) { - Vector pt = toVector(defender.getLocation()); - RegionManager mgr = plugin.getGlobalRegionManager().get(player.getWorld()); - ApplicableRegionSet set = mgr.getApplicableRegions(pt); - - if (!set.allows(DefaultFlag.MOB_DAMAGE, plugin.wrapPlayer(player))) { - event.setCancelled(true); - return; - } - } - } - - if (type == DamageCause.DROWNING && cfg.hasAmphibiousMode(player)) { - player.setRemainingAir(player.getMaximumAir()); - event.setCancelled(true); - return; - } - - ItemStack helmet = player.getInventory().getHelmet(); - - if (type == DamageCause.DROWNING && wcfg.pumpkinScuba - && helmet != null - && (helmet.getTypeId() == BlockID.PUMPKIN - || helmet.getTypeId() == BlockID.JACKOLANTERN)) { - player.setRemainingAir(player.getMaximumAir()); - event.setCancelled(true); - return; - } - - if (wcfg.disableFallDamage && type == DamageCause.FALL) { - event.setCancelled(true); - return; - } - - if (wcfg.disableFireDamage && (type == DamageCause.FIRE - || type == DamageCause.FIRE_TICK)) { - event.setCancelled(true); - return; - } - - if (wcfg.disableDrowningDamage && type == DamageCause.DROWNING) { - player.setRemainingAir(player.getMaximumAir()); - event.setCancelled(true); - return; - } - - if (wcfg.teleportOnSuffocation && type == DamageCause.SUFFOCATION) { - BukkitUtil.findFreePosition(player); - event.setCancelled(true); - return; - } - - if (wcfg.disableSuffocationDamage && type == DamageCause.SUFFOCATION) { - event.setCancelled(true); - return; - } - } - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onEntityCombust(EntityCombustEvent event) { - Entity entity = event.getEntity(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(entity.getWorld()); - - if (entity instanceof Player) { - Player player = (Player) entity; - - if (cfg.hasGodMode(player) || (wcfg.useRegions && RegionQueryUtil.isInvincible(plugin, player))) { - event.setCancelled(true); - return; - } - } - } - - /* - * Called on entity explode. - */ - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onEntityExplode(EntityExplodeEvent event) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - Location l = event.getLocation(); - World world = l.getWorld(); - WorldConfiguration wcfg = cfg.get(world); - Entity ent = event.getEntity(); - - if (cfg.activityHaltToggle) { - if (ent != null) { - ent.remove(); - } - event.setCancelled(true); - return; - } - - if (ent instanceof Creeper) { - if (wcfg.blockCreeperExplosions) { - event.setCancelled(true); - return; - } - if (wcfg.blockCreeperBlockDamage) { - event.blockList().clear(); - return; - } - - if (wcfg.useRegions) { - RegionManager mgr = plugin.getGlobalRegionManager().get(world); - - for (Block block : event.blockList()) { - if (!mgr.getApplicableRegions(toVector(block)).allows(DefaultFlag.CREEPER_EXPLOSION)) { - event.blockList().clear(); - if (wcfg.explosionFlagCancellation) event.setCancelled(true); - return; - } - } - } - } else if (ent instanceof EnderDragon) { - if (wcfg.blockEnderDragonBlockDamage) { - event.blockList().clear(); - return; - } - - if (wcfg.useRegions) { - RegionManager mgr = plugin.getGlobalRegionManager().get(world); - - for (Block block : event.blockList()) { - if (!mgr.getApplicableRegions(toVector(block)).allows(DefaultFlag.ENDERDRAGON_BLOCK_DAMAGE)) { - event.blockList().clear(); - if (wcfg.explosionFlagCancellation) event.setCancelled(true); - return; - } - } - } - } else if (ent instanceof TNTPrimed || ent instanceof ExplosiveMinecart) { - if (wcfg.blockTNTExplosions) { - event.setCancelled(true); - return; - } - if (wcfg.blockTNTBlockDamage) { - event.blockList().clear(); - return; - } - - if (wcfg.useRegions) { - RegionManager mgr = plugin.getGlobalRegionManager().get(world); - - for (Block block : event.blockList()) { - if (!mgr.getApplicableRegions(toVector(block)).allows(DefaultFlag.TNT)) { - event.blockList().clear(); - if (wcfg.explosionFlagCancellation) event.setCancelled(true); - return; - } - } - } - } else if (ent instanceof Fireball) { - if (ent instanceof WitherSkull) { - if (wcfg.blockWitherSkullExplosions) { - event.setCancelled(true); - return; - } - if (wcfg.blockWitherSkullBlockDamage) { - event.blockList().clear(); - return; - } - } else { - if (wcfg.blockFireballExplosions) { - event.setCancelled(true); - return; - } - if (wcfg.blockFireballBlockDamage) { - event.blockList().clear(); - return; - } - } - // allow wither skull blocking since there is no dedicated flag atm - if (wcfg.useRegions) { - RegionManager mgr = plugin.getGlobalRegionManager().get(world); - - for (Block block : event.blockList()) { - if (!mgr.getApplicableRegions(toVector(block)).allows(DefaultFlag.GHAST_FIREBALL)) { - event.blockList().clear(); - if (wcfg.explosionFlagCancellation) event.setCancelled(true); - return; - } - } - } - } else if (ent instanceof Wither) { - if (wcfg.blockWitherExplosions) { - event.setCancelled(true); - return; - } - if (wcfg.blockWitherBlockDamage) { - event.blockList().clear(); - return; - } - } else { - // unhandled entity - if (wcfg.blockOtherExplosions) { - event.setCancelled(true); - return; - } - if (wcfg.useRegions) { - RegionManager mgr = plugin.getGlobalRegionManager().get(world); - for (Block block : event.blockList()) { - if (!mgr.getApplicableRegions(toVector(block)).allows(DefaultFlag.OTHER_EXPLOSION)) { - event.blockList().clear(); - if (wcfg.explosionFlagCancellation) event.setCancelled(true); - return; - } - } - } - } - - - if (wcfg.signChestProtection) { - for (Block block : event.blockList()) { - if (wcfg.isChestProtected(block)) { - event.blockList().clear(); - return; - } - } - } - - } - - /* - * Called on explosion prime - */ - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onExplosionPrime(ExplosionPrimeEvent event) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(event.getEntity().getWorld()); - Entity ent = event.getEntity(); - - if (cfg.activityHaltToggle) { - ent.remove(); - event.setCancelled(true); - return; - } - - if (event.getEntityType() == EntityType.WITHER) { - if (wcfg.blockWitherExplosions) { - event.setCancelled(true); - return; - } - } else if (event.getEntityType() == EntityType.WITHER_SKULL) { - if (wcfg.blockWitherSkullExplosions) { - event.setCancelled(true); - return; - } - } else if (event.getEntityType() == EntityType.FIREBALL) { - if (wcfg.blockFireballExplosions) { - event.setCancelled(true); - return; - } - } else if (event.getEntityType() == EntityType.CREEPER) { - if (wcfg.blockCreeperExplosions) { - event.setCancelled(true); - return; - } - } else if (event.getEntityType() == EntityType.PRIMED_TNT - || event.getEntityType() == EntityType.MINECART_TNT) { - if (wcfg.blockTNTExplosions) { - event.setCancelled(true); - return; - } - } - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onCreatureSpawn(CreatureSpawnEvent event) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - - if (cfg.activityHaltToggle) { - event.setCancelled(true); - return; - } - - WorldConfiguration wcfg = cfg.get(event.getEntity().getWorld()); - - // allow spawning of creatures from plugins - if (!wcfg.blockPluginSpawning && event.getSpawnReason() == CreatureSpawnEvent.SpawnReason.CUSTOM) { - return; - } - - if (wcfg.allowTamedSpawns - && event.getEntity() instanceof Tameable // nullsafe check - && ((Tameable) event.getEntity()).isTamed()) { - return; - } - - EntityType entityType = event.getEntityType(); - - if (wcfg.blockCreatureSpawn.contains(entityType)) { - event.setCancelled(true); - return; - } - - Location eventLoc = event.getLocation(); - - if (wcfg.useRegions && cfg.useRegionsCreatureSpawnEvent) { - Vector pt = toVector(eventLoc); - RegionManager mgr = plugin.getGlobalRegionManager().get(eventLoc.getWorld()); - // @TODO get victims' stacktraces and find out why it's null anyway - if (mgr == null) return; - ApplicableRegionSet set = mgr.getApplicableRegions(pt); - - if (!set.allows(DefaultFlag.MOB_SPAWNING)) { - event.setCancelled(true); - return; - } - - Set entityTypes = set.getFlag(DefaultFlag.DENY_SPAWN); - if (entityTypes != null && entityTypes.contains(entityType)) { - event.setCancelled(true); - return; - } - } - - if (wcfg.blockGroundSlimes && entityType == EntityType.SLIME - && eventLoc.getY() >= 60 - && event.getSpawnReason() == SpawnReason.NATURAL) { - event.setCancelled(true); - return; - } - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onCreatePortal(EntityCreatePortalEvent event) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(event.getEntity().getWorld()); - - switch (event.getEntityType()) { - case ENDER_DRAGON: - if (wcfg.blockEnderDragonPortalCreation) event.setCancelled(true); - break; - } - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onPigZap(PigZapEvent event) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(event.getEntity().getWorld()); - - if (wcfg.disablePigZap) { - event.setCancelled(true); - } - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onCreeperPower(CreeperPowerEvent event) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(event.getEntity().getWorld()); - - if (wcfg.disableCreeperPower) { - event.setCancelled(true); - } - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onEntityRegainHealth(EntityRegainHealthEvent event) { - - Entity ent = event.getEntity(); - World world = ent.getWorld(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - - if (wcfg.disableHealthRegain) { - event.setCancelled(true); - return; - } - } - - /** - * Called when an entity changes a block somehow - * - * @param event Relevant event details - */ - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onEntityChangeBlock(EntityChangeBlockEvent event) { - Entity ent = event.getEntity(); - Block block = event.getBlock(); - Location location = block.getLocation(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(ent.getWorld()); - if (ent instanceof Enderman) { - if (wcfg.disableEndermanGriefing) { - event.setCancelled(true); - return; - } - - if (wcfg.useRegions) { - if (!plugin.getGlobalRegionManager().allows(DefaultFlag.ENDER_BUILD, location)) { - event.setCancelled(true); - return; - } - } - } else if (ent.getType() == EntityType.WITHER) { - if (wcfg.blockWitherBlockDamage || wcfg.blockWitherExplosions) { - event.setCancelled(true); - return; - } - } else if (/*ent instanceof Zombie && */event instanceof EntityBreakDoorEvent) { - if (wcfg.blockZombieDoorDestruction) { - event.setCancelled(true); - return; - } - } - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onFoodLevelChange(FoodLevelChangeEvent event) { - if (event.getEntity() instanceof Player) { - Player player = (Player) event.getEntity(); - if (event.getFoodLevel() < player.getFoodLevel() && isInvincible(player)) { - event.setCancelled(true); - } - } - } - - @EventHandler(ignoreCancelled = true) - public void onPotionSplash(PotionSplashEvent event) { - Entity entity = event.getEntity(); - ThrownPotion potion = event.getPotion(); - World world = entity.getWorld(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - - Events.fireToCancel(event, new ItemInteractEvent(event, Causes.create(potion.getShooter()), Interaction.INTERACT, world, potion.getItem())); - - 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 - * to override it. (worldguard.god.override-regions) - * - * @param player The player to check - * @return Whether {@code player} is invincible - */ - private boolean isInvincible(Player player) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(player.getWorld()); - - boolean god = cfg.hasGodMode(player); - if (wcfg.useRegions) { - Boolean flag = RegionQueryUtil.isAllowedInvinciblity(plugin, player); - boolean allowed = flag == null || flag; - boolean invincible = RegionQueryUtil.isInvincible(plugin, player); - - if (allowed) { - return god || invincible; - } else { - return (god && plugin.hasPermission(player, "worldguard.god.override-regions")) - || invincible; - } - } else { - return god; - } - } - - /** - * Using a DisallowedPVPEvent, notifies other plugins that WorldGuard - * wants to cancel a PvP damage event.
- * If this event is not cancelled, the attacking player is notified that - * PvP is disabled and WorldGuard cancels the damage event. - * - * @param attackingPlayer The attacker - * @param defendingPlayer The defender - * @param event The event that caused WorldGuard to act - */ - public void tryCancelPVPEvent(final Player attackingPlayer, final Player defendingPlayer, EntityDamageByEntityEvent event, boolean aggressorTriggered) { - final DisallowedPVPEvent disallowedPVPEvent = new DisallowedPVPEvent(attackingPlayer, defendingPlayer, event); - plugin.getServer().getPluginManager().callEvent(disallowedPVPEvent); - if (!disallowedPVPEvent.isCancelled()) { - if (aggressorTriggered) attackingPlayer.sendMessage(ChatColor.DARK_RED + "You are in a no-PvP area."); - else attackingPlayer.sendMessage(ChatColor.DARK_RED + "That player is in a no-PvP area."); - event.setCancelled(true); - } - } - - /** - * Checks regions and config settings to protect items from being knocked - * out of item frames. - * @param attacker attacking entity - * @param defender item frame being damaged - * @return true if the event should be cancelled - */ - private boolean checkItemFrameProtection(Entity attacker, ItemFrame defender) { - World world = attacker.getWorld(); - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - if (wcfg.useRegions) { - // bukkit throws this event when a player attempts to remove an item from a frame - RegionManager mgr = plugin.getGlobalRegionManager().get(world); - if (attacker instanceof Player) { - Player player = (Player) attacker; - LocalPlayer localPlayer = plugin.wrapPlayer(player); - if (!plugin.getGlobalRegionManager().hasBypass(player, world) - && !mgr.getApplicableRegions(defender.getLocation()) - .canBuild(localPlayer)) { - player.sendMessage(ChatColor.DARK_RED + "You don't have permission for this area."); - return true; - } - } else { - if (!plugin.getGlobalRegionManager().allows( - DefaultFlag.ENTITY_ITEM_FRAME_DESTROY, defender.getLocation())) { - return true; - } - } - } - if (wcfg.blockEntityItemFrameDestroy && !(attacker instanceof Player)) { - return true; - } - return false; - } - -} +/* + * 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.listener; + +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.blocks.BlockID; +import com.sk89q.worldguard.LocalPlayer; +import com.sk89q.worldguard.bukkit.BukkitUtil; +import com.sk89q.worldguard.bukkit.ConfigurationManager; +import com.sk89q.worldguard.bukkit.RegionQueryUtil; +import com.sk89q.worldguard.bukkit.WorldConfiguration; +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import com.sk89q.worldguard.protection.ApplicableRegionSet; +import com.sk89q.worldguard.protection.GlobalRegionManager; +import com.sk89q.worldguard.protection.events.DisallowedPVPEvent; +import com.sk89q.worldguard.protection.flags.DefaultFlag; +import com.sk89q.worldguard.protection.managers.RegionManager; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.entity.Creeper; +import org.bukkit.entity.EnderDragon; +import org.bukkit.entity.EnderPearl; +import org.bukkit.entity.Enderman; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Fireball; +import org.bukkit.entity.ItemFrame; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; +import org.bukkit.entity.TNTPrimed; +import org.bukkit.entity.Tameable; +import org.bukkit.entity.ThrownPotion; +import org.bukkit.entity.Wither; +import org.bukkit.entity.WitherSkull; +import org.bukkit.entity.Wolf; +import org.bukkit.entity.minecart.ExplosiveMinecart; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; +import org.bukkit.event.entity.CreeperPowerEvent; +import org.bukkit.event.entity.EntityBreakDoorEvent; +import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.event.entity.EntityCombustEvent; +import org.bukkit.event.entity.EntityCreatePortalEvent; +import org.bukkit.event.entity.EntityDamageByBlockEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.EntityInteractEvent; +import org.bukkit.event.entity.EntityRegainHealthEvent; +import org.bukkit.event.entity.ExpBottleEvent; +import org.bukkit.event.entity.ExplosionPrimeEvent; +import org.bukkit.event.entity.FoodLevelChangeEvent; +import org.bukkit.event.entity.PigZapEvent; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.entity.PotionSplashEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.projectiles.ProjectileSource; + +import java.util.Set; + +import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector; + +/** + * Listener for entity related events. + * + * @author sk89q + */ +public class WorldGuardEntityListener implements Listener { + + private WorldGuardPlugin plugin; + + /** + * Construct the object; + * + * @param plugin The plugin instance + */ + public WorldGuardEntityListener(WorldGuardPlugin plugin) { + this.plugin = plugin; + } + + /** + * Register events. + */ + public void registerEvents() { + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onEntityInteract(EntityInteractEvent event) { + Entity entity = event.getEntity(); + Block block = event.getBlock(); + + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(entity.getWorld()); + + if (block.getTypeId() == BlockID.SOIL) { + if (/* entity instanceof Creature && // catch for any entity (not thrown for players) */ + wcfg.disableCreatureCropTrampling) { + event.setCancelled(true); + } + } + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onExpBottle(ExpBottleEvent event) { + WorldConfiguration wcfg = plugin.getGlobalStateManager().get(event.getEntity().getWorld()); + + if (wcfg.disableExpDrops || !plugin.getGlobalRegionManager().allows(DefaultFlag.EXP_DROPS, + event.getEntity().getLocation())) { + event.setExperience(0); + // event.setShowEffect(false); // don't want to cancel the bottle entirely I suppose, just the exp + } + } + + @EventHandler(priority = EventPriority.HIGH) + public void onEntityDeath(EntityDeathEvent event) { + WorldConfiguration wcfg = plugin.getGlobalStateManager().get(event.getEntity().getWorld()); + + if (wcfg.disableExpDrops || !plugin.getGlobalRegionManager().allows(DefaultFlag.EXP_DROPS, + event.getEntity().getLocation())) { + event.setDroppedExp(0); + } + + if (event instanceof PlayerDeathEvent && wcfg.disableDeathMessages) { + ((PlayerDeathEvent) event).setDeathMessage(""); + } + } + + private void onEntityDamageByBlock(EntityDamageByBlockEvent event) { + Entity defender = event.getEntity(); + DamageCause type = event.getCause(); + + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(defender.getWorld()); + + if (defender instanceof Wolf && ((Wolf) defender).isTamed()) { + if (wcfg.antiWolfDumbness && !(type == DamageCause.VOID)) { + event.setCancelled(true); + return; + } + } else if (defender instanceof Player) { + Player player = (Player) defender; + + if (isInvincible(player)) { + event.setCancelled(true); + return; + } + + if (wcfg.disableLavaDamage && type == DamageCause.LAVA) { + event.setCancelled(true); + player.setFireTicks(0); + return; + } + + if (wcfg.disableContactDamage && type == DamageCause.CONTACT) { + event.setCancelled(true); + return; + } + + if (wcfg.teleportOnVoid && type == DamageCause.VOID) { + BukkitUtil.findFreePosition(player); + event.setCancelled(true); + return; + } + + if (wcfg.disableVoidDamage && type == DamageCause.VOID) { + event.setCancelled(true); + return; + } + + if (type == DamageCause.BLOCK_EXPLOSION + && (wcfg.disableExplosionDamage || wcfg.blockOtherExplosions + || (wcfg.explosionFlagCancellation + && !plugin.getGlobalRegionManager().allows(DefaultFlag.OTHER_EXPLOSION, player.getLocation())))) { + event.setCancelled(true); + return; + } + } else { + + // for whatever reason, plugin-caused explosions with a null entity count as block explosions and aren't + // handled anywhere else + if (type == DamageCause.BLOCK_EXPLOSION + && (wcfg.blockOtherExplosions + || (wcfg.explosionFlagCancellation + && !plugin.getGlobalRegionManager().allows(DefaultFlag.OTHER_EXPLOSION, defender.getLocation())))) { + event.setCancelled(true); + return; + } + } + } + + private void onEntityDamageByEntity(EntityDamageByEntityEvent event) { + + if (event.getDamager() instanceof Projectile) { + onEntityDamageByProjectile(event); + return; + } + + Entity attacker = event.getDamager(); + Entity defender = event.getEntity(); + + if (defender instanceof ItemFrame) { + if (checkItemFrameProtection(attacker, (ItemFrame) defender)) { + event.setCancelled(true); + return; + } + } + + if (defender instanceof Player) { + Player player = (Player) defender; + LocalPlayer localPlayer = plugin.wrapPlayer(player); + + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(player.getWorld()); + + if (isInvincible(player)) { + if (wcfg.regionInvinciblityRemovesMobs + && attacker instanceof LivingEntity && !(attacker instanceof Player) + && !(attacker instanceof Tameable && ((Tameable) attacker).isTamed())) { + attacker.remove(); + } + + event.setCancelled(true); + return; + } + + if (wcfg.disableLightningDamage && event.getCause() == DamageCause.LIGHTNING) { + event.setCancelled(true); + return; + } + + if (wcfg.disableExplosionDamage) { + switch (event.getCause()) { + case BLOCK_EXPLOSION: + case ENTITY_EXPLOSION: + event.setCancelled(true); + return; + } + } + + if (attacker != null) { + if (attacker instanceof Player) { + if (wcfg.useRegions) { + Vector pt = toVector(defender.getLocation()); + Vector pt2 = toVector(attacker.getLocation()); + RegionManager mgr = plugin.getGlobalRegionManager().get(player.getWorld()); + + if (!mgr.getApplicableRegions(pt2).allows(DefaultFlag.PVP, plugin.wrapPlayer((Player) attacker))) { + tryCancelPVPEvent((Player) attacker, player, event, true); + } else if (!mgr.getApplicableRegions(pt).allows(DefaultFlag.PVP ,localPlayer)) { + tryCancelPVPEvent((Player) attacker, player, event, false); + } + } + } + + if (attacker instanceof TNTPrimed || attacker instanceof ExplosiveMinecart) { + + // The check for explosion damage should be handled already... But... What ever... + if (wcfg.blockTNTExplosions) { + event.setCancelled(true); + return; + } + if (wcfg.useRegions && wcfg.explosionFlagCancellation) { + Vector pt = toVector(defender.getLocation()); + RegionManager mgr = plugin.getGlobalRegionManager().get(player.getWorld()); + ApplicableRegionSet set = mgr.getApplicableRegions(pt); + if (!set.allows(DefaultFlag.TNT, localPlayer)) { + event.setCancelled(true); + return; + } + } + } + + if (attacker instanceof Fireball) { + if (attacker instanceof WitherSkull) { + if (wcfg.blockWitherSkullExplosions) { + event.setCancelled(true); + return; + } + } else { + if (wcfg.blockFireballExplosions) { + event.setCancelled(true); + return; + } + } + if (wcfg.useRegions) { + Fireball fireball = (Fireball) attacker; + Vector pt = toVector(defender.getLocation()); + RegionManager mgr = plugin.getGlobalRegionManager().get(player.getWorld()); + ApplicableRegionSet set = mgr.getApplicableRegions(pt); + if (fireball.getShooter() instanceof Player) { + Vector pt2 = toVector(((Player) fireball.getShooter()).getLocation()); + if (!mgr.getApplicableRegions(pt2).allows(DefaultFlag.PVP, plugin.wrapPlayer((Player) fireball.getShooter()))) { + tryCancelPVPEvent((Player) fireball.getShooter(), player, event, true); + } else if (!set.allows(DefaultFlag.PVP, localPlayer)) { + tryCancelPVPEvent((Player) fireball.getShooter(), player, event, false); + } + } else { + if (!set.allows(DefaultFlag.GHAST_FIREBALL, localPlayer) && wcfg.explosionFlagCancellation) { + event.setCancelled(true); + return; + } + } + + } + } + + if (attacker instanceof LivingEntity && !(attacker instanceof Player)) { + if (attacker instanceof Creeper && wcfg.blockCreeperExplosions) { + event.setCancelled(true); + return; + } + + if (wcfg.disableMobDamage) { + event.setCancelled(true); + return; + } + + if (wcfg.useRegions) { + Vector pt = toVector(defender.getLocation()); + RegionManager mgr = plugin.getGlobalRegionManager().get(player.getWorld()); + ApplicableRegionSet set = mgr.getApplicableRegions(pt); + + if (!set.allows(DefaultFlag.MOB_DAMAGE, localPlayer) && !(attacker instanceof Tameable)) { + event.setCancelled(true); + return; + } + + if (attacker instanceof Creeper) { + if (!set.allows(DefaultFlag.CREEPER_EXPLOSION, localPlayer) && wcfg.explosionFlagCancellation) { + event.setCancelled(true); + return; + } + } + if (attacker instanceof Tameable) { + if (((Tameable) attacker).getOwner() == null) { + if (!set.allows(DefaultFlag.MOB_DAMAGE, localPlayer)) { + event.setCancelled(true); + return; + } + } + if (!(((Tameable) attacker).getOwner() instanceof Player)) { + return; + } + Player beastMaster = (Player) ((Tameable) attacker).getOwner(); + Vector pt2 = toVector(attacker.getLocation()); + if (!mgr.getApplicableRegions(pt2).allows(DefaultFlag.PVP, plugin.wrapPlayer(beastMaster))) { + tryCancelPVPEvent(beastMaster, player, event, true); + } else if (!set.allows(DefaultFlag.PVP, localPlayer)) { + tryCancelPVPEvent(beastMaster, player, event, false); + } + } + } + } + } + } + } + + private void onEntityDamageByProjectile(EntityDamageByEntityEvent event) { + Entity defender = event.getEntity(); + Entity attacker; + ProjectileSource source = ((Projectile) event.getDamager()).getShooter(); + if (source instanceof LivingEntity) { + attacker = (LivingEntity) source; + } else { + return; + } + + if (defender instanceof Player) { + Player player = (Player) defender; + LocalPlayer localPlayer = plugin.wrapPlayer(player); + + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(player.getWorld()); + + // Check Invincible + if (isInvincible(player)) { + event.setCancelled(true); + return; + } + + // Check Mob + if (attacker != null && !(attacker instanceof Player)) { + if (wcfg.disableMobDamage) { + event.setCancelled(true); + return; + } + if (wcfg.useRegions) { + Vector pt = toVector(defender.getLocation()); + RegionManager mgr = plugin.getGlobalRegionManager().get(player.getWorld()); + + if (!mgr.getApplicableRegions(pt).allows(DefaultFlag.MOB_DAMAGE, localPlayer)) { + event.setCancelled(true); + return; + } + } + } + + // Check Player + // if (event.getDamager() instanceof EnderPearl || event.getDamager() instanceof Snowball) return; + if (attacker != null && attacker instanceof Player) { + if (event.getDamager() instanceof EnderPearl && attacker == player) return; + if (wcfg.useRegions) { + Vector pt = toVector(defender.getLocation()); + Vector pt2 = toVector(attacker.getLocation()); + RegionManager mgr = plugin.getGlobalRegionManager().get(player.getWorld()); + + if (!mgr.getApplicableRegions(pt2).allows(DefaultFlag.PVP, plugin.wrapPlayer((Player) attacker))) { + tryCancelPVPEvent((Player) attacker, player, event, true); + } else if (!mgr.getApplicableRegions(pt).allows(DefaultFlag.PVP, localPlayer)) { + tryCancelPVPEvent((Player) attacker, player, event, false); + } + } + } + } else if (defender instanceof ItemFrame) { + if (checkItemFrameProtection(attacker, (ItemFrame) defender)) { + event.setCancelled(true); + return; + } + } + + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onEntityDamage(EntityDamageEvent event) { + + if (event instanceof EntityDamageByEntityEvent) { + this.onEntityDamageByEntity((EntityDamageByEntityEvent) event); + return; + } else if (event instanceof EntityDamageByBlockEvent) { + this.onEntityDamageByBlock((EntityDamageByBlockEvent) event); + return; + } + + Entity defender = event.getEntity(); + DamageCause type = event.getCause(); + + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(defender.getWorld()); + + if (defender instanceof Wolf && ((Wolf) defender).isTamed()) { + if (wcfg.antiWolfDumbness) { + event.setCancelled(true); + return; + } + } else if (defender instanceof Player) { + Player player = (Player) defender; + + if (isInvincible(player)) { + event.setCancelled(true); + player.setFireTicks(0); + return; + } + + if (type == DamageCause.WITHER) { + // wither boss DoT tick + if (wcfg.disableMobDamage) { + event.setCancelled(true); + return; + } + + if (wcfg.useRegions) { + Vector pt = toVector(defender.getLocation()); + RegionManager mgr = plugin.getGlobalRegionManager().get(player.getWorld()); + ApplicableRegionSet set = mgr.getApplicableRegions(pt); + + if (!set.allows(DefaultFlag.MOB_DAMAGE, plugin.wrapPlayer(player))) { + event.setCancelled(true); + return; + } + } + } + + if (type == DamageCause.DROWNING && cfg.hasAmphibiousMode(player)) { + player.setRemainingAir(player.getMaximumAir()); + event.setCancelled(true); + return; + } + + ItemStack helmet = player.getInventory().getHelmet(); + + if (type == DamageCause.DROWNING && wcfg.pumpkinScuba + && helmet != null + && (helmet.getTypeId() == BlockID.PUMPKIN + || helmet.getTypeId() == BlockID.JACKOLANTERN)) { + player.setRemainingAir(player.getMaximumAir()); + event.setCancelled(true); + return; + } + + if (wcfg.disableFallDamage && type == DamageCause.FALL) { + event.setCancelled(true); + return; + } + + if (wcfg.disableFireDamage && (type == DamageCause.FIRE + || type == DamageCause.FIRE_TICK)) { + event.setCancelled(true); + return; + } + + if (wcfg.disableDrowningDamage && type == DamageCause.DROWNING) { + player.setRemainingAir(player.getMaximumAir()); + event.setCancelled(true); + return; + } + + if (wcfg.teleportOnSuffocation && type == DamageCause.SUFFOCATION) { + BukkitUtil.findFreePosition(player); + event.setCancelled(true); + return; + } + + if (wcfg.disableSuffocationDamage && type == DamageCause.SUFFOCATION) { + event.setCancelled(true); + return; + } + } + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onEntityCombust(EntityCombustEvent event) { + Entity entity = event.getEntity(); + + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(entity.getWorld()); + + if (entity instanceof Player) { + Player player = (Player) entity; + + if (cfg.hasGodMode(player) || (wcfg.useRegions && RegionQueryUtil.isInvincible(plugin, player))) { + event.setCancelled(true); + return; + } + } + } + + /* + * Called on entity explode. + */ + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onEntityExplode(EntityExplodeEvent event) { + ConfigurationManager cfg = plugin.getGlobalStateManager(); + Location l = event.getLocation(); + World world = l.getWorld(); + WorldConfiguration wcfg = cfg.get(world); + Entity ent = event.getEntity(); + + if (cfg.activityHaltToggle) { + if (ent != null) { + ent.remove(); + } + event.setCancelled(true); + return; + } + + if (ent instanceof Creeper) { + if (wcfg.blockCreeperExplosions) { + event.setCancelled(true); + return; + } + if (wcfg.blockCreeperBlockDamage) { + event.blockList().clear(); + return; + } + + if (wcfg.useRegions) { + RegionManager mgr = plugin.getGlobalRegionManager().get(world); + + for (Block block : event.blockList()) { + if (!mgr.getApplicableRegions(toVector(block)).allows(DefaultFlag.CREEPER_EXPLOSION)) { + event.blockList().clear(); + if (wcfg.explosionFlagCancellation) event.setCancelled(true); + return; + } + } + } + } else if (ent instanceof EnderDragon) { + if (wcfg.blockEnderDragonBlockDamage) { + event.blockList().clear(); + return; + } + + if (wcfg.useRegions) { + RegionManager mgr = plugin.getGlobalRegionManager().get(world); + + for (Block block : event.blockList()) { + if (!mgr.getApplicableRegions(toVector(block)).allows(DefaultFlag.ENDERDRAGON_BLOCK_DAMAGE)) { + event.blockList().clear(); + if (wcfg.explosionFlagCancellation) event.setCancelled(true); + return; + } + } + } + } else if (ent instanceof TNTPrimed || ent instanceof ExplosiveMinecart) { + if (wcfg.blockTNTExplosions) { + event.setCancelled(true); + return; + } + if (wcfg.blockTNTBlockDamage) { + event.blockList().clear(); + return; + } + + if (wcfg.useRegions) { + RegionManager mgr = plugin.getGlobalRegionManager().get(world); + + for (Block block : event.blockList()) { + if (!mgr.getApplicableRegions(toVector(block)).allows(DefaultFlag.TNT)) { + event.blockList().clear(); + if (wcfg.explosionFlagCancellation) event.setCancelled(true); + return; + } + } + } + } else if (ent instanceof Fireball) { + if (ent instanceof WitherSkull) { + if (wcfg.blockWitherSkullExplosions) { + event.setCancelled(true); + return; + } + if (wcfg.blockWitherSkullBlockDamage) { + event.blockList().clear(); + return; + } + } else { + if (wcfg.blockFireballExplosions) { + event.setCancelled(true); + return; + } + if (wcfg.blockFireballBlockDamage) { + event.blockList().clear(); + return; + } + } + // allow wither skull blocking since there is no dedicated flag atm + if (wcfg.useRegions) { + RegionManager mgr = plugin.getGlobalRegionManager().get(world); + + for (Block block : event.blockList()) { + if (!mgr.getApplicableRegions(toVector(block)).allows(DefaultFlag.GHAST_FIREBALL)) { + event.blockList().clear(); + if (wcfg.explosionFlagCancellation) event.setCancelled(true); + return; + } + } + } + } else if (ent instanceof Wither) { + if (wcfg.blockWitherExplosions) { + event.setCancelled(true); + return; + } + if (wcfg.blockWitherBlockDamage) { + event.blockList().clear(); + return; + } + } else { + // unhandled entity + if (wcfg.blockOtherExplosions) { + event.setCancelled(true); + return; + } + if (wcfg.useRegions) { + RegionManager mgr = plugin.getGlobalRegionManager().get(world); + for (Block block : event.blockList()) { + if (!mgr.getApplicableRegions(toVector(block)).allows(DefaultFlag.OTHER_EXPLOSION)) { + event.blockList().clear(); + if (wcfg.explosionFlagCancellation) event.setCancelled(true); + return; + } + } + } + } + + + if (wcfg.signChestProtection) { + for (Block block : event.blockList()) { + if (wcfg.isChestProtected(block)) { + event.blockList().clear(); + return; + } + } + } + + } + + /* + * Called on explosion prime + */ + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onExplosionPrime(ExplosionPrimeEvent event) { + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(event.getEntity().getWorld()); + Entity ent = event.getEntity(); + + if (cfg.activityHaltToggle) { + ent.remove(); + event.setCancelled(true); + return; + } + + if (event.getEntityType() == EntityType.WITHER) { + if (wcfg.blockWitherExplosions) { + event.setCancelled(true); + return; + } + } else if (event.getEntityType() == EntityType.WITHER_SKULL) { + if (wcfg.blockWitherSkullExplosions) { + event.setCancelled(true); + return; + } + } else if (event.getEntityType() == EntityType.FIREBALL) { + if (wcfg.blockFireballExplosions) { + event.setCancelled(true); + return; + } + } else if (event.getEntityType() == EntityType.CREEPER) { + if (wcfg.blockCreeperExplosions) { + event.setCancelled(true); + return; + } + } else if (event.getEntityType() == EntityType.PRIMED_TNT + || event.getEntityType() == EntityType.MINECART_TNT) { + if (wcfg.blockTNTExplosions) { + event.setCancelled(true); + return; + } + } + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onCreatureSpawn(CreatureSpawnEvent event) { + ConfigurationManager cfg = plugin.getGlobalStateManager(); + + if (cfg.activityHaltToggle) { + event.setCancelled(true); + return; + } + + WorldConfiguration wcfg = cfg.get(event.getEntity().getWorld()); + + // allow spawning of creatures from plugins + if (!wcfg.blockPluginSpawning && event.getSpawnReason() == CreatureSpawnEvent.SpawnReason.CUSTOM) { + return; + } + + if (wcfg.allowTamedSpawns + && event.getEntity() instanceof Tameable // nullsafe check + && ((Tameable) event.getEntity()).isTamed()) { + return; + } + + EntityType entityType = event.getEntityType(); + + if (wcfg.blockCreatureSpawn.contains(entityType)) { + event.setCancelled(true); + return; + } + + Location eventLoc = event.getLocation(); + + if (wcfg.useRegions && cfg.useRegionsCreatureSpawnEvent) { + Vector pt = toVector(eventLoc); + RegionManager mgr = plugin.getGlobalRegionManager().get(eventLoc.getWorld()); + // @TODO get victims' stacktraces and find out why it's null anyway + if (mgr == null) return; + ApplicableRegionSet set = mgr.getApplicableRegions(pt); + + if (!set.allows(DefaultFlag.MOB_SPAWNING)) { + event.setCancelled(true); + return; + } + + Set entityTypes = set.getFlag(DefaultFlag.DENY_SPAWN); + if (entityTypes != null && entityTypes.contains(entityType)) { + event.setCancelled(true); + return; + } + } + + if (wcfg.blockGroundSlimes && entityType == EntityType.SLIME + && eventLoc.getY() >= 60 + && event.getSpawnReason() == SpawnReason.NATURAL) { + event.setCancelled(true); + return; + } + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onCreatePortal(EntityCreatePortalEvent event) { + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(event.getEntity().getWorld()); + + switch (event.getEntityType()) { + case ENDER_DRAGON: + if (wcfg.blockEnderDragonPortalCreation) event.setCancelled(true); + break; + } + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onPigZap(PigZapEvent event) { + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(event.getEntity().getWorld()); + + if (wcfg.disablePigZap) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onCreeperPower(CreeperPowerEvent event) { + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(event.getEntity().getWorld()); + + if (wcfg.disableCreeperPower) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onEntityRegainHealth(EntityRegainHealthEvent event) { + + Entity ent = event.getEntity(); + World world = ent.getWorld(); + + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(world); + + if (wcfg.disableHealthRegain) { + event.setCancelled(true); + return; + } + } + + /** + * Called when an entity changes a block somehow + * + * @param event Relevant event details + */ + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onEntityChangeBlock(EntityChangeBlockEvent event) { + Entity ent = event.getEntity(); + Block block = event.getBlock(); + Location location = block.getLocation(); + + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(ent.getWorld()); + if (ent instanceof Enderman) { + if (wcfg.disableEndermanGriefing) { + event.setCancelled(true); + return; + } + + if (wcfg.useRegions) { + if (!plugin.getGlobalRegionManager().allows(DefaultFlag.ENDER_BUILD, location)) { + event.setCancelled(true); + return; + } + } + } else if (ent.getType() == EntityType.WITHER) { + if (wcfg.blockWitherBlockDamage || wcfg.blockWitherExplosions) { + event.setCancelled(true); + return; + } + } else if (/*ent instanceof Zombie && */event instanceof EntityBreakDoorEvent) { + if (wcfg.blockZombieDoorDestruction) { + event.setCancelled(true); + return; + } + } + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onFoodLevelChange(FoodLevelChangeEvent event) { + if (event.getEntity() instanceof Player) { + Player player = (Player) event.getEntity(); + if (event.getFoodLevel() < player.getFoodLevel() && isInvincible(player)) { + event.setCancelled(true); + } + } + } + + @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 + * to override it. (worldguard.god.override-regions) + * + * @param player The player to check + * @return Whether {@code player} is invincible + */ + private boolean isInvincible(Player player) { + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(player.getWorld()); + + boolean god = cfg.hasGodMode(player); + if (wcfg.useRegions) { + Boolean flag = RegionQueryUtil.isAllowedInvinciblity(plugin, player); + boolean allowed = flag == null || flag; + boolean invincible = RegionQueryUtil.isInvincible(plugin, player); + + if (allowed) { + return god || invincible; + } else { + return (god && plugin.hasPermission(player, "worldguard.god.override-regions")) + || invincible; + } + } else { + return god; + } + } + + /** + * Using a DisallowedPVPEvent, notifies other plugins that WorldGuard + * wants to cancel a PvP damage event.
+ * If this event is not cancelled, the attacking player is notified that + * PvP is disabled and WorldGuard cancels the damage event. + * + * @param attackingPlayer The attacker + * @param defendingPlayer The defender + * @param event The event that caused WorldGuard to act + */ + public void tryCancelPVPEvent(final Player attackingPlayer, final Player defendingPlayer, EntityDamageByEntityEvent event, boolean aggressorTriggered) { + final DisallowedPVPEvent disallowedPVPEvent = new DisallowedPVPEvent(attackingPlayer, defendingPlayer, event); + plugin.getServer().getPluginManager().callEvent(disallowedPVPEvent); + if (!disallowedPVPEvent.isCancelled()) { + if (aggressorTriggered) attackingPlayer.sendMessage(ChatColor.DARK_RED + "You are in a no-PvP area."); + else attackingPlayer.sendMessage(ChatColor.DARK_RED + "That player is in a no-PvP area."); + event.setCancelled(true); + } + } + + /** + * Checks regions and config settings to protect items from being knocked + * out of item frames. + * @param attacker attacking entity + * @param defender item frame being damaged + * @return true if the event should be cancelled + */ + private boolean checkItemFrameProtection(Entity attacker, ItemFrame defender) { + World world = attacker.getWorld(); + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(world); + if (wcfg.useRegions) { + // bukkit throws this event when a player attempts to remove an item from a frame + RegionManager mgr = plugin.getGlobalRegionManager().get(world); + if (!(attacker instanceof Player)) { + if (!plugin.getGlobalRegionManager().allows( + DefaultFlag.ENTITY_ITEM_FRAME_DESTROY, defender.getLocation())) { + return true; + } + } + } + if (wcfg.blockEntityItemFrameDestroy && !(attacker instanceof Player)) { + return true; + } + return false; + } + +} diff --git a/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardHangingListener.java b/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardHangingListener.java new file mode 100644 index 00000000..8a767f09 --- /dev/null +++ b/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardHangingListener.java @@ -0,0 +1,122 @@ +/* + * 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.listener; + +import com.sk89q.worldguard.bukkit.ConfigurationManager; +import com.sk89q.worldguard.bukkit.WorldConfiguration; +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import com.sk89q.worldguard.protection.flags.DefaultFlag; +import org.bukkit.World; +import org.bukkit.entity.Creeper; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Hanging; +import org.bukkit.entity.ItemFrame; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Painting; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.hanging.HangingBreakByEntityEvent; +import org.bukkit.event.hanging.HangingBreakEvent; +import org.bukkit.event.hanging.HangingBreakEvent.RemoveCause; +import org.bukkit.projectiles.ProjectileSource; + +/** + * Listener for painting related events. + * + * @author BangL + */ +public class WorldGuardHangingListener implements Listener { + + private WorldGuardPlugin plugin; + + /** + * Construct the object; + * + * @param plugin The plugin instance + */ + public WorldGuardHangingListener(WorldGuardPlugin plugin) { + this.plugin = plugin; + } + + /** + * Register events. + */ + public void registerEvents() { + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onHangingBreak(HangingBreakEvent event) { + Hanging hanging = event.getEntity(); + World world = hanging.getWorld(); + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(world); + + if (event instanceof HangingBreakByEntityEvent) { + HangingBreakByEntityEvent entityEvent = (HangingBreakByEntityEvent) event; + Entity removerEntity = entityEvent.getRemover(); + if (removerEntity instanceof Projectile) { + Projectile projectile = (Projectile) removerEntity; + ProjectileSource remover = projectile.getShooter(); + removerEntity = (remover instanceof LivingEntity ? (LivingEntity) remover : null); + } + + if (!(removerEntity instanceof Player)) { + if (removerEntity instanceof Creeper) { + if (wcfg.blockCreeperBlockDamage || wcfg.blockCreeperExplosions) { + event.setCancelled(true); + return; + } + if (wcfg.useRegions && !plugin.getGlobalRegionManager().allows(DefaultFlag.CREEPER_EXPLOSION, hanging.getLocation())) { + event.setCancelled(true); + return; + } + } + + // this now covers dispensers as well, if removerEntity is null above, + // due to a non-LivingEntity ProjectileSource + if (hanging instanceof Painting + && (wcfg.blockEntityPaintingDestroy + || (wcfg.useRegions + && !plugin.getGlobalRegionManager().allows(DefaultFlag.ENTITY_PAINTING_DESTROY, hanging.getLocation())))) { + event.setCancelled(true); + } else if (hanging instanceof ItemFrame + && (wcfg.blockEntityItemFrameDestroy + || (wcfg.useRegions + && !plugin.getGlobalRegionManager().allows(DefaultFlag.ENTITY_ITEM_FRAME_DESTROY, hanging.getLocation())))) { + event.setCancelled(true); + } + } + } else { + // Explosions from mobs are not covered by HangingBreakByEntity + if (hanging instanceof Painting && wcfg.blockEntityPaintingDestroy + && event.getCause() == RemoveCause.EXPLOSION) { + event.setCancelled(true); + } else if (hanging instanceof ItemFrame && wcfg.blockEntityItemFrameDestroy + && event.getCause() == RemoveCause.EXPLOSION) { + event.setCancelled(true); + } + } + } + +} diff --git a/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardPlayerListener.java b/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardPlayerListener.java new file mode 100644 index 00000000..6b4ce0eb --- /dev/null +++ b/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardPlayerListener.java @@ -0,0 +1,733 @@ +/* + * 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.listener; + +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.blocks.BlockID; +import com.sk89q.worldguard.LocalPlayer; +import com.sk89q.worldguard.blacklist.event.ItemUseBlacklistEvent; +import com.sk89q.worldguard.bukkit.BukkitUtil; +import com.sk89q.worldguard.bukkit.ConfigurationManager; +import com.sk89q.worldguard.bukkit.FlagStateManager.PlayerFlagState; +import com.sk89q.worldguard.bukkit.WorldConfiguration; +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import com.sk89q.worldguard.protection.ApplicableRegionSet; +import com.sk89q.worldguard.protection.flags.DefaultFlag; +import com.sk89q.worldguard.protection.managers.RegionManager; +import com.sk89q.worldguard.protection.regions.ProtectedRegion; +import com.sk89q.worldguard.util.command.CommandFilter; +import org.bukkit.ChatColor; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.PlayerBedEnterEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerFishEvent; +import org.bukkit.event.player.PlayerGameModeChangeEvent; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerItemHeldEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerLoginEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.player.PlayerRespawnEvent; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.PluginManager; + +import java.util.Iterator; +import java.util.Set; +import java.util.logging.Level; +import java.util.regex.Pattern; + +import static com.sk89q.worldguard.bukkit.BukkitUtil.createTarget; +import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector; + +/** + * Handles all events thrown in relation to a player. + */ +public class WorldGuardPlayerListener implements Listener { + + private Pattern opPattern = Pattern.compile("^/op(?:\\s.*)?$", Pattern.CASE_INSENSITIVE); + private WorldGuardPlugin plugin; + + /** + * Construct the object; + * + * @param plugin + */ + public WorldGuardPlayerListener(WorldGuardPlugin plugin) { + this.plugin = plugin; + } + + /** + * Register events. + */ + public void registerEvents() { + final PluginManager pm = plugin.getServer().getPluginManager(); + pm.registerEvents(this, plugin); + + if (plugin.getGlobalStateManager().usePlayerMove) { + pm.registerEvents(new PlayerMoveHandler(), plugin); + } + } + + // unsure if anyone actually started using this yet, but just in case... + @Deprecated + public static boolean checkMove(WorldGuardPlugin plugin, Player player, World world, Location from, Location to) { + return checkMove(plugin, player, from, to); // drop world since it used to be mishandled + } + + /** + * Handles movement related events, including changing gamemode, sending + * greeting/farewell messages, etc. + * A reference to WorldGuardPlugin is required to keep this method static + * although WGBukkit.getPlugin() may be used. + * @return true if the movement should not be allowed + */ + public static boolean checkMove(WorldGuardPlugin plugin, Player player, Location from, Location to) { + PlayerFlagState state = plugin.getFlagStateManager().getState(player); + + //Flush states in multiworld scenario + if (state.lastWorld != null && !state.lastWorld.equals(to.getWorld())) { + plugin.getFlagStateManager().forget(player); + state = plugin.getFlagStateManager().getState(player); + } + + World world = from.getWorld(); + World toWorld = to.getWorld(); + + LocalPlayer localPlayer = plugin.wrapPlayer(player); + boolean hasBypass = plugin.getGlobalRegionManager().hasBypass(player, world); + boolean hasRemoteBypass; + if (world.equals(toWorld)) { + hasRemoteBypass = hasBypass; + } else { + hasRemoteBypass = plugin.getGlobalRegionManager().hasBypass(player, toWorld); + } + + RegionManager mgr = plugin.getGlobalRegionManager().get(toWorld); + Vector pt = new Vector(to.getBlockX(), to.getBlockY(), to.getBlockZ()); + ApplicableRegionSet set = mgr.getApplicableRegions(pt); + + /* + // check if region is full + // get the lowest number of allowed members in any region + boolean regionFull = false; + String maxPlayerMessage = null; + if (!hasBypass) { + for (ProtectedRegion region : set) { + if (region instanceof GlobalProtectedRegion) { + continue; // global region can't have a max + } + // get the max for just this region + Integer maxPlayers = region.getFlag(DefaultFlag.MAX_PLAYERS); + if (maxPlayers == null) { + continue; + } + int occupantCount = 0; + for(Player occupant : world.getPlayers()) { + // each player in this region counts as one toward the max of just this region + // A person with bypass doesn't count as an occupant of the region + if (!occupant.equals(player) && !plugin.getGlobalRegionManager().hasBypass(occupant, world)) { + if (region.contains(BukkitUtil.toVector(occupant.getLocation()))) { + if (++occupantCount >= maxPlayers) { + regionFull = true; + maxPlayerMessage = region.getFlag(DefaultFlag.MAX_PLAYERS_MESSAGE); + // At least one region in the set is full, we are going to use this message because it + // was the first one we detected as full. In reality we should check them all and then + // resolve the message from full regions, but that is probably a lot laggier (and this + // is already pretty laggy. In practice, we can't really control which one we get first + // right here. + break; + } + } + } + } + } + } + */ + + boolean entryAllowed = set.allows(DefaultFlag.ENTRY, localPlayer); + if (!hasRemoteBypass && (!entryAllowed /*|| regionFull*/)) { + String message = /*maxPlayerMessage != null ? maxPlayerMessage :*/ "You are not permitted to enter this area."; + + player.sendMessage(ChatColor.DARK_RED + message); + return true; + } + + // Have to set this state + if (state.lastExitAllowed == null) { + state.lastExitAllowed = plugin.getGlobalRegionManager().get(world) + .getApplicableRegions(toVector(from)) + .allows(DefaultFlag.EXIT, localPlayer); + } + + boolean exitAllowed = set.allows(DefaultFlag.EXIT, localPlayer); + if (!hasBypass && exitAllowed && !state.lastExitAllowed) { + player.sendMessage(ChatColor.DARK_RED + "You are not permitted to leave this area."); + return true; + } + +// WorldGuardRegionMoveEvent event = new WorldGuardRegionMoveEvent(plugin, player, state, set, from, to); +// Bukkit.getPluginManager().callEvent(event); + + String greeting = set.getFlag(DefaultFlag.GREET_MESSAGE);//, localPlayer); + String farewell = set.getFlag(DefaultFlag.FAREWELL_MESSAGE);//, localPlayer); + Boolean notifyEnter = set.getFlag(DefaultFlag.NOTIFY_ENTER);//, localPlayer); + Boolean notifyLeave = set.getFlag(DefaultFlag.NOTIFY_LEAVE);//, localPlayer); + GameMode gameMode = set.getFlag(DefaultFlag.GAME_MODE); + + if (state.lastFarewell != null && (farewell == null + || !state.lastFarewell.equals(farewell))) { + String replacedFarewell = plugin.replaceMacros( + player, BukkitUtil.replaceColorMacros(state.lastFarewell)); + player.sendMessage(replacedFarewell.replaceAll("\\\\n", "\n").split("\\n")); + } + + if (greeting != null && (state.lastGreeting == null + || !state.lastGreeting.equals(greeting))) { + String replacedGreeting = plugin.replaceMacros( + player, BukkitUtil.replaceColorMacros(greeting)); + player.sendMessage(replacedGreeting.replaceAll("\\\\n", "\n").split("\\n")); + } + + if ((notifyLeave == null || !notifyLeave) + && state.notifiedForLeave != null && state.notifiedForLeave) { + plugin.broadcastNotification(ChatColor.GRAY + "WG: " + + ChatColor.LIGHT_PURPLE + player.getName() + + ChatColor.GOLD + " left NOTIFY region"); + } + + if (notifyEnter != null && notifyEnter && (state.notifiedForEnter == null + || !state.notifiedForEnter)) { + StringBuilder regionList = new StringBuilder(); + + for (ProtectedRegion region : set) { + if (regionList.length() != 0) { + regionList.append(", "); + } + regionList.append(region.getId()); + } + + plugin.broadcastNotification(ChatColor.GRAY + "WG: " + + ChatColor.LIGHT_PURPLE + player.getName() + + ChatColor.GOLD + " entered NOTIFY region: " + + ChatColor.WHITE + + regionList); + } + + if (!hasBypass && gameMode != null) { + if (player.getGameMode() != gameMode) { + state.lastGameMode = player.getGameMode(); + player.setGameMode(gameMode); + } else if (state.lastGameMode == null) { + state.lastGameMode = player.getServer().getDefaultGameMode(); + } + } else { + if (state.lastGameMode != null) { + GameMode mode = state.lastGameMode; + state.lastGameMode = null; + player.setGameMode(mode); + } + } + + state.lastGreeting = greeting; + state.lastFarewell = farewell; + state.notifiedForEnter = notifyEnter; + state.notifiedForLeave = notifyLeave; + state.lastExitAllowed = exitAllowed; + state.lastWorld = to.getWorld(); + state.lastBlockX = to.getBlockX(); + state.lastBlockY = to.getBlockY(); + state.lastBlockZ = to.getBlockZ(); + return false; + } + + class PlayerMoveHandler implements Listener { + @EventHandler(priority = EventPriority.HIGH) + public void onPlayerMove(PlayerMoveEvent event) { + Player player = event.getPlayer(); + World world = player.getWorld(); + + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(world); + + if (player.getVehicle() != null) { + return; // handled in vehicle listener + } + if (wcfg.useRegions) { + // Did we move a block? + if (event.getFrom().getBlockX() != event.getTo().getBlockX() + || event.getFrom().getBlockY() != event.getTo().getBlockY() + || event.getFrom().getBlockZ() != event.getTo().getBlockZ()) { + boolean result = checkMove(plugin, player, event.getFrom(), event.getTo()); + if (result) { + Location newLoc = event.getFrom(); + newLoc.setX(newLoc.getBlockX() + 0.5); + newLoc.setY(newLoc.getBlockY()); + newLoc.setZ(newLoc.getBlockZ() + 0.5); + event.setTo(newLoc); + } + } + } + } + } + + @EventHandler + public void onPlayerGameModeChange(PlayerGameModeChangeEvent event) { + Player player = event.getPlayer(); + WorldConfiguration wcfg = plugin.getGlobalStateManager().get(player.getWorld()); + if (wcfg.useRegions && !plugin.getGlobalRegionManager().hasBypass(player, player.getWorld())) { + GameMode gameMode = plugin.getGlobalRegionManager().get(player.getWorld()) + .getApplicableRegions(player.getLocation()).getFlag(DefaultFlag.GAME_MODE); + if (plugin.getFlagStateManager().getState(player).lastGameMode != null + && gameMode != null && event.getNewGameMode() != gameMode) { + event.setCancelled(true); + } + } + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + Player player = event.getPlayer(); + World world = player.getWorld(); + + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(world); + + if (cfg.activityHaltToggle) { + player.sendMessage(ChatColor.YELLOW + + "Intensive server activity has been HALTED."); + + int removed = 0; + + for (Entity entity : world.getEntities()) { + if (BukkitUtil.isIntensiveEntity(entity)) { + entity.remove(); + removed++; + } + } + + if (removed > 10) { + plugin.getLogger().info("Halt-Act: " + removed + " entities (>10) auto-removed from " + + player.getWorld().toString()); + } + } + + if (wcfg.fireSpreadDisableToggle) { + player.sendMessage(ChatColor.YELLOW + + "Fire spread is currently globally disabled for this world."); + } + + if (!cfg.hasCommandBookGodMode() && cfg.autoGodMode && (plugin.inGroup(player, "wg-invincible") + || plugin.hasPermission(player, "worldguard.auto-invincible"))) { + plugin.getLogger().log(Level.INFO, "Enabled auto-god mode for " + player.getName()); + cfg.enableGodMode(player); + } + + if (plugin.inGroup(player, "wg-amphibious")) { + plugin.getLogger().log(Level.INFO, "Enabled no-drowning mode for " + player.getName() + " (player is in group 'wg-amphibious')"); + cfg.enableAmphibiousMode(player); + } + + if (wcfg.useRegions) { + PlayerFlagState state = plugin.getFlagStateManager().getState(player); + Location loc = player.getLocation(); + state.lastWorld = loc.getWorld(); + state.lastBlockX = loc.getBlockX(); + state.lastBlockY = loc.getBlockY(); + state.lastBlockZ = loc.getBlockZ(); + } + } + + @EventHandler(ignoreCancelled = true) + public void onPlayerChat(AsyncPlayerChatEvent event) { + Player player = event.getPlayer(); + WorldConfiguration wcfg = plugin.getGlobalStateManager().get(player.getWorld()); + if (wcfg.useRegions) { + if (!plugin.getGlobalRegionManager().allows(DefaultFlag.SEND_CHAT, player.getLocation())) { + player.sendMessage(ChatColor.RED + "You don't have permission to chat in this region!"); + event.setCancelled(true); + return; + } + + for (Iterator i = event.getRecipients().iterator(); i.hasNext();) { + if (!plugin.getGlobalRegionManager().allows(DefaultFlag.RECEIVE_CHAT, i.next().getLocation())) { + i.remove(); + } + } + if (event.getRecipients().size() == 0) { + event.setCancelled(true); + } + } + } + + @EventHandler(ignoreCancelled = true) + public void onPlayerLogin(PlayerLoginEvent event) { + Player player = event.getPlayer(); + ConfigurationManager cfg = plugin.getGlobalStateManager(); + + String hostKey = cfg.hostKeys.get(player.getName().toLowerCase()); + if (hostKey != null) { + String hostname = event.getHostname(); + int colonIndex = hostname.indexOf(':'); + if (colonIndex != -1) { + hostname = hostname.substring(0, colonIndex); + } + + if (!hostname.equals(hostKey)) { + event.disallow(PlayerLoginEvent.Result.KICK_OTHER, + "You did not join with the valid host key!"); + plugin.getLogger().warning("WorldGuard host key check: " + + player.getName() + " joined with '" + hostname + + "' but '" + hostKey + "' was expected. Kicked!"); + return; + } + } + + if (cfg.deopOnJoin) { + player.setOp(false); + } + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) { + Player player = event.getPlayer(); + World world = player.getWorld(); + + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(world); + + // This is to make the enter/exit flags accurate -- move events are not + // sent constantly, so it is possible to move just a little enough to + // not trigger the event and then rejoin so that you are then considered + // outside the border. This should work around that. + if (wcfg.useRegions) { + boolean hasBypass = plugin.getGlobalRegionManager().hasBypass(player, world); + PlayerFlagState state = plugin.getFlagStateManager().getState(player); + + if (state.lastWorld != null && !hasBypass) { + LocalPlayer localPlayer = plugin.wrapPlayer(player); + RegionManager mgr = plugin.getGlobalRegionManager().get(world); + Location loc = player.getLocation(); + Vector pt = new Vector(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + ApplicableRegionSet set = mgr.getApplicableRegions(pt); + + if (state.lastExitAllowed == null) { + state.lastExitAllowed = set.allows(DefaultFlag.EXIT, localPlayer); + } + + if (!state.lastExitAllowed || !set.allows(DefaultFlag.ENTRY, localPlayer)) { + // Only if we have the last location cached + if (state.lastWorld.equals(world)) { + Location newLoc = new Location(world, state.lastBlockX + 0.5, + state.lastBlockY, state.lastBlockZ + 0.5); + player.teleport(newLoc); + } + } + } + } + + cfg.forgetPlayer(plugin.wrapPlayer(player)); + plugin.forgetPlayer(player); + } + + @EventHandler(priority = EventPriority.HIGH) + public void onPlayerInteract(PlayerInteractEvent event) { + Player player = event.getPlayer(); + World world = player.getWorld(); + + if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { + handleBlockRightClick(event); + } else if (event.getAction() == Action.PHYSICAL) { + handlePhysicalInteract(event); + } + + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(world); + + if (wcfg.removeInfiniteStacks + && !plugin.hasPermission(player, "worldguard.override.infinite-stack")) { + int slot = player.getInventory().getHeldItemSlot(); + ItemStack heldItem = player.getInventory().getItem(slot); + if (heldItem != null && heldItem.getAmount() < 0) { + player.getInventory().setItem(slot, null); + player.sendMessage(ChatColor.RED + "Infinite stack removed."); + } + } + } + + /** + * Called when a player right clicks a block. + * + * @param event Thrown event + */ + private void handleBlockRightClick(PlayerInteractEvent event) { + if (event.isCancelled()) { + return; + } + + Block block = event.getClickedBlock(); + World world = block.getWorld(); + int type = block.getTypeId(); + Player player = event.getPlayer(); + ItemStack item = player.getItemInHand(); + + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(world); + + // Infinite stack removal + if ((type == BlockID.CHEST + || type == BlockID.JUKEBOX + || type == BlockID.DISPENSER + || type == BlockID.FURNACE + || type == BlockID.BURNING_FURNACE + || type == BlockID.BREWING_STAND + || type == BlockID.ENCHANTMENT_TABLE) + && wcfg.removeInfiniteStacks + && !plugin.hasPermission(player, "worldguard.override.infinite-stack")) { + for (int slot = 0; slot < 40; slot++) { + ItemStack heldItem = player.getInventory().getItem(slot); + if (heldItem != null && heldItem.getAmount() < 0) { + player.getInventory().setItem(slot, null); + player.sendMessage(ChatColor.RED + "Infinite stack in slot #" + slot + " removed."); + } + } + } + + if (wcfg.useRegions) { + Vector pt = toVector(block); + RegionManager mgr = plugin.getGlobalRegionManager().get(world); + Block placedIn = block.getRelative(event.getBlockFace()); + ApplicableRegionSet set = mgr.getApplicableRegions(pt); + ApplicableRegionSet placedInSet = mgr.getApplicableRegions(placedIn.getLocation()); + LocalPlayer localPlayer = plugin.wrapPlayer(player); + + if (item.getTypeId() == wcfg.regionWand && plugin.hasPermission(player, "worldguard.region.wand")) { + if (set.size() > 0) { + player.sendMessage(ChatColor.YELLOW + "Can you build? " + + (set.canBuild(localPlayer) ? "Yes" : "No")); + + StringBuilder str = new StringBuilder(); + for (Iterator it = set.iterator(); it.hasNext();) { + str.append(it.next().getId()); + if (it.hasNext()) { + str.append(", "); + } + } + + player.sendMessage(ChatColor.YELLOW + "Applicable regions: " + str.toString()); + } else { + player.sendMessage(ChatColor.YELLOW + "WorldGuard: No defined regions here!"); + } + + event.setCancelled(true); + } + } + } + + /** + * Called when a player steps on a pressure plate or tramples crops. + * + * @param event Thrown event + */ + private void handlePhysicalInteract(PlayerInteractEvent event) { + if (event.isCancelled()) return; + + Player player = event.getPlayer(); + Block block = event.getClickedBlock(); //not actually clicked but whatever + int type = block.getTypeId(); + World world = player.getWorld(); + + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(world); + + if (block.getTypeId() == BlockID.SOIL && wcfg.disablePlayerCropTrampling) { + event.setCancelled(true); + return; + } + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onPlayerDropItem(PlayerDropItemEvent event) { + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(event.getPlayer().getWorld()); + Player player = event.getPlayer(); + + if (wcfg.useRegions) { + if (!plugin.getGlobalRegionManager().hasBypass(player, player.getWorld()) + && !plugin.getGlobalRegionManager().allows(DefaultFlag.ITEM_DROP, player.getLocation())) { + event.setCancelled(true); + player.sendMessage(ChatColor.RED + "You don't have permission to do that in this area."); + } + } + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onPlayerFish(PlayerFishEvent event) { + WorldConfiguration wcfg = plugin.getGlobalStateManager().get(event.getPlayer().getWorld()); + + if (wcfg.disableExpDrops || !plugin.getGlobalRegionManager().allows(DefaultFlag.EXP_DROPS, + event.getPlayer().getLocation())) { + event.setExpToDrop(0); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerRespawn(PlayerRespawnEvent event) { + Player player = event.getPlayer(); + Location location = player.getLocation(); + + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(player.getWorld()); + + if (wcfg.useRegions) { + Vector pt = toVector(location); + RegionManager mgr = plugin.getGlobalRegionManager().get(player.getWorld()); + ApplicableRegionSet set = mgr.getApplicableRegions(pt); + + LocalPlayer localPlayer = plugin.wrapPlayer(player); + com.sk89q.worldedit.Location spawn = set.getFlag(DefaultFlag.SPAWN_LOC, localPlayer); + + if (spawn != null) { + event.setRespawnLocation(com.sk89q.worldedit.bukkit.BukkitUtil.toLocation(spawn)); + } + } + } + + @EventHandler(priority = EventPriority.HIGH) + public void onItemHeldChange(PlayerItemHeldEvent event) { + Player player = event.getPlayer(); + + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(player.getWorld()); + + if (wcfg.removeInfiniteStacks + && !plugin.hasPermission(player, "worldguard.override.infinite-stack")) { + int newSlot = event.getNewSlot(); + ItemStack heldItem = player.getInventory().getItem(newSlot); + if (heldItem != null && heldItem.getAmount() < 0) { + player.getInventory().setItem(newSlot, null); + player.sendMessage(ChatColor.RED + "Infinite stack removed."); + } + } + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onPlayerBedEnter(PlayerBedEnterEvent event) { + Player player = event.getPlayer(); + Location location = player.getLocation(); + + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(player.getWorld()); + + if (wcfg.useRegions) { + Vector pt = toVector(location); + RegionManager mgr = plugin.getGlobalRegionManager().get(player.getWorld()); + ApplicableRegionSet set = mgr.getApplicableRegions(pt); + + if (!plugin.getGlobalRegionManager().hasBypass(player, player.getWorld()) + && !set.allows(DefaultFlag.SLEEP, plugin.wrapPlayer(player))) { + event.setCancelled(true); + player.sendMessage("This bed doesn't belong to you!"); + return; + } + } + } + + @EventHandler(priority= EventPriority.LOW, ignoreCancelled = true) + public void onPlayerTeleport(PlayerTeleportEvent event) { + World world = event.getFrom().getWorld(); + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(world); + + if (wcfg.useRegions) { + RegionManager mgr = plugin.getGlobalRegionManager().get(event.getFrom().getWorld()); + Vector pt = new Vector(event.getTo().getBlockX(), event.getTo().getBlockY(), event.getTo().getBlockZ()); + Vector ptFrom = new Vector(event.getFrom().getBlockX(), event.getFrom().getBlockY(), event.getFrom().getBlockZ()); + ApplicableRegionSet set = mgr.getApplicableRegions(pt); + ApplicableRegionSet setFrom = mgr.getApplicableRegions(ptFrom); + LocalPlayer localPlayer = plugin.wrapPlayer(event.getPlayer()); + + if (cfg.usePlayerTeleports) { + boolean result = checkMove(plugin, event.getPlayer(), event.getFrom(), event.getTo()); + if (result) { + event.setCancelled(true); + return; + } + } + + if (event.getCause() == TeleportCause.ENDER_PEARL) { + if (!plugin.getGlobalRegionManager().hasBypass(localPlayer, world) + && !(set.allows(DefaultFlag.ENDERPEARL, localPlayer) + && setFrom.allows(DefaultFlag.ENDERPEARL, localPlayer))) { + event.getPlayer().sendMessage(ChatColor.DARK_RED + "You're not allowed to go there."); + event.setCancelled(true); + return; + } + } + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { + Player player = event.getPlayer(); + LocalPlayer localPlayer = plugin.wrapPlayer(player); + World world = player.getWorld(); + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(world); + + if (wcfg.useRegions && !plugin.getGlobalRegionManager().hasBypass(player, world)) { + Vector pt = toVector(player.getLocation()); + RegionManager mgr = plugin.getGlobalRegionManager().get(world); + ApplicableRegionSet set = mgr.getApplicableRegions(pt); + + Set allowedCommands = set.getFlag(DefaultFlag.ALLOWED_CMDS, localPlayer); + Set blockedCommands = set.getFlag(DefaultFlag.BLOCKED_CMDS, localPlayer); + CommandFilter test = new CommandFilter(allowedCommands, blockedCommands); + + if (!test.apply(event.getMessage())) { + player.sendMessage(ChatColor.RED + event.getMessage() + " is not allowed in this area."); + event.setCancelled(true); + return; + } + } + + if (cfg.blockInGameOp) { + if (opPattern.matcher(event.getMessage()).matches()) { + player.sendMessage(ChatColor.RED + "/op can only be used in console (as set by a WG setting)."); + event.setCancelled(true); + return; + } + } + } +} diff --git a/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardServerListener.java b/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardServerListener.java similarity index 95% rename from src/main/java/com/sk89q/worldguard/bukkit/WorldGuardServerListener.java rename to src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardServerListener.java index 6ab068bb..2d3b049b 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardServerListener.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardServerListener.java @@ -17,8 +17,9 @@ * along with this program. If not, see . */ -package com.sk89q.worldguard.bukkit; +package com.sk89q.worldguard.bukkit.listener; +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.server.PluginDisableEvent; diff --git a/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardVehicleListener.java b/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardVehicleListener.java similarity index 59% rename from src/main/java/com/sk89q/worldguard/bukkit/WorldGuardVehicleListener.java rename to src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardVehicleListener.java index 2f95575a..8d5b1b6a 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardVehicleListener.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardVehicleListener.java @@ -1,110 +1,75 @@ -/* - * 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; - -import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector; - -import org.bukkit.ChatColor; -import org.bukkit.World; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.entity.Vehicle; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.vehicle.VehicleDestroyEvent; -import org.bukkit.event.vehicle.VehicleMoveEvent; -import com.sk89q.worldedit.Vector; -import com.sk89q.worldguard.LocalPlayer; -import com.sk89q.worldguard.protection.ApplicableRegionSet; -import com.sk89q.worldguard.protection.flags.DefaultFlag; -import com.sk89q.worldguard.protection.managers.RegionManager; - -public class WorldGuardVehicleListener implements Listener { - - private WorldGuardPlugin plugin; - - /** - * Construct the object; - * - * @param plugin - */ - public WorldGuardVehicleListener(WorldGuardPlugin plugin) { - this.plugin = plugin; - } - - /** - * Register events. - */ - public void registerEvents() { - plugin.getServer().getPluginManager().registerEvents(this, plugin); - } - - @EventHandler - public void onVehicleDestroy(VehicleDestroyEvent event) { - Vehicle vehicle = event.getVehicle(); - Entity destroyer = event.getAttacker(); - - if (!(destroyer instanceof Player)) return; // don't care - Player player = (Player) destroyer; - World world = vehicle.getWorld(); - - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - - if (wcfg.useRegions) { - Vector pt = toVector(vehicle.getLocation()); - RegionManager mgr = plugin.getGlobalRegionManager().get(world); - ApplicableRegionSet set = mgr.getApplicableRegions(pt); - LocalPlayer localPlayer = plugin.wrapPlayer(player); - - if (!plugin.getGlobalRegionManager().hasBypass(player, world) - && !set.canBuild(localPlayer) - && !set.allows(DefaultFlag.DESTROY_VEHICLE, localPlayer)) { - player.sendMessage(ChatColor.DARK_RED + "You don't have permission to destroy vehicles here."); - event.setCancelled(true); - return; - } - } - } - - @EventHandler - public void onVehicleMove(VehicleMoveEvent event) { - Vehicle vehicle = event.getVehicle(); - if (vehicle.getPassenger() == null - || !(vehicle.getPassenger() instanceof Player)) return; - Player player = (Player) vehicle.getPassenger(); - World world = vehicle.getWorld(); - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - - if (wcfg.useRegions) { - // Did we move a block? - if (event.getFrom().getBlockX() != event.getTo().getBlockX() - || event.getFrom().getBlockY() != event.getTo().getBlockY() - || event.getFrom().getBlockZ() != event.getTo().getBlockZ()) { - boolean result = WorldGuardPlayerListener.checkMove(plugin, player, event.getFrom(), event.getTo()); - if (result) { - vehicle.setVelocity(new org.bukkit.util.Vector(0,0,0)); - vehicle.teleport(event.getFrom()); - } - } - } - } -} +/* + * 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.listener; + +import com.sk89q.worldguard.bukkit.ConfigurationManager; +import com.sk89q.worldguard.bukkit.WorldConfiguration; +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.entity.Vehicle; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.vehicle.VehicleMoveEvent; + +public class WorldGuardVehicleListener implements Listener { + + private WorldGuardPlugin plugin; + + /** + * Construct the object; + * + * @param plugin + */ + public WorldGuardVehicleListener(WorldGuardPlugin plugin) { + this.plugin = plugin; + } + + /** + * Register events. + */ + public void registerEvents() { + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + @EventHandler + public void onVehicleMove(VehicleMoveEvent event) { + Vehicle vehicle = event.getVehicle(); + if (vehicle.getPassenger() == null + || !(vehicle.getPassenger() instanceof Player)) return; + Player player = (Player) vehicle.getPassenger(); + World world = vehicle.getWorld(); + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(world); + + if (wcfg.useRegions) { + // Did we move a block? + if (event.getFrom().getBlockX() != event.getTo().getBlockX() + || event.getFrom().getBlockY() != event.getTo().getBlockY() + || event.getFrom().getBlockZ() != event.getTo().getBlockZ()) { + boolean result = WorldGuardPlayerListener.checkMove(plugin, player, event.getFrom(), event.getTo()); + if (result) { + vehicle.setVelocity(new org.bukkit.util.Vector(0,0,0)); + vehicle.teleport(event.getFrom()); + } + } + } + } +} diff --git a/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardWeatherListener.java b/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardWeatherListener.java similarity index 94% rename from src/main/java/com/sk89q/worldguard/bukkit/WorldGuardWeatherListener.java rename to src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardWeatherListener.java index a3019a96..7fc1578e 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardWeatherListener.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardWeatherListener.java @@ -1,111 +1,114 @@ -/* - * 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; - -import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector; - -import org.bukkit.Location; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.weather.LightningStrikeEvent; -import org.bukkit.event.weather.ThunderChangeEvent; -import org.bukkit.event.weather.WeatherChangeEvent; -import com.sk89q.worldedit.Vector; -import com.sk89q.worldguard.protection.ApplicableRegionSet; -import com.sk89q.worldguard.protection.flags.DefaultFlag; -import com.sk89q.worldguard.protection.managers.RegionManager; - -public class WorldGuardWeatherListener implements Listener { - - /** - * Plugin. - */ - private WorldGuardPlugin plugin; - - /** - * Construct the object; - * - * @param plugin The plugin instance - */ - public WorldGuardWeatherListener(WorldGuardPlugin plugin) { - this.plugin = plugin; - } - - public void registerEvents() { - plugin.getServer().getPluginManager().registerEvents(this, plugin); - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onWeatherChange(WeatherChangeEvent event) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(event.getWorld()); - - if (event.toWeatherState()) { - if (wcfg.disableWeather) { - event.setCancelled(true); - } - } else { - if (!wcfg.disableWeather && wcfg.alwaysRaining) { - event.setCancelled(true); - } - } - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onThunderChange(ThunderChangeEvent event) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(event.getWorld()); - - if (event.toThunderState()) { - if (wcfg.disableThunder) { - event.setCancelled(true); - } - } else { - if (!wcfg.disableWeather && wcfg.alwaysThundering) { - event.setCancelled(true); - } - } - } - - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onLightningStrike(LightningStrikeEvent event) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(event.getWorld()); - - if (wcfg.disallowedLightningBlocks.size() > 0) { - int targetId = event.getLightning().getLocation().getBlock().getTypeId(); - if (wcfg.disallowedLightningBlocks.contains(targetId)) { - event.setCancelled(true); - } - } - - Location loc = event.getLightning().getLocation(); - if (wcfg.useRegions) { - Vector pt = toVector(loc); - RegionManager mgr = plugin.getGlobalRegionManager().get(loc.getWorld()); - ApplicableRegionSet set = mgr.getApplicableRegions(pt); - - if (!set.allows(DefaultFlag.LIGHTNING)) { - event.setCancelled(true); - } - } - } -} +/* + * 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.listener; + +import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector; + +import com.sk89q.worldguard.bukkit.ConfigurationManager; +import com.sk89q.worldguard.bukkit.WorldConfiguration; +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import org.bukkit.Location; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.weather.LightningStrikeEvent; +import org.bukkit.event.weather.ThunderChangeEvent; +import org.bukkit.event.weather.WeatherChangeEvent; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldguard.protection.ApplicableRegionSet; +import com.sk89q.worldguard.protection.flags.DefaultFlag; +import com.sk89q.worldguard.protection.managers.RegionManager; + +public class WorldGuardWeatherListener implements Listener { + + /** + * Plugin. + */ + private WorldGuardPlugin plugin; + + /** + * Construct the object; + * + * @param plugin The plugin instance + */ + public WorldGuardWeatherListener(WorldGuardPlugin plugin) { + this.plugin = plugin; + } + + public void registerEvents() { + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onWeatherChange(WeatherChangeEvent event) { + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(event.getWorld()); + + if (event.toWeatherState()) { + if (wcfg.disableWeather) { + event.setCancelled(true); + } + } else { + if (!wcfg.disableWeather && wcfg.alwaysRaining) { + event.setCancelled(true); + } + } + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onThunderChange(ThunderChangeEvent event) { + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(event.getWorld()); + + if (event.toThunderState()) { + if (wcfg.disableThunder) { + event.setCancelled(true); + } + } else { + if (!wcfg.disableWeather && wcfg.alwaysThundering) { + event.setCancelled(true); + } + } + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onLightningStrike(LightningStrikeEvent event) { + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(event.getWorld()); + + if (wcfg.disallowedLightningBlocks.size() > 0) { + int targetId = event.getLightning().getLocation().getBlock().getTypeId(); + if (wcfg.disallowedLightningBlocks.contains(targetId)) { + event.setCancelled(true); + } + } + + Location loc = event.getLightning().getLocation(); + if (wcfg.useRegions) { + Vector pt = toVector(loc); + RegionManager mgr = plugin.getGlobalRegionManager().get(loc.getWorld()); + ApplicableRegionSet set = mgr.getApplicableRegions(pt); + + if (!set.allows(DefaultFlag.LIGHTNING)) { + event.setCancelled(true); + } + } + } +} diff --git a/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardWorldListener.java b/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardWorldListener.java similarity index 92% rename from src/main/java/com/sk89q/worldguard/bukkit/WorldGuardWorldListener.java rename to src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardWorldListener.java index 9b94ede4..89a498c7 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardWorldListener.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/listener/WorldGuardWorldListener.java @@ -1,97 +1,101 @@ -/* - * 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; - -import org.bukkit.World; -import org.bukkit.entity.Entity; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.world.ChunkLoadEvent; -import org.bukkit.event.world.WorldLoadEvent; - -public class WorldGuardWorldListener implements Listener { - - private WorldGuardPlugin plugin; - - /** - * Construct the object; - * - * @param plugin The plugin instance - */ - public WorldGuardWorldListener(WorldGuardPlugin plugin) { - this.plugin = plugin; - } - - /** - * Register events. - */ - public void registerEvents() { - plugin.getServer().getPluginManager().registerEvents(this, plugin); - } - - @EventHandler - public void onChunkLoad(ChunkLoadEvent event) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - - if (cfg.activityHaltToggle) { - int removed = 0; - - for (Entity entity : event.getChunk().getEntities()) { - if (BukkitUtil.isIntensiveEntity(entity)) { - entity.remove(); - removed++; - } - } - - if (removed > 50) { - plugin.getLogger().info("Halt-Act: " + removed + " entities (>50) auto-removed from " - + event.getChunk().toString()); - } - } - } - - @EventHandler - public void onWorldLoad(WorldLoadEvent event) { - initWorld(event.getWorld()); - } - - /** - * Initialize the settings for the specified world - * @see WorldConfiguration#alwaysRaining - * @see WorldConfiguration#disableWeather - * @see WorldConfiguration#alwaysThundering - * @see WorldConfiguration#disableThunder - * @param world The specified world - */ - public void initWorld(World world) { - ConfigurationManager cfg = plugin.getGlobalStateManager(); - WorldConfiguration wcfg = cfg.get(world); - if (wcfg.alwaysRaining && !wcfg.disableWeather) { - world.setStorm(true); - } else if (wcfg.disableWeather && !wcfg.alwaysRaining) { - world.setStorm(false); - } - if (wcfg.alwaysThundering && !wcfg.disableThunder) { - world.setThundering(true); - } else if (wcfg.disableThunder && !wcfg.alwaysThundering) { - world.setStorm(false); - } - } -} +/* + * 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.listener; + +import com.sk89q.worldguard.bukkit.BukkitUtil; +import com.sk89q.worldguard.bukkit.ConfigurationManager; +import com.sk89q.worldguard.bukkit.WorldConfiguration; +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import org.bukkit.World; +import org.bukkit.entity.Entity; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.world.ChunkLoadEvent; +import org.bukkit.event.world.WorldLoadEvent; + +public class WorldGuardWorldListener implements Listener { + + private WorldGuardPlugin plugin; + + /** + * Construct the object; + * + * @param plugin The plugin instance + */ + public WorldGuardWorldListener(WorldGuardPlugin plugin) { + this.plugin = plugin; + } + + /** + * Register events. + */ + public void registerEvents() { + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + @EventHandler + public void onChunkLoad(ChunkLoadEvent event) { + ConfigurationManager cfg = plugin.getGlobalStateManager(); + + if (cfg.activityHaltToggle) { + int removed = 0; + + for (Entity entity : event.getChunk().getEntities()) { + if (BukkitUtil.isIntensiveEntity(entity)) { + entity.remove(); + removed++; + } + } + + if (removed > 50) { + plugin.getLogger().info("Halt-Act: " + removed + " entities (>50) auto-removed from " + + event.getChunk().toString()); + } + } + } + + @EventHandler + public void onWorldLoad(WorldLoadEvent event) { + initWorld(event.getWorld()); + } + + /** + * Initialize the settings for the specified world + * @see WorldConfiguration#alwaysRaining + * @see WorldConfiguration#disableWeather + * @see WorldConfiguration#alwaysThundering + * @see WorldConfiguration#disableThunder + * @param world The specified world + */ + public void initWorld(World world) { + ConfigurationManager cfg = plugin.getGlobalStateManager(); + WorldConfiguration wcfg = cfg.get(world); + if (wcfg.alwaysRaining && !wcfg.disableWeather) { + world.setStorm(true); + } else if (wcfg.disableWeather && !wcfg.alwaysRaining) { + world.setStorm(false); + } + if (wcfg.alwaysThundering && !wcfg.disableThunder) { + world.setThundering(true); + } else if (wcfg.disableThunder && !wcfg.alwaysThundering) { + world.setStorm(false); + } + } +} diff --git a/src/main/java/com/sk89q/worldguard/internal/Blocks.java b/src/main/java/com/sk89q/worldguard/bukkit/util/Blocks.java similarity index 56% rename from src/main/java/com/sk89q/worldguard/internal/Blocks.java rename to src/main/java/com/sk89q/worldguard/bukkit/util/Blocks.java index 7d82b045..2a7323ee 100644 --- a/src/main/java/com/sk89q/worldguard/internal/Blocks.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/util/Blocks.java @@ -17,17 +17,18 @@ * along with this program. If not, see . */ -package com.sk89q.worldguard.internal; +package com.sk89q.worldguard.bukkit.util; import org.bukkit.block.Block; -import org.bukkit.block.Hopper; -import org.bukkit.material.Attachable; +import org.bukkit.material.Bed; import org.bukkit.material.MaterialData; -import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; /** - * Block related utility methods. + * Utility methods to deal with blocks. */ public final class Blocks { @@ -35,21 +36,25 @@ private Blocks() { } /** - * Get the block that this block attaches to. + * Get a list of connected blocks to the given block, not including + * the given block. * - * @param block the block to check - * @return the block attached to or null + * @param block the block + * @return a list of connected blocks, not including the given block */ - @Nullable - public static Block getAttachesTo(Block block) { + public static List getConnected(Block block) { MaterialData data = block.getState().getData(); - if (data instanceof Attachable) { - Attachable attachable = (Attachable) data; - return block.getRelative(attachable.getAttachedFace()); + if (data instanceof Bed) { + Bed bed = (Bed) data; + if (bed.isHeadOfBed()) { + return Arrays.asList(block.getRelative(bed.getFacing().getOppositeFace())); + } else { + return Arrays.asList(block.getRelative(bed.getFacing())); + } + } else { + return Collections.emptyList(); } - - return null; } } diff --git a/src/main/java/com/sk89q/worldguard/bukkit/util/Entities.java b/src/main/java/com/sk89q/worldguard/bukkit/util/Entities.java new file mode 100644 index 00000000..765b9f0e --- /dev/null +++ b/src/main/java/com/sk89q/worldguard/bukkit/util/Entities.java @@ -0,0 +1,114 @@ +/* + * 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.util; + +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Projectile; +import org.bukkit.entity.Tameable; +import org.bukkit.projectiles.ProjectileSource; + +import javax.annotation.Nullable; + +public final class Entities { + + private Entities() { + } + + /** + * Test whether the given entity is tameable and tamed. + * + * @param entity the entity, or null + * @return true if tamed + */ + public static boolean isTamed(@Nullable Entity entity) { + return entity instanceof Tameable && ((Tameable) entity).isTamed(); + } + + /** + * Return if the given entity type is TNT-based. + * + * @param type the type + * @return true if TNT based + */ + public static boolean isTNTBased(EntityType type) { + return type == EntityType.PRIMED_TNT || type == EntityType.MINECART_TNT; + } + + /** + * Return if the given entity type is a fireball + * (not including wither skulls). + * + * @param type the type + * @return true if a fireball + */ + public static boolean isFireball(EntityType type) { + return type == EntityType.FIREBALL || type == EntityType.SMALL_FIREBALL; + } + + /** + * Test whether the given entity type is a vehicle type. + * + * @param type the type + * @return true if the type is a vehicle type + */ + public static boolean isVehicle(EntityType type) { + return type == EntityType.BOAT + || isMinecart(type); + } + + /** + * Test whether the given entity type is a Minecart type. + * + * @param type the type + * @return true if the type is a Minecart type + */ + public static boolean isMinecart(EntityType type) { + return type == EntityType.MINECART + || type == EntityType.MINECART_CHEST + || type == EntityType.MINECART_COMMAND + || type == EntityType.MINECART_FURNACE + || type == EntityType.MINECART_HOPPER + || type == EntityType.MINECART_MOB_SPAWNER + || type == EntityType.MINECART_TNT; + } + + /** + * Get the underlying shooter of a projectile if one exists. + * + * @param entity the entity + * @return the shooter + */ + public static Entity getShooter(Entity entity) { + + while (entity instanceof Projectile) { + Projectile projectile = (Projectile) entity; + ProjectileSource remover = projectile.getShooter(); + if (remover instanceof Entity && remover != entity) { + entity = (Entity) remover; + } else { + return entity; + } + } + + return entity; + } + +} diff --git a/src/main/java/com/sk89q/worldguard/bukkit/util/EventEnums.java b/src/main/java/com/sk89q/worldguard/bukkit/util/EventEnums.java new file mode 100644 index 00000000..2db34f0d --- /dev/null +++ b/src/main/java/com/sk89q/worldguard/bukkit/util/EventEnums.java @@ -0,0 +1,77 @@ +/* + * 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.util; + +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; + +/** + * Utility methods to deal with event-related enums in Bukkit. + */ +public final class EventEnums { + + private EventEnums() { + } + + /** + * Return whether the given damage cause is fire-reltaed. + * + * @param cause the cause + * @return true if fire related + */ + public static boolean isFireCause(DamageCause cause) { + return cause == DamageCause.FIRE || cause == DamageCause.FIRE_TICK; + } + + /** + * Return whether the given cause is an explosion. + * + * @param cause the cause + * @return true if it is an explosion cuase + */ + public static boolean isExplosionCause(DamageCause cause) { + return cause == DamageCause.BLOCK_EXPLOSION || cause == DamageCause.ENTITY_EXPLOSION; + } + + /** + * Restore the statistic associated with the given cause. For example, + * for the {@link DamageCause#DROWNING} cause, the entity would have its + * air level set to its maximum. + * + * @param entity the entity + * @param cause the cuase + */ + public static void restoreStatistic(Entity entity, DamageCause cause) { + if (cause == DamageCause.DROWNING && entity instanceof LivingEntity) { + LivingEntity living = (LivingEntity) entity; + living.setRemainingAir(living.getMaximumAir()); + } + + if (isFireCause(cause)) { + entity.setFireTicks(0); + } + + if (cause == DamageCause.LAVA) { + entity.setFireTicks(0); + } + } + +} diff --git a/src/main/java/com/sk89q/worldguard/internal/Events.java b/src/main/java/com/sk89q/worldguard/bukkit/util/Events.java similarity index 71% rename from src/main/java/com/sk89q/worldguard/internal/Events.java rename to src/main/java/com/sk89q/worldguard/bukkit/util/Events.java index 6e92be49..6ad8ec73 100644 --- a/src/main/java/com/sk89q/worldguard/internal/Events.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/util/Events.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldguard.internal; +package com.sk89q.worldguard.bukkit.util; import org.bukkit.Bukkit; import org.bukkit.event.Cancellable; @@ -34,8 +34,20 @@ private Events() { } /** - * Fire the {@code eventToFire} if {@code original} has not been cancelled - * and cancel the original if the fired event is cancelled. + * Fire the {@code eventToFire} and return whether the event was cancelled. + * + * @param eventToFire the event to fire + * @param an event that can be fired and is cancellable + * @return true if the event was cancelled + */ + public static boolean fireAndTestCancel( T eventToFire) { + Bukkit.getServer().getPluginManager().callEvent(eventToFire); + return eventToFire.isCancelled(); + } + + /** + * Fire the {@code eventToFire} and cancel the original if the fired event + * is cancelled. * * @param original the original event to potentially cancel * @param eventToFire the event to fire to consider cancelling the original event @@ -43,20 +55,18 @@ private Events() { * @return true if the event was fired and it caused the original event to be cancelled */ public static boolean fireToCancel(Cancellable original, T eventToFire) { - if (!original.isCancelled()) { - Bukkit.getServer().getPluginManager().callEvent(eventToFire); - if (eventToFire.isCancelled()) { - original.setCancelled(true); - return true; - } + Bukkit.getServer().getPluginManager().callEvent(eventToFire); + if (eventToFire.isCancelled()) { + original.setCancelled(true); + return true; } return false; } /** - * Fire the {@code eventToFire} if {@code original} - * and cancel the original if the fired event is cancelled. + * Fire the {@code eventToFire} and cancel the original if the fired event + * is cancelled. * * @param original the original event to potentially cancel * @param eventToFire the event to fire to consider cancelling the original event diff --git a/src/main/java/com/sk89q/worldguard/bukkit/util/Materials.java b/src/main/java/com/sk89q/worldguard/bukkit/util/Materials.java new file mode 100644 index 00000000..12e1a095 --- /dev/null +++ b/src/main/java/com/sk89q/worldguard/bukkit/util/Materials.java @@ -0,0 +1,597 @@ +/* + * 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.util; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.entity.EntityType; +import org.bukkit.material.Dye; +import org.bukkit.material.MaterialData; + +import javax.annotation.Nullable; +import java.util.HashMap; +import java.util.Map; + +/** + * Material utility class. + */ +public final class Materials { + + private static final int MODIFIED_ON_CLICK = 1; + private static final int MODIFIES_BLOCKS = 2; + + private static final BiMap ENTITY_ITEMS = HashBiMap.create(); + private static final Map MATERIAL_FLAGS = new HashMap(); + + static { + ENTITY_ITEMS.put(EntityType.PAINTING, Material.PAINTING); + ENTITY_ITEMS.put(EntityType.ARROW, Material.ARROW); + ENTITY_ITEMS.put(EntityType.SNOWBALL, Material.SNOW_BALL); + ENTITY_ITEMS.put(EntityType.FIREBALL, Material.FIREBALL); + ENTITY_ITEMS.put(EntityType.SMALL_FIREBALL, Material.FIREWORK_CHARGE); + ENTITY_ITEMS.put(EntityType.ENDER_PEARL, Material.ENDER_PEARL); + ENTITY_ITEMS.put(EntityType.THROWN_EXP_BOTTLE, Material.EXP_BOTTLE); + ENTITY_ITEMS.put(EntityType.ITEM_FRAME, Material.ITEM_FRAME); + ENTITY_ITEMS.put(EntityType.PRIMED_TNT, Material.TNT); + ENTITY_ITEMS.put(EntityType.FIREWORK, Material.FIREWORK); + ENTITY_ITEMS.put(EntityType.MINECART_COMMAND, Material.COMMAND_MINECART); + ENTITY_ITEMS.put(EntityType.BOAT, Material.BOAT); + ENTITY_ITEMS.put(EntityType.MINECART, Material.MINECART); + ENTITY_ITEMS.put(EntityType.MINECART_CHEST, Material.STORAGE_MINECART); + ENTITY_ITEMS.put(EntityType.MINECART_FURNACE, Material.POWERED_MINECART); + ENTITY_ITEMS.put(EntityType.MINECART_TNT, Material.EXPLOSIVE_MINECART); + ENTITY_ITEMS.put(EntityType.MINECART_HOPPER, Material.HOPPER_MINECART); + ENTITY_ITEMS.put(EntityType.SPLASH_POTION, Material.POTION); + ENTITY_ITEMS.put(EntityType.EGG, Material.EGG); + + MATERIAL_FLAGS.put(Material.AIR, 0); + MATERIAL_FLAGS.put(Material.STONE, 0); + MATERIAL_FLAGS.put(Material.GRASS, 0); + MATERIAL_FLAGS.put(Material.DIRT, 0); + MATERIAL_FLAGS.put(Material.COBBLESTONE, 0); + MATERIAL_FLAGS.put(Material.WOOD, 0); + MATERIAL_FLAGS.put(Material.SAPLING, 0); + MATERIAL_FLAGS.put(Material.BEDROCK, 0); + MATERIAL_FLAGS.put(Material.WATER, 0); + MATERIAL_FLAGS.put(Material.STATIONARY_WATER, 0); + MATERIAL_FLAGS.put(Material.LAVA, 0); + MATERIAL_FLAGS.put(Material.STATIONARY_LAVA, 0); + MATERIAL_FLAGS.put(Material.SAND, 0); + MATERIAL_FLAGS.put(Material.GRAVEL, 0); + MATERIAL_FLAGS.put(Material.GOLD_ORE, 0); + MATERIAL_FLAGS.put(Material.IRON_ORE, 0); + MATERIAL_FLAGS.put(Material.COAL_ORE, 0); + MATERIAL_FLAGS.put(Material.LOG, 0); + MATERIAL_FLAGS.put(Material.LEAVES, 0); + MATERIAL_FLAGS.put(Material.SPONGE, 0); + MATERIAL_FLAGS.put(Material.GLASS, 0); + MATERIAL_FLAGS.put(Material.LAPIS_ORE, 0); + MATERIAL_FLAGS.put(Material.LAPIS_BLOCK, 0); + MATERIAL_FLAGS.put(Material.DISPENSER, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.SANDSTONE, 0); + MATERIAL_FLAGS.put(Material.NOTE_BLOCK, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.BED_BLOCK, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.POWERED_RAIL, 0); + MATERIAL_FLAGS.put(Material.DETECTOR_RAIL, 0); + MATERIAL_FLAGS.put(Material.PISTON_STICKY_BASE, 0); + MATERIAL_FLAGS.put(Material.WEB, 0); + MATERIAL_FLAGS.put(Material.LONG_GRASS, 0); + MATERIAL_FLAGS.put(Material.DEAD_BUSH, 0); + MATERIAL_FLAGS.put(Material.PISTON_BASE, 0); + MATERIAL_FLAGS.put(Material.PISTON_EXTENSION, 0); + MATERIAL_FLAGS.put(Material.WOOL, 0); + MATERIAL_FLAGS.put(Material.PISTON_MOVING_PIECE, 0); + MATERIAL_FLAGS.put(Material.YELLOW_FLOWER, 0); + MATERIAL_FLAGS.put(Material.RED_ROSE, 0); + MATERIAL_FLAGS.put(Material.BROWN_MUSHROOM, 0); + MATERIAL_FLAGS.put(Material.RED_MUSHROOM, 0); + MATERIAL_FLAGS.put(Material.GOLD_BLOCK, 0); + MATERIAL_FLAGS.put(Material.IRON_BLOCK, 0); + MATERIAL_FLAGS.put(Material.DOUBLE_STEP, 0); + MATERIAL_FLAGS.put(Material.STEP, 0); + MATERIAL_FLAGS.put(Material.BRICK, 0); + MATERIAL_FLAGS.put(Material.TNT, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.BOOKSHELF, 0); + MATERIAL_FLAGS.put(Material.MOSSY_COBBLESTONE, 0); + MATERIAL_FLAGS.put(Material.OBSIDIAN, 0); + MATERIAL_FLAGS.put(Material.TORCH, 0); + MATERIAL_FLAGS.put(Material.FIRE, 0); + MATERIAL_FLAGS.put(Material.MOB_SPAWNER, 0); + MATERIAL_FLAGS.put(Material.WOOD_STAIRS, 0); + MATERIAL_FLAGS.put(Material.CHEST, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.REDSTONE_WIRE, 0); + MATERIAL_FLAGS.put(Material.DIAMOND_ORE, 0); + MATERIAL_FLAGS.put(Material.DIAMOND_BLOCK, 0); + MATERIAL_FLAGS.put(Material.WORKBENCH, 0); + MATERIAL_FLAGS.put(Material.CROPS, 0); + MATERIAL_FLAGS.put(Material.SOIL, 0); + MATERIAL_FLAGS.put(Material.FURNACE, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.BURNING_FURNACE, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.SIGN_POST, 0); + MATERIAL_FLAGS.put(Material.WOODEN_DOOR, 0); + MATERIAL_FLAGS.put(Material.LADDER, 0); + MATERIAL_FLAGS.put(Material.RAILS, 0); + MATERIAL_FLAGS.put(Material.COBBLESTONE_STAIRS, 0); + MATERIAL_FLAGS.put(Material.WALL_SIGN, 0); + MATERIAL_FLAGS.put(Material.LEVER, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.STONE_PLATE, 0); + MATERIAL_FLAGS.put(Material.IRON_DOOR_BLOCK, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.WOOD_PLATE, 0); + MATERIAL_FLAGS.put(Material.REDSTONE_ORE, 0); + MATERIAL_FLAGS.put(Material.GLOWING_REDSTONE_ORE, 0); + MATERIAL_FLAGS.put(Material.REDSTONE_TORCH_OFF, 0); + MATERIAL_FLAGS.put(Material.REDSTONE_TORCH_ON, 0); + MATERIAL_FLAGS.put(Material.STONE_BUTTON, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.SNOW, 0); + MATERIAL_FLAGS.put(Material.ICE, 0); + MATERIAL_FLAGS.put(Material.SNOW_BLOCK, 0); + MATERIAL_FLAGS.put(Material.CACTUS, 0); + MATERIAL_FLAGS.put(Material.CLAY, 0); + MATERIAL_FLAGS.put(Material.SUGAR_CANE_BLOCK, 0); + MATERIAL_FLAGS.put(Material.JUKEBOX, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.FENCE, 0); + MATERIAL_FLAGS.put(Material.PUMPKIN, 0); + MATERIAL_FLAGS.put(Material.NETHERRACK, 0); + MATERIAL_FLAGS.put(Material.SOUL_SAND, 0); + MATERIAL_FLAGS.put(Material.GLOWSTONE, 0); + MATERIAL_FLAGS.put(Material.PORTAL, 0); + MATERIAL_FLAGS.put(Material.JACK_O_LANTERN, 0); + MATERIAL_FLAGS.put(Material.CAKE_BLOCK, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.DIODE_BLOCK_OFF, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.DIODE_BLOCK_ON, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.STAINED_GLASS, 0); + MATERIAL_FLAGS.put(Material.TRAP_DOOR, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.MONSTER_EGGS, 0); + MATERIAL_FLAGS.put(Material.SMOOTH_BRICK, 0); + MATERIAL_FLAGS.put(Material.HUGE_MUSHROOM_1, 0); + MATERIAL_FLAGS.put(Material.HUGE_MUSHROOM_2, 0); + MATERIAL_FLAGS.put(Material.IRON_FENCE, 0); + MATERIAL_FLAGS.put(Material.THIN_GLASS, 0); + MATERIAL_FLAGS.put(Material.MELON_BLOCK, 0); + MATERIAL_FLAGS.put(Material.PUMPKIN_STEM, 0); + MATERIAL_FLAGS.put(Material.MELON_STEM, 0); + MATERIAL_FLAGS.put(Material.VINE, 0); + MATERIAL_FLAGS.put(Material.FENCE_GATE, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.BRICK_STAIRS, 0); + MATERIAL_FLAGS.put(Material.SMOOTH_STAIRS, 0); + MATERIAL_FLAGS.put(Material.MYCEL, 0); + MATERIAL_FLAGS.put(Material.WATER_LILY, 0); + MATERIAL_FLAGS.put(Material.NETHER_BRICK, 0); + MATERIAL_FLAGS.put(Material.NETHER_FENCE, 0); + MATERIAL_FLAGS.put(Material.NETHER_BRICK_STAIRS, 0); + MATERIAL_FLAGS.put(Material.NETHER_WARTS, 0); + MATERIAL_FLAGS.put(Material.ENCHANTMENT_TABLE, 0); + MATERIAL_FLAGS.put(Material.BREWING_STAND, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.CAULDRON, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.ENDER_PORTAL, 0); + MATERIAL_FLAGS.put(Material.ENDER_PORTAL_FRAME, 0); + MATERIAL_FLAGS.put(Material.ENDER_STONE, 0); + MATERIAL_FLAGS.put(Material.DRAGON_EGG, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.REDSTONE_LAMP_OFF, 0); + MATERIAL_FLAGS.put(Material.REDSTONE_LAMP_ON, 0); + MATERIAL_FLAGS.put(Material.WOOD_DOUBLE_STEP, 0); + MATERIAL_FLAGS.put(Material.WOOD_STEP, 0); + MATERIAL_FLAGS.put(Material.COCOA, 0); + MATERIAL_FLAGS.put(Material.SANDSTONE_STAIRS, 0); + MATERIAL_FLAGS.put(Material.EMERALD_ORE, 0); + MATERIAL_FLAGS.put(Material.ENDER_CHEST, 0); + MATERIAL_FLAGS.put(Material.TRIPWIRE_HOOK, 0); + MATERIAL_FLAGS.put(Material.TRIPWIRE, 0); + MATERIAL_FLAGS.put(Material.EMERALD_BLOCK, 0); + MATERIAL_FLAGS.put(Material.SPRUCE_WOOD_STAIRS, 0); + MATERIAL_FLAGS.put(Material.BIRCH_WOOD_STAIRS, 0); + MATERIAL_FLAGS.put(Material.JUNGLE_WOOD_STAIRS, 0); + MATERIAL_FLAGS.put(Material.COMMAND, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.BEACON, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.COBBLE_WALL, 0); + MATERIAL_FLAGS.put(Material.FLOWER_POT, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.CARROT, 0); + MATERIAL_FLAGS.put(Material.POTATO, 0); + MATERIAL_FLAGS.put(Material.WOOD_BUTTON, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.SKULL, 0); + MATERIAL_FLAGS.put(Material.ANVIL, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.TRAPPED_CHEST, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.GOLD_PLATE, 0); + MATERIAL_FLAGS.put(Material.IRON_PLATE, 0); + MATERIAL_FLAGS.put(Material.REDSTONE_COMPARATOR_OFF, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.REDSTONE_COMPARATOR_ON, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.DAYLIGHT_DETECTOR, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.REDSTONE_BLOCK, 0); + MATERIAL_FLAGS.put(Material.QUARTZ_ORE, 0); + MATERIAL_FLAGS.put(Material.HOPPER, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.QUARTZ_BLOCK, 0); + MATERIAL_FLAGS.put(Material.QUARTZ_STAIRS, 0); + MATERIAL_FLAGS.put(Material.ACTIVATOR_RAIL, 0); + MATERIAL_FLAGS.put(Material.DROPPER, MODIFIED_ON_CLICK); + MATERIAL_FLAGS.put(Material.STAINED_CLAY, 0); + MATERIAL_FLAGS.put(Material.STAINED_GLASS_PANE, 0); + MATERIAL_FLAGS.put(Material.LEAVES_2, 0); + MATERIAL_FLAGS.put(Material.LOG_2, 0); + MATERIAL_FLAGS.put(Material.ACACIA_STAIRS, 0); + MATERIAL_FLAGS.put(Material.DARK_OAK_STAIRS, 0); + MATERIAL_FLAGS.put(Material.HAY_BLOCK, 0); + MATERIAL_FLAGS.put(Material.CARPET, 0); + MATERIAL_FLAGS.put(Material.HARD_CLAY, 0); + MATERIAL_FLAGS.put(Material.COAL_BLOCK, 0); + MATERIAL_FLAGS.put(Material.PACKED_ICE, 0); + MATERIAL_FLAGS.put(Material.DOUBLE_PLANT, 0); + + MATERIAL_FLAGS.put(Material.IRON_SPADE, 0); + MATERIAL_FLAGS.put(Material.IRON_PICKAXE, 0); + MATERIAL_FLAGS.put(Material.IRON_AXE, 0); + MATERIAL_FLAGS.put(Material.FLINT_AND_STEEL, 0); + MATERIAL_FLAGS.put(Material.APPLE, 0); + MATERIAL_FLAGS.put(Material.BOW, 0); + MATERIAL_FLAGS.put(Material.ARROW, 0); + MATERIAL_FLAGS.put(Material.COAL, 0); + MATERIAL_FLAGS.put(Material.DIAMOND, 0); + MATERIAL_FLAGS.put(Material.IRON_INGOT, 0); + MATERIAL_FLAGS.put(Material.GOLD_INGOT, 0); + MATERIAL_FLAGS.put(Material.IRON_SWORD, 0); + MATERIAL_FLAGS.put(Material.WOOD_SWORD, 0); + MATERIAL_FLAGS.put(Material.WOOD_SPADE, 0); + MATERIAL_FLAGS.put(Material.WOOD_PICKAXE, 0); + MATERIAL_FLAGS.put(Material.WOOD_AXE, 0); + MATERIAL_FLAGS.put(Material.STONE_SWORD, 0); + MATERIAL_FLAGS.put(Material.STONE_SPADE, 0); + MATERIAL_FLAGS.put(Material.STONE_PICKAXE, 0); + MATERIAL_FLAGS.put(Material.STONE_AXE, 0); + MATERIAL_FLAGS.put(Material.DIAMOND_SWORD, 0); + MATERIAL_FLAGS.put(Material.DIAMOND_SPADE, 0); + MATERIAL_FLAGS.put(Material.DIAMOND_PICKAXE, 0); + MATERIAL_FLAGS.put(Material.DIAMOND_AXE, 0); + MATERIAL_FLAGS.put(Material.STICK, 0); + MATERIAL_FLAGS.put(Material.BOWL, 0); + MATERIAL_FLAGS.put(Material.MUSHROOM_SOUP, 0); + MATERIAL_FLAGS.put(Material.GOLD_SWORD, 0); + MATERIAL_FLAGS.put(Material.GOLD_SPADE, 0); + MATERIAL_FLAGS.put(Material.GOLD_PICKAXE, 0); + MATERIAL_FLAGS.put(Material.GOLD_AXE, 0); + MATERIAL_FLAGS.put(Material.STRING, 0); + MATERIAL_FLAGS.put(Material.FEATHER, 0); + MATERIAL_FLAGS.put(Material.SULPHUR, 0); + MATERIAL_FLAGS.put(Material.WOOD_HOE, MODIFIES_BLOCKS); + MATERIAL_FLAGS.put(Material.STONE_HOE, MODIFIES_BLOCKS); + MATERIAL_FLAGS.put(Material.IRON_HOE, MODIFIES_BLOCKS); + MATERIAL_FLAGS.put(Material.DIAMOND_HOE, MODIFIES_BLOCKS); + MATERIAL_FLAGS.put(Material.GOLD_HOE, MODIFIES_BLOCKS); + MATERIAL_FLAGS.put(Material.SEEDS, MODIFIES_BLOCKS); + MATERIAL_FLAGS.put(Material.WHEAT, 0); + MATERIAL_FLAGS.put(Material.BREAD, 0); + MATERIAL_FLAGS.put(Material.LEATHER_HELMET, 0); + MATERIAL_FLAGS.put(Material.LEATHER_CHESTPLATE, 0); + MATERIAL_FLAGS.put(Material.LEATHER_LEGGINGS, 0); + MATERIAL_FLAGS.put(Material.LEATHER_BOOTS, 0); + MATERIAL_FLAGS.put(Material.CHAINMAIL_HELMET, 0); + MATERIAL_FLAGS.put(Material.CHAINMAIL_CHESTPLATE, 0); + MATERIAL_FLAGS.put(Material.CHAINMAIL_LEGGINGS, 0); + MATERIAL_FLAGS.put(Material.CHAINMAIL_BOOTS, 0); + MATERIAL_FLAGS.put(Material.IRON_HELMET, 0); + MATERIAL_FLAGS.put(Material.IRON_CHESTPLATE, 0); + MATERIAL_FLAGS.put(Material.IRON_LEGGINGS, 0); + MATERIAL_FLAGS.put(Material.IRON_BOOTS, 0); + MATERIAL_FLAGS.put(Material.DIAMOND_HELMET, 0); + MATERIAL_FLAGS.put(Material.DIAMOND_CHESTPLATE, 0); + MATERIAL_FLAGS.put(Material.DIAMOND_LEGGINGS, 0); + MATERIAL_FLAGS.put(Material.DIAMOND_BOOTS, 0); + MATERIAL_FLAGS.put(Material.GOLD_HELMET, 0); + MATERIAL_FLAGS.put(Material.GOLD_CHESTPLATE, 0); + MATERIAL_FLAGS.put(Material.GOLD_LEGGINGS, 0); + MATERIAL_FLAGS.put(Material.GOLD_BOOTS, 0); + MATERIAL_FLAGS.put(Material.FLINT, 0); + MATERIAL_FLAGS.put(Material.PORK, 0); + MATERIAL_FLAGS.put(Material.GRILLED_PORK, 0); + MATERIAL_FLAGS.put(Material.PAINTING, 0); + MATERIAL_FLAGS.put(Material.GOLDEN_APPLE, 0); + MATERIAL_FLAGS.put(Material.SIGN, 0); + MATERIAL_FLAGS.put(Material.WOOD_DOOR, 0); + MATERIAL_FLAGS.put(Material.BUCKET, 0); + MATERIAL_FLAGS.put(Material.WATER_BUCKET, 0); + MATERIAL_FLAGS.put(Material.LAVA_BUCKET, 0); + MATERIAL_FLAGS.put(Material.MINECART, 0); + MATERIAL_FLAGS.put(Material.SADDLE, 0); + MATERIAL_FLAGS.put(Material.IRON_DOOR, 0); + MATERIAL_FLAGS.put(Material.REDSTONE, 0); + MATERIAL_FLAGS.put(Material.SNOW_BALL, 0); + MATERIAL_FLAGS.put(Material.BOAT, 0); + MATERIAL_FLAGS.put(Material.LEATHER, 0); + MATERIAL_FLAGS.put(Material.MILK_BUCKET, 0); + MATERIAL_FLAGS.put(Material.CLAY_BRICK, 0); + MATERIAL_FLAGS.put(Material.CLAY_BALL, 0); + MATERIAL_FLAGS.put(Material.SUGAR_CANE, 0); + MATERIAL_FLAGS.put(Material.PAPER, 0); + MATERIAL_FLAGS.put(Material.BOOK, 0); + MATERIAL_FLAGS.put(Material.SLIME_BALL, 0); + MATERIAL_FLAGS.put(Material.STORAGE_MINECART, 0); + MATERIAL_FLAGS.put(Material.POWERED_MINECART, 0); + MATERIAL_FLAGS.put(Material.EGG, 0); + MATERIAL_FLAGS.put(Material.COMPASS, 0); + MATERIAL_FLAGS.put(Material.FISHING_ROD, 0); + MATERIAL_FLAGS.put(Material.WATCH, 0); + MATERIAL_FLAGS.put(Material.GLOWSTONE_DUST, 0); + MATERIAL_FLAGS.put(Material.RAW_FISH, 0); + MATERIAL_FLAGS.put(Material.COOKED_FISH, 0); + MATERIAL_FLAGS.put(Material.INK_SACK, 0); + MATERIAL_FLAGS.put(Material.BONE, 0); + MATERIAL_FLAGS.put(Material.SUGAR, 0); + MATERIAL_FLAGS.put(Material.CAKE, 0); + MATERIAL_FLAGS.put(Material.BED, 0); + MATERIAL_FLAGS.put(Material.DIODE, 0); + MATERIAL_FLAGS.put(Material.COOKIE, 0); + MATERIAL_FLAGS.put(Material.MAP, 0); + MATERIAL_FLAGS.put(Material.SHEARS, MODIFIES_BLOCKS); + MATERIAL_FLAGS.put(Material.MELON, 0); + MATERIAL_FLAGS.put(Material.PUMPKIN_SEEDS, 0); + MATERIAL_FLAGS.put(Material.MELON_SEEDS, 0); + MATERIAL_FLAGS.put(Material.RAW_BEEF, 0); + MATERIAL_FLAGS.put(Material.COOKED_BEEF, 0); + MATERIAL_FLAGS.put(Material.RAW_CHICKEN, 0); + MATERIAL_FLAGS.put(Material.COOKED_CHICKEN, 0); + MATERIAL_FLAGS.put(Material.ROTTEN_FLESH, 0); + MATERIAL_FLAGS.put(Material.ENDER_PEARL, 0); + MATERIAL_FLAGS.put(Material.BLAZE_ROD, 0); + MATERIAL_FLAGS.put(Material.GHAST_TEAR, 0); + MATERIAL_FLAGS.put(Material.GOLD_NUGGET, 0); + MATERIAL_FLAGS.put(Material.NETHER_STALK, 0); + MATERIAL_FLAGS.put(Material.POTION, 0); + MATERIAL_FLAGS.put(Material.GLASS_BOTTLE, 0); + MATERIAL_FLAGS.put(Material.SPIDER_EYE, 0); + MATERIAL_FLAGS.put(Material.FERMENTED_SPIDER_EYE, 0); + MATERIAL_FLAGS.put(Material.BLAZE_POWDER, 0); + MATERIAL_FLAGS.put(Material.MAGMA_CREAM, 0); + MATERIAL_FLAGS.put(Material.BREWING_STAND_ITEM, 0); + MATERIAL_FLAGS.put(Material.CAULDRON_ITEM, 0); + MATERIAL_FLAGS.put(Material.EYE_OF_ENDER, 0); + MATERIAL_FLAGS.put(Material.SPECKLED_MELON, 0); + MATERIAL_FLAGS.put(Material.MONSTER_EGG, 0); + MATERIAL_FLAGS.put(Material.EXP_BOTTLE, 0); + MATERIAL_FLAGS.put(Material.FIREBALL, 0); + MATERIAL_FLAGS.put(Material.BOOK_AND_QUILL, 0); + MATERIAL_FLAGS.put(Material.WRITTEN_BOOK, 0); + MATERIAL_FLAGS.put(Material.EMERALD, 0); + MATERIAL_FLAGS.put(Material.ITEM_FRAME, 0); + MATERIAL_FLAGS.put(Material.FLOWER_POT_ITEM, 0); + MATERIAL_FLAGS.put(Material.CARROT_ITEM, 0); + MATERIAL_FLAGS.put(Material.POTATO_ITEM, 0); + MATERIAL_FLAGS.put(Material.BAKED_POTATO, 0); + MATERIAL_FLAGS.put(Material.POISONOUS_POTATO, 0); + MATERIAL_FLAGS.put(Material.EMPTY_MAP, 0); + MATERIAL_FLAGS.put(Material.GOLDEN_CARROT, 0); + MATERIAL_FLAGS.put(Material.SKULL_ITEM, 0); + MATERIAL_FLAGS.put(Material.CARROT_STICK, 0); + MATERIAL_FLAGS.put(Material.NETHER_STAR, 0); + MATERIAL_FLAGS.put(Material.PUMPKIN_PIE, 0); + MATERIAL_FLAGS.put(Material.FIREWORK, 0); + MATERIAL_FLAGS.put(Material.FIREWORK_CHARGE, 0); + MATERIAL_FLAGS.put(Material.ENCHANTED_BOOK, 0); + MATERIAL_FLAGS.put(Material.REDSTONE_COMPARATOR, 0); + MATERIAL_FLAGS.put(Material.NETHER_BRICK_ITEM, 0); + MATERIAL_FLAGS.put(Material.QUARTZ, 0); + MATERIAL_FLAGS.put(Material.EXPLOSIVE_MINECART, 0); + MATERIAL_FLAGS.put(Material.HOPPER_MINECART, 0); + MATERIAL_FLAGS.put(Material.IRON_BARDING, 0); + MATERIAL_FLAGS.put(Material.GOLD_BARDING, 0); + MATERIAL_FLAGS.put(Material.DIAMOND_BARDING, 0); + MATERIAL_FLAGS.put(Material.LEASH, 0); + MATERIAL_FLAGS.put(Material.NAME_TAG, 0); + MATERIAL_FLAGS.put(Material.COMMAND_MINECART, 0); + MATERIAL_FLAGS.put(Material.GOLD_RECORD, 0); + MATERIAL_FLAGS.put(Material.GREEN_RECORD, 0); + MATERIAL_FLAGS.put(Material.RECORD_3, 0); + MATERIAL_FLAGS.put(Material.RECORD_4, 0); + MATERIAL_FLAGS.put(Material.RECORD_5, 0); + MATERIAL_FLAGS.put(Material.RECORD_6, 0); + MATERIAL_FLAGS.put(Material.RECORD_7, 0); + MATERIAL_FLAGS.put(Material.RECORD_8, 0); + MATERIAL_FLAGS.put(Material.RECORD_9, 0); + MATERIAL_FLAGS.put(Material.RECORD_10, 0); + MATERIAL_FLAGS.put(Material.RECORD_11, 0); + MATERIAL_FLAGS.put(Material.RECORD_12, 0); + } + + private Materials() { + } + + /** + * Get the related material for an entity type. + * + * @param type the entity type + * @return the related material or {@code null} if one is not known or exists + */ + @Nullable + public static Material getRelatedMaterial(EntityType type) { + return ENTITY_ITEMS.get(type); + } + + /** + * Get the material of the block placed by the given bucket, defaulting + * to water if the bucket type is not known. + * + *

If a non-bucket material is given, it will be assumed to be + * an unknown bucket type. If the given bucket doesn't have a block form + * (it can't be placed), then water will be returned (i.e. for milk). + * Be aware that either the stationary or non-stationary material may be + * returned.

+ * + * @param type the bucket material + * @return the block material + */ + public static Material getBucketBlockMaterial(Material type) { + switch (type) { + case LAVA_BUCKET: + return Material.LAVA; + case MILK_BUCKET: + return Material.WATER; + default: + return Material.WATER; + } + } + + /** + * Test whether the given material is a mushroom. + * + * @param material the material + * @return true if a mushroom block + */ + public static boolean isMushroom(Material material) { + return material == Material.RED_MUSHROOM || material == Material.BROWN_MUSHROOM; + } + + /** + * Test whether the given material is a leaf block. + * + * @param material the material + * @return true if a leaf block + */ + public static boolean isLeaf(Material material) { + return material == Material.LEAVES || material == Material.LEAVES_2; + } + + /** + * Test whether the given material is a liquid block. + * + * @param material the material + * @return true if a liquid block + */ + public static boolean isLiquid(Material material) { + return isWater(material) || isLava(material); + } + + /** + * Test whether the given material is water. + * + * @param material the material + * @return true if a water block + */ + public static boolean isWater(Material material) { + return material == Material.WATER || material == Material.STATIONARY_WATER; + } + + /** + * Test whether the given material is lava. + * + * @param material the material + * @return true if a lava block + */ + public static boolean isLava(Material material) { + return material == Material.LAVA || material == Material.STATIONARY_LAVA; + } + + /** + * Test whether the given material is a portal material. + * + * @param material the material + * @return true if a portal block + */ + public static boolean isPortal(Material material) { + return material == Material.PORTAL || material == Material.ENDER_PORTAL; + } + + /** + * Test whether the given material data is of the given dye color. + * + *

Returns false for non-dyed items.

+ * + * @param data the data + * @return true if it is the provided dye color + */ + public static boolean isDyeColor(MaterialData data, DyeColor color) { + return data instanceof Dye && ((Dye) data).getColor() == color; + } + + /** + * Test whether the given material is a rail block. + * + * @param material the material + * @return true if a rail block + */ + public static boolean isRailBlock(Material material) { + return material == Material.RAILS + || material == Material.ACTIVATOR_RAIL + || material == Material.DETECTOR_RAIL + || material == Material.POWERED_RAIL; + } + + /** + * Test whether the given material is a Minecart. + * + * @param material the material + * @return true if a Minecart item + */ + public static boolean isMinecart(Material material) { + return material == Material.MINECART + || material == Material.COMMAND_MINECART + || material == Material.EXPLOSIVE_MINECART + || material == Material.HOPPER_MINECART + || material == Material.POWERED_MINECART + || material == Material.STORAGE_MINECART; + } + + /** + * Test whether the given material is an inventory block. + * + * @param material the material + * @return true if an inventory block + */ + public static boolean isInventoryBlock(Material material) { + return material == Material.CHEST + || material == Material.JUKEBOX + || material == Material.DISPENSER + || material == Material.FURNACE + || material == Material.BURNING_FURNACE + || material == Material.BREWING_STAND + || material == Material.TRAPPED_CHEST + || material == Material.HOPPER + || material == Material.DROPPER; + } + + /** + * Test whether the given material is a block that is modified when it is + * left or right clicked. + * + *

This test is conservative, returning true for blocks that it is not + * aware of.

+ * + * @param material the material + * @return true if the block is modified + */ + public static boolean isBlockModifiedOnClick(Material material) { + Integer flags = MATERIAL_FLAGS.get(material); + return flags == null || (flags & MODIFIED_ON_CLICK) == MODIFIED_ON_CLICK; + } + + /** + * Test whether the given item modifies a given block when right clicked. + * + *

This test is conservative, returning true for items that it is not + * aware of or does not have the details for.

+ * + * @param item the item + * @param block the block + * @return true if the item is applied to the block + */ + public static boolean isItemAppliedToBlock(Material item, Material block) { + Integer flags = MATERIAL_FLAGS.get(item); + return flags == null || (flags & MODIFIES_BLOCKS) == MODIFIES_BLOCKS; + } + +} diff --git a/src/main/java/com/sk89q/worldguard/bukkit/util/RegionQuery.java b/src/main/java/com/sk89q/worldguard/bukkit/util/RegionQuery.java new file mode 100644 index 00000000..12f4f747 --- /dev/null +++ b/src/main/java/com/sk89q/worldguard/bukkit/util/RegionQuery.java @@ -0,0 +1,95 @@ +/* + * 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.util; + +import com.sk89q.worldguard.LocalPlayer; +import com.sk89q.worldguard.bukkit.BukkitUtil; +import com.sk89q.worldguard.bukkit.ConfigurationManager; +import com.sk89q.worldguard.bukkit.WorldConfiguration; +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import com.sk89q.worldguard.protection.GlobalRegionManager; +import com.sk89q.worldguard.protection.flags.StateFlag; +import com.sk89q.worldguard.protection.managers.RegionManager; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Player; + +import javax.annotation.Nullable; + +import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector; + +public class RegionQuery { + + private final ConfigurationManager config; + private final GlobalRegionManager globalManager; + @Nullable + private final LocalPlayer localPlayer; + + public RegionQuery(WorldGuardPlugin plugin, @Nullable Player player) { + this.config = plugin.getGlobalStateManager(); + this.globalManager = plugin.getGlobalRegionManager(); + this.localPlayer = player != null ? plugin.wrapPlayer(player) : null; + } + + public boolean canBuild(Location location) { + World world = location.getWorld(); + WorldConfiguration worldConfig = config.get(world); + + if (!worldConfig.useRegions) { + return true; + } + + if (localPlayer != null && globalManager.hasBypass(localPlayer, world)) { + return true; + } else { + RegionManager manager = globalManager.get(location.getWorld()); + return manager.getApplicableRegions(BukkitUtil.toVector(location)).canBuild(localPlayer); + } + } + + public boolean canConstruct(Location location) { + World world = location.getWorld(); + WorldConfiguration worldConfig = config.get(world); + + if (!worldConfig.useRegions) { + return true; + } + + if (localPlayer != null && globalManager.hasBypass(localPlayer, world)) { + return true; + } else { + RegionManager manager = globalManager.get(location.getWorld()); + return manager.getApplicableRegions(BukkitUtil.toVector(location)).canConstruct(localPlayer); + } + } + + public boolean allows(StateFlag flag, Location location) { + World world = location.getWorld(); + WorldConfiguration worldConfig = config.get(world); + + if (!worldConfig.useRegions) { + return true; + } + + RegionManager manager = globalManager.get(location.getWorld()); + return manager.getApplicableRegions(toVector(location)).allows(flag, localPlayer); + } + +} diff --git a/src/main/java/com/sk89q/worldguard/bukkit/util/WGMetadata.java b/src/main/java/com/sk89q/worldguard/bukkit/util/WGMetadata.java new file mode 100644 index 00000000..6aecfa60 --- /dev/null +++ b/src/main/java/com/sk89q/worldguard/bukkit/util/WGMetadata.java @@ -0,0 +1,78 @@ +/* + * 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.util; + +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.metadata.MetadataValue; +import org.bukkit.metadata.Metadatable; + +import javax.annotation.Nullable; +import java.util.List; + +/** + * Utility methods for dealing with metadata on entities. + * + *

WorldGuard is placed as the owner of all values.

+ */ +public final class WGMetadata { + + private WGMetadata() { + } + + /** + * Add some metadata to a target. + * + * @param target the target + * @param key the key + * @param value the value + */ + public static void put(Metadatable target, String key, Object value) { + target.setMetadata(key, new FixedMetadataValue(WorldGuardPlugin.inst(), value)); + } + + /** + * Get the (first) metadata value on the given target that has the given + * key and is of the given class type. + * + * @param target the target + * @param key the key + * @param expected the type of the value + * @param the type of the value + * @return a value, or {@code null} if one does not exists + */ + @Nullable + @SuppressWarnings("unchecked") + public static T getIfPresent(Metadatable target, String key, Class expected) { + List values = target.getMetadata(key); + WorldGuardPlugin owner = WorldGuardPlugin.inst(); + for (MetadataValue value : values) { + if (value.getOwningPlugin() == owner) { + Object v = value.value(); + if (expected.isInstance(v)) { + return (T) v; + } + } + } + + return null; + } + +} diff --git a/src/main/java/com/sk89q/worldguard/internal/cause/Cause.java b/src/main/java/com/sk89q/worldguard/internal/cause/Cause.java deleted file mode 100644 index 828f9db1..00000000 --- a/src/main/java/com/sk89q/worldguard/internal/cause/Cause.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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.internal.cause; - -/** - * Represents a possible cause of an event. - * - *

Example causes include players, blocks, entities, and many more.

- * - * @param the wrapped object type - */ -public interface Cause { - - /** - * Get the underlying object. - * - * @return the underlying object - */ - T get(); - -} diff --git a/src/main/java/com/sk89q/worldguard/internal/cause/Causes.java b/src/main/java/com/sk89q/worldguard/internal/cause/Causes.java deleted file mode 100644 index 45b09df2..00000000 --- a/src/main/java/com/sk89q/worldguard/internal/cause/Causes.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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.internal.cause; - -import org.bukkit.block.Block; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; - -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; - -/** - * Utility methods to handle {@code Cause}s. - */ -public final class Causes { - - private Causes() { - } - - /** - * Get the first player that is in the list of causes. - * - * @param causes a list of causes, where the originating causes are at the beginning - * @return the player or null - */ - @Nullable - public static Player getInvolvedPlayer(List> causes) { - for (Cause cause : causes) { - if (cause instanceof PlayerCause) { - return ((PlayerCause) cause).get(); - } - } - - return null; - } - - /** - * Test whether the list of causes may indicate that a player was part of - * the cause, directly or indirectly. - * - *

An indirect cause would be a dispenser, for example.

- * - * @param causes a list of cuases - * @return true if the event involved a player - */ - public static boolean mayInvolvePlayer(List> causes) { - for (Cause cause : causes) { - if (cause instanceof PlayerCause || cause instanceof BlockCause) { - return true; // This needs to be made smarter later - } - } - - return false; - } - - /** - * Create a list of causes from a list of objects representing causes. - * - * @param cause an array of causes, where the originating causes are at the beginning - * @return a list of causes, where the originating causes are at the beginning - */ - public static List> create(Object ... cause) { - List> causes = new ArrayList>(cause.length); - for (Object o : cause) { - if (o == null) { - continue; - } - - if (o instanceof Player) { - causes.add(new PlayerCause((Player) o)); - } else if (o instanceof Block) { - causes.add(new BlockCause((Block) o)); - } else if (o instanceof Entity) { - causes.add(new EntityCause((Entity) o)); - } else { - causes.add(new UnknownCause(o)); - } - } - return causes; - } - -} diff --git a/src/main/java/com/sk89q/worldguard/internal/cause/PlayerCause.java b/src/main/java/com/sk89q/worldguard/internal/cause/PlayerCause.java deleted file mode 100644 index 2b4e63f5..00000000 --- a/src/main/java/com/sk89q/worldguard/internal/cause/PlayerCause.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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.internal.cause; - -import org.bukkit.entity.Player; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * A cause that is the player. - */ -public class PlayerCause implements Cause { - - private final Player player; - - /** - * Create a new instance. - * - * @param player the player - */ - public PlayerCause(Player player) { - checkNotNull(player); - this.player = player; - } - - @Override - public Player get() { - return player; - } - -} diff --git a/src/main/java/com/sk89q/worldguard/internal/cause/UnknownCause.java b/src/main/java/com/sk89q/worldguard/internal/cause/UnknownCause.java deleted file mode 100644 index d811ac20..00000000 --- a/src/main/java/com/sk89q/worldguard/internal/cause/UnknownCause.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.internal.cause; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * A cause that is not known. - */ -public class UnknownCause implements Cause { - - private final Object cause; - - /** - * Create a new instance. - * - * @param cause the underlying object - */ - public UnknownCause(Object cause) { - checkNotNull(cause); - this.cause = cause; - } - - @Override - public Object get() { - return cause; - } - -} diff --git a/src/main/java/com/sk89q/worldguard/internal/event/Interaction.java b/src/main/java/com/sk89q/worldguard/internal/event/Interaction.java deleted file mode 100644 index 583eb4b6..00000000 --- a/src/main/java/com/sk89q/worldguard/internal/event/Interaction.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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.internal.event; - -/** - * Represents a possible act upon an object. - */ -public enum Interaction { - - PLACE, - BREAK, - INTERACT - -} diff --git a/src/main/java/com/sk89q/worldguard/internal/listener/BlacklistListener.java b/src/main/java/com/sk89q/worldguard/internal/listener/BlacklistListener.java deleted file mode 100644 index d750cfcd..00000000 --- a/src/main/java/com/sk89q/worldguard/internal/listener/BlacklistListener.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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.internal.listener; - -import com.sk89q.worldguard.blacklist.event.BlockBreakBlacklistEvent; -import com.sk89q.worldguard.blacklist.event.BlockPlaceBlacklistEvent; -import com.sk89q.worldguard.blacklist.event.ItemDestroyWithBlacklistEvent; -import com.sk89q.worldguard.bukkit.WorldConfiguration; -import com.sk89q.worldguard.bukkit.WorldGuardPlugin; -import com.sk89q.worldguard.internal.cause.Causes; -import com.sk89q.worldguard.internal.event.BlockInteractEvent; -import org.bukkit.block.Block; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; - -import static com.sk89q.worldguard.bukkit.BukkitUtil.createTarget; -import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector; - -/** - * Handle events that need to be processed by the blacklist. - */ -public class BlacklistListener extends AbstractListener { - - /** - * Construct the listener. - * - * @param plugin an instance of WorldGuardPlugin - */ - public BlacklistListener(WorldGuardPlugin plugin) { - super(plugin); - } - - @EventHandler(ignoreCancelled = true) - public void handleBlockInteract(BlockInteractEvent event) { - Player player = Causes.getInvolvedPlayer(event.getCauses()); - Block target = event.getTarget(); - WorldConfiguration wcfg = getWorldConfig(player); - - // Blacklist guard - if (wcfg.getBlacklist() == null) { - return; - } - - if (player != null) { - switch (event.getInteraction()) { - case BREAK: - if (!wcfg.getBlacklist().check( - new BlockBreakBlacklistEvent(getPlugin().wrapPlayer(player), toVector(target), createTarget(target)), false, false)) { - event.setCancelled(true); - return; - } - - if (!wcfg.getBlacklist().check( - new ItemDestroyWithBlacklistEvent(getPlugin().wrapPlayer(player), toVector(target), createTarget(player.getItemInHand())), false, false)) { - event.setCancelled(true); - return; - } - - break; - - case PLACE: - if (!wcfg.getBlacklist().check( - new BlockPlaceBlacklistEvent(getPlugin().wrapPlayer(player), toVector(target), createTarget(target)), false, false)) { - event.setCancelled(true); - return; - } - - break; - } - } - } - -} diff --git a/src/main/java/com/sk89q/worldguard/internal/listener/ChestProtectionListener.java b/src/main/java/com/sk89q/worldguard/internal/listener/ChestProtectionListener.java deleted file mode 100644 index c2e3c2d2..00000000 --- a/src/main/java/com/sk89q/worldguard/internal/listener/ChestProtectionListener.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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.internal.listener; - -import com.sk89q.worldguard.bukkit.WorldConfiguration; -import com.sk89q.worldguard.bukkit.WorldGuardPlugin; -import com.sk89q.worldguard.internal.cause.Causes; -import com.sk89q.worldguard.internal.event.Interaction; -import com.sk89q.worldguard.internal.event.BlockInteractEvent; -import org.bukkit.ChatColor; -import org.bukkit.block.Block; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; - -/** - * Handle events that need to be processed by the chest protection. - */ -public class ChestProtectionListener extends AbstractListener { - - /** - * Construct the listener. - * - * @param plugin an instance of WorldGuardPlugin - */ - public ChestProtectionListener(WorldGuardPlugin plugin) { - super(plugin); - } - - @EventHandler(ignoreCancelled = true) - public void handleBlockInteract(BlockInteractEvent event) { - Player player = Causes.getInvolvedPlayer(event.getCauses()); - Block target = event.getTarget(); - WorldConfiguration wcfg = getWorldConfig(player); - - // Early guard - if (!wcfg.signChestProtection) { - return; - } - - if (player != null) { - if (wcfg.isChestProtected(target, player)) { - player.sendMessage(ChatColor.DARK_RED + "This chest is protected."); - event.setCancelled(true); - return; - } - - if (event.getInteraction() == Interaction.PLACE) { - if (wcfg.getChestProtection().isChest(target.getTypeId())) { - if (wcfg.isAdjacentChestProtected(target, player)) { - player.sendMessage(ChatColor.DARK_RED + "This spot is for a chest that you don't have permission for."); - event.setCancelled(true); - return; - } - } - } - } - } - -} diff --git a/src/main/java/com/sk89q/worldguard/internal/listener/RegionProtectionListener.java b/src/main/java/com/sk89q/worldguard/internal/listener/RegionProtectionListener.java deleted file mode 100644 index bf9a526b..00000000 --- a/src/main/java/com/sk89q/worldguard/internal/listener/RegionProtectionListener.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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.internal.listener; - -import com.sk89q.worldguard.bukkit.WorldGuardPlugin; -import com.sk89q.worldguard.internal.cause.Causes; -import com.sk89q.worldguard.internal.event.Interaction; -import com.sk89q.worldguard.internal.event.BlockInteractEvent; -import org.bukkit.ChatColor; -import org.bukkit.block.Block; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; - -/** - * Handle events that need to be processed by region protection. - */ -public class RegionProtectionListener extends AbstractListener { - - /** - * Construct the listener. - * - * @param plugin an instance of WorldGuardPlugin - */ - public RegionProtectionListener(WorldGuardPlugin plugin) { - super(plugin); - } - - private void tellErrorMessage(CommandSender sender, Object subject) { - sender.sendMessage(ChatColor.DARK_RED + "You don't have permission for this area."); - } - - @EventHandler(ignoreCancelled = true) - public void handleBlockInteract(BlockInteractEvent event) { - Player player = Causes.getInvolvedPlayer(event.getCauses()); - Block target = event.getTarget(); - - if (player != null) { - if (!getPlugin().getGlobalRegionManager().canBuild(player, target)) { - tellErrorMessage(player, target); - event.setCancelled(true); - return; - } - - if (event.getInteraction() != Interaction.INTERACT) { - if (!getPlugin().getGlobalRegionManager().canConstruct(player, target)) { - tellErrorMessage(player, target); - event.setCancelled(true); - return; - } - } - } - } - -}