aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/at')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/Storage.java30
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/Slayer.java5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt7
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/HypixelTIck.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/SlayerQuestCompleteEvent.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerItemProfitTracker.kt174
-rw-r--r--src/main/java/at/hannibal2/skyhanni/test/PriceSource.kt8
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt12
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt4
9 files changed, 191 insertions, 55 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/config/Storage.java b/src/main/java/at/hannibal2/skyhanni/config/Storage.java
index 2de960a30..ec37aa1f7 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/Storage.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/Storage.java
@@ -189,5 +189,35 @@ public class Storage {
@Expose
public long nextCityProjectParticipationTime = 0L;
+
+ @Expose
+ public Map<String, SlayerProfitList> slayerProfitData = new HashMap<>();
+
+ public static class SlayerProfitList {
+
+ @Expose
+ public Map<String, SlayerItemProfit> items = new HashMap<>();
+
+ @Expose
+ public long mobKillCoins = 0;
+
+ @Expose
+ public long slayerSpawnCost = 0;
+
+ @Expose
+ public int slayerCompletedCount = 0;
+
+ public static class SlayerItemProfit {
+ @Expose
+ public String internalName;
+ @Expose
+ public long timesDropped;
+ @Expose
+ public long totalAmount;
+ @Expose
+ public boolean hidden;
+ }
+ }
+
}
} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/Slayer.java b/src/main/java/at/hannibal2/skyhanni/config/features/Slayer.java
index a5dad699c..0f69f6a20 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/Slayer.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/Slayer.java
@@ -105,6 +105,11 @@ public class Slayer {
public boolean priceInChat = false;
@Expose
+ @ConfigOption(name = "Show Price From", desc = "Show price from Bazaar or NPC.")
+ @ConfigEditorDropdown(values = {"Instant Sell", "Sell Offer", "NPC"})
+ public int priceFrom = 0;
+
+ @Expose
@ConfigOption(name = "Minimum Price", desc = "Items below this price will not show up in chat.")
@ConfigEditorSlider(minValue = 1, maxValue = 5_000_000, minStep = 1)
public int minimumPrice = 100_000;
diff --git a/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt
index 0d063146d..b5c287d5a 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt
@@ -2,6 +2,7 @@ package at.hannibal2.skyhanni.data
import at.hannibal2.skyhanni.events.LorenzChatEvent
import at.hannibal2.skyhanni.events.SlayerChangeEvent
+import at.hannibal2.skyhanni.events.SlayerQuestCompleteEvent
import at.hannibal2.skyhanni.features.bazaar.BazaarApi
import at.hannibal2.skyhanni.features.slayer.SlayerType
import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
@@ -82,9 +83,15 @@ object SlayerAPI {
@SubscribeEvent
fun onChat(event: LorenzChatEvent) {
+ if (!LorenzUtils.inSkyBlock) return
+
if (event.message.contains("§r§5§lSLAYER QUEST STARTED!")) {
questStartTime = System.currentTimeMillis()
}
+
+ if (event.message == " §r§a§lSLAYER QUEST COMPLETE!") {
+ SlayerQuestCompleteEvent().postAndCatch()
+ }
}
@SubscribeEvent
diff --git a/src/main/java/at/hannibal2/skyhanni/events/HypixelTIck.kt b/src/main/java/at/hannibal2/skyhanni/events/HypixelTIck.kt
deleted file mode 100644
index 42f015ff5..000000000
--- a/src/main/java/at/hannibal2/skyhanni/events/HypixelTIck.kt
+++ /dev/null
@@ -1,3 +0,0 @@
-package at.hannibal2.skyhanni.events
-
-class HypixelTickEvent: LorenzEvent() \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/events/SlayerQuestCompleteEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/SlayerQuestCompleteEvent.kt
new file mode 100644
index 000000000..5ed7ecac2
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/events/SlayerQuestCompleteEvent.kt
@@ -0,0 +1,3 @@
+package at.hannibal2.skyhanni.events
+
+class SlayerQuestCompleteEvent: LorenzEvent() \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerItemProfitTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerItemProfitTracker.kt
index e4ca7ca28..2e733a398 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerItemProfitTracker.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerItemProfitTracker.kt
@@ -1,23 +1,27 @@
package at.hannibal2.skyhanni.features.slayer
import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.config.Storage
+import at.hannibal2.skyhanni.data.ProfileStorageData
import at.hannibal2.skyhanni.data.SlayerAPI
import at.hannibal2.skyhanni.events.*
+import at.hannibal2.skyhanni.features.bazaar.BazaarApi
+import at.hannibal2.skyhanni.features.bazaar.BazaarData
+import at.hannibal2.skyhanni.test.PriceSource
+import at.hannibal2.skyhanni.utils.*
import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
import at.hannibal2.skyhanni.utils.ItemUtils.name
import at.hannibal2.skyhanni.utils.ItemUtils.nameWithEnchantment
-import at.hannibal2.skyhanni.utils.LorenzLogger
-import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.LorenzUtils.addAsSingletonList
-import at.hannibal2.skyhanni.utils.LorenzUtils.editCopy
+import at.hannibal2.skyhanni.utils.LorenzUtils.addSelector
import at.hannibal2.skyhanni.utils.LorenzUtils.sortedDesc
-import at.hannibal2.skyhanni.utils.NEUItems
-import at.hannibal2.skyhanni.utils.NumberUtil
import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
import at.hannibal2.skyhanni.utils.RenderUtils.renderStringsAndItems
import at.hannibal2.skyhanni.utils.StringUtils.removeColor
+import at.hannibal2.skyhanni.utils.renderables.Renderable
import com.google.common.cache.CacheBuilder
import net.minecraft.client.Minecraft
+import net.minecraft.client.gui.inventory.GuiInventory
import net.minecraft.entity.item.EntityItem
import net.minecraft.network.play.server.S0DPacketCollectItem
import net.minecraftforge.fml.common.eventhandler.EventPriority
@@ -30,17 +34,13 @@ class SlayerItemProfitTracker {
private var itemLogCategory = ""
private var display = listOf<List<Any>>()
- private var itemLogs = mapOf<String, ItemLog>()
- private val logger = LorenzLogger("slayer_item_profit_tracker")
+ private val logger = LorenzLogger("slayer/item_profit_tracker")
+ private var inventoryOpen = false
+ private var lastClickDelay = 0L
- private fun addSlayerCosts(price: Double) {
+ private fun addSlayerCosts(price: Int) {
val itemLog = currentLog() ?: return
-
- val name = "Slayer Spawn Costs"
- itemLog.items = itemLog.items.editCopy {
- val (oldCoins, oldAmount) = getOrDefault(name, 0.0 to 0)
- this[name] = oldCoins + price to oldAmount + 1
- }
+ itemLog.slayerSpawnCost += price
update()
}
@@ -51,54 +51,56 @@ class SlayerItemProfitTracker {
if (event.reason == PurseChangeCause.GAIN_MOB_KILL) {
if (SlayerAPI.isInSlayerArea) {
logger.log("Coins gained for killing mobs: ${coins.addSeparators()}")
- addMobKillCoins(coins)
+ addMobKillCoins(coins.toInt())
}
}
if (event.reason == PurseChangeCause.LOSE_SLAYER_QUEST_STARTED) {
logger.log("Coins paid for starting slayer quest: ${coins.addSeparators()}")
- addSlayerCosts(coins)
+ addSlayerCosts(coins.toInt())
}
}
@SubscribeEvent
fun onSlayerChange(event: SlayerChangeEvent) {
val newSlayer = event.newSlayer
- itemLogCategory = if (newSlayer == "") {
- ""
- } else {
- newSlayer.split(" ").dropLast(1).joinToString(" ")
- }
+ itemLogCategory = newSlayer.removeColor()
update()
}
- private fun addMobKillCoins(coins: Double) {
+ private fun addMobKillCoins(coins: Int) {
val itemLog = currentLog() ?: return
itemLog.mobKillCoins += coins
update()
}
- private fun addItemPickup(totalPrice: Double, displayName: String, stackSize: Int) {
+ private fun addItemPickup(internalName: String, stackSize: Int) {
val itemLog = currentLog() ?: return
- itemLog.items = itemLog.items.editCopy {
- val (oldCoins, oldAmount) = getOrDefault(displayName, 0.0 to 0)
- this[displayName] = oldCoins + totalPrice to oldAmount + stackSize
- }
+ val slayerItemProfit =
+ itemLog.items.getOrPut(internalName) { Storage.ProfileSpecific.SlayerProfitList.SlayerItemProfit() }
+
+ slayerItemProfit.timesDropped++
+ slayerItemProfit.totalAmount += stackSize
update()
}
- private fun currentLog(): ItemLog? {
+ private fun currentLog(): Storage.ProfileSpecific.SlayerProfitList? {
if (itemLogCategory == "") return null
- itemLogs[itemLogCategory]?.let {
- return it
+ val profileSpecific = ProfileStorageData.profileSpecific ?: return null
+
+ return profileSpecific.slayerProfitData.getOrPut(itemLogCategory) {
+ Storage.ProfileSpecific.SlayerProfitList()
}
+ }
- val itemLog = ItemLog(itemLogCategory)
- itemLogs = itemLogs.editCopy { this[itemLogCategory] = itemLog }
+ @SubscribeEvent
+ fun onQuestComplete(event: SlayerQuestCompleteEvent) {
+ val itemLog = currentLog() ?: return
- return itemLog
+ itemLog.slayerCompletedCount++
+ update()
}
@SubscribeEvent(priority = EventPriority.LOW, receiveCanceled = true)
@@ -123,8 +125,7 @@ class SlayerItemProfitTracker {
if (internalName == "") return
val (itemName, price) = SlayerAPI.getItemNameAndPrice(itemStack)
- val displayName = NEUItems.getItemStack(internalName).nameWithEnchantment ?: "internalName"
- addItemPickup(price, displayName, itemStack.stackSize)
+ addItemPickup(internalName, itemStack.stackSize)
logger.log("Coins gained for picking up an item ($itemName) ${price.addSeparators()}")
if (config.priceInChat) {
if (config.minimumPrice < price) {
@@ -140,31 +141,99 @@ class SlayerItemProfitTracker {
private fun drawDisplay() = buildList<List<Any>> {
val itemLog = currentLog() ?: return@buildList
- val displayName = itemLog.displayName.removeColor()
- addAsSingletonList("§e§l$displayName Profit Tracker")
+ addAsSingletonList("§e§l$itemLogCategory Profit Tracker")
var profit = 0.0
- val map = mutableMapOf<String, Double>()
- for ((name, value) in itemLog.items) {
- val (price, amount) = value
- val profitPrefix = if (price < 0) "§c" else "§6"
+ val map = mutableMapOf<Renderable, Long>()
+ for ((internalName, itemProfit) in itemLog.items) {
+ val amount = itemProfit.totalAmount
+
+ val bazaarData = BazaarApi.getBazaarDataByInternalName(internalName) ?: continue
+ val price = (getPrice(bazaarData) * amount).toLong()
+ var name = NEUItems.getItemStack(internalName).nameWithEnchantment ?: internalName
val priceFormat = NumberUtil.format(price)
- map["§7${amount.addSeparators()}x $name§7: $profitPrefix$priceFormat"] = price
+ val hidden = itemProfit.hidden
+ if (hidden) {
+// text += " §c(hidden)"
+ name = StringUtils.addFormat(name, "§m")
+ }
+ val text = " §7${amount.addSeparators()}x $name§7: §6$priceFormat"
+
+ val timesDropped = itemProfit.timesDropped
+ val percentage = timesDropped.toDouble() / itemLog.slayerCompletedCount
+ val perBoss = LorenzUtils.formatPercentage(percentage.coerceAtMost(1.0))
+
+
+ val renderable = if (inventoryOpen) Renderable.clickAndHover(
+ text, listOf(
+ "§7Dropped §e$timesDropped §7times.",
+ "§7Your drop rate: §c$perBoss",
+ "",
+ "§eClick to " + (if (hidden) "show" else "hide") + "!"
+ )
+ ) {
+ if (System.currentTimeMillis() > lastClickDelay + 150) {
+ lastClickDelay = System.currentTimeMillis()
+ itemProfit.hidden = !hidden
+ update()
+ }
+ } else Renderable.string(text)
+ if (inventoryOpen || !hidden) {
+ map[renderable] = price
+ }
profit += price
}
val mobKillCoins = itemLog.mobKillCoins
- if (mobKillCoins != 0.0) {
+ if (mobKillCoins != 0L) {
val mobKillCoinsFormat = NumberUtil.format(mobKillCoins)
- map["§7Mob kill coins: §6$mobKillCoinsFormat"] = mobKillCoins
+ map[Renderable.hoverTips(" §7Mob kill coins: §6$mobKillCoinsFormat",
+ listOf("§7Killing mobs gives you coins (more with scavenger)",
+ "§7You got §e$mobKillCoinsFormat §7coins in total this way"))] = mobKillCoins
+ profit += mobKillCoins
+ }
+ val slayerSpawnCost = itemLog.slayerSpawnCost
+ if (slayerSpawnCost != 0L) {
+ val mobKillCoinsFormat = NumberUtil.format(slayerSpawnCost)
+ map[Renderable.hoverTips(" §7Slayer Spawn Costs: §c$mobKillCoinsFormat",
+ listOf("§7You paid §c$mobKillCoinsFormat §7in total", "§7for starting the slayer quests."))] = slayerSpawnCost
+ profit += slayerSpawnCost
}
for (text in map.sortedDesc().keys) {
- addAsSingletonList(" $text")
+ addAsSingletonList(text)
}
+ val slayerCompletedCount = itemLog.slayerCompletedCount
+ addAsSingletonList(Renderable.hoverTips("§7Bosses killed: §e$slayerCompletedCount",
+ listOf("§7You killed the $itemLogCategory boss", "§e$slayerCompletedCount §7times.")))
+
profit += mobKillCoins
val profitFormat = NumberUtil.format(profit)
val profitPrefix = if (profit < 0) "§c" else "§6"
- addAsSingletonList("§eTotal Profit: $profitPrefix$profitFormat")
+
+ val profitPerBoss = profit / itemLog.slayerCompletedCount
+ val profitPerBossFormat = NumberUtil.format(profitPerBoss)
+
+ val text = "§eTotal Profit: $profitPrefix$profitFormat"
+ addAsSingletonList(Renderable.hoverTips(text, listOf("§7Profit per boss: $profitPrefix$profitPerBossFormat")))
+
+ if (inventoryOpen) {
+ addSelector(" ", PriceSource.values(),
+ getName = { type -> type.displayName },
+ isCurrent = { it.ordinal == config.priceFrom },
+ onChange = {
+ config.priceFrom = it.ordinal
+ update()
+ })
+ }
+ }
+
+ private fun getPrice(bazaarData: BazaarData): Double {
+ return when (config.priceFrom) {
+ 0 -> bazaarData.sellPrice
+ 1 -> bazaarData.buyPrice
+
+ else -> bazaarData.npcPrice
+ }
}
@SubscribeEvent
@@ -172,14 +241,15 @@ class SlayerItemProfitTracker {
if (!isEnabled()) return
if (!SlayerAPI.isInSlayerArea) return
+ val currentlyOpen = Minecraft.getMinecraft().currentScreen is GuiInventory
+ if (inventoryOpen != currentlyOpen) {
+ inventoryOpen = currentlyOpen
+ update()
+ }
+
+
config.pos.renderStringsAndItems(display, posLabel = "Slayer Item Profit Tracker")
}
fun isEnabled() = LorenzUtils.inSkyBlock && config.enabled
-
- class ItemLog(val displayName: String) {
- // display name -> (totalCoins, amount)
- var items = mapOf<String, Pair<Double, Int>>()
- var mobKillCoins = 0.0
- }
}
diff --git a/src/main/java/at/hannibal2/skyhanni/test/PriceSource.kt b/src/main/java/at/hannibal2/skyhanni/test/PriceSource.kt
new file mode 100644
index 000000000..684440ba1
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/test/PriceSource.kt
@@ -0,0 +1,8 @@
+package at.hannibal2.skyhanni.test
+
+enum class PriceSource(val displayName: String) {
+ BAZAAR_INSTANT_SELL("Instant Sell"),
+ BAZAAR_SELL_OFFER("Sell Offer"),
+ NPC("Npc Price"),
+ ;
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt
index fc043e26b..90dcddf9b 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt
@@ -93,4 +93,16 @@ object StringUtils {
fun encodeBase64(input: String) = Base64.getEncoder().encodeToString(input.toByteArray())
fun decodeBase64(input: String) = Base64.getDecoder().decode(input).decodeToString()
+
+ fun addFormat(text: String, format: String): String {
+ if (text.length < 2) return text
+
+ val rawText = text.substring(2)
+ return if (rawText == text.removeColor()) {
+ val originalColor = text.substring(0, 2)
+ "$originalColor$format$rawText"
+ } else {
+ "$format$text"
+ }
+ }
} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt b/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt
index 9917799f7..5047c4744 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt
@@ -48,6 +48,10 @@ interface Renderable {
return clickable(hoverable(underlined(renderable), renderable, condition), onClick, 0, condition)
}
+ fun clickAndHover(text: String, tips: List<String>, onClick: () -> Unit): Renderable {
+ return clickable(hoverTips(text, tips), onClick)
+ }
+
fun clickable(render: Renderable, onClick: () -> Unit, button: Int = 0, condition: () -> Boolean = { true }) =
object : Renderable {
override val width: Int