瀏覽代碼

*CLEANUP* - mcPlayerListener.java

Also moved some stuff around to more appropriate files, created classes
for a few Runnables, and mcLocale'd a couple of strings.
GJ 13 年之前
父節點
當前提交
4359dc764f

+ 1 - 0
Changelog.txt

@@ -30,6 +30,7 @@ Version 2.0.00-dev
  ! Changed Call of the Wild to activate on left-click rather than right-click
  ! Changed Blast Mining to track based on Entity ID vs. Location
  ! Changed mmoedit to save a profile when used (this will make mctop update)
+ ! Changed a few Runnable tasks to have their own classes
 
 Version 1.3.02
  + Added in game guides for Mining, Excavation, and Acrobatics. Simply type /skillname ? to access them

+ 311 - 292
src/main/java/com/gmail/nossr50/listeners/mcPlayerListener.java

@@ -1,6 +1,5 @@
 package com.gmail.nossr50.listeners;
 
-import java.util.HashSet;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -8,10 +7,8 @@ import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
 import org.bukkit.Material;
 import org.bukkit.block.Block;
-import org.bukkit.entity.Entity;
 import org.bukkit.entity.EntityType;
 import org.bukkit.entity.Player;
-import org.bukkit.entity.TNTPrimed;
 import org.bukkit.event.EventHandler;
 import org.bukkit.event.EventPriority;
 import org.bukkit.event.Listener;
@@ -31,317 +28,339 @@ import org.bukkit.inventory.ItemStack;
 import com.gmail.nossr50.BlockChecks;
 import com.gmail.nossr50.Combat;
 import com.gmail.nossr50.Item;
-import com.gmail.nossr50.ItemChecks;
 import com.gmail.nossr50.Users;
-import com.gmail.nossr50.m;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.mcPermissions;
 import com.gmail.nossr50.commands.general.XprateCommand;
 import com.gmail.nossr50.config.LoadProperties;
 import com.gmail.nossr50.runnables.RemoveProfileFromMemoryTask;
 import com.gmail.nossr50.spout.SpoutStuff;
-import com.gmail.nossr50.datatypes.AbilityType;
 import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.datatypes.SkillType;
 import com.gmail.nossr50.locale.mcLocale;
 import com.gmail.nossr50.party.Party;
+import com.gmail.nossr50.skills.BlastMining;
 import com.gmail.nossr50.skills.Fishing;
+import com.gmail.nossr50.skills.Herbalism;
 import com.gmail.nossr50.skills.Repair;
 import com.gmail.nossr50.skills.Skills;
 import com.gmail.nossr50.skills.Taming;
 
 
