diff --git a/src/com/sk89q/worldguard/bukkit/SignChestProtection.java b/src/com/sk89q/worldguard/bukkit/SignChestProtection.java new file mode 100644 index 00000000..8f39e3e4 --- /dev/null +++ b/src/com/sk89q/worldguard/bukkit/SignChestProtection.java @@ -0,0 +1,125 @@ +// $Id$ +/* + * WorldGuard + * Copyright (C) 2010 sk89q + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +package com.sk89q.worldguard.bukkit; + +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; +import org.bukkit.block.Sign; +import org.bukkit.entity.Player; + +/** + * Utility class for sign chest protection. + * + * @author sk89q + */ +public class SignChestProtection { + + public boolean isProtected(Block block, Player player) { + if (isChest(block.getType())) { + Block below = block.getRelative(0, -1, 0); + return isProtectedSignAround(below, player); + } else if (block.getType() == Material.SIGN_POST) { + return isProtectedSignAndChestBinary(block, player); + } else { + Block above = block.getRelative(0, 1, 0); + Boolean res = isProtectedSign(above, player); + if (res != null) return res; + return false; + } + } + + private boolean isProtectedSignAround(Block searchBlock, Player player) { + Block side; + Boolean res; + + side = searchBlock; + res = isProtectedSign(side, player); + if (res != null) return res; + + side = searchBlock.getRelative(-1, 0, 0); + res = isProtectedSignAndChest(side, player); + if (res != null) return res; + + side = searchBlock.getRelative(1, 0, 0); + res = isProtectedSignAndChest(side, player); + if (res != null) return res; + + side = searchBlock.getRelative(0, 0, -1); + res = isProtectedSignAndChest(side, player); + if (res != null) return res; + + side = searchBlock.getRelative(0, 0, 1); + res = isProtectedSignAndChest(side, player); + if (res != null) return res; + + return false; + } + + private Boolean isProtectedSign(Sign sign, Player player) { + if (sign.getLine(0).equalsIgnoreCase("[Lock]")) { + if (player == null) { // No player, no access + return true; + } + + String name = player.getName(); + if (name.equalsIgnoreCase(sign.getLine(1).trim()) + || name.equalsIgnoreCase(sign.getLine(2).trim()) + || name.equalsIgnoreCase(sign.getLine(3).trim())) { + return false; + } + + // No access! + return true; + } + + return null; + } + + private Boolean isProtectedSign(Block block, Player player) { + BlockState state = block.getState(); + if (state == null || !(state instanceof Sign)) { + return null; + } + return isProtectedSign((Sign) state, player); + } + + private Boolean isProtectedSignAndChest(Block block, Player player) { + if (!isChest(block.getRelative(0, 1, 0).getType())) { + return null; + } + return isProtectedSign(block, player); + } + + private boolean isProtectedSignAndChestBinary(Block block, Player player) { + Boolean res = isProtectedSignAndChest(block, player); + if (res == null || res == false) { + return false; + } + return true; + } + + private boolean isChest(Material material) { + return material == Material.CHEST + || material == Material.DISPENSER + || material == Material.FURNACE + || material == Material.BURNING_FURNACE; + } +} diff --git a/src/com/sk89q/worldguard/bukkit/WorldConfiguration.java b/src/com/sk89q/worldguard/bukkit/WorldConfiguration.java index cfdfbeaf..cbd56789 100644 --- a/src/com/sk89q/worldguard/bukkit/WorldConfiguration.java +++ b/src/com/sk89q/worldguard/bukkit/WorldConfiguration.java @@ -31,7 +31,9 @@ import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; +import org.bukkit.block.Block; import org.bukkit.entity.CreatureType; +import org.bukkit.entity.Player; import org.bukkit.util.config.Configuration; /** @@ -52,6 +54,7 @@ public class WorldConfiguration { private File blacklistFile; private Blacklist blacklist; + private SignChestProtection chestProtection = new SignChestProtection(); /* Configuration data start */ public boolean fireSpreadDisableToggle; @@ -97,6 +100,7 @@ public class WorldConfiguration { public boolean claimOnlyInsideExistingRegions; public int maxRegionCountPerPlayer; public boolean antiWolfDumbness; + public boolean signChestProtection; /* Configuration data end */ @@ -169,6 +173,8 @@ private void loadConfiguration() { disableSuffocationDamage = config.getBoolean("player-damage.disable-suffocation-damage", false); disableContactDamage = config.getBoolean("player-damage.disable-contact-damage", false); teleportOnSuffocation = config.getBoolean("player-damage.teleport-on-suffocation", false); + + signChestProtection = config.getBoolean("chest-protection.enable", false); useRegions = config.getBoolean("regions.enable", true); highFreqFlags = config.getBoolean("regions.high-frequency-flags", false); @@ -288,5 +294,22 @@ public Blacklist getBlacklist() { public String getWorldName() { return this.worldName; } + + public boolean isChestProtected(Block block, Player player) { + if (!signChestProtection) { + return false; + } + if (plugin.hasPermission(player, "worldguard.chest-protection.override")) { + return false; + } + return chestProtection.isProtected(block, player); + } + + public boolean isChestProtected(Block block) { + if (!signChestProtection) { + return false; + } + return chestProtection.isProtected(block, null); + } } diff --git a/src/com/sk89q/worldguard/bukkit/WorldGuardBlockListener.java b/src/com/sk89q/worldguard/bukkit/WorldGuardBlockListener.java index 0382e063..9d7091da 100644 --- a/src/com/sk89q/worldguard/bukkit/WorldGuardBlockListener.java +++ b/src/com/sk89q/worldguard/bukkit/WorldGuardBlockListener.java @@ -25,6 +25,7 @@ import org.bukkit.plugin.PluginManager; import org.bukkit.block.Block; import org.bukkit.ChatColor; +import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.World; import org.bukkit.event.block.*; @@ -62,6 +63,7 @@ public void registerEvents() { pm.registerEvent(Event.Type.BLOCK_PHYSICS, this, Priority.Normal, plugin); pm.registerEvent(Event.Type.BLOCK_PLACE, this, Priority.High, plugin); pm.registerEvent(Event.Type.BLOCK_BURN, this, Priority.High, plugin); + pm.registerEvent(Event.Type.SIGN_CHANGE, this, Priority.High, plugin); pm.registerEvent(Event.Type.REDSTONE_CHANGE, this, Priority.High, plugin); } @@ -116,6 +118,12 @@ public void onBlockBreak(BlockBreakEvent event) { return; } } + + if (wcfg.isChestProtected(event.getBlock(), player)) { + player.sendMessage(ChatColor.DARK_RED + "The chest is protected."); + event.setCancelled(true); + return; + } } /** @@ -449,6 +457,60 @@ public void onBlockRedstoneChange(BlockRedstoneEvent event) { } } + /** + * Called when a sign is changed. + */ + @Override + public void onSignChange(SignChangeEvent event) { + + Player player = event.getPlayer(); + WorldConfiguration wcfg = getWorldConfig(player); + + if (wcfg.signChestProtection) { + if (event.getLine(0).equalsIgnoreCase("[Lock]")) { + if (event.getBlock().getType() != Material.SIGN_POST) { + player.sendMessage(ChatColor.RED + + "The [Lock] sign must be a sign post, not a wall sign."); + + dropSign(event.getBlock()); + event.setCancelled(true); + return; + } else if (!event.getLine(1).equalsIgnoreCase(player.getName())) { + player.sendMessage(ChatColor.RED + + "The first owner line must be your name."); + + dropSign(event.getBlock()); + event.setCancelled(true); + return; + } else { + event.setLine(1, "[Lock]"); + player.sendMessage(ChatColor.YELLOW + + "A chest or double chest above is now protected."); + } + } + } else { + if (event.getLine(0).equalsIgnoreCase("[Lock]")) { + player.sendMessage(ChatColor.RED + + "WorldGuard's sign chest protection is disabled."); + + dropSign(event.getBlock()); + event.setCancelled(true); + return; + } + } + } + + /** + * Drops a sign item and removes a sign. + * + * @param block + */ + private void dropSign(Block block) { + block.setTypeId(0); + block.getWorld().dropItemNaturally(block.getLocation(), + new ItemStack(Material.SIGN)); + } + /** * Remove water around a sponge. * diff --git a/src/com/sk89q/worldguard/bukkit/WorldGuardEntityListener.java b/src/com/sk89q/worldguard/bukkit/WorldGuardEntityListener.java index 009a1b33..38eb6b49 100644 --- a/src/com/sk89q/worldguard/bukkit/WorldGuardEntityListener.java +++ b/src/com/sk89q/worldguard/bukkit/WorldGuardEntityListener.java @@ -20,6 +20,7 @@ import com.sk89q.worldguard.protection.flags.DefaultFlag; import com.sk89q.worldguard.protection.managers.RegionManager; +import org.bukkit.block.Block; import org.bukkit.event.Event.Priority; import org.bukkit.event.Event; import org.bukkit.plugin.PluginManager; @@ -324,6 +325,15 @@ public void onEntityExplode(EntityExplodeEvent event) { } } } + + if (wcfg.signChestProtection) { + for (Block block : event.blockList()) { + if (wcfg.isChestProtected(block)) { + event.setCancelled(true); + return; + } + } + } } @Override diff --git a/src/com/sk89q/worldguard/bukkit/WorldGuardPlayerListener.java b/src/com/sk89q/worldguard/bukkit/WorldGuardPlayerListener.java index ce1a1bd8..4bebab52 100644 --- a/src/com/sk89q/worldguard/bukkit/WorldGuardPlayerListener.java +++ b/src/com/sk89q/worldguard/bukkit/WorldGuardPlayerListener.java @@ -243,6 +243,18 @@ public void handleBlockRightClick(PlayerInteractEvent event) { } } + if ((block.getType() == Material.CHEST + || block.getType() == Material.DISPENSER + || block.getType() == Material.FURNACE + || block.getType() == Material.BURNING_FURNACE)) { + + if (wcfg.isChestProtected(block, player)) { + player.sendMessage(ChatColor.DARK_RED + "The chest is protected."); + event.setCancelled(true); + return; + } + } + /*if (wcfg.useRegions && wcfg.useiConomy && cfg.getiConomy() != null && (type == Material.SIGN_POST || type == Material.SIGN || type == Material.WALL_SIGN)) { BlockState block = blockClicked.getState();