Sfoglia il codice sorgente

MASSIVE Permissions overhaul. Added a handful of new permissions,
renamed a few more. Changed Green Terra to handle blocks based on
perms rather than the config file.

For more details, read the diff.

GJ 12 anni fa
parent
commit
701822c69f
73 ha cambiato i file con 478 aggiunte e 963 eliminazioni
  1. 1 0
      Changelog.txt
  2. 13 12
      src/main/java/com/gmail/nossr50/commands/CommandHelper.java
  3. 1 1
      src/main/java/com/gmail/nossr50/commands/CommandRegistrationHelper.java
  4. 3 2
      src/main/java/com/gmail/nossr50/commands/admin/AddlevelsCommand.java
  5. 3 2
      src/main/java/com/gmail/nossr50/commands/admin/AddxpCommand.java
  6. 5 4
      src/main/java/com/gmail/nossr50/commands/admin/HardcoreCommand.java
  7. 3 2
      src/main/java/com/gmail/nossr50/commands/admin/McgodCommand.java
  8. 3 2
      src/main/java/com/gmail/nossr50/commands/admin/McrefreshCommand.java
  9. 3 2
      src/main/java/com/gmail/nossr50/commands/admin/MmoeditCommand.java
  10. 8 7
      src/main/java/com/gmail/nossr50/commands/admin/SkillresetCommand.java
  11. 5 4
      src/main/java/com/gmail/nossr50/commands/admin/VampirismCommand.java
  12. 3 2
      src/main/java/com/gmail/nossr50/commands/admin/XprateCommand.java
  13. 4 7
      src/main/java/com/gmail/nossr50/commands/player/InspectCommand.java
  14. 3 2
      src/main/java/com/gmail/nossr50/commands/player/McabilityCommand.java
  15. 17 10
      src/main/java/com/gmail/nossr50/commands/player/McmmoCommand.java
  16. 5 4
      src/main/java/com/gmail/nossr50/commands/player/McrankCommand.java
  17. 2 1
      src/main/java/com/gmail/nossr50/commands/player/MctopCommand.java
  18. 0 5
      src/main/java/com/gmail/nossr50/config/Config.java
  19. 2 1
      src/main/java/com/gmail/nossr50/datatypes/McMMOPlayer.java
  20. 16 16
      src/main/java/com/gmail/nossr50/listeners/BlockListener.java
  21. 8 8
      src/main/java/com/gmail/nossr50/listeners/PlayerListener.java
  22. 0 5
      src/main/java/com/gmail/nossr50/party/commands/PartyAcceptCommand.java
  23. 0 5
      src/main/java/com/gmail/nossr50/party/commands/PartyChangeOwnerCommand.java
  24. 1 5
      src/main/java/com/gmail/nossr50/party/commands/PartyChangePasswordCommand.java
  25. 8 1
      src/main/java/com/gmail/nossr50/party/commands/PartyCommand.java
  26. 0 5
      src/main/java/com/gmail/nossr50/party/commands/PartyCreateCommand.java
  27. 0 5
      src/main/java/com/gmail/nossr50/party/commands/PartyDisbandCommand.java
  28. 0 5
      src/main/java/com/gmail/nossr50/party/commands/PartyExpShareCommand.java
  29. 0 5
      src/main/java/com/gmail/nossr50/party/commands/PartyInviteCommand.java
  30. 0 5
      src/main/java/com/gmail/nossr50/party/commands/PartyItemShareCommand.java
  31. 0 5
      src/main/java/com/gmail/nossr50/party/commands/PartyJoinCommand.java
  32. 0 5
      src/main/java/com/gmail/nossr50/party/commands/PartyKickCommand.java
  33. 3 2
      src/main/java/com/gmail/nossr50/party/commands/PartyLockCommand.java
  34. 0 5
      src/main/java/com/gmail/nossr50/party/commands/PartyQuitCommand.java
  35. 0 5
      src/main/java/com/gmail/nossr50/party/commands/PartyRenameCommand.java
  36. 3 3
      src/main/java/com/gmail/nossr50/party/commands/PtpCommand.java
  37. 3 1
      src/main/java/com/gmail/nossr50/runnables/McTopAsync.java
  38. 4 3
      src/main/java/com/gmail/nossr50/skills/SkillCommand.java
  39. 7 2
      src/main/java/com/gmail/nossr50/skills/SkillManager.java
  40. 2 2
      src/main/java/com/gmail/nossr50/skills/archery/ArcheryCommand.java
  41. 1 1
      src/main/java/com/gmail/nossr50/skills/archery/ArcheryManager.java
  42. 3 3
      src/main/java/com/gmail/nossr50/skills/axes/AxesCommand.java
  43. 2 2
      src/main/java/com/gmail/nossr50/skills/excavation/Excavation.java
  44. 1 1
      src/main/java/com/gmail/nossr50/skills/excavation/ExcavationCommand.java
  45. 7 5
      src/main/java/com/gmail/nossr50/skills/fishing/Fishing.java
  46. 3 3
      src/main/java/com/gmail/nossr50/skills/fishing/FishingCommand.java
  47. 2 2
      src/main/java/com/gmail/nossr50/skills/fishing/ShakeMob.java
  48. 13 18
      src/main/java/com/gmail/nossr50/skills/herbalism/Herbalism.java
  49. 1 14
      src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismBlock.java
  50. 5 3
      src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismCommand.java
  51. 2 2
      src/main/java/com/gmail/nossr50/skills/mining/MiningCommand.java
  52. 1 1
      src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java
  53. 3 3
      src/main/java/com/gmail/nossr50/skills/repair/Repair.java
  54. 8 8
      src/main/java/com/gmail/nossr50/skills/repair/RepairCommand.java
  55. 3 3
      src/main/java/com/gmail/nossr50/skills/repair/RepairItemType.java
  56. 8 8
      src/main/java/com/gmail/nossr50/skills/repair/RepairMaterialType.java
  57. 1 1
      src/main/java/com/gmail/nossr50/skills/smelting/FluxMiningEventHandler.java
  58. 2 2
      src/main/java/com/gmail/nossr50/skills/smelting/SmeltResourceEventHandler.java
  59. 2 2
      src/main/java/com/gmail/nossr50/skills/smelting/SmeltingCommand.java
  60. 3 3
      src/main/java/com/gmail/nossr50/skills/smelting/SmeltingManager.java
  61. 1 1
      src/main/java/com/gmail/nossr50/skills/swords/SwordsCommand.java
  62. 2 2
      src/main/java/com/gmail/nossr50/skills/unarmed/UnarmedCommand.java
  63. 1 1
      src/main/java/com/gmail/nossr50/skills/unarmed/UnarmedManager.java
  64. 1 1
      src/main/java/com/gmail/nossr50/skills/utilities/AbilityType.java
  65. 12 12
      src/main/java/com/gmail/nossr50/skills/utilities/CombatTools.java
  66. 13 13
      src/main/java/com/gmail/nossr50/skills/utilities/PerksUtils.java
  67. 13 11
      src/main/java/com/gmail/nossr50/skills/utilities/SkillTools.java
  68. 2 2
      src/main/java/com/gmail/nossr50/skills/woodcutting/Woodcutting.java
  69. 1 1
      src/main/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingCommand.java
  70. 2 1
      src/main/java/com/gmail/nossr50/spout/commands/XplockCommand.java
  71. 170 643
      src/main/java/com/gmail/nossr50/util/Permissions.java
  72. 0 5
      src/main/resources/config.yml
  73. 50 17
      src/main/resources/plugin.yml

+ 1 - 0
Changelog.txt

@@ -68,6 +68,7 @@ Version 1.4.00-dev
  = Fixed a bug where a new party leader wasn't appointed, after the previous party leader left
  = Fixed a bug where Disarm and Deflect had wrong values
  = Fixed Magic Hunter (Fishing ability) favoring certain enchants
+ ! Changed Green Terra blocks to be determined via permissions instead of the config file
  ! Config files are now backed up even when running in SQL mode
  ! Changed /p and /a to use /partychat and /adminchat as the default command name. The use of /p, /pc, /a, and /ac is still supported.
  ! We're now using Bukkit sounds instead of Spout sounds.

+ 13 - 12
src/main/java/com/gmail/nossr50/commands/CommandHelper.java

@@ -7,6 +7,7 @@ import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.skills.utilities.SkillTools;
 import com.gmail.nossr50.skills.utilities.SkillType;
