diff --git a/src/main/java/de/hysky/skyblocker/skyblock/accessories/AccessoriesHelperWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/accessories/AccessoriesHelperWidget.java index c2d14255086..ce929b376ad 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/accessories/AccessoriesHelperWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/accessories/AccessoriesHelperWidget.java @@ -207,7 +207,7 @@ private static OptionalDouble getPrice(Accessory acc) { DoubleBooleanPair optionalPrice = ItemUtils.getItemPrice(stack); double price; if (optionalPrice.rightBoolean()) price = optionalPrice.firstDouble(); - else price = ItemUtils.getCraftCost(stack.getSkyblockApiId()); + else price = ItemUtils.getCraftCost(stack.getNeuName()); if (price <= 0) return OptionalDouble.empty(); return OptionalDouble.of(price); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/CraftPriceTooltip.java b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/CraftPriceTooltip.java index 8cfb386a536..4986899bf0e 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/CraftPriceTooltip.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/CraftPriceTooltip.java @@ -10,11 +10,13 @@ import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.NEURepoManager; import io.github.moulberry.repo.data.NEUIngredient; -import io.github.moulberry.repo.data.NEUItem; import io.github.moulberry.repo.data.NEUKatUpgradeRecipe; +import io.github.moulberry.repo.data.NEUMobDropRecipe; import io.github.moulberry.repo.data.NEURecipe; import io.github.moulberry.repo.data.NEUTradeRecipe; import it.unimi.dsi.fastutil.objects.Object2DoubleMap; +import it.unimi.dsi.fastutil.objects.Object2DoubleMaps; +import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import org.jspecify.annotations.Nullable; import org.slf4j.Logger; @@ -22,7 +24,8 @@ import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import java.util.Optional; +import java.util.Set; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; import net.minecraft.world.inventory.Slot; @@ -30,7 +33,7 @@ public class CraftPriceTooltip extends SimpleTooltipAdder { protected static final Logger LOGGER = LoggerFactory.getLogger(CraftPriceTooltip.class.getName()); - private static final Map cachedCraftCosts = new ConcurrentHashMap<>(); + private static final Map cachedCraftCosts = Object2DoubleMaps.synchronize(new Object2DoubleOpenHashMap<>()); private static final int MAX_RECURSION_DEPTH = 15; public CraftPriceTooltip(int priority) { @@ -38,34 +41,40 @@ public CraftPriceTooltip(int priority) { } @Override - public void addToTooltip(@Nullable Slot focusedSloFt, ItemStack stack, List lines) { + public void addToTooltip(@Nullable Slot focusedSlot, ItemStack stack, List lines) { if (TooltipInfoType.LOWEST_BINS.getData() == null || TooltipInfoType.BAZAAR.getData() == null) { ItemTooltip.nullWarning(); return; } - NEUItem neuItem = NEURepoManager.getItemByNeuId(stack.getNeuName()); - if (neuItem == null) return; - - List neuRecipes = neuItem.getRecipes(); - if (neuRecipes.isEmpty()) return; - NEURecipe recipe = neuRecipes.getFirst(); - + String itemId = stack.getNeuName(); try { - double totalCraftCost = getItemCost(recipe, 0); - if (totalCraftCost <= 0) return; + double craftPrice = cachedCraftCosts.computeIfAbsent(itemId, CraftPriceTooltip::getItemCost); + if (craftPrice <= 0) return; int count = Math.max(ItemUtils.getItemCountInSack(stack, stack.skyblocker$getLoreStrings()).orElse(ItemUtils.getItemCountInStash(lines.getFirst()).orElse(stack.getCount())), 1); - - recipe.getAllOutputs().stream().findFirst().ifPresent(outputIngredient -> - lines.add(Component.literal(String.format("%-20s", "Crafting Price:")).withStyle(ChatFormatting.GOLD) - .append(ItemTooltip.getCoinsMessage(totalCraftCost / outputIngredient.getAmount(), count)))); + lines.add(Component.literal(String.format("%-20s", "Crafting Price:")).withStyle(ChatFormatting.GOLD) + .append(ItemTooltip.getCoinsMessage(craftPrice, count))); } catch (Exception e) { - LOGGER.error("[Skyblocker Craft Price] Error calculating craftprice tooltip for: {}", stack.getNeuName(), e); + LOGGER.error("[Skyblocker Craft Price] Error calculating craft price for: {}", stack.getNeuName(), e); } } - public static double getItemCost(NEURecipe recipe, int depth) { - if (depth >= MAX_RECURSION_DEPTH || recipe instanceof NEUKatUpgradeRecipe || recipe instanceof NEUTradeRecipe) return -1; + public static double getItemCost(String neuId) { + return getItemCost(neuId, 0); + } + + public static double getItemCost(String neuId, int depth) { + Set neuRecipes = NEURepoManager.getRecipes().get(neuId); + if (neuRecipes == null || neuRecipes.isEmpty()) return -1; + + Optional recipe = neuRecipes.stream().filter(CraftPriceTooltip::isValidRecipe).findFirst(); + if (recipe.isEmpty()) return -1; + return recipe.get().getAllOutputs().stream().filter(x -> x.getItemId().equals(neuId)).map(NEUIngredient::getAmount).findAny() + .map(amount -> getRecipeCost(recipe.get(), depth + 1) / amount).orElse(-1.0); + } + + public static double getRecipeCost(NEURecipe recipe, int depth) { + if (depth >= MAX_RECURSION_DEPTH || !isValidRecipe(recipe)) return -1; double totalCraftCost = 0; for (NEUIngredient input : recipe.getAllInputs()) { @@ -91,14 +100,11 @@ public static double getItemCost(NEURecipe recipe, int depth) { cachedCraftCosts.put(inputItemName, itemCost); } - NEUItem neuItem = NEURepoManager.getItemByNeuId(inputItemName); - if (neuItem != null) { - List neuRecipes = neuItem.getRecipes(); - if (!neuRecipes.isEmpty()) { - double craftCost = getItemCost(neuRecipes.getFirst(), depth + 1); - if (craftCost != -1) itemCost = Math.min(itemCost, craftCost); - cachedCraftCosts.put(inputItemName, itemCost); - } + double craftCost = getItemCost(inputItemName, depth + 1); + if (craftCost > 0) { + if (itemCost > 0) itemCost = Math.min(itemCost, craftCost); + else itemCost = craftCost; + cachedCraftCosts.put(inputItemName, itemCost); } totalCraftCost += itemCost * inputItemCount; @@ -106,8 +112,14 @@ public static double getItemCost(NEURecipe recipe, int depth) { return totalCraftCost; } + public static boolean isValidRecipe(NEURecipe recipe) { + return !(recipe instanceof NEUKatUpgradeRecipe || recipe instanceof NEUTradeRecipe || recipe instanceof NEUMobDropRecipe); + } + public static void clearCache() { cachedCraftCosts.clear(); + cachedCraftCosts.put(NEUIngredient.NEU_SENTINEL_COINS, 1d); + cachedCraftCosts.put(NEUIngredient.NEU_SENTINEL_EMPTY, 0d); } @Override diff --git a/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java b/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java index c449e3f47d0..c164a0a742e 100644 --- a/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java +++ b/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java @@ -22,7 +22,6 @@ import de.hysky.skyblocker.skyblock.item.tooltip.adders.ObtainedDateTooltip; import de.hysky.skyblocker.skyblock.item.tooltip.info.TooltipInfoType; import de.hysky.skyblocker.utils.networth.NetworthCalculator; -import io.github.moulberry.repo.data.NEUItem; import it.unimi.dsi.fastutil.doubles.DoubleBooleanPair; import it.unimi.dsi.fastutil.ints.IntIntPair; import it.unimi.dsi.fastutil.longs.LongBooleanPair; @@ -378,12 +377,8 @@ public static DoubleBooleanPair getItemPrice(@Nullable String skyblockApiId, boo return DoubleBooleanPair.of(0, false); } - public static double getCraftCost(String skyblockApiId) { - NEUItem neuItem = NEURepoManager.getItemByNeuId(skyblockApiId); - if (neuItem != null && !neuItem.getRecipes().isEmpty()) { - return CraftPriceTooltip.getItemCost(neuItem.getRecipes().getFirst(), 0); - } - return 0; + public static double getCraftCost(String neuId) { + return CraftPriceTooltip.getItemCost(neuId); } /**