-public class mcPlayerListener implements Listener 
-{
-	protected static final Logger log = Logger.getLogger("Minecraft"); //$NON-NLS-1$
-	private mcMMO plugin;
-
-	public mcPlayerListener(mcMMO instance) 
-	{
-		plugin = instance;
-	}
-	
-	@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
-	public void onPlayerWorldChangeEvent(PlayerChangedWorldEvent event)
-	{
-	    Player player = event.getPlayer();
-	    PlayerProfile PP = Users.getProfile(player);
-	    
-	    if(PP.getGodMode())
-	    {
-	        if(!mcPermissions.getInstance().mcgod(player))
-	        {
-	            PP.toggleGodMode();
-	            player.sendMessage("[mcMMO] God Mode not permitted on this world (See Permissions)");
-	        }
-	    }
-	}
-	
-	@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
-	public void onPlayerFish(PlayerFishEvent event) 
-	{
-		Player player = event.getPlayer();
-		if(mcPermissions.getInstance().fishing(player))
-		{
-			State state = event.getState();
-			Entity caught = event.getCaught();
-			if(state == State.CAUGHT_FISH)
-			{
-				if(caught instanceof org.bukkit.entity.Item)
-					Fishing.processResults(event);
-			} 
-			else if (state == State.CAUGHT_ENTITY)
-			{
-				int skillLevel = Users.getProfile(player).getSkillLevel(SkillType.FISHING);
-				if(skillLevel >= 150)
-					Fishing.shakeMob(event);
-			}
-		}
-	}
-
-	@EventHandler(ignoreCancelled = true)
-	public void onPlayerPickupItem(PlayerPickupItemEvent event) 
-	{
-		if(Users.getProfile(event.getPlayer()).getBerserkMode())
-			 event.setCancelled(true);
-	}
-	
-	@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
-	public void onPlayerLogin(PlayerLoginEvent event) 
-	{
-		Users.addUser(event.getPlayer());
-	}
-
-	@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
-	public void onPlayerQuit(PlayerQuitEvent event) 
-	{
-		/*
-		 * GARBAGE COLLECTION
-		 */
-		//Discard the PlayerProfile object
-		Player player = event.getPlayer();
-		PlayerProfile PP = Users.getProfile(player);
-		if(LoadProperties.spoutEnabled && SpoutStuff.playerHUDs.containsKey(player))
-			SpoutStuff.playerHUDs.remove(player);
-		
-		//Bleed it out
-		if(PP.getBleedTicks() > 0)
-			Combat.dealDamage(player, PP.getBleedTicks()*2);
-		
-		//Save PlayerData to MySQL/FlatFile on player quit
-		PP.save();
-		
-		//Schedule PlayerProfile removal 2 minutes after quitting
-		Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new RemoveProfileFromMemoryTask(player), 2400);
-	}
-
-	@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
-	public void onPlayerJoin(PlayerJoinEvent event) 
-	{
-		Player player = event.getPlayer();
-		if(mcPermissions.getInstance().motd(player) && LoadProperties.enableMotd)
-		{
-			player.sendMessage(mcLocale.getString("mcPlayerListener.MOTD", new Object[] {plugin.getDescription().getVersion(), "mcmmo"}));
-			player.sendMessage(mcLocale.getString("mcPlayerListener.WIKI"));
-		}
-		//THIS IS VERY BAD WAY TO DO THINGS, NEED BETTER WAY
-		if(XprateCommand.xpevent)
-			player.sendMessage(ChatColor.GOLD+"mcMMO is currently in an XP rate event! XP rate is "+LoadProperties.xpGainMultiplier+"x!");
-	}
-
-	@EventHandler(priority = EventPriority.MONITOR)
-	public void onPlayerInteract(PlayerInteractEvent event) 
-	{
-		Player player = event.getPlayer();
-		PlayerProfile PP = Users.getProfile(player);
-		Action action = event.getAction();
-		Block block = event.getClickedBlock();
-		ItemStack is = player.getItemInHand();
-		Material mat;
+public class mcPlayerListener implements Listener {
+    protected static final Logger log = Logger.getLogger("Minecraft");
+    private mcMMO plugin;
+
+    public mcPlayerListener(mcMMO instance) {
+        plugin = instance;
+    }
+
+    /**
+     * Monitor PlayerChangedWorld events.
+     *
+     * @param event The event to watch
+     */
+    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
+    public void onPlayerWorldChangeEvent(PlayerChangedWorldEvent event) {
+        Player player = event.getPlayer();
+        PlayerProfile PP = Users.getProfile(player);
+
+        if (PP.getGodMode()) {
+            if (!mcPermissions.getInstance().mcgod(player)) {
+                PP.toggleGodMode();
+                player.sendMessage(mcLocale.getString("GodMode.Forbidden"));
+            }
+        }
+    }
+
+    /**
+     * Monitor PlayerFish events.
+     *
+     * @param event The event to watch
+     */
+    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
+    public void onPlayerFish(PlayerFishEvent event) {
+        Player player = event.getPlayer();
+
+        if (mcPermissions.getInstance().fishing(player)) {
+            State state = event.getState();
+
+            switch (state) {
+            case CAUGHT_FISH:
+                Fishing.processResults(event);
+                break;
+
+            case CAUGHT_ENTITY:
+                if (Users.getProfile(player).getSkillLevel(SkillType.FISHING) >= 150) {
+                    Fishing.shakeMob(event);
+                }
+                break;
+
+            default:
+                break;
+            }
+        }
+    }
+
+    /**
+     * Monitor PlaterPickupItem events.
+     *
+     * @param event The event to watch
+     */
+    @EventHandler(ignoreCancelled = true)
+    public void onPlayerPickupItem(PlayerPickupItemEvent event) {
+        if (Users.getProfile(event.getPlayer()).getBerserkMode()) {
+             event.setCancelled(true);
+        }
+    }
+
+    /**
+     * Monitor PlayerLogin events.
+     *
+     * @param event The event to watch
+     */
+    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
+    public void onPlayerLogin(PlayerLoginEvent event) {
+        Users.addUser(event.getPlayer());
+    }
+
+    /**
+     * Monitor PlayerQuit events.
+     *
+     * @param event The event to watch
+     */
+    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
+    public void onPlayerQuit(PlayerQuitEvent event) {
+        Player player = event.getPlayer();
+        PlayerProfile PP = Users.getProfile(player);
+
+        /* GARBAGE COLLECTION */
+
+        //Remove Spout Stuff
+        if(LoadProperties.spoutEnabled && SpoutStuff.playerHUDs.containsKey(player)) {
+            SpoutStuff.playerHUDs.remove(player);
+        }
+
+        //Bleed it out
+        if(PP.getBleedTicks() > 0) {
+            Combat.dealDamage(player, PP.getBleedTicks()*2);
+        }
+
+        //Save PlayerData to MySQL/FlatFile on player quit
+        PP.save();
+
+        //Schedule PlayerProfile removal 2 minutes after quitting
+        Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new RemoveProfileFromMemoryTask(player), 2400);
+    }
+
+    /**
+     * Monitor PlayerJoin events.
+     *
+     * @param event The event to watch
+     */
+    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
+    public void onPlayerJoin(PlayerJoinEvent event) {
+        Player player = event.getPlayer();
+
+        if (mcPermissions.getInstance().motd(player) && LoadProperties.enableMotd) {
+            player.sendMessage(mcLocale.getString("mcPlayerListener.MOTD", new Object[] {plugin.getDescription().getVersion(), "mcmmo"}));
+            player.sendMessage(mcLocale.getString("mcPlayerListener.WIKI"));
+        }
+
+        //THIS IS VERY BAD WAY TO DO THINGS, NEED BETTER WAY
+        if (XprateCommand.xpevent) {
+            player.sendMessage(mcLocale.getString("XPRate.Event", new Object[] {LoadProperties.xpGainMultiplier}));
+        }
+    }
+
+    /**
+     * Monitor PlayerInteract events.
+     *
+     * @param event The event to watch
+     */
+    @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
+    public void onPlayerInteract(PlayerInteractEvent event) {
+        Player player = event.getPlayer();
+
+        Action action = event.getAction();
+        Block block = event.getClickedBlock();
+        ItemStack is = player.getItemInHand();
+        Material mat;
+
+        /* Fix for NPE on interacting with air */
         if (block == null) {
             mat = Material.AIR;
         }
         else {
             mat = block.getType();
         }
-		
-		/*
-		 * Ability checks
-		 */
-		if(action == Action.RIGHT_CLICK_BLOCK)
-		{
-
-			if(block != null && mcPermissions.getInstance().repair(player) && block.getTypeId() == LoadProperties.anvilID && (Repair.isTools(is) || Repair.isArmor(is)))
-			{
-				Repair.repairCheck(player, is, event.getClickedBlock());
-				event.setCancelled(true);
-				player.updateInventory();
-			}
-
-			if(LoadProperties.enableAbilities && BlockChecks.abilityBlockCheck(mat))
-			{
-				if(block != null && ItemChecks.isHoe(is) && !mat.equals(Material.DIRT) && !mat.equals(Material.GRASS) && !mat.equals(Material.SOIL))
-					Skills.activationCheck(player, SkillType.HERBALISM);
-				
-				Skills.activationCheck(player, SkillType.AXES);
-				Skills.activationCheck(player, SkillType.EXCAVATION);
-				Skills.activationCheck(player, SkillType.MINING);
-				Skills.activationCheck(player, SkillType.SWORDS);
-				Skills.activationCheck(player, SkillType.UNARMED);
-				Skills.activationCheck(player, SkillType.WOODCUTTING);
-			}
-
-			//GREEN THUMB
-			if(block != null && mcPermissions.getInstance().herbalism(player) && (mat.equals(Material.COBBLESTONE) || mat.equals(Material.DIRT) || mat.equals(Material.SMOOTH_BRICK)) && is.getType().equals(Material.SEEDS))
-			{
-				boolean pass = false;
-				int seeds = is.getAmount();
-				player.setItemInHand(new ItemStack(Material.SEEDS, seeds - 1));
-					
-				if(Math.random() * 1500 <= PP.getSkillLevel(SkillType.HERBALISM) && m.blockBreakSimulate(block, player, false))
-				{
-					switch(mat)
-					{
-					case COBBLESTONE:
-						if(LoadProperties.enableCobbleToMossy)
-						{
-							block.setType(Material.MOSSY_COBBLESTONE);
-							pass = true;
-						}
-						break;
-					case DIRT:
-						if(LoadProperties.enableDirtToGrass)
-						{
-							block.setType(Material.GRASS);
-							pass = true;
-						}
-						break;
-					case SMOOTH_BRICK:
-						if(LoadProperties.enableSmoothToMossy)
-						{
-							pass = true;
-							block.setData((byte)1);
-						}
-						break;
-					}
-					
-					if(pass == false)
-						player.sendMessage(mcLocale.getString("mcPlayerListener.GreenThumbFail"));
-				}
-				return;
-			}
-		}
-		
-		if(LoadProperties.enableAbilities && action == Action.RIGHT_CLICK_AIR)
-		{
-			Skills.activationCheck(player, SkillType.AXES);
-			Skills.activationCheck(player, SkillType.EXCAVATION);
-			Skills.activationCheck(player, SkillType.HERBALISM);
-			Skills.activationCheck(player, SkillType.MINING);
-			Skills.activationCheck(player, SkillType.SWORDS);
-			Skills.activationCheck(player, SkillType.UNARMED);
-			Skills.activationCheck(player, SkillType.WOODCUTTING);
-		}
-		
-		/*
-		 * ITEM CHECKS
-		 */
-		if(action == Action.RIGHT_CLICK_AIR)
-			Item.itemchecks(player);
-		if(action == Action.RIGHT_CLICK_BLOCK && BlockChecks.abilityBlockCheck(mat))
-			Item.itemchecks(player);
-		
-		if(player.isSneaking() && mcPermissions.getInstance().taming(player) && (action == Action.LEFT_CLICK_AIR || action == Action.LEFT_CLICK_BLOCK))
-		{
-			if(is.getType().equals(Material.RAW_FISH))
-				Taming.animalSummon(EntityType.OCELOT, player);
-			if(is.getType().equals(Material.BONE))
-				Taming.animalSummon(EntityType.WOLF, player);
-		}
-		
-		//BLAST MINING
-		if((action == Action.RIGHT_CLICK_BLOCK || action == Action.RIGHT_CLICK_AIR) && is.getTypeId() == LoadProperties.detonatorID)
-		{
-			//Gotta make snow transparent...
-			HashSet<Byte> transparent = new HashSet<Byte>();
-			transparent.add((byte) 78);
-			transparent.add((byte) 0);
-			
-			Block b = player.getTargetBlock(transparent, 100);
-			if(b.getType().equals(Material.TNT) && mcPermissions.getInstance().blastMining(player) && m.blockBreakSimulate(b, player, true) && Users.getProfile(player).getSkillLevel(SkillType.MINING) >= 125)
-			{
-			    AbilityType ability = AbilityType.BLAST_MINING;
-			    //Check cooldown
-	            if(!Skills.cooldownOver(player, (PP.getSkillDATS(ability) * 1000), ability.getCooldown()))
-	            {
-	                player.sendMessage(mcLocale.getString("Skills.TooTired") + ChatColor.YELLOW + " (" + Skills.calculateTimeLeft(player, (PP.getSkillDATS(ability) * 1000), ability.getCooldown()) + "s)");
-	                return;
-	            }
-	            //Send message to nearby players
-	            for(Player y : player.getWorld().getPlayers())
-                {
-                    if(y != player && m.isNear(player.getLocation(), y.getLocation(), 10))
-                        y.sendMessage(ability.getAbilityPlayer(player));
+
+        switch (action) {
+        case RIGHT_CLICK_BLOCK:
+
+            /* REPAIR CHECKS */
+            if (mcPermissions.getInstance().repair(player) && block.getTypeId() == LoadProperties.anvilID && (Repair.isTools(is) || Repair.isArmor(is))) {
+                Repair.repairCheck(player, is, event.getClickedBlock());
+                event.setCancelled(true);
+                player.updateInventory();
+            }
+
+            /* ACTIVATION CHECKS */
+            if (LoadProperties.enableAbilities && BlockChecks.abilityBlockCheck(mat)) {
+                if (!mat.equals(Material.DIRT) && !mat.equals(Material.GRASS) && !mat.equals(Material.SOIL)) {
+                    Skills.activationCheck(player, SkillType.HERBALISM);
+                }
+
+                Skills.activationCheck(player, SkillType.AXES);
+                Skills.activationCheck(player, SkillType.EXCAVATION);
+                Skills.activationCheck(player, SkillType.MINING);
+                Skills.activationCheck(player, SkillType.SWORDS);
+                Skills.activationCheck(player, SkillType.UNARMED);
+                Skills.activationCheck(player, SkillType.WOODCUTTING);
+            }
+
+            /* GREEN THUMB CHECK */
+            if (mcPermissions.getInstance().herbalism(player) && Herbalism.makeMossy(mat) && is.getType().equals(Material.SEEDS)) {
+                Herbalism.greenThumbBlocks(is, player, block);
+            }
+
+            /* ITEM CHECKS */
+            if (BlockChecks.abilityBlockCheck(mat)) {
+                Item.itemchecks(player);
+            }
+
+            /* BLAST MINING CHECK */
+            if (mcPermissions.getInstance().blastMining(player) && is.getTypeId() == LoadProperties.detonatorID) {
+                BlastMining.remoteDetonation(player, plugin);
+            }
+
+            break;
+
+        case RIGHT_CLICK_AIR:
+
+            /* ACTIVATION CHECKS */
+            if (LoadProperties.enableAbilities) {
+                Skills.activationCheck(player, SkillType.AXES);
+                Skills.activationCheck(player, SkillType.EXCAVATION);
+                Skills.activationCheck(player, SkillType.HERBALISM);
+                Skills.activationCheck(player, SkillType.MINING);
+                Skills.activationCheck(player, SkillType.SWORDS);
+                Skills.activationCheck(player, SkillType.UNARMED);
+                Skills.activationCheck(player, SkillType.WOODCUTTING);
+            }
+
+            /* ITEM CHECKS */
+            Item.itemchecks(player);
+
+            /* BLAST MINING CHECK */
+            if (mcPermissions.getInstance().blastMining(player) && is.getTypeId() == LoadProperties.detonatorID) {
+                BlastMining.remoteDetonation(player, plugin);
+            }
+
+            break;
+
+        case LEFT_CLICK_AIR:
+        case LEFT_CLICK_BLOCK:
+
+            /* CALL OF THE WILD CHECKS */
+            if (player.isSneaking() && mcPermissions.getInstance().taming(player)) {
+                if (is.getType().equals(Material.RAW_FISH)) {
+                    Taming.animalSummon(EntityType.OCELOT, player);
+                }
+                else if (is.getType().equals(Material.BONE)) {
+                    Taming.animalSummon(EntityType.WOLF, player);
+                }
+            }
+
+            break;
+
+        default:
+            break;
+        }
+    }
+
+    /**
+     * Monitor PlayerChat events.
+     *
+     * @param event The event to watch
+     */
+    @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
+    public void onPlayerChat(PlayerChatEvent event) {
+        Player player = event.getPlayer();
+        PlayerProfile PP = Users.getProfile(player);
+        boolean partyChat = PP.getPartyChatMode();
+        boolean adminChat = PP.getAdminChatMode();
+
+        if (partyChat || adminChat) {
+            event.setCancelled(true);
+
+            String name = "";
+            boolean displayNames = false;
+            ChatColor color = ChatColor.WHITE;
+            String logHeader = "";
+
+            /* Set the pChat & aChat specific stuff */
+            if (partyChat) {
+                if (!PP.inParty()) {
+                    player.sendMessage("You're not in a party, type /p to leave party chat mode."); //TODO: Use mcLocale
+                    return;
+                }
+
+                displayNames = LoadProperties.pDisplayNames;
+                color = ChatColor.GREEN;
+                logHeader = "[P](" + PP.getParty() + ")<";
+            }
+            else if (adminChat) {
+                displayNames = LoadProperties.aDisplayNames;
+                color = ChatColor.AQUA;
+                logHeader = "[A]<";
+            }
+
+            /* Format & display */
+            if (displayNames) {
+                name = player.getDisplayName();
+            }
+            else {
+                name = player.getName();
+            }
+
+            String format = color + "(" + ChatColor.WHITE + name + color + ") " + event.getMessage();
+
+            for (Player x : Bukkit.getServer().getOnlinePlayers()) {
+                if (partyChat && Party.getInstance().inSameParty(player, x))
+                    x.sendMessage(format);
+                else if (adminChat && (x.isOp() || mcPermissions.getInstance().adminChat(x))) {
+                    x.sendMessage(format);
                 }
-	            
-	            player.sendMessage(ChatColor.GRAY+"**BOOM**");
-	            
-	            TNTPrimed tnt = player.getWorld().spawn(b.getLocation(), TNTPrimed.class);
-	            plugin.misc.tntTracker.put(tnt.getEntityId(), player);
-				b.setType(Material.AIR);
-				tnt.setFuseTicks(0);
-				PP.setSkillDATS(ability, System.currentTimeMillis()); //Save DATS for Blast Mining
-				PP.setBlastMiningInformed(false);
-			}
-		}
-	}
-
-	@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
-	public void onPlayerChat(PlayerChatEvent event) 
-	{
-		Player player = event.getPlayer();
-		PlayerProfile PP = Users.getProfile(player);
-		if(PP.getPartyChatMode())
-		{
-			event.setCancelled(true);
-			
-			if(!PP.inParty()) {
-				player.sendMessage("You're not in a party, type /p to leave party chat mode."); //TODO: Use mcLocale
-				return;
-			}
-			
-			String name = (LoadProperties.pDisplayNames) ? player.getDisplayName() : player.getName();
-			String format = ChatColor.GREEN + "(" + ChatColor.WHITE + name + ChatColor.GREEN + ") "+event.getMessage();
-			for(Player x : Bukkit.getServer().getOnlinePlayers())
-			{
-				if(Party.getInstance().inSameParty(player, x))
-					x.sendMessage(format);
-			}
-			log.log(Level.INFO, "[P](" + PP.getParty() + ")<" + name + ">" + event.getMessage());
-		} else if (PP.getAdminChatMode()) {
-			event.setCancelled(true);
-			String name = (LoadProperties.aDisplayNames) ? player.getDisplayName() : player.getName();
-			String format = ChatColor.AQUA + "{" + ChatColor.WHITE + name + ChatColor.AQUA + "} "+event.getMessage();
-			for(Player x : Bukkit.getServer().getOnlinePlayers())
-			{
-				if(x.isOp() || mcPermissions.getInstance().adminChat(x))
-					x.sendMessage(format);
-			}
-			log.log(Level.INFO, "[A]<" + name + ">" + event.getMessage());
-		}
-	}
-	
-	// Dynamically aliasing commands need to be re-done.
-	// For now, using a command with an alias will send both the original command, and the mcMMO command
-	@EventHandler(priority = EventPriority.LOWEST)
-	public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
-		String message = event.getMessage();
-		if(!message.startsWith("/")) return;
-		String command = message.substring(1).split(" ")[0];
-		if(plugin.aliasMap.containsKey(command)) {
-			if(command.equalsIgnoreCase(plugin.aliasMap.get(command))) return;
-			//event.setCancelled(true);
-			event.getPlayer().chat(message.replaceFirst(command, plugin.aliasMap.get(command)));
-		}
-	}
+            }
+
+            log.log(Level.INFO, logHeader + name + ">" + event.getMessage());
+        }
+    }
+
+    // Dynamically aliasing commands need to be re-done.
+    // For now, using a command with an alias will send both the original command, and the mcMMO command
+
+    /**
+     * Monitor PlayerCommandPreprocess events.
+     *
+     * @param event The event to watch
+     */
+    @EventHandler(priority = EventPriority.LOWEST)
+    public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
+        String message = event.getMessage();
+        
+        if (!message.startsWith("/")) {
+            return;
+        }
+
+        String command = message.substring(1).split(" ")[0];
+
+        if (plugin.aliasMap.containsKey(command)) {
+            if(command.equalsIgnoreCase(plugin.aliasMap.get(command))) {
+                return;
+            }
+            event.getPlayer().chat(message.replaceFirst(command, plugin.aliasMap.get(command)));
+        }
+    }
 }

