mirror of
				https://github.com/mcMMO-Dev/mcMMO.git
				synced 2025-10-31 01:03:44 +01:00 
			
		
		
		
	Command update - Mining. Also fixed typo on new Herbalism permission.
This commit is contained in:
		| @@ -23,6 +23,7 @@ Version 1.3.07 | |||||||
|  ! Changed Mining to ignore blocks when the pick is enchanted with Silk Touch |  ! Changed Mining to ignore blocks when the pick is enchanted with Silk Touch | ||||||
|  ! Changed Super Breaker to be non-functional when used with a Silk Touch enchanted pick |  ! Changed Super Breaker to be non-functional when used with a Silk Touch enchanted pick | ||||||
|  ! Changed MySQL to save player information 50ms apart from each other to reduce the load on the MySQL server |  ! Changed MySQL to save player information 50ms apart from each other to reduce the load on the MySQL server | ||||||
|  |  ! Changed the permission node for Blast Mining detonation to mcmmo.ability.blastmining.detonate (was mcmmo.skills.blastmining) for the sake of consistency | ||||||
|  - Removed some unused permission nodes |  - Removed some unused permission nodes | ||||||
|  |  | ||||||
| Version 1.3.06 | Version 1.3.06 | ||||||
|   | |||||||
| @@ -1,5 +1,7 @@ | |||||||
| package com.gmail.nossr50.commands.skills; | package com.gmail.nossr50.commands.skills; | ||||||
|  |  | ||||||
|  | import java.text.DecimalFormat; | ||||||
|  |  | ||||||
| import org.bukkit.command.Command; | import org.bukkit.command.Command; | ||||||
| import org.bukkit.command.CommandExecutor; | import org.bukkit.command.CommandExecutor; | ||||||
| import org.bukkit.command.CommandSender; | import org.bukkit.command.CommandSender; | ||||||
| @@ -9,16 +11,24 @@ import com.gmail.nossr50.commands.CommandHelper; | |||||||
| import com.gmail.nossr50.datatypes.PlayerProfile; | import com.gmail.nossr50.datatypes.PlayerProfile; | ||||||
| import com.gmail.nossr50.datatypes.SkillType; | import com.gmail.nossr50.datatypes.SkillType; | ||||||
| import com.gmail.nossr50.locale.LocaleLoader; | import com.gmail.nossr50.locale.LocaleLoader; | ||||||
|  | import com.gmail.nossr50.util.Misc; | ||||||
| import com.gmail.nossr50.util.Page; | import com.gmail.nossr50.util.Page; | ||||||
|  | import com.gmail.nossr50.util.Permissions; | ||||||
| import com.gmail.nossr50.util.Users; | import com.gmail.nossr50.util.Users; | ||||||
|  |  | ||||||
| public class MiningCommand implements CommandExecutor { | public class MiningCommand implements CommandExecutor { | ||||||
|     private float skillValue; |     private float skillValue; | ||||||
|     private String doubleDropChance; |     private String doubleDropChance; | ||||||
|     private String superBreakerLength; |     private String superBreakerLength; | ||||||
|     private int blastMiningRank; |     private String blastMiningRank; | ||||||
|     private int blastRadiusIncrease; |     private String blastRadiusIncrease; | ||||||
|     private int blastDamageDecrease; |     private String blastDamageDecrease; | ||||||
|  |  | ||||||
|  |     private boolean canSuperBreaker; | ||||||
|  |     private boolean canDoubleDrop; | ||||||
|  |     private boolean canBlast; | ||||||
|  |     private boolean canBiggerBombs; | ||||||
|  |     private boolean canDemoExpert; | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { |     public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { | ||||||
| @@ -35,42 +45,74 @@ public class MiningCommand implements CommandExecutor { | |||||||
|  |  | ||||||
|         skillValue = (float) PP.getSkillLevel(SkillType.MINING); |         skillValue = (float) PP.getSkillLevel(SkillType.MINING); | ||||||
|         dataCalculations(skillValue); |         dataCalculations(skillValue); | ||||||
|  |         permissionsCheck(player); | ||||||
|  |  | ||||||
|         player.sendMessage(LocaleLoader.getString("Skills.Header", new Object[] { LocaleLoader.getString("Mining.SkillName") })); |         player.sendMessage(LocaleLoader.getString("Skills.Header", new Object[] { LocaleLoader.getString("Mining.SkillName") })); | ||||||
|         player.sendMessage(LocaleLoader.getString("Commands.XPGain", new Object[] { LocaleLoader.getString("Commands.XPGain.Mining") })); |         player.sendMessage(LocaleLoader.getString("Commands.XPGain", new Object[] { LocaleLoader.getString("Commands.XPGain.Mining") })); | ||||||
|         player.sendMessage(LocaleLoader.getString("Effects.Level", new Object[] { PP.getSkillLevel(SkillType.MINING), PP.getSkillXpLevel(SkillType.MINING), PP.getXpToLevel(SkillType.MINING) })); |         player.sendMessage(LocaleLoader.getString("Effects.Level", new Object[] { PP.getSkillLevel(SkillType.MINING), PP.getSkillXpLevel(SkillType.MINING), PP.getXpToLevel(SkillType.MINING) })); | ||||||
|  |  | ||||||
|  |         if (canBiggerBombs || canBlast || canDemoExpert || canDoubleDrop || canSuperBreaker) { | ||||||
|             player.sendMessage(LocaleLoader.getString("Skills.Header", new Object[] { LocaleLoader.getString("Effects.Effects") })); |             player.sendMessage(LocaleLoader.getString("Skills.Header", new Object[] { LocaleLoader.getString("Effects.Effects") })); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (canSuperBreaker) { | ||||||
|             player.sendMessage(LocaleLoader.getString("Effects.Template", new Object[] { LocaleLoader.getString("Mining.Effect.0"), LocaleLoader.getString("Mining.Effect.1") })); |             player.sendMessage(LocaleLoader.getString("Effects.Template", new Object[] { LocaleLoader.getString("Mining.Effect.0"), LocaleLoader.getString("Mining.Effect.1") })); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (canDoubleDrop) { | ||||||
|             player.sendMessage(LocaleLoader.getString("Effects.Template", new Object[] { LocaleLoader.getString("Mining.Effect.2"), LocaleLoader.getString("Mining.Effect.3") })); |             player.sendMessage(LocaleLoader.getString("Effects.Template", new Object[] { LocaleLoader.getString("Mining.Effect.2"), LocaleLoader.getString("Mining.Effect.3") })); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (canBlast) { | ||||||
|             player.sendMessage(LocaleLoader.getString("Effects.Template", new Object[] { LocaleLoader.getString("Mining.Effect.4"), LocaleLoader.getString("Mining.Effect.5") })); |             player.sendMessage(LocaleLoader.getString("Effects.Template", new Object[] { LocaleLoader.getString("Mining.Effect.4"), LocaleLoader.getString("Mining.Effect.5") })); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (canBiggerBombs) { | ||||||
|             player.sendMessage(LocaleLoader.getString("Effects.Template", new Object[] { LocaleLoader.getString("Mining.Effect.6"), LocaleLoader.getString("Mining.Effect.7") })); |             player.sendMessage(LocaleLoader.getString("Effects.Template", new Object[] { LocaleLoader.getString("Mining.Effect.6"), LocaleLoader.getString("Mining.Effect.7") })); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (canDemoExpert) { | ||||||
|             player.sendMessage(LocaleLoader.getString("Effects.Template", new Object[] { LocaleLoader.getString("Mining.Effect.8"), LocaleLoader.getString("Mining.Effect.9") })); |             player.sendMessage(LocaleLoader.getString("Effects.Template", new Object[] { LocaleLoader.getString("Mining.Effect.8"), LocaleLoader.getString("Mining.Effect.9") })); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (canBiggerBombs || canBlast || canDemoExpert || canDoubleDrop || canSuperBreaker) { | ||||||
|             player.sendMessage(LocaleLoader.getString("Skills.Header", new Object[] { LocaleLoader.getString("Commands.Stats.Self") })); |             player.sendMessage(LocaleLoader.getString("Skills.Header", new Object[] { LocaleLoader.getString("Commands.Stats.Self") })); | ||||||
|         player.sendMessage(LocaleLoader.getString("Mining.Effect.DropChance", new Object[] { doubleDropChance })); |         } | ||||||
|         player.sendMessage(LocaleLoader.getString("Mining.Ability.Length", new Object[] { superBreakerLength })); |  | ||||||
|  |  | ||||||
|  |         if (canDoubleDrop) { | ||||||
|  |             player.sendMessage(LocaleLoader.getString("Mining.Effect.DropChance", new Object[] { doubleDropChance })); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (canSuperBreaker) { | ||||||
|  |             player.sendMessage(LocaleLoader.getString("Mining.Ability.Length", new Object[] { superBreakerLength })); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (canBlast) { | ||||||
|             if (PP.getSkillLevel(SkillType.MINING) < 125) { |             if (PP.getSkillLevel(SkillType.MINING) < 125) { | ||||||
|                 player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Mining.Ability.Locked.0") })); |                 player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Mining.Ability.Locked.0") })); | ||||||
|             } |             } | ||||||
|             else { |             else { | ||||||
|             player.sendMessage(LocaleLoader.getString("Mining.Blast.Rank", new Object[] { blastMiningRank, LocaleLoader.getString("Mining.Blast.Effect." + (blastMiningRank - 1)) })); |                 player.sendMessage(LocaleLoader.getString("Mining.Blast.Rank", new Object[] { blastMiningRank, LocaleLoader.getString("Mining.Blast.Effect." + (Misc.getInt(blastMiningRank) - 1)) })); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         if (canBiggerBombs) { | ||||||
|             if (PP.getSkillLevel(SkillType.MINING) < 250) { |             if (PP.getSkillLevel(SkillType.MINING) < 250) { | ||||||
|                 player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Mining.Ability.Locked.1") })); |                 player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Mining.Ability.Locked.1") })); | ||||||
|             } |             } | ||||||
|             else { |             else { | ||||||
|                 player.sendMessage(LocaleLoader.getString("Mining.Blast.Radius.Increase", new Object[] { blastRadiusIncrease })); |                 player.sendMessage(LocaleLoader.getString("Mining.Blast.Radius.Increase", new Object[] { blastRadiusIncrease })); | ||||||
|             } |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (canDemoExpert) { | ||||||
|             if (PP.getSkillLevel(SkillType.MINING) < 500) { |             if (PP.getSkillLevel(SkillType.MINING) < 500) { | ||||||
|                 player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Mining.Ability.Locked.2") })); |                 player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Mining.Ability.Locked.2") })); | ||||||
|             } |             } | ||||||
|             else { |             else { | ||||||
|                 player.sendMessage(LocaleLoader.getString("Mining.Effect.Decrease", new Object[] { blastDamageDecrease })); |                 player.sendMessage(LocaleLoader.getString("Mining.Effect.Decrease", new Object[] { blastDamageDecrease })); | ||||||
|             } |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|         Page.grabGuidePageForSkill(SkillType.MINING, player, args); |         Page.grabGuidePageForSkill(SkillType.MINING, player, args); | ||||||
|  |  | ||||||
| @@ -78,61 +120,73 @@ public class MiningCommand implements CommandExecutor { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void dataCalculations(float skillValue) { |     private void dataCalculations(float skillValue) { | ||||||
|  |         DecimalFormat percent = new DecimalFormat("##0.00%"); | ||||||
|  |  | ||||||
|         superBreakerLength = String.valueOf(2 + ((int) skillValue / 50)); |         superBreakerLength = String.valueOf(2 + ((int) skillValue / 50)); | ||||||
|  |  | ||||||
|         if (skillValue >= 1000) { |         if (skillValue >= 1000) { | ||||||
|             blastMiningRank = 8; |             blastMiningRank = "8"; | ||||||
|             blastDamageDecrease = 100; |             blastDamageDecrease = "100.00%"; | ||||||
|             blastRadiusIncrease = 4; |             blastRadiusIncrease = "4"; | ||||||
|             doubleDropChance = "100"; |             doubleDropChance = "100.00%"; | ||||||
|         } |         } | ||||||
|         else if (skillValue >= 875) { |         else if (skillValue >= 875) { | ||||||
|             blastMiningRank = 7; |             blastMiningRank = "7"; | ||||||
|             blastDamageDecrease = 50; |             blastDamageDecrease = "50.00%"; | ||||||
|             blastRadiusIncrease = 3; |             blastRadiusIncrease = "3"; | ||||||
|             doubleDropChance = String.valueOf(skillValue / 10); |             doubleDropChance = percent.format(skillValue / 1000); | ||||||
|         } |         } | ||||||
|         else if (skillValue >= 750) { |         else if (skillValue >= 750) { | ||||||
|             blastMiningRank = 6; |             blastMiningRank = "6"; | ||||||
|             blastDamageDecrease = 50; |             blastDamageDecrease = "50.00%"; | ||||||
|             blastRadiusIncrease = 3; |             blastRadiusIncrease = "3"; | ||||||
|             doubleDropChance = String.valueOf(skillValue / 10); |             doubleDropChance = percent.format(skillValue / 1000); | ||||||
|         } |         } | ||||||
|         else if (skillValue >= 625) { |         else if (skillValue >= 625) { | ||||||
|             blastMiningRank = 5; |             blastMiningRank = "5"; | ||||||
|             blastDamageDecrease = 25; |             blastDamageDecrease = "25.00%"; | ||||||
|             blastRadiusIncrease = 2; |             blastRadiusIncrease = "2"; | ||||||
|             doubleDropChance = String.valueOf(skillValue / 10); |             doubleDropChance = percent.format(skillValue / 1000); | ||||||
|         } |         } | ||||||
|         else if (skillValue >= 500) { |         else if (skillValue >= 500) { | ||||||
|             blastMiningRank = 4; |             blastMiningRank = "4"; | ||||||
|             blastDamageDecrease = 25; |             blastDamageDecrease = "25.00%"; | ||||||
|             blastRadiusIncrease = 2; |             blastRadiusIncrease = "2"; | ||||||
|             doubleDropChance = String.valueOf(skillValue / 10); |             doubleDropChance = percent.format(skillValue / 1000); | ||||||
|         } |         } | ||||||
|         else if (skillValue >= 375) { |         else if (skillValue >= 375) { | ||||||
|             blastMiningRank = 3; |             blastMiningRank = "3"; | ||||||
|             blastDamageDecrease = 0; |             blastDamageDecrease = "0.00%"; | ||||||
|             blastRadiusIncrease = 1; |             blastRadiusIncrease = "1"; | ||||||
|             doubleDropChance = String.valueOf(skillValue / 10); |             doubleDropChance = percent.format(skillValue / 1000); | ||||||
|         } |         } | ||||||
|         else if (skillValue >= 250) { |         else if (skillValue >= 250) { | ||||||
|             blastMiningRank = 2; |             blastMiningRank = "2"; | ||||||
|             blastDamageDecrease = 0; |             blastDamageDecrease = "0.00%"; | ||||||
|             blastRadiusIncrease = 1; |             blastRadiusIncrease = "1"; | ||||||
|             doubleDropChance = String.valueOf(skillValue / 10); |             doubleDropChance = percent.format(skillValue / 1000); | ||||||
|         } |         } | ||||||
|         else if (skillValue >= 125) { |         else if (skillValue >= 125) { | ||||||
|             blastMiningRank = 1; |             blastMiningRank = "1"; | ||||||
|             blastDamageDecrease = 0; |             blastDamageDecrease = "0.00%"; | ||||||
|             blastRadiusIncrease = 0; |             blastRadiusIncrease = "0"; | ||||||
|             doubleDropChance = String.valueOf(skillValue / 10); |             doubleDropChance = percent.format(skillValue / 1000); | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             blastMiningRank = 0; |             blastMiningRank = "0"; | ||||||
|             blastDamageDecrease = 0; |             blastDamageDecrease = "0.00%"; | ||||||
|             blastRadiusIncrease = 0; |             blastRadiusIncrease = "0"; | ||||||
|             doubleDropChance = String.valueOf(skillValue / 10); |             doubleDropChance = percent.format(skillValue / 1000); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     private void permissionsCheck(Player player) { | ||||||
|  |         Permissions permInstance = Permissions.getInstance(); | ||||||
|  |  | ||||||
|  |         canBiggerBombs = permInstance.biggerBombs(player); | ||||||
|  |         canBlast = permInstance.blastMining(player); | ||||||
|  |         canDemoExpert = permInstance.demolitionsExpertise(player); | ||||||
|  |         canDoubleDrop = permInstance.miningDoubleDrops(player); | ||||||
|  |         canSuperBreaker = permInstance.superBreaker(player); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -285,8 +285,8 @@ public class BlastMining { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         /* Send message to nearby players */ |         /* Send message to nearby players */ | ||||||
|         for(Player y : player.getWorld().getPlayers()) { |         for (Player y : player.getWorld().getPlayers()) { | ||||||
|             if(y != player && Misc.isNear(player.getLocation(), y.getLocation(), MAX_DISTANCE_AWAY)) { |             if (y != player && Misc.isNear(player.getLocation(), y.getLocation(), MAX_DISTANCE_AWAY)) { | ||||||
|                 y.sendMessage(ability.getAbilityPlayer(player)); |                 y.sendMessage(ability.getAbilityPlayer(player)); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -336,6 +336,10 @@ public class Permissions { | |||||||
|         return player.hasPermission("mcmmo.ability.blastmining.demolitionsexpertise"); |         return player.hasPermission("mcmmo.ability.blastmining.demolitionsexpertise"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public boolean blastMining(Player player) { | ||||||
|  |         return player.hasPermission("mcmmo.ability.blastmining.detonate"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /* |     /* | ||||||
|      * MCMMO.ITEM.* |      * MCMMO.ITEM.* | ||||||
|      */ |      */ | ||||||
| @@ -392,10 +396,6 @@ public class Permissions { | |||||||
|         return player.hasPermission("mcmmo.skills.mining"); |         return player.hasPermission("mcmmo.skills.mining"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public boolean blastMining(Player player) { |  | ||||||
|         return player.hasPermission("mcmmo.skills.blastmining"); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public boolean fishing(Player player) { |     public boolean fishing(Player player) { | ||||||
|         return player.hasPermission("mcmmo.skills.fishing"); |         return player.hasPermission("mcmmo.skills.fishing"); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -271,7 +271,7 @@ Taming.Ability.Locked.3=LOCKED UNTIL 750+ SKILL (SHARPENED CLAWS) | |||||||
| Taming.Ability.Locked.4=LOCKED UNTIL 50+ SKILL (FAST FOOD SERVICE) | Taming.Ability.Locked.4=LOCKED UNTIL 50+ SKILL (FAST FOOD SERVICE) | ||||||
| Taming.Combat.Chance.Gore=[[RED]]Gore Chance: [[YELLOW]]{0}% | Taming.Combat.Chance.Gore=[[RED]]Gore Chance: [[YELLOW]]{0}% | ||||||
| Taming.Effect.0=Beast Lore | Taming.Effect.0=Beast Lore | ||||||
| Taming.Effect.1=Bone-whacking inspects wolves/ocelots | Taming.Effect.1=Bone-whacking inspects wolves & ocelots | ||||||
| Taming.Effect.10=Shock Proof | Taming.Effect.10=Shock Proof | ||||||
| Taming.Effect.11=Explosive Damage Reduction | Taming.Effect.11=Explosive Damage Reduction | ||||||
| Taming.Effect.12=Call of the Wild | Taming.Effect.12=Call of the Wild | ||||||
|   | |||||||
| @@ -318,7 +318,7 @@ permissions: | |||||||
|             mcmmo.ability.herbalism.greenterra: true |             mcmmo.ability.herbalism.greenterra: true | ||||||
|             mcmmo.ability.herbalism.greenthumbblocks: true |             mcmmo.ability.herbalism.greenthumbblocks: true | ||||||
|             mcmmo.ability.herbalism.greenthumbwheat: true |             mcmmo.ability.herbalism.greenthumbwheat: true | ||||||
|             mcmmo.ability.herbalism.foodbonus: true |             mcmmo.ability.herbalism.farmersdiet: true | ||||||
|     mcmmo.ability.herbalism.doubledrops: |     mcmmo.ability.herbalism.doubledrops: | ||||||
|         description: Allows double drop chance from Herbalism |         description: Allows double drop chance from Herbalism | ||||||
|     mcmmo.ability.herbalism.greenterra: |     mcmmo.ability.herbalism.greenterra: | ||||||
| @@ -385,12 +385,15 @@ permissions: | |||||||
|         children: |         children: | ||||||
|             mcmmo.ability.blastmining.biggerbombs: true |             mcmmo.ability.blastmining.biggerbombs: true | ||||||
|             mcmmo.ability.blastmining.demolitionsexpertise: true |             mcmmo.ability.blastmining.demolitionsexpertise: true | ||||||
|  |             mcmmo.ability.blastmining.detonate: true | ||||||
|     mcmmo.ability.blastmining.biggerbombs: |     mcmmo.ability.blastmining.biggerbombs: | ||||||
|         description: Allows access to the Bigger Bombs ability |         description: Allows access to the Bigger Bombs ability | ||||||
|     mcmmo.ability.blastmining.demolitionsexpertise: |     mcmmo.ability.blastmining.demolitionsexpertise: | ||||||
|         description: Allows access to the Demolitions Expertise ability |         description: Allows access to the Demolitions Expertise ability | ||||||
|  |     mcmmo.ability.blastmining.detonate: | ||||||
|  |         description: Allows for remote TNT detonation | ||||||
|     mcmmo.item.*: |     mcmmo.item.*: | ||||||
|         description: Implies all mcmmo.item permissions. |         description: Implies all mcmmo.item permissions | ||||||
|         children: |         children: | ||||||
|             mcmmo.item.chimaerawing: true  |             mcmmo.item.chimaerawing: true  | ||||||
|     mcmmo.item.chimaerawing: |     mcmmo.item.chimaerawing: | ||||||
| @@ -461,5 +464,3 @@ permissions: | |||||||
|         description: Allows access to the Axes skill |         description: Allows access to the Axes skill | ||||||
|     mcmmo.skills.acrobatics: |     mcmmo.skills.acrobatics: | ||||||
|         description: Allows access to the Acrobatics skill |         description: Allows access to the Acrobatics skill | ||||||
|     mcmmo.skills.blastmining: |  | ||||||
|         description: Allows access to the Blast Mining subskill for Mining |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 GJ
					GJ