Skip to content

Commit

Permalink
Merge pull request #781 from BigloBot/Craft-Cost-Tooltip
Browse files Browse the repository at this point in the history
Add Craft Cost Tooltip
  • Loading branch information
kevinthegreat1 authored Jul 8, 2024
2 parents 438ff23 + a8de449 commit f9c8129
Show file tree
Hide file tree
Showing 7 changed files with 164 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import de.hysky.skyblocker.config.ConfigUtils;
import de.hysky.skyblocker.config.SkyblockerConfig;
import de.hysky.skyblocker.config.configs.GeneralConfig;
import de.hysky.skyblocker.skyblock.item.tooltip.adders.CraftPriceTooltip;
import de.hysky.skyblocker.skyblock.shortcut.ShortcutsConfigScreen;
import dev.isxander.yacl3.api.*;
import dev.isxander.yacl3.api.controller.FloatSliderControllerBuilder;
Expand Down Expand Up @@ -163,6 +164,14 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig
newValue -> config.general.itemTooltip.enableBazaarPrice = newValue)
.controller(ConfigUtils::createBooleanController)
.build())
.option(Option.<GeneralConfig.Craft>createBuilder()
.name(Text.translatable("skyblocker.config.general.itemTooltip.craft"))
.binding(defaults.general.itemTooltip.enableCraftingCost,
() -> config.general.itemTooltip.enableCraftingCost,
newValue -> config.general.itemTooltip.enableCraftingCost = newValue)
.listener((Option<GeneralConfig.Craft> ignored, GeneralConfig.Craft ignored2) -> CraftPriceTooltip.clearCache())
.controller(ConfigUtils::createEnumCyclingListController)
.build())
.option(Option.<Boolean>createBuilder()
.name(Text.translatable("skyblocker.config.general.itemTooltip.enableObtainedDate"))
.binding(defaults.general.itemTooltip.enableObtainedDate,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ public static class ItemTooltip {
@SerialEntry
public boolean enableBazaarPrice = true;

@SerialEntry
public Craft enableCraftingCost = Craft.OFF;

@SerialEntry
public boolean enableObtainedDate = true;

Expand All @@ -139,6 +142,23 @@ public String toString() {
}
}

public enum Craft {
SELL_ORDER, BUY_ORDER, OFF;

@Override
public String toString() {
return I18n.translate("skyblocker.config.general.itemTooltip.craft." + name());
}

public String getOrder() {
return switch (this) {
case SELL_ORDER -> "sellPrice";
case BUY_ORDER -> "buyPrice";
case OFF -> null;
};
}
}

public static class ItemInfoDisplay {
@SerialEntry
public boolean slotText = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.config.configs.GeneralConfig;
import de.hysky.skyblocker.skyblock.item.tooltip.adders.CraftPriceTooltip;
import de.hysky.skyblocker.utils.Constants;
import de.hysky.skyblocker.utils.Utils;
import de.hysky.skyblocker.utils.scheduler.Scheduler;
Expand Down Expand Up @@ -129,6 +130,8 @@ public static void init() {
LOGGER.error("Encountered unknown error while downloading tooltip data", e);
return null;
});

CraftPriceTooltip.clearCache();
}, 1200, true);
}
}
Original file line number Diff line number Diff line change
@@ -1,29 +1,23 @@
package de.hysky.skyblocker.skyblock.item.tooltip;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.gson.stream.JsonReader;
import de.hysky.skyblocker.SkyblockerMod;
import de.hysky.skyblocker.config.SkyblockerConfig;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.config.configs.GeneralConfig;
import de.hysky.skyblocker.utils.Http;
import de.hysky.skyblocker.utils.Utils;
import org.jetbrains.annotations.Nullable;

import java.io.StringReader;
import java.net.http.HttpHeaders;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.function.Predicate;

import org.jetbrains.annotations.Nullable;

public enum TooltipInfoType implements Runnable {
NPC("https://hysky.de/api/npcprice", itemTooltip -> itemTooltip.enableNPCPrice, true),
BAZAAR("https://hysky.de/api/bazaar", itemTooltip -> itemTooltip.enableBazaarPrice || SkyblockerConfigManager.get().dungeons.dungeonChestProfit.enableProfitCalculator || SkyblockerConfigManager.get().dungeons.dungeonChestProfit.croesusProfit || SkyblockerConfigManager.get().uiAndVisuals.chestValue.enableChestValue, itemTooltip -> itemTooltip.enableBazaarPrice, false),
LOWEST_BINS("https://hysky.de/api/auctions/lowestbins", itemTooltip -> itemTooltip.enableLowestBIN || SkyblockerConfigManager.get().dungeons.dungeonChestProfit.enableProfitCalculator || SkyblockerConfigManager.get().dungeons.dungeonChestProfit.croesusProfit || SkyblockerConfigManager.get().uiAndVisuals.chestValue.enableChestValue, itemTooltip -> itemTooltip.enableLowestBIN, false),
BAZAAR("https://hysky.de/api/bazaar", itemTooltip -> itemTooltip.enableBazaarPrice || itemTooltip.enableCraftingCost.getOrder() != null || SkyblockerConfigManager.get().dungeons.dungeonChestProfit.enableProfitCalculator || SkyblockerConfigManager.get().dungeons.dungeonChestProfit.croesusProfit || SkyblockerConfigManager.get().uiAndVisuals.chestValue.enableChestValue, itemTooltip -> itemTooltip.enableBazaarPrice, false),
LOWEST_BINS("https://hysky.de/api/auctions/lowestbins", itemTooltip -> itemTooltip.enableLowestBIN || itemTooltip.enableCraftingCost.getOrder() != null || SkyblockerConfigManager.get().dungeons.dungeonChestProfit.enableProfitCalculator || SkyblockerConfigManager.get().dungeons.dungeonChestProfit.croesusProfit || SkyblockerConfigManager.get().uiAndVisuals.chestValue.enableChestValue, itemTooltip -> itemTooltip.enableLowestBIN, false),
ONE_DAY_AVERAGE("https://hysky.de/api/auctions/lowestbins/average/1day.json", itemTooltip -> itemTooltip.enableAvgBIN, false),
THREE_DAY_AVERAGE("https://hysky.de/api/auctions/lowestbins/average/3day.json", itemTooltip -> itemTooltip.enableAvgBIN || SkyblockerConfigManager.get().uiAndVisuals.searchOverlay.enableAuctionHouse, itemTooltip -> itemTooltip.enableAvgBIN, false),
MOTES("https://hysky.de/api/motesprice", itemTooltip -> itemTooltip.enableMotesPrice, itemTooltip -> itemTooltip.enableMotesPrice && Utils.isInTheRift(), true),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import de.hysky.skyblocker.mixins.accessors.HandledScreenAccessor;
import de.hysky.skyblocker.skyblock.chocolatefactory.ChocolateFactorySolver;
import de.hysky.skyblocker.skyblock.item.tooltip.adders.*;
import de.hysky.skyblocker.skyblock.item.tooltip.adders.CraftPriceTooltip;
import de.hysky.skyblocker.utils.Utils;
import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback;
import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
Expand All @@ -27,12 +28,13 @@ public class TooltipManager {
new BazaarPriceTooltip(2),
new LBinTooltip(3),
new AvgBinTooltip(4),
new DungeonQualityTooltip(5),
new MotesTooltip(6),
new ObtainedDateTooltip(7),
new MuseumTooltip(8),
new ColorTooltip(9),
new AccessoryTooltip(10),
new CraftPriceTooltip(5),
new DungeonQualityTooltip(6),
new MotesTooltip(7),
new ObtainedDateTooltip(8),
new MuseumTooltip(9),
new ColorTooltip(10),
new AccessoryTooltip(11),
};
private static final ArrayList<TooltipAdder> currentScreenAdders = new ArrayList<>();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package de.hysky.skyblocker.skyblock.item.tooltip.adders;

import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.config.configs.GeneralConfig;
import de.hysky.skyblocker.skyblock.item.tooltip.ItemTooltip;
import de.hysky.skyblocker.skyblock.item.tooltip.TooltipAdder;
import de.hysky.skyblocker.skyblock.item.tooltip.TooltipInfoType;
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.NEURecipe;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.slot.Slot;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import org.apache.commons.lang3.math.NumberUtils;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class CraftPriceTooltip extends TooltipAdder {
protected static final Logger LOGGER = LoggerFactory.getLogger(CraftPriceTooltip.class.getName());
private static final Map<String, Double> cachedCraftCosts = new ConcurrentHashMap<>();
private static final int MAX_RECURSION_DEPTH = 15;

public CraftPriceTooltip(int priority) {
super(priority);
}

@Override
public void addToTooltip(@Nullable Slot focusedSloFt, ItemStack stack, List<Text> lines) {
if (SkyblockerConfigManager.get().general.itemTooltip.enableCraftingCost == GeneralConfig.Craft.OFF) return;

String internalID = stack.getSkyblockId();
if (stack.getNeuName() == null || internalID == null) return;

if (TooltipInfoType.LOWEST_BINS.getData() == null || TooltipInfoType.BAZAAR.getData() == null) {
ItemTooltip.nullWarning();
return;
}

NEUItem neuItem = NEURepoManager.NEU_REPO.getItems().getItemBySkyblockId(internalID);
if (neuItem == null) return;

List<NEURecipe> neuRecipes = neuItem.getRecipes();
if (neuRecipes.isEmpty() || neuRecipes.getFirst() instanceof io.github.moulberry.repo.data.NEUKatUpgradeRecipe) return;

try {
double totalCraftCost = getItemCost(neuRecipes.getFirst(), 0);

if (totalCraftCost == 0) return;

int amountInStack;
if (lines.get(1).getString().endsWith("Sack")) {
String line = lines.get(3).getSiblings().get(1).getString().replace(",", "");
amountInStack = NumberUtils.isParsable(line) && !line.equals("0") ? Integer.parseInt(line) : stack.getCount();
} else amountInStack = stack.getCount();

neuRecipes.getFirst().getAllOutputs().stream().findFirst().ifPresent(outputIngredient ->
lines.add(Text.literal(String.format("%-20s", "Crafting Price:")).formatted(Formatting.GOLD)
.append(ItemTooltip.getCoinsMessage(totalCraftCost / outputIngredient.getAmount(), amountInStack))));

} catch (Exception e) {
LOGGER.error("[Skyblocker Craft Price] Error calculating craftprice tooltip for: " + internalID, e);
}
}

private double getItemCost(NEURecipe recipe, int depth) {
if (depth >= MAX_RECURSION_DEPTH) return -1;

double totalCraftCost = 0;
for (NEUIngredient input : recipe.getAllInputs()) {
String inputItemName = input.getItemId();
double inputItemCount = input.getAmount();
if (cachedCraftCosts.containsKey(inputItemName)) {
totalCraftCost += cachedCraftCosts.get(inputItemName) * inputItemCount;
continue;
}

double itemCost = 0;

if (TooltipInfoType.BAZAAR.getData().has(inputItemName)) {
itemCost = TooltipInfoType.BAZAAR.getData().getAsJsonObject(inputItemName).get(SkyblockerConfigManager.get().general.itemTooltip.enableCraftingCost.getOrder()).getAsDouble();
} else if (TooltipInfoType.LOWEST_BINS.getData().has(inputItemName)) {
itemCost = TooltipInfoType.LOWEST_BINS.getData().get(inputItemName).getAsDouble();
}

if (itemCost > 0) {
cachedCraftCosts.put(inputItemName, itemCost);
}

NEUItem neuItem = NEURepoManager.NEU_REPO.getItems().getItemBySkyblockId(inputItemName);
if (neuItem != null) {
List<NEURecipe> 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);
}
}

totalCraftCost += itemCost * inputItemCount;
}
return totalCraftCost;
}

public static void clearCache() {
cachedCraftCosts.clear();
}
}
6 changes: 6 additions & 0 deletions src/main/resources/assets/skyblocker/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@
"skyblocker.config.general.itemTooltip.avg.BOTH": "Both",
"skyblocker.config.general.itemTooltip.avg.ONE_DAY": "1 day price",
"skyblocker.config.general.itemTooltip.avg.THREE_DAY": "3 day price",
"skyblocker.config.general.itemTooltip.avg": "Average Type",
"skyblocker.config.general.itemTooltip.dungeonQuality": "Dungeon Quality",
"skyblocker.config.general.itemTooltip.dungeonQuality.@Tooltip": "Displays quality and tier of dungeon drops from mobs.\n\n\nReminder:\nTier 1-3 dropped from F1-F3\nTier 4-7 dropped from F4-F7 or M1-M4\nTier 8-10 are dropped only from M5-M7",
"skyblocker.config.general.itemTooltip.enableAccessoriesHelper": "Enable Accessories Helper",
Expand All @@ -239,6 +240,11 @@
"skyblocker.config.general.itemTooltip.enableAccessoriesHelper.@Tooltip[5]": "You don't own any accessory from this family.",
"skyblocker.config.general.itemTooltip.enableAvgBIN": "Enable Avg. BIN Price",
"skyblocker.config.general.itemTooltip.enableBazaarPrice": "Enable Bazaar buy/sell Price",
"skyblocker.config.general.itemTooltip.craft": "Crafting Cost",
"skyblocker.config.general.itemTooltip.craft.@Tooltip": "You can choose which Bazaar order type to use in crafting calculation",
"skyblocker.config.general.itemTooltip.craft.OFF": "Off",
"skyblocker.config.general.itemTooltip.craft.SELL_ORDER": "Sell Order",
"skyblocker.config.general.itemTooltip.craft.BUY_ORDER": "Buy Order",
"skyblocker.config.general.itemTooltip.enableExoticTooltip": "Enable Exotic Tooltip",
"skyblocker.config.general.itemTooltip.enableExoticTooltip.@Tooltip": "Displays the type of exotic below the item's name if an armor piece is exotic.",
"skyblocker.config.general.itemTooltip.enableLowestBIN": "Enable Lowest BIN Price",
Expand Down

0 comments on commit f9c8129

Please sign in to comment.