diff --git a/README.md b/README.md index f48852e..b5254ea 100644 --- a/README.md +++ b/README.md @@ -15,14 +15,15 @@ the plugin can be downloaded on the or [on GitHub](https://github.com/alexcrea/CustomAnvil/releases/latest) --- **Custom Anvil** have the following features: -- Vanilla like default configuration -- Custom enchantment level limit -- Custom anvil recipes -- Custom enchant restrictions (allow unsafe enchantment only for a group of item or create new restriction) -- Custom items of unit repairs (repair damaged with unit of "material", for example the repair of diamond sword by diamonds) -- Custom XP cost for every aspect of the anvil +- Vanilla like default configuration. +- Custom enchantment level limit. +- Custom anvil recipes. +- Custom enchant restrictions (allow unsafe enchantment only for a group of item or create new restriction). +- Custom items of unit repairs (repair damaged with unit of "material", for example the repair of diamond sword by diamonds). +- Custom XP cost for every aspect of the anvil. - Permissions to bypass level limit or enchantment restriction. -- Gui to configure the plugin in game +- Display xp cost instead of "to expensive" when above lv 40. (need ProtocoLib) +- Gui to configure the plugin in game. --- ### Permissions: ```yml @@ -54,8 +55,8 @@ Default configuration can be found on following links: There is non known issue, if you find one please report the issue. ### Planned: -- Semi manual config update on pluign or minecraft update -- Check unknow registered enchantment & warn -- Warn admin on unsuported minecraft version +- Semi manual config update on plugin or minecraft update +- Check unknown registered enchantment & warn +- Warn admin on unsupported minecraft version diff --git a/build.gradle.kts b/build.gradle.kts index 06420e2..6a58a40 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,11 +4,14 @@ plugins { } group = "xyz.alexcrea" -version = "1.4.4" +version = "1.4.5" repositories { mavenCentral() maven(url = "https://hub.spigotmc.org/nexus/content/repositories/snapshots/") + + // ProtocoLib + maven (url = "https://repo.dmulloy2.net/repository/public/" ) } dependencies { @@ -20,6 +23,8 @@ dependencies { // Gui library compileOnly("com.github.stefvanschie.inventoryframework:IF:0.10.13") + // Protocolib + compileOnly("com.comphenix.protocol:ProtocolLib:5.1.0") testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.0") diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/MainConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/MainConfigGui.java index 5046bb7..9b8fb90 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/MainConfigGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/MainConfigGui.java @@ -9,25 +9,26 @@ import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import xyz.alexcrea.cuanvil.gui.config.global.*; -import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; +import xyz.alexcrea.cuanvil.packet.PacketManager; import java.util.Collections; public class MainConfigGui extends ChestGui { - public final static MainConfigGui INSTANCE = new MainConfigGui(); + private final static MainConfigGui INSTANCE = new MainConfigGui(); - static { - INSTANCE.init(); + public static MainConfigGui getInstance() { + return INSTANCE; } private MainConfigGui() { super(3, "\u00A78Anvil Config", CustomAnvil.instance); + init(CustomAnvil.instance.packetManager); } - private void init() { + private void init(PacketManager packetManager) { Pattern pattern = new Pattern( "000000000", "012304567", @@ -47,7 +48,7 @@ public class MainConfigGui extends ChestGui { basicConfigMeta.setLore(Collections.singletonList("\u00A77Click here to open basic config menu")); basicConfigItemstack.setItemMeta(basicConfigMeta); - GuiItem basicConfigItem = GuiGlobalItems.goToGuiItem(basicConfigItemstack, BasicConfigGui.INSTANCE); + GuiItem basicConfigItem = GuiGlobalItems.goToGuiItem(basicConfigItemstack, new BasicConfigGui(packetManager)); pane.bindItem('1', basicConfigItem); // enchant level limit item diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/BasicConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/BasicConfigGui.java index 2e9bdd2..6476bec 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/BasicConfigGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/BasicConfigGui.java @@ -9,6 +9,7 @@ import kotlin.ranges.IntRange; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; import xyz.alexcrea.cuanvil.config.ConfigHolder; import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; import xyz.alexcrea.cuanvil.gui.config.MainConfigGui; @@ -17,7 +18,9 @@ import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; +import xyz.alexcrea.cuanvil.packet.PacketManager; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -26,17 +29,22 @@ import java.util.Collections; */ public class BasicConfigGui extends ValueUpdatableGui { - public final static BasicConfigGui INSTANCE = new BasicConfigGui(); + private static BasicConfigGui INSTANCE; - static { - INSTANCE.init(); + public static BasicConfigGui getInstance() { + return INSTANCE; } + private final PacketManager packetManager; /** * Constructor of this Global gui for basic settings. */ - private BasicConfigGui() { - super(3, "\u00A78Basic Config", CustomAnvil.instance); + public BasicConfigGui(PacketManager packetManager) { + super(4, "\u00A78Basic Config", CustomAnvil.instance); + INSTANCE = this; + + this.packetManager = packetManager; + init(); } PatternPane pane; @@ -47,67 +55,93 @@ public class BasicConfigGui extends ValueUpdatableGui { private void init() { Pattern pattern = new Pattern( GuiSharedConstant.EMPTY_GUI_FULL_LINE, - "012345670", + "0L0T0I0S0", + "0C0R0U0r0", "B00000000" ); - pane = new PatternPane(0, 0, 9, 3, pattern); + pane = new PatternPane(0, 0, 9, 4, pattern); addPane(pane); - GuiGlobalItems.addBackItem(pane, MainConfigGui.INSTANCE); + GuiGlobalItems.addBackItem(pane, MainConfigGui.getInstance()); GuiGlobalItems.addBackgroundItem(pane); prepareValues(); updateGuiValues(); } - private BoolSettingsGui.BoolSettingFactory limitRepairFactory; - private IntSettingsGui.IntSettingFactory repairCostFactory; - private GuiItem notNeededLimitValueItem; - private BoolSettingsGui.BoolSettingFactory removeRepairLimit; - private IntSettingsGui.IntSettingFactory itemRepairCost; - private IntSettingsGui.IntSettingFactory unitRepairCost; - private IntSettingsGui.IntSettingFactory itemRenameCost; - private IntSettingsGui.IntSettingFactory sacrificeIllegalEnchantCost; + private BoolSettingsGui.BoolSettingFactory capAnvilCostFactory; // L character + private GuiItem noCapRepairItem; + private IntSettingsGui.IntSettingFactory maxAnvilCostFactory; // C character + private GuiItem noMaxCostItem; + + private BoolSettingsGui.BoolSettingFactory removeAnvilCostLimit; // R character + private BoolSettingsGui.BoolSettingFactory replaceTooExpensive; // T character + + private IntSettingsGui.IntSettingFactory itemRepairCost; // I character + private IntSettingsGui.IntSettingFactory unitRepairCost; // U character + private IntSettingsGui.IntSettingFactory itemRenameCost; // r character + private IntSettingsGui.IntSettingFactory sacrificeIllegalEnchantCost; // S character /** * Prepare basic gui displayed items factory and static items.. */ protected void prepareValues() { - // limit repair item - this.limitRepairFactory = BoolSettingsGui.boolFactory("\u00A78Limit Repair Cost ?", this, - ConfigOptions.LIMIT_REPAIR_COST, ConfigHolder.DEFAULT_CONFIG, ConfigOptions.DEFAULT_LIMIT_REPAIR, - "\u00A77Whether all anvil actions cost should be capped.", - "\u00A77If true, all anvil repairs will max out at the value of \u00A7aLimit Repair Value\u00A77."); - - // repair cost item - IntRange range = ConfigOptions.REPAIR_LIMIT_RANGE; - this.repairCostFactory = IntSettingsGui.intFactory("\u00A78Repair Cost Limit", this, - ConfigOptions.LIMIT_REPAIR_VALUE, ConfigHolder.DEFAULT_CONFIG, - Arrays.asList( - "\u00A77Value to limit repair costs to when \u00A7aLimit Repair Value\u00A77 is true.", - "\u00A77Valid values include \u00A7e1 \u00A77to \u00A7e39\u00A77: " + - "vanilla would display \u00A7e40+\u00A77 as \u00A7ctoo expensive\u00A77." - ), - range.getFirst(), range.getLast(), - ConfigOptions.DEFAULT_LIMIT_REPAIR_VALUE, - 1, 5, 10); - - // repair cost not needed + // cap anvil cost + this.capAnvilCostFactory = BoolSettingsGui.boolFactory("\u00A78Cap Anvil Cost ?", this, + ConfigHolder.DEFAULT_CONFIG, + ConfigOptions.CAP_ANVIL_COST, ConfigOptions.DEFAULT_CAP_ANVIL_COST, + "\u00A77All anvil cost will be capped to \u00A7aMax Anvil Cost\u00A77 if enabled.", + "\u00A77In other words:", + "\u00A77For any anvil cost greater than \u00A7aMax Anvil Cost\u00A77, Cost will be set to \u00A7aMax Anvil Cost\u00A77."); + // cap anvil cost not needed ItemStack item = new ItemStack(Material.BARRIER); ItemMeta meta = item.getItemMeta(); assert meta != null; - meta.setDisplayName("\u00A7cLimit Repair Value"); - meta.setLore(Collections.singletonList("\u00A77This config need \u00A7cLimit Repair Cost\u00A77 enabled.")); + meta.setDisplayName("\u00A7cCap Anvil Cost ?"); + meta.setLore(Collections.singletonList("\u00A77This config only work if \u00A7cLimit Repair Cost\u00A77 is disabled.")); item.setItemMeta(meta); - this.notNeededLimitValueItem = new GuiItem(item, GuiGlobalActions.stayInPlace, CustomAnvil.instance); + this.noCapRepairItem = new GuiItem(item, GuiGlobalActions.stayInPlace, CustomAnvil.instance); + + + // repair cost item + IntRange range = ConfigOptions.MAX_ANVIL_COST_RANGE; + this.maxAnvilCostFactory = IntSettingsGui.intFactory("\u00A78Max Anvil Cost", this, + ConfigOptions.MAX_ANVIL_COST, ConfigHolder.DEFAULT_CONFIG, + Arrays.asList( + "\u00A77Max cost the Anvil can get to.", + "\u00A77Valid values include \u00A7e0 \u00A77to \u00A7e1000\u00A77.", + "\u00A77Cost will be displayed as \u00A7cToo Expensive\u00A77:", + "\u00A77- If Cost is above \u00A7e39", + "\u00A77- And \u00A7eReplace Too Expensive\u00A77 is disabled" + ), + range.getFirst(), range.getLast(), + ConfigOptions.DEFAULT_MAX_ANVIL_COST, + 1, 5, 10); + // max anvil cost not needed + item = new ItemStack(Material.BARRIER); + meta = item.getItemMeta(); + assert meta != null; + + meta.setDisplayName("\u00A7cMax Anvil Cost"); + meta.setLore(Collections.singletonList("\u00A77This config only work if \u00A7cLimit Repair Cost\u00A77 is disabled.")); + item.setItemMeta(meta); + this.noMaxCostItem = new GuiItem(item, GuiGlobalActions.stayInPlace, CustomAnvil.instance); + // remove repair limit item - this.removeRepairLimit = BoolSettingsGui.boolFactory("\u00A78Remove Repair Limit ?", this, - ConfigOptions.REMOVE_REPAIR_LIMIT, ConfigHolder.DEFAULT_CONFIG, ConfigOptions.DEFAULT_REMOVE_LIMIT, - "\u00A77Whether the anvil's repair limit should be removed entirely.", - "\u00A77The anvil will still visually display \u00A7ctoo expensive\u00A77.", - "\u00A77However the action will be completable."); + this.removeAnvilCostLimit = BoolSettingsGui.boolFactory("\u00A78Remove Anvil Cost Limit ?", this, + ConfigHolder.DEFAULT_CONFIG, + ConfigOptions.REMOVE_ANVIL_COST_LIMIT, ConfigOptions.DEFAULT_REMOVE_ANVIL_COST_LIMIT, + "\u00A77Whether the anvil's cost limit should be removed entirely.", + "\u00A77The anvil will still visually display \u00A7cToo Expensive\u00A77 if \u00A7eReplace Too Expensive\u00A77 is disabled.", + "\u00A77However, the action will be completable if xp requirement is meet."); + + // replace too expensive item + this.replaceTooExpensive = BoolSettingsGui.boolFactory("\u00A78Replace Too Expensive ?", this, + ConfigHolder.DEFAULT_CONFIG, + ConfigOptions.REPLACE_TOO_EXPENSIVE, ConfigOptions.DEFAULT_REPLACE_TOO_EXPENSIVE, + getReplaceToExpensiveLore()); // item repair cost range = ConfigOptions.REPAIR_COST_RANGE; @@ -158,40 +192,63 @@ public class BasicConfigGui extends ValueUpdatableGui { } + @NotNull + private String[] getReplaceToExpensiveLore() { + ArrayList lore = new ArrayList<>(); + lore.add("\u00A77Whenever anvil cost is above \u00A7e39\u00A77 should display the true price and not \u00A7cToo Expensive\u00A77."); + lore.add("\u00A77However, when bypassing \u00A7cToo Expensive\u00A77, anvil price will be displayed as \u00A7aGreen\u00A77."); + lore.add("\u00A77Even if cost is displayed as \u00A7aGreen\u00A77:"); + lore.add("\u00A77If the player do not have the required xp level, the action will not be completable."); + + if(!this.packetManager.isProtocoLibInstalled()){ + lore.add(""); + lore.add("\u00A74/!\\\u00A7cCaution/!\\ \u00A7cYou need ProtocoLib installed for this to work."); + } + + String[] loreAsArray = new String[lore.size()]; + return lore.toArray(loreAsArray); + } + @Override public void updateGuiValues() { - // limit repair item - GuiItem limitRepairItem = this.limitRepairFactory.getItem(); - pane.bindItem('1', limitRepairItem); - - // rename cost item - GuiItem limitRepairValueItem; - if (this.limitRepairFactory.getConfiguredValue()) { - limitRepairValueItem = this.repairCostFactory.getItem(Material.EXPERIENCE_BOTTLE); + // limit and cap anvil cost item + GuiItem capAnvilCostItem; + GuiItem maxAnvilCostItem; + if (!this.removeAnvilCostLimit.getConfiguredValue()) { + capAnvilCostItem = this.capAnvilCostFactory.getItem("Cap Anvil Cost"); + maxAnvilCostItem = this.maxAnvilCostFactory.getItem(Material.EXPERIENCE_BOTTLE, "Max Anvil Cost"); } else { - limitRepairValueItem = this.notNeededLimitValueItem; + capAnvilCostItem = this.noCapRepairItem; + maxAnvilCostItem = this.noMaxCostItem; } - pane.bindItem('2', limitRepairValueItem); + + pane.bindItem('L', capAnvilCostItem); + pane.bindItem('C', maxAnvilCostItem); // remove repair limit item - GuiItem removeRepairLimitItem = this.removeRepairLimit.getItem(); - pane.bindItem('3', removeRepairLimitItem); + GuiItem removeRepairLimitItem = this.removeAnvilCostLimit.getItem("Remove Anvil Cost Limit"); + pane.bindItem('R', removeRepairLimitItem); + + // replace too expensive item + GuiItem replaceToExpensiveItem = this.replaceTooExpensive.getItem(); + pane.bindItem('T', replaceToExpensiveItem); + // item repair cost GuiItem itemRepairCostItem = this.itemRepairCost.getItem(Material.ANVIL); - pane.bindItem('4', itemRepairCostItem); + pane.bindItem('I', itemRepairCostItem); // unit repair cost GuiItem unitRepairCostItem = this.unitRepairCost.getItem(Material.DIAMOND); - pane.bindItem('5', unitRepairCostItem); + pane.bindItem('U', unitRepairCostItem); // item rename cost GuiItem itemRenameCost = this.itemRenameCost.getItem(Material.NAME_TAG); - pane.bindItem('6', itemRenameCost); + pane.bindItem('r', itemRenameCost); // sacrifice illegal enchant cost GuiItem illegalCostItem = this.sacrificeIllegalEnchantCost.getItem(Material.ENCHANTED_BOOK); - pane.bindItem('7', illegalCostItem); + pane.bindItem('S', illegalCostItem); update(); } diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/EnchantCostConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/EnchantCostConfigGui.java index 1e85c90..dc3d2d9 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/EnchantCostConfigGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/global/EnchantCostConfigGui.java @@ -51,7 +51,7 @@ public class EnchantCostConfigGui extends AbstractEnchantConfigGui extends ValueUpdatableGui { // Back item panel Pattern pattern = getBackgroundPattern(); this.backgroundPane = new PatternPane(0, 0, 9, 6, Pane.Priority.LOW, pattern); - GuiGlobalItems.addBackItem(this.backgroundPane, MainConfigGui.INSTANCE); + GuiGlobalItems.addBackItem(this.backgroundPane, MainConfigGui.getInstance()); } diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/UnitRepairElementListGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/UnitRepairElementListGui.java index b4a1d6d..3a571f2 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/UnitRepairElementListGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/UnitRepairElementListGui.java @@ -116,8 +116,8 @@ public class UnitRepairElementListGui extends SettingGuiListConfigGui displayLore, int scale, boolean asPercentage, boolean nullOnZero, double min, double max, double defaultVal, double... steps) { return new DoubleSettingFactory( title, parent, - configPath, config, + config, + configPath, displayLore, scale, asPercentage, nullOnZero, min, max, defaultVal, steps); @@ -408,8 +410,8 @@ public class DoubleSettingGui extends AbstractSettingGui { * * @param title The title of the gui. * @param parent Parent gui to go back when completed. - * @param configPath Configuration path of this setting. * @param config Configuration holder of this setting. + * @param configPath Configuration path of this setting. * @param displayLore Gui display item lore. * @param scale The scale of the decimal. * @param asPercentage If we should display the value as a %. @@ -424,7 +426,8 @@ public class DoubleSettingGui extends AbstractSettingGui { */ protected DoubleSettingFactory( @NotNull String title, @NotNull ValueUpdatableGui parent, - @NotNull String configPath, @NotNull ConfigHolder config, + @NotNull ConfigHolder config, + @NotNull String configPath, @Nullable List displayLore, int scale, boolean asPercentage, boolean nullOnZero, double min, double max, double defaultVal, double... steps) { diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/EnchantCostSettingsGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/EnchantCostSettingsGui.java index 50df43b..0e3c3f8 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/EnchantCostSettingsGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/EnchantCostSettingsGui.java @@ -243,8 +243,8 @@ public class EnchantCostSettingsGui extends IntSettingsGui { * * @param title The title of the gui. * @param parent Parent gui to go back when completed. - * @param configPath Configuration path of this setting. * @param config Configuration holder of this setting. + * @param configPath Configuration path of this setting. * @param displayLore Gui display item lore. * @param min Minimum value of this setting. * @param max Maximum value of this setting. @@ -258,7 +258,7 @@ public class EnchantCostSettingsGui extends IntSettingsGui { */ public static EnchantCostSettingFactory enchantCostFactory( @NotNull String title, @NotNull ValueUpdatableGui parent, - @NotNull String configPath, @NotNull ConfigHolder config, + @NotNull ConfigHolder config, @NotNull String configPath, @Nullable List displayLore, int min, int max, int defaultItemVal, int defaultBookVal, int... steps) { diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiSharedConstant.java b/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiSharedConstant.java index 1c492b1..a35076d 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiSharedConstant.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/util/GuiSharedConstant.java @@ -46,7 +46,7 @@ public class GuiSharedConstant { ); BACK_TO_MAIN_MENU_BIG_LIST_DISPLAY_BACKGROUND_PANE = new PatternPane(0, 0, 9, 6, Pane.Priority.LOW, pattern); - GuiGlobalItems.addBackItem(BACK_TO_MAIN_MENU_BIG_LIST_DISPLAY_BACKGROUND_PANE, MainConfigGui.INSTANCE); + GuiGlobalItems.addBackItem(BACK_TO_MAIN_MENU_BIG_LIST_DISPLAY_BACKGROUND_PANE, MainConfigGui.getInstance()); GuiGlobalItems.addBackgroundItem(BACK_TO_MAIN_MENU_BIG_LIST_DISPLAY_BACKGROUND_PANE); BACK_TO_MAIN_MENU_BIG_LIST_DISPLAY_BACKGROUND_PANE.bindItem('1', GuiSharedConstant.SECONDARY_BACKGROUND_ITEM); diff --git a/src/main/kotlin/io/delilaheve/AnvilEventListener.kt b/src/main/kotlin/io/delilaheve/AnvilEventListener.kt index 4138695..fd9bfdd 100644 --- a/src/main/kotlin/io/delilaheve/AnvilEventListener.kt +++ b/src/main/kotlin/io/delilaheve/AnvilEventListener.kt @@ -19,6 +19,7 @@ import org.bukkit.event.EventPriority.HIGHEST import org.bukkit.event.Listener import org.bukkit.event.inventory.ClickType import org.bukkit.event.inventory.InventoryClickEvent +import org.bukkit.event.inventory.InventoryCloseEvent import org.bukkit.event.inventory.PrepareAnvilEvent import org.bukkit.inventory.AnvilInventory import org.bukkit.inventory.InventoryView.Property.REPAIR_COST @@ -26,6 +27,7 @@ import org.bukkit.inventory.ItemStack import org.bukkit.inventory.meta.Repairable import xyz.alexcrea.cuanvil.config.ConfigHolder import xyz.alexcrea.cuanvil.group.ConflictType +import xyz.alexcrea.cuanvil.packet.PacketManager import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair import kotlin.math.min @@ -34,7 +36,7 @@ import kotlin.math.min /** * Listener for anvil events */ -class AnvilEventListener : Listener { +class AnvilEventListener(private val packetManager: PacketManager) : Listener { companion object { // Anvil's output slot @@ -97,7 +99,6 @@ class AnvilEventListener : Listener { // Test for merge if (first.canMergeWith(second)) { - val newEnchants = first.findEnchantments() .combineWith(second.findEnchantments(), first.type, player) val resultItem = first.clone() @@ -208,7 +209,6 @@ class AnvilEventListener : Listener { if ((output == inventory.getItem(ANVIL_INPUT_LEFT)) || !allowed ) { - event.result = Event.Result.DENY return } @@ -332,6 +332,13 @@ class AnvilEventListener : Listener { repairCost += calculatePenalty(leftItem, null, resultCopy) repairCost += resultAmount * ConfigOptions.unitRepairCost + if ( + !ConfigOptions.doRemoveCostLimit && + ConfigOptions.doCapCost) { + + repairCost = min(repairCost, ConfigOptions.maxAnvilCost) + } + if ((inventory.maximumRepairCost < repairCost) || (player.level < repairCost) ) return @@ -520,8 +527,11 @@ class AnvilEventListener : Listener { ignoreRules: Boolean = false ) { // Test repair cost limit - val finalAnvilCost = if (ConfigOptions.limitRepairCost && !ignoreRules) { - min(anvilCost, ConfigOptions.limitRepairValue) + val finalAnvilCost = if ( + !ignoreRules && + !ConfigOptions.doRemoveCostLimit && + ConfigOptions.doCapCost) { + min(anvilCost, ConfigOptions.maxAnvilCost) } else { anvilCost } @@ -533,25 +543,45 @@ class AnvilEventListener : Listener { .server .scheduler .runTask(CustomAnvil.instance, Runnable { - if (ConfigOptions.removeRepairLimit || ignoreRules) { - inventory.maximumRepairCost = Int.MAX_VALUE - } else{ - inventory.maximumRepairCost = 40 // minecraft default - } - inventory.repairCost = finalAnvilCost + inventory.maximumRepairCost = + if (ConfigOptions.doRemoveCostLimit || ignoreRules) + { Int.MAX_VALUE } + else + { ConfigOptions.maxAnvilCost + 1 } + inventory.repairCost = finalAnvilCost event.view.setProperty(REPAIR_COST, finalAnvilCost) val player = event.view.player if(player is Player){ + if(player.gameMode != GameMode.CREATIVE ){ + val bypassToExpensive = (ConfigOptions.doReplaceTooExpensive) && + (finalAnvilCost >= 40) && + finalAnvilCost < inventory.maximumRepairCost + + packetManager.setInstantBuild(player, bypassToExpensive) + } + player.updateInventory() } }) } + @EventHandler + fun onAnvilClose(event: InventoryCloseEvent){ + val player = event.player + if(event.inventory !is AnvilInventory) return + if(player is Player && GameMode.CREATIVE != player.gameMode){ + packetManager.setInstantBuild(player, false) + } + + } + } + + private class SlotContainer(val type: SlotType, val slot: Int) private enum class SlotType { CURSOR, diff --git a/src/main/kotlin/io/delilaheve/CustomAnvil.kt b/src/main/kotlin/io/delilaheve/CustomAnvil.kt index 52ee56e..3948676 100644 --- a/src/main/kotlin/io/delilaheve/CustomAnvil.kt +++ b/src/main/kotlin/io/delilaheve/CustomAnvil.kt @@ -8,6 +8,9 @@ import xyz.alexcrea.cuanvil.command.EditConfigExecutor import xyz.alexcrea.cuanvil.command.ReloadExecutor import xyz.alexcrea.cuanvil.config.ConfigHolder import xyz.alexcrea.cuanvil.listener.ChatEventListener +import xyz.alexcrea.cuanvil.packet.NoProtocoLib +import xyz.alexcrea.cuanvil.packet.PacketManager +import xyz.alexcrea.cuanvil.packet.ProtocoLibWrapper import xyz.alexcrea.cuanvil.util.Metrics import xyz.alexcrea.cuanvil.util.MetricsUtil import java.io.File @@ -66,14 +69,20 @@ class CustomAnvil : JavaPlugin() { instance.logger.info(message) } } + + } + lateinit var packetManager: PacketManager + /** * Setup plugin for use */ override fun onEnable() { instance = this + val pluginManager = Bukkit.getPluginManager(); + // Disable old plugin name if exist val potentialPlugin = Bukkit.getPluginManager().getPlugin("UnsafeEnchantsPlus") if (potentialPlugin != null) { @@ -82,9 +91,15 @@ class CustomAnvil : JavaPlugin() { logger.warning("Please note CustomAnvil is a more recent version of UnsafeEnchantsPlus") } + // Load ProtocolLib dependency if exist + packetManager = if(pluginManager.isPluginEnabled("ProtocolLib")) + { ProtocoLibWrapper(); } + else + { NoProtocoLib(); } + // Load chat listener chatListener = ChatEventListener() - Bukkit.getPluginManager().registerEvents(chatListener, this) + pluginManager.registerEvents(chatListener, this) // Load config val success = ConfigHolder.loadConfig() @@ -98,7 +113,7 @@ class CustomAnvil : JavaPlugin() { prepareCommand() server.pluginManager.registerEvents( - AnvilEventListener(), + AnvilEventListener(packetManager), this ) } diff --git a/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt b/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt index b9cfa7a..2ee3749 100644 --- a/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt +++ b/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt @@ -10,14 +10,17 @@ import xyz.alexcrea.cuanvil.config.ConfigHolder */ object ConfigOptions { - // Path for default enchantment limits - private const val DEFAULT_LIMIT_PATH = "default_limit" + // Path for limiting anvil cost + const val CAP_ANVIL_COST = "limit_repair_cost" - // Path for limiting repair cost - const val LIMIT_REPAIR_COST = "limit_repair_cost" + // Path for max anvil cost value + const val MAX_ANVIL_COST = "limit_repair_value" - // Path for repair value limit - const val LIMIT_REPAIR_VALUE = "limit_repair_value" + // Path for removing anvil cost limits + const val REMOVE_ANVIL_COST_LIMIT = "remove_repair_limit" + + // Path for removing too expensive when unused + const val REPLACE_TOO_EXPENSIVE = "replace_too_expensive" // Path for level cost on item repair const val ITEM_REPAIR_COST = "item_repair_cost" @@ -31,12 +34,14 @@ object ConfigOptions { // Path for level cost on illegal enchantment on sacrifice const val SACRIFICE_ILLEGAL_COST = "sacrifice_illegal_enchant_cost" - // Path for removing repair cost limits - const val REMOVE_REPAIR_LIMIT = "remove_repair_limit" + // Path for default enchantment limits + private const val DEFAULT_LIMIT_PATH = "default_limit" + // Root path for enchantment limits const val ENCHANT_LIMIT_ROOT = "enchant_limits" + // Root path for enchantment values const val ENCHANT_VALUES_ROOT = "enchant_values" @@ -44,20 +49,25 @@ object ConfigOptions { private const val KEY_BOOK = "book" private const val KEY_ITEM = "item" + // Debug logging toggle path private const val DEBUG_LOGGING = "debug_log" // Debug verbose logging toggle path private const val VERBOSE_DEBUG_LOGGING = "debug_log_verbose" - // Default value for enchantment limits - private const val DEFAULT_ENCHANT_LIMIT = 5 // Default value for limiting repair cost - const val DEFAULT_LIMIT_REPAIR = false + const val DEFAULT_CAP_ANVIL_COST = false // Default value for repair cost limit - const val DEFAULT_LIMIT_REPAIR_VALUE = 39 + const val DEFAULT_MAX_ANVIL_COST = 39 + + // Default for removing repair cost limits + const val DEFAULT_REMOVE_ANVIL_COST_LIMIT = false + + // Default for removing repair cost limits + const val DEFAULT_REPLACE_TOO_EXPENSIVE = false // Default value for level cost on item repair const val DEFAULT_ITEM_REPAIR_COST = 2 @@ -71,31 +81,9 @@ object ConfigOptions { // Default value for level cost on illegal enchantment on sacrifice const val DEFAULT_SACRIFICE_ILLEGAL_COST = 1 - // Valid range for repair cost limit - @JvmField - val REPAIR_LIMIT_RANGE = 1..39 - // Valid range for repair cost - @JvmField - val REPAIR_COST_RANGE = 0..255 - - // Valid range for rename cost - @JvmField - val ITEM_RENAME_COST_RANGE = 0..255 - - // Valid range for illegal enchantment conflict cost - @JvmField - val SACRIFICE_ILLEGAL_COST_RANGE = 0..255 - - // Default for removing repair cost limits - const val DEFAULT_REMOVE_LIMIT = false - - // Valid range for an enchantment limit - @JvmField - val ENCHANT_LIMIT_RANGE = 1..255 - - // Default value for an enchantment multiplier - private const val DEFAULT_ENCHANT_VALUE = 0 + // Default value for enchantment limits + private const val DEFAULT_ENCHANT_LIMIT = 5 // Default value for debug logging private const val DEFAULT_DEBUG_LOG = false @@ -103,36 +91,71 @@ object ConfigOptions { // Default value for debug logging private const val DEFAULT_VERBOSE_DEBUG_LOG = false + + // Valid range for repair cost limit + @JvmField + val MAX_ANVIL_COST_RANGE = 0..1000 + + // Valid range for repair cost + @JvmField + val REPAIR_COST_RANGE = 0..1000 + + // Valid range for rename cost + @JvmField + val ITEM_RENAME_COST_RANGE = 0..1000 + + // Valid range for illegal enchantment conflict cost + @JvmField + val SACRIFICE_ILLEGAL_COST_RANGE = 0..1000 + + // Valid range for an enchantment limit + @JvmField + val ENCHANT_LIMIT_RANGE = 1..255 + + + // Default value for an enchantment multiplier + private const val DEFAULT_ENCHANT_VALUE = 0 + /** - * Default enchantment limit + * Whether to cap anvil costs */ - private val defaultEnchantLimit: Int + val doCapCost: Boolean get() { return ConfigHolder.DEFAULT_CONFIG .config - .getInt(DEFAULT_LIMIT_PATH, DEFAULT_ENCHANT_LIMIT) + .getBoolean(CAP_ANVIL_COST, DEFAULT_CAP_ANVIL_COST) } /** - * Whether to limit repair costs to the vanilla limit + * Value to limit anvil costs to */ - val limitRepairCost: Boolean + val maxAnvilCost: Int get() { return ConfigHolder.DEFAULT_CONFIG .config - .getBoolean(LIMIT_REPAIR_COST, DEFAULT_LIMIT_REPAIR) + .getInt(MAX_ANVIL_COST, DEFAULT_MAX_ANVIL_COST) + .takeIf { it in MAX_ANVIL_COST_RANGE } + ?: DEFAULT_MAX_ANVIL_COST } /** - * Value to limit repair costs to + * Whether to remove anvil cost limit */ - val limitRepairValue: Int + val doRemoveCostLimit: Boolean get() { return ConfigHolder.DEFAULT_CONFIG .config - .getInt(LIMIT_REPAIR_VALUE, DEFAULT_LIMIT_REPAIR_VALUE) - .takeIf { it in REPAIR_LIMIT_RANGE } - ?: DEFAULT_LIMIT_REPAIR_VALUE + .getBoolean(REMOVE_ANVIL_COST_LIMIT, DEFAULT_REMOVE_ANVIL_COST_LIMIT) + } + + /** + * Whether to remove repair cost limit + */ + val doReplaceTooExpensive: Boolean + get() { + return ConfigHolder.DEFAULT_CONFIG + .config + .getBoolean(REPLACE_TOO_EXPENSIVE, DEFAULT_REPLACE_TOO_EXPENSIVE) } /** @@ -184,13 +207,13 @@ object ConfigOptions { } /** - * Whether to remove repair cost limit + * Default enchantment limit */ - val removeRepairLimit: Boolean + private val defaultEnchantLimit: Int get() { return ConfigHolder.DEFAULT_CONFIG .config - .getBoolean(REMOVE_REPAIR_LIMIT, DEFAULT_REMOVE_LIMIT) + .getInt(DEFAULT_LIMIT_PATH, DEFAULT_ENCHANT_LIMIT) } /** @@ -292,13 +315,14 @@ object ConfigOptions { fun getBasicConfigKeys(): Array { return arrayOf( DEFAULT_LIMIT_PATH, - LIMIT_REPAIR_COST, - LIMIT_REPAIR_VALUE, + CAP_ANVIL_COST, + MAX_ANVIL_COST, + REPLACE_TOO_EXPENSIVE, ITEM_REPAIR_COST, UNIT_REPAIR_COST, ITEM_RENAME_COST, SACRIFICE_ILLEGAL_COST, - REMOVE_REPAIR_LIMIT + REMOVE_ANVIL_COST_LIMIT ) } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt index 8b188ab..e05a4f2 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt @@ -16,7 +16,7 @@ class EditConfigExecutor : CommandExecutor { return false } if (sender !is HumanEntity) return false - MainConfigGui.INSTANCE.show(sender) + MainConfigGui.getInstance().show(sender) return true } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt index 841773f..50ef1c8 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt @@ -36,7 +36,7 @@ class ReloadExecutor : CommandExecutor { if (!ConfigHolder.reloadAllFromDisk(hardfail)) return false // Then update all global gui containing value from config - BasicConfigGui.INSTANCE.updateGuiValues() + BasicConfigGui.getInstance()?.updateGuiValues() EnchantCostConfigGui.INSTANCE.updateGuiValues() EnchantLimitConfigGui.INSTANCE.updateGuiValues() diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/packet/NoProtocoLib.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/packet/NoProtocoLib.kt new file mode 100644 index 0000000..29c2074 --- /dev/null +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/packet/NoProtocoLib.kt @@ -0,0 +1,13 @@ +package xyz.alexcrea.cuanvil.packet + +import org.bukkit.entity.Player + +class NoProtocoLib: PacketManager { + override val isProtocoLibInstalled: Boolean + get() = false + + // ProtocoLib not installed: We do nothing + + override fun setInstantBuild(player: Player, instantBuild: Boolean) {} + +} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/packet/PacketManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/packet/PacketManager.kt new file mode 100644 index 0000000..a59a48c --- /dev/null +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/packet/PacketManager.kt @@ -0,0 +1,11 @@ +package xyz.alexcrea.cuanvil.packet + +import org.bukkit.entity.Player + +interface PacketManager { + + val isProtocoLibInstalled: Boolean + + fun setInstantBuild(player: Player, instantBuild: Boolean) + +} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/packet/ProtocoLibWrapper.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/packet/ProtocoLibWrapper.kt new file mode 100644 index 0000000..f7e5e92 --- /dev/null +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/packet/ProtocoLibWrapper.kt @@ -0,0 +1,39 @@ +package xyz.alexcrea.cuanvil.packet + +import com.comphenix.protocol.PacketType +import com.comphenix.protocol.ProtocolLibrary +import com.comphenix.protocol.ProtocolManager +import com.comphenix.protocol.events.PacketContainer +import org.bukkit.entity.Player +import java.lang.reflect.InvocationTargetException + +class ProtocoLibWrapper: PacketManager { + + private val protocolManager: ProtocolManager = ProtocolLibrary.getProtocolManager(); + + override val isProtocoLibInstalled: Boolean + get() = true + + override fun setInstantBuild(player: Player, instantBuild: Boolean) { + val packet = PacketContainer(PacketType.Play.Server.ABILITIES) + + // Set player's properties + packet.float + .write(0, player.flySpeed / 2) + .write(1, player.walkSpeed / 2) + + packet.booleans + .write(0, player.isInvulnerable) + .write(1, player.isFlying) + .write(2, player.allowFlight) + .write(3, instantBuild) + + // Send packet + try { + protocolManager.sendServerPacket(player, packet) + } catch (e: InvocationTargetException) { + e.printStackTrace() + } + } + +} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/MetricsUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/MetricsUtil.kt index 46f7cf5..3d080f1 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/MetricsUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/MetricsUtil.kt @@ -7,7 +7,7 @@ import xyz.alexcrea.cuanvil.config.ConfigHolder object MetricsUtil { - private const val baseConfigHash = -1592940914 + private const val baseConfigHash = 1000387384 private const val enchantLimitsConfigHash = -275034280 private const val enchantValuesConfigHash = -17048020 private const val enchantConflictConfigHash = 546475833 diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 98784be..aa09cf4 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,44 +1,58 @@ -# Whether all anvil actions cost should be capped +# All anvil cost will be capped to limit_repair_value if enabled. # -# If true, all anvil repairs will max out at the value of limit_repair_value +# In other words: +# For any anvil cost greater than limit_repair_value, Cost will be set to limit_repair_value. limit_repair_cost: false -# Value to limit repair costs to when limit_repair_cost is true +# Max cost value the Anvil can get to. # -# Valid values include 1 to 39 (vanilla will consider 40+ as "too expensive") +# Valid values include 0 to 1000. +# Cost will be displayed as "Too Expensive": +# - If Cost is above 39 +# - And replace_too_expensive is disabled (false) limit_repair_value: 39 -# Whether the anvil's repair limit should be removed entirely +# Whether the anvil's cost limit should be removed entirely. # -# The anvil will still visually display "too expensive" however the action will be completable +# The anvil will still visually display "Too Expensive" if "replace_too_expensive" is disabled +# However, the action will be completable if xp requirement is meet. remove_repair_limit: false +# Whenever anvil cost is above 39 should display the true price and not "Too Expensive". +# +# However, when bypassing "Too Expensive", anvil price will be displayed as Green. +# If the action is not completable, the cost will still be displayed as "Too expensive". +# That mean you also need to change other settings like remove_repair_limit or limit_repair_cost. +# +# Require ProtocoLib. +replace_too_expensive: false + # XP Level amount added to the anvil when the item is repaired by another item of the same type # -# Valid values include 0 to 255 +# Valid values include 0 to 1000 item_repair_cost: 2 +# XP Level amount added to the anvil when the item is renamed +# +# Valid values include 0 to 1000 +item_rename_cost: 1 + # XP Level amount added to the anvil when the item is repaired by an "unit" # For example: a Diamond on a Diamond Sword # What's considered unit for what can be edited on the unit repair configuration. # -# Valid values include 0 to 255 +# Valid values include 0 to 1000 unit_repair_cost: 1 -# XP Level amount added to the anvil when the item is renamed -# -# Valid values include 0 to 255 -item_rename_cost: 1 - # XP Level amount added to the anvil when a sacrifice enchantment # conflict with one of the left item enchantment # -# Valid values include 0 to 255 +# Valid values include 0 to 1000 sacrifice_illegal_enchant_cost: 1 # Default limit to apply to any enchants missing from override_limits # -# Valid values include 1 to 255 +# Valid values include 1 to 1000 default_limit: 5 # Override limits for specific enchants @@ -229,4 +243,4 @@ debug_log: false # Whether to show verbose debug logging debug_log_verbose: false -configVersion: 1.4.3 +configVersion: 1.4.5 diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 53c5951..b9873d6 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,7 +1,7 @@ main: io.delilaheve.CustomAnvil name: CustomAnvil prefix: "Custom Anvil" -version: 1.4.4 +version: 1.4.5 description: Allow to customise anvil mechanics api-version: 1.18 load: POSTWORLD @@ -44,4 +44,5 @@ permissions: # soft depend on old name, so I can disable it if it is on the same server # as it is the old name for this plugin softdepend: - - UnsafeEnchantsPlus \ No newline at end of file + - UnsafeEnchantsPlus + - ProtocolLib