diff --git a/README.md b/README.md index 7c8a257..c6c1844 100644 --- a/README.md +++ b/README.md @@ -170,13 +170,18 @@ I really **enjoyed** the plugin, so I decided to **update and improve it further | `powermining.enchant.plow.all` | Allows enchanting all Plows | `op` | ## **πŸ“Œ Change Log** -### πŸ†• **Latest Update - February 16, 2025** +### πŸ†• **Latest Update (v1.2) - February 24, 2025** +- **πŸ’  XP Orbs** - Made a config setting for XP drops +- **🐞 Silk Touch** - Fixed a bug where silk touch still gave XP drops. +- **πŸ› οΈ Config Migrator** - Fixed config migrator accidentally deleting recipes. + +### **πŸ“Œ Previous Updates** +#### πŸ†• **February 16, 2025** - **πŸ’Ό Jobs** - Fixed plugin not working, when [Jobs Reborn](https://www.spigotmc.org/resources/jobs-reborn.4216/) wasn't installed. - **πŸ”¨ Anvils** - Fixed Anvils not adding durability when the Item with lower durability was on the right site. - **✨ Enchantments** - Fixed Unbreaking enchantment not working correctly. - **πŸ› οΈ Durability** - Fixed Items with enchantments not breaking correctly. -### **πŸ“Œ Previous Updates** #### πŸ“… **February 15, 2025** - **πŸ’Ό Jobs support** - Added support for [Jobs Reborn](https://www.spigotmc.org/resources/jobs-reborn.4216/). diff --git a/pom.xml b/pom.xml index 365f6a0..7e5783c 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ jodelle.powermining JodellePowerMining - 1.1.2 + 1.2 jar @@ -20,7 +20,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.13.0 + 3.14.0 21 21 @@ -112,7 +112,7 @@ com.sk89q.worldguard worldguard-bukkit - 7.0.13-SNAPSHOT + 7.0.13 provided diff --git a/src/main/java/jodelle/powermining/listeners/BlockBreakListener.java b/src/main/java/jodelle/powermining/listeners/BlockBreakListener.java index c826e48..f265a07 100644 --- a/src/main/java/jodelle/powermining/listeners/BlockBreakListener.java +++ b/src/main/java/jodelle/powermining/listeners/BlockBreakListener.java @@ -11,6 +11,8 @@ import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.ExperienceOrb; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -21,6 +23,7 @@ import org.bukkit.inventory.ItemStack; import java.util.List; +import java.util.Random; import javax.annotation.Nonnull; @@ -60,50 +63,50 @@ public BlockBreakListener(@Nonnull PowerMining plugin) { public void onBlockBreak(BlockBreakEvent event) { Player player = event.getPlayer(); ItemStack handItem = player.getInventory().getItemInMainHand(); - + // Ensure the player is holding an item if (handItem == null || handItem.getType() == Material.AIR) { return; } - + // Debug message if tool has a custom name if (handItem.getItemMeta() != null && handItem.getItemMeta().hasDisplayName()) { debuggingMessages.sendConsoleMessage( ChatColor.RED + "Broke a block with item: " + handItem.getItemMeta().getDisplayName()); } - + // Perform basic verifications (permissions, tool type, sneaking) if (basicVerifications(player, handItem)) { return; } - + final Block centerBlock = event.getBlock(); final String playerName = player.getName(); - final PlayerInteractListener pil = (plugin.getPlayerInteractHandler() != null) - ? plugin.getPlayerInteractHandler().getListener() + final PlayerInteractListener pil = (plugin.getPlayerInteractHandler() != null) + ? plugin.getPlayerInteractHandler().getListener() : null; - + if (pil == null) { debuggingMessages.sendConsoleMessage(ChatColor.RED + "PlayerInteractListener is null."); return; } - + final BlockFace blockFace = pil.getBlockFaceByPlayerName(playerName); - + int radius = Math.max(0, plugin.getConfig().getInt("Radius", Reference.RADIUS) - 1); int depth = Math.max(0, plugin.getConfig().getInt("Depth", Reference.DEPTH) - 1); - + List surroundingBlocks = PowerUtils.getSurroundingBlocks(blockFace, centerBlock, radius, depth); - + if (surroundingBlocks.isEmpty()) { debuggingMessages.sendConsoleMessage(ChatColor.RED + "No surrounding blocks found."); return; } - + // Handle durability reduction for the main block first if (player.getGameMode().equals(GameMode.SURVIVAL)) { PowerUtils.reduceDurability(player, handItem); - + // Schedule a delayed inventory update to ensure proper tool breaking Bukkit.getScheduler().runTaskLater(plugin, () -> { if (player.getInventory().getItemInMainHand().getType() == Material.AIR) { @@ -111,14 +114,14 @@ public void onBlockBreak(BlockBreakEvent event) { } }, 1L); } - + for (Block block : surroundingBlocks) { int exp = checkAndBreakBlock(player, handItem, block); - + // Handle durability reduction per surrounding block if (player.getGameMode().equals(GameMode.SURVIVAL)) { PowerUtils.reduceDurability(player, handItem); - + // Schedule a delayed inventory update to prevent tool reappearing Bukkit.getScheduler().runTaskLater(plugin, () -> { if (player.getInventory().getItemInMainHand().getType() == Material.AIR) { @@ -126,17 +129,17 @@ public void onBlockBreak(BlockBreakEvent event) { } }, 1L); } - + // Handle XP drops if (exp > 0) { BlockExpEvent expEvent = new BlockExpEvent(block, exp); plugin.getServer().getPluginManager().callEvent(expEvent); - + ExperienceOrb orb = block.getWorld().spawn(block.getLocation(), ExperienceOrb.class); orb.setExperience(expEvent.getExpToDrop()); } } - } + } /** * Checks and breaks a block if it is compatible with the PowerTool. @@ -172,18 +175,30 @@ private int checkAndBreakBlock(Player player, ItemStack handItem, @Nonnull Block .sendConsoleMessage(ChatColor.GREEN + "βœ… Jobs Reborn notified for block: " + block.getType()); } - // XP Drops - int expToDrop = switch (blockMat) { - case COAL_ORE, DEEPSLATE_COAL_ORE -> (int) (Math.random() * 3); // 0-2 XP - case DIAMOND_ORE, DEEPSLATE_DIAMOND_ORE, EMERALD_ORE, DEEPSLATE_EMERALD_ORE -> - 3 + (int) (Math.random() * 5); // 3-7 XP - case REDSTONE_ORE, DEEPSLATE_REDSTONE_ORE, LAPIS_ORE, DEEPSLATE_LAPIS_ORE -> - 2 + (int) (Math.random() * 4); // 2-6 XP - case NETHER_QUARTZ_ORE -> 2 + (int) (Math.random() * 3); // 2-5 XP - case NETHER_GOLD_ORE -> 1 + (int) (Math.random() * 5); // 1-5 XP - case SPAWNER -> 15 + (int) (Math.random() * 30); // 15-43 XP - default -> 0; // No XP for blocks not listed - }; + // Retrieve XP drop configuration for this block + int expToDrop = 0; + try { + ConfigurationSection xpDropsSection = plugin.getConfig().getConfigurationSection("xp-drops"); + if (xpDropsSection == null) { + plugin.getLogger().warning("XP drops configuration section 'xp-drops' not found. Using default XP of 0 for " + blockMat); + } else { + ConfigurationSection blockSection = xpDropsSection.getConfigurationSection(blockMat.toString()); + if (blockSection == null) { + debuggingMessages.sendConsoleMessage("XP drop configuration for block " + blockMat + " not found. Using default XP of 0."); + } else { + int minXp = blockSection.getInt("min", 0); + int maxXp = blockSection.getInt("max", minXp); + if (maxXp < minXp) { + plugin.getLogger().warning("Invalid XP configuration for block " + blockMat + ": max (" + maxXp + ") is less than min (" + minXp + "). Using default XP of 0."); + } else { + // Calculate a random XP value within the range (inclusive) + expToDrop = minXp + new Random().nextInt(maxXp - minXp + 1); + } + } + } + } catch (Exception e) { + plugin.getLogger().severe("Error while retrieving XP drop configuration for block " + blockMat + ": " + e.getMessage()); + } // Break the block naturally if conditions are met if (block.breakNaturally(handItem) && player.getGameMode().equals(GameMode.SURVIVAL)) { @@ -192,7 +207,13 @@ private int checkAndBreakBlock(Player player, ItemStack handItem, @Nonnull Block } } - return expToDrop; // Return XP only for eligible blocks + if (handItem != null && handItem.getItemMeta() != null && handItem.getItemMeta().hasEnchant(Enchantment.SILK_TOUCH)) { + debuggingMessages.sendConsoleMessage("Silk Touch detected on tool; no XP will be dropped for block " + blockMat); + return expToDrop = 0; + } + else { + return expToDrop; + } } return 0; // Return 0 XP if conditions aren't met diff --git a/src/main/java/jodelle/powermining/managers/ConfigMigrator.java b/src/main/java/jodelle/powermining/managers/ConfigMigrator.java index 3716bfa..e306b28 100644 --- a/src/main/java/jodelle/powermining/managers/ConfigMigrator.java +++ b/src/main/java/jodelle/powermining/managers/ConfigMigrator.java @@ -1,16 +1,18 @@ package jodelle.powermining.managers; import jodelle.powermining.PowerMining; - import org.bukkit.configuration.file.FileConfiguration; import java.util.*; /** - * Handles the migration of the configuration file to ensure compatibility with newer versions of the PowerMining plugin. + * Handles the migration of the configuration file to ensure compatibility with + * newer versions of the PowerMining plugin. * *

- * This class checks for outdated configuration formats and updates them to the latest version. - * It ensures that required settings are present, renames deprecated keys, and converts the recipe format + * This class checks for outdated configuration formats and updates them to the + * latest version. + * It ensures that required settings are present, renames deprecated keys, and + * converts the recipe format * to a structured format while enforcing a consistent order of tools. *

*/ @@ -21,12 +23,13 @@ public class ConfigMigrator { /** * The current version of the configuration format. */ - private static final String CURRENT_VERSION = "1.0"; // New version for migration + private static final String CURRENT_VERSION = "1.2"; // Updated version for migration /** * Constructs a {@code ConfigMigrator} instance. * - * @param plugin The instance of {@link PowerMining} responsible for managing the configuration. + * @param plugin The instance of {@link PowerMining} responsible for managing + * the configuration. */ public ConfigMigrator(PowerMining plugin) { this.plugin = plugin; @@ -36,18 +39,29 @@ public ConfigMigrator(PowerMining plugin) { * Checks and migrates the configuration file if it is outdated. * *

- * This method ensures that required configuration keys exist, renames deprecated keys, - * removes old sections, and converts recipes into the new structured format while maintaining + * This method ensures that required configuration keys exist, renames + * deprecated keys, + * removes old sections, and converts recipes into the new structured format + * while maintaining * a predefined order for tools. *

*/ public void migrateConfig() { FileConfiguration config = plugin.getConfig(); - String configVersion = config.getString("configVersion", null); + String configVersionStr = config.getString("configVersion", null); + double configVersion = 0.0; + if (configVersionStr != null) { + try { + configVersion = Double.parseDouble(configVersionStr); + } catch (NumberFormatException e) { + plugin.getLogger() + .warning("Invalid configVersion format (" + configVersionStr + "). Defaulting version to 0."); + } + } - // If config is already updated, stop migration - if ("1.0".equals(configVersion)) { - plugin.getLogger().info("Config is already up-to-date (v1.0). No migration needed."); + // If config is already updated (>= 1.2), stop migration + if (configVersion >= 1.2) { + plugin.getLogger().info("Config is already up-to-date (v" + configVersion + "). No migration needed."); return; } @@ -72,91 +86,142 @@ public void migrateConfig() { plugin.getLogger().info("Renamed 'Deep' to 'Depth' (Value: " + depthValue + ")"); } - // STEP 1: Extract Old Recipes Before Deleting - List oldRecipes = config.getList("Recipes"); // Store before deleting + if (configVersion < 1.0) { + // STEP 1: Extract Old Recipes Before Deleting + List oldRecipes = config.getList("Recipes"); // Store before deleting - // STEP 2: Remove Old "Recipes" Section - if (config.contains("Recipes")) { - config.set("Recipes", null); - plugin.getLogger().info("Removed old 'Recipes' section."); - } - - // STEP 3: Convert Old Recipe Format to New Format - Map> newRecipes = new HashMap<>(); + // STEP 2: Remove Old "Recipes" Section + if (config.contains("Recipes")) { + config.set("Recipes", null); + plugin.getLogger().info("Removed old 'Recipes' section."); + } - if (oldRecipes != null) { - for (Object entry : oldRecipes) { - if (!(entry instanceof LinkedHashMap)) - continue; - LinkedHashMap rawMap = (LinkedHashMap) entry; + // STEP 3: Convert Old Recipe Format to New Format + Map> newRecipes = new HashMap<>(); - for (Map.Entry rawEntry : rawMap.entrySet()) { - if (!(rawEntry.getKey() instanceof String) || !(rawEntry.getValue() instanceof List)) { - plugin.getLogger().warning("Skipping invalid recipe format: " + rawEntry); + if (oldRecipes != null) { + for (Object entry : oldRecipes) { + if (!(entry instanceof LinkedHashMap)) continue; - } + LinkedHashMap rawMap = (LinkedHashMap) entry; - String toolName = (String) rawEntry.getKey(); - List rawList = (List) rawEntry.getValue(); - Map ingredients = new LinkedHashMap<>(); + for (Map.Entry rawEntry : rawMap.entrySet()) { + if (!(rawEntry.getKey() instanceof String) || !(rawEntry.getValue() instanceof List)) { + plugin.getLogger().warning("Skipping invalid recipe format: " + rawEntry); + continue; + } - String[] layout = { "", "", "" }; - for (int i = 0; i < rawList.size(); i++) { - String value = (String) rawList.get(i); - int row = i / 3; - char symbol = (char) ('A' + i); + String toolName = (String) rawEntry.getKey(); + List rawList = (List) rawEntry.getValue(); + Map ingredients = new LinkedHashMap<>(); - if (value.equalsIgnoreCase("EMPTY") || value.equalsIgnoreCase("AIR")) { - ingredients.put(String.valueOf(symbol), "AIR"); - } else { - ingredients.put(String.valueOf(symbol), value); - } + String[] layout = { "", "", "" }; + for (int i = 0; i < rawList.size(); i++) { + String value = (String) rawList.get(i); + int row = i / 3; + char symbol = (char) ('A' + i); - layout[row] += symbol; - } + if (value.equalsIgnoreCase("EMPTY") || value.equalsIgnoreCase("AIR")) { + ingredients.put(String.valueOf(symbol), "AIR"); + } else { + ingredients.put(String.valueOf(symbol), value); + } - Map orderedRecipeData = new LinkedHashMap<>(); - orderedRecipeData.put("recipe-ingredients", ingredients); - orderedRecipeData.put("recipe-shape", Arrays.asList(layout)); + layout[row] += symbol; + } - newRecipes.put(toolName, orderedRecipeData); + Map orderedRecipeData = new LinkedHashMap<>(); + orderedRecipeData.put("recipe-ingredients", ingredients); + orderedRecipeData.put("recipe-shape", Arrays.asList(layout)); + + newRecipes.put(toolName, orderedRecipeData); + } } } - } - // STEP 4: Enforce Tool Order - List toolOrder = Arrays.asList( - "WOODEN_HAMMER", "STONE_HAMMER", "IRON_HAMMER", "GOLDEN_HAMMER", "DIAMOND_HAMMER", "NETHERITE_HAMMER", - "WOODEN_EXCAVATOR", "STONE_EXCAVATOR", "IRON_EXCAVATOR", "GOLDEN_EXCAVATOR", "DIAMOND_EXCAVATOR", - "NETHERITE_EXCAVATOR", - "WOODEN_PLOW", "STONE_PLOW", "IRON_PLOW", "GOLDEN_PLOW", "DIAMOND_PLOW", "NETHERITE_PLOW"); + // STEP 4: Enforce Tool Order + List toolOrder = Arrays.asList( + "WOODEN_HAMMER", "STONE_HAMMER", "IRON_HAMMER", "GOLDEN_HAMMER", "DIAMOND_HAMMER", + "NETHERITE_HAMMER", + "WOODEN_EXCAVATOR", "STONE_EXCAVATOR", "IRON_EXCAVATOR", "GOLDEN_EXCAVATOR", "DIAMOND_EXCAVATOR", + "NETHERITE_EXCAVATOR", + "WOODEN_PLOW", "STONE_PLOW", "IRON_PLOW", "GOLDEN_PLOW", "DIAMOND_PLOW", "NETHERITE_PLOW"); - Map> migratedRecipes = new LinkedHashMap<>(); + Map> migratedRecipes = new LinkedHashMap<>(); - for (String toolName : toolOrder) { - if (!newRecipes.containsKey(toolName)) - continue; + for (String toolName : toolOrder) { + if (!newRecipes.containsKey(toolName)) + continue; - Map recipeData = newRecipes.get(toolName); + Map recipeData = newRecipes.get(toolName); - Map orderedRecipeData = new LinkedHashMap<>(); - if (recipeData.containsKey("recipe-ingredients")) { - orderedRecipeData.put("recipe-ingredients", recipeData.get("recipe-ingredients")); - } - if (recipeData.containsKey("recipe-shape")) { - orderedRecipeData.put("recipe-shape", recipeData.get("recipe-shape")); + Map orderedRecipeData = new LinkedHashMap<>(); + if (recipeData.containsKey("recipe-ingredients")) { + orderedRecipeData.put("recipe-ingredients", recipeData.get("recipe-ingredients")); + } + if (recipeData.containsKey("recipe-shape")) { + orderedRecipeData.put("recipe-shape", recipeData.get("recipe-shape")); + } + + migratedRecipes.put(toolName, orderedRecipeData); } - migratedRecipes.put(toolName, orderedRecipeData); + // STEP 5: Store the Correctly Ordered Recipes in "recipes" + config.set("recipes", migratedRecipes); + plugin.getLogger().info("Recipes migrated successfully with enforced tool order."); } - // STEP 5: Store the Correctly Ordered Recipes in "recipes" - config.set("recipes", migratedRecipes); - plugin.getLogger().info("Recipes migrated successfully with enforced tool order."); + if (configVersion < 1.2) { + // STEP 6: Migrate config to version 1.2 by adding the xp-drops section + if (!config.contains("xp-drops") || config.getConfigurationSection("xp-drops").getKeys(false).isEmpty()) { + config.createSection("xp-drops"); + config.set("xp-drops.COAL_ORE.min", 0); + config.set("xp-drops.COAL_ORE.max", 2); + config.set("xp-drops.DEEPSLATE_COAL_ORE.min", 0); + config.set("xp-drops.DEEPSLATE_COAL_ORE.max", 2); + config.set("xp-drops.DIAMOND_ORE.min", 3); + config.set("xp-drops.DIAMOND_ORE.max", 7); + config.set("xp-drops.DEEPSLATE_DIAMOND_ORE.min", 3); + config.set("xp-drops.DEEPSLATE_DIAMOND_ORE.max", 7); + config.set("xp-drops.EMERALD_ORE.min", 3); + config.set("xp-drops.EMERALD_ORE.max", 7); + config.set("xp-drops.DEEPSLATE_EMERALD_ORE.min", 3); + config.set("xp-drops.DEEPSLATE_EMERALD_ORE.max", 7); + config.set("xp-drops.LAPIS_ORE.min", 2); + config.set("xp-drops.LAPIS_ORE.max", 5); + config.set("xp-drops.DEEPSLATE_LAPIS_ORE.min", 2); + config.set("xp-drops.DEEPSLATE_LAPIS_ORE.max", 5); + config.set("xp-drops.REDSTONE_ORE.min", 1); + config.set("xp-drops.REDSTONE_ORE.max", 5); + config.set("xp-drops.DEEPSLATE_REDSTONE_ORE.min", 1); + config.set("xp-drops.DEEPSLATE_REDSTONE_ORE.max", 5); + config.set("xp-drops.NETHER_QUARTZ_ORE.min", 2); + config.set("xp-drops.NETHER_QUARTZ_ORE.max", 5); + config.set("xp-drops.NETHER_GOLD_ORE.min", 0); + config.set("xp-drops.NETHER_GOLD_ORE.max", 1); + config.set("xp-drops.SCULK.min", 1); + config.set("xp-drops.SCULK.max", 1); + config.set("xp-drops.SCULK_SENSOR.min", 5); + config.set("xp-drops.SCULK_SENSOR.max", 5); + config.set("xp-drops.SCULK_SHRIEKER.min", 5); + config.set("xp-drops.SCULK_SHRIEKER.max", 5); + config.set("xp-drops.SCULK_CATALYST.min", 5); + config.set("xp-drops.SCULK_CATALYST.max", 5); + config.set("xp-drops.CALIBRATED_SCULK_SENSOR.min", 5); + config.set("xp-drops.CALIBRATED_SCULK_SENSOR.max", 5); + config.set("xp-drops.SPAWNER.min", 15); + config.set("xp-drops.SPAWNER.max", 43); + plugin.getLogger().info("Added new xp-drops section to config with default values."); + } else { + plugin.getLogger().info("xp-drops section already exists, skipping creation."); + } + + // Update the configuration version to 1.2 + config.set("configVersion", CURRENT_VERSION); + plugin.getLogger().info("Config version updated to " + CURRENT_VERSION + "."); + } // STEP 6: Save Config (Now That Everything is Set) - config.set("configVersion", CURRENT_VERSION); - plugin.getLogger().info("Set configVersion to " + CURRENT_VERSION); plugin.saveConfig(); plugin.reloadConfig(); // Reload config, so recipes are correctly loaded plugin.getLogger().info("Config migration complete."); diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 91940ca..87453bd 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -765,6 +765,84 @@ recipes: - "NHN" - "ENE" +# ⚑ XP Drops Configuration +# ========================= +# +# πŸ”Ή What this does: +# - Defines the XP drop ranges for various block types when broken. +# - Each block material has a minimum and maximum XP value. +# - Changes require a server restart or running: `/powermining admin reload` +# +# πŸ”Ή How to Define XP Drop Ranges: +# - Use exact block material names from Spigot's Material list (case-sensitive). +# - Full list of valid materials: πŸ”— [Spigot API - Material List](https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/Material.html) +# - The range is defined using two keys: `min` and `max`. +# - Example: +# COAL_ORE: +# min: 0 +# max: 2 +# +# πŸ”Ή Important Notes: +# - Ensure that `max` is not less than `min` to avoid configuration errors. +# - Available default values can be found in the plugin documentation or GitHub. +# +# ⚑ Customize as needed! +xp-drops: + COAL_ORE: + min: 0 + max: 2 + DEEPSLATE_COAL_ORE: + min: 0 + max: 2 + DIAMOND_ORE: + min: 3 + max: 7 + DEEPSLATE_DIAMOND_ORE: + min: 3 + max: 7 + EMERALD_ORE: + min: 3 + max: 7 + DEEPSLATE_EMERALD_ORE: + min: 3 + max: 7 + LAPIS_ORE: + min: 2 + max: 5 + DEEPSLATE_LAPIS_ORE: + min: 2 + max: 5 + REDSTONE_ORE: + min: 1 + max: 5 + DEEPSLATE_REDSTONE_ORE: + min: 1 + max: 5 + NETHER_QUARTZ_ORE: + min: 2 + max: 5 + NETHER_GOLD_ORE: + min: 0 + max: 1 + SCULK: + min: 1 + max: 1 + SCULK_SENSOR: + min: 5 + max: 5 + SCULK_SHRIEKER: + min: 5 + max: 5 + SCULK_CATALYST: + min: 5 + max: 5 + CALIBRATED_SCULK_SENSOR: + min: 5 + max: 5 + SPAWNER: + min: 15 + max: 43 + # βš™οΈ Configuration Version # ------------------------ # This value tracks the version of the configuration file. @@ -773,7 +851,7 @@ recipes: # 🚨 Do NOT change this value! 🚨 # - Modifying it may cause the plugin to stop working. # - If there’s an issue, delete the config file and restart the server or reload the plugin to regenerate it. -configVersion: "1.0" +configVersion: "1.2" # πŸ› οΈ Debug Mode # ------------- diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 289d98a..7da6ac8 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: JodellePowerMining main: jodelle.powermining.PowerMining -version: 1.1.2 +version: 1.2 authors: [JodelleLover, Holt] description: Implements Hammer, Excavator and Plow tools for faster mining, version updated from BloodyShade. api-version: "1.21.4"