From 0245386a8301cc5f45f4a4c8be8c66786016080e Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Date: Wed, 29 Mar 2023 19:37:52 +0200 Subject: Added Anita Medal Profit - Helps to identify profitable items to buy at the Anita item shop and potential profit from selling the item at the auction house. --- .../java/at/hannibal2/skyhanni/SkyHanniMod.java | 3 +- .../hannibal2/skyhanni/config/features/Garden.java | 20 +++ .../skyhanni/features/garden/AnitaMedalProfit.kt | 141 +++++++++++++++++++++ .../features/garden/GardenNextPlotPrice.kt | 7 +- .../features/garden/GardenVisitorFeatures.kt | 7 +- .../skyhanni/features/garden/SkyMartBestProfit.kt | 109 ---------------- .../skyhanni/features/garden/SkyMartCopperPrice.kt | 86 +++++++++++++ .../java/at/hannibal2/skyhanni/test/LorenzTest.kt | 4 +- .../at/hannibal2/skyhanni/utils/LorenzUtils.kt | 19 +++ 9 files changed, 279 insertions(+), 117 deletions(-) create mode 100644 src/main/java/at/hannibal2/skyhanni/features/garden/AnitaMedalProfit.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/garden/SkyMartBestProfit.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/garden/SkyMartCopperPrice.kt (limited to 'src/main/java/at') diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java index e23c2c37b..1d5281b60 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java @@ -212,7 +212,7 @@ public class SkyHanniMod { loadModule(new TpsCounter()); loadModule(new ParticleHider()); loadModule(new MiscFeatures()); - loadModule(new SkyMartBestProfit()); + loadModule(new SkyMartCopperPrice()); loadModule(new GardenVisitorFeatures()); loadModule(new GardenInventoryNumbers()); loadModule(new GardenVisitorTimer()); @@ -233,6 +233,7 @@ public class SkyHanniMod { loadModule(new JoinCrystalHollows()); loadModule(new GardenVisitorColorNames()); loadModule(new GardenTeleportPadCompactName()); + loadModule(new AnitaMedalProfit()); Commands.INSTANCE.init(); diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/Garden.java b/src/main/java/at/hannibal2/skyhanni/config/features/Garden.java index 528eb7966..b440f9dbd 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/Garden.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/Garden.java @@ -584,6 +584,26 @@ public class Garden { @ConfigAccordionId(id = 12) public boolean teleportPadsCompactName = false; + @Expose + @ConfigOption(name = "Anita Medal Profit", desc = "") + @ConfigEditorAccordion(id = 12) + public boolean anitaMedalProfit = false; + + @Expose + @ConfigOption( + name = "Show Prices", + desc = "Helps to identify profitable items to buy at the Anita item shop " + + "and potential profit from selling the item at the auction house." + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 12) + public boolean anitaMedalProfitEnabled = true; + + @Expose + public Position anitaMedalProfitPos = new Position(206, 158, false, true); + + + @Expose @ConfigOption(name = "Plot Price", desc = "Show the price of the plot in coins when inside the Configure Plots inventory.") @ConfigEditorBoolean diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/AnitaMedalProfit.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/AnitaMedalProfit.kt new file mode 100644 index 000000000..fa6500bcb --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/AnitaMedalProfit.kt @@ -0,0 +1,141 @@ +package at.hannibal2.skyhanni.features.garden + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.InventoryCloseEvent +import at.hannibal2.skyhanni.events.InventoryOpenEvent +import at.hannibal2.skyhanni.utils.ItemUtils +import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.ItemUtils.name +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzUtils.addAsSingletonList +import at.hannibal2.skyhanni.utils.NEUItems +import at.hannibal2.skyhanni.utils.NumberUtil +import at.hannibal2.skyhanni.utils.RenderUtils.renderStringsAndItems +import net.minecraft.item.ItemStack +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +class AnitaMedalProfit { + private val config get() = SkyHanniMod.feature.garden + private var display = listOf>() + + companion object { + var inInventory = false + } + + enum class MedalType(val displayName: String, val factorBronze: Int) { + GOLD("§6Gold medal", 8), + SILVER("§fSilver medal", 2), + BRONZE("§cBronze medal", 1), + ; + } + + private fun getMedal(name: String) = MedalType.values().firstOrNull { it.displayName == name } + + @SubscribeEvent + fun onInventoryClose(event: InventoryCloseEvent) { + inInventory = false + } + + @SubscribeEvent + fun onInventoryOpen(event: InventoryOpenEvent) { + if (!config.anitaMedalProfitEnabled) return + if (event.inventoryName != "Anita") return + + inInventory = true + + val table = mutableMapOf, Pair>() + for ((_, item) in event.inventoryItems) { + readItem(item, table) + } + + val newList = mutableListOf>() + newList.addAsSingletonList("§eMedal Profit") + LorenzUtils.fillTable(newList, table) + display = newList + } + + private fun readItem(item: ItemStack, table: MutableMap, Pair>) { + var itemName = item.name ?: return + if (itemName == " ") return + if (itemName.endsWith("Enchanted Book")) { + itemName = item.getLore()[0] + } + + val fullCost = getFullCost(getRequiredItems(item)) + if (fullCost < 0) return + + val (name, amount) = ItemUtils.readItemAmount(itemName) + if (name == null) return + + val internalName = try { + NEUItems.getInternalName(name) + } catch (e: Exception) { + // TODO make a better alternative + item.getInternalName() + } + + val itemPrice = NEUItems.getPrice(internalName) * amount + if (itemPrice < 0) return + + val profit = itemPrice - fullCost + val format = NumberUtil.format(profit) + val color = if (profit > 0) "§6" else "§c" + table[Pair(itemName, "$color$format")] = Pair(profit, internalName) + } + + private fun getFullCost(requiredItems: MutableList): Double { + val jacobTicketPrice = NEUItems.getPrice("JACOBS_TICKET") + var otherItemsPrice = 0.0 + for (rawItemName in requiredItems) { + val (name, amount) = ItemUtils.readItemAmount(rawItemName) + if (name == null) { + LorenzUtils.error("§c[SkyHanni] Could not read item '$rawItemName'") + continue + } + + val medal = getMedal(name) + otherItemsPrice += if (medal != null) { + val bronze = medal.factorBronze * amount + bronze * jacobTicketPrice + } else { + val internalName = NEUItems.getInternalName(name) + NEUItems.getPrice(internalName) * amount + } + } + return otherItemsPrice + } + + private fun getRequiredItems(item: ItemStack): MutableList { + val items = mutableListOf() + var next = false + for (line in item.getLore()) { + if (line == "§7Cost") { + next = true + continue + } + if (next) { + if (line == "") { + next = false + continue + } + + items.add(line.replace("§8 ", " §8")) + } + } + return items + } + + @SubscribeEvent + fun onBackgroundDraw(event: GuiRenderEvent.ChestBackgroundRenderEvent) { + if (inInventory) { + config.anitaMedalProfitPos.renderStringsAndItems( + display, + extraSpace = 5, + itemScale = 1.7, + posLabel = "Anita Medal Profit" + ) + } + } +} \ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextPlotPrice.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextPlotPrice.kt index abea33203..85b61db60 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextPlotPrice.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextPlotPrice.kt @@ -1,11 +1,8 @@ package at.hannibal2.skyhanni.features.garden import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.utils.InventoryUtils -import at.hannibal2.skyhanni.utils.ItemUtils +import at.hannibal2.skyhanni.utils.* import at.hannibal2.skyhanni.utils.ItemUtils.name -import at.hannibal2.skyhanni.utils.NEUItems -import at.hannibal2.skyhanni.utils.NumberUtil import net.minecraftforge.event.entity.player.ItemTooltipEvent import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @@ -39,6 +36,8 @@ class GardenNextPlotPrice { val price = lowestBin * amount val format = NumberUtil.format(price) list[i] = list[i] + " §7(§6$format§7)" + } else { + LorenzUtils.error("§c[SkyHanni] Could not read item '$line'") } break } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenVisitorFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenVisitorFeatures.kt index df71986ed..917b40b85 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenVisitorFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenVisitorFeatures.kt @@ -77,7 +77,10 @@ class GardenVisitorFeatures { if (line.isEmpty()) break val (itemName, amount) = ItemUtils.readItemAmount(line) - if (itemName == null) continue + if (itemName == null) { + LorenzUtils.error("§c[SkyHanni] Could not read item '$line'") + continue + } val internalName = NEUItems.getInternalName(itemName) visitor.items[internalName] = amount } @@ -287,6 +290,8 @@ class GardenVisitorFeatures { list.add(i + itemsWithSpeedCounter, " §7- $formatName($formatSpeed§7)") } } + } else { + LorenzUtils.error("§c[SkyHanni] Could not read item '$line'") } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/SkyMartBestProfit.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/SkyMartBestProfit.kt deleted file mode 100644 index a4d1e5bd1..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/SkyMartBestProfit.kt +++ /dev/null @@ -1,109 +0,0 @@ -package at.hannibal2.skyhanni.features.garden - -import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.events.GuiRenderEvent -import at.hannibal2.skyhanni.events.InventoryCloseEvent -import at.hannibal2.skyhanni.events.InventoryOpenEvent -import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName -import at.hannibal2.skyhanni.utils.ItemUtils.getLore -import at.hannibal2.skyhanni.utils.ItemUtils.name -import at.hannibal2.skyhanni.utils.LorenzUtils.addAsSingletonList -import at.hannibal2.skyhanni.utils.LorenzUtils.sortedDesc -import at.hannibal2.skyhanni.utils.NEUItems -import at.hannibal2.skyhanni.utils.NumberUtil -import at.hannibal2.skyhanni.utils.RenderUtils.renderStringsAndItems -import at.hannibal2.skyhanni.utils.StringUtils.removeColor -import net.minecraft.client.Minecraft -import net.minecraft.item.ItemStack -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -import java.util.regex.Pattern - -class SkyMartBestProfit { - - private val pattern = Pattern.compile("§c(.*) Copper") - private var display = listOf>() - private val config get() = SkyHanniMod.feature.garden - - @SubscribeEvent - fun onInventoryOpen(event: InventoryOpenEvent) { - if (!isEnabled()) return - - if (event.inventoryName != "SkyMart") return - - val priceMap = mutableMapOf, Double>() - val iconMap = mutableMapOf() - - for (stack in event.inventoryItems.values) { - for (line in stack.getLore()) { - val matcher = pattern.matcher(line) - if (!matcher.matches()) continue - - val internalName = stack.getInternalName() - val lowestBin = NEUItems.getPrice(internalName) - if (lowestBin == -1.0) continue - - val amount = matcher.group(1).replace(",", "").toInt() - val factor = lowestBin / amount - val perFormat = NumberUtil.format(factor) - val priceFormat = NumberUtil.format(lowestBin) - val amountFormat = NumberUtil.format(amount) - - var name = stack.name!! - if (name == "§fEnchanted Book") { - name = stack.getLore()[0] - } - - NEUItems.getItemStackOrNull(internalName)?.let { - iconMap[name] = it - } - - val advancedStats = if (config.skyMartCopperPriceAdvancedStats) { - " §7(§6$priceFormat §7/ §c$amountFormat Copper§7)" - } else "" - val pair = Pair(name, "§6§l$perFormat$advancedStats") - priceMap[pair] = factor - } - } - - display = drawDisplay(priceMap, iconMap) - } - - private fun drawDisplay( - priceMap: MutableMap, Double>, - iconMap: MutableMap, - ): MutableList> { - val newList = mutableListOf>() - - newList.addAsSingletonList("Coins per §cCopper§f:") - newList.addAsSingletonList("") - - val keys = priceMap.sortedDesc().keys - val renderer = Minecraft.getMinecraft().fontRendererObj - val longest = keys.map { it.first }.maxOfOrNull { renderer.getStringWidth(it.removeColor()) } ?: 0 - - for ((name, second) in keys) { - var displayName = "$name§f:" - while (renderer.getStringWidth(displayName.removeColor()) < longest) { - displayName += " " - } - iconMap[name]?.let { - newList.add(listOf(it, "$displayName $second")) - } - } - return newList - } - - @SubscribeEvent - fun onInventoryClose(event: InventoryCloseEvent) { - display = emptyList() - } - - @SubscribeEvent - fun onBackgroundDraw(event: GuiRenderEvent.ChestBackgroundRenderEvent) { - if (isEnabled()) { - config.skyMartCopperPricePos.renderStringsAndItems(display, posLabel = "Sky Mart Copper Price") - } - } - - private fun isEnabled() = GardenAPI.inGarden() && config.skyMartCopperPrice -} \ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/SkyMartCopperPrice.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/SkyMartCopperPrice.kt new file mode 100644 index 000000000..7457224e6 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/SkyMartCopperPrice.kt @@ -0,0 +1,86 @@ +package at.hannibal2.skyhanni.features.garden + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.InventoryCloseEvent +import at.hannibal2.skyhanni.events.InventoryOpenEvent +import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.ItemUtils.name +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzUtils.addAsSingletonList +import at.hannibal2.skyhanni.utils.NEUItems +import at.hannibal2.skyhanni.utils.NumberUtil +import at.hannibal2.skyhanni.utils.RenderUtils.renderStringsAndItems +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import java.util.regex.Pattern + +class SkyMartCopperPrice { + private val pattern = Pattern.compile("§c(.*) Copper") + private var display = listOf>() + private val config get() = SkyHanniMod.feature.garden + + companion object { + var inInventory = false + } + + @SubscribeEvent + fun onInventoryOpen(event: InventoryOpenEvent) { + if (!isEnabled()) return + if (event.inventoryName != "SkyMart") return + + inInventory = true + val table = mutableMapOf, Pair>() + for (stack in event.inventoryItems.values) { + for (line in stack.getLore()) { + val matcher = pattern.matcher(line) + if (!matcher.matches()) continue + + val internalName = stack.getInternalName() + val lowestBin = NEUItems.getPrice(internalName) + if (lowestBin == -1.0) continue + + val amount = matcher.group(1).replace(",", "").toInt() + val factor = lowestBin / amount + val perFormat = NumberUtil.format(factor) + val priceFormat = NumberUtil.format(lowestBin) + val amountFormat = NumberUtil.format(amount) + + var name = stack.name!! + if (name == "§fEnchanted Book") { + name = stack.getLore()[0] + } + + val advancedStats = if (config.skyMartCopperPriceAdvancedStats) { + " §7(§6$priceFormat §7/ §c$amountFormat Copper§7)" + } else "" + val pair = Pair("$name§f:", "§6§l$perFormat$advancedStats") + table[pair] = Pair(factor, internalName) + } + } + + val newList = mutableListOf>() + newList.addAsSingletonList("§eCoins per Copper§f:") + LorenzUtils.fillTable(newList, table) + display = newList + } + + @SubscribeEvent + fun onInventoryClose(event: InventoryCloseEvent) { + inInventory = false + } + + @SubscribeEvent + fun onBackgroundDraw(event: GuiRenderEvent.ChestBackgroundRenderEvent) { + if (inInventory) { + config.skyMartCopperPricePos.renderStringsAndItems( + display, + extraSpace = 5, + itemScale = 1.7, + posLabel = "Sky Mart Copper Price" + ) + } + } + + private fun isEnabled() = GardenAPI.inGarden() && config.skyMartCopperPrice +} \ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/test/LorenzTest.kt b/src/main/java/at/hannibal2/skyhanni/test/LorenzTest.kt index 9f78e5452..02feac91c 100644 --- a/src/main/java/at/hannibal2/skyhanni/test/LorenzTest.kt +++ b/src/main/java/at/hannibal2/skyhanni/test/LorenzTest.kt @@ -52,8 +52,8 @@ class LorenzTest { // SoundUtils.createSound(name, pitch).playSound() -// a = args[0].toDouble() -// b = args[1].toDouble() + a = args[0].toDouble() + b = args[1].toDouble() // c = args[2].toDouble() // for (line in (Minecraft.getMinecraft().ingameGUI.tabList as AccessorGuiPlayerTabOverlay).footer.unformattedText diff --git a/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt index 7378d6131..8e9b9de9e 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt @@ -171,4 +171,23 @@ object LorenzUtils { fun MutableList>.addAsSingletonList(text: E) { add(Collections.singletonList(text)) } + + // (key -> value) -> (sorting value -> key item icon) + fun fillTable(list: MutableList>, data: MutableMap, Pair>) { + val keys = data.mapValues { (_, v) -> v.first }.sortedDesc().keys + val renderer = Minecraft.getMinecraft().fontRendererObj + val longest = keys.map { it.first }.maxOfOrNull { renderer.getStringWidth(it.removeColor()) } ?: 0 + + for (pair in keys) { + val (name, second) = pair + var displayName = name + while (renderer.getStringWidth(displayName.removeColor()) < longest) { + displayName += " " + } + + NEUItems.getItemStackOrNull(data[pair]!!.second)?.let { + list.add(listOf(it, "$displayName $second")) + } + } + } } \ No newline at end of file -- cgit