diff --git a/.classpath b/.classpath deleted file mode 100644 index a66543b7..00000000 --- a/.classpath +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index ee907c3b..00000000 --- a/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -encoding//src/com/untamedears/citadel/Citadel.java=UTF-8 diff --git a/Citadel.jar b/Citadel.jar deleted file mode 100644 index 27a9d078..00000000 Binary files a/Citadel.jar and /dev/null differ diff --git a/bin/META-INF/MANIFEST.MF b/bin/META-INF/MANIFEST.MF deleted file mode 100644 index 58630c02..00000000 --- a/bin/META-INF/MANIFEST.MF +++ /dev/null @@ -1,2 +0,0 @@ -Manifest-Version: 1.0 - diff --git a/config.yml b/config.yml index baf4708a..3412378d 100644 --- a/config.yml +++ b/config.yml @@ -4,7 +4,13 @@ general: autoModeReset: 30 redstoneDistance: 9 groupsAllowed: 60 + reinforceNormal: true + inaccessibleInfo: false materials: +- name: AIR + strength: 5 + requirements: 1 + flasher: GLASS - name: STONE strength: 25 requirements: 1 @@ -20,8 +26,14 @@ materials: additionalSecurable: - BED_BLOCK - BOOKSHELF +- JUKEBOX - BEACON +- HOPPER +- DROPPER +- TRAPPED_CHEST - ANVIL +- ENDER_CHEST +- MOB_SPAWNER nonReinforceable: - SAPLING - GRASS @@ -38,6 +50,7 @@ nonReinforceable: - SNOW - ICE - CACTUS +- CARROT - SUGAR_CANE_BLOCK - PORTAL - CAKE_BLOCK diff --git a/craftbukkit.jar b/craftbukkit.jar deleted file mode 100644 index daa6b556..00000000 Binary files a/craftbukkit.jar and /dev/null differ diff --git a/pom.xml b/pom.xml deleted file mode 100644 index fe77fe22..00000000 --- a/pom.xml +++ /dev/null @@ -1,73 +0,0 @@ - - 4.0.0 - - com.untamedears.citadel - citadel - 2.0-SNAPSHOT - jar - - Citadel - Bukkit Server Plugin - 2012 - - ${basedir}/src - - - maven-compiler-plugin - 2.3.2 - - 1.6 - 1.6 - - - - - - - CP1252 - - - - - org.bukkit - craftbukkit - 1.3.2-R1.0 - - - - - - - bukkit-repo - http://repo.bukkit.org/content/groups/public/ - - - - - - - - diff --git a/src/META-INF/MANIFEST.MF b/src/META-INF/MANIFEST.MF deleted file mode 100644 index 59499bce..00000000 --- a/src/META-INF/MANIFEST.MF +++ /dev/null @@ -1,2 +0,0 @@ -Manifest-Version: 1.0 - diff --git a/src/com/untamedears/citadel/ConfigManager.java b/src/com/untamedears/citadel/ConfigManager.java index 1578d99a..d4a25446 100644 --- a/src/com/untamedears/citadel/ConfigManager.java +++ b/src/com/untamedears/citadel/ConfigManager.java @@ -22,6 +22,8 @@ public class ConfigManager { private int autoModeReset; private boolean verboseLogging; private double redstoneDistance; + private boolean reinforceNormal; + private boolean inaccessibleInfo; private int groupsAllowed; private long cacheMaxAge; private int cacheMaxChunks; @@ -34,6 +36,8 @@ public void load(){ autoModeReset = config.getInt("general.autoModeReset"); verboseLogging = config.getBoolean("general.verboseLogging"); redstoneDistance = config.getDouble("general.redstoneDistance"); + reinforceNormal = config.getBoolean("general.reinforceNormal"); + inaccessibleInfo = config.getBoolean("general.inaccessibleInfo"); groupsAllowed = config.getInt("general.groupsAllowed"); cacheMaxAge = config.getLong("caching.max_age"); cacheMaxChunks = config.getInt("caching.max_chunks"); @@ -88,6 +92,22 @@ public double getRedstoneDistance(){ public void setRedstoneDistance(double rd){ this.redstoneDistance = rd; } + + public boolean getReinforceNormal(){ + return this.reinforceNormal; + } + + public void setReinforceNormal(boolean rn){ + this.reinforceNormal = rn; + } + + public boolean getInaccessibleInfo(){ + return this.inaccessibleInfo; + } + + public void setInaccessibleInfo(boolean ii){ + this.inaccessibleInfo = ii; + } public int getAutoModeReset(){ return this.autoModeReset; diff --git a/src/com/untamedears/citadel/Metrics.java b/src/com/untamedears/citadel/Metrics.java index 1b6f03ae..bd4ccd1f 100644 --- a/src/com/untamedears/citadel/Metrics.java +++ b/src/com/untamedears/citadel/Metrics.java @@ -360,7 +360,7 @@ private void postPlugin(final boolean isPing) throws IOException { data.append(encode("guid")).append('=').append(encode(guid)); encodeDataPair(data, "version", description.getVersion()); encodeDataPair(data, "server", Bukkit.getVersion()); - encodeDataPair(data, "players", Integer.toString(Bukkit.getServer().getOnlinePlayers().length)); + encodeDataPair(data, "players", Integer.toString(Bukkit.getServer().getOnlinePlayers().size())); encodeDataPair(data, "revision", String.valueOf(REVISION)); // If we're pinging, append it diff --git a/src/com/untamedears/citadel/Utility.java b/src/com/untamedears/citadel/Utility.java index 539a284b..50d099fc 100644 --- a/src/com/untamedears/citadel/Utility.java +++ b/src/com/untamedears/citadel/Utility.java @@ -6,6 +6,7 @@ import java.util.Map; import java.util.Random; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.DyeColor; import org.bukkit.Location; @@ -13,6 +14,7 @@ import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.command.CommandSender; +import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.material.MaterialData; @@ -45,13 +47,15 @@ public class Utility { } public static Block getAttachedChest(Block block) { - if (block.getType() == Material.CHEST) + Material mat = block.getType(); + if (mat == Material.CHEST || mat == Material.TRAPPED_CHEST) { for (BlockFace face : new BlockFace[]{BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST}) { Block b = block.getRelative(face); - if (b.getType() == Material.CHEST) { + if (b.getType() == mat) { return b; } } + } return null; } @@ -68,12 +72,12 @@ public static IReinforcement createNaturalReinforcement(Block block) { return nr; } - public static IReinforcement createPlayerReinforcement(Player player, Block block) { + public static IReinforcement createPlayerReinforcement(final Player player, Block block) { int blockTypeId = block.getTypeId(); if (PlayerReinforcement.NON_REINFORCEABLE.contains(blockTypeId)) return null; PlayerState state = PlayerState.get(player); - ReinforcementMaterial material; + final ReinforcementMaterial material; switch (state.getMode()) { case REINFORCEMENT: case REINFORCEMENT_SINGLE_BLOCK: @@ -88,56 +92,114 @@ public static IReinforcement createPlayerReinforcement(Player player, Block bloc case FORTIFICATION: material = state.getReinforcementMaterial(); break; + case NORMAL: + case INFO: + material = ReinforcementMaterial.get(Material.AIR); + break; default: return null; } - if (player.getInventory().contains(material.getMaterial(), material.getRequirements())) { - Faction group = state.getFaction(); - if(group == null){ - try { - group = Citadel.getMemberManager().getMember(player.getDisplayName()).getPersonalGroup(); - } catch (NullPointerException e){ - sendMessage(player, ChatColor.RED, "You don't seem to have a personal group. Try logging out and back in first"); - } - } + // get group + Faction group = state.getFaction(); + if(group == null){ + try { + group = Citadel.getMemberManager().getMember(player.getDisplayName()).getPersonalGroup(); + } catch (NullPointerException e){ + sendMessage(player, ChatColor.RED, "You don't seem to have a personal group. Try logging out and back in first"); + return null; + } + } - // workaround fix for 1.4.6, it doesnt remove the placed item if its already removed for some reason? - if ((state.getMode() == PlacementMode.FORTIFICATION) && (blockTypeId == material.getMaterialId())) { - ItemStack stack = player.getItemInHand(); - if (stack.getAmount() < material.getRequirements() + 1) { - sendMessage(player, ChatColor.RED, "Not enough material in hand to place and fortify this block"); - return null; - } - stack.setAmount(stack.getAmount() - (material.getRequirements() + 1)); - player.setItemInHand(stack); - } - else { - player.getInventory().removeItem(material.getRequiredMaterials()); - } - //TODO: there will eventually be a better way to flush inventory changes to the client - player.updateInventory(); - PlayerReinforcement reinforcement = new PlayerReinforcement(block, material, group, state.getSecurityLevel()); - reinforcement = (PlayerReinforcement)Citadel.getReinforcementManager().addReinforcement(reinforcement); - String securityLevelText = state.getSecurityLevel().name(); - if(securityLevelText.equalsIgnoreCase("group")){ - securityLevelText = securityLevelText + "-" + state.getFaction().getName(); - } - sendThrottledMessage(player, ChatColor.GREEN, "Reinforced with %s at security level %s", material.getMaterial().name(), securityLevelText); - Citadel.warning(String.format("PlRein:%s:%d@%s,%d,%d,%d", - player.getName(), material.getMaterialId(), block.getWorld().getName(), block.getX(), block.getY(), block.getZ())); - // TODO: enable chained flashers, they're pretty cool - //new BlockFlasher(block, material.getFlasher()).start(getPlugin()); - //new BlockFlasher(block, material.getFlasher()).chain(securityMaterial.get(state.getSecurityLevel())).start(); - return reinforcement; - } else { - return null; + // decrement material if its not air + if(material.getMaterial() != Material.AIR) + { + if (player.getInventory().contains(material.getMaterial(), material.getRequirements())) + { + Bukkit.getScheduler().scheduleSyncDelayedTask(Citadel.getPlugin(), new Runnable() + { + public void run() { + player.getInventory().removeItem(material.getRequiredMaterials()); + //TODO: there will eventually be a better way to flush inventory changes to the client + player.updateInventory(); + } + }, 1); + } + else + { + return null; + } + } + + // create the reinforcement + PlayerReinforcement reinforcement = new PlayerReinforcement(block, material, group, state.getSecurityLevel()); + reinforcement = (PlayerReinforcement)Citadel.getReinforcementManager().addReinforcement(reinforcement); + + // inform them if not in normal mode + if(state.getMode() != PlacementMode.NORMAL) + { + String securityLevelText = state.getSecurityLevel().name(); + if(securityLevelText.equalsIgnoreCase("group")){ + securityLevelText = securityLevelText + "-" + state.getFaction().getName(); + } + sendThrottledMessage(player, ChatColor.GREEN, String.format("Reinforced with %s at security level %s", material.getMaterial().name(), securityLevelText).replace("with AIR", "by hand")); } + + //Citadel.warning(String.format("PlRein:%s:%d@%s,%d,%d,%d", + // player.getName(), material.getMaterialId(), block.getWorld().getName(), block.getX(), block.getY(), block.getZ())); + // TODO: enable chained flashers, they're pretty cool + //new BlockFlasher(block, material.getFlasher()).start(getPlugin()); + //new BlockFlasher(block, material.getFlasher()).chain(securityMaterial.get(state.getSecurityLevel())).start(); + return reinforcement; } public static void sendMessage(CommandSender sender, ChatColor color, String messageFormat, Object... params) { sender.sendMessage(color + String.format(messageFormat, params)); } + + public static void damagePlayerTool(final Player player) { + if(player == null) { + return; + } + + if(player.getItemInHand() == null) { + return; + } + + switch(player.getItemInHand().getType()) { + case WOOD_PICKAXE: + case WOOD_AXE: + case WOOD_SPADE: + + case GOLD_PICKAXE: + case GOLD_AXE: + case GOLD_SPADE: + + case STONE_PICKAXE: + case STONE_AXE: + case STONE_SPADE: + + case IRON_PICKAXE: + case IRON_AXE: + case IRON_SPADE: + + case DIAMOND_PICKAXE: + case DIAMOND_AXE: + case DIAMOND_SPADE: + Bukkit.getScheduler().scheduleSyncDelayedTask(Citadel.getPlugin(), new Runnable() { + public void run() { + ItemStack hand = player.getItemInHand(); + + int unbreak = hand.getEnchantmentLevel(Enchantment.DURABILITY); + if(rng.nextDouble() < 1/(unbreak+1)) + { + hand.setDurability((short)(hand.getDurability() + 1)); // not sure why this is backwards, but it is + player.setItemInHand(hand.getDurability() > hand.getType().getMaxDurability() ? null : hand); + } + } + }, 0); + } + } public static void sendThrottledMessage(CommandSender sender, ChatColor color, String messageFormat, Object... params) { if (sender instanceof Player) { @@ -164,7 +226,7 @@ public static boolean explodeReinforcement(Block block) { } public static boolean maybeReinforcementDamaged(Block block) { - AccessDelegate delegate = AccessDelegate.getDelegate(block); + AccessDelegate delegate = AccessDelegate.getDelegate(block); IReinforcement reinforcement = delegate.getReinforcement(); return reinforcement != null && reinforcementDamaged(reinforcement); } @@ -192,7 +254,10 @@ public static boolean reinforcementBroken(IReinforcement reinforcement) { if (rng.nextDouble() <= pr.getHealth()) { Location location = pr.getBlock().getLocation(); ReinforcementMaterial material = pr.getMaterial(); - location.getWorld().dropItem(location, material.getRequiredMaterials()); + if(material.getMaterial() != Material.AIR) + { + location.getWorld().dropItem(location, material.getRequiredMaterials()); + } } return pr.isSecurable(); } diff --git a/src/com/untamedears/citadel/access/AccessDelegate.java b/src/com/untamedears/citadel/access/AccessDelegate.java index 88c52ab6..bd90d247 100644 --- a/src/com/untamedears/citadel/access/AccessDelegate.java +++ b/src/com/untamedears/citadel/access/AccessDelegate.java @@ -19,11 +19,11 @@ public abstract class AccessDelegate { public static AccessDelegate getDelegate(Block block) { MaterialData data = block.getState().getData(); - if (data instanceof Door) { - return new DoorAccessDelegate(block, (Door) data); - } else if (data instanceof Bed) { + if (DoorAccessDelegate.canDelegate(block, data)) { + return new DoorAccessDelegate(block, data); + } else if (BedAccessDelegate.canDelegate(block, data)) { return new BedAccessDelegate(block, (Bed) data); - } else if (block.getType() == Material.CHEST) { + } else if (ChestAccessDelegate.canDelegate(block, data)) { return new ChestAccessDelegate(block, data); } else { return new AccessDelegate(block, data) { @@ -45,11 +45,11 @@ protected void delegate() { public AccessDelegate(Block block, T data) { this.block = block; this.data = data; - + if (shouldDelegate()) { - Citadel.info("Attempted interaction with %s block at " + block.getLocation().toString()); + Citadel.info("Attempted interaction with " + block.getType() + " block at " + block.getLocation().toString()); delegate(); - Citadel.info("Delegated to %s block at " + block.getLocation().toString()); + Citadel.info("Delegated to " + this.block.getType() + " block at " + this.block.getLocation().toString()); } } diff --git a/src/com/untamedears/citadel/access/BedAccessDelegate.java b/src/com/untamedears/citadel/access/BedAccessDelegate.java index 08b3eb90..d6120532 100644 --- a/src/com/untamedears/citadel/access/BedAccessDelegate.java +++ b/src/com/untamedears/citadel/access/BedAccessDelegate.java @@ -1,7 +1,9 @@ package com.untamedears.citadel.access; +import org.bukkit.block.Block; import org.bukkit.block.Block; import org.bukkit.material.Bed; +import org.bukkit.material.MaterialData; /** * Created by IntelliJ IDEA. @@ -10,6 +12,9 @@ * Time: 3:24 PM */ public class BedAccessDelegate extends AccessDelegate { + public static boolean canDelegate(Block block, MaterialData data) { + return (data instanceof Bed); + } public BedAccessDelegate(Block block, Bed data) { super(block, data); } diff --git a/src/com/untamedears/citadel/access/ChestAccessDelegate.java b/src/com/untamedears/citadel/access/ChestAccessDelegate.java index 79ec0d1f..9f4de856 100644 --- a/src/com/untamedears/citadel/access/ChestAccessDelegate.java +++ b/src/com/untamedears/citadel/access/ChestAccessDelegate.java @@ -1,5 +1,6 @@ package com.untamedears.citadel.access; +import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.material.MaterialData; @@ -12,6 +13,10 @@ * Time: 3:27 PM */ public class ChestAccessDelegate extends AccessDelegate { + public static boolean canDelegate(Block block, MaterialData data) { + final Material mat = block.getType(); + return mat.equals(Material.CHEST) || mat.equals(Material.TRAPPED_CHEST); + } private Block attachedChest; diff --git a/src/com/untamedears/citadel/access/DoorAccessDelegate.java b/src/com/untamedears/citadel/access/DoorAccessDelegate.java index d33f0f96..b20cedf1 100644 --- a/src/com/untamedears/citadel/access/DoorAccessDelegate.java +++ b/src/com/untamedears/citadel/access/DoorAccessDelegate.java @@ -1,22 +1,41 @@ package com.untamedears.citadel.access; +import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; -import org.bukkit.material.Door; +import org.bukkit.material.MaterialData; /** * Created by IntelliJ IDEA. * User: chrisrico * Date: 3/23/12 * Time: 3:26 PM */ -public class DoorAccessDelegate extends AccessDelegate { - public DoorAccessDelegate(Block block, Door data) { +public class DoorAccessDelegate extends AccessDelegate { + public static boolean canDelegate(Block block, MaterialData data) { + return isDoorType(block.getType()); + } + public DoorAccessDelegate(Block block, MaterialData data) { super(block, data); } + + public static boolean isDoorType(Material mat) { + switch(mat) { + case WOOD_DOOR: + case WOODEN_DOOR: + case ACACIA_DOOR: + case SPRUCE_DOOR: + case JUNGLE_DOOR: + case DARK_OAK_DOOR: + case BIRCH_DOOR: + return true; + default: + return false; + } + } @Override protected boolean shouldDelegate() { - return data.isTopHalf(); + return isDoorType(block.getRelative(BlockFace.DOWN).getType()); } @Override diff --git a/src/com/untamedears/citadel/command/commands/ConsoleCommands.java b/src/com/untamedears/citadel/command/commands/ConsoleCommands.java index f1542b85..2974c145 100644 --- a/src/com/untamedears/citadel/command/commands/ConsoleCommands.java +++ b/src/com/untamedears/citadel/command/commands/ConsoleCommands.java @@ -61,6 +61,9 @@ public boolean GetConfig(ConsoleCommandSender sender, String[] args) { } else if (settingName.equalsIgnoreCase("redstoneDistance")) { sendMessage(sender, ChatColor.YELLOW, "redstoneDistance == " + cm.getRedstoneDistance()); + } else if (settingName.equalsIgnoreCase("reinforceNormal")) { + sendMessage(sender, ChatColor.YELLOW, "reinforceNormal == " + cm.getReinforceNormal()); + } else if (settingName.equalsIgnoreCase("groupsAllowed")) { sendMessage(sender, ChatColor.YELLOW, "groupsAllowed == " + cm.getGroupsAllowed()); @@ -98,6 +101,9 @@ public boolean SetConfig(ConsoleCommandSender sender, String[] args) { } else if (settingName.equalsIgnoreCase("redstoneDistance")) { cm.setRedstoneDistance(Double.parseDouble(value)); + } else if (settingName.equalsIgnoreCase("reinforceNormal")) { + cm.setReinforceNormal(Boolean.parseBoolean(value)); + } else if (settingName.equalsIgnoreCase("groupsAllowed")) { cm.setGroupsAllowed(Integer.parseInt(value)); diff --git a/src/com/untamedears/citadel/dao/CitadelDao.java b/src/com/untamedears/citadel/dao/CitadelDao.java index 62bdaedd..8e95b49e 100644 --- a/src/com/untamedears/citadel/dao/CitadelDao.java +++ b/src/com/untamedears/citadel/dao/CitadelDao.java @@ -80,7 +80,12 @@ protected List> getDatabaseClasses() { } public Object save(Object object) { - getDatabase().save(object); + try { + getDatabase().save(object); + } + catch(PersistenceException e) { + // probably placing fortified block where fortified air already exists + } return object; } diff --git a/src/com/untamedears/citadel/entity/IReinforcement.java b/src/com/untamedears/citadel/entity/IReinforcement.java index ad4cd8dd..2b755c1c 100644 --- a/src/com/untamedears/citadel/entity/IReinforcement.java +++ b/src/com/untamedears/citadel/entity/IReinforcement.java @@ -12,4 +12,5 @@ public abstract interface IReinforcement extends public double getHealth(); public String getHealthText(); public String getStatus(); + public int getMaterialId(); } diff --git a/src/com/untamedears/citadel/entity/NaturalReinforcement.java b/src/com/untamedears/citadel/entity/NaturalReinforcement.java index 671e14d4..4751b7a7 100644 --- a/src/com/untamedears/citadel/entity/NaturalReinforcement.java +++ b/src/com/untamedears/citadel/entity/NaturalReinforcement.java @@ -84,6 +84,10 @@ public int compareTo(IReinforcement r) { return this.id_.compareTo(r.getId()); } + public int getMaterialId() { + return -1; + } + @Override public int hashCode() { return this.id_.hashCode(); diff --git a/src/com/untamedears/citadel/entity/PlayerReinforcement.java b/src/com/untamedears/citadel/entity/PlayerReinforcement.java index f3885e27..93c8a974 100644 --- a/src/com/untamedears/citadel/entity/PlayerReinforcement.java +++ b/src/com/untamedears/citadel/entity/PlayerReinforcement.java @@ -16,8 +16,8 @@ import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.block.Block; -import org.bukkit.block.ContainerBlock; import org.bukkit.entity.Player; +import org.bukkit.inventory.InventoryHolder; import org.bukkit.material.Openable; import com.untamedears.citadel.Citadel; @@ -182,7 +182,7 @@ public String getStatus() { return String.format("%s %s with %s", verb, getHealthText(), - getMaterial().getMaterial().name()); + getMaterial().getMaterial().name()).replace(" with AIR", " by hand"); } public boolean isAccessible(Player player) { @@ -225,7 +225,7 @@ public boolean isBypassable(Player player) { public boolean isSecurable() { Block block = getBlock(); - return block.getState() instanceof ContainerBlock + return block.getState() instanceof InventoryHolder || block.getState().getData() instanceof Openable || SECURABLE.contains(block.getTypeId()); } diff --git a/src/com/untamedears/citadel/entity/PlayerState.java b/src/com/untamedears/citadel/entity/PlayerState.java index 60013fce..a3c78aec 100644 --- a/src/com/untamedears/citadel/entity/PlayerState.java +++ b/src/com/untamedears/citadel/entity/PlayerState.java @@ -39,8 +39,8 @@ public static void remove(Player player) { private Integer cancelModePid; public PlayerState(Player player) { - reset(); this.player = player; + reset(); bypassMode = false; } @@ -50,7 +50,8 @@ public PlayerState(Player player) { public void reset() { mode = PlacementMode.NORMAL; fortificationMaterial = null; - securityLevel = SecurityLevel.PUBLIC; + securityLevel = SecurityLevel.PRIVATE; + setFaction(Citadel.getMemberManager().getMember(player).getPersonalGroup()); } public PlacementMode getMode() { diff --git a/src/com/untamedears/citadel/listener/BlockListener.java b/src/com/untamedears/citadel/listener/BlockListener.java index ae308d19..175f92d4 100644 --- a/src/com/untamedears/citadel/listener/BlockListener.java +++ b/src/com/untamedears/citadel/listener/BlockListener.java @@ -6,10 +6,13 @@ import static com.untamedears.citadel.Utility.reinforcementBroken; import static com.untamedears.citadel.Utility.reinforcementDamaged; import static com.untamedears.citadel.Utility.sendMessage; +import static com.untamedears.citadel.Utility.sendThrottledMessage; +import static com.untamedears.citadel.Utility.damagePlayerTool; +import java.util.Arrays; +import java.util.Collection; import java.util.ConcurrentModificationException; -import java.util.HashSet; -import java.util.Set; +import java.util.List; import org.bukkit.ChatColor; import org.bukkit.Location; @@ -17,7 +20,11 @@ import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; +import org.bukkit.block.DoubleChest; +import org.bukkit.block.Hopper; +import org.bukkit.entity.Minecart; import org.bukkit.entity.Player; +import org.bukkit.entity.minecart.HopperMinecart; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; @@ -28,6 +35,9 @@ import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.block.BlockRedstoneEvent; import org.bukkit.event.block.BlockPhysicsEvent; +import org.bukkit.event.inventory.InventoryMoveItemEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import org.bukkit.material.MaterialData; @@ -37,17 +47,56 @@ import org.bukkit.World; import com.untamedears.citadel.Citadel; -import com.untamedears.citadel.PlacementMode; import com.untamedears.citadel.SecurityLevel; import com.untamedears.citadel.access.AccessDelegate; import com.untamedears.citadel.entity.PlayerState; import com.untamedears.citadel.entity.IReinforcement; -import com.untamedears.citadel.entity.NaturalReinforcement; import com.untamedears.citadel.entity.PlayerReinforcement; import com.untamedears.citadel.entity.ReinforcementMaterial; +import net.sacredlabyrinth.Phaed.PreciousStones.PreciousStones; + public class BlockListener implements Listener { + public static final List planar_sides = Arrays.asList( + BlockFace.NORTH, BlockFace.SOUTH, BlockFace.WEST, BlockFace.EAST); + + private boolean canPlace(Block block, String player_name) { + Material block_mat = block.getType(); + + // check that a hopper isn't placed under another persons protected chest + if (block_mat == Material.HOPPER){ + Block above = block.getRelative(BlockFace.UP); + if (above.getState() instanceof InventoryHolder) { + IReinforcement rein = AccessDelegate.getDelegate(above).getReinforcement(); + if (null != rein && rein instanceof PlayerReinforcement) { + PlayerReinforcement pr = (PlayerReinforcement)rein; + if (!pr.isAccessible(player_name)) { + return false; + } + } + } + } + + // check that a chest isn't placed next to another persons protected chest + if (block_mat == Material.CHEST || block_mat == Material.TRAPPED_CHEST){ + for (BlockFace direction : planar_sides) { + Block adjacent = block.getRelative(direction); + if (!(adjacent.getState() instanceof InventoryHolder)) { + continue; + } + IReinforcement rein = AccessDelegate.getDelegate(adjacent).getReinforcement(); + if (null != rein && rein instanceof PlayerReinforcement) { + PlayerReinforcement pr = (PlayerReinforcement)rein; + if (!pr.isAccessible(player_name)) { + return false; + } + } + } + } + return true; + } + /** * This handles the BlockPlaceEvent for Fortification mode (all placed blocks are reinforced) * @@ -56,22 +105,43 @@ public class BlockListener implements Listener { @EventHandler(ignoreCancelled = true) public void placeFortifiedBlock(BlockPlaceEvent bpe) { Player player = bpe.getPlayer(); + Block block = bpe.getBlockPlaced(); + + if(!canPlace(block, player.getName())) { + sendThrottledMessage(player, ChatColor.RED, "Cancelled block place, mismatched reinforcement."); + bpe.setCancelled(true); + return; + } + PlayerState state = PlayerState.get(player); - if (state.getMode() != PlacementMode.FORTIFICATION) { - // if we are not in fortification mode - // cancel event if we are not in normal mode - if (state.getMode() == PlacementMode.REINFORCEMENT || state.getMode() == PlacementMode.REINFORCEMENT_SINGLE_BLOCK) - bpe.setCancelled(true); + switch (state.getMode()) + { + case NORMAL: + case INFO: + if(Citadel.getConfigManager().getReinforceNormal() == true) + { + createPlayerReinforcement(player, block); + } + return; + + case FORTIFICATION: + break; + + case REINFORCEMENT: + case REINFORCEMENT_SINGLE_BLOCK: + bpe.setCancelled(true); return; + + default: + return; } - Block block = bpe.getBlockPlaced(); PlayerInventory inventory = player.getInventory(); ReinforcementMaterial material = state.getReinforcementMaterial(); ItemStack required = material.getRequiredMaterials(); - if (inventory.contains(material.getMaterial(), required.getAmount())) { + if (material.getMaterialId() == 0 || inventory.contains(material.getMaterial(), required.getAmount())) { if (createPlayerReinforcement(player, block) == null) { sendMessage(player, ChatColor.RED, "%s is not a reinforcible material", block.getType().name()); } else { @@ -89,12 +159,15 @@ public void blockBreak(BlockBreakEvent bbe) { Block block = bbe.getBlock(); Player player = bbe.getPlayer(); - AccessDelegate delegate = AccessDelegate.getDelegate(block); - IReinforcement reinforcement = delegate.getReinforcement(); + IReinforcement reinforcement = AccessDelegate.getDelegate(block).getReinforcement(); if (reinforcement == null) { reinforcement = createNaturalReinforcement(block); if (reinforcement != null && reinforcementDamaged(reinforcement)) { - bbe.setCancelled(true); + if (block != null && player != null) { + PreciousStones.getInstance().getSnitchManager().recordSnitchBlockBreak(player, block); + } + damagePlayerTool(player); + bbe.setCancelled(true); block.getDrops().clear(); } return; @@ -104,7 +177,7 @@ public void blockBreak(BlockBreakEvent bbe) { if (reinforcement instanceof PlayerReinforcement) { PlayerReinforcement pr = (PlayerReinforcement)reinforcement; PlayerState state = PlayerState.get(player); - if (state.isBypassMode() && pr.isBypassable(player)) { + if (pr.isBypassable(player) && (state.isBypassMode() || pr.getMaterialId() == 0)) { Citadel.info(player.getDisplayName() + " bypassed reinforcement %s at " + pr.getBlock().getLocation().toString()); is_cancelled = reinforcementBroken(reinforcement); @@ -120,40 +193,99 @@ public void blockBreak(BlockBreakEvent bbe) { } if (is_cancelled) { - bbe.setCancelled(true); + if (block != null && player != null) { + PreciousStones.getInstance().getSnitchManager().recordSnitchBlockBreak(player, block); + } + damagePlayerTool(player); + bbe.setCancelled(true); block.getDrops().clear(); } } + public PlayerReinforcement getReinforcement(InventoryHolder holder) { + // Returns reinforcement of the inventory's holder or null if none exists + Location loc; + if (holder instanceof DoubleChest) { + loc = ((DoubleChest)holder).getLocation(); + } else if (holder instanceof BlockState) { + loc = ((BlockState)holder).getLocation(); + } else if (holder instanceof Minecart) { + // Vehicle inventories (should get the track?) + loc = ((Minecart)holder).getLocation(); + } else { + return null; + } + IReinforcement reinforcement = AccessDelegate.getDelegate(loc.getBlock()).getReinforcement(); + if (null != reinforcement && reinforcement instanceof PlayerReinforcement) { + PlayerReinforcement pr = (PlayerReinforcement)reinforcement; + // Treat public reinforcements as if they don't exist + if (!pr.getSecurityLevel().equals(SecurityLevel.PUBLIC)) { + return pr; + } + } + return null; + } + + @EventHandler(ignoreCancelled = true) + public void hopperTransfer(InventoryMoveItemEvent e) { + + try { + InventoryHolder taker = e.getDestination().getHolder(); + PlayerReinforcement takerRein = getReinforcement(taker); + InventoryHolder giver = e.getSource().getHolder(); + PlayerReinforcement giverRein = getReinforcement(giver); + + if(giverRein == null) { + // feeding from unowned block always allowed + Citadel.info("allowing public giver"); + return; + } + + if(takerRein == null) { + // unowned takers never allowed + Citadel.info("disallowing public taker"); + e.setCancelled(true); + return; + } + + if(takerRein.getOwner() == giverRein.getOwner()) { + Citadel.info("allowing same owner named " + takerRein.getOwner().getName()); + return; + } + + if(giverRein.isAccessible(takerRein.getOwner().getName())) { + Citadel.info("allowing allowed taker named " + takerRein.getOwner().getName()); + return; + } + + } catch(Exception er) { + Citadel.warning("error handling hopperTransfer, disallowing"); + Citadel.printStackTrace(er); + } + + // by default deny + Citadel.info("disallowing by default"); + e.setCancelled(true); + } + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH) - public void pistonExtend(BlockPistonExtendEvent bpee) { - Block piston = bpee.getBlock(); - BlockState state = piston.getState(); - MaterialData data = state.getData(); - BlockFace direction = null; - - if (data instanceof PistonBaseMaterial) { - direction = ((PistonBaseMaterial) data).getFacing(); - } + public void pistonExtend(BlockPistonExtendEvent bpee) + { + for(Block block : bpee.getBlocks()) + { + IReinforcement reinforcement = AccessDelegate.getDelegate(block).getReinforcement(); - // if no direction was found, no point in going on - if (direction == null) - return; - - // Check the affected blocks - for (int i = 1; i < bpee.getLength() + 2; i++) { - Block block = piston.getRelative(direction, i); - - if (block.getType() == Material.AIR){ - break; - } - - AccessDelegate delegate = AccessDelegate.getDelegate(block); - IReinforcement reinforcement = delegate.getReinforcement(); - - if (reinforcement != null){ - bpee.setCancelled(true); - break; + if (reinforcement != null) + { + if(reinforcement.getMaterialId() == 0) + { + reinforcementBroken(reinforcement); + } + else + { + bpee.setCancelled(true); + break; + } } } } @@ -164,7 +296,7 @@ public void pistonRetract(BlockPistonRetractEvent bpre) { BlockState state = piston.getState(); MaterialData data = state.getData(); BlockFace direction = null; - + // Check the block it pushed directly if (data instanceof PistonBaseMaterial) { direction = ((PistonBaseMaterial) data).getFacing(); @@ -179,54 +311,63 @@ public void pistonRetract(BlockPistonRetractEvent bpre) { AccessDelegate delegate = AccessDelegate.getDelegate(moved); IReinforcement reinforcement = delegate.getReinforcement(); - if (reinforcement != null) { - bpre.setCancelled(true); + if (reinforcement != null) + { + if(reinforcement.getMaterialId() == 0) + { + reinforcementBroken(reinforcement); + } + else + { + bpre.setCancelled(true); + } } + } - private static final Material matfire = Material.FIRE; @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH) public void blockBurn(BlockBurnEvent bbe) { boolean wasprotected = maybeReinforcementDamaged(bbe.getBlock()); if (wasprotected) { bbe.setCancelled(wasprotected); - Block block = bbe.getBlock(); - // Basic essential fire protection - if (block.getRelative(0,1,0).getType() == matfire) {block.getRelative(0,1,0).setTypeId(0);} // Essential - // Extended fire protection (recommend) - if (block.getRelative(1,0,0).getType() == matfire) {block.getRelative(1,0,0).setTypeId(0);} - if (block.getRelative(-1,0,0).getType() == matfire) {block.getRelative(-1,0,0).setTypeId(0);} - if (block.getRelative(0,-1,0).getType() == matfire) {block.getRelative(0,-1,0).setTypeId(0);} - if (block.getRelative(0,0,1).getType() == matfire) {block.getRelative(0,0,1).setTypeId(0);} - if (block.getRelative(0,0,-1).getType() == matfire) {block.getRelative(0,0,-1).setTypeId(0);} - // Aggressive fire protection (would seriously reduce effectiveness of flint down to near the "you'd have to use it 25 times" mentality) - /* - if (block.getRelative(1,1,0).getType() == matfire) {block.getRelative(1,1,0).setTypeId(0);} - if (block.getRelative(1,-1,0).getType() == matfire) {block.getRelative(1,-1,0).setTypeId(0);} - if (block.getRelative(-1,1,0).getType() == matfire) {block.getRelative(-1,1,0).setTypeId(0);} - if (block.getRelative(-1,-1,0).getType() == matfire) {block.getRelative(-1,-1,0).setTypeId(0);} - if (block.getRelative(0,1,1).getType() == matfire) {block.getRelative(0,1,1).setTypeId(0);} - if (block.getRelative(0,-1,1).getType() == matfire) {block.getRelative(0,-1,1).setTypeId(0);} - if (block.getRelative(0,1,-1).getType() == matfire) {block.getRelative(0,1,-1).setTypeId(0);} - if (block.getRelative(0,-1,-1).getType() == matfire) {block.getRelative(0,-1,-1).setTypeId(0);} - */ + Block block = bbe.getBlock(); + Block rblock; + // super aggressive fire protection! suppress all fire within a 5 block cube around the fire + for(int x = -2; x <= 2; x++) { + for(int y = -2; y <= 2; y++) { + for(int z = -2; z <= 2; z++) { + rblock = block.getRelative(x,y,z); + switch(rblock.getType()) { + case FIRE: + rblock.setType(Material.AIR); + break; + + case LAVA: + case STATIONARY_LAVA: + rblock.setType(Material.COBBLESTONE); + break; + } + } + } + } + } } - } + @EventHandler(ignoreCancelled = true, priority = EventPriority.LOW) public void blockPhysics(BlockPhysicsEvent bpe) { Material changedType = bpe.getChangedType(); - if (Material.LAVA == changedType) { + if (Material.LAVA == changedType || Material.WATER == changedType) { Block block = bpe.getBlock(); - // Protection for reinforced rails types from lava. Similar to water, transform surrounding blocks in cobblestone to stop the lava effect. + // Protection for reinforced rails types from lava and water. Similar to water/lava, transform surrounding blocks in cobblestone or obsidian to stop the lava/water effect. if (Material.RAILS == block.getType() || Material.POWERED_RAIL == block.getType() || Material.DETECTOR_RAIL == block.getType()) { boolean isReinforced = maybeReinforcementDamaged(block); if (isReinforced) { - for (BlockFace blockFace : new BlockFace[]{BlockFace.DOWN, BlockFace.UP, BlockFace.EAST, BlockFace.WEST, BlockFace.NORTH, BlockFace.SOUTH}) { + for (final BlockFace blockFace : new BlockFace[]{BlockFace.DOWN, BlockFace.UP, BlockFace.EAST, BlockFace.WEST, BlockFace.NORTH, BlockFace.SOUTH}) { Block otherBlock = block.getRelative(blockFace); - if (Material.LAVA == otherBlock.getType()) { - otherBlock.setType(Material.COBBLESTONE); - otherBlock.getWorld().playEffect(otherBlock.getLocation(), Effect.EXTINGUISH, 0); + if (Material.LAVA == otherBlock.getType() || Material.WATER == otherBlock.getType()) { + otherBlock.setType(Material.COBBLESTONE); + otherBlock.getWorld().playEffect(otherBlock.getLocation(), Effect.EXTINGUISH, 0); } } } @@ -276,7 +417,7 @@ public void redstonePower(BlockRedstoneEvent bre) { double max_z = blockLocation.getZ() + redstoneDistance; World blockWorld = blockLocation.getWorld(); //Set onlinePlayers = new HashSet(Citadel.getMemberManager().getOnlinePlayers()); - Player[] onlinePlayers = Citadel.getPlugin().getServer().getOnlinePlayers(); + Collection onlinePlayers = Citadel.getPlugin().getServer().getOnlinePlayers(); boolean isAuthorizedPlayerNear = false; try { for (Player player : onlinePlayers) { diff --git a/src/com/untamedears/citadel/listener/EntityListener.java b/src/com/untamedears/citadel/listener/EntityListener.java index dcf509a5..c0fd215f 100644 --- a/src/com/untamedears/citadel/listener/EntityListener.java +++ b/src/com/untamedears/citadel/listener/EntityListener.java @@ -54,7 +54,9 @@ public void breakDoor(EntityBreakDoorEvent ebde) { @EventHandler(ignoreCancelled = true) public void changeBlock(EntityChangeBlockEvent ecbe) { - ecbe.setCancelled(maybeReinforcementDamaged(ecbe.getBlock())); + if(ecbe.getEntityType() != EntityType.FALLING_BLOCK) { + ecbe.setCancelled(maybeReinforcementDamaged(ecbe.getBlock())); + } } @EventHandler(ignoreCancelled = true) diff --git a/src/com/untamedears/citadel/listener/PlayerListener.java b/src/com/untamedears/citadel/listener/PlayerListener.java index 8c26db08..14586da2 100644 --- a/src/com/untamedears/citadel/listener/PlayerListener.java +++ b/src/com/untamedears/citadel/listener/PlayerListener.java @@ -96,7 +96,7 @@ public void bookshelf(PlayerInteractEvent pie) { @EventHandler(ignoreCancelled = true, priority = EventPriority.LOW) public void bucketEmpty(PlayerBucketEmptyEvent pbee) { Material bucket = pbee.getBucket(); - if (Material.LAVA_BUCKET == bucket) { + if (Material.LAVA_BUCKET == bucket || Material.WATER_BUCKET == bucket) { Block block = pbee.getBlockClicked(); BlockFace face = pbee.getBlockFace(); Block relativeBlock = block.getRelative(face); @@ -108,7 +108,7 @@ public void bucketEmpty(PlayerBucketEmptyEvent pbee) { } } - @EventHandler(priority = EventPriority.HIGHEST) + @EventHandler(priority = EventPriority.HIGH) public void interact(PlayerInteractEvent pie) { try { if (!pie.hasBlock()) return; @@ -164,7 +164,14 @@ public void interact(PlayerInteractEvent pie) { } sendMessage(player, ChatColor.GREEN, message); } else { - sendMessage(player, ChatColor.RED, "%s, security: %s", reinforcementStatus, securityLevel); + if(Citadel.getConfigManager().getInaccessibleInfo()) + { + sendMessage(player, ChatColor.RED, "%s, security: %s", reinforcementStatus, securityLevel); + } + else + { + sendMessage(player, ChatColor.RED, "%s is %s", block.getType().name(), reinforcement.isSecurable() ? "locked" : "reinforced"); + } } } break; @@ -177,26 +184,34 @@ public void interact(PlayerInteractEvent pie) { } createPlayerReinforcement(player, block); } else if (reinforcement.isBypassable(player)) { - boolean update = false; - String message = ""; - if (reinforcement.getSecurityLevel() != state.getSecurityLevel()){ - reinforcement.setSecurityLevel(state.getSecurityLevel()); - update = true; - message = String.format("Changed security level %s", reinforcement.getSecurityLevel().name()); + if(reinforcement.getMaterialId() == 0) + { + reinforcementBroken(reinforcement); + createPlayerReinforcement(player, block); } - if(!reinforcement.getOwner().equals(state.getFaction())) { - reinforcement.setOwner(state.getFaction()); - update = true; - if(!message.equals("")){ - message = message + ". "; + else + { + boolean update = false; + String message = ""; + if (reinforcement.getSecurityLevel() != state.getSecurityLevel()){ + reinforcement.setSecurityLevel(state.getSecurityLevel()); + update = true; + message = String.format("Changed security level %s", reinforcement.getSecurityLevel().name()); } - if(reinforcement.getSecurityLevel() != SecurityLevel.PRIVATE){ - message = message + String.format("Changed group to %s", state.getFaction().getName()); + if(!reinforcement.getOwner().equals(state.getFaction())) { + reinforcement.setOwner(state.getFaction()); + update = true; + if(!message.equals("")){ + message = message + ". "; + } + if(reinforcement.getSecurityLevel() != SecurityLevel.PRIVATE){ + message = message + String.format("Changed group to %s", state.getFaction().getName()); + } + } + if(update){ + Citadel.getReinforcementManager().addReinforcement(reinforcement); + sendMessage(player, ChatColor.GREEN, message); } - } - if(update){ - Citadel.getReinforcementManager().addReinforcement(reinforcement); - sendMessage(player, ChatColor.GREEN, message); } } else { sendMessage(player, ChatColor.RED, "You are not permitted to modify this reinforcement"); diff --git a/src/com/untamedears/citadel/task/BlockFlasher.java b/src/com/untamedears/citadel/task/BlockFlasher.java index 615864c3..aaef939a 100644 --- a/src/com/untamedears/citadel/task/BlockFlasher.java +++ b/src/com/untamedears/citadel/task/BlockFlasher.java @@ -2,8 +2,8 @@ import org.bukkit.block.Block; import org.bukkit.block.BlockState; -import org.bukkit.block.ContainerBlock; import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; import org.bukkit.material.MaterialData; @@ -65,8 +65,8 @@ private void revert() { } private void setCleanupTask() { - if (originalState instanceof ContainerBlock) { - final Inventory inventory = ((ContainerBlock) originalState).getInventory(); + if (originalState instanceof InventoryHolder) { + final Inventory inventory = ((InventoryHolder) originalState).getInventory(); final ItemStack[] contents = inventory.getContents(); cleanupTask = new Runnable() { public void run() {