Skip to content

Commit

Permalink
v1.7.1 (#48)
Browse files Browse the repository at this point in the history
Fix getting cost for color renaming causing null pointer exception when
inventory name is null (Fix #47)
Add safety when executing dependency handling code
  • Loading branch information
alexcrea authored Jan 25, 2025
1 parent 5f557e3 commit 33474c3
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 31 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ plugins {
}

group = "xyz.alexcrea"
version = "1.7.0"
version = "1.7.1"

repositories {
// EcoEnchants
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/io/delilaheve/util/ConfigOptions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ object ConfigOptions {
private const val KEY_ITEM = "item"

// Debug flag
private const val DEBUG_LOGGING = "debug_log"
private const val VERBOSE_DEBUG_LOGGING = "debug_log_verbose"
const val DEBUG_LOGGING = "debug_log"
const val VERBOSE_DEBUG_LOGGING = "debug_log_verbose"

// ----------------------
// Default config values
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package xyz.alexcrea.cuanvil.dependency

import io.delilaheve.CustomAnvil
import org.bukkit.Bukkit
import org.bukkit.ChatColor
import org.bukkit.entity.HumanEntity
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.inventory.PrepareAnvilEvent
Expand All @@ -15,6 +16,8 @@ import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerSelector
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 java.util.logging.Level

object DependencyManager {

Expand Down Expand Up @@ -96,10 +99,25 @@ object DependencyManager {

// Then handle plugin reload
ecoEnchantCompatibility?.handleConfigReload()

}

// Return true if should bypass (either by a dependency or error)
fun tryEventPreAnvilBypass(event: PrepareAnvilEvent, player: HumanEntity): Boolean {
try {
return unsafeTryEventPreAnvilBypass(event, player)
} catch (e: Exception){
CustomAnvil.instance.logger.log(Level.SEVERE, "Error while trying to handle custom anvil supported plugin: ", e)

// Just in case to avoid illegal items
event.inventory.setItem(ANVIL_OUTPUT_SLOT, null)

// Finally, warn the player, maybe a lot of time but better warn than do nothing
event.view.player.sendMessage(ChatColor.RED.toString() + "Error while handling the anvil.")
return true
}
}

private fun unsafeTryEventPreAnvilBypass(event: PrepareAnvilEvent, player: HumanEntity): Boolean {
var bypass = false

// Test if disenchantment used prepare anvil
Expand All @@ -118,11 +136,44 @@ object DependencyManager {
return bypass
}

fun treatAnvilResult(event: PrepareAnvilEvent, result: ItemStack) {
// Return true only if error occurred (and so should bypass rest)
fun tryTreatAnvilResult(event: PrepareAnvilEvent, result: ItemStack): Boolean {
try {
unsafeTryTreatAnvilResult(event, result)
return false
} catch (e: Exception){
CustomAnvil.instance.logger.log(Level.SEVERE, "Error while trying to handle custom anvil supported plugin: ", e)

// Just in case to avoid illegal items
event.inventory.setItem(ANVIL_OUTPUT_SLOT, null)

// Finally, warn the player, maybe a lot of time but better warn than do nothing
event.view.player.sendMessage(ChatColor.RED.toString() + "Error while handling the anvil.")
return true
}
}

private fun unsafeTryTreatAnvilResult(event: PrepareAnvilEvent, result: ItemStack) {
excellentEnchantsCompatibility?.treatAnvilResult(event, result)
}

// Return true if should bypass (either by a dependency or error)
fun tryClickAnvilResultBypass(event: InventoryClickEvent, inventory: AnvilInventory): Boolean {
try {
return unsafeTryClickAnvilResultBypass(event, inventory)
} catch (e: Exception){
CustomAnvil.instance.logger.log(Level.SEVERE, "Error while trying to handle custom anvil supported plugin: ", e)

// Just in case to avoid illegal items
event.inventory.setItem(ANVIL_OUTPUT_SLOT, null)

// Finally, warn the player, maybe a lot of time but better warn than do nothing
event.whoClicked.sendMessage(ChatColor.RED.toString() + "Error while handling the anvil.")
return true
}
}

private fun unsafeTryClickAnvilResultBypass(event: InventoryClickEvent, inventory: AnvilInventory): Boolean {
var bypass = false

// Test if disenchantment used event click
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,15 @@ class AnvilResultListener: Listener {
if (event.rawSlot != ANVIL_OUTPUT_SLOT) {
return
}

// Test if the event should bypass custom anvil.
if(DependencyManager.tryClickAnvilResultBypass(event, inventory)) return

val output = inventory.getItem(ANVIL_OUTPUT_SLOT) ?: return
val leftItem = inventory.getItem(ANVIL_INPUT_LEFT) ?: return
val rightItem = inventory.getItem(ANVIL_INPUT_RIGHT)

if(!GameMode.CREATIVE.equals(player.gameMode) && inventory.repairCost >= inventory.maximumRepairCost) {
if(GameMode.CREATIVE != player.gameMode && inventory.repairCost >= inventory.maximumRepairCost) {
event.result = Event.Result.DENY
return
}
Expand Down Expand Up @@ -96,7 +97,6 @@ class AnvilResultListener: Listener {
}
}


private fun onCustomCraft(event: InventoryClickEvent,
recipe: AnvilCustomRecipe,
player: Player,
Expand All @@ -122,7 +122,7 @@ class AnvilResultListener: Listener {

// Handle not creative middle click...
if (event.click != ClickType.MIDDLE &&
!handleCustomCraftClick(event, recipe, inventory, player, leftItem, rightItem, amount, xpCost)) return;
!handleCustomCraftClick(event, recipe, inventory, player, leftItem, rightItem, amount, xpCost)) return

// Finally, we add the item to the player
if (slotDestination.type == SlotType.CURSOR) {
Expand Down Expand Up @@ -222,7 +222,7 @@ class AnvilResultListener: Listener {
resultCopy: ItemStack, resultAmount: Int): Int {
if (player.gameMode == GameMode.CREATIVE) return 0

var repairCost = 0;
var repairCost = 0
// Get repairCost
leftItem.itemMeta?.let { leftMeta ->
val leftName = leftMeta.displayName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import xyz.alexcrea.cuanvil.util.AnvilColorUtil
import xyz.alexcrea.cuanvil.util.AnvilXpUtil
import xyz.alexcrea.cuanvil.util.CustomRecipeUtil
import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair
import java.util.logging.Level

/**
* Listener for anvil events
Expand All @@ -45,7 +46,7 @@ class PrepareAnvilListener : Listener {
val player: HumanEntity = event.viewers.first()

// Test if the event should bypass custom anvil.
if(DependencyManager.tryEventPreAnvilBypass(event, player)) return
if (DependencyManager.tryEventPreAnvilBypass(event, player)) return

val inventory = event.inventory
val first = inventory.getItem(ANVIL_INPUT_LEFT) ?: return
Expand Down Expand Up @@ -76,6 +77,7 @@ class PrepareAnvilListener : Listener {

}

// return true if a custom recipe exist with these ingredient
private fun testCustomRecipe(event: PrepareAnvilEvent, inventory: AnvilInventory,
player: HumanEntity,
first: ItemStack, second: ItemStack?): Boolean {
Expand All @@ -89,7 +91,7 @@ class PrepareAnvilListener : Listener {
resultItem.amount *= amount

event.result = resultItem
DependencyManager.treatAnvilResult(event, resultItem)
if(DependencyManager.tryTreatAnvilResult(event, resultItem)) return true
AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, recipe.xpCostPerCraft * amount, true)

return true
Expand All @@ -108,35 +110,38 @@ class PrepareAnvilListener : Listener {
}

event.result = resultItem
DependencyManager.treatAnvilResult(event, resultItem)
if(DependencyManager.tryTreatAnvilResult(event, resultItem)) return

anvilCost += AnvilXpUtil.calculatePenalty(first, null, resultItem)

AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, anvilCost)
}

private fun handleRename(resultItem: ItemStack, inventory: AnvilInventory, player: HumanEntity): Int {
// Rename item and add renaming cost
resultItem.itemMeta?.let {
val displayName = ChatColor.stripColor(it.displayName)
var inventoryName = ChatColor.stripColor(inventory.renameText)
// Can be null
var inventoryName = ChatColor.stripColor(inventory.renameText)

var sumCost = 0
var sumCost = 0
var useColor = false
if(ConfigOptions.renameColorPossible && inventoryName != null){
val resultString = StringBuilder(inventoryName)

var useColor = false
if(ConfigOptions.renameColorPossible){
val resultString = StringBuilder(inventoryName)
useColor = AnvilColorUtil.handleRenamingColor(resultString, player)

useColor = AnvilColorUtil.handleRenamingColor(resultString, player)
if(useColor) {
inventoryName = resultString.toString()

if(useColor) {
inventoryName = resultString.toString()

sumCost+= ConfigOptions.useOfColorCost
}
sumCost+= ConfigOptions.useOfColorCost
}
}

// Rename item and add renaming cost
resultItem.itemMeta?.let {
val displayName =
if (useColor) it.displayName
else ChatColor.stripColor(it.displayName)

if ((!useColor && (!displayName.contentEquals(inventoryName))) || (useColor && !(it.displayName).contentEquals(inventoryName))) {
if (!displayName.contentEquals(inventoryName)) {
it.setDisplayName(inventoryName)
resultItem.itemMeta = it

Expand Down Expand Up @@ -178,11 +183,12 @@ class PrepareAnvilListener : Listener {

// Finally, we set result
event.result = resultItem
DependencyManager.treatAnvilResult(event, resultItem)
if(DependencyManager.tryTreatAnvilResult(event, resultItem)) return

AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, anvilCost)
}

// return true if there is a valid unit repair with these ingredients
private fun testUnitRepair(event: PrepareAnvilEvent, inventory: AnvilInventory, player: HumanEntity,
first: ItemStack, second: ItemStack): Boolean {
val unitRepairAmount = first.getRepair(second) ?: return false
Expand All @@ -204,7 +210,7 @@ class PrepareAnvilListener : Listener {
return true
}
event.result = resultItem
DependencyManager.treatAnvilResult(event, resultItem)
if(DependencyManager.tryTreatAnvilResult(event, resultItem)) return true

AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, anvilCost)
return true
Expand Down
28 changes: 26 additions & 2 deletions src/test/java/xyz/alexcrea/cuanvil/anvil/AnvilFuseTests.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package xyz.alexcrea.cuanvil.anvil;

import io.delilaheve.util.ConfigOptions;
import net.kyori.adventure.text.Component;
import org.bukkit.Material;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.AnvilInventory;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.Repairable;
import org.eclipse.aether.util.ConfigUtils;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
Expand All @@ -32,8 +36,9 @@ public static void setUp() {
AnvilFuseTests.anvil = (AnvilInventory) anvil;
player.openInventory(anvil);

ConfigHolder.DEFAULT_CONFIG.getConfig().set("debug_log", true);
ConfigHolder.DEFAULT_CONFIG.getConfig().set("debug_log_verbose", true);
ConfigHolder.DEFAULT_CONFIG.getConfig().set(ConfigOptions.DEBUG_LOGGING, true);
ConfigHolder.DEFAULT_CONFIG.getConfig().set(ConfigOptions.VERBOSE_DEBUG_LOGGING, true);
ConfigHolder.DEFAULT_CONFIG.getConfig().set(ConfigOptions.ALLOW_COLOR_CODE, true); // For rename test
}

@BeforeEach
Expand Down Expand Up @@ -100,4 +105,23 @@ public void underFuseTest(){
AnvilFuseTestUtil.executeAnvilTest(anvil, player, data);
}

// Note: currently anvil can only have null name. maybe handle differently later
@Test
public void nullNameResetTest(){
ItemStack base = new ItemStack(Material.NETHERITE_SWORD);
ItemStack expected = base.clone();

ItemMeta meta = expected.getItemMeta();
meta.displayName(Component.text("test"));
base.setItemMeta(meta);

AnvilFuseTestData data = new AnvilFuseTestData(
base, null,
expected, expected, null
// TODO add expected price
);

AnvilFuseTestUtil.executeAnvilTest(anvil, player, data);
}

}
15 changes: 15 additions & 0 deletions src/test/java/xyz/alexcrea/cuanvil/util/AnvilFuseTestData.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,19 @@ public AnvilFuseTestData(
this(leftItem, rightItem, expectedResult, null
);
}

public AnvilFuseTestData(
@Nullable ItemStack leftItem,
@Nullable ItemStack rightItem,
@Nullable ItemStack expectedResult,

@Nullable ItemStack expectedAfterLeftPlaced,
@Nullable ItemStack expectedAfterRightPlaced
){
this(leftItem, rightItem,
expectedResult, expectedAfterLeftPlaced, expectedAfterRightPlaced,
null, null, null
);
}

}

0 comments on commit 33474c3

Please sign in to comment.