+import com.gmail.nossr50.util.Permissions;
 
 public final class CommandHelper {
     private CommandHelper() {}
@@ -31,23 +32,23 @@ public final class CommandHelper {
         if (SkillTools.hasGatheringSkills(inspect)) {
             display.sendMessage(LocaleLoader.getString("Stats.Header.Gathering"));
 
-            if (inspect.hasPermission("mcmmo.skills.excavation")) {
+            if (Permissions.skillEnabled(inspect, SkillType.EXCAVATION)) {
                 display.sendMessage(LocaleLoader.getString("Skills.Stats", LocaleLoader.getString("Excavation.Listener"), profile.getSkillLevel(SkillType.EXCAVATION), profile.getSkillXpLevel(SkillType.EXCAVATION), profile.getXpToLevel(SkillType.EXCAVATION)));
             }
 
-            if (inspect.hasPermission("mcmmo.skills.fishing")) {
+            if (Permissions.skillEnabled(inspect, SkillType.FISHING)) {
                 display.sendMessage(LocaleLoader.getString("Skills.Stats", LocaleLoader.getString("Fishing.Listener"), profile.getSkillLevel(SkillType.FISHING), profile.getSkillXpLevel(SkillType.FISHING), profile.getXpToLevel(SkillType.FISHING)));
             }
 
-            if (inspect.hasPermission("mcmmo.skills.fishing")) {
+            if (Permissions.skillEnabled(inspect, SkillType.HERBALISM)) {
                 display.sendMessage(LocaleLoader.getString("Skills.Stats", LocaleLoader.getString("Herbalism.Listener"), profile.getSkillLevel(SkillType.HERBALISM), profile.getSkillXpLevel(SkillType.HERBALISM), profile.getXpToLevel(SkillType.HERBALISM)));
             }
 
-            if (inspect.hasPermission("mcmmo.skills.mining")) {
+            if (Permissions.skillEnabled(inspect, SkillType.MINING)) {
                 display.sendMessage(LocaleLoader.getString("Skills.Stats", LocaleLoader.getString("Mining.Listener"), profile.getSkillLevel(SkillType.MINING), profile.getSkillXpLevel(SkillType.MINING), profile.getXpToLevel(SkillType.MINING)));
             }
 
-            if (inspect.hasPermission("mcmmo.skills.woodcutting")) {
+            if (Permissions.skillEnabled(inspect, SkillType.WOODCUTTING)) {
                 display.sendMessage(LocaleLoader.getString("Skills.Stats", LocaleLoader.getString("Woodcutting.Listener"), profile.getSkillLevel(SkillType.WOODCUTTING), profile.getSkillXpLevel(SkillType.WOODCUTTING), profile.getXpToLevel(SkillType.WOODCUTTING)));
             }
         }
@@ -68,23 +69,23 @@ public final class CommandHelper {
         if (SkillTools.hasCombatSkills(inspect)) {
             display.sendMessage(LocaleLoader.getString("Stats.Header.Combat"));
 
-            if (inspect.hasPermission("mcmmo.skills.axes")) {
+            if (Permissions.skillEnabled(inspect, SkillType.AXES)) {
                 display.sendMessage(LocaleLoader.getString("Skills.Stats", LocaleLoader.getString("Axes.Listener"), profile.getSkillLevel(SkillType.AXES), profile.getSkillXpLevel(SkillType.AXES), profile.getXpToLevel(SkillType.AXES)));
             }
 
-            if (inspect.hasPermission("mcmmo.skills.archery")) {
+            if (Permissions.skillEnabled(inspect, SkillType.ARCHERY)) {
                 display.sendMessage(LocaleLoader.getString("Skills.Stats", LocaleLoader.getString("Archery.Listener"), profile.getSkillLevel(SkillType.ARCHERY), profile.getSkillXpLevel(SkillType.ARCHERY), profile.getXpToLevel(SkillType.ARCHERY)));
             }
 
-            if (inspect.hasPermission("mcmmo.skills.swords")) {
+            if (Permissions.skillEnabled(inspect, SkillType.SWORDS)) {
                 display.sendMessage(LocaleLoader.getString("Skills.Stats", LocaleLoader.getString("Swords.Listener"), profile.getSkillLevel(SkillType.SWORDS), profile.getSkillXpLevel(SkillType.SWORDS), profile.getXpToLevel(SkillType.SWORDS)));
             }
 
-            if (inspect.hasPermission("mcmmo.skills.taming")) {
+            if (Permissions.skillEnabled(inspect, SkillType.TAMING)) {
                 display.sendMessage(LocaleLoader.getString("Skills.Stats", LocaleLoader.getString("Taming.Listener"), profile.getSkillLevel(SkillType.TAMING), profile.getSkillXpLevel(SkillType.TAMING), profile.getXpToLevel(SkillType.TAMING)));
             }
 
-            if (inspect.hasPermission("mcmmo.skills.unarmed")) {
+            if (Permissions.skillEnabled(inspect, SkillType.UNARMED)) {
                 display.sendMessage(LocaleLoader.getString("Skills.Stats", LocaleLoader.getString("Unarmed.Listener"), profile.getSkillLevel(SkillType.UNARMED), profile.getSkillXpLevel(SkillType.UNARMED), profile.getXpToLevel(SkillType.UNARMED)));
             }
         }
@@ -105,11 +106,11 @@ public final class CommandHelper {
         if (SkillTools.hasMiscSkills(inspect)) {
             display.sendMessage(LocaleLoader.getString("Stats.Header.Misc"));
 
-            if (inspect.hasPermission("mcmmo.skills.acrobatics")) {
+            if (Permissions.skillEnabled(inspect, SkillType.ACROBATICS)) {
                 display.sendMessage(LocaleLoader.getString("Skills.Stats", LocaleLoader.getString("Acrobatics.Listener"), profile.getSkillLevel(SkillType.ACROBATICS), profile.getSkillXpLevel(SkillType.ACROBATICS), profile.getXpToLevel(SkillType.ACROBATICS)));
             }
 
-            if (inspect.hasPermission("mcmmo.skills.repair")) {
+            if (Permissions.skillEnabled(inspect, SkillType.REPAIR)) {
                 display.sendMessage(LocaleLoader.getString("Skills.Stats", LocaleLoader.getString("Repair.Listener"), profile.getSkillLevel(SkillType.REPAIR), profile.getSkillXpLevel(SkillType.REPAIR), profile.getXpToLevel(SkillType.REPAIR)));
             }
         }

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

@@ -215,7 +215,7 @@ public final class CommandRegistrationHelper {
     public static void registerMcmmoCommand() {
         PluginCommand command = mcMMO.p.getCommand("mcmmo");
         command.setDescription(LocaleLoader.getString("Commands.Description.mcmmo"));
-        command.setPermission("mcmmo.commands.mcmmo;mcmmo.commands.mcmmo.help");
+        command.setPermission("mcmmo.commands.mcmmo.description;mcmmo.commands.mcmmo.help");
         command.setPermissionMessage(permissionsMessage);
         command.setUsage(LocaleLoader.getString("Commands.Usage.0", "mcmmo"));
         command.setUsage(command.getUsage() + "\n" + LocaleLoader.getString("Commands.Usage.1", "mcmmo", "help"));

+ 3 - 2
src/main/java/com/gmail/nossr50/commands/admin/AddlevelsCommand.java

@@ -10,6 +10,7 @@ import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.skills.utilities.SkillTools;
 import com.gmail.nossr50.skills.utilities.SkillType;
+import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.StringUtils;
 import com.gmail.nossr50.util.Users;
 
@@ -23,7 +24,7 @@ public class AddlevelsCommand implements CommandExecutor{
 
         switch (args.length) {
         case 2:
-            if (!sender.hasPermission("mcmmo.commands.addlevels")) {
+            if (!Permissions.addlevels(sender)) {
                 sender.sendMessage(command.getPermissionMessage());
                 return true;
             }
@@ -71,7 +72,7 @@ public class AddlevelsCommand implements CommandExecutor{
             return true;
 
         case 3:
-            if (!sender.hasPermission("mcmmo.commands.addlevels.others")) {
+            if (!Permissions.addlevelsOthers(sender)) {
                 sender.sendMessage(command.getPermissionMessage());
                 return true;
             }

+ 3 - 2
src/main/java/com/gmail/nossr50/commands/admin/AddxpCommand.java

@@ -9,6 +9,7 @@ import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.skills.utilities.SkillTools;
 import com.gmail.nossr50.skills.utilities.SkillType;
+import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.StringUtils;
 import com.gmail.nossr50.util.Users;
 
@@ -23,7 +24,7 @@ public class AddxpCommand implements CommandExecutor {
 
         switch (args.length) {
         case 2:
-            if (!sender.hasPermission("mcmmo.commands.addxp")) {
+            if (!Permissions.addxp(sender)) {
                 sender.sendMessage(command.getPermissionMessage());
                 return true;
             }
@@ -69,7 +70,7 @@ public class AddxpCommand implements CommandExecutor {
             return true;
 
         case 3:
-            if (!sender.hasPermission("mcmmo.commands.addxp.others")) {
+            if (!Permissions.addxpOthers(sender)) {
                 sender.sendMessage(command.getPermissionMessage());
                 return true;
             }

+ 5 - 4
src/main/java/com/gmail/nossr50/commands/admin/HardcoreCommand.java

@@ -9,6 +9,7 @@ import org.bukkit.command.CommandSender;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.locale.LocaleLoader;
+import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.StringUtils;
 
 public class HardcoreCommand implements CommandExecutor{
@@ -17,7 +18,7 @@ public class HardcoreCommand implements CommandExecutor{
     public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
         switch (args.length) {
         case 0:
-            if (!sender.hasPermission("mcmmo.commands.hardcore.toggle")) {
+            if (!Permissions.hardcoreToggle(sender)) {
                 sender.sendMessage(command.getPermissionMessage());
                 return true;
             }
@@ -33,7 +34,7 @@ public class HardcoreCommand implements CommandExecutor{
 
         case 1:
             if (args[0].equalsIgnoreCase("on") || args[0].equalsIgnoreCase("true") || args[0].equalsIgnoreCase("enabled")) {
-                if (!sender.hasPermission("mcmmo.commands.hardcore.toggle")) {
+                if (!Permissions.hardcoreToggle(sender)) {
                     sender.sendMessage(command.getPermissionMessage());
                     return true;
                 }
@@ -43,7 +44,7 @@ public class HardcoreCommand implements CommandExecutor{
             }
 
             if (args[0].equalsIgnoreCase("off") || args[0].equalsIgnoreCase("false") || args[0].equalsIgnoreCase("disabled")) {
-                if (!sender.hasPermission("mcmmo.commands.hardcore.toggle")) {
+                if (!Permissions.hardcoreToggle(sender)) {
                     sender.sendMessage(command.getPermissionMessage());
                     return true;
                 }
@@ -56,7 +57,7 @@ public class HardcoreCommand implements CommandExecutor{
                 return false;
             }
 
-            if (!sender.hasPermission("mcmmo.commands.hardcore.modify")) {
+            if (!Permissions.hardcoreModify(sender)) {
                 sender.sendMessage(command.getPermissionMessage());
                 return true;
             }

+ 3 - 2
src/main/java/com/gmail/nossr50/commands/admin/McgodCommand.java

@@ -8,6 +8,7 @@ import org.bukkit.entity.Player;
 import com.gmail.nossr50.datatypes.McMMOPlayer;
 import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.locale.LocaleLoader;
+import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.Users;
 
 public class McgodCommand implements CommandExecutor {
@@ -17,7 +18,7 @@ public class McgodCommand implements CommandExecutor {
 
         switch (args.length) {
         case 0:
-            if (!sender.hasPermission("mcmmo.commands.mcgod")) {
+            if (!Permissions.mcgod(sender)) {
                 sender.sendMessage(command.getPermissionMessage());
                 return true;
             }
@@ -44,7 +45,7 @@ public class McgodCommand implements CommandExecutor {
             return true;
 
         case 1:
-            if (!sender.hasPermission("mcmmo.commands.mcgod.others")) {
+            if (!Permissions.mcgodOthers(sender)) {
                 sender.sendMessage(command.getPermissionMessage());
                 return true;
             }

+ 3 - 2
src/main/java/com/gmail/nossr50/commands/admin/McrefreshCommand.java

@@ -8,6 +8,7 @@ import org.bukkit.entity.Player;
 import com.gmail.nossr50.datatypes.McMMOPlayer;
 import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.locale.LocaleLoader;
+import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.Users;
 
 public class McrefreshCommand implements CommandExecutor {
@@ -17,7 +18,7 @@ public class McrefreshCommand implements CommandExecutor {
 
         switch (args.length) {
         case 0:
-            if (!sender.hasPermission("mcmmo.commands.mcrefresh")) {
+            if (!Permissions.mcrefresh(sender)) {
                 sender.sendMessage(command.getPermissionMessage());
                 return true;
             }
@@ -37,7 +38,7 @@ public class McrefreshCommand implements CommandExecutor {
             return true;
 
         case 1:
-            if (!sender.hasPermission("mcmmo.commands.mcrefresh.others")) {
+            if (!Permissions.mcrefreshOthers(sender)) {
                 sender.sendMessage(command.getPermissionMessage());
                 return true;
             }

+ 3 - 2
src/main/java/com/gmail/nossr50/commands/admin/MmoeditCommand.java

@@ -10,6 +10,7 @@ import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.skills.utilities.SkillTools;
 import com.gmail.nossr50.skills.utilities.SkillType;
+import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.StringUtils;
 import com.gmail.nossr50.util.Users;
 
@@ -23,7 +24,7 @@ public class MmoeditCommand implements CommandExecutor {
 
         switch (args.length) {
         case 2:
-            if (!sender.hasPermission("mcmmo.commands.mmoedit")) {
+            if (!Permissions.mmoedit(sender)) {
                 sender.sendMessage(command.getPermissionMessage());
                 return true;
             }
@@ -67,7 +68,7 @@ public class MmoeditCommand implements CommandExecutor {
             return true;
 
         case 3:
-            if (!sender.hasPermission("mcmmo.commands.mmoedit.others")) {
+            if (!Permissions.mmoeditOthers(sender)) {
                 sender.sendMessage(command.getPermissionMessage());
                 return true;
             }

+ 8 - 7
src/main/java/com/gmail/nossr50/commands/admin/SkillresetCommand.java

@@ -10,6 +10,7 @@ import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.skills.utilities.SkillTools;
 import com.gmail.nossr50.skills.utilities.SkillType;
+import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.Users;
 
 public class SkillresetCommand implements CommandExecutor {
@@ -22,7 +23,7 @@ public class SkillresetCommand implements CommandExecutor {
 
         switch (args.length) {
         case 1:
-            if (!sender.hasPermission("mcmmo.commands.skillreset")) {
+            if (!Permissions.skillreset(sender)) {
                 sender.sendMessage(command.getPermissionMessage());
                 return true;
             }
@@ -47,7 +48,7 @@ public class SkillresetCommand implements CommandExecutor {
                         continue;
                     }
 
-                    if (!sender.hasPermission("mcmmo.commands.skillreset." + skillType.toString().toLowerCase())) {
+                    if (!Permissions.skillreset(sender, skillType)) {
                         sender.sendMessage(command.getPermissionMessage());
                         continue;
                     }
@@ -61,7 +62,7 @@ public class SkillresetCommand implements CommandExecutor {
                 skill = SkillType.getSkill(args[0]);
                 skillName = SkillTools.getSkillName(skill);
 
-                if (!sender.hasPermission("mcmmo.commands.skillreset." + skill.toString().toLowerCase())) {
+                if (!Permissions.skillreset(sender, skill)) {
                     sender.sendMessage(command.getPermissionMessage());
                     return true;
                 }
@@ -73,7 +74,7 @@ public class SkillresetCommand implements CommandExecutor {
             return true;
 
         case 2:
-            if (!sender.hasPermission("mcmmo.commands.skillreset.others")) {
+            if (!Permissions.skillresetOthers(sender)) {
                 sender.sendMessage(command.getPermissionMessage());
                 return true;
             }
@@ -90,7 +91,7 @@ public class SkillresetCommand implements CommandExecutor {
                 skill = SkillType.getSkill(args[1]);
                 skillName = SkillTools.getSkillName(skill);
 
-                if (!sender.hasPermission("mcmmo.commands.skillreset.others." + skill.toString().toLowerCase())) {
+                if (!Permissions.skillresetOthers(sender, skill)) {
                     sender.sendMessage(command.getPermissionMessage());
                     return true;
                 }
@@ -113,7 +114,7 @@ public class SkillresetCommand implements CommandExecutor {
                             continue;
                         }
 
-                        if (!sender.hasPermission("mcmmo.commands.skillreset.others." + skillType.toString().toLowerCase())) {
+                        if (!Permissions.skillresetOthers(sender, skill)) {
                             sender.sendMessage(command.getPermissionMessage());
                             continue;
                         }
@@ -136,7 +137,7 @@ public class SkillresetCommand implements CommandExecutor {
                             continue;
                         }
 
-                        if (!sender.hasPermission("mcmmo.commands.skillreset.others." + skillType.toString().toLowerCase())) {
+                        if (!Permissions.skillresetOthers(sender, skill)) {
                             sender.sendMessage(command.getPermissionMessage());
                             continue;
                         }

+ 5 - 4
src/main/java/com/gmail/nossr50/commands/admin/VampirismCommand.java

@@ -9,6 +9,7 @@ import org.bukkit.command.CommandSender;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.locale.LocaleLoader;
+import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.StringUtils;
 
 public class VampirismCommand implements CommandExecutor {
@@ -22,7 +23,7 @@ public class VampirismCommand implements CommandExecutor {
 
         switch (args.length) {
         case 0:
-            if (!sender.hasPermission("mcmmo.commands.vampirism.toggle")) {
+            if (!Permissions.vampirismToggle(sender)) {
                 sender.sendMessage(command.getPermissionMessage());
                 return true;
             }
@@ -38,7 +39,7 @@ public class VampirismCommand implements CommandExecutor {
 
         case 1:
             if (args[0].equalsIgnoreCase("on") || args[0].equalsIgnoreCase("true") || args[0].equalsIgnoreCase("enabled")) {
-                if (!sender.hasPermission("mcmmo.commands.vampirism.toggle")) {
+                if (!Permissions.vampirismToggle(sender)) {
                     sender.sendMessage(command.getPermissionMessage());
                     return true;
                 }
@@ -48,7 +49,7 @@ public class VampirismCommand implements CommandExecutor {
             }
 
             if (args[0].equalsIgnoreCase("off") || args[0].equalsIgnoreCase("false") || args[0].equalsIgnoreCase("disabled")) {
-                if (!sender.hasPermission("mcmmo.commands.vampirism.toggle")) {
+                if (!Permissions.vampirismToggle(sender)) {
                     sender.sendMessage(command.getPermissionMessage());
                     return true;
                 }
@@ -61,7 +62,7 @@ public class VampirismCommand implements CommandExecutor {
                 return false;
             }
 
-            if (!sender.hasPermission("mcmmo.commands.vampirism.modify")) {
+            if (!Permissions.vampirismModify(sender)) {
                 sender.sendMessage(command.getPermissionMessage());
                 return true;
             }

+ 3 - 2
src/main/java/com/gmail/nossr50/commands/admin/XprateCommand.java

@@ -7,6 +7,7 @@ import org.bukkit.command.CommandSender;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.locale.LocaleLoader;
+import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.StringUtils;
 
 public class XprateCommand implements CommandExecutor {
@@ -20,7 +21,7 @@ public class XprateCommand implements CommandExecutor {
                 return false;
             }
 
-            if (!sender.hasPermission("mcmmo.commands.xprate.reset")) {
+            if (!Permissions.xprateReset(sender)) {
                 sender.sendMessage(command.getPermissionMessage());
                 return true;
             }
@@ -38,7 +39,7 @@ public class XprateCommand implements CommandExecutor {
                 return false;
             }
 
-            if (!sender.hasPermission("mcmmo.commands.xprate.set")) {
+            if (!Permissions.xprateSet(sender)) {
                 sender.sendMessage(command.getPermissionMessage());
                 return true;
             }

+ 4 - 7
src/main/java/com/gmail/nossr50/commands/player/InspectCommand.java

@@ -11,6 +11,7 @@ import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.skills.utilities.SkillType;
 import com.gmail.nossr50.util.Misc;
+import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.Users;
 
 public class InspectCommand implements CommandExecutor {
@@ -20,11 +21,6 @@ public class InspectCommand implements CommandExecutor {
 
         switch (args.length) {
         case 1:
-            if (!sender.hasPermission("mcmmo.commands.inspect")) {
-                sender.sendMessage(command.getPermissionMessage());
-                return true;
-            }
-
             McMMOPlayer mcMMOPlayer = Users.getPlayer(args[0]);
 
             // If the mcMMOPlayer doesn't exist, create a temporary profile and check if it's present in the database. If it's not, abort the process.
@@ -36,7 +32,8 @@ public class InspectCommand implements CommandExecutor {
                     return true;
                 }
 
-                if (sender instanceof Player && !sender.hasPermission("mcmmo.commands.inspect.offline")) {
+                // TODO: Why do we care if this is a player?
+                if (sender instanceof Player && !Permissions.inspectOffline(sender)) {
                     sender.sendMessage(LocaleLoader.getString("Inspect.Offline"));
                     return true;
                 }
@@ -67,7 +64,7 @@ public class InspectCommand implements CommandExecutor {
                 if (sender instanceof Player) {
                     Player inspector = (Player) sender;
 
-                    if (!Misc.isNear(inspector.getLocation(), target.getLocation(), 5.0) && !inspector.hasPermission("mcmmo.commands.inspect.far")) {
+                    if (!Misc.isNear(inspector.getLocation(), target.getLocation(), 5.0) && !Permissions.inspectFar(inspector)) {
                         sender.sendMessage(LocaleLoader.getString("Inspect.TooFar"));
                         return true;
                     }

+ 3 - 2
src/main/java/com/gmail/nossr50/commands/player/McabilityCommand.java

@@ -8,6 +8,7 @@ import org.bukkit.entity.Player;
 import com.gmail.nossr50.datatypes.McMMOPlayer;
 import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.locale.LocaleLoader;
+import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.Users;
 
 public class McabilityCommand implements CommandExecutor {
@@ -17,7 +18,7 @@ public class McabilityCommand implements CommandExecutor {
 
         switch (args.length) {
         case 0:
-            if (!sender.hasPermission("mcmmo.commands.mcability")) {
+            if (!Permissions.mcability(sender)) {
                 sender.sendMessage(command.getPermissionMessage());
                 return true;
             }
@@ -35,7 +36,7 @@ public class McabilityCommand implements CommandExecutor {
             return true;
 
         case 1:
-            if (!sender.hasPermission("mcmmo.commands.mcability.others")) {
+            if (!Permissions.mcabilityOthers(sender)) {
                 sender.sendMessage(command.getPermissionMessage());
                 return true;
             }

+ 17 - 10
src/main/java/com/gmail/nossr50/commands/player/McmmoCommand.java

@@ -10,6 +10,8 @@ import org.getspout.spoutapi.player.SpoutPlayer;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.locale.LocaleLoader;
+import com.gmail.nossr50.party.commands.PartySubcommandType;
+import com.gmail.nossr50.util.Permissions;
 
 public class McmmoCommand implements CommandExecutor {
     @Override
@@ -17,6 +19,11 @@ public class McmmoCommand implements CommandExecutor {
 
         switch (args.length) {
         case 0:
+            if (!Permissions.mcmmoDescription(sender)) {
+                sender.sendMessage(command.getPermissionMessage());
+                return true;
+            }
+
             String description = LocaleLoader.getString("mcMMO.Description");
             String[] mcSplit = description.split(",");
             sender.sendMessage(mcSplit);
@@ -36,7 +43,7 @@ public class McmmoCommand implements CommandExecutor {
 
         case 1:
             if (args[0].equalsIgnoreCase("?") || args[0].equalsIgnoreCase("help") || args[0].equalsIgnoreCase("commands")) {
-                if (!sender.hasPermission("mcmmo.commands.mcmmo.help")) {
+                if (!Permissions.mcmmoHelp(sender)) {
                     sender.sendMessage(command.getPermissionMessage());
                     return true;
                 }
@@ -54,20 +61,20 @@ public class McmmoCommand implements CommandExecutor {
     }
 
     private void displayPartyCommands(CommandSender sender) {
-        if (sender.hasPermission("mcmmo.commands.party")) {
+        if (Permissions.party(sender)) {
             sender.sendMessage(LocaleLoader.getString("Commands.Party.Commands"));
             sender.sendMessage("/party create <" + LocaleLoader.getString("Commands.Usage.PartyName") + "> " + LocaleLoader.getString("Commands.Party1"));
             sender.sendMessage("/party join <" + LocaleLoader.getString("Commands.Usage.Player") + "> " + LocaleLoader.getString("Commands.Party2"));
             sender.sendMessage("/party quit " + LocaleLoader.getString("Commands.Party.Quit"));
 
-            if (sender.hasPermission("mcmmo.chat.party")) {
+            if (Permissions.partyChat(sender)) {
                 sender.sendMessage("/party chat " + LocaleLoader.getString("Commands.Party.Toggle"));
             }
 
             sender.sendMessage("/party invite <" + LocaleLoader.getString("Commands.Usage.Player") + "> " + LocaleLoader.getString("Commands.Party.Invite"));
             sender.sendMessage("/party accept " + LocaleLoader.getString("Commands.Party.Accept"));
 
-            if (sender.hasPermission("mcmmo.commands.ptp")) {
+            if (Permissions.partySubcommand(sender, PartySubcommandType.TELEPORT)) {
                 sender.sendMessage("/party teleport " + LocaleLoader.getString("Commands.Party.Teleport"));
             }
         }
@@ -78,27 +85,27 @@ public class McmmoCommand implements CommandExecutor {
         sender.sendMessage("/mcstats " + LocaleLoader.getString("Commands.Stats"));
         sender.sendMessage("/mctop " + LocaleLoader.getString("Commands.Leaderboards"));
 
-        if (sender.hasPermission("mcmmo.commands.skillreset")) {
+        if (Permissions.skillreset(sender)) {
             sender.sendMessage("/skillreset <skill|all> " + LocaleLoader.getString("Commands.Reset"));
         }
 
-        if (sender.hasPermission("mcmmo.commands.mcability")) {
+        if (Permissions.mcability(sender)) {
             sender.sendMessage("/mcability " + LocaleLoader.getString("Commands.ToggleAbility"));
         }
 
-        if (sender.hasPermission("mcmmo.chat.admin")) {
+        if (Permissions.adminChat(sender)) {
             sender.sendMessage("/adminchat " + LocaleLoader.getString("Commands.AdminToggle"));
         }
 
-        if (sender.hasPermission("mcmmo.commands.inspect")) {
+        if (Permissions.inspect(sender)) {
             sender.sendMessage("/inspect " + LocaleLoader.getString("Commands.Inspect"));
         }
 
-        if (sender.hasPermission("mcmmo.commands.mmoedit")) {
+        if (Permissions.mmoedit(sender)) {
             sender.sendMessage("/mmoedit " + LocaleLoader.getString("Commands.mmoedit"));
         }
 
-        if (sender.hasPermission("mcmmo.commands.mcgod")) {
+        if (Permissions.mcgod(sender)) {
             sender.sendMessage("/mcgod " + LocaleLoader.getString("Commands.mcgod"));
         }
 

+ 5 - 4
src/main/java/com/gmail/nossr50/commands/player/McrankCommand.java

@@ -16,6 +16,7 @@ import com.gmail.nossr50.runnables.McRankAsync;
 import com.gmail.nossr50.skills.utilities.SkillTools;
 import com.gmail.nossr50.skills.utilities.SkillType;
 import com.gmail.nossr50.util.Misc;
+import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.Users;
 
 public class McrankCommand implements CommandExecutor {
@@ -23,7 +24,7 @@ public class McrankCommand implements CommandExecutor {
     public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
         switch (args.length) {
         case 0:
-            if (!sender.hasPermission("mcmmo.commands.mcrank")) {
+            if (!Permissions.mcrank(sender)) {
                 sender.sendMessage(command.getPermissionMessage());
                 return true;
             }
@@ -43,7 +44,7 @@ public class McrankCommand implements CommandExecutor {
             return true;
 
         case 1:
-            if (!sender.hasPermission("mcmmo.commands.mcrank.others")) {
+            if (!Permissions.mcrankOthers(sender)) {
                 sender.sendMessage(command.getPermissionMessage());
                 return true;
             }
@@ -58,7 +59,7 @@ public class McrankCommand implements CommandExecutor {
                     return true;
                 }
 
-                if (sender instanceof Player && !!sender.hasPermission("mcmmo.commands.mcrank.others.offline")) {
+                if (sender instanceof Player && !Permissions.mcrankOffline(sender)) {
                     sender.sendMessage(LocaleLoader.getString("Inspect.Offline"));
                     return true;
                 }
@@ -66,7 +67,7 @@ public class McrankCommand implements CommandExecutor {
             else {
                 Player target = mcMMOPlayer.getPlayer();
 
-                if (sender instanceof Player && !Misc.isNear(((Player) sender).getLocation(), target.getLocation(), 5.0) && !sender.hasPermission("mcmmo.commands.mcrank.others.far")) {
+                if (sender instanceof Player && !Misc.isNear(((Player) sender).getLocation(), target.getLocation(), 5.0) && !Permissions.mcrankFar(sender)) {
                     sender.sendMessage(LocaleLoader.getString("Inspect.TooFar"));
                     return true;
                 }

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

@@ -13,6 +13,7 @@ import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.runnables.McTopAsync;
 import com.gmail.nossr50.skills.utilities.SkillTools;
 import com.gmail.nossr50.skills.utilities.SkillType;
+import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.StringUtils;
 
 public class MctopCommand implements CommandExecutor {
@@ -72,7 +73,7 @@ public class MctopCommand implements CommandExecutor {
     }
 
     private void flatfileDisplay(int page, String skill, CommandSender sender, Command command) {
-        if (!skill.equalsIgnoreCase("all") && !sender.hasPermission("mcmmo.commands.mctop." + skill.toLowerCase())) {
+        if (!skill.equalsIgnoreCase("all") && !Permissions.mctop(sender, SkillType.getSkill(skill))) {
             sender.sendMessage(command.getPermissionMessage());
             return;
         }

+ 0 - 5
src/main/java/com/gmail/nossr50/config/Config.java

@@ -182,11 +182,6 @@ public class Config extends ConfigLoader {
     public int getHerbalismXPCarrot() { return config.getInt("Experience.Herbalism.Carrot", 50); }
     public int getHerbalismXPPotato() { return config.getInt("Experience.Herbalism.Potato", 50); }
 
-    public boolean getHerbalismGreenThumbCobbleToMossy() { return config.getBoolean("Skills.Herbalism.Green_Thumb.Cobble_To_Mossy", true); }
-    public boolean getHerbalismGreenThumbCobbleWallToMossyWall() { return config.getBoolean("Skills.Herbalism.Green_Thumb.CobbleWall_To_MossyWall", true); }
-    public boolean getHerbalismGreenThumbSmoothbrickToMossy() { return config.getBoolean("Skills.Herbalism.Green_Thumb.SmoothBrick_To_MossyBrick", true); }
-    public boolean getHerbalismGreenThumbDirtToGrass() { return config.getBoolean("Skills.Herbalism.Green_Thumb.Dirt_To_Grass", true); }
-
     public boolean getBrownMushroomsDoubleDropsEnabled() { return config.getBoolean("Double_Drops.Herbalism.Brown_Mushrooms", true); }
     public boolean getCactiDoubleDropsEnabled() { return config.getBoolean("Double_Drops.Herbalism.Cacti", true); }
     public boolean getWheatDoubleDropsEnabled() { return config.getBoolean("Double_Drops.Herbalism.Wheat", true); }

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

@@ -17,6 +17,7 @@ import com.gmail.nossr50.skills.utilities.SkillTools;
 import com.gmail.nossr50.skills.utilities.SkillType;
 import com.gmail.nossr50.spout.huds.SpoutHud;
 import com.gmail.nossr50.util.Misc;
+import com.gmail.nossr50.util.Permissions;
 
 public class McMMOPlayer {
     private Player player;
@@ -50,7 +51,7 @@ public class McMMOPlayer {
                 continue;
             }
 
-            if (player.hasPermission("mcmmo.skills." + type.toString().toLowerCase())) {
+            if (Permissions.skillEnabled(player, type)) {
                 powerLevel += profile.getSkillLevel(type);
             }
         }

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

@@ -44,6 +44,7 @@ import com.gmail.nossr50.skills.woodcutting.Woodcutting;
 import com.gmail.nossr50.util.BlockChecks;
 import com.gmail.nossr50.util.ItemChecks;
 import com.gmail.nossr50.util.Misc;
+import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.Users;
 
 public class BlockListener implements Listener {
@@ -151,7 +152,7 @@ public class BlockListener implements Listener {
         /* HERBALISM */
         if (BlockChecks.canBeGreenTerra(block)) {
             /* Green Terra */
-            if (profile.getToolPreparationMode(ToolType.HOE) && player.hasPermission("mcmmo.ability.herbalism.greenterra")) {
+            if (profile.getToolPreparationMode(ToolType.HOE) && Permissions.greenTerra(player)) {
                 SkillTools.abilityCheck(player, SkillType.HERBALISM);
             }
 
@@ -159,7 +160,7 @@ 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 (player.hasPermission("mcmmo.skills.herbalism")) {
+            if (Permissions.skillEnabled(player, SkillType.HERBALISM)) {
                 Herbalism.herbalismProcCheck(block, mcMMOPlayer, plugin); //Double drops
 
                 if (profile.getAbilityMode(AbilityType.GREEN_TERRA)) {
@@ -169,7 +170,7 @@ public class BlockListener implements Listener {
         }
 
         /* MINING */
-        else if (BlockChecks.canBeSuperBroken(block) && ItemChecks.isPickaxe(heldItem) && player.hasPermission("mcmmo.skills.mining") && !mcMMO.placeStore.isTrue(block)) {
+        else if (BlockChecks.canBeSuperBroken(block) && ItemChecks.isPickaxe(heldItem) && Permissions.skillEnabled(player, SkillType.MINING) && !mcMMO.placeStore.isTrue(block)) {
             MiningManager miningManager = new MiningManager(mcMMOPlayer);
             miningManager.miningBlockCheck(block);
 
@@ -179,8 +180,8 @@ public class BlockListener implements Listener {
         }
 
         /* WOOD CUTTING */
-        else if (BlockChecks.isLog(block) && player.hasPermission("mcmmo.skills.woodcutting") && !mcMMO.placeStore.isTrue(block)) {
-            if (profile.getAbilityMode(AbilityType.TREE_FELLER) && player.hasPermission("mcmmo.ability.woodcutting.treefeller") && ItemChecks.isAxe(heldItem)) {
+        else if (BlockChecks.isLog(block) && Permissions.skillEnabled(player, SkillType.WOODCUTTING) && !mcMMO.placeStore.isTrue(block)) {
+            if (profile.getAbilityMode(AbilityType.TREE_FELLER) && Permissions.treeFeller(player) && ItemChecks.isAxe(heldItem)) {
                 Woodcutting.beginTreeFeller(mcMMOPlayer, block);
             }
             else {
@@ -196,7 +197,7 @@ public class BlockListener implements Listener {
         }
 
         /* EXCAVATION */
-        else if (BlockChecks.canBeGigaDrillBroken(block) && ItemChecks.isShovel(heldItem) && player.hasPermission("mcmmo.skills.excavation") && !mcMMO.placeStore.isTrue(block)) {
+        else if (BlockChecks.canBeGigaDrillBroken(block) && ItemChecks.isShovel(heldItem) && Permissions.skillEnabled(player, SkillType.EXCAVATION) && !mcMMO.placeStore.isTrue(block)) {
             Excavation.excavationProcCheck(block, mcMMOPlayer);
 
             if (profile.getAbilityMode(AbilityType.GIGA_DRILL_BREAKER)) {
@@ -230,10 +231,10 @@ public class BlockListener implements Listener {
         Block block = event.getBlock();
         ItemStack heldItem = player.getItemInHand();
 
-        if (player.hasPermission("mcmmo.ability.herbalism.hylianluck") && ItemChecks.isSword(heldItem)) {
+        if (Permissions.hylianLuck(player) && ItemChecks.isSword(heldItem)) {
             Herbalism.hylianLuck(block, player, event);
         }
-        else if (BlockChecks.canBeFluxMined(block) && ItemChecks.isPickaxe(heldItem) && !heldItem.containsEnchantment(Enchantment.SILK_TOUCH) && player.hasPermission("mcmmo.ability.smelting.fluxmining") && !mcMMO.placeStore.isTrue(block)) {
+        else if (BlockChecks.canBeFluxMined(block) && ItemChecks.isPickaxe(heldItem) && !heldItem.containsEnchantment(Enchantment.SILK_TOUCH) && Permissions.fluxMining(player) && !mcMMO.placeStore.isTrue(block)) {
             SmeltingManager smeltingManager = new SmeltingManager(Users.getPlayer(player));
             smeltingManager.fluxMining(event);
         }
@@ -278,19 +279,19 @@ public class BlockListener implements Listener {
                 }
             }
 
-            if (profile.getToolPreparationMode(ToolType.HOE) && ItemChecks.isHoe(heldItem) && (BlockChecks.canBeGreenTerra(block) || BlockChecks.canMakeMossy(block)) && player.hasPermission("mcmmo.ability.herbalism.greenterra")) {
+            if (profile.getToolPreparationMode(ToolType.HOE) && ItemChecks.isHoe(heldItem) && (BlockChecks.canBeGreenTerra(block) || BlockChecks.canMakeMossy(block)) && Permissions.greenTerra(player)) {
                 SkillTools.abilityCheck(player, SkillType.HERBALISM);
             }
-            else if (profile.getToolPreparationMode(ToolType.AXE) && ItemChecks.isAxe(heldItem) && BlockChecks.isLog(block) && player.hasPermission("mcmmo.ability.woodcutting.treefeller")) {
+            else if (profile.getToolPreparationMode(ToolType.AXE) && ItemChecks.isAxe(heldItem) && BlockChecks.isLog(block) && Permissions.treeFeller(player)) {
                 SkillTools.abilityCheck(player, SkillType.WOODCUTTING);
             }
-            else if (profile.getToolPreparationMode(ToolType.PICKAXE) && ItemChecks.isPickaxe(heldItem) && BlockChecks.canBeSuperBroken(block) && player.hasPermission("mcmmo.ability.mining.superbreaker")) {
+            else if (profile.getToolPreparationMode(ToolType.PICKAXE) && ItemChecks.isPickaxe(heldItem) && BlockChecks.canBeSuperBroken(block) && Permissions.superBreaker(player)) {
                 SkillTools.abilityCheck(player, SkillType.MINING);
             }
-            else if (profile.getToolPreparationMode(ToolType.SHOVEL) && ItemChecks.isShovel(heldItem) && BlockChecks.canBeGigaDrillBroken(block) && player.hasPermission("mcmmo.ability.excavation.gigadrillbreaker")) {
+            else if (profile.getToolPreparationMode(ToolType.SHOVEL) && ItemChecks.isShovel(heldItem) && BlockChecks.canBeGigaDrillBroken(block) && Permissions.gigaDrillBreaker(player)) {
                 SkillTools.abilityCheck(player, SkillType.EXCAVATION);
             }
-            else if (profile.getToolPreparationMode(ToolType.FISTS) && heldItem.getType() == Material.AIR && (BlockChecks.canBeGigaDrillBroken(block) || block.getType() == Material.SNOW || (block.getType() == Material.SMOOTH_BRICK && block.getData() == 0x0)) && player.hasPermission("mcmmo.ability.unarmed.berserk")) {
+            else if (profile.getToolPreparationMode(ToolType.FISTS) && heldItem.getType() == Material.AIR && (BlockChecks.canBeGigaDrillBroken(block) || block.getType() == Material.SNOW || (block.getType() == Material.SMOOTH_BRICK && block.getData() == 0x0)) && Permissions.berserk(player)) {
                 SkillTools.abilityCheck(player, SkillType.UNARMED);
             }
         }
@@ -332,8 +333,7 @@ public class BlockListener implements Listener {
          *
          * We don't need to check permissions here because they've already been checked for the ability to even activate.
          */
-        // Except right here, which is for the Green Thumb activation, not the normal effect of Green Terra
-        if (profile.getAbilityMode(AbilityType.GREEN_TERRA) && BlockChecks.canMakeMossy(block) && player.hasPermission("mcmmo.ability.herbalism.greenthumbblocks")) {
+        if (profile.getAbilityMode(AbilityType.GREEN_TERRA) && BlockChecks.canMakeMossy(block)) {
             Herbalism.greenTerra(player, block);
         }
         else if (profile.getAbilityMode(AbilityType.BERSERK)) {
@@ -347,7 +347,7 @@ public class BlockListener implements Listener {
                 }
             }
             // Another perm check for the cracked blocks activation
-            else if (BlockChecks.canBeCracked(block) && player.hasPermission("mcmmo.ability.unarmed.blockcracker")) {
+            else if (BlockChecks.canBeCracked(block) && Permissions.blockCracker(player)) {
                 Unarmed.blockCracker(player, block);
             }
         }

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

@@ -77,7 +77,7 @@ public class PlayerListener implements Listener {
             return;
         }
 
-        if (!Permissions.hardcoremodeBypass(player)) {
+        if (!Permissions.hardcoreBypass(player)) {
             Player killer = player.getKiller();
 
             if (killer != null && Config.getInstance().getHardcoreVampirismEnabled()) {
@@ -157,7 +157,7 @@ public class PlayerListener implements Listener {
     public void onPlayerFish(PlayerFishEvent event) {
         Player player = event.getPlayer();
 
-        if (Misc.isNPCEntity(player) || !Permissions.fishing(player)) {
+        if (Misc.isNPCEntity(player) || !Permissions.skillEnabled(player, SkillType.FISHING)) {
             return;
         }
 
@@ -172,7 +172,7 @@ public class PlayerListener implements Listener {
         case CAUGHT_ENTITY:
             Entity entity = event.getCaught();
 
-            if (entity instanceof LivingEntity && skillLevel >= AdvancedConfig.getInstance().getShakeUnlockLevel() && Permissions.shakeMob(player)) {
+            if (entity instanceof LivingEntity && skillLevel >= AdvancedConfig.getInstance().getShakeUnlockLevel() && Permissions.shake(player)) {
                 Fishing.beginShakeMob(player, (LivingEntity) entity, skillLevel);
             }
 
@@ -237,7 +237,7 @@ public class PlayerListener implements Listener {
             player.sendMessage(LocaleLoader.getString("XPRate.Event", Config.getInstance().getExperienceGainsGlobalMultiplier()));
         }
 
-        if (player.hasPermission("mcmmo.tools.updatecheck") && mcMMO.p.updateAvailable) {
+        if (Permissions.updateNotifications(player) && mcMMO.p.updateAvailable) {
             player.sendMessage(LocaleLoader.getString("UpdateChecker.outdated"));
             player.sendMessage(LocaleLoader.getString("UpdateChecker.newavailable"));
         }
@@ -279,7 +279,7 @@ public class PlayerListener implements Listener {
             int blockID = block.getTypeId();
 
             /* REPAIR CHECKS */
-            if (blockID == Repair.anvilID && Permissions.repair(player) && mcMMO.repairManager.isRepairable(heldItem)) {
+            if (blockID == Repair.anvilID && Permissions.skillEnabled(player, SkillType.REPAIR) && mcMMO.repairManager.isRepairable(heldItem)) {
                 mcMMO.repairManager.handleRepair(Users.getPlayer(player), heldItem);
                 event.setCancelled(true);
                 player.updateInventory();
@@ -291,7 +291,7 @@ public class PlayerListener implements Listener {
                 player.updateInventory();
             }
             /* BLAST MINING CHECK */
-            else if (player.isSneaking() && Permissions.blastMining(player) && heldItem.getTypeId() == BlastMining.detonatorID) {
+            else if (player.isSneaking() && Permissions.remoteDetonation(player) && heldItem.getTypeId() == BlastMining.detonatorID) {
                 MiningManager miningManager = new MiningManager(Users.getPlayer(player));
                 miningManager.detonate(event);
             }
@@ -300,7 +300,7 @@ public class PlayerListener implements Listener {
 
         case RIGHT_CLICK_AIR:
             /* BLAST MINING CHECK */
-            if (player.isSneaking() && Permissions.blastMining(player) && heldItem.getTypeId() == BlastMining.detonatorID) {
+            if (player.isSneaking() && Permissions.remoteDetonation(player) && heldItem.getTypeId() == BlastMining.detonatorID) {
                 MiningManager miningManager = new MiningManager(Users.getPlayer(player));
                 miningManager.detonate(event);
             }
@@ -350,7 +350,7 @@ public class PlayerListener implements Listener {
             }
 
             /* GREEN THUMB CHECK */
-            if (heldItem.getType() == Material.SEEDS && BlockChecks.canMakeMossy(block) && Permissions.greenThumbBlocks(player)) {
+            if (heldItem.getType() == Material.SEEDS && BlockChecks.canMakeMossy(block)) {
                 Herbalism.greenThumbBlocks(heldItem, player, block);
             }
 

+ 0 - 5
src/main/java/com/gmail/nossr50/party/commands/PartyAcceptCommand.java

@@ -16,11 +16,6 @@ public class PartyAcceptCommand implements CommandExecutor {
 
     @Override
     public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
-        if (!sender.hasPermission("mcmmo.commands.party.accept")) {
-            sender.sendMessage(command.getPermissionMessage());
-            return true;
-        }
-
         switch (args.length) {
         case 1:
             player = (Player) sender;

+ 0 - 5
src/main/java/com/gmail/nossr50/party/commands/PartyChangeOwnerCommand.java

@@ -14,11 +14,6 @@ import com.gmail.nossr50.util.Users;
 public class PartyChangeOwnerCommand implements CommandExecutor {
     @Override
     public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
-        if (!sender.hasPermission("mcmmo.commands.party.owner")) {
-            sender.sendMessage(command.getPermissionMessage());
-            return true;
-        }
-
         switch (args.length) {
         case 2:
             Party playerParty = Users.getPlayer((Player) sender).getParty();

+ 1 - 5
src/main/java/com/gmail/nossr50/party/commands/PartyChangePasswordCommand.java

@@ -13,12 +13,8 @@ public class PartyChangePasswordCommand implements CommandExecutor {
 
     @Override
     public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
-        if (!sender.hasPermission("mcmmo.commands.party.password")) {
-            sender.sendMessage(command.getPermissionMessage());
-            return true;
-        }
-
         Party playerParty = Users.getPlayer((Player) sender).getParty();
+
         switch (args.length) {
         case 1:
             unprotectParty(sender, playerParty);

+ 8 - 1
src/main/java/com/gmail/nossr50/party/commands/PartyCommand.java

@@ -9,6 +9,7 @@ import com.gmail.nossr50.chat.commands.PartyChatCommand;
 import com.gmail.nossr50.commands.CommandHelper;
 import com.gmail.nossr50.datatypes.McMMOPlayer;
 import com.gmail.nossr50.locale.LocaleLoader;
+import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.Users;
 
 public class PartyCommand implements CommandExecutor {
@@ -39,7 +40,7 @@ public class PartyCommand implements CommandExecutor {
             return true;
         }
 
-        if (!sender.hasPermission("mcmmo.commands.party")) {
+        if (!Permissions.party(sender)) {
             sender.sendMessage(command.getPermissionMessage());
             return true;
         }
@@ -62,6 +63,12 @@ public class PartyCommand implements CommandExecutor {
             return printUsage();
         }
 
+        // Can't use this for lock/unlock since they're handled by the same command
+        if (subcommand != PartySubcommandType.LOCK && subcommand != PartySubcommandType.UNLOCK && !Permissions.partySubcommand(sender, subcommand)) {
+            sender.sendMessage(command.getPermissionMessage());
+            return true;
+        }
+
         switch (subcommand) {
         case JOIN:
             return partyJoinCommand.onCommand(sender, command, label, args);

+ 0 - 5
src/main/java/com/gmail/nossr50/party/commands/PartyCreateCommand.java

@@ -17,11 +17,6 @@ public class PartyCreateCommand implements CommandExecutor {
 
     @Override
     public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
-        if (!sender.hasPermission("mcmmo.commands.party.create")) {
-            sender.sendMessage(command.getPermissionMessage());
-            return true;
-        }
-
         switch (args.length) {
         case 2:
         case 3:

+ 0 - 5
src/main/java/com/gmail/nossr50/party/commands/PartyDisbandCommand.java

@@ -14,11 +14,6 @@ import com.gmail.nossr50.util.Users;
 public class PartyDisbandCommand implements CommandExecutor {
     @Override
     public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
-        if (!sender.hasPermission("mcmmo.commands.party.disband")) {
-            sender.sendMessage(command.getPermissionMessage());
-            return true;
-        }
-
         switch (args.length) {
         case 1:
             Party playerParty = Users.getPlayer((Player) sender).getParty();

+ 0 - 5
src/main/java/com/gmail/nossr50/party/commands/PartyExpShareCommand.java

@@ -23,11 +23,6 @@ public class PartyExpShareCommand implements CommandExecutor {
             return true;
         }
 
-        if (!sender.hasPermission("mcmmo.commands.party.expshare")) {
-            sender.sendMessage(command.getPermissionMessage());
-            return true;
-        }
-
         switch (args.length) {
         case 2:
             playerParty = Users.getPlayer((Player) sender).getParty();

+ 0 - 5
src/main/java/com/gmail/nossr50/party/commands/PartyInviteCommand.java

@@ -21,11 +21,6 @@ public class PartyInviteCommand implements CommandExecutor {
 
     @Override
     public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
-        if (!sender.hasPermission("mcmmo.commands.party.invite")) {
-            sender.sendMessage(command.getPermissionMessage());
-            return true;
-        }
-
         switch (args.length) {
         case 2:
             if (!mcMMO.p.getServer().getOfflinePlayer(args[1]).isOnline()) {

+ 0 - 5
src/main/java/com/gmail/nossr50/party/commands/PartyItemShareCommand.java

@@ -23,11 +23,6 @@ public class PartyItemShareCommand implements CommandExecutor {
             return true;
         }
 
-        if (!sender.hasPermission("mcmmo.commands.party.itemshare")) {
-            sender.sendMessage(command.getPermissionMessage());
-            return true;
-        }
-
         switch (args.length) {
         case 2:
             playerParty = Users.getPlayer((Player) sender).getParty();

+ 0 - 5
src/main/java/com/gmail/nossr50/party/commands/PartyJoinCommand.java

@@ -23,11 +23,6 @@ public class PartyJoinCommand implements CommandExecutor {
 
     @Override
     public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
-        if (!sender.hasPermission("mcmmo.commands.party.join")) {
-            sender.sendMessage(command.getPermissionMessage());
-            return true;
-        }
-
         switch (args.length) {
         case 2:
         case 3:

+ 0 - 5
src/main/java/com/gmail/nossr50/party/commands/PartyKickCommand.java

@@ -16,11 +16,6 @@ import com.gmail.nossr50.util.Users;
 public class PartyKickCommand implements CommandExecutor {
     @Override
     public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
-        if (!sender.hasPermission("mcmmo.commands.party.kick")) {
-            sender.sendMessage(command.getPermissionMessage());
-            return true;
-        }
-
         switch (args.length) {
         case 2:
             Party playerParty = Users.getPlayer((Player) sender).getParty();

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

@@ -7,6 +7,7 @@ import org.bukkit.entity.Player;
 
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.party.Party;
+import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.Users;
 
 public class PartyLockCommand implements CommandExecutor {
@@ -55,7 +56,7 @@ public class PartyLockCommand implements CommandExecutor {
      * Handle locking a party.
      */
     private void lockParty(CommandSender sender, Command command) {
-        if (!sender.hasPermission("mcmmo.commands.party.lock")) {
+        if (!Permissions.partySubcommand(sender, PartySubcommandType.LOCK)) {
             sender.sendMessage(command.getPermissionMessage());
             return;
         }
@@ -75,7 +76,7 @@ public class PartyLockCommand implements CommandExecutor {
      * @return true if party is successfully unlocked, false otherwise.
      */
     private void unlockParty(CommandSender sender, Command command) {
-        if (!sender.hasPermission("mcmmo.commands.party.unlock")) {
+        if (!Permissions.partySubcommand(sender, PartySubcommandType.UNLOCK)) {
             sender.sendMessage(command.getPermissionMessage());
             return;
         }

+ 0 - 5
src/main/java/com/gmail/nossr50/party/commands/PartyQuitCommand.java

@@ -17,11 +17,6 @@ public class PartyQuitCommand implements CommandExecutor {
 
     @Override
     public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
-        if (!sender.hasPermission("mcmmo.commands.party.quit")) {
-            sender.sendMessage(command.getPermissionMessage());
-            return true;
-        }
-
         switch (args.length) {
         case 1:
             player = (Player) sender;

+ 0 - 5
src/main/java/com/gmail/nossr50/party/commands/PartyRenameCommand.java

@@ -15,11 +15,6 @@ public class PartyRenameCommand implements CommandExecutor {
 
     @Override
     public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
-        if (!sender.hasPermission("mcmmo.commands.party.rename")) {
-            sender.sendMessage(command.getPermissionMessage());
-            return true;
-        }
-
         Party playerParty = Users.getPlayer((Player) sender).getParty();
         String leaderName = playerParty.getLeader();
 

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

@@ -38,7 +38,7 @@ public class PtpCommand implements CommandExecutor {
             playerProfile = mcMMOPlayer.getProfile();
 
             if (args[0].equalsIgnoreCase("toggle")) {
-                if (!sender.hasPermission("mcmmo.commands.ptp.toggle")) {
+                if (!Permissions.partyTeleportToggle(sender)) {
                     sender.sendMessage(command.getPermissionMessage());
                     return true;
                 }
@@ -47,7 +47,7 @@ public class PtpCommand implements CommandExecutor {
             }
 
             if (args[0].equalsIgnoreCase("acceptany") || args[0].equalsIgnoreCase("acceptall")) {
-                if (!sender.hasPermission("mcmmo.commands.ptp.acceptall")) {
+                if (!Permissions.partyTeleportAcceptAll(sender)) {
                     sender.sendMessage(command.getPermissionMessage());
                     return true;
                 }
@@ -63,7 +63,7 @@ public class PtpCommand implements CommandExecutor {
             }
 
             if (args[0].equalsIgnoreCase("accept")) {
-                if (!sender.hasPermission("mcmmo.commands.ptp.accept")) {
+                if (!Permissions.partyTeleportAccept(sender)) {
                     sender.sendMessage(command.getPermissionMessage());
                     return true;
                 }

+ 3 - 1
src/main/java/com/gmail/nossr50/runnables/McTopAsync.java

@@ -12,6 +12,8 @@ import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.database.Database;
 import com.gmail.nossr50.locale.LocaleLoader;
+import com.gmail.nossr50.skills.utilities.SkillType;
+import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.StringUtils;
 
 public class McTopAsync implements Runnable {
@@ -31,7 +33,7 @@ public class McTopAsync implements Runnable {
     @Override
     public void run() {
         if (!query.equalsIgnoreCase("taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing")) {
-            if (!sender.hasPermission("mcmmo.commands.mctop." + query.toLowerCase())) {
+            if (!Permissions.mctop(sender, SkillType.getSkill(query))) {
                 sender.sendMessage(command.getPermissionMessage());
                 return;
             }

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

@@ -13,11 +13,12 @@ import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.skills.utilities.PerksUtils;
 import com.gmail.nossr50.skills.utilities.SkillTools;
 import com.gmail.nossr50.skills.utilities.SkillType;
+import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.StringUtils;
 import com.gmail.nossr50.util.Users;
 
 public abstract class SkillCommand implements CommandExecutor {
-    private SkillType skill;
+    protected SkillType skill;
     private String skillString;
 
     protected Player player;
@@ -49,8 +50,8 @@ public abstract class SkillCommand implements CommandExecutor {
         }
 
         skillValue = profile.getSkillLevel(skill);
-        isLucky = player.hasPermission("mcmmo.perks.lucky." + skill.toString().toLowerCase());
-        hasEndurance = (player.hasPermission("mcmmo.perks.activationtime.twelveseconds") || player.hasPermission("mcmmo.perks.activationtime.eightseconds") || player.hasPermission("mcmmo.perks.activationtime.fourseconds"));
+        isLucky = Permissions.lucky(sender, skill);
+        hasEndurance = (Permissions.twelveSecondActivationBoost(sender) || Permissions.eightSecondActivationBoost(sender) || Permissions.fourSecondActivationBoost(sender));
 
         dataCalculations();
         permissionsCheck();

+ 7 - 2
src/main/java/com/gmail/nossr50/skills/SkillManager.java

@@ -3,17 +3,18 @@ package com.gmail.nossr50.skills;
 import com.gmail.nossr50.datatypes.McMMOPlayer;
 import com.gmail.nossr50.skills.utilities.PerksUtils;
 import com.gmail.nossr50.skills.utilities.SkillType;
-import com.gmail.nossr50.util.Permissions;
 
 public abstract class SkillManager {
     protected McMMOPlayer mcMMOPlayer;
     protected int skillLevel;
     protected int activationChance;
+    protected SkillType skill;
 
     public SkillManager(McMMOPlayer mcMMOPlayer, SkillType skill) {
         this.mcMMOPlayer = mcMMOPlayer;
         this.skillLevel = mcMMOPlayer.getProfile().getSkillLevel(skill);
-        this.activationChance = PerksUtils.handleLuckyPerks(Permissions.lucky(mcMMOPlayer.getPlayer(), skill));
+        this.activationChance = PerksUtils.handleLuckyPerks(mcMMOPlayer.getPlayer(), skill);
+        this.skill = skill;
     }
 
     public McMMOPlayer getMcMMOPlayer() {
@@ -27,4 +28,8 @@ public abstract class SkillManager {
     public int getActivationChance() {
         return activationChance;
     }
+
+    public SkillType getSkill() {
+        return skill;
+    }
 }

+ 2 - 2
src/main/java/com/gmail/nossr50/skills/archery/ArcheryCommand.java

@@ -45,9 +45,9 @@ public class ArcheryCommand extends SkillCommand {
 
     @Override
     protected void permissionsCheck() {
-        canSkillShot = Permissions.archeryBonus(player);
+        canSkillShot = Permissions.bonusDamage(player, skill);
         canDaze = Permissions.daze(player);
-        canRetrieve = Permissions.trackArrows(player);
+        canRetrieve = Permissions.arrowRetrieval(player);
     }
 
     @Override

+ 1 - 1
src/main/java/com/gmail/nossr50/skills/archery/ArcheryManager.java

@@ -75,7 +75,7 @@ public class ArcheryManager extends SkillManager {
      * @param event The event to modify.
      */
     public void skillShot(EntityDamageEvent event) {
-        if (skillLevel >= Archery.skillShotIncreaseLevel && Permissions.archeryBonus(mcMMOPlayer.getPlayer())) {
+        if (skillLevel >= Archery.skillShotIncreaseLevel && Permissions.bonusDamage(mcMMOPlayer.getPlayer(), skill)) {
             SkillShotEventHandler eventHandler = new SkillShotEventHandler(this, event);
 
             eventHandler.calculateDamageBonus();

+ 3 - 3
src/main/java/com/gmail/nossr50/skills/axes/AxesCommand.java

@@ -52,9 +52,9 @@ public class AxesCommand extends SkillCommand {
     @Override
     protected void permissionsCheck() {
         canSkullSplitter = Permissions.skullSplitter(player);
-        canCritical = Permissions.criticalHit(player);
-        canBonusDamage = Permissions.axeBonus(player);
-        canImpact = Permissions.impact(player);
+        canCritical = Permissions.criticalStrikes(player);
+        canBonusDamage = Permissions.bonusDamage(player, skill);
+        canImpact = Permissions.armorImpact(player);
         canGreaterImpact = Permissions.greaterImpact(player);
     }
 

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

@@ -67,7 +67,7 @@ public class Excavation {
         Player player = mcMMOPlayer.getPlayer();
         List<ExcavationTreasure> treasures = new ArrayList<ExcavationTreasure>();
 
-        if (Permissions.excavationTreasures(player)) {
+        if (Permissions.excavationTreasureHunter(player)) {
             switch (material) {
             case DIRT:
                 treasures = TreasuresConfig.getInstance().excavationFromDirt;
@@ -105,7 +105,7 @@ public class Excavation {
 
             for (ExcavationTreasure treasure : treasures) {
                 if (mcMMOPlayer.getProfile().getSkillLevel(SkillType.EXCAVATION) >= treasure.getDropLevel()) {
-                    int activationChance = PerksUtils.handleLuckyPerks(Permissions.luckyExcavation(player));
+                    int activationChance = PerksUtils.handleLuckyPerks(player, SkillType.EXCAVATION);
 
                     if (Misc.getRandom().nextDouble() * activationChance <= treasure.getDropChance()) {
                         xp += treasure.getXp();

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

@@ -27,7 +27,7 @@ public class ExcavationCommand extends SkillCommand {
     @Override
     protected void permissionsCheck() {
         canGigaDrill = Permissions.gigaDrillBreaker(player);
-        canTreasureHunt = Permissions.excavationTreasures(player);
+        canTreasureHunt = Permissions.excavationTreasureHunter(player);
     }
 
     @Override

+ 7 - 5
src/main/java/com/gmail/nossr50/skills/fishing/Fishing.java

@@ -119,7 +119,7 @@ public final class Fishing {
             treasureXp = treasure.getXp();
             ItemStack treasureDrop = treasure.getDrop();
 
-            if (Permissions.fishingMagic(player) && beginMagicHunter(player, skillLevel, treasureDrop, player.getWorld().hasStorm())) {
+            if (Permissions.magicHunter(player) && beginMagicHunter(player, skillLevel, treasureDrop, player.getWorld().hasStorm())) {
                 player.sendMessage(LocaleLoader.getString("Fishing.MagicFound"));
             }
 
@@ -130,7 +130,9 @@ public final class Fishing {
         }
 
         mcMMOPlayer.beginXpGain(SkillType.FISHING, Config.getInstance().getFishingBaseXP() + treasureXp);
-        event.setExpToDrop(event.getExpToDrop() * getVanillaXpMultiplier(skillLevel));
+        if (Permissions.vanillaXpBoost(player, SkillType.FISHING)) {
+            event.setExpToDrop(event.getExpToDrop() * getVanillaXpMultiplier(skillLevel));
+        }
     }
 
     /**
@@ -141,7 +143,7 @@ public final class Fishing {
      * @return Chosen treasure
      */
     private static FishingTreasure checkForTreasure(Player player, int skillLevel) {
-        if (!Config.getInstance().getFishingDropsEnabled() || !Permissions.fishingTreasures(player)) {
+        if (!Config.getInstance().getFishingDropsEnabled() || !Permissions.fishingTreasureHunter(player)) {
             return null;
         }
 
@@ -161,7 +163,7 @@ public final class Fishing {
 
         FishingTreasure treasure = rewards.get(Misc.getRandom().nextInt(rewards.size()));
         ItemStack treasureDrop = treasure.getDrop();
-        int activationChance = PerksUtils.handleLuckyPerks(Permissions.luckyFishing(player));
+        int activationChance = PerksUtils.handleLuckyPerks(player, SkillType.FISHING);
 
         if (Misc.getRandom().nextDouble() * activationChance > treasure.getDropChance()) {
             return null;
@@ -190,7 +192,7 @@ public final class Fishing {
             return false;
         }
 
-        int activationChance = PerksUtils.handleLuckyPerks(Permissions.luckyFishing(player));
+        int activationChance = PerksUtils.handleLuckyPerks(player, SkillType.FISHING);
 
         if (storm) {
             activationChance = (int) (activationChance * 0.909);

+ 3 - 3
src/main/java/com/gmail/nossr50/skills/fishing/FishingCommand.java

@@ -51,9 +51,9 @@ public class FishingCommand extends SkillCommand {
 
     @Override
     protected void permissionsCheck() {
-        canTreasureHunt = Permissions.fishingTreasures(player);
-        canMagicHunt = Permissions.fishingMagic(player);
-        canShake = Permissions.shakeMob(player);
+        canTreasureHunt = Permissions.fishingTreasureHunter(player);
+        canMagicHunt = Permissions.magicHunter(player);
+        canShake = Permissions.shake(player);
         canFishermansDiet = Permissions.fishermansDiet(player);
     }
 

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

@@ -19,8 +19,8 @@ import org.bukkit.potion.PotionType;
 import com.gmail.nossr50.skills.fishing.Fishing.Tier;
 import com.gmail.nossr50.skills.utilities.CombatTools;
 import com.gmail.nossr50.skills.utilities.PerksUtils;
+import com.gmail.nossr50.skills.utilities.SkillType;
 import com.gmail.nossr50.util.Misc;
-import com.gmail.nossr50.util.Permissions;
 
 public final class ShakeMob {
     private ShakeMob() {}
@@ -33,7 +33,7 @@ public final class ShakeMob {
      * @param skillLevel Fishing level of the player
      */
     public static void process(Player player, LivingEntity mob, int skillLevel) {
-        int activationChance = PerksUtils.handleLuckyPerks(Permissions.luckyFishing(player));
+        int activationChance = PerksUtils.handleLuckyPerks(player, SkillType.FISHING);
 
         if (getShakeProbability(skillLevel) <= Misc.getRandom().nextInt(activationChance)) {
             return;

+ 13 - 18
src/main/java/com/gmail/nossr50/skills/herbalism/Herbalism.java

@@ -50,11 +50,6 @@ public class Herbalism {
     public static double hylianLuckMaxChance = AdvancedConfig.getInstance().getHylianLuckChanceMax();
     public static int hylianLuckMaxLevel = AdvancedConfig.getInstance().getHylianLucksMaxLevel();
 
-    public static boolean greenTerraWalls = Config.getInstance().getHerbalismGreenThumbCobbleWallToMossyWall();
-    public static boolean greenTerraSmoothBrick = Config.getInstance().getHerbalismGreenThumbSmoothbrickToMossy();
-    public static boolean greenTerraDirt = Config.getInstance().getHerbalismGreenThumbDirtToGrass();
-    public static boolean greenTerraCobble = Config.getInstance().getHerbalismGreenThumbCobbleToMossy();
-
     /**
      * Handle the farmers diet skill.
      *
@@ -94,27 +89,27 @@ public class Herbalism {
         if (SkillTools.blockBreakSimulate(block, player, false)) {
             Material type = block.getType();
 
+            if (!Permissions.greenThumbBlock(player, type)) {
+                return;
+            }
+
             switch (type) {
             case SMOOTH_BRICK:
-                if (greenTerraSmoothBrick && block.getData() == 0x0) {
+                if (block.getData() == 0x0) {
                     block.setData((byte) 0x1);
                 }
                 return;
 
             case DIRT:
-                if (greenTerraDirt) {
-                    block.setType(Material.GRASS);
-                }
+                block.setType(Material.GRASS);
                 return;
 
             case COBBLESTONE:
-                if (greenTerraCobble) {
-                    block.setType(Material.MOSSY_COBBLESTONE);
-                }
+                block.setType(Material.MOSSY_COBBLESTONE);
                 return;
 
             case COBBLE_WALL:
-                if (greenTerraWalls && block.getData() == 0x0) {
+                if (block.getData() == 0x0) {
                     block.setData((byte) 0x1);
                 }
                 return;
@@ -190,8 +185,8 @@ public class Herbalism {
             xp = customBlock.getXpGain();
         }
 
-        if (Permissions.herbalismDoubleDrops(player)) {
-            int activationChance = PerksUtils.handleLuckyPerks(Permissions.luckyHerbalism(player));
+        if (Permissions.doubleDrops(player, SkillType.HERBALISM)) {
+            int activationChance = PerksUtils.handleLuckyPerks(player, SkillType.HERBALISM);
             double chance = (doubleDropsMaxChance / doubleDropsMaxLevel) * SkillTools.skillCheck(herbLevel, doubleDropsMaxLevel);
 
             if (chance > Misc.getRandom().nextInt(activationChance)) {
@@ -255,7 +250,7 @@ public class Herbalism {
             return;
         }
 
-        int activationChance = PerksUtils.handleLuckyPerks(Permissions.luckyHerbalism(player));
+        int activationChance = PerksUtils.handleLuckyPerks(player, SkillType.HERBALISM);
         float chance = (float) (greenThumbMaxChance / greenThumbMaxLevel * herbLevel);
 
         if (chance > greenThumbMaxChance) {
@@ -302,7 +297,7 @@ public class Herbalism {
 
         player.setItemInHand(new ItemStack(Material.SEEDS, seeds - 1));
 
-        int activationChance = PerksUtils.handleLuckyPerks(Permissions.luckyHerbalism(player));
+        int activationChance = PerksUtils.handleLuckyPerks(player, SkillType.HERBALISM);
 
         float chance = (float) ((greenThumbMaxChance / greenThumbMaxLevel) * skillLevel);
         if (chance > greenThumbMaxChance) chance = (float) greenThumbMaxChance;
@@ -319,7 +314,7 @@ public class Herbalism {
         int skillLevel = Users.getPlayer(player).getProfile().getSkillLevel(SkillType.HERBALISM);
 
         double chance = (hylianLuckMaxChance / hylianLuckMaxLevel) * SkillTools.skillCheck(skillLevel, hylianLuckMaxLevel);
-        int activationChance = PerksUtils.handleLuckyPerks(Permissions.luckyHerbalism(player));
+        int activationChance = PerksUtils.handleLuckyPerks(player, SkillType.HERBALISM);
 
         if (chance > Misc.getRandom().nextInt(activationChance)) {
             List<HylianTreasure> treasures = new ArrayList<HylianTreasure>();

+ 1 - 14
src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismBlock.java

@@ -69,20 +69,7 @@ public enum HerbalismBlock {
     }
 
     public boolean hasGreenThumbPermission(Player player) {
-        switch (this) {
-        case CARROT:
-            return Permissions.greenThumbCarrots(player);
-        case COCOA:
-            return Permissions.greenThumbCocoa(player);
-        case CROPS:
-            return Permissions.greenThumbWheat(player);
-        case POTATO:
-            return Permissions.greenThumbPotatoes(player);
-        case NETHER_WARTS:
-            return Permissions.greenThumbNetherwart(player);
-        default:
-            return false;
-        }
+        return Permissions.greenThumbPlant(player, blockType);
     }
 
     public static HerbalismBlock getHerbalismBlock(Material blockType) {

+ 5 - 3
src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismCommand.java

@@ -1,5 +1,7 @@
 package com.gmail.nossr50.skills.herbalism;
 
+import org.bukkit.Material;
+
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.skills.SkillCommand;
 import com.gmail.nossr50.skills.utilities.SkillType;
@@ -61,10 +63,10 @@ public class HerbalismCommand extends SkillCommand {
     protected void permissionsCheck() {
         hasHylianLuck = Permissions.hylianLuck(player);
         canGreenTerra = Permissions.greenTerra(player);
-        canGreenThumbWheat = Permissions.greenThumbWheat(player);
-        canGreenThumbBlocks = Permissions.greenThumbBlocks(player);
+        canGreenThumbWheat = Permissions.greenThumbPlant(player, Material.CROPS); //TODO: This isn't really accurate - they could have perms for other crops but not wheat.
+        canGreenThumbBlocks = (Permissions.greenThumbBlock(player, Material.DIRT) || Permissions.greenThumbBlock(player, Material.COBBLESTONE) || Permissions.greenThumbBlock(player, Material.COBBLE_WALL) || Permissions.greenThumbBlock(player, Material.SMOOTH_BRICK));
         canFarmersDiet = Permissions.farmersDiet(player);
-        canDoubleDrop = Permissions.herbalismDoubleDrops(player);
+        canDoubleDrop = Permissions.doubleDrops(player, skill);
         doubleDropsDisabled = Herbalism.doubleDropsDisabled;
     }
 

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

@@ -88,9 +88,9 @@ public class MiningCommand extends SkillCommand {
     @Override
     protected void permissionsCheck() {
         canBiggerBombs = Permissions.biggerBombs(player);
-        canBlast = Permissions.blastMining(player);
+        canBlast = Permissions.remoteDetonation(player);
         canDemoExpert = Permissions.demolitionsExpertise(player);
-        canDoubleDrop = Permissions.miningDoubleDrops(player);
+        canDoubleDrop = Permissions.doubleDrops(player, skill);
         canSuperBreaker = Permissions.superBreaker(player);
         doubleDropsDisabled = Mining.doubleDropsDisabled;
     }

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

@@ -112,7 +112,7 @@ public class MiningManager extends SkillManager{
         MiningBlockEventHandler eventHandler = new MiningBlockEventHandler(this, block);
         eventHandler.processXPGain();
 
-        if (!Permissions.miningDoubleDrops(mcMMOPlayer.getPlayer())) {
+        if (!Permissions.doubleDrops(mcMMOPlayer.getPlayer(), skill)) {
             return;
         }
 

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

@@ -110,7 +110,7 @@ public class Repair {
         for (Entry<Enchantment, Integer> enchant : enchants.entrySet()) {
             Enchantment enchantment = enchant.getKey();
 
-            int activationChance = PerksUtils.handleLuckyPerks(Permissions.luckyRepair(player));
+            int activationChance = PerksUtils.handleLuckyPerks(player, SkillType.REPAIR);
 
             if (Misc.getRandom().nextInt(activationChance) <= getEnchantChance(rank)) {
                 int enchantLevel = enchant.getValue();
@@ -237,9 +237,9 @@ public class Repair {
         int chance = (int) ((SUPER_REPAIR_CHANCE_MAX / SUPER_REPAIR_MAX_BONUS_LEVEL) * skillLevel);
         if (skillLevel >= SUPER_REPAIR_MAX_BONUS_LEVEL) chance = (int) SUPER_REPAIR_CHANCE_MAX;
 
-        int activationChance = PerksUtils.handleLuckyPerks(Permissions.luckyRepair(player));
+        int activationChance = PerksUtils.handleLuckyPerks(player, SkillType.REPAIR);
 
-        if (chance > Misc.getRandom().nextInt(activationChance) && Permissions.repairBonus(player)) {
+        if (chance > Misc.getRandom().nextInt(activationChance) && Permissions.superRepair(player)) {
             player.sendMessage(LocaleLoader.getString("Repair.Skills.FeltEasy"));
             return true;
         }

+ 8 - 8
src/main/java/com/gmail/nossr50/skills/repair/RepairCommand.java

@@ -69,17 +69,17 @@ public class RepairCommand extends SkillCommand {
 
     @Override
     protected void permissionsCheck() {
-        canSuperRepair = Permissions.repairBonus(player);
+        canSuperRepair = Permissions.superRepair(player);
         canMasterRepair = Permissions.repairMastery(player);
         canArcaneForge = Permissions.arcaneForging(player);
         canSalvage = Permissions.salvage(player);
-        canRepairDiamond = Permissions.diamondRepair(player);
-        canRepairGold = Permissions.goldRepair(player);
-        canRepairIron = Permissions.ironRepair(player);
-        canRepairStone = Permissions.stoneRepair(player);
-        canRepairString = Permissions.stringRepair(player);
-        canRepairLeather = Permissions.leatherRepair(player);
-        canRepairWood = Permissions.woodRepair(player);
+        canRepairDiamond = Permissions.repairDiamond(player);
+        canRepairGold = Permissions.repairGold(player);
+        canRepairIron = Permissions.repairIron(player);
+        canRepairStone = Permissions.repairStone(player);
+        canRepairString = Permissions.repairString(player);
+        canRepairLeather = Permissions.repairLeather(player);
+        canRepairWood = Permissions.repairWood(player);
         arcaneBypass = Permissions.arcaneBypass(player);
     }
 

+ 3 - 3
src/main/java/com/gmail/nossr50/skills/repair/RepairItemType.java

@@ -18,13 +18,13 @@ public enum RepairItemType {
     public boolean getPermissions(Player player) {
         switch (this) {
         case ARMOR:
-            return Permissions.armorRepair(player);
+            return Permissions.repairArmor(player);
 
         case TOOL:
-            return Permissions.toolRepair(player);
+            return Permissions.repairTools(player);
 
         case OTHER:
-            return Permissions.otherRepair(player);
+            return Permissions.repairOtherItems(player);
 
         default:
             return false;

+ 8 - 8
src/main/java/com/gmail/nossr50/skills/repair/RepairMaterialType.java

@@ -23,28 +23,28 @@ public enum RepairMaterialType {
     public boolean getPermissions(Player player) {
         switch (this) {
         case STRING:
-            return Permissions.stringRepair(player);
+            return Permissions.repairString(player);
 
         case LEATHER:
-            return Permissions.leatherRepair(player);
+            return Permissions.repairLeather(player);
 
         case WOOD:
-            return Permissions.woodRepair(player);
+            return Permissions.repairWood(player);
 
         case STONE:
-            return Permissions.stoneRepair(player);
+            return Permissions.repairStone(player);
 
         case IRON:
-            return Permissions.ironRepair(player);
+            return Permissions.repairIron(player);
 
         case GOLD:
-            return Permissions.goldRepair(player);
+            return Permissions.repairGold(player);
 
         case DIAMOND:
-            return Permissions.diamondRepair(player);
+            return Permissions.repairDiamond(player);
 
         case OTHER:
-            return Permissions.otherMaterialRepair(player);
+            return Permissions.repairOtherMaterials(player);
 
         default:
             return false;

+ 1 - 1
src/main/java/com/gmail/nossr50/skills/smelting/FluxMiningEventHandler.java

@@ -51,7 +51,7 @@ public class FluxMiningEventHandler {
 
         McMMOPlayer mcMMOPlayer = manager.getMcMMOPlayer();
 
-        if (Permissions.secondSmelt(mcMMOPlayer.getPlayer())) {
+        if (Permissions.doubleDrops(mcMMOPlayer.getPlayer(), manager.getSkill())) {
             int chance = (int) ((Mining.doubleDropsMaxChance / Mining.doubleDropsMaxLevel) * (SkillTools.skillCheck(mcMMOPlayer.getProfile().getSkillLevel(SkillType.MINING), Mining.doubleDropsMaxLevel)));
             Misc.randomDropItem(location, item, chance);
         }

+ 2 - 2
src/main/java/com/gmail/nossr50/skills/smelting/SmeltResourceEventHandler.java

@@ -67,11 +67,11 @@ public class SmeltResourceEventHandler {
         McMMOPlayer mcMMOPlayer = manager.getMcMMOPlayer();
         Player player = mcMMOPlayer.getPlayer();
 
-        if (Permissions.mining(player)) {
+        if (Permissions.skillEnabled(player, SkillType.MINING)) {
             mcMMOPlayer.beginXpGain(SkillType.MINING, xp / 2);
         }
 
-        if (Permissions.repair(player)) {
+        if (Permissions.skillEnabled(player, SkillType.REPAIR)) {
             mcMMOPlayer.beginXpGain(SkillType.REPAIR, xp / 2);
         }
     }

+ 2 - 2
src/main/java/com/gmail/nossr50/skills/smelting/SmeltingCommand.java

@@ -58,9 +58,9 @@ public class SmeltingCommand extends SkillCommand {
     @Override
     protected void permissionsCheck() {
         canFuelEfficiency = Permissions.fuelEfficiency(player);
-        canSecondSmelt = Permissions.secondSmelt(player);
+        canSecondSmelt = Permissions.doubleDrops(player, skill);
         canFluxMine = Permissions.fluxMining(player);
-        canVanillaXPBoost = Permissions.smeltingVanillaXPBoost(player);
+        canVanillaXPBoost = Permissions.vanillaXpBoost(player, skill);
     }
 
     @Override

+ 3 - 3
src/main/java/com/gmail/nossr50/skills/smelting/SmeltingManager.java

@@ -44,11 +44,11 @@ public class SmeltingManager extends SkillManager {
 
         SmeltResourceEventHandler eventHandler = new SmeltResourceEventHandler(this, event);
 
-        if (Permissions.smelting(player)) {
+        if (Permissions.skillEnabled(player, skill)) {
             eventHandler.handleXPGain();
         }
 
-        if (!Permissions.secondSmelt(player)) {
+        if (!Permissions.doubleDrops(player, skill)) {
             return;
         }
 
@@ -74,7 +74,7 @@ public class SmeltingManager extends SkillManager {
     }
 
     public void vanillaXPBoost(FurnaceExtractEvent event) {
-        if (skillLevel < Smelting.vanillaXPBoostRank1Level || !Permissions.smeltingVanillaXPBoost(mcMMOPlayer.getPlayer())) {
+        if (skillLevel < Smelting.vanillaXPBoostRank1Level || !Permissions.vanillaXpBoost(mcMMOPlayer.getPlayer(), skill)) {
             return;
         }
 

+ 1 - 1
src/main/java/com/gmail/nossr50/skills/swords/SwordsCommand.java

@@ -49,7 +49,7 @@ public class SwordsCommand extends SkillCommand {
 
     @Override
     protected void permissionsCheck() {
-        canBleed = Permissions.swordsBleed(player);
+        canBleed = Permissions.bleed(player);
         canCounter = Permissions.counterAttack(player);
         canSerratedStrike = Permissions.serratedStrikes(player);
     }

+ 2 - 2
src/main/java/com/gmail/nossr50/skills/unarmed/UnarmedCommand.java

@@ -60,8 +60,8 @@ public class UnarmedCommand extends SkillCommand {
     @Override
     protected void permissionsCheck() {
         canBerserk = Permissions.berserk(player);
-        canBonusDamage = Permissions.unarmedBonus(player);
-        canDeflect = Permissions.deflect(player);
+        canBonusDamage = Permissions.bonusDamage(player, skill);
+        canDeflect = Permissions.arrowDeflect(player);
         canDisarm = Permissions.disarm(player);
         canIronGrip = Permissions.ironGrip(player);
     }

+ 1 - 1
src/main/java/com/gmail/nossr50/skills/unarmed/UnarmedManager.java

@@ -87,7 +87,7 @@ public class UnarmedManager extends SkillManager {
 
         double chance = (Unarmed.ironGripMaxChance / Unarmed.ironGripMaxBonusLevel) * eventHandler.skillModifier;
 
-        if (chance > Misc.getRandom().nextInt(PerksUtils.handleLuckyPerks(Permissions.luckyUnarmed(defender)))) {
+        if (chance > Misc.getRandom().nextInt(PerksUtils.handleLuckyPerks(defender, skill))) {
             eventHandler.sendAbilityMessages();
             return true;
         }

+ 1 - 1
src/main/java/com/gmail/nossr50/skills/utilities/AbilityType.java

@@ -150,7 +150,7 @@ public enum AbilityType {
             return Permissions.berserk(player);
 
         case BLAST_MINING:
-            return Permissions.blastMining(player);
+            return Permissions.remoteDetonation(player);
 
         case GIGA_DRILL_BREAKER:
             return Permissions.gigaDrillBreaker(player);

+ 12 - 12
src/main/java/com/gmail/nossr50/skills/utilities/CombatTools.java

@@ -87,7 +87,7 @@ public final class CombatTools {
                     return;
                 }
 
-                if (Permissions.swords(player)) {
+                if (Permissions.skillEnabled(player, SkillType.SWORDS)) {
                     McMMOPlayer mcMMOPlayer = Users.getPlayer(player);
                     PlayerProfile profile = mcMMOPlayer.getProfile();
                     SwordsManager swordsManager = new SwordsManager(mcMMOPlayer);
@@ -97,7 +97,7 @@ public final class CombatTools {
                         SkillTools.abilityCheck(player, SkillType.SWORDS);
                     }
 
-                    if (Permissions.swordsBleed(player)) {
+                    if (Permissions.bleed(player)) {
                         swordsManager.bleedCheck(target);
                     }
 
@@ -118,7 +118,7 @@ public final class CombatTools {
                     return;
                 }
 
-                if (Permissions.axes(player)) {
+                if (Permissions.skillEnabled(player, SkillType.AXES)) {
                     McMMOPlayer mcMMOPlayer = Users.getPlayer(player);
                     PlayerProfile profile = mcMMOPlayer.getProfile();
                     AxeManager axeManager = new AxeManager(mcMMOPlayer);
@@ -127,15 +127,15 @@ public final class CombatTools {
                         SkillTools.abilityCheck(player, SkillType.AXES);
                     }
 
-                    if (Permissions.axeBonus(player)) {
+                    if (Permissions.bonusDamage(player, axeManager.getSkill())) {
                         axeManager.bonusDamage(event);
                     }
 
-                    if (!target.isDead() && Permissions.criticalHit(player)) {
+                    if (!target.isDead() && Permissions.criticalStrikes(player)) {
                         axeManager.criticalHitCheck(event, target);
                     }
 
-                    if (!target.isDead() && Permissions.impact(player)) {
+                    if (!target.isDead() && Permissions.armorImpact(player)) {
                         axeManager.impact(event, target);
                     }
 
@@ -156,7 +156,7 @@ public final class CombatTools {
                     return;
                 }
 
-                if (Permissions.unarmed(player)) {
+                if (Permissions.skillEnabled(player, SkillType.UNARMED)) {
                     McMMOPlayer mcMMOPlayer = Users.getPlayer(player);
                     PlayerProfile profile = mcMMOPlayer.getProfile();
                     UnarmedManager unarmedManager = new UnarmedManager(mcMMOPlayer);
@@ -166,7 +166,7 @@ public final class CombatTools {
                         SkillTools.abilityCheck(player, SkillType.UNARMED);
                     }
 
-                    if (Permissions.unarmedBonus(player)) {
+                    if (Permissions.bonusDamage(player, unarmedManager.getSkill())) {
                         unarmedManager.bonusDamage(event);
                     }
 
@@ -210,7 +210,7 @@ public final class CombatTools {
                     return;
                 }
 
-                if (Permissions.taming(master)) {
+                if (Permissions.skillEnabled(master, SkillType.TAMING)) {
                     McMMOPlayer mcMMOPlayer = Users.getPlayer(master);
                     TamingManager tamingManager = new TamingManager(mcMMOPlayer);
                     int skillLevel = tamingManager.getSkillLevel();
@@ -303,13 +303,13 @@ public final class CombatTools {
             return;
         }
 
-        if (Permissions.archery(shooter)) {
+        if (Permissions.skillEnabled(shooter, SkillType.ARCHERY)) {
             McMMOPlayer mcMMOPlayer = Users.getPlayer(shooter);
             ArcheryManager archeryManager = new ArcheryManager(mcMMOPlayer);
             archeryManager.skillShot(event);
 
             if (target instanceof Player) {
-                if (Unarmed.pvpEnabled && ((Player) target).getItemInHand().getType() == Material.AIR && Permissions.deflect((Player) target)) {
+                if (Unarmed.pvpEnabled && ((Player) target).getItemInHand().getType() == Material.AIR && Permissions.arrowDeflect((Player) target)) {
                     UnarmedManager unarmedManager = new UnarmedManager(Users.getPlayer((Player) target));
                     unarmedManager.deflectCheck(event);
                 }
@@ -320,7 +320,7 @@ public final class CombatTools {
                 }
             }
 
-            if (!(shooter.getItemInHand().containsEnchantment(Enchantment.ARROW_INFINITE)) && Permissions.trackArrows(shooter)) {
+            if (!(shooter.getItemInHand().containsEnchantment(Enchantment.ARROW_INFINITE)) && Permissions.arrowRetrieval(shooter)) {
                 archeryManager.trackArrows(target);
             }
 

+ 13 - 13
src/main/java/com/gmail/nossr50/skills/utilities/PerksUtils.java

@@ -11,13 +11,13 @@ public final class PerksUtils {
     private PerksUtils() {};
 
     public static int handleCooldownPerks(Player player, int cooldown) {
-        if (Permissions.cooldownsHalved(player)) {
+        if (Permissions.halvedCooldowns(player)) {
             cooldown *= 0.5;
         }
-        else if (Permissions.cooldownsThirded(player)) {
+        else if (Permissions.thirdedCooldowns(player)) {
             cooldown *= (1.0 / 3.0);
         }
-        else if (Permissions.cooldownsQuartered(player)) {
+        else if (Permissions.quarteredCooldowns(player)) {
             cooldown *= 0.75;
         }
 
@@ -25,13 +25,13 @@ public final class PerksUtils {
     }
 
     public static int handleActivationPerks(Player player, int ticks, int maxTicks) {
-        if (Permissions.activationTwelve(player)) {
+        if (Permissions.twelveSecondActivationBoost(player)) {
             ticks += 12;
         }
-        else if (Permissions.activationEight(player)) {
+        else if (Permissions.eightSecondActivationBoost(player)) {
             ticks += 8;
         }
-        else if (Permissions.activationFour(player)) {
+        else if (Permissions.fourSecondActivationBoost(player)) {
             ticks += 4;
         }
 
@@ -43,19 +43,19 @@ public final class PerksUtils {
     }
 
     public static int handleXpPerks(Player player, int xp) {
-        if (player.hasPermission("mcmmo.perks.xp.quadruple")) {
+        if (Permissions.quadrupleXp(player)) {
             xp *= 4;
         }
-        else if (player.hasPermission("mcmmo.perks.xp.triple")) {
+        else if (Permissions.tripleXp(player)) {
             xp *= 3;
         }
-        else if (player.hasPermission("mcmmo.perks.xp.150percentboost")) {
+        else if (Permissions.doubleAndOneHalfXp(player)) {
             xp *= 2.5;
         }
-        else if (player.hasPermission("mcmmo.perks.xp.150percentboost")) {
+        else if (Permissions.doubleXp(player)) {
             xp *= 2;
         }
-        else if (player.hasPermission("mcmmo.perks.xp.50percentboost")) {
+        else if (Permissions.oneAndOneHalfXp(player)) {
             xp *= 1.5;
         }
 
@@ -68,8 +68,8 @@ public final class PerksUtils {
      * @param isLucky true if the player has the appropriate "lucky" perk, false otherwise
      * @return the activation chance
      */
-    public static int handleLuckyPerks(boolean isLucky) {
-        if (isLucky) {
+    public static int handleLuckyPerks(Player player, SkillType skill) {
+        if (Permissions.lucky(player, skill)) {
             return LUCKY_SKILL_ACTIVATION_CHANCE;
         }
     

+ 13 - 11
src/main/java/com/gmail/nossr50/skills/utilities/SkillTools.java

@@ -316,11 +316,11 @@ public class SkillTools {
      * @return true if the player has combat skills, false otherwise
      */
     public static boolean hasCombatSkills(Player player) {
-        if (Permissions.axes(player)
-                || Permissions.archery(player)
-                || Permissions.swords(player)
-                || Permissions.taming(player)
-                || Permissions.unarmed(player)) {
+        if (Permissions.skillEnabled(player, SkillType.AXES)
+                || Permissions.skillEnabled(player, SkillType.ARCHERY)
+                || Permissions.skillEnabled(player, SkillType.SWORDS)
+                || Permissions.skillEnabled(player, SkillType.TAMING)
+                || Permissions.skillEnabled(player, SkillType.UNARMED)) {
             return true;
         }
 
@@ -334,11 +334,11 @@ public class SkillTools {
      * @return true if the player has gathering skills, false otherwise
      */
     public static boolean hasGatheringSkills(Player player) {
-        if (Permissions.excavation(player)
-                || Permissions.fishing(player)
-                || Permissions.herbalism(player)
-                || Permissions.mining(player)
-                || Permissions.woodcutting(player)) {
+        if (Permissions.skillEnabled(player, SkillType.EXCAVATION)
+                || Permissions.skillEnabled(player, SkillType.FISHING)
+                || Permissions.skillEnabled(player, SkillType.HERBALISM)
+                || Permissions.skillEnabled(player, SkillType.MINING)
+                || Permissions.skillEnabled(player, SkillType.WOODCUTTING)) {
             return true;
         }
 
@@ -352,7 +352,9 @@ public class SkillTools {
      * @return true if the player has misc skills, false otherwise
      */
     public static boolean hasMiscSkills(Player player) {
-        if (Permissions.acrobatics(player) || Permissions.repair(player)) {
+        if (Permissions.skillEnabled(player, SkillType.ACROBATICS)
+                || Permissions.skillEnabled(player, SkillType.SMELTING)
+                || Permissions.skillEnabled(player, SkillType.REPAIR)) {
             return true;
         }
 

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

@@ -77,7 +77,7 @@ public final class Woodcutting {
 
         Player player = mcMMOPlayer.getPlayer();
 
-        if (Permissions.woodcuttingDoubleDrops(player)) {
+        if (Permissions.doubleDrops(player, SkillType.WOODCUTTING)) {
             checkForDoubleDrop(mcMMOPlayer, block);
         }
 
@@ -143,7 +143,7 @@ public final class Woodcutting {
         double configDoubleDropChance = ADVANCED_CONFIG.getWoodcuttingDoubleDropChance();
         int configDoubleDropMaxLevel = ADVANCED_CONFIG.getWoodcuttingDoubleDropMaxLevel();
         int probability = (int) ((configDoubleDropChance / configDoubleDropMaxLevel) * Users.getPlayer(player).getProfile().getSkillLevel(SkillType.WOODCUTTING));
-        int activationChance = PerksUtils.handleLuckyPerks(Permissions.luckyWoodcutting(player));
+        int activationChance = PerksUtils.handleLuckyPerks(player, SkillType.WOODCUTTING);
 
         if (probability > configDoubleDropChance) {
             probability = (int) configDoubleDropChance;

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

@@ -38,7 +38,7 @@ public class WoodcuttingCommand extends SkillCommand {
     @Override
     protected void permissionsCheck() {
         canTreeFell = Permissions.treeFeller(player);
-        canDoubleDrop = Permissions.woodcuttingDoubleDrops(player);
+        canDoubleDrop = Permissions.doubleDrops(player, skill);
         canLeafBlow = Permissions.leafBlower(player);
     }
 

+ 2 - 1
src/main/java/com/gmail/nossr50/spout/commands/XplockCommand.java

@@ -6,6 +6,7 @@ import org.bukkit.command.CommandSender;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.skills.utilities.SkillTools;
 import com.gmail.nossr50.skills.utilities.SkillType;
+import com.gmail.nossr50.util.Permissions;
 
 public class XplockCommand extends SpoutCommand {
     @Override
@@ -38,7 +39,7 @@ public class XplockCommand extends SpoutCommand {
 
         SkillType skill = SkillType.getSkill(args[0]);
 
-        if (!sender.hasPermission("mcmmo.commands.xplock." + skill.toString().toLowerCase())) {
+        if (!Permissions.xplock(sender, skill)) {
             sender.sendMessage(command.getPermissionMessage());
             return true;
         }

+ 170 - 643
src/main/java/com/gmail/nossr50/util/Permissions.java

@@ -4,705 +4,232 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.bukkit.Bukkit;
+import org.bukkit.Material;
 import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
+import org.bukkit.permissions.Permissible;
 import org.bukkit.permissions.Permission;
 import org.bukkit.plugin.PluginManager;
 
+import com.gmail.nossr50.party.commands.PartySubcommandType;
 import com.gmail.nossr50.skills.utilities.SkillType;
 
 public final class Permissions {
     private Permissions() {}
 
-    public static boolean hasPermission(CommandSender sender, String perm) {
-        return (sender.hasPermission(perm));
-    }
-
-    public static boolean hasDynamicPermission(CommandSender sender, String perm, String defaultType) {
-        Map<String, Object> m = new HashMap<String, Object>();
-
-        if(defaultType != null) {
-            m.put("default", defaultType);
-        }
-
-        PluginManager manager = Bukkit.getPluginManager();
-
-        if (manager.getPermission(perm) == null) {
-            Permission.loadPermission(perm, m);
-        }
-
-        return hasPermission(sender, perm);
-    }
-
-    /*
-     * GENERIC PERMISSIONS
-     */
-
-    public static boolean motd(Player player) {
-        return player.hasPermission("mcmmo.motd");
-    }
-
-    /**
-     * @deprecated Use the permission "mcmmo.all" instead.
-     */
-    @Deprecated
-    public static boolean admin(Player player) {
-        return player.hasPermission("mcmmo.admin");
-    }
-
-    /*
-     * MCMMO.BYPASS.*
-     */
-    public static boolean hardcoremodeBypass(Player player) {
-        return player.hasPermission("mcmmo.bypass.hardcoremode");
-    }
-
-    public static boolean arcaneBypass(Player player) {
-        return player.hasPermission("mcmmo.bypass.arcanebypass");
-    }
-
-    /**
-     * @deprecated Use {@link #inspectFar(player)} instead.
-     */
-    @Deprecated
-    public static boolean inspectDistanceBypass(Player player) {
-        return player.hasPermission("mcmmo.bypass.inspect.distance");
-    }
-
-    public static boolean inspectFar(Player player) {
-        return (player.hasPermission("mcmmo.commands.inspect.far"));
-    }
-
-    /**
-     * @deprecated Use {@link #inspectOffline(player)} instead.
-     */
-    @Deprecated
-    public static boolean inspectOfflineBypass(Player player) {
-        return player.hasPermission("mcmmo.bypass.inspect.offline");
-    }
-
-    public static boolean inspectOffline(Player player) {
-        return (player.hasPermission("mcmmo.commands.inspect.offline"));
-    }
-
-    /*
-     * MCMMO.TOOLS.*
-     */
-
-    public static boolean mcrefresh(Player player) {
-        return player.hasPermission("mcmmo.tools.mcrefresh");
-    }
-
-    public static boolean mcremove(Player player) {
-        return player.hasPermission("mcmmo.tools.mcremove");
-    }
-
-    /**
-     * @deprecated Use {@link #mmoeditCommand(player)} instead.
-     */
-    @Deprecated
-    public static boolean mmoedit(CommandSender sender) {
-        return sender.hasPermission("mcmmo.tools.mmoedit");
-    }
-
-    /**
-     * @deprecated Use {@link #mcgodCommand(player)} instead.
-     */
-    @Deprecated
-    public static boolean mcgod(CommandSender sender) {
-        return sender.hasPermission("mcmmo.tools.mcgod");
-    }
-
-    /*
-     * MCMMO.PERKS.LUCKY*
-     */
-
-    public static boolean lucky(Player player, SkillType skill) {
-        return player.hasPermission("mcmmo.perks.lucky." + skill.toString().toLowerCase());
-    }
-
-    public static boolean luckyAcrobatics(Player player) {
-        return player.hasPermission("mcmmo.perks.lucky.acrobatics");
-    }
-
-    public static boolean luckyArchery(Player player) {
-        return player.hasPermission("mcmmo.perks.lucky.archery");
-    }
-
-    public static boolean luckyAxes(Player player) {
-        return player.hasPermission("mcmmo.perks.lucky.axes");
-    }
-
-    public static boolean luckyExcavation(Player player) {
-        return player.hasPermission("mcmmo.perks.lucky.excavation");
-    }
-
-    public static boolean luckyFishing(Player player) {
-        return player.hasPermission("mcmmo.perks.lucky.fishing");
-    }
-
-    public static boolean luckyHerbalism(Player player) {
-        return player.hasPermission("mcmmo.perks.lucky.herbalism");
-    }
-
-    public static boolean luckyMining(Player player) {
-        return player.hasPermission("mcmmo.perks.lucky.mining");
-    }
-
-    public static boolean luckyRepair(Player player) {
-        return player.hasPermission("mcmmo.perks.lucky.repair");
-    }
-
-    public static boolean luckySmelting(Player player) {
-        return player.hasPermission("mcmmo.perks.lucky.smelting");
-    }
-
-    public static boolean luckySwords(Player player) {
-        return player.hasPermission("mcmmo.perks.lucky.swords");
-    }
-
-    public static boolean luckyTaming(Player player) {
-        return player.hasPermission("mcmmo.perks.lucky.taming");
-    }
-
-    public static boolean luckyUnarmed(Player player) {
-        return player.hasPermission("mcmmo.perks.lucky.unarmed");
-    }
-
-    public static boolean luckyWoodcutting(Player player) {
-        return player.hasPermission("mcmmo.perks.lucky.woodcutting");
-    }
-
     /*
-     * MCMMO.PERKS.XP*
+     * GENERAL
      */
 
-    public static boolean xpQuadruple(Player player) {
-        return player.hasPermission("mcmmo.perks.xp.quadruple");
-    }
+    public static boolean motd(Permissible permissible) { return permissible.hasPermission("mcmmo.motd"); }
+    public static boolean updateNotifications(Permissible permissible) {return permissible.hasPermission("mcmmo.tools.updatecheck"); }
+    public static boolean chimaeraWing(Permissible permissible) { return permissible.hasPermission("mcmmo.item.chimaerawing"); }
 
-    public static boolean xpTriple(Player player) {
-        return player.hasPermission("mcmmo.perks.xp.triple");
-    }
+    /* BYPASS */
+    public static boolean hardcoreBypass(Permissible permissible) { return permissible.hasPermission("mcmmo.bypass.hardcoremode"); }
+    public static boolean arcaneBypass(Permissible permissible) { return permissible.hasPermission("mcmmo.bypass.arcanebypass"); }
 
-    public static boolean xpDoubleAndOneHalf(Player player) {
-        return player.hasPermission("mcmmo.perks.xp.150percentboost");
-    }
-
-    public static boolean xpDouble(Player player) {
-        return player.hasPermission("mcmmo.perks.xp.double");
-    }
-
-    public static boolean xpOneAndOneHalf(Player player) {
-        return player.hasPermission("mcmmo.perks.xp.50percentboost");
-    }
+    /* CHAT */
+    public static boolean partyChat(Permissible permissible) { return permissible.hasPermission("mcmmo.chat.partychat"); }
+    public static boolean adminChat(Permissible permissible) { return permissible.hasPermission("mcmmo.chat.adminchat"); }
 
     /*
-     * MCMMO.PERKS.COOLDOWNS*
+     * COMMANDS
      */
 
-    public static boolean cooldownsHalved(Player player) {
-        return player.hasPermission("mcmmo.perks.cooldowns.halved");
-    }
+    public static boolean addlevels(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.addlevels"); }
+    public static boolean addlevelsOthers(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.addlevels.others"); }
 
-    public static boolean cooldownsThirded(Player player) {
-        return player.hasPermission("mcmmo.perks.cooldowns.thirded");
-    }
+    public static boolean addxp(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.addxp"); }
+    public static boolean addxpOthers(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.addxp.others"); }
 
-    public static boolean cooldownsQuartered(Player player) {
-        return player.hasPermission("mcmmo.perks.cooldowns.quartered");
-    }
+    public static boolean hardcoreModify(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.hardcore.modify"); }
+    public static boolean hardcoreToggle(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.hardcore.toggle"); }
 
-    /*
-     * MCMMO.PERKS.ACTIVATIONTIME*
-     */
-
-    public static boolean activationTwelve(Player player) {
-        return player.hasPermission("mcmmo.perks.activationtime.twelveseconds");
-    }
+    public static boolean inspect(Permissible permissible) { return (permissible.hasPermission("mcmmo.commands.inspect")); }
+    public static boolean inspectFar(Permissible permissible) { return (permissible.hasPermission("mcmmo.commands.inspect.far")); }
+    public static boolean inspectOffline(Permissible permissible) { return (permissible.hasPermission("mcmmo.commands.inspect.offline")); }
 
-    public static boolean activationEight(Player player) {
-        return player.hasPermission("mcmmo.perks.activationtime.eightseconds");
-    }
+    public static boolean mcability(Permissible permissible) { return (permissible.hasPermission("mcmmo.commands.mcability")); }
+    public static boolean mcabilityOthers(Permissible permissible) { return (permissible.hasPermission("mcmmo.commands.mcability.others")); }
 
-    public static boolean activationFour(Player player) {
-        return player.hasPermission("mcmmo.perks.activationtime.fourseconds");
-    }
+    public static boolean mcgod(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.mcgod"); }
+    public static boolean mcgodOthers(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.mcgod.others"); }
 
-    /*
-     * MCMMO.ABILITY.TAMING.*
-     */
+    public static boolean mcmmoDescription(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.mcmmo.description"); }
+    public static boolean mcmmoHelp(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.mcmmo.help"); }
 
-    public static boolean fastFoodService(Player player) {
-        return player.hasPermission("mcmmo.ability.taming.fastfoodservice");
-    }
+    public static boolean mcrank(Permissible permissible) { return (permissible.hasPermission("mcmmo.commands.mcrank")); }
+    public static boolean mcrankOthers(Permissible permissible) { return (permissible.hasPermission("mcmmo.commands.mcrank.others")); }
+    public static boolean mcrankFar(Permissible permissible) { return (permissible.hasPermission("mcmmo.commands.mcrank.others.far")); }
+    public static boolean mcrankOffline(Permissible permissible) { return (permissible.hasPermission("mcmmo.commands.mcrank.others.offline")); }
 
-    public static boolean sharpenedClaws(Player player) {
-        return player.hasPermission("mcmmo.ability.taming.sharpenedclaws");
-    }
+    public static boolean mcrefresh(Permissible permissible) { return (permissible.hasPermission("mcmmo.commands.mcrefresh")); }
+    public static boolean mcrefreshOthers(Permissible permissible) { return (permissible.hasPermission("mcmmo.commands.mcrefresh.others")); }
 
-    public static boolean gore(Player player) {
-        return player.hasPermission("mcmmo.ability.taming.gore");
-    }
+    public static boolean mctop(Permissible permissible, SkillType skill) { return permissible.hasPermission("mcmmo.commands.mctop." + skill.toString().toLowerCase()); }
 
-    public static boolean callOfTheWild(Player player) {
-        return player.hasPermission("mcmmo.ability.taming.callofthewild");
-    }
+    public static boolean mmoedit(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.mmoedit"); }
+    public static boolean mmoeditOthers(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.mmoedit.others"); }
 
-    public static boolean environmentallyAware(Player player) {
-        return player.hasPermission("mcmmo.ability.taming.environmentallyaware");
-    }
+    public static boolean skillreset(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.skillreset"); }
+    public static boolean skillreset(Permissible permissible, SkillType skill) { return permissible.hasPermission("mcmmo.commands.skillreset." + skill.toString().toLowerCase()); }
+    public static boolean skillresetOthers(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.skillreset.others"); }
+    public static boolean skillresetOthers(Permissible permissible, SkillType skill) { return permissible.hasPermission("mcmmo.commands.skillreset.others." + skill.toString().toLowerCase()); }
 
-    public static boolean thickFur(Player player) {
-        return player.hasPermission("mcmmo.ability.taming.thickfur");
-    }
+    public static boolean xplock(Permissible permissible, SkillType skill) { return permissible.hasPermission("mcmmo.commands.xplock." + skill.toString().toLowerCase()); }
 
-    public static boolean shockProof(Player player) {
-        return player.hasPermission("mcmmo.ability.taming.shockproof");
-    }
+    public static boolean xprateSet(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.xprate.set"); }
+    public static boolean xprateReset(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.xprate.reset"); }
 
-    public static boolean beastLore(Player player) {
-        return player.hasPermission("mcmmo.ability.taming.beastlore");
-    }
+    public static boolean vampirismModify(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.vampirism.modify"); }
+    public static boolean vampirismToggle(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.vampirism.toggle"); }
 
     /*
-     * MCMMO.ABILITY.FISHING.*
+     * PERKS
      */
 
-    public static boolean shakeMob(Player player) {
-        return player.hasPermission("mcmmo.ability.fishing.shakemob");
-    }
+    public static boolean lucky(Permissible permissible, SkillType skill) { return permissible.hasPermission("mcmmo.perks.lucky." + skill.toString().toLowerCase()); }
 
-    public static boolean fishingTreasures(Player player) {
-        return player.hasPermission("mcmmo.ability.fishing.treasures");
-    }
+    /* XP PERKS */
+    public static boolean quadrupleXp(Permissible permissible) { return permissible.hasPermission("mcmmo.perks.xp.quadruple"); }
+    public static boolean tripleXp(Permissible permissible) { return permissible.hasPermission("mcmmo.perks.xp.triple"); }
+    public static boolean doubleAndOneHalfXp(Permissible permissible) { return permissible.hasPermission("mcmmo.perks.xp.150percentboost"); }
+    public static boolean doubleXp(Permissible permissible) { return permissible.hasPermission("mcmmo.perks.xp.double"); }
+    public static boolean oneAndOneHalfXp(Permissible permissible) { return permissible.hasPermission("mcmmo.perks.xp.50percentboost"); }
 
-    public static boolean fishingMagic(Player player) {
-        return player.hasPermission("mcmmo.ability.fishing.magic");
-    }
+    /* ACTIVATION PERKS */
+    public static boolean twelveSecondActivationBoost(Permissible permissible) { return permissible.hasPermission("mcmmo.perks.activationtime.twelveseconds"); }
+    public static boolean eightSecondActivationBoost(Permissible permissible) { return permissible.hasPermission("mcmmo.perks.activationtime.eightseconds"); }
+    public static boolean fourSecondActivationBoost(Permissible permissible) { return permissible.hasPermission("mcmmo.perks.activationtime.fourseconds"); }
 
-    public static boolean fishermansDiet(Player player) {
-        return player.hasPermission("mcmmo.ability.fishing.fishermansdiet");
-    }
-
-    public static boolean fishingVanillaXPBoost(Player player) {
-        return player.hasPermission("mcmmo.ability.fishing.vanillaxpboost");
-    }
+    /* COOLDOWN PERKS */
+    public static boolean halvedCooldowns(Permissible permissible) { return permissible.hasPermission("mcmmo.perks.cooldowns.halved"); }
+    public static boolean thirdedCooldowns(Permissible permissible) { return permissible.hasPermission("mcmmo.perks.cooldowns.thirded"); }
+    public static boolean quarteredCooldowns(Permissible permissible) { return permissible.hasPermission("mcmmo.perks.cooldowns.quartered"); }
 
     /*
-     * MCMMO.ABILITY.MINING.*
+     * SKILLS
      */
 
-    public static boolean superBreaker(Player player) {
-        return player.hasPermission("mcmmo.ability.mining.superbreaker");
-    }
+    public static boolean skillEnabled(Permissible permissible, SkillType skill) {return permissible.hasPermission("mcmmo.skills." + skill.toString().toLowerCase()); }
+    public static boolean doubleDrops(Permissible permissible, SkillType skill) { return permissible.hasPermission("mcmmo.ability." + skill.toString().toLowerCase() + ".doubledrops"); }
+    public static boolean vanillaXpBoost(Permissible permissible, SkillType skill) { return permissible.hasPermission("mcmmo.ability." + skill.toString().toLowerCase() + ".vanillaxpboost"); }
+    public static boolean bonusDamage(Permissible permissible, SkillType skill) { return permissible.hasPermission("mcmmo.ability." + skill.toString().toLowerCase() + ".bonusdamage"); }
 
-    public static boolean miningDoubleDrops(Player player) {
-        return player.hasPermission("mcmmo.ability.mining.doubledrops");
-    }
+    /* ACROBATICS */
+    public static boolean dodge(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.acrobatics.dodge"); }
+    public static boolean gracefulRoll(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.acrobatics.gracefulroll"); }
+    public static boolean roll(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.acrobatics.roll"); }
 
-    /*
-     * MCMMO.ABILITY.WOODCUTTING.*
-     */
+    /* ARCHERY */
+    public static boolean arrowRetrieval(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.archery.trackarrows"); }
+    public static boolean daze(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.archery.daze"); }
 
-    public static boolean treeFeller(Player player) {
-        return player.hasPermission("mcmmo.ability.woodcutting.treefeller");
-    }
+    /* AXES */
+    public static boolean armorImpact(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.axes.impact"); }
+    public static boolean criticalStrikes(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.axes.criticalhit"); }
+    public static boolean greaterImpact(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.axes.greaterimpact"); }
+    public static boolean skullSplitter(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.axes.skullsplitter"); }
 
-    public static boolean leafBlower(Player player) {
-        return player.hasPermission("mcmmo.ability.woodcutting.leafblower");
-    }
+    /* EXCAVATION */
+    public static boolean gigaDrillBreaker(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.excavation.gigadrillbreaker"); }
+    public static boolean excavationTreasureHunter(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.excavation.treasures"); }
 
-    public static boolean woodcuttingDoubleDrops(Player player) {
-        return player.hasPermission("mcmmo.ability.woodcutting.doubledrops");
-    }
+    /* FISHING */
+    public static boolean fishermansDiet(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.fishing.fishermansdiet"); }
+    public static boolean fishingTreasureHunter(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.fishing.treasures"); }
+    public static boolean magicHunter(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.fishing.magic"); }
+    public static boolean shake(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.fishing.shakemob"); }
 
-    /*
-     * MCMMO.ABILITY.REPAIR.*
-     */
-
-    public static boolean repairBonus(Player player) {
-        return player.hasPermission("mcmmo.ability.repair.repairbonus");
-    }
+    /* HERBALISM */
+    public static boolean farmersDiet(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.herbalism.farmersdiet"); }
+    public static boolean greenTerra(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.herbalism.greenterra"); }
+    public static boolean greenThumbBlock(Permissible permissible, Material material) { return permissible.hasPermission("mcmmo.ability.herbalism.greenthumb.blocks." + material.toString().replace("_", "").toLowerCase()); }
+    public static boolean greenThumbPlant(Permissible permissible, Material material) { return permissible.hasPermission("mcmmo.ability.herbalism.greenthumb.plants." + material.toString().replace("_", "").toLowerCase()); }
+    public static boolean hylianLuck(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.herbalism.hylianluck"); }
 
-    public static boolean repairMastery(Player player) {
-        return player.hasPermission("mcmmo.ability.repair.repairmastery");
-    }
+    /* MINING */
+    public static boolean biggerBombs(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.mining.blastmining.biggerbombs"); }
+    public static boolean demolitionsExpertise(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.mining.blastmining.demolitionsexpertise"); }
+    public static boolean remoteDetonation(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.mining.blastmining.detonate"); }
+    public static boolean superBreaker(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.mining.superbreaker"); }
 
-    public static boolean arcaneForging(Player player) {
-        return player.hasPermission("mcmmo.ability.repair.arcaneforging");
-    }
+    /* REPAIR */
+    public static boolean arcaneForging(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.repair.arcaneforging"); }
+    public static boolean repairMastery(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.repair.repairmastery"); }
+    public static boolean salvage(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.repair.salvage"); }
+    public static boolean superRepair(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.repair.repairbonus"); }
 
-    public static boolean woodRepair(Player player) {
-        return player.hasPermission("mcmmo.ability.repair.woodrepair");
-    }
+    public static boolean repairArmor(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.repair.armorrepair"); }
+    public static boolean repairTools(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.repair.toolrepair"); }
+    public static boolean repairOtherItems(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.repair.otherrepair"); }
 
-    public static boolean stoneRepair(Player player) {
-        return player.hasPermission("mcmmo.ability.repair.stonerepair");
-    }
-
-    public static boolean leatherRepair(Player player) {
-        return player.hasPermission("mcmmo.ability.repair.leatherrepair");
-    }
-
-    public static boolean ironRepair(Player player) {
-        return player.hasPermission("mcmmo.ability.repair.ironrepair");
-    }
-
-    public static boolean goldRepair(Player player) {
-        return player.hasPermission("mcmmo.ability.repair.goldrepair");
-    }
-
-    public static boolean diamondRepair(Player player) {
-        return player.hasPermission("mcmmo.ability.repair.diamondrepair");
-    }
-
-    public static boolean armorRepair(Player player) {
-        return player.hasPermission("mcmmo.ability.repair.armorrepair");
-    }
-
-    public static boolean toolRepair(Player player) {
-        return player.hasPermission("mcmmo.ability.repair.toolrepair");
-    }
-
-    public static boolean otherMaterialRepair(Player player) {
-        return player.hasPermission("mcmmo.ability.repair.othermaterialrepair");
-    }
-
-    public static boolean otherRepair(Player player) {
-        return player.hasPermission("mcmmo.ability.repair.otherrepair");
-    }
-
-    public static boolean stringRepair(Player player) {
-        return player.hasPermission("mcmmo.ability.repair.stringrepair");
-    }
-
-    public static boolean salvage(Player player) {
-        return player.hasPermission("mcmmo.ability.repair.salvage");
-    }
-
-
-    /*
-     * MCMMO.ABILITY.UNARMED.*
-     */
-
-    public static boolean unarmedBonus(Player player) {
-        return player.hasPermission("mcmmo.ability.unarmed.bonusdamage");
-    }
-
-    public static boolean disarm(Player player) {
-        return player.hasPermission("mcmmo.ability.unarmed.disarm");
-    }
-
-    public static boolean berserk(Player player) {
-        return player.hasPermission("mcmmo.ability.unarmed.berserk");
-    }
-
-    public static boolean deflect(Player player) {
-        return player.hasPermission("mcmmo.ability.unarmed.deflect");
-    }
-
-    public static boolean ironGrip(Player player) {
-        return player.hasPermission("mcmmo.ability.unarmed.irongrip");
-    }
-
-    /*
-     * MCMMO.ABILITY.ARCHERY.*
-     */
-
-    public static boolean trackArrows(Player player) {
-        return player.hasPermission("mcmmo.ability.archery.trackarrows");
-    }
-
-    public static boolean daze(Player player) {
-        return player.hasPermission("mcmmo.ability.archery.daze");
-    }
-
-    public static boolean archeryBonus(Player player) {
-        return player.hasPermission("mcmmo.ability.archery.bonusdamage");
-    }
-
-    /*
-     * MCMMO.ABILITY.HERBALISM.*
-     */
-
-    public static boolean herbalismDoubleDrops(Player player) {
-        return player.hasPermission("mcmmo.ability.herbalism.doubledrops");
-    }
-
-    public static boolean greenTerra(Player player) {
-        return player.hasPermission("mcmmo.ability.herbalism.greenterra");
-    }
-
-    public static boolean greenThumbBlocks(Player player) {
-        return player.hasPermission("mcmmo.ability.herbalism.greenthumbblocks");
-    }
-
-    public static boolean greenThumbCarrots(Player player) {
-        return player.hasPermission("mcmmo.ability.herbalism.greenthumbcarrots");
-    }
-
-    public static boolean greenThumbCocoa(Player player) {
-        return player.hasPermission("mcmmo.ability.herbalism.greenthumbcocoa");
-    }
-
-    public static boolean greenThumbNetherwart(Player player) {
-        return player.hasPermission("mcmmo.ability.herbalism.greenthumbnetherwart");
-    }
-
-    public static boolean greenThumbPotatoes(Player player) {
-        return player.hasPermission("mcmmo.ability.herbalism.greenthumbpotatoes");
-    }
-
-    public static boolean greenThumbWheat(Player player) {
-        return player.hasPermission("mcmmo.ability.herbalism.greenthumbwheat");
-    }
-
-    public static boolean farmersDiet(Player player) {
-        return player.hasPermission("mcmmo.ability.herbalism.farmersdiet");
-    }
-
-    public static boolean hylianLuck(Player player) {
-        return player.hasPermission("mcmmo.ability.herbalism.hylianluck");
-    }
-
-    /*
-     * MCMMO.ABILITY.EXCAVATION.*
-     */
-
-    public static boolean gigaDrillBreaker(Player player) {
-        return player.hasPermission("mcmmo.ability.excavation.gigadrillbreaker");
-    }
-
-    public static boolean excavationTreasures(Player player) {
-        return player.hasPermission("mcmmo.ability.excavation.treasures");
-    }
-
-    /*
-     * MCMMO.ABILITY.SWORDS.*
-     */
-
-    public static boolean swordsBleed(Player player) {
-        return player.hasPermission("mcmmo.ability.swords.bleed");
-    }
-
-    public static boolean serratedStrikes(Player player) {
-        return player.hasPermission("mcmmo.ability.swords.serratedstrikes");
-    }
-
-    public static boolean counterAttack(Player player) {
-        return player.hasPermission("mcmmo.ability.swords.counterattack");
-    }
-
-    /*
-     * MCMMO.ABILITY.AXES.*
-     */
-
-    public static boolean skullSplitter(Player player) {
-        return player.hasPermission("mcmmo.ability.axes.skullsplitter");
-    }
-
-    public static boolean axeBonus(Player player) {
-        return player.hasPermission("mcmmo.ability.axes.bonusdamage");
-    }
-
-    public static boolean criticalHit(Player player) {
-        return player.hasPermission("mcmmo.ability.axes.criticalhit");
-    }
-
-    public static boolean impact(Player player) {
-        return player.hasPermission("mcmmo.ability.axes.impact");
-    }
-
-    public static boolean greaterImpact(Player player) {
-        return player.hasPermission("mcmmo.ability.axes.greaterimpact");
-    }
-
-    /*
-     * MCMMO.ABILITY.ACROBATICS.*
-     */
-
-    public static boolean roll(Player player) {
-        return player.hasPermission("mcmmo.ability.acrobatics.roll");
-    }
-
-    public static boolean gracefulRoll(Player player) {
-        return player.hasPermission("mcmmo.ability.acrobatics.gracefulroll");
-    }
-
-    public static boolean dodge(Player player) {
-        return player.hasPermission("mcmmo.ability.acrobatics.dodge");
-    }
-
-    /*
-     * MCMMO.ABILITY.BLASTMINING.*
-     */
-
-    public static boolean biggerBombs(Player player) {
-        return player.hasPermission("mcmmo.ability.mining.blastmining.biggerbombs");
-    }
-
-    public static boolean demolitionsExpertise(Player player) {
-        return player.hasPermission("mcmmo.ability.mining.blastmining.demolitionsexpertise");
-    }
-
-    public static boolean blastMining(Player player) {
-        return player.hasPermission("mcmmo.ability.mining.blastmining.detonate");
-    }
-
-    /*
-     * MCMMO.ABILITY.SMELTING.* 
-     */
-
-    public static boolean fuelEfficiency(Player player) {
-        return player.hasPermission("mcmmo.ability.smelting.fuelefficiency");
-    }
-
-    public static boolean secondSmelt(Player player) {
-        return player.hasPermission("mcmmo.ability.smelting.secondsmelt");
-    }
-
-    public static boolean fluxMining(Player player) {
-        return player.hasPermission("mcmmo.ability.smelting.fluxmining");
-    }
-
-    public static boolean smeltingVanillaXPBoost(Player player) {
-        return player.hasPermission("mcmmo.ability.smelting.vanillaxpboost");
-    }
-
-    /*
-     * MCMMO.ITEM.*
-     */
-
-    public static boolean chimaeraWing(Player player) {
-        return hasPermission(player, "mcmmo.item.chimaerawing");
-    }
-
-    /*
-     * MCMMO.COMMANDS.*
-     */
-
-    public static boolean mmoeditCommand(Player player) {
-        return (player.hasPermission("mcmmo.commands.mmoedit"));
-    }
-
-    public static boolean skillResetCommand(Player player) {
-        return (player.hasPermission("mcmmo.commands.skillreset"));
-    }
-
-    public static boolean mcAbilityCommand(Player player) {
-        return (player.hasPermission("mcmmo.commands.mcability"));
-    }
-
-    public static boolean mcgodCommand(CommandSender sender) {
-        return (hasPermission(sender, "mcmmo.commands.mcgod"));
-    }
-
-    /**
-     * @deprecated Use {@link #mcAbilityCommand(player)} instead.
-     */
-    @Deprecated
-    public static boolean mcAbility(Player player) {
-        return player.hasPermission("mcmmo.commands.ability");
-    }
-
-    public static boolean partyTeleport(Player player) {
-        return player.hasPermission("mcmmo.commands.ptp");
-    }
-
-    public static boolean inspect(Player player) {
-        return player.hasPermission("mcmmo.commands.inspect");
-    }
-
-    public static boolean party(Player player) {
-        return player.hasPermission("mcmmo.commands.party");
-    }
-
-    /**
-     * @deprecated Use {@link #skillResetCommand(player)} instead.
-     */
-    @Deprecated
-    public static boolean skillReset(Player player) {
-        return player.hasPermission("mcmmo.skillreset");
-    }
-
-    /*
-     * MCMMO.CHAT.*
-     */
-
-    public static boolean partyChat(Player player) {
-        return player.hasPermission("mcmmo.chat.partychat");
-    }
-
-    public static boolean partyLock(Player player) {
-        return player.hasPermission("mcmmo.chat.partylock");
-    }
-
-    public static boolean adminChat(Player player) {
-        return player.hasPermission("mcmmo.chat.adminchat");
-    }
-
-    /*
-     * MCMMO.SKILLS.*
-     */
-
-    public static boolean taming(Player player) {
-        return player.hasPermission("mcmmo.skills.taming");
-    }
-
-    public static boolean mining(Player player) {
-        return player.hasPermission("mcmmo.skills.mining");
-    }
-
-    public static boolean fishing(Player player) {
-        return player.hasPermission("mcmmo.skills.fishing");
-    }
-
-    public static boolean woodcutting(Player player) {
-        return player.hasPermission("mcmmo.skills.woodcutting");
-    }
-
-    public static boolean repair(Player player) {
-        return player.hasPermission("mcmmo.skills.repair");
-    }
-
-    public static boolean unarmed(Player player) {
-        return player.hasPermission("mcmmo.skills.unarmed");
-    }
-
-    public static boolean archery(Player player) {
-        return player.hasPermission("mcmmo.skills.archery");
-    }
-
-    public static boolean herbalism(Player player) {
-        return player.hasPermission("mcmmo.skills.herbalism");
-    }
-
-    public static boolean excavation(Player player) {
-        return player.hasPermission("mcmmo.skills.excavation");
-    }
-
-    public static boolean swords(Player player) {
-        return player.hasPermission("mcmmo.skills.swords");
-    }
-
-    public static boolean axes(Player player) {
-        return player.hasPermission("mcmmo.skills.axes");
-    }
+    public static boolean repairDiamond(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.repair.diamondrepair"); }
+    public static boolean repairGold(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.repair.goldrepair"); }
+    public static boolean repairIron(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.repair.ironrepair"); }
+    public static boolean repairLeather(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.repair.leatherrepair"); }
+    public static boolean repairOtherMaterials(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.repair.othermaterialrepair"); }
+    public static boolean repairString(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.repair.stringrepair"); }
+    public static boolean repairStone(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.repair.stonerepair"); }
+    public static boolean repairWood(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.repair.woodrepair"); }
+
+    /* SMELTING */
+    public static boolean fluxMining(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.smelting.fluxmining"); }
+    public static boolean fuelEfficiency(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.smelting.fuelefficiency"); }
+
+    /* SWORDS */
+    public static boolean bleed(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.swords.bleed"); }
+    public static boolean counterAttack(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.swords.counterattack"); }
+    public static boolean serratedStrikes(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.swords.serratedstrikes"); }
+
+    /* TAMING */
+    public static boolean beastLore(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.taming.beastlore"); }
+    public static boolean callOfTheWild(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.taming.callofthewild"); }
+    public static boolean environmentallyAware(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.taming.environmentallyaware"); }
+    public static boolean fastFoodService(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.taming.fastfoodservice"); }
+    public static boolean gore(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.taming.gore"); }
+    public static boolean thickFur(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.taming.thickfur"); }
+    public static boolean sharpenedClaws(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.taming.sharpenedclaws"); }
+    public static boolean shockProof(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.taming.shockproof"); }
+
+    /* UNARMED */
+    public static boolean arrowDeflect(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.unarmed.deflect"); }
+    public static boolean berserk(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.unarmed.berserk"); }
+    public static boolean blockCracker(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.unarmed.blockcracker"); }
+    public static boolean disarm(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.unarmed.disarm"); }
+    public static boolean ironGrip(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.unarmed.irongrip"); }
+
+    /* WOODCUTTING */
+    public static boolean leafBlower(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.woodcutting.leafblower"); }
+    public static boolean treeFeller(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.woodcutting.treefeller"); }
+
+    /*
+     * PARTY
+     */
+
+    public static boolean party(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.party"); }
+    public static boolean partySubcommand(Permissible permissible, PartySubcommandType subcommand) {return permissible.hasPermission("mcmmo.commands.party." + subcommand.toString().toLowerCase()); }
+    public static boolean friendlyFire(Permissible permissible) { return permissible.hasPermission("mcmmo.party.friendlyfire"); }
+
+    /* TELEPORT */
+    public static boolean partyTeleportAccept(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.ptp.accept"); }
+    public static boolean partyTeleportAcceptAll(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.ptp.acceptall"); }
+    public static boolean partyTeleportToggle(Permissible permissible) { return permissible.hasPermission("mcmmo.commands.ptp.toggle"); }
+
+    // TODO: Still think there's a better way to handle this
+    public static boolean hasDynamicPermission(CommandSender sender, String perm, String defaultType) {
+        Map<String, Object> m = new HashMap<String, Object>();
 
-    public static boolean acrobatics(Player player) {
-        return player.hasPermission("mcmmo.skills.acrobatics");
-    }
+        if(defaultType != null) {
+            m.put("default", defaultType);
+        }
 
-    public static boolean smelting(Player player) {
-        return player.hasPermission("mcmmo.skills.smelting");
-    }
+        PluginManager manager = Bukkit.getPluginManager();
 
-    /*
-     * MCMMO.PARTY.*
-     */
+        if (manager.getPermission(perm) == null) {
+            Permission.loadPermission(perm, m);
+        }
 
-    public static boolean friendlyFire(Player player) {
-        return player.hasPermission("mcmmo.party.friendlyfire");
+        return sender.hasPermission(perm);
     }
 }

+ 0 - 5
src/main/resources/config.yml

@@ -149,11 +149,6 @@ Skills:
     Herbalism:
         Level_Cap: 0
         Prevent_AFK_Leveling: true
-        Green_Thumb:
-            Cobble_To_Mossy: true
-            CobbleWall_To_MossyWall: true
-            SmoothBrick_To_MossyBrick: true
-            Dirt_To_Grass: true
     Mining:
         Level_Cap: 0
         Detonator_ID: 259

+ 50 - 17
src/main/resources/plugin.yml

@@ -272,12 +272,8 @@ permissions:
             mcmmo.ability.herbalism.doubledrops: true
             mcmmo.ability.herbalism.farmersdiet: true
             mcmmo.ability.herbalism.greenterra: true
-            mcmmo.ability.herbalism.greenthumbblocks: true
-            mcmmo.ability.herbalism.greenthumbcarrots: true
-            mcmmo.ability.herbalism.greenthumbcocoa: true
-            mcmmo.ability.herbalism.greenthumbnetherwart: true
-            mcmmo.ability.herbalism.greenthumbpotatoes: true
-            mcmmo.ability.herbalism.greenthumbwheat: true
+            mcmmo.ability.herbalism.greenthumb.blocks.all: true
+            mcmmo.ability.herbalims.greenthumb.plants.all: true
             mcmmo.ability.herbalism.hylianluck: true
     mcmmo.ability.herbalism.doubledrops:
         description: Allows double drop chance from Herbalism
@@ -285,18 +281,39 @@ permissions:
         description: Allows access to the Farmer's Diet ability
     mcmmo.ability.herbalism.greenterra:
         description: Allows access to the Green Terra ability
-    mcmmo.ability.herbalism.greenthumbblocks:
-        description: Allows access to the Green Thumb ability for blocks
-    mcmmo.ability.herbalism.greenthumbcarrots:
+    mcmmo.ability.herbalism.greenthumb.blocks.all:
+        description: Allows access to all Green Thumb abilities for blocks
+        children:
+            mcmmo.ability.herbalism.greenthumb.blocks.cobblestone: true
+            mcmmo.ability.herbalism.greenthumb.blocks.cobblewall: true
+            mcmmo.ability.herbalism.greenthumb.blocks.dirt: true
+            mcmmo.ability.herbalism.greenthumb.blocks.smoothbrick: true
+    mcmmo.ability.herbalism.greenthumb.blocks.cobblestone:
+        description: Allows access to the Green Thumb ability for cobblestone
+    mcmmo.ability.herbalism.greenthumb.blocks.cobblewall:
+        description: Allows access to the Green Thumb ability for cobblestone walls
+    mcmmo.ability.herbalism.greenthumb.blocks.dirt:
+        description: Allows access to the Green Thumb ability for dirt
+    mcmmo.ability.herbalism.greenthumb.blocks.smoothbrick:
+        description: Allows access to the Green Thumb ability for smooth brick
+    mcmmo.ability.herbalism.greenthumb.plants.all:
+        description: Allows access to all Green Thumb abilities for plants
+        children:
+            mcmmo.ability.herbalism.greenthumb.plants.carrot: true
+            mcmmo.ability.herbalism.greenthumb.plants.cocoa: true
+            mcmmo.ability.herbalism.greenthumb.plants.crops: true
+            mcmmo.ability.herbalism.greenthumb.plants.netherwarts: true
+            mcmmo.ability.herbalism.greenthumb.plants.potato: true
+    mcmmo.ability.herbalism.greenthumb.plants.carrot:
         description: Allows access to the Green Thumb ability for carrots
-    mcmmo.ability.herbalism.greenthumbcocoa:
+    mcmmo.ability.herbalism.greenthumb.plants.cocoa:
         description: Allows access to the Green Thumb ability for cocoa
-    mcmmo.ability.herbalism.greenthumbnetherwart:
+    mcmmo.ability.herbalism.greenthumb.plants.crops:
+        description: Allows access to the Green Thumb ability for wheat
+    mcmmo.ability.herbalism.greenthumb.plants.netherwarts:
         description: Allows access to the Green Thumb ability for netherwart
-    mcmmo.ability.herbalism.greenthumbpotatoes:
+    mcmmo.ability.herbalism.greenthumb.plants.potato:
         description: Allows access to the Green Thumb ability for potatoes
-    mcmmo.ability.herbalism.greenthumbwheat:
-        description: Allows access to the Green Thumb ability for wheat
     mcmmo.ability.herbalism.hylianluck:
         description: Allows access to the Hylian Luck ability
     mcmmo.ability.mining.*:
@@ -400,7 +417,7 @@ permissions:
         description: Allows access to the Flux Mining ability
     mcmmo.ability.smelting.fuelefficiency:
         description: Allows access to the Fuel Efficiency ability
-    mcmmo.ability.smelting.secondsmelt:
+    mcmmo.ability.smelting.doubledrops:
         description: Allows access to the Second Smelt ability
     mcmmo.ability.smelting.vanillaxpboost:
         description: Allows vanilla XP boost from Smelting
@@ -701,9 +718,9 @@ permissions:
     mcmmo.commands.mcmmo.all:
         description: Implies access to all mcmmo.commands.mcmmo permissions.
         children:
-            mcmmo.commands.mcmmo: true
+            mcmmo.commands.mcmmo.description: true
             mcmmo.commands.mcmmo.help: true
-    mcmmo.commands.mcmmo:
+    mcmmo.commands.mcmmo.description:
         description: Allows access to the mcmmo command
     mcmmo.commands.mcmmo.help:
         description: Allows access to the mcmmo help command
@@ -807,9 +824,12 @@ permissions:
         children:
             mcmmo.commands.party: true
             mcmmo.commands.party.accept: true
+            mcmmo.commands.party.chat: true
             mcmmo.commands.party.create: true
             mcmmo.commands.party.disband: true
             mcmmo.commands.party.expshare: true
+            mcmmo.commands.party.help: true
+            mcmmo.commands.party.info: true
             mcmmo.commands.party.invite: true
             mcmmo.commands.party.itemshare: true
             mcmmo.commands.party.join: true
@@ -819,17 +839,26 @@ permissions:
             mcmmo.commands.party.password: true
             mcmmo.commands.party.quit: true
             mcmmo.commands.party.rename: true
+            mcmmo.commands.party.teleport: true
             mcmmo.commands.party.unlock: true
     mcmmo.commands.party:
         description: Allows access to the party command
     mcmmo.commands.party.accept:
         description: Allows access to the party accept command
+    mcmmo.commands.party.chat:
+        description: Dummy permission for mcmmo.chat.partychat
+        children:
+            mcmmo.chat.partychat: true
     mcmmo.commands.party.create:
         description: Allows access to the party create command
     mcmmo.commands.party.disband:
         description: Allows access to the party disband command
     mcmmo.commands.party.expshare:
         description: Allows access to the party expshare command
+    mcmmo.commands.party.help:
+        description: Allows access to the party help command
+    mcmmo.commands.party.info:
+        description: Allows access to the party info command
     mcmmo.commands.party.invite:
         description: Allows access to the party invite command
     mcmmo.commands.party.itemshare:
@@ -848,6 +877,10 @@ permissions:
         description: Allows access to the party quit command
     mcmmo.commands.party.rename:
         description: Allows access to the party rename command
+    mcmmo.commands.party.teleport:
+        description: Dummy permission for mcmmo.commands.ptp
+        children:
+            mcmmo.commands.ptp: true
     mcmmo.commands.party.unlock:
         description: Allows access to the party unlock command
     mcmmo.commands.ptp.*: