2
0
nossr50 7 сар өмнө
parent
commit
4ba85aa444
32 өөрчлөгдсөн 764 нэмэгдсэн , 1521 устгасан
  1. 8 7
      Changelog.txt
  2. 0 324
      src/main/java/com/gmail/nossr50/commands/McImportCommand.java
  3. 1 0
      src/main/java/com/gmail/nossr50/config/experience/ExperienceConfig.java
  4. 0 35
      src/main/java/com/gmail/nossr50/config/mods/ArmorConfigManager.java
  5. 0 35
      src/main/java/com/gmail/nossr50/config/mods/BlockConfigManager.java
  6. 0 93
      src/main/java/com/gmail/nossr50/config/mods/CustomArmorLegacyConfig.java
  7. 0 98
      src/main/java/com/gmail/nossr50/config/mods/CustomBlockLegacyConfig.java
  8. 0 60
      src/main/java/com/gmail/nossr50/config/mods/CustomEntityLegacyConfig.java
  9. 0 107
      src/main/java/com/gmail/nossr50/config/mods/CustomToolLegacyConfig.java
  10. 0 35
      src/main/java/com/gmail/nossr50/config/mods/EntityConfigManager.java
  11. 0 35
      src/main/java/com/gmail/nossr50/config/mods/ToolConfigManager.java
  12. 6 18
      src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java
  13. 10 13
      src/main/java/com/gmail/nossr50/datatypes/skills/SuperAbilityType.java
  14. 83 68
      src/main/java/com/gmail/nossr50/listeners/BlockListener.java
  15. 0 28
      src/main/java/com/gmail/nossr50/mcMMO.java
  16. 4 17
      src/main/java/com/gmail/nossr50/skills/excavation/Excavation.java
  17. 34 16
      src/main/java/com/gmail/nossr50/skills/excavation/ExcavationManager.java
  18. 34 25
      src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java
  19. 0 24
      src/main/java/com/gmail/nossr50/skills/mining/Mining.java
  20. 33 28
      src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java
  21. 8 8
      src/main/java/com/gmail/nossr50/skills/unarmed/UnarmedManager.java
  22. 93 71
      src/main/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingManager.java
  23. 133 25
      src/main/java/com/gmail/nossr50/util/BlockUtils.java
  24. 17 3
      src/main/java/com/gmail/nossr50/util/Misc.java
  25. 275 275
      src/main/java/com/gmail/nossr50/util/ModManager.java
  26. 0 10
      src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java
  27. 1 6
      src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java
  28. 0 9
      src/main/java/com/gmail/nossr50/util/text/ConfigStringUtils.java
  29. 0 6
      src/main/resources/plugin.yml
  30. 3 6
      src/test/java/com/gmail/nossr50/MMOTestEnvironment.java
  31. 12 20
      src/test/java/com/gmail/nossr50/skills/excavation/ExcavationTest.java
  32. 9 16
      src/test/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingTest.java

+ 8 - 7
Changelog.txt

@@ -1,5 +1,6 @@
 Version 2.2.024
-    Significant optimizations to the way mcMMO handles grabbing XP values for blocks
+    Fixed a bug where Giga Drill breaker was giving out more drop chance than intended
+    Large optimizations to most block interactions in mcMMO code
 
 Version 2.2.023
     Compatibility with Minecraft 1.21.3
@@ -2563,7 +2564,7 @@ Version 2.1.38
 Version 2.1.37
     Fixed a potential IndexOutOfBoundsException when informing a disconnected player that their Blast Mining was off CD
     Updated hu_HU locale (thanks andris)
-    
+
 Version 2.1.36
     Updated German locale (Thanks OverCrave)
     Fixed a bug preventing Villagers from giving combat XP
@@ -3551,7 +3552,7 @@ Version 1.3.13
  + Added displaying bonus perks on skill commands
  + Added config option to disable gaining Acrobatics XP from dodging lightning
  + Added missing skill guides. They're finally here!
- + Added more localization 
+ + Added more localization
  + Added a very secret easter egg
  = Fix issue with Sand/Gravel tracking
  = Fix possible NPE when using the PartyAPI to add a player to a party that doesn't exist.
@@ -3648,7 +3649,7 @@ Version 1.3.11
  = Fixed bug where mcMMO could throw NPE errors if trees cut down were from a custom mod and had an id of 17
  = Fixed dupe bug where mcMMO would ignore other block-protection plugins for various abilities
  = Fixed NPE with hardcore mode's vampirism
- 
+
 Version 1.3.10
  + Added 1.3.1 compatibility
  + Added permission node for Iron Grip ability (mcmmo.ability.unarmed.irongrip)
@@ -3910,7 +3911,7 @@ Version 1.3.02
 Version 1.3.01
  = Fixed bug where Tree Feller had no cooldown
  = Fixed bug with activating Skull Splitter after using Tree Feller
- 
+
 Version 1.3.00
  + Added ability to customize drops for Excavation skill (treasures.yml)
  + Added ability to customize drops for Fishing skill (treasures.yml)
@@ -3974,7 +3975,7 @@ Version 1.3.00
  - Removed unused settings from config.yml (HP Regen)
  - Removed Nether Brick from Mining XP Tables
  - Removed Stone Brick from Mining XP Tables
- 
+
 Version 1.2.12
  - Fixed issue that caused terrible MySQL performance and negative XP on levelup (Issue #134)
  - Fixed addxp command taking xprate and skill modifiers into account
@@ -4983,7 +4984,7 @@ Version 0.5.9
 Version 0.5.8
 
     Fixed bug where players inventories would dupe during combat
-    
+
 Version 0.5.7
 
     Fixed monsters instant killing players

+ 0 - 324
src/main/java/com/gmail/nossr50/commands/McImportCommand.java

@@ -1,324 +0,0 @@
-package com.gmail.nossr50.commands;
-
-import com.gmail.nossr50.datatypes.skills.ModConfigType;
-import com.gmail.nossr50.mcMMO;
-import com.gmail.nossr50.util.Misc;
-import org.bukkit.Material;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
-import org.bukkit.command.CommandSender;
-import org.jetbrains.annotations.NotNull;
-
-import java.io.*;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Locale;
-
-public class McImportCommand implements CommandExecutor {
-    int fileAmount;
-
-    @Override
-    public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
-        if (args.length == 0) {
-            importModConfig();
-            return true;
-        }
-        return false;
-    }
-
-    public boolean importModConfig() {
-        String importFilePath = mcMMO.getModDirectory() + File.separator + "import";
-        File importFile = new File(importFilePath, "import.log");
-        mcMMO.p.getLogger().info("Starting import of mod materials...");
-        fileAmount = 0;
-
-        HashMap<ModConfigType, ArrayList<String>> materialNames = new HashMap<>();
-
-        BufferedReader in = null;
-
-        try {
-            // Open the file
-            in = new BufferedReader(new FileReader(importFile));
-
-            String line;
-            String materialName;
-            String modName;
-
-            // While not at the end of the file
-            while ((line = in.readLine()) != null) {
-                String[] split1 = line.split("material ");
-
-                if (split1.length != 2) {
-                    continue;
-                }
-
-                String[] split2 = split1[1].split(" with");
-
-                if (split2.length != 2) {
-                    continue;
-                }
-
-                materialName = split2[0];
-
-                // Categorise each material under a mod config type
-                ModConfigType type = ModConfigType.getModConfigType(materialName);
-
-                if (!materialNames.containsKey(type)) {
-                    materialNames.put(type, new ArrayList<>());
-                }
-
-                materialNames.get(type).add(materialName);
-            }
-        }
-        catch (FileNotFoundException e) {
-            mcMMO.p.getLogger().warning("Could not find " + importFile.getAbsolutePath() + " ! (No such file or directory)");
-            mcMMO.p.getLogger().warning("Copy and paste latest.log to " + importFile.getParentFile().getAbsolutePath() + " and rename it to import.log");
-            return false;
-        }
-        catch (Exception e) {
-            e.printStackTrace();
-            return false;
-        }
-        finally {
-            tryClose(in);
-        }
-
-        createOutput(materialNames);
-
-        mcMMO.p.getLogger().info("Import finished! Created " + fileAmount + " files!");
-        return true;
-    }
-
-    private void createOutput(HashMap<ModConfigType, ArrayList<String>> materialNames) {
-        for (ModConfigType modConfigType : materialNames.keySet()) {
-            HashMap<String, ArrayList<String>> materialNamesType = new HashMap<>();
-
-            for (String materialName : materialNames.get(modConfigType)) {
-                String modName = Misc.getModName(materialName);
-
-                if (!materialNamesType.containsKey(modName)) {
-                    materialNamesType.put(modName, new ArrayList<>());
-                }
-
-                materialNamesType.get(modName).add(materialName);
-            }
-
-            createOutput(modConfigType, materialNamesType);
-        }
-
-    }
-
-    private void tryClose(Closeable c) {
-        if (c == null) {
-            return;
-        }
-        try {
-            c.close();
-        }
-        catch (IOException e) {
-            e.printStackTrace();
-        }
-    }
-
-    private void createOutput(ModConfigType modConfigType, HashMap<String, ArrayList<String>> materialNames) {
-        File outputFilePath = new File(mcMMO.getModDirectory() + File.separator + "output");
-        if (!outputFilePath.exists() && !outputFilePath.mkdirs()) {
-            mcMMO.p.getLogger().severe("Could not create output directory! " + outputFilePath.getAbsolutePath());
-        }
-
-        FileWriter out = null;
-        String type = modConfigType.name().toLowerCase(Locale.ENGLISH);
-
-        for (String modName : materialNames.keySet()) {
-            File outputFile = new File(outputFilePath, modName + "." + type + ".yml");
-            mcMMO.p.getLogger().info("Creating " + outputFile.getName());
-            try {
-                if (outputFile.exists() && !outputFile.delete()) {
-                    mcMMO.p.getLogger().severe("Not able to delete old output file! " + outputFile.getAbsolutePath());
-                }
-
-                if (!outputFile.createNewFile()) {
-                    mcMMO.p.getLogger().severe("Could not create output file! " + outputFile.getAbsolutePath());
-                    continue;
-                }
-
-                StringBuilder writer = new StringBuilder();
-                HashMap<String, ArrayList<String>> configSections = getConfigSections(modConfigType, modName, materialNames);
-
-                if (configSections == null) {
-                    mcMMO.p.getLogger().severe("Something went wrong!! type is " + type);
-                    return;
-                }
-
-                // Write the file, go through each skill and write all the materials
-                for (String configSection : configSections.keySet()) {
-                    if (configSection.equals("UNIDENTIFIED")) {
-                        writer.append("# This isn't a valid config section and all materials in this category need to be").append("\r\n");
-                        writer.append("# copy and pasted to a valid section of this config file.").append("\r\n");
-                    }
-                    writer.append(configSection).append(":").append("\r\n");
-
-                    for (String line : configSections.get(configSection)) {
-                        writer.append(line).append("\r\n");
-                    }
-
-                    writer.append("\r\n");
-                }
-
-                out = new FileWriter(outputFile);
-                out.write(writer.toString());
-            } catch (Exception e) {
-                e.printStackTrace();
-                return;
-            } finally {
-                tryClose(out);
-                fileAmount++;
-            }
-        }
-    }
-
-    private HashMap<String, ArrayList<String>> getConfigSections(ModConfigType type, String modName, HashMap<String, ArrayList<String>> materialNames) {
-        switch (type) {
-            case BLOCKS:
-                return getConfigSectionsBlocks(modName, materialNames);
-            case TOOLS:
-                return getConfigSectionsTools(modName, materialNames);
-            case ARMOR:
-                return getConfigSectionsArmor(modName, materialNames);
-            case UNKNOWN:
-                return getConfigSectionsUnknown(modName, materialNames);
-        }
-
-        return null;
-    }
-
-    private HashMap<String, ArrayList<String>> getConfigSectionsBlocks(String modName, HashMap<String, ArrayList<String>> materialNames) {
-        HashMap<String, ArrayList<String>> configSections = new HashMap<>();
-
-        // Go through all the materials and categorise them under a skill
-        for (String materialName : materialNames.get(modName)) {
-            String skillName = "UNIDENTIFIED";
-            if (materialName.contains("ORE")) {
-                skillName = "Mining";
-            } else if (materialName.contains("LOG") || materialName.contains("LEAVES")) {
-                skillName = "Woodcutting";
-            } else if (materialName.contains("GRASS") || materialName.contains("SHORT_GRASS") || materialName.contains("FLOWER") || materialName.contains("CROP")) {
-                skillName = "Herbalism";
-            } else if (materialName.contains("DIRT") || materialName.contains("SAND")) {
-                skillName = "Excavation";
-            }
-
-            if (!configSections.containsKey(skillName)) {
-                configSections.put(skillName, new ArrayList<>());
-            }
-
-            ArrayList<String> skillContents = configSections.get(skillName);
-            skillContents.add("    " + materialName + "|0:");
-            skillContents.add("    " + "    " + "XP_Gain: 99");
-            skillContents.add("    " + "    " + "Double_Drops_Enabled: true");
-
-            if (skillName.equals("Mining")) {
-                skillContents.add("    " + "    " + "Smelting_XP_Gain: 9");
-            } else if (skillName.equals("Woodcutting")) {
-                skillContents.add("    " + "    " + "Is_Log: " + materialName.contains("LOG"));
-            }
-        }
-
-        return configSections;
-    }
-
-    private HashMap<String, ArrayList<String>> getConfigSectionsTools(String modName, HashMap<String, ArrayList<String>> materialNames) {
-        HashMap<String, ArrayList<String>> configSections = new HashMap<>();
-
-        // Go through all the materials and categorise them under a tool type
-        for (String materialName : materialNames.get(modName)) {
-            String toolType = "UNIDENTIFIED";
-            if (materialName.contains("PICKAXE")) {
-                toolType = "Pickaxes";
-            } else if (materialName.contains("AXE")) {
-                toolType = "Axes";
-            } else if (materialName.contains("BOW")) {
-                toolType = "Bows";
-            } else if (materialName.contains("HOE")) {
-                toolType = "Hoes";
-            } else if (materialName.contains("SHOVEL") || materialName.contains("SPADE")) {
-                toolType = "Shovels";
-            } else if (materialName.contains("SWORD")) {
-                toolType = "Swords";
-            }
-
-            if (!configSections.containsKey(toolType)) {
-                configSections.put(toolType, new ArrayList<>());
-            }
-
-            ArrayList<String> skillContents = configSections.get(toolType);
-            skillContents.add("    " + materialName + ":");
-            skillContents.add("    " + "    " + "XP_Modifier: 1.0");
-            skillContents.add("    " + "    " + "Tier: 1");
-            skillContents.add("    " + "    " + "Ability_Enabled: true");
-            addRepairableLines(materialName, skillContents);
-        }
-
-        return configSections;
-    }
-
-    private HashMap<String, ArrayList<String>> getConfigSectionsArmor(String modName, HashMap<String, ArrayList<String>> materialNames) {
-        HashMap<String, ArrayList<String>> configSections = new HashMap<>();
-
-        // Go through all the materials and categorise them under an armor type
-        for (String materialName : materialNames.get(modName)) {
-            String toolType = "UNIDENTIFIED";
-            if (materialName.contains("BOOT") || materialName.contains("SHOE")) {
-                toolType = "Boots";
-            } else if (materialName.contains("CHESTPLATE") || materialName.contains("CHEST")) {
-                toolType = "Chestplates";
-            } else if (materialName.contains("HELM") || materialName.contains("HAT")) {
-                toolType = "Helmets";
-            } else if (materialName.contains("LEGGINGS") || materialName.contains("LEGS") || materialName.contains("PANTS")) {
-                toolType = "Leggings";
-            }
-
-            if (!configSections.containsKey(toolType)) {
-                configSections.put(toolType, new ArrayList<>());
-            }
-
-            ArrayList<String> skillContents = configSections.get(toolType);
-            skillContents.add("    " + materialName + ":");
-            addRepairableLines(materialName, skillContents);
-        }
-
-        return configSections;
-    }
-
-    private void addRepairableLines(String materialName, ArrayList<String> skillContents) {
-        skillContents.add("    " + "    " + "Repairable: true");
-        skillContents.add("    " + "    " + "Repair_Material: REPAIR_MATERIAL_NAME");
-        skillContents.add("    " + "    " + "Repair_Material_Data_Value: 0");
-        skillContents.add("    " + "    " + "Repair_Material_Quantity: 9");
-        skillContents.add("    " + "    " + "Repair_Material_Pretty_Name: Repair Item Name");
-        skillContents.add("    " + "    " + "Repair_MinimumLevel: 0");
-        skillContents.add("    " + "    " + "Repair_XpMultiplier: 1.0");
-
-        Material material = Material.matchMaterial(materialName);
-        short durability = (material == null) ? (short) 9999 : material.getMaxDurability();
-        skillContents.add("    " + "    " + "Durability: " + ((durability > 0) ? durability : (short) 9999));
-    }
-
-    private HashMap<String, ArrayList<String>> getConfigSectionsUnknown(String modName, HashMap<String, ArrayList<String>> materialNames) {
-        HashMap<String, ArrayList<String>> configSections = new HashMap<>();
-
-        // Go through all the materials and print them
-        for (String materialName : materialNames.get(modName)) {
-            String configKey = "UNIDENTIFIED";
-
-            if (!configSections.containsKey(configKey)) {
-                configSections.put(configKey, new ArrayList<>());
-            }
-
-            ArrayList<String> skillContents = configSections.get(configKey);
-            skillContents.add("    " + materialName);
-        }
-
-        return configSections;
-    }
-}

+ 1 - 0
src/main/java/com/gmail/nossr50/config/experience/ExperienceConfig.java

@@ -376,6 +376,7 @@ public class ExperienceConfig extends BukkitConfig {
         return getXp(skill, material) > 0;
     }
 
+    @Deprecated(forRemoval = true, since = "2.2.024")
     public boolean doesBlockGiveSkillXP(PrimarySkillType skill, BlockData data) {
         return getXp(skill, data) > 0;
     }

+ 0 - 35
src/main/java/com/gmail/nossr50/config/mods/ArmorConfigManager.java

@@ -1,35 +0,0 @@
-package com.gmail.nossr50.config.mods;
-
-import com.gmail.nossr50.mcMMO;
-import com.gmail.nossr50.util.ModManager;
-
-import java.io.File;
-import java.util.regex.Pattern;
-
-public class ArmorConfigManager {
-    public ArmorConfigManager(mcMMO plugin) {
-        Pattern middlePattern = Pattern.compile("armor\\.(?:.+)\\.yml");
-        Pattern startPattern = Pattern.compile("(?:.+)\\.armor\\.yml");
-        File dataFolder = new File(mcMMO.getModDirectory());
-        File vanilla = new File(dataFolder, "armor.default.yml");
-        ModManager modManager = mcMMO.getModManager();
-
-        if (!vanilla.exists()) {
-            plugin.saveResource(vanilla.getParentFile().getName() + File.separator + "armor.default.yml", false);
-        }
-
-        for (String fileName : dataFolder.list()) {
-            if (!middlePattern.matcher(fileName).matches() && !startPattern.matcher(fileName).matches()) {
-                continue;
-            }
-
-            File file = new File(dataFolder, fileName);
-
-            if (file.isDirectory()) {
-                continue;
-            }
-
-            modManager.registerCustomArmor(new CustomArmorLegacyConfig(fileName));
-        }
-    }
-}

+ 0 - 35
src/main/java/com/gmail/nossr50/config/mods/BlockConfigManager.java

@@ -1,35 +0,0 @@
-package com.gmail.nossr50.config.mods;
-
-import com.gmail.nossr50.mcMMO;
-import com.gmail.nossr50.util.ModManager;
-
-import java.io.File;
-import java.util.regex.Pattern;
-
-public class BlockConfigManager {
-    public BlockConfigManager(mcMMO plugin) {
-        Pattern middlePattern = Pattern.compile("blocks\\.(?:.+)\\.yml");
-        Pattern startPattern = Pattern.compile("(?:.+)\\.blocks\\.yml");
-        File dataFolder = new File(mcMMO.getModDirectory());
-        File vanilla = new File(dataFolder, "blocks.default.yml");
-        ModManager modManager = mcMMO.getModManager();
-
-        if (!vanilla.exists()) {
-            plugin.saveResource(vanilla.getParentFile().getName() + File.separator + "blocks.default.yml", false);
-        }
-
-        for (String fileName : dataFolder.list()) {
-            if (!middlePattern.matcher(fileName).matches() && !startPattern.matcher(fileName).matches()) {
-                continue;
-            }
-
-            File file = new File(dataFolder, fileName);
-
-            if (file.isDirectory()) {
-                continue;
-            }
-
-            modManager.registerCustomBlocks(new CustomBlockLegacyConfig(fileName));
-        }
-    }
-}

+ 0 - 93
src/main/java/com/gmail/nossr50/config/mods/CustomArmorLegacyConfig.java

@@ -1,93 +0,0 @@
-package com.gmail.nossr50.config.mods;
-
-import com.gmail.nossr50.config.LegacyConfigLoader;
-import com.gmail.nossr50.datatypes.skills.ItemType;
-import com.gmail.nossr50.datatypes.skills.MaterialType;
-import com.gmail.nossr50.mcMMO;
-import com.gmail.nossr50.skills.repair.repairables.Repairable;
-import com.gmail.nossr50.skills.repair.repairables.RepairableFactory;
-import org.bukkit.Material;
-import org.bukkit.configuration.ConfigurationSection;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-public class CustomArmorLegacyConfig extends LegacyConfigLoader {
-    public List<Material> customBoots = new ArrayList<>();
-    public List<Material> customChestplates = new ArrayList<>();
-    public List<Material> customHelmets = new ArrayList<>();
-    public List<Material> customLeggings = new ArrayList<>();
-    public List<Repairable> repairables = new ArrayList<>();
-    private boolean needsUpdate = false;
-
-    protected CustomArmorLegacyConfig(String fileName) {
-        super("mods", fileName);
-        loadKeys();
-    }
-
-    @Override
-    protected void loadKeys() {
-        loadArmor("Boots", customBoots);
-        loadArmor("Chestplates", customChestplates);
-        loadArmor("Helmets", customHelmets);
-        loadArmor("Leggings", customLeggings);
-
-        if (needsUpdate) {
-            needsUpdate = false;
-            backup();
-        }
-    }
-
-    private void loadArmor(String armorType, List<Material> materialList) {
-        if (needsUpdate) {
-            return;
-        }
-
-        ConfigurationSection armorSection = config.getConfigurationSection(armorType);
-
-        if (armorSection == null) {
-            return;
-        }
-
-        Set<String> armorConfigSet = armorSection.getKeys(false);
-
-        for (String armorName : armorConfigSet) {
-            if (config.contains(armorType + "." + armorName + "." + ".ID")) {
-                needsUpdate = true;
-                return;
-            }
-
-            Material armorMaterial = Material.matchMaterial(armorName);
-
-            if (armorMaterial == null) {
-                mcMMO.p.getLogger().warning("Invalid material name. This item will be skipped. - " + armorName);
-                continue;
-            }
-
-            boolean repairable = config.getBoolean(armorType + "." + armorName + ".Repairable");
-            Material repairMaterial = Material.matchMaterial(config.getString(armorType + "." + armorName + ".Repair_Material", ""));
-
-            if (repairable && (repairMaterial == null)) {
-                mcMMO.p.getLogger().warning("Incomplete repair information. This item will be unrepairable. - " + armorName);
-                repairable = false;
-            }
-
-            if (repairable) {
-                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);
-
-                short durability = armorMaterial.getMaxDurability();
-
-                if (durability == 0) {
-                    durability = (short) config.getInt(armorType + "." + armorName + ".Durability", 70);
-                }
-
-                repairables.add(RepairableFactory.getRepairable(armorMaterial, repairMaterial, repairItemName, repairMinimumLevel, durability, ItemType.ARMOR, MaterialType.OTHER, repairXpMultiplier));
-            }
-
-            materialList.add(armorMaterial);
-        }
-    }
-}

+ 0 - 98
src/main/java/com/gmail/nossr50/config/mods/CustomBlockLegacyConfig.java

@@ -1,98 +0,0 @@
-package com.gmail.nossr50.config.mods;
-
-import com.gmail.nossr50.config.LegacyConfigLoader;
-import com.gmail.nossr50.datatypes.mods.CustomBlock;
-import com.gmail.nossr50.mcMMO;
-import org.bukkit.Material;
-import org.bukkit.configuration.ConfigurationSection;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Set;
-
-public class CustomBlockLegacyConfig extends LegacyConfigLoader {
-    public List<Material> customExcavationBlocks = new ArrayList<>();
-    public List<Material> customHerbalismBlocks = new ArrayList<>();
-    public List<Material> customMiningBlocks = new ArrayList<>();
-    public List<Material> customOres = new ArrayList<>();
-    public List<Material> customLogs = new ArrayList<>();
-    public List<Material> customLeaves = new ArrayList<>();
-    public List<Material> customAbilityBlocks = new ArrayList<>();
-    public HashMap<Material, CustomBlock> customBlockMap = new HashMap<>();
-    private boolean needsUpdate = false;
-
-    protected CustomBlockLegacyConfig(String fileName) {
-        super("mods", fileName);
-        loadKeys();
-    }
-
-    @Override
-    protected void loadKeys() {
-        loadBlocks("Excavation", customExcavationBlocks);
-        loadBlocks("Herbalism", customHerbalismBlocks);
-        loadBlocks("Mining", customMiningBlocks);
-        loadBlocks("Woodcutting", null);
-        loadBlocks("Ability_Blocks", customAbilityBlocks);
-
-        if (needsUpdate) {
-            needsUpdate = false;
-            backup();
-        }
-    }
-
-    private void loadBlocks(String skillType, List<Material> blockList) {
-        if (needsUpdate) {
-            return;
-        }
-
-        ConfigurationSection skillSection = config.getConfigurationSection(skillType);
-
-        if (skillSection == null) {
-            return;
-        }
-
-        Set<String> skillConfigSet = skillSection.getKeys(false);
-
-        for (String blockName : skillConfigSet) {
-            if (config.contains(skillType + "." + blockName + ".Drop_Item")) {
-                needsUpdate = true;
-                return;
-            }
-
-            String[] blockInfo = blockName.split("[|]");
-
-            Material blockMaterial = Material.matchMaterial(blockInfo[0]);
-
-            if (blockMaterial == null) {
-                mcMMO.p.getLogger().warning("Invalid material name. This item will be skipped. - " + blockInfo[0]);
-                continue;
-            }
-
-            if (blockList != null) {
-                blockList.add(blockMaterial);
-            }
-
-            if (skillType.equals("Ability_Blocks")) {
-                continue;
-            }
-
-            int xp = config.getInt(skillType + "." + blockName + ".XP_Gain");
-            int smeltingXp = 0;
-
-            if (skillType.equals("Mining") && config.getBoolean(skillType + "." + blockName + ".Is_Ore")) {
-                customOres.add(blockMaterial);
-                smeltingXp = config.getInt(skillType + "." + blockName + ".Smelting_XP_Gain", xp / 10);
-            } else if (skillType.equals("Woodcutting")) {
-                if (config.getBoolean(skillType + "." + blockName + ".Is_Log")) {
-                    customLogs.add(blockMaterial);
-                } else {
-                    customLeaves.add(blockMaterial);
-                    xp = 0; // Leaves don't grant XP
-                }
-            }
-
-            customBlockMap.put(blockMaterial, new CustomBlock(xp, config.getBoolean(skillType + "." + blockName + ".Double_Drops_Enabled"), smeltingXp));
-        }
-    }
-}

+ 0 - 60
src/main/java/com/gmail/nossr50/config/mods/CustomEntityLegacyConfig.java

@@ -1,60 +0,0 @@
-package com.gmail.nossr50.config.mods;
-
-import com.gmail.nossr50.config.LegacyConfigLoader;
-import com.gmail.nossr50.datatypes.mods.CustomEntity;
-import com.gmail.nossr50.mcMMO;
-import org.bukkit.Material;
-import org.bukkit.inventory.ItemStack;
-
-import java.util.HashMap;
-
-public class CustomEntityLegacyConfig extends LegacyConfigLoader {
-    public HashMap<String, CustomEntity> customEntityClassMap = new HashMap<>();
-    public HashMap<String, CustomEntity> customEntityTypeMap = new HashMap<>();
-
-    protected CustomEntityLegacyConfig(String fileName) {
-        super("mods", fileName);
-        loadKeys();
-    }
-
-    @Override
-    protected void loadKeys() {
-        if (config.getConfigurationSection("Hostile") != null) {
-            backup();
-            return;
-        }
-
-        for (String entityName : config.getKeys(false)) {
-            Class<?> clazz = null;
-            String className = config.getString(entityName + ".Class", "");
-
-            try {
-                clazz = Class.forName(className);
-            } catch (ClassNotFoundException e) {
-                mcMMO.p.getLogger().warning("Invalid class (" + className + ") detected for " + entityName + ".");
-                mcMMO.p.getLogger().warning("This custom entity may not function properly.");
-            }
-
-            String entityTypeName = entityName.replace("_", ".");
-            double xpMultiplier = config.getDouble(entityName + ".XP_Multiplier", 1.0D);
-
-            boolean canBeTamed = config.getBoolean(entityName + ".Tameable");
-            int tamingXp = config.getInt(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");
-
-            if (canBeSummoned && (callOfTheWildMaterial == null || callOfTheWildAmount == 0)) {
-                mcMMO.p.getLogger().warning("Incomplete Call of the Wild information. This entity will not be able to be summoned by Call of the Wild.");
-                canBeSummoned = false;
-            }
-
-            CustomEntity entity = new CustomEntity(xpMultiplier, canBeTamed, tamingXp, canBeSummoned, (canBeSummoned ? new ItemStack(callOfTheWildMaterial) : null), callOfTheWildAmount);
-
-            customEntityTypeMap.put(entityTypeName, entity);
-            customEntityClassMap.put(clazz == null ? null : clazz.getName(), entity);
-        }
-    }
-}

+ 0 - 107
src/main/java/com/gmail/nossr50/config/mods/CustomToolLegacyConfig.java

@@ -1,107 +0,0 @@
-package com.gmail.nossr50.config.mods;
-
-import com.gmail.nossr50.config.LegacyConfigLoader;
-import com.gmail.nossr50.datatypes.mods.CustomTool;
-import com.gmail.nossr50.datatypes.skills.ItemType;
-import com.gmail.nossr50.datatypes.skills.MaterialType;
-import com.gmail.nossr50.mcMMO;
-import com.gmail.nossr50.skills.repair.repairables.Repairable;
-import com.gmail.nossr50.skills.repair.repairables.RepairableFactory;
-import org.bukkit.Material;
-import org.bukkit.configuration.ConfigurationSection;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Set;
-
-public class CustomToolLegacyConfig extends LegacyConfigLoader {
-    public List<Material> customAxes = new ArrayList<>();
-    public List<Material> customBows = new ArrayList<>();
-    public List<Material> customHoes = new ArrayList<>();
-    public List<Material> customPickaxes = new ArrayList<>();
-    public List<Material> customShovels = new ArrayList<>();
-    public List<Material> customSwords = new ArrayList<>();
-    public HashMap<Material, CustomTool> customToolMap = new HashMap<>();
-    public List<Repairable> repairables = new ArrayList<>();
-    private boolean needsUpdate = false;
-
-    protected CustomToolLegacyConfig(String fileName) {
-        super("mods", fileName);
-        loadKeys();
-    }
-
-    @Override
-    protected void loadKeys() {
-        loadTool("Axes", customAxes);
-        loadTool("Bows", customBows);
-        loadTool("Hoes", customHoes);
-        loadTool("Pickaxes", customPickaxes);
-        loadTool("Shovels", customShovels);
-        loadTool("Swords", customSwords);
-
-        if (needsUpdate) {
-            needsUpdate = false;
-            backup();
-        }
-    }
-
-    private void loadTool(String toolType, List<Material> materialList) {
-        if (needsUpdate) {
-            return;
-        }
-
-        ConfigurationSection toolSection = config.getConfigurationSection(toolType);
-
-        if (toolSection == null) {
-            return;
-        }
-
-        Set<String> toolConfigSet = toolSection.getKeys(false);
-
-        for (String toolName : toolConfigSet) {
-            if (config.contains(toolType + "." + toolName + "." + ".ID")) {
-                needsUpdate = true;
-                return;
-            }
-
-            Material toolMaterial = Material.matchMaterial(toolName);
-
-            if (toolMaterial == null) {
-                mcMMO.p.getLogger().warning("Invalid material name. This item will be skipped. - " + toolName);
-                continue;
-            }
-
-            boolean repairable = config.getBoolean(toolType + "." + toolName + ".Repairable");
-            Material repairMaterial = Material.matchMaterial(config.getString(toolType + "." + toolName + ".Repair_Material", ""));
-
-            if (repairable && (repairMaterial == null)) {
-                mcMMO.p.getLogger().warning("Incomplete repair information. This item will be unrepairable. - " + toolName);
-                repairable = false;
-            }
-
-            if (repairable) {
-                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);
-
-                short durability = toolMaterial.getMaxDurability();
-
-                if (durability == 0) {
-                    durability = (short) config.getInt(toolType + "." + toolName + ".Durability", 60);
-                }
-
-                repairables.add(RepairableFactory.getRepairable(toolMaterial, repairMaterial, repairItemName, repairMinimumLevel, 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);
-
-            CustomTool tool = new CustomTool(tier, abilityEnabled, multiplier);
-
-            materialList.add(toolMaterial);
-            customToolMap.put(toolMaterial, tool);
-        }
-    }
-}

+ 0 - 35
src/main/java/com/gmail/nossr50/config/mods/EntityConfigManager.java

@@ -1,35 +0,0 @@
-package com.gmail.nossr50.config.mods;
-
-import com.gmail.nossr50.mcMMO;
-import com.gmail.nossr50.util.ModManager;
-
-import java.io.File;
-import java.util.regex.Pattern;
-
-public class EntityConfigManager {
-    public EntityConfigManager(mcMMO plugin) {
-        Pattern middlePattern = Pattern.compile("entities\\.(?:.+)\\.yml");
-        Pattern startPattern = Pattern.compile("(?:.+)\\.entities\\.yml");
-        File dataFolder = new File(mcMMO.getModDirectory());
-        File vanilla = new File(dataFolder, "entities.default.yml");
-        ModManager modManager = mcMMO.getModManager();
-
-        if (!vanilla.exists()) {
-            plugin.saveResource(vanilla.getParentFile().getName() + File.separator + "entities.default.yml", false);
-        }
-
-        for (String fileName : dataFolder.list()) {
-            if (!middlePattern.matcher(fileName).matches() && !startPattern.matcher(fileName).matches()) {
-                continue;
-            }
-
-            File file = new File(dataFolder, fileName);
-
-            if (file.isDirectory()) {
-                continue;
-            }
-
-            modManager.registerCustomEntities(new CustomEntityLegacyConfig(fileName));
-        }
-    }
-}

+ 0 - 35
src/main/java/com/gmail/nossr50/config/mods/ToolConfigManager.java

@@ -1,35 +0,0 @@
-package com.gmail.nossr50.config.mods;
-
-import com.gmail.nossr50.mcMMO;
-import com.gmail.nossr50.util.ModManager;
-
-import java.io.File;
-import java.util.regex.Pattern;
-
-public class ToolConfigManager {
-    public ToolConfigManager(mcMMO plugin) {
-        Pattern middlePattern = Pattern.compile("tools\\.(?:.+)\\.yml");
-        Pattern startPattern = Pattern.compile("(?:.+)\\.tools\\.yml");
-        File dataFolder = new File(mcMMO.getModDirectory());
-        File vanilla = new File(dataFolder, "tools.default.yml");
-        ModManager modManager = mcMMO.getModManager();
-
-        if (!vanilla.exists()) {
-            plugin.saveResource(vanilla.getParentFile().getName() + File.separator + "tools.default.yml", false);
-        }
-
-        for (String fileName : dataFolder.list()) {
-            if (!middlePattern.matcher(fileName).matches() && !startPattern.matcher(fileName).matches()) {
-                continue;
-            }
-
-            File file = new File(dataFolder, fileName);
-
-            if (file.isDirectory()) {
-                continue;
-            }
-
-            modManager.registerCustomTools(new CustomToolLegacyConfig(fileName));
-        }
-    }
-}

+ 6 - 18
src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java

@@ -10,7 +10,6 @@ import com.gmail.nossr50.datatypes.experience.XPGainReason;
 import com.gmail.nossr50.datatypes.experience.XPGainSource;
 import com.gmail.nossr50.datatypes.interactions.NotificationType;
 import com.gmail.nossr50.datatypes.meta.RuptureTaskMeta;
-import com.gmail.nossr50.datatypes.mods.CustomTool;
 import com.gmail.nossr50.datatypes.party.Party;
 import com.gmail.nossr50.datatypes.party.PartyTeleportRecord;
 import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
@@ -385,13 +384,14 @@ public class McMMOPlayer implements Identified {
     }
 
     /**
-     * Get the mode of an ability.
+     * Get the mode of a superAbilityType.
      *
-     * @param ability The ability to check
-     * @return true if the ability is enabled, false otherwise
+     * @param superAbilityType The superAbilityType to check
+     * @return true if the superAbilityType is enabled, false otherwise
      */
-    public boolean getAbilityMode(SuperAbilityType ability) {
-        return abilityMode.get(ability);
+    public boolean getAbilityMode(@NotNull SuperAbilityType superAbilityType) {
+        requireNonNull(superAbilityType, "superAbilityType cannot be null");
+        return abilityMode.get(superAbilityType);
     }
 
     /**
@@ -864,14 +864,6 @@ public class McMMOPlayer implements Identified {
 
         xp = (float) ((xp * ExperienceConfig.getInstance().getFormulaSkillModifier(primarySkillType)) * ExperienceConfig.getInstance().getExperienceGainsGlobalMultiplier());
 
-        if (mcMMO.p.getGeneralConfig().getToolModsEnabled()) {
-            CustomTool tool = mcMMO.getModManager().getTool(player.getInventory().getItemInMainHand());
-
-            if (tool != null) {
-                xp *= tool.getXpMultiplier();
-            }
-        }
-
         return PerksUtils.handleXpPerks(player, xp, primarySkillType);
     }
 
@@ -985,10 +977,6 @@ public class McMMOPlayer implements Identified {
 
         ItemStack inHand = player.getInventory().getItemInMainHand();
 
-        if (mcMMO.getModManager().isCustomTool(inHand) && !mcMMO.getModManager().getTool(inHand).isAbilityEnabled()) {
-            return;
-        }
-
         if (!getAbilityUse()) {
             return;
         }

+ 10 - 13
src/main/java/com/gmail/nossr50/datatypes/skills/SuperAbilityType.java

@@ -6,8 +6,9 @@ import com.gmail.nossr50.util.BlockUtils;
 import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.text.StringUtils;
 import org.bukkit.Material;
-import org.bukkit.block.BlockState;
+import org.bukkit.block.Block;
 import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
 
 public enum SuperAbilityType {
     EXPLOSIVE_SHOT("Archery.Skills.ExplosiveShot.On",
@@ -218,20 +219,16 @@ public enum SuperAbilityType {
         };
     }
 
-    /**
-     * Check if a block is affected by this ability.
-     *
-     * @param blockState the block to check
-     * @return true if the block is affected by this ability, false otherwise
-     */
-    public boolean blockCheck(BlockState blockState) {
+    public boolean blockCheck(@NotNull Block block) {
         return switch (this) {
             case BERSERK ->
-                    (BlockUtils.affectedByGigaDrillBreaker(blockState) || blockState.getType() == Material.SNOW || mcMMO.getMaterialMapStore().isGlass(blockState.getType()));
-            case GIGA_DRILL_BREAKER -> BlockUtils.affectedByGigaDrillBreaker(blockState);
-            case GREEN_TERRA -> BlockUtils.canMakeMossy(blockState);
-            case SUPER_BREAKER -> BlockUtils.affectedBySuperBreaker(blockState);
-            case TREE_FELLER -> BlockUtils.hasWoodcuttingXP(blockState);
+                    (BlockUtils.affectedByGigaDrillBreaker(block)
+                            || block.getType() == Material.SNOW
+                            || mcMMO.getMaterialMapStore().isGlass(block.getType()));
+            case GIGA_DRILL_BREAKER -> BlockUtils.affectedByGigaDrillBreaker(block);
+            case GREEN_TERRA -> BlockUtils.canMakeMossy(block);
+            case SUPER_BREAKER -> BlockUtils.affectedBySuperBreaker(block);
+            case TREE_FELLER -> BlockUtils.hasWoodcuttingXP(block);
             default -> false;
         };
     }

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

@@ -58,7 +58,7 @@ public class BlockListener implements Listener {
         int tileEntityTolerance = 1;
 
         // beetroot hotfix, potentially other plants may need this fix
-        if (event.getBlockState().getType() == Material.BEETROOTS)
+        if (event.getBlock().getType() == Material.BEETROOTS)
             tileEntityTolerance = 2;
 
         //Track how many "things" are being dropped
@@ -214,7 +214,9 @@ public class BlockListener implements Listener {
         if (ExperienceConfig.getInstance().preventStoneLavaFarming()) {
             BlockState newState = event.getNewState();
 
-            if (newState.getType() != Material.OBSIDIAN && ExperienceConfig.getInstance().doesBlockGiveSkillXP(PrimarySkillType.MINING, newState.getBlockData())) {
+            if (newState.getType() != Material.OBSIDIAN
+                    && ExperienceConfig.getInstance().doesBlockGiveSkillXP(
+                            PrimarySkillType.MINING, newState.getType())) {
                 Block block = newState.getBlock();
                 if (BlockUtils.isWithinWorldBounds(block)) {
                     BlockUtils.setUnnaturalBlock(block);
@@ -317,7 +319,7 @@ public class BlockListener implements Listener {
     @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
     public void onBlockBreak(BlockBreakEvent event) {
         /* WORLD BLACKLIST CHECK */
-        Block block = event.getBlock();
+        final Block block = event.getBlock();
 
         if (event instanceof FakeBlockBreakEvent) {
             return;
@@ -336,16 +338,14 @@ public class BlockListener implements Listener {
             }
         }
 
-        BlockState blockState = block.getState();
-        Location location = blockState.getLocation();
-
-//        if (!BlockUtils.shouldBeWatched(blockState)) {
-//            return;
-//        }
+        final Location location = block.getLocation();
 
         /* ALCHEMY - Cancel any brew in progress for that BrewingStand */
-        if (blockState instanceof BrewingStand && Alchemy.brewingStandMap.containsKey(location)) {
-            Alchemy.brewingStandMap.get(location).cancelBrew();
+        if (block.getType() == Material.BREWING_STAND) {
+            final BlockState blockState = block.getState();
+                if (blockState instanceof BrewingStand && Alchemy.brewingStandMap.containsKey(location)) {
+                    Alchemy.brewingStandMap.get(location).cancelBrew();
+                }
         }
 
         Player player = event.getPlayer();
@@ -368,7 +368,7 @@ public class BlockListener implements Listener {
         ItemStack heldItem = player.getInventory().getItemInMainHand();
 
         /* HERBALISM */
-        if (BlockUtils.affectedByGreenTerra(blockState)) {
+        if (BlockUtils.affectedByGreenTerra(block)) {
             HerbalismManager herbalismManager = mcMMOPlayer.getHerbalismManager();
 
             /* Green Terra */
@@ -391,39 +391,40 @@ public class BlockListener implements Listener {
         }
 
         /* MINING */
-        else if (BlockUtils.affectedBySuperBreaker(blockState)
+        else if (BlockUtils.affectedBySuperBreaker(block)
                 && (ItemUtils.isPickaxe(heldItem) || ItemUtils.isHoe(heldItem))
                 && mcMMO.p.getSkillTools().doesPlayerHaveSkillPermission(player, PrimarySkillType.MINING)
-                && !mcMMO.getUserBlockTracker().isIneligible(blockState)) {
+                && !mcMMO.getUserBlockTracker().isIneligible(block)) {
             MiningManager miningManager = mcMMOPlayer.getMiningManager();
-            miningManager.miningBlockCheck(blockState);
+            miningManager.miningBlockCheck(block);
         }
 
         /* WOOD CUTTING */
-        else if (BlockUtils.hasWoodcuttingXP(blockState) && ItemUtils.isAxe(heldItem)
-                && mcMMO.p.getSkillTools().doesPlayerHaveSkillPermission(player, PrimarySkillType.WOODCUTTING) && !mcMMO.getUserBlockTracker().isIneligible(blockState)) {
+        else if (BlockUtils.hasWoodcuttingXP(block) && ItemUtils.isAxe(heldItem)
+                && mcMMO.p.getSkillTools().doesPlayerHaveSkillPermission(player, PrimarySkillType.WOODCUTTING)
+                && !mcMMO.getUserBlockTracker().isIneligible(block)) {
             WoodcuttingManager woodcuttingManager = mcMMOPlayer.getWoodcuttingManager();
             if (woodcuttingManager.canUseTreeFeller(heldItem)) {
-                woodcuttingManager.processTreeFeller(blockState);
+                woodcuttingManager.processTreeFeller(block);
             } else {
                 //Check for XP
-                woodcuttingManager.processWoodcuttingBlockXP(blockState);
+                woodcuttingManager.processWoodcuttingBlockXP(block);
 
                 //Check for bonus drops
-                woodcuttingManager.processBonusDropCheck(blockState);
+                woodcuttingManager.processBonusDropCheck(block);
             }
         }
 
         /* EXCAVATION */
-        else if (BlockUtils.affectedByGigaDrillBreaker(blockState)
+        else if (BlockUtils.affectedByGigaDrillBreaker(block)
                 && ItemUtils.isShovel(heldItem)
                 && mcMMO.p.getSkillTools().doesPlayerHaveSkillPermission(player, PrimarySkillType.EXCAVATION)
-                && !mcMMO.getUserBlockTracker().isIneligible(blockState)) {
-            ExcavationManager excavationManager = mcMMOPlayer.getExcavationManager();
-            excavationManager.excavationBlockCheck(blockState);
+                && !mcMMO.getUserBlockTracker().isIneligible(block)) {
+            final ExcavationManager excavationManager = mcMMOPlayer.getExcavationManager();
+            excavationManager.excavationBlockCheck(block);
 
             if (mcMMOPlayer.getAbilityMode(SuperAbilityType.GIGA_DRILL_BREAKER)) {
-                excavationManager.gigaDrillBreaker(blockState);
+                excavationManager.gigaDrillBreaker(block);
             }
         }
 
@@ -498,8 +499,8 @@ public class BlockListener implements Listener {
      */
     @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
     public void onBlockDamage(BlockDamageEvent event) {
-        Player player = event.getPlayer();
-        BlockState blockState = event.getBlock().getState();
+        final Player player = event.getPlayer();
+        final Block block = event.getBlock();
 
         /* WORLD BLACKLIST CHECK */
         if (WorldBlacklist.isWorldBlacklisted(event.getBlock().getWorld()))
@@ -530,31 +531,35 @@ public class BlockListener implements Listener {
          *
          * We check permissions here before processing activation.
          */
-        if (BlockUtils.canActivateAbilities(blockState)) {
+        if (BlockUtils.canActivateAbilities(block)) {
             ItemStack heldItem = player.getInventory().getItemInMainHand();
 
-            if (mcMMOPlayer.getToolPreparationMode(ToolType.HOE) && ItemUtils.isHoe(heldItem) && (BlockUtils.affectedByGreenTerra(blockState) || BlockUtils.canMakeMossy(blockState)) && Permissions.greenTerra(player)) {
+            if (mcMMOPlayer.getToolPreparationMode(ToolType.HOE)
+                    && ItemUtils.isHoe(heldItem)
+                    && (BlockUtils.affectedByGreenTerra(block)
+                    || BlockUtils.canMakeMossy(block))
+                    && Permissions.greenTerra(player)) {
                 mcMMOPlayer.checkAbilityActivation(PrimarySkillType.HERBALISM);
-            } else if (mcMMOPlayer.getToolPreparationMode(ToolType.AXE) && ItemUtils.isAxe(heldItem) && BlockUtils.hasWoodcuttingXP(blockState) && Permissions.treeFeller(player)) {
+            } else if (mcMMOPlayer.getToolPreparationMode(ToolType.AXE) && ItemUtils.isAxe(heldItem) && BlockUtils.hasWoodcuttingXP(block) && Permissions.treeFeller(player)) {
                 mcMMOPlayer.checkAbilityActivation(PrimarySkillType.WOODCUTTING);
-            } else if (mcMMOPlayer.getToolPreparationMode(ToolType.PICKAXE) && ItemUtils.isPickaxe(heldItem) && BlockUtils.affectedBySuperBreaker(blockState) && Permissions.superBreaker(player)) {
+            } else if (mcMMOPlayer.getToolPreparationMode(ToolType.PICKAXE) && ItemUtils.isPickaxe(heldItem) && BlockUtils.affectedBySuperBreaker(block) && Permissions.superBreaker(player)) {
                 mcMMOPlayer.checkAbilityActivation(PrimarySkillType.MINING);
-            } else if (mcMMOPlayer.getToolPreparationMode(ToolType.SHOVEL) && ItemUtils.isShovel(heldItem) && BlockUtils.affectedByGigaDrillBreaker(blockState) && Permissions.gigaDrillBreaker(player)) {
+            } else if (mcMMOPlayer.getToolPreparationMode(ToolType.SHOVEL) && ItemUtils.isShovel(heldItem) && BlockUtils.affectedByGigaDrillBreaker(block) && Permissions.gigaDrillBreaker(player)) {
                 mcMMOPlayer.checkAbilityActivation(PrimarySkillType.EXCAVATION);
-            } else if (mcMMOPlayer.getToolPreparationMode(ToolType.FISTS) && heldItem.getType() == Material.AIR && (BlockUtils.affectedByGigaDrillBreaker(blockState)
-                    || mcMMO.getMaterialMapStore().isGlass(blockState.getType())
-                    || blockState.getType() == Material.SNOW
-                    || BlockUtils.affectedByBlockCracker(blockState) && Permissions.berserk(player))) {
+            } else if (mcMMOPlayer.getToolPreparationMode(ToolType.FISTS) && heldItem.getType() == Material.AIR && (BlockUtils.affectedByGigaDrillBreaker(block)
+                    || mcMMO.getMaterialMapStore().isGlass(block.getType())
+                    || block.getType() == Material.SNOW
+                    || BlockUtils.affectedByBlockCracker(block) && Permissions.berserk(player))) {
                 mcMMOPlayer.checkAbilityActivation(PrimarySkillType.UNARMED);
 
                 if (mcMMOPlayer.getAbilityMode(SuperAbilityType.BERSERK)) {
-                    if (SuperAbilityType.BERSERK.blockCheck(blockState) && EventUtils.simulateBlockBreak(blockState.getBlock(), player)) {
+                    if (SuperAbilityType.BERSERK.blockCheck(block) && EventUtils.simulateBlockBreak(block, player)) {
                         event.setInstaBreak(true);
 
-                        if (blockState.getType().getKey().getKey().contains("glass")) {
-                            SoundManager.worldSendSound(player.getWorld(), blockState.getLocation(), SoundType.GLASS);
+                        if (block.getType().getKey().getKey().contains("glass")) {
+                            SoundManager.worldSendSound(player.getWorld(), block.getLocation(), SoundType.GLASS);
                         } else {
-                            SoundManager.sendSound(player, blockState.getLocation(), SoundType.POP);
+                            SoundManager.sendSound(player, block.getLocation(), SoundType.POP);
                         }
                     }
                 }
@@ -566,8 +571,8 @@ 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.hasWoodcuttingXP(blockState) && mcMMO.p.getGeneralConfig().getTreeFellerSoundsEnabled()) {
-            SoundManager.sendSound(player, blockState.getLocation(), SoundType.FIZZ);
+        if (mcMMOPlayer.getAbilityMode(SuperAbilityType.TREE_FELLER) && BlockUtils.hasWoodcuttingXP(block) && mcMMO.p.getGeneralConfig().getTreeFellerSoundsEnabled()) {
+            SoundManager.sendSound(player, block.getLocation(), SoundType.FIZZ);
         }
     }
 
@@ -598,41 +603,38 @@ public class BlockListener implements Listener {
             return;
         }
 
-        McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
+        final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
 
-        //Profile not loaded
-        if (UserManager.getPlayer(player) == null) {
+        if (mcMMOPlayer == null) {
             return;
         }
 
         ItemStack heldItem = player.getInventory().getItemInMainHand();
         Block block = event.getBlock();
-        BlockState blockState = block.getState();
 
         /*
          * ABILITY TRIGGER CHECKS
          *
          * We don't need to check permissions here because they've already been checked for the ability to even activate.
          */
-        if (mcMMOPlayer.getAbilityMode(SuperAbilityType.GREEN_TERRA) && BlockUtils.canMakeMossy(blockState)) {
-            if (mcMMOPlayer.getHerbalismManager().processGreenTerraBlockConversion(blockState)) {
-                blockState.update(true);
-            }
+        if (mcMMOPlayer.getAbilityMode(SuperAbilityType.GREEN_TERRA) && BlockUtils.canMakeMossy(block)) {
+            mcMMOPlayer.getHerbalismManager().processGreenTerraBlockConversion(block);
         } else if (mcMMOPlayer.getAbilityMode(SuperAbilityType.BERSERK) && (heldItem.getType() == Material.AIR || mcMMO.p.getGeneralConfig().getUnarmedItemsAsUnarmed())) {
-            if (mcMMOPlayer.getUnarmedManager().canUseBlockCracker() && BlockUtils.affectedByBlockCracker(blockState)) {
-                if (EventUtils.simulateBlockBreak(block, player) && mcMMOPlayer.getUnarmedManager().blockCrackerCheck(blockState)) {
-                    blockState.update();
+            if (mcMMOPlayer.getUnarmedManager().canUseBlockCracker() && BlockUtils.affectedByBlockCracker(block)) {
+                if (EventUtils.simulateBlockBreak(block, player)) {
+                    mcMMOPlayer.getUnarmedManager().blockCrackerCheck(block.getState());
                 }
-            } else if (!event.getInstaBreak() && SuperAbilityType.BERSERK.blockCheck(blockState) && EventUtils.simulateBlockBreak(block, player)) {
+            } else if (!event.getInstaBreak() && SuperAbilityType.BERSERK.blockCheck(block)
+                    && EventUtils.simulateBlockBreak(block, player)) {
                 event.setInstaBreak(true);
 
-                if (blockState.getType().getKey().getKey().contains("glass")) {
+                if (block.getType().getKey().getKey().contains("glass")) {
                     SoundManager.worldSendSound(player.getWorld(), block.getLocation(), SoundType.GLASS);
                 } else {
                     SoundManager.sendSound(player, block.getLocation(), SoundType.POP);
                 }
             }
-        } else if (mcMMOPlayer.getWoodcuttingManager().canUseLeafBlower(heldItem) && BlockUtils.isNonWoodPartOfTree(blockState) && EventUtils.simulateBlockBreak(block, player)) {
+        } else if (mcMMOPlayer.getWoodcuttingManager().canUseLeafBlower(heldItem) && BlockUtils.isNonWoodPartOfTree(block) && EventUtils.simulateBlockBreak(block, player)) {
             event.setInstaBreak(true);
             SoundManager.sendSound(player, block.getLocation(), SoundType.POP);
         }
@@ -648,29 +650,30 @@ public class BlockListener implements Listener {
             return;
         }
 
-        BlockState blockState = event.getBlock().getState();
-
         ItemStack heldItem = player.getInventory().getItemInMainHand();
 
-        cleanupAbilityTools(player, mcMMOPlayer, blockState, heldItem);
+        cleanupAbilityTools(mcMMOPlayer, event.getBlock(), heldItem);
 
-        debugStickDump(player, blockState);
+        debugStickDump(player, event.getBlock());
     }
 
     //TODO: Rewrite this
     //TODO: Convert into locale strings
-    private void debugStickDump(Player player, BlockState blockState) {
+    private void debugStickDump(Player player, Block block) {
         //Profile not loaded
-        if (UserManager.getPlayer(player) == null) {
+        final McMMOPlayer mmoPlayer = UserManager.getPlayer(player);
+        if (mmoPlayer == null) {
             return;
         }
 
-        if (UserManager.getPlayer(player).isDebugMode()) {
+        final BlockState blockState = block.getState();
+
+        if (mmoPlayer.isDebugMode()) {
             if (mcMMO.getUserBlockTracker().isIneligible(blockState))
                 player.sendMessage("[mcMMO DEBUG] This block is not natural and does not reward treasures/XP");
             else {
                 player.sendMessage("[mcMMO DEBUG] This block is considered natural by mcMMO");
-                UserManager.getPlayer(player).getExcavationManager().printExcavationDebug(player, blockState);
+                mmoPlayer.getExcavationManager().printExcavationDebug(player, block);
             }
 
             if (WorldGuardUtils.isWorldGuardLoaded()) {
@@ -704,14 +707,26 @@ public class BlockListener implements Listener {
         }
     }
 
-    private void cleanupAbilityTools(Player player, McMMOPlayer mcMMOPlayer, BlockState blockState, ItemStack heldItem) {
+    /**
+     * Clean up ability tools after a block break event.
+     * @param mmoPlayer The player
+     * @param block The block
+     * @param heldItem The item in the player's hand
+     */
+    private void cleanupAbilityTools(McMMOPlayer mmoPlayer, Block block, ItemStack heldItem) {
         if (HiddenConfig.getInstance().useEnchantmentBuffs()) {
-            if ((ItemUtils.isPickaxe(heldItem) && !mcMMOPlayer.getAbilityMode(SuperAbilityType.SUPER_BREAKER)) || (ItemUtils.isShovel(heldItem) && !mcMMOPlayer.getAbilityMode(SuperAbilityType.GIGA_DRILL_BREAKER))) {
+            if ((ItemUtils.isPickaxe(heldItem)
+                    && !mmoPlayer.getAbilityMode(SuperAbilityType.SUPER_BREAKER))
+                    || (ItemUtils.isShovel(heldItem)
+                    && !mmoPlayer.getAbilityMode(SuperAbilityType.GIGA_DRILL_BREAKER))) {
                 SkillUtils.removeAbilityBuff(heldItem);
             }
         } else {
-            if ((mcMMOPlayer.getAbilityMode(SuperAbilityType.SUPER_BREAKER) && !BlockUtils.affectedBySuperBreaker(blockState)) || (mcMMOPlayer.getAbilityMode(SuperAbilityType.GIGA_DRILL_BREAKER) && !BlockUtils.affectedByGigaDrillBreaker(blockState))) {
-                SkillUtils.removeAbilityBoostsFromInventory(player);
+            if ((mmoPlayer.getAbilityMode(SuperAbilityType.SUPER_BREAKER)
+                    && !BlockUtils.affectedBySuperBreaker(block))
+                    || (mmoPlayer.getAbilityMode(SuperAbilityType.GIGA_DRILL_BREAKER)
+                    && !BlockUtils.affectedByGigaDrillBreaker(block))) {
+                SkillUtils.removeAbilityBoostsFromInventory(mmoPlayer.getPlayer());
             }
         }
     }

+ 0 - 28
src/main/java/com/gmail/nossr50/mcMMO.java

@@ -4,10 +4,6 @@ import com.gmail.nossr50.chat.ChatManager;
 import com.gmail.nossr50.commands.CommandManager;
 import com.gmail.nossr50.config.*;
 import com.gmail.nossr50.config.experience.ExperienceConfig;
-import com.gmail.nossr50.config.mods.ArmorConfigManager;
-import com.gmail.nossr50.config.mods.BlockConfigManager;
-import com.gmail.nossr50.config.mods.EntityConfigManager;
-import com.gmail.nossr50.config.mods.ToolConfigManager;
 import com.gmail.nossr50.config.party.PartyConfig;
 import com.gmail.nossr50.config.skills.alchemy.PotionConfig;
 import com.gmail.nossr50.config.skills.repair.RepairConfigManager;
@@ -82,7 +78,6 @@ public class mcMMO extends JavaPlugin {
     private static ChunkManager chunkManager;
     private static RepairableManager repairableManager;
     private static SalvageableManager salvageableManager;
-    private static ModManager modManager;
     private static DatabaseManager databaseManager;
     private static FormulaManager formulaManager;
     private static UpgradeManager upgradeManager;
@@ -188,8 +183,6 @@ public class mcMMO extends JavaPlugin {
 
             upgradeManager = new UpgradeManager();
 
-            modManager = new ModManager();
-
             // Init Material Maps
             materialMapStore = new MaterialMapStore();
             // Init compatibility mappers
@@ -474,10 +467,6 @@ public class mcMMO extends JavaPlugin {
         return databaseManager;
     }
 
-    public static ModManager getModManager() {
-        return modManager;
-    }
-
     public static UpgradeManager getUpgradeManager() {
         return upgradeManager;
     }
@@ -576,25 +565,8 @@ public class mcMMO extends JavaPlugin {
 
         List<Repairable> repairables = new ArrayList<>();
 
-        if (generalConfig.getToolModsEnabled()) {
-            new ToolConfigManager(this);
-        }
-
-        if (generalConfig.getArmorModsEnabled()) {
-            new ArmorConfigManager(this);
-        }
-
-        if (generalConfig.getBlockModsEnabled()) {
-            new BlockConfigManager(this);
-        }
-
-        if (generalConfig.getEntityModsEnabled()) {
-            new EntityConfigManager(this);
-        }
-
         // Load repair configs, make manager, and register them at this time
         repairables.addAll(new RepairConfigManager(this).getLoadedRepairables());
-        repairables.addAll(modManager.getLoadedRepairables());
         repairableManager = new SimpleRepairableManager(repairables.size());
         repairableManager.registerRepairables(repairables);
 

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

@@ -1,11 +1,8 @@
 package com.gmail.nossr50.skills.excavation;
 
-import com.gmail.nossr50.config.experience.ExperienceConfig;
 import com.gmail.nossr50.config.treasure.TreasureConfig;
-import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
 import com.gmail.nossr50.datatypes.treasure.ExcavationTreasure;
-import com.gmail.nossr50.mcMMO;
-import org.bukkit.block.BlockState;
+import org.bukkit.block.Block;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -16,23 +13,13 @@ public class Excavation {
     /**
      * Get the list of possible {@link ExcavationTreasure|ExcavationTreasures} obtained from a given block.
      *
-     * @param blockState The {@link BlockState} of the block to check.
+     * @param block The {@link Block} to check for treasures
      * @return the list of treasures that could be found
      */
-    protected static List<ExcavationTreasure> getTreasures(BlockState blockState) {
-        String friendly = getMaterialConfigString(blockState.getBlockData().getMaterial());
+    protected static List<ExcavationTreasure> getTreasures(Block block) {
+        String friendly = getMaterialConfigString(block.getBlockData().getMaterial());
         if (TreasureConfig.getInstance().excavationMap.containsKey(friendly))
             return TreasureConfig.getInstance().excavationMap.get(friendly);
         return new ArrayList<>();
     }
-
-    protected static int getBlockXP(BlockState blockState) {
-        int xp = ExperienceConfig.getInstance().getXp(PrimarySkillType.EXCAVATION, blockState.getType());
-
-        if (xp == 0 && mcMMO.getModManager().isCustomExcavationBlock(blockState)) {
-            xp = mcMMO.getModManager().getBlock(blockState).getXpGain();
-        }
-
-        return xp;
-    }
 }

+ 34 - 16
src/main/java/com/gmail/nossr50/skills/excavation/ExcavationManager.java

@@ -1,6 +1,7 @@
 package com.gmail.nossr50.skills.excavation;
 
 import com.gmail.nossr50.api.ItemSpawnReason;
+import com.gmail.nossr50.config.experience.ExperienceConfig;
 import com.gmail.nossr50.datatypes.experience.XPGainReason;
 import com.gmail.nossr50.datatypes.experience.XPGainSource;
 import com.gmail.nossr50.datatypes.player.McMMOPlayer;
@@ -16,6 +17,7 @@ import com.gmail.nossr50.util.random.ProbabilityUtil;
 import com.gmail.nossr50.util.skills.RankUtils;
 import com.gmail.nossr50.util.skills.SkillUtils;
 import org.bukkit.Location;
+import org.bukkit.block.Block;
 import org.bukkit.block.BlockState;
 import org.bukkit.entity.Player;
 import org.jetbrains.annotations.NotNull;
@@ -35,21 +37,27 @@ public class ExcavationManager extends SkillManager {
      *
      * @param blockState The {@link BlockState} to check ability activation for
      */
+    @Deprecated(forRemoval = true, since = "2.2.024")
     public void excavationBlockCheck(BlockState blockState) {
-        int xp = Excavation.getBlockXP(blockState);
-        requireNonNull(blockState, "excavationBlockCheck: blockState cannot be null");
+        excavationBlockCheck(blockState.getBlock());
+    }
+
+
+    public void excavationBlockCheck(Block block) {
+        int xp = ExperienceConfig.getInstance().getXp(PrimarySkillType.EXCAVATION, block.getType());
+        requireNonNull(block, "excavationBlockCheck: block cannot be null");
         if (Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.EXCAVATION_ARCHAEOLOGY)) {
-            List<ExcavationTreasure> treasures = getTreasures(blockState);
+            List<ExcavationTreasure> treasures = getTreasures(block);
 
             if (!treasures.isEmpty()) {
                 int skillLevel = getSkillLevel();
-                Location location = Misc.getBlockCenter(blockState);
+                Location location = Misc.getBlockCenter(block);
 
                 for (ExcavationTreasure treasure : treasures) {
                     if (skillLevel >= treasure.getDropLevel()
                             && ProbabilityUtil.isStaticSkillRNGSuccessful(
-                                    PrimarySkillType.EXCAVATION, mmoPlayer, treasure.getDropProbability())) {
-                        processExcavationBonusesOnBlock(blockState, treasure, location);
+                            PrimarySkillType.EXCAVATION, mmoPlayer, treasure.getDropProbability())) {
+                        processExcavationBonusesOnBlock(treasure, location);
                     }
                 }
             }
@@ -58,14 +66,24 @@ public class ExcavationManager extends SkillManager {
         applyXpGain(xp, XPGainReason.PVE, XPGainSource.SELF);
     }
 
-    @VisibleForTesting
+    @Deprecated(forRemoval = true, since = "2.2.024")
     public List<ExcavationTreasure> getTreasures(@NotNull BlockState blockState) {
         requireNonNull(blockState, "blockState cannot be null");
-        return Excavation.getTreasures(blockState);
+        return getTreasures(blockState.getBlock());
+    }
+
+    public List<ExcavationTreasure> getTreasures(@NotNull Block block) {
+        requireNonNull(block, "block cannot be null");
+        return Excavation.getTreasures(block);
     }
 
     @VisibleForTesting
-    public void processExcavationBonusesOnBlock(BlockState blockState, ExcavationTreasure treasure, Location location) {
+    @Deprecated(forRemoval = true, since = "2.2.024")
+    public void processExcavationBonusesOnBlock(BlockState ignored, ExcavationTreasure treasure, Location location) {
+        processExcavationBonusesOnBlock(treasure, location);
+    }
+
+    public void processExcavationBonusesOnBlock(ExcavationTreasure treasure, Location location) {
         //Spawn Vanilla XP orbs if a dice roll succeeds
         if (ProbabilityUtil.isStaticSkillRNGSuccessful(
                 PrimarySkillType.EXCAVATION, mmoPlayer, getArchaelogyExperienceOrbChance())) {
@@ -92,9 +110,9 @@ public class ExcavationManager extends SkillManager {
         return RankUtils.getRank(getPlayer(), SubSkillType.EXCAVATION_ARCHAEOLOGY);
     }
 
-    public void printExcavationDebug(Player player, BlockState blockState) {
+    public void printExcavationDebug(Player player, Block block) {
         if (Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.EXCAVATION_ARCHAEOLOGY)) {
-            List<ExcavationTreasure> treasures = Excavation.getTreasures(blockState);
+            List<ExcavationTreasure> treasures = Excavation.getTreasures(block);
 
             if (!treasures.isEmpty()) {
                 for (ExcavationTreasure treasure : treasures) {
@@ -113,12 +131,12 @@ public class ExcavationManager extends SkillManager {
     /**
      * Process the Giga Drill Breaker ability.
      *
-     * @param blockState The {@link BlockState} to check ability activation for
+     * @param block The {@link Block} to check ability activation for
      */
-    public void gigaDrillBreaker(BlockState blockState) {
-        excavationBlockCheck(blockState);
-        excavationBlockCheck(blockState);
+    public void gigaDrillBreaker(Block block) {
+        excavationBlockCheck(block);
 
-        SkillUtils.handleDurabilityChange(getPlayer().getInventory().getItemInMainHand(), mcMMO.p.getGeneralConfig().getAbilityToolDamage());
+        SkillUtils.handleDurabilityChange(getPlayer().getInventory().getItemInMainHand(),
+                mcMMO.p.getGeneralConfig().getAbilityToolDamage());
     }
 }

+ 34 - 25
src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java

@@ -184,31 +184,36 @@ public class HerbalismManager extends SkillManager {
         return SkillUtils.handleFoodSkills(getPlayer(), eventFoodLevel, SubSkillType.HERBALISM_FARMERS_DIET);
     }
 
-    /**
-     * Process the Green Terra ability.
-     *
-     * @param blockState The {@link BlockState} to check ability activation for
-     * @return true if the ability was successful, false otherwise
-     */
-    public boolean processGreenTerraBlockConversion(BlockState blockState) {
-        Player player = getPlayer();
+    public void processGreenTerraBlockConversion(BlockState blockState) {
+        final Player player = getPlayer();
 
         if (!Permissions.greenThumbBlock(player, blockState.getType())) {
-            return false;
+            return;
         }
 
         PlayerInventory playerInventory = player.getInventory();
         ItemStack seed = new ItemStack(Material.WHEAT_SEEDS);
 
         if (!playerInventory.containsAtLeast(seed, 1)) {
-            NotificationManager.sendPlayerInformation(player, NotificationType.REQUIREMENTS_NOT_MET, "Herbalism.Ability.GTe.NeedMore");
-            return false;
+            NotificationManager.sendPlayerInformation(player,
+                    NotificationType.REQUIREMENTS_NOT_MET, "Herbalism.Ability.GTe.NeedMore");
+            return;
         }
 
         playerInventory.removeItem(seed);
-        player.updateInventory(); // Needed until replacement available
+        // player.updateInventory();
 
-        return Herbalism.convertGreenTerraBlocks(blockState);
+        Herbalism.convertGreenTerraBlocks(blockState);
+        blockState.update(true);
+    }
+
+    /**
+     * Process the Green Terra ability.
+     *
+     * @param block The {@link Block} to check ability activation for
+     */
+    public void processGreenTerraBlockConversion(Block block) {
+        processGreenTerraBlockConversion(block.getState());
     }
 
     /**
@@ -363,13 +368,13 @@ public class HerbalismManager extends SkillManager {
                 if (plantData instanceof Ageable ageable) {
 
                     if (isAgeableMature(ageable) || isBizarreAgeable(plantData)) {
-                        if (checkDoubleDrop(brokenPlantState)) {
-                            markForBonusDrops(brokenPlantState);
+                        if (checkDoubleDrop(brokenPlant)) {
+                            markForBonusDrops(brokenPlant);
                         }
                     }
-                } else if (checkDoubleDrop(brokenPlantState)) {
+                } else if (checkDoubleDrop(brokenPlant)) {
                     //Add metadata to mark this block for double or triple drops
-                    markForBonusDrops(brokenPlantState);
+                    markForBonusDrops(brokenPlant);
                 }
             } else {
 
@@ -379,10 +384,10 @@ public class HerbalismManager extends SkillManager {
                  *
                  */
 
-                //If it's a Crop we need to reward XP when its fully grown
+                //If it's a crop, we need to reward XP when its fully grown
                 if (isAgeableAndFullyMature(plantData) && !isBizarreAgeable(plantData)) {
                     //Add metadata to mark this block for double or triple drops
-                    markForBonusDrops(brokenPlantState);
+                    markForBonusDrops(brokenPlant);
                 }
             }
         }
@@ -405,10 +410,14 @@ public class HerbalismManager extends SkillManager {
         return false;
     }
 
-    public void markForBonusDrops(BlockState brokenPlantState) {
+    /**
+     * Mark a block for bonus drops.
+     * @param block the block to mark
+     */
+    public void markForBonusDrops(Block block) {
         //Add metadata to mark this block for double or triple drops
         boolean awardTriple = mmoPlayer.getAbilityMode(SuperAbilityType.GREEN_TERRA);
-        BlockUtils.markDropsAsBonus(brokenPlantState, awardTriple);
+        BlockUtils.markDropsAsBonus(block, awardTriple);
     }
 
     /**
@@ -681,12 +690,12 @@ public class HerbalismManager extends SkillManager {
     /**
      * Check for success on herbalism double drops
      *
-     * @param blockState target block state
+     * @param block target block state
      * @return true if the double drop succeeds
      */
-    private boolean checkDoubleDrop(@NotNull BlockState blockState) {
-        requireNonNull(blockState, "BlockState cannot be null");
-        return BlockUtils.checkDoubleDrops(mmoPlayer, blockState, SubSkillType.HERBALISM_DOUBLE_DROPS);
+    private boolean checkDoubleDrop(@NotNull Block block) {
+        requireNonNull(block, "BlockState cannot be null");
+        return BlockUtils.checkDoubleDrops(mmoPlayer, block, SubSkillType.HERBALISM_DOUBLE_DROPS);
     }
 
     /**

+ 0 - 24
src/main/java/com/gmail/nossr50/skills/mining/Mining.java

@@ -1,24 +0,0 @@
-package com.gmail.nossr50.skills.mining;
-
-import com.gmail.nossr50.config.experience.ExperienceConfig;
-import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
-import com.gmail.nossr50.mcMMO;
-import org.bukkit.block.BlockState;
-
-public class Mining {
-
-    /**
-     * Calculate XP gain for Mining.
-     *
-     * @param blockState The {@link BlockState} to check ability activation for
-     */
-    public static int getBlockXp(BlockState blockState) {
-        int xp = ExperienceConfig.getInstance().getXp(PrimarySkillType.MINING, blockState.getType());
-
-        if (xp == 0 && mcMMO.getModManager().isCustomMiningBlock(blockState)) {
-            xp = mcMMO.getModManager().getBlock(blockState).getXpGain();
-        }
-
-        return xp;
-    }
-}

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

@@ -85,10 +85,15 @@ public class MiningManager extends SkillManager {
      *
      * @param blockState The {@link BlockState} to check ability activation for
      */
+    @Deprecated(since = "2.2.024", forRemoval = true)
     public void miningBlockCheck(BlockState blockState) {
+        miningBlockCheck(blockState.getBlock());
+    }
+
+    public void miningBlockCheck(Block block) {
         Player player = getPlayer();
 
-        applyXpGain(Mining.getBlockXp(blockState), XPGainReason.PVE);
+        applyXpGain(ExperienceConfig.getInstance().getXp(PrimarySkillType.MINING, block), XPGainReason.PVE);
 
         if (!Permissions.isSubSkillEnabled(player, SubSkillType.MINING_DOUBLE_DROPS)) {
             return;
@@ -98,7 +103,7 @@ public class MiningManager extends SkillManager {
             SkillUtils.handleDurabilityChange(getPlayer().getInventory().getItemInMainHand(), mcMMO.p.getGeneralConfig().getAbilityToolDamage());
         }
 
-        if (!mcMMO.p.getGeneralConfig().getDoubleDropsEnabled(PrimarySkillType.MINING, blockState.getType()) || !canDoubleDrop())
+        if (!mcMMO.p.getGeneralConfig().getDoubleDropsEnabled(PrimarySkillType.MINING, block.getType()) || !canDoubleDrop())
             return;
 
         boolean silkTouch = player.getInventory().getItemInMainHand().containsEnchantment(Enchantment.SILK_TOUCH);
@@ -109,30 +114,31 @@ public class MiningManager extends SkillManager {
         //Mining mastery allows for a chance of triple drops
         if (canMotherLode()) {
             //Triple Drops failed so do a normal double drops check
-            if (!processTripleDrops(blockState)) {
-                processDoubleDrops(blockState);
+            if (!processTripleDrops(block)) {
+                processDoubleDrops(block);
             }
         } else {
             //If the user has no mastery, proceed with normal double drop routine
-            processDoubleDrops(blockState);
+            processDoubleDrops(block);
         }
     }
 
-    private boolean processTripleDrops(@NotNull BlockState blockState) {
+    private boolean processTripleDrops(@NotNull Block block) {
         //TODO: Make this readable
         if (ProbabilityUtil.isSkillRNGSuccessful(SubSkillType.MINING_MOTHER_LODE, mmoPlayer)) {
-            BlockUtils.markDropsAsBonus(blockState, 2);
+            BlockUtils.markDropsAsBonus(block, 2);
             return true;
         } else {
             return false;
         }
     }
 
-    private void processDoubleDrops(@NotNull BlockState blockState) {
+    private void processDoubleDrops(@NotNull Block block) {
         //TODO: Make this readable
         if (ProbabilityUtil.isSkillRNGSuccessful(SubSkillType.MINING_DOUBLE_DROPS, mmoPlayer)) {
-            boolean useTriple = mmoPlayer.getAbilityMode(SuperAbilityType.SUPER_BREAKER) && mcMMO.p.getAdvancedConfig().getAllowMiningTripleDrops();
-            BlockUtils.markDropsAsBonus(blockState, useTriple);
+            boolean useTriple = mmoPlayer.getAbilityMode(SuperAbilityType.SUPER_BREAKER)
+                    && mcMMO.p.getAdvancedConfig().getAllowMiningTripleDrops();
+            BlockUtils.markDropsAsBonus(block, useTriple);
         }
     }
 
@@ -180,59 +186,58 @@ public class MiningManager extends SkillManager {
 
         var increasedYieldFromBonuses = yield + (yield * getOreBonus());
         // Strip out only stuff that gives mining XP
-        List<BlockState> ores = new ArrayList<>();
-        List<BlockState> notOres = new ArrayList<>();
+        List<Block> ores = new ArrayList<>();
+        List<Block> notOres = new ArrayList<>();
         for (Block targetBlock : event.blockList()) {
-            BlockState blockState = targetBlock.getState();
 
             if(mcMMO.getUserBlockTracker().isIneligible(targetBlock))
                 continue;
 
             if (ExperienceConfig.getInstance().getXp(PrimarySkillType.MINING, targetBlock) != 0) {
-                if (BlockUtils.isOre(blockState) && !(targetBlock instanceof Container)) {
-                    ores.add(blockState);
+                if (BlockUtils.isOre(targetBlock) && !(targetBlock instanceof Container)) {
+                    ores.add(targetBlock);
                 }
             } else {
-                notOres.add(blockState);
+                notOres.add(targetBlock);
             }
         }
 
         int xp = 0;
         int dropMultiplier = getDropMultiplier();
 
-        for(BlockState blockState : notOres) {
-            if (isDropIllegal(blockState.getType()))
+        for(Block block : notOres) {
+            if (isDropIllegal(block.getType()))
                 continue;
 
-            if (blockState.getType().isItem() && Probability.ofPercent(50).evaluate()) {
+            if (block.getType().isItem() && Probability.ofPercent(50).evaluate()) {
                 ItemUtils.spawnItem(getPlayer(),
-                        Misc.getBlockCenter(blockState),
-                        new ItemStack(blockState.getType()),
+                        Misc.getBlockCenter(block),
+                        new ItemStack(block.getType()),
                         ItemSpawnReason.BLAST_MINING_DEBRIS_NON_ORES); // Initial block that would have been dropped
             }
         }
-        for (BlockState blockState : ores) {
+        for (Block block : ores) {
             // currentOreYield only used for drop calculations for ores
             float currentOreYield = increasedYieldFromBonuses;
 
-            if (isDropIllegal(blockState.getType())) {
+            if (isDropIllegal(block.getType())) {
                 continue;
             }
 
             // Always give XP for every ore destroyed
-            xp += Mining.getBlockXp(blockState);
+            xp += ExperienceConfig.getInstance().getXp(PrimarySkillType.MINING, block);
             while(currentOreYield > 0) {
                 if (Probability.ofValue(currentOreYield).evaluate()) {
                     Collection<ItemStack> oreDrops = isPickaxe(mmoPlayer.getPlayer().getInventory().getItemInMainHand())
-                            ? blockState.getBlock().getDrops(mmoPlayer.getPlayer().getInventory().getItemInMainHand())
-                            : List.of(new ItemStack(blockState.getType()));
-                    ItemUtils.spawnItems(getPlayer(), Misc.getBlockCenter(blockState),
+                            ? block.getDrops(mmoPlayer.getPlayer().getInventory().getItemInMainHand())
+                            : List.of(new ItemStack(block.getType()));
+                    ItemUtils.spawnItems(getPlayer(), Misc.getBlockCenter(block),
                             oreDrops, BLAST_MINING_BLACKLIST, ItemSpawnReason.BLAST_MINING_ORES);
 
                     if (mcMMO.p.getAdvancedConfig().isBlastMiningBonusDropsEnabled()) {
                         for (int i = 1; i < dropMultiplier; i++) {
                             ItemUtils.spawnItems(getPlayer(),
-                                    Misc.getBlockCenter(blockState),
+                                    Misc.getBlockCenter(block),
                                     oreDrops,
                                     BLAST_MINING_BLACKLIST,
                                     ItemSpawnReason.BLAST_MINING_ORES_BONUS_DROP);

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

@@ -68,29 +68,29 @@ public class UnarmedManager extends SkillManager {
         return Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.UNARMED_BLOCK_CRACKER);
     }
 
-    public boolean blockCrackerCheck(@NotNull BlockState blockState) {
+    public void blockCrackerCheck(@NotNull BlockState blockState) {
         if (!ProbabilityUtil.isNonRNGSkillActivationSuccessful(SubSkillType.UNARMED_BLOCK_CRACKER, mmoPlayer)) {
-            return false;
+            return;
         }
 
         switch (blockState.getType()) {
             case STONE_BRICKS:
                 if (!Unarmed.blockCrackerSmoothBrick) {
-                    return false;
+                    return;
                 }
 
                 blockState.getBlock().setType(Material.CRACKED_STONE_BRICKS);
-                return true;
+                blockState.update(true);
+                return;
             case INFESTED_STONE_BRICKS:
                 if (!Unarmed.blockCrackerSmoothBrick) {
-                    return false;
+                    return;
                 }
 
                 blockState.getBlock().setType(Material.INFESTED_CRACKED_STONE_BRICKS);
-                return true;
-
+                blockState.update(true);
+                return;
             default:
-                return false;
         }
     }
 

+ 93 - 71
src/main/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingManager.java

@@ -97,50 +97,60 @@ public class WoodcuttingManager extends SkillManager {
      *
      * @param blockState Block being broken
      */
+    @Deprecated(forRemoval = true, since = "2.2.024")
     public void processBonusDropCheck(@NotNull BlockState blockState) {
+        processBonusDropCheck(blockState.getBlock());
+    }
+
+    public void processBonusDropCheck(@NotNull Block block) {
         //TODO: Why isn't this using the item drop event? Potentially because of Tree Feller? This should be adjusted either way.
-        if (mcMMO.p.getGeneralConfig().getDoubleDropsEnabled(PrimarySkillType.WOODCUTTING, blockState.getType())) {
+        if (mcMMO.p.getGeneralConfig().getDoubleDropsEnabled(PrimarySkillType.WOODCUTTING, block.getType())) {
             //Mastery enabled for player
             if (Permissions.canUseSubSkill(getPlayer(), SubSkillType.WOODCUTTING_CLEAN_CUTS)) {
-                if (checkCleanCutsActivation(blockState.getType())) {
+                if (checkCleanCutsActivation(block.getType())) {
                     //Triple drops
-                    spawnHarvestLumberBonusDrops(blockState);
-                    spawnHarvestLumberBonusDrops(blockState);
+                    spawnHarvestLumberBonusDrops(block);
+                    spawnHarvestLumberBonusDrops(block);
                 } else {
                     //Harvest Lumber Check
-                    if (checkHarvestLumberActivation(blockState.getType())) {
-                        spawnHarvestLumberBonusDrops(blockState);
+                    if (checkHarvestLumberActivation(block.getType())) {
+                        spawnHarvestLumberBonusDrops(block);
                     }
                 }
-            //No Mastery (no Clean Cuts)
+                //No Mastery (no Clean Cuts)
             } else if (Permissions.canUseSubSkill(getPlayer(), SubSkillType.WOODCUTTING_HARVEST_LUMBER)) {
-                if (checkHarvestLumberActivation(blockState.getType())) {
-                    spawnHarvestLumberBonusDrops(blockState);
+                if (checkHarvestLumberActivation(block.getType())) {
+                    spawnHarvestLumberBonusDrops(block);
                 }
             }
         }
     }
 
+    @Deprecated(forRemoval = true, since = "2.2.024")
     public void processWoodcuttingBlockXP(@NotNull BlockState blockState) {
-        if (mcMMO.getUserBlockTracker().isIneligible(blockState))
+        processWoodcuttingBlockXP(blockState.getBlock());
+    }
+
+    public void processWoodcuttingBlockXP(@NotNull Block block) {
+        if (mcMMO.getUserBlockTracker().isIneligible(block))
             return;
 
-        int xp = getExperienceFromLog(blockState);
-        applyXpGain(xp, XPGainReason.PVE);
+        int xp = getExperienceFromLog(block);
+        applyXpGain(xp, XPGainReason.PVE, XPGainSource.SELF);
     }
 
     /**
      * Begins Tree Feller
      *
-     * @param blockState Block being broken
+     * @param startingBlock The first startingBlock broken
      */
-    public void processTreeFeller(BlockState blockState) {
-        Player player = getPlayer();
-        Set<BlockState> treeFellerBlocks = new HashSet<>();
+    public void processTreeFeller(Block startingBlock) {
+        final Player player = getPlayer();
+        Set<Block> treeFellerBlocks = new HashSet<>();
 
         treeFellerReachedThreshold = false;
 
-        processTree(blockState, treeFellerBlocks);
+        processTree(startingBlock, treeFellerBlocks);
 
         // If the tool can't sustain the durability loss
         if (!handleDurabilityLoss(treeFellerBlocks, player.getInventory().getItemInMainHand(), player)) {
@@ -160,21 +170,17 @@ public class WoodcuttingManager extends SkillManager {
     }
 
     /**
-     * Processes Tree Feller in a recursive manner
-     *
-     * @param blockState Block being checked
-     * @param treeFellerBlocks List of blocks to be removed
-     */
-    /*
+     * Process the tree feller ability.
+     * <p>
      * Algorithm: An int[][] of X/Z directions is created on static class
      * initialization, representing a cylinder with radius of about 2 - the
      * (0,0) center and all (+-2, +-2) corners are omitted.
-     *
+     * <p>
      * processTreeFellerTargetBlock() returns a boolean, which is used for the sole purpose of
      * switching between these two behaviors:
-     *
+     * <p>
      * (Call blockState "this log" for the below explanation.)
-     *
+     * <p>
      *  [A] There is another log above this log (TRUNK)
      *    Only the flat cylinder in the directions array is searched.
      *  [B] There is not another log above this log (BRANCH AND TOP)
@@ -182,19 +188,19 @@ public class WoodcuttingManager extends SkillManager {
      *    block in the Y-axis, and the block below this log is checked as
      *    well. Due to the fact that the directions array will catch all
      *    blocks on a red mushroom, the special method for it is eliminated.
-     *
+     * <p>
      * This algorithm has been shown to achieve a performance of 2-5
      * milliseconds on regular trees and 10-15 milliseconds on jungle trees
      * once the JIT has optimized the function (use the ability about 4 times
      * before taking measurements).
      */
-    private void processTree(BlockState blockState, Set<BlockState> treeFellerBlocks) {
-        List<BlockState> futureCenterBlocks = new ArrayList<>();
+    private void processTree(Block block, Set<Block> treeFellerBlocks) {
+        List<Block> futureCenterBlocks = new ArrayList<>();
 
         // Check the block up and take different behavior (smaller search) if it's a log
-        if (processTreeFellerTargetBlock(blockState.getBlock().getRelative(BlockFace.UP).getState(), futureCenterBlocks, treeFellerBlocks)) {
+        if (processTreeFellerTargetBlock(block.getRelative(BlockFace.UP), futureCenterBlocks, treeFellerBlocks)) {
             for (int[] dir : directions) {
-                processTreeFellerTargetBlock(blockState.getBlock().getRelative(dir[0], 0, dir[1]).getState(), futureCenterBlocks, treeFellerBlocks);
+                processTreeFellerTargetBlock(block.getRelative(dir[0], 0, dir[1]), futureCenterBlocks, treeFellerBlocks);
 
                 if (treeFellerReachedThreshold) {
                     return;
@@ -202,11 +208,11 @@ public class WoodcuttingManager extends SkillManager {
             }
         } else {
             // Cover DOWN
-            processTreeFellerTargetBlock(blockState.getBlock().getRelative(BlockFace.DOWN).getState(), futureCenterBlocks, treeFellerBlocks);
+            processTreeFellerTargetBlock(block.getRelative(BlockFace.DOWN), futureCenterBlocks, treeFellerBlocks);
             // Search in a cube
             for (int y = -1; y <= 1; y++) {
                 for (int[] dir : directions) {
-                    processTreeFellerTargetBlock(blockState.getBlock().getRelative(dir[0], y, dir[1]).getState(), futureCenterBlocks, treeFellerBlocks);
+                    processTreeFellerTargetBlock(block.getRelative(dir[0], y, dir[1]), futureCenterBlocks, treeFellerBlocks);
 
                     if (treeFellerReachedThreshold) {
                         return;
@@ -216,7 +222,7 @@ public class WoodcuttingManager extends SkillManager {
         }
 
         // Recursive call for each log found
-        for (BlockState futureCenterBlock : futureCenterBlocks) {
+        for (Block futureCenterBlock : futureCenterBlocks) {
             if (treeFellerReachedThreshold) {
                 return;
             }
@@ -233,7 +239,8 @@ public class WoodcuttingManager extends SkillManager {
      * @param player the player holding the item
      * @return True if the tool can sustain the durability loss
      */
-    private static boolean handleDurabilityLoss(@NotNull Set<BlockState> treeFellerBlocks, @NotNull ItemStack inHand, @NotNull Player player) {
+    private static boolean handleDurabilityLoss(@NotNull Set<Block> treeFellerBlocks,
+                                                @NotNull ItemStack inHand, @NotNull Player player) {
         //Treat the NBT tag for unbreakable and the durability enchant differently
         ItemMeta meta = inHand.getItemMeta();
 
@@ -244,8 +251,8 @@ public class WoodcuttingManager extends SkillManager {
         int durabilityLoss = 0;
         Material type = inHand.getType();
 
-        for (BlockState blockState : treeFellerBlocks) {
-            if (BlockUtils.hasWoodcuttingXP(blockState)) {
+        for (Block block : treeFellerBlocks) {
+            if (BlockUtils.hasWoodcuttingXP(block)) {
                 durabilityLoss += mcMMO.p.getGeneralConfig().getAbilityToolDamage();
             }
         }
@@ -261,7 +268,9 @@ public class WoodcuttingManager extends SkillManager {
 
         SkillUtils.handleDurabilityChange(inHand, durabilityLoss);
         int durability = meta instanceof Damageable ? ((Damageable) meta).getDamage(): 0;
-        return (durability < (mcMMO.getRepairableManager().isRepairable(type) ? mcMMO.getRepairableManager().getRepairable(type).getMaximumDurability() : type.getMaxDurability()));
+        return (durability < (mcMMO.getRepairableManager().isRepairable(type)
+                ? mcMMO.getRepairableManager().getRepairable(type).getMaximumDurability()
+                : type.getMaxDurability()));
     }
 
     /**
@@ -269,15 +278,17 @@ public class WoodcuttingManager extends SkillManager {
      * list of blocks used for future recursive calls of
      * 'processTree()'
      *
-     * @param blockState Block to be added
+     * @param block Block to be added
      * @param futureCenterBlocks List of blocks that will be used to call
      *     'processTree()'
      * @param treeFellerBlocks List of blocks to be removed
-     * @return true if and only if the given blockState was a Log not already
+     * @return true if and only if the given block was a Log not already
      *     in treeFellerBlocks.
      */
-    private boolean processTreeFellerTargetBlock(@NotNull BlockState blockState, @NotNull List<BlockState> futureCenterBlocks, @NotNull Set<BlockState> treeFellerBlocks) {
-        if (treeFellerBlocks.contains(blockState) || mcMMO.getUserBlockTracker().isIneligible(blockState)) {
+    private boolean processTreeFellerTargetBlock(@NotNull Block block,
+                                                 @NotNull List<Block> futureCenterBlocks,
+                                                 @NotNull Set<Block> treeFellerBlocks) {
+        if (treeFellerBlocks.contains(block) || mcMMO.getUserBlockTracker().isIneligible(block)) {
             return false;
         }
 
@@ -286,12 +297,12 @@ public class WoodcuttingManager extends SkillManager {
             treeFellerReachedThreshold = true;
         }
 
-        if (BlockUtils.hasWoodcuttingXP(blockState)) {
-            treeFellerBlocks.add(blockState);
-            futureCenterBlocks.add(blockState);
+        if (BlockUtils.hasWoodcuttingXP(block)) {
+            treeFellerBlocks.add(block);
+            futureCenterBlocks.add(block);
             return true;
-        } else if (BlockUtils.isNonWoodPartOfTree(blockState)) {
-            treeFellerBlocks.add(blockState);
+        } else if (BlockUtils.isNonWoodPartOfTree(block)) {
+            treeFellerBlocks.add(block);
             return false;
         }
         return false;
@@ -302,15 +313,14 @@ public class WoodcuttingManager extends SkillManager {
      *
      * @param treeFellerBlocks List of blocks to be dropped
      */
-    private void dropTreeFellerLootFromBlocks(@NotNull Set<BlockState> treeFellerBlocks) {
+    private void dropTreeFellerLootFromBlocks(@NotNull Set<Block> treeFellerBlocks) {
         Player player = getPlayer();
         int xp = 0;
         int processedLogCount = 0;
         ItemStack itemStack = player.getInventory().getItemInMainHand();
 
-        for (BlockState blockState : treeFellerBlocks) {
+        for (Block block : treeFellerBlocks) {
             int beforeXP = xp;
-            Block block = blockState.getBlock();
 
             if (!EventUtils.simulateBlockBreak(block, player, FakeBlockBreakEventType.TREE_FELLER)) {
                 continue;
@@ -320,20 +330,21 @@ public class WoodcuttingManager extends SkillManager {
              * Handle Drops & XP
              */
 
-            if (BlockUtils.hasWoodcuttingXP(blockState)) {
+            if (BlockUtils.hasWoodcuttingXP(block)) {
                 //Add XP
-                xp += processTreeFellerXPGains(blockState, processedLogCount);
+                xp += processTreeFellerXPGains(block, processedLogCount);
 
                 //Drop displaced block
-                spawnItemsFromCollection(player, getBlockCenter(blockState), block.getDrops(itemStack), ItemSpawnReason.TREE_FELLER_DISPLACED_BLOCK);
+                spawnItemsFromCollection(player, getBlockCenter(block),
+                        block.getDrops(itemStack), ItemSpawnReason.TREE_FELLER_DISPLACED_BLOCK);
 
                 //Bonus Drops / Harvest lumber checks
-                processBonusDropCheck(blockState);
-            } else if (BlockUtils.isNonWoodPartOfTree(blockState)) {
+                processBonusDropCheck(block);
+            } else if (BlockUtils.isNonWoodPartOfTree(block)) {
                 // 75% of the time do not drop leaf blocks
                 if (ThreadLocalRandom.current().nextInt(100) > 75) {
                     spawnItemsFromCollection(player,
-                            getBlockCenter(blockState),
+                            getBlockCenter(block),
                             block.getDrops(itemStack),
                             ItemSpawnReason.TREE_FELLER_DISPLACED_BLOCK);
                 } else if (hasUnlockedSubskill(player, SubSkillType.WOODCUTTING_KNOCK_ON_WOOD)) {
@@ -341,7 +352,7 @@ public class WoodcuttingManager extends SkillManager {
                     ItemUtils.spawnItemsConditionally(block.getDrops(itemStack),
                             IS_SAPLING_OR_PROPAGULE,
                             ItemSpawnReason.TREE_FELLER_DISPLACED_BLOCK,
-                            getBlockCenter(blockState),
+                            getBlockCenter(block),
                             // only spawn saplings
                             player
                     );
@@ -353,15 +364,14 @@ public class WoodcuttingManager extends SkillManager {
                         if (mcMMO.p.getAdvancedConfig().isKnockOnWoodXPOrbEnabled()) {
                             if (ProbabilityUtil.isStaticSkillRNGSuccessful(PrimarySkillType.WOODCUTTING, mmoPlayer, 10)) {
                                 int randOrbCount = Math.max(1, Misc.getRandom().nextInt(100));
-                                Misc.spawnExperienceOrb(blockState.getLocation(), randOrbCount);
+                                Misc.spawnExperienceOrb(block.getLocation(), randOrbCount);
                             }
                         }
                     }
                 }
             }
 
-            blockState.setType(Material.AIR);
-            blockState.update(true);
+            block.setType(Material.AIR);
 
             //Update only when XP changes
             processedLogCount = updateProcessedLogCount(xp, processedLogCount, beforeXP);
@@ -383,15 +393,15 @@ public class WoodcuttingManager extends SkillManager {
      * Experience is only reduced if the config option to reduce Tree Feller XP is set
      * Experience per log will not fall below 1 unless the experience for that log is set to 0 in the config
      *
-     * @param blockState Log being broken
+     * @param block Log being broken
      * @param woodCount how many logs have given out XP for this tree feller so far
      * @return Amount of experience
      */
-    private static int processTreeFellerXPGains(BlockState blockState, int woodCount) {
-        if (mcMMO.getUserBlockTracker().isIneligible(blockState))
+    private static int processTreeFellerXPGains(Block block, int woodCount) {
+        if (mcMMO.getUserBlockTracker().isIneligible(block))
             return 0;
 
-        int rawXP = ExperienceConfig.getInstance().getXp(PrimarySkillType.WOODCUTTING, blockState.getType());
+        int rawXP = ExperienceConfig.getInstance().getXp(PrimarySkillType.WOODCUTTING, block.getType());
 
         if (rawXP <= 0)
             return 0;
@@ -401,7 +411,7 @@ public class WoodcuttingManager extends SkillManager {
             rawXP = Math.max(1, reducedXP);
             return rawXP;
         } else {
-            return ExperienceConfig.getInstance().getXp(PrimarySkillType.WOODCUTTING, blockState.getType());
+            return ExperienceConfig.getInstance().getXp(PrimarySkillType.WOODCUTTING, block.getType());
         }
     }
 
@@ -411,12 +421,19 @@ public class WoodcuttingManager extends SkillManager {
      * @param blockState Log being broken
      * @return Amount of experience
      */
+    @Deprecated(forRemoval = true, since = "2.2.024")
     protected static int getExperienceFromLog(BlockState blockState) {
-        if (mcMMO.getModManager().isCustomLog(blockState)) {
-            return mcMMO.getModManager().getBlock(blockState).getXpGain();
-        }
+        return getExperienceFromLog(blockState.getBlock());
+    }
 
-        return ExperienceConfig.getInstance().getXp(PrimarySkillType.WOODCUTTING, blockState.getType());
+    /**
+     * Retrieves the experience reward from a log
+     *
+     * @param block Log being broken
+     * @return Amount of experience
+     */
+    protected static int getExperienceFromLog(Block block) {
+        return ExperienceConfig.getInstance().getXp(PrimarySkillType.WOODCUTTING, block.getType());
     }
 
     /**
@@ -424,11 +441,16 @@ public class WoodcuttingManager extends SkillManager {
      *
      * @param blockState Block being broken
      */
+    @Deprecated(forRemoval = true, since = "2.2.024")
     void spawnHarvestLumberBonusDrops(@NotNull BlockState blockState) {
+        spawnHarvestLumberBonusDrops(blockState.getBlock());
+    }
+
+    void spawnHarvestLumberBonusDrops(@NotNull Block block) {
         spawnItemsFromCollection(
                 getPlayer(),
-                getBlockCenter(blockState),
-                blockState.getBlock().getDrops(getPlayer().getInventory().getItemInMainHand()),
+                getBlockCenter(block),
+                block.getDrops(getPlayer().getInventory().getItemInMainHand()),
                 ItemSpawnReason.BONUS_DROPS);
     }
 }

+ 133 - 25
src/main/java/com/gmail/nossr50/util/BlockUtils.java

@@ -38,11 +38,19 @@ public final class BlockUtils {
      * @param blockState target blockstate
      * @param triple     marks the block to give triple drops
      */
+    @Deprecated(forRemoval = true, since = "2.2.024")
     public static void markDropsAsBonus(BlockState blockState, boolean triple) {
         if (triple)
-            blockState.setMetadata(MetadataConstants.METADATA_KEY_BONUS_DROPS, new BonusDropMeta(2, mcMMO.p));
+            blockState.getBlock().setMetadata(MetadataConstants.METADATA_KEY_BONUS_DROPS, new BonusDropMeta(2, mcMMO.p));
         else
-            blockState.setMetadata(MetadataConstants.METADATA_KEY_BONUS_DROPS, new BonusDropMeta(1, mcMMO.p));
+            blockState.getBlock().setMetadata(MetadataConstants.METADATA_KEY_BONUS_DROPS, new BonusDropMeta(1, mcMMO.p));
+    }
+
+    public static void markDropsAsBonus(Block block, boolean triple) {
+        if (triple)
+            block.setMetadata(MetadataConstants.METADATA_KEY_BONUS_DROPS, new BonusDropMeta(2, mcMMO.p));
+        else
+            block.setMetadata(MetadataConstants.METADATA_KEY_BONUS_DROPS, new BonusDropMeta(1, mcMMO.p));
     }
 
     /**
@@ -90,10 +98,20 @@ public final class BlockUtils {
      * @param blockState target blockstate
      * @param amount amount of extra items to drop
      */
+    @Deprecated(forRemoval = true, since = "2.2.024")
     public static void markDropsAsBonus(BlockState blockState, int amount) {
             blockState.setMetadata(MetadataConstants.METADATA_KEY_BONUS_DROPS, new BonusDropMeta(amount, mcMMO.p));
     }
 
+    /**
+     * Marks a block to drop extra copies of items
+     * @param block target block
+     * @param amount the number of extra items to drop
+     */
+    public static void markDropsAsBonus(Block block, int amount) {
+        block.setMetadata(MetadataConstants.METADATA_KEY_BONUS_DROPS, new BonusDropMeta(amount, mcMMO.p));
+    }
+
     /**
      * Checks if a player successfully passed the double drop check
      *
@@ -114,6 +132,7 @@ public final class BlockUtils {
      * @param subSkillType the subskill involved
      * @return true if the player succeeded in the check
      */
+    @Deprecated(forRemoval = true, since = "2.2.024")
     public static boolean checkDoubleDrops(@Nullable McMMOPlayer mmoPlayer, @NotNull BlockState blockState,
                                            @NotNull SubSkillType subSkillType) {
         requireNonNull(blockState, "blockState cannot be null");
@@ -126,6 +145,25 @@ public final class BlockUtils {
         return false;
     }
 
+    /**
+     * Checks if a player successfully passed the double drop check
+     * @param mmoPlayer the player involved in the check
+     * @param block the block
+     * @param subSkillType the subskill involved
+     * @return true if the player succeeded in the check
+     */
+    public static boolean checkDoubleDrops(@Nullable McMMOPlayer mmoPlayer, @NotNull Block block,
+                                           @NotNull SubSkillType subSkillType) {
+        requireNonNull(block, "block cannot be null");
+        requireNonNull(subSkillType, "subSkillType cannot be null");
+        if (mcMMO.p.getGeneralConfig().getDoubleDropsEnabled(subSkillType.getParentSkill(), block.getType())
+                && Permissions.isSubSkillEnabled(mmoPlayer, subSkillType)) {
+            return ProbabilityUtil.isSkillRNGSuccessful(subSkillType, mmoPlayer);
+        }
+
+        return false;
+    }
+
     /**
      * Checks to see if a given block awards XP.
      *
@@ -133,11 +171,18 @@ public final class BlockUtils {
      * @return true if the block awards XP, false otherwise
      */
     public static boolean shouldBeWatched(BlockState blockState) {
-        return affectedByGigaDrillBreaker(blockState) || affectedByGreenTerra(blockState) || affectedBySuperBreaker(blockState) || hasWoodcuttingXP(blockState)
-                || mcMMO.p.getGeneralConfig().getDoubleDropsEnabled(PrimarySkillType.MINING, blockState.getType())
-                || mcMMO.p.getGeneralConfig().getDoubleDropsEnabled(PrimarySkillType.EXCAVATION, blockState.getType())
-                || mcMMO.p.getGeneralConfig().getDoubleDropsEnabled(PrimarySkillType.WOODCUTTING, blockState.getType())
-                || mcMMO.p.getGeneralConfig().getDoubleDropsEnabled(PrimarySkillType.SMELTING, blockState.getType());
+        return shouldBeWatched(blockState.getType());
+    }
+
+    public static boolean shouldBeWatched(Material material) {
+        return affectedByGigaDrillBreaker(material)
+                || affectedByGreenTerra(material)
+                || affectedBySuperBreaker(material)
+                || hasWoodcuttingXP(material)
+                || mcMMO.p.getGeneralConfig().getDoubleDropsEnabled(PrimarySkillType.MINING, material)
+                || mcMMO.p.getGeneralConfig().getDoubleDropsEnabled(PrimarySkillType.EXCAVATION, material)
+                || mcMMO.p.getGeneralConfig().getDoubleDropsEnabled(PrimarySkillType.WOODCUTTING, material)
+                || mcMMO.p.getGeneralConfig().getDoubleDropsEnabled(PrimarySkillType.SMELTING, material);
     }
 
     /**
@@ -147,10 +192,15 @@ public final class BlockUtils {
      * @return true if the block should allow ability activation, false
      * otherwise
      */
+    @Deprecated(forRemoval = true, since = "2.2.024")
     public static boolean canActivateAbilities(BlockState blockState) {
         return !mcMMO.getMaterialMapStore().isAbilityActivationBlackListed(blockState.getType());
     }
 
+    public static boolean canActivateAbilities(Block block) {
+        return !mcMMO.getMaterialMapStore().isAbilityActivationBlackListed(block.getType());
+    }
+
     /**
      * Check if a given block should allow for the activation of tools
      * Activating a tool is step 1 of a 2 step process for super ability activation
@@ -172,7 +222,25 @@ public final class BlockUtils {
      * @return true if the block is an ore, false otherwise
      */
     public static boolean isOre(BlockState blockState) {
-        return MaterialUtils.isOre(blockState.getType());
+        return isOre(blockState.getType());
+    }
+
+    /**
+     * Check if a given block is an ore
+     * @param block The {@link Block} to check
+     * @return true if the block is an ore, false otherwise
+     */
+    public static boolean isOre(Block block) {
+        return isOre(block.getType());
+    }
+
+    /**
+     * Check if a given material is an ore
+     * @param material The {@link Material} to check
+     * @return true if the material is an ore, false otherwise
+     */
+    public static boolean isOre(Material material) {
+        return MaterialUtils.isOre(material);
     }
 
     /**
@@ -181,10 +249,15 @@ public final class BlockUtils {
      * @param blockState The {@link BlockState} of the block to check
      * @return true if the block can be made mossy, false otherwise
      */
+    @Deprecated(since = "2.2.024")
     public static boolean canMakeMossy(BlockState blockState) {
         return mcMMO.getMaterialMapStore().isMossyWhiteListed(blockState.getType());
     }
 
+    public static boolean canMakeMossy(Block block) {
+        return mcMMO.getMaterialMapStore().isMossyWhiteListed(block.getType());
+    }
+
     /**
      * Determine if a given block should be affected by Green Terra
      *
@@ -192,41 +265,56 @@ public final class BlockUtils {
      * @return true if the block should affected by Green Terra, false otherwise
      */
     public static boolean affectedByGreenTerra(BlockState blockState) {
-        if (ExperienceConfig.getInstance().doesBlockGiveSkillXP(PrimarySkillType.HERBALISM, blockState.getBlockData())) {
-            return true;
-        }
+        return affectedByGreenTerra(blockState.getType());
+    }
 
-        return mcMMO.getModManager().isCustomHerbalismBlock(blockState);
+    public static boolean affectedByGreenTerra(Block block) {
+        return affectedByGreenTerra(block.getType());
+    }
+
+    public static boolean affectedByGreenTerra(Material material) {
+        return ExperienceConfig.getInstance().doesBlockGiveSkillXP(PrimarySkillType.HERBALISM, material);
+    }
+
+    public static boolean affectedBySuperBreaker(BlockState blockState) {
+        return affectedBySuperBreaker(blockState.getType());
     }
 
     /**
      * Determine if a given block should be affected by Super Breaker
      *
-     * @param blockState The {@link BlockState} of the block to check
+     * @param block The {@link Block} to check
      * @return true if the block should affected by Super Breaker, false
      * otherwise
      */
-    public static boolean affectedBySuperBreaker(BlockState blockState) {
-        if (mcMMO.getMaterialMapStore().isIntendedToolPickaxe(blockState.getType()))
-            return true;
+    public static boolean affectedBySuperBreaker(Block block) {
+        return affectedBySuperBreaker(block.getType());
+    }
 
-        if (ExperienceConfig.getInstance().doesBlockGiveSkillXP(PrimarySkillType.MINING, blockState.getBlockData()))
+    public static boolean affectedBySuperBreaker(Material material) {
+        if (mcMMO.getMaterialMapStore().isIntendedToolPickaxe(material))
             return true;
 
-        return mcMMO.getModManager().isCustomMiningBlock(blockState);
+        return ExperienceConfig.getInstance().doesBlockGiveSkillXP(PrimarySkillType.MINING, material);
     }
 
     /**
      * Determine if a given block should be affected by Giga Drill Breaker
      *
      * @param blockState The {@link BlockState} of the block to check
-     * @return true if the block should affected by Giga Drill Breaker, false
+     * @return true if the block should be affected by Giga Drill Breaker, false
      * otherwise
      */
     public static boolean affectedByGigaDrillBreaker(@NotNull BlockState blockState) {
-        if (ExperienceConfig.getInstance().doesBlockGiveSkillXP(PrimarySkillType.EXCAVATION, blockState.getBlockData()))
-            return true;
-        return mcMMO.getModManager().isCustomExcavationBlock(blockState);
+        return affectedByGigaDrillBreaker(blockState.getType());
+    }
+
+    public static boolean affectedByGigaDrillBreaker(@NotNull Block block) {
+        return affectedByGigaDrillBreaker(block.getType());
+    }
+
+    public static boolean affectedByGigaDrillBreaker(@NotNull Material material) {
+        return ExperienceConfig.getInstance().doesBlockGiveSkillXP(PrimarySkillType.EXCAVATION, material);
     }
 
     /**
@@ -236,7 +324,15 @@ public final class BlockUtils {
      * @return true if the block is a log, false otherwise
      */
     public static boolean hasWoodcuttingXP(@NotNull BlockState blockState) {
-        return ExperienceConfig.getInstance().doesBlockGiveSkillXP(PrimarySkillType.WOODCUTTING, blockState.getBlockData());
+        return hasWoodcuttingXP(blockState.getType());
+    }
+
+    public static boolean hasWoodcuttingXP(@NotNull Block block) {
+        return hasWoodcuttingXP(block.getType());
+    }
+
+    public static boolean hasWoodcuttingXP(@NotNull Material material) {
+        return ExperienceConfig.getInstance().doesBlockGiveSkillXP(PrimarySkillType.WOODCUTTING, material);
     }
 
     /**
@@ -246,7 +342,11 @@ public final class BlockUtils {
      * @return true if the block is a leaf, false otherwise
      */
     public static boolean isNonWoodPartOfTree(@NotNull BlockState blockState) {
-        return mcMMO.getMaterialMapStore().isTreeFellerDestructible(blockState.getType());
+        return isNonWoodPartOfTree(blockState.getType());
+    }
+
+    public static boolean isNonWoodPartOfTree(@NotNull Block block) {
+        return isNonWoodPartOfTree(block.getType());
     }
 
     public static boolean isNonWoodPartOfTree(@NotNull Material material) {
@@ -289,7 +389,15 @@ public final class BlockUtils {
      * otherwise
      */
     public static boolean affectedByBlockCracker(BlockState blockState) {
-        return mcMMO.getMaterialMapStore().isBlockCrackerWhiteListed(blockState.getType());
+        return affectedByBlockCracker(blockState.getType());
+    }
+
+    public static boolean affectedByBlockCracker(Block block) {
+        return affectedByBlockCracker(block.getType());
+    }
+
+    public static boolean affectedByBlockCracker(Material material) {
+        return mcMMO.getMaterialMapStore().isBlockCrackerWhiteListed(material);
     }
 
     /**

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

@@ -6,6 +6,7 @@ import com.gmail.nossr50.runnables.player.PlayerProfileLoadingTask;
 import com.gmail.nossr50.util.player.UserManager;
 import com.google.common.collect.ImmutableSet;
 import org.bukkit.Location;
+import org.bukkit.block.Block;
 import org.bukkit.block.BlockState;
 import org.bukkit.entity.*;
 import org.jetbrains.annotations.NotNull;
@@ -35,7 +36,10 @@ public final class Misc {
     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 @NotNull Set<String> modNames = ImmutableSet.of("LOTR", "BUILDCRAFT", "ENDERIO", "ENHANCEDBIOMES", "IC2", "METALLURGY", "FORESTRY", "GALACTICRAFT", "RAILCRAFT", "TWILIGHTFOREST", "THAUMCRAFT", "GRAVESTONEMOD", "GROWTHCRAFT", "ARCTICMOBS", "DEMONMOBS", "INFERNOMOBS", "SWAMPMOBS", "MARICULTURE", "MINESTRAPPOLATION");
+    public static final @NotNull Set<String> modNames = ImmutableSet.of("LOTR", "BUILDCRAFT", "ENDERIO",
+            "ENHANCEDBIOMES", "IC2", "METALLURGY", "FORESTRY", "GALACTICRAFT", "RAILCRAFT", "TWILIGHTFOREST",
+            "THAUMCRAFT", "GRAVESTONEMOD", "GROWTHCRAFT", "ARCTICMOBS", "DEMONMOBS", "INFERNOMOBS", "SWAMPMOBS",
+            "MARICULTURE", "MINESTRAPPOLATION");
 
     private Misc() {}
 
@@ -97,7 +101,15 @@ public final class Misc {
      * @return A {@link Location} lying at the center of the block
      */
     public static Location getBlockCenter(BlockState blockState) {
-        return blockState.getLocation().add(0.5, 0.5, 0.5);
+        return getBlockCenter(blockState.getLocation());
+    }
+
+    public static Location getBlockCenter(Block block) {
+        return getBlockCenter(block.getLocation());
+    }
+
+    public static Location getBlockCenter(Location location) {
+        return location.add(0.5, 0.5, 0.5);
     }
 
     public static void profileCleanup(@NotNull String playerName) {
@@ -111,7 +123,9 @@ public final class Misc {
 
     public static void printProgress(int convertedUsers, int progressInterval, long startMillis) {
         if ((convertedUsers % progressInterval) == 0) {
-            mcMMO.p.getLogger().info(String.format("Conversion progress: %d users at %.2f users/second", convertedUsers, convertedUsers / (double) ((System.currentTimeMillis() - startMillis) / TIME_CONVERSION_FACTOR)));
+            mcMMO.p.getLogger().info(String.format("Conversion progress: %d users at %.2f users/second",
+                    convertedUsers,
+                    convertedUsers / (double) ((System.currentTimeMillis() - startMillis) / TIME_CONVERSION_FACTOR)));
         }
     }
 

+ 275 - 275
src/main/java/com/gmail/nossr50/util/ModManager.java

@@ -1,275 +1,275 @@
-package com.gmail.nossr50.util;
-
-import com.gmail.nossr50.config.mods.CustomArmorLegacyConfig;
-import com.gmail.nossr50.config.mods.CustomBlockLegacyConfig;
-import com.gmail.nossr50.config.mods.CustomEntityLegacyConfig;
-import com.gmail.nossr50.config.mods.CustomToolLegacyConfig;
-import com.gmail.nossr50.datatypes.mods.CustomBlock;
-import com.gmail.nossr50.datatypes.mods.CustomEntity;
-import com.gmail.nossr50.datatypes.mods.CustomTool;
-import com.gmail.nossr50.mcMMO;
-import com.gmail.nossr50.skills.repair.repairables.Repairable;
-import org.bukkit.Material;
-import org.bukkit.block.BlockState;
-import org.bukkit.configuration.file.YamlConfiguration;
-import org.bukkit.entity.Entity;
-import org.bukkit.inventory.ItemStack;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-public class ModManager {
-    private final List<Repairable> repairables = new ArrayList<>();
-
-    // Armor Mods
-    private final List<Material> customBoots       = new ArrayList<>();
-    private final List<Material> customChestplates = new ArrayList<>();
-    private final List<Material> customHelmets     = new ArrayList<>();
-    private final List<Material> customLeggings    = new ArrayList<>();
-
-    // Block Mods
-    private final List<Material> customExcavationBlocks  = new ArrayList<>();
-    private final List<Material> customHerbalismBlocks   = new ArrayList<>();
-    private final List<Material> customMiningBlocks      = new ArrayList<>();
-    private final List<Material> customOres              = new ArrayList<>();
-    private final List<Material> customLogs              = new ArrayList<>();
-    private final List<Material> customLeaves            = new ArrayList<>();
-    private final List<Material> customAbilityBlocks     = new ArrayList<>();
-    private final HashMap<Material, CustomBlock> customBlockMap = new HashMap<>();
-
-    // Entity Mods
-    private final HashMap<String, CustomEntity> customEntityClassMap = new HashMap<>();
-    private final HashMap<String, CustomEntity> customEntityTypeMap  = new HashMap<>();
-
-    // Tool Mods
-    private final List<Material> customAxes     = new ArrayList<>();
-    private final List<Material> customBows     = new ArrayList<>();
-    private final List<Material> customHoes     = new ArrayList<>();
-    private final List<Material> customPickaxes = new ArrayList<>();
-    private final List<Material> customShovels  = new ArrayList<>();
-    private final List<Material> customSwords   = new ArrayList<>();
-    private final HashMap<Material, CustomTool> customToolMap = new HashMap<>();
-
-    public void registerCustomArmor(CustomArmorLegacyConfig config) {
-        customBoots.addAll(config.customBoots);
-        customChestplates.addAll(config.customChestplates);
-        customHelmets.addAll(config.customHelmets);
-        customLeggings.addAll(config.customLeggings);
-        repairables.addAll(config.repairables);
-    }
-
-    public void registerCustomBlocks(CustomBlockLegacyConfig config) {
-        customExcavationBlocks.addAll(config.customExcavationBlocks);
-        customHerbalismBlocks.addAll(config.customHerbalismBlocks);
-        customMiningBlocks.addAll(config.customMiningBlocks);
-        customOres.addAll(config.customOres);
-        customLogs.addAll(config.customLogs);
-        customLeaves.addAll(config.customLeaves);
-        customAbilityBlocks.addAll(config.customAbilityBlocks);
-        customBlockMap.putAll(config.customBlockMap);
-    }
-
-    public void registerCustomEntities(CustomEntityLegacyConfig config) {
-        customEntityClassMap.putAll(config.customEntityClassMap);
-        customEntityTypeMap.putAll(config.customEntityTypeMap);
-    }
-
-    public void registerCustomTools(CustomToolLegacyConfig config) {
-        customAxes.addAll(config.customAxes);
-        customBows.addAll(config.customBows);
-        customHoes.addAll(config.customHoes);
-        customPickaxes.addAll(config.customPickaxes);
-        customShovels.addAll(config.customShovels);
-        customSwords.addAll(config.customSwords);
-        customToolMap.putAll(config.customToolMap);
-        repairables.addAll(config.repairables);
-    }
-
-    public boolean isCustomBoots(Material material) {
-        return mcMMO.p.getGeneralConfig().getArmorModsEnabled() && customBoots.contains(material);
-    }
-
-    public boolean isCustomChestplate(Material material) {
-        return mcMMO.p.getGeneralConfig().getArmorModsEnabled() && customChestplates.contains(material);
-    }
-
-    public boolean isCustomHelmet(Material material) {
-        return mcMMO.p.getGeneralConfig().getArmorModsEnabled() && customHelmets.contains(material);
-    }
-
-    public boolean isCustomLeggings(Material material) {
-        return mcMMO.p.getGeneralConfig().getArmorModsEnabled() && customLeggings.contains(material);
-    }
-
-    public boolean isCustomAxe(Material material) {
-        return mcMMO.p.getGeneralConfig().getToolModsEnabled() && customAxes.contains(material);
-    }
-
-    public boolean isCustomBow(Material material) {
-        return mcMMO.p.getGeneralConfig().getToolModsEnabled() && customBows.contains(material);
-    }
-
-    public boolean isCustomHoe(Material material) {
-        return mcMMO.p.getGeneralConfig().getToolModsEnabled() && customHoes.contains(material);
-    }
-
-    public boolean isCustomPickaxe(Material material) {
-        return mcMMO.p.getGeneralConfig().getToolModsEnabled() && customPickaxes.contains(material);
-    }
-
-    public boolean isCustomShovel(Material material) {
-        return mcMMO.p.getGeneralConfig().getToolModsEnabled() && customShovels.contains(material);
-    }
-
-    public boolean isCustomSword(Material material) {
-        return mcMMO.p.getGeneralConfig().getToolModsEnabled() && customSwords.contains(material);
-    }
-
-    public boolean isCustomOre(Material data) {
-        return mcMMO.p.getGeneralConfig().getBlockModsEnabled() && customOres.contains(data);
-    }
-
-    public boolean isCustomLog(BlockState state) {
-        return mcMMO.p.getGeneralConfig().getBlockModsEnabled() && customLogs.contains(state.getType());
-    }
-
-    public boolean isCustomAbilityBlock(BlockState state) {
-        return mcMMO.p.getGeneralConfig().getBlockModsEnabled() && customAbilityBlocks.contains(state.getType());
-    }
-
-    public boolean isCustomExcavationBlock(BlockState state) {
-        return mcMMO.p.getGeneralConfig().getBlockModsEnabled() && customExcavationBlocks.contains(state.getType());
-    }
-
-    public boolean isCustomHerbalismBlock(BlockState state) {
-        return mcMMO.p.getGeneralConfig().getBlockModsEnabled() && customHerbalismBlocks.contains(state.getType());
-    }
-
-    public boolean isCustomMiningBlock(BlockState state) {
-        return mcMMO.p.getGeneralConfig().getBlockModsEnabled() && customMiningBlocks.contains(state.getType());
-    }
-
-    public CustomBlock getBlock(BlockState state) {
-        return customBlockMap.get(state.getType());
-    }
-
-    public CustomBlock getBlock(Material data) {
-        return customBlockMap.get(data);
-    }
-
-    /**
-     * Checks to see if an item is a custom tool.
-     *
-     * @param item Item to check
-     * @return true if the item is a custom tool, false otherwise
-     */
-    public boolean isCustomTool(ItemStack item) {
-        return mcMMO.p.getGeneralConfig().getToolModsEnabled() && item != null && customToolMap.containsKey(item.getType());
-    }
-
-    /**
-     * Get the custom tool associated with an item.
-     *
-     * @param item The item to check
-     * @return the tool if it exists, null otherwise
-     */
-    public CustomTool getTool(ItemStack item) {
-        return item == null ? null : customToolMap.get(item.getType());
-    }
-
-    public List<Repairable> getLoadedRepairables() {
-        return repairables;
-    }
-
-    public boolean isCustomEntity(Entity entity) {
-        if (!mcMMO.p.getGeneralConfig().getEntityModsEnabled()) {
-            return false;
-        }
-
-        if (customEntityTypeMap.containsKey(entity.getType().toString())) {
-            return true;
-        }
-
-        try {
-            return customEntityClassMap.containsKey(((Class<?>) entity.getClass().getDeclaredField("entityClass").get(entity)).getName());
-        }
-        catch (Exception e) {
-            if (e instanceof NoSuchFieldException || e instanceof IllegalArgumentException || e instanceof IllegalAccessException) {
-                return customEntityClassMap.containsKey(entity.getClass().getName());
-            }
-
-            e.printStackTrace();
-            return false;
-        }
-    }
-
-    public CustomEntity getEntity(Entity entity) {
-        CustomEntity customEntity = customEntityTypeMap.get(entity.getType().toString());
-
-        if (customEntity == null) {
-            try {
-                customEntity = customEntityClassMap.get(((Class<?>) entity.getClass().getDeclaredField("entityClass").get(entity)).getName());
-            }
-            catch (Exception e) {
-                if (e instanceof NoSuchFieldException || e instanceof IllegalArgumentException || e instanceof IllegalAccessException) {
-                    customEntity = customEntityClassMap.get(entity.getClass().getName());
-                } else {
-                    e.printStackTrace();
-                }
-            }
-        }
-
-        return customEntity;
-    }
-
-    public void addCustomEntity(Entity entity) {
-        if (!mcMMO.p.getGeneralConfig().getEntityModsEnabled()) {
-            return;
-        }
-
-        File entityFile = new File(mcMMO.p.getDataFolder(), "mods" + File.separator + "entities.default.yml");
-        YamlConfiguration entitiesFile = YamlConfiguration.loadConfiguration(entityFile);
-
-        String entityName = entity.getType().toString();
-        String sanitizedEntityName = entityName.replace(".", "_");
-
-        if (entitiesFile.getKeys(false).contains(sanitizedEntityName)) {
-            return;
-        }
-
-        entitiesFile.set(sanitizedEntityName + ".XP_Multiplier", 1.0D);
-        entitiesFile.set(sanitizedEntityName + ".Tameable", false);
-        entitiesFile.set(sanitizedEntityName + ".Taming_XP", 0);
-        entitiesFile.set(sanitizedEntityName + ".CanBeSummoned", false);
-        entitiesFile.set(sanitizedEntityName + ".COTW_Material", "");
-        entitiesFile.set(sanitizedEntityName + ".COTW_Material_Data", 0);
-        entitiesFile.set(sanitizedEntityName + ".COTW_Material_Amount", 0);
-
-        String className = "";
-
-        try {
-            className = ((Class<?>) entity.getClass().getDeclaredField("entityClass").get(entity)).getName();
-        }
-        catch (Exception e) {
-            if (e instanceof NoSuchFieldException || e instanceof IllegalArgumentException || e instanceof IllegalAccessException) {
-                className = entity.getClass().getName();
-            } else {
-                e.printStackTrace();
-            }
-        }
-
-        CustomEntity customEntity = new CustomEntity(1.0D, false, 0, false, null, 0);
-        customEntityTypeMap.put(entityName, customEntity);
-        customEntityClassMap.put(className, customEntity);
-
-        try {
-            entitiesFile.save(entityFile);
-            LogUtils.debug(mcMMO.p.getLogger(), entity.getType().toString() + " was added to the custom entities file!");
-        }
-        catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-}
+//package com.gmail.nossr50.util;
+//
+//import com.gmail.nossr50.config.mods.CustomArmorLegacyConfig;
+//import com.gmail.nossr50.config.mods.CustomBlockLegacyConfig;
+//import com.gmail.nossr50.config.mods.CustomEntityLegacyConfig;
+//import com.gmail.nossr50.config.mods.CustomToolLegacyConfig;
+//import com.gmail.nossr50.datatypes.mods.CustomBlock;
+//import com.gmail.nossr50.datatypes.mods.CustomEntity;
+//import com.gmail.nossr50.datatypes.mods.CustomTool;
+//import com.gmail.nossr50.mcMMO;
+//import com.gmail.nossr50.skills.repair.repairables.Repairable;
+//import org.bukkit.Material;
+//import org.bukkit.block.BlockState;
+//import org.bukkit.configuration.file.YamlConfiguration;
+//import org.bukkit.entity.Entity;
+//import org.bukkit.inventory.ItemStack;
+//
+//import java.io.File;
+//import java.util.ArrayList;
+//import java.util.HashMap;
+//import java.util.List;
+//
+//public class ModManager {
+//    private final List<Repairable> repairables = new ArrayList<>();
+//
+//    // Armor Mods
+//    private final List<Material> customBoots       = new ArrayList<>();
+//    private final List<Material> customChestplates = new ArrayList<>();
+//    private final List<Material> customHelmets     = new ArrayList<>();
+//    private final List<Material> customLeggings    = new ArrayList<>();
+//
+//    // Block Mods
+//    private final List<Material> customExcavationBlocks  = new ArrayList<>();
+//    private final List<Material> customHerbalismBlocks   = new ArrayList<>();
+//    private final List<Material> customMiningBlocks      = new ArrayList<>();
+//    private final List<Material> customOres              = new ArrayList<>();
+//    private final List<Material> customLogs              = new ArrayList<>();
+//    private final List<Material> customLeaves            = new ArrayList<>();
+//    private final List<Material> customAbilityBlocks     = new ArrayList<>();
+//    private final HashMap<Material, CustomBlock> customBlockMap = new HashMap<>();
+//
+//    // Entity Mods
+//    private final HashMap<String, CustomEntity> customEntityClassMap = new HashMap<>();
+//    private final HashMap<String, CustomEntity> customEntityTypeMap  = new HashMap<>();
+//
+//    // Tool Mods
+//    private final List<Material> customAxes     = new ArrayList<>();
+//    private final List<Material> customBows     = new ArrayList<>();
+//    private final List<Material> customHoes     = new ArrayList<>();
+//    private final List<Material> customPickaxes = new ArrayList<>();
+//    private final List<Material> customShovels  = new ArrayList<>();
+//    private final List<Material> customSwords   = new ArrayList<>();
+//    private final HashMap<Material, CustomTool> customToolMap = new HashMap<>();
+//
+//    public void registerCustomArmor(CustomArmorLegacyConfig config) {
+//        customBoots.addAll(config.customBoots);
+//        customChestplates.addAll(config.customChestplates);
+//        customHelmets.addAll(config.customHelmets);
+//        customLeggings.addAll(config.customLeggings);
+//        repairables.addAll(config.repairables);
+//    }
+//
+//    public void registerCustomBlocks(CustomBlockLegacyConfig config) {
+//        customExcavationBlocks.addAll(config.customExcavationBlocks);
+//        customHerbalismBlocks.addAll(config.customHerbalismBlocks);
+//        customMiningBlocks.addAll(config.customMiningBlocks);
+//        customOres.addAll(config.customOres);
+//        customLogs.addAll(config.customLogs);
+//        customLeaves.addAll(config.customLeaves);
+//        customAbilityBlocks.addAll(config.customAbilityBlocks);
+//        customBlockMap.putAll(config.customBlockMap);
+//    }
+//
+//    public void registerCustomEntities(CustomEntityLegacyConfig config) {
+//        customEntityClassMap.putAll(config.customEntityClassMap);
+//        customEntityTypeMap.putAll(config.customEntityTypeMap);
+//    }
+//
+//    public void registerCustomTools(CustomToolLegacyConfig config) {
+//        customAxes.addAll(config.customAxes);
+//        customBows.addAll(config.customBows);
+//        customHoes.addAll(config.customHoes);
+//        customPickaxes.addAll(config.customPickaxes);
+//        customShovels.addAll(config.customShovels);
+//        customSwords.addAll(config.customSwords);
+//        customToolMap.putAll(config.customToolMap);
+//        repairables.addAll(config.repairables);
+//    }
+//
+//    public boolean isCustomBoots(Material material) {
+//        return mcMMO.p.getGeneralConfig().getArmorModsEnabled() && customBoots.contains(material);
+//    }
+//
+//    public boolean isCustomChestplate(Material material) {
+//        return mcMMO.p.getGeneralConfig().getArmorModsEnabled() && customChestplates.contains(material);
+//    }
+//
+//    public boolean isCustomHelmet(Material material) {
+//        return mcMMO.p.getGeneralConfig().getArmorModsEnabled() && customHelmets.contains(material);
+//    }
+//
+//    public boolean isCustomLeggings(Material material) {
+//        return mcMMO.p.getGeneralConfig().getArmorModsEnabled() && customLeggings.contains(material);
+//    }
+//
+//    public boolean isCustomAxe(Material material) {
+//        return mcMMO.p.getGeneralConfig().getToolModsEnabled() && customAxes.contains(material);
+//    }
+//
+//    public boolean isCustomBow(Material material) {
+//        return mcMMO.p.getGeneralConfig().getToolModsEnabled() && customBows.contains(material);
+//    }
+//
+//    public boolean isCustomHoe(Material material) {
+//        return mcMMO.p.getGeneralConfig().getToolModsEnabled() && customHoes.contains(material);
+//    }
+//
+//    public boolean isCustomPickaxe(Material material) {
+//        return mcMMO.p.getGeneralConfig().getToolModsEnabled() && customPickaxes.contains(material);
+//    }
+//
+//    public boolean isCustomShovel(Material material) {
+//        return mcMMO.p.getGeneralConfig().getToolModsEnabled() && customShovels.contains(material);
+//    }
+//
+//    public boolean isCustomSword(Material material) {
+//        return mcMMO.p.getGeneralConfig().getToolModsEnabled() && customSwords.contains(material);
+//    }
+//
+//    public boolean isCustomOre(Material data) {
+//        return mcMMO.p.getGeneralConfig().getBlockModsEnabled() && customOres.contains(data);
+//    }
+//
+//    public boolean isCustomLog(BlockState state) {
+//        return mcMMO.p.getGeneralConfig().getBlockModsEnabled() && customLogs.contains(state.getType());
+//    }
+//
+//    public boolean isCustomAbilityBlock(BlockState state) {
+//        return mcMMO.p.getGeneralConfig().getBlockModsEnabled() && customAbilityBlocks.contains(state.getType());
+//    }
+//
+//    public boolean isCustomExcavationBlock(BlockState state) {
+//        return mcMMO.p.getGeneralConfig().getBlockModsEnabled() && customExcavationBlocks.contains(state.getType());
+//    }
+//
+//    public boolean isCustomHerbalismBlock(BlockState state) {
+//        return mcMMO.p.getGeneralConfig().getBlockModsEnabled() && customHerbalismBlocks.contains(state.getType());
+//    }
+//
+//    public boolean isCustomMiningBlock(BlockState state) {
+//        return mcMMO.p.getGeneralConfig().getBlockModsEnabled() && customMiningBlocks.contains(state.getType());
+//    }
+//
+//    public CustomBlock getBlock(BlockState state) {
+//        return customBlockMap.get(state.getType());
+//    }
+//
+//    public CustomBlock getBlock(Material data) {
+//        return customBlockMap.get(data);
+//    }
+//
+//    /**
+//     * Checks to see if an item is a custom tool.
+//     *
+//     * @param item Item to check
+//     * @return true if the item is a custom tool, false otherwise
+//     */
+//    public boolean isCustomTool(ItemStack item) {
+//        return mcMMO.p.getGeneralConfig().getToolModsEnabled() && item != null && customToolMap.containsKey(item.getType());
+//    }
+//
+//    /**
+//     * Get the custom tool associated with an item.
+//     *
+//     * @param item The item to check
+//     * @return the tool if it exists, null otherwise
+//     */
+//    public CustomTool getTool(ItemStack item) {
+//        return item == null ? null : customToolMap.get(item.getType());
+//    }
+//
+//    public List<Repairable> getLoadedRepairables() {
+//        return repairables;
+//    }
+//
+//    public boolean isCustomEntity(Entity entity) {
+//        if (!mcMMO.p.getGeneralConfig().getEntityModsEnabled()) {
+//            return false;
+//        }
+//
+//        if (customEntityTypeMap.containsKey(entity.getType().toString())) {
+//            return true;
+//        }
+//
+//        try {
+//            return customEntityClassMap.containsKey(((Class<?>) entity.getClass().getDeclaredField("entityClass").get(entity)).getName());
+//        }
+//        catch (Exception e) {
+//            if (e instanceof NoSuchFieldException || e instanceof IllegalArgumentException || e instanceof IllegalAccessException) {
+//                return customEntityClassMap.containsKey(entity.getClass().getName());
+//            }
+//
+//            e.printStackTrace();
+//            return false;
+//        }
+//    }
+//
+//    public CustomEntity getEntity(Entity entity) {
+//        CustomEntity customEntity = customEntityTypeMap.get(entity.getType().toString());
+//
+//        if (customEntity == null) {
+//            try {
+//                customEntity = customEntityClassMap.get(((Class<?>) entity.getClass().getDeclaredField("entityClass").get(entity)).getName());
+//            }
+//            catch (Exception e) {
+//                if (e instanceof NoSuchFieldException || e instanceof IllegalArgumentException || e instanceof IllegalAccessException) {
+//                    customEntity = customEntityClassMap.get(entity.getClass().getName());
+//                } else {
+//                    e.printStackTrace();
+//                }
+//            }
+//        }
+//
+//        return customEntity;
+//    }
+//
+//    public void addCustomEntity(Entity entity) {
+//        if (!mcMMO.p.getGeneralConfig().getEntityModsEnabled()) {
+//            return;
+//        }
+//
+//        File entityFile = new File(mcMMO.p.getDataFolder(), "mods" + File.separator + "entities.default.yml");
+//        YamlConfiguration entitiesFile = YamlConfiguration.loadConfiguration(entityFile);
+//
+//        String entityName = entity.getType().toString();
+//        String sanitizedEntityName = entityName.replace(".", "_");
+//
+//        if (entitiesFile.getKeys(false).contains(sanitizedEntityName)) {
+//            return;
+//        }
+//
+//        entitiesFile.set(sanitizedEntityName + ".XP_Multiplier", 1.0D);
+//        entitiesFile.set(sanitizedEntityName + ".Tameable", false);
+//        entitiesFile.set(sanitizedEntityName + ".Taming_XP", 0);
+//        entitiesFile.set(sanitizedEntityName + ".CanBeSummoned", false);
+//        entitiesFile.set(sanitizedEntityName + ".COTW_Material", "");
+//        entitiesFile.set(sanitizedEntityName + ".COTW_Material_Data", 0);
+//        entitiesFile.set(sanitizedEntityName + ".COTW_Material_Amount", 0);
+//
+//        String className = "";
+//
+//        try {
+//            className = ((Class<?>) entity.getClass().getDeclaredField("entityClass").get(entity)).getName();
+//        }
+//        catch (Exception e) {
+//            if (e instanceof NoSuchFieldException || e instanceof IllegalArgumentException || e instanceof IllegalAccessException) {
+//                className = entity.getClass().getName();
+//            } else {
+//                e.printStackTrace();
+//            }
+//        }
+//
+//        CustomEntity customEntity = new CustomEntity(1.0D, false, 0, false, null, 0);
+//        customEntityTypeMap.put(entityName, customEntity);
+//        customEntityClassMap.put(className, customEntity);
+//
+//        try {
+//            entitiesFile.save(entityFile);
+//            LogUtils.debug(mcMMO.p.getLogger(), entity.getType().toString() + " was added to the custom entities file!");
+//        }
+//        catch (Exception e) {
+//            e.printStackTrace();
+//        }
+//    }
+//}

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

@@ -313,15 +313,6 @@ public final class CommandRegistrationManager {
         command.setExecutor(new McscoreboardCommand());
     }
 
-    private static void registerMcImportCommand() {
-        PluginCommand command = mcMMO.p.getCommand("mcimport");
-        command.setDescription("Import mod config files"); //TODO: Localize
-        command.setPermission("mcmmo.commands.mcimport");
-        command.setPermissionMessage(permissionsMessage);
-        command.setUsage(LocaleLoader.getString("Commands.Usage.0", "mcimport"));
-        command.setExecutor(new McImportCommand());
-    }
-
     private static void registerReloadLocaleCommand() {
         PluginCommand command = mcMMO.p.getCommand("mcmmoreloadlocale");
         command.setDescription("Reloads locale"); // TODO: Localize
@@ -351,7 +342,6 @@ public final class CommandRegistrationManager {
         registerXPBarCommand();
         registerMmoInfoCommand();
         registerMmoDebugCommand();
-        registerMcImportCommand();
         registerMcabilityCommand();
         registerMcgodCommand();
         registerMcChatSpyCommand();

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

@@ -898,9 +898,7 @@ public final class CombatUtils {
                 baseXP = 20 * ExperienceConfig.getInstance().getPlayerVersusPlayerXP();
             }
         } else {
-            if (mcMMO.getModManager().isCustomEntity(target)) {
-                baseXP = mcMMO.getModManager().getEntity(target).getXpMultiplier();
-            } else if (target instanceof Animals) {
+            if (target instanceof Animals) {
                 EntityType type = target.getType();
                 baseXP = ExperienceConfig.getInstance().getAnimalsXP(type);
             } else if (target instanceof Monster) {
@@ -919,7 +917,6 @@ public final class CombatUtils {
                     }
                 } else {
                     baseXP = 1.0;
-                    mcMMO.getModManager().addCustomEntity(target);
                 }
             }
 
@@ -1046,8 +1043,6 @@ public final class CombatUtils {
             tier = 4;
         } else if (ItemUtils.isNetheriteTool(inHand)) {
             tier = 5;
-        } else if (mcMMO.getModManager().isCustomTool(inHand)) {
-            tier = mcMMO.getModManager().getTool(inHand).getTier();
         }
 
         return tier;

+ 0 - 9
src/main/java/com/gmail/nossr50/util/text/ConfigStringUtils.java

@@ -1,7 +1,6 @@
 package com.gmail.nossr50.util.text;
 
 import com.gmail.nossr50.datatypes.party.PartyFeature;
-import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
 import org.bukkit.Material;
 import org.bukkit.entity.EntityType;
 import org.jetbrains.annotations.NotNull;
@@ -11,7 +10,6 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.Function;
 
 import static com.gmail.nossr50.util.text.StringUtils.getCapitalized;
-import static java.util.Objects.requireNonNull;
 
 /**
  * Utility class for String operations, including formatting and caching deterministic results to improve performance.
@@ -22,15 +20,8 @@ public class ConfigStringUtils {
 
     // Using concurrent hash maps to avoid concurrency issues (Folia)
     private static final Map<EntityType, String> configEntityStrings = new ConcurrentHashMap<>();
-    private static final Map<SuperAbilityType, String> configSuperAbilityStrings = new ConcurrentHashMap<>();
     private static final Map<Material, String> configMaterialStrings = new ConcurrentHashMap<>();
     private static final Map<PartyFeature, String> configPartyFeatureStrings = new ConcurrentHashMap<>();
-    
-    public static String getConfigSuperAbilityString(SuperAbilityType superAbilityType) {
-        requireNonNull(superAbilityType, "superAbilityType cannot be null");
-        return configSuperAbilityStrings.computeIfAbsent(superAbilityType,
-                ConfigStringUtils::createConfigFriendlyString);
-    }
 
     public static String getMaterialConfigString(Material material) {
         return configMaterialStrings.computeIfAbsent(material, ConfigStringUtils::createConfigFriendlyString);

+ 0 - 6
src/main/resources/plugin.yml

@@ -67,9 +67,6 @@ commands:
     mcgod:
         description: Toggle mcMMO god-mode on/off
         permission: mcmmo.commands.mcgod
-    mcimport:
-        description: Import mod config files
-        permission: mcmmo.commands.mcimport
     mcstats:
         aliases: [stats]
         description: Shows your mcMMO stats and xp
@@ -917,7 +914,6 @@ permissions:
             mcmmo.commands.mcchatspy.others: true
             mcmmo.commands.mcgod: true
             mcmmo.commands.mcgod.others: true
-            mcmmo.commands.mcimport: true
             mcmmo.commands.mcpurge: true
             mcmmo.commands.mcrank.others.all: true
             mcmmo.commands.mcrefresh: true
@@ -1021,8 +1017,6 @@ permissions:
         description: Allows access to the mcnotify command
     mcmmo.commands.mcpurge:
         description: Allows access to the mcpurge command
-    mcmmo.commands.mcimport:
-        description: Allows access to the mcimport command
     mcmmo.commands.mcrank:
         description: Allows access to the mcrank command
     mcmmo.commands.mcrank.others.*:

+ 3 - 6
src/test/java/com/gmail/nossr50/MMOTestEnvironment.java

@@ -22,6 +22,7 @@ import com.gmail.nossr50.util.skills.SkillTools;
 import com.gmail.nossr50.util.sounds.SoundManager;
 import org.bukkit.*;
 import org.bukkit.block.Block;
+import org.bukkit.block.BlockState;
 import org.bukkit.entity.Player;
 import org.bukkit.event.Event;
 import org.bukkit.inventory.ItemFactory;
@@ -46,7 +47,6 @@ public abstract class MMOTestEnvironment {
     protected MockedStatic<RankUtils> mockedRankUtils;
     protected MockedStatic<UserManager> mockedUserManager;
     protected MockedStatic<Misc> mockedMisc;
-    protected MockedStatic<SkillTools> mockedSkillTools;
     protected MockedStatic<EventUtils> mockedEventUtils;
     protected MockedStatic<NotificationManager> notificationManager;
     protected MockedStatic<SoundManager> mockedSoundManager;
@@ -91,10 +91,6 @@ public abstract class MMOTestEnvironment {
         chunkManager = mock(ChunkManager.class);
         when(mcMMO.getUserBlockTracker()).thenReturn(chunkManager);
 
-        // shut off mod manager for woodcutting
-        when(mcMMO.getModManager()).thenReturn(mock(ModManager.class));
-        when(mcMMO.getModManager().isCustomLog(any())).thenReturn(false);
-
         // chat config
         mockedChatConfig = mockStatic(ChatConfig.class);
         when(ChatConfig.getInstance()).thenReturn(mock(ChatConfig.class));
@@ -154,7 +150,8 @@ public abstract class MMOTestEnvironment {
 
         // wire Misc
         this.mockedMisc = mockStatic(Misc.class);
-        when(Misc.getBlockCenter(any())).thenReturn(new Location(world, 0, 0, 0));
+        when(Misc.getBlockCenter(any(Block.class))).thenReturn(new Location(world, 0, 0, 0));
+        when(Misc.getBlockCenter(any(BlockState.class))).thenReturn(new Location(world, 0, 0, 0));
 
         // setup player and player related mocks after everything else
         this.player = mock(Player.class);

+ 12 - 20
src/test/java/com/gmail/nossr50/skills/excavation/ExcavationTest.java

@@ -60,21 +60,17 @@ class ExcavationTest extends MMOTestEnvironment {
         mmoPlayer.modifySkill(PrimarySkillType.EXCAVATION, 1000);
 
         // Wire block
-        BlockState blockState = Mockito.mock(BlockState.class);
-        BlockData blockData = Mockito.mock(BlockData.class);
         Block block = Mockito.mock(Block.class);
-        when(blockState.getBlockData()).thenReturn(blockData);
-        when(blockState.getType()).thenReturn(Material.SAND);
-        when(blockData.getMaterial()).thenReturn(Material.SAND);
-        when(blockState.getBlock()).thenReturn(block);
-        when(blockState.getBlock().getDrops(any())).thenReturn(null);
+        when(block.getType()).thenReturn(Material.SAND);
+        when(block.getDrops(any())).thenReturn(null);
 
         ExcavationManager excavationManager = Mockito.spy(new ExcavationManager(mmoPlayer));
-        doReturn(getGuaranteedTreasureDrops()).when(excavationManager).getTreasures(blockState);
-        excavationManager.excavationBlockCheck(blockState);
+        doReturn(getGuaranteedTreasureDrops()).when(excavationManager).getTreasures(block);
+        excavationManager.excavationBlockCheck(block);
 
         // verify ExcavationManager.processExcavationBonusesOnBlock was called
-        verify(excavationManager, atLeastOnce()).processExcavationBonusesOnBlock(any(BlockState.class), any(ExcavationTreasure.class), any(Location.class));
+        verify(excavationManager, atLeastOnce()).processExcavationBonusesOnBlock(
+                any(ExcavationTreasure.class), any(Location.class));
     }
 
     @Test
@@ -82,21 +78,17 @@ class ExcavationTest extends MMOTestEnvironment {
         mmoPlayer.modifySkill(PrimarySkillType.EXCAVATION, 1000);
 
         // Wire block
-        BlockState blockState = Mockito.mock(BlockState.class);
-        BlockData blockData = Mockito.mock(BlockData.class);
         Block block = Mockito.mock(Block.class);
-        when(blockState.getBlockData()).thenReturn(blockData);
-        when(blockState.getType()).thenReturn(Material.SAND);
-        when(blockData.getMaterial()).thenReturn(Material.SAND);
-        when(blockState.getBlock()).thenReturn(block);
-        when(blockState.getBlock().getDrops(any())).thenReturn(null);
+        when(block.getType()).thenReturn(Material.SAND);
+        when(block.getDrops(any())).thenReturn(null);
 
         ExcavationManager excavationManager = Mockito.spy(new ExcavationManager(mmoPlayer));
-        doReturn(getImpossibleTreasureDrops()).when(excavationManager).getTreasures(blockState);
-        excavationManager.excavationBlockCheck(blockState);
+        doReturn(getImpossibleTreasureDrops()).when(excavationManager).getTreasures(block);
+        excavationManager.excavationBlockCheck(block);
 
         // verify ExcavationManager.processExcavationBonusesOnBlock was called
-        verify(excavationManager, never()).processExcavationBonusesOnBlock(any(BlockState.class), any(ExcavationTreasure.class), any(Location.class));
+        verify(excavationManager, never()).processExcavationBonusesOnBlock(any(ExcavationTreasure.class),
+                any(Location.class));
     }
 
     private List<ExcavationTreasure> getGuaranteedTreasureDrops() {

+ 9 - 16
src/test/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingTest.java

@@ -8,7 +8,6 @@ import com.gmail.nossr50.datatypes.skills.SubSkillType;
 import com.gmail.nossr50.util.skills.RankUtils;
 import org.bukkit.Material;
 import org.bukkit.block.Block;
-import org.bukkit.block.BlockState;
 import org.bukkit.entity.Player;
 import org.bukkit.inventory.ItemStack;
 import org.junit.jupiter.api.AfterEach;
@@ -62,42 +61,36 @@ class WoodcuttingTest extends MMOTestEnvironment {
     void harvestLumberShouldDoubleDrop() {
         mmoPlayer.modifySkill(PrimarySkillType.WOODCUTTING, 1000);
 
-        BlockState blockState = Mockito.mock(BlockState.class);
         Block block = Mockito.mock(Block.class);
-        // wire block
-        Mockito.when(blockState.getBlock()).thenReturn(block);
-
         // return empty collection if ItemStack
-        Mockito.when(blockState.getBlock().getDrops(any())).thenReturn(Collections.emptyList());
-        Mockito.when(blockState.getType()).thenReturn(Material.OAK_LOG);
-        woodcuttingManager.processBonusDropCheck(blockState);
+        Mockito.when(block.getDrops(any())).thenReturn(Collections.emptyList());
+        Mockito.when(block.getType()).thenReturn(Material.OAK_LOG);
+        woodcuttingManager.processBonusDropCheck(block);
 
         // verify bonus drops were spawned
         // TODO: using at least once since triple drops can also happen
         // TODO: Change the test env to disallow triple drop in the future
-        Mockito.verify(woodcuttingManager, Mockito.atLeastOnce()).spawnHarvestLumberBonusDrops(blockState);
+        Mockito.verify(woodcuttingManager, Mockito.atLeastOnce()).spawnHarvestLumberBonusDrops(block);
     }
 
     @Test
     void harvestLumberShouldNotDoubleDrop() {
         mmoPlayer.modifySkill(PrimarySkillType.WOODCUTTING, 0);
 
-        BlockState blockState = Mockito.mock(BlockState.class);
         Block block = Mockito.mock(Block.class);
         // wire block
-        Mockito.when(blockState.getBlock()).thenReturn(block);
 
-        Mockito.when(blockState.getBlock().getDrops(any())).thenReturn(null);
-        Mockito.when(blockState.getType()).thenReturn(Material.OAK_LOG);
-        woodcuttingManager.processBonusDropCheck(blockState);
+        Mockito.when(block.getDrops(any())).thenReturn(null);
+        Mockito.when(block.getType()).thenReturn(Material.OAK_LOG);
+        woodcuttingManager.processBonusDropCheck(block);
 
         // verify bonus drops were not spawned
-        Mockito.verify(woodcuttingManager, Mockito.times(0)).spawnHarvestLumberBonusDrops(blockState);
+        Mockito.verify(woodcuttingManager, Mockito.times(0)).spawnHarvestLumberBonusDrops(block);
     }
 
     @Test
     void testProcessWoodcuttingBlockXP() {
-        BlockState targetBlock = Mockito.mock(BlockState.class);
+        Block targetBlock = Mockito.mock(Block.class);
         Mockito.when(targetBlock.getType()).thenReturn(Material.OAK_LOG);
         // wire XP
         Mockito.when(ExperienceConfig.getInstance().getXp(PrimarySkillType.WOODCUTTING, Material.OAK_LOG)).thenReturn(5);