Ver código fonte

Crimes were commited today.
PrimarySkillType was a mess... SkillTools is not much better though.

nossr50 6 anos atrás
pai
commit
084b5edf1f
66 arquivos alterados com 1143 adições e 984 exclusões
  1. 2 2
      src/main/java/com/gmail/nossr50/api/ExperienceAPI.java
  2. 1 1
      src/main/java/com/gmail/nossr50/api/SkillAPI.java
  3. 1 1
      src/main/java/com/gmail/nossr50/commands/experience/AddLevelsCommand.java
  4. 1 1
      src/main/java/com/gmail/nossr50/commands/experience/AddXPCommand.java
  5. 4 4
      src/main/java/com/gmail/nossr50/commands/experience/ExperienceCommand.java
  6. 1 1
      src/main/java/com/gmail/nossr50/commands/experience/SkillEditCommand.java
  7. 5 5
      src/main/java/com/gmail/nossr50/commands/experience/SkillResetCommand.java
  8. 14 2
      src/main/java/com/gmail/nossr50/commands/party/PartyInfoCommand.java
  9. 1 2
      src/main/java/com/gmail/nossr50/commands/party/teleport/PtpAcceptCommand.java
  10. 2 3
      src/main/java/com/gmail/nossr50/commands/party/teleport/PtpCommand.java
  11. 1 1
      src/main/java/com/gmail/nossr50/commands/player/LeaderboardCommand.java
  12. 6 7
      src/main/java/com/gmail/nossr50/commands/skills/SkillCommand.java
  13. 1 1
      src/main/java/com/gmail/nossr50/commands/skills/SkillGuideCommand.java
  14. 1 1
      src/main/java/com/gmail/nossr50/core/DynamicSettingsManager.java
  15. 10 10
      src/main/java/com/gmail/nossr50/database/FlatFileDatabaseManager.java
  16. 11 11
      src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java
  17. 0 25
      src/main/java/com/gmail/nossr50/datatypes/mods/CustomBlock.java
  18. 0 45
      src/main/java/com/gmail/nossr50/datatypes/mods/CustomEntity.java
  19. 0 25
      src/main/java/com/gmail/nossr50/datatypes/mods/CustomTool.java
  20. 0 23
      src/main/java/com/gmail/nossr50/datatypes/party/ItemShareType.java
  21. 9 3
      src/main/java/com/gmail/nossr50/datatypes/party/Party.java
  22. 0 13
      src/main/java/com/gmail/nossr50/datatypes/party/PartyFeature.java
  23. 2 1
      src/main/java/com/gmail/nossr50/datatypes/party/PartyTeleportRecord.java
  24. 1 3
      src/main/java/com/gmail/nossr50/datatypes/party/ShareMode.java
  25. 77 26
      src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java
  26. 14 10
      src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java
  27. 15 251
      src/main/java/com/gmail/nossr50/datatypes/skills/PrimarySkillType.java
  28. 14 13
      src/main/java/com/gmail/nossr50/datatypes/skills/SubSkillType.java
  29. 1 2
      src/main/java/com/gmail/nossr50/datatypes/skills/behaviours/HerbalismBehaviour.java
  30. 8 9
      src/main/java/com/gmail/nossr50/datatypes/skills/subskills/acrobatics/Roll.java
  31. 25 0
      src/main/java/com/gmail/nossr50/dumpster/CustomBlock.java
  32. 45 0
      src/main/java/com/gmail/nossr50/dumpster/CustomEntity.java
  33. 25 0
      src/main/java/com/gmail/nossr50/dumpster/CustomTool.java
  34. 1 1
      src/main/java/com/gmail/nossr50/events/skills/secondaryabilities/SubSkillEvent.java
  35. 7 7
      src/main/java/com/gmail/nossr50/listeners/BlockListener.java
  36. 4 5
      src/main/java/com/gmail/nossr50/listeners/InventoryListener.java
  37. 9 10
      src/main/java/com/gmail/nossr50/listeners/PlayerListener.java
  38. 10 2
      src/main/java/com/gmail/nossr50/mcMMO.java
  39. 18 1
      src/main/java/com/gmail/nossr50/party/ShareHandler.java
  40. 2 2
      src/main/java/com/gmail/nossr50/runnables/commands/LeaderboardsCommandDisplayTask.java
  41. 2 2
      src/main/java/com/gmail/nossr50/runnables/commands/RankCommandDisplayTask.java
  42. 1 1
      src/main/java/com/gmail/nossr50/runnables/database/FormulaConversionTask.java
  43. 1 2
      src/main/java/com/gmail/nossr50/runnables/items/ChimaeraWingWarmup.java
  44. 1 2
      src/main/java/com/gmail/nossr50/runnables/items/TeleportationWarmup.java
  45. 2 3
      src/main/java/com/gmail/nossr50/runnables/skills/AbilityDisableTask.java
  46. 2 3
      src/main/java/com/gmail/nossr50/skills/acrobatics/AcrobaticsManager.java
  47. 5 2
      src/main/java/com/gmail/nossr50/skills/axes/AxesManager.java
  48. 1 2
      src/main/java/com/gmail/nossr50/skills/excavation/ExcavationManager.java
  49. 1 2
      src/main/java/com/gmail/nossr50/skills/fishing/FishingManager.java
  50. 1 2
      src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java
  51. 1 2
      src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java
  52. 1 2
      src/main/java/com/gmail/nossr50/skills/repair/RepairManager.java
  53. 1 2
      src/main/java/com/gmail/nossr50/skills/salvage/SalvageManager.java
  54. 1 2
      src/main/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingManager.java
  55. 2 3
      src/main/java/com/gmail/nossr50/util/ChimaeraWing.java
  56. 3 3
      src/main/java/com/gmail/nossr50/util/EventManager.java
  57. 4 4
      src/main/java/com/gmail/nossr50/util/HardcoreManager.java
  58. 1 2
      src/main/java/com/gmail/nossr50/util/Motd.java
  59. 1 1
      src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java
  60. 3 4
      src/main/java/com/gmail/nossr50/util/commands/CommandTools.java
  61. 2 2
      src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardStrings.java
  62. 4 4
      src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardWrapper.java
  63. 13 13
      src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java
  64. 1 1
      src/main/java/com/gmail/nossr50/util/skills/RankUtils.java
  65. 739 0
      src/main/java/com/gmail/nossr50/util/skills/SkillTools.java
  66. 0 388
      src/main/java/com/gmail/nossr50/util/skills/SkillUtils.java

+ 2 - 2
src/main/java/com/gmail/nossr50/api/ExperienceAPI.java

@@ -707,7 +707,7 @@
 //        int powerLevel = 0;
 //        PlayerProfile profile = getOfflineProfile(playerName);
 //
-//        for (PrimarySkillType type : PrimarySkillType.NON_CHILD_SKILLS) {
+//        for (PrimarySkillType type : pluginRef.getSkillTools().NON_CHILD_SKILLS) {
 //            powerLevel += profile.getSkillLevel(type);
 //        }
 //
@@ -727,7 +727,7 @@
 //        int powerLevel = 0;
 //        PlayerProfile profile = getOfflineProfile(uuid);
 //
-//        for (PrimarySkillType type : PrimarySkillType.NON_CHILD_SKILLS) {
+//        for (PrimarySkillType type : pluginRef.getSkillTools().NON_CHILD_SKILLS) {
 //            powerLevel += profile.getSkillLevel(type);
 //        }
 //

+ 1 - 1
src/main/java/com/gmail/nossr50/api/SkillAPI.java

@@ -31,7 +31,7 @@
 //     * @return a list of strings with valid skill names
 //     */
 //    public static List<String> getNonChildSkills() {
-//        return getListFromEnum(PrimarySkillType.NON_CHILD_SKILLS);
+//        return getListFromEnum(pluginRef.getSkillTools().NON_CHILD_SKILLS);
 //    }
 //
 //    /**

+ 1 - 1
src/main/java/com/gmail/nossr50/commands/experience/AddLevelsCommand.java

@@ -44,6 +44,6 @@ public class AddLevelsCommand extends ExperienceCommand {
 
     @Override
     protected void handlePlayerMessageSkill(Player player, int value, PrimarySkillType skill) {
-        player.sendMessage(pluginRef.getLocaleManager().getString("Commands.addlevels.AwardSkill.1", value, skill.getName()));
+        player.sendMessage(pluginRef.getLocaleManager().getString("Commands.addlevels.AwardSkill.1", value, skill.getLocalizedSkillName()));
     }
 }

+ 1 - 1
src/main/java/com/gmail/nossr50/commands/experience/AddXPCommand.java

@@ -46,6 +46,6 @@ public class AddXPCommand extends ExperienceCommand {
 
     @Override
     protected void handlePlayerMessageSkill(Player player, int value, PrimarySkillType skill) {
-        player.sendMessage(pluginRef.getLocaleManager().getString("Commands.addxp.AwardSkill", value, skill.getName()));
+        player.sendMessage(pluginRef.getLocaleManager().getString("Commands.addxp.AwardSkill", value, skill.getLocalizedSkillName()));
     }
 }

+ 4 - 4
src/main/java/com/gmail/nossr50/commands/experience/ExperienceCommand.java

@@ -28,7 +28,7 @@ public abstract class ExperienceCommand implements TabExecutor {
         if (skill == null) {
             sender.sendMessage(pluginRef.getLocaleManager().getString("Commands.addlevels.AwardAll.2", playerName));
         } else {
-            sender.sendMessage(pluginRef.getLocaleManager().getString("Commands.addlevels.AwardSkill.2", skill.getName(), playerName));
+            sender.sendMessage(pluginRef.getLocaleManager().getString("Commands.addlevels.AwardSkill.2", skill.getLocalizedSkillName(), playerName));
         }
     }
 
@@ -51,7 +51,7 @@ public abstract class ExperienceCommand implements TabExecutor {
                     return true;
                 }
 