+ 3 - 276
src/main/java/com/gmail/nossr50/m.java

@@ -1,8 +1,5 @@
 package com.gmail.nossr50;
 
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import org.bukkit.Bukkit;
@@ -12,11 +9,13 @@ import org.bukkit.entity.*;
 import org.bukkit.event.entity.EntityDamageEvent;
 import org.bukkit.event.player.PlayerAnimationEvent;
 import org.bukkit.inventory.ItemStack;
+
 import com.gmail.nossr50.config.*;
 import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.datatypes.SkillType;
 import com.gmail.nossr50.events.FakeBlockBreakEvent;
 import com.gmail.nossr50.events.McMMOItemSpawnEvent;
+import com.gmail.nossr50.runnables.SQLConversionTask;
 import com.gmail.nossr50.skills.Repair;
 
 public class m {
@@ -251,278 +250,6 @@ public class m {
             return;
         }
 
-        Bukkit.getScheduler().scheduleAsyncDelayedTask(Bukkit.getPluginManager().getPlugin("mcMMO"), new Runnable() {
-            public void run() {
-                String location = "plugins/mcMMO/FlatFileStuff/mcmmo.users";
-
-                try {
-
-                    //Open the user file
-                    FileReader file = new FileReader(location);
-                    BufferedReader in = new BufferedReader(file);
-                    String line = "";
-                    String playerName = null;
-                    String party = null;
-                    String mining = null;
-                    String woodcutting = null;
-                    String repair = null;
-                    String unarmed = null;
-                    String herbalism = null;
-                    String excavation = null;
-                    String archery = null;
-                    String swords = null;
-                    String axes = null;
-                    String acrobatics = null;
-                    String taming = null;
-                    String fishing = null;
-                    String miningXP = null;
-                    String woodCuttingXP = null;
-                    String repairXP = null;
-                    String unarmedXP = null;
-                    String herbalismXP = null;
-                    String excavationXP = null;
-                    String archeryXP = null;
-                    String swordsXP = null;
-                    String axesXP = null;
-                    String acrobaticsXP = null;
-                    String tamingXP = null;
-                    String fishingXP = null;
-                    int id = 0;
-                    int theCount = 0;
-
-                    while ((line = in.readLine()) != null) {
-
-                        //Find if the line contains the player we want.
-                        String[] character = line.split(":");
-                        playerName = character[0];
-
-                        //Check for things we don't want put in the DB
-                        if (playerName == null || playerName.equals("null") || playerName.equals("#Storage place for user information")) {
-                            continue;
-                        }
-
-                        if (character.length > 1) {
-                            mining = character[1];
-                        }
-
-                        if (character.length > 3) {
-                            party = character[3];
-                        }
-
-                        if (character.length > 4) {
-                            miningXP = character[4];
-                        }
-
-                        if (character.length > 5) {
-                            woodcutting = character[5];
-                        }
-
-                        if (character.length > 6) {
-                            woodCuttingXP = character[6];
-                        }
-
-                        if (character.length > 7) {
-                            repair = character[7];
-                        }
-
-                        if (character.length > 8) {
-                            unarmed = character[8];
-                        }
-
-                        if (character.length > 9) {
-                            herbalism = character[9];
-                        }
-
-                        if (character.length > 10) {
-                            excavation = character[10];
-                        }
-
-                        if (character.length > 11) {
-                            archery = character[11];
-                        }
-
-                        if (character.length > 12) {
-                            swords = character[12];
-                        }
-
-                        if (character.length > 13) {
-                            axes = character[13];
-                        }
-
-                        if (character.length > 14) {
-                            acrobatics = character[14];
-                        }
-
-                        if (character.length > 15) {
-                            repairXP = character[15];
-                        }
-
-                        if (character.length > 16) {
-                            unarmedXP = character[16];
-                        }
-
-                        if (character.length > 17) {
-                            herbalismXP = character[17];
-                        }
-
-                        if (character.length > 18) {
-                            excavationXP = character[18];
-                        }
-
-                        if (character.length > 19) {
-                            archeryXP = character[19];
-                        }
-
-                        if (character.length > 20) {
-                            swordsXP = character[20];
-                        }
-
-                        if (character.length > 21) {
-                            axesXP = character[21];
-                        }
-
-                        if (character.length > 22) {
-                            acrobaticsXP = character[22];
-                        }
-
-                        if (character.length > 24) {
-                            taming = character[24];
-                        }
-
-                        if (character.length > 25) {
-                            tamingXP = character[25];
-                        }
-
-                        if (character.length > 34) {
-                            fishing = character[34];
-                        }
-
-                        if (character.length > 35) {
-                            fishingXP = character[35];
-                        }
-
-                        //Check to see if the user is in the DB
-                        id = mcMMO.database.getInt("SELECT id FROM "
-                                + LoadProperties.MySQLtablePrefix
-                                + "users WHERE user = '" + playerName + "'");
-
-                        if (id > 0) {
-                            theCount++;
-
-                            //Update the skill values
-                            mcMMO.database.write("UPDATE "
-                                    + LoadProperties.MySQLtablePrefix
-                                    + "users SET lastlogin = " + 0
-                                    + " WHERE id = " + id);
-                            mcMMO.database.write("UPDATE "
-                                    + LoadProperties.MySQLtablePrefix
-                                    + "skills SET " + "  taming = taming+"
-                                    + getInt(taming) + ", mining = mining+"
-                                    + getInt(mining) + ", repair = repair+"
-                                    + getInt(repair)
-                                    + ", woodcutting = woodcutting+"
-                                    + getInt(woodcutting)
-                                    + ", unarmed = unarmed+" + getInt(unarmed)
-                                    + ", herbalism = herbalism+"
-                                    + getInt(herbalism)
-                                    + ", excavation = excavation+"
-                                    + getInt(excavation)
-                                    + ", archery = archery+" + getInt(archery)
-                                    + ", swords = swords+" + getInt(swords)
-                                    + ", axes = axes+" + getInt(axes)
-                                    + ", acrobatics = acrobatics+"
-                                    + getInt(acrobatics)
-                                    + ", fishing = fishing+" + getInt(fishing)
-                                    + " WHERE user_id = " + id);
-                            mcMMO.database.write("UPDATE "
-                                    + LoadProperties.MySQLtablePrefix
-                                    + "experience SET " + "  taming = "
-                                    + getInt(tamingXP) + ", mining = "
-                                    + getInt(miningXP) + ", repair = "
-                                    + getInt(repairXP) + ", woodcutting = "
-                                    + getInt(woodCuttingXP) + ", unarmed = "
-                                    + getInt(unarmedXP) + ", herbalism = "
-                                    + getInt(herbalismXP) + ", excavation = "
-                                    + getInt(excavationXP) + ", archery = "
-                                    + getInt(archeryXP) + ", swords = "
-                                    + getInt(swordsXP) + ", axes = "
-                                    + getInt(axesXP) + ", acrobatics = "
-                                    + getInt(acrobaticsXP) + ", fishing = "
-                                    + getInt(fishingXP) + " WHERE user_id = "
-                                    + id);
-                        }
-                        else {
-                            theCount++;
-
-                            //Create the user in the DB
-                            mcMMO.database.write("INSERT INTO "
-                                    + LoadProperties.MySQLtablePrefix
-                                    + "users (user, lastlogin) VALUES ('"
-                                    + playerName + "',"
-                                    + System.currentTimeMillis() / 1000 + ")");
-                            id = mcMMO.database
-                                    .getInt("SELECT id FROM "
-                                            + LoadProperties.MySQLtablePrefix
-                                            + "users WHERE user = '"
-                                            + playerName + "'");
-                            mcMMO.database.write("INSERT INTO "
-                                    + LoadProperties.MySQLtablePrefix
-                                    + "skills (user_id) VALUES (" + id + ")");
-                            mcMMO.database.write("INSERT INTO "
-                                    + LoadProperties.MySQLtablePrefix
-                                    + "experience (user_id) VALUES (" + id
-                                    + ")");
-                            //Update the skill values
-                            mcMMO.database.write("UPDATE "
-                                    + LoadProperties.MySQLtablePrefix
-                                    + "users SET lastlogin = " + 0
-                                    + " WHERE id = " + id);
-                            mcMMO.database.write("UPDATE "
-                                    + LoadProperties.MySQLtablePrefix
-                                    + "users SET party = '" + party
-                                    + "' WHERE id = " + id);
-                            mcMMO.database.write("UPDATE "
-                                    + LoadProperties.MySQLtablePrefix
-                                    + "skills SET " + "  taming = "
-                                    + getInt(taming) + ", mining = "
-                                    + getInt(mining) + ", repair = "
-                                    + getInt(repair) + ", woodcutting = "
-                                    + getInt(woodcutting) + ", unarmed = "
-                                    + getInt(unarmed) + ", herbalism = "
-                                    + getInt(herbalism) + ", excavation = "
-                                    + getInt(excavation) + ", archery = "
-                                    + getInt(archery) + ", swords = "
-                                    + getInt(swords) + ", axes = "
-                                    + getInt(axes) + ", acrobatics = "
-                                    + getInt(acrobatics) + ", fishing = "
-                                    + getInt(fishing) + " WHERE user_id = "
-                                    + id);
-                            mcMMO.database.write("UPDATE "
-                                    + LoadProperties.MySQLtablePrefix
-                                    + "experience SET " + "  taming = "
-                                    + getInt(tamingXP) + ", mining = "
-                                    + getInt(miningXP) + ", repair = "
-                                    + getInt(repairXP) + ", woodcutting = "
-                                    + getInt(woodCuttingXP) + ", unarmed = "
-                                    + getInt(unarmedXP) + ", herbalism = "
-                                    + getInt(herbalismXP) + ", excavation = "
-                                    + getInt(excavationXP) + ", archery = "
-                                    + getInt(archeryXP) + ", swords = "
-                                    + getInt(swordsXP) + ", axes = "
-                                    + getInt(axesXP) + ", acrobatics = "
-                                    + getInt(acrobaticsXP) + ", fishing = "
-                                    + getInt(fishingXP) + " WHERE user_id = "
-                                    + id);
-                        }
-                    }
-
-                    System.out.println("[mcMMO] MySQL Updated from users file, " + theCount + " items added/updated to MySQL DB");
-                    in.close();
-                }
-                catch (Exception e) {
-                    log.log(Level.SEVERE, "Exception while reading " + location + " (Are you sure you formatted it correctly?)", e);
-                }
-            }
-        }, 1);
+        Bukkit.getScheduler().scheduleAsyncDelayedTask(Bukkit.getPluginManager().getPlugin("mcMMO"), new SQLConversionTask(log), 1);
     }
 }

