瀏覽代碼

new config system pt 5

nossr50 6 年之前
父節點
當前提交
f6a3084a47
共有 100 個文件被更改,包括 1881 次插入1756 次删除
  1. 3 3
      bukkit/src/main/java/com/gmail/nossr50/commands/MHDCommand.java
  2. 2 2
      bukkit/src/main/java/com/gmail/nossr50/commands/McmmoCommand.java
  3. 2 2
      bukkit/src/main/java/com/gmail/nossr50/commands/McscoreboardCommand.java
  4. 2 2
      bukkit/src/main/java/com/gmail/nossr50/commands/chat/ChatCommand.java
  5. 2 2
      bukkit/src/main/java/com/gmail/nossr50/commands/chat/PartyChatCommand.java
  6. 2 2
      bukkit/src/main/java/com/gmail/nossr50/commands/database/McpurgeCommand.java
  7. 2 2
      bukkit/src/main/java/com/gmail/nossr50/commands/database/MmoshowdbCommand.java
  8. 2 2
      bukkit/src/main/java/com/gmail/nossr50/commands/hardcore/HardcoreCommand.java
  9. 2 2
      bukkit/src/main/java/com/gmail/nossr50/commands/hardcore/VampirismCommand.java
  10. 2 2
      bukkit/src/main/java/com/gmail/nossr50/commands/party/PartyInfoCommand.java
  11. 2 2
      bukkit/src/main/java/com/gmail/nossr50/commands/party/PartyInviteCommand.java
  12. 2 2
      bukkit/src/main/java/com/gmail/nossr50/commands/party/PartyItemShareCommand.java
  13. 2 2
      bukkit/src/main/java/com/gmail/nossr50/commands/party/PartyXpShareCommand.java
  14. 3 3
      bukkit/src/main/java/com/gmail/nossr50/commands/party/alliance/PartyAllianceCommand.java
  15. 3 3
      bukkit/src/main/java/com/gmail/nossr50/commands/party/teleport/PtpAcceptCommand.java
  16. 6 6
      bukkit/src/main/java/com/gmail/nossr50/commands/party/teleport/PtpCommand.java
  17. 5 5
      bukkit/src/main/java/com/gmail/nossr50/commands/player/InspectCommand.java
  18. 3 3
      bukkit/src/main/java/com/gmail/nossr50/commands/player/MccooldownCommand.java
  19. 4 4
      bukkit/src/main/java/com/gmail/nossr50/commands/player/McrankCommand.java
  20. 4 4
      bukkit/src/main/java/com/gmail/nossr50/commands/player/McstatsCommand.java
  21. 4 4
      bukkit/src/main/java/com/gmail/nossr50/commands/player/MctopCommand.java
  22. 3 3
      bukkit/src/main/java/com/gmail/nossr50/commands/skills/SkillCommand.java
  23. 2 2
      bukkit/src/main/java/com/gmail/nossr50/listeners/BlockListener.java
  24. 3 3
      bukkit/src/main/java/com/gmail/nossr50/listeners/EntityListener.java
  25. 4 4
      bukkit/src/main/java/com/gmail/nossr50/listeners/InventoryListener.java
  26. 13 13
      bukkit/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java
  27. 6 6
      bukkit/src/main/java/com/gmail/nossr50/listeners/SelfListener.java
  28. 19 19
      bukkit/src/main/java/com/gmail/nossr50/mcMMO.java
  29. 7 1
      core/src/main/java/com/gmail/nossr50/core/McmmoCore.java
  30. 3 3
      core/src/main/java/com/gmail/nossr50/core/api/ExperienceAPI.java
  31. 2 2
      core/src/main/java/com/gmail/nossr50/core/api/PartyAPI.java
  32. 2 2
      core/src/main/java/com/gmail/nossr50/core/chat/AdminChatManager.java
  33. 2 2
      core/src/main/java/com/gmail/nossr50/core/chat/PartyChatManager.java
  34. 1 2
      core/src/main/java/com/gmail/nossr50/core/config/AdvancedConfig.java
  35. 218 948
      core/src/main/java/com/gmail/nossr50/core/config/Config.java
  36. 19 0
      core/src/main/java/com/gmail/nossr50/core/config/ConfigKeyRegister.java
  37. 44 0
      core/src/main/java/com/gmail/nossr50/core/config/ConfigValidated.java
  38. 0 315
      core/src/main/java/com/gmail/nossr50/core/config/ConfigurableLoader.java
  39. 12 9
      core/src/main/java/com/gmail/nossr50/core/config/CoreSkillsConfig.java
  40. 1041 0
      core/src/main/java/com/gmail/nossr50/core/config/MainConfig.java
  41. 16 7
      core/src/main/java/com/gmail/nossr50/core/config/RankConfig.java
  42. 11 0
      core/src/main/java/com/gmail/nossr50/core/config/RegistersKeys.java
  43. 28 15
      core/src/main/java/com/gmail/nossr50/core/config/SoundConfig.java
  44. 8 0
      core/src/main/java/com/gmail/nossr50/core/config/Unload.java
  45. 62 52
      core/src/main/java/com/gmail/nossr50/core/config/experience/ExperienceConfig.java
  46. 3 2
      core/src/main/java/com/gmail/nossr50/core/config/mods/ArmorConfigManager.java
  47. 5 5
      core/src/main/java/com/gmail/nossr50/core/config/mods/BlockConfigManager.java
  48. 27 20
      core/src/main/java/com/gmail/nossr50/core/config/mods/CustomArmorConfig.java
  49. 7 7
      core/src/main/java/com/gmail/nossr50/core/config/mods/CustomBlockConfig.java
  50. 10 10
      core/src/main/java/com/gmail/nossr50/core/config/mods/CustomEntityConfig.java
  51. 13 13
      core/src/main/java/com/gmail/nossr50/core/config/mods/CustomToolConfig.java
  52. 5 9
      core/src/main/java/com/gmail/nossr50/core/config/party/ItemWeightConfig.java
  53. 2 2
      core/src/main/java/com/gmail/nossr50/core/config/skills/alchemy/PotionConfig.java
  54. 21 24
      core/src/main/java/com/gmail/nossr50/core/config/skills/repair/RepairConfig.java
  55. 12 12
      core/src/main/java/com/gmail/nossr50/core/config/skills/salvage/SalvageConfig.java
  56. 26 26
      core/src/main/java/com/gmail/nossr50/core/config/treasure/TreasureConfig.java
  57. 2 2
      core/src/main/java/com/gmail/nossr50/core/data/database/DatabaseManager.java
  58. 5 5
      core/src/main/java/com/gmail/nossr50/core/datatypes/party/Party.java
  59. 2 2
      core/src/main/java/com/gmail/nossr50/core/datatypes/party/PartyFeature.java
  60. 2 2
      core/src/main/java/com/gmail/nossr50/core/datatypes/party/PartyTeleportRecord.java
  61. 9 9
      core/src/main/java/com/gmail/nossr50/core/datatypes/player/McMMOPlayer.java
  62. 2 2
      core/src/main/java/com/gmail/nossr50/core/datatypes/player/PlayerProfile.java
  63. 2 2
      core/src/main/java/com/gmail/nossr50/core/locale/LocaleLoader.java
  64. 7 7
      core/src/main/java/com/gmail/nossr50/core/party/PartyManager.java
  65. 2 2
      core/src/main/java/com/gmail/nossr50/core/party/ShareHandler.java
  66. 6 0
      core/src/main/java/com/gmail/nossr50/core/platform/Platform.java
  67. 4 4
      core/src/main/java/com/gmail/nossr50/core/runnables/backups/CleanBackupsTask.java
  68. 2 2
      core/src/main/java/com/gmail/nossr50/core/runnables/commands/McrankCommandDisplayTask.java
  69. 2 2
      core/src/main/java/com/gmail/nossr50/core/runnables/commands/MctopCommandDisplayTask.java
  70. 2 2
      core/src/main/java/com/gmail/nossr50/core/runnables/database/UserPurgeTask.java
  71. 3 3
      core/src/main/java/com/gmail/nossr50/core/runnables/items/ChimaeraWingWarmup.java
  72. 2 2
      core/src/main/java/com/gmail/nossr50/core/runnables/items/TeleportationWarmup.java
  73. 2 2
      core/src/main/java/com/gmail/nossr50/core/runnables/party/PartyAutoKickTask.java
  74. 3 3
      core/src/main/java/com/gmail/nossr50/core/runnables/party/PartyChatTask.java
  75. 4 4
      core/src/main/java/com/gmail/nossr50/core/runnables/player/PlayerProfileLoadingTask.java
  76. 2 2
      core/src/main/java/com/gmail/nossr50/core/runnables/skills/AbilityDisableTask.java
  77. 2 2
      core/src/main/java/com/gmail/nossr50/core/runnables/skills/ToolLowerTask.java
  78. 11 11
      core/src/main/java/com/gmail/nossr50/core/skills/PrimarySkillType.java
  79. 3 3
      core/src/main/java/com/gmail/nossr50/core/skills/SuperAbilityType.java
  80. 2 2
      core/src/main/java/com/gmail/nossr50/core/skills/child/salvage/Salvage.java
  81. 5 5
      core/src/main/java/com/gmail/nossr50/core/skills/child/salvage/SalvageManager.java
  82. 3 3
      core/src/main/java/com/gmail/nossr50/core/skills/child/smelting/SmeltingManager.java
  83. 2 2
      core/src/main/java/com/gmail/nossr50/core/skills/primary/acrobatics/Acrobatics.java
  84. 2 2
      core/src/main/java/com/gmail/nossr50/core/skills/primary/excavation/ExcavationManager.java
  85. 4 4
      core/src/main/java/com/gmail/nossr50/core/skills/primary/fishing/FishingManager.java
  86. 3 3
      core/src/main/java/com/gmail/nossr50/core/skills/primary/herbalism/HerbalismManager.java
  87. 2 2
      core/src/main/java/com/gmail/nossr50/core/skills/primary/mining/BlastMining.java
  88. 3 3
      core/src/main/java/com/gmail/nossr50/core/skills/primary/mining/MiningManager.java
  89. 2 2
      core/src/main/java/com/gmail/nossr50/core/skills/primary/repair/Repair.java
  90. 5 5
      core/src/main/java/com/gmail/nossr50/core/skills/primary/repair/RepairManager.java
  91. 8 8
      core/src/main/java/com/gmail/nossr50/core/skills/primary/taming/TamingManager.java
  92. 2 2
      core/src/main/java/com/gmail/nossr50/core/skills/primary/taming/TrackedTamingEntity.java
  93. 2 2
      core/src/main/java/com/gmail/nossr50/core/skills/primary/unarmed/Unarmed.java
  94. 4 4
      core/src/main/java/com/gmail/nossr50/core/skills/primary/woodcutting/Woodcutting.java
  95. 5 5
      core/src/main/java/com/gmail/nossr50/core/skills/subskills/acrobatics/Roll.java
  96. 2 2
      core/src/main/java/com/gmail/nossr50/core/skills/treasure/Treasure.java
  97. 15 15
      core/src/main/java/com/gmail/nossr50/core/util/ChimaeraWing.java
  98. 5 5
      core/src/main/java/com/gmail/nossr50/core/util/HardcoreManager.java
  99. 2 2
      core/src/main/java/com/gmail/nossr50/core/util/ItemUtils.java
  100. 6 6
      core/src/main/java/com/gmail/nossr50/core/util/Misc.java

+ 3 - 3
bukkit/src/main/java/com/gmail/nossr50/commands/MHDCommand.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.commands;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.data.database.FlatfileDatabaseManager;
 import com.gmail.nossr50.core.data.database.SQLDatabaseManager;
