瀏覽代碼

Merge branch 'master' of https://github.com/mcMMO-Dev/mcMMO

Glitchfinder 12 年之前
父節點
當前提交
660e68b0a3
共有 23 個文件被更改,包括 289 次插入258 次删除
  1. 4 3
      src/main/java/com/gmail/nossr50/listeners/BlockListener.java
  2. 0 1
      src/main/java/com/gmail/nossr50/mcMMO.java
  3. 4 4
      src/main/java/com/gmail/nossr50/skills/acrobatics/Acrobatics.java
  4. 5 7
      src/main/java/com/gmail/nossr50/skills/acrobatics/AcrobaticsEventHandler.java
  5. 14 17
      src/main/java/com/gmail/nossr50/skills/acrobatics/AcrobaticsManager.java
  6. 1 7
      src/main/java/com/gmail/nossr50/skills/acrobatics/DodgeEventHandler.java
  7. 1 10
      src/main/java/com/gmail/nossr50/skills/acrobatics/RollEventHandler.java
  8. 3 4
      src/main/java/com/gmail/nossr50/skills/archery/Archery.java
  9. 3 5
      src/main/java/com/gmail/nossr50/skills/archery/ArcheryBonusDamageEventHandler.java
  10. 1 1
      src/main/java/com/gmail/nossr50/skills/gathering/Excavation.java
  11. 2 1
      src/main/java/com/gmail/nossr50/skills/gathering/Fishing.java
  12. 5 4
      src/main/java/com/gmail/nossr50/skills/gathering/Herbalism.java
  13. 9 4
      src/main/java/com/gmail/nossr50/skills/mining/BlastMining.java
  14. 14 103
      src/main/java/com/gmail/nossr50/skills/mining/Mining.java
  15. 54 0
      src/main/java/com/gmail/nossr50/skills/mining/MiningBlockEventHandler.java
  16. 0 39
      src/main/java/com/gmail/nossr50/skills/mining/MiningDropsBlockHandler.java
  17. 33 10
      src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java
  18. 123 0
      src/main/java/com/gmail/nossr50/skills/mining/SuperBreakerEventHandler.java
  19. 0 30
      src/main/java/com/gmail/nossr50/skills/repair/Repair.java
  20. 0 3
      src/main/java/com/gmail/nossr50/util/Database.java
  21. 11 1
      src/main/java/com/gmail/nossr50/util/Misc.java
  22. 0 2
      src/main/java/com/gmail/nossr50/util/Permissions.java
  23. 2 2
      src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/HashChunkManager.java

+ 4 - 3
src/main/java/com/gmail/nossr50/listeners/BlockListener.java

@@ -30,7 +30,6 @@ import com.gmail.nossr50.events.fake.FakePlayerAnimationEvent;
 import com.gmail.nossr50.runnables.StickyPistonTracker;
 import com.gmail.nossr50.skills.gathering.Excavation;
 import com.gmail.nossr50.skills.gathering.Herbalism;
-import com.gmail.nossr50.skills.mining.Mining;
 import com.gmail.nossr50.skills.mining.MiningManager;
 import com.gmail.nossr50.skills.gathering.WoodCutting;
 import com.gmail.nossr50.skills.repair.Repair;
@@ -357,15 +356,17 @@ public class BlockListener implements Listener {
             }
         }
         else if (profile.getAbilityMode(AbilityType.SUPER_BREAKER) && Skills.triggerCheck(player, block, AbilityType.SUPER_BREAKER)) {
+            MiningManager manager = new MiningManager(player);
+
             if (configInstance.getMiningRequiresTool()) {
                 if (ItemChecks.isPickaxe(inHand)) {
                     event.setInstaBreak(true);
-                    Mining.superBreakerBlockCheck(player, block);
+                    manager.superBreakerBlockCheck(block);
                 }
             }
             else {
                 event.setInstaBreak(true);
-                Mining.superBreakerBlockCheck(player, block);
+                manager.superBreakerBlockCheck(block);
             }
         }
         else if (profile.getSkillLevel(SkillType.WOODCUTTING) >= LEAF_BLOWER_LEVEL && (material.equals(Material.LEAVES) || (configInstance.getBlockModsEnabled() && ModChecks.isCustomLeafBlock(block)))) {

+ 0 - 1
src/main/java/com/gmail/nossr50/mcMMO.java

@@ -83,7 +83,6 @@ import com.gmail.nossr50.util.blockmeta.chunkmeta.ChunkManagerFactory;
 
 
 public class mcMMO extends JavaPlugin {
-
     private final PlayerListener playerListener = new PlayerListener(this);
     private final BlockListener blockListener = new BlockListener(this);
     private final EntityListener entityListener = new EntityListener(this);

+ 4 - 4
src/main/java/com/gmail/nossr50/skills/acrobatics/Acrobatics.java

@@ -5,7 +5,9 @@ import java.util.Random;
 import com.gmail.nossr50.config.AdvancedConfig;
 
 public class Acrobatics {
-    static AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
+    private static AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
+    private static Random random = new Random();
+
     public static final int DODGE_MAX_CHANCE = advancedConfig.getDodgeChanceMax();
     public static final int DODGE_MAX_BONUS_LEVEL = advancedConfig.getDodgeMaxBonusLevel();
     public static final int DODGE_XP_MODIFIER = advancedConfig.getDodgeXPModifier();
@@ -18,9 +20,7 @@ public class Acrobatics {
     public static final int ROLL_XP_MODIFIER = advancedConfig.getRollXPModifier();
     public static final int FALL_XP_MODIFIER = advancedConfig.getFallXPModifier();
 
-    private static Random random = new Random();
-
-    public static Random getRandom() {
+    protected static Random getRandom() {
         return random;
     }
 }

+ 5 - 7
src/main/java/com/gmail/nossr50/skills/acrobatics/AcrobaticsEventHandler.java

@@ -3,6 +3,8 @@ package com.gmail.nossr50.skills.acrobatics;
 import org.bukkit.entity.Player;
 import org.bukkit.event.entity.EntityDamageEvent;
 
+import com.gmail.nossr50.util.Misc;
+
 public abstract class AcrobaticsEventHandler {
     protected AcrobaticsManager manager;
     protected Player player;
@@ -51,14 +53,10 @@ public abstract class AcrobaticsEventHandler {
      * @return true if the damage is fatal, false otherwise
      */
     protected boolean isFatal(int damage) {
-        if(player == null)
-            return true;
-
-        if (player.getHealth() - damage < 1) {
+        if (Misc.isCitizensNPC(player) || player.getHealth() - damage < 1) {
             return true;
         }
-        else {
-            return false;
-        }
+
+        return false;
     }
 }

+ 14 - 17
src/main/java/com/gmail/nossr50/skills/acrobatics/AcrobaticsManager.java

@@ -6,10 +6,13 @@ import org.bukkit.event.entity.EntityDamageEvent;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.datatypes.SkillType;
+import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.Users;
 
 public class AcrobaticsManager {
+    private static Config config = Config.getInstance();
+
     private Player player;
     private PlayerProfile profile;
     private int skillLevel;
@@ -26,29 +29,28 @@ public class AcrobaticsManager {
      * @param event The event to check
      */
     public void rollCheck(EntityDamageEvent event) {
-        if(player == null)
-            return;
-
-        if (!Permissions.roll(player)) {
+        if (Misc.isCitizensNPC(player) || !Permissions.roll(player)) {
             return;
         }
 
-        if(Config.getInstance().getAcrobaticsAFKDisabled() && player.isInsideVehicle())
+        if (config.getAcrobaticsAFKDisabled() && player.isInsideVehicle()) {
             return;
+        }
 
         RollEventHandler eventHandler = new RollEventHandler(this, event);
 
         int randomChance = 100;
-
         if (Permissions.luckyAcrobatics(player)) {
             randomChance = (int) (randomChance * 0.75);
         }
 
-        float chance = (float) (((double) Acrobatics.ROLL_MAX_CHANCE / (double) Acrobatics.ROLL_MAX_BONUS_LEVEL) * skillLevel);
-        if (chance > Acrobatics.ROLL_MAX_CHANCE) chance = Acrobatics.ROLL_MAX_CHANCE;
+        float chance;
+
         if (eventHandler.isGraceful) {
-        	chance = (float) (((double) Acrobatics.GRACEFUL_MAX_CHANCE / (double) Acrobatics.GRACEFUL_MAX_BONUS_LEVEL) * skillLevel);
-        	if (chance > Acrobatics.GRACEFUL_MAX_CHANCE) chance = Acrobatics.GRACEFUL_MAX_CHANCE;
+            chance = ((float) Acrobatics.GRACEFUL_MAX_CHANCE / Acrobatics.GRACEFUL_MAX_BONUS_LEVEL) * eventHandler.skillModifier;
+        }
+        else {
+            chance = ((float) Acrobatics.ROLL_MAX_CHANCE / Acrobatics.ROLL_MAX_BONUS_LEVEL) * eventHandler.skillModifier;
         }
 
         if (chance > Acrobatics.getRandom().nextInt(randomChance) && !eventHandler.isFatal(eventHandler.modifiedDamage)) {
@@ -67,23 +69,18 @@ public class AcrobaticsManager {
      * @param event The event to check
      */
     public void dodgeCheck(EntityDamageEvent event) {
-        if(player == null)
-            return;
-
-        if (!Permissions.dodge(player)) {
+        if (Misc.isCitizensNPC(player) || !Permissions.dodge(player)) {
             return;
         }
 
         DodgeEventHandler eventHandler = new DodgeEventHandler(this, event);
 
         int randomChance = 100;
-
         if (Permissions.luckyAcrobatics(player)) {
             randomChance = (int) (randomChance * 0.75);
         }
 
-        float chance = (float) (((double) Acrobatics.DODGE_MAX_CHANCE / (double) Acrobatics.DODGE_MAX_BONUS_LEVEL) * skillLevel);
-        if (chance > Acrobatics.DODGE_MAX_CHANCE) chance = Acrobatics.DODGE_MAX_CHANCE;
+        float chance = ((float) Acrobatics.DODGE_MAX_CHANCE / Acrobatics.DODGE_MAX_BONUS_LEVEL) * eventHandler.skillModifier;
 
         if (chance > Acrobatics.getRandom().nextInt(randomChance) && !eventHandler.isFatal(eventHandler.modifiedDamage)) {
             eventHandler.modifyEventDamage();

+ 1 - 7
src/main/java/com/gmail/nossr50/skills/acrobatics/DodgeEventHandler.java

@@ -39,20 +39,14 @@ public class DodgeEventHandler extends AcrobaticsEventHandler {
 
     @Override
     protected void sendAbilityMessage() {
-        if(player == null)
-            return;
-
         player.sendMessage(LocaleLoader.getString("Acrobatics.Combat.Proc"));
     }
 
     @Override
     protected void processXPGain(int xp) {
-        if(player == null)
-            return;
-
         PlayerProfile profile = manager.getProfile();
 
-        if (System.currentTimeMillis() >= profile.getRespawnATS() + 5) {
+        if (System.currentTimeMillis() >= profile.getRespawnATS() + Misc.PLAYER_RESPAWN_COOLDOWN_SECONDS) {
             Skills.xpProcessing(player, profile, SkillType.ACROBATICS, xp);
         }
     }

+ 1 - 10
src/main/java/com/gmail/nossr50/skills/acrobatics/RollEventHandler.java

@@ -9,7 +9,7 @@ import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.Skills;
 
 public class RollEventHandler extends AcrobaticsEventHandler {
-    public boolean isGraceful;
+    protected boolean isGraceful;
     private int damageThreshold;
 
     protected RollEventHandler(AcrobaticsManager manager, EntityDamageEvent event) {
@@ -56,9 +56,6 @@ public class RollEventHandler extends AcrobaticsEventHandler {
 
     @Override
     protected void sendAbilityMessage() {
-        if(player == null)
-            return;
-
         if (isGraceful) {
             player.sendMessage(LocaleLoader.getString("Acrobatics.Ability.Proc"));
         }
@@ -70,9 +67,6 @@ public class RollEventHandler extends AcrobaticsEventHandler {
 
     @Override
     protected void processXPGain(int xpGain) {
-        if(player == null)
-            return;
-
         Skills.xpProcessing(player, manager.getProfile(), SkillType.ACROBATICS, xpGain);
     }
 
@@ -80,9 +74,6 @@ public class RollEventHandler extends AcrobaticsEventHandler {
      * Check if this is a graceful roll.
      */
     private void isGracefulRoll() {
-        if(player == null)
-            return;
-
         if (Permissions.gracefulRoll(player)) {
             this.isGraceful = player.isSneaking();
         }

+ 3 - 4
src/main/java/com/gmail/nossr50/skills/archery/Archery.java

@@ -13,7 +13,7 @@ import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.util.Misc;
 
 public class Archery {
-    static AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
+    private static AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
     private static Random random = new Random();
     private static List<TrackedEntity> trackedEntities = new ArrayList<TrackedEntity>();
 
@@ -30,14 +30,13 @@ public class Archery {
 
     protected static void incrementTrackerValue(LivingEntity livingEntity) {
         for (TrackedEntity trackedEntity : trackedEntities) {
-            if (trackedEntity.getLivingEntity() == livingEntity) {
+            if (trackedEntity.getLivingEntity().getEntityId() == livingEntity.getEntityId()) {
                 trackedEntity.incrementArrowCount();
                 return;
             }
         }
 
-        //If the entity isn't tracked yet
-        addToTracker(livingEntity);
+        addToTracker(livingEntity); //If the entity isn't tracked yet
     }
 
     protected static void addToTracker(LivingEntity livingEntity) {

+ 3 - 5
src/main/java/com/gmail/nossr50/skills/archery/ArcheryBonusDamageEventHandler.java

@@ -14,13 +14,11 @@ public class ArcheryBonusDamageEventHandler {
     }
 
     protected void calculateDamageBonus() {
-        double damageBonus = ((manager.getSkillLevel() / Archery.BONUS_DAMAGE_INCREASE_LEVEL) * Archery.BONUS_DAMAGE_INCREASE_PERCENT);
+        this.damageBonusPercent = ((manager.getSkillLevel() / Archery.BONUS_DAMAGE_INCREASE_LEVEL) * Archery.BONUS_DAMAGE_INCREASE_PERCENT);
 
-        if (damageBonus > Archery.BONUS_DAMAGE_MAX_BONUS_PERCENTAGE) {
-            damageBonus = Archery.BONUS_DAMAGE_MAX_BONUS_PERCENTAGE;
+        if (damageBonusPercent > Archery.BONUS_DAMAGE_MAX_BONUS_PERCENTAGE) {
+            damageBonusPercent = Archery.BONUS_DAMAGE_MAX_BONUS_PERCENTAGE;
         }
-
-        this.damageBonusPercent = damageBonus;
     }
 
     protected void modifyEventDamage() {

+ 1 - 1
src/main/java/com/gmail/nossr50/skills/gathering/Excavation.java

@@ -133,7 +133,7 @@ public class Excavation {
 
         Skills.abilityDurabilityLoss(player.getItemInHand(), Config.getInstance().getAbilityToolDamage());
 
-        if (!mcMMO.placeStore.isTrue(block) && !Misc.blockBreakSimulate(block, player, true)) {
+        if (!mcMMO.placeStore.isTrue(block) && Misc.blockBreakSimulate(block, player, true)) {
             FakePlayerAnimationEvent armswing = new FakePlayerAnimationEvent(player);
             mcMMO.p.getServer().getPluginManager().callEvent(armswing);
 

+ 2 - 1
src/main/java/com/gmail/nossr50/skills/gathering/Fishing.java

@@ -5,6 +5,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Random;
 
+import org.bukkit.DyeColor;
 import org.bukkit.Location;
 import org.bukkit.Material;
 import org.bukkit.enchantments.Enchantment;
@@ -404,7 +405,7 @@ public class Fishing {
 
             case SQUID:
                 ItemStack item = new ItemStack(Material.INK_SACK, 1, (short) 0);
-                item.setData(new MaterialData(Material.INK_SACK, (byte) 0x0));
+                item.setData(new MaterialData(Material.INK_SACK, DyeColor.BLACK.getDyeData()));
 
                 Misc.dropItem(location, item);
                 break;

+ 5 - 4
src/main/java/com/gmail/nossr50/skills/gathering/Herbalism.java

@@ -3,6 +3,7 @@ package com.gmail.nossr50.skills.gathering;
 import java.util.Random;
 
 import org.bukkit.CropState;
+import org.bukkit.DyeColor;
 import org.bukkit.Location;
 import org.bukkit.Material;
 import org.bukkit.block.Block;
@@ -268,7 +269,7 @@ public class Herbalism {
             }
             else {
                 if (mat == Material.COCOA) {
-                    is = new ItemStack(Material.INK_SACK, 1, (short) 3);
+                    is = new ItemStack(Material.INK_SACK, 1, DyeColor.BROWN.getDyeData());
                 }
                 else if (mat == Material.CARROT) {
                     is = new ItemStack(Material.CARROT_ITEM, 1, (short) 0);
@@ -421,7 +422,7 @@ public class Herbalism {
             break;
         case COCOA:
             // Broken: Requires an update to bukkit to enable seaching for variable-sized ItemStacks.
-            hasSeeds = inventory.contains(new ItemStack(Material.INK_SACK, 1, (short) 3), 1);
+            hasSeeds = inventory.contains(new ItemStack(Material.INK_SACK, 1, DyeColor.BROWN.getDyeData()), 1);
             break;
         case CARROT:
             hasSeeds = inventory.contains(Material.CARROT_ITEM);
@@ -455,8 +456,8 @@ public class Herbalism {
                 inventory.removeItem(new ItemStack(Material.SEEDS));
                 break;
             case COCOA:
-                Misc.dropItem(location, new ItemStack(Material.INK_SACK, 3, (short) 3));
-                inventory.removeItem(new ItemStack(Material.INK_SACK, 1, (short) 3));
+                Misc.dropItem(location, new ItemStack(Material.INK_SACK, 3, DyeColor.BROWN.getDyeData()));
+                inventory.removeItem(new ItemStack(Material.INK_SACK, 1, DyeColor.BROWN.getDyeData()));
                 break;
             case CARROT:
                 Misc.dropItem(location, new ItemStack(Material.CARROT_ITEM));

+ 9 - 4
src/main/java/com/gmail/nossr50/skills/mining/BlastMining.java

@@ -7,6 +7,7 @@ import java.util.List;
 import java.util.Random;
 
 import org.bukkit.ChatColor;
+import org.bukkit.Location;
 import org.bukkit.Material;
 import org.bukkit.block.Block;
 import org.bukkit.entity.Player;
@@ -57,15 +58,17 @@ public class BlastMining {
 
         while (oresIterator.hasNext()) {
             Block temp = oresIterator.next();
+            Location tempLocation = temp.getLocation();
+            Material tempType = temp.getType();
 
             if (random.nextFloat() < (yield + oreBonus)) {
                 blocksDropped.add(temp);
-                Mining.miningDrops(temp);
+                Mining.miningDrops(temp, tempLocation, tempType);
 
                 if (!mcMMO.placeStore.isTrue(temp)) {
                     for (int i = 1 ; i < extraDrops ; i++) {
                         blocksDropped.add(temp);
-                        Mining.miningDrops(temp);
+                        Mining.miningDrops(temp, tempLocation, tempType);
                     }
                 }
             }
@@ -76,9 +79,11 @@ public class BlastMining {
 
             while (debrisIterator.hasNext()) {
                 Block temp = debrisIterator.next();
+                Location tempLocation = temp.getLocation();
+                Material tempType = temp.getType();
 
                 if (random.nextFloat() < (yield - debrisReduction))
-                    Mining.miningDrops(temp);
+                    Mining.miningDrops(temp, tempLocation, tempType);
             }
         }
 
@@ -173,7 +178,7 @@ public class BlastMining {
 
         for (Block block : xp) {
             if (!mcMMO.placeStore.isTrue(block)) {
-                Mining.miningXP(player, block);
+                Mining.miningXP(player, Users.getProfile(player), block, block.getType());
             }
         }
     }

+ 14 - 103
src/main/java/com/gmail/nossr50/skills/mining/Mining.java

@@ -3,26 +3,22 @@ package com.gmail.nossr50.skills.mining;
 import java.util.Random;
 
 import org.bukkit.CoalType;
+import org.bukkit.DyeColor;
 import org.bukkit.Location;
 import org.bukkit.Material;
 import org.bukkit.block.Block;
 import org.bukkit.entity.Player;
 import org.bukkit.inventory.ItemStack;
 import org.bukkit.material.MaterialData;
-import org.getspout.spoutapi.sound.SoundEffect;
 
-import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.datatypes.SkillType;
 import com.gmail.nossr50.datatypes.mods.CustomBlock;
-import com.gmail.nossr50.events.fake.FakePlayerAnimationEvent;
-import com.gmail.nossr50.spout.SpoutSounds;
 import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.ModChecks;
 import com.gmail.nossr50.util.Skills;
-import com.gmail.nossr50.util.Users;
 
 public class Mining {
     private static AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
@@ -32,16 +28,17 @@ public class Mining {
     public static final int DOUBLE_DROPS_MAX_BONUS_LEVEL = advancedConfig.getMiningDoubleDropMaxLevel();
     public static final int DOUBLE_DROPS_MAX_CHANCE = advancedConfig.getMiningDoubleDropChance();
 
+    public static final int DIAMOND_TOOL_TIER = 4;
+    public static final int IRON_TOOL_TIER = 3;
+    public static final int STONE_TOOL_TIER = 2;
+
     /**
      * Award XP for Mining blocks.
      *
      * @param player The player to award XP to
      * @param block The block to award XP for
      */
-    public static void miningXP(Player player, Block block) {
-        PlayerProfile profile = Users.getProfile(player);
-        Material type = block.getType();
-        
+     protected static void miningXP(Player player, PlayerProfile profile, Block block, Material type) {
         int xp = 0;
 
         switch (type) {
@@ -112,99 +109,14 @@ public class Mining {
         Skills.xpProcessing(player, profile, SkillType.MINING, xp);
     }
 
-    /**
-     * Handle the Super Breaker ability.
-     *
-     * @param player The player using the ability
-     * @param block The block being affected
-     */
-    public static void superBreakerBlockCheck(Player player, Block block) {
-        Material type = block.getType();
-        int tier = Misc.getTier(player.getItemInHand());
-        int durabilityLoss = config.getAbilityToolDamage();
-        FakePlayerAnimationEvent armswing = new FakePlayerAnimationEvent(player);
-
-        if (ModChecks.isCustomMiningBlock(block)) {
-            if (ModChecks.getCustomBlock(block).getTier() < tier) {
-                return;
-            }
-
-            if (mcMMO.placeStore.isTrue(block) || Misc.blockBreakSimulate(block, player, true)) {
-                return;
-            }
-
-            mcMMO.p.getServer().getPluginManager().callEvent(armswing);
-            Skills.abilityDurabilityLoss(player.getItemInHand(), durabilityLoss);
-
-            MiningManager manager = new MiningManager(player);
-            manager.miningBlockCheck(block);
-
-            if (mcMMO.spoutEnabled) {
-                SpoutSounds.playSoundForPlayer(SoundEffect.POP, player, block.getLocation());
-            }
-        }
-        else {
-            switch (type) {
-            case OBSIDIAN:
-                if (tier < 4) {
-                    return;
-                }
-                durabilityLoss = durabilityLoss * 5; //Obsidian needs to do more damage than normal
-                /* FALL THROUGH */
-
-            case DIAMOND_ORE:
-            case GLOWING_REDSTONE_ORE:
-            case GOLD_ORE:
-            case LAPIS_ORE:
-            case REDSTONE_ORE:
-            case EMERALD_ORE:
-                if (tier < 3) {
-                    return;
-                }
-                /* FALL THROUGH */
-
-            case IRON_ORE:
-                if (tier < 2) {
-                    return;
-                }
-                /* FALL THROUGH */
-
-            case COAL_ORE:
-            case ENDER_STONE:
-            case GLOWSTONE:
-            case MOSSY_COBBLESTONE:
-            case NETHERRACK:
-            case SANDSTONE:
-            case STONE:
-                if (mcMMO.placeStore.isTrue(block) || Misc.blockBreakSimulate(block, player, true)) {
-                    return;
-                }
-
-                mcMMO.p.getServer().getPluginManager().callEvent(armswing);
-                Skills.abilityDurabilityLoss(player.getItemInHand(), durabilityLoss);
-
-                MiningManager manager = new MiningManager(player);
-                manager.miningBlockCheck(block);
-
-                if (mcMMO.spoutEnabled) {
-                    SpoutSounds.playSoundForPlayer(SoundEffect.POP, player, block.getLocation());
-                }
-
-            default:
-                return;
-            }
-        }
-    }
-
-
     /**
      * Handle double drops when using Silk Touch.
      *
      * @param block The block to process drops for
+     * @param location The location of the block
+     * @param type The material type of the block
      */
-    protected static void silkTouchDrops(Block block) {
-        Location location = block.getLocation();
-        Material type = block.getType();
+    protected static void silkTouchDrops(Block block, Location location, Material type) {
         ItemStack item = new ItemStack(type);
 
         switch (type) {
@@ -215,7 +127,7 @@ public class Mining {
         case NETHERRACK:
         case OBSIDIAN:
         case SANDSTONE:
-            miningDrops(block);
+            miningDrops(block, location, type);
             break;
 
         case COAL_ORE:
@@ -269,17 +181,16 @@ public class Mining {
             }
             break;
         }
-
     }
 
     /**
      * Drop items from Mining & Blast Mining skills.
      *
      * @param block The block to process drops for
+     * @param location The location of the block
+     * @param type The material type of the block
      */
-    protected static void miningDrops(Block block) {
-        Location location = block.getLocation();
-        Material type = block.getType();
+    protected static void miningDrops(Block block, Location location, Material type) {
         ItemStack item = new ItemStack(type);
 
         switch (type) {
@@ -335,7 +246,7 @@ public class Mining {
 
         case LAPIS_ORE:
             if (config.getLapisDoubleDropsEnabled()) {
-                item = (new MaterialData(Material.INK_SACK, (byte) 0x4)).toItemStack(1);
+                item = (new MaterialData(Material.INK_SACK, DyeColor.BLUE.getDyeData())).toItemStack(1);
 
                 Misc.dropItems(location, item, 4);
                 Misc.randomDropItems(location, item, 50, 4);

+ 54 - 0
src/main/java/com/gmail/nossr50/skills/mining/MiningBlockEventHandler.java

@@ -0,0 +1,54 @@
+package com.gmail.nossr50.skills.mining;
+
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.enchantments.Enchantment;
+import org.bukkit.entity.Player;
+
+import com.gmail.nossr50.util.Misc;
+
+public class MiningBlockEventHandler {
+    private MiningManager manager;
+    private Player player;
+
+    private Block block;
+    private Location blockLocation;
+    private Material blockType;
+
+    protected int skillModifier;
+
+    protected MiningBlockEventHandler(MiningManager manager, Block block) {
+        this.manager = manager;
+        this.player = manager.getPlayer();
+
+        this.block = block;
+        this.blockLocation = block.getLocation();
+        this.blockType = block.getType();
+
+        calculateSkillModifier();
+    }
+
+    protected void calculateSkillModifier() {
+        this.skillModifier = Misc.skillCheck(manager.getSkillLevel(), Mining.DOUBLE_DROPS_MAX_BONUS_LEVEL);
+    }
+
+    /**
+     * Process Mining block drops.
+     *
+     * @param player The player mining the block
+     * @param block The block being broken
+     */
+    protected void processDrops() {
+        if (player.getItemInHand().containsEnchantment(Enchantment.SILK_TOUCH)) {
+            Mining.silkTouchDrops(block, blockLocation, blockType);
+        }
+        else {
+            Mining.miningDrops(block, blockLocation, blockType);
+        }
+    }
+
+    protected void processXP() {
+        Mining.miningXP(player, manager.getProfile(), block, blockType);
+    }
+}

+ 0 - 39
src/main/java/com/gmail/nossr50/skills/mining/MiningDropsBlockHandler.java

@@ -1,39 +0,0 @@
-package com.gmail.nossr50.skills.mining;
-
-import org.bukkit.block.Block;
-import org.bukkit.enchantments.Enchantment;
-
-import com.gmail.nossr50.util.Misc;
-
-public class MiningDropsBlockHandler {
-    private MiningManager manager;
-    private Block block;
-
-    protected int skillModifier;
-
-    protected MiningDropsBlockHandler(MiningManager manager, Block block) {
-        this.manager = manager;
-        this.block = block;
-
-        calculateSkillModifier();
-    }
-
-    protected void calculateSkillModifier() {
-        this.skillModifier = Misc.skillCheck(manager.getSkillLevel(), Mining.DOUBLE_DROPS_MAX_BONUS_LEVEL);
-    }
-
-    /**
-     * Process Mining block drops.
-     *
-     * @param player The player mining the block
-     * @param block The block being broken
-     */
-    protected void processDrops() {
-        if (manager.getPlayer().getItemInHand().containsEnchantment(Enchantment.SILK_TOUCH)) {
-            Mining.silkTouchDrops(block);
-        }
-        else {
-            Mining.miningDrops(block);
-        }
-    }
-}

+ 33 - 10
src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java

@@ -6,6 +6,7 @@ import org.bukkit.entity.Player;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.datatypes.SkillType;
+import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.Users;
 
@@ -13,7 +14,6 @@ public class MiningManager {
     private Player player;
     private PlayerProfile profile;
     private int skillLevel;
-    private Permissions permissionsInstance;
 
     public MiningManager (Player player) {
         this.player = player;
@@ -32,35 +32,58 @@ public class MiningManager {
             return;
         }
 
-        Mining.miningXP(player, block);
+        MiningBlockEventHandler eventHandler = new MiningBlockEventHandler(this, block);
+
+        eventHandler.processXP();
 
         if (!Permissions.miningDoubleDrops(player)) {
             return;
         }
 
-        MiningDropsBlockHandler blockHandler = new MiningDropsBlockHandler(this, block);
-
         int randomChance = 100;
         if (Permissions.luckyMining(player)) {
             randomChance = (int) (randomChance * 0.75);
         }
 
-        float chance = (float) (((double) Mining.DOUBLE_DROPS_MAX_CHANCE / Mining.DOUBLE_DROPS_MAX_BONUS_LEVEL) * blockHandler.skillModifier);
+        float chance = ((float) Mining.DOUBLE_DROPS_MAX_CHANCE / Mining.DOUBLE_DROPS_MAX_BONUS_LEVEL) * eventHandler.skillModifier;
 
         if (chance > Mining.getRandom().nextInt(randomChance)) {
-            blockHandler.processDrops();
+            eventHandler.processDrops();
         }
     }
 
-    protected int getSkillLevel() {
-        return skillLevel;
+    /**
+     * Handle the Super Breaker ability.
+     *
+     * @param player The player using the ability
+     * @param block The block being affected
+     */
+    public void superBreakerBlockCheck(Block block) {
+        if (mcMMO.placeStore.isTrue(block) || !Misc.blockBreakSimulate(block, player, true)) {
+            return;
+        }
+
+        SuperBreakerEventHandler eventHandler = new SuperBreakerEventHandler(this, block);
+
+        if (eventHandler.tierCheck()) {
+            return;
+        }
+
+        eventHandler.callFakeArmswing();
+        eventHandler.processDurabilityLoss();
+        eventHandler.processDropsAndXP();
+        eventHandler.playSpoutSound();
     }
 
-    protected Permissions getPermissionsInstance() {
-        return permissionsInstance;
+    protected int getSkillLevel() {
+        return skillLevel;
     }
 
     protected Player getPlayer() {
         return player;
     }
+
+    protected PlayerProfile getProfile() {
+        return profile;
+    }
 }

+ 123 - 0
src/main/java/com/gmail/nossr50/skills/mining/SuperBreakerEventHandler.java

@@ -0,0 +1,123 @@
+package com.gmail.nossr50.skills.mining;
+
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.getspout.spoutapi.sound.SoundEffect;
+
+import com.gmail.nossr50.mcMMO;
+import com.gmail.nossr50.events.fake.FakePlayerAnimationEvent;
+import com.gmail.nossr50.spout.SpoutSounds;
+import com.gmail.nossr50.util.Misc;
+import com.gmail.nossr50.util.ModChecks;
+import com.gmail.nossr50.util.Skills;
+
+public class SuperBreakerEventHandler {
+    private MiningManager manager;
+    private Player player;
+
+    private Block block;
+    private Material blockType;
+    private boolean customBlock;
+
+    private ItemStack heldItem;
+    private int tier;
+
+    private int durabilityLoss;
+    private FakePlayerAnimationEvent armswing;
+
+    protected SuperBreakerEventHandler (MiningManager manager, Block block) {
+        this.manager = manager;
+        this.player = manager.getPlayer();
+
+        this.block = block;
+        this.blockType = block.getType();
+        this.customBlock = ModChecks.isCustomMiningBlock(block);
+
+        this.heldItem = player.getItemInHand();
+        this.tier = Misc.getTier(heldItem);
+
+        this.armswing = new FakePlayerAnimationEvent(player);
+
+        calculateDurabilityLoss();
+    }
+
+    protected void callFakeArmswing() {
+        mcMMO.p.getServer().getPluginManager().callEvent(armswing);
+    }
+
+    protected void processDurabilityLoss() {
+        Skills.abilityDurabilityLoss(heldItem, durabilityLoss);
+    }
+
+    protected void processDropsAndXP() {
+        manager.miningBlockCheck(block);
+    }
+
+    protected void playSpoutSound() {
+        SpoutSounds.playSoundForPlayer(SoundEffect.POP, player, block.getLocation());
+    }
+
+    /**
+     * Check for the proper tier of item for use with Super Breaker.
+     *
+     * @return True if the item is the required tier or higher, false otherwise
+     */
+    protected boolean tierCheck() {
+        if (customBlock) {
+            if (ModChecks.getCustomBlock(block).getTier() < tier) {
+                return false;
+            }
+            else {
+                return true;
+            }
+        }
+        else {
+            switch (blockType) {
+            case OBSIDIAN:
+                if (tier < Mining.DIAMOND_TOOL_TIER) {
+                    return false;
+                }
+                /* FALL THROUGH */
+
+            case DIAMOND_ORE:
+            case GLOWING_REDSTONE_ORE:
+            case GOLD_ORE:
+            case LAPIS_ORE:
+            case REDSTONE_ORE:
+            case EMERALD_ORE:
+                if (tier < Mining.IRON_TOOL_TIER) {
+                    return false;
+                }
+                /* FALL THROUGH */
+
+            case IRON_ORE:
+                if (tier < Mining.STONE_TOOL_TIER) {
+                    return false;
+                }
+                /* FALL THROUGH */
+
+            case COAL_ORE:
+            case ENDER_STONE:
+            case GLOWSTONE:
+            case MOSSY_COBBLESTONE:
+            case NETHERRACK:
+            case SANDSTONE:
+            case STONE:
+                return true;
+
+            default:
+                return false;
+            }
+        }
+    }
+
+    private void calculateDurabilityLoss() {
+        this.durabilityLoss = Misc.TOOL_DURABILITY_LOSS;
+
+        if (blockType.equals(Material.OBSIDIAN)) {
+            durabilityLoss = durabilityLoss * 5;
+        }
+    }
+}

+ 0 - 30
src/main/java/com/gmail/nossr50/skills/repair/Repair.java

@@ -1,6 +1,5 @@
 package com.gmail.nossr50.skills.repair;
 
-import java.lang.reflect.Field;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Random;
@@ -108,7 +107,6 @@ public class Repair {
                 is.removeEnchantment(x);
             }
             player.sendMessage(LocaleLoader.getString("Repair.Arcane.Lost"));
-            clearEnchantTag(is);
             return;
         }
 
@@ -142,7 +140,6 @@ public class Repair {
 
         if (newEnchants.isEmpty()) {
             player.sendMessage(LocaleLoader.getString("Repair.Arcane.Fail"));
-            clearEnchantTag(is);
         }
         else if (downgraded || newEnchants.size() < enchants.size()) {
             player.sendMessage(LocaleLoader.getString("Repair.Arcane.Downgrade"));
@@ -152,33 +149,6 @@ public class Repair {
         }
     }
 
-    private static void clearEnchantTag(ItemStack is) {
-        Object o;
-        Class c;
-        Field f;
-
-        o = is;
-        c = o.getClass();
-
-        try {
-            f = c.getDeclaredField("handle");
-            f.setAccessible(true);
-            o = f.get(o);
-
-            c = o.getClass();
-            f = c.getDeclaredField("tag");
-            o = f.get(o);
-
-            c = o.getClass();
-            f = c.getDeclaredField("map");
-            f.setAccessible(true);
-            Map tagMap = (Map) f.get(o);
-
-            tagMap.remove("ench");
-        }
-        catch(Exception e) {}
-    }
-
     /**
      * Gets chance of keeping enchantment during repair.
      *

+ 0 - 3
src/main/java/com/gmail/nossr50/util/Database.java

@@ -287,9 +287,6 @@ public class Database {
         boolean isValid = false;
         boolean exists = (connection != null);
 
-        // Initialized as needed later
-        long timestamp=0;
-
         // If we're waiting for server to recover then leave early
         if (nextReconnectTimestamp > 0 && nextReconnectTimestamp > System.nanoTime()) {
             return false;

+ 11 - 1
src/main/java/com/gmail/nossr50/util/Misc.java

@@ -20,9 +20,19 @@ import com.gmail.nossr50.events.fake.FakePlayerAnimationEvent;
 import com.gmail.nossr50.events.items.McMMOItemSpawnEvent;
 
 public class Misc {
-
     private static Random random = new Random();
 
+    public static final int TOOL_DURABILITY_LOSS = Config.getInstance().getAbilityToolDamage();
+    public static final int PLAYER_RESPAWN_COOLDOWN_SECONDS = 5;
+
+    public static boolean isCitizensNPC(Player player) {
+        if (player == null || Users.getProfile(player) == null || player.hasMetadata("NPC")) {
+            return true;
+        }
+
+        return false;
+    }
+
     /**
      * Gets a capitalized version of the target string.
      *

+ 0 - 2
src/main/java/com/gmail/nossr50/util/Permissions.java

@@ -4,8 +4,6 @@ import org.bukkit.command.CommandSender;
 import org.bukkit.entity.Player;
 
 public class Permissions {
-    private static volatile Permissions instance;
-
     public static boolean hasPermission(CommandSender sender, String perm)
     {
         if(sender.hasPermission(perm))

+ 2 - 2
src/main/java/com/gmail/nossr50/util/blockmeta/chunkmeta/HashChunkManager.java

@@ -167,8 +167,8 @@ public class HashChunkManager implements ChunkManager {
         if(in != null) {
             store.put(world.getName() + "," + cx + "," + cz, in);
 
-            List mobs = in.getSpawnedMobs();
-            List pets = in.getSpawnedPets();
+            List<UUID> mobs = in.getSpawnedMobs();
+            List<UUID> pets = in.getSpawnedPets();
 
             if(mobs.isEmpty() && pets.isEmpty())
                 return;