diff --git a/build.gradle b/build.gradle index d68b010..0c11539 100644 --- a/build.gradle +++ b/build.gradle @@ -35,11 +35,12 @@ repositories { } dependencies { - implementation 'de.tr7zw:item-nbt-api:2.12.1' - implementation 'com.github.Redempt:RedLib:6.5.8' - implementation 'com.github.cryptomorin:XSeries:9.7.0' - implementation 'com.github.Revxrsal.Lamp:common:3.1.5' - implementation 'com.github.Revxrsal.Lamp:bukkit:3.1.5' + implementation 'de.tr7zw:item-nbt-api:2.12.2' + implementation 'com.github.Redempt:RedLib:6.5.9' + implementation 'com.github.Redempt:Crunch:2.0' + implementation 'com.github.cryptomorin:XSeries:9.8.0' + implementation 'com.github.Revxrsal.Lamp:common:3.1.8' + implementation 'com.github.Revxrsal.Lamp:bukkit:3.1.8' implementation 'com.github.Sven65:Item-Names:1.0.0' compileOnly 'org.spigotmc:spigot-api:1.14.4-R0.1-SNAPSHOT' @@ -48,7 +49,7 @@ dependencies { } group = 'me.byteful.plugin' -version = '1.3.5.2' +version = '1.3.6' description = 'LevelTools' java.sourceCompatibility = JavaVersion.VERSION_1_8 diff --git a/src/main/java/me/byteful/plugin/leveltools/LevelToolsCommand.java b/src/main/java/me/byteful/plugin/leveltools/LevelToolsCommand.java index 1f42b44..5e06993 100644 --- a/src/main/java/me/byteful/plugin/leveltools/LevelToolsCommand.java +++ b/src/main/java/me/byteful/plugin/leveltools/LevelToolsCommand.java @@ -37,6 +37,7 @@ public void onReload(CommandSender sender) { plugin.reloadConfig(); plugin.setAnvilCombineMode(); + plugin.setLevelXpFormula(); sender.sendMessage(colorize(Objects.requireNonNull(plugin.getConfig().getString("messages.successful_reload")))); } diff --git a/src/main/java/me/byteful/plugin/leveltools/LevelToolsPlugin.java b/src/main/java/me/byteful/plugin/leveltools/LevelToolsPlugin.java index fbf3c59..4202808 100644 --- a/src/main/java/me/byteful/plugin/leveltools/LevelToolsPlugin.java +++ b/src/main/java/me/byteful/plugin/leveltools/LevelToolsPlugin.java @@ -8,6 +8,9 @@ import org.bukkit.Bukkit; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; +import redempt.crunch.CompiledExpression; +import redempt.crunch.Crunch; +import redempt.crunch.functional.EvaluationEnvironment; import redempt.redlib.blockdata.BlockDataManager; import redempt.redlib.misc.Task; import revxrsal.commands.bukkit.BukkitCommandHandler; @@ -15,7 +18,6 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.StandardCopyOption; import java.util.Objects; import java.util.concurrent.TimeUnit; @@ -26,6 +28,7 @@ public final class LevelToolsPlugin extends JavaPlugin { private BukkitCommandHandler commandManager; private AnvilCombineMode anvilCombineMode; private UpdateChecker updateChecker; + private CompiledExpression levelXpFormula; public static LevelToolsPlugin getInstance() { return instance; @@ -40,21 +43,7 @@ public void onEnable() { getDataFolder().mkdirs(); } - // Support older file names. final Path blocksFile = getDataFolder().toPath().resolve("player_placed_blocks.db"); - final Path oldFile = getDataFolder().toPath().resolve("blocks.db"); - if (Files.exists(oldFile)) { - if (Files.exists(blocksFile)) { - getLogger().warning("Found old 'blocks.db' file, but ignored it because a newer 'player_placed_blocks.db' file exists!"); - } else { - try { - Files.move(oldFile, blocksFile, StandardCopyOption.COPY_ATTRIBUTES); - getLogger().warning("Found old 'blocks.db' file... Renamed to newer 'player_placed_blocks.db' file."); - } catch (IOException e) { - e.printStackTrace(); - } - } - } if (!Files.exists(blocksFile)) { try { @@ -69,8 +58,9 @@ public void onEnable() { getLogger().info("Loaded BlockDataManager..."); saveDefaultConfig(); - getConfig().options().copyDefaults(); + getConfig().options().copyDefaults(true); setAnvilCombineMode(); + setLevelXpFormula(); getLogger().info("Loaded configuration..."); if (getConfig().getBoolean("update.start")) { @@ -121,6 +111,12 @@ public void setAnvilCombineMode() { anvilCombineMode = AnvilCombineMode.fromName(Objects.requireNonNull(getConfig().getString("anvil_combine"))); } + public void setLevelXpFormula() { + final EvaluationEnvironment env = new EvaluationEnvironment(); + env.setVariableNames("{current_level}"); + levelXpFormula = Crunch.compileExpression(getConfig().getString("level_xp_formula"), env); + } + public BlockDataManager getBlockDataManager() { return blockDataManager; } @@ -129,6 +125,10 @@ public AnvilCombineMode getAnvilCombineMode() { return anvilCombineMode; } + public CompiledExpression getLevelXpFormula() { + return levelXpFormula; + } + public BukkitCommandHandler getCommandManager() { return commandManager; } diff --git a/src/main/java/me/byteful/plugin/leveltools/api/item/LevelToolsItem.java b/src/main/java/me/byteful/plugin/leveltools/api/item/LevelToolsItem.java index d23f900..02a3751 100644 --- a/src/main/java/me/byteful/plugin/leveltools/api/item/LevelToolsItem.java +++ b/src/main/java/me/byteful/plugin/leveltools/api/item/LevelToolsItem.java @@ -5,6 +5,7 @@ import org.bukkit.enchantments.Enchantment; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import redempt.crunch.CompiledExpression; public interface LevelToolsItem { @NotNull ItemStack getItemStack(); @@ -22,41 +23,14 @@ public interface LevelToolsItem { void setLastHandledReward(int rewardKey); default double getMaxXp() { - final double xpStart = LevelToolsPlugin.getInstance().getConfig().getDouble("level_xp_start"); - double increaseAmount = LevelToolsPlugin.getInstance().getConfig().getDouble("level_xp_increase.amount"); - final String mode = LevelToolsPlugin.getInstance().getConfig().getString("level_xp_increase.mode"); + final CompiledExpression formula = LevelToolsPlugin.getInstance().getLevelXpFormula(); + final double nextXpRequirement = LevelToolsUtil.round(formula.evaluate(getLevel()), 1); - if (xpStart < 1.0) { - throw new RuntimeException("Failed to find valid value for 'level_xp_start'. Please make sure it is equal to or over 1.0. Check your configuration!"); + if (nextXpRequirement <= 0.0) { + throw new RuntimeException("The next XP requirement formula returned a value too small! Please optimize your formula."); } - if (increaseAmount < 1.0) { - throw new RuntimeException("Failed to find valid value for 'level_xp_increase -> amount'. Please make sure it is equal to or over 1.0. Check your configuration!"); - } - - if (mode == null) { - throw new RuntimeException("Failed to find valid value for 'level_xp_increase -> mode'. Please check your configuration!"); - } - - double nextXp = xpStart; - - if (getLevel() > 0) { - if (mode.equalsIgnoreCase("ADD")) { - nextXp = xpStart + (getLevel() * increaseAmount); - } else if (mode.equalsIgnoreCase("MULTIPLY")) { - nextXp = xpStart * (Math.pow(increaseAmount, getLevel() * 1.0)); - } else { - throw new RuntimeException("Mode for 'level_xp_increase' is not 'ADD' or 'MULTIPLY'. Please check your configuration!"); - } - } - - final double rounded = LevelToolsUtil.round(nextXp, 1); - - if (rounded <= 0.0) { - throw new RuntimeException("Failed to round " + nextXp + " to the first place. Please modify your values to get a better result! Check your configuration!"); - } - - return rounded; + return nextXpRequirement; } void enchant(Enchantment enchantment, int level); diff --git a/src/main/java/me/byteful/plugin/leveltools/listeners/XPListener.java b/src/main/java/me/byteful/plugin/leveltools/listeners/XPListener.java index a64707f..ac3f5a9 100644 --- a/src/main/java/me/byteful/plugin/leveltools/listeners/XPListener.java +++ b/src/main/java/me/byteful/plugin/leveltools/listeners/XPListener.java @@ -8,6 +8,7 @@ import me.byteful.plugin.leveltools.api.item.LevelToolsItem; import me.byteful.plugin.leveltools.util.LevelToolsUtil; import me.byteful.plugin.leveltools.util.Text; +import me.byteful.plugin.leveltools.util.XPBooster; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.configuration.ConfigurationSection; @@ -28,6 +29,7 @@ protected void handle(LevelToolsItem tool, Player player, double modifier) { return; } + modifier = Math.max(0, XPBooster.apply(player, modifier)); // It's best if we just prevent negative XP addition :) double newXp = LevelToolsUtil.round(tool.getXp() + modifier, 1); final LevelToolsXPIncreaseEvent xpEvent = new LevelToolsXPIncreaseEvent(tool, player, newXp, false); diff --git a/src/main/java/me/byteful/plugin/leveltools/util/XPBooster.java b/src/main/java/me/byteful/plugin/leveltools/util/XPBooster.java new file mode 100644 index 0000000..c05f2a5 --- /dev/null +++ b/src/main/java/me/byteful/plugin/leveltools/util/XPBooster.java @@ -0,0 +1,21 @@ +package me.byteful.plugin.leveltools.util; + +import me.byteful.plugin.leveltools.LevelToolsPlugin; +import org.bukkit.entity.Player; +import org.bukkit.permissions.PermissionAttachmentInfo; + +public final class XPBooster { + public static double apply(Player player, double xp) { + for (PermissionAttachmentInfo permission : player.getEffectivePermissions()) { + if (!permission.getValue() || !permission.getPermission().startsWith("leveltools.booster.")) continue; + + try { + xp *= Double.parseDouble(permission.getPermission().substring(19)); + } catch (Exception e) { + LevelToolsPlugin.getInstance().getLogger().warning("Failed to parse LevelTools XPBooster permission: " + permission.getPermission()); + } + } + + return xp; + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index f8db8c5..dad7d3e 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -33,15 +33,9 @@ messages: # Modes: "HIGHER_OF_BOTH" (Takes level and xp of higher level item), "LOWER_OF_BOTH" (Takes level and xp of lower level item), OR "ADD_BOTH" (Adds the level and XP of both items) anvil_combine: "ADD_BOTH" -# The amount of XP needed to get from level 0 to level 1. -level_xp_start: 100.0 - -# The increase in amount of XP needed to get from level to level. -# Ex: If we are on level 1 and the level_xp_start is on 100.0 and the mode is ADD with 100.0, it would take 200.0 XP to get to level 2 from level 1. -# Ex 2: If we are on level 1 and the level_xp_start is on 100.0 and the mode is MULTIPLY with 2.0, it would take 200.0 XP to get to level 2 from level 1. -level_xp_increase: - mode: "ADD" # Modes: "ADD" or "MULTIPLY" - amount: 100.0 +# The mathematical formula to calculate the required XP for next level. +# Placeholders/Variables provided: {current_level} +level_xp_formula: "100 + {current_level} * 100" # Should blocks that are placed by a player count towards XP? # May cause lag on a large server. Recommended to keep this true.