-                skill = PrimarySkillType.getSkill(args[0]);
+                skill = PrimarySkillType.matchSkill(args[0]);
 
                 if (args[1].equalsIgnoreCase("all")) {
                     skill = null;
@@ -82,7 +82,7 @@ public abstract class ExperienceCommand implements TabExecutor {
                     return true;
                 }
 
-                skill = PrimarySkillType.getSkill(args[1]);
+                skill = PrimarySkillType.matchSkill(args[1]);
 
                 if (args[1].equalsIgnoreCase("all")) {
                     skill = null;
@@ -153,7 +153,7 @@ public abstract class ExperienceCommand implements TabExecutor {
 
     protected void editValues(Player player, PlayerProfile profile, PrimarySkillType skill, int value) {
         if (skill == null) {
-            for (PrimarySkillType primarySkillType : PrimarySkillType.NON_CHILD_SKILLS) {
+            for (PrimarySkillType primarySkillType : pluginRef.getSkillTools().NON_CHILD_SKILLS) {
                 handleCommand(player, profile, primarySkillType, value);
             }
 

+ 1 - 1
src/main/java/com/gmail/nossr50/commands/experience/SkillEditCommand.java

@@ -49,6 +49,6 @@ public class SkillEditCommand extends ExperienceCommand {
 
     @Override
     protected void handlePlayerMessageSkill(Player player, int value, PrimarySkillType skill) {
-        player.sendMessage(pluginRef.getLocaleManager().getString("Commands.mmoedit.Modified.1", skill.getName(), value));
+        player.sendMessage(pluginRef.getLocaleManager().getString("Commands.mmoedit.Modified.1", skill.getLocalizedSkillName(), value));
     }
 }

+ 5 - 5
src/main/java/com/gmail/nossr50/commands/experience/SkillResetCommand.java

@@ -34,7 +34,7 @@ public class SkillResetCommand implements TabExecutor {
         if (skill == null) {
             sender.sendMessage(pluginRef.getLocaleManager().getString("Commands.addlevels.AwardAll.2", playerName));
         } else {
-            sender.sendMessage(pluginRef.getLocaleManager().getString("Commands.addlevels.AwardSkill.2", skill.getName(), playerName));
+            sender.sendMessage(pluginRef.getLocaleManager().getString("Commands.addlevels.AwardSkill.2", skill.getLocalizedSkillName(), playerName));
         }
     }
 
@@ -59,7 +59,7 @@ public class SkillResetCommand implements TabExecutor {
                 if (args[0].equalsIgnoreCase("all")) {
                     skill = null;
                 } else {
-                    skill = PrimarySkillType.getSkill(args[1]);
+                    skill = PrimarySkillType.matchSkill(args[1]);
                 }
 
                 editValues((Player) sender, pluginRef.getUserManager().getPlayer(sender.getName()).getProfile(), skill);
@@ -78,7 +78,7 @@ public class SkillResetCommand implements TabExecutor {
                 if (args[1].equalsIgnoreCase("all")) {
                     skill = null;
                 } else {
-                    skill = PrimarySkillType.getSkill(args[1]);
+                    skill = PrimarySkillType.matchSkill(args[1]);
                 }
 
                 String playerName = pluginRef.getCommandTools().getMatchedPlayerName(args[0]);
@@ -150,7 +150,7 @@ public class SkillResetCommand implements TabExecutor {
     }
 
     protected void handlePlayerMessageSkill(Player player, PrimarySkillType skill) {
-        player.sendMessage(pluginRef.getLocaleManager().getString("Commands.Reset.Single", skill.getName()));
+        player.sendMessage(pluginRef.getLocaleManager().getString("Commands.Reset.Single", skill.getLocalizedSkillName()));
     }
 
     private boolean validateArguments(CommandSender sender, String skillName) {
@@ -159,7 +159,7 @@ public class SkillResetCommand implements TabExecutor {
 
     protected void editValues(Player player, PlayerProfile profile, PrimarySkillType skill) {
         if (skill == null) {
-            for (PrimarySkillType primarySkillType : PrimarySkillType.NON_CHILD_SKILLS) {
+            for (PrimarySkillType primarySkillType : pluginRef.getSkillTools().NON_CHILD_SKILLS) {
                 handleCommand(player, profile, primarySkillType);
             }
 

+ 14 - 2
src/main/java/com/gmail/nossr50/commands/party/PartyInfoCommand.java

@@ -5,6 +5,7 @@ import com.gmail.nossr50.datatypes.party.PartyFeature;
 import com.gmail.nossr50.datatypes.party.ShareMode;
 import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.mcMMO;
+import com.gmail.nossr50.util.StringUtils;
 import org.bukkit.ChatColor;
 import org.bukkit.command.Command;
 import org.bukkit.command.CommandExecutor;
@@ -72,9 +73,9 @@ public class PartyInfoCommand implements CommandExecutor {
             }
 
             if (isUnlockedFeature(party, partyFeature)) {
-                unlockedPartyFeatures.add(partyFeature.getLocaleString());
+                unlockedPartyFeatures.add(getPartyFeatureLocaleString(partyFeature));
             } else {
-                lockedPartyFeatures.add(partyFeature.getFeatureLockedLocaleString());
+                lockedPartyFeatures.add(getFeatureLockedLocaleString(partyFeature));
             }
         }
 
@@ -85,6 +86,17 @@ public class PartyInfoCommand implements CommandExecutor {
         }
     }
 
+    public String getPartyFeatureLocaleString(PartyFeature partyFeature) {
+        return pluginRef.getLocaleManager().getString("Party.Feature." + StringUtils.getPrettyPartyFeatureString(partyFeature).replace(" ", ""));
+    }
+
+    public String getFeatureLockedLocaleString(PartyFeature partyFeature) {
+        return pluginRef.getLocaleManager().getString("Ability.Generic.Template.Lock",
+                pluginRef.getLocaleManager().getString("Party.Feature.Locked."
+                                + StringUtils.getPrettyPartyFeatureString(partyFeature).replace(" ", ""),
+                        pluginRef.getPartyManager().getPartyFeatureUnlockLevel(partyFeature)));
+    }
+
     private boolean isUnlockedFeature(Party party, PartyFeature partyFeature) {
         return party.getLevel() >= pluginRef.getPartyManager().getPartyFeatureUnlockLevel(partyFeature);
     }

+ 1 - 2
src/main/java/com/gmail/nossr50/commands/party/teleport/PtpAcceptCommand.java

@@ -3,7 +3,6 @@ package com.gmail.nossr50.commands.party.teleport;
 import com.gmail.nossr50.datatypes.party.PartyTeleportRecord;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.util.Permissions;
-import com.gmail.nossr50.util.skills.SkillUtils;
 import org.bukkit.World;
 import org.bukkit.command.Command;
 import org.bukkit.command.CommandExecutor;
@@ -38,7 +37,7 @@ public class PtpAcceptCommand implements CommandExecutor {
             return true;
         }
 
-        if (SkillUtils.cooldownExpired(ptpRecord.getTimeout(), pluginRef.getConfigManager().getConfigParty().getPTP().getPtpRequestTimeout())) {
+        if (pluginRef.getSkillTools().cooldownExpired(ptpRecord.getTimeout(), pluginRef.getConfigManager().getConfigParty().getPTP().getPtpRequestTimeout())) {
             ptpRecord.removeRequest();
             player.sendMessage(pluginRef.getLocaleManager().getString("Commands.ptp.RequestExpired"));
             return true;

+ 2 - 3
src/main/java/com/gmail/nossr50/commands/party/teleport/PtpCommand.java

@@ -8,7 +8,6 @@ import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.Permissions;
-import com.gmail.nossr50.util.skills.SkillUtils;
 import com.gmail.nossr50.worldguard.WorldGuardUtils;
 import com.google.common.collect.ImmutableList;
 import org.bukkit.command.Command;
@@ -91,7 +90,7 @@ public class PtpCommand implements TabExecutor {
             int hurtCooldown = pluginRef.getConfigManager().getConfigParty().getPTP().getPtpRecentlyHurtCooldown();
 
             if (hurtCooldown > 0) {
-                int timeRemaining = SkillUtils.calculateTimeLeft(recentlyHurt * Misc.TIME_CONVERSION_FACTOR, hurtCooldown, player);
+                int timeRemaining = pluginRef.getSkillTools().calculateTimeLeft(recentlyHurt * Misc.TIME_CONVERSION_FACTOR, hurtCooldown, player);
 
                 if (timeRemaining > 0) {
                     player.sendMessage(pluginRef.getLocaleManager().getString("Item.Injured.Wait", timeRemaining));
@@ -112,7 +111,7 @@ public class PtpCommand implements TabExecutor {
             long ptpLastUse = mcMMOPlayer.getPartyTeleportRecord().getLastUse();
 
             if (ptpCooldown > 0) {
-                int timeRemaining = SkillUtils.calculateTimeLeft(ptpLastUse * Misc.TIME_CONVERSION_FACTOR, ptpCooldown, player);
+                int timeRemaining = pluginRef.getSkillTools().calculateTimeLeft(ptpLastUse * Misc.TIME_CONVERSION_FACTOR, ptpCooldown, player);
 
                 if (timeRemaining > 0) {
                     player.sendMessage(pluginRef.getLocaleManager().getString("Item.Generic.Wait", timeRemaining));

+ 1 - 1
src/main/java/com/gmail/nossr50/commands/player/LeaderboardCommand.java

@@ -128,7 +128,7 @@ public class LeaderboardCommand implements TabExecutor {
             return null;
         }
 
-        PrimarySkillType skill = PrimarySkillType.getSkill(skillName);
+        PrimarySkillType skill = PrimarySkillType.matchSkill(skillName);
 
         if (pluginRef.getCommandTools().isChildSkill(sender, skill)) {
             return null;

+ 6 - 7
src/main/java/com/gmail/nossr50/commands/skills/SkillCommand.java

@@ -10,7 +10,6 @@ import com.gmail.nossr50.util.StringUtils;
 import com.gmail.nossr50.util.random.RandomChanceUtil;
 import com.gmail.nossr50.util.skills.RankUtils;
 import com.gmail.nossr50.util.skills.SkillActivationType;
-import com.gmail.nossr50.util.skills.SkillUtils;
 import com.google.common.collect.ImmutableList;
 import net.md_5.bungee.api.ChatColor;
 import net.md_5.bungee.api.chat.TextComponent;
@@ -36,7 +35,7 @@ public abstract class SkillCommand implements TabExecutor {
     public SkillCommand(PrimarySkillType skill, mcMMO pluginRef) {
         this.pluginRef = pluginRef;
         this.skill = skill;
-        skillName = skill.getName();
+        skillName = skill.getLocalizedSkillName();
         skillGuideCommand = new SkillGuideCommand(skill, pluginRef);
     }
 
@@ -70,7 +69,7 @@ public abstract class SkillCommand implements TabExecutor {
                 McMMOPlayer mcMMOPlayer = pluginRef.getUserManager().getPlayer(player);
 
                 boolean isLucky = Permissions.lucky(player, skill);
-                boolean hasEndurance = SkillUtils.getEnduranceLength(player) > 0;
+                boolean hasEndurance = pluginRef.getSkillTools().getEnduranceLength(player) > 0;
                 double skillValue = mcMMOPlayer.getSkillLevel(skill);
 
                 //Send the players a few blank lines to make finding the top of the skill command easier
@@ -174,10 +173,10 @@ public abstract class SkillCommand implements TabExecutor {
 
             for (int i = 0; i < parentList.size(); i++) {
                 if (i + 1 < parentList.size()) {
-                    parentMessage.append(pluginRef.getLocaleManager().getString("Effects.Child.ParentList", parentList.get(i).getName(), mcMMOPlayer.getSkillLevel(parentList.get(i))));
+                    parentMessage.append(pluginRef.getLocaleManager().getString("Effects.Child.ParentList", parentList.get(i).getLocalizedSkillName(), mcMMOPlayer.getSkillLevel(parentList.get(i))));
                     parentMessage.append(ChatColor.GRAY + ", ");
                 } else {
-                    parentMessage.append(pluginRef.getLocaleManager().getString("Effects.Child.ParentList", parentList.get(i).getName(), mcMMOPlayer.getSkillLevel(parentList.get(i))));
+                    parentMessage.append(pluginRef.getLocaleManager().getString("Effects.Child.ParentList", parentList.get(i).getLocalizedSkillName(), mcMMOPlayer.getSkillLevel(parentList.get(i))));
                 }
             }
 
@@ -211,9 +210,9 @@ public abstract class SkillCommand implements TabExecutor {
 
     protected String[] formatLengthDisplayValues(Player player, double skillValue) {
 
-        int length = SkillUtils.calculateAbilityLength(pluginRef.getUserManager().getPlayer(player), skill, skill.getSuperAbility());
+        int length = pluginRef.getSkillTools().calculateAbilityLength(pluginRef.getUserManager().getPlayer(player), skill, skill.getSuperAbility());
 
-        int enduranceLength = SkillUtils.calculateAbilityLengthPerks(pluginRef.getUserManager().getPlayer(player), skill, skill.getSuperAbility());
+        int enduranceLength = pluginRef.getSkillTools().calculateAbilityLengthPerks(pluginRef.getUserManager().getPlayer(player), skill, skill.getSuperAbility());
 
         return new String[]{String.valueOf(length), String.valueOf(enduranceLength)};
     }

+ 1 - 1
src/main/java/com/gmail/nossr50/commands/skills/SkillGuideCommand.java

@@ -17,7 +17,7 @@ public class SkillGuideCommand implements CommandExecutor {
     private final mcMMO pluginRef;
 
     public SkillGuideCommand(PrimarySkillType skill, mcMMO pluginRef) {
-        header = pluginRef.getLocaleManager().getString("Guides.Header", skill.getName());
+        header = pluginRef.getLocaleManager().getString("Guides.Header", skill.getLocalizedSkillName());
         guide = getGuide(skill);
         invalidPage = pluginRef.getLocaleManager().getString("Guides.Page.Invalid");
         this.pluginRef = pluginRef;

+ 1 - 1
src/main/java/com/gmail/nossr50/core/DynamicSettingsManager.java

@@ -44,8 +44,8 @@ public class DynamicSettingsManager {
     private HashMap<PartyFeature, Integer> partyFeatureUnlocks;
 
     /* Skill Behaviours */
-    private SkillBehaviourManager skillBehaviourManager;
     //TODO: This class is a band-aid fix for a large problem with mcMMO code, they will be removed once the new skill system is in place
+    private SkillBehaviourManager skillBehaviourManager;
 
 
     public DynamicSettingsManager(mcMMO pluginRef) {

+ 10 - 10
src/main/java/com/gmail/nossr50/database/FlatFileDatabaseManager.java

@@ -406,7 +406,7 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
 
         Map<PrimarySkillType, Integer> skills = new HashMap<>();
 
-        for (PrimarySkillType skill : PrimarySkillType.NON_CHILD_SKILLS) {
+        for (PrimarySkillType skill : pluginRef.getSkillTools().NON_CHILD_SKILLS) {
             skills.put(skill, getPlayerRank(playerName, playerStatHash.get(skill)));
         }
 
@@ -533,11 +533,11 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
                 if (create) {
                     if (uuid == null) {
                         newUser(playerName, uuid);
-                        return new PlayerProfile(playerName, true);
+                        return new PlayerProfile(pluginRef, playerName, true);
                     }
 
                     newUser(playerName, uuid);
-                    return new PlayerProfile(playerName, uuid, true);
+                    return new PlayerProfile(pluginRef, playerName, uuid, true);
                 }
             } catch (Exception e) {
                 e.printStackTrace();
@@ -556,10 +556,10 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
 
         // Return unloaded profile
         if (uuid == null) {
-            return new PlayerProfile(playerName);
+            return new PlayerProfile(pluginRef, playerName);
         }
 
-        return new PlayerProfile(playerName, uuid);
+        return new PlayerProfile(pluginRef, playerName, uuid);
     }
 
     public void convertUsers(DatabaseManager destination) {
@@ -583,7 +583,7 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
                         e.printStackTrace();
                     }
                     convertedUsers++;
-                    Misc.printProgress(convertedUsers, progressInterval, startMillis);
+                    printProgress(convertedUsers, startMillis, pluginRef.getLogger());
                 }
             } catch (Exception e) {
                 e.printStackTrace();
@@ -909,7 +909,7 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
                         }
 
                         if (pluginRef.getPlayerLevelingSettings().getConfigSectionLevelCaps().getReducePlayerSkillsAboveCap()) {
-                            for (PrimarySkillType skill : PrimarySkillType.NON_CHILD_SKILLS) {
+                            for (PrimarySkillType skill : pluginRef.getSkillTools().NON_CHILD_SKILLS) {
                                 int index = getSkillIndex(skill);
                                 if (index >= character.length) {
                                     continue;
@@ -918,7 +918,7 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
                                 if (pluginRef.getPlayerLevelingSettings().isSkillLevelCapEnabled(skill)) {
                                     int cap = pluginRef.getPlayerLevelingSettings().getSkillLevelCap(skill);
                                     if (Integer.valueOf(character[index]) > cap) {
-                                        pluginRef.getLogger().warning("Truncating " + skill.getName() + " to configured max level for player " + character[USERNAME]);
+                                        pluginRef.getLogger().warning("Truncating " + pluginRef.getSkillTools().getLocalizedSkillName(skill) + " to configured max level for player " + character[USERNAME]);
                                         character[index] = cap + "";
                                         updated = true;
                                     }
@@ -1051,7 +1051,7 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
 
                         if (pluginRef.getPlayerLevelingSettings().getConfigSectionLevelCaps().getReducePlayerSkillsAboveCap()) {
                             Map<PrimarySkillType, Integer> skills = getSkillMapFromLine(character);
-                            for (PrimarySkillType skill : PrimarySkillType.NON_CHILD_SKILLS) {
+                            for (PrimarySkillType skill : pluginRef.getSkillTools().NON_CHILD_SKILLS) {
                                 int cap = Integer.MAX_VALUE;
                                 if (skills.get(skill) > cap) {
                                     updated = true;
@@ -1194,7 +1194,7 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
             uniquePlayerDataMap.put(UniqueDataType.CHIMAERA_WING_DATS, 0);
         }
 
-        return new PlayerProfile(character[USERNAME], uuid, skills, skillsXp, skillsDATS, mobHealthbarType, scoreboardTipsShown, uniquePlayerDataMap);
+        return new PlayerProfile(pluginRef, character[USERNAME], uuid, skills, skillsXp, skillsDATS, mobHealthbarType, scoreboardTipsShown, uniquePlayerDataMap);
     }
 
     private Map<PrimarySkillType, Integer> getSkillMapFromLine(String[] character) {

+ 11 - 11
src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java

@@ -279,7 +279,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
             statement.setInt(12, profile.getSkillLevel(PrimarySkillType.FISHING));
             statement.setInt(13, profile.getSkillLevel(PrimarySkillType.ALCHEMY));
             int total = 0;
-            for (PrimarySkillType primarySkillType : PrimarySkillType.NON_CHILD_SKILLS)
+            for (PrimarySkillType primarySkillType : pluginRef.getSkillTools().NON_CHILD_SKILLS)
                 total += profile.getSkillLevel(primarySkillType);
             statement.setInt(14, total);
             statement.setInt(15, id);
@@ -401,7 +401,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
 
         try {
             connection = getConnection(PoolIdentifier.MISC);
-            for (PrimarySkillType primarySkillType : PrimarySkillType.NON_CHILD_SKILLS) {
+            for (PrimarySkillType primarySkillType : pluginRef.getSkillTools().NON_CHILD_SKILLS) {
                 String skillName = primarySkillType.name().toLowerCase();
                 // Get count of all users with higher skill level than player
                 String sql = "SELECT COUNT(*) AS rank FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id WHERE " + skillName + " > 0 " +
@@ -563,10 +563,10 @@ public final class SQLDatabaseManager implements DatabaseManager {
                     id = newUser(connection, playerName, uuid);
                     create = false;
                     if (id == -1) {
-                        return new PlayerProfile(playerName, false);
+                        return new PlayerProfile(pluginRef, playerName, false);
                     }
                 } else {
-                    return new PlayerProfile(playerName, false);
+                    return new PlayerProfile(pluginRef, playerName, false);
                 }
             }
             // There is such a user
@@ -633,7 +633,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
 
         // return unloaded profile
         if (!retry) {
-            return new PlayerProfile(playerName, false);
+            return new PlayerProfile(pluginRef, playerName, false);
         }
 
         // Retry, and abort on re-failure
@@ -674,7 +674,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
                     // Ignore
                 }
                 convertedUsers++;
-                Misc.printProgress(convertedUsers, progressInterval, startMillis);
+                printProgress(convertedUsers, startMillis, pluginRef.getLogger());
             }
         } catch (SQLException e) {
             printErrors(e);
@@ -850,7 +850,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
             resultSet = statement.executeQuery();
             if (!resultSet.next()) {
                 String startingLevel = "'" + pluginRef.getPlayerLevelingSettings().getConfigSectionLevelingGeneral().getStartingLevel() + "'";
-                String totalLevel = "'" + (pluginRef.getPlayerLevelingSettings().getConfigSectionLevelingGeneral().getStartingLevel() * (PrimarySkillType.values().length - PrimarySkillType.CHILD_SKILLS.size())) + "'";
+                String totalLevel = "'" + (pluginRef.getPlayerLevelingSettings().getConfigSectionLevelingGeneral().getStartingLevel() * (PrimarySkillType.values().length - pluginRef.getSkillTools().COMBAT_SKILLS.size())) + "'";
                 createStatement = connection.createStatement();
                 createStatement.executeUpdate("CREATE TABLE IF NOT EXISTS `" + tablePrefix + "skills` ("
                         + "`user_id` int(10) unsigned NOT NULL,"
@@ -907,7 +907,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
 
             //Level Cap Stuff
             if (pluginRef.getPlayerLevelingSettings().getConfigSectionLevelCaps().getReducePlayerSkillsAboveCap()) {
-                for (PrimarySkillType skill : PrimarySkillType.NON_CHILD_SKILLS) {
+                for (PrimarySkillType skill : pluginRef.getSkillTools().NON_CHILD_SKILLS) {
                     if (!pluginRef.getPlayerLevelingSettings().isSkillLevelCapEnabled(skill))
                         continue;
 
@@ -1140,7 +1140,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
             uuid = null;
         }
 
-        return new PlayerProfile(playerName, uuid, skills, skillsXp, skillsDATS, mobHealthbarType, scoreboardTipsShown, uniqueData);
+        return new PlayerProfile(pluginRef, playerName, uuid, skills, skillsXp, skillsDATS, mobHealthbarType, scoreboardTipsShown, uniqueData);
     }
 
     private void printErrors(SQLException ex) {
@@ -1240,10 +1240,10 @@ public final class SQLDatabaseManager implements DatabaseManager {
             resultSet = statement.executeQuery("SHOW INDEX FROM `" + tablePrefix + "skills` WHERE `Key_name` LIKE 'idx\\_%'");
             resultSet.last();
 
-            if (resultSet.getRow() != PrimarySkillType.NON_CHILD_SKILLS.size()) {
+            if (resultSet.getRow() != pluginRef.getSkillTools().NON_CHILD_SKILLS.size()) {
                 pluginRef.getLogger().info("Indexing tables, this may take a while on larger databases");
 
-                for (PrimarySkillType skill : PrimarySkillType.NON_CHILD_SKILLS) {
+                for (PrimarySkillType skill : pluginRef.getSkillTools().NON_CHILD_SKILLS) {
                     String skill_name = skill.name().toLowerCase();
 
                     try {

+ 0 - 25
src/main/java/com/gmail/nossr50/datatypes/mods/CustomBlock.java

@@ -1,25 +0,0 @@
-package com.gmail.nossr50.datatypes.mods;
-
-public class CustomBlock {
-    private int xpGain;
-    private boolean canDoubleDrop;
-    private int smeltingXpGain;
-
-    public CustomBlock(int xpGain, boolean canDoubleDrop, int smeltingXpGain) {
-        this.xpGain = xpGain;
-        this.canDoubleDrop = canDoubleDrop;
-        this.smeltingXpGain = smeltingXpGain;
-    }
-
-    public int getXpGain() {
-        return xpGain;
-    }
-
-    public boolean isDoubleDropEnabled() {
-        return canDoubleDrop;
-    }
-
-    public int getSmeltingXpGain() {
-        return smeltingXpGain;
-    }
-}

+ 0 - 45
src/main/java/com/gmail/nossr50/datatypes/mods/CustomEntity.java

@@ -1,45 +0,0 @@
-package com.gmail.nossr50.datatypes.mods;
-
-import org.bukkit.inventory.ItemStack;
-
-public class CustomEntity {
-    private double xpMultiplier;
-    private boolean canBeTamed;
-    private int tamingXP;
-    private boolean canBeSummoned;
-    private ItemStack callOfTheWildItem;
-    private int callOfTheWildAmount;
-
-    public CustomEntity(double xpMultiplier, boolean canBeTamed, int tamingXP, boolean canBeSummoned, ItemStack callOfTheWildItem, int callOfTheWildAmount) {
-        this.xpMultiplier = xpMultiplier;
-        this.canBeTamed = canBeTamed;
-        this.tamingXP = tamingXP;
-        this.canBeSummoned = canBeSummoned;
-        this.callOfTheWildItem = callOfTheWildItem;
-        this.callOfTheWildAmount = callOfTheWildAmount;
-    }
-
-    public double getXpMultiplier() {
-        return xpMultiplier;
-    }
-
-    public boolean canBeTamed() {
-        return canBeTamed;
-    }
-
-    public int getTamingXP() {
-        return tamingXP;
-    }
-
-    public boolean canBeSummoned() {
-        return canBeSummoned;
-    }
-
-    public ItemStack getCallOfTheWildItem() {
-        return callOfTheWildItem;
-    }
-
-    public int getCallOfTheWildAmount() {
-        return callOfTheWildAmount;
-    }
-}

+ 0 - 25
src/main/java/com/gmail/nossr50/datatypes/mods/CustomTool.java

@@ -1,25 +0,0 @@
-package com.gmail.nossr50.datatypes.mods;
-
-public class CustomTool {
-    private double xpMultiplier;
-    private boolean abilityEnabled;
-    private int tier;
-
-    public CustomTool(int tier, boolean abilityEnabled, double xpMultiplier) {
-        this.xpMultiplier = xpMultiplier;
-        this.abilityEnabled = abilityEnabled;
-        this.tier = tier;
-    }
-
-    public double getXpMultiplier() {
-        return xpMultiplier;
-    }
-
-    public boolean isAbilityEnabled() {
-        return abilityEnabled;
-    }
-
-    public int getTier() {
-        return tier;
-    }
-}

+ 0 - 23
src/main/java/com/gmail/nossr50/datatypes/party/ItemShareType.java

@@ -1,9 +1,5 @@
 package com.gmail.nossr50.datatypes.party;
 
-import com.gmail.nossr50.util.ItemUtils;
-import com.gmail.nossr50.util.StringUtils;
-import org.bukkit.inventory.ItemStack;
-
 public enum ItemShareType {
     LOOT,
     MINING,
@@ -11,23 +7,4 @@ public enum ItemShareType {
     WOODCUTTING,
     MISC;
 
-    public static ItemShareType getShareType(ItemStack itemStack) {
-        if (ItemUtils.isMobDrop(itemStack)) {
-            return LOOT;
-        } else if (ItemUtils.isMiningDrop(itemStack)) {
-            return MINING;
-        } else if (ItemUtils.isHerbalismDrop(itemStack)) {
-            return HERBALISM;
-        } else if (ItemUtils.isWoodcuttingDrop(itemStack)) {
-            return WOODCUTTING;
-        } else if (pluginRef.getConfigManager().getConfigParty().getPartyItemShare().getItemShareMap().get(itemStack.getType()) != null) {
-            return MISC;
-        }
-
-        return null;
-    }
-
-    public String getLocaleString() {
-        return pluginRef.getLocaleManager().getString("Party.ItemShare.Category." + StringUtils.getCapitalized(this.toString()));
-    }
 }

+ 9 - 3
src/main/java/com/gmail/nossr50/datatypes/party/Party.java

@@ -4,6 +4,7 @@ import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.party.ShareHandler;
 import com.gmail.nossr50.util.Misc;
+import com.gmail.nossr50.util.StringUtils;
 import com.gmail.nossr50.util.sounds.SoundManager;
 import com.gmail.nossr50.util.sounds.SoundType;
 import org.bukkit.Bukkit;
@@ -43,7 +44,8 @@ public class Party {
     private boolean shareWoodcuttingDrops = true;
     private boolean shareMiscDrops = true;
 
-    public Party(String name) {
+    public Party(String name, mcMMO pluginRef) {
+        this.pluginRef = pluginRef;
         this.name = name;
     }
 
@@ -81,7 +83,7 @@ public class Party {
     }
 
     private void initShareHandler() {
-        shareHandler = new ShareHandler(pluginRef);
+        shareHandler = new ShareHandler(pluginRef, this);
     }
 
     public LinkedHashMap<UUID, String> getMembers() {
@@ -169,13 +171,17 @@ public class Party {
 
         for (ItemShareType shareType : ItemShareType.values()) {
             if (sharingDrops(shareType)) {
-                shareCategories.add(shareType.getLocaleString());
+                shareCategories.add(getShareTypeLocaleString(shareType));
             }
         }
 
         return shareCategories;
     }
 
+    public String getShareTypeLocaleString(ItemShareType itemShareType) {
+        return pluginRef.getLocaleManager().getString("Party.ItemShare.Category." + StringUtils.getCapitalized(itemShareType.toString()));
+    }
+
     public int getLevel() {
         return level;
     }

+ 0 - 13
src/main/java/com/gmail/nossr50/datatypes/party/PartyFeature.java

@@ -2,7 +2,6 @@ package com.gmail.nossr50.datatypes.party;
 
 import com.gmail.nossr50.commands.party.PartySubcommandType;
 import com.gmail.nossr50.util.Permissions;
-import com.gmail.nossr50.util.StringUtils;
 import org.bukkit.entity.Player;
 
 public enum PartyFeature {
@@ -12,17 +11,6 @@ public enum PartyFeature {
     ITEM_SHARE,
     XP_SHARE;
 
-    public String getLocaleString() {
-        return pluginRef.getLocaleManager().getString("Party.Feature." + StringUtils.getPrettyPartyFeatureString(this).replace(" ", ""));
-    }
-
-    public String getFeatureLockedLocaleString() {
-        return pluginRef.getLocaleManager().getString("Ability.Generic.Template.Lock",
-                pluginRef.getLocaleManager().getString("Party.Feature.Locked."
-                                + StringUtils.getPrettyPartyFeatureString(this).replace(" ", ""),
-                        pluginRef.getPartyManager().getPartyFeatureUnlockLevel(this)));
-    }
-
     public boolean hasPermission(Player player) {
         PartySubcommandType partySubCommandType;
         switch (this) {
@@ -45,7 +33,6 @@ public enum PartyFeature {
                 return false;
         }
 
-
         return Permissions.partySubcommand(player, partySubCommandType);
     }
 }

+ 2 - 1
src/main/java/com/gmail/nossr50/datatypes/party/PartyTeleportRecord.java

@@ -1,5 +1,6 @@
 package com.gmail.nossr50.datatypes.party;
 
+import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.util.Misc;
 import org.bukkit.entity.Player;
 
@@ -8,7 +9,7 @@ public class PartyTeleportRecord {
     private boolean enabled, confirmRequired;
     private int timeout, lastUse;
 
-    public PartyTeleportRecord() {
+    public PartyTeleportRecord(mcMMO pluginRef) {
         requestor = null;
         enabled = true;
         confirmRequired = pluginRef.getConfigManager().getConfigParty().getPTP().isPtpAcceptRequired();

+ 1 - 3
src/main/java/com/gmail/nossr50/datatypes/party/ShareMode.java

@@ -11,11 +11,9 @@ public enum ShareMode {
         } catch (IllegalArgumentException ex) {
             if (string.equalsIgnoreCase("even")) {
                 return EQUAL;
-            } else if (pluginRef.getCommandTools().shouldDisableToggle(string)) {
+            } else {
                 return NONE;
             }
-
-            return null;
         }
     }
 }

+ 77 - 26
src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java

@@ -1,5 +1,6 @@
 package com.gmail.nossr50.datatypes.player;
 
+import com.gmail.nossr50.api.exceptions.InvalidSkillException;
 import com.gmail.nossr50.datatypes.chat.ChatMode;
 import com.gmail.nossr50.datatypes.experience.XPGainReason;
 import com.gmail.nossr50.datatypes.experience.XPGainSource;
@@ -34,7 +35,6 @@ import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.experience.ExperienceBarManager;
 import com.gmail.nossr50.util.skills.PerksUtils;
 import com.gmail.nossr50.util.skills.RankUtils;
-import com.gmail.nossr50.util.skills.SkillUtils;
 import com.gmail.nossr50.util.sounds.SoundManager;
 import com.gmail.nossr50.util.sounds.SoundType;
 import org.apache.commons.lang.Validate;
@@ -94,19 +94,8 @@ public class McMMOPlayer {
             profile.setUniqueId(uuid);
         }
 
-        /*
-         * I'm using this method because it makes code shorter and safer (we don't have to add all SkillTypes manually),
-         * but I actually have no idea about the performance impact, if there is any.
-         * If in the future someone wants to remove this, don't forget to also remove what is in the PrimarySkillType enum. - bm01
-         */
-        try {
-            for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
-                skillManagers.put(primarySkillType, primarySkillType.getManagerClass().getConstructor(McMMOPlayer.class).newInstance(this));
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-            pluginRef.getPluginLoader().disablePlugin(pluginRef);
-        }
+        //What was here before initSkillManagers() was worse, trust me
+        initSkillManagers();
 
         for (SuperAbilityType superAbilityType : SuperAbilityType.values()) {
             abilityMode.put(superAbilityType, false);
@@ -121,6 +110,68 @@ public class McMMOPlayer {
         fillPersonalXPModifiers(); //Cache players XP rates
     }
 
+    private void initSkillManagers() {
+        for(PrimarySkillType primarySkillType : PrimarySkillType.values()) {
+            try {
+                initManager(primarySkillType);
+            } catch (InvalidSkillException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private void initManager(PrimarySkillType primarySkillType) throws InvalidSkillException {
+        switch(primarySkillType) {
+            case ACROBATICS:
+                skillManagers.put(primarySkillType, new AcrobaticsManager(pluginRef, this));
+                break;
+            case ALCHEMY:
+                skillManagers.put(primarySkillType, new AlchemyManager(pluginRef, this));
+                break;
+            case ARCHERY:
+                skillManagers.put(primarySkillType, new ArcheryManager(pluginRef, this));
+                break;
+            case AXES:
+                skillManagers.put(primarySkillType, new AxesManager(pluginRef, this));
+                break;
+            case EXCAVATION:
+                skillManagers.put(primarySkillType, new ExcavationManager(pluginRef, this));
+                break;
+            case FISHING:
+                skillManagers.put(primarySkillType, new FishingManager(pluginRef, this));
+                break;
+            case HERBALISM:
+                skillManagers.put(primarySkillType, new HerbalismManager(pluginRef, this));
+                break;
+            case MINING:
+                skillManagers.put(primarySkillType, new MiningManager(pluginRef, this));
+                break;
+            case REPAIR:
+                skillManagers.put(primarySkillType, new RepairManager(pluginRef, this));
+                break;
+            case SALVAGE:
+                skillManagers.put(primarySkillType, new SalvageManager(pluginRef, this));
+                break;
+            case SMELTING:
+                skillManagers.put(primarySkillType, new SmeltingManager(pluginRef, this));
+                break;
+            case SWORDS:
+                skillManagers.put(primarySkillType, new SwordsManager(pluginRef, this));
+                break;
+            case TAMING:
+                skillManagers.put(primarySkillType, new TamingManager(pluginRef, this));
+                break;
+            case UNARMED:
+                skillManagers.put(primarySkillType, new UnarmedManager(pluginRef, this));
+                break;
+            case WOODCUTTING:
+                skillManagers.put(primarySkillType, new WoodcuttingManager(pluginRef, this));
+                break;
+            default:
+                throw new InvalidSkillException("The skill named has no manager! Contact the devs!");
+        }
+    }
+
     /**
      * Grabs custom XP values for a player if they exist, if they don't defaults them to 1.0
      * Values are stored in a hash map for constant speed lookups
@@ -165,7 +216,7 @@ public class McMMOPlayer {
         if(hasReachedPowerLevelCap()) {
             pluginRef.getNotificationManager().sendPlayerInformationChatOnly(player, "LevelCap.PowerLevel", String.valueOf(pluginRef.getConfigManager().getConfigLeveling().getPowerLevelCap()));
         } else if(hasReachedLevelCap(primarySkillType)) {
-            pluginRef.getNotificationManager().sendPlayerInformationChatOnly(player, "LevelCap.Skill", String.valueOf(pluginRef.getConfigManager().getConfigLeveling().getSkillLevelCap(primarySkillType)), primarySkillType.getName());
+            pluginRef.getNotificationManager().sendPlayerInformationChatOnly(player, "LevelCap.Skill", String.valueOf(pluginRef.getConfigManager().getConfigLeveling().getSkillLevelCap(primarySkillType)), primarySkillType.getLocalizedSkillName());
         }
 
         //Updates from Party sources
@@ -467,8 +518,8 @@ public class McMMOPlayer {
     public int getPowerLevel() {
         int powerLevel = 0;
 
-        for (PrimarySkillType type : PrimarySkillType.NON_CHILD_SKILLS) {
-            if (type.getPermissions(player)) {
+        for (PrimarySkillType type : pluginRef.getSkillTools().NON_CHILD_SKILLS) {
+            if (type.doesPlayerHaveSkillPermission(player)) {
                 powerLevel += getSkillLevel(type);
             }
         }
@@ -519,7 +570,7 @@ public class McMMOPlayer {
             double splitXp = xp / parentSkills.size();
 
             for (PrimarySkillType parentSkill : parentSkills) {
-                if (parentSkill.getPermissions(player)) {
+                if (parentSkill.doesPlayerHaveSkillPermission(player)) {
                     beginXpGain(parentSkill, splitXp, xpGainReason, xpGainSource);
                 }
             }
@@ -563,7 +614,7 @@ public class McMMOPlayer {
      * @param xp               Experience amount to add
      */
     public void applyXpGain(PrimarySkillType primarySkillType, double xp, XPGainReason xpGainReason, XPGainSource xpGainSource) {
-        if (!primarySkillType.getPermissions(player)) {
+        if (!primarySkillType.doesPlayerHaveSkillPermission(player)) {
             return;
         }
 
@@ -647,7 +698,7 @@ public class McMMOPlayer {
 
     public void setupPartyData() {
         party = pluginRef.getPartyManager().getPlayerParty(player.getName(), player.getUniqueId());
-        ptpRecord = new PartyTeleportRecord();
+        ptpRecord = new PartyTeleportRecord(pluginRef);
 
         if (inParty()) {
             loginParty();
@@ -831,7 +882,7 @@ public class McMMOPlayer {
      * @param skill The skill the ability is based on
      */
     public void checkAbilityActivation(PrimarySkillType skill) {
-        ToolType tool = skill.getTool();
+        ToolType tool = skill.getPrimarySkillToolType();
         SuperAbilityType ability = skill.getSuperAbility();
 
         if (getAbilityMode(ability) || !ability.getPermissions(player)) {
@@ -844,7 +895,7 @@ public class McMMOPlayer {
             int diff = RankUtils.getSuperAbilityUnlockRequirement(skill.getSuperAbility()) - getSkillLevel(skill);
 
             //Inform the player they are not yet skilled enough
-            pluginRef.getNotificationManager().sendPlayerInformation(player, NotificationType.ABILITY_COOLDOWN, "Skills.AbilityGateRequirementFail", String.valueOf(diff), skill.getName());
+            pluginRef.getNotificationManager().sendPlayerInformation(player, NotificationType.ABILITY_COOLDOWN, "Skills.AbilityGateRequirementFail", String.valueOf(diff), skill.getLocalizedSkillName());
             return;
         }
 
@@ -872,19 +923,19 @@ public class McMMOPlayer {
             //player.sendMessage(ability.getAbilityOn());
         }
 
-        SkillUtils.sendSkillMessage(player, NotificationType.SUPER_ABILITY_ALERT_OTHERS, ability.getAbilityPlayer());
+        pluginRef.getSkillTools().sendSkillMessage(player, NotificationType.SUPER_ABILITY_ALERT_OTHERS, ability.getAbilityPlayer());
 
         //Sounds
         SoundManager.worldSendSound(player.getWorld(), player.getLocation(), SoundType.ABILITY_ACTIVATED_GENERIC);
 
-        int abilityLength = SkillUtils.calculateAbilityLengthPerks(this, skill, ability);
+        int abilityLength = pluginRef.getSkillTools().calculateAbilityLengthPerks(this, skill, ability);
 
         // Enable the ability
         profile.setAbilityDATS(ability, System.currentTimeMillis() + (abilityLength * Misc.TIME_CONVERSION_FACTOR));
         setAbilityMode(ability, true);
 
         if (ability == SuperAbilityType.SUPER_BREAKER || ability == SuperAbilityType.GIGA_DRILL_BREAKER) {
-            SkillUtils.handleAbilitySpeedIncrease(player);
+            pluginRef.getSkillTools().handleAbilitySpeedIncrease(player);
         }
 
         setToolPreparationMode(tool, false);
@@ -913,7 +964,7 @@ public class McMMOPlayer {
         }
 
         SuperAbilityType ability = skill.getSuperAbility();
-        ToolType tool = skill.getTool();
+        ToolType tool = skill.getPrimarySkillToolType();
 
         /*
          * Woodcutting & Axes need to be treated differently.

+ 14 - 10
src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java

@@ -4,6 +4,7 @@ import com.gmail.nossr50.datatypes.MobHealthbarType;
 import com.gmail.nossr50.datatypes.experience.SkillXpGain;
 import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
 import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
+import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.runnables.player.PlayerProfileSaveTask;
 import com.gmail.nossr50.skills.child.FamilyTree;
 import com.google.common.collect.ImmutableMap;
@@ -31,13 +32,15 @@ public class PlayerProfile {
     // Store previous XP gains for diminished returns
     private DelayQueue<SkillXpGain> gainedSkillsXp = new DelayQueue<SkillXpGain>();
     private HashMap<PrimarySkillType, Double> rollingSkillsXp = new HashMap<PrimarySkillType, Double>();
+    private final mcMMO pluginRef;
 
     @Deprecated
-    public PlayerProfile(String playerName) {
-        this(playerName, null);
+    public PlayerProfile(mcMMO pluginRef, String playerName) {
+        this(pluginRef, playerName, null);
     }
 
-    public PlayerProfile(String playerName, UUID uuid) {
+    public PlayerProfile(mcMMO pluginRef, String playerName, UUID uuid) {
+        this.pluginRef = pluginRef;
         this.uuid = uuid;
         this.playerName = playerName;
 
@@ -48,7 +51,7 @@ public class PlayerProfile {
             abilityDATS.put(superAbilityType, 0);
         }
 
-        for (PrimarySkillType primarySkillType : PrimarySkillType.NON_CHILD_SKILLS) {
+        for (PrimarySkillType primarySkillType : pluginRef.getSkillTools().NON_CHILD_SKILLS) {
             skills.put(primarySkillType, pluginRef.getPlayerLevelingSettings().getConfigSectionLevelingGeneral().getStartingLevel());
             skillsXp.put(primarySkillType, 0.0);
         }
@@ -58,17 +61,18 @@ public class PlayerProfile {
     }
 
     @Deprecated
-    public PlayerProfile(String playerName, boolean isLoaded) {
-        this(playerName);
+    public PlayerProfile(mcMMO pluginRef, String playerName, boolean isLoaded) {
+        this(pluginRef, playerName);
         this.loaded = isLoaded;
     }
 
-    public PlayerProfile(String playerName, UUID uuid, boolean isLoaded) {
-        this(playerName, uuid);
+    public PlayerProfile(mcMMO pluginRef, String playerName, UUID uuid, boolean isLoaded) {
+        this(pluginRef, playerName, uuid);
         this.loaded = isLoaded;
     }
 
-    public PlayerProfile(String playerName, UUID uuid, Map<PrimarySkillType, Integer> levelData, Map<PrimarySkillType, Double> xpData, Map<SuperAbilityType, Integer> cooldownData, MobHealthbarType mobHealthbarType, int scoreboardTipsShown, Map<UniqueDataType, Integer> uniqueProfileData) {
+    public PlayerProfile(mcMMO pluginRef, String playerName, UUID uuid, Map<PrimarySkillType, Integer> levelData, Map<PrimarySkillType, Double> xpData, Map<SuperAbilityType, Integer> cooldownData, MobHealthbarType mobHealthbarType, int scoreboardTipsShown, Map<UniqueDataType, Integer> uniqueProfileData) {
+        this.pluginRef = pluginRef;
         this.playerName = playerName;
         this.uuid = uuid;
         this.mobHealthbarType = mobHealthbarType;
@@ -106,7 +110,7 @@ public class PlayerProfile {
         }
 
         // TODO should this part be synchronized?
-        PlayerProfile profileCopy = new PlayerProfile(playerName, uuid, ImmutableMap.copyOf(skills), ImmutableMap.copyOf(skillsXp), ImmutableMap.copyOf(abilityDATS), mobHealthbarType, scoreboardTipsShown, ImmutableMap.copyOf(uniquePlayerData));
+        PlayerProfile profileCopy = new PlayerProfile(pluginRef, playerName, uuid, ImmutableMap.copyOf(skills), ImmutableMap.copyOf(skillsXp), ImmutableMap.copyOf(abilityDATS), mobHealthbarType, scoreboardTipsShown, ImmutableMap.copyOf(uniquePlayerData));
         changed = !pluginRef.getDatabaseManager().saveUser(profileCopy);
 
         if (changed) {

+ 15 - 251
src/main/java/com/gmail/nossr50/datatypes/skills/PrimarySkillType.java

@@ -1,255 +1,19 @@
 package com.gmail.nossr50.datatypes.skills;
 
-import com.gmail.nossr50.skills.SkillManager;
-import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager;
-import com.gmail.nossr50.skills.alchemy.AlchemyManager;
-import com.gmail.nossr50.skills.archery.ArcheryManager;
-import com.gmail.nossr50.skills.axes.AxesManager;
-import com.gmail.nossr50.skills.excavation.ExcavationManager;
-import com.gmail.nossr50.skills.fishing.FishingManager;
-import com.gmail.nossr50.skills.herbalism.HerbalismManager;
-import com.gmail.nossr50.skills.mining.MiningManager;
-import com.gmail.nossr50.skills.repair.RepairManager;
-import com.gmail.nossr50.skills.salvage.SalvageManager;
-import com.gmail.nossr50.skills.smelting.SmeltingManager;
-import com.gmail.nossr50.skills.swords.SwordsManager;
-import com.gmail.nossr50.skills.taming.TamingManager;
-import com.gmail.nossr50.skills.unarmed.UnarmedManager;
-import com.gmail.nossr50.skills.woodcutting.WoodcuttingManager;
-import com.gmail.nossr50.util.Permissions;
-import com.gmail.nossr50.util.StringUtils;
-import com.gmail.nossr50.util.skills.RankUtils;
-import com.google.common.collect.ImmutableList;
-import org.bukkit.Color;
-import org.bukkit.entity.Entity;
-import org.bukkit.entity.Player;
-import org.bukkit.entity.Tameable;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
 public enum PrimarySkillType {
-    ACROBATICS(AcrobaticsManager.class, Color.WHITE,
-            ImmutableList.of(SubSkillType.ACROBATICS_DODGE, SubSkillType.ACROBATICS_ROLL), "Acrobatics"),
-    ALCHEMY(AlchemyManager.class, Color.FUCHSIA,
-            ImmutableList.of(), "Alchemy"),
-    ARCHERY(ArcheryManager.class, Color.MAROON,
-            ImmutableList.of(SubSkillType.ARCHERY_DAZE, SubSkillType.ARCHERY_ARCHERY_LIMIT_BREAK, SubSkillType.ARCHERY_ARROW_RETRIEVAL, SubSkillType.ARCHERY_SKILL_SHOT), "Archery"),
-    AXES(AxesManager.class, Color.AQUA, SuperAbilityType.SKULL_SPLITTER, ToolType.AXE,
-            ImmutableList.of(SubSkillType.AXES_SKULL_SPLITTER, SubSkillType.AXES_AXES_LIMIT_BREAK, SubSkillType.AXES_ARMOR_IMPACT, SubSkillType.AXES_AXE_MASTERY, SubSkillType.AXES_CRITICAL_STRIKES, SubSkillType.AXES_GREATER_IMPACT), "Axes"),
-    EXCAVATION(ExcavationManager.class, Color.fromRGB(139, 69, 19), SuperAbilityType.GIGA_DRILL_BREAKER, ToolType.SHOVEL,
-            ImmutableList.of(SubSkillType.EXCAVATION_GIGA_DRILL_BREAKER, SubSkillType.EXCAVATION_ARCHAEOLOGY), "Excavation"),
-    FISHING(FishingManager.class, Color.NAVY,
-            ImmutableList.of(SubSkillType.FISHING_FISHERMANS_DIET, SubSkillType.FISHING_TREASURE_HUNTER, SubSkillType.FISHING_ICE_FISHING, SubSkillType.FISHING_MAGIC_HUNTER, SubSkillType.FISHING_MASTER_ANGLER, SubSkillType.FISHING_SHAKE, SubSkillType.FISHING_INNER_PEACE), "Fishing"),
-    HERBALISM(HerbalismManager.class, Color.GREEN, SuperAbilityType.GREEN_TERRA, ToolType.HOE,
-            ImmutableList.of(SubSkillType.HERBALISM_GREEN_TERRA, SubSkillType.HERBALISM_FARMERS_DIET, SubSkillType.HERBALISM_GREEN_THUMB, SubSkillType.HERBALISM_DOUBLE_DROPS, SubSkillType.HERBALISM_HYLIAN_LUCK, SubSkillType.HERBALISM_SHROOM_THUMB), "Herbalism"),
-    MINING(MiningManager.class, Color.GRAY, SuperAbilityType.SUPER_BREAKER, ToolType.PICKAXE,
-            ImmutableList.of(SubSkillType.MINING_SUPER_BREAKER, SubSkillType.MINING_DEMOLITIONS_EXPERTISE, SubSkillType.MINING_BIGGER_BOMBS, SubSkillType.MINING_BLAST_MINING, SubSkillType.MINING_DOUBLE_DROPS), "Mining"),
-    REPAIR(RepairManager.class, Color.SILVER,
-            ImmutableList.of(SubSkillType.REPAIR_ARCANE_FORGING, SubSkillType.REPAIR_REPAIR_MASTERY, SubSkillType.REPAIR_SUPER_REPAIR), "Repair"),
-    SALVAGE(SalvageManager.class, Color.ORANGE,
-            ImmutableList.of(SubSkillType.SALVAGE_SCRAP_COLLECTOR, SubSkillType.SALVAGE_ARCANE_SALVAGE), "Salvage"),
-    SMELTING(SmeltingManager.class, Color.YELLOW,
-            ImmutableList.of(SubSkillType.SMELTING_UNDERSTANDING_THE_ART, /*SubSkillType.SMELTING_FLUX_MINING,*/ SubSkillType.SMELTING_FUEL_EFFICIENCY, SubSkillType.SMELTING_SECOND_SMELT), "Smelting"),
-    SWORDS(SwordsManager.class, Color.fromRGB(178, 34, 34), SuperAbilityType.SERRATED_STRIKES, ToolType.SWORD,
-            ImmutableList.of(SubSkillType.SWORDS_SERRATED_STRIKES, SubSkillType.SWORDS_SWORDS_LIMIT_BREAK, SubSkillType.SWORDS_STAB, SubSkillType.SWORDS_RUPTURE, SubSkillType.SWORDS_COUNTER_ATTACK), "Swords"),
-    TAMING(TamingManager.class, Color.PURPLE,
-            ImmutableList.of(SubSkillType.TAMING_BEAST_LORE, SubSkillType.TAMING_CALL_OF_THE_WILD, SubSkillType.TAMING_ENVIRONMENTALLY_AWARE, SubSkillType.TAMING_FAST_FOOD_SERVICE, SubSkillType.TAMING_GORE, SubSkillType.TAMING_HOLY_HOUND, SubSkillType.TAMING_SHARPENED_CLAWS, SubSkillType.TAMING_SHOCK_PROOF, SubSkillType.TAMING_THICK_FUR, SubSkillType.TAMING_PUMMEL), "Taming"),
-    UNARMED(UnarmedManager.class, Color.BLACK, SuperAbilityType.BERSERK, ToolType.FISTS,
-            ImmutableList.of(SubSkillType.UNARMED_BERSERK, SubSkillType.UNARMED_UNARMED_LIMIT_BREAK, SubSkillType.UNARMED_BLOCK_CRACKER, SubSkillType.UNARMED_ARROW_DEFLECT, SubSkillType.UNARMED_DISARM, SubSkillType.UNARMED_IRON_ARM_STYLE, SubSkillType.UNARMED_IRON_GRIP), "Unarmed"),
-    WOODCUTTING(WoodcuttingManager.class, Color.OLIVE, SuperAbilityType.TREE_FELLER, ToolType.AXE,
-            ImmutableList.of(SubSkillType.WOODCUTTING_LEAF_BLOWER, SubSkillType.WOODCUTTING_TREE_FELLER, SubSkillType.WOODCUTTING_HARVEST_LUMBER), "Woodcutting");
-
-    private Class<? extends SkillManager> managerClass;
-    private Color skillColor;
-    private String capitalizedName;
-    private SuperAbilityType ability;
-    private ToolType tool;
-    private List<SubSkillType> subSkillTypes;
-
-    public String getCapitalizedName() {
-        return capitalizedName;
-    }
-
-    public static final List<String> SKILL_NAMES;
-    public static final List<String> SUBSKILL_NAMES;
-    public static final List<PrimarySkillType> CHILD_SKILLS;
-    public static final List<PrimarySkillType> NON_CHILD_SKILLS;
-    public static final List<PrimarySkillType> COMBAT_SKILLS = ImmutableList.of(ARCHERY, AXES, SWORDS, TAMING, UNARMED);
-    public static final List<PrimarySkillType> GATHERING_SKILLS = ImmutableList.of(EXCAVATION, FISHING, HERBALISM, MINING, WOODCUTTING);
-    public static final List<PrimarySkillType> MISC_SKILLS = ImmutableList.of(ACROBATICS, ALCHEMY, REPAIR, SALVAGE, SMELTING);
-
-    static {
-        List<PrimarySkillType> childSkills = new ArrayList<>();
-        List<PrimarySkillType> nonChildSkills = new ArrayList<>();
-        ArrayList<String> names = new ArrayList<>();
-        ArrayList<String> subSkillNames = new ArrayList<>();
-
-        for (PrimarySkillType skill : values()) {
-            if (skill.isChildSkill()) {
-                childSkills.add(skill);
-            } else {
-                nonChildSkills.add(skill);
-            }
-
-            for (SubSkillType subSkillType : skill.subSkillTypes) {
-                subSkillNames.add(subSkillType.getNiceNameNoSpaces(subSkillType));
-            }
-            names.add(skill.getName());
-        }
-
-        Collections.sort(names);
-        SKILL_NAMES = ImmutableList.copyOf(names);
-        SUBSKILL_NAMES = ImmutableList.copyOf(subSkillNames);
-
-        CHILD_SKILLS = ImmutableList.copyOf(childSkills);
-        NON_CHILD_SKILLS = ImmutableList.copyOf(nonChildSkills);
-    }
-
-    private PrimarySkillType(Class<? extends SkillManager> managerClass, Color skillColor, List<SubSkillType> subSkillTypes, String capitalizedName) {
-        this(managerClass, skillColor, null, null, subSkillTypes, capitalizedName);
-    }
-
-    private PrimarySkillType(Class<? extends SkillManager> managerClass, Color skillColor, SuperAbilityType ability, ToolType tool, List<SubSkillType> subSkillTypes, String capitalizedName) {
-        this.managerClass = managerClass;
-        this.skillColor = skillColor;
-        this.ability = ability;
-        this.tool = tool;
-        this.subSkillTypes = subSkillTypes;
-        this.capitalizedName = capitalizedName;
-    }
-
-    public static PrimarySkillType getSkill(String skillName) {
-        if (!pluginRef.getConfigManager().getConfigLanguage().getTargetLanguage().equalsIgnoreCase("en_US")) {
-            for (PrimarySkillType type : values()) {
-                if (skillName.equalsIgnoreCase(pluginRef.getLocaleManager().getString(StringUtils.getCapitalized(type.name()) + ".SkillName"))) {
-                    return type;
-                }
-            }
-        }
-
-        for (PrimarySkillType type : values()) {
-            if (type.name().equalsIgnoreCase(skillName)) {
-                return type;
-            }
-        }
-
-        if (!skillName.equalsIgnoreCase("all")) {
-            pluginRef.getLogger().warning("Invalid mcMMO skill (" + skillName + ")"); //TODO: Localize
-        }
-
-        return null;
-    }
-
-    public static PrimarySkillType bySecondaryAbility(SubSkillType subSkillType) {
-        for (PrimarySkillType type : values()) {
-            if (type.getSkillAbilities().contains(subSkillType)) {
-                return type;
-            }
-        }
-
-        pluginRef.getLogger().severe("Unable to locate parent for "+subSkillType.toString());
-        return null;
-    }
-
-    public static PrimarySkillType byAbility(SuperAbilityType ability) {
-        for (PrimarySkillType type : values()) {
-            if (type.getSuperAbility() == ability) {
-                return type;
-            }
-        }
-
-        return null;
-    }
-
-    public Class<? extends SkillManager> getManagerClass() {
-        return managerClass;
-    }
-
-    public SuperAbilityType getSuperAbility() {
-        return ability;
-    }
-
-    /**
-     * Get the max level of this skill.
-     *
-     * @return the max level of this skill
-     */
-    public int getMaxLevel() {
-        return pluginRef.getPlayerLevelingSettings().getSkillLevelCap(this);
-    }
-
-    /*public boolean getDoubleDropsDisabled() {
-        return MainConfig.getInstance().getDoubleDropsDisabled(this);
-    }*/
-
-    public boolean isSuperAbilityUnlocked(Player player) {
-        return RankUtils.getRank(player, getSuperAbility().getSubSkillTypeDefinition()) >= 1;
-    }
-
-    /*public void setHardcoreStatLossEnabled(boolean enable) {
-        MainConfig.getInstance().setHardcoreStatLossEnabled(this, enable);
-    }*/
-
-    public boolean getPVPEnabled() {
-        return pluginRef.getConfigManager().getConfigCoreSkills().isPVPEnabled(this);
-    }
-
-    /*public void setHardcoreVampirismEnabled(boolean enable) {
-        MainConfig.getInstance().setHardcoreVampirismEnabled(this, enable);
-    }*/
-
-    public boolean getPVEEnabled() {
-        return pluginRef.getConfigManager().getConfigCoreSkills().isPVEEnabled(this);
-    }
-
-    public boolean getHardcoreStatLossEnabled() {
-        return pluginRef.getConfigManager().getConfigHardcore().getDeathPenalty().getSkillToggleMap().get(this);
-    }
-
-    public boolean getHardcoreVampirismEnabled() {
-        return pluginRef.getConfigManager().getConfigHardcore().getVampirism().getSkillToggleMap().get(this);
-    }
-
-    public ToolType getTool() {
-        return tool;
-    }
-
-    public List<SubSkillType> getSkillAbilities() {
-        return subSkillTypes;
-    }
-
-    public double getXpModifier() {
-        return pluginRef.getConfigManager().getConfigLeveling().getSkillXpFormulaModifier(this);
-    }
-
-    // TODO: This is a little "hacky", we probably need to add something to distinguish child skills in the enum, or to use another enum for them
-    public boolean isChildSkill() {
-        switch (this) {
-            case SALVAGE:
-            case SMELTING:
-                return true;
-
-            default:
-                return false;
-        }
-    }
-
-    public String getName() {
-        //return MainConfig.getInstance().getLocale().equalsIgnoreCase("en_US") ? StringUtils.getCapitalized(this.toString()) : StringUtils.getCapitalized(pluginRef.getLocaleManager().getString(StringUtils.getCapitalized(this.toString()) + ".SkillName"));
-        return StringUtils.getCapitalized(pluginRef.getLocaleManager().getString(StringUtils.getCapitalized(this.toString()) + ".SkillName"));
-    }
-
-    public boolean getPermissions(Player player) {
-        return Permissions.skillEnabled(player, this);
-    }
-
-/*    public void celebrateLevelUp(Player player) {
-        ParticleEffectUtils.fireworkParticleShower(player, skillColor);
-    }*/
-
-    public boolean shouldProcess(Entity target) {
-        return (target instanceof Player || (target instanceof Tameable && ((Tameable) target).isTamed())) ? getPVPEnabled() : getPVEEnabled();
-    }
+    ACROBATICS,
+    ALCHEMY,
+    ARCHERY,
+    AXES,
+    EXCAVATION,
+    FISHING,
+    HERBALISM,
+    MINING,
+    REPAIR,
+    SALVAGE,
+    SMELTING,
+    SWORDS,
+    TAMING,
+    UNARMED,
+    WOODCUTTING
 }

+ 14 - 13
src/main/java/com/gmail/nossr50/datatypes/skills/SubSkillType.java

@@ -1,6 +1,7 @@
 package com.gmail.nossr50.datatypes.skills;
 
 import com.gmail.nossr50.config.hocon.HOCONUtil;
+import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.util.StringUtils;
 
 public enum SubSkillType {
@@ -131,7 +132,7 @@ public enum SubSkillType {
      * @return
      */
     public PrimarySkillType getParentSkill() {
-        return PrimarySkillType.bySecondaryAbility(this);
+        return PrimarySkillType.getPrimarySkillBySubSkill(this);
     }
 
     /**
@@ -268,7 +269,7 @@ public enum SubSkillType {
      *
      * @return The parent skill as defined in the locale
      */
-    public String getParentNiceNameLocale() {
+    public String getParentNiceNameLocale(mcMMO pluginRef) {
         return pluginRef.getLocaleManager().getString(StringUtils.getCapitalized(getParentSkill().toString()) + ".SkillName");
     }
 
@@ -307,41 +308,41 @@ public enum SubSkillType {
         return StringUtils.getCapitalized(getParentSkill().toString()) + ".SubSkill." + getConfigName(toString());
     }
 
-    public String getLocaleName() {
-        return getFromLocaleSubAddress(".Name");
+    public String getLocaleName(mcMMO pluginRef) {
+        return getFromLocaleSubAddress(pluginRef,".Name");
     }
 
-    public String getLocaleDescription() {
-        return getFromLocaleSubAddress(".Description");
+    public String getLocaleDescription(mcMMO pluginRef) {
+        return getFromLocaleSubAddress(pluginRef,".Description");
     }
 
-    public String getLocaleStatDescription() {
-        return getFromLocaleSubAddress(".Stat");
+    public String getLocaleStatDescription(mcMMO pluginRef) {
+        return getFromLocaleSubAddress(pluginRef,".Stat");
     }
 
     public String getLocaleKeyStatDescription() {
         return getLocaleKeyFromSubAddress(".Stat");
     }
 
-    public String getLocaleStatExtraDescription() {
-        return getFromLocaleSubAddress(".Stat.Extra");
+    public String getLocaleStatExtraDescription(mcMMO pluginRef) {
+        return getFromLocaleSubAddress(pluginRef,".Stat.Extra");
     }
 
     public String getLocaleKeyStatExtraDescription() {
         return getLocaleKeyFromSubAddress(".Stat.Extra");
     }
 
-    public String getLocaleStat(String... vars) {
+    public String getLocaleStat(mcMMO pluginRef, String... vars) {
         String statMsg = pluginRef.getLocaleManager().getString("Ability.Generic.Template", (Object[]) vars);
         return statMsg;
     }
 
-    public String getCustomLocaleStat(String... vars) {
+    public String getCustomLocaleStat(mcMMO pluginRef, String... vars) {
         String statMsg = pluginRef.getLocaleManager().getString("Ability.Generic.Template.Custom", (Object[]) vars);
         return statMsg;
     }
 
-    private String getFromLocaleSubAddress(String s) {
+    private String getFromLocaleSubAddress(mcMMO pluginRef, String s) {
         return pluginRef.getLocaleManager().getString(getLocaleKeyRoot() + s);
     }
 

+ 1 - 2
src/main/java/com/gmail/nossr50/datatypes/skills/behaviours/HerbalismBehaviour.java

@@ -4,7 +4,6 @@ import com.gmail.nossr50.core.MetadataConstants;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.skills.herbalism.HerbalismManager;
 import com.gmail.nossr50.util.BlockUtils;
-import com.gmail.nossr50.util.skills.SkillUtils;
 import org.bukkit.Material;
 import org.bukkit.block.Block;
 import org.bukkit.block.BlockFace;
@@ -218,6 +217,6 @@ public class HerbalismBehaviour {
      * @return true if the block is recently regrown, false otherwise
      */
     public boolean isRecentlyRegrown(BlockState blockState) {
-        return blockState.hasMetadata(MetadataConstants.GREEN_THUMB_METAKEY) && !SkillUtils.cooldownExpired(blockState.getMetadata(MetadataConstants.GREEN_THUMB_METAKEY).get(0).asInt(), 1);
+        return blockState.hasMetadata(MetadataConstants.GREEN_THUMB_METAKEY) && !pluginRef.getSkillTools().cooldownExpired(blockState.getMetadata(MetadataConstants.GREEN_THUMB_METAKEY).get(0).asInt(), 1);
     }
 }

+ 8 - 9
src/main/java/com/gmail/nossr50/datatypes/skills/subskills/acrobatics/Roll.java

@@ -12,7 +12,6 @@ import com.gmail.nossr50.util.random.RandomChanceUtil;
 import com.gmail.nossr50.util.skills.PerksUtils;
 import com.gmail.nossr50.util.skills.RankUtils;
 import com.gmail.nossr50.util.skills.SkillActivationType;
-import com.gmail.nossr50.util.skills.SkillUtils;
 import com.gmail.nossr50.util.sounds.SoundManager;
 import com.gmail.nossr50.util.sounds.SoundType;
 import net.md_5.bungee.api.chat.ComponentBuilder;
@@ -208,17 +207,17 @@ public class Roll extends AcrobaticsSubSkill {
             SoundManager.sendCategorizedSound(player, player.getLocation(), SoundType.ROLL_ACTIVATED, SoundCategory.PLAYERS);
 
             if (!pluginRef.getConfigManager().getConfigExploitPrevention().getConfigSectionExploitAcrobatics().isPreventAcrobaticsAbuse())
-                SkillUtils.applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, true), XPGainReason.PVE);
+                pluginRef.getSkillTools().applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, true), XPGainReason.PVE);
             else if (!isExploiting(player) && mcMMOPlayer.getAcrobaticsManager().canGainRollXP())
-                SkillUtils.applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, true), XPGainReason.PVE);
+                pluginRef.getSkillTools().applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, true), XPGainReason.PVE);
 
             addFallLocation(player);
             return modifiedDamage;
         } else if (!isFatal(player, damage)) {
             if (!pluginRef.getConfigManager().getConfigExploitPrevention().getConfigSectionExploitAcrobatics().isPreventAcrobaticsAbuse())
-                SkillUtils.applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, true), XPGainReason.PVE);
+                pluginRef.getSkillTools().applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, true), XPGainReason.PVE);
             else if (!isExploiting(player) && mcMMOPlayer.getAcrobaticsManager().canGainRollXP())
-                SkillUtils.applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, false), XPGainReason.PVE);
+                pluginRef.getSkillTools().applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, false), XPGainReason.PVE);
         }
 
         addFallLocation(player);
@@ -247,17 +246,17 @@ public class Roll extends AcrobaticsSubSkill {
             SoundManager.sendCategorizedSound(player, player.getLocation(), SoundType.ROLL_ACTIVATED, SoundCategory.PLAYERS, 0.5F);
 
             if (!pluginRef.getConfigManager().getConfigExploitPrevention().getConfigSectionExploitAcrobatics().isPreventAcrobaticsAbuse())
-                SkillUtils.applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, true), XPGainReason.PVE);
+                pluginRef.getSkillTools().applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, true), XPGainReason.PVE);
             else if (!isExploiting(player) && mcMMOPlayer.getAcrobaticsManager().canGainRollXP())
-                SkillUtils.applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, true), XPGainReason.PVE);
+                pluginRef.getSkillTools().applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, true), XPGainReason.PVE);
 
             addFallLocation(player);
             return modifiedDamage;
         } else if (!isFatal(player, damage)) {
             if (!pluginRef.getConfigManager().getConfigExploitPrevention().getConfigSectionExploitAcrobatics().isPreventAcrobaticsAbuse())
-                SkillUtils.applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, true), XPGainReason.PVE);
+                pluginRef.getSkillTools().applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, true), XPGainReason.PVE);
             else if (!isExploiting(player) && mcMMOPlayer.getAcrobaticsManager().canGainRollXP())
-                SkillUtils.applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, false), XPGainReason.PVE);
+                pluginRef.getSkillTools().applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, false), XPGainReason.PVE);
 
             addFallLocation(player);
         }

+ 25 - 0
src/main/java/com/gmail/nossr50/dumpster/CustomBlock.java

@@ -0,0 +1,25 @@
+//package com.gmail.nossr50.datatypes.mods;
+//
+//public class CustomBlock {
+//    private int xpGain;
+//    private boolean canDoubleDrop;
+//    private int smeltingXpGain;
+//
+//    public CustomBlock(int xpGain, boolean canDoubleDrop, int smeltingXpGain) {
+//        this.xpGain = xpGain;
+//        this.canDoubleDrop = canDoubleDrop;
+//        this.smeltingXpGain = smeltingXpGain;
+//    }
+//
+//    public int getXpGain() {
+//        return xpGain;
+//    }
+//
+//    public boolean isDoubleDropEnabled() {
+//        return canDoubleDrop;
+//    }
+//
+//    public int getSmeltingXpGain() {
+//        return smeltingXpGain;
+//    }
+//}

+ 45 - 0
src/main/java/com/gmail/nossr50/dumpster/CustomEntity.java

@@ -0,0 +1,45 @@
+//package com.gmail.nossr50.datatypes.mods;
+//
+//import org.bukkit.inventory.ItemStack;
+//
+//public class CustomEntity {
+//    private double xpMultiplier;
+//    private boolean canBeTamed;
+//    private int tamingXP;
+//    private boolean canBeSummoned;
+//    private ItemStack callOfTheWildItem;
+//    private int callOfTheWildAmount;
+//
+//    public CustomEntity(double xpMultiplier, boolean canBeTamed, int tamingXP, boolean canBeSummoned, ItemStack callOfTheWildItem, int callOfTheWildAmount) {
+//        this.xpMultiplier = xpMultiplier;
+//        this.canBeTamed = canBeTamed;
+//        this.tamingXP = tamingXP;
+//        this.canBeSummoned = canBeSummoned;
+//        this.callOfTheWildItem = callOfTheWildItem;
+//        this.callOfTheWildAmount = callOfTheWildAmount;
+//    }
+//
+//    public double getXpMultiplier() {
+//        return xpMultiplier;
+//    }
+//
+//    public boolean canBeTamed() {
+//        return canBeTamed;
+//    }
+//
+//    public int getTamingXP() {
+//        return tamingXP;
+//    }
+//
+//    public boolean canBeSummoned() {
+//        return canBeSummoned;
+//    }
+//
+//    public ItemStack getCallOfTheWildItem() {
+//        return callOfTheWildItem;
+//    }
+//
+//    public int getCallOfTheWildAmount() {
+//        return callOfTheWildAmount;
+//    }
+//}

+ 25 - 0
src/main/java/com/gmail/nossr50/dumpster/CustomTool.java

@@ -0,0 +1,25 @@
+//package com.gmail.nossr50.datatypes.mods;
+//
+//public class CustomTool {
+//    private double xpMultiplier;
+//    private boolean abilityEnabled;
+//    private int tier;
+//
+//    public CustomTool(int tier, boolean abilityEnabled, double xpMultiplier) {
+//        this.xpMultiplier = xpMultiplier;
+//        this.abilityEnabled = abilityEnabled;
+//        this.tier = tier;
+//    }
+//
+//    public double getXpMultiplier() {
+//        return xpMultiplier;
+//    }
+//
+//    public boolean isAbilityEnabled() {
+//        return abilityEnabled;
+//    }
+//
+//    public int getTier() {
+//        return tier;
+//    }
+//}

+ 1 - 1
src/main/java/com/gmail/nossr50/events/skills/secondaryabilities/SubSkillEvent.java

@@ -20,7 +20,7 @@ public class SubSkillEvent extends McMMOPlayerSkillEvent implements Cancellable
      */
     @Deprecated
     public SubSkillEvent(Player player, SubSkillType subSkillType) {
-        super(player, PrimarySkillType.bySecondaryAbility(subSkillType));
+        super(player, PrimarySkillType.getPrimarySkillBySubSkill(subSkillType));
         this.subSkillType = subSkillType;
     }
 

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

@@ -182,15 +182,15 @@ public class BlockListener implements Listener {
         McMMOPlayer mcMMOPlayer = pluginRef.getUserManager().getPlayer(player);
 
         if (blockState.getType() == Repair.getInstance().getAnvilMaterial()
-                && PrimarySkillType.REPAIR.getPermissions(player)) {
+                && PrimarySkillType.REPAIR.doesPlayerHaveSkillPermission(player)) {
             if (mcMMOPlayer == null)
                 return;
 
             if (blockState.getType() == Repair.getInstance().getAnvilMaterial()
-                    && PrimarySkillType.REPAIR.getPermissions(player)) {
+                    && PrimarySkillType.REPAIR.doesPlayerHaveSkillPermission(player)) {
                 mcMMOPlayer.getRepairManager().placedAnvilCheck();
             } else if (blockState.getType() == Salvage.anvilMaterial
-                    && PrimarySkillType.SALVAGE.getPermissions(player)) {
+                    && PrimarySkillType.SALVAGE.doesPlayerHaveSkillPermission(player)) {
                 mcMMOPlayer.getSalvageManager().placedAnvilCheck();
             }
         }
@@ -297,19 +297,19 @@ public class BlockListener implements Listener {
              * We don't check the block store here because herbalism has too many unusual edge cases.
              * Instead, we check it inside the drops handler.
              */
-            if (PrimarySkillType.HERBALISM.getPermissions(player)) {
+            if (PrimarySkillType.HERBALISM.doesPlayerHaveSkillPermission(player)) {
                 herbalismManager.herbalismBlockCheck(blockState);
             }
         }
 
         /* MINING */
-        else if (BlockUtils.affectedBySuperBreaker(blockState) && ItemUtils.isPickaxe(heldItem) && PrimarySkillType.MINING.getPermissions(player) && !pluginRef.getPlaceStore().isTrue(blockState)) {
+        else if (BlockUtils.affectedBySuperBreaker(blockState) && ItemUtils.isPickaxe(heldItem) && PrimarySkillType.MINING.doesPlayerHaveSkillPermission(player) && !pluginRef.getPlaceStore().isTrue(blockState)) {
             MiningManager miningManager = mcMMOPlayer.getMiningManager();
             miningManager.miningBlockCheck(blockState);
         }
 
         /* WOOD CUTTING */
-        else if (BlockUtils.isLog(blockState) && ItemUtils.isAxe(heldItem) && PrimarySkillType.WOODCUTTING.getPermissions(player) && !pluginRef.getPlaceStore().isTrue(blockState)) {
+        else if (BlockUtils.isLog(blockState) && ItemUtils.isAxe(heldItem) && PrimarySkillType.WOODCUTTING.doesPlayerHaveSkillPermission(player) && !pluginRef.getPlaceStore().isTrue(blockState)) {
             WoodcuttingManager woodcuttingManager = mcMMOPlayer.getWoodcuttingManager();
             if (woodcuttingManager.canUseTreeFeller(heldItem)) {
                 woodcuttingManager.processTreeFeller(blockState);
@@ -319,7 +319,7 @@ public class BlockListener implements Listener {
         }
 
         /* EXCAVATION */
-        else if (BlockUtils.affectedByGigaDrillBreaker(blockState) && ItemUtils.isShovel(heldItem) && PrimarySkillType.EXCAVATION.getPermissions(player) && !pluginRef.getPlaceStore().isTrue(blockState)) {
+        else if (BlockUtils.affectedByGigaDrillBreaker(blockState) && ItemUtils.isShovel(heldItem) && PrimarySkillType.EXCAVATION.doesPlayerHaveSkillPermission(player) && !pluginRef.getPlaceStore().isTrue(blockState)) {
             ExcavationManager excavationManager = mcMMOPlayer.getExcavationManager();
             excavationManager.excavationBlockCheck(blockState);
 

+ 4 - 5
src/main/java/com/gmail/nossr50/listeners/InventoryListener.java

@@ -8,7 +8,6 @@ import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.runnables.player.PlayerUpdateInventoryTask;
 import com.gmail.nossr50.util.ItemUtils;
 import com.gmail.nossr50.util.Permissions;
-import com.gmail.nossr50.util.skills.SkillUtils;
 import com.gmail.nossr50.worldguard.WorldGuardUtils;
 import org.bukkit.Material;
 import org.bukkit.block.Block;
@@ -136,7 +135,7 @@ public class InventoryListener implements Listener {
                 return;
         }
 
-        if (!pluginRef.getUserManager().hasPlayerDataKey(player) || !PrimarySkillType.SMELTING.getPermissions(player)) {
+        if (!pluginRef.getUserManager().hasPlayerDataKey(player) || !PrimarySkillType.SMELTING.doesPlayerHaveSkillPermission(player)) {
             return;
         }
 
@@ -420,15 +419,15 @@ public class InventoryListener implements Listener {
 
     @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
     public void onInventoryClickEvent(InventoryClickEvent event) {
-        SkillUtils.removeAbilityBuff(event.getCurrentItem());
+        pluginRef.getSkillTools().removeAbilityBuff(event.getCurrentItem());
         if (event.getAction() == InventoryAction.HOTBAR_SWAP) {
-            SkillUtils.removeAbilityBuff(event.getWhoClicked().getInventory().getItem(event.getHotbarButton()));
+            pluginRef.getSkillTools().removeAbilityBuff(event.getWhoClicked().getInventory().getItem(event.getHotbarButton()));
         }
     }
 
     @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
     public void onInventoryOpenEvent(InventoryOpenEvent event) {
-        SkillUtils.removeAbilityBuff(event.getPlayer().getInventory().getItemInMainHand());
+        pluginRef.getSkillTools().removeAbilityBuff(event.getPlayer().getInventory().getItemInMainHand());
     }
 
     @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)

+ 9 - 10
src/main/java/com/gmail/nossr50/listeners/PlayerListener.java

@@ -21,7 +21,6 @@ import com.gmail.nossr50.skills.salvage.SalvageManager;
 import com.gmail.nossr50.skills.taming.TamingManager;
 import com.gmail.nossr50.util.*;
 import com.gmail.nossr50.util.skills.RankUtils;
-import com.gmail.nossr50.util.skills.SkillUtils;
 import com.gmail.nossr50.util.sounds.SoundManager;
 import com.gmail.nossr50.util.sounds.SoundType;
 import com.gmail.nossr50.worldguard.WorldGuardUtils;
@@ -228,7 +227,7 @@ public class PlayerListener implements Listener {
             drop.setMetadata(MetadataConstants.DROPPED_ITEM_TRACKING_METAKEY, MetadataConstants.metadataValue);
         }
 
-        SkillUtils.removeAbilityBuff(dropStack);
+        pluginRef.getSkillTools().removeAbilityBuff(dropStack);
     }
 
     /**
@@ -253,7 +252,7 @@ public class PlayerListener implements Listener {
                 return;
         }
 
-        if (!pluginRef.getUserManager().hasPlayerDataKey(player) || !PrimarySkillType.FISHING.getPermissions(player)) {
+        if (!pluginRef.getUserManager().hasPlayerDataKey(player) || !PrimarySkillType.FISHING.doesPlayerHaveSkillPermission(player)) {
             return;
         }
 
@@ -328,7 +327,7 @@ public class PlayerListener implements Listener {
                 return;
         }
 
-        if (!pluginRef.getUserManager().hasPlayerDataKey(player) || !PrimarySkillType.FISHING.getPermissions(player)) {
+        if (!pluginRef.getUserManager().hasPlayerDataKey(player) || !PrimarySkillType.FISHING.doesPlayerHaveSkillPermission(player)) {
             return;
         }
 
@@ -594,7 +593,7 @@ public class PlayerListener implements Listener {
                 if (!pluginRef.getConfigManager().getConfigSuperAbilities().isMustSneakToActivate() || player.isSneaking()) {
                     /* REPAIR CHECKS */
                     if (type == Repair.getInstance().getAnvilMaterial()
-                            && PrimarySkillType.REPAIR.getPermissions(player)
+                            && PrimarySkillType.REPAIR.doesPlayerHaveSkillPermission(player)
                             && pluginRef.getRepairableManager().isRepairable(heldItem)
                             && heldItem.getAmount() <= 1) {
                         RepairManager repairManager = mcMMOPlayer.getRepairManager();
@@ -608,7 +607,7 @@ public class PlayerListener implements Listener {
                     }
                     /* SALVAGE CHECKS */
                     else if (type == Salvage.anvilMaterial
-                            && PrimarySkillType.SALVAGE.getPermissions(player)
+                            && PrimarySkillType.SALVAGE.doesPlayerHaveSkillPermission(player)
                             && RankUtils.hasUnlockedSubskill(player, SubSkillType.SALVAGE_SCRAP_COLLECTOR)
                             && pluginRef.getSalvageableManager().isSalvageable(heldItem)
                             && heldItem.getAmount() <= 1) {
@@ -617,7 +616,7 @@ public class PlayerListener implements Listener {
 
                                 // Make sure the player knows what he's doing when trying to salvage an enchanted item
                                 if (salvageManager.checkConfirmation(true)) {
-                                    SkillUtils.handleAbilitySpeedDecrease(player);
+                                    pluginRef.getSkillTools().handleAbilitySpeedDecrease(player);
                                     salvageManager.handleSalvage(block.getLocation(), heldItem);
                                     player.updateInventory();
                                 }
@@ -639,7 +638,7 @@ public class PlayerListener implements Listener {
 
                 if (!pluginRef.getConfigManager().getConfigSuperAbilities().isMustSneakToActivate() || player.isSneaking()) {
                     /* REPAIR CHECKS */
-                    if (type == Repair.getInstance().getAnvilMaterial() && PrimarySkillType.REPAIR.getPermissions(player) && pluginRef.getRepairableManager().isRepairable(heldItem)) {
+                    if (type == Repair.getInstance().getAnvilMaterial() && PrimarySkillType.REPAIR.doesPlayerHaveSkillPermission(player) && pluginRef.getRepairableManager().isRepairable(heldItem)) {
                         RepairManager repairManager = mcMMOPlayer.getRepairManager();
 
                         // Cancel repairing an enchanted item
@@ -649,7 +648,7 @@ public class PlayerListener implements Listener {
                         }
                     }
                     /* SALVAGE CHECKS */
-                    else if (type == Salvage.anvilMaterial && PrimarySkillType.SALVAGE.getPermissions(player) && pluginRef.getSalvageableManager().isSalvageable(heldItem)) {
+                    else if (type == Salvage.anvilMaterial && PrimarySkillType.SALVAGE.doesPlayerHaveSkillPermission(player) && pluginRef.getSalvageableManager().isSalvageable(heldItem)) {
                         SalvageManager salvageManager = mcMMOPlayer.getSalvageManager();
 
                         // Cancel salvaging an enchanted item
@@ -883,7 +882,7 @@ public class PlayerListener implements Listener {
             // Do these ACTUALLY have to be lower case to work properly?
             for (PrimarySkillType skill : PrimarySkillType.values()) {
                 String skillName = skill.toString().toLowerCase();
-                String localizedName = skill.getName().toLowerCase();
+                String localizedName = skill.getLocalizedSkillName().toLowerCase();
 
                 if (lowerCaseCommand.equals(localizedName)) {
                     event.setMessage(message.replace(command, skillName));

+ 10 - 2
src/main/java/com/gmail/nossr50/mcMMO.java

@@ -40,7 +40,7 @@ import com.gmail.nossr50.util.player.PlayerLevelUtils;
 import com.gmail.nossr50.util.player.UserManager;
 import com.gmail.nossr50.util.scoreboards.ScoreboardManager;
 import com.gmail.nossr50.util.skills.RankUtils;
-import com.gmail.nossr50.util.skills.SkillUtils;
+import com.gmail.nossr50.util.skills.SkillTools;
 import com.gmail.nossr50.worldguard.WorldGuardManager;
 import net.shatteredlands.shatt.backup.ZipLibrary;
 import org.bstats.bukkit.Metrics;
@@ -87,6 +87,7 @@ public class mcMMO extends JavaPlugin {
     /* Not-Managers but my naming scheme sucks */
     private DatabaseManagerFactory databaseManagerFactory;
     private CommandTools commandTools;
+    private SkillTools skillTools; //TODO: Remove once a new skill system is in place
     private TextComponentFactory textComponentFactory;
 
     /* Never-Ending tasks */
@@ -235,6 +236,9 @@ public class mcMMO extends JavaPlugin {
 
         //Init Scoreboard Manager
         scoreboardManager = new ScoreboardManager(this);
+
+        //Init Skill Tools
+        skillTools = new SkillTools(this);
     }
 
     @Override
@@ -585,7 +589,7 @@ public class mcMMO extends JavaPlugin {
             if (configManager.getConfigItems().isChimaeraWingEnabled()) {
                 Recipe recipe = getChimaeraWingRecipe();
 
-                if(!SkillUtils.hasRecipeBeenRegistered(recipe))
+                if(!getSkillTools().hasRecipeBeenRegistered(recipe))
                     getServer().addRecipe(getChimaeraWingRecipe());
             }
         }, 40);
@@ -734,4 +738,8 @@ public class mcMMO extends JavaPlugin {
     public BleedTimerTask getBleedTimerTask() {
         return bleedTimerTask;
     }
+
+    public SkillTools getSkillTools() {
+        return skillTools;
+    }
 }

+ 18 - 1
src/main/java/com/gmail/nossr50/party/ShareHandler.java

@@ -8,6 +8,7 @@ import com.gmail.nossr50.datatypes.party.ShareMode;
 import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
 import com.gmail.nossr50.mcMMO;
+import com.gmail.nossr50.util.ItemUtils;
 import com.gmail.nossr50.util.Misc;
 import org.bukkit.Material;
 import org.bukkit.entity.Item;
@@ -73,7 +74,7 @@ public final class ShareHandler {
      */
     public boolean handleItemShare(Item drop, McMMOPlayer mcMMOPlayer) {
         ItemStack itemStack = drop.getItemStack();
-        ItemShareType dropType = ItemShareType.getShareType(itemStack);
+        ItemShareType dropType = getShareType(itemStack);
 
         if (dropType == null) {
             return false;
@@ -157,6 +158,22 @@ public final class ShareHandler {
         }
     }
 
+    public ItemShareType getShareType(ItemStack itemStack) {
+        if (ItemUtils.isMobDrop(itemStack)) {
+            return ItemShareType.LOOT;
+        } else if (ItemUtils.isMiningDrop(itemStack)) {
+            return ItemShareType.MINING;
+        } else if (ItemUtils.isHerbalismDrop(itemStack)) {
+            return ItemShareType.HERBALISM;
+        } else if (ItemUtils.isWoodcuttingDrop(itemStack)) {
+            return ItemShareType.WOODCUTTING;
+        } else if (pluginRef.getConfigManager().getConfigParty().getPartyItemShare().getItemShareMap().get(itemStack.getType()) != null) {
+            return ItemShareType.MISC;
+        }
+
+        return null;
+    }
+
     private int getItemWeight(Material material) {
         if (pluginRef.getConfigManager().getConfigParty().getPartyItemShare().getItemShareMap().get(material) == null)
             return 5;

+ 2 - 2
src/main/java/com/gmail/nossr50/runnables/commands/LeaderboardsCommandDisplayTask.java

@@ -59,9 +59,9 @@ public class LeaderboardsCommandDisplayTask extends BukkitRunnable {
             }
         } else {
             if (sender instanceof Player) {
-                sender.sendMessage(pluginRef.getLocaleManager().getString("Commands.Skill.Leaderboard", skill.getName()));
+                sender.sendMessage(pluginRef.getLocaleManager().getString("Commands.Skill.Leaderboard", skill.getLocalizedSkillName()));
             } else {
-                sender.sendMessage(ChatColor.stripColor(pluginRef.getLocaleManager().getString("Commands.Skill.Leaderboard", skill.getName())));
+                sender.sendMessage(ChatColor.stripColor(pluginRef.getLocaleManager().getString("Commands.Skill.Leaderboard", skill.getLocalizedSkillName())));
             }
         }
 

+ 2 - 2
src/main/java/com/gmail/nossr50/runnables/commands/RankCommandDisplayTask.java

@@ -47,13 +47,13 @@ public class RankCommandDisplayTask extends BukkitRunnable {
         sender.sendMessage(pluginRef.getLocaleManager().getString("Commands.mcrank.Heading"));
         sender.sendMessage(pluginRef.getLocaleManager().getString("Commands.mcrank.Player", playerName));
 
-        for (PrimarySkillType skill : PrimarySkillType.NON_CHILD_SKILLS) {
+        for (PrimarySkillType skill : pluginRef.getSkillTools().NON_CHILD_SKILLS) {
 //            if (!skill.getPermissions(player)) {
 //                continue;
 //            }
 
             rank = skills.get(skill);
-            sender.sendMessage(pluginRef.getLocaleManager().getString("Commands.mcrank.Skill", skill.getName(), (rank == null ? pluginRef.getLocaleManager().getString("Commands.mcrank.Unranked") : rank)));
+            sender.sendMessage(pluginRef.getLocaleManager().getString("Commands.mcrank.Skill", skill.getLocalizedSkillName(), (rank == null ? pluginRef.getLocaleManager().getString("Commands.mcrank.Unranked") : rank)));
         }
 
         rank = skills.get(null);

+ 1 - 1
src/main/java/com/gmail/nossr50/runnables/database/FormulaConversionTask.java

@@ -61,7 +61,7 @@ public class FormulaConversionTask extends BukkitRunnable {
     private void editValues(PlayerProfile profile) {
         pluginRef.debug("========================================================================");
         pluginRef.debug("Conversion report for " + profile.getPlayerName() + ":");
-        for (PrimarySkillType primarySkillType : PrimarySkillType.NON_CHILD_SKILLS) {
+        for (PrimarySkillType primarySkillType : pluginRef.getSkillTools().NON_CHILD_SKILLS) {
             int oldLevel = profile.getSkillLevel(primarySkillType);
             int oldXPLevel = profile.getSkillXpLevel(primarySkillType);
             int totalOldXP = pluginRef.getFormulaManager().calculateTotalExperience(oldLevel, oldXPLevel, previousFormula);

+ 1 - 2
src/main/java/com/gmail/nossr50/runnables/items/ChimaeraWingWarmup.java

@@ -5,7 +5,6 @@ import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.util.ChimaeraWing;
 import com.gmail.nossr50.util.ItemUtils;
 import com.gmail.nossr50.util.Misc;
-import com.gmail.nossr50.util.skills.SkillUtils;
 import org.bukkit.Location;
 import org.bukkit.entity.Player;
 import org.bukkit.inventory.ItemStack;
@@ -47,7 +46,7 @@ public class ChimaeraWingWarmup extends BukkitRunnable {
         int hurtCooldown = pluginRef.getConfigManager().getConfigItems().getRecentlyHurtCooldown();
 
         if (hurtCooldown > 0) {
-            int timeRemaining = SkillUtils.calculateTimeLeft(recentlyHurt * Misc.TIME_CONVERSION_FACTOR, hurtCooldown, player);
+            int timeRemaining = pluginRef.getSkillTools().calculateTimeLeft(recentlyHurt * Misc.TIME_CONVERSION_FACTOR, hurtCooldown, player);
 
             if (timeRemaining > 0) {
                 player.sendMessage(pluginRef.getLocaleManager().getString("Item.Injured.Wait", timeRemaining));

+ 1 - 2
src/main/java/com/gmail/nossr50/runnables/items/TeleportationWarmup.java

@@ -3,7 +3,6 @@ package com.gmail.nossr50.runnables.items;
 import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.util.Misc;
-import com.gmail.nossr50.util.skills.SkillUtils;
 import org.bukkit.Location;
 import org.bukkit.entity.Player;
 import org.bukkit.scheduler.BukkitRunnable;
@@ -42,7 +41,7 @@ public class TeleportationWarmup extends BukkitRunnable {
         int hurtCooldown = pluginRef.getConfigManager().getConfigParty().getPTP().getPtpRecentlyHurtCooldown();
 
         if (hurtCooldown > 0) {
-            int timeRemaining = SkillUtils.calculateTimeLeft(recentlyHurt * Misc.TIME_CONVERSION_FACTOR, hurtCooldown, teleportingPlayer);
+            int timeRemaining = pluginRef.getSkillTools().calculateTimeLeft(recentlyHurt * Misc.TIME_CONVERSION_FACTOR, hurtCooldown, teleportingPlayer);
 
             if (timeRemaining > 0) {
                 teleportingPlayer.sendMessage(pluginRef.getLocaleManager().getString("Item.Injured.Wait", timeRemaining));

+ 2 - 3
src/main/java/com/gmail/nossr50/runnables/skills/AbilityDisableTask.java

@@ -6,7 +6,6 @@ import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.skills.PerksUtils;
-import com.gmail.nossr50.util.skills.SkillUtils;
 import org.bukkit.Chunk;
 import org.bukkit.World;
 import org.bukkit.entity.Player;
@@ -34,7 +33,7 @@ public class AbilityDisableTask extends BukkitRunnable {
         switch (ability) {
             case SUPER_BREAKER:
             case GIGA_DRILL_BREAKER:
-                SkillUtils.handleAbilitySpeedDecrease(player);
+                pluginRef.getSkillTools().handleAbilitySpeedDecrease(player);
                 // Fallthrough
 
             case BERSERK:
@@ -56,7 +55,7 @@ public class AbilityDisableTask extends BukkitRunnable {
         }
 
 
-        SkillUtils.sendSkillMessage(player, NotificationType.SUPER_ABILITY_ALERT_OTHERS, ability.getAbilityPlayerOff());
+        pluginRef.getSkillTools().sendSkillMessage(player, NotificationType.SUPER_ABILITY_ALERT_OTHERS, ability.getAbilityPlayerOff());
         new AbilityCooldownTask(pluginRef, mcMMOPlayer, ability).runTaskLater(pluginRef, PerksUtils.handleCooldownPerks(player, ability.getCooldown()) * Misc.TICK_CONVERSION_FACTOR);
     }
 

+ 2 - 3
src/main/java/com/gmail/nossr50/skills/acrobatics/AcrobaticsManager.java

@@ -15,7 +15,6 @@ import com.gmail.nossr50.util.random.RandomChanceUtil;
 import com.gmail.nossr50.util.skills.ParticleEffectUtils;
 import com.gmail.nossr50.util.skills.RankUtils;
 import com.gmail.nossr50.util.skills.SkillActivationType;
-import com.gmail.nossr50.util.skills.SkillUtils;
 import org.bukkit.Location;
 import org.bukkit.entity.Entity;
 import org.bukkit.entity.Player;
@@ -72,7 +71,7 @@ public class AcrobaticsManager extends SkillManager {
                 return false;
             }*/
 
-            return skill.shouldProcess(damager);
+            return skill.canCombatSkillsTrigger(damager);
         }
 
         return false;
@@ -98,7 +97,7 @@ public class AcrobaticsManager extends SkillManager {
             //Check respawn to prevent abuse
             if (!pluginRef.getConfigManager().getConfigExploitPrevention().getConfigSectionExploitAcrobatics().isPreventAcrobaticsAbuse())
                 applyXpGain((float) (damage * acrobaticsBehaviour.getDodgeXpModifier()), XPGainReason.PVP);
-            else if (SkillUtils.cooldownExpired(mcMMOPlayer.getRespawnATS(), Misc.PLAYER_RESPAWN_COOLDOWN_SECONDS)
+            else if (pluginRef.getSkillTools().cooldownExpired(mcMMOPlayer.getRespawnATS(), Misc.PLAYER_RESPAWN_COOLDOWN_SECONDS)
                     && mcMMOPlayer.getTeleportATS() < System.currentTimeMillis()) {
                 applyXpGain((float) (damage * acrobaticsBehaviour.getDodgeXpModifier()), XPGainReason.PVP);
             }

+ 5 - 2
src/main/java/com/gmail/nossr50/skills/axes/AxesManager.java

@@ -12,7 +12,10 @@ import com.gmail.nossr50.skills.SkillManager;
 import com.gmail.nossr50.util.ItemUtils;
 import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.random.RandomChanceUtil;
-import com.gmail.nossr50.util.skills.*;
+import com.gmail.nossr50.util.skills.CombatUtils;
+import com.gmail.nossr50.util.skills.ParticleEffectUtils;
+import com.gmail.nossr50.util.skills.RankUtils;
+import com.gmail.nossr50.util.skills.SkillActivationType;
 import org.bukkit.entity.LivingEntity;
 import org.bukkit.entity.Player;
 import org.bukkit.event.entity.EntityDamageEvent.DamageModifier;
@@ -122,7 +125,7 @@ public class AxesManager extends SkillManager {
         for (ItemStack armor : target.getEquipment().getArmorContents()) {
             if (armor != null && ItemUtils.isArmor(armor)) {
                 if (RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_STATIC_CHANCE, SubSkillType.AXES_ARMOR_IMPACT, getPlayer())) {
-                    SkillUtils.handleDurabilityChange(armor, durabilityDamage, 1);
+                    pluginRef.getSkillTools().handleDurabilityChange(armor, durabilityDamage, 1);
                 }
             }
         }

+ 1 - 2
src/main/java/com/gmail/nossr50/skills/excavation/ExcavationManager.java

@@ -12,7 +12,6 @@ import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.random.RandomChanceUtil;
 import com.gmail.nossr50.util.skills.RankUtils;
-import com.gmail.nossr50.util.skills.SkillUtils;
 import org.bukkit.Location;
 import org.bukkit.block.BlockState;
 import org.bukkit.entity.EntityType;
@@ -105,6 +104,6 @@ public class ExcavationManager extends SkillManager {
         excavationBlockCheck(blockState);
         excavationBlockCheck(blockState);
 
-        SkillUtils.handleDurabilityChange(getPlayer().getInventory().getItemInMainHand(), pluginRef.getConfigManager().getConfigSuperAbilities().getSuperAbilityLimits().getToolDurabilityDamage());
+        pluginRef.getSkillTools().handleDurabilityChange(getPlayer().getInventory().getItemInMainHand(), pluginRef.getConfigManager().getConfigSuperAbilities().getSuperAbilityLimits().getToolDurabilityDamage());
     }
 }

+ 1 - 2
src/main/java/com/gmail/nossr50/skills/fishing/FishingManager.java

@@ -25,7 +25,6 @@ import com.gmail.nossr50.util.random.RandomChanceSkillStatic;
 import com.gmail.nossr50.util.random.RandomChanceUtil;
 import com.gmail.nossr50.util.skills.CombatUtils;
 import com.gmail.nossr50.util.skills.RankUtils;
-import com.gmail.nossr50.util.skills.SkillUtils;
 import com.gmail.nossr50.util.sounds.SoundManager;
 import com.gmail.nossr50.util.sounds.SoundType;
 import org.bukkit.Bukkit;
@@ -226,7 +225,7 @@ public class FishingManager extends SkillManager {
      * @return the modified change in hunger for the event
      */
     public int handleFishermanDiet(int eventFoodLevel) {
-        return SkillUtils.handleFoodSkills(getPlayer(), eventFoodLevel, SubSkillType.FISHING_FISHERMANS_DIET);
+        return pluginRef.getSkillTools().handleFoodSkills(getPlayer(), eventFoodLevel, SubSkillType.FISHING_FISHERMANS_DIET);
     }
 
     public void iceFishing(FishHook hook, Block block) {

+ 1 - 2
src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java

@@ -19,7 +19,6 @@ import com.gmail.nossr50.util.random.RandomChanceSkillStatic;
 import com.gmail.nossr50.util.random.RandomChanceUtil;
 import com.gmail.nossr50.util.skills.RankUtils;
 import com.gmail.nossr50.util.skills.SkillActivationType;
-import com.gmail.nossr50.util.skills.SkillUtils;
 import org.bukkit.Location;
 import org.bukkit.Material;
 import org.bukkit.block.BlockState;
@@ -91,7 +90,7 @@ public class HerbalismManager extends SkillManager {
      * @return the modified change in hunger for the event
      */
     public int farmersDiet(int eventFoodLevel) {
-        return SkillUtils.handleFoodSkills(getPlayer(), eventFoodLevel, SubSkillType.HERBALISM_FARMERS_DIET);
+        return pluginRef.getSkillTools().handleFoodSkills(getPlayer(), eventFoodLevel, SubSkillType.HERBALISM_FARMERS_DIET);
     }
 
     /**

+ 1 - 2
src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java

@@ -16,7 +16,6 @@ import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.random.RandomChanceUtil;
 import com.gmail.nossr50.util.skills.RankUtils;
-import com.gmail.nossr50.util.skills.SkillUtils;
 import org.bukkit.Material;
 import org.bukkit.block.Block;
 import org.bukkit.block.BlockState;
@@ -93,7 +92,7 @@ public class MiningManager extends SkillManager {
         applyXpGain(miningBehaviour.getBlockXp(blockState), XPGainReason.PVE);
 
         if (mcMMOPlayer.getAbilityMode(skill.getSuperAbility())) {
-            SkillUtils.handleDurabilityChange(getPlayer().getInventory().getItemInMainHand(), pluginRef.getConfigManager().getConfigSuperAbilities().getSuperAbilityLimits().getToolDurabilityDamage());
+            pluginRef.getSkillTools().handleDurabilityChange(getPlayer().getInventory().getItemInMainHand(), pluginRef.getConfigManager().getConfigSuperAbilities().getSuperAbilityLimits().getToolDurabilityDamage());
         }
 
         if (!canDoubleDrop() || !pluginRef.getDynamicSettingsManager().getBonusDropManager().isBonusDropWhitelisted(blockState.getType()))

+ 1 - 2
src/main/java/com/gmail/nossr50/skills/repair/RepairManager.java

@@ -12,7 +12,6 @@ import com.gmail.nossr50.util.random.RandomChanceSkillStatic;
 import com.gmail.nossr50.util.random.RandomChanceUtil;
 import com.gmail.nossr50.util.skills.RankUtils;
 import com.gmail.nossr50.util.skills.SkillActivationType;
-import com.gmail.nossr50.util.skills.SkillUtils;
 import com.gmail.nossr50.util.sounds.SoundManager;
 import com.gmail.nossr50.util.sounds.SoundType;
 import org.bukkit.enchantments.Enchantment;
@@ -185,7 +184,7 @@ public class RepairManager extends SkillManager {
         Player player = getPlayer();
         long lastUse = getLastAnvilUse();
 
-        if (!SkillUtils.cooldownExpired(lastUse, 3) || !pluginRef.getConfigManager().getConfigRepair().getRepairGeneral().isEnchantedItemsRequireConfirm()) {
+        if (!pluginRef.getSkillTools().cooldownExpired(lastUse, 3) || !pluginRef.getConfigManager().getConfigRepair().getRepairGeneral().isEnchantedItemsRequireConfirm()) {
             return true;
         }
 

+ 1 - 2
src/main/java/com/gmail/nossr50/skills/salvage/SalvageManager.java

@@ -14,7 +14,6 @@ import com.gmail.nossr50.util.StringUtils;
 import com.gmail.nossr50.util.random.RandomChanceSkillStatic;
 import com.gmail.nossr50.util.random.RandomChanceUtil;
 import com.gmail.nossr50.util.skills.RankUtils;
-import com.gmail.nossr50.util.skills.SkillUtils;
 import com.gmail.nossr50.util.sounds.SoundManager;
 import com.gmail.nossr50.util.sounds.SoundType;
 import org.bukkit.Location;
@@ -283,7 +282,7 @@ public class SalvageManager extends SkillManager {
         Player player = getPlayer();
         long lastUse = getLastAnvilUse();
 
-        if (!SkillUtils.cooldownExpired(lastUse, 3) || !pluginRef.getConfigManager().getConfigSalvage().getGeneral().isEnchantedItemsRequireConfirm()) {
+        if (!pluginRef.getSkillTools().cooldownExpired(lastUse, 3) || !pluginRef.getConfigManager().getConfigSalvage().getGeneral().isEnchantedItemsRequireConfirm()) {
             return true;
         }
 

+ 1 - 2
src/main/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingManager.java

@@ -17,7 +17,6 @@ import com.gmail.nossr50.util.random.RandomChanceUtil;
 import com.gmail.nossr50.util.skills.CombatUtils;
 import com.gmail.nossr50.util.skills.RankUtils;
 import com.gmail.nossr50.util.skills.SkillActivationType;
-import com.gmail.nossr50.util.skills.SkillUtils;
 import org.bukkit.Material;
 import org.bukkit.block.Block;
 import org.bukkit.block.BlockFace;
@@ -206,7 +205,7 @@ public class WoodcuttingManager extends SkillManager {
             }
         }
 
-        SkillUtils.handleDurabilityChange(inHand, durabilityLoss);
+        pluginRef.getSkillTools().handleDurabilityChange(inHand, durabilityLoss);
         return (inHand.getDurability() < (pluginRef.getRepairableManager().isRepairable(type) ? pluginRef.getRepairableManager().getRepairable(type).getMaximumDurability() : type.getMaxDurability()));
     }
 

+ 2 - 3
src/main/java/com/gmail/nossr50/util/ChimaeraWing.java

@@ -5,7 +5,6 @@ import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.runnables.items.ChimaeraWingWarmup;
 import com.gmail.nossr50.util.skills.CombatUtils;
-import com.gmail.nossr50.util.skills.SkillUtils;
 import com.gmail.nossr50.util.sounds.SoundManager;
 import com.gmail.nossr50.util.sounds.SoundType;
 import org.bukkit.Location;
@@ -59,7 +58,7 @@ public final class ChimaeraWing {
         int cooldown = pluginRef.getConfigManager().getConfigItems().getCooldown();
 
         if (cooldown > 0) {
-            int timeRemaining = SkillUtils.calculateTimeLeft(lastTeleport * Misc.TIME_CONVERSION_FACTOR, cooldown, player);
+            int timeRemaining = pluginRef.getSkillTools().calculateTimeLeft(lastTeleport * Misc.TIME_CONVERSION_FACTOR, cooldown, player);
 
             if (timeRemaining > 0) {
                 pluginRef.getNotificationManager().sendPlayerInformation(player, NotificationType.ABILITY_COOLDOWN, "Item.Generic.Wait", String.valueOf(timeRemaining));
@@ -71,7 +70,7 @@ public final class ChimaeraWing {
         int hurtCooldown = pluginRef.getConfigManager().getConfigItems().getRecentlyHurtCooldown();
 
         if (hurtCooldown > 0) {
-            int timeRemaining = SkillUtils.calculateTimeLeft(recentlyHurt * Misc.TIME_CONVERSION_FACTOR, hurtCooldown, player);
+            int timeRemaining = pluginRef.getSkillTools().calculateTimeLeft(recentlyHurt * Misc.TIME_CONVERSION_FACTOR, hurtCooldown, player);
 
             if (timeRemaining > 0) {
                 pluginRef.getNotificationManager().sendPlayerInformation(player, NotificationType.ITEM_MESSAGE, "Item.Injured.Wait", String.valueOf(timeRemaining));

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

@@ -342,7 +342,7 @@ public class EventManager {
             experienceChanged = event.getExperienceChanged();
             PlayerProfile playerProfile = pluginRef.getUserManager().getPlayer(player).getProfile();
 
-            for (PrimarySkillType primarySkillType : PrimarySkillType.NON_CHILD_SKILLS) {
+            for (PrimarySkillType primarySkillType : pluginRef.getSkillTools().NON_CHILD_SKILLS) {
                 String skillName = primarySkillType.toString();
                 int playerSkillLevel = playerProfile.getSkillLevel(primarySkillType);
 
@@ -389,7 +389,7 @@ public class EventManager {
 
             PlayerProfile victimProfile = pluginRef.getUserManager().getPlayer(victim).getProfile();
 
-            for (PrimarySkillType primarySkillType : PrimarySkillType.NON_CHILD_SKILLS) {
+            for (PrimarySkillType primarySkillType : pluginRef.getSkillTools().NON_CHILD_SKILLS) {
                 String skillName = primarySkillType.toString();
                 int victimSkillLevel = victimProfile.getSkillLevel(primarySkillType);
 
@@ -413,7 +413,7 @@ public class EventManager {
     }
 
     public void callAbilityDeactivateEvent(Player player, SuperAbilityType ability) {
-        McMMOPlayerAbilityDeactivateEvent event = new McMMOPlayerAbilityDeactivateEvent(player, PrimarySkillType.byAbility(ability));
+        McMMOPlayerAbilityDeactivateEvent event = new McMMOPlayerAbilityDeactivateEvent(player, PrimarySkillType.getPrimarySkillBySuperAbility(ability));
         pluginRef.getServer().getPluginManager().callEvent(event);
 
     }

+ 4 - 4
src/main/java/com/gmail/nossr50/util/HardcoreManager.java

@@ -33,7 +33,7 @@ public final class HardcoreManager {
         HashMap<String, Integer> levelChanged = new HashMap<>();
         HashMap<String, Double> experienceChanged = new HashMap<>();
 
-        for (PrimarySkillType primarySkillType : PrimarySkillType.NON_CHILD_SKILLS) {
+        for (PrimarySkillType primarySkillType : pluginRef.getSkillTools().NON_CHILD_SKILLS) {
             if (!primarySkillType.getHardcoreStatLossEnabled()) {
                 levelChanged.put(primarySkillType.toString(), 0);
                 experienceChanged.put(primarySkillType.toString(), 0.0);
@@ -86,7 +86,7 @@ public final class HardcoreManager {
         HashMap<String, Integer> levelChanged = new HashMap<>();
         HashMap<String, Double> experienceChanged = new HashMap<>();
 
-        for (PrimarySkillType primarySkillType : PrimarySkillType.NON_CHILD_SKILLS) {
+        for (PrimarySkillType primarySkillType : pluginRef.getSkillTools().NON_CHILD_SKILLS) {
             if (!primarySkillType.getHardcoreVampirismEnabled()) {
                 levelChanged.put(primarySkillType.toString(), 0);
                 experienceChanged.put(primarySkillType.toString(), 0.0);
@@ -134,7 +134,7 @@ public final class HardcoreManager {
     public static boolean isStatLossEnabled() {
         boolean enabled = false;
 
-        for (PrimarySkillType primarySkillType : PrimarySkillType.NON_CHILD_SKILLS) {
+        for (PrimarySkillType primarySkillType : pluginRef.getSkillTools().NON_CHILD_SKILLS) {
             if (primarySkillType.getHardcoreStatLossEnabled()) {
                 enabled = true;
                 break;
@@ -152,7 +152,7 @@ public final class HardcoreManager {
     public static boolean isVampirismEnabled() {
         boolean enabled = false;
 
-        for (PrimarySkillType primarySkillType : PrimarySkillType.NON_CHILD_SKILLS) {
+        for (PrimarySkillType primarySkillType : pluginRef.getSkillTools().NON_CHILD_SKILLS) {
             if (primarySkillType.getHardcoreVampirismEnabled()) {
                 enabled = true;
                 break;

+ 1 - 2
src/main/java/com/gmail/nossr50/util/Motd.java

@@ -2,7 +2,6 @@ package com.gmail.nossr50.util;
 
 import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
 import com.gmail.nossr50.util.skills.PerksUtils;
-import com.gmail.nossr50.util.skills.SkillUtils;
 import org.bukkit.entity.Player;
 import org.bukkit.plugin.PluginDescriptionFile;
 
@@ -111,7 +110,7 @@ public final class Motd {
      * @param player Target player
      */
     public static void displayActivationPerks(Player player) {
-        int perkAmount = SkillUtils.getEnduranceLength(player);
+        int perkAmount = pluginRef.getSkillTools().getEnduranceLength(player);
 
         if (perkAmount > 0) {
             player.sendMessage(PERK_PREFIX + pluginRef.getLocaleManager().getString("Effects.Template", pluginRef.getLocaleManager().getString("Perks.ActivationTime.Name"), pluginRef.getLocaleManager().getString("Perks.ActivationTime.Desc", perkAmount)));

+ 1 - 1
src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java

@@ -37,7 +37,7 @@ public final class CommandRegistrationManager {
     private void registerSkillCommands() {
         for (PrimarySkillType skill : PrimarySkillType.values()) {
             String commandName = skill.toString().toLowerCase();
-            String localizedName = skill.getName().toLowerCase();
+            String localizedName = skill.getLocalizedSkillName().toLowerCase();
 
             PluginCommand command;
 

+ 3 - 4
src/main/java/com/gmail/nossr50/util/commands/CommandTools.java

@@ -7,7 +7,6 @@ import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.StringUtils;
-import com.gmail.nossr50.util.skills.SkillUtils;
 import org.bukkit.OfflinePlayer;
 import org.bukkit.command.CommandSender;
 import org.bukkit.entity.Player;
@@ -77,7 +76,7 @@ public final class CommandTools {
             return true;
         }
 
-        PlayerProfile profile = new PlayerProfile(playerName, false);
+        PlayerProfile profile = new PlayerProfile(pluginRef, playerName, false);
 
         if (unloadedProfile(sender, profile)) {
             return false;
@@ -138,7 +137,7 @@ public final class CommandTools {
     }
 
     public boolean isInvalidSkill(CommandSender sender, String skillName) {
-        if (SkillUtils.isSkill(skillName)) {
+        if (pluginRef.getSkillTools().isSkill(skillName)) {
             return false;
         }
 
@@ -214,7 +213,7 @@ public final class CommandTools {
         displayData.add(header);
 
         for (PrimarySkillType skill : skillGroup) {
-            if (skill.getPermissions(inspect)) {
+            if (skill.doesPlayerHaveSkillPermission(inspect)) {
                 displayData.add(displaySkill(profile, skill));
             }
         }

+ 2 - 2
src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardStrings.java

@@ -99,7 +99,7 @@ public class ScoreboardStrings {
             int i = 0;
             for (PrimarySkillType type : PrimarySkillType.values()) {
                 // Include child skills
-                skillLabelBuilder.put(type, getShortenedName(colors.get(i) + type.getName(), false));
+                skillLabelBuilder.put(type, getShortenedName(colors.get(i) + type.getLocalizedSkillName(), false));
 
                 if (type.getSuperAbility() != null) {
                     abilityLabelBuilder.put(type.getSuperAbility(), getShortenedName(colors.get(i) + type.getSuperAbility().getName()));
@@ -121,7 +121,7 @@ public class ScoreboardStrings {
         else {
             for (PrimarySkillType type : PrimarySkillType.values()) {
                 // Include child skills
-                skillLabelBuilder.put(type, getShortenedName(ChatColor.GREEN + type.getName()));
+                skillLabelBuilder.put(type, getShortenedName(ChatColor.GREEN + type.getLocalizedSkillName()));
 
                 if (type.getSuperAbility() != null) {
                     abilityLabelBuilder.put(type.getSuperAbility(), formatAbility(type.getSuperAbility().getName()));

+ 4 - 4
src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardWrapper.java

@@ -483,13 +483,13 @@ public class ScoreboardWrapper {
 
                 // Calculate power level here
                 int powerLevel = 0;
-                for (PrimarySkillType skill : PrimarySkillType.NON_CHILD_SKILLS) { // Don't include child skills, makes the list too long
+                for (PrimarySkillType skill : pluginRef.getSkillTools().NON_CHILD_SKILLS) { // Don't include child skills, makes the list too long
                     int level = newProfile.getSkillLevel(skill);
 
                     powerLevel += level;
 
                     // TODO: Verify that this is what we want - calculated in power level but not displayed
-                    if (!skill.getPermissions(player)) {
+                    if (!skill.doesPlayerHaveSkillPermission(player)) {
                         continue;
                     }
 
@@ -516,8 +516,8 @@ public class ScoreboardWrapper {
         Integer rank;
         Player player = pluginRef.getServer().getPlayerExact(playerName);
 
-        for (PrimarySkillType skill : PrimarySkillType.NON_CHILD_SKILLS) {
-            if (!skill.getPermissions(player)) {
+        for (PrimarySkillType skill : pluginRef.getSkillTools().NON_CHILD_SKILLS) {
+            if (!skill.doesPlayerHaveSkillPermission(player)) {
                 continue;
             }
 

+ 13 - 13
src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java

@@ -260,7 +260,7 @@ public final class CombatUtils {
             }
 
             if (ItemUtils.isSword(player.getInventory().getItemInMainHand())) {
-                if (!PrimarySkillType.SWORDS.shouldProcess(target)) {
+                if (!PrimarySkillType.SWORDS.canCombatSkillsTrigger(target)) {
                     return;
                 }
 
@@ -298,27 +298,27 @@ public final class CombatUtils {
             }
 
             if (ItemUtils.isSword(heldItem)) {
-                if (!PrimarySkillType.SWORDS.shouldProcess(target)) {
+                if (!PrimarySkillType.SWORDS.canCombatSkillsTrigger(target)) {
                     return;
                 }
 
-                if (PrimarySkillType.SWORDS.getPermissions(player)) {
+                if (PrimarySkillType.SWORDS.doesPlayerHaveSkillPermission(player)) {
                     processSwordCombat(target, player, event);
                 }
             } else if (ItemUtils.isAxe(heldItem)) {
-                if (!PrimarySkillType.AXES.shouldProcess(target)) {
+                if (!PrimarySkillType.AXES.canCombatSkillsTrigger(target)) {
                     return;
                 }
 
-                if (PrimarySkillType.AXES.getPermissions(player)) {
+                if (PrimarySkillType.AXES.doesPlayerHaveSkillPermission(player)) {
                     processAxeCombat(target, player, event);
                 }
             } else if (ItemUtils.isUnarmed(heldItem)) {
-                if (!PrimarySkillType.UNARMED.shouldProcess(target)) {
+                if (!PrimarySkillType.UNARMED.canCombatSkillsTrigger(target)) {
                     return;
                 }
 
-                if (PrimarySkillType.UNARMED.getPermissions(player)) {
+                if (PrimarySkillType.UNARMED.doesPlayerHaveSkillPermission(player)) {
                     processUnarmedCombat(target, player, event);
                 }
             }
@@ -326,10 +326,10 @@ public final class CombatUtils {
             Wolf wolf = (Wolf) damager;
             AnimalTamer tamer = wolf.getOwner();
 
-            if (tamer instanceof Player && PrimarySkillType.TAMING.shouldProcess(target)) {
+            if (tamer instanceof Player && PrimarySkillType.TAMING.canCombatSkillsTrigger(target)) {
                 Player master = (Player) tamer;
 
-                if (!Misc.isNPCEntityExcludingVillagers(master) && PrimarySkillType.TAMING.getPermissions(master)) {
+                if (!Misc.isNPCEntityExcludingVillagers(master) && PrimarySkillType.TAMING.doesPlayerHaveSkillPermission(master)) {
                     processTamingCombat(target, master, wolf, event);
                 }
             }
@@ -337,14 +337,14 @@ public final class CombatUtils {
             Arrow arrow = (Arrow) damager;
             ProjectileSource projectileSource = arrow.getShooter();
 
-            if (projectileSource instanceof Player && PrimarySkillType.ARCHERY.shouldProcess(target)) {
+            if (projectileSource instanceof Player && PrimarySkillType.ARCHERY.canCombatSkillsTrigger(target)) {
                 Player player = (Player) projectileSource;
 
-                if (!Misc.isNPCEntityExcludingVillagers(player) && PrimarySkillType.ARCHERY.getPermissions(player)) {
+                if (!Misc.isNPCEntityExcludingVillagers(player) && PrimarySkillType.ARCHERY.doesPlayerHaveSkillPermission(player)) {
                     processArcheryCombat(target, player, event, arrow);
                 }
 
-                if (target.getType() != EntityType.CREEPER && !Misc.isNPCEntityExcludingVillagers(player) && PrimarySkillType.TAMING.getPermissions(player)) {
+                if (target.getType() != EntityType.CREEPER && !Misc.isNPCEntityExcludingVillagers(player) && PrimarySkillType.TAMING.doesPlayerHaveSkillPermission(player)) {
                     McMMOPlayer mcMMOPlayer = pluginRef.getUserManager().getPlayer(player);
                     TamingManager tamingManager = mcMMOPlayer.getTamingManager();
                     tamingManager.attackTarget(target);
@@ -538,7 +538,7 @@ public final class CombatUtils {
             xpGainReason = XPGainReason.PVP;
             Player defender = (Player) target;
 
-            if (defender.isOnline() && SkillUtils.cooldownExpired(mcMMOPlayer.getRespawnATS(), Misc.PLAYER_RESPAWN_COOLDOWN_SECONDS)) {
+            if (defender.isOnline() && pluginRef.getSkillTools().cooldownExpired(mcMMOPlayer.getRespawnATS(), Misc.PLAYER_RESPAWN_COOLDOWN_SECONDS)) {
                 baseXPMultiplier = 20 * pluginRef.getDynamicSettingsManager().getExperienceManager().getSpecialCombatXP(SpecialXPKey.PVP);
             }
         } else {

+ 1 - 1
src/main/java/com/gmail/nossr50/util/skills/RankUtils.java

@@ -383,7 +383,7 @@ public class RankUtils {
 
         try {
             SkillRankProperty skillRankProperty
-                    = (SkillRankProperty) rankConfigRoot.getNode(subSkillType.getParentSkill().getCapitalizedName())
+                    = (SkillRankProperty) rankConfigRoot.getNode(subSkillType.getParentSkill().getCapitalizedPrimarySkillName())
                     .getNode(subSkillType.getHoconFriendlyConfigName())
                     .getValue(TypeToken.of(SkillRankProperty.class));
 

+ 739 - 0
src/main/java/com/gmail/nossr50/util/skills/SkillTools.java

@@ -0,0 +1,739 @@
+package com.gmail.nossr50.util.skills;
+
+import com.gmail.nossr50.api.exceptions.InvalidSkillException;
+import com.gmail.nossr50.datatypes.experience.XPGainReason;
+import com.gmail.nossr50.datatypes.experience.XPGainSource;
+import com.gmail.nossr50.datatypes.interactions.NotificationType;
+import com.gmail.nossr50.datatypes.player.McMMOPlayer;
+import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
+import com.gmail.nossr50.datatypes.skills.SubSkillType;
+import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
+import com.gmail.nossr50.datatypes.skills.ToolType;
+import com.gmail.nossr50.mcMMO;
+import com.gmail.nossr50.util.ItemUtils;
+import com.gmail.nossr50.util.Misc;
+import com.gmail.nossr50.util.Permissions;
+import com.gmail.nossr50.util.StringUtils;
+import com.google.common.collect.ImmutableList;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.enchantments.Enchantment;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Tameable;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.Recipe;
+import org.bukkit.inventory.ShapedRecipe;
+import org.bukkit.inventory.ShapelessRecipe;
+import org.bukkit.inventory.meta.ItemMeta;
+
+import java.util.*;
+
+/**
+ * This class handles misc operations involving skills
+ * It also keeps track of the hard-coded relationship between skills
+ * This class will be removed once the new skill system is in place
+ */
+public class SkillTools {
+
+    private final mcMMO pluginRef;
+    private final int ENCHANT_SPEED_VAR;
+
+    public final List<String> LOCALIZED_SKILL_NAMES;
+    public final List<String> SUBSKILL_NAMES;
+    public final List<PrimarySkillType> CHILD_SKILLS;
+    public final List<PrimarySkillType> NON_CHILD_SKILLS;
+    public final List<PrimarySkillType> COMBAT_SKILLS;
+    public final List<PrimarySkillType> GATHERING_SKILLS;
+    public final List<PrimarySkillType> MISC_SKILLS;
+
+    private HashMap<SubSkillType, PrimarySkillType> subSkillParentRelationshipMap; //TODO: This disgusts me, but it will have to do until the new skill system is in place
+    private HashMap<SuperAbilityType, PrimarySkillType> superAbilityParentRelationshipMap; //TODO: This disgusts me, but it will have to do until the new skill system is in place
+    private HashMap<PrimarySkillType, HashSet<SubSkillType>> primarySkillChildrenMap; //TODO: This disgusts me, but it will have to do until the new skill system is in place
+
+    // The map below is for the super abilities which require readying a tool, its everything except blast mining
+    private HashMap<PrimarySkillType, SuperAbilityType> mainActivatedAbilityChildMap; //TODO: This disgusts me, but it will have to do until the new skill system is in place
+    private HashMap<PrimarySkillType, ToolType> primarySkillToolMap; //TODO: Christ..
+
+    public SkillTools(mcMMO pluginRef) {
+        this.pluginRef = pluginRef;
+
+        this.ENCHANT_SPEED_VAR = 5;
+
+        initSubSkillRelationshipMap();
+        initPrimaryChildMap();
+        initPrimaryToolMap();
+        initSuperAbilityParentRelationships();
+        buildSubSkillNameList();
+
+        List<PrimarySkillType> childSkills = new ArrayList<>();
+        List<PrimarySkillType> nonChildSkills = new ArrayList<>();
+
+        for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
+            if (isChildSkill(primarySkillType)) {
+                childSkills.add(primarySkillType);
+            } else {
+                nonChildSkills.add(primarySkillType);
+            }
+        }
+
+        COMBAT_SKILLS = ImmutableList.of(PrimarySkillType.ARCHERY, PrimarySkillType.AXES, PrimarySkillType.SWORDS, PrimarySkillType.TAMING, PrimarySkillType.UNARMED);
+        GATHERING_SKILLS = ImmutableList.of(PrimarySkillType.EXCAVATION, PrimarySkillType.FISHING, PrimarySkillType.HERBALISM, PrimarySkillType.MINING, PrimarySkillType.WOODCUTTING);
+        MISC_SKILLS = ImmutableList.of(PrimarySkillType.ACROBATICS, PrimarySkillType.ALCHEMY, PrimarySkillType.REPAIR, PrimarySkillType.SALVAGE, PrimarySkillType.SMELTING);
+
+        LOCALIZED_SKILL_NAMES = ImmutableList.copyOf(buildLocalizedPrimarySkillNames());
+        SUBSKILL_NAMES = ImmutableList.copyOf(buildSubSkillNameList());
+
+        CHILD_SKILLS = ImmutableList.copyOf(childSkills);
+        NON_CHILD_SKILLS = ImmutableList.copyOf(nonChildSkills);
+    }
+
+    //TODO: What is with this design?
+    private void initPrimaryToolMap() {
+        primarySkillToolMap = new HashMap<>();
+
+        primarySkillToolMap.put(PrimarySkillType.AXES, ToolType.AXE);
+        primarySkillToolMap.put(PrimarySkillType.WOODCUTTING, ToolType.AXE);
+        primarySkillToolMap.put(PrimarySkillType.UNARMED, ToolType.FISTS);
+        primarySkillToolMap.put(PrimarySkillType.SWORDS, ToolType.SWORD);
+        primarySkillToolMap.put(PrimarySkillType.EXCAVATION, ToolType.SHOVEL);
+        primarySkillToolMap.put(PrimarySkillType.HERBALISM, ToolType.HOE);
+        primarySkillToolMap.put(PrimarySkillType.MINING, ToolType.PICKAXE);
+    }
+
+    private void initSuperAbilityParentRelationships() {
+        superAbilityParentRelationshipMap = new HashMap<>();
+        mainActivatedAbilityChildMap = new HashMap<>();
+
+        for(SuperAbilityType superAbilityType : SuperAbilityType.values()) {
+            try {
+                PrimarySkillType parent = getSuperAbilityParent(superAbilityType);
+                superAbilityParentRelationshipMap.put(superAbilityType, parent);
+
+                if(superAbilityType != SuperAbilityType.BLAST_MINING) {
+                    //This map is used only for abilities that have a tool readying phase, so blast mining is ignored
+                    mainActivatedAbilityChildMap.put(parent, superAbilityType);
+                }
+            } catch (InvalidSkillException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private PrimarySkillType getSuperAbilityParent(SuperAbilityType superAbilityType) throws InvalidSkillException {
+        switch(superAbilityType) {
+            case BERSERK:
+                return PrimarySkillType.UNARMED;
+            case GREEN_TERRA:
+                return PrimarySkillType.HERBALISM;
+            case TREE_FELLER:
+                return PrimarySkillType.WOODCUTTING;
+            case SUPER_BREAKER:
+            case BLAST_MINING:
+                return PrimarySkillType.MINING;
+            case SKULL_SPLITTER:
+                return PrimarySkillType.AXES;
+            case SERRATED_STRIKES:
+                return PrimarySkillType.SWORDS;
+            case GIGA_DRILL_BREAKER:
+                return PrimarySkillType.EXCAVATION;
+            default:
+                throw new InvalidSkillException("No parent defined for super ability! "+superAbilityType.toString());
+        }
+    }
+
+    /**
+     * Builds a list of localized {@link PrimarySkillType} names
+     * @return list of localized {@link PrimarySkillType} names
+     */
+    private ArrayList<String> buildLocalizedPrimarySkillNames() {
+        ArrayList<String> localizedSkillNameList = new ArrayList<>();
+
+        for(PrimarySkillType primarySkillType : PrimarySkillType.values()) {
+            localizedSkillNameList.add(getLocalizedSkillName(primarySkillType));
+        }
+
+        Collections.sort(localizedSkillNameList);
+
+        return localizedSkillNameList;
+    }
+
+    /**
+     * Builds a map containing a HashSet of SubSkillTypes considered Children of PrimarySkillType
+     * Disgusting Hacky Fix until the new skill system is in place
+     */
+    private void initPrimaryChildMap() {
+        primarySkillChildrenMap = new HashMap<>();
+
+        //Init the empty Hash Sets
+        for(PrimarySkillType primarySkillType : PrimarySkillType.values()) {
+            primarySkillChildrenMap.put(primarySkillType, new HashSet<SubSkillType>());
+        }
+
+        //Fill in the hash sets
+        for(SubSkillType subSkillType : SubSkillType.values()) {
+            PrimarySkillType parentSkill = subSkillParentRelationshipMap.get(subSkillType);
+
+            //Add this subskill as a child
+            primarySkillChildrenMap.get(parentSkill).add(subSkillType);
+        }
+    }
+
+    /**
+     * Makes a list of the "nice" version of sub skill names
+     * Used in tab completion mostly
+     * @return a list of formatted sub skill names
+     */
+    private ArrayList<String> buildSubSkillNameList() {
+        ArrayList<String> subSkillNameList = new ArrayList<>();
+
+        for(SubSkillType subSkillType : SubSkillType.values()) {
+            subSkillNameList.add(subSkillType.getNiceNameNoSpaces(subSkillType));
+        }
+
+        return subSkillNameList;
+    }
+
+    /**
+     * Builds a map containing the relationships of SubSkillTypes to PrimarySkillTypes
+     * Disgusting Hacky Fix until the new skill system is in place
+     */
+    private void initSubSkillRelationshipMap() {
+        subSkillParentRelationshipMap = new HashMap<>();
+
+        //Super hacky and disgusting
+        for(PrimarySkillType primarySkillType : PrimarySkillType.values()) {
+            for(SubSkillType subSkillType : SubSkillType.values()) {
+                String[] splitSubSkillName = subSkillType.toString().split("_");
+
+                if(primarySkillType.toString().equalsIgnoreCase(splitSubSkillName[0])) {
+                    //Parent Skill Found
+                    subSkillParentRelationshipMap.put(subSkillType, primarySkillType);
+                }
+            }
+        }
+    }
+
+    public void applyXpGain(McMMOPlayer mcMMOPlayer, PrimarySkillType skill, float xp, XPGainReason xpGainReason) {
+        mcMMOPlayer.beginXpGain(skill, xp, xpGainReason, XPGainSource.SELF);
+    }
+
+    public void applyXpGain(McMMOPlayer mcMMOPlayer, PrimarySkillType skill, float xp, XPGainReason xpGainReason, XPGainSource xpGainSource) {
+        mcMMOPlayer.beginXpGain(skill, xp, xpGainReason, xpGainSource);
+    }
+
+    /**
+     * Calculates how long a given ability should last in seconds
+     * Does not factor in perks
+     * @param mcMMOPlayer target mcMMO Player
+     * @param skill target skill
+     * @param superAbilityType target Super Ability
+     * @return how long an ability should last in seconds
+     */
+    public int calculateAbilityLength(McMMOPlayer mcMMOPlayer, PrimarySkillType skill, SuperAbilityType superAbilityType) {
+        //These values change depending on whether or not the server is in retro mode
+        int abilityLengthVar = pluginRef.getConfigManager().getConfigSuperAbilities().getSuperAbilityStartingSeconds();
+
+        int maxLength = pluginRef.getConfigManager().getConfigSuperAbilities().getMaxLengthForSuper(superAbilityType);
+
+        int skillLevel = mcMMOPlayer.getSkillLevel(skill);
+
+        int ticks;
+
+        //Ability cap of 0 or below means no cap
+        if (maxLength > 0) {
+            ticks = Math.min(2 + (Math.min(maxLength, skillLevel) / abilityLengthVar), maxLength);
+        } else {
+            ticks = Math.min(2 + (Math.min(maxLength, skillLevel) / abilityLengthVar), maxLength);
+        }
+
+        return ticks;
+    }
+
+    /**
+     * Calculates how long a given ability should last in seconds
+     * Adds in perks if the player has any
+     * @param mcMMOPlayer target mcMMO Player
+     * @param skill target skill
+     * @param superAbilityType target Super Ability
+     * @return how long an ability should last in seconds
+     */
+    public int calculateAbilityLengthPerks(McMMOPlayer mcMMOPlayer, PrimarySkillType skill, SuperAbilityType superAbilityType) {
+        return getEnduranceLength(mcMMOPlayer.getPlayer()) + calculateAbilityLength(mcMMOPlayer, skill, superAbilityType);
+    }
+
+    public int getEnduranceLength(Player player) {
+        if (Permissions.twelveSecondActivationBoost(player)) {
+            return 12;
+        } else if (Permissions.eightSecondActivationBoost(player)) {
+            return  8;
+        } else if (Permissions.fourSecondActivationBoost(player)) {
+            return  4;
+        } else {
+            return 0;
+        }
+    }
+
+    public int handleFoodSkills(Player player, int eventFoodLevel, SubSkillType subSkillType) {
+        int curRank = RankUtils.getRank(player, subSkillType);
+
+        int currentFoodLevel = player.getFoodLevel();
+        int foodChange = eventFoodLevel - currentFoodLevel;
+
+        foodChange += curRank;
+
+        return currentFoodLevel + foodChange;
+    }
+
+    /**
+     * Calculate the time remaining until the cooldown expires.
+     *
+     * @param deactivatedTimeStamp Time of deactivation
+     * @param cooldown             The length of the cooldown
+     * @param player               The Player to check for cooldown perks
+     * @return the number of seconds remaining before the cooldown expires
+     */
+    public int calculateTimeLeft(long deactivatedTimeStamp, int cooldown, Player player) {
+        return (int) (((deactivatedTimeStamp + (PerksUtils.handleCooldownPerks(player, cooldown) * Misc.TIME_CONVERSION_FACTOR)) - System.currentTimeMillis()) / Misc.TIME_CONVERSION_FACTOR);
+    }
+
+    /**
+     * Check if the cooldown has expired.
+     * This does NOT account for cooldown perks!
+     *
+     * @param deactivatedTimeStamp Time of deactivation in seconds
+     * @param cooldown             The length of the cooldown in seconds
+     * @return true if the cooldown is expired
+     */
+    public boolean cooldownExpired(long deactivatedTimeStamp, int cooldown) {
+        return System.currentTimeMillis() >= (deactivatedTimeStamp + cooldown) * Misc.TIME_CONVERSION_FACTOR;
+    }
+
+    /**
+     * Checks if the given string represents a valid skill
+     *
+     * @param skillName The name of the skill to check
+     * @return true if this is a valid skill, false otherwise
+     */
+    public boolean isSkill(String skillName) {
+        return pluginRef.getConfigManager().getConfigLanguage().getTargetLanguage().equalsIgnoreCase("en_US") ? matchSkill(skillName) != null : isLocalizedSkill(skillName);
+    }
+
+    public void sendSkillMessage(Player player, NotificationType notificationType, String key) {
+        Location location = player.getLocation();
+
+        for (Player otherPlayer : player.getWorld().getPlayers()) {
+            if (otherPlayer != player && Misc.isNear(location, otherPlayer.getLocation(), Misc.SKILL_MESSAGE_MAX_SENDING_DISTANCE)) {
+                pluginRef.getNotificationManager().sendNearbyPlayersInformation(otherPlayer, notificationType, key, player.getName());
+            }
+        }
+    }
+
+    public void handleAbilitySpeedIncrease(Player player) {
+        ItemStack heldItem = player.getInventory().getItemInMainHand();
+
+        if (heldItem == null || heldItem.getType() == Material.AIR) {
+            return;
+        }
+
+        int efficiencyLevel = heldItem.getEnchantmentLevel(Enchantment.DIG_SPEED);
+        ItemMeta itemMeta = heldItem.getItemMeta();
+        List<String> itemLore = new ArrayList<>();
+
+        if (itemMeta.hasLore()) {
+            itemLore = itemMeta.getLore();
+        }
+
+        itemLore.add("mcMMO Ability Tool");
+        itemMeta.addEnchant(Enchantment.DIG_SPEED, efficiencyLevel + ENCHANT_SPEED_VAR, true);
+
+        itemMeta.setLore(itemLore);
+        heldItem.setItemMeta(itemMeta);
+        player.updateInventory();
+
+        /*else {
+            int duration = 0;
+            int amplifier = 0;
+
+            if (player.hasPotionEffect(PotionEffectType.FAST_DIGGING)) {
+                for (PotionEffect effect : player.getActivePotionEffects()) {
+                    if (effect.getType() == PotionEffectType.FAST_DIGGING) {
+                        duration = effect.getDuration();
+                        amplifier = effect.getAmplifier();
+                        break;
+                    }
+                }
+            }
+
+            McMMOPlayer mcMMOPlayer = pluginRef.getUserManager().getPlayer(player);
+
+            //Not Loaded
+            if(mcMMOPlayer == null)
+                return;
+
+            PrimarySkillType skill = mcMMOPlayer.getAbilityMode(SuperAbilityType.SUPER_BREAKER) ? PrimarySkillType.MINING : PrimarySkillType.EXCAVATION;
+
+            int abilityLengthVar = AdvancedConfig.getInstance().getAbilityLength();
+            int abilityLengthCap = AdvancedConfig.getInstance().getAbilityLengthCap();
+
+            int ticks;
+
+            if(abilityLengthCap > 0)
+            {
+                ticks = PerksUtils.calculateAbilityLength(player,  Math.min(abilityLengthCap, 2 + (mcMMOPlayer.getSkillLevel(skill) / abilityLengthVar)),
+                        skill.getSuperAbility().getMaxLength()) * Misc.TICK_CONVERSION_FACTOR;
+            } else {
+                ticks = PerksUtils.calculateAbilityLength(player, 2 + ((mcMMOPlayer.getSkillLevel(skill)) / abilityLengthVar),
+                        skill.getSuperAbility().getMaxLength()) * Misc.TICK_CONVERSION_FACTOR;
+            }
+
+            PotionEffect abilityBuff = new PotionEffect(PotionEffectType.FAST_DIGGING, duration + ticks, amplifier + 10);
+            player.addPotionEffect(abilityBuff, true);
+        }*/
+    }
+
+    public void handleAbilitySpeedDecrease(Player player) {
+        for (ItemStack item : player.getInventory().getContents()) {
+            removeAbilityBuff(item);
+        }
+    }
+
+    public void removeAbilityBuff(ItemStack item) {
+        if (item == null || item.getType() == Material.AIR || (!ItemUtils.isPickaxe(item) && !ItemUtils.isShovel(item)) || !item.containsEnchantment(Enchantment.DIG_SPEED)) {
+            return;
+        }
+
+        ItemMeta itemMeta = item.getItemMeta();
+
+        if (itemMeta.hasLore()) {
+            List<String> itemLore = itemMeta.getLore();
+
+            if (itemLore.remove("mcMMO Ability Tool")) {
+                int efficiencyLevel = item.getEnchantmentLevel(Enchantment.DIG_SPEED);
+
+                if (efficiencyLevel <= ENCHANT_SPEED_VAR) {
+                    itemMeta.removeEnchant(Enchantment.DIG_SPEED);
+                } else {
+                    itemMeta.addEnchant(Enchantment.DIG_SPEED, efficiencyLevel - ENCHANT_SPEED_VAR, true);
+                }
+
+                itemMeta.setLore(itemLore);
+                item.setItemMeta(itemMeta);
+            }
+        }
+    }
+
+    public void handleDurabilityChange(ItemStack itemStack, int durabilityModifier) {
+        handleDurabilityChange(itemStack, durabilityModifier, 1.0);
+    }
+
+    /**
+     * Modify the durability of an ItemStack.
+     *
+     * @param itemStack          The ItemStack which durability should be modified
+     * @param durabilityModifier the amount to modify the durability by
+     * @param maxDamageModifier  the amount to adjust the max damage by
+     */
+    public void handleDurabilityChange(ItemStack itemStack, double durabilityModifier, double maxDamageModifier) {
+        if(itemStack.getItemMeta() != null && itemStack.getItemMeta().isUnbreakable()) {
+            return;
+        }
+
+        Material type = itemStack.getType();
+        short maxDurability = pluginRef.getRepairableManager().isRepairable(type) ? pluginRef.getRepairableManager().getRepairable(type).getMaximumDurability() : type.getMaxDurability();
+        durabilityModifier = (int) Math.min(durabilityModifier / (itemStack.getEnchantmentLevel(Enchantment.DURABILITY) + 1), maxDurability * maxDamageModifier);
+
+        itemStack.setDurability((short) Math.min(itemStack.getDurability() + durabilityModifier, maxDurability));
+    }
+
+    private boolean isLocalizedSkill(String skillName) {
+        for (PrimarySkillType skill : PrimarySkillType.values()) {
+            if (skillName.equalsIgnoreCase(pluginRef.getLocaleManager().getString(StringUtils.getCapitalized(skill.toString()) + ".SkillName"))) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    protected Material getRepairAndSalvageItem(ItemStack inHand) {
+        if (ItemUtils.isDiamondTool(inHand) || ItemUtils.isDiamondArmor(inHand)) {
+            return Material.DIAMOND;
+        } else if (ItemUtils.isGoldTool(inHand) || ItemUtils.isGoldArmor(inHand)) {
+            return Material.GOLD_INGOT;
+        } else if (ItemUtils.isIronTool(inHand) || ItemUtils.isIronArmor(inHand)) {
+            return Material.IRON_INGOT;
+        } else if (ItemUtils.isStoneTool(inHand)) {
+            return Material.COBBLESTONE;
+        } else if (ItemUtils.isWoodTool(inHand)) {
+            return Material.OAK_WOOD;
+        } else if (ItemUtils.isLeatherArmor(inHand)) {
+            return Material.LEATHER;
+        } else if (ItemUtils.isStringTool(inHand)) {
+            return Material.STRING;
+        } else {
+            return null;
+        }
+    }
+
+    public int getRepairAndSalvageQuantities(ItemStack item) {
+        return getRepairAndSalvageQuantities(item.getType(), getRepairAndSalvageItem(item));
+    }
+
+    public int getRepairAndSalvageQuantities(Material itemMaterial, Material recipeMaterial) {
+        int quantity = 0;
+
+        for(Iterator<? extends Recipe> recipeIterator = Bukkit.getServer().recipeIterator(); recipeIterator.hasNext();) {
+            Recipe bukkitRecipe = recipeIterator.next();
+
+            if(bukkitRecipe.getResult().getType() != itemMaterial)
+                continue;
+
+            if(bukkitRecipe instanceof ShapelessRecipe) {
+                for (ItemStack ingredient : ((ShapelessRecipe) bukkitRecipe).getIngredientList()) {
+                    if (ingredient != null
+                            && (recipeMaterial == null || ingredient.getType() == recipeMaterial)
+                            && (ingredient.getType() == recipeMaterial)) {
+                        quantity += ingredient.getAmount();
+                    }
+                }
+            } else if(bukkitRecipe instanceof ShapedRecipe) {
+                for (ItemStack ingredient : ((ShapedRecipe) bukkitRecipe).getIngredientMap().values()) {
+                    if (ingredient != null
+                            && (recipeMaterial == null || ingredient.getType() == recipeMaterial)
+                            && (ingredient.getType() == recipeMaterial)) {
+                        quantity += ingredient.getAmount();
+                    }
+                }
+            }
+        }
+
+        return quantity;
+    }
+
+    public int getRepairAndSalvageQuantities(Material itemMaterial, List<Material> recipeMaterials) {
+        int quantity = 0;
+
+        for(Iterator<? extends Recipe> recipeIterator = Bukkit.getServer().recipeIterator(); recipeIterator.hasNext();) {
+            Recipe bukkitRecipe = recipeIterator.next();
+
+            if(bukkitRecipe.getResult().getType() != itemMaterial)
+                continue;
+
+            boolean matchedIngredient = false;
+
+            for(Material recipeMaterial : recipeMaterials) {
+                if(matchedIngredient)
+                    break;
+
+                if(bukkitRecipe instanceof ShapelessRecipe) {
+                    for (ItemStack ingredient : ((ShapelessRecipe) bukkitRecipe).getIngredientList()) {
+                        if (ingredient != null
+                                && (recipeMaterial == null || ingredient.getType() == recipeMaterial)
+                                && (ingredient.getType() == recipeMaterial)) {
+                            quantity += ingredient.getAmount();
+                            matchedIngredient = true;
+                        }
+                    }
+                } else if(bukkitRecipe instanceof ShapedRecipe) {
+                    for (ItemStack ingredient : ((ShapedRecipe) bukkitRecipe).getIngredientMap().values()) {
+                        if (ingredient != null
+                                && (recipeMaterial == null || ingredient.getType() == recipeMaterial)
+                                && (ingredient.getType() == recipeMaterial)) {
+                            quantity += ingredient.getAmount();
+                            matchedIngredient = true;
+                        }
+                    }
+                }
+            }
+        }
+
+        return quantity;
+    }
+
+    /**
+     * Determine if a recipe has already been registered
+     * @param recipe target recipe
+     * @return true if the recipe has already been registered
+     */
+    //TODO: Why is this in this class?
+    //TODO: Why is this in this class?
+    //TODO: Why is this in this class?
+    //TODO: Why is this in this class?
+    //TODO: Why is this in this class?
+    //TODO: Why is this in this class?
+    //TODO: Why is this in this class?
+    //TODO: Why is this in this class?
+    //TODO: Why is this in this class?
+    //TODO: Why is this in this class?
+    //TODO: Why is this in this class?
+    //TODO: Why is this in this class?
+    //TODO: Why is this in this class?
+    //TODO: Why is this in this class?
+    //TODO: Why is this in this class?
+    //TODO: Why is this in this class?
+    public boolean hasRecipeBeenRegistered(Recipe recipe) {
+        for(Iterator<? extends Recipe> recipeIterator = Bukkit.getServer().recipeIterator(); recipeIterator.hasNext();) {
+            Recipe bukkitRecipe = recipeIterator.next();
+
+            if(bukkitRecipe.getResult().isSimilar(recipe.getResult())) {
+                return true;
+            }
+
+        }
+        return false;
+    }
+
+    /**
+     * Matches a string of a skill to a skill
+     * This is NOT case sensitive
+     * First it checks the locale file and tries to match by the localized name of the skill
+     * Then if nothing is found it checks against the hard coded "name" of the skill, which is just its name in English
+     * @param skillName target skill name
+     * @return the matching PrimarySkillType if one is found, otherwise null
+     */
+    public PrimarySkillType matchSkill(String skillName) {
+        if (!pluginRef.getConfigManager().getConfigLanguage().getTargetLanguage().equalsIgnoreCase("en_US")) {
+            for (PrimarySkillType type : PrimarySkillType.values()) {
+                if (skillName.equalsIgnoreCase(pluginRef.getLocaleManager().getString(StringUtils.getCapitalized(type.name()) + ".SkillName"))) {
+                    return type;
+                }
+            }
+        }
+
+        for (PrimarySkillType type : PrimarySkillType.values()) {
+            if (type.name().equalsIgnoreCase(skillName)) {
+                return type;
+            }
+        }
+
+        if (!skillName.equalsIgnoreCase("all")) {
+            pluginRef.getLogger().warning("Invalid mcMMO skill (" + skillName + ")"); //TODO: Localize
+        }
+
+        return null;
+    }
+
+    /**
+     * Gets the PrimarySkillStype to which a SubSkillType belongs
+     * Return null if it does not belong to one.. which should be impossible in most circumstances
+     * @param subSkillType target subskill
+     * @return the PrimarySkillType of this SubSkill, null if it doesn't exist
+     */
+    public PrimarySkillType getPrimarySkillBySubSkill(SubSkillType subSkillType) {
+        return subSkillParentRelationshipMap.get(subSkillType);
+    }
+
+    /**
+     * Gets the PrimarySkillStype to which a SuperAbilityType belongs
+     * Return null if it does not belong to one.. which should be impossible in most circumstances
+     * @param superAbilityType target super ability
+     * @return the PrimarySkillType of this SuperAbilityType, null if it doesn't exist
+     */
+    public PrimarySkillType getPrimarySkillBySuperAbility(SuperAbilityType superAbilityType) {
+        return superAbilityParentRelationshipMap.get(superAbilityType);
+    }
+
+    public SuperAbilityType getSuperAbility(PrimarySkillType primarySkillType) {
+        return mainActivatedAbilityChildMap.get(primarySkillType);
+    }
+
+    public boolean isSuperAbilityUnlocked(Player player, PrimarySkillType primarySkillType) {
+        return RankUtils.getRank(player, getSuperAbility(primarySkillType).getSubSkillTypeDefinition()) >= 1;
+    }
+
+    public boolean getPVPEnabled(PrimarySkillType primarySkillType) {
+        return pluginRef.getConfigManager().getConfigCoreSkills().isPVPEnabled(primarySkillType);
+    }
+
+    public boolean getPVEEnabled(PrimarySkillType primarySkillType) {
+        return pluginRef.getConfigManager().getConfigCoreSkills().isPVEEnabled(primarySkillType);
+    }
+
+    public boolean getHardcoreStatLossEnabled() {
+        return pluginRef.getConfigManager().getConfigHardcore().getDeathPenalty().getSkillToggleMap().get(this);
+    }
+
+    public boolean getHardcoreVampirismEnabled() {
+        return pluginRef.getConfigManager().getConfigHardcore().getVampirism().getSkillToggleMap().get(this);
+    }
+
+    public ToolType getPrimarySkillToolType(PrimarySkillType primarySkillType) {
+        return primarySkillToolMap.get(primarySkillType);
+    }
+
+    public List<SubSkillType> getSkillAbilities(PrimarySkillType primarySkillType) {
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        //TODO: Cache this!
+        return new ArrayList<>(primarySkillChildrenMap.get(primarySkillType));
+    }
+
+    public double getXpModifier(PrimarySkillType primarySkillType) {
+        return pluginRef.getConfigManager().getConfigLeveling().getSkillXpFormulaModifier(primarySkillType);
+    }
+
+    // TODO: This is a little "hacky", we probably need to add something to distinguish child skills in the enum, or to use another enum for them
+    public boolean isChildSkill(PrimarySkillType primarySkillType) {
+        switch (primarySkillType) {
+            case SALVAGE:
+            case SMELTING:
+                return true;
+
+            default:
+                return false;
+        }
+    }
+
+    /**
+     * Get the localized name for a {@link PrimarySkillType}
+     * @param primarySkillType target {@link PrimarySkillType}
+     * @return the localized name for a {@link PrimarySkillType}
+     */
+    public String getLocalizedSkillName(PrimarySkillType primarySkillType) {
+        return StringUtils.getCapitalized(pluginRef.getLocaleManager().getString(StringUtils.getCapitalized(primarySkillType.toString()) + ".SkillName"));
+    }
+
+    public boolean doesPlayerHaveSkillPermission(PrimarySkillType primarySkillType, Player player) {
+        return Permissions.skillEnabled(player, primarySkillType);
+    }
+
+    public boolean canCombatSkillsTrigger(PrimarySkillType primarySkillType, Entity target) {
+        return (target instanceof Player || (target instanceof Tameable && ((Tameable) target).isTamed())) ? getPVPEnabled(primarySkillType) : getPVEEnabled(primarySkillType);
+    }
+
+    public String getCapitalizedPrimarySkillName(PrimarySkillType primarySkillType) {
+        return StringUtils.getCapitalized(primarySkillType.toString());
+    }
+}

+ 0 - 388
src/main/java/com/gmail/nossr50/util/skills/SkillUtils.java

@@ -1,388 +0,0 @@
-package com.gmail.nossr50.util.skills;
-
-import com.gmail.nossr50.datatypes.experience.XPGainReason;
-import com.gmail.nossr50.datatypes.experience.XPGainSource;
-import com.gmail.nossr50.datatypes.interactions.NotificationType;
-import com.gmail.nossr50.datatypes.player.McMMOPlayer;
-import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
-import com.gmail.nossr50.datatypes.skills.SubSkillType;
-import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
-import com.gmail.nossr50.util.ItemUtils;
-import com.gmail.nossr50.util.Misc;
-import com.gmail.nossr50.util.Permissions;
-import com.gmail.nossr50.util.StringUtils;
-import org.bukkit.Bukkit;
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.enchantments.Enchantment;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.inventory.Recipe;
-import org.bukkit.inventory.ShapedRecipe;
-import org.bukkit.inventory.ShapelessRecipe;
-import org.bukkit.inventory.meta.ItemMeta;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-public class SkillUtils {
-
-    public static final int ENCHANT_SPEED_VAR = 5;
-
-    public static void applyXpGain(McMMOPlayer mcMMOPlayer, PrimarySkillType skill, float xp, XPGainReason xpGainReason) {
-        mcMMOPlayer.beginXpGain(skill, xp, xpGainReason, XPGainSource.SELF);
-    }
-
-    public static void applyXpGain(McMMOPlayer mcMMOPlayer, PrimarySkillType skill, float xp, XPGainReason xpGainReason, XPGainSource xpGainSource) {
-        mcMMOPlayer.beginXpGain(skill, xp, xpGainReason, xpGainSource);
-    }
-
-    /**
-     * Calculates how long a given ability should last in seconds
-     * Does not factor in perks
-     * @param mcMMOPlayer target mcMMO Player
-     * @param skill target skill
-     * @param superAbilityType target Super Ability
-     * @return how long an ability should last in seconds
-     */
-    public static int calculateAbilityLength(McMMOPlayer mcMMOPlayer, PrimarySkillType skill, SuperAbilityType superAbilityType) {
-        //These values change depending on whether or not the server is in retro mode
-        int abilityLengthVar = pluginRef.getConfigManager().getConfigSuperAbilities().getSuperAbilityStartingSeconds();
-
-        int maxLength = pluginRef.getConfigManager().getConfigSuperAbilities().getMaxLengthForSuper(superAbilityType);
-
-        int skillLevel = mcMMOPlayer.getSkillLevel(skill);
-
-        int ticks;
-
-        //Ability cap of 0 or below means no cap
-        if (maxLength > 0) {
-            ticks = Math.min(2 + (Math.min(maxLength, skillLevel) / abilityLengthVar), maxLength);
-        } else {
-            ticks = Math.min(2 + (Math.min(maxLength, skillLevel) / abilityLengthVar), maxLength);
-        }
-
-        return ticks;
-    }
-
-    /**
-     * Calculates how long a given ability should last in seconds
-     * Adds in perks if the player has any
-     * @param mcMMOPlayer target mcMMO Player
-     * @param skill target skill
-     * @param superAbilityType target Super Ability
-     * @return how long an ability should last in seconds
-     */
-    public static int calculateAbilityLengthPerks(McMMOPlayer mcMMOPlayer, PrimarySkillType skill, SuperAbilityType superAbilityType) {
-        return getEnduranceLength(mcMMOPlayer.getPlayer()) + calculateAbilityLength(mcMMOPlayer, skill, superAbilityType);
-    }
-
-    public static int getEnduranceLength(Player player) {
-        if (Permissions.twelveSecondActivationBoost(player)) {
-            return 12;
-        } else if (Permissions.eightSecondActivationBoost(player)) {
-            return  8;
-        } else if (Permissions.fourSecondActivationBoost(player)) {
-            return  4;
-        } else {
-            return 0;
-        }
-    }
-
-    public static int handleFoodSkills(Player player, int eventFoodLevel, SubSkillType subSkillType) {
-        int curRank = RankUtils.getRank(player, subSkillType);
-
-        int currentFoodLevel = player.getFoodLevel();
-        int foodChange = eventFoodLevel - currentFoodLevel;
-
-        foodChange += curRank;
-
-        return currentFoodLevel + foodChange;
-    }
-
-    /**
-     * Calculate the time remaining until the cooldown expires.
-     *
-     * @param deactivatedTimeStamp Time of deactivation
-     * @param cooldown             The length of the cooldown
-     * @param player               The Player to check for cooldown perks
-     * @return the number of seconds remaining before the cooldown expires
-     */
-    public static int calculateTimeLeft(long deactivatedTimeStamp, int cooldown, Player player) {
-        return (int) (((deactivatedTimeStamp + (PerksUtils.handleCooldownPerks(player, cooldown) * Misc.TIME_CONVERSION_FACTOR)) - System.currentTimeMillis()) / Misc.TIME_CONVERSION_FACTOR);
-    }
-
-    /**
-     * Check if the cooldown has expired.
-     * This does NOT account for cooldown perks!
-     *
-     * @param deactivatedTimeStamp Time of deactivation in seconds
-     * @param cooldown             The length of the cooldown in seconds
-     * @return true if the cooldown is expired
-     */
-    public static boolean cooldownExpired(long deactivatedTimeStamp, int cooldown) {
-        return System.currentTimeMillis() >= (deactivatedTimeStamp + cooldown) * Misc.TIME_CONVERSION_FACTOR;
-    }
-
-    /**
-     * Checks if the given string represents a valid skill
-     *
-     * @param skillName The name of the skill to check
-     * @return true if this is a valid skill, false otherwise
-     */
-    public static boolean isSkill(String skillName) {
-        return pluginRef.getConfigManager().getConfigLanguage().getTargetLanguage().equalsIgnoreCase("en_US") ? PrimarySkillType.getSkill(skillName) != null : isLocalizedSkill(skillName);
-    }
-
-    public static void sendSkillMessage(Player player, NotificationType notificationType, String key) {
-        Location location = player.getLocation();
-
-        for (Player otherPlayer : player.getWorld().getPlayers()) {
-            if (otherPlayer != player && Misc.isNear(location, otherPlayer.getLocation(), Misc.SKILL_MESSAGE_MAX_SENDING_DISTANCE)) {
-                pluginRef.getNotificationManager().sendNearbyPlayersInformation(otherPlayer, notificationType, key, player.getName());
-            }
-        }
-    }
-
-    public static void handleAbilitySpeedIncrease(Player player) {
-        ItemStack heldItem = player.getInventory().getItemInMainHand();
-
-        if (heldItem == null || heldItem.getType() == Material.AIR) {
-            return;
-        }
-
-        int efficiencyLevel = heldItem.getEnchantmentLevel(Enchantment.DIG_SPEED);
-        ItemMeta itemMeta = heldItem.getItemMeta();
-        List<String> itemLore = new ArrayList<>();
-
-        if (itemMeta.hasLore()) {
-            itemLore = itemMeta.getLore();
-        }
-
-        itemLore.add("mcMMO Ability Tool");
-        itemMeta.addEnchant(Enchantment.DIG_SPEED, efficiencyLevel + ENCHANT_SPEED_VAR, true);
-
-        itemMeta.setLore(itemLore);
-        heldItem.setItemMeta(itemMeta);
-        player.updateInventory();
-
-        /*else {
-            int duration = 0;
-            int amplifier = 0;
-
-            if (player.hasPotionEffect(PotionEffectType.FAST_DIGGING)) {
-                for (PotionEffect effect : player.getActivePotionEffects()) {
-                    if (effect.getType() == PotionEffectType.FAST_DIGGING) {
-                        duration = effect.getDuration();
-                        amplifier = effect.getAmplifier();
-                        break;
-                    }
-                }
-            }
-
-            McMMOPlayer mcMMOPlayer = pluginRef.getUserManager().getPlayer(player);
-
-            //Not Loaded
-            if(mcMMOPlayer == null)
-                return;
-
-            PrimarySkillType skill = mcMMOPlayer.getAbilityMode(SuperAbilityType.SUPER_BREAKER) ? PrimarySkillType.MINING : PrimarySkillType.EXCAVATION;
-
-            int abilityLengthVar = AdvancedConfig.getInstance().getAbilityLength();
-            int abilityLengthCap = AdvancedConfig.getInstance().getAbilityLengthCap();
-
-            int ticks;
-
-            if(abilityLengthCap > 0)
-            {
-                ticks = PerksUtils.calculateAbilityLength(player,  Math.min(abilityLengthCap, 2 + (mcMMOPlayer.getSkillLevel(skill) / abilityLengthVar)),
-                        skill.getSuperAbility().getMaxLength()) * Misc.TICK_CONVERSION_FACTOR;
-            } else {
-                ticks = PerksUtils.calculateAbilityLength(player, 2 + ((mcMMOPlayer.getSkillLevel(skill)) / abilityLengthVar),
-                        skill.getSuperAbility().getMaxLength()) * Misc.TICK_CONVERSION_FACTOR;
-            }
-
-            PotionEffect abilityBuff = new PotionEffect(PotionEffectType.FAST_DIGGING, duration + ticks, amplifier + 10);
-            player.addPotionEffect(abilityBuff, true);
-        }*/
-    }
-
-    public static void handleAbilitySpeedDecrease(Player player) {
-        for (ItemStack item : player.getInventory().getContents()) {
-            removeAbilityBuff(item);
-        }
-    }
-
-    public static void removeAbilityBuff(ItemStack item) {
-        if (item == null || item.getType() == Material.AIR || (!ItemUtils.isPickaxe(item) && !ItemUtils.isShovel(item)) || !item.containsEnchantment(Enchantment.DIG_SPEED)) {
-            return;
-        }
-
-        ItemMeta itemMeta = item.getItemMeta();
-
-        if (itemMeta.hasLore()) {
-            List<String> itemLore = itemMeta.getLore();
-
-            if (itemLore.remove("mcMMO Ability Tool")) {
-                int efficiencyLevel = item.getEnchantmentLevel(Enchantment.DIG_SPEED);
-
-                if (efficiencyLevel <= ENCHANT_SPEED_VAR) {
-                    itemMeta.removeEnchant(Enchantment.DIG_SPEED);
-                } else {
-                    itemMeta.addEnchant(Enchantment.DIG_SPEED, efficiencyLevel - ENCHANT_SPEED_VAR, true);
-                }
-
-                itemMeta.setLore(itemLore);
-                item.setItemMeta(itemMeta);
-            }
-        }
-    }
-
-    public static void handleDurabilityChange(ItemStack itemStack, int durabilityModifier) {
-        handleDurabilityChange(itemStack, durabilityModifier, 1.0);
-    }
-
-    /**
-     * Modify the durability of an ItemStack.
-     *
-     * @param itemStack          The ItemStack which durability should be modified
-     * @param durabilityModifier the amount to modify the durability by
-     * @param maxDamageModifier  the amount to adjust the max damage by
-     */
-    public static void handleDurabilityChange(ItemStack itemStack, double durabilityModifier, double maxDamageModifier) {
-        if(itemStack.getItemMeta() != null && itemStack.getItemMeta().isUnbreakable()) {
-            return;
-        }
-
-        Material type = itemStack.getType();
-        short maxDurability = pluginRef.getRepairableManager().isRepairable(type) ? pluginRef.getRepairableManager().getRepairable(type).getMaximumDurability() : type.getMaxDurability();
-        durabilityModifier = (int) Math.min(durabilityModifier / (itemStack.getEnchantmentLevel(Enchantment.DURABILITY) + 1), maxDurability * maxDamageModifier);
-
-        itemStack.setDurability((short) Math.min(itemStack.getDurability() + durabilityModifier, maxDurability));
-    }
-
-    private static boolean isLocalizedSkill(String skillName) {
-        for (PrimarySkillType skill : PrimarySkillType.values()) {
-            if (skillName.equalsIgnoreCase(pluginRef.getLocaleManager().getString(StringUtils.getCapitalized(skill.toString()) + ".SkillName"))) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    protected static Material getRepairAndSalvageItem(ItemStack inHand) {
-        if (ItemUtils.isDiamondTool(inHand) || ItemUtils.isDiamondArmor(inHand)) {
-            return Material.DIAMOND;
-        } else if (ItemUtils.isGoldTool(inHand) || ItemUtils.isGoldArmor(inHand)) {
-            return Material.GOLD_INGOT;
-        } else if (ItemUtils.isIronTool(inHand) || ItemUtils.isIronArmor(inHand)) {
-            return Material.IRON_INGOT;
-        } else if (ItemUtils.isStoneTool(inHand)) {
-            return Material.COBBLESTONE;
-        } else if (ItemUtils.isWoodTool(inHand)) {
-            return Material.OAK_WOOD;
-        } else if (ItemUtils.isLeatherArmor(inHand)) {
-            return Material.LEATHER;
-        } else if (ItemUtils.isStringTool(inHand)) {
-            return Material.STRING;
-        } else {
-            return null;
-        }
-    }
-
-    public static int getRepairAndSalvageQuantities(ItemStack item) {
-        return getRepairAndSalvageQuantities(item.getType(), getRepairAndSalvageItem(item));
-    }
-
-    public static int getRepairAndSalvageQuantities(Material itemMaterial, Material recipeMaterial) {
-        int quantity = 0;
-
-        for(Iterator<? extends Recipe> recipeIterator = Bukkit.getServer().recipeIterator(); recipeIterator.hasNext();) {
-            Recipe bukkitRecipe = recipeIterator.next();
-
-            if(bukkitRecipe.getResult().getType() != itemMaterial)
-                continue;
-
-            if(bukkitRecipe instanceof ShapelessRecipe) {
-                for (ItemStack ingredient : ((ShapelessRecipe) bukkitRecipe).getIngredientList()) {
-                    if (ingredient != null
-                            && (recipeMaterial == null || ingredient.getType() == recipeMaterial)
-                            && (ingredient.getType() == recipeMaterial)) {
-                        quantity += ingredient.getAmount();
-                    }
-                }
-            } else if(bukkitRecipe instanceof ShapedRecipe) {
-                for (ItemStack ingredient : ((ShapedRecipe) bukkitRecipe).getIngredientMap().values()) {
-                    if (ingredient != null
-                            && (recipeMaterial == null || ingredient.getType() == recipeMaterial)
-                            && (ingredient.getType() == recipeMaterial)) {
-                        quantity += ingredient.getAmount();
-                    }
-                }
-            }
-        }
-
-        return quantity;
-    }
-
-    public static int getRepairAndSalvageQuantities(Material itemMaterial, List<Material> recipeMaterials) {
-        int quantity = 0;
-
-        for(Iterator<? extends Recipe> recipeIterator = Bukkit.getServer().recipeIterator(); recipeIterator.hasNext();) {
-            Recipe bukkitRecipe = recipeIterator.next();
-
-            if(bukkitRecipe.getResult().getType() != itemMaterial)
-                continue;
-
-            boolean matchedIngredient = false;
-
-            for(Material recipeMaterial : recipeMaterials) {
-                if(matchedIngredient)
-                    break;
-
-                if(bukkitRecipe instanceof ShapelessRecipe) {
-                    for (ItemStack ingredient : ((ShapelessRecipe) bukkitRecipe).getIngredientList()) {
-                        if (ingredient != null
-                                && (recipeMaterial == null || ingredient.getType() == recipeMaterial)
-                                && (ingredient.getType() == recipeMaterial)) {
-                            quantity += ingredient.getAmount();
-                            matchedIngredient = true;
-                        }
-                    }
-                } else if(bukkitRecipe instanceof ShapedRecipe) {
-                    for (ItemStack ingredient : ((ShapedRecipe) bukkitRecipe).getIngredientMap().values()) {
-                        if (ingredient != null
-                                && (recipeMaterial == null || ingredient.getType() == recipeMaterial)
-                                && (ingredient.getType() == recipeMaterial)) {
-                            quantity += ingredient.getAmount();
-                            matchedIngredient = true;
-                        }
-                    }
-                }
-            }
-        }
-
-        return quantity;
-    }
-
-    /**
-     * Determine if a recipe has already been registered
-     * @param recipe target recipe
-     * @return true if the recipe has already been registered
-     */
-    public static boolean hasRecipeBeenRegistered(Recipe recipe) {
-        for(Iterator<? extends Recipe> recipeIterator = Bukkit.getServer().recipeIterator(); recipeIterator.hasNext();) {
-            Recipe bukkitRecipe = recipeIterator.next();
-
-            if(bukkitRecipe.getResult().isSimilar(recipe.getResult())) {
-                return true;
-            }
-
-        }
-        return false;
-    }
-
-
-}