@@ -21,7 +21,7 @@ public class MHDCommand implements TabExecutor {
             SQLDatabaseManager m = (SQLDatabaseManager) mcMMO.getDatabaseManager();
             m.resetMobHealthSettings();
             for (McMMOPlayer player : UserManager.getPlayers()) {
-                player.getProfile().setMobHealthbarType(Config.getInstance().getMobHealthbarDefault());
+                player.getProfile().setMobHealthbarType(MainConfig.getInstance().getMobHealthbarDefault());
             }
             sender.sendMessage("Mob health reset");
             return true;
@@ -30,7 +30,7 @@ public class MHDCommand implements TabExecutor {
             FlatfileDatabaseManager m = (FlatfileDatabaseManager) mcMMO.getDatabaseManager();
             m.resetMobHealthSettings();
             for (McMMOPlayer player : UserManager.getPlayers()) {
-                player.getProfile().setMobHealthbarType(Config.getInstance().getMobHealthbarDefault());
+                player.getProfile().setMobHealthbarType(MainConfig.getInstance().getMobHealthbarDefault());
             }
             sender.sendMessage("Mob health reset");
             return true;

+ 2 - 2
bukkit/src/main/java/com/gmail/nossr50/commands/McmmoCommand.java

@@ -1,7 +1,7 @@
 package com.gmail.nossr50.commands;
 
 import com.gmail.nossr50.commands.party.PartySubcommandType;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.locale.LocaleLoader;
 import com.gmail.nossr50.core.util.Permissions;
 import com.gmail.nossr50.mcMMO;
@@ -24,7 +24,7 @@ public class McmmoCommand implements CommandExecutor {
                 String[] mcSplit = description.split(",");
                 sender.sendMessage(mcSplit);
 
-                if (Config.getInstance().getDonateMessageEnabled()) {
+                if (MainConfig.getInstance().getDonateMessageEnabled()) {
                     sender.sendMessage(LocaleLoader.getString("MOTD.Donate"));
                     sender.sendMessage(ChatColor.GOLD + " - " + ChatColor.GREEN + "com.gmail.nossr50@com.gmail.com" + ChatColor.GOLD + " Paypal");
                 }

+ 2 - 2
bukkit/src/main/java/com/gmail/nossr50/commands/McscoreboardCommand.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.commands;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.locale.LocaleLoader;
 import com.gmail.nossr50.core.util.commands.CommandUtils;
 import com.gmail.nossr50.core.util.scoreboards.ScoreboardManager;
@@ -31,7 +31,7 @@ public class McscoreboardCommand implements TabExecutor {
                 }
 
                 if (args[0].equalsIgnoreCase("keep")) {
-                    if (!Config.getInstance().getAllowKeepBoard() || !Config.getInstance().getScoreboardsEnabled()) {
+                    if (!MainConfig.getInstance().getAllowKeepBoard() || !MainConfig.getInstance().getScoreboardsEnabled()) {
                         sender.sendMessage(LocaleLoader.getString("Commands.Disabled"));
                         return true;
                     }

+ 2 - 2
bukkit/src/main/java/com/gmail/nossr50/commands/chat/ChatCommand.java

@@ -2,7 +2,7 @@ package com.gmail.nossr50.commands.chat;
 
 import com.gmail.nossr50.core.chat.ChatManager;
 import com.gmail.nossr50.core.chat.ChatManagerFactory;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.chat.ChatMode;
 import com.gmail.nossr50.core.datatypes.party.PartyFeature;
@@ -118,7 +118,7 @@ public abstract class ChatCommand implements TabExecutor {
             return;
         }
 
-        if (chatMode == ChatMode.PARTY && (mcMMOPlayer.getParty().getLevel() < Config.getInstance().getPartyFeatureUnlockLevel(PartyFeature.CHAT))) {
+        if (chatMode == ChatMode.PARTY && (mcMMOPlayer.getParty().getLevel() < MainConfig.getInstance().getPartyFeatureUnlockLevel(PartyFeature.CHAT))) {
             sender.sendMessage(LocaleLoader.getString("Party.Feature.Disabled.1"));
             return;
         }

+ 2 - 2
bukkit/src/main/java/com/gmail/nossr50/commands/chat/PartyChatCommand.java

@@ -1,7 +1,7 @@
 package com.gmail.nossr50.commands.chat;
 
 import com.gmail.nossr50.core.chat.PartyChatManager;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.chat.ChatMode;
 import com.gmail.nossr50.core.datatypes.party.Party;
@@ -29,7 +29,7 @@ public class PartyChatCommand extends ChatCommand {
                 return;
             }
 
-            if (party.getLevel() < Config.getInstance().getPartyFeatureUnlockLevel(PartyFeature.CHAT)) {
+            if (party.getLevel() < MainConfig.getInstance().getPartyFeatureUnlockLevel(PartyFeature.CHAT)) {
                 sender.sendMessage(LocaleLoader.getString("Party.Feature.Disabled.1"));
                 return;
             }

+ 2 - 2
bukkit/src/main/java/com/gmail/nossr50/commands/database/McpurgeCommand.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.commands.database;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.locale.LocaleLoader;
 import com.gmail.nossr50.mcMMO;
 import com.google.common.collect.ImmutableList;
@@ -17,7 +17,7 @@ public class McpurgeCommand implements TabExecutor {
             case 0:
                 mcMMO.getDatabaseManager().purgePowerlessUsers();
 
-                if (Config.getInstance().getOldUsersCutoff() != -1) {
+                if (MainConfig.getInstance().getOldUsersCutoff() != -1) {
                     mcMMO.getDatabaseManager().purgeOldUsers();
                 }
 

+ 2 - 2
bukkit/src/main/java/com/gmail/nossr50/commands/database/MmoshowdbCommand.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.commands.database;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.database.DatabaseManagerFactory;
 import com.gmail.nossr50.core.locale.LocaleLoader;
 import com.google.common.collect.ImmutableList;
@@ -22,7 +22,7 @@ public class MmoshowdbCommand implements TabExecutor {
                     return true;
                 }
 
-                sender.sendMessage(LocaleLoader.getString("Commands.mmoshowdb", (Config.getInstance().getUseMySQL() ? "sql" : "flatfile")));
+                sender.sendMessage(LocaleLoader.getString("Commands.mmoshowdb", (MainConfig.getInstance().getUseMySQL() ? "sql" : "flatfile")));
                 return true;
 
             default:

+ 2 - 2
bukkit/src/main/java/com/gmail/nossr50/commands/hardcore/HardcoreCommand.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.commands.hardcore;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.locale.LocaleLoader;
 import com.gmail.nossr50.core.skills.PrimarySkillType;
 import com.gmail.nossr50.core.util.Permissions;
@@ -45,7 +45,7 @@ public class HardcoreCommand extends HardcoreModeCommand {
 
     @Override
     protected void modify(CommandSender sender, double newPercentage) {
-        Config.getInstance().setHardcoreDeathStatPenaltyPercentage(newPercentage);
+        MainConfig.getInstance().setHardcoreDeathStatPenaltyPercentage(newPercentage);
         sender.sendMessage(LocaleLoader.getString("Hardcore.DeathStatLoss.PercentageChanged", percent.format(newPercentage / 100.0D)));
     }
 

+ 2 - 2
bukkit/src/main/java/com/gmail/nossr50/commands/hardcore/VampirismCommand.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.commands.hardcore;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.locale.LocaleLoader;
 import com.gmail.nossr50.core.skills.PrimarySkillType;
 import com.gmail.nossr50.core.util.Permissions;
@@ -45,7 +45,7 @@ public class VampirismCommand extends HardcoreModeCommand {
 
     @Override
     protected void modify(CommandSender sender, double newPercentage) {
-        Config.getInstance().setHardcoreVampirismStatLeechPercentage(newPercentage);
+        MainConfig.getInstance().setHardcoreVampirismStatLeechPercentage(newPercentage);
         sender.sendMessage(LocaleLoader.getString("Hardcore.Vampirism.PercentageChanged", percent.format(newPercentage / 100.0D)));
     }
 

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

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.commands.party;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.party.Party;
 import com.gmail.nossr50.core.datatypes.party.PartyFeature;
@@ -78,7 +78,7 @@ public class PartyInfoCommand implements CommandExecutor {
     }
 
     private boolean isUnlockedFeature(Party party, PartyFeature partyFeature) {
-        return party.getLevel() >= Config.getInstance().getPartyFeatureUnlockLevel(partyFeature);
+        return party.getLevel() >= MainConfig.getInstance().getPartyFeatureUnlockLevel(partyFeature);
     }
 
     private void displayShareModeInfo(Player player, Party party) {

+ 2 - 2
bukkit/src/main/java/com/gmail/nossr50/commands/party/PartyInviteCommand.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.commands.party;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.party.Party;
 import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
@@ -47,7 +47,7 @@ public class PartyInviteCommand implements CommandExecutor {
                 Party playerParty = mcMMOPlayer.getParty();
 
                 if (PartyManager.isPartyFull(target, playerParty)) {
-                    player.sendMessage(LocaleLoader.getString("Commands.Party.PartyFull.Invite", target.getName(), playerParty.toString(), Config.getInstance().getPartyMaxSize()));
+                    player.sendMessage(LocaleLoader.getString("Commands.Party.PartyFull.Invite", target.getName(), playerParty.toString(), MainConfig.getInstance().getPartyMaxSize()));
                     return true;
                 }
 

+ 2 - 2
bukkit/src/main/java/com/gmail/nossr50/commands/party/PartyItemShareCommand.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.commands.party;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.party.ItemShareType;
 import com.gmail.nossr50.core.datatypes.party.Party;
@@ -19,7 +19,7 @@ public class PartyItemShareCommand implements CommandExecutor {
     public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
         Party party = UserManager.getPlayer((Player) sender).getParty();
 
-        if (party.getLevel() < Config.getInstance().getPartyFeatureUnlockLevel(PartyFeature.ITEM_SHARE)) {
+        if (party.getLevel() < MainConfig.getInstance().getPartyFeatureUnlockLevel(PartyFeature.ITEM_SHARE)) {
             sender.sendMessage(LocaleLoader.getString("Party.Feature.Disabled.4"));
             return true;
         }

+ 2 - 2
bukkit/src/main/java/com/gmail/nossr50/commands/party/PartyXpShareCommand.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.commands.party;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.party.Party;
 import com.gmail.nossr50.core.datatypes.party.PartyFeature;
@@ -18,7 +18,7 @@ public class PartyXpShareCommand implements CommandExecutor {
     public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
         Party party = UserManager.getPlayer((Player) sender).getParty();
 
-        if (party.getLevel() < Config.getInstance().getPartyFeatureUnlockLevel(PartyFeature.XP_SHARE)) {
+        if (party.getLevel() < MainConfig.getInstance().getPartyFeatureUnlockLevel(PartyFeature.XP_SHARE)) {
             sender.sendMessage(LocaleLoader.getString("Party.Feature.Disabled.5"));
             return true;
         }

+ 3 - 3
bukkit/src/main/java/com/gmail/nossr50/commands/party/alliance/PartyAllianceCommand.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.commands.party.alliance;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.party.Party;
 import com.gmail.nossr50.core.datatypes.party.PartyFeature;
@@ -42,7 +42,7 @@ public class PartyAllianceCommand implements TabExecutor {
 
         switch (args.length) {
             case 1:
-                if (playerParty.getLevel() < Config.getInstance().getPartyFeatureUnlockLevel(PartyFeature.ALLIANCE)) {
+                if (playerParty.getLevel() < MainConfig.getInstance().getPartyFeatureUnlockLevel(PartyFeature.ALLIANCE)) {
                     sender.sendMessage(LocaleLoader.getString("Party.Feature.Disabled.3"));
                     return true;
                 }
@@ -60,7 +60,7 @@ public class PartyAllianceCommand implements TabExecutor {
 
             case 2:
             case 3:
-                if (playerParty.getLevel() < Config.getInstance().getPartyFeatureUnlockLevel(PartyFeature.ALLIANCE)) {
+                if (playerParty.getLevel() < MainConfig.getInstance().getPartyFeatureUnlockLevel(PartyFeature.ALLIANCE)) {
                     sender.sendMessage(LocaleLoader.getString("Party.Feature.Disabled.3"));
                     return true;
                 }

+ 3 - 3
bukkit/src/main/java/com/gmail/nossr50/commands/party/teleport/PtpAcceptCommand.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.commands.party.teleport;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.party.PartyTeleportRecord;
 import com.gmail.nossr50.core.locale.LocaleLoader;
@@ -28,7 +28,7 @@ public class PtpAcceptCommand implements CommandExecutor {
             return true;
         }
 
-        if (SkillUtils.cooldownExpired(ptpRecord.getTimeout(), Config.getInstance().getPTPCommandTimeout())) {
+        if (SkillUtils.cooldownExpired(ptpRecord.getTimeout(), MainConfig.getInstance().getPTPCommandTimeout())) {
             ptpRecord.removeRequest();
             player.sendMessage(LocaleLoader.getString("Commands.ptp.RequestExpired"));
             return true;
@@ -41,7 +41,7 @@ public class PtpAcceptCommand implements CommandExecutor {
             return true;
         }
 
-        if (Config.getInstance().getPTPCommandWorldPermissions()) {
+        if (MainConfig.getInstance().getPTPCommandWorldPermissions()) {
             World targetWorld = target.getWorld();
             World playerWorld = player.getWorld();
 

+ 6 - 6
bukkit/src/main/java/com/gmail/nossr50/commands/party/teleport/PtpCommand.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.commands.party.teleport;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.config.WorldBlacklist;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.party.Party;
@@ -72,7 +72,7 @@ public class PtpCommand implements TabExecutor {
         McMMOPlayer mcMMOPlayer = UserManager.getPlayer(teleportingPlayer);
         McMMOPlayer mcMMOTarget = UserManager.getPlayer(targetPlayer);
 
-        long warmup = Config.getInstance().getPTPCommandWarmup();
+        long warmup = MainConfig.getInstance().getPTPCommandWarmup();
 
         mcMMOPlayer.actualizeTeleportCommenceLocation(teleportingPlayer);
 
@@ -115,7 +115,7 @@ public class PtpCommand implements TabExecutor {
 
         Party party = mcMMOPlayer.getParty();
 
-        if (party.getLevel() < Config.getInstance().getPartyFeatureUnlockLevel(PartyFeature.TELEPORT)) {
+        if (party.getLevel() < MainConfig.getInstance().getPartyFeatureUnlockLevel(PartyFeature.TELEPORT)) {
             sender.sendMessage(LocaleLoader.getString("Party.Feature.Disabled.2"));
             return true;
         }
@@ -131,7 +131,7 @@ public class PtpCommand implements TabExecutor {
                 }
 
                 long recentlyHurt = mcMMOPlayer.getRecentlyHurt();
-                int hurtCooldown = Config.getInstance().getPTPCommandRecentlyHurtCooldown();
+                int hurtCooldown = MainConfig.getInstance().getPTPCommandRecentlyHurtCooldown();
 
                 if (hurtCooldown > 0) {
                     int timeRemaining = SkillUtils.calculateTimeLeft(recentlyHurt * Misc.TIME_CONVERSION_FACTOR, hurtCooldown, player);
@@ -151,7 +151,7 @@ public class PtpCommand implements TabExecutor {
                     return true;
                 }
 
-                int ptpCooldown = Config.getInstance().getPTPCommandCooldown();
+                int ptpCooldown = MainConfig.getInstance().getPTPCommandCooldown();
                 long ptpLastUse = mcMMOPlayer.getPartyTeleportRecord().getLastUse();
 
                 if (ptpCooldown > 0) {
@@ -216,6 +216,6 @@ public class PtpCommand implements TabExecutor {
         player.sendMessage(LocaleLoader.getString("Commands.Invite.Success"));
 
         target.sendMessage(LocaleLoader.getString("Commands.ptp.Request1", player.getName()));
-        target.sendMessage(LocaleLoader.getString("Commands.ptp.Request2", Config.getInstance().getPTPCommandTimeout()));
+        target.sendMessage(LocaleLoader.getString("Commands.ptp.Request2", MainConfig.getInstance().getPTPCommandTimeout()));
     }
 }

+ 5 - 5
bukkit/src/main/java/com/gmail/nossr50/commands/player/InspectCommand.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.commands.player;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.core.datatypes.player.PlayerProfile;
@@ -40,10 +40,10 @@ public class InspectCommand implements TabExecutor {
                         return true;
                     }
 
-                    if (Config.getInstance().getScoreboardsEnabled() && sender instanceof Player && Config.getInstance().getInspectUseBoard()) {
+                    if (MainConfig.getInstance().getScoreboardsEnabled() && sender instanceof Player && MainConfig.getInstance().getInspectUseBoard()) {
                         ScoreboardManager.enablePlayerInspectScoreboard((Player) sender, profile);
 
-                        if (!Config.getInstance().getInspectUseChat()) {
+                        if (!MainConfig.getInstance().getInspectUseChat()) {
                             return true;
                         }
                     }
@@ -77,10 +77,10 @@ public class InspectCommand implements TabExecutor {
                         return true;
                     }
 
-                    if (Config.getInstance().getScoreboardsEnabled() && sender instanceof Player && Config.getInstance().getInspectUseBoard()) {
+                    if (MainConfig.getInstance().getScoreboardsEnabled() && sender instanceof Player && MainConfig.getInstance().getInspectUseBoard()) {
                         ScoreboardManager.enablePlayerInspectScoreboard((Player) sender, mcMMOPlayer.getProfile());
 
-                        if (!Config.getInstance().getInspectUseChat()) {
+                        if (!MainConfig.getInstance().getInspectUseChat()) {
                             return true;
                         }
                     }

+ 3 - 3
bukkit/src/main/java/com/gmail/nossr50/commands/player/MccooldownCommand.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.commands.player;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.core.locale.LocaleLoader;
@@ -30,10 +30,10 @@ public class MccooldownCommand implements TabExecutor {
             case 0:
                 Player player = (Player) sender;
 
-                if (Config.getInstance().getScoreboardsEnabled() && Config.getInstance().getCooldownUseBoard()) {
+                if (MainConfig.getInstance().getScoreboardsEnabled() && MainConfig.getInstance().getCooldownUseBoard()) {
                     ScoreboardManager.enablePlayerCooldownScoreboard(player);
 
-                    if (!Config.getInstance().getCooldownUseChat()) {
+                    if (!MainConfig.getInstance().getCooldownUseChat()) {
                         return true;
                     }
                 }

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

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.commands.player;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.core.locale.LocaleLoader;
@@ -87,7 +87,7 @@ public class McrankCommand implements TabExecutor {
     private void display(CommandSender sender, String playerName) {
         if (sender instanceof Player) {
             McMMOPlayer mcMMOPlayer = UserManager.getPlayer(sender.getName());
-            long cooldownMillis = Math.max(Config.getInstance().getDatabasePlayerCooldown(), 1750);
+            long cooldownMillis = Math.max(MainConfig.getInstance().getDatabasePlayerCooldown(), 1750);
 
             if (mcMMOPlayer.getDatabaseATS() + cooldownMillis > System.currentTimeMillis()) {
                 sender.sendMessage(LocaleLoader.getString("Commands.Database.Cooldown"));
@@ -104,8 +104,8 @@ public class McrankCommand implements TabExecutor {
             mcMMOPlayer.actualizeDatabaseATS();
         }
 
-        boolean useBoard = Config.getInstance().getScoreboardsEnabled() && (sender instanceof Player) && (Config.getInstance().getRankUseBoard());
-        boolean useChat = !useBoard || Config.getInstance().getRankUseChat();
+        boolean useBoard = MainConfig.getInstance().getScoreboardsEnabled() && (sender instanceof Player) && (MainConfig.getInstance().getRankUseBoard());
+        boolean useChat = !useBoard || MainConfig.getInstance().getRankUseChat();
 
         new McrankCommandAsyncTask(playerName, sender, useBoard, useChat).runTaskAsynchronously(mcMMO.p);
     }

+ 4 - 4
bukkit/src/main/java/com/gmail/nossr50/commands/player/McstatsCommand.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.commands.player;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.locale.LocaleLoader;
 import com.gmail.nossr50.core.util.commands.CommandUtils;
@@ -28,10 +28,10 @@ public class McstatsCommand implements TabExecutor {
             case 0:
                 Player player = (Player) sender;
 
-                if (Config.getInstance().getStatsUseBoard() && Config.getInstance().getScoreboardsEnabled()) {
+                if (MainConfig.getInstance().getStatsUseBoard() && MainConfig.getInstance().getScoreboardsEnabled()) {
                     ScoreboardManager.enablePlayerStatsScoreboard(player);
 
-                    if (!Config.getInstance().getStatsUseChat()) {
+                    if (!MainConfig.getInstance().getStatsUseChat()) {
                         return true;
                     }
                 }
@@ -43,7 +43,7 @@ public class McstatsCommand implements TabExecutor {
                 CommandUtils.printCombatSkills(player);
                 CommandUtils.printMiscSkills(player);
 
-                int powerLevelCap = Config.getInstance().getPowerLevelCap();
+                int powerLevelCap = MainConfig.getInstance().getPowerLevelCap();
 
                 if (powerLevelCap != Integer.MAX_VALUE) {
                     player.sendMessage(LocaleLoader.getString("Commands.PowerLevel.Capped", UserManager.getPlayer(player).getPowerLevel(), powerLevelCap));

+ 4 - 4
bukkit/src/main/java/com/gmail/nossr50/commands/player/MctopCommand.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.commands.player;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.core.locale.LocaleLoader;
@@ -87,7 +87,7 @@ public class MctopCommand implements TabExecutor {
             }
 
             McMMOPlayer mcMMOPlayer = UserManager.getPlayer(sender.getName());
-            long cooldownMillis = Math.max(Config.getInstance().getDatabasePlayerCooldown(), 1750);
+            long cooldownMillis = Math.max(MainConfig.getInstance().getDatabasePlayerCooldown(), 1750);
 
             if (mcMMOPlayer.getDatabaseATS() + cooldownMillis > System.currentTimeMillis()) {
                 double seconds = ((mcMMOPlayer.getDatabaseATS() + cooldownMillis) - System.currentTimeMillis()) / 1000;
@@ -113,8 +113,8 @@ public class MctopCommand implements TabExecutor {
     }
 
     private void display(int page, PrimarySkillType skill, CommandSender sender) {
-        boolean useBoard = (sender instanceof Player) && (Config.getInstance().getTopUseBoard());
-        boolean useChat = !useBoard || Config.getInstance().getTopUseChat();
+        boolean useBoard = (sender instanceof Player) && (MainConfig.getInstance().getTopUseBoard());
+        boolean useChat = !useBoard || MainConfig.getInstance().getTopUseChat();
 
         new MctopCommandAsyncTask(page, skill, sender, useBoard, useChat).runTaskAsynchronously(mcMMO.p);
     }

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

@@ -1,7 +1,7 @@
 package com.gmail.nossr50.commands.skills;
 
 import com.gmail.nossr50.core.config.AdvancedConfig;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.core.locale.LocaleLoader;
@@ -105,13 +105,13 @@ public abstract class SkillCommand implements TabExecutor {
 
 
                 //Link Header
-                if (Config.getInstance().getUrlLinksEnabled()) {
+                if (MainConfig.getInstance().getUrlLinksEnabled()) {
                     player.sendMessage(LocaleLoader.getString("Overhaul.mcMMO.Header"));
                     TextComponentFactory.sendPlayerUrlHeader(player);
                 }
 
 
-                if (Config.getInstance().getScoreboardsEnabled() && Config.getInstance().getSkillUseBoard()) {
+                if (MainConfig.getInstance().getScoreboardsEnabled() && MainConfig.getInstance().getSkillUseBoard()) {
                     ScoreboardManager.enablePlayerSkillScoreboard(player, skill);
                 }
 

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

@@ -1,7 +1,7 @@
 package com.gmail.nossr50.listeners;
 
 import com.gmail.nossr50.config.experience.ExperienceConfig;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.config.ChunkConversionOptions;
 import com.gmail.nossr50.core.config.WorldBlacklist;
 import com.gmail.nossr50.core.data.UserManager;
@@ -429,7 +429,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.
          */
-        if (mcMMOPlayer.getAbilityMode(SuperAbilityType.TREE_FELLER) && BlockUtils.isLog(blockState) && Config.getInstance().getTreeFellerSoundsEnabled()) {
+        if (mcMMOPlayer.getAbilityMode(SuperAbilityType.TREE_FELLER) && BlockUtils.isLog(blockState) && MainConfig.getInstance().getTreeFellerSoundsEnabled()) {
             SoundManager.sendSound(player, blockState.getLocation(), SoundType.FIZZ);
         }
     }

+ 3 - 3
bukkit/src/main/java/com/gmail/nossr50/listeners/EntityListener.java

@@ -2,7 +2,7 @@ package com.gmail.nossr50.listeners;
 
 import com.gmail.nossr50.config.experience.ExperienceConfig;
 import com.gmail.nossr50.core.config.AdvancedConfig;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.config.WorldBlacklist;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.meta.OldName;
@@ -208,7 +208,7 @@ public class EntityListener implements Listener {
                 Player attackingPlayer = (Player) attacker;
                 if (event.getDamage(DamageModifier.ABSORPTION) > 0) {
                     //If friendly fire is off don't allow players to hurt one another
-                    if (!Config.getInstance().getPartyFriendlyFire())
+                    if (!MainConfig.getInstance().getPartyFriendlyFire())
                         if ((PartyManager.inSameParty(defendingPlayer, attackingPlayer) || PartyManager.areAllies(defendingPlayer, attackingPlayer)) && !(Permissions.friendlyFire(attackingPlayer) && Permissions.friendlyFire(defendingPlayer))) {
                             event.setCancelled(true);
                             return;
@@ -276,7 +276,7 @@ public class EntityListener implements Listener {
             }
 
             //Party Friendly Fire
-            if (!Config.getInstance().getPartyFriendlyFire())
+            if (!MainConfig.getInstance().getPartyFriendlyFire())
                 if ((PartyManager.inSameParty(defendingPlayer, attackingPlayer) || PartyManager.areAllies(defendingPlayer, attackingPlayer)) && !(Permissions.friendlyFire(attackingPlayer) && Permissions.friendlyFire(defendingPlayer))) {
                     event.setCancelled(true);
                     return;

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

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.listeners;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.config.WorldBlacklist;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.runnables.player.PlayerUpdateInventoryTask;
@@ -373,17 +373,17 @@ public class InventoryListener implements Listener {
 
         ItemStack item = event.getItem();
 
-        if (Config.getInstance().getPreventHopperTransferIngredients() && item.getType() != Material.POTION && item.getType() != Material.SPLASH_POTION && item.getType() != Material.LINGERING_POTION) {
+        if (MainConfig.getInstance().getPreventHopperTransferIngredients() && item.getType() != Material.POTION && item.getType() != Material.SPLASH_POTION && item.getType() != Material.LINGERING_POTION) {
             event.setCancelled(true);
             return;
         }
 
-        if (Config.getInstance().getPreventHopperTransferBottles() && (item.getType() == Material.POTION || item.getType() == Material.SPLASH_POTION || item.getType() == Material.LINGERING_POTION)) {
+        if (MainConfig.getInstance().getPreventHopperTransferBottles() && (item.getType() == Material.POTION || item.getType() == Material.SPLASH_POTION || item.getType() == Material.LINGERING_POTION)) {
             event.setCancelled(true);
             return;
         }
 
-        if (Config.getInstance().getEnabledForHoppers() && AlchemyPotionBrewer.isValidIngredient(null, item)) {
+        if (MainConfig.getInstance().getEnabledForHoppers() && AlchemyPotionBrewer.isValidIngredient(null, item)) {
             AlchemyPotionBrewer.scheduleCheck(null, (BrewingStand) holder);
         }
     }

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

@@ -4,7 +4,7 @@ import com.gmail.nossr50.config.experience.ExperienceConfig;
 import com.gmail.nossr50.core.chat.ChatManager;
 import com.gmail.nossr50.core.chat.ChatManagerFactory;
 import com.gmail.nossr50.core.chat.PartyChatManager;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.config.WorldBlacklist;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.chat.ChatMode;
@@ -74,7 +74,7 @@ public class PlayerListener implements Listener {
                 return;
         }
 
-        if (!UserManager.hasPlayerDataKey(player) || Config.getInstance().getXPAfterTeleportCooldown() <= 0 || event.getFrom().equals(event.getTo())) {
+        if (!UserManager.hasPlayerDataKey(player) || MainConfig.getInstance().getXPAfterTeleportCooldown() <= 0 || event.getFrom().equals(event.getTo())) {
             return;
         }
 
@@ -251,7 +251,7 @@ public class PlayerListener implements Listener {
                 //TODO Update to new API once available! Waiting for case CAUGHT_TREASURE:
                 Item fishingCatch = (Item) event.getCaught();
 
-                if (Config.getInstance().getFishingOverrideTreasures() &&
+                if (MainConfig.getInstance().getFishingOverrideTreasures() &&
                         fishingCatch.getItemStack().getType() != Material.SALMON &&
                         fishingCatch.getItemStack().getType() != Material.COD &&
                         fishingCatch.getItemStack().getType() != Material.TROPICAL_FISH &&
@@ -397,7 +397,7 @@ public class PlayerListener implements Listener {
 
             /*if (player.getInventory().getItemInMainHand().getType() == Material.AIR) {
                 Unarmed.handleItemPickup(player, event);
-                *//*boolean cancel = Config.getInstance().getUnarmedItemPickupDisabled() || pickupSuccess;
+                *//*boolean cancel = MainConfig.getInstance().getUnarmedItemPickupDisabled() || pickupSuccess;
                 event.setCancelled(cancel);
 
                 if (pickupSuccess) {
@@ -448,7 +448,7 @@ public class PlayerListener implements Listener {
 
         new PlayerProfileLoadingTask(player).runTaskLaterAsynchronously(mcMMO.p, 1); // 1 Tick delay to ensure the player is marked as online before we begin loading
 
-        if (Config.getInstance().getMOTDEnabled() && Permissions.motd(player)) {
+        if (MainConfig.getInstance().getMOTDEnabled() && Permissions.motd(player)) {
             Motd.displayAll(player);
         }
 
@@ -509,7 +509,7 @@ public class PlayerListener implements Listener {
             case RIGHT_CLICK_BLOCK:
                 Material type = block.getType();
 
-                if (!Config.getInstance().getAbilitiesOnlyActivateWhenSneaking() || player.isSneaking()) {
+                if (!MainConfig.getInstance().getAbilitiesOnlyActivateWhenSneaking() || player.isSneaking()) {
                     /* REPAIR CHECKS */
                     if (type == Repair.anvilMaterial && PrimarySkillType.REPAIR.getPermissions(player) && mcMMO.getRepairableManager().isRepairable(heldItem)) {
                         RepairManager repairManager = mcMMOPlayer.getRepairManager();
@@ -548,7 +548,7 @@ public class PlayerListener implements Listener {
             case LEFT_CLICK_BLOCK:
                 type = block.getType();
 
-                if (!Config.getInstance().getAbilitiesOnlyActivateWhenSneaking() || player.isSneaking()) {
+                if (!MainConfig.getInstance().getAbilitiesOnlyActivateWhenSneaking() || player.isSneaking()) {
                     /* REPAIR CHECKS */
                     if (type == Repair.anvilMaterial && PrimarySkillType.REPAIR.getPermissions(player) && mcMMO.getRepairableManager().isRepairable(heldItem)) {
                         RepairManager repairManager = mcMMOPlayer.getRepairManager();
@@ -615,7 +615,7 @@ public class PlayerListener implements Listener {
 
                 /* ACTIVATION & ITEM CHECKS */
                 if (BlockUtils.canActivateTools(blockState)) {
-                    if (Config.getInstance().getAbilitiesEnabled()) {
+                    if (MainConfig.getInstance().getAbilitiesEnabled()) {
                         if (BlockUtils.canActivateHerbalism(blockState)) {
                             mcMMOPlayer.processAbilityActivation(PrimarySkillType.HERBALISM);
                         }
@@ -669,7 +669,7 @@ public class PlayerListener implements Listener {
                 }
 
                 /* ACTIVATION CHECKS */
-                if (Config.getInstance().getAbilitiesEnabled()) {
+                if (MainConfig.getInstance().getAbilitiesEnabled()) {
                     mcMMOPlayer.processAbilityActivation(PrimarySkillType.AXES);
                     mcMMOPlayer.processAbilityActivation(PrimarySkillType.EXCAVATION);
                     mcMMOPlayer.processAbilityActivation(PrimarySkillType.HERBALISM);
@@ -701,11 +701,11 @@ public class PlayerListener implements Listener {
                 Material type = heldItem.getType();
                 TamingManager tamingManager = mcMMOPlayer.getTamingManager();
 
-                if (type == Config.getInstance().getTamingCOTWMaterial(EntityType.WOLF)) {
+                if (type == MainConfig.getInstance().getTamingCOTWMaterial(EntityType.WOLF)) {
                     tamingManager.summonWolf();
-                } else if (type == Config.getInstance().getTamingCOTWMaterial(EntityType.OCELOT)) {
+                } else if (type == MainConfig.getInstance().getTamingCOTWMaterial(EntityType.OCELOT)) {
                     tamingManager.summonOcelot();
-                } else if (type == Config.getInstance().getTamingCOTWMaterial(EntityType.HORSE)) {
+                } else if (type == MainConfig.getInstance().getTamingCOTWMaterial(EntityType.HORSE)) {
                     tamingManager.summonHorse();
                 }
 
@@ -767,7 +767,7 @@ public class PlayerListener implements Listener {
      */
     @EventHandler(priority = EventPriority.LOWEST)
     public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
-        if (!Config.getInstance().getLocale().equalsIgnoreCase("en_US")) {
+        if (!MainConfig.getInstance().getLocale().equalsIgnoreCase("en_US")) {
             String message = event.getMessage();
             String command = message.substring(1).split(" ")[0];
             String lowerCaseCommand = command.toLowerCase();

+ 6 - 6
bukkit/src/main/java/com/gmail/nossr50/listeners/SelfListener.java

@@ -1,7 +1,7 @@
 package com.gmail.nossr50.listeners;
 
 import com.gmail.nossr50.config.experience.ExperienceConfig;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.experience.XPGainReason;
 import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
@@ -38,27 +38,27 @@ public class SelfListener implements Listener {
             UserManager.getPlayer(player).processUnlockNotifications(plugin, event.getSkill(), previousLevelGained);
         }
 
-        if (Config.getInstance().getScoreboardsEnabled())
+        if (MainConfig.getInstance().getScoreboardsEnabled())
             ScoreboardManager.handleLevelUp(player, skill);
 
-        if (!Config.getInstance().getLevelUpEffectsEnabled()) {
+        if (!MainConfig.getInstance().getLevelUpEffectsEnabled()) {
             return;
         }
 
-        if ((event.getSkillLevel() % Config.getInstance().getLevelUpEffectsTier()) == 0) {
+        if ((event.getSkillLevel() % MainConfig.getInstance().getLevelUpEffectsTier()) == 0) {
             skill.celebrateLevelUp(player);
         }
     }
 
     @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
     public void onPlayerXp(McMMOPlayerXpGainEvent event) {
-        if (Config.getInstance().getScoreboardsEnabled())
+        if (MainConfig.getInstance().getScoreboardsEnabled())
             ScoreboardManager.handleXp(event.getPlayer(), event.getSkill());
     }
 
     @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
     public void onAbility(McMMOPlayerAbilityActivateEvent event) {
-        if (Config.getInstance().getScoreboardsEnabled())
+        if (MainConfig.getInstance().getScoreboardsEnabled())
             ScoreboardManager.cooldownUpdate(event.getPlayer(), event.getSkill());
     }
 

+ 19 - 19
bukkit/src/main/java/com/gmail/nossr50/mcMMO.java

@@ -103,7 +103,7 @@ public class mcMMO extends JavaPlugin {
     /* Plugin Checks */
     private static boolean healthBarPluginEnabled;
     private static boolean isRetroModeEnabled;
-    // Config Validation Check
+    // MainConfig Validation Check
     public boolean noErrorsInConfigFiles = true;
     // XP Event Check
     private boolean xpEventEnabled;
@@ -206,7 +206,7 @@ public class mcMMO extends JavaPlugin {
             }
 
             //Store this value so other plugins can check it
-            isRetroModeEnabled = Config.getInstance().getIsRetroMode();
+            isRetroModeEnabled = MainConfig.getInstance().getIsRetroMode();
 
             if (getServer().getName().equals("Cauldron") || getServer().getName().equals("MCPC+")) {
                 checkModConfigs();
@@ -243,7 +243,7 @@ public class mcMMO extends JavaPlugin {
 
             placeStore = ChunkManagerFactory.getChunkManager(); // Get our ChunkletManager
 
-            if (Config.getInstance().getPTPCommandWorldPermissions()) {
+            if (MainConfig.getInstance().getPTPCommandWorldPermissions()) {
                 Permissions.generateWorldTeleportPermissions();
             }
 
@@ -254,11 +254,11 @@ public class mcMMO extends JavaPlugin {
 
             Metrics metrics;
 
-            if (Config.getInstance().getIsMetricsEnabled()) {
+            if (MainConfig.getInstance().getIsMetricsEnabled()) {
                 metrics = new Metrics(this);
                 metrics.addCustomChart(new Metrics.SimplePie("version", () -> getDescription().getVersion()));
 
-                if (Config.getInstance().getIsRetroMode())
+                if (MainConfig.getInstance().getIsRetroMode())
                     metrics.addCustomChart(new Metrics.SimplePie("scaling", () -> "Standard"));
                 else
                     metrics.addCustomChart(new Metrics.SimplePie("scaling", () -> "Retro"));
@@ -297,7 +297,7 @@ public class mcMMO extends JavaPlugin {
             PartyManager.saveParties(); // Save our parties
 
             //TODO: Needed?
-            if (Config.getInstance().getScoreboardsEnabled())
+            if (MainConfig.getInstance().getScoreboardsEnabled())
                 ScoreboardManager.teardownAll();
 
             formulaManager.saveFormula();
@@ -313,7 +313,7 @@ public class mcMMO extends JavaPlugin {
         debug("Unregister all events...");
         HandlerList.unregisterAll(this); // Cancel event registrations
 
-        if (Config.getInstance().getBackupsEnabled()) {
+        if (MainConfig.getInstance().getBackupsEnabled()) {
             // Remove other tasks BEFORE starting the Backup, or we just cancel it straight away.
             try {
                 ZipLibrary.mcMMOBackup();
@@ -425,19 +425,19 @@ public class mcMMO extends JavaPlugin {
         List<Repairable> repairables = new ArrayList<Repairable>();
         List<Salvageable> salvageables = new ArrayList<Salvageable>();
 
-        if (Config.getInstance().getToolModsEnabled()) {
+        if (MainConfig.getInstance().getToolModsEnabled()) {
             new ToolConfigManager(this);
         }
 
-        if (Config.getInstance().getArmorModsEnabled()) {
+        if (MainConfig.getInstance().getArmorModsEnabled()) {
             new ArmorConfigManager(this);
         }
 
-        if (Config.getInstance().getBlockModsEnabled()) {
+        if (MainConfig.getInstance().getBlockModsEnabled()) {
             new BlockConfigManager(this);
         }
 
-        if (Config.getInstance().getEntityModsEnabled()) {
+        if (MainConfig.getInstance().getEntityModsEnabled()) {
             new EntityConfigManager(this);
         }
 
@@ -487,7 +487,7 @@ public class mcMMO extends JavaPlugin {
 
     private void registerCustomRecipes() {
         getServer().getScheduler().scheduleSyncDelayedTask(this, () -> {
-            if (Config.getInstance().getChimaeraEnabled()) {
+            if (MainConfig.getInstance().getChimaeraEnabled()) {
                 getServer().addRecipe(ChimaeraWing.getChimaeraWingRecipe());
             }
         }, 40);
@@ -495,7 +495,7 @@ public class mcMMO extends JavaPlugin {
 
     private void scheduleTasks() {
         // Periodic save timer (Saves every 10 minutes by default)
-        long saveIntervalTicks = Config.getInstance().getSaveInterval() * 1200;
+        long saveIntervalTicks = MainConfig.getInstance().getSaveInterval() * 1200;
         new SaveTimerTask().runTaskTimer(this, saveIntervalTicks, saveIntervalTicks);
 
         // Cleanup the backups folder
@@ -505,7 +505,7 @@ public class mcMMO extends JavaPlugin {
         new BleedTimerTask().runTaskTimer(this, 1 * Misc.TICK_CONVERSION_FACTOR, 1 * (Misc.TICK_CONVERSION_FACTOR / 2));
 
         // Old & Powerless User remover
-        long purgeIntervalTicks = Config.getInstance().getPurgeInterval() * 60L * 60L * Misc.TICK_CONVERSION_FACTOR;
+        long purgeIntervalTicks = MainConfig.getInstance().getPurgeInterval() * 60L * 60L * Misc.TICK_CONVERSION_FACTOR;
 
         if (purgeIntervalTicks == 0) {
             new UserPurgeTask().runTaskLaterAsynchronously(this, 2 * Misc.TICK_CONVERSION_FACTOR); // Start 2 seconds after startup.
@@ -514,7 +514,7 @@ public class mcMMO extends JavaPlugin {
         }
 
         // Automatically remove old members from parties
-        long kickIntervalTicks = Config.getInstance().getAutoPartyKickInterval() * 60L * 60L * Misc.TICK_CONVERSION_FACTOR;
+        long kickIntervalTicks = MainConfig.getInstance().getAutoPartyKickInterval() * 60L * 60L * Misc.TICK_CONVERSION_FACTOR;
 
         if (kickIntervalTicks == 0) {
             new PartyAutoKickTask().runTaskLater(this, 2 * Misc.TICK_CONVERSION_FACTOR); // Start 2 seconds after startup.
@@ -536,22 +536,22 @@ public class mcMMO extends JavaPlugin {
     }
 
     private void checkModConfigs() {
-        if (!Config.getInstance().getToolModsEnabled()) {
+        if (!MainConfig.getInstance().getToolModsEnabled()) {
             getLogger().warning("Cauldron implementation found, but the custom tool config for mcMMO is disabled!");
             getLogger().info("To enable, set Mods.Tool_Mods_Enabled to TRUE in config.yml.");
         }
 
-        if (!Config.getInstance().getArmorModsEnabled()) {
+        if (!MainConfig.getInstance().getArmorModsEnabled()) {
             getLogger().warning("Cauldron implementation found, but the custom armor config for mcMMO is disabled!");
             getLogger().info("To enable, set Mods.Armor_Mods_Enabled to TRUE in config.yml.");
         }
 
-        if (!Config.getInstance().getBlockModsEnabled()) {
+        if (!MainConfig.getInstance().getBlockModsEnabled()) {
             getLogger().warning("Cauldron implementation found, but the custom block config for mcMMO is disabled!");
             getLogger().info("To enable, set Mods.Block_Mods_Enabled to TRUE in config.yml.");
         }
 
-        if (!Config.getInstance().getEntityModsEnabled()) {
+        if (!MainConfig.getInstance().getEntityModsEnabled()) {
             getLogger().warning("Cauldron implementation found, but the custom entity config for mcMMO is disabled!");
             getLogger().info("To enable, set Mods.Entity_Mods_Enabled to TRUE in config.yml.");
         }

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

@@ -6,6 +6,7 @@ import com.gmail.nossr50.core.mcmmo.plugin.Plugin;
 import com.gmail.nossr50.core.mcmmo.server.Server;
 import com.gmail.nossr50.core.mcmmo.tasks.TaskScheduler;
 import com.gmail.nossr50.core.platform.Platform;
+import com.gmail.nossr50.core.util.ModManager;
 import com.gmail.nossr50.core.util.experience.FormulaManager;
 import com.gmail.nossr50.core.util.upgrade.UpgradeManager;
 
@@ -22,8 +23,9 @@ public class McmmoCore {
 
     //Why do all these things need to be here? Sigh...
     private static DatabaseManager databaseManager;
-    private static UpgradeManager upgradeManager;
+    private static UpgradeManager upgradeManager; //TODO: I can't even remember what this one did
     private static FormulaManager formulaManager;
+    private static ModManager modManager; //TODO: Probably need to rewrite this
 
     /**
      * Returns our Logger
@@ -64,4 +66,8 @@ public class McmmoCore {
     public static FormulaManager getFormulaManager() { return formulaManager; }
 
     public static boolean isRetroModeEnabled() { return retroModeEnabled; }
+
+    public static ModManager getModManager() { return modManager; }
+
+    public static String getModDataFolderPath() { return platform.getModDataFolderPath(); }
 }

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

@@ -1,7 +1,7 @@
 package com.gmail.nossr50.core.api;
 
 import com.gmail.nossr50.core.api.exceptions.*;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.config.experience.ExperienceConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.experience.FormulaType;
@@ -716,7 +716,7 @@ public final class ExperienceAPI {
      * @throws InvalidSkillException if the given skill is not valid
      */
     public static int getLevelCap(String skillType) {
-        return Config.getInstance().getLevelCap(getSkillType(skillType));
+        return MainConfig.getInstance().getLevelCap(getSkillType(skillType));
     }
 
     /**
@@ -727,7 +727,7 @@ public final class ExperienceAPI {
      * @return the overall power level cap
      */
     public static int getPowerLevelCap() {
-        return Config.getInstance().getPowerLevelCap();
+        return MainConfig.getInstance().getPowerLevelCap();
     }
 
     /**

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

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.api;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
 import com.gmail.nossr50.core.datatypes.party.Party;
@@ -101,7 +101,7 @@ public final class PartyAPI {
      * @return the max party size on this server
      */
     public static int getMaxPartySize() {
-        return Config.getInstance().getPartyMaxSize();
+        return MainConfig.getInstance().getPartyMaxSize();
     }
 
     /**

+ 2 - 2
core/src/main/java/com/gmail/nossr50/core/chat/AdminChatManager.java

@@ -1,12 +1,12 @@
 package com.gmail.nossr50.core.chat;
 
 import com.gmail.nossr50.core.McmmoCore;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.events.chat.McMMOAdminChatEvent;
 
 public class AdminChatManager extends ChatManager {
     protected AdminChatManager() {
-        super(Config.getInstance().getAdminDisplayNames(), Config.getInstance().getAdminChatPrefix());
+        super(MainConfig.getInstance().getAdminDisplayNames(), MainConfig.getInstance().getAdminChatPrefix());
     }
 
     @Override

+ 2 - 2
core/src/main/java/com/gmail/nossr50/core/chat/PartyChatManager.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.chat;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.datatypes.party.Party;
 import com.gmail.nossr50.core.runnables.party.PartyChatTask;
 import com.gmail.nossr50.events.chat.McMMOPartyChatEvent;
@@ -10,7 +10,7 @@ public class PartyChatManager extends ChatManager {
     private Party party;
 
     protected PartyChatManager(Plugin plugin) {
-        super(plugin, Config.getInstance().getPartyDisplayNames(), Config.getInstance().getPartyChatPrefix());
+        super(plugin, MainConfig.getInstance().getPartyDisplayNames(), MainConfig.getInstance().getPartyChatPrefix());
     }
 
     public void setParty(Party party) {

+ 1 - 2
core/src/main/java/com/gmail/nossr50/core/config/AdvancedConfig.java

@@ -5,13 +5,12 @@ import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
 import com.gmail.nossr50.core.mcmmo.colors.ChatColor;
 import com.gmail.nossr50.core.skills.SubSkillType;
 import com.gmail.nossr50.core.skills.subskills.AbstractSubSkill;
-import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable;
 
 import java.util.ArrayList;
 import java.util.List;
 
 //@ConfigSerializable
-public class AdvancedConfig extends ConfigurableLoader {
+public class AdvancedConfig extends ConfigValidated {
 
     public static final String SKILLS = "Skills";
     public static final String GENERAL = "General";

+ 218 - 948
core/src/main/java/com/gmail/nossr50/core/config/Config.java

@@ -1,1032 +1,302 @@
 package com.gmail.nossr50.core.config;
 
 import com.gmail.nossr50.core.McmmoCore;
-import com.gmail.nossr50.core.data.database.SQLDatabaseManager;
-import com.gmail.nossr50.core.datatypes.party.PartyFeature;
-import com.gmail.nossr50.core.skills.MobHealthbarType;
-import com.gmail.nossr50.core.skills.PrimarySkillType;
-import com.gmail.nossr50.core.skills.SuperAbilityType;
-import com.gmail.nossr50.core.util.StringUtils;
+import com.google.common.io.Files;
+import ninja.leaping.configurate.ConfigurationNode;
+import ninja.leaping.configurate.commented.CommentedConfigurationNode;
+import ninja.leaping.configurate.loader.ConfigurationLoader;
+import ninja.leaping.configurate.yaml.YAMLConfigurationLoader;
+import org.yaml.snakeyaml.DumperOptions;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
 
-public class Config extends ConfigurableLoader {
-    private static Config instance;
+/**
+ * Handles loading and cacheing configuration settings from a configurable compatible config file
+ */
+//@ConfigSerializable
+public abstract class Config implements VersionedConfig, Unload {
 
-    private Config() {
-        super(McmmoCore.getDataFolderPath().getAbsoluteFile(), "config.yml");
-        validate();
-    }
-
-    public static Config getInstance() {
-        if (instance == null) {
-            instance = new Config();
-        }
-
-        return instance;
-    }
-
-    @Override
-    protected void loadKeys() {
-
-    }
-
-    @Override
-    protected boolean validateKeys() {
-        // Validate all the settings!
-        List<String> reason = new ArrayList<String>();
-
-        /* General Settings */
-        if (getSaveInterval() <= 0) {
-            reason.add("General.Save_Interval should be greater than 0!");
-        }
-
-        /* MySQL Settings */
-        for (SQLDatabaseManager.PoolIdentifier identifier : SQLDatabaseManager.PoolIdentifier.values()) {
-            if (getMySQLMaxConnections(identifier) <= 0) {
-                reason.add("MySQL.Database.MaxConnections." + StringUtils.getCapitalized(identifier.toString()) + " should be greater than 0!");
-            }
-            if (getMySQLMaxPoolSize(identifier) <= 0) {
-                reason.add("MySQL.Database.MaxPoolSize." + StringUtils.getCapitalized(identifier.toString()) + " should be greater than 0!");
-            }
-        }
-
-        /* Mob Healthbar */
-        if (getMobHealthbarTime() == 0) {
-            reason.add("Mob_Healthbar.Display_Time cannot be 0! Set to -1 to disable or set a valid value.");
-        }
-
-        /* Scoreboards */
-        /*if (getRankScoreboardTime() != -1 && getRankScoreboardTime() <= 0) {
-            reason.add("Scoreboard.Types.Rank.Display_Time should be greater than 0, or -1!");
-        }
-
-        if (getStatsScoreboardTime() != -1 && getStatsScoreboardTime() <= 0) {
-            reason.add("Scoreboard.Types.Stats.Display_Time should be greater than 0, or -1!");
-        }
-
-        if (getTopScoreboardTime() != -1 && getTopScoreboardTime() <= 0) {
-            reason.add("Scoreboard.Types.Top.Display_Time should be greater than 0, or -1!");
-        }
-
-        if (getInspectScoreboardTime() != -1 && getInspectScoreboardTime() <= 0) {
-            reason.add("Scoreboard.Types.Inspect.Display_Time should be greater than 0, or -1!");
-        }
-
-        if (getSkillScoreboardTime() != -1 && getSkillScoreboardTime() <= 0) {
-            reason.add("Scoreboard.Types.Skill.Display_Time should be greater than 0, or -1!");
-        }
-
-        if (getSkillLevelUpTime() != -1 && getSkillScoreboardTime() <= 0) {
-            reason.add("Scoreboard.Types.Skill.Display_Time should be greater than 0, or -1!");
-        }
-
-        if (!(getRankUseChat() || getRankUseBoard())) {
-            reason.add("Either Board or Print in Scoreboard.Types.Rank must be true!");
-        }
-
-        if (!(getTopUseChat() || getTopUseBoard())) {
-            reason.add("Either Board or Print in Scoreboard.Types.Top must be true!");
-        }
-
-        if (!(getStatsUseChat() || getStatsUseBoard())) {
-            reason.add("Either Board or Print in Scoreboard.Types.Stats must be true!");
-        }
-
-        if (!(getInspectUseChat() || getInspectUseBoard())) {
-            reason.add("Either Board or Print in Scoreboard.Types.Inspect must be true!");
-        }*/
-
-        /* Database Purging */
-        if (getPurgeInterval() < -1) {
-            reason.add("Database_Purging.Purge_Interval should be greater than, or equal to -1!");
-        }
-
-        if (getOldUsersCutoff() != -1 && getOldUsersCutoff() <= 0) {
-            reason.add("Database_Purging.Old_User_Cutoff should be greater than 0 or -1!");
-        }
-
-        /* Hardcore Mode */
-        if (getHardcoreDeathStatPenaltyPercentage() < 0.01 || getHardcoreDeathStatPenaltyPercentage() > 100) {
-            reason.add("Hardcore.Death_Stat_Loss.Penalty_Percentage only accepts values from 0.01 to 100!");
-        }
-
-        if (getHardcoreVampirismStatLeechPercentage() < 0.01 || getHardcoreVampirismStatLeechPercentage() > 100) {
-            reason.add("Hardcore.Vampirism.Leech_Percentage only accepts values from 0.01 to 100!");
-        }
-
-        /* Items */
-        if (getChimaeraUseCost() < 1 || getChimaeraUseCost() > 64) {
-            reason.add("Items.Chimaera_Wing.Use_Cost only accepts values from 1 to 64!");
-        }
-
-        if (getChimaeraRecipeCost() < 1 || getChimaeraRecipeCost() > 9) {
-            reason.add("Items.Chimaera_Wing.Recipe_Cost only accepts values from 1 to 9!");
-        }
-
-        if (getChimaeraItem() == null) {
-            reason.add("Items.Chimaera_Wing.Item_Name is invalid!");
-        }
-
-        /* Particles */
-        if (getLevelUpEffectsTier() < 1) {
-            reason.add("Particles.LevelUp_Tier should be at least 1!");
-        }
-
-        /* PARTY SETTINGS */
-        if (getAutoPartyKickInterval() < -1) {
-            reason.add("Party.AutoKick_Interval should be at least -1!");
-        }
+    /* PATH VARS */
 
-        if (getAutoPartyKickTime() < 0) {
-            reason.add("Party.Old_Party_Member_Cutoff should be at least 0!");
-        }
-
-        if (getPartyShareBonusBase() <= 0) {
-            reason.add("Party.Sharing.ExpShare_bonus_base should be greater than 0!");
-        }
-
-        if (getPartyShareBonusIncrease() < 0) {
-            reason.add("Party.Sharing.ExpShare_bonus_increase should be at least 0!");
-        }
-
-        if (getPartyShareBonusCap() <= 0) {
-            reason.add("Party.Sharing.ExpShare_bonus_cap should be greater than 0!");
-        }
-
-        if (getPartyShareRange() <= 0) {
-            reason.add("Party.Sharing.Range should be greater than 0!");
-        }
-
-        if (getPartyXpCurveMultiplier() < 1) {
-            reason.add("Party.Leveling.Xp_Curve_Modifier should be at least 1!");
-        }
-
-        for (PartyFeature partyFeature : PartyFeature.values()) {
-            if (getPartyFeatureUnlockLevel(partyFeature) < 0) {
-                reason.add("Party.Leveling." + StringUtils.getPrettyPartyFeatureString(partyFeature).replace(" ", "") + "_UnlockLevel should be at least 0!");
-            }
-        }
+    public final File DIRECTORY_DATA_FOLDER; //Directory that the file is in
+    public final String FILE_RELATIVE_PATH; //Relative Path to the file
+    protected final String DIRECTORY_DEFAULTS = "defaults";
 
-        /* Inspect command distance */
-        if (getInspectDistance() <= 0) {
-            reason.add("Commands.inspect.Max_Distance should be greater than 0!");
-        }
+    /* LOADERS */
 
-        if (getTreeFellerThreshold() <= 0) {
-            reason.add("Abilities.Limits.Tree_Feller_Threshold should be greater than 0!");
-        }
+    private YAMLConfigurationLoader defaultCopyLoader;
+    private YAMLConfigurationLoader userCopyLoader;
 
-        if (getFishingLureModifier() < 0) {
-            reason.add("Abilities.Fishing.Lure_Modifier should be at least 0!");
-        }
+    /* CONFIG FILES */
 
-        if (getDetonatorItem() == null) {
-            reason.add("Skills.Mining.Detonator_Item is invalid!");
-        }
+    private File resourceConfigCopy; //Copy of the default config from the JAR (file is copied so that admins can easily compare to defaults)
+    private File resourceUserCopy; //File in the /$MCMMO_ROOT/mcMMO/ directory that may contain user edited settings
 
-        if (getRepairAnvilMaterial() == null) {
-            reason.add("Skills.Repair.Anvil_Type is invalid!!");
-        }
+    /* ROOT NODES */
 
-        if (getSalvageAnvilMaterial() == null) {
-            reason.add("Skills.Repair.Salvage_Anvil_Type is invalid!");
-        }
+    private ConfigurationNode userRootNode = null;
+    private ConfigurationNode defaultRootNode = null;
 
-        if (getRepairAnvilMaterial() == getSalvageAnvilMaterial()) {
-            reason.add("Cannot use the same item for Repair and Salvage anvils!");
-        }
+    /* CONFIG MANAGER */
+    private ConfigurationLoader<CommentedConfigurationNode> configManager;
 
-        if (getTamingCOTWMaterial(EntityType.WOLF) == null) {
-            reason.add("Skills.Taming.Call_Of_The_Wild.Wolf.Item_Material is invalid!!");
-        }
-
-        if (getTamingCOTWMaterial(EntityType.OCELOT) == null) {
-            reason.add("Skills.Taming.Call_Of_The_Wild.Ocelot.Item_Material is invalid!!");
-        }
-
-        if (getTamingCOTWMaterial(EntityType.HORSE) == null) {
-            reason.add("Skills.Taming.Call_Of_The_Wild.Horse.Item_Material is invalid!!");
-        }
+    public Config(String pathToParentFolder, String relativePath) {
+        //TODO: Check if this works...
+        this(new File(pathToParentFolder), relativePath);
+        System.out.println("mcMMO Debug: Don't forget to check if loading config file by string instead of File works...");
+    }
 
-        if (getTamingCOTWCost(EntityType.WOLF) <= 0) {
-            reason.add("Skills.Taming.Call_Of_The_Wild.Wolf.Item_Amount should be greater than 0!");
-        }
+    public Config(File pathToParentFolder, String relativePath) {
+        /*
+         * These must be at the top
+         */
+        mkdirDefaults(); // Make our default config dir
+        DIRECTORY_DATA_FOLDER = pathToParentFolder; //Data Folder for our plugin
+        FILE_RELATIVE_PATH = relativePath; //Relative path to config from a parent folder
 
-        if (getTamingCOTWCost(EntityType.OCELOT) <= 0) {
-            reason.add("Skills.Taming.Call_Of_The_Wild.Ocelot.Item_Amount should be greater than 0!");
-        }
+        //Attempt IO Operations
+        try {
+            //Makes sure we have valid Files corresponding to this config
+            initConfigFiles();
 
-        if (getTamingCOTWCost(EntityType.HORSE) <= 0) {
-            reason.add("Skills.Taming.Call_Of_The_Wild.Horse.Item_Amount should be greater than 0!");
-        }
+            //Init MainConfig Loaders
+            initConfigLoaders();
 
-        if (getTamingCOTWAmount(EntityType.WOLF) <= 0) {
-            reason.add("Skills.Taming.Call_Of_The_Wild.Wolf.Summon_Amount should be greater than 0!");
-        }
+            //Load MainConfig Nodes
+            loadConfig();
 
-        if (getTamingCOTWAmount(EntityType.OCELOT) <= 0) {
-            reason.add("Skills.Taming.Call_Of_The_Wild.Ocelot.Summon_Amount should be greater than 0!");
+            //Attempt to update user file, and then load it into memory
+            readConfig();
+        } catch (IOException e) {
+            e.printStackTrace();
         }
 
-        if (getTamingCOTWAmount(EntityType.HORSE) <= 0) {
-            reason.add("Skills.Taming.Call_Of_The_Wild.Horse.Summon_Amount should be greater than 0!");
-        }
 
-        return noErrorsInConfig(reason);
     }
 
-    /*
-     * GENERAL SETTINGS
+    /**
+     * Initializes the default copy File and the user config File
+     * @throws IOException
      */
+    private void initConfigFiles() throws IOException {
+        //Init our config copy
+        resourceConfigCopy = initDefaultConfig();
 
-    /* General Settings */
-    public boolean getIsMetricsEnabled() {
-        return config.getBoolean("Metrics.bstats", true);
-    }
-
-    //Retro mode will default the value to true if the config file doesn't contain the entry (server is from a previous mcMMO install)
-    public boolean getIsRetroMode() {
-        return config.getBoolean("General.RetroMode.Enabled", true);
-    }
-
-    public String getLocale() {
-        return config.getString("General.Locale", "en_us");
-    }
-
-    public boolean getMOTDEnabled() {
-        return config.getBoolean("General.MOTD_Enabled", true);
-    }
-
-    public boolean getShowProfileLoadedMessage() {
-        return config.getBoolean("General.Show_Profile_Loaded", true);
-    }
-
-    public boolean getDonateMessageEnabled() {
-        return config.getBoolean("Commands.mcmmo.Donate_Message", true);
-    }
-
-    public int getSaveInterval() {
-        return config.getInt("General.Save_Interval", 10);
-    }
-
-    public boolean getStatsTrackingEnabled() {
-        return config.getBoolean("General.Stats_Tracking", true);
-    }
-
-    public boolean getUpdateCheckEnabled() {
-        return config.getBoolean("General.Update_Check", true);
-    }
-
-    public boolean getPreferBeta() {
-        return config.getBoolean("General.Prefer_Beta", false);
-    }
-
-    public boolean getVerboseLoggingEnabled() {
-        return config.getBoolean("General.Verbose_Logging", false);
+        //Init the user file
+        resourceUserCopy = initUserConfig();
     }
 
-    public String getPartyChatPrefix() {
-        return config.getString("Commands.partychat.Chat_Prefix_Format", "[[GREEN]]([[WHITE]]{0}[[GREEN]])");
-    }
-
-    public boolean getPartyChatColorLeaderName() {
-        return config.getBoolean("Commands.partychat.Gold_Leader_Name", true);
-    }
-
-    public boolean getPartyDisplayNames() {
-        return config.getBoolean("Commands.partychat.Use_Display_Names", true);
-    }
-
-    public String getPartyChatPrefixAlly() {
-        return config.getString("Commands.partychat.Chat_Prefix_Format_Ally", "[[GREEN]](A)[[RESET]]");
-    }
-
-    public String getAdminChatPrefix() {
-        return config.getString("Commands.adminchat.Chat_Prefix_Format", "[[AQUA]][[[WHITE]]{0}[[AQUA]]]");
-    }
-
-    public boolean getAdminDisplayNames() {
-        return config.getBoolean("Commands.adminchat.Use_Display_Names", true);
-    }
-
-    public boolean getMatchOfflinePlayers() {
-        return config.getBoolean("Commands.Generic.Match_OfflinePlayers", false);
-    }
-
-    public long getDatabasePlayerCooldown() {
-        return config.getLong("Commands.Database.Player_Cooldown", 1750);
-    }
-
-    public boolean getLevelUpSoundsEnabled() {
-        return config.getBoolean("General.LevelUp_Sounds", true);
-    }
-
-    public boolean getRefreshChunksEnabled() {
-        return config.getBoolean("General.Refresh_Chunks", false);
-    }
-
-    public boolean getMobHealthbarEnabled() {
-        return config.getBoolean("Mob_Healthbar.Enabled", true);
-    }
-
-    /* Mob Healthbar */
-    public MobHealthbarType getMobHealthbarDefault() {
+    /**
+     * Loads the root node for the default config File and user config File
+     */
+    private void loadConfig()
+    {
         try {
-            return MobHealthbarType.valueOf(config.getString("Mob_Healthbar.Display_Type", "HEARTS").toUpperCase().trim());
-        } catch (IllegalArgumentException ex) {
-            return MobHealthbarType.HEARTS;
-        }
-    }
-
-    public int getMobHealthbarTime() {
-        return config.getInt("Mob_Healthbar.Display_Time", 3);
-    }
-
-    /* Scoreboards */
-    public boolean getScoreboardsEnabled() {
-        return config.getBoolean("Scoreboard.UseScoreboards", true);
-    }
-
-    public boolean getPowerLevelTagsEnabled() {
-        return config.getBoolean("Scoreboard.Power_Level_Tags", false);
-    }
-
-    public boolean getAllowKeepBoard() {
-        return config.getBoolean("Scoreboard.Allow_Keep", true);
-    }
-
-    public int getTipsAmount() {
-        return config.getInt("Scoreboard.Tips_Amount", 5);
-    }
-
-    public boolean getShowStatsAfterLogin() {
-        return config.getBoolean("Scoreboard.Show_Stats_After_Login", false);
-    }
-
-    public boolean getScoreboardRainbows() {
-        return config.getBoolean("Scoreboard.Rainbows", false);
-    }
-
-    public boolean getShowAbilityNames() {
-        return config.getBoolean("Scoreboard.Ability_Names", true);
-    }
-
-    public boolean getRankUseChat() {
-        return config.getBoolean("Scoreboard.Types.Rank.Print", false);
-    }
-
-    public boolean getRankUseBoard() {
-        return config.getBoolean("Scoreboard.Types.Rank.Board", true);
-    }
-
-    public int getRankScoreboardTime() {
-        return config.getInt("Scoreboard.Types.Rank.Display_Time", 10);
-    }
-
-    public boolean getTopUseChat() {
-        return config.getBoolean("Scoreboard.Types.Top.Print", true);
-    }
-
-    public boolean getTopUseBoard() {
-        return config.getBoolean("Scoreboard.Types.Top.Board", true);
-    }
-
-    public int getTopScoreboardTime() {
-        return config.getInt("Scoreboard.Types.Top.Display_Time", 15);
-    }
-
-    public boolean getStatsUseChat() {
-        return config.getBoolean("Scoreboard.Types.Stats.Print", true);
-    }
-
-    public boolean getStatsUseBoard() {
-        return config.getBoolean("Scoreboard.Types.Stats.Board", true);
-    }
-
-    public int getStatsScoreboardTime() {
-        return config.getInt("Scoreboard.Types.Stats.Display_Time", 10);
-    }
-
-    public boolean getInspectUseChat() {
-        return config.getBoolean("Scoreboard.Types.Inspect.Print", true);
-    }
-
-    public boolean getInspectUseBoard() {
-        return config.getBoolean("Scoreboard.Types.Inspect.Board", true);
-    }
-
-    public int getInspectScoreboardTime() {
-        return config.getInt("Scoreboard.Types.Inspect.Display_Time", 25);
-    }
-
-    public boolean getCooldownUseChat() {
-        return config.getBoolean("Scoreboard.Types.Cooldown.Print", false);
-    }
-
-    public boolean getCooldownUseBoard() {
-        return config.getBoolean("Scoreboard.Types.Cooldown.Board", true);
-    }
-
-    public int getCooldownScoreboardTime() {
-        return config.getInt("Scoreboard.Types.Cooldown.Display_Time", 41);
-    }
-
-    public boolean getSkillUseBoard() {
-        return config.getBoolean("Scoreboard.Types.Skill.Board", true);
-    }
-
-    public int getSkillScoreboardTime() {
-        return config.getInt("Scoreboard.Types.Skill.Display_Time", 30);
-    }
-
-    public boolean getSkillLevelUpBoard() {
-        return config.getBoolean("Scoreboard.Types.Skill.LevelUp_Board", true);
-    }
-
-    public int getSkillLevelUpTime() {
-        return config.getInt("Scoreboard.Types.Skill.LevelUp_Time", 5);
-    }
-
-    /* Database Purging */
-    public int getPurgeInterval() {
-        return config.getInt("Database_Purging.Purge_Interval", -1);
-    }
-
-    public int getOldUsersCutoff() {
-        return config.getInt("Database_Purging.Old_User_Cutoff", 6);
-    }
-
-    /* Backups */
-    public boolean getBackupsEnabled() {
-        return config.getBoolean("Backups.Enabled", true);
-    }
-
-    public boolean getKeepLast24Hours() {
-        return config.getBoolean("Backups.Keep.Last_24_Hours", true);
-    }
-
-    public boolean getKeepDailyLastWeek() {
-        return config.getBoolean("Backups.Keep.Daily_Last_Week", true);
-    }
-
-    public boolean getKeepWeeklyPastMonth() {
-        return config.getBoolean("Backups.Keep.Weekly_Past_Months", true);
-    }
-
-    /* mySQL */
-    public boolean getUseMySQL() {
-        return config.getBoolean("MySQL.Enabled", false);
-    }
-
-    public String getMySQLTablePrefix() {
-        return config.getString("MySQL.Database.TablePrefix", "mcmmo_");
-    }
-
-    public String getMySQLDatabaseName() {
-        return getStringIncludingInts("MySQL.Database.Name");
-    }
-
-    public String getMySQLUserName() {
-        return getStringIncludingInts("MySQL.Database.User_Name");
-    }
-
-    public int getMySQLServerPort() {
-        return config.getInt("MySQL.Server.Port", 3306);
-    }
-
-    public String getMySQLServerName() {
-        return config.getString("MySQL.Server.Address", "localhost");
-    }
+            final ConfigurationNode defaultConfig = this.defaultCopyLoader.load();
+            defaultRootNode = defaultConfig;
 
-    public String getMySQLUserPassword() {
-        return getStringIncludingInts("MySQL.Database.User_Password");
-    }
-
-    public int getMySQLMaxConnections(SQLDatabaseManager.PoolIdentifier identifier) {
-        return config.getInt("MySQL.Database.MaxConnections." + StringUtils.getCapitalized(identifier.toString()), 30);
-    }
-
-    public int getMySQLMaxPoolSize(SQLDatabaseManager.PoolIdentifier identifier) {
-        return config.getInt("MySQL.Database.MaxPoolSize." + StringUtils.getCapitalized(identifier.toString()), 10);
-    }
-
-    public boolean getMySQLSSL() {
-        return config.getBoolean("MySQL.Server.SSL", true);
-    }
+            final ConfigurationNode userConfig = this.userCopyLoader.load();
+            userRootNode = userConfig;
 
-    private String getStringIncludingInts(String key) {
-        String str = config.getString(key);
-
-        if (str == null) {
-            str = String.valueOf(config.getInt(key));
-        }
-
-        if (str.equals("0")) {
-            str = "No value set for '" + key + "'";
+        } catch (IOException e) {
+            e.printStackTrace();
         }
-        return str;
-    }
-
-    /* Hardcore Mode */
-    public boolean getHardcoreStatLossEnabled(PrimarySkillType primarySkillType) {
-        return config.getBoolean("Hardcore.Death_Stat_Loss.Enabled." + StringUtils.getCapitalized(primarySkillType.toString()), false);
-    }
-
-    public void setHardcoreStatLossEnabled(PrimarySkillType primarySkillType, boolean enabled) {
-        config.set("Hardcore.Death_Stat_Loss.Enabled." + StringUtils.getCapitalized(primarySkillType.toString()), enabled);
-    }
-
-    public double getHardcoreDeathStatPenaltyPercentage() {
-        return config.getDouble("Hardcore.Death_Stat_Loss.Penalty_Percentage", 75.0D);
-    }
-
-    public void setHardcoreDeathStatPenaltyPercentage(double value) {
-        config.set("Hardcore.Death_Stat_Loss.Penalty_Percentage", value);
-    }
-
-    public int getHardcoreDeathStatPenaltyLevelThreshold() {
-        return config.getInt("Hardcore.Death_Stat_Loss.Level_Threshold", 0);
-    }
-
-    public boolean getHardcoreVampirismEnabled(PrimarySkillType primarySkillType) {
-        return config.getBoolean("Hardcore.Vampirism.Enabled." + StringUtils.getCapitalized(primarySkillType.toString()), false);
-    }
-
-    public void setHardcoreVampirismEnabled(PrimarySkillType primarySkillType, boolean enabled) {
-        config.set("Hardcore.Vampirism.Enabled." + StringUtils.getCapitalized(primarySkillType.toString()), enabled);
-    }
-
-    public double getHardcoreVampirismStatLeechPercentage() {
-        return config.getDouble("Hardcore.Vampirism.Leech_Percentage", 5.0D);
-    }
-
-    public void setHardcoreVampirismStatLeechPercentage(double value) {
-        config.set("Hardcore.Vampirism.Leech_Percentage", value);
-    }
-
-    public int getHardcoreVampirismLevelThreshold() {
-        return config.getInt("Hardcore.Vampirism.Level_Threshold", 0);
-    }
-
-    /* SMP Mods */
-    public boolean getToolModsEnabled() {
-        return config.getBoolean("Mods.Tool_Mods_Enabled", false);
-    }
-
-    public boolean getArmorModsEnabled() {
-        return config.getBoolean("Mods.Armor_Mods_Enabled", false);
-    }
-
-    public boolean getBlockModsEnabled() {
-        return config.getBoolean("Mods.Block_Mods_Enabled", false);
-    }
-
-    public boolean getEntityModsEnabled() {
-        return config.getBoolean("Mods.Entity_Mods_Enabled", false);
-    }
-
-    /* Items */
-    public int getChimaeraUseCost() {
-        return config.getInt("Items.Chimaera_Wing.Use_Cost", 1);
-    }
-
-    public int getChimaeraRecipeCost() {
-        return config.getInt("Items.Chimaera_Wing.Recipe_Cost", 5);
-    }
-
-    public Material getChimaeraItem() {
-        return Material.matchMaterial(config.getString("Items.Chimaera_Wing.Item_Name", "Feather"));
-    }
-
-    public boolean getChimaeraEnabled() {
-        return config.getBoolean("Items.Chimaera_Wing.Enabled", true);
-    }
-
-    public boolean getChimaeraPreventUseUnderground() {
-        return config.getBoolean("Items.Chimaera_Wing.Prevent_Use_Underground", true);
-    }
-
-    public boolean getChimaeraUseBedSpawn() {
-        return config.getBoolean("Items.Chimaera_Wing.Use_Bed_Spawn", true);
-    }
-
-    public int getChimaeraCooldown() {
-        return config.getInt("Items.Chimaera_Wing.Cooldown", 240);
-    }
-
-    public int getChimaeraWarmup() {
-        return config.getInt("Items.Chimaera_Wing.Warmup", 5);
-    }
-
-    public int getChimaeraRecentlyHurtCooldown() {
-        return config.getInt("Items.Chimaera_Wing.RecentlyHurt_Cooldown", 60);
-    }
-
-    public boolean getChimaeraSoundEnabled() {
-        return config.getBoolean("Items.Chimaera_Wing.Sound_Enabled", true);
-    }
-
-    public boolean getFluxPickaxeSoundEnabled() {
-        return config.getBoolean("Items.Flux_Pickaxe.Sound_Enabled", true);
-    }
-
-    /* Particles */
-    public boolean getAbilityActivationEffectEnabled() {
-        return config.getBoolean("Particles.Ability_Activation", true);
-    }
-
-    public boolean getAbilityDeactivationEffectEnabled() {
-        return config.getBoolean("Particles.Ability_Deactivation", true);
-    }
-
-    public boolean getBleedEffectEnabled() {
-        return config.getBoolean("Particles.Bleed", true);
-    }
-
-    public boolean getDodgeEffectEnabled() {
-        return config.getBoolean("Particles.Dodge", true);
-    }
-
-    public boolean getFluxEffectEnabled() {
-        return config.getBoolean("Particles.Flux", true);
-    }
-
-    public boolean getGreaterImpactEffectEnabled() {
-        return config.getBoolean("Particles.Greater_Impact", true);
-    }
-
-    public boolean getCallOfTheWildEffectEnabled() {
-        return config.getBoolean("Particles.Call_of_the_Wild", true);
-    }
-
-    public boolean getLevelUpEffectsEnabled() {
-        return config.getBoolean("Particles.LevelUp_Enabled", true);
-    }
-
-    public int getLevelUpEffectsTier() {
-        return config.getInt("Particles.LevelUp_Tier", 100);
-    }
-
-    public boolean getLargeFireworks() {
-        return config.getBoolean("Particles.LargeFireworks", true);
-    }
-
-    /* PARTY SETTINGS */
-    public boolean getPartyFriendlyFire() {
-        return config.getBoolean("Party.FriendlyFire", false);
-    }
-
-    public int getPartyMaxSize() {
-        return config.getInt("Party.MaxSize", -1);
-    }
-
-    public int getAutoPartyKickInterval() {
-        return config.getInt("Party.AutoKick_Interval", 12);
-    }
-
-    public int getAutoPartyKickTime() {
-        return config.getInt("Party.Old_Party_Member_Cutoff", 7);
-    }
-
-    public double getPartyShareBonusBase() {
-        return config.getDouble("Party.Sharing.ExpShare_bonus_base", 1.1D);
-    }
-
-    public double getPartyShareBonusIncrease() {
-        return config.getDouble("Party.Sharing.ExpShare_bonus_increase", 0.05D);
-    }
-
-    public double getPartyShareBonusCap() {
-        return config.getDouble("Party.Sharing.ExpShare_bonus_cap", 1.5D);
-    }
-
-    public double getPartyShareRange() {
-        return config.getDouble("Party.Sharing.Range", 75.0D);
-    }
-
-    public int getPartyLevelCap() {
-        int cap = config.getInt("Party.Leveling.Level_Cap", 10);
-        return (cap <= 0) ? Integer.MAX_VALUE : cap;
-    }
-
-    public int getPartyXpCurveMultiplier() {
-        return config.getInt("Party.Leveling.Xp_Curve_Modifier", 3);
-    }
-
-    public boolean getPartyXpNearMembersNeeded() {
-        return config.getBoolean("Party.Leveling.Near_Members_Needed", false);
-    }
-
-    public boolean getPartyInformAllMembers() {
-        return config.getBoolean("Party.Leveling.Inform_All_Party_Members_On_LevelUp", false);
     }
 
-    public int getPartyFeatureUnlockLevel(PartyFeature partyFeature) {
-        return config.getInt("Party.Leveling." + StringUtils.getPrettyPartyFeatureString(partyFeature).replace(" ", "") + "_UnlockLevel", 0);
-    }
-
-    /* Party Teleport Settings */
-    public int getPTPCommandCooldown() {
-        return config.getInt("Commands.ptp.Cooldown", 120);
-    }
-
-    public int getPTPCommandWarmup() {
-        return config.getInt("Commands.ptp.Warmup", 5);
-    }
-
-    public int getPTPCommandRecentlyHurtCooldown() {
-        return config.getInt("Commands.ptp.RecentlyHurt_Cooldown", 60);
-    }
-
-    public int getPTPCommandTimeout() {
-        return config.getInt("Commands.ptp.Request_Timeout", 300);
-    }
-
-    public boolean getPTPCommandConfirmRequired() {
-        return config.getBoolean("Commands.ptp.Accept_Required", true);
-    }
-
-    public boolean getPTPCommandWorldPermissions() {
-        return config.getBoolean("Commands.ptp.World_Based_Permissions", false);
-    }
-
-    /* Inspect command distance */
-    public double getInspectDistance() {
-        return config.getDouble("Commands.inspect.Max_Distance", 30.0D);
-    }
-
-    /*
-     * ABILITY SETTINGS
+    /**
+     * Initializes the YAMLConfigurationLoaders for this config
      */
-
-    /* General Settings */
-    public boolean getUrlLinksEnabled() {
-        return config.getBoolean("Commands.Skills.URL_Links");
-    }
-
-    public boolean getAbilityMessagesEnabled() {
-        return config.getBoolean("Abilities.Messages", true);
-    }
-
-    public boolean getAbilitiesEnabled() {
-        return config.getBoolean("Abilities.Enabled", true);
-    }
-
-    public boolean getAbilitiesOnlyActivateWhenSneaking() {
-        return config.getBoolean("Abilities.Activation.Only_Activate_When_Sneaking", false);
-    }
-
-    public boolean getAbilitiesGateEnabled() {
-        return config.getBoolean("Abilities.Activation.Level_Gate_Abilities");
-    }
-
-    public int getCooldown(SuperAbilityType ability) {
-        return config.getInt("Abilities.Cooldowns." + ability.toString());
-    }
-
-    public int getMaxLength(SuperAbilityType ability) {
-        return config.getInt("Abilities.Max_Seconds." + ability.toString());
-    }
-
-    /* Durability Settings */
-    public int getAbilityToolDamage() {
-        return config.getInt("Abilities.Tools.Durability_Loss", 1);
-    }
-
-    /* Thresholds */
-    public int getTreeFellerThreshold() {
-        return config.getInt("Abilities.Limits.Tree_Feller_Threshold", 500);
+    private void initConfigLoaders()
+    {
+        this.defaultCopyLoader = YAMLConfigurationLoader.builder().setPath(resourceConfigCopy.toPath()).setFlowStyle(DumperOptions.FlowStyle.BLOCK).build();
+        this.userCopyLoader = YAMLConfigurationLoader.builder().setPath(resourceUserCopy.toPath()).setFlowStyle(DumperOptions.FlowStyle.FLOW).build();
     }
 
-    /*
-     * SKILL SETTINGS
+    /**
+     * Copies a new file from the JAR to the defaults directory and uses that new file to initialize our resourceConfigCopy
+     * @see Config#resourceConfigCopy
+     * @throws IOException
      */
-    public boolean getDoubleDropsEnabled(PrimarySkillType skill, Material material) {
-        return config.getBoolean("Double_Drops." + StringUtils.getCapitalized(skill.toString()) + "." + StringUtils.getPrettyItemString(material).replace(" ", "_"));
+    private File initDefaultConfig() throws IOException {
+        return copyDefaultFromJar(getDefaultConfigCopyRelativePath(), true);
     }
 
-    public boolean getDoubleDropsDisabled(PrimarySkillType skill) {
-        String skillName = StringUtils.getCapitalized(skill.toString());
-        ConfigurationSection section = config.getConfigurationSection("Double_Drops." + skillName);
-        if (section == null)
-            return false;
-        Set<String> keys = section.getKeys(false);
-        boolean disabled = true;
+    /**
+     * Attemps to load the config file if it exists, if it doesn't it copies a new one from within the JAR
+     * @return user config File
+     * @see Config#resourceUserCopy
+     * @throws IOException
+     */
+    private File initUserConfig() throws IOException {
+        File userCopy = new File(DIRECTORY_DATA_FOLDER, FILE_RELATIVE_PATH); //Load the user file;
 
-        for (String key : keys) {
-            if (config.getBoolean("Double_Drops." + skillName + "." + key)) {
-                disabled = false;
-                break;
-            }
+        if(userCopy.exists())
+        {
+            // Yay
+            return userCopy;
+        }
+        else
+        {
+            //If it's gone we copy default files
+            //Note that we don't copy the values from the default copy put in /defaults/ that file exists only as a reference to admins and is unreliable
+            return copyDefaultFromJar(FILE_RELATIVE_PATH, false);
         }
-
-        return disabled;
-    }
-
-    /* Axes */
-    public int getAxesGate() {
-        return config.getInt("Skills.Axes.Ability_Activation_Level_Gate", 10);
-    }
-
-    /* Acrobatics */
-    public boolean getDodgeLightningDisabled() {
-        return config.getBoolean("Skills.Acrobatics.Prevent_Dodge_Lightning", false);
-    }
-
-    public int getXPAfterTeleportCooldown() {
-        return config.getInt("Skills.Acrobatics.XP_After_Teleport_Cooldown", 5);
-    }
-
-    /* Alchemy */
-    public boolean getEnabledForHoppers() {
-        return config.getBoolean("Skills.Alchemy.Enabled_for_Hoppers", true);
-    }
-
-    public boolean getPreventHopperTransferIngredients() {
-        return config.getBoolean("Skills.Alchemy.Prevent_Hopper_Transfer_Ingredients", false);
-    }
-
-    public boolean getPreventHopperTransferBottles() {
-        return config.getBoolean("Skills.Alchemy.Prevent_Hopper_Transfer_Bottles", false);
-    }
-
-    /* Fishing */
-    public boolean getFishingDropsEnabled() {
-        return config.getBoolean("Skills.Fishing.Drops_Enabled", true);
-    }
-
-    public boolean getFishingOverrideTreasures() {
-        return config.getBoolean("Skills.Fishing.Override_Vanilla_Treasures", true);
-    }
-
-    public boolean getFishingExtraFish() {
-        return config.getBoolean("Skills.Fishing.Extra_Fish", true);
-    }
-
-    public double getFishingLureModifier() {
-        return config.getDouble("Skills.Fishing.Lure_Modifier", 4.0D);
-    }
-
-    /* Mining */
-    public Material getDetonatorItem() {
-        return Material.matchMaterial(config.getString("Skills.Mining.Detonator_Name", "FLINT_AND_STEEL"));
-    }
-
-    public int getMiningGate() {
-        return config.getInt("Skills.Mining.Ability_Activation_Level_Gate", 10);
-    }
-
-    /* Excavation */
-    public int getExcavationGate() {
-        return config.getInt("Skills.Excavation.Ability_Activation_Level_Gate", 10);
-    }
-
-    /* Repair */
-    public boolean getRepairAnvilMessagesEnabled() {
-        return config.getBoolean("Skills.Repair.Anvil_Messages", true);
-    }
-
-    public boolean getRepairAnvilPlaceSoundsEnabled() {
-        return config.getBoolean("Skills.Repair.Anvil_Placed_Sounds", true);
-    }
-
-    public boolean getRepairAnvilUseSoundsEnabled() {
-        return config.getBoolean("Skills.Repair.Anvil_Use_Sounds", true);
-    }
-
-    public Material getRepairAnvilMaterial() {
-        return Material.matchMaterial(config.getString("Skills.Repair.Anvil_Material", "IRON_BLOCK"));
-    }
-
-    public boolean getRepairConfirmRequired() {
-        return config.getBoolean("Skills.Repair.Confirm_Required", true);
-    }
-
-    /* Salvage */
-    public boolean getSalvageAnvilMessagesEnabled() {
-        return config.getBoolean("Skills.Salvage.Anvil_Messages", true);
     }
 
-    public boolean getSalvageAnvilPlaceSoundsEnabled() {
-        return config.getBoolean("Skills.Salvage.Anvil_Placed_Sounds", true);
-    }
+    /**
+     * Used to make a new config file at a specified relative output path inside the data directory by copying the matching file found in that same relative path within the JAR
+     * @param relativeOutputPath the path to the output file
+     * @param deleteOld whether or not to delete the existing output file on disk
+     * @return a copy of the default config within the JAR
+     * @throws IOException
+     */
+    private File copyDefaultFromJar(String relativeOutputPath, boolean deleteOld) throws IOException
+    {
+        /*
+         * Gen a Default config from inside the JAR
+         */
+        McmmoCore.getLogger().info("Preparing to copy internal resource file (in JAR) - "+FILE_RELATIVE_PATH);
+        InputStream inputStream = McmmoCore.getResource(FILE_RELATIVE_PATH);
 
-    public boolean getSalvageAnvilUseSoundsEnabled() {
-        return config.getBoolean("Skills.Salvage.Anvil_Use_Sounds", true);
-    }
+        byte[] buffer = new byte[inputStream.available()];
+        inputStream.read(buffer);
 
-    public Material getSalvageAnvilMaterial() {
-        return Material.matchMaterial(config.getString("Skills.Salvage.Anvil_Material", "GOLD_BLOCK"));
-    }
+        //This is a copy of the default file, which we will overwrite every time mcMMO loads
+        File targetFile = new File(DIRECTORY_DATA_FOLDER, relativeOutputPath);
 
-    public boolean getSalvageConfirmRequired() {
-        return config.getBoolean("Skills.Salvage.Confirm_Required", true);
-    }
+        //Wipe old default file on disk
+        if (targetFile.exists() && deleteOld)
+        {
+            McmmoCore.getLogger().info("Updating file " + relativeOutputPath);
+            targetFile.delete(); //Necessary?
+        }
 
-    /* Unarmed */
-    public boolean getUnarmedBlockCrackerSmoothbrickToCracked() {
-        return config.getBoolean("Skills.Unarmed.Block_Cracker.SmoothBrick_To_CrackedBrick", true);
-    }
+        if(!targetFile.exists())
+        {
+            targetFile.getParentFile().mkdirs();
+            targetFile.createNewFile(); //New File Boys
+        }
 
-    public boolean getUnarmedItemPickupDisabled() {
-        return config.getBoolean("Skills.Unarmed.Item_Pickup_Disabled_Full_Inventory", true);
-    }
+        Files.write(buffer, targetFile);
+        McmmoCore.getLogger().info("Created config file - " + relativeOutputPath);
 
-    public boolean getUnarmedItemsAsUnarmed() {
-        return config.getBoolean("Skills.Unarmed.Items_As_Unarmed", false);
-    }
+        inputStream.close(); //Close the input stream
 
-    public int getUnarmedGate() {
-        return config.getInt("Skills.Unarmed.Ability_Activation_Level_Gate", 10);
+        return targetFile;
     }
 
-    /* Swords */
-    public int getSwordsGate() {
-        return config.getInt("Skills.Swords.Ability_Activation_Level_Gate", 10);
+    /**
+     * The path to the defaults directory
+     * @return the path to the defaults directory
+     */
+    private String getDefaultConfigCopyRelativePath() {
+        return DIRECTORY_DEFAULTS + File.separator + FILE_RELATIVE_PATH;
     }
 
-    /* Taming */
-    public Material getTamingCOTWMaterial(EntityType type) {
-        return Material.matchMaterial(config.getString("Skills.Taming.Call_Of_The_Wild." + StringUtils.getPrettyEntityTypeString(type) + ".Item_Material"));
-    }
+    /**
+     * Creates the defaults directory
+     */
+    private void mkdirDefaults() {
+        //Make Default Subdirectory
+        File defaultsDir = new File (DIRECTORY_DATA_FOLDER, "defaults");
 
-    public int getTamingCOTWCost(EntityType type) {
-        return config.getInt("Skills.Taming.Call_Of_The_Wild." + StringUtils.getPrettyEntityTypeString(type) + ".Item_Amount");
+        if(!defaultsDir.exists())
+            defaultsDir.mkdir();
     }
 
-    public int getTamingCOTWAmount(EntityType type) {
-        return config.getInt("Skills.Taming.Call_Of_The_Wild." + StringUtils.getPrettyEntityTypeString(type) + ".Summon_Amount");
+    /**
+     * Configs are versioned based on when they had significant changes to keys
+     * @return current MainConfig Version String
+     */
+    public String getVersion()
+    {
+         return String.valueOf(getConfigVersion());
     }
 
-    public int getTamingCOTWLength(EntityType type) {
-        return config.getInt("Skills.Taming.Call_Of_The_Wild." + StringUtils.getPrettyEntityTypeString(type) + ".Summon_Length");
-    }
+    /**
+     * Attempts to read the loaded config file
+     * MainConfig will have any necessary updates applied
+     * MainConfig will be compared to the default config to see if it is missing any nodes
+     * MainConfig will have any missing nodes inserted with their default value
+     */
+    public void readConfig() {
+        McmmoCore.getLogger().info("Attempting to read " + FILE_RELATIVE_PATH + ".");
 
-    public int getTamingCOTWMaxAmount(EntityType type) {
-        return config.getInt("Skills.Taming.Call_Of_The_Wild." + StringUtils.getPrettyEntityTypeString(type) + ".Summon_Max_Amount");
-    }
+        int version = this.userRootNode.getNode("ConfigVersion").getInt();
+        McmmoCore.getLogger().info(FILE_RELATIVE_PATH + " version is " + version);
 
-    public double getTamingCOTWRange() {
-        return config.getDouble("Skills.Taming.Call_Of_The_Wild.Range", 40.0D);
+        //Update our config
+        updateConfig();
     }
 
-    /* Woodcutting */
-    public boolean getWoodcuttingDoubleDropsEnabled(BlockData material) {
-        return config.getBoolean("Double_Drops.Woodcutting." + StringUtils.getFriendlyConfigBlockDataString(material));
-    }
+    /**
+     * Compares the users config file to the default and adds any missing nodes and applies any necessary updates
+     */
+    private void updateConfig()
+    {
+        McmmoCore.getLogger().info(defaultRootNode.getChildrenMap().size() +" items in default children map");
+        McmmoCore.getLogger().info(userRootNode.getChildrenMap().size() +" items in default root map");
 
-    public boolean getTreeFellerSoundsEnabled() {
-        return config.getBoolean("Skills.Woodcutting.Tree_Feller_Sounds", true);
-    }
+        // Merge Values from default
+        userRootNode = userRootNode.mergeValuesFrom(defaultRootNode);
 
-    public int getWoodcuttingGate() {
-        return config.getInt("Skills.Woodcutting.Ability_Activation_Level_Gate", 10);
-    }
+        // Update config version
+        updateConfigVersion();
 
-    /* AFK Leveling */
-    public boolean getAcrobaticsPreventAFK() {
-        return config.getBoolean("Skills.Acrobatics.Prevent_AFK_Leveling", true);
+        //Attempt to save
+        try {
+            saveUserCopy();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
     }
 
-    public int getAcrobaticsAFKMaxTries() {
-        return config.getInt("Skills.Acrobatics.Max_Tries_At_Same_Location", 3);
+    /**
+     * Saves the current state information of the config to the users copy (which they may edit)
+     * @throws IOException
+     */
+    private void saveUserCopy() throws IOException
+    {
+        McmmoCore.getLogger().info("Saving new node");
+        userCopyLoader.save(userRootNode);
     }
 
-    public boolean getHerbalismPreventAFK() {
-        return config.getBoolean("Skills.Herbalism.Prevent_AFK_Leveling", true);
+    /**
+     * Performs any necessary operations to update this config
+     */
+    private void updateConfigVersion() {
+        // Set a version for our config
+        this.userRootNode.getNode("ConfigVersion").setValue(getConfigVersion());
+        McmmoCore.getLogger().info("Updated config to ["+getConfigVersion()+"] - " + FILE_RELATIVE_PATH);
     }
 
-    /* Level Caps */
-    public int getPowerLevelCap() {
-        int cap = config.getInt("General.Power_Level_Cap", 0);
-        return (cap <= 0) ? Integer.MAX_VALUE : cap;
+    /**
+     * Returns the root node of this config
+     * @return the root node of this config
+     */
+    protected ConfigurationNode getUserRootNode() {
+        return userRootNode;
     }
 
-    public int getLevelCap(PrimarySkillType skill) {
-        int cap = config.getInt("Skills." + StringUtils.getCapitalized(skill.toString()) + ".Level_Cap");
-        return (cap <= 0) ? Integer.MAX_VALUE : cap;
+    int getIntValue(String... path)
+    {
+        return userRootNode.getNode(path).getInt();
     }
 
-
-    /*public int isSuperAbilityUnlocked(PrimarySkillType skill) {
-        return config.getInt("Skills." + StringUtils.getCapitalized(skill.toString()) + ".Ability_Activation_Level_Gate");
-    }*/
-
-    public boolean getTruncateSkills() {
-        return config.getBoolean("General.TruncateSkills", false);
+    double getDoubleValue(String... path)
+    {
+        return userRootNode.getNode(path).getDouble();
     }
 
-    /* PVP & PVE Settings */
-    public boolean getPVPEnabled(PrimarySkillType skill) {
-        return config.getBoolean("Skills." + StringUtils.getCapitalized(skill.toString()) + ".Enabled_For_PVP", true);
+    boolean getBooleanValue(String... path)
+    {
+        return userRootNode.getNode(path).getBoolean();
     }
 
-    public boolean getPVEEnabled(PrimarySkillType skill) {
-        return config.getBoolean("Skills." + StringUtils.getCapitalized(skill.toString()) + ".Enabled_For_PVE", true);
+    String getStringValue(String... path)
+    {
+        return userRootNode.getNode(path).getString();
     }
-
-    //public float getMasterVolume() { return (float) config.getDouble("Sounds.MasterVolume", 1.0); }
 }

+ 19 - 0
core/src/main/java/com/gmail/nossr50/core/config/ConfigKeyRegister.java

@@ -0,0 +1,19 @@
+package com.gmail.nossr50.core.config;
+
+import java.io.File;
+
+/**
+ * Represents a config file that registers keys after its initialized
+ */
+public abstract class ConfigKeyRegister extends Config implements RegistersKeys {
+
+    public ConfigKeyRegister(String pathToParentFolder, String relativePath) {
+        super(pathToParentFolder, relativePath);
+        loadKeys();
+    }
+
+    public ConfigKeyRegister(File pathToParentFolder, String relativePath) {
+        super(pathToParentFolder, relativePath);
+        loadKeys();
+    }
+}

+ 44 - 0
core/src/main/java/com/gmail/nossr50/core/config/ConfigValidated.java

@@ -0,0 +1,44 @@
+package com.gmail.nossr50.core.config;
+
+import com.gmail.nossr50.core.McmmoCore;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * This class is used for config files that validate their entries
+ */
+public abstract class ConfigValidated extends Config implements DefaultKeys {
+    public ConfigValidated(String parentFolderPath, String relativePath)
+    {
+        super(parentFolderPath, relativePath);
+        validateEntries();
+    }
+
+    public ConfigValidated(File parentFolderFile, String relativePath)
+    {
+        super(parentFolderFile, relativePath);
+        validateEntries();
+    }
+
+    /**
+     * Prints all errors found when validating the config
+     */
+    private void validateEntries()
+    {
+        /*
+         * Print Errors about Keys
+         */
+
+        List<String> validKeyErrors = validateKeys(); // Validate Keys
+
+        if(validKeyErrors != null && validKeyErrors.size() > 0)
+        {
+            for(String error : validKeyErrors)
+            {
+                McmmoCore.getLogger().severe(error);
+            }
+        }
+    }
+
+}

+ 0 - 315
core/src/main/java/com/gmail/nossr50/core/config/ConfigurableLoader.java

@@ -1,315 +0,0 @@
-package com.gmail.nossr50.core.config;
-
-import com.gmail.nossr50.core.McmmoCore;
-import com.google.common.io.Files;
-import ninja.leaping.configurate.ConfigurationNode;
-import ninja.leaping.configurate.commented.CommentedConfigurationNode;
-import ninja.leaping.configurate.loader.ConfigurationLoader;
-import ninja.leaping.configurate.yaml.YAMLConfigurationLoader;
-import org.yaml.snakeyaml.DumperOptions;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.List;
-
-/**
- * Handles loading and cacheing configuration settings from a configurable compatible config file
- */
-//@ConfigSerializable
-public abstract class ConfigurableLoader implements DefaultKeys, VersionedConfig {
-
-    /* PATH VARS */
-
-    public final File DIRECTORY_DATA_FOLDER; //Directory that the file is in
-    public final String FILE_RELATIVE_PATH; //Relative Path to the file
-    protected final String DIRECTORY_DEFAULTS = "defaults";
-
-    /* LOADERS */
-
-    private YAMLConfigurationLoader defaultCopyLoader;
-    private YAMLConfigurationLoader userCopyLoader;
-
-    /* CONFIG FILES */
-
-    private File resourceConfigCopy; //Copy of the default config from the JAR (file is copied so that admins can easily compare to defaults)
-    private File resourceUserCopy; //File in the /$MCMMO_ROOT/mcMMO/ directory that may contain user edited settings
-
-    /* ROOT NODES */
-
-    private ConfigurationNode userRootNode = null;
-    private ConfigurationNode defaultRootNode = null;
-
-    /* CONFIG MANAGER */
-    private ConfigurationLoader<CommentedConfigurationNode> configManager;
-
-    public ConfigurableLoader(String pathToParentFolder, String relativePath) {
-        //TODO: Check if this works...
-        this(new File(pathToParentFolder), relativePath);
-        System.out.println("mcMMO Debug: Don't forget to check if loading config file by string instead of File works...");
-    }
-
-    public ConfigurableLoader(File pathToParentFolder, String relativePath) {
-        /*
-         * These must be at the top
-         */
-        mkdirDefaults(); // Make our default config dir
-        DIRECTORY_DATA_FOLDER = pathToParentFolder; //Data Folder for our plugin
-        FILE_RELATIVE_PATH = relativePath; //Relative path to config from a parent folder
-
-        //Attempt IO Operations
-        try {
-            //Makes sure we have valid Files corresponding to this config
-            initConfigFiles();
-
-            //Init Config Loaders
-            initConfigLoaders();
-
-            //Load Config Nodes
-            loadConfig();
-
-            //Attempt to update user file, and then load it into memory
-            readConfig();
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-
-        /*
-         * Print Errors about Keys
-         */
-
-        List<String> validKeyErrors = validateKeys(); // Validate Keys
-
-        if(validKeyErrors != null && validKeyErrors.size() > 0)
-        {
-            for(String error : validKeyErrors)
-            {
-                McmmoCore.getLogger().severe(error);
-            }
-        }
-    }
-
-    /**
-     * Initializes the default copy File and the user config File
-     * @throws IOException
-     */
-    private void initConfigFiles() throws IOException {
-        //Init our config copy
-        resourceConfigCopy = initDefaultConfig();
-
-        //Init the user file
-        resourceUserCopy = initUserConfig();
-    }
-
-    /**
-     * Loads the root node for the default config File and user config File
-     */
-    private void loadConfig()
-    {
-        try {
-            final ConfigurationNode defaultConfig = this.defaultCopyLoader.load();
-            defaultRootNode = defaultConfig;
-
-            final ConfigurationNode userConfig = this.userCopyLoader.load();
-            userRootNode = userConfig;
-
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-    }
-
-    /**
-     * Initializes the YAMLConfigurationLoaders for this config
-     */
-    private void initConfigLoaders()
-    {
-        this.defaultCopyLoader = YAMLConfigurationLoader.builder().setPath(resourceConfigCopy.toPath()).setFlowStyle(DumperOptions.FlowStyle.BLOCK).build();
-        this.userCopyLoader = YAMLConfigurationLoader.builder().setPath(resourceUserCopy.toPath()).setFlowStyle(DumperOptions.FlowStyle.FLOW).build();
-    }
-
-    /**
-     * Copies a new file from the JAR to the defaults directory and uses that new file to initialize our resourceConfigCopy
-     * @see ConfigurableLoader#resourceConfigCopy
-     * @throws IOException
-     */
-    private File initDefaultConfig() throws IOException {
-        return copyDefaultFromJar(getDefaultConfigCopyRelativePath(), true);
-    }
-
-    /**
-     * Attemps to load the config file if it exists, if it doesn't it copies a new one from within the JAR
-     * @return user config File
-     * @see ConfigurableLoader#resourceUserCopy
-     * @throws IOException
-     */
-    private File initUserConfig() throws IOException {
-        File userCopy = new File(DIRECTORY_DATA_FOLDER, FILE_RELATIVE_PATH); //Load the user file;
-
-        if(userCopy.exists())
-        {
-            // Yay
-            return userCopy;
-        }
-        else
-        {
-            //If it's gone we copy default files
-            //Note that we don't copy the values from the default copy put in /defaults/ that file exists only as a reference to admins and is unreliable
-            return copyDefaultFromJar(FILE_RELATIVE_PATH, false);
-        }
-    }
-
-    /**
-     * Used to make a new config file at a specified relative output path inside the data directory by copying the matching file found in that same relative path within the JAR
-     * @param relativeOutputPath the path to the output file
-     * @param deleteOld whether or not to delete the existing output file on disk
-     * @return a copy of the default config within the JAR
-     * @throws IOException
-     */
-    private File copyDefaultFromJar(String relativeOutputPath, boolean deleteOld) throws IOException
-    {
-        /*
-         * Gen a Default config from inside the JAR
-         */
-        McmmoCore.getLogger().info("Preparing to copy internal resource file (in JAR) - "+FILE_RELATIVE_PATH);
-        InputStream inputStream = McmmoCore.getResource(FILE_RELATIVE_PATH);
-
-        byte[] buffer = new byte[inputStream.available()];
-        inputStream.read(buffer);
-
-        //This is a copy of the default file, which we will overwrite every time mcMMO loads
-        File targetFile = new File(DIRECTORY_DATA_FOLDER, relativeOutputPath);
-
-        //Wipe old default file on disk
-        if (targetFile.exists() && deleteOld)
-        {
-            McmmoCore.getLogger().info("Updating file " + relativeOutputPath);
-            targetFile.delete(); //Necessary?
-        }
-
-        if(!targetFile.exists())
-        {
-            targetFile.getParentFile().mkdirs();
-            targetFile.createNewFile(); //New File Boys
-        }
-
-        Files.write(buffer, targetFile);
-        McmmoCore.getLogger().info("Created config file - " + relativeOutputPath);
-
-        inputStream.close(); //Close the input stream
-
-        return targetFile;
-    }
-
-    /**
-     * The path to the defaults directory
-     * @return the path to the defaults directory
-     */
-    private String getDefaultConfigCopyRelativePath() {
-        return DIRECTORY_DEFAULTS + File.separator + FILE_RELATIVE_PATH;
-    }
-
-    /**
-     * Creates the defaults directory
-     */
-    private void mkdirDefaults() {
-        //Make Default Subdirectory
-        File defaultsDir = new File (DIRECTORY_DATA_FOLDER, "defaults");
-
-        if(!defaultsDir.exists())
-            defaultsDir.mkdir();
-    }
-
-    /**
-     * Configs are versioned based on when they had significant changes to keys
-     * @return current Config Version String
-     */
-    public String getVersion()
-    {
-         return String.valueOf(getConfigVersion());
-    }
-
-    /**
-     * Attempts to read the loaded config file
-     * Config will have any necessary updates applied
-     * Config will be compared to the default config to see if it is missing any nodes
-     * Config will have any missing nodes inserted with their default value
-     */
-    public void readConfig() {
-        McmmoCore.getLogger().info("Attempting to read " + FILE_RELATIVE_PATH + ".");
-
-        int version = this.userRootNode.getNode("ConfigVersion").getInt();
-        McmmoCore.getLogger().info(FILE_RELATIVE_PATH + " version is " + version);
-
-        //Update our config
-        updateConfig();
-    }
-
-    /**
-     * Compares the users config file to the default and adds any missing nodes and applies any necessary updates
-     */
-    private void updateConfig()
-    {
-        McmmoCore.getLogger().info(defaultRootNode.getChildrenMap().size() +" items in default children map");
-        McmmoCore.getLogger().info(userRootNode.getChildrenMap().size() +" items in default root map");
-
-        // Merge Values from default
-        userRootNode = userRootNode.mergeValuesFrom(defaultRootNode);
-
-        // Update config version
-        updateConfigVersion();
-
-        //Attempt to save
-        try {
-            saveUserCopy();
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-    }
-
-    /**
-     * Saves the current state information of the config to the users copy (which they may edit)
-     * @throws IOException
-     */
-    private void saveUserCopy() throws IOException
-    {
-        McmmoCore.getLogger().info("Saving new node");
-        userCopyLoader.save(userRootNode);
-    }
-
-    /**
-     * Performs any necessary operations to update this config
-     */
-    private void updateConfigVersion() {
-        // Set a version for our config
-        this.userRootNode.getNode("ConfigVersion").setValue(getConfigVersion());
-        McmmoCore.getLogger().info("Updated config to ["+getConfigVersion()+"] - " + FILE_RELATIVE_PATH);
-    }
-
-    /**
-     * Returns the root node of this config
-     * @return the root node of this config
-     */
-    protected ConfigurationNode getUserRootNode() {
-        return userRootNode;
-    }
-
-    int getIntValue(String... path)
-    {
-        return userRootNode.getNode(path).getInt();
-    }
-
-    double getDoubleValue(String... path)
-    {
-        return userRootNode.getNode(path).getDouble();
-    }
-
-    boolean getBooleanValue(String... path)
-    {
-        return userRootNode.getNode(path).getBoolean();
-    }
-
-    String getStringValue(String... path)
-    {
-        return userRootNode.getNode(path).getString();
-    }
-}

+ 12 - 9
core/src/main/java/com/gmail/nossr50/core/config/CoreSkillsConfig.java

@@ -5,12 +5,11 @@ import com.gmail.nossr50.core.skills.PrimarySkillType;
 import com.gmail.nossr50.core.skills.subskills.AbstractSubSkill;
 import com.gmail.nossr50.core.util.StringUtils;
 
-public class CoreSkillsConfig extends ConfigurableLoader {
+public class CoreSkillsConfig extends Config {
     private static CoreSkillsConfig instance;
 
     public CoreSkillsConfig() {
         super(McmmoCore.getDataFolderPath().getAbsoluteFile(),"coreskills.yml");
-        validate();
     }
 
     public static CoreSkillsConfig getInstance() {
@@ -20,15 +19,19 @@ public class CoreSkillsConfig extends ConfigurableLoader {
         return instance;
     }
 
+    /**
+     * The version of this config
+     *
+     * @return
+     */
     @Override
-    protected void loadKeys() {
-
+    public double getConfigVersion() {
+        return 1;
     }
 
     @Override
-    protected boolean validateKeys() {
-
-        return true;
+    public void unload() {
+        instance = null;
     }
 
     /*
@@ -43,7 +46,7 @@ public class CoreSkillsConfig extends ConfigurableLoader {
      * @return true if subskill is enabled
      */
     public boolean isSkillEnabled(AbstractSubSkill abstractSubSkill) {
-        return config.getBoolean(StringUtils.getCapitalized(abstractSubSkill.getPrimarySkill().toString()) + "." + abstractSubSkill.getConfigKeyName() + ".Enabled", true);
+        return getBooleanValue(StringUtils.getCapitalized(abstractSubSkill.getPrimarySkill().toString()) + "." + abstractSubSkill.getConfigKeyName() + ".Enabled", true);
     }
 
     /**
@@ -53,6 +56,6 @@ public class CoreSkillsConfig extends ConfigurableLoader {
      * @return true if enabled
      */
     public boolean isPrimarySkillEnabled(PrimarySkillType primarySkillType) {
-        return config.getBoolean(StringUtils.getCapitalized(primarySkillType.toString()) + ".Enabled", true);
+        return getBooleanValue(StringUtils.getCapitalized(primarySkillType.toString()) + ".Enabled", true);
     }
 }

+ 1041 - 0
core/src/main/java/com/gmail/nossr50/core/config/MainConfig.java

@@ -0,0 +1,1041 @@
+package com.gmail.nossr50.core.config;
+
+import com.gmail.nossr50.core.McmmoCore;
+import com.gmail.nossr50.core.data.database.SQLDatabaseManager;
+import com.gmail.nossr50.core.datatypes.party.PartyFeature;
+import com.gmail.nossr50.core.skills.MobHealthbarType;
+import com.gmail.nossr50.core.skills.PrimarySkillType;
+import com.gmail.nossr50.core.skills.SuperAbilityType;
+import com.gmail.nossr50.core.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+public class MainConfig extends ConfigValidated {
+    private static MainConfig instance;
+
+    private MainConfig() {
+        super(McmmoCore.getDataFolderPath().getAbsoluteFile(), "config.yml");
+    }
+
+    public static MainConfig getInstance() {
+        if (instance == null) {
+            instance = new MainConfig();
+        }
+
+        return instance;
+    }
+
+    @Override
+    public void unload() {
+        instance = null;
+    }
+
+    /**
+     * The version of this config
+     *
+     * @return
+     */
+    @Override
+    public double getConfigVersion() {
+        return 1;
+    }
+
+    @Override
+    public List<String> validateKeys() {
+        // Validate all the settings!
+        List<String> reason = new ArrayList<String>();
+
+        /* General Settings */
+        if (getSaveInterval() <= 0) {
+            reason.add("General.Save_Interval should be greater than 0!");
+        }
+
+        /* MySQL Settings */
+        for (SQLDatabaseManager.PoolIdentifier identifier : SQLDatabaseManager.PoolIdentifier.values()) {
+            if (getMySQLMaxConnections(identifier) <= 0) {
+                reason.add("MySQL.Database.MaxConnections." + StringUtils.getCapitalized(identifier.toString()) + " should be greater than 0!");
+            }
+            if (getMySQLMaxPoolSize(identifier) <= 0) {
+                reason.add("MySQL.Database.MaxPoolSize." + StringUtils.getCapitalized(identifier.toString()) + " should be greater than 0!");
+            }
+        }
+
+        /* Mob Healthbar */
+        if (getMobHealthbarTime() == 0) {
+            reason.add("Mob_Healthbar.Display_Time cannot be 0! Set to -1 to disable or set a valid value.");
+        }
+
+        /* Scoreboards */
+        /*if (getRankScoreboardTime() != -1 && getRankScoreboardTime() <= 0) {
+            reason.add("Scoreboard.Types.Rank.Display_Time should be greater than 0, or -1!");
+        }
+
+        if (getStatsScoreboardTime() != -1 && getStatsScoreboardTime() <= 0) {
+            reason.add("Scoreboard.Types.Stats.Display_Time should be greater than 0, or -1!");
+        }
+
+        if (getTopScoreboardTime() != -1 && getTopScoreboardTime() <= 0) {
+            reason.add("Scoreboard.Types.Top.Display_Time should be greater than 0, or -1!");
+        }
+
+        if (getInspectScoreboardTime() != -1 && getInspectScoreboardTime() <= 0) {
+            reason.add("Scoreboard.Types.Inspect.Display_Time should be greater than 0, or -1!");
+        }
+
+        if (getSkillScoreboardTime() != -1 && getSkillScoreboardTime() <= 0) {
+            reason.add("Scoreboard.Types.Skill.Display_Time should be greater than 0, or -1!");
+        }
+
+        if (getSkillLevelUpTime() != -1 && getSkillScoreboardTime() <= 0) {
+            reason.add("Scoreboard.Types.Skill.Display_Time should be greater than 0, or -1!");
+        }
+
+        if (!(getRankUseChat() || getRankUseBoard())) {
+            reason.add("Either Board or Print in Scoreboard.Types.Rank must be true!");
+        }
+
+        if (!(getTopUseChat() || getTopUseBoard())) {
+            reason.add("Either Board or Print in Scoreboard.Types.Top must be true!");
+        }
+
+        if (!(getStatsUseChat() || getStatsUseBoard())) {
+            reason.add("Either Board or Print in Scoreboard.Types.Stats must be true!");
+        }
+
+        if (!(getInspectUseChat() || getInspectUseBoard())) {
+            reason.add("Either Board or Print in Scoreboard.Types.Inspect must be true!");
+        }*/
+
+        /* Database Purging */
+        if (getPurgeInterval() < -1) {
+            reason.add("Database_Purging.Purge_Interval should be greater than, or equal to -1!");
+        }
+
+        if (getOldUsersCutoff() != -1 && getOldUsersCutoff() <= 0) {
+            reason.add("Database_Purging.Old_User_Cutoff should be greater than 0 or -1!");
+        }
+
+        /* Hardcore Mode */
+        if (getHardcoreDeathStatPenaltyPercentage() < 0.01 || getHardcoreDeathStatPenaltyPercentage() > 100) {
+            reason.add("Hardcore.Death_Stat_Loss.Penalty_Percentage only accepts values from 0.01 to 100!");
+        }
+
+        if (getHardcoreVampirismStatLeechPercentage() < 0.01 || getHardcoreVampirismStatLeechPercentage() > 100) {
+            reason.add("Hardcore.Vampirism.Leech_Percentage only accepts values from 0.01 to 100!");
+        }
+
+        /* Items */
+        if (getChimaeraUseCost() < 1 || getChimaeraUseCost() > 64) {
+            reason.add("Items.Chimaera_Wing.Use_Cost only accepts values from 1 to 64!");
+        }
+
+        if (getChimaeraRecipeCost() < 1 || getChimaeraRecipeCost() > 9) {
+            reason.add("Items.Chimaera_Wing.Recipe_Cost only accepts values from 1 to 9!");
+        }
+
+        if (getChimaeraItem() == null) {
+            reason.add("Items.Chimaera_Wing.Item_Name is invalid!");
+        }
+
+        /* Particles */
+        if (getLevelUpEffectsTier() < 1) {
+            reason.add("Particles.LevelUp_Tier should be at least 1!");
+        }
+
+        /* PARTY SETTINGS */
+        if (getAutoPartyKickInterval() < -1) {
+            reason.add("Party.AutoKick_Interval should be at least -1!");
+        }
+
+        if (getAutoPartyKickTime() < 0) {
+            reason.add("Party.Old_Party_Member_Cutoff should be at least 0!");
+        }
+
+        if (getPartyShareBonusBase() <= 0) {
+            reason.add("Party.Sharing.ExpShare_bonus_base should be greater than 0!");
+        }
+
+        if (getPartyShareBonusIncrease() < 0) {
+            reason.add("Party.Sharing.ExpShare_bonus_increase should be at least 0!");
+        }
+
+        if (getPartyShareBonusCap() <= 0) {
+            reason.add("Party.Sharing.ExpShare_bonus_cap should be greater than 0!");
+        }
+
+        if (getPartyShareRange() <= 0) {
+            reason.add("Party.Sharing.Range should be greater than 0!");
+        }
+
+        if (getPartyXpCurveMultiplier() < 1) {
+            reason.add("Party.Leveling.Xp_Curve_Modifier should be at least 1!");
+        }
+
+        for (PartyFeature partyFeature : PartyFeature.values()) {
+            if (getPartyFeatureUnlockLevel(partyFeature) < 0) {
+                reason.add("Party.Leveling." + StringUtils.getPrettyPartyFeatureString(partyFeature).replace(" ", "") + "_UnlockLevel should be at least 0!");
+            }
+        }
+
+        /* Inspect command distance */
+        if (getInspectDistance() <= 0) {
+            reason.add("Commands.inspect.Max_Distance should be greater than 0!");
+        }
+
+        if (getTreeFellerThreshold() <= 0) {
+            reason.add("Abilities.Limits.Tree_Feller_Threshold should be greater than 0!");
+        }
+
+        if (getFishingLureModifier() < 0) {
+            reason.add("Abilities.Fishing.Lure_Modifier should be at least 0!");
+        }
+
+        if (getDetonatorItem() == null) {
+            reason.add("Skills.Mining.Detonator_Item is invalid!");
+        }
+
+        if (getRepairAnvilMaterial() == null) {
+            reason.add("Skills.Repair.Anvil_Type is invalid!!");
+        }
+
+        if (getSalvageAnvilMaterial() == null) {
+            reason.add("Skills.Repair.Salvage_Anvil_Type is invalid!");
+        }
+
+        if (getRepairAnvilMaterial() == getSalvageAnvilMaterial()) {
+            reason.add("Cannot use the same item for Repair and Salvage anvils!");
+        }
+
+        if (getTamingCOTWMaterial(EntityType.WOLF) == null) {
+            reason.add("Skills.Taming.Call_Of_The_Wild.Wolf.Item_Material is invalid!!");
+        }
+
+        if (getTamingCOTWMaterial(EntityType.OCELOT) == null) {
+            reason.add("Skills.Taming.Call_Of_The_Wild.Ocelot.Item_Material is invalid!!");
+        }
+
+        if (getTamingCOTWMaterial(EntityType.HORSE) == null) {
+            reason.add("Skills.Taming.Call_Of_The_Wild.Horse.Item_Material is invalid!!");
+        }
+
+        if (getTamingCOTWCost(EntityType.WOLF) <= 0) {
+            reason.add("Skills.Taming.Call_Of_The_Wild.Wolf.Item_Amount should be greater than 0!");
+        }
+
+        if (getTamingCOTWCost(EntityType.OCELOT) <= 0) {
+            reason.add("Skills.Taming.Call_Of_The_Wild.Ocelot.Item_Amount should be greater than 0!");
+        }
+
+        if (getTamingCOTWCost(EntityType.HORSE) <= 0) {
+            reason.add("Skills.Taming.Call_Of_The_Wild.Horse.Item_Amount should be greater than 0!");
+        }
+
+        if (getTamingCOTWAmount(EntityType.WOLF) <= 0) {
+            reason.add("Skills.Taming.Call_Of_The_Wild.Wolf.Summon_Amount should be greater than 0!");
+        }
+
+        if (getTamingCOTWAmount(EntityType.OCELOT) <= 0) {
+            reason.add("Skills.Taming.Call_Of_The_Wild.Ocelot.Summon_Amount should be greater than 0!");
+        }
+
+        if (getTamingCOTWAmount(EntityType.HORSE) <= 0) {
+            reason.add("Skills.Taming.Call_Of_The_Wild.Horse.Summon_Amount should be greater than 0!");
+        }
+
+        return reason;
+    }
+
+    /*
+     * GENERAL SETTINGS
+     */
+
+    /* General Settings */
+    public boolean getIsMetricsEnabled() {
+        return getBooleanValue("Metrics.bstats", true);
+    }
+
+    //Retro mode will default the value to true if the config file doesn't contain the entry (server is from a previous mcMMO install)
+    public boolean getIsRetroMode() {
+        return getBooleanValue("General.RetroMode.Enabled", true);
+    }
+
+    public String getLocale() {
+        return getStringValue("General.Locale", "en_us");
+    }
+
+    public boolean getMOTDEnabled() {
+        return getBooleanValue("General.MOTD_Enabled", true);
+    }
+
+    public boolean getShowProfileLoadedMessage() {
+        return getBooleanValue("General.Show_Profile_Loaded", true);
+    }
+
+    public boolean getDonateMessageEnabled() {
+        return getBooleanValue("Commands.mcmmo.Donate_Message", true);
+    }
+
+    public int getSaveInterval() {
+        return getIntValue("General.Save_Interval", 10);
+    }
+
+    public boolean getStatsTrackingEnabled() {
+        return getBooleanValue("General.Stats_Tracking", true);
+    }
+
+    public boolean getUpdateCheckEnabled() {
+        return getBooleanValue("General.Update_Check", true);
+    }
+
+    public boolean getPreferBeta() {
+        return getBooleanValue("General.Prefer_Beta", false);
+    }
+
+    public boolean getVerboseLoggingEnabled() {
+        return getBooleanValue("General.Verbose_Logging", false);
+    }
+
+    public String getPartyChatPrefix() {
+        return getStringValue("Commands.partychat.Chat_Prefix_Format", "[[GREEN]]([[WHITE]]{0}[[GREEN]])");
+    }
+
+    public boolean getPartyChatColorLeaderName() {
+        return getBooleanValue("Commands.partychat.Gold_Leader_Name", true);
+    }
+
+    public boolean getPartyDisplayNames() {
+        return getBooleanValue("Commands.partychat.Use_Display_Names", true);
+    }
+
+    public String getPartyChatPrefixAlly() {
+        return getStringValue("Commands.partychat.Chat_Prefix_Format_Ally", "[[GREEN]](A)[[RESET]]");
+    }
+
+    public String getAdminChatPrefix() {
+        return getStringValue("Commands.adminchat.Chat_Prefix_Format", "[[AQUA]][[[WHITE]]{0}[[AQUA]]]");
+    }
+
+    public boolean getAdminDisplayNames() {
+        return getBooleanValue("Commands.adminchat.Use_Display_Names", true);
+    }
+
+    public boolean getMatchOfflinePlayers() {
+        return getBooleanValue("Commands.Generic.Match_OfflinePlayers", false);
+    }
+
+    public long getDatabasePlayerCooldown() {
+        return config.getLong("Commands.Database.Player_Cooldown", 1750);
+    }
+
+    public boolean getLevelUpSoundsEnabled() {
+        return getBooleanValue("General.LevelUp_Sounds", true);
+    }
+
+    public boolean getRefreshChunksEnabled() {
+        return getBooleanValue("General.Refresh_Chunks", false);
+    }
+
+    public boolean getMobHealthbarEnabled() {
+        return getBooleanValue("Mob_Healthbar.Enabled", true);
+    }
+
+    /* Mob Healthbar */
+    public MobHealthbarType getMobHealthbarDefault() {
+        try {
+            return MobHealthbarType.valueOf(getStringValue("Mob_Healthbar.Display_Type", "HEARTS").toUpperCase().trim());
+        } catch (IllegalArgumentException ex) {
+            return MobHealthbarType.HEARTS;
+        }
+    }
+
+    public int getMobHealthbarTime() {
+        return getIntValue("Mob_Healthbar.Display_Time", 3);
+    }
+
+    /* Scoreboards */
+    public boolean getScoreboardsEnabled() {
+        return getBooleanValue("Scoreboard.UseScoreboards", true);
+    }
+
+    public boolean getPowerLevelTagsEnabled() {
+        return getBooleanValue("Scoreboard.Power_Level_Tags", false);
+    }
+
+    public boolean getAllowKeepBoard() {
+        return getBooleanValue("Scoreboard.Allow_Keep", true);
+    }
+
+    public int getTipsAmount() {
+        return getIntValue("Scoreboard.Tips_Amount", 5);
+    }
+
+    public boolean getShowStatsAfterLogin() {
+        return getBooleanValue("Scoreboard.Show_Stats_After_Login", false);
+    }
+
+    public boolean getScoreboardRainbows() {
+        return getBooleanValue("Scoreboard.Rainbows", false);
+    }
+
+    public boolean getShowAbilityNames() {
+        return getBooleanValue("Scoreboard.Ability_Names", true);
+    }
+
+    public boolean getRankUseChat() {
+        return getBooleanValue("Scoreboard.Types.Rank.Print", false);
+    }
+
+    public boolean getRankUseBoard() {
+        return getBooleanValue("Scoreboard.Types.Rank.Board", true);
+    }
+
+    public int getRankScoreboardTime() {
+        return getIntValue("Scoreboard.Types.Rank.Display_Time", 10);
+    }
+
+    public boolean getTopUseChat() {
+        return getBooleanValue("Scoreboard.Types.Top.Print", true);
+    }
+
+    public boolean getTopUseBoard() {
+        return getBooleanValue("Scoreboard.Types.Top.Board", true);
+    }
+
+    public int getTopScoreboardTime() {
+        return getIntValue("Scoreboard.Types.Top.Display_Time", 15);
+    }
+
+    public boolean getStatsUseChat() {
+        return getBooleanValue("Scoreboard.Types.Stats.Print", true);
+    }
+
+    public boolean getStatsUseBoard() {
+        return getBooleanValue("Scoreboard.Types.Stats.Board", true);
+    }
+
+    public int getStatsScoreboardTime() {
+        return getIntValue("Scoreboard.Types.Stats.Display_Time", 10);
+    }
+
+    public boolean getInspectUseChat() {
+        return getBooleanValue("Scoreboard.Types.Inspect.Print", true);
+    }
+
+    public boolean getInspectUseBoard() {
+        return getBooleanValue("Scoreboard.Types.Inspect.Board", true);
+    }
+
+    public int getInspectScoreboardTime() {
+        return getIntValue("Scoreboard.Types.Inspect.Display_Time", 25);
+    }
+
+    public boolean getCooldownUseChat() {
+        return getBooleanValue("Scoreboard.Types.Cooldown.Print", false);
+    }
+
+    public boolean getCooldownUseBoard() {
+        return getBooleanValue("Scoreboard.Types.Cooldown.Board", true);
+    }
+
+    public int getCooldownScoreboardTime() {
+        return getIntValue("Scoreboard.Types.Cooldown.Display_Time", 41);
+    }
+
+    public boolean getSkillUseBoard() {
+        return getBooleanValue("Scoreboard.Types.Skill.Board", true);
+    }
+
+    public int getSkillScoreboardTime() {
+        return getIntValue("Scoreboard.Types.Skill.Display_Time", 30);
+    }
+
+    public boolean getSkillLevelUpBoard() {
+        return getBooleanValue("Scoreboard.Types.Skill.LevelUp_Board", true);
+    }
+
+    public int getSkillLevelUpTime() {
+        return getIntValue("Scoreboard.Types.Skill.LevelUp_Time", 5);
+    }
+
+    /* Database Purging */
+    public int getPurgeInterval() {
+        return getIntValue("Database_Purging.Purge_Interval", -1);
+    }
+
+    public int getOldUsersCutoff() {
+        return getIntValue("Database_Purging.Old_User_Cutoff", 6);
+    }
+
+    /* Backups */
+    public boolean getBackupsEnabled() {
+        return getBooleanValue("Backups.Enabled", true);
+    }
+
+    public boolean getKeepLast24Hours() {
+        return getBooleanValue("Backups.Keep.Last_24_Hours", true);
+    }
+
+    public boolean getKeepDailyLastWeek() {
+        return getBooleanValue("Backups.Keep.Daily_Last_Week", true);
+    }
+
+    public boolean getKeepWeeklyPastMonth() {
+        return getBooleanValue("Backups.Keep.Weekly_Past_Months", true);
+    }
+
+    /* mySQL */
+    public boolean getUseMySQL() {
+        return getBooleanValue("MySQL.Enabled", false);
+    }
+
+    public String getMySQLTablePrefix() {
+        return getStringValue("MySQL.Database.TablePrefix", "mcmmo_");
+    }
+
+    public String getMySQLDatabaseName() {
+        return getStringIncludingInts("MySQL.Database.Name");
+    }
+
+    public String getMySQLUserName() {
+        return getStringIncludingInts("MySQL.Database.User_Name");
+    }
+
+    public int getMySQLServerPort() {
+        return getIntValue("MySQL.Server.Port", 3306);
+    }
+
+    public String getMySQLServerName() {
+        return getStringValue("MySQL.Server.Address", "localhost");
+    }
+
+    public String getMySQLUserPassword() {
+        return getStringIncludingInts("MySQL.Database.User_Password");
+    }
+
+    public int getMySQLMaxConnections(SQLDatabaseManager.PoolIdentifier identifier) {
+        return getIntValue("MySQL.Database.MaxConnections." + StringUtils.getCapitalized(identifier.toString()), 30);
+    }
+
+    public int getMySQLMaxPoolSize(SQLDatabaseManager.PoolIdentifier identifier) {
+        return getIntValue("MySQL.Database.MaxPoolSize." + StringUtils.getCapitalized(identifier.toString()), 10);
+    }
+
+    public boolean getMySQLSSL() {
+        return getBooleanValue("MySQL.Server.SSL", true);
+    }
+
+    private String getStringIncludingInts(String key) {
+        String str = getStringValue(key);
+
+        if (str == null) {
+            str = String.valueOf(getIntValue(key));
+        }
+
+        if (str.equals("0")) {
+            str = "No value set for '" + key + "'";
+        }
+        return str;
+    }
+
+    /* Hardcore Mode */
+    public boolean getHardcoreStatLossEnabled(PrimarySkillType primarySkillType) {
+        return getBooleanValue("Hardcore.Death_Stat_Loss.Enabled." + StringUtils.getCapitalized(primarySkillType.toString()), false);
+    }
+
+    public void setHardcoreStatLossEnabled(PrimarySkillType primarySkillType, boolean enabled) {
+        config.set("Hardcore.Death_Stat_Loss.Enabled." + StringUtils.getCapitalized(primarySkillType.toString()), enabled);
+    }
+
+    public double getHardcoreDeathStatPenaltyPercentage() {
+        return getDoubleValue("Hardcore.Death_Stat_Loss.Penalty_Percentage", 75.0D);
+    }
+
+    public void setHardcoreDeathStatPenaltyPercentage(double value) {
+        config.set("Hardcore.Death_Stat_Loss.Penalty_Percentage", value);
+    }
+
+    public int getHardcoreDeathStatPenaltyLevelThreshold() {
+        return getIntValue("Hardcore.Death_Stat_Loss.Level_Threshold", 0);
+    }
+
+    public boolean getHardcoreVampirismEnabled(PrimarySkillType primarySkillType) {
+        return getBooleanValue("Hardcore.Vampirism.Enabled." + StringUtils.getCapitalized(primarySkillType.toString()), false);
+    }
+
+    public void setHardcoreVampirismEnabled(PrimarySkillType primarySkillType, boolean enabled) {
+        config.set("Hardcore.Vampirism.Enabled." + StringUtils.getCapitalized(primarySkillType.toString()), enabled);
+    }
+
+    public double getHardcoreVampirismStatLeechPercentage() {
+        return getDoubleValue("Hardcore.Vampirism.Leech_Percentage", 5.0D);
+    }
+
+    public void setHardcoreVampirismStatLeechPercentage(double value) {
+        config.set("Hardcore.Vampirism.Leech_Percentage", value);
+    }
+
+    public int getHardcoreVampirismLevelThreshold() {
+        return getIntValue("Hardcore.Vampirism.Level_Threshold", 0);
+    }
+
+    /* SMP Mods */
+    public boolean getToolModsEnabled() {
+        return getBooleanValue("Mods.Tool_Mods_Enabled", false);
+    }
+
+    public boolean getArmorModsEnabled() {
+        return getBooleanValue("Mods.Armor_Mods_Enabled", false);
+    }
+
+    public boolean getBlockModsEnabled() {
+        return getBooleanValue("Mods.Block_Mods_Enabled", false);
+    }
+
+    public boolean getEntityModsEnabled() {
+        return getBooleanValue("Mods.Entity_Mods_Enabled", false);
+    }
+
+    /* Items */
+    public int getChimaeraUseCost() {
+        return getIntValue("Items.Chimaera_Wing.Use_Cost", 1);
+    }
+
+    public int getChimaeraRecipeCost() {
+        return getIntValue("Items.Chimaera_Wing.Recipe_Cost", 5);
+    }
+
+    public Material getChimaeraItem() {
+        return Material.matchMaterial(getStringValue("Items.Chimaera_Wing.Item_Name", "Feather"));
+    }
+
+    public boolean getChimaeraEnabled() {
+        return getBooleanValue("Items.Chimaera_Wing.Enabled", true);
+    }
+
+    public boolean getChimaeraPreventUseUnderground() {
+        return getBooleanValue("Items.Chimaera_Wing.Prevent_Use_Underground", true);
+    }
+
+    public boolean getChimaeraUseBedSpawn() {
+        return getBooleanValue("Items.Chimaera_Wing.Use_Bed_Spawn", true);
+    }
+
+    public int getChimaeraCooldown() {
+        return getIntValue("Items.Chimaera_Wing.Cooldown", 240);
+    }
+
+    public int getChimaeraWarmup() {
+        return getIntValue("Items.Chimaera_Wing.Warmup", 5);
+    }
+
+    public int getChimaeraRecentlyHurtCooldown() {
+        return getIntValue("Items.Chimaera_Wing.RecentlyHurt_Cooldown", 60);
+    }
+
+    public boolean getChimaeraSoundEnabled() {
+        return getBooleanValue("Items.Chimaera_Wing.Sound_Enabled", true);
+    }
+
+    public boolean getFluxPickaxeSoundEnabled() {
+        return getBooleanValue("Items.Flux_Pickaxe.Sound_Enabled", true);
+    }
+
+    /* Particles */
+    public boolean getAbilityActivationEffectEnabled() {
+        return getBooleanValue("Particles.Ability_Activation", true);
+    }
+
+    public boolean getAbilityDeactivationEffectEnabled() {
+        return getBooleanValue("Particles.Ability_Deactivation", true);
+    }
+
+    public boolean getBleedEffectEnabled() {
+        return getBooleanValue("Particles.Bleed", true);
+    }
+
+    public boolean getDodgeEffectEnabled() {
+        return getBooleanValue("Particles.Dodge", true);
+    }
+
+    public boolean getFluxEffectEnabled() {
+        return getBooleanValue("Particles.Flux", true);
+    }
+
+    public boolean getGreaterImpactEffectEnabled() {
+        return getBooleanValue("Particles.Greater_Impact", true);
+    }
+
+    public boolean getCallOfTheWildEffectEnabled() {
+        return getBooleanValue("Particles.Call_of_the_Wild", true);
+    }
+
+    public boolean getLevelUpEffectsEnabled() {
+        return getBooleanValue("Particles.LevelUp_Enabled", true);
+    }
+
+    public int getLevelUpEffectsTier() {
+        return getIntValue("Particles.LevelUp_Tier", 100);
+    }
+
+    public boolean getLargeFireworks() {
+        return getBooleanValue("Particles.LargeFireworks", true);
+    }
+
+    /* PARTY SETTINGS */
+    public boolean getPartyFriendlyFire() {
+        return getBooleanValue("Party.FriendlyFire", false);
+    }
+
+    public int getPartyMaxSize() {
+        return getIntValue("Party.MaxSize", -1);
+    }
+
+    public int getAutoPartyKickInterval() {
+        return getIntValue("Party.AutoKick_Interval", 12);
+    }
+
+    public int getAutoPartyKickTime() {
+        return getIntValue("Party.Old_Party_Member_Cutoff", 7);
+    }
+
+    public double getPartyShareBonusBase() {
+        return getDoubleValue("Party.Sharing.ExpShare_bonus_base", 1.1D);
+    }
+
+    public double getPartyShareBonusIncrease() {
+        return getDoubleValue("Party.Sharing.ExpShare_bonus_increase", 0.05D);
+    }
+
+    public double getPartyShareBonusCap() {
+        return getDoubleValue("Party.Sharing.ExpShare_bonus_cap", 1.5D);
+    }
+
+    public double getPartyShareRange() {
+        return getDoubleValue("Party.Sharing.Range", 75.0D);
+    }
+
+    public int getPartyLevelCap() {
+        int cap = getIntValue("Party.Leveling.Level_Cap", 10);
+        return (cap <= 0) ? Integer.MAX_VALUE : cap;
+    }
+
+    public int getPartyXpCurveMultiplier() {
+        return getIntValue("Party.Leveling.Xp_Curve_Modifier", 3);
+    }
+
+    public boolean getPartyXpNearMembersNeeded() {
+        return getBooleanValue("Party.Leveling.Near_Members_Needed", false);
+    }
+
+    public boolean getPartyInformAllMembers() {
+        return getBooleanValue("Party.Leveling.Inform_All_Party_Members_On_LevelUp", false);
+    }
+
+    public int getPartyFeatureUnlockLevel(PartyFeature partyFeature) {
+        return getIntValue("Party.Leveling." + StringUtils.getPrettyPartyFeatureString(partyFeature).replace(" ", "") + "_UnlockLevel", 0);
+    }
+
+    /* Party Teleport Settings */
+    public int getPTPCommandCooldown() {
+        return getIntValue("Commands.ptp.Cooldown", 120);
+    }
+
+    public int getPTPCommandWarmup() {
+        return getIntValue("Commands.ptp.Warmup", 5);
+    }
+
+    public int getPTPCommandRecentlyHurtCooldown() {
+        return getIntValue("Commands.ptp.RecentlyHurt_Cooldown", 60);
+    }
+
+    public int getPTPCommandTimeout() {
+        return getIntValue("Commands.ptp.Request_Timeout", 300);
+    }
+
+    public boolean getPTPCommandConfirmRequired() {
+        return getBooleanValue("Commands.ptp.Accept_Required", true);
+    }
+
+    public boolean getPTPCommandWorldPermissions() {
+        return getBooleanValue("Commands.ptp.World_Based_Permissions", false);
+    }
+
+    /* Inspect command distance */
+    public double getInspectDistance() {
+        return getDoubleValue("Commands.inspect.Max_Distance", 30.0D);
+    }
+
+    /*
+     * ABILITY SETTINGS
+     */
+
+    /* General Settings */
+    public boolean getUrlLinksEnabled() {
+        return getBooleanValue("Commands.Skills.URL_Links");
+    }
+
+    public boolean getAbilityMessagesEnabled() {
+        return getBooleanValue("Abilities.Messages", true);
+    }
+
+    public boolean getAbilitiesEnabled() {
+        return getBooleanValue("Abilities.Enabled", true);
+    }
+
+    public boolean getAbilitiesOnlyActivateWhenSneaking() {
+        return getBooleanValue("Abilities.Activation.Only_Activate_When_Sneaking", false);
+    }
+
+    public boolean getAbilitiesGateEnabled() {
+        return getBooleanValue("Abilities.Activation.Level_Gate_Abilities");
+    }
+
+    public int getCooldown(SuperAbilityType ability) {
+        return getIntValue("Abilities.Cooldowns." + ability.toString());
+    }
+
+    public int getMaxLength(SuperAbilityType ability) {
+        return getIntValue("Abilities.Max_Seconds." + ability.toString());
+    }
+
+    /* Durability Settings */
+    public int getAbilityToolDamage() {
+        return getIntValue("Abilities.Tools.Durability_Loss", 1);
+    }
+
+    /* Thresholds */
+    public int getTreeFellerThreshold() {
+        return getIntValue("Abilities.Limits.Tree_Feller_Threshold", 500);
+    }
+
+    /*
+     * SKILL SETTINGS
+     */
+    public boolean getDoubleDropsEnabled(PrimarySkillType skill, Material material) {
+        return getBooleanValue("Double_Drops." + StringUtils.getCapitalized(skill.toString()) + "." + StringUtils.getPrettyItemString(material).replace(" ", "_"));
+    }
+
+    public boolean getDoubleDropsDisabled(PrimarySkillType skill) {
+        String skillName = StringUtils.getCapitalized(skill.toString());
+        ConfigurationSection section = config.getConfigurationSection("Double_Drops." + skillName);
+        if (section == null)
+            return false;
+        Set<String> keys = section.getKeys(false);
+        boolean disabled = true;
+
+        for (String key : keys) {
+            if (getBooleanValue("Double_Drops." + skillName + "." + key)) {
+                disabled = false;
+                break;
+            }
+        }
+
+        return disabled;
+    }
+
+    /* Axes */
+    public int getAxesGate() {
+        return getIntValue("Skills.Axes.Ability_Activation_Level_Gate", 10);
+    }
+
+    /* Acrobatics */
+    public boolean getDodgeLightningDisabled() {
+        return getBooleanValue("Skills.Acrobatics.Prevent_Dodge_Lightning", false);
+    }
+
+    public int getXPAfterTeleportCooldown() {
+        return getIntValue("Skills.Acrobatics.XP_After_Teleport_Cooldown", 5);
+    }
+
+    /* Alchemy */
+    public boolean getEnabledForHoppers() {
+        return getBooleanValue("Skills.Alchemy.Enabled_for_Hoppers", true);
+    }
+
+    public boolean getPreventHopperTransferIngredients() {
+        return getBooleanValue("Skills.Alchemy.Prevent_Hopper_Transfer_Ingredients", false);
+    }
+
+    public boolean getPreventHopperTransferBottles() {
+        return getBooleanValue("Skills.Alchemy.Prevent_Hopper_Transfer_Bottles", false);
+    }
+
+    /* Fishing */
+    public boolean getFishingDropsEnabled() {
+        return getBooleanValue("Skills.Fishing.Drops_Enabled", true);
+    }
+
+    public boolean getFishingOverrideTreasures() {
+        return getBooleanValue("Skills.Fishing.Override_Vanilla_Treasures", true);
+    }
+
+    public boolean getFishingExtraFish() {
+        return getBooleanValue("Skills.Fishing.Extra_Fish", true);
+    }
+
+    public double getFishingLureModifier() {
+        return getDoubleValue("Skills.Fishing.Lure_Modifier", 4.0D);
+    }
+
+    /* Mining */
+    public Material getDetonatorItem() {
+        return Material.matchMaterial(getStringValue("Skills.Mining.Detonator_Name", "FLINT_AND_STEEL"));
+    }
+
+    public int getMiningGate() {
+        return getIntValue("Skills.Mining.Ability_Activation_Level_Gate", 10);
+    }
+
+    /* Excavation */
+    public int getExcavationGate() {
+        return getIntValue("Skills.Excavation.Ability_Activation_Level_Gate", 10);
+    }
+
+    /* Repair */
+    public boolean getRepairAnvilMessagesEnabled() {
+        return getBooleanValue("Skills.Repair.Anvil_Messages", true);
+    }
+
+    public boolean getRepairAnvilPlaceSoundsEnabled() {
+        return getBooleanValue("Skills.Repair.Anvil_Placed_Sounds", true);
+    }
+
+    public boolean getRepairAnvilUseSoundsEnabled() {
+        return getBooleanValue("Skills.Repair.Anvil_Use_Sounds", true);
+    }
+
+    public Material getRepairAnvilMaterial() {
+        return Material.matchMaterial(getStringValue("Skills.Repair.Anvil_Material", "IRON_BLOCK"));
+    }
+
+    public boolean getRepairConfirmRequired() {
+        return getBooleanValue("Skills.Repair.Confirm_Required", true);
+    }
+
+    /* Salvage */
+    public boolean getSalvageAnvilMessagesEnabled() {
+        return getBooleanValue("Skills.Salvage.Anvil_Messages", true);
+    }
+
+    public boolean getSalvageAnvilPlaceSoundsEnabled() {
+        return getBooleanValue("Skills.Salvage.Anvil_Placed_Sounds", true);
+    }
+
+    public boolean getSalvageAnvilUseSoundsEnabled() {
+        return getBooleanValue("Skills.Salvage.Anvil_Use_Sounds", true);
+    }
+
+    public Material getSalvageAnvilMaterial() {
+        return Material.matchMaterial(getStringValue("Skills.Salvage.Anvil_Material", "GOLD_BLOCK"));
+    }
+
+    public boolean getSalvageConfirmRequired() {
+        return getBooleanValue("Skills.Salvage.Confirm_Required", true);
+    }
+
+    /* Unarmed */
+    public boolean getUnarmedBlockCrackerSmoothbrickToCracked() {
+        return getBooleanValue("Skills.Unarmed.Block_Cracker.SmoothBrick_To_CrackedBrick", true);
+    }
+
+    public boolean getUnarmedItemPickupDisabled() {
+        return getBooleanValue("Skills.Unarmed.Item_Pickup_Disabled_Full_Inventory", true);
+    }
+
+    public boolean getUnarmedItemsAsUnarmed() {
+        return getBooleanValue("Skills.Unarmed.Items_As_Unarmed", false);
+    }
+
+    public int getUnarmedGate() {
+        return getIntValue("Skills.Unarmed.Ability_Activation_Level_Gate", 10);
+    }
+
+    /* Swords */
+    public int getSwordsGate() {
+        return getIntValue("Skills.Swords.Ability_Activation_Level_Gate", 10);
+    }
+
+    /* Taming */
+    public Material getTamingCOTWMaterial(EntityType type) {
+        return Material.matchMaterial(getStringValue("Skills.Taming.Call_Of_The_Wild." + StringUtils.getPrettyEntityTypeString(type) + ".Item_Material"));
+    }
+
+    public int getTamingCOTWCost(EntityType type) {
+        return getIntValue("Skills.Taming.Call_Of_The_Wild." + StringUtils.getPrettyEntityTypeString(type) + ".Item_Amount");
+    }
+
+    public int getTamingCOTWAmount(EntityType type) {
+        return getIntValue("Skills.Taming.Call_Of_The_Wild." + StringUtils.getPrettyEntityTypeString(type) + ".Summon_Amount");
+    }
+
+    public int getTamingCOTWLength(EntityType type) {
+        return getIntValue("Skills.Taming.Call_Of_The_Wild." + StringUtils.getPrettyEntityTypeString(type) + ".Summon_Length");
+    }
+
+    public int getTamingCOTWMaxAmount(EntityType type) {
+        return getIntValue("Skills.Taming.Call_Of_The_Wild." + StringUtils.getPrettyEntityTypeString(type) + ".Summon_Max_Amount");
+    }
+
+    public double getTamingCOTWRange() {
+        return getDoubleValue("Skills.Taming.Call_Of_The_Wild.Range", 40.0D);
+    }
+
+    /* Woodcutting */
+    public boolean getWoodcuttingDoubleDropsEnabled(BlockData material) {
+        return getBooleanValue("Double_Drops.Woodcutting." + StringUtils.getFriendlyConfigBlockDataString(material));
+    }
+
+    public boolean getTreeFellerSoundsEnabled() {
+        return getBooleanValue("Skills.Woodcutting.Tree_Feller_Sounds", true);
+    }
+
+    public int getWoodcuttingGate() {
+        return getIntValue("Skills.Woodcutting.Ability_Activation_Level_Gate", 10);
+    }
+
+    /* AFK Leveling */
+    public boolean getAcrobaticsPreventAFK() {
+        return getBooleanValue("Skills.Acrobatics.Prevent_AFK_Leveling", true);
+    }
+
+    public int getAcrobaticsAFKMaxTries() {
+        return getIntValue("Skills.Acrobatics.Max_Tries_At_Same_Location", 3);
+    }
+
+    public boolean getHerbalismPreventAFK() {
+        return getBooleanValue("Skills.Herbalism.Prevent_AFK_Leveling", true);
+    }
+
+    /* Level Caps */
+    public int getPowerLevelCap() {
+        int cap = getIntValue("General.Power_Level_Cap", 0);
+        return (cap <= 0) ? Integer.MAX_VALUE : cap;
+    }
+
+    public int getLevelCap(PrimarySkillType skill) {
+        int cap = getIntValue("Skills." + StringUtils.getCapitalized(skill.toString()) + ".Level_Cap");
+        return (cap <= 0) ? Integer.MAX_VALUE : cap;
+    }
+
+
+    /*public int isSuperAbilityUnlocked(PrimarySkillType skill) {
+        return getIntValue("Skills." + StringUtils.getCapitalized(skill.toString()) + ".Ability_Activation_Level_Gate");
+    }*/
+
+    public boolean getTruncateSkills() {
+        return getBooleanValue("General.TruncateSkills", false);
+    }
+
+    /* PVP & PVE Settings */
+    public boolean getPVPEnabled(PrimarySkillType skill) {
+        return getBooleanValue("Skills." + StringUtils.getCapitalized(skill.toString()) + ".Enabled_For_PVP", true);
+    }
+
+    public boolean getPVEEnabled(PrimarySkillType skill) {
+        return getBooleanValue("Skills." + StringUtils.getCapitalized(skill.toString()) + ".Enabled_For_PVE", true);
+    }
+
+    //public float getMasterVolume() { return (float) getDoubleValue("Sounds.MasterVolume", 1.0); }
+}

+ 16 - 7
core/src/main/java/com/gmail/nossr50/core/config/RankConfig.java

@@ -7,12 +7,11 @@ import com.gmail.nossr50.core.skills.subskills.AbstractSubSkill;
 import java.util.ArrayList;
 import java.util.List;
 
-public class RankConfig extends ConfigurableLoader {
+public class RankConfig extends ConfigValidated {
     private static RankConfig instance;
 
     public RankConfig() {
         super(McmmoCore.getDataFolderPath().getAbsoluteFile(),"skillranks.yml");
-        validate();
         this.instance = this;
     }
 
@@ -24,12 +23,22 @@ public class RankConfig extends ConfigurableLoader {
     }
 
     @Override
-    protected void loadKeys() {
+    public void unload() {
+        instance = null;
+    }
 
+    /**
+     * The version of this config
+     *
+     * @return
+     */
+    @Override
+    public double getConfigVersion() {
+        return 1;
     }
 
     @Override
-    protected boolean validateKeys() {
+    public List<String> validateKeys() {
         List<String> reason = new ArrayList<String>();
 
         /*
@@ -37,7 +46,7 @@ public class RankConfig extends ConfigurableLoader {
          */
         checkKeys(reason);
 
-        return noErrorsInConfig(reason);
+        return reason;
     }
 
     /**
@@ -74,14 +83,14 @@ public class RankConfig extends ConfigurableLoader {
      * @return the level requirement for a subskill at this particular rank
      */
     private int findRankByRootAddress(int rank, String key) {
-        String scalingKey = Config.getInstance().getIsRetroMode() ? ".RetroMode." : ".Standard.";
+        String scalingKey = MainConfig.getInstance().getIsRetroMode() ? ".RetroMode." : ".Standard.";
 
         String targetRank = "Rank_" + rank;
 
         key += scalingKey;
         key += targetRank;
 
-        return config.getInt(key);
+        return getIntValue(key);
     }
 
     /**

+ 11 - 0
core/src/main/java/com/gmail/nossr50/core/config/RegistersKeys.java

@@ -0,0 +1,11 @@
+package com.gmail.nossr50.core.config;
+
+/**
+ * A class that registers keys
+ */
+public interface RegistersKeys {
+    /**
+     * Loads up keys
+     */
+    void loadKeys();
+}

+ 28 - 15
core/src/main/java/com/gmail/nossr50/core/config/SoundConfig.java

@@ -3,12 +3,14 @@ package com.gmail.nossr50.core.config;
 import com.gmail.nossr50.core.McmmoCore;
 import com.gmail.nossr50.core.util.sounds.SoundType;
 
-public class SoundConfig extends ConfigurableLoader {
+import java.util.ArrayList;
+import java.util.List;
+
+public class SoundConfig extends ConfigValidated {
     private static SoundConfig instance;
 
     public SoundConfig() {
         super(McmmoCore.getDataFolderPath().getAbsoluteFile(), "sounds.yml");
-        validate();
         this.instance = this;
     }
 
@@ -20,45 +22,56 @@ public class SoundConfig extends ConfigurableLoader {
     }
 
     @Override
-    protected void loadKeys() {
+    public void unload() {
+        instance = null;
+    }
 
+    /**
+     * The version of this config
+     *
+     * @return
+     */
+    @Override
+    public double getConfigVersion() {
+        return 1;
     }
 
     @Override
-    protected boolean validateKeys() {
+    public List<String> validateKeys() {
+        ArrayList<String> reasons = new ArrayList<>();
+
         for (SoundType soundType : SoundType.values()) {
-            if (config.getDouble("Sounds." + soundType.toString() + ".Volume") < 0) {
-                plugin.getLogger().info("[mcMMO] Sound volume cannot be below 0 for " + soundType.toString());
-                return false;
+            if (getDoubleValue("Sounds." + soundType.toString() + ".Volume") < 0) {
+                reasons.add("[mcMMO] Sound volume cannot be below 0 for " + soundType.toString());
             }
 
             //Sounds with custom pitching don't use pitch values
             if (!soundType.usesCustomPitch()) {
-                if (config.getDouble("Sounds." + soundType.toString() + ".Pitch") < 0) {
-                    plugin.getLogger().info("[mcMMO] Sound pitch cannot be below 0 for " + soundType.toString());
-                    return false;
+                if (getDoubleValue("Sounds." + soundType.toString() + ".Pitch") < 0) {
+                    reasons.add("[mcMMO] Sound pitch cannot be below 0 for " + soundType.toString());
                 }
             }
         }
-        return true;
+
+        return reasons;
     }
 
     public float getMasterVolume() {
-        return (float) config.getDouble("Sounds.MasterVolume", 1.0);
+        return (float) getDoubleValue("Sounds.MasterVolume", 1.0);
     }
 
     public float getVolume(SoundType soundType) {
         String key = "Sounds." + soundType.toString() + ".Volume";
-        return (float) config.getDouble(key);
+        return (float) getDoubleValue(key);
     }
 
     public float getPitch(SoundType soundType) {
         String key = "Sounds." + soundType.toString() + ".Pitch";
-        return (float) config.getDouble(key);
+        return (float) getDoubleValue(key);
     }
 
     public boolean getIsEnabled(SoundType soundType) {
         String key = "Sounds." + soundType.toString() + ".Enabled";
-        return config.getBoolean(key, true);
+        return getBooleanValue(key, true);
     }
 }

+ 8 - 0
core/src/main/java/com/gmail/nossr50/core/config/Unload.java

@@ -0,0 +1,8 @@
+package com.gmail.nossr50.core.config;
+
+/**
+ * Unloads values, sort of like a constructor
+ */
+public interface Unload {
+    void unload();
+}

+ 62 - 52
core/src/main/java/com/gmail/nossr50/core/config/experience/ExperienceConfig.java

@@ -1,7 +1,7 @@
 package com.gmail.nossr50.core.config.experience;
 
 import com.gmail.nossr50.core.McmmoCore;
-import com.gmail.nossr50.core.config.ConfigurableLoader;
+import com.gmail.nossr50.core.config.ConfigValidated;
 import com.gmail.nossr50.core.datatypes.experience.FormulaType;
 import com.gmail.nossr50.core.skills.MaterialType;
 import com.gmail.nossr50.core.skills.PotionStage;
@@ -11,12 +11,11 @@ import com.gmail.nossr50.core.util.StringUtils;
 import java.util.ArrayList;
 import java.util.List;
 
-public class ExperienceConfig extends ConfigurableLoader {
+public class ExperienceConfig extends ConfigValidated {
     private static ExperienceConfig instance;
 
     private ExperienceConfig() {
-        super(McmmoCore.getDataFolderPath().getAbsoluteFile(),"experience.yml");
-        validate();
+        super(McmmoCore.getDataFolderPath().getAbsoluteFile(), "experience.yml");
     }
 
     public static ExperienceConfig getInstance() {
@@ -27,12 +26,23 @@ public class ExperienceConfig extends ConfigurableLoader {
         return instance;
     }
 
+    /**
+     * The version of this config
+     *
+     * @return
+     */
+    @Override
+    public double getConfigVersion() {
+        return 1;
+    }
+
     @Override
-    protected void loadKeys() {
+    public void unload() {
+        instance = null; //TODO: this might be a bit problematic
     }
 
     @Override
-    protected boolean validateKeys() {
+    public List<String> validateKeys() {
         List<String> reason = new ArrayList<String>();
 
         /*
@@ -131,7 +141,7 @@ public class ExperienceConfig extends ConfigurableLoader {
             reason.add("Experience.Taming.Animal_Taming.Ocelot should be greater than 0!");
         }
 
-        return noErrorsInConfig(reason);
+        return reason;
     }
 
     /*
@@ -140,34 +150,34 @@ public class ExperienceConfig extends ConfigurableLoader {
 
     /* EXPLOIT TOGGLES */
     public boolean isEndermanEndermiteFarmingPrevented() {
-        return config.getBoolean("ExploitFix.EndermanEndermiteFarms", true);
+        return getBooleanValue("ExploitFix.EndermanEndermiteFarms", true);
     }
 
     /* Curve settings */
     public FormulaType getFormulaType() {
-        return FormulaType.getFormulaType(config.getString("Experience_Formula.Curve"));
+        return FormulaType.getFormulaType(getStringValue("Experience_Formula.Curve"));
     }
 
     public boolean getCumulativeCurveEnabled() {
-        return config.getBoolean("Experience_Formula.Cumulative_Curve", false);
+        return getBooleanValue("Experience_Formula.Cumulative_Curve", false);
     }
 
     /* Curve values */
     public double getMultiplier(FormulaType type) {
-        return config.getDouble("Experience_Formula." + StringUtils.getCapitalized(type.toString()) + "_Values.multiplier");
+        return getDoubleValue("Experience_Formula." + StringUtils.getCapitalized(type.toString()) + "_Values.multiplier");
     }
 
     public int getBase(FormulaType type) {
-        return config.getInt("Experience_Formula." + StringUtils.getCapitalized(type.toString()) + "_Values.base");
+        return getIntValue("Experience_Formula." + StringUtils.getCapitalized(type.toString()) + "_Values.base");
     }
 
     public double getExponent(FormulaType type) {
-        return config.getDouble("Experience_Formula." + StringUtils.getCapitalized(type.toString()) + "_Values.exponent");
+        return getDoubleValue("Experience_Formula." + StringUtils.getCapitalized(type.toString()) + "_Values.exponent");
     }
 
     /* Global modifier */
     public double getExperienceGainsGlobalMultiplier() {
-        return config.getDouble("Experience_Formula.Multiplier.Global", 1.0);
+        return getDoubleValue("Experience_Formula.Multiplier.Global", 1.0);
     }
 
     public void setExperienceGainsGlobalMultiplier(double value) {
@@ -176,48 +186,48 @@ public class ExperienceConfig extends ConfigurableLoader {
 
     /* PVP modifier */
     public double getPlayerVersusPlayerXP() {
-        return config.getDouble("Experience_Formula.Multiplier.PVP", 1.0);
+        return getDoubleValue("Experience_Formula.Multiplier.PVP", 1.0);
     }
 
     /* Spawned Mob modifier */
     public double getSpawnedMobXpMultiplier() {
-        return config.getDouble("Experience_Formula.Mobspawners.Multiplier", 0.0);
+        return getDoubleValue("Experience_Formula.Mobspawners.Multiplier", 0.0);
     }
 
     public double getBredMobXpMultiplier() {
-        return config.getDouble("Experience_Formula.Breeding.Multiplier", 1.0);
+        return getDoubleValue("Experience_Formula.Breeding.Multiplier", 1.0);
     }
 
     /* Skill modifiers */
     public double getFormulaSkillModifier(PrimarySkillType skill) {
-        return config.getDouble("Experience_Formula.Modifier." + StringUtils.getCapitalized(skill.toString()));
+        return getDoubleValue("Experience_Formula.Modifier." + StringUtils.getCapitalized(skill.toString()));
     }
 
     /* Custom XP perk */
     public double getCustomXpPerkBoost() {
-        return config.getDouble("Experience_Formula.Custom_XP_Perk.Boost", 1.25);
+        return getDoubleValue("Experience_Formula.Custom_XP_Perk.Boost", 1.25);
     }
 
     /* Diminished Returns */
     public float getDiminishedReturnsCap() {
-        return (float) config.getDouble("Dimished_Returns.Guaranteed_Minimum_Percentage", 0.05D);
+        return (float) getDoubleValue("Dimished_Returns.Guaranteed_Minimum_Percentage", 0.05D);
     }
 
     public boolean getDiminishedReturnsEnabled() {
-        return config.getBoolean("Diminished_Returns.Enabled", false);
+        return getBooleanValue("Diminished_Returns.Enabled", false);
     }
 
     public int getDiminishedReturnsThreshold(PrimarySkillType skill) {
-        return config.getInt("Diminished_Returns.Threshold." + StringUtils.getCapitalized(skill.toString()), 20000);
+        return getIntValue("Diminished_Returns.Threshold." + StringUtils.getCapitalized(skill.toString()), 20000);
     }
 
     public int getDiminishedReturnsTimeInterval() {
-        return config.getInt("Diminished_Returns.Time_Interval", 10);
+        return getIntValue("Diminished_Returns.Time_Interval", 10);
     }
 
     /* Conversion */
     public double getExpModifier() {
-        return config.getDouble("Conversion.Exp_Modifier", 1);
+        return getDoubleValue("Conversion.Exp_Modifier", 1);
     }
 
     /*
@@ -226,20 +236,20 @@ public class ExperienceConfig extends ConfigurableLoader {
 
     /* General Settings */
     public boolean getExperienceGainsPlayerVersusPlayerEnabled() {
-        return config.getBoolean("Experience.PVP.Rewards", true);
+        return getBooleanValue("Experience.PVP.Rewards", true);
     }
 
     /* Combat XP Multipliers */
     public double getCombatXP(EntityType entity) {
-        return config.getDouble("Experience.Combat.Multiplier." + StringUtils.getPrettyEntityTypeString(entity).replace(" ", "_"));
+        return getDoubleValue("Experience.Combat.Multiplier." + StringUtils.getPrettyEntityTypeString(entity).replace(" ", "_"));
     }
 
     public double getAnimalsXP(EntityType entity) {
-        return config.getDouble("Experience.Combat.Multiplier." + StringUtils.getPrettyEntityTypeString(entity).replace(" ", "_"), getAnimalsXP());
+        return getDoubleValue("Experience.Combat.Multiplier." + StringUtils.getPrettyEntityTypeString(entity).replace(" ", "_"), getAnimalsXP());
     }
 
     public double getAnimalsXP() {
-        return config.getDouble("Experience.Combat.Multiplier.Animals", 1.0);
+        return getDoubleValue("Experience.Combat.Multiplier.Animals", 1.0);
     }
 
     public boolean hasCombatXP(EntityType entity) {
@@ -251,13 +261,13 @@ public class ExperienceConfig extends ConfigurableLoader {
         String baseString = "Experience." + StringUtils.getCapitalized(skill.toString()) + ".";
         String explicitString = baseString + StringUtils.getExplicitConfigMaterialString(data);
         if (config.contains(explicitString))
-            return config.getInt(explicitString);
+            return getIntValue(explicitString);
         String friendlyString = baseString + StringUtils.getFriendlyConfigMaterialString(data);
         if (config.contains(friendlyString))
-            return config.getInt(friendlyString);
+            return getIntValue(friendlyString);
         String wildcardString = baseString + StringUtils.getWildcardConfigMaterialString(data);
         if (config.contains(wildcardString))
-            return config.getInt(wildcardString);
+            return getIntValue(wildcardString);
         return 0;
     }
 
@@ -266,13 +276,13 @@ public class ExperienceConfig extends ConfigurableLoader {
         String baseString = "Experience." + StringUtils.getCapitalized(skill.toString()) + ".";
         String explicitString = baseString + StringUtils.getExplicitConfigBlockDataString(data);
         if (config.contains(explicitString))
-            return config.getInt(explicitString);
+            return getIntValue(explicitString);
         String friendlyString = baseString + StringUtils.getFriendlyConfigBlockDataString(data);
         if (config.contains(friendlyString))
-            return config.getInt(friendlyString);
+            return getIntValue(friendlyString);
         String wildcardString = baseString + StringUtils.getWildcardConfigBlockDataString(data);
         if (config.contains(wildcardString))
-            return config.getInt(wildcardString);
+            return getIntValue(wildcardString);
         return 0;
     }
 
@@ -305,31 +315,31 @@ public class ExperienceConfig extends ConfigurableLoader {
      */
 
     public boolean isPartyExperienceBarsEnabled() {
-        return config.getBoolean("Experience_Bars.Update.Party", true);
+        return getBooleanValue("Experience_Bars.Update.Party", true);
     }
 
     public boolean isPassiveGainsExperienceBarsEnabled() {
-        return config.getBoolean("Experience_Bars.Update.Passive", true);
+        return getBooleanValue("Experience_Bars.Update.Passive", true);
     }
 
     public boolean getDoExperienceBarsAlwaysUpdateTitle() {
-        return config.getBoolean("Experience_Bars.ThisMayCauseLag.AlwaysUpdateTitlesWhenXPIsGained.Enable", false) || getAddExtraDetails();
+        return getBooleanValue("Experience_Bars.ThisMayCauseLag.AlwaysUpdateTitlesWhenXPIsGained.Enable", false) || getAddExtraDetails();
     }
 
     public boolean getAddExtraDetails() {
-        return config.getBoolean("Experience_Bars.ThisMayCauseLag.AlwaysUpdateTitlesWhenXPIsGained.ExtraDetails", false);
+        return getBooleanValue("Experience_Bars.ThisMayCauseLag.AlwaysUpdateTitlesWhenXPIsGained.ExtraDetails", false);
     }
 
     public boolean isExperienceBarsEnabled() {
-        return config.getBoolean("Experience_Bars.Enable", true);
+        return getBooleanValue("Experience_Bars.Enable", true);
     }
 
     public boolean isExperienceBarEnabled(PrimarySkillType primarySkillType) {
-        return config.getBoolean("Experience_Bars." + StringUtils.getCapitalized(primarySkillType.toString()) + ".Enable", true);
+        return getBooleanValue("Experience_Bars." + StringUtils.getCapitalized(primarySkillType.toString()) + ".Enable", true);
     }
 
     public BarColor getExperienceBarColor(PrimarySkillType primarySkillType) {
-        String colorValueFromConfig = config.getString("Experience_Bars." + StringUtils.getCapitalized(primarySkillType.toString()) + ".Color");
+        String colorValueFromConfig = getStringValue("Experience_Bars." + StringUtils.getCapitalized(primarySkillType.toString()) + ".Color");
 
         for (BarColor barColor : BarColor.values()) {
             if (barColor.toString().equalsIgnoreCase(colorValueFromConfig))
@@ -341,7 +351,7 @@ public class ExperienceConfig extends ConfigurableLoader {
     }
 
     public BarStyle getExperienceBarStyle(PrimarySkillType primarySkillType) {
-        String colorValueFromConfig = config.getString("Experience_Bars." + StringUtils.getCapitalized(primarySkillType.toString()) + ".BarStyle");
+        String colorValueFromConfig = getStringValue("Experience_Bars." + StringUtils.getCapitalized(primarySkillType.toString()) + ".BarStyle");
 
         for (BarStyle barStyle : BarStyle.values()) {
             if (barStyle.toString().equalsIgnoreCase(colorValueFromConfig))
@@ -354,46 +364,46 @@ public class ExperienceConfig extends ConfigurableLoader {
 
     /* Acrobatics */
     public int getDodgeXPModifier() {
-        return config.getInt("Experience.Acrobatics.Dodge", 120);
+        return getIntValue("Experience.Acrobatics.Dodge", 120);
     }
 
     public int getRollXPModifier() {
-        return config.getInt("Experience.Acrobatics.Roll", 80);
+        return getIntValue("Experience.Acrobatics.Roll", 80);
     }
 
     public int getFallXPModifier() {
-        return config.getInt("Experience.Acrobatics.Fall", 120);
+        return getIntValue("Experience.Acrobatics.Fall", 120);
     }
 
     public double getFeatherFallXPModifier() {
-        return config.getDouble("Experience.Acrobatics.FeatherFall_Multiplier", 2.0);
+        return getDoubleValue("Experience.Acrobatics.FeatherFall_Multiplier", 2.0);
     }
 
     /* Alchemy */
     public double getPotionXP(PotionStage stage) {
-        return config.getDouble("Experience.Alchemy.Potion_Stage_" + stage.toNumerical(), 10D);
+        return getDoubleValue("Experience.Alchemy.Potion_Stage_" + stage.toNumerical(), 10D);
     }
 
     /* Archery */
     public double getArcheryDistanceMultiplier() {
-        return config.getDouble("Experience.Archery.Distance_Multiplier", 0.025);
+        return getDoubleValue("Experience.Archery.Distance_Multiplier", 0.025);
     }
 
     public int getFishingShakeXP() {
-        return config.getInt("Experience.Fishing.Shake", 50);
+        return getIntValue("Experience.Fishing.Shake", 50);
     }
 
     /* Repair */
     public double getRepairXPBase() {
-        return config.getDouble("Experience.Repair.Base", 1000.0);
+        return getDoubleValue("Experience.Repair.Base", 1000.0);
     }
 
     public double getRepairXP(MaterialType repairMaterialType) {
-        return config.getDouble("Experience.Repair." + StringUtils.getCapitalized(repairMaterialType.toString()));
+        return getDoubleValue("Experience.Repair." + StringUtils.getCapitalized(repairMaterialType.toString()));
     }
 
     /* Taming */
     public int getTamingXP(EntityType type) {
-        return config.getInt("Experience.Taming.Animal_Taming." + StringUtils.getPrettyEntityTypeString(type));
+        return getIntValue("Experience.Taming.Animal_Taming." + StringUtils.getPrettyEntityTypeString(type));
     }
 }

+ 3 - 2
core/src/main/java/com/gmail/nossr50/core/config/mods/ArmorConfigManager.java

@@ -1,15 +1,16 @@
 package com.gmail.nossr50.core.config.mods;
 
+import com.gmail.nossr50.core.McmmoCore;
 import com.gmail.nossr50.core.util.ModManager;
 
 import java.io.File;
 import java.util.regex.Pattern;
 
 public class ArmorConfigManager {
-    public ArmorConfigManager(mcMMO plugin) {
+    public ArmorConfigManager() {
         Pattern middlePattern = Pattern.compile("armor\\.(?:.+)\\.yml");
         Pattern startPattern = Pattern.compile("(?:.+)\\.armor\\.yml");
-        File dataFolder = new File(mcMMO.getModDirectory());
+        File dataFolder = new File(McmmoCore.getModDataFolderPath());
         File vanilla = new File(dataFolder, "armor.default.yml");
         ModManager modManager = mcMMO.getModManager();
 

+ 5 - 5
core/src/main/java/com/gmail/nossr50/core/config/mods/BlockConfigManager.java

@@ -1,18 +1,18 @@
 package com.gmail.nossr50.core.config.mods;
 
-import com.gmail.nossr50.mcMMO;
-import com.gmail.nossr50.util.ModManager;
+import com.gmail.nossr50.core.McmmoCore;
+import com.gmail.nossr50.core.util.ModManager;
 
 import java.io.File;
 import java.util.regex.Pattern;
 
 public class BlockConfigManager {
-    public BlockConfigManager(mcMMO plugin) {
+    public BlockConfigManager() {
         Pattern middlePattern = Pattern.compile("blocks\\.(?:.+)\\.yml");
         Pattern startPattern = Pattern.compile("(?:.+)\\.blocks\\.yml");
-        File dataFolder = new File(mcMMO.getModDirectory());
+        File dataFolder = new File(McmmoCore.getModDataFolderPath());
         File vanilla = new File(dataFolder, "blocks.default.yml");
-        ModManager modManager = mcMMO.getModManager();
+        ModManager modManager = McmmoCore.getModManager();
 
         if (!vanilla.exists()) {
             plugin.saveResource(vanilla.getParentFile().getName() + File.separator + "blocks.default.yml", false);

+ 27 - 20
core/src/main/java/com/gmail/nossr50/core/config/mods/CustomArmorConfig.java

@@ -1,22 +1,19 @@
 package com.gmail.nossr50.core.config.mods;
 
 import com.gmail.nossr50.core.McmmoCore;
-import com.gmail.nossr50.core.config.ConfigLoader;
-import com.gmail.nossr50.core.config.ConfigurableLoader;
-import com.gmail.nossr50.core.mcmmo.skills.ItemType;
-import com.gmail.nossr50.core.mcmmo.skills.MaterialType;
-import com.gmail.nossr50.skills.repair.repairables.Repairable;
-import com.gmail.nossr50.skills.repair.repairables.RepairableFactory;
-import com.gmail.nossr50.util.skills.SkillUtils;
-import org.bukkit.Material;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.inventory.ItemStack;
+import com.gmail.nossr50.core.config.ConfigKeyRegister;
+import com.gmail.nossr50.core.mcmmo.item.ItemStack;
+import com.gmail.nossr50.core.skills.ItemType;
+import com.gmail.nossr50.core.skills.MaterialType;
+import com.gmail.nossr50.core.skills.primary.repair.repairables.Repairable;
+import com.gmail.nossr50.core.skills.primary.repair.repairables.RepairableFactory;
+import com.gmail.nossr50.core.util.skills.SkillUtils;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 
-public class CustomArmorConfig extends ConfigurableLoader {
+public class CustomArmorConfig extends ConfigKeyRegister {
     public List<Material> customBoots = new ArrayList<Material>();
     public List<Material> customChestplates = new ArrayList<Material>();
     public List<Material> customHelmets = new ArrayList<Material>();
@@ -29,8 +26,18 @@ public class CustomArmorConfig extends ConfigurableLoader {
         loadKeys();
     }
 
+    /**
+     * The version of this config
+     *
+     * @return
+     */
     @Override
-    protected void loadKeys() {
+    public double getConfigVersion() {
+        return 1;
+    }
+
+    @Override
+    public void loadKeys() {
         loadArmor("Boots", customBoots);
         loadArmor("Chestplates", customChestplates);
         loadArmor("Helmets", customHelmets);
@@ -68,8 +75,8 @@ public class CustomArmorConfig extends ConfigurableLoader {
                 continue;
             }
 
-            boolean repairable = config.getBoolean(armorType + "." + armorName + ".Repairable");
-            Material repairMaterial = Material.matchMaterial(config.getString(armorType + "." + armorName + ".Repair_Material", ""));
+            boolean repairable = getBooleanValue(armorType + "." + armorName + ".Repairable");
+            Material repairMaterial = Material.matchMaterial(getStringValue(armorType + "." + armorName + ".Repair_Material", ""));
 
             if (repairable && (repairMaterial == null)) {
                 plugin.getLogger().warning("Incomplete repair information. This item will be unrepairable. - " + armorName);
@@ -77,21 +84,21 @@ public class CustomArmorConfig extends ConfigurableLoader {
             }
 
             if (repairable) {
-                byte repairData = (byte) config.getInt(armorType + "." + armorName + ".Repair_Material_Data_Value", -1);
+                byte repairData = (byte) getIntValue(armorType + "." + armorName + ".Repair_Material_Data_Value", -1);
                 int repairQuantity = SkillUtils.getRepairAndSalvageQuantities(new ItemStack(armorMaterial), repairMaterial, repairData);
 
                 if (repairQuantity == 0) {
-                    repairQuantity = config.getInt(armorType + "." + armorName + ".Repair_Material_Quantity", 2);
+                    repairQuantity = getIntValue(armorType + "." + armorName + ".Repair_Material_Quantity", 2);
                 }
 
-                String repairItemName = config.getString(armorType + "." + armorName + ".Repair_Material_Pretty_Name");
-                int repairMinimumLevel = config.getInt(armorType + "." + armorName + ".Repair_MinimumLevel", 0);
-                double repairXpMultiplier = config.getDouble(armorType + "." + armorName + ".Repair_XpMultiplier", 1);
+                String repairItemName = getStringValue(armorType + "." + armorName + ".Repair_Material_Pretty_Name");
+                int repairMinimumLevel = getIntValue(armorType + "." + armorName + ".Repair_MinimumLevel", 0);
+                double repairXpMultiplier = getDoubleValue(armorType + "." + armorName + ".Repair_XpMultiplier", 1);
 
                 short durability = armorMaterial.getMaxDurability();
 
                 if (durability == 0) {
-                    durability = (short) config.getInt(armorType + "." + armorName + ".Durability", 70);
+                    durability = (short) getIntValue(armorType + "." + armorName + ".Durability", 70);
                 }
 
                 repairables.add(RepairableFactory.getRepairable(armorMaterial, repairMaterial, repairData, repairItemName, repairMinimumLevel, repairQuantity, durability, ItemType.ARMOR, MaterialType.OTHER, repairXpMultiplier));

+ 7 - 7
core/src/main/java/com/gmail/nossr50/core/config/mods/CustomBlockConfig.java

@@ -2,7 +2,7 @@ package com.gmail.nossr50.core.config.mods;
 
 import com.gmail.nossr50.core.McmmoCore;
 import com.gmail.nossr50.core.config.ConfigLoader;
-import com.gmail.nossr50.core.config.ConfigurableLoader;
+import com.gmail.nossr50.core.config.ConfigKeyRegister;
 import com.gmail.nossr50.core.mcmmo.mods.CustomBlock;
 import org.bukkit.Material;
 import org.bukkit.configuration.ConfigurationSection;
@@ -12,7 +12,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Set;
 
-public class CustomBlockConfig extends ConfigurableLoader {
+public class CustomBlockConfig extends ConfigKeyRegister {
     public List<Material> customExcavationBlocks = new ArrayList<>();
     public List<Material> customHerbalismBlocks = new ArrayList<>();
     public List<Material> customMiningBlocks = new ArrayList<>();
@@ -78,14 +78,14 @@ public class CustomBlockConfig extends ConfigurableLoader {
                 continue;
             }
 
-            int xp = config.getInt(skillType + "." + blockName + ".XP_Gain");
+            int xp = getIntValue(skillType + "." + blockName + ".XP_Gain");
             int smeltingXp = 0;
 
-            if (skillType.equals("Mining") && config.getBoolean(skillType + "." + blockName + ".Is_Ore")) {
+            if (skillType.equals("Mining") && getBooleanValue(skillType + "." + blockName + ".Is_Ore")) {
                 customOres.add(blockMaterial);
-                smeltingXp = config.getInt(skillType + "." + blockName + ".Smelting_XP_Gain", xp / 10);
+                smeltingXp = getIntValue(skillType + "." + blockName + ".Smelting_XP_Gain", xp / 10);
             } else if (skillType.equals("Woodcutting")) {
-                if (config.getBoolean(skillType + "." + blockName + ".Is_Log")) {
+                if (getBooleanValue(skillType + "." + blockName + ".Is_Log")) {
                     customLogs.add(blockMaterial);
                 } else {
                     customLeaves.add(blockMaterial);
@@ -93,7 +93,7 @@ public class CustomBlockConfig extends ConfigurableLoader {
                 }
             }
 
-            customBlockMap.put(blockMaterial, new CustomBlock(xp, config.getBoolean(skillType + "." + blockName + ".Double_Drops_Enabled"), smeltingXp));
+            customBlockMap.put(blockMaterial, new CustomBlock(xp, getBooleanValue(skillType + "." + blockName + ".Double_Drops_Enabled"), smeltingXp));
         }
     }
 }

+ 10 - 10
core/src/main/java/com/gmail/nossr50/core/config/mods/CustomEntityConfig.java

@@ -2,7 +2,7 @@ package com.gmail.nossr50.core.config.mods;
 
 import com.gmail.nossr50.core.McmmoCore;
 import com.gmail.nossr50.core.config.ConfigLoader;
-import com.gmail.nossr50.core.config.ConfigurableLoader;
+import com.gmail.nossr50.core.config.Config;
 import com.gmail.nossr50.core.mcmmo.mods.CustomEntity;
 import org.apache.commons.lang.ClassUtils;
 import org.bukkit.Material;
@@ -10,7 +10,7 @@ import org.bukkit.inventory.ItemStack;
 
 import java.util.HashMap;
 
-public class CustomEntityConfig extends ConfigurableLoader {
+public class CustomEntityConfig extends Config {
     public HashMap<String, CustomEntity> customEntityClassMap = new HashMap<String, CustomEntity>();
     public HashMap<String, CustomEntity> customEntityTypeMap = new HashMap<String, CustomEntity>();
 
@@ -28,7 +28,7 @@ public class CustomEntityConfig extends ConfigurableLoader {
 
         for (String entityName : config.getKeys(false)) {
             Class<?> clazz = null;
-            String className = config.getString(entityName + ".Class", "");
+            String className = getStringValue(entityName + ".Class", "");
 
             try {
                 clazz = ClassUtils.getClass(className);
@@ -38,15 +38,15 @@ public class CustomEntityConfig extends ConfigurableLoader {
             }
 
             String entityTypeName = entityName.replace("_", ".");
-            double xpMultiplier = config.getDouble(entityName + ".XP_Multiplier", 1.0D);
+            double xpMultiplier = getDoubleValue(entityName + ".XP_Multiplier", 1.0D);
 
-            boolean canBeTamed = config.getBoolean(entityName + ".Tameable");
-            int tamingXp = config.getInt(entityName + ".Taming_XP");
+            boolean canBeTamed = getBooleanValue(entityName + ".Tameable");
+            int tamingXp = getIntValue(entityName + ".Taming_XP");
 
-            boolean canBeSummoned = config.getBoolean(entityName + ".CanBeSummoned");
-            Material callOfTheWildMaterial = Material.matchMaterial(config.getString(entityName + ".COTW_Material", ""));
-            byte callOfTheWildData = (byte) config.getInt(entityName + ".COTW_Material_Data");
-            int callOfTheWildAmount = config.getInt(entityName + ".COTW_Material_Amount");
+            boolean canBeSummoned = getBooleanValue(entityName + ".CanBeSummoned");
+            Material callOfTheWildMaterial = Material.matchMaterial(getStringValue(entityName + ".COTW_Material", ""));
+            byte callOfTheWildData = (byte) getIntValue(entityName + ".COTW_Material_Data");
+            int callOfTheWildAmount = getIntValue(entityName + ".COTW_Material_Amount");
 
             if (canBeSummoned && (callOfTheWildMaterial == null || callOfTheWildAmount == 0)) {
                 plugin.getLogger().warning("Incomplete Call of the Wild information. This entity will not be able to be summoned by Call of the Wild.");

+ 13 - 13
core/src/main/java/com/gmail/nossr50/core/config/mods/CustomToolConfig.java

@@ -2,7 +2,7 @@ package com.gmail.nossr50.core.config.mods;
 
 import com.gmail.nossr50.core.McmmoCore;
 import com.gmail.nossr50.core.config.ConfigLoader;
-import com.gmail.nossr50.core.config.ConfigurableLoader;
+import com.gmail.nossr50.core.config.Config;
 import com.gmail.nossr50.core.mcmmo.mods.CustomTool;
 import com.gmail.nossr50.core.mcmmo.skills.ItemType;
 import com.gmail.nossr50.core.mcmmo.skills.MaterialType;
@@ -18,7 +18,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Set;
 
-public class CustomToolConfig extends ConfigurableLoader {
+public class CustomToolConfig extends Config {
     public List<Material> customAxes = new ArrayList<Material>();
     public List<Material> customBows = new ArrayList<Material>();
     public List<Material> customHoes = new ArrayList<Material>();
@@ -75,8 +75,8 @@ public class CustomToolConfig extends ConfigurableLoader {
                 continue;
             }
 
-            boolean repairable = config.getBoolean(toolType + "." + toolName + ".Repairable");
-            Material repairMaterial = Material.matchMaterial(config.getString(toolType + "." + toolName + ".Repair_Material", ""));
+            boolean repairable = getBooleanValue(toolType + "." + toolName + ".Repairable");
+            Material repairMaterial = Material.matchMaterial(getStringValue(toolType + "." + toolName + ".Repair_Material", ""));
 
             if (repairable && (repairMaterial == null)) {
                 plugin.getLogger().warning("Incomplete repair information. This item will be unrepairable. - " + toolName);
@@ -84,29 +84,29 @@ public class CustomToolConfig extends ConfigurableLoader {
             }
 
             if (repairable) {
-                byte repairData = (byte) config.getInt(toolType + "." + toolName + ".Repair_Material_Data_Value", -1);
+                byte repairData = (byte) getIntValue(toolType + "." + toolName + ".Repair_Material_Data_Value", -1);
                 int repairQuantity = SkillUtils.getRepairAndSalvageQuantities(new ItemStack(toolMaterial), repairMaterial, repairData);
 
                 if (repairQuantity == 0) {
-                    repairQuantity = config.getInt(toolType + "." + toolName + ".Repair_Material_Quantity", 2);
+                    repairQuantity = getIntValue(toolType + "." + toolName + ".Repair_Material_Quantity", 2);
                 }
 
-                String repairItemName = config.getString(toolType + "." + toolName + ".Repair_Material_Pretty_Name");
-                int repairMinimumLevel = config.getInt(toolType + "." + toolName + ".Repair_MinimumLevel", 0);
-                double repairXpMultiplier = config.getDouble(toolType + "." + toolName + ".Repair_XpMultiplier", 1);
+                String repairItemName = getStringValue(toolType + "." + toolName + ".Repair_Material_Pretty_Name");
+                int repairMinimumLevel = getIntValue(toolType + "." + toolName + ".Repair_MinimumLevel", 0);
+                double repairXpMultiplier = getDoubleValue(toolType + "." + toolName + ".Repair_XpMultiplier", 1);
 
                 short durability = toolMaterial.getMaxDurability();
 
                 if (durability == 0) {
-                    durability = (short) config.getInt(toolType + "." + toolName + ".Durability", 60);
+                    durability = (short) getIntValue(toolType + "." + toolName + ".Durability", 60);
                 }
 
                 repairables.add(RepairableFactory.getRepairable(toolMaterial, repairMaterial, repairData, repairItemName, repairMinimumLevel, repairQuantity, durability, ItemType.TOOL, MaterialType.OTHER, repairXpMultiplier));
             }
 
-            double multiplier = config.getDouble(toolType + "." + toolName + ".XP_Modifier", 1.0);
-            boolean abilityEnabled = config.getBoolean(toolType + "." + toolName + ".Ability_Enabled", true);
-            int tier = config.getInt(toolType + "." + toolName + ".Tier", 1);
+            double multiplier = getDoubleValue(toolType + "." + toolName + ".XP_Modifier", 1.0);
+            boolean abilityEnabled = getBooleanValue(toolType + "." + toolName + ".Ability_Enabled", true);
+            int tier = getIntValue(toolType + "." + toolName + ".Tier", 1);
 
             CustomTool tool = new CustomTool(tier, abilityEnabled, multiplier);
 

+ 5 - 9
core/src/main/java/com/gmail/nossr50/core/config/party/ItemWeightConfig.java

@@ -1,14 +1,10 @@
 package com.gmail.nossr50.core.config.party;
 
 import com.gmail.nossr50.core.McmmoCore;
-import com.gmail.nossr50.core.config.ConfigLoader;
-import com.gmail.nossr50.core.config.ConfigurableLoader;
-import com.gmail.nossr50.util.StringUtils;
-import org.bukkit.Material;
+import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.util.StringUtils;
 
-import java.util.HashSet;
-
-public class ItemWeightConfig extends ConfigurableLoader {
+public class ItemWeightConfig extends Config {
     private static ItemWeightConfig instance;
 
     private ItemWeightConfig() {
@@ -24,13 +20,13 @@ public class ItemWeightConfig extends ConfigurableLoader {
     }
 
     public int getItemWeight(Material material) {
-        return config.getInt("Item_Weights." + StringUtils.getPrettyItemString(material).replace(" ", "_"), config.getInt("Item_Weights.Default"));
+        return getIntValue("Item_Weights." + StringUtils.getPrettyItemString(material).replace(" ", "_"), getIntValue("Item_Weights.Default"));
     }
 
     public HashSet<Material> getMiscItems() {
         HashSet<Material> miscItems = new HashSet<Material>();
 
-        for (String item : config.getStringList("Party_Shareables.Misc_Items")) {
+        for (String item : getStringValueList("Party_Shareables.Misc_Items")) {
             Material material = Material.getMaterial(item.toUpperCase());
 
             if (material != null) {

+ 2 - 2
core/src/main/java/com/gmail/nossr50/core/config/skills/alchemy/PotionConfig.java

@@ -1,7 +1,7 @@
 package com.gmail.nossr50.core.config.skills.alchemy;
 
 import com.gmail.nossr50.core.McmmoCore;
-import com.gmail.nossr50.core.config.ConfigurableLoader;
+import com.gmail.nossr50.core.config.Config;
 import com.gmail.nossr50.core.mcmmo.colors.ChatColor;
 import com.gmail.nossr50.core.mcmmo.item.ItemStack;
 import com.gmail.nossr50.core.skills.primary.alchemy.AlchemyPotion;
@@ -12,7 +12,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-public class PotionConfig extends ConfigurableLoader {
+public class PotionConfig extends Config {
     private static PotionConfig instance;
 
     private List<ItemStack> concoctionsIngredientsTierOne = new ArrayList<ItemStack>();

+ 21 - 24
core/src/main/java/com/gmail/nossr50/core/config/skills/repair/RepairConfig.java

@@ -1,22 +1,19 @@
-package com.gmail.nossr50.config.skills.repair;
-
-import com.gmail.nossr50.config.ConfigLoader;
-import com.gmail.nossr50.core.config.ConfigurableLoader;
-import com.gmail.nossr50.core.mcmmo.skills.ItemType;
-import com.gmail.nossr50.core.mcmmo.skills.MaterialType;
-import com.gmail.nossr50.skills.repair.repairables.Repairable;
-import com.gmail.nossr50.skills.repair.repairables.RepairableFactory;
-import com.gmail.nossr50.util.ItemUtils;
-import com.gmail.nossr50.util.skills.SkillUtils;
-import org.bukkit.Material;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.inventory.ItemStack;
+package com.gmail.nossr50.core.config.skills.repair;
+
+import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.mcmmo.item.ItemStack;
+import com.gmail.nossr50.core.skills.ItemType;
+import com.gmail.nossr50.core.skills.MaterialType;
+import com.gmail.nossr50.core.skills.primary.repair.repairables.Repairable;
+import com.gmail.nossr50.core.skills.primary.repair.repairables.RepairableFactory;
+import com.gmail.nossr50.core.util.ItemUtils;
+import com.gmail.nossr50.core.util.skills.SkillUtils;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 
-public class RepairConfig extends ConfigurableLoader {
+public class RepairConfig extends Config {
     private List<Repairable> repairables;
 
     public RepairConfig(String fileName) {
@@ -49,7 +46,7 @@ public class RepairConfig extends ConfigurableLoader {
 
             // Repair Material Type
             MaterialType repairMaterialType = MaterialType.OTHER;
-            String repairMaterialTypeString = config.getString("Repairables." + key + ".MaterialType", "OTHER");
+            String repairMaterialTypeString = getStringValue("Repairables." + key + ".MaterialType", "OTHER");
 
             if (!config.contains("Repairables." + key + ".MaterialType") && itemMaterial != null) {
                 ItemStack repairItem = new ItemStack(itemMaterial);
@@ -78,7 +75,7 @@ public class RepairConfig extends ConfigurableLoader {
             }
 
             // Repair Material
-            String repairMaterialName = config.getString("Repairables." + key + ".RepairMaterial");
+            String repairMaterialName = getStringValue("Repairables." + key + ".RepairMaterial");
             Material repairMaterial = (repairMaterialName == null ? repairMaterialType.getDefaultMaterial() : Material.matchMaterial(repairMaterialName));
 
             if (repairMaterial == null) {
@@ -86,10 +83,10 @@ public class RepairConfig extends ConfigurableLoader {
             }
 
             // Maximum Durability
-            short maximumDurability = (itemMaterial != null ? itemMaterial.getMaxDurability() : (short) config.getInt("Repairables." + key + ".MaximumDurability"));
+            short maximumDurability = (itemMaterial != null ? itemMaterial.getMaxDurability() : (short) getIntValue("Repairables." + key + ".MaximumDurability"));
 
             if (maximumDurability <= 0) {
-                maximumDurability = (short) config.getInt("Repairables." + key + ".MaximumDurability");
+                maximumDurability = (short) getIntValue("Repairables." + key + ".MaximumDurability");
             }
 
             if (maximumDurability <= 0) {
@@ -98,7 +95,7 @@ public class RepairConfig extends ConfigurableLoader {
 
             // ItemStack Type
             ItemType repairItemType = ItemType.OTHER;
-            String repairItemTypeString = config.getString("Repairables." + key + ".ItemType", "OTHER");
+            String repairItemTypeString = getStringValue("Repairables." + key + ".ItemType", "OTHER");
 
             if (!config.contains("Repairables." + key + ".ItemType") && itemMaterial != null) {
                 ItemStack repairItem = new ItemStack(itemMaterial);
@@ -116,19 +113,19 @@ public class RepairConfig extends ConfigurableLoader {
                 }
             }
 
-            byte repairMetadata = (byte) config.getInt("Repairables." + key + ".RepairMaterialMetadata", -1);
-            int minimumLevel = config.getInt("Repairables." + key + ".MinimumLevel");
-            double xpMultiplier = config.getDouble("Repairables." + key + ".XpMultiplier", 1);
+            byte repairMetadata = (byte) getIntValue("Repairables." + key + ".RepairMaterialMetadata", -1);
+            int minimumLevel = getIntValue("Repairables." + key + ".MinimumLevel");
+            double xpMultiplier = getDoubleValue("Repairables." + key + ".XpMultiplier", 1);
 
             if (minimumLevel < 0) {
                 reason.add(key + " has an invalid MinimumLevel of " + minimumLevel);
             }
 
             // Minimum Quantity
-            int minimumQuantity = (itemMaterial != null ? SkillUtils.getRepairAndSalvageQuantities(new ItemStack(itemMaterial), repairMaterial, repairMetadata) : config.getInt("Repairables." + key + ".MinimumQuantity", 2));
+            int minimumQuantity = (itemMaterial != null ? SkillUtils.getRepairAndSalvageQuantities(new ItemStack(itemMaterial), repairMaterial, repairMetadata) : getIntValue("Repairables." + key + ".MinimumQuantity", 2));
 
             if (minimumQuantity <= 0 && itemMaterial != null) {
-                minimumQuantity = config.getInt("Repairables." + key + ".MinimumQuantity", 2);
+                minimumQuantity = getIntValue("Repairables." + key + ".MinimumQuantity", 2);
             }
 
             if (minimumQuantity <= 0) {

+ 12 - 12
core/src/main/java/com/gmail/nossr50/core/config/skills/salvage/SalvageConfig.java

@@ -2,7 +2,7 @@ package com.gmail.nossr50.config.skills.salvage;
 
 import com.gmail.nossr50.config.ConfigLoader;
 import com.gmail.nossr50.core.McmmoCore;
-import com.gmail.nossr50.core.config.ConfigurableLoader;
+import com.gmail.nossr50.core.config.Config;
 import com.gmail.nossr50.core.mcmmo.skills.ItemType;
 import com.gmail.nossr50.core.mcmmo.skills.MaterialType;
 import com.gmail.nossr50.skills.salvage.salvageables.Salvageable;
@@ -17,7 +17,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 
-public class SalvageConfig extends ConfigurableLoader {
+public class SalvageConfig extends Config {
     private List<Salvageable> salvageables;
 
     public SalvageConfig(String fileName) {
@@ -45,7 +45,7 @@ public class SalvageConfig extends ConfigurableLoader {
 
             // Salvage Material Type
             MaterialType salvageMaterialType = MaterialType.OTHER;
-            String salvageMaterialTypeString = config.getString("Salvageables." + key + ".MaterialType", "OTHER");
+            String salvageMaterialTypeString = getStringValue("Salvageables." + key + ".MaterialType", "OTHER");
 
             if (!config.contains("Salvageables." + key + ".MaterialType") && itemMaterial != null) {
                 ItemStack salvageItem = new ItemStack(itemMaterial);
@@ -74,7 +74,7 @@ public class SalvageConfig extends ConfigurableLoader {
             }
 
             // Salvage Material
-            String salvageMaterialName = config.getString("Salvageables." + key + ".SalvageMaterial");
+            String salvageMaterialName = getStringValue("Salvageables." + key + ".SalvageMaterial");
             Material salvageMaterial = (salvageMaterialName == null ? salvageMaterialType.getDefaultMaterial() : Material.matchMaterial(salvageMaterialName));
 
             if (salvageMaterial == null) {
@@ -82,11 +82,11 @@ public class SalvageConfig extends ConfigurableLoader {
             }
 
             // Maximum Durability
-            short maximumDurability = (itemMaterial != null ? itemMaterial.getMaxDurability() : (short) config.getInt("Salvageables." + key + ".MaximumDurability"));
+            short maximumDurability = (itemMaterial != null ? itemMaterial.getMaxDurability() : (short) getIntValue("Salvageables." + key + ".MaximumDurability"));
 
             // ItemStack Type
             ItemType salvageItemType = ItemType.OTHER;
-            String salvageItemTypeString = config.getString("Salvageables." + key + ".ItemType", "OTHER");
+            String salvageItemTypeString = getStringValue("Salvageables." + key + ".ItemType", "OTHER");
 
             if (!config.contains("Salvageables." + key + ".ItemType") && itemMaterial != null) {
                 ItemStack salvageItem = new ItemStack(itemMaterial);
@@ -104,22 +104,22 @@ public class SalvageConfig extends ConfigurableLoader {
                 }
             }
 
-            byte salvageMetadata = (byte) config.getInt("Salvageables." + key + ".SalvageMaterialMetadata", -1);
-            int minimumLevel = config.getInt("Salvageables." + key + ".MinimumLevel");
-            double xpMultiplier = config.getDouble("Salvageables." + key + ".XpMultiplier", 1);
+            byte salvageMetadata = (byte) getIntValue("Salvageables." + key + ".SalvageMaterialMetadata", -1);
+            int minimumLevel = getIntValue("Salvageables." + key + ".MinimumLevel");
+            double xpMultiplier = getDoubleValue("Salvageables." + key + ".XpMultiplier", 1);
 
             if (minimumLevel < 0) {
                 reason.add(key + " has an invalid MinimumLevel of " + minimumLevel);
             }
 
             // Maximum Quantity
-            int maximumQuantity = (itemMaterial != null ? SkillUtils.getRepairAndSalvageQuantities(new ItemStack(itemMaterial), salvageMaterial, salvageMetadata) : config.getInt("Salvageables." + key + ".MaximumQuantity", 2));
+            int maximumQuantity = (itemMaterial != null ? SkillUtils.getRepairAndSalvageQuantities(new ItemStack(itemMaterial), salvageMaterial, salvageMetadata) : getIntValue("Salvageables." + key + ".MaximumQuantity", 2));
 
             if (maximumQuantity <= 0 && itemMaterial != null) {
-                maximumQuantity = config.getInt("Salvageables." + key + ".MaximumQuantity", 1);
+                maximumQuantity = getIntValue("Salvageables." + key + ".MaximumQuantity", 1);
             }
 
-            int configMaximumQuantity = config.getInt("Salvageables." + key + ".MaximumQuantity", -1);
+            int configMaximumQuantity = getIntValue("Salvageables." + key + ".MaximumQuantity", -1);
 
             if (configMaximumQuantity > 0) {
                 maximumQuantity = configMaximumQuantity;

+ 26 - 26
core/src/main/java/com/gmail/nossr50/core/config/treasure/TreasureConfig.java

@@ -1,7 +1,7 @@
 package com.gmail.nossr50.core.config.treasure;
 
 import com.gmail.nossr50.core.McmmoCore;
-import com.gmail.nossr50.core.config.ConfigurableLoader;
+import com.gmail.nossr50.core.config.Config;
 import com.gmail.nossr50.core.mcmmo.colors.ChatColor;
 import com.gmail.nossr50.core.mcmmo.item.ItemStack;
 import com.gmail.nossr50.core.skills.treasure.*;
@@ -12,7 +12,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 
-public class TreasureConfig extends ConfigurableLoader {
+public class TreasureConfig extends Config {
 
     private static TreasureConfig instance;
 
@@ -47,8 +47,8 @@ public class TreasureConfig extends ConfigurableLoader {
             double totalItemDropRate = 0;
 
             for (Rarity rarity : Rarity.values()) {
-                double enchantDropRate = config.getDouble("Enchantment_Drop_Rates." + tier + "." + rarity.toString());
-                double itemDropRate = config.getDouble("Item_Drop_Rates." + tier + "." + rarity.toString());
+                double enchantDropRate = getDoubleValue("Enchantment_Drop_Rates." + tier + "." + rarity.toString());
+                double itemDropRate = getDoubleValue("Item_Drop_Rates." + tier + "." + rarity.toString());
 
                 if ((enchantDropRate < 0.0 || enchantDropRate > 100.0) && rarity != Rarity.RECORD) {
                     reason.add("The enchant drop rate for " + tier + " items that are " + rarity.toString() + "should be between 0.0 and 100.0!");
@@ -134,8 +134,8 @@ public class TreasureConfig extends ConfigurableLoader {
                 material = Material.matchMaterial(materialName);
             }
 
-            int amount = config.getInt(type + "." + treasureName + ".Amount");
-            short data = (treasureInfo.length == 2) ? Short.parseShort(treasureInfo[1]) : (short) config.getInt(type + "." + treasureName + ".Data");
+            int amount = getIntValue(type + "." + treasureName + ".Amount");
+            short data = (treasureInfo.length == 2) ? Short.parseShort(treasureInfo[1]) : (short) getIntValue(type + "." + treasureName + ".Data");
 
             if (material == null) {
                 reason.add("Invalid material: " + materialName);
@@ -153,9 +153,9 @@ public class TreasureConfig extends ConfigurableLoader {
              * XP, Drop Chance, and Drop Level
              */
 
-            int xp = config.getInt(type + "." + treasureName + ".XP");
-            double dropChance = config.getDouble(type + "." + treasureName + ".Drop_Chance");
-            int dropLevel = config.getInt(type + "." + treasureName + ".Drop_Level");
+            int xp = getIntValue(type + "." + treasureName + ".XP");
+            double dropChance = getDoubleValue(type + "." + treasureName + ".Drop_Chance");
+            int dropLevel = getIntValue(type + "." + treasureName + ".Drop_Level");
 
             if (xp < 0) {
                 reason.add(treasureName + " has an invalid XP value: " + xp);
@@ -175,7 +175,7 @@ public class TreasureConfig extends ConfigurableLoader {
             Rarity rarity = null;
 
             if (isFishing) {
-                rarity = Rarity.getRarity(config.getString(type + "." + treasureName + ".Rarity"));
+                rarity = Rarity.getRarity(getStringValue(type + "." + treasureName + ".Rarity"));
 
                 if (rarity == null) {
                     reason.add("Invalid Rarity for item: " + treasureName);
@@ -197,21 +197,21 @@ public class TreasureConfig extends ConfigurableLoader {
 
                     PotionType potionType = null;
                     try {
-                        potionType = PotionType.valueOf(config.getString(type + "." + treasureName + ".PotionData.PotionType", "WATER"));
+                        potionType = PotionType.valueOf(getStringValue(type + "." + treasureName + ".PotionData.PotionType", "WATER"));
                     } catch (IllegalArgumentException ex) {
-                        reason.add("Invalid Potion_Type: " + config.getString(type + "." + treasureName + ".PotionData.PotionType", "WATER"));
+                        reason.add("Invalid Potion_Type: " + getStringValue(type + "." + treasureName + ".PotionData.PotionType", "WATER"));
                     }
-                    boolean extended = config.getBoolean(type + "." + treasureName + ".PotionData.Extended", false);
-                    boolean upgraded = config.getBoolean(type + "." + treasureName + ".PotionData.Upgraded", false);
+                    boolean extended = getBooleanValue(type + "." + treasureName + ".PotionData.Extended", false);
+                    boolean upgraded = getBooleanValue(type + "." + treasureName + ".PotionData.Upgraded", false);
                     itemMeta.setBasePotionData(new PotionData(potionType, extended, upgraded));
 
                     if (config.contains(type + "." + treasureName + ".Custom_Name")) {
-                        itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', config.getString(type + "." + treasureName + ".Custom_Name")));
+                        itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', getStringValue(type + "." + treasureName + ".Custom_Name")));
                     }
 
                     if (config.contains(type + "." + treasureName + ".Lore")) {
                         List<String> lore = new ArrayList<String>();
-                        for (String s : config.getStringList(type + "." + treasureName + ".Lore")) {
+                        for (String s : getStringValueList(type + "." + treasureName + ".Lore")) {
                             lore.add(ChatColor.translateAlternateColorCodes('&', s));
                         }
                         itemMeta.setLore(lore);
@@ -223,14 +223,14 @@ public class TreasureConfig extends ConfigurableLoader {
 
                 if (config.contains(type + "." + treasureName + ".Custom_Name")) {
                     ItemMeta itemMeta = item.getItemMeta();
-                    itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', config.getString(type + "." + treasureName + ".Custom_Name")));
+                    itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', getStringValue(type + "." + treasureName + ".Custom_Name")));
                     item.setItemMeta(itemMeta);
                 }
 
                 if (config.contains(type + "." + treasureName + ".Lore")) {
                     ItemMeta itemMeta = item.getItemMeta();
                     List<String> lore = new ArrayList<String>();
-                    for (String s : config.getStringList(type + "." + treasureName + ".Lore")) {
+                    for (String s : getStringValueList(type + "." + treasureName + ".Lore")) {
                         lore.add(ChatColor.translateAlternateColorCodes('&', s));
                     }
                     itemMeta.setLore(lore);
@@ -250,7 +250,7 @@ public class TreasureConfig extends ConfigurableLoader {
                     shakeMap.get(entityType).add(shakeTreasure);
                 } else if (isExcavation) {
                     ExcavationTreasure excavationTreasure = new ExcavationTreasure(item, xp, dropChance, dropLevel);
-                    List<String> dropList = config.getStringList(type + "." + treasureName + ".Drops_From");
+                    List<String> dropList = getStringValueList(type + "." + treasureName + ".Drops_From");
 
                     for (String blockType : dropList) {
                         if (!excavationMap.containsKey(blockType))
@@ -259,7 +259,7 @@ public class TreasureConfig extends ConfigurableLoader {
                     }
                 } else if (isHylian) {
                     HylianTreasure hylianTreasure = new HylianTreasure(item, xp, dropChance, dropLevel);
-                    List<String> dropList = config.getStringList(type + "." + treasureName + ".Drops_From");
+                    List<String> dropList = getStringValueList(type + "." + treasureName + ".Drops_From");
 
                     for (String dropper : dropList) {
                         if (dropper.equals("Bushes")) {
@@ -318,7 +318,7 @@ public class TreasureConfig extends ConfigurableLoader {
             }
 
             for (String enchantmentName : enchantmentSection.getKeys(false)) {
-                int level = config.getInt("Enchantments_Rarity." + rarity.toString() + "." + enchantmentName);
+                int level = getIntValue("Enchantments_Rarity." + rarity.toString() + "." + enchantmentName);
                 Enchantment enchantment = EnchantmentUtils.getByName(enchantmentName);
 
                 if (enchantment == null) {
@@ -336,22 +336,22 @@ public class TreasureConfig extends ConfigurableLoader {
     }
 
     public boolean getInventoryStealStacks() {
-        return config.getBoolean("Shake.PLAYER.INVENTORY.Whole_Stacks");
+        return getBooleanValue("Shake.PLAYER.INVENTORY.Whole_Stacks");
     }
 
     public double getInventoryStealDropChance() {
-        return config.getDouble("Shake.PLAYER.INVENTORY.Drop_Chance");
+        return getDoubleValue("Shake.PLAYER.INVENTORY.Drop_Chance");
     }
 
     public int getInventoryStealDropLevel() {
-        return config.getInt("Shake.PLAYER.INVENTORY.Drop_Level");
+        return getIntValue("Shake.PLAYER.INVENTORY.Drop_Level");
     }
 
     public double getItemDropRate(int tier, Rarity rarity) {
-        return config.getDouble("Item_Drop_Rates.Tier_" + tier + "." + rarity.toString());
+        return getDoubleValue("Item_Drop_Rates.Tier_" + tier + "." + rarity.toString());
     }
 
     public double getEnchantmentDropRate(int tier, Rarity rarity) {
-        return config.getDouble("Enchantment_Drop_Rates.Tier_" + tier + "." + rarity.toString());
+        return getDoubleValue("Enchantment_Drop_Rates.Tier_" + tier + "." + rarity.toString());
     }
 }

+ 2 - 2
core/src/main/java/com/gmail/nossr50/core/data/database/DatabaseManager.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.data.database;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.datatypes.database.DatabaseType;
 import com.gmail.nossr50.core.datatypes.database.PlayerStat;
 import com.gmail.nossr50.core.datatypes.player.PlayerProfile;
@@ -12,7 +12,7 @@ import java.util.UUID;
 
 public interface DatabaseManager {
     // One month in milliseconds
-    public final long PURGE_TIME = 2630000000L * Config.getInstance().getOldUsersCutoff();
+    public final long PURGE_TIME = 2630000000L * MainConfig.getInstance().getOldUsersCutoff();
     // During convertUsers, how often to output a status
     public final int progressInterval = 200;
 

+ 5 - 5
core/src/main/java/com/gmail/nossr50/core/datatypes/party/Party.java

@@ -1,7 +1,7 @@
 package com.gmail.nossr50.core.datatypes.party;
 
 import com.gmail.nossr50.config.experience.ExperienceConfig;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.datatypes.experience.FormulaType;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.mcMMO;
@@ -190,7 +190,7 @@ public class Party {
 
     public int getXpToLevel() {
         FormulaType formulaType = ExperienceConfig.getInstance().getFormulaType();
-        return (mcMMO.getFormulaManager().getCachedXpToLevel(level, formulaType)) * (getOnlineMembers().size() + Config.getInstance().getPartyXpCurveMultiplier());
+        return (mcMMO.getFormulaManager().getCachedXpToLevel(level, formulaType)) * (getOnlineMembers().size() + MainConfig.getInstance().getPartyXpCurveMultiplier());
     }
 
     public String getXpToLevelPercentage() {
@@ -229,13 +229,13 @@ public class Party {
             return;
         }
 
-        if (!Config.getInstance().getPartyInformAllMembers()) {
+        if (!MainConfig.getInstance().getPartyInformAllMembers()) {
             Player leader = mcMMO.p.getServer().getPlayer(this.leader.getUniqueId());
 
             if (leader != null) {
                 leader.sendMessage(LocaleLoader.getString("Party.LevelUp", levelsGained, getLevel()));
 
-                if (Config.getInstance().getLevelUpSoundsEnabled()) {
+                if (MainConfig.getInstance().getLevelUpSoundsEnabled()) {
                     SoundManager.sendSound(leader, leader.getLocation(), SoundType.LEVEL_UP);
                 }
             }
@@ -246,7 +246,7 @@ public class Party {
     }
 
     public boolean hasReachedLevelCap() {
-        return Config.getInstance().getPartyLevelCap() < getLevel() + 1;
+        return MainConfig.getInstance().getPartyLevelCap() < getLevel() + 1;
     }
 
     public ShareMode getXpShareMode() {

+ 2 - 2
core/src/main/java/com/gmail/nossr50/core/datatypes/party/PartyFeature.java

@@ -1,7 +1,7 @@
 package com.gmail.nossr50.core.datatypes.party;
 
 import com.gmail.nossr50.commands.party.PartySubcommandType;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.StringUtils;
@@ -19,7 +19,7 @@ public enum PartyFeature {
     }
 
     public String getFeatureLockedLocaleString() {
-        return LocaleLoader.getString("Ability.Generic.Template.Lock", LocaleLoader.getString("Party.Feature.Locked." + StringUtils.getPrettyPartyFeatureString(this).replace(" ", ""), Config.getInstance().getPartyFeatureUnlockLevel(this)));
+        return LocaleLoader.getString("Ability.Generic.Template.Lock", LocaleLoader.getString("Party.Feature.Locked." + StringUtils.getPrettyPartyFeatureString(this).replace(" ", ""), MainConfig.getInstance().getPartyFeatureUnlockLevel(this)));
     }
 
     public boolean hasPermission(Player player) {

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

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.datatypes.party;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.util.Misc;
 import org.bukkit.entity.Player;
 
@@ -12,7 +12,7 @@ public class PartyTeleportRecord {
     public PartyTeleportRecord() {
         requestor = null;
         enabled = true;
-        confirmRequired = Config.getInstance().getPTPCommandConfirmRequired();
+        confirmRequired = MainConfig.getInstance().getPTPCommandConfirmRequired();
         timeout = 0;
         lastUse = 0;
     }

+ 9 - 9
core/src/main/java/com/gmail/nossr50/core/datatypes/player/McMMOPlayer.java

@@ -2,7 +2,7 @@ package com.gmail.nossr50.core.datatypes.player;
 
 import com.gmail.nossr50.core.McmmoCore;
 import com.gmail.nossr50.core.config.AdvancedConfig;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.config.WorldBlacklist;
 import com.gmail.nossr50.core.config.experience.ExperienceConfig;
 import com.gmail.nossr50.core.data.UserManager;
@@ -490,7 +490,7 @@ public class McMMOPlayer {
             return;
         }
 
-        if (!Config.getInstance().getPartyXpNearMembersNeeded() || !PartyManager.getNearMembers(this).isEmpty()) {
+        if (!MainConfig.getInstance().getPartyXpNearMembersNeeded() || !PartyManager.getNearMembers(this).isEmpty()) {
             party.applyXpGain(modifyXpGain(skill, xp));
         }
     }
@@ -553,7 +553,7 @@ public class McMMOPlayer {
             return;
         }
 
-        if (Config.getInstance().getLevelUpSoundsEnabled()) {
+        if (MainConfig.getInstance().getLevelUpSoundsEnabled()) {
             SoundManager.sendSound(player, player.getLocation(), SoundType.LEVEL_UP);
         }
 
@@ -739,13 +739,13 @@ public class McMMOPlayer {
      * @return Modified experience
      */
     private float modifyXpGain(PrimarySkillType primarySkillType, float xp) {
-        if (player.getGameMode() == GameMode.CREATIVE || (primarySkillType.getMaxLevel() <= getSkillLevel(primarySkillType)) || (Config.getInstance().getPowerLevelCap() <= getPowerLevel())) {
+        if (player.getGameMode() == GameMode.CREATIVE || (primarySkillType.getMaxLevel() <= getSkillLevel(primarySkillType)) || (MainConfig.getInstance().getPowerLevelCap() <= getPowerLevel())) {
             return 0;
         }
 
         xp = (float) (xp / primarySkillType.getXpModifier() * ExperienceConfig.getInstance().getExperienceGainsGlobalMultiplier());
 
-        if (Config.getInstance().getToolModsEnabled()) {
+        if (MainConfig.getInstance().getToolModsEnabled()) {
             CustomTool tool = mcMMO.getModManager().getTool(player.getInventory().getItemInMainHand());
 
             if (tool != null) {
@@ -854,7 +854,7 @@ public class McMMOPlayer {
     }
 
     public void processAbilityActivation(PrimarySkillType skill) {
-        if (Config.getInstance().getAbilitiesOnlyActivateWhenSneaking() && !player.isSneaking()) {
+        if (MainConfig.getInstance().getAbilitiesOnlyActivateWhenSneaking() && !player.isSneaking()) {
             return;
         }
 
@@ -891,7 +891,7 @@ public class McMMOPlayer {
                 }
             }
 
-            if (Config.getInstance().getAbilityMessagesEnabled()) {
+            if (MainConfig.getInstance().getAbilityMessagesEnabled()) {
                 NotificationManager.sendPlayerInformation(player, NotificationType.TOOL, tool.getRaiseTool());
                 SoundManager.sendSound(player, player.getLocation(), SoundType.TOOL_READY);
             }
@@ -913,7 +913,7 @@ public class McMMOPlayer {
     }
 
     private boolean hasReachedLevelCap(PrimarySkillType skill) {
-        return (skill.getMaxLevel() < getSkillLevel(skill) + 1) || (Config.getInstance().getPowerLevelCap() < getPowerLevel() + 1);
+        return (skill.getMaxLevel() < getSkillLevel(skill) + 1) || (MainConfig.getInstance().getPowerLevelCap() < getPowerLevel() + 1);
     }
 
     /*
@@ -985,7 +985,7 @@ public class McMMOPlayer {
 
         UserManager.remove(thisPlayer);
 
-        if (Config.getInstance().getScoreboardsEnabled())
+        if (MainConfig.getInstance().getScoreboardsEnabled())
             ScoreboardManager.teardownPlayer(thisPlayer);
 
         if (inParty()) {

+ 2 - 2
core/src/main/java/com/gmail/nossr50/core/datatypes/player/PlayerProfile.java

@@ -2,7 +2,7 @@ package com.gmail.nossr50.core.datatypes.player;
 
 import com.gmail.nossr50.config.experience.ExperienceConfig;
 import com.gmail.nossr50.core.config.AdvancedConfig;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.experience.FormulaType;
 import com.gmail.nossr50.core.datatypes.experience.SkillXpGain;
@@ -46,7 +46,7 @@ public class PlayerProfile {
         this.uuid = uuid;
         this.playerName = playerName;
 
-        mobHealthbarType = Config.getInstance().getMobHealthbarDefault();
+        mobHealthbarType = MainConfig.getInstance().getMobHealthbarDefault();
         scoreboardTipsShown = 0;
 
         for (SuperAbilityType superAbilityType : SuperAbilityType.values()) {

+ 2 - 2
core/src/main/java/com/gmail/nossr50/core/locale/LocaleLoader.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.locale;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.mcMMO;
 import org.bukkit.ChatColor;
 
@@ -77,7 +77,7 @@ public final class LocaleLoader {
         if (bundle == null) {
             Locale.setDefault(new Locale("en", "US"));
             Locale locale = null;
-            String[] myLocale = Config.getInstance().getLocale().split("[-_ ]");
+            String[] myLocale = MainConfig.getInstance().getLocale().split("[-_ ]");
 
             if (myLocale.length == 1) {
                 locale = new Locale(myLocale[0]);

+ 7 - 7
core/src/main/java/com/gmail/nossr50/core/party/PartyManager.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.party;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.chat.ChatMode;
 import com.gmail.nossr50.core.datatypes.database.UpgradeType;
@@ -63,7 +63,7 @@ public final class PartyManager {
      * @return true if party is full and cannot be joined
      */
     public static boolean isPartyFull(Player player, Party targetParty) {
-        return !Permissions.partySizeBypass(player) && Config.getInstance().getPartyMaxSize() >= 1 && targetParty.getOnlineMembers().size() >= Config.getInstance().getPartyMaxSize();
+        return !Permissions.partySizeBypass(player) && MainConfig.getInstance().getPartyMaxSize() >= 1 && targetParty.getOnlineMembers().size() >= MainConfig.getInstance().getPartyMaxSize();
     }
 
     /**
@@ -131,7 +131,7 @@ public final class PartyManager {
 
         if (party != null) {
             Player player = mcMMOPlayer.getPlayer();
-            double range = Config.getInstance().getPartyShareRange();
+            double range = MainConfig.getInstance().getPartyShareRange();
 
             for (Player member : party.getOnlineMembers()) {
                 if (!player.equals(member) && member.isValid() && Misc.isNear(player.getLocation(), member.getLocation(), range)) {
@@ -149,7 +149,7 @@ public final class PartyManager {
 
         if (party != null) {
             Player player = mcMMOPlayer.getPlayer();
-            double range = Config.getInstance().getPartyShareRange();
+            double range = MainConfig.getInstance().getPartyShareRange();
 
             for (Player member : party.getVisibleMembers(player)) {
                 if (!player.equals(member)
@@ -403,8 +403,8 @@ public final class PartyManager {
         /*
          * Don't let players join a full party
          */
-        if (Config.getInstance().getPartyMaxSize() > 0 && invite.getMembers().size() >= Config.getInstance().getPartyMaxSize()) {
-            NotificationManager.sendPlayerInformation(mcMMOPlayer.getPlayer(), NotificationType.PARTY_MESSAGE, "Commands.Party.PartyFull.InviteAccept", invite.getName(), String.valueOf(Config.getInstance().getPartyMaxSize()));
+        if (MainConfig.getInstance().getPartyMaxSize() > 0 && invite.getMembers().size() >= MainConfig.getInstance().getPartyMaxSize()) {
+            NotificationManager.sendPlayerInformation(mcMMOPlayer.getPlayer(), NotificationType.PARTY_MESSAGE, "Commands.Party.PartyFull.InviteAccept", invite.getName(), String.valueOf(MainConfig.getInstance().getPartyMaxSize()));
             return;
         }
 
@@ -761,7 +761,7 @@ public final class PartyManager {
      * @param level        The current party level
      */
     public static void informPartyMembersLevelUp(Party party, int levelsGained, int level) {
-        boolean levelUpSoundsEnabled = Config.getInstance().getLevelUpSoundsEnabled();
+        boolean levelUpSoundsEnabled = MainConfig.getInstance().getLevelUpSoundsEnabled();
         for (Player member : party.getOnlineMembers()) {
             member.sendMessage(LocaleLoader.getString("Party.LevelUp", levelsGained, level));
 

+ 2 - 2
core/src/main/java/com/gmail/nossr50/core/party/ShareHandler.java

@@ -1,7 +1,7 @@
 package com.gmail.nossr50.core.party;
 
 import com.gmail.nossr50.config.party.ItemWeightConfig;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.experience.XPGainReason;
 import com.gmail.nossr50.core.datatypes.experience.XPGainSource;
@@ -45,7 +45,7 @@ public final class ShareHandler {
         nearMembers.add(mcMMOPlayer.getPlayer());
 
         int partySize = nearMembers.size();
-        double shareBonus = Math.min(Config.getInstance().getPartyShareBonusBase() + (partySize * Config.getInstance().getPartyShareBonusIncrease()), Config.getInstance().getPartyShareBonusCap());
+        double shareBonus = Math.min(MainConfig.getInstance().getPartyShareBonusBase() + (partySize * MainConfig.getInstance().getPartyShareBonusIncrease()), MainConfig.getInstance().getPartyShareBonusCap());
         float splitXp = (float) (xp / partySize * shareBonus);
 
         for (Player member : nearMembers) {

+ 6 - 0
core/src/main/java/com/gmail/nossr50/core/platform/Platform.java

@@ -71,4 +71,10 @@ public interface Platform {
      * @return this platform's data folder
      */
     File getDataFolderPath();
+
+    /**
+     * Gets the path of the mods config folder inside the Data folder for this platform
+     * @return this platform's mod config subdirectory
+     */
+    String getModDataFolderPath();
 }

+ 4 - 4
core/src/main/java/com/gmail/nossr50/core/runnables/backups/CleanBackupsTask.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.runnables.backups;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.mcMMO;
 import org.bukkit.scheduler.BukkitRunnable;
 
@@ -48,10 +48,10 @@ public class CleanBackupsTask extends BukkitRunnable {
             int weekOfYear = cal.get(Calendar.WEEK_OF_YEAR);
             int year = cal.get(Calendar.YEAR);
 
-            if (isPast24Hours(date) && Config.getInstance().getKeepLast24Hours()) {
+            if (isPast24Hours(date) && MainConfig.getInstance().getKeepLast24Hours()) {
                 // Keep all files from the last 24 hours
                 continue;
-            } else if (isLastWeek(date) && !savedDays.contains(dayOfWeek) && Config.getInstance().getKeepDailyLastWeek()) {
+            } else if (isLastWeek(date) && !savedDays.contains(dayOfWeek) && MainConfig.getInstance().getKeepDailyLastWeek()) {
                 // Keep daily backups of the past week
                 savedDays.add(dayOfWeek);
                 continue;
@@ -62,7 +62,7 @@ public class CleanBackupsTask extends BukkitRunnable {
                     savedYearsWeeks.put(year, savedWeeks);
                 }
 
-                if (!savedWeeks.contains(weekOfYear) && Config.getInstance().getKeepWeeklyPastMonth()) {
+                if (!savedWeeks.contains(weekOfYear) && MainConfig.getInstance().getKeepWeeklyPastMonth()) {
                     // Keep one net.shatteredlands.shatt.backup of each week
                     savedWeeks.add(weekOfYear);
                     continue;

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

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.runnables.commands;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.locale.LocaleLoader;
 import com.gmail.nossr50.core.skills.PrimarySkillType;
 import com.gmail.nossr50.mcMMO;
@@ -30,7 +30,7 @@ public class McrankCommandDisplayTask extends BukkitRunnable {
 
     @Override
     public void run() {
-        if (useBoard && Config.getInstance().getScoreboardsEnabled()) {
+        if (useBoard && MainConfig.getInstance().getScoreboardsEnabled()) {
             displayBoard();
         }
 

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

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.runnables.commands;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.datatypes.database.PlayerStat;
 import com.gmail.nossr50.core.locale.LocaleLoader;
 import com.gmail.nossr50.core.skills.PrimarySkillType;
@@ -34,7 +34,7 @@ public class MctopCommandDisplayTask extends BukkitRunnable {
 
     @Override
     public void run() {
-        if (useBoard && Config.getInstance().getScoreboardsEnabled()) {
+        if (useBoard && MainConfig.getInstance().getScoreboardsEnabled()) {
             displayBoard();
         }
 

+ 2 - 2
core/src/main/java/com/gmail/nossr50/core/runnables/database/UserPurgeTask.java

@@ -1,7 +1,7 @@
 package com.gmail.nossr50.core.runnables.database;
 
 import com.gmail.nossr50.core.McmmoCore;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 
 import java.util.concurrent.locks.ReentrantLock;
 
@@ -13,7 +13,7 @@ public class UserPurgeTask implements Runnable {
         lock.lock();
         McmmoCore.getDatabaseManager().purgePowerlessUsers();
 
-        if (Config.getInstance().getOldUsersCutoff() != -1) {
+        if (MainConfig.getInstance().getOldUsersCutoff() != -1) {
             McmmoCore.getDatabaseManager().purgeOldUsers();
         }
         lock.unlock();

+ 3 - 3
core/src/main/java/com/gmail/nossr50/core/runnables/items/ChimaeraWingWarmup.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.runnables.items;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.core.locale.LocaleLoader;
 import com.gmail.nossr50.util.ChimaeraWing;
@@ -36,13 +36,13 @@ public class ChimaeraWingWarmup extends BukkitRunnable {
 
         ItemStack inHand = player.getInventory().getItemInMainHand();
 
-        if (!ItemUtils.isChimaeraWing(inHand) || inHand.getAmount() < Config.getInstance().getChimaeraUseCost()) {
+        if (!ItemUtils.isChimaeraWing(inHand) || inHand.getAmount() < MainConfig.getInstance().getChimaeraUseCost()) {
             player.sendMessage(LocaleLoader.getString("Skills.NeedMore", LocaleLoader.getString("Item.ChimaeraWing.Name")));
             return;
         }
 
         long recentlyHurt = mcMMOPlayer.getRecentlyHurt();
-        int hurtCooldown = Config.getInstance().getChimaeraRecentlyHurtCooldown();
+        int hurtCooldown = MainConfig.getInstance().getChimaeraRecentlyHurtCooldown();
 
         if (hurtCooldown > 0) {
             int timeRemaining = SkillUtils.calculateTimeLeft(recentlyHurt * Misc.TIME_CONVERSION_FACTOR, hurtCooldown, player);

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

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.runnables.items;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.core.locale.LocaleLoader;
 import com.gmail.nossr50.party.PartyManager;
@@ -40,7 +40,7 @@ public class TeleportationWarmup extends BukkitRunnable {
             return;
         }
 
-        int hurtCooldown = Config.getInstance().getPTPCommandRecentlyHurtCooldown();
+        int hurtCooldown = MainConfig.getInstance().getPTPCommandRecentlyHurtCooldown();
 
         if (hurtCooldown > 0) {
             int timeRemaining = SkillUtils.calculateTimeLeft(recentlyHurt * Misc.TIME_CONVERSION_FACTOR, hurtCooldown, teleportingPlayer);

+ 2 - 2
core/src/main/java/com/gmail/nossr50/core/runnables/party/PartyAutoKickTask.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.runnables.party;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.datatypes.party.Party;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.party.PartyManager;
@@ -14,7 +14,7 @@ import java.util.Map.Entry;
 import java.util.UUID;
 
 public class PartyAutoKickTask extends BukkitRunnable {
-    private final static long KICK_TIME = 24L * 60L * 60L * 1000L * Config.getInstance().getAutoPartyKickTime();
+    private final static long KICK_TIME = 24L * 60L * 60L * 1000L * MainConfig.getInstance().getAutoPartyKickTime();
 
     @Override
     public void run() {

+ 3 - 3
core/src/main/java/com/gmail/nossr50/core/runnables/party/PartyChatTask.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.runnables.party;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.datatypes.party.Party;
 import com.gmail.nossr50.core.locale.LocaleLoader;
 import org.bukkit.ChatColor;
@@ -30,7 +30,7 @@ public class PartyChatTask extends BukkitRunnable {
 
     @Override
     public void run() {
-        if (Config.getInstance().getPartyChatColorLeaderName() && senderName.equalsIgnoreCase(party.getLeader().getPlayerName())) {
+        if (MainConfig.getInstance().getPartyChatColorLeaderName() && senderName.equalsIgnoreCase(party.getLeader().getPlayerName())) {
             message = message.replaceFirst(Pattern.quote(displayName), ChatColor.GOLD + Matcher.quoteReplacement(displayName) + ChatColor.RESET);
         }
 
@@ -40,7 +40,7 @@ public class PartyChatTask extends BukkitRunnable {
 
         if (party.getAlly() != null) {
             for (Player member : party.getAlly().getOnlineMembers()) {
-                String allyPrefix = LocaleLoader.formatString(Config.getInstance().getPartyChatPrefixAlly());
+                String allyPrefix = LocaleLoader.formatString(MainConfig.getInstance().getPartyChatPrefixAlly());
                 member.sendMessage(allyPrefix + message);
             }
         }

+ 4 - 4
core/src/main/java/com/gmail/nossr50/core/runnables/player/PlayerProfileLoadingTask.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.runnables.player;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.core.datatypes.player.PlayerProfile;
@@ -77,16 +77,16 @@ public class PlayerProfileLoadingTask extends BukkitRunnable {
             UserManager.track(mcMMOPlayer);
             mcMMOPlayer.actualizeRespawnATS();
 
-            if (Config.getInstance().getScoreboardsEnabled()) {
+            if (MainConfig.getInstance().getScoreboardsEnabled()) {
                 ScoreboardManager.setupPlayer(player);
 
-                if (Config.getInstance().getShowStatsAfterLogin()) {
+                if (MainConfig.getInstance().getShowStatsAfterLogin()) {
                     ScoreboardManager.enablePlayerStatsScoreboard(player);
                     new McScoreboardKeepTask(player).runTaskLater(mcMMO.p, 1 * Misc.TICK_CONVERSION_FACTOR);
                 }
             }
 
-            if (Config.getInstance().getShowProfileLoadedMessage()) {
+            if (MainConfig.getInstance().getShowProfileLoadedMessage()) {
                 player.sendMessage(LocaleLoader.getString("Profile.Loading.Success"));
             }
 

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

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.runnables.skills;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
 import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.core.skills.SuperAbilityType;
@@ -40,7 +40,7 @@ public class AbilityDisableTask extends BukkitRunnable {
                 // Fallthrough
 
             case BERSERK:
-                if (Config.getInstance().getRefreshChunksEnabled()) {
+                if (MainConfig.getInstance().getRefreshChunksEnabled()) {
                     resendChunkRadiusAt(player, 1);
                 }
                 // Fallthrough

+ 2 - 2
core/src/main/java/com/gmail/nossr50/core/runnables/skills/ToolLowerTask.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.runnables.skills;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
 import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.core.skills.ToolType;
@@ -24,7 +24,7 @@ public class ToolLowerTask extends BukkitRunnable {
 
         mcMMOPlayer.setToolPreparationMode(tool, false);
 
-        if (Config.getInstance().getAbilityMessagesEnabled()) {
+        if (MainConfig.getInstance().getAbilityMessagesEnabled()) {
             NotificationManager.sendPlayerInformation(mcMMOPlayer.getPlayer(), NotificationType.TOOL, tool.getLowerTool());
         }
     }

+ 11 - 11
core/src/main/java/com/gmail/nossr50/core/skills/PrimarySkillType.java

@@ -1,7 +1,7 @@
 package com.gmail.nossr50.core.skills;
 
 import com.gmail.nossr50.core.McmmoCore;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.config.experience.ExperienceConfig;
 import com.gmail.nossr50.core.locale.LocaleLoader;
 import com.gmail.nossr50.core.mcmmo.colors.Color;
@@ -104,7 +104,7 @@ public enum PrimarySkillType {
     }
 
     public static PrimarySkillType getSkill(String skillName) {
-        if (!Config.getInstance().getLocale().equalsIgnoreCase("en_US")) {
+        if (!MainConfig.getInstance().getLocale().equalsIgnoreCase("en_US")) {
             for (PrimarySkillType type : values()) {
                 if (skillName.equalsIgnoreCase(LocaleLoader.getString(StringUtils.getCapitalized(type.name()) + ".SkillName"))) {
                     return type;
@@ -158,7 +158,7 @@ public enum PrimarySkillType {
      * @return the max level of this skill
      */
     public int getMaxLevel() {
-        return Config.getInstance().getLevelCap(this);
+        return MainConfig.getInstance().getLevelCap(this);
     }
 
     public boolean isSuperAbilityUnlocked(Player player) {
@@ -166,31 +166,31 @@ public enum PrimarySkillType {
     }
 
     public boolean getPVPEnabled() {
-        return Config.getInstance().getPVPEnabled(this);
+        return MainConfig.getInstance().getPVPEnabled(this);
     }
 
     public boolean getPVEEnabled() {
-        return Config.getInstance().getPVEEnabled(this);
+        return MainConfig.getInstance().getPVEEnabled(this);
     }
 
     public boolean getDoubleDropsDisabled() {
-        return Config.getInstance().getDoubleDropsDisabled(this);
+        return MainConfig.getInstance().getDoubleDropsDisabled(this);
     }
 
     public boolean getHardcoreStatLossEnabled() {
-        return Config.getInstance().getHardcoreStatLossEnabled(this);
+        return MainConfig.getInstance().getHardcoreStatLossEnabled(this);
     }
 
     public void setHardcoreStatLossEnabled(boolean enable) {
-        Config.getInstance().setHardcoreStatLossEnabled(this, enable);
+        MainConfig.getInstance().setHardcoreStatLossEnabled(this, enable);
     }
 
     public boolean getHardcoreVampirismEnabled() {
-        return Config.getInstance().getHardcoreVampirismEnabled(this);
+        return MainConfig.getInstance().getHardcoreVampirismEnabled(this);
     }
 
     public void setHardcoreVampirismEnabled(boolean enable) {
-        Config.getInstance().setHardcoreVampirismEnabled(this, enable);
+        MainConfig.getInstance().setHardcoreVampirismEnabled(this, enable);
     }
 
     public ToolType getTool() {
@@ -218,7 +218,7 @@ public enum PrimarySkillType {
     }
 
     public String getName() {
-        return Config.getInstance().getLocale().equalsIgnoreCase("en_US") ? StringUtils.getCapitalized(this.toString()) : StringUtils.getCapitalized(LocaleLoader.getString(StringUtils.getCapitalized(this.toString()) + ".SkillName"));
+        return MainConfig.getInstance().getLocale().equalsIgnoreCase("en_US") ? StringUtils.getCapitalized(this.toString()) : StringUtils.getCapitalized(LocaleLoader.getString(StringUtils.getCapitalized(this.toString()) + ".SkillName"));
     }
 
     public boolean getPermissions(Player player) {

+ 3 - 3
core/src/main/java/com/gmail/nossr50/core/skills/SuperAbilityType.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.skills;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.mcmmo.block.BlockState;
 import com.gmail.nossr50.core.mcmmo.entity.Player;
 import com.gmail.nossr50.core.util.BlockUtils;
@@ -99,11 +99,11 @@ public enum SuperAbilityType {
     }
 
     public int getCooldown() {
-        return Config.getInstance().getCooldown(this);
+        return MainConfig.getInstance().getCooldown(this);
     }
 
     public int getMaxLength() {
-        return Config.getInstance().getMaxLength(this);
+        return MainConfig.getInstance().getMaxLength(this);
     }
 
     public String getAbilityOn() {

+ 2 - 2
core/src/main/java/com/gmail/nossr50/core/skills/child/salvage/Salvage.java

@@ -1,11 +1,11 @@
 package com.gmail.nossr50.core.skills.child.salvage;
 
 import com.gmail.nossr50.core.config.AdvancedConfig;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import org.bukkit.Material;
 
 public class Salvage {
-    public static Material anvilMaterial = Config.getInstance().getSalvageAnvilMaterial();
+    public static Material anvilMaterial = MainConfig.getInstance().getSalvageAnvilMaterial();
 
     /*public static int    salvageMaxPercentageLevel = AdvancedConfig.getInstance().getSalvageMaxPercentageLevel();
     public static double salvageMaxPercentage      = AdvancedConfig.getInstance().getSalvageMaxPercentage();

+ 5 - 5
core/src/main/java/com/gmail/nossr50/core/skills/child/salvage/SalvageManager.java

@@ -1,7 +1,7 @@
 package com.gmail.nossr50.core.skills.child.salvage;
 
 import com.gmail.nossr50.core.config.AdvancedConfig;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
 import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.core.locale.LocaleLoader;
@@ -49,11 +49,11 @@ public class SalvageManager extends SkillManager {
             return;
         }
 
-        if (Config.getInstance().getSalvageAnvilMessagesEnabled()) {
+        if (MainConfig.getInstance().getSalvageAnvilMessagesEnabled()) {
             NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Salvage.Listener.Anvil");
         }
 
-        if (Config.getInstance().getSalvageAnvilPlaceSoundsEnabled()) {
+        if (MainConfig.getInstance().getSalvageAnvilPlaceSoundsEnabled()) {
             SoundManager.sendSound(player, player.getLocation(), SoundType.ANVIL);
         }
 
@@ -130,7 +130,7 @@ public class SalvageManager extends SkillManager {
         Misc.dropItems(location, salvageResults, 1);
 
         // BWONG BWONG BWONG - CLUNK!
-        if (Config.getInstance().getSalvageAnvilUseSoundsEnabled()) {
+        if (MainConfig.getInstance().getSalvageAnvilUseSoundsEnabled()) {
             SoundManager.sendSound(player, player.getLocation(), SoundType.ANVIL);
             SoundManager.sendSound(player, player.getLocation(), SoundType.ITEM_BREAK);
 
@@ -248,7 +248,7 @@ public class SalvageManager extends SkillManager {
         Player player = getPlayer();
         long lastUse = getLastAnvilUse();
 
-        if (!SkillUtils.cooldownExpired(lastUse, 3) || !Config.getInstance().getSalvageConfirmRequired()) {
+        if (!SkillUtils.cooldownExpired(lastUse, 3) || !MainConfig.getInstance().getSalvageConfirmRequired()) {
             return true;
         }
 

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

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.skills.child.smelting;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.datatypes.experience.XPGainReason;
 import com.gmail.nossr50.core.datatypes.experience.XPGainSource;
 import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
@@ -79,13 +79,13 @@ public class SmeltingManager extends SkillManager {
             // We need to distribute Mining XP here, because the block break event gets cancelled
             applyXpGain(Mining.getBlockXp(blockState), XPGainReason.PVE, XPGainSource.PASSIVE);
 
-            SkillUtils.handleDurabilityChange(getPlayer().getInventory().getItemInMainHand(), Config.getInstance().getAbilityToolDamage());
+            SkillUtils.handleDurabilityChange(getPlayer().getInventory().getItemInMainHand(), MainConfig.getInstance().getAbilityToolDamage());
 
             Misc.dropItems(Misc.getBlockCenter(blockState), item, isSecondSmeltSuccessful() ? 2 : 1);
 
             blockState.setType(Material.AIR);
 
-            if (Config.getInstance().getFluxPickaxeSoundEnabled()) {
+            if (MainConfig.getInstance().getFluxPickaxeSoundEnabled()) {
                 SoundManager.sendSound(player, blockState.getLocation(), SoundType.FIZZ);
             }
 

+ 2 - 2
core/src/main/java/com/gmail/nossr50/core/skills/primary/acrobatics/Acrobatics.java

@@ -2,12 +2,12 @@ package com.gmail.nossr50.core.skills.primary.acrobatics;
 
 import com.gmail.nossr50.config.experience.ExperienceConfig;
 import com.gmail.nossr50.core.config.AdvancedConfig;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 
 public final class Acrobatics {
     public static double dodgeDamageModifier = AdvancedConfig.getInstance().getDodgeDamageModifier();
     public static int dodgeXpModifier = ExperienceConfig.getInstance().getDodgeXPModifier();
-    public static boolean dodgeLightningDisabled = Config.getInstance().getDodgeLightningDisabled();
+    public static boolean dodgeLightningDisabled = MainConfig.getInstance().getDodgeLightningDisabled();
 
     private Acrobatics() {
     }

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

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.skills.primary.excavation;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.datatypes.experience.XPGainReason;
 import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.core.skills.PrimarySkillType;
@@ -77,6 +77,6 @@ public class ExcavationManager extends SkillManager {
         excavationBlockCheck(blockState);
         excavationBlockCheck(blockState);
 
-        SkillUtils.handleDurabilityChange(getPlayer().getInventory().getItemInMainHand(), Config.getInstance().getAbilityToolDamage());
+        SkillUtils.handleDurabilityChange(getPlayer().getInventory().getItemInMainHand(), MainConfig.getInstance().getAbilityToolDamage());
     }
 }

+ 4 - 4
core/src/main/java/com/gmail/nossr50/core/skills/primary/fishing/FishingManager.java

@@ -2,7 +2,7 @@ package com.gmail.nossr50.core.skills.primary.fishing;
 
 import com.gmail.nossr50.config.experience.ExperienceConfig;
 import com.gmail.nossr50.core.config.AdvancedConfig;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.config.treasure.TreasureConfig;
 import com.gmail.nossr50.core.datatypes.experience.XPGainReason;
 import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
@@ -197,7 +197,7 @@ public class FishingManager extends SkillManager {
         Player player = getPlayer();
         FishingTreasure treasure = null;
 
-        if (Config.getInstance().getFishingDropsEnabled() && Permissions.isSubSkillEnabled(player, SubSkillType.FISHING_TREASURE_HUNTER)) {
+        if (MainConfig.getInstance().getFishingDropsEnabled() && Permissions.isSubSkillEnabled(player, SubSkillType.FISHING_TREASURE_HUNTER)) {
             treasure = getFishingTreasure();
             this.fishingCatch = null;
         }
@@ -234,7 +234,7 @@ public class FishingManager extends SkillManager {
                     NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Fishing.Ability.TH.MagicFound");
                 }
 
-                if (Config.getInstance().getFishingExtraFish()) {
+                if (MainConfig.getInstance().getFishingExtraFish()) {
                     Misc.dropItem(player.getEyeLocation(), fishingCatch.getItemStack());
                 }
 
@@ -364,7 +364,7 @@ public class FishingManager extends SkillManager {
         }
 
         // Rather than subtracting luck (and causing a minimum 3% chance for every drop), scale by luck.
-        diceRoll *= (1.0 - luck * Config.getInstance().getFishingLureModifier() / 100);
+        diceRoll *= (1.0 - luck * MainConfig.getInstance().getFishingLureModifier() / 100);
 
         FishingTreasure treasure = null;
 

+ 3 - 3
core/src/main/java/com/gmail/nossr50/core/skills/primary/herbalism/HerbalismManager.java

@@ -1,7 +1,7 @@
 package com.gmail.nossr50.core.skills.primary.herbalism;
 
 import com.gmail.nossr50.config.experience.ExperienceConfig;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.config.treasure.TreasureConfig;
 import com.gmail.nossr50.core.datatypes.experience.XPGainReason;
 import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
@@ -36,7 +36,7 @@ public class HerbalismManager extends SkillManager {
     }
 
     public boolean canBlockCheck() {
-        return !(Config.getInstance().getHerbalismPreventAFK() && getPlayer().isInsideVehicle());
+        return !(MainConfig.getInstance().getHerbalismPreventAFK() && getPlayer().isInsideVehicle());
     }
 
     public boolean canGreenThumbBlock(BlockState blockState) {
@@ -148,7 +148,7 @@ public class HerbalismManager extends SkillManager {
         } else {
             xp = ExperienceConfig.getInstance().getXp(skill, blockState.getBlockData());
 
-            if (Config.getInstance().getDoubleDropsEnabled(skill, material) && Permissions.isSubSkillEnabled(player, SubSkillType.HERBALISM_DOUBLE_DROPS)) {
+            if (MainConfig.getInstance().getDoubleDropsEnabled(skill, material) && Permissions.isSubSkillEnabled(player, SubSkillType.HERBALISM_DOUBLE_DROPS)) {
                 drops = blockState.getBlock().getDrops();
             }
 

+ 2 - 2
core/src/main/java/com/gmail/nossr50/core/skills/primary/mining/BlastMining.java

@@ -1,7 +1,7 @@
 package com.gmail.nossr50.core.skills.primary.mining;
 
 import com.gmail.nossr50.core.config.AdvancedConfig;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.skills.SubSkillType;
 import com.gmail.nossr50.mcMMO;
@@ -42,7 +42,7 @@ public class BlastMining {
     }*/
 
     public final static int MAXIMUM_REMOTE_DETONATION_DISTANCE = 100;
-    public static Material detonator = Config.getInstance().getDetonatorItem();
+    public static Material detonator = MainConfig.getInstance().getDetonatorItem();
 
     public static double getBlastRadiusModifier(int rank) {
         return AdvancedConfig.getInstance().getBlastRadiusModifier(rank);

+ 3 - 3
core/src/main/java/com/gmail/nossr50/core/skills/primary/mining/MiningManager.java

@@ -1,7 +1,7 @@
 package com.gmail.nossr50.core.skills.primary.mining;
 
 import com.gmail.nossr50.core.config.AdvancedConfig;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.datatypes.experience.XPGainReason;
 import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
 import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
@@ -85,10 +85,10 @@ public class MiningManager extends SkillManager {
         Material material = blockState.getType();
 
         if (mcMMOPlayer.getAbilityMode(skill.getAbility())) {
-            SkillUtils.handleDurabilityChange(getPlayer().getInventory().getItemInMainHand(), Config.getInstance().getAbilityToolDamage());
+            SkillUtils.handleDurabilityChange(getPlayer().getInventory().getItemInMainHand(), MainConfig.getInstance().getAbilityToolDamage());
         }
 
-        if ((mcMMO.getModManager().isCustomMiningBlock(blockState) && !mcMMO.getModManager().getBlock(blockState).isDoubleDropEnabled()) || !Config.getInstance().getDoubleDropsEnabled(skill, material)) {
+        if ((mcMMO.getModManager().isCustomMiningBlock(blockState) && !mcMMO.getModManager().getBlock(blockState).isDoubleDropEnabled()) || !MainConfig.getInstance().getDoubleDropsEnabled(skill, material)) {
             return;
         }
 

+ 2 - 2
core/src/main/java/com/gmail/nossr50/core/skills/primary/repair/Repair.java

@@ -1,12 +1,12 @@
 package com.gmail.nossr50.core.skills.primary.repair;
 
 import com.gmail.nossr50.core.config.AdvancedConfig;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import org.bukkit.Material;
 
 public class Repair {
     public static int repairMasteryMaxBonusLevel = AdvancedConfig.getInstance().getRepairMasteryMaxLevel();
     public static double repairMasteryMaxBonus = AdvancedConfig.getInstance().getRepairMasteryMaxBonus();
 
-    public static Material anvilMaterial = Config.getInstance().getRepairAnvilMaterial();
+    public static Material anvilMaterial = MainConfig.getInstance().getRepairAnvilMaterial();
 }

+ 5 - 5
core/src/main/java/com/gmail/nossr50/core/skills/primary/repair/RepairManager.java

@@ -2,7 +2,7 @@ package com.gmail.nossr50.core.skills.primary.repair;
 
 import com.gmail.nossr50.config.experience.ExperienceConfig;
 import com.gmail.nossr50.core.config.AdvancedConfig;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.datatypes.experience.XPGainReason;
 import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
 import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
@@ -51,11 +51,11 @@ public class RepairManager extends SkillManager {
             return;
         }
 
-        if (Config.getInstance().getRepairAnvilMessagesEnabled()) {
+        if (MainConfig.getInstance().getRepairAnvilMessagesEnabled()) {
             NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Repair.Listener.Anvil");
         }
 
-        if (Config.getInstance().getRepairAnvilPlaceSoundsEnabled()) {
+        if (MainConfig.getInstance().getRepairAnvilPlaceSoundsEnabled()) {
             SoundManager.sendSound(player, player.getLocation(), SoundType.ANVIL);
         }
 
@@ -155,7 +155,7 @@ public class RepairManager extends SkillManager {
         applyXpGain((float) ((getPercentageRepaired(startDurability, newDurability, repairable.getMaximumDurability()) * repairable.getXpMultiplier()) * ExperienceConfig.getInstance().getRepairXPBase() * ExperienceConfig.getInstance().getRepairXP(repairable.getRepairMaterialType())), XPGainReason.PVE);
 
         // BWONG BWONG BWONG
-        if (Config.getInstance().getRepairAnvilUseSoundsEnabled()) {
+        if (MainConfig.getInstance().getRepairAnvilUseSoundsEnabled()) {
             SoundManager.sendSound(player, player.getLocation(), SoundType.ANVIL);
             SoundManager.sendSound(player, player.getLocation(), SoundType.ITEM_BREAK);
         }
@@ -177,7 +177,7 @@ public class RepairManager extends SkillManager {
         Player player = getPlayer();
         long lastUse = getLastAnvilUse();
 
-        if (!SkillUtils.cooldownExpired(lastUse, 3) || !Config.getInstance().getRepairConfirmRequired()) {
+        if (!SkillUtils.cooldownExpired(lastUse, 3) || !MainConfig.getInstance().getRepairConfirmRequired()) {
             return true;
         }
 

+ 8 - 8
core/src/main/java/com/gmail/nossr50/core/skills/primary/taming/TamingManager.java

@@ -2,7 +2,7 @@ package com.gmail.nossr50.core.skills.primary.taming;
 
 import com.gmail.nossr50.config.experience.ExperienceConfig;
 import com.gmail.nossr50.core.config.AdvancedConfig;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.experience.XPGainReason;
 import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
@@ -168,7 +168,7 @@ public class TamingManager extends SkillManager {
             return;
         }
 
-        callOfTheWild(EntityType.OCELOT, Config.getInstance().getTamingCOTWCost(EntityType.OCELOT));
+        callOfTheWild(EntityType.OCELOT, MainConfig.getInstance().getTamingCOTWCost(EntityType.OCELOT));
     }
 
     /**
@@ -182,7 +182,7 @@ public class TamingManager extends SkillManager {
             return;
         }
 
-        callOfTheWild(EntityType.WOLF, Config.getInstance().getTamingCOTWCost(EntityType.WOLF));
+        callOfTheWild(EntityType.WOLF, MainConfig.getInstance().getTamingCOTWCost(EntityType.WOLF));
     }
 
     /**
@@ -196,7 +196,7 @@ public class TamingManager extends SkillManager {
             return;
         }
 
-        callOfTheWild(EntityType.HORSE, Config.getInstance().getTamingCOTWCost(EntityType.HORSE));
+        callOfTheWild(EntityType.HORSE, MainConfig.getInstance().getTamingCOTWCost(EntityType.HORSE));
     }
 
     /**
@@ -290,8 +290,8 @@ public class TamingManager extends SkillManager {
             return;
         }
 
-        int amount = Config.getInstance().getTamingCOTWAmount(type);
-        int tamingCOTWLength = Config.getInstance().getTamingCOTWLength(type);
+        int amount = MainConfig.getInstance().getTamingCOTWAmount(type);
+        int tamingCOTWLength = MainConfig.getInstance().getTamingCOTWLength(type);
 
         for (int i = 0; i < amount; i++) {
             if (!summonAmountCheck(type)) {
@@ -360,7 +360,7 @@ public class TamingManager extends SkillManager {
     }
 
     private boolean rangeCheck(EntityType type) {
-        double range = Config.getInstance().getTamingCOTWRange();
+        double range = MainConfig.getInstance().getTamingCOTWRange();
         Player player = getPlayer();
 
         if (range == 0) {
@@ -380,7 +380,7 @@ public class TamingManager extends SkillManager {
     private boolean summonAmountCheck(EntityType entityType) {
         Player player = getPlayer();
 
-        int maxAmountSummons = Config.getInstance().getTamingCOTWMaxAmount(entityType);
+        int maxAmountSummons = MainConfig.getInstance().getTamingCOTWMaxAmount(entityType);
 
         if (maxAmountSummons <= 0) {
             return true;

+ 2 - 2
core/src/main/java/com/gmail/nossr50/core/skills/primary/taming/TrackedTamingEntity.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.skills.primary.taming;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.skills.CombatUtils;
@@ -22,7 +22,7 @@ public class TrackedTamingEntity extends BukkitRunnable {
         this.livingEntity = livingEntity;
         this.id = livingEntity.getUniqueId();
 
-        int tamingCOTWLength = Config.getInstance().getTamingCOTWLength(livingEntity.getType());
+        int tamingCOTWLength = MainConfig.getInstance().getTamingCOTWLength(livingEntity.getType());
 
         if (tamingCOTWLength > 0) {
             this.length = tamingCOTWLength * Misc.TICK_CONVERSION_FACTOR;

+ 2 - 2
core/src/main/java/com/gmail/nossr50/core/skills/primary/unarmed/Unarmed.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.skills.primary.unarmed;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.util.sounds.SoundManager;
 import com.gmail.nossr50.util.sounds.SoundType;
 import org.bukkit.entity.Player;
@@ -8,7 +8,7 @@ import org.bukkit.event.entity.EntityPickupItemEvent;
 import org.bukkit.inventory.ItemStack;
 
 public class Unarmed {
-    public static boolean blockCrackerSmoothBrick = Config.getInstance().getUnarmedBlockCrackerSmoothbrickToCracked();
+    public static boolean blockCrackerSmoothBrick = MainConfig.getInstance().getUnarmedBlockCrackerSmoothbrickToCracked();
     public static double berserkDamageModifier = 1.5;
     public static long lastAttacked = 0;
     public static long attackInterval = 750;

+ 4 - 4
core/src/main/java/com/gmail/nossr50/core/skills/primary/woodcutting/Woodcutting.java

@@ -1,7 +1,7 @@
 package com.gmail.nossr50.core.skills.primary.woodcutting;
 
 import com.gmail.nossr50.config.experience.ExperienceConfig;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.skills.PrimarySkillType;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.util.BlockUtils;
@@ -28,7 +28,7 @@ public final class Woodcutting {
             new int[]{1, -2}, new int[]{1, -1}, new int[]{1, 0}, new int[]{1, 1}, new int[]{1, 2},
             new int[]{2, -1}, new int[]{2, 0}, new int[]{2, 1},
     };
-    public static int treeFellerThreshold = Config.getInstance().getTreeFellerThreshold();
+    public static int treeFellerThreshold = MainConfig.getInstance().getTreeFellerThreshold();
     protected static boolean treeFellerReachedThreshold = false;
 
     private Woodcutting() {
@@ -58,7 +58,7 @@ public final class Woodcutting {
         if (mcMMO.getModManager().isCustomLog(blockState) && mcMMO.getModManager().getBlock(blockState).isDoubleDropEnabled()) {
             Misc.dropItems(Misc.getBlockCenter(blockState), blockState.getBlock().getDrops());
         } else {
-            if (Config.getInstance().getWoodcuttingDoubleDropsEnabled(blockState.getBlockData())) {
+            if (MainConfig.getInstance().getWoodcuttingDoubleDropsEnabled(blockState.getBlockData())) {
                 Misc.dropItems(Misc.getBlockCenter(blockState), blockState.getBlock().getDrops());
             }
         }
@@ -143,7 +143,7 @@ public final class Woodcutting {
 
         for (BlockState blockState : treeFellerBlocks) {
             if (BlockUtils.isLog(blockState)) {
-                durabilityLoss += Config.getInstance().getAbilityToolDamage();
+                durabilityLoss += MainConfig.getInstance().getAbilityToolDamage();
             }
         }
 

+ 5 - 5
core/src/main/java/com/gmail/nossr50/core/skills/subskills/acrobatics/Roll.java

@@ -2,7 +2,7 @@ package com.gmail.nossr50.core.skills.subskills.acrobatics;
 
 import com.gmail.nossr50.config.experience.ExperienceConfig;
 import com.gmail.nossr50.core.config.AdvancedConfig;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.LimitedSizeList;
 import com.gmail.nossr50.core.datatypes.experience.XPGainReason;
@@ -212,7 +212,7 @@ public class Roll extends AcrobaticsSubSkill {
             SoundManager.sendCategorizedSound(player, player.getLocation(), SoundType.ROLL_ACTIVATED, SoundCategory.PLAYERS);
             //player.sendMessage(LocaleLoader.getString("Acrobatics.Roll.Text"));
 
-            //if (!SkillUtils.cooldownExpired((long) mcMMOPlayer.getTeleportATS(), Config.getInstance().getXPAfterTeleportCooldown())) {
+            //if (!SkillUtils.cooldownExpired((long) mcMMOPlayer.getTeleportATS(), MainConfig.getInstance().getXPAfterTeleportCooldown())) {
             if (!isExploiting(player))
                 SkillUtils.applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, true), XPGainReason.PVE);
             //}
@@ -220,7 +220,7 @@ public class Roll extends AcrobaticsSubSkill {
             addFallLocation(player);
             return modifiedDamage;
         } else if (!isFatal(player, damage)) {
-            //if (!SkillUtils.cooldownExpired((long) mcMMOPlayer.getTeleportATS(), Config.getInstance().getXPAfterTeleportCooldown())) {
+            //if (!SkillUtils.cooldownExpired((long) mcMMOPlayer.getTeleportATS(), MainConfig.getInstance().getXPAfterTeleportCooldown())) {
             if (!isExploiting(player))
                 SkillUtils.applyXpGain(mcMMOPlayer, getPrimarySkill(), calculateRollXP(player, damage, false), XPGainReason.PVE);
             //}
@@ -272,7 +272,7 @@ public class Roll extends AcrobaticsSubSkill {
      * @return true if exploits are detected, false otherwise
      */
     private boolean isExploiting(Player player) {
-        if (!Config.getInstance().getAcrobaticsPreventAFK()) {
+        if (!MainConfig.getInstance().getAcrobaticsPreventAFK()) {
             return false;
         }
 
@@ -291,7 +291,7 @@ public class Roll extends AcrobaticsSubSkill {
         return false; //NOT EXPLOITING
 /*
         Location fallLocation = player.getLocation();
-        int maxTries = Config.getInstance().getAcrobaticsAFKMaxTries();
+        int maxTries = MainConfig.getInstance().getAcrobaticsAFKMaxTries();
 
         boolean sameLocation = (lastFallLocation != null && Misc.isNear(lastFallLocation, fallLocation, 2));
 

+ 2 - 2
core/src/main/java/com/gmail/nossr50/core/skills/treasure/Treasure.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.skills.treasure;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import org.bukkit.inventory.ItemStack;
 
 public abstract class Treasure {
@@ -42,7 +42,7 @@ public abstract class Treasure {
 
     public int getDropLevel() {
         //If they are in retro mode all requirements are scaled up by 10
-        if (Config.getInstance().getIsRetroMode())
+        if (MainConfig.getInstance().getIsRetroMode())
             return dropLevel * 10;
 
         return dropLevel;

+ 15 - 15
core/src/main/java/com/gmail/nossr50/core/util/ChimaeraWing.java

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.util;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
 import com.gmail.nossr50.core.datatypes.player.McMMOPlayer;
@@ -38,7 +38,7 @@ public final class ChimaeraWing {
      * @param player Player whose item usage to check
      */
     public static void activationCheck(Player player) {
-        if (!Config.getInstance().getChimaeraEnabled()) {
+        if (!MainConfig.getInstance().getChimaeraEnabled()) {
             return;
         }
 
@@ -61,13 +61,13 @@ public final class ChimaeraWing {
 
         int amount = inHand.getAmount();
 
-        if (amount < Config.getInstance().getChimaeraUseCost()) {
-            NotificationManager.sendPlayerInformation(player, NotificationType.REQUIREMENTS_NOT_MET, "Item.ChimaeraWing.NotEnough", String.valueOf(Config.getInstance().getChimaeraUseCost() - amount), "Item.ChimaeraWing.Name");
+        if (amount < MainConfig.getInstance().getChimaeraUseCost()) {
+            NotificationManager.sendPlayerInformation(player, NotificationType.REQUIREMENTS_NOT_MET, "Item.ChimaeraWing.NotEnough", String.valueOf(MainConfig.getInstance().getChimaeraUseCost() - amount), "Item.ChimaeraWing.Name");
             return;
         }
 
         long lastTeleport = mcMMOPlayer.getChimeraWingLastUse();
-        int cooldown = Config.getInstance().getChimaeraCooldown();
+        int cooldown = MainConfig.getInstance().getChimaeraCooldown();
 
         if (cooldown > 0) {
             int timeRemaining = SkillUtils.calculateTimeLeft(lastTeleport * Misc.TIME_CONVERSION_FACTOR, cooldown, player);
@@ -79,7 +79,7 @@ public final class ChimaeraWing {
         }
 
         long recentlyHurt = mcMMOPlayer.getRecentlyHurt();
-        int hurtCooldown = Config.getInstance().getChimaeraRecentlyHurtCooldown();
+        int hurtCooldown = MainConfig.getInstance().getChimaeraRecentlyHurtCooldown();
 
         if (hurtCooldown > 0) {
             int timeRemaining = SkillUtils.calculateTimeLeft(recentlyHurt * Misc.TIME_CONVERSION_FACTOR, hurtCooldown, player);
@@ -92,9 +92,9 @@ public final class ChimaeraWing {
 
         location = player.getLocation();
 
-        if (Config.getInstance().getChimaeraPreventUseUnderground()) {
+        if (MainConfig.getInstance().getChimaeraPreventUseUnderground()) {
             if (location.getY() < player.getWorld().getHighestBlockYAt(location)) {
-                player.getInventory().setItemInMainHand(new ItemStack(getChimaeraWing(amount - Config.getInstance().getChimaeraUseCost())));
+                player.getInventory().setItemInMainHand(new ItemStack(getChimaeraWing(amount - MainConfig.getInstance().getChimaeraUseCost())));
                 NotificationManager.sendPlayerInformation(player, NotificationType.REQUIREMENTS_NOT_MET, "Item.ChimaeraWing.Fail");
                 player.updateInventory();
                 player.setVelocity(new Vector(0, 0.5D, 0));
@@ -106,7 +106,7 @@ public final class ChimaeraWing {
 
         mcMMOPlayer.actualizeTeleportCommenceLocation(player);
 
-        long warmup = Config.getInstance().getChimaeraWarmup();
+        long warmup = MainConfig.getInstance().getChimaeraWarmup();
 
         if (warmup > 0) {
             NotificationManager.sendPlayerInformation(player, NotificationType.ITEM_MESSAGE, "Teleport.Commencing", String.valueOf(warmup));
@@ -119,7 +119,7 @@ public final class ChimaeraWing {
     public static void chimaeraExecuteTeleport() {
         Player player = mcMMOPlayer.getPlayer();
 
-        if (Config.getInstance().getChimaeraUseBedSpawn() && player.getBedSpawnLocation() != null) {
+        if (MainConfig.getInstance().getChimaeraUseBedSpawn() && player.getBedSpawnLocation() != null) {
             player.teleport(player.getBedSpawnLocation());
         } else {
             Location spawnLocation = player.getWorld().getSpawnLocation();
@@ -130,12 +130,12 @@ public final class ChimaeraWing {
             }
         }
 
-        player.getInventory().setItemInMainHand(new ItemStack(getChimaeraWing(player.getInventory().getItemInMainHand().getAmount() - Config.getInstance().getChimaeraUseCost())));
+        player.getInventory().setItemInMainHand(new ItemStack(getChimaeraWing(player.getInventory().getItemInMainHand().getAmount() - MainConfig.getInstance().getChimaeraUseCost())));
         player.updateInventory();
         mcMMOPlayer.actualizeChimeraWingLastUse();
         mcMMOPlayer.setTeleportCommenceLocation(null);
 
-        if (Config.getInstance().getChimaeraSoundEnabled()) {
+        if (MainConfig.getInstance().getChimaeraSoundEnabled()) {
             SoundManager.sendSound(player, location, SoundType.CHIMAERA_WING);
         }
 
@@ -143,7 +143,7 @@ public final class ChimaeraWing {
     }
 
     public static ItemStack getChimaeraWing(int amount) {
-        ItemStack itemStack = new ItemStack(Config.getInstance().getChimaeraItem(), amount);
+        ItemStack itemStack = new ItemStack(MainConfig.getInstance().getChimaeraItem(), amount);
 
         ItemMeta itemMeta = itemStack.getItemMeta();
         itemMeta.setDisplayName(ChatColor.GOLD + LocaleLoader.getString("Item.ChimaeraWing.Name"));
@@ -158,8 +158,8 @@ public final class ChimaeraWing {
     }
 
     public static ShapelessRecipe getChimaeraWingRecipe() {
-        Material ingredient = Config.getInstance().getChimaeraItem();
-        int amount = Config.getInstance().getChimaeraRecipeCost();
+        Material ingredient = MainConfig.getInstance().getChimaeraItem();
+        int amount = MainConfig.getInstance().getChimaeraRecipeCost();
 
         ShapelessRecipe chimeraWing = new ShapelessRecipe(new NamespacedKey(mcMMO.p, "Chimera"), getChimaeraWing(1));
         chimeraWing.addIngredient(amount, ingredient);

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

@@ -1,6 +1,6 @@
 package com.gmail.nossr50.core.util;
 
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.data.UserManager;
 import com.gmail.nossr50.core.datatypes.interactions.NotificationType;
 import com.gmail.nossr50.core.datatypes.player.PlayerProfile;
@@ -15,8 +15,8 @@ public final class HardcoreManager {
     }
 
     public static void invokeStatPenalty(Player player) {
-        double statLossPercentage = Config.getInstance().getHardcoreDeathStatPenaltyPercentage();
-        int levelThreshold = Config.getInstance().getHardcoreDeathStatPenaltyLevelThreshold();
+        double statLossPercentage = MainConfig.getInstance().getHardcoreDeathStatPenaltyPercentage();
+        int levelThreshold = MainConfig.getInstance().getHardcoreDeathStatPenaltyLevelThreshold();
 
         PlayerProfile playerProfile = UserManager.getPlayer(player).getProfile();
         int totalLevelsLost = 0;
@@ -57,8 +57,8 @@ public final class HardcoreManager {
     }
 
     public static void invokeVampirism(Player killer, Player victim) {
-        double vampirismStatLeechPercentage = Config.getInstance().getHardcoreVampirismStatLeechPercentage();
-        int levelThreshold = Config.getInstance().getHardcoreVampirismLevelThreshold();
+        double vampirismStatLeechPercentage = MainConfig.getInstance().getHardcoreVampirismStatLeechPercentage();
+        int levelThreshold = MainConfig.getInstance().getHardcoreVampirismLevelThreshold();
 
         PlayerProfile killerProfile = UserManager.getPlayer(killer).getProfile();
         PlayerProfile victimProfile = UserManager.getPlayer(victim).getProfile();

+ 2 - 2
core/src/main/java/com/gmail/nossr50/core/util/ItemUtils.java

@@ -1,7 +1,7 @@
 package com.gmail.nossr50.core.util;
 
 import com.gmail.nossr50.config.party.ItemWeightConfig;
-import com.gmail.nossr50.core.config.Config;
+import com.gmail.nossr50.core.config.MainConfig;
 import com.gmail.nossr50.core.locale.LocaleLoader;
 import com.gmail.nossr50.mcMMO;
 import org.bukkit.ChatColor;
@@ -150,7 +150,7 @@ public final class ItemUtils {
      * @return true if the item counts as unarmed, false otherwise
      */
     public static boolean isUnarmed(ItemStack item) {
-        if (Config.getInstance().getUnarmedItemsAsUnarmed()) {
+        if (MainConfig.getInstance().getUnarmedItemsAsUnarmed()) {
             return !isMinecraftTool(item);
         }
 

+ 6 - 6
core/src/main/java/com/gmail/nossr50/core/util/Misc.java

@@ -27,14 +27,14 @@ public final class Misc {
 
     // Sound Pitches & Volumes from CB
 /*    public static final float ANVIL_USE_PITCH  = 0.3F;  // Not in CB directly, I went off the place sound values
-    public static final float ANVIL_USE_VOLUME = 1.0F * Config.getInstance().getMasterVolume();  // Not in CB directly, I went off the place sound values
-    public static final float FIZZ_VOLUME      = 0.5F * Config.getInstance().getMasterVolume();
-    public static final float POP_VOLUME       = 0.2F * Config.getInstance().getMasterVolume();
-    public static final float BAT_VOLUME       = 1.0F * Config.getInstance().getMasterVolume();
+    public static final float ANVIL_USE_VOLUME = 1.0F * MainConfig.getInstance().getMasterVolume();  // Not in CB directly, I went off the place sound values
+    public static final float FIZZ_VOLUME      = 0.5F * MainConfig.getInstance().getMasterVolume();
+    public static final float POP_VOLUME       = 0.2F * MainConfig.getInstance().getMasterVolume();
+    public static final float BAT_VOLUME       = 1.0F * MainConfig.getInstance().getMasterVolume();
     public static final float BAT_PITCH        = 0.6F;
-    public static final float GHAST_VOLUME     = 1.0F * Config.getInstance().getMasterVolume();
+    public static final float GHAST_VOLUME     = 1.0F * MainConfig.getInstance().getMasterVolume();
     public static final float LEVELUP_PITCH    = 0.5F;  // Reduced to differentiate between vanilla level-up
-    public static final float LEVELUP_VOLUME   = 0.75F * Config.getInstance().getMasterVolume(); // Use max volume always*/
+    public static final float LEVELUP_VOLUME   = 0.75F * MainConfig.getInstance().getMasterVolume(); // Use max volume always*/
     private static Random random = new Random();
 
     private Misc() {

部分文件因文件數量過多而無法顯示