diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/event/CAConfigReadyEvent.java b/src/main/java/xyz/alexcrea/cuanvil/api/event/CAConfigReadyEvent.java index 24691db..67d27a8 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/api/event/CAConfigReadyEvent.java +++ b/src/main/java/xyz/alexcrea/cuanvil/api/event/CAConfigReadyEvent.java @@ -3,6 +3,23 @@ package xyz.alexcrea.cuanvil.api.event; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +/** + * Called when the configuration of CustomAnvil is ready. + * It is called either on the plugin startup or on the plugin config reload. + *

+ * If you want to listen to the first trigger of this event (first configuration load. aka plugin load) + * you will need to register the listener on your plugin onEnable or earlier + *

+ * This event indicate that can start to register your recipes, item groups and conflicts. + * The vanilla and custom enchantments should already have been provided to CustomAnvil. + * Configuration can be changed any time after this event is triggered but never before. + *

+ * use {@link xyz.alexcrea.cuanvil.api.ConflictAPI ConflictApi}, + * {@link xyz.alexcrea.cuanvil.gui.config.global.CustomRecipeConfigGui CustomRecipeConfigGui}, + * {@link xyz.alexcrea.cuanvil.api.MaterialGroupApi MaterialGroupApi} + * and {@link xyz.alexcrea.cuanvil.api.UnitRepairApi UnitRepairApi} + * to add/remove/edit configurations + */ public class CAConfigReadyEvent extends Event { private static final HandlerList HANDLERS = new HandlerList(); diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/event/CAEnchantRegistryReadyEvent.java b/src/main/java/xyz/alexcrea/cuanvil/api/event/CAEnchantRegistryReadyEvent.java index 3e2fdf8..3ffe372 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/api/event/CAEnchantRegistryReadyEvent.java +++ b/src/main/java/xyz/alexcrea/cuanvil/api/event/CAEnchantRegistryReadyEvent.java @@ -3,6 +3,17 @@ package xyz.alexcrea.cuanvil.api.event; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +/** + * Called when custom anvil is ready to accept registration on custom enchantment. + *

+ * If you want to listen this event + * you will need to register the listener on your plugin onEnable or earlier + *

+ * Custom enchantments may be registered later but may cause issue if registered too later + * (after configuration loading phase. see {@link CAConfigReadyEvent}) + *

+ * use {@link xyz.alexcrea.cuanvil.api.EnchantmentApi EnchantmentApi} to register and unregister your custom enchantments + */ public class CAEnchantRegistryReadyEvent extends Event { private static final HandlerList HANDLERS = new HandlerList(); diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CAClickResultBypassEvent.java b/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CAClickResultBypassEvent.java new file mode 100644 index 0000000..a27c65e --- /dev/null +++ b/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CAClickResultBypassEvent.java @@ -0,0 +1,63 @@ +package xyz.alexcrea.cuanvil.api.event.listener; + +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.jetbrains.annotations.NotNull; + +/** + * Called before custom anvil process the click on the result on the anvil inventory. + *

+ * This event is called after checking that the inventory is an anvil inventory and that the click is on the result slot + * but before checking if the player has the custom anvil affected permission. + *

+ * This event being cancelled will make CustomAnvil abort the click on result process. + *

+ * Most of the time you would likely need {@link CAPreAnvilBypassEvent} or {@link CAEarlyPreAnvilBypassEvent} + * for this event to be useful. + *

+ * There is also {@link CATreatAnvilResultEvent} that may be better for some use case. + */ +public class CAClickResultBypassEvent extends Event implements Cancellable { + + private static final HandlerList HANDLERS = new HandlerList(); + + public static HandlerList getHandlerList() { + return HANDLERS; + } + + @Override + public @NotNull HandlerList getHandlers() { + return HANDLERS; + } + + private boolean cancelled = false; + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancelled = cancel; + } + + @NotNull + private final InventoryClickEvent event; + + /** + * Get the bukkit inventory click event causing to this event + * + * @return The click event causing to this event + */ + @NotNull + public InventoryClickEvent getEvent() { + return event; + } + + public CAClickResultBypassEvent(@NotNull InventoryClickEvent event) { + this.event = event; + } +} diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CAEarlyPreAnvilBypassEvent.java b/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CAEarlyPreAnvilBypassEvent.java new file mode 100644 index 0000000..2fbd275 --- /dev/null +++ b/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CAEarlyPreAnvilBypassEvent.java @@ -0,0 +1,63 @@ +package xyz.alexcrea.cuanvil.api.event.listener; + +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.event.inventory.PrepareAnvilEvent; +import org.jetbrains.annotations.NotNull; + +/** + * Called before custom anvil process the prepare anvil event. + *

+ * This event will always get called when CustomAnvil need to handle + *

+ * This event being cancelled will make CustomAnvil abort the anvil process. + *

+ * You should also use {@link CAClickResultBypassEvent} if you want to use this event for something useful. + *

+ * It is also recommended that you read about {@link CAPreAnvilBypassEvent} and {@link CATreatAnvilResultEvent} + * as your use case may be more prone to use theses. + */ +public class CAEarlyPreAnvilBypassEvent extends Event implements Cancellable { + + private static final HandlerList HANDLERS = new HandlerList(); + + public static HandlerList getHandlerList() { + return HANDLERS; + } + + @Override + public @NotNull HandlerList getHandlers() { + return HANDLERS; + } + + private boolean cancelled = false; + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancelled = cancel; + } + + @NotNull + private final PrepareAnvilEvent event; + + /** + * Get the bukkit pre anvil event causing this event + * + * @return The pre anvil event causing to this event + */ + @NotNull + public PrepareAnvilEvent getEvent() { + return event; + } + + public CAEarlyPreAnvilBypassEvent(@NotNull PrepareAnvilEvent event) { + this.event = event; + } + +} diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CAPreAnvilBypassEvent.java b/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CAPreAnvilBypassEvent.java new file mode 100644 index 0000000..18334e3 --- /dev/null +++ b/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CAPreAnvilBypassEvent.java @@ -0,0 +1,66 @@ +package xyz.alexcrea.cuanvil.api.event.listener; + +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.event.inventory.PrepareAnvilEvent; +import org.jetbrains.annotations.NotNull; + +/** + * Called before custom anvil process the prepare anvil event. + *

+ * This event is called after {@link CAEarlyPreAnvilBypassEvent}, + * after checking that there is at least an item on the left slot + * and after checking if any of the 2 item is marked as immutable + * but before checking if the player has the custom anvil affected permission. + *

+ * This event being cancelled will make CustomAnvil abort the anvil process. + *

+ * You should also use {@link CAClickResultBypassEvent} if you want to use this event for something useful. + *

+ * It is also recommended that you read about {@link CAEarlyPreAnvilBypassEvent} and {@link CATreatAnvilResultEvent} + * as your use case may be more prone to use theses. + */ +public class CAPreAnvilBypassEvent extends Event implements Cancellable { + + private static final HandlerList HANDLERS = new HandlerList(); + + public static HandlerList getHandlerList() { + return HANDLERS; + } + + @Override + public @NotNull HandlerList getHandlers() { + return HANDLERS; + } + + private boolean cancelled = false; + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancelled = cancel; + } + + @NotNull + private final PrepareAnvilEvent event; + + /** + * Get the bukkit pre anvil event causing this event + * + * @return The pre anvil event causing this event + */ + @NotNull + public PrepareAnvilEvent getEvent() { + return event; + } + + public CAPreAnvilBypassEvent(@NotNull PrepareAnvilEvent event) { + this.event = event; + } + +} diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CATreatAnvilResultEvent.java b/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CATreatAnvilResultEvent.java new file mode 100644 index 0000000..1675d1a --- /dev/null +++ b/src/main/java/xyz/alexcrea/cuanvil/api/event/listener/CATreatAnvilResultEvent.java @@ -0,0 +1,131 @@ +package xyz.alexcrea.cuanvil.api.event.listener; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.event.inventory.PrepareAnvilEvent; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import xyz.alexcrea.cuanvil.util.AnvilUseType; + +/** + * Called after custom anvil processed the click on the result on the anvil inventory. + * This event should be used to modify the result of an anvil use. + *

+ * You may also want to check {@link CAClickResultBypassEvent}, + * {@link CAPreAnvilBypassEvent} + * and {@link CAEarlyPreAnvilBypassEvent} for your use case + *

+ * A null result will cancel this pre anvil event + */ +@SuppressWarnings("unused") +public class CATreatAnvilResultEvent extends Event { + + private static final HandlerList HANDLERS = new HandlerList(); + + public static HandlerList getHandlerList() { + return HANDLERS; + } + + @Override + public @NotNull HandlerList getHandlers() { + return HANDLERS; + } + + @NotNull + private final PrepareAnvilEvent event; + + private final AnvilUseType useType; + + @Nullable + private ItemStack result; + + private int levelCost; + + public CATreatAnvilResultEvent(@NotNull PrepareAnvilEvent event, AnvilUseType useType, @Nullable ItemStack result, int levelCost) { + this.event = event; + this.useType = useType; + this.result = result; + this.levelCost = levelCost; + } + + /** + * Get the bukkit inventory click event causing to this event. + * + * @return The click event causing to this event. + */ + public @NotNull PrepareAnvilEvent getEvent() { + return event; + } + + /** + * Get the type of use source of the result. + * + * @return The craft use type. + */ + public AnvilUseType getUseType() { + return useType; + } + + /** + * Get the current result + *

+ * note that it will not be null unless another listener previously set it to null. + * + * @return The current result. + */ + public @Nullable ItemStack getResult() { + return result; + } + + /** + * Set the current result + *

+ * note that a null result will cancel this anvil use. + * + * @param result The new result + */ + public void setResult(@Nullable ItemStack result) { + this.result = result; + } + + /** + * Get the level cost displayed on the anvil. + *

Important note:

+ * the final price are re calculated on click for the following use case: + * + * This value will be used as final price for: + *
  • Item merge
  • + *
  • Item rename
  • + * + * + * @return The current cost. + */ + public int getLevelCost() { + return levelCost; + } + + /** + * Set the level cost displayed on the anvil. + *

    Important note:

    + * the final price are re calculated on click for the following use case: + * + * This value will be used as final price for: + *
  • Item merge
  • + *
  • Item rename
  • + * + * + * @param levelCost The new cost. + */ + public void setLevelCost(int levelCost) { + this.levelCost = levelCost; + } +} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt index 85d326f..09980b5 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt @@ -8,6 +8,10 @@ import org.bukkit.event.inventory.InventoryClickEvent import org.bukkit.event.inventory.PrepareAnvilEvent import org.bukkit.inventory.AnvilInventory import org.bukkit.inventory.ItemStack +import xyz.alexcrea.cuanvil.api.event.listener.CAClickResultBypassEvent +import xyz.alexcrea.cuanvil.api.event.listener.CAEarlyPreAnvilBypassEvent +import xyz.alexcrea.cuanvil.api.event.listener.CAPreAnvilBypassEvent +import xyz.alexcrea.cuanvil.api.event.listener.CATreatAnvilResultEvent import xyz.alexcrea.cuanvil.config.ConfigHolder import xyz.alexcrea.cuanvil.dependency.datapack.DataPackDependency import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester @@ -19,6 +23,7 @@ import xyz.alexcrea.cuanvil.dependency.scheduler.BukkitScheduler import xyz.alexcrea.cuanvil.dependency.scheduler.FoliaScheduler import xyz.alexcrea.cuanvil.dependency.scheduler.TaskScheduler import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT +import xyz.alexcrea.cuanvil.util.AnvilUseType import java.util.logging.Level object DependencyManager { @@ -139,10 +144,14 @@ object DependencyManager { } private fun earlyUnsafeTryEventPreAnvilBypass(event: PrepareAnvilEvent, player: HumanEntity): Boolean { - var bypass = false + // Run the event + val bypassEvent = CAEarlyPreAnvilBypassEvent(event) + Bukkit.getPluginManager().callEvent(bypassEvent) + + var bypass = bypassEvent.isCancelled // Test if the inventory is a gui(version specific) - if (externGuiTester?.testIfGui(event.view) == true) bypass = true + if (!bypass && (externGuiTester?.testIfGui(event.view) == true)) bypass = true return bypass } @@ -171,10 +180,14 @@ object DependencyManager { } private fun unsafeTryEventPreAnvilBypass(event: PrepareAnvilEvent, player: HumanEntity): Boolean { - var bypass = false + // Run the event + val bypassEvent = CAPreAnvilBypassEvent(event) + Bukkit.getPluginManager().callEvent(bypassEvent) + + var bypass = bypassEvent.isCancelled // Test if disenchantment used prepare anvil - if (disenchantmentCompatibility?.testPrepareAnvil(event, player) == true) bypass = true + if (!bypass && (disenchantmentCompatibility?.testPrepareAnvil(event, player) == true)) bypass = true // Test heaven bags used prepare anvil if (!bypass && (havenBagsCompatibility?.testPrepareAnvil(event, player) == true)) bypass = true @@ -189,11 +202,12 @@ object DependencyManager { return bypass } - // Return true only if error occurred (and so should bypass rest) - fun tryTreatAnvilResult(event: PrepareAnvilEvent, result: ItemStack): Boolean { + // Return null if there was an issue + fun tryTreatAnvilResult(event: PrepareAnvilEvent, result: ItemStack, useType: AnvilUseType, cost: Int): CATreatAnvilResultEvent? { + val treatEvent = CATreatAnvilResultEvent(event, useType, result, cost) try { - unsafeTryTreatAnvilResult(event, result) - return false + unsafeTryTreatAnvilResult(treatEvent) + return treatEvent; } catch (e: Exception) { CustomAnvil.instance.logger.log( Level.SEVERE, @@ -209,12 +223,14 @@ object DependencyManager { "[" + ChatColor.YELLOW.toString() + "CustomAnvil" + ChatColor.WHITE.toString() + "] " + ChatColor.RED.toString() + "Error while handling the anvil." ) - return true + return null } } - private fun unsafeTryTreatAnvilResult(event: PrepareAnvilEvent, result: ItemStack) { - excellentEnchantsCompatibility?.treatAnvilResult(event, result) + private fun unsafeTryTreatAnvilResult(event: CATreatAnvilResultEvent) { + Bukkit.getPluginManager().callEvent(event) + + excellentEnchantsCompatibility?.treatAnvilResult(event) } // Return true if should bypass (either by a dependency or error) @@ -241,10 +257,14 @@ object DependencyManager { } private fun unsafeTryClickAnvilResultBypass(event: InventoryClickEvent, inventory: AnvilInventory): Boolean { - var bypass = false + // Run the event + val bypassEvent = CAClickResultBypassEvent(event) + Bukkit.getPluginManager().callEvent(bypassEvent) + + var bypass = bypassEvent.isCancelled // Test if disenchantment used event click - if (disenchantmentCompatibility?.testAnvilResult(event, inventory) == true) bypass = true + if (!bypass && (disenchantmentCompatibility?.testAnvilResult(event, inventory) == true)) bypass = true // Test if haven bag used event click if (!bypass && (havenBagsCompatibility?.testAnvilResult(event, inventory) == true)) bypass = true diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ExcellentEnchantsDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ExcellentEnchantsDependency.kt index 301460b..2aee624 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ExcellentEnchantsDependency.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ExcellentEnchantsDependency.kt @@ -8,6 +8,7 @@ import org.bukkit.event.inventory.PrepareAnvilEvent import org.bukkit.inventory.ItemStack import org.bukkit.plugin.RegisteredListener import xyz.alexcrea.cuanvil.api.EnchantmentApi +import xyz.alexcrea.cuanvil.api.event.listener.CATreatAnvilResultEvent import xyz.alexcrea.cuanvil.enchant.wrapped.CAEEPreV5Enchantment import xyz.alexcrea.cuanvil.enchant.wrapped.CAEEV5Enchantment import xyz.alexcrea.cuanvil.enchant.wrapped.CALegacyEEEnchantment @@ -46,7 +47,7 @@ class ExcellentEnchantsDependency { } } - if(listenerVersion == null){ + if (listenerVersion == null) { CustomAnvil.instance.logger.severe("Found issue with listener of Excellent Enchants. compatiblity is broken. please contact CustomAnvil devs") } @@ -124,20 +125,23 @@ class ExcellentEnchantsDependency { toUnregister.add(registeredListener) } } + ListenerVersion.PRE_V5 -> { if (listener is PreV5AnvilListener) { this.preV5AnvilListener = listener toUnregister.add(registeredListener) } } + ListenerVersion.LEGACY -> { if (listener is LegacyAnvilListener) { this.legacyAnvilListener = listener toUnregister.add(registeredListener) } } + null -> { - } + } } } @@ -188,11 +192,14 @@ class ExcellentEnchantsDependency { return handleRechargeMethod.invoke(this.usedAnvilListener, event, first, second) as Boolean } - fun treatAnvilResult(event: PrepareAnvilEvent, result: ItemStack) { - val first: ItemStack = treatInput(event.inventory.getItem(0)) - val second: ItemStack = treatInput(event.inventory.getItem(1)) + fun treatAnvilResult(event: CATreatAnvilResultEvent) { + val result = event.result + if (result == null) return - handleCombineMethod.invoke(this.usedAnvilListener, event, first, second, result) + val first: ItemStack = treatInput(event.event.inventory.getItem(0)) + val second: ItemStack = treatInput(event.event.inventory.getItem(1)) + + handleCombineMethod.invoke(this.usedAnvilListener, event.event, first, second, result) } fun testAnvilResult(event: InventoryClickEvent): Any { diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt index 0e9141f..64e43d1 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt @@ -46,7 +46,6 @@ class AnvilResultListener : Listener { @EventHandler(ignoreCancelled = true) fun anvilExtractionCheck(event: InventoryClickEvent) { val player = event.whoClicked as? Player ?: return - if (!player.hasPermission(CustomAnvil.affectedByPluginPermission)) return val inventory = event.inventory as? AnvilInventory ?: return if (event.rawSlot != ANVIL_OUTPUT_SLOT) { @@ -56,6 +55,8 @@ class AnvilResultListener : Listener { // Test if the event should bypass custom anvil. if (DependencyManager.tryClickAnvilResultBypass(event, inventory)) return + if (!player.hasPermission(CustomAnvil.affectedByPluginPermission)) return + val output = inventory.getItem(ANVIL_OUTPUT_SLOT) ?: return val leftItem = inventory.getItem(ANVIL_INPUT_LEFT) ?: return val rightItem = inventory.getItem(ANVIL_INPUT_RIGHT) diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt index 604c20f..dd1f5b9 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt @@ -46,11 +46,15 @@ class PrepareAnvilListener : Listener { fun anvilCombineCheck(event: PrepareAnvilEvent) { // Should find player val player: HumanEntity = InventoryViewUtil.getInstance().getPlayer(event.view) + val inventory = event.inventory // Test if custom anvil is bypassed before immutability test - if (DependencyManager.earlyTryEventPreAnvilBypass(event, player)) return + if (DependencyManager.earlyTryEventPreAnvilBypass(event, player)) { + // even if we got bypassed we still want to set price + AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, event.inventory.repairCost) + return + } - val inventory = event.inventory val first = inventory.getItem(ANVIL_INPUT_LEFT) ?: return val second = inventory.getItem(ANVIL_INPUT_RIGHT) @@ -62,7 +66,11 @@ class PrepareAnvilListener : Listener { } // Test if the event should bypass custom anvil. - if (DependencyManager.tryEventPreAnvilBypass(event, player)) return + if (DependencyManager.tryEventPreAnvilBypass(event, player)) { + // even if we got bypassed we still want to set price + AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, event.inventory.repairCost) + return + } if (!player.hasPermission(CustomAnvil.affectedByPluginPermission)) return @@ -133,16 +141,20 @@ class PrepareAnvilListener : Listener { val resultItem: ItemStack = recipe.resultItem!!.clone() resultItem.amount *= amount - event.result = resultItem - if (DependencyManager.tryTreatAnvilResult(event, resultItem)) return true - + // Maybe add an option on custom craft to ignore/not ignore penalty ?? val xpCost = recipe.determineCost(amount, first, resultItem) val levelCost = if (recipe.removeExactLinearXp) AnvilXpUtil.calculateMinimumLevelForXp(xpCost) else AnvilXpUtil.calculateLevelForXp(xpCost) - AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, levelCost, true) + val finalResult = DependencyManager.tryTreatAnvilResult(event, resultItem, AnvilUseType.CUSTOM_CRAFT, levelCost) + if (finalResult == null) return false + + event.result = finalResult.result + if (finalResult.result == null) return false + + AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, finalResult.levelCost, true) return true } @@ -160,12 +172,15 @@ class PrepareAnvilListener : Listener { return } - event.result = resultItem - if (DependencyManager.tryTreatAnvilResult(event, resultItem)) return - anvilCost += AnvilXpUtil.calculatePenalty(first, null, resultItem, AnvilUseType.RENAME_ONLY) - AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, anvilCost) + val finalResult = DependencyManager.tryTreatAnvilResult(event, resultItem, AnvilUseType.RENAME_ONLY, anvilCost) + if (finalResult == null) return + + event.result = finalResult.result + if (finalResult.result == null) return + + AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, finalResult.levelCost) } private fun handleRename(resultItem: ItemStack, inventory: AnvilInventory, player: HumanEntity): Int { @@ -241,10 +256,13 @@ class PrepareAnvilListener : Listener { anvilCost += handleRename(resultItem, inventory, player) // Finally, we set result - event.result = resultItem - if (DependencyManager.tryTreatAnvilResult(event, resultItem)) return + val finalResult = DependencyManager.tryTreatAnvilResult(event, resultItem, AnvilUseType.MERGE, anvilCost) + if (finalResult == null) return - AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, anvilCost) + event.result = finalResult.result + if (finalResult.result == null) return + + AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, finalResult.levelCost) } // return true if there is a valid unit repair with these ingredients @@ -270,10 +288,14 @@ class PrepareAnvilListener : Listener { event.result = null return true } - event.result = resultItem - if (DependencyManager.tryTreatAnvilResult(event, resultItem)) return true - AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, anvilCost) + val finalResult = DependencyManager.tryTreatAnvilResult(event, resultItem, AnvilUseType.UNIT_REPAIR, anvilCost) + if (finalResult == null) return false + + event.result = finalResult.result + if (finalResult.result == null) return false + + AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, finalResult.levelCost) return true } diff --git a/src/test/java/xyz/alexcrea/cuanvil/api/event/CAConfigReadyEventTest.java b/src/test/java/xyz/alexcrea/cuanvil/api/event/CAConfigReadyEventTest.java new file mode 100644 index 0000000..ff73a59 --- /dev/null +++ b/src/test/java/xyz/alexcrea/cuanvil/api/event/CAConfigReadyEventTest.java @@ -0,0 +1,49 @@ +package xyz.alexcrea.cuanvil.api.event; + +import io.delilaheve.CustomAnvil; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockbukkit.mockbukkit.MockBukkit; +import org.mockbukkit.mockbukkit.matcher.plugin.PluginManagerFiredEventClassMatcher; +import xyz.alexcrea.cuanvil.tests.SharedOnlyMockBukkit; + +public class CAConfigReadyEventTest extends SharedOnlyMockBukkit { + + private CustomAnvil plugin; + + @Test + public void startup() { + boolean beforeStart = PluginManagerFiredEventClassMatcher + .hasNotFiredEventInstance(CAConfigReadyEvent.class) + .matches(server.getPluginManager()); + + Assertions.assertTrue(beforeStart, "Somehow, event fired before plugin being loaded ?"); + + // Load the plugin + plugin = MockBukkit.load(CustomAnvil.class); + + boolean postStart = PluginManagerFiredEventClassMatcher + .hasNotFiredEventInstance(CAConfigReadyEvent.class) + .matches(server.getPluginManager()); + + Assertions.assertTrue(postStart, "Event fired before plugin finished being loaded"); + + // Config load phase + server.getScheduler().performOneTick(); + boolean postConfig = PluginManagerFiredEventClassMatcher + .hasFiredEventInstance(CAConfigReadyEvent.class) + .matches(server.getPluginManager()); + + Assertions.assertTrue(postConfig, "Event did not fire after the config phase"); + } + + @AfterEach + public void pluginTeardown() { + if (plugin != null) { + server.getPluginManager().disablePlugin(plugin); + plugin = null; + } + } + +} diff --git a/src/test/java/xyz/alexcrea/cuanvil/api/event/CAEnchantRegistryReadyEventTest.java b/src/test/java/xyz/alexcrea/cuanvil/api/event/CAEnchantRegistryReadyEventTest.java new file mode 100644 index 0000000..2c79388 --- /dev/null +++ b/src/test/java/xyz/alexcrea/cuanvil/api/event/CAEnchantRegistryReadyEventTest.java @@ -0,0 +1,49 @@ +package xyz.alexcrea.cuanvil.api.event; + +import io.delilaheve.CustomAnvil; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockbukkit.mockbukkit.MockBukkit; +import org.mockbukkit.mockbukkit.matcher.plugin.PluginManagerFiredEventClassMatcher; +import xyz.alexcrea.cuanvil.tests.SharedOnlyMockBukkit; + +public class CAEnchantRegistryReadyEventTest extends SharedOnlyMockBukkit { + + private CustomAnvil plugin; + + @Test + public void startup() { + boolean beforeStart = PluginManagerFiredEventClassMatcher + .hasNotFiredEventInstance(CAEnchantRegistryReadyEvent.class) + .matches(server.getPluginManager()); + + Assertions.assertTrue(beforeStart, "Somehow, event fired before plugin being loaded ?"); + + // Load the plugin + plugin = MockBukkit.load(CustomAnvil.class); + + boolean postStart = PluginManagerFiredEventClassMatcher + .hasNotFiredEventInstance(CAEnchantRegistryReadyEvent.class) + .matches(server.getPluginManager()); + + Assertions.assertTrue(postStart, "Event fired before plugin finished being loaded"); + + // Config load phase + server.getScheduler().performOneTick(); + boolean postConfig = PluginManagerFiredEventClassMatcher + .hasFiredEventInstance(CAEnchantRegistryReadyEvent.class) + .matches(server.getPluginManager()); + + Assertions.assertTrue(postConfig, "Event did not fire after the config phase"); + } + + @AfterEach + public void pluginTeardown() { + if (plugin != null) { + server.getPluginManager().disablePlugin(plugin); + plugin = null; + } + } + +}