+ 41 - 0
src/main/java/com/gmail/nossr50/runnables/GreenThumbTimer.java

@@ -0,0 +1,41 @@
+package com.gmail.nossr50.runnables;
+
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+
+import com.gmail.nossr50.datatypes.PlayerProfile;
+import com.gmail.nossr50.datatypes.SkillType;
+
+public class GreenThumbTimer implements Runnable {
+    private Block block;
+    private PlayerProfile PP;
+
+    public GreenThumbTimer(Block block, PlayerProfile PP) {
+        this.block = block;
+        this.PP = PP;
+    }
+
+    @Override
+    public void run() {
+        block.setType(Material.CROPS);
+
+        //This replants the wheat at a certain stage in development based on Herbalism Skill
+        if (!PP.getGreenTerraMode()) {
+            if (PP.getSkillLevel(SkillType.HERBALISM) >= 600) {
+                block.setData((byte) 0x4);
+            }
+            else if (PP.getSkillLevel(SkillType.HERBALISM) >= 400) {
+                block.setData((byte) 0x3);
+            }
+            else if (PP.getSkillLevel(SkillType.HERBALISM) >= 200) {
+                block.setData((byte) 0x2);
+            }
+            else {
+                block.setData((byte) 0x1);
+            }
+        }
+        else {
+            block.setData((byte) 0x4);
+        }
+    }
+}

+ 288 - 0
src/main/java/com/gmail/nossr50/runnables/SQLConversionTask.java

@@ -0,0 +1,288 @@
+package com.gmail.nossr50.runnables;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.gmail.nossr50.m;
+import com.gmail.nossr50.mcMMO;
+import com.gmail.nossr50.config.LoadProperties;
+
+public class SQLConversionTask implements Runnable {
+    private Logger log;
+    
+    public SQLConversionTask(Logger log) {
+        this.log = log;
+    }
+
+    @Override
+    public void run() {
+        String location = "plugins/mcMMO/FlatFileStuff/mcmmo.users";
+
+        try {
+            FileReader file = new FileReader(location);
+            BufferedReader in = new BufferedReader(file);
+            String line = "";
+            String playerName = null;
+            String party = null;
+            String mining = null;
+            String woodcutting = null;
+            String repair = null;
+            String unarmed = null;
+            String herbalism = null;
+            String excavation = null;
+            String archery = null;
+            String swords = null;
+            String axes = null;
+            String acrobatics = null;
+            String taming = null;
+            String fishing = null;
+            String miningXP = null;
+            String woodCuttingXP = null;
+            String repairXP = null;
+            String unarmedXP = null;
+            String herbalismXP = null;
+            String excavationXP = null;
+            String archeryXP = null;
+            String swordsXP = null;
+            String axesXP = null;
+            String acrobaticsXP = null;
+            String tamingXP = null;
+            String fishingXP = null;
+            int id = 0;
+            int theCount = 0;
+
+            while ((line = in.readLine()) != null) {
+
+                //Find if the line contains the player we want.
+                String[] character = line.split(":");
+                playerName = character[0];
+
+                //Check for things we don't want put in the DB
+                if (playerName == null || playerName.equals("null") || playerName.equals("#Storage place for user information")) {
+                    continue;
+                }
+
+                if (character.length > 1) {
+                    mining = character[1];
+                }
+
+                if (character.length > 3) {
+                    party = character[3];
+                }
+
+                if (character.length > 4) {
+                    miningXP = character[4];
+                }
+
+                if (character.length > 5) {
+                    woodcutting = character[5];
+                }
+
+                if (character.length > 6) {
+                    woodCuttingXP = character[6];
+                }
+
+                if (character.length > 7) {
+                    repair = character[7];
+                }
+
+                if (character.length > 8) {
+                    unarmed = character[8];
+                }
+
+                if (character.length > 9) {
+                    herbalism = character[9];
+                }
+
+                if (character.length > 10) {
+                    excavation = character[10];
+                }
+
+                if (character.length > 11) {
+                    archery = character[11];
+                }
+
+                if (character.length > 12) {
+                    swords = character[12];
+                }
+
+                if (character.length > 13) {
+                    axes = character[13];
+                }
+
+                if (character.length > 14) {
+                    acrobatics = character[14];
+                }
+
+                if (character.length > 15) {
+                    repairXP = character[15];
+                }
+
+                if (character.length > 16) {
+                    unarmedXP = character[16];
+                }
+
+                if (character.length > 17) {
+                    herbalismXP = character[17];
+                }
+
+                if (character.length > 18) {
+                    excavationXP = character[18];
+                }
+
+                if (character.length > 19) {
+                    archeryXP = character[19];
+                }
+
+                if (character.length > 20) {
+                    swordsXP = character[20];
+                }
+
+                if (character.length > 21) {
+                    axesXP = character[21];
+                }
+
+                if (character.length > 22) {
+                    acrobaticsXP = character[22];
+                }
+
+                if (character.length > 24) {
+                    taming = character[24];
+                }
+
+                if (character.length > 25) {
+                    tamingXP = character[25];
+                }
+
+                if (character.length > 34) {
+                    fishing = character[34];
+                }
+
+                if (character.length > 35) {
+                    fishingXP = character[35];
+                }
+
+                //Check to see if the user is in the DB
+                id = mcMMO.database.getInt("SELECT id FROM "
+                        + LoadProperties.MySQLtablePrefix
+                        + "users WHERE user = '" + playerName + "'");
+
+                if (id > 0) {
+                    theCount++;
+
+                    //Update the skill values
+                    mcMMO.database.write("UPDATE "
+                            + LoadProperties.MySQLtablePrefix
+                            + "users SET lastlogin = " + 0
+                            + " WHERE id = " + id);
+                    mcMMO.database.write("UPDATE "
+                            + LoadProperties.MySQLtablePrefix
+                            + "skills SET " + "  taming = taming+"
+                            + m.getInt(taming) + ", mining = mining+"
+                            + m.getInt(mining) + ", repair = repair+"
+                            + m.getInt(repair)
+                            + ", woodcutting = woodcutting+"
+                            + m.getInt(woodcutting)
+                            + ", unarmed = unarmed+" + m.getInt(unarmed)
+                            + ", herbalism = herbalism+"
+                            + m.getInt(herbalism)
+                            + ", excavation = excavation+"
+                            + m.getInt(excavation)
+                            + ", archery = archery+" + m.getInt(archery)
+                            + ", swords = swords+" + m.getInt(swords)
+                            + ", axes = axes+" + m.getInt(axes)
+                            + ", acrobatics = acrobatics+"
+                            + m.getInt(acrobatics)
+                            + ", fishing = fishing+" + m.getInt(fishing)
+                            + " WHERE user_id = " + id);
+                    mcMMO.database.write("UPDATE "
+                            + LoadProperties.MySQLtablePrefix
+                            + "experience SET " + "  taming = "
+                            + m.getInt(tamingXP) + ", mining = "
+                            + m.getInt(miningXP) + ", repair = "
+                            + m.getInt(repairXP) + ", woodcutting = "
+                            + m.getInt(woodCuttingXP) + ", unarmed = "
+                            + m.getInt(unarmedXP) + ", herbalism = "
+                            + m.getInt(herbalismXP) + ", excavation = "
+                            + m.getInt(excavationXP) + ", archery = "
+                            + m.getInt(archeryXP) + ", swords = "
+                            + m.getInt(swordsXP) + ", axes = "
+                            + m.getInt(axesXP) + ", acrobatics = "
+                            + m.getInt(acrobaticsXP) + ", fishing = "
+                            + m.getInt(fishingXP) + " WHERE user_id = "
+                            + id);
+                }
+                else {
+                    theCount++;
+
+                    //Create the user in the DB
+                    mcMMO.database.write("INSERT INTO "
+                            + LoadProperties.MySQLtablePrefix
+                            + "users (user, lastlogin) VALUES ('"
+                            + playerName + "',"
+                            + System.currentTimeMillis() / 1000 + ")");
+                    id = mcMMO.database.getInt("SELECT id FROM "
+                                    + LoadProperties.MySQLtablePrefix
+                                    + "users WHERE user = '"
+                                    + playerName + "'");
+                    mcMMO.database.write("INSERT INTO "
+                            + LoadProperties.MySQLtablePrefix
+                            + "skills (user_id) VALUES (" + id + ")");
+                    mcMMO.database.write("INSERT INTO "
+                            + LoadProperties.MySQLtablePrefix
+                            + "experience (user_id) VALUES (" + id
+                            + ")");
+                    //Update the skill values
+                    mcMMO.database.write("UPDATE "
+                            + LoadProperties.MySQLtablePrefix
+                            + "users SET lastlogin = " + 0
+                            + " WHERE id = " + id);
+                    mcMMO.database.write("UPDATE "
+                            + LoadProperties.MySQLtablePrefix
+                            + "users SET party = '" + party
+                            + "' WHERE id = " + id);
+                    mcMMO.database.write("UPDATE "
+                            + LoadProperties.MySQLtablePrefix
+                            + "skills SET " + "  taming = "
+                            + m.getInt(taming) + ", mining = "
+                            + m.getInt(mining) + ", repair = "
+                            + m.getInt(repair) + ", woodcutting = "
+                            + m.getInt(woodcutting) + ", unarmed = "
+                            + m.getInt(unarmed) + ", herbalism = "
+                            + m.getInt(herbalism) + ", excavation = "
+                            + m.getInt(excavation) + ", archery = "
+                            + m.getInt(archery) + ", swords = "
+                            + m.getInt(swords) + ", axes = "
+                            + m.getInt(axes) + ", acrobatics = "
+                            + m.getInt(acrobatics) + ", fishing = "
+                            + m.getInt(fishing) + " WHERE user_id = "
+                            + id);
+                    mcMMO.database.write("UPDATE "
+                            + LoadProperties.MySQLtablePrefix
+                            + "experience SET " + "  taming = "
+                            + m.getInt(tamingXP) + ", mining = "
+                            + m.getInt(miningXP) + ", repair = "
+                            + m.getInt(repairXP) + ", woodcutting = "
+                            + m.getInt(woodCuttingXP) + ", unarmed = "
+                            + m.getInt(unarmedXP) + ", herbalism = "
+                            + m.getInt(herbalismXP) + ", excavation = "
+                            + m.getInt(excavationXP) + ", archery = "
+                            + m.getInt(archeryXP) + ", swords = "
+                            + m.getInt(swordsXP) + ", axes = "
+                            + m.getInt(axesXP) + ", acrobatics = "
+                            + m.getInt(acrobaticsXP) + ", fishing = "
+                            + m.getInt(fishingXP) + " WHERE user_id = "
+                            + id);
+                }
+            }
+
+            System.out.println("[mcMMO] MySQL Updated from users file, " + theCount + " items added/updated to MySQL DB");
+            in.close();
+        }
+        catch (Exception e) {
+            log.log(Level.SEVERE, "Exception while reading " + location + " (Are you sure you formatted it correctly?)", e);
+        }
+    }
+}

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

@@ -13,6 +13,7 @@ public class mcSaveTimer implements Runnable {
         this.plugin = plugin;
     }
     
+    @Override
     public void run() 
     {
         //All player data will be saved periodically through this

+ 46 - 2
src/main/java/com/gmail/nossr50/skills/BlastMining.java

@@ -1,19 +1,27 @@
 package com.gmail.nossr50.skills;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
 import org.bukkit.block.Block;
 import org.bukkit.entity.Player;
+import org.bukkit.entity.TNTPrimed;
 import org.bukkit.event.entity.EntityDamageEvent;
 import org.bukkit.event.entity.EntityExplodeEvent;
 import org.bukkit.event.entity.ExplosionPrimeEvent;
 
 import com.gmail.nossr50.BlockChecks;
 import com.gmail.nossr50.Users;
+import com.gmail.nossr50.m;
 import com.gmail.nossr50.mcMMO;
+import com.gmail.nossr50.datatypes.AbilityType;
+import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.datatypes.SkillType;
+import com.gmail.nossr50.locale.mcLocale;
 
 public class BlastMining{
 	
@@ -160,7 +168,7 @@ public class BlastMining{
 		if(skillLevel >= 750)
 			radius++;
 		if(skillLevel >= 1000)
-			radius++;	
+			radius++;
 		event.setRadius(radius);
 	}
 	
@@ -185,5 +193,41 @@ public class BlastMining{
 		event.setDamage(damage);
 	}
 
-	
+    public static void remoteDetonation(Player player, mcMMO plugin) {
+        PlayerProfile PP = Users.getProfile(player);
+        HashSet<Byte> transparent = new HashSet<Byte>();
+
+        transparent.add((byte) 78); //SNOW
+        transparent.add((byte) 0); //AIR
+
+        Block b = player.getTargetBlock(transparent, 100);
+
+        if(b.getType().equals(Material.TNT) && m.blockBreakSimulate(b, player, true) && PP.getSkillLevel(SkillType.MINING) >= 125) {
+            AbilityType ability = AbilityType.BLAST_MINING;
+
+            /* Check Cooldown */
+            if(!Skills.cooldownOver(player, (PP.getSkillDATS(ability) * 1000), ability.getCooldown())) {
+                player.sendMessage(mcLocale.getString("Skills.TooTired") + ChatColor.YELLOW + " (" + Skills.calculateTimeLeft(player, (PP.getSkillDATS(ability) * 1000), ability.getCooldown()) + "s)");
+                return;
+            }
+
+            /* Send message to nearby players */
+            for(Player y : player.getWorld().getPlayers()) {
+                if(y != player && m.isNear(player.getLocation(), y.getLocation(), 10)) {
+                    y.sendMessage(ability.getAbilityPlayer(player));
+                }
+            }
+
+            player.sendMessage(mcLocale.getString("BlastMining.Boom"));
+
+            /* Create the TNT entity */
+            TNTPrimed tnt = player.getWorld().spawn(b.getLocation(), TNTPrimed.class);
+            plugin.misc.tntTracker.put(tnt.getEntityId(), player);
+            b.setType(Material.AIR);
+            tnt.setFuseTicks(0);
+
+            PP.setSkillDATS(ability, System.currentTimeMillis()); //Save DATS for Blast Mining
+            PP.setBlastMiningInformed(false);
+        }
+    }
 }

+ 42 - 33
src/main/java/com/gmail/nossr50/skills/Herbalism.java

@@ -15,6 +15,8 @@ import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.config.LoadProperties;
 import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.datatypes.SkillType;
+import com.gmail.nossr50.locale.mcLocale;
+import com.gmail.nossr50.runnables.GreenThumbTimer;
 
 public class Herbalism {
 
@@ -36,14 +38,16 @@ public class Herbalism {
             inventory.removeItem(new ItemStack(Material.SEEDS, 1));
             player.updateInventory();
 
-            if (LoadProperties.enableSmoothToMossy && type.equals(Material.SMOOTH_BRICK)) {
-                block.setData((byte) 0x1);
-            }
-            else if (LoadProperties.enableDirtToGrass && type.equals(Material.DIRT)) {
-                block.setType(Material.GRASS);
-            }
-            else if (LoadProperties.enableCobbleToMossy && type.equals(Material.COBBLESTONE)) {
-                block.setType(Material.MOSSY_COBBLESTONE);
+            if (m.blockBreakSimulate(block, player, false)) {
+                if (LoadProperties.enableSmoothToMossy && type.equals(Material.SMOOTH_BRICK)) {
+                    block.setData((byte) 0x1);
+                }
+                else if (LoadProperties.enableDirtToGrass && type.equals(Material.DIRT)) {
+                    block.setType(Material.GRASS);
+                }
+                else if (LoadProperties.enableCobbleToMossy && type.equals(Material.COBBLESTONE)) {
+                    block.setType(Material.MOSSY_COBBLESTONE);
+                }
             }
         }
     }
@@ -142,7 +146,7 @@ public class Herbalism {
             if (data == (byte) 0x7) {
                 mat = Material.WHEAT;
                 xp = LoadProperties.mwheat;
-                greenThumb(block, player, event, plugin);
+                greenThumbWheat(block, player, event, plugin);
             }
             break;
 
@@ -241,15 +245,15 @@ public class Herbalism {
     }
 
     /**
-     * Apply the Green Thumb ability.
+     * Apply the Green Thumb ability to crops.
      *
      * @param block The block to apply the ability to
      * @param player The player using the ability
      * @param event The event triggering the ability
      * @param plugin mcMMO plugin instance
      */
-    private static void greenThumb(final Block block, Player player, BlockBreakEvent event, mcMMO plugin) {
-        final PlayerProfile PP = Users.getProfile(player);
+    private static void greenThumbWheat(Block block, Player player, BlockBreakEvent event, mcMMO plugin) {
+        PlayerProfile PP = Users.getProfile(player);
         int herbLevel = PP.getSkillLevel(SkillType.HERBALISM);
         PlayerInventory inventory = player.getInventory();
         boolean hasSeeds = inventory.contains(Material.SEEDS);
@@ -257,31 +261,36 @@ public class Herbalism {
 
         if (hasSeeds && PP.getGreenTerraMode() || hasSeeds && (herbLevel >= 1500 || (Math.random() * 1500 <= herbLevel))) {
             event.setCancelled(true);
+
             m.mcDropItem(loc, new ItemStack(Material.WHEAT, 1));
-            m.mcDropItems(loc, new ItemStack(Material.SEEDS, 1), 3);
-
-            Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
-                public void run() {
-                    block.setType(Material.CROPS);
-
-                    //This replants the wheat at a certain stage in development based on Herbalism Skill
-                    if (!PP.getGreenTerraMode()) {
-                        if (PP.getSkillLevel(SkillType.HERBALISM) >= 600)
-                            block.setData((byte) 0x4);
-                        else if (PP.getSkillLevel(SkillType.HERBALISM) >= 400)
-                            block.setData((byte) 0x3);
-                        else if (PP.getSkillLevel(SkillType.HERBALISM) >= 200)
-                            block.setData((byte) 0x2);
-                        else
-                            block.setData((byte) 0x1);
-                    }
-                    else
-                        block.setData((byte) 0x4);
-                }
-            }, 1);
+            m.mcRandomDropItems(loc, new ItemStack(Material.SEEDS, 1), 50, 3);
+
+            Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new GreenThumbTimer(block, PP), 1);
 
             inventory.removeItem(new ItemStack(Material.SEEDS, 1));
             player.updateInventory();
         }
     }
+
+    /**
+     * Apply the Green Thumb ability to blocks.
+     *
+     * @param is The item in the player's hand
+     * @param player The player activating the ability
+     * @param block The block being used in the ability
+     */
+    public static void greenThumbBlocks(ItemStack is, Player player, Block block) {
+        PlayerProfile PP = Users.getProfile(player);
+        int skillLevel = PP.getSkillLevel(SkillType.HERBALISM);
+        int seeds = is.getAmount();
+
+        player.setItemInHand(new ItemStack(Material.SEEDS, seeds - 1));
+
+        if (skillLevel > 1500 || Math.random() * 1500 <= skillLevel) {
+            greenTerra(player, block);
+        }
+        else {
+            player.sendMessage(mcLocale.getString("mcPlayerListener.GreenThumbFail"));
+        }
+    }
 }

+ 4 - 1
src/main/resources/locale/locale_de.properties

@@ -440,4 +440,7 @@ Guides.Repair=Guide coming soon...
 Guides.Swords=Guide coming soon...
 Guides.Taming=Guide coming soon...
 Guides.Unarmed=Guide coming soon...
-Guides.Woodcutting=Guide coming soon...
+Guides.Woodcutting=Guide coming soon...
+GodMode.Forbidden=[mcMMO] God Mode not permitted on this world (See Permissions)
+XPRate.Event = [[GOLD]]mcMMO is currently in an XP rate event! XP rate is {0}x!
+BlastMining.Boom = [[GRAY]]**BOOM**

+ 4 - 1
src/main/resources/locale/locale_en_us.properties

@@ -435,4 +435,7 @@ Guides.Repair=Guide coming soon...
 Guides.Swords=Guide coming soon...
 Guides.Taming=Guide coming soon...
 Guides.Unarmed=Guide coming soon...
-Guides.Woodcutting=Guide coming soon...
+Guides.Woodcutting=Guide coming soon...
+GodMode.Forbidden=[mcMMO] God Mode not permitted on this world (See Permissions)
+XPRate.Event = [[GOLD]]mcMMO is currently in an XP rate event! XP rate is {0}x!
+BlastMining.Boom = [[GRAY]]**BOOM**

+ 4 - 1
src/main/resources/locale/locale_es_es.properties

@@ -433,4 +433,7 @@ Guides.Repair=Guide coming soon...
 Guides.Swords=Guide coming soon...
 Guides.Taming=Guide coming soon...
 Guides.Unarmed=Guide coming soon...
-Guides.Woodcutting=Guide coming soon...
+Guides.Woodcutting=Guide coming soon...
+GodMode.Forbidden=[mcMMO] God Mode not permitted on this world (See Permissions)
+XPRate.Event = [[GOLD]]mcMMO is currently in an XP rate event! XP rate is {0}x!
+BlastMining.Boom = [[GRAY]]**BOOM**

+ 4 - 1
src/main/resources/locale/locale_fi.properties

@@ -422,4 +422,7 @@ Guides.Repair=Guide coming soon...
 Guides.Swords=Guide coming soon...
 Guides.Taming=Guide coming soon...
 Guides.Unarmed=Guide coming soon...
-Guides.Woodcutting=Guide coming soon...
+Guides.Woodcutting=Guide coming soon...
+GodMode.Forbidden=[mcMMO] God Mode not permitted on this world (See Permissions)
+XPRate.Event = [[GOLD]]mcMMO is currently in an XP rate event! XP rate is {0}x!
+BlastMining.Boom = [[GRAY]]**BOOM**

+ 4 - 1
src/main/resources/locale/locale_fr.properties

@@ -433,4 +433,7 @@ Guides.Repair=Guide coming soon...
 Guides.Swords=Guide coming soon...
 Guides.Taming=Guide coming soon...
 Guides.Unarmed=Guide coming soon...
-Guides.Woodcutting=Guide coming soon...
+Guides.Woodcutting=Guide coming soon...
+GodMode.Forbidden=[mcMMO] God Mode not permitted on this world (See Permissions)
+XPRate.Event = [[GOLD]]mcMMO is currently in an XP rate event! XP rate is {0}x!
+BlastMining.Boom = [[GRAY]]**BOOM**

+ 4 - 1
src/main/resources/locale/locale_nl.properties

@@ -439,4 +439,7 @@ Guides.Repair=Guide coming soon...
 Guides.Swords=Guide coming soon...
 Guides.Taming=Guide coming soon...
 Guides.Unarmed=Guide coming soon...
-Guides.Woodcutting=Guide coming soon...
+Guides.Woodcutting=Guide coming soon...
+GodMode.Forbidden=[mcMMO] God Mode not permitted on this world (See Permissions)
+XPRate.Event = [[GOLD]]mcMMO is currently in an XP rate event! XP rate is {0}x!
+BlastMining.Boom = [[GRAY]]**BOOM**

+ 4 - 1
src/main/resources/locale/locale_pl.properties

@@ -433,4 +433,7 @@ Guides.Repair=Guide coming soon...
 Guides.Swords=Guide coming soon...
 Guides.Taming=Guide coming soon...
 Guides.Unarmed=Guide coming soon...
-Guides.Woodcutting=Guide coming soon...
+Guides.Woodcutting=Guide coming soon...
+GodMode.Forbidden=[mcMMO] God Mode not permitted on this world (See Permissions)
+XPRate.Event = [[GOLD]]mcMMO is currently in an XP rate event! XP rate is {0}x!
+BlastMining.Boom = [[GRAY]]**BOOM**

+ 4 - 1
src/main/resources/locale/locale_pt_br.properties

@@ -440,4 +440,7 @@ Guides.Repair=Guide coming soon...
 Guides.Swords=Guide coming soon...
 Guides.Taming=Guide coming soon...
 Guides.Unarmed=Guide coming soon...
-Guides.Woodcutting=Guide coming soon...
+Guides.Woodcutting=Guide coming soon...
+GodMode.Forbidden=[mcMMO] God Mode not permitted on this world (See Permissions)
+XPRate.Event = [[GOLD]]mcMMO is currently in an XP rate event! XP rate is {0}x!
+BlastMining.Boom = [[GRAY]]**BOOM**

+ 4 - 1
src/main/resources/locale/locale_ru.properties

@@ -425,4 +425,7 @@ Guides.Repair=Guide coming soon...
 Guides.Swords=Guide coming soon...
 Guides.Taming=Guide coming soon...
 Guides.Unarmed=Guide coming soon...
-Guides.Woodcutting=Guide coming soon...
+Guides.Woodcutting=Guide coming soon...
+GodMode.Forbidden=[mcMMO] God Mode not permitted on this world (See Permissions)
+XPRate.Event = [[GOLD]]mcMMO is currently in an XP rate event! XP rate is {0}x!
+BlastMining.Boom = [[GRAY]]**BOOM**