diff --git a/src/com/untamedears/citadel/NaturalReinforcementConfig.java b/src/com/untamedears/citadel/NaturalReinforcementConfig.java index 7d4bcdc1..cd519360 100644 --- a/src/com/untamedears/citadel/NaturalReinforcementConfig.java +++ b/src/com/untamedears/citadel/NaturalReinforcementConfig.java @@ -1,5 +1,9 @@ package com.untamedears.citadel; +import java.util.Random; +import java.util.List; +import java.util.ArrayList; + import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; @@ -14,6 +18,8 @@ public class NaturalReinforcementConfig { private int maxDurability_; private int variance_; private double yAdjustment_; + private List chipOptions; + private boolean disableNormalDrops; public NaturalReinforcementConfig(int materialId, int baseDurability) { setMaterialId(materialId); @@ -22,6 +28,8 @@ public NaturalReinforcementConfig(int materialId, int baseDurability) { maxDurability_ = MAX_DURABILITY; variance_ = 0; yAdjustment_ = 0.0; + disableNormalDrops = false; + chipOptions = new ArrayList(); } public NaturalReinforcementConfig(ConfigurationSection config) { @@ -39,6 +47,7 @@ public NaturalReinforcementConfig(ConfigurationSection config) { } } int baseDurability = config.getInt("durability", Integer.MIN_VALUE); + System.err.println(String.format("Natural reinforcement created on %s, durability %d", materialName, baseDurability)); if (baseDurability == Integer.MIN_VALUE) { throw new Error( "[Citadel] Unconfigured Natural Reinforcement Durability for " + @@ -49,6 +58,19 @@ public NaturalReinforcementConfig(ConfigurationSection config) { setMaxDurability(config.getInt("maximum", MAX_DURABILITY)); setVariance(config.getInt("variance", 0)); setYAdjustment(config.getDouble("yadjust", 0.00000001)); + disableNormalDrops = config.getBoolean("disableNormalDrops", false); + + // Configure chips dropped + chipOptions = new ArrayList(); + ConfigurationSection chipsConfig = config.getConfigurationSection("chipDrops"); + if (chipsConfig != null) { + for (String chipMaterialName : chipsConfig.getKeys(false)) { + ChipChance option = new ChipChance(); + option.probability = chipsConfig.getDouble(chipMaterialName, 0.0); + option.droppedItem = Material.matchMaterial(chipMaterialName); + chipOptions.add(option); + } + } } public int getMaterialId() { return materialId_; } @@ -103,4 +125,22 @@ public int generateDurability(int blockY) { } return durability; } + + public boolean getDisableNormalDrops() { + return disableNormalDrops; + } + + public Material generateChipDrop(Random random) { + for (ChipChance option : chipOptions) { + if (random.nextFloat() < option.probability) { + return option.droppedItem; + } + } + return null; + } + + private class ChipChance { + public double probability; + public Material droppedItem; + } } diff --git a/src/com/untamedears/citadel/Utility.java b/src/com/untamedears/citadel/Utility.java index c1f4de38..0da40f22 100644 --- a/src/com/untamedears/citadel/Utility.java +++ b/src/com/untamedears/citadel/Utility.java @@ -196,9 +196,9 @@ public static boolean maybeReinforcementDamaged(Block block) { } public static boolean reinforcementDamaged(IReinforcement reinforcement) { - reinforcement.setDurability(reinforcement.getDurability() - 1); - boolean cancelled = reinforcement.getDurability() > 0; - if (reinforcement.getDurability() <= 0) { + boolean isBroken = reinforcement.breakOnce(); + boolean cancelled = !isBroken; + if (!cancelled) { cancelled = reinforcementBroken(reinforcement); } else { if (reinforcement instanceof PlayerReinforcement) { diff --git a/src/com/untamedears/citadel/dao/CitadelCachingDao.java b/src/com/untamedears/citadel/dao/CitadelCachingDao.java index 7bd45e2d..bf4e8e44 100644 --- a/src/com/untamedears/citadel/dao/CitadelCachingDao.java +++ b/src/com/untamedears/citadel/dao/CitadelCachingDao.java @@ -345,7 +345,7 @@ public IReinforcement findReinforcement( Block block ){ } public IReinforcement save( IReinforcement r ){ - if (r.getDurability() <= 0) + if (r.isBroken()) { delete(r); return null; diff --git a/src/com/untamedears/citadel/entity/IReinforcement.java b/src/com/untamedears/citadel/entity/IReinforcement.java index ad4cd8dd..33854f72 100644 --- a/src/com/untamedears/citadel/entity/IReinforcement.java +++ b/src/com/untamedears/citadel/entity/IReinforcement.java @@ -7,9 +7,9 @@ public abstract interface IReinforcement extends public ReinforcementKey getId(); public void setId(ReinforcementKey id); public Block getBlock(); - public int getDurability(); - public void setDurability(int durability); public double getHealth(); public String getHealthText(); public String getStatus(); + public boolean isBroken(); + public boolean breakOnce(); } diff --git a/src/com/untamedears/citadel/entity/NaturalReinforcement.java b/src/com/untamedears/citadel/entity/NaturalReinforcement.java index 671e14d4..6c39d1ff 100644 --- a/src/com/untamedears/citadel/entity/NaturalReinforcement.java +++ b/src/com/untamedears/citadel/entity/NaturalReinforcement.java @@ -1,8 +1,13 @@ package com.untamedears.citadel.entity; import java.util.HashMap; +import java.util.Random; +import java.util.List; +import java.util.ArrayList; import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; import org.bukkit.block.Block; import com.untamedears.citadel.NaturalReinforcementConfig; @@ -16,15 +21,18 @@ public class NaturalReinforcement implements IReinforcement { new HashMap(); private ReinforcementKey id_; - private int durability_; + private boolean broken_; private int max_durability_; + private Random random; - public NaturalReinforcement() {} + public NaturalReinforcement() { + this.random = new Random(); + } - public NaturalReinforcement(Block block, int breakCount) { + public NaturalReinforcement(Block block, int max_durability) { this.id_ = new ReinforcementKey(block); - this.durability_ = breakCount; - this.max_durability_ = breakCount; + this.max_durability_ = max_durability; + this.random = new Random(); } public ReinforcementKey getId() { return id_; } @@ -41,34 +49,22 @@ public Block getBlock() { } } - public int getDurability() { return durability_; } - public void setDurability(int durability) { durability_ = durability; } - public int getMaxDurability() { return max_durability_; } public void setMaxDurability(int max_durability) { this.max_durability_ = max_durability; } public double getHealth() { - return (double) durability_ / (double) max_durability_; + return 1.0; } public String getHealthText() { - double health = getHealth(); - if (health > 0.75) { - return "excellently"; - } else if (health > 0.50) { - return "well"; - } else if (health > 0.25) { - return "decently"; - } else { - return "poorly"; - } + return "naturally"; } public String getStatus() { return getHealthText(); } @Override public String toString() { - return String.format("%s, durability: %d of %d", id_, durability_, max_durability_); + return String.format("%s, hardness %d", id_, max_durability_); } @Override @@ -88,4 +84,36 @@ public int compareTo(IReinforcement r) { public int hashCode() { return this.id_.hashCode(); } + + @Override + public boolean isBroken() { + return broken_; + } + + @Override + public boolean breakOnce() { + if (broken_) return true; + if (random.nextInt(max_durability_) == 0) { + broken_ = true; + } + return broken_; + } + + public List generateChipDrops() { + List result = new ArrayList(); + NaturalReinforcementConfig config = getConfig(); + if (config == null) { + return null; + } + + Material mat = getConfig().generateChipDrop(random); + if (mat != null) { + result.add(new ItemStack(mat, 1)); + } + return result; + } + + public NaturalReinforcementConfig getConfig() { + return NaturalReinforcement.CONFIGURATION.get(getBlock().getTypeId()); + } } diff --git a/src/com/untamedears/citadel/entity/PlayerReinforcement.java b/src/com/untamedears/citadel/entity/PlayerReinforcement.java index f3885e27..b51c08c0 100644 --- a/src/com/untamedears/citadel/entity/PlayerReinforcement.java +++ b/src/com/untamedears/citadel/entity/PlayerReinforcement.java @@ -253,6 +253,19 @@ public int hashCode() { return this.id.hashCode(); } + @Override + public boolean isBroken() { + return this.durability <= 0; + } + + @Override + public boolean breakOnce() { + if (!isBroken()) { + this.durability--; + } + return isBroken(); + } + public DbUpdateAction getDbAction() { return this.dbAction; } public void setDbAction(DbUpdateAction value) { this.dbAction = value; } } diff --git a/src/com/untamedears/citadel/listener/BlockListener.java b/src/com/untamedears/citadel/listener/BlockListener.java index ae308d19..4a2f7e7a 100644 --- a/src/com/untamedears/citadel/listener/BlockListener.java +++ b/src/com/untamedears/citadel/listener/BlockListener.java @@ -10,6 +10,7 @@ import java.util.ConcurrentModificationException; import java.util.HashSet; import java.util.Set; +import java.util.List; import org.bukkit.ChatColor; import org.bukkit.Location; @@ -28,6 +29,7 @@ import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.block.BlockRedstoneEvent; import org.bukkit.event.block.BlockPhysicsEvent; +import org.bukkit.enchantments.Enchantment; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import org.bukkit.material.MaterialData; @@ -88,6 +90,7 @@ public void placeFortifiedBlock(BlockPlaceEvent bpe) { public void blockBreak(BlockBreakEvent bbe) { Block block = bbe.getBlock(); Player player = bbe.getPlayer(); + List extraDrops = null; AccessDelegate delegate = AccessDelegate.getDelegate(block); IReinforcement reinforcement = delegate.getReinforcement(); @@ -115,6 +118,31 @@ public void blockBreak(BlockBreakEvent bbe) { // The player reinforcement broke. Now check for natural is_cancelled = createNaturalReinforcement(block) != null; } + } else if (reinforcement instanceof NaturalReinforcement) { + NaturalReinforcement natural = (NaturalReinforcement) reinforcement; + is_cancelled = reinforcementDamaged(reinforcement); + + // Check for silk touch and bypass all chip behaviour to avoid infinite mining + ItemStack tool = player.getItemInHand(); + boolean silkTouch = tool.containsEnchantment(Enchantment.SILK_TOUCH); + if (!silkTouch) { + if (is_cancelled) { + // Drop chips if not using silk touch + extraDrops = natural.generateChipDrops(); + if (extraDrops.size() > 0) { + tool.setDurability((short) (tool.getDurability() + 1)); + if (tool.getDurability() >= tool.getType().getMaxDurability()) { + player.setItemInHand(null); + } + } + } else { + // Block drops if told to and not using silk touch + if (natural.getConfig().getDisableNormalDrops()) { + bbe.setCancelled(true); + block.setType(Material.AIR); + } + } + } } else { is_cancelled = reinforcementDamaged(reinforcement); } @@ -123,6 +151,18 @@ public void blockBreak(BlockBreakEvent bbe) { bbe.setCancelled(true); block.getDrops().clear(); } + + if (extraDrops != null) { + Location centerOfBlock = block.getLocation().add(0.5, 0.5, 0.5); + Location playerHeadLocation = player.getLocation().add(0, 1, 0); + Location difference = playerHeadLocation.subtract(centerOfBlock); + // Drop 1 block in direction of player's head + Location dropPosition = centerOfBlock.add(difference.multiply(1.0 / difference.length())); + + for (ItemStack drop : extraDrops) { + block.getWorld().dropItemNaturally(dropPosition, drop); + } + } } @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH)