aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni/data
diff options
context:
space:
mode:
authorhannibal2 <24389977+hannibal00212@users.noreply.github.com>2023-09-16 12:34:18 +0200
committerhannibal2 <24389977+hannibal00212@users.noreply.github.com>2023-09-16 12:34:18 +0200
commit4293cfd919c3c93d4532534f722c407d7ad1370d (patch)
treef9f612f021ef7f4283d74312edfaca30badc6749 /src/main/java/at/hannibal2/skyhanni/data
parent538e3ceb76f8e0b590291ce9aa90aa94896cdcb6 (diff)
parent024ba52fb69b6cd44b4e31542867f802de656f15 (diff)
downloadSkyHanni-cum.tar.gz
SkyHanni-cum.tar.bz2
SkyHanni-cum.zip
Merge branch 'beta' into cumcum
# Conflicts: # src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt # src/main/java/at/hannibal2/skyhanni/config/features/AshfangConfig.java
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/data')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt9
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt19
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/ItemTipHelper.kt14
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/MayorElection.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/OwnInventoryData.kt4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/ProfileStorageData.kt30
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt335
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/TitleUtils.kt12
10 files changed, 401 insertions, 34 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt b/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt
index 4954d2caf..c7ddf1777 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt
@@ -156,8 +156,8 @@ object ChatManager {
val chatGUI = Minecraft.getMinecraft().ingameGUI.chatGUI
@Suppress("UNCHECKED_CAST")
- val chatLines = chatLinesField.invokeExact(chatGUI) as MutableList<ChatLine>
- if (!chatLines.removeIf { it.chatComponent === message }) return
+ val chatLines = chatLinesField.invokeExact(chatGUI) as MutableList<ChatLine?>? ?: return
+ if (!chatLines.removeIf { it?.chatComponent === message }) return
chatGUI.refreshChat()
val history = messageHistory[IdentityCharacteristics(message)] ?: return
diff --git a/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt b/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt
index be373f62f..d778be299 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt
@@ -91,12 +91,9 @@ class GuiEditManager {
fun isInGui() = Minecraft.getMinecraft().currentScreen is GuiPositionEditor
fun Position.getDummySize(random: Boolean = false): Vector2i {
- if (random) {
- return Vector2i(5, 5)
- } else {
- val (x, y) = currentBorderSize[internalName] ?: return Vector2i(1, 1)
- return Vector2i(x, y)
- }
+ if (random) return Vector2i(5, 5)
+ val (x, y) = currentBorderSize[internalName] ?: return Vector2i(1, 1)
+ return Vector2i((x * effectiveScale).toInt(), (y * effectiveScale).toInt())
}
fun Position.getAbsX() = getAbsX0(getDummySize(true).x)
diff --git a/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt b/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt
index f8b0cfed3..abd5615ea 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt
@@ -1,17 +1,24 @@
package at.hannibal2.skyhanni.data
+import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.events.*
+import at.hannibal2.skyhanni.utils.LocationUtils.isPlayerInside
import at.hannibal2.skyhanni.utils.LorenzLogger
import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher
import at.hannibal2.skyhanni.utils.StringUtils.removeColor
import at.hannibal2.skyhanni.utils.TabListData
import net.minecraft.client.Minecraft
+import net.minecraft.util.AxisAlignedBB
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import net.minecraftforge.fml.common.network.FMLNetworkEvent
class HypixelData {
private val tabListProfilePattern = "§e§lProfile: §r§a(?<profile>.*)".toPattern()
+ private val westVillageFarmArea = AxisAlignedBB(-54.0, 69.0, -115.0, -40.0, 75.0, -127.0)
+ private val howlingCaveArea = AxisAlignedBB(-401.0, 50.0, -104.0, -337.0, 90.0, 36.0)
+ private val fakeZealotBruiserHideoutArea = AxisAlignedBB(-520.0, 66.0, -332.0, -558.0, 85.0, -280.0)
+ private val realZealotBruiserHideoutArea = AxisAlignedBB(-552.0, 50.0, -245.0, -580.0, 72.0, -209.0)
companion object {
var hypixelLive = false
@@ -69,10 +76,20 @@ class HypixelData {
fun onTick(event: LorenzTickEvent) {
if (event.isMod(2)) {
if (LorenzUtils.inSkyBlock) {
- skyBlockArea = ScoreboardData.sidebarLinesFormatted
+ val originalLocation = ScoreboardData.sidebarLinesFormatted
.firstOrNull { it.startsWith(" §7⏣ ") || it.startsWith(" §5ф ") }
?.substring(5)?.removeColor()
?: "?"
+
+ skyBlockArea = when {
+ skyBlockIsland == IslandType.THE_RIFT && westVillageFarmArea.isPlayerInside() -> "Dreadfarm"
+ skyBlockIsland == IslandType.THE_PARK && howlingCaveArea.isPlayerInside() -> "Howling Cave"
+ skyBlockIsland == IslandType.THE_END && fakeZealotBruiserHideoutArea.isPlayerInside() -> "The End"
+ skyBlockIsland == IslandType.THE_END && realZealotBruiserHideoutArea.isPlayerInside() -> "Zealot Bruiser Hideout"
+
+ else -> originalLocation
+ }
+
checkProfileName()
}
}
diff --git a/src/main/java/at/hannibal2/skyhanni/data/ItemTipHelper.kt b/src/main/java/at/hannibal2/skyhanni/data/ItemTipHelper.kt
index ee699b161..30f2b51b7 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/ItemTipHelper.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/ItemTipHelper.kt
@@ -7,6 +7,7 @@ import at.hannibal2.skyhanni.events.RenderItemTipEvent
import at.hannibal2.skyhanni.mixins.transformers.gui.AccessorGuiContainer
import at.hannibal2.skyhanni.utils.InventoryUtils.getInventoryName
import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.RenderUtils.drawSlotText
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.inventory.GuiChest
import net.minecraft.client.renderer.GlStateManager
@@ -26,20 +27,13 @@ class ItemTipHelper {
if (itemTipEvent.renderObjects.isEmpty()) return
- GlStateManager.disableLighting()
- GlStateManager.disableDepth()
- GlStateManager.disableBlend()
-
for (renderObject in itemTipEvent.renderObjects) {
- val fontRenderer = event.fontRenderer
val text = renderObject.text
- val x = event.x + 17 - fontRenderer.getStringWidth(text) + renderObject.offsetX
+ val x = event.x + 17 + renderObject.offsetX
val y = event.y + 9 + renderObject.offsetY
- fontRenderer.drawStringWithShadow(text, x.toFloat(), y.toFloat(), 16777215)
- }
- GlStateManager.enableLighting()
- GlStateManager.enableDepth()
+ event.drawSlotText(x, y, text, 1f)
+ }
}
@SubscribeEvent(priority = EventPriority.HIGHEST)
diff --git a/src/main/java/at/hannibal2/skyhanni/data/MayorElection.kt b/src/main/java/at/hannibal2/skyhanni/data/MayorElection.kt
index 0681b8632..2508391d9 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/MayorElection.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/MayorElection.kt
@@ -58,7 +58,7 @@ class MayorElection {
private fun checkCurrentMayor() {
var currentYear = SkyBlockTime.now().year
- // The time in the current skyblock year when the election circle will restart
+ // The time in the current SkyBlock year when the election circle will restart
val month = 3 // Late Spring
val nextMayorTime = SkyBlockTime(currentYear, month, day = 27).toMillis()
diff --git a/src/main/java/at/hannibal2/skyhanni/data/OwnInventoryData.kt b/src/main/java/at/hannibal2/skyhanni/data/OwnInventoryData.kt
index dd9ccef71..93d85d1a6 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/OwnInventoryData.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/OwnInventoryData.kt
@@ -2,7 +2,7 @@ package at.hannibal2.skyhanni.data
import at.hannibal2.skyhanni.api.CollectionAPI
import at.hannibal2.skyhanni.events.InventoryCloseEvent
-import at.hannibal2.skyhanni.events.OwnInventorItemUpdateEvent
+import at.hannibal2.skyhanni.events.OwnInventoryItemUpdateEvent
import at.hannibal2.skyhanni.events.PacketEvent
import at.hannibal2.skyhanni.features.bazaar.BazaarApi
import at.hannibal2.skyhanni.utils.ItemUtils.getInternalNameOrNull
@@ -29,7 +29,7 @@ class OwnInventoryData {
val windowId = packet.func_149175_c()
if (windowId == 0) {
val item = packet.func_149174_e() ?: return
- OwnInventorItemUpdateEvent(item).postAndCatch()
+ OwnInventoryItemUpdateEvent(item).postAndCatch()
}
}
if (packet is S2FPacketSetSlot) {
diff --git a/src/main/java/at/hannibal2/skyhanni/data/ProfileStorageData.kt b/src/main/java/at/hannibal2/skyhanni/data/ProfileStorageData.kt
index f9eb6b024..b4ad1d1af 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/ProfileStorageData.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/ProfileStorageData.kt
@@ -1,6 +1,7 @@
package at.hannibal2.skyhanni.data
import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.config.SackData
import at.hannibal2.skyhanni.config.Storage
import at.hannibal2.skyhanni.events.*
import at.hannibal2.skyhanni.utils.LorenzUtils
@@ -17,6 +18,10 @@ object ProfileStorageData {
private var nextProfile: String? = null
+
+ private var sackPlayers: SackData.PlayerSpecific? = null
+ var sackProfiles: SackData.ProfileSpecific? = null
+
@SubscribeEvent(priority = EventPriority.HIGHEST)
fun onChat(event: LorenzChatEvent) {
"§7Switching to profile (?<name>.*)\\.\\.\\.".toPattern().matchMatcher(event.message) {
@@ -32,25 +37,35 @@ object ProfileStorageData {
nextProfile = null
val playerSpecific = playerSpecific
+ val sackPlayers = sackPlayers
if (playerSpecific == null) {
LorenzUtils.error("profileSpecific after profile swap can not be set: playerSpecific is null!")
return
}
- loadProfileSpecific(playerSpecific, profileName, "profile swap (chat message)")
+ if (sackPlayers == null) {
+ LorenzUtils.error("sackPlayers after profile swap can not be set: sackPlayers is null!")
+ return
+ }
+ loadProfileSpecific(playerSpecific, sackPlayers, profileName, "profile swap (chat message)")
ConfigLoadEvent().postAndCatch()
}
@SubscribeEvent(priority = EventPriority.HIGHEST)
fun onProfileJoin(event: ProfileJoinEvent) {
val playerSpecific = playerSpecific
+ val sackPlayers = sackPlayers
if (playerSpecific == null) {
LorenzUtils.error("playerSpecific is null in ProfileJoinEvent!")
return
}
+ if (sackPlayers == null) {
+ LorenzUtils.error("sackPlayers is null in sackPlayers!")
+ return
+ }
if (profileSpecific == null) {
val profileName = event.name
- loadProfileSpecific(playerSpecific, profileName, "first join (chat message)")
+ loadProfileSpecific(playerSpecific, sackPlayers, profileName, "first join (chat message)")
}
}
@@ -58,11 +73,12 @@ object ProfileStorageData {
fun onTabListUpdate(event: TabListUpdateEvent) {
if (profileSpecific != null) return
val playerSpecific = playerSpecific ?: return
+ val sackPlayers = sackPlayers ?: return
for (line in event.tabList) {
val pattern = "§e§lProfile: §r§a(?<name>.*)".toPattern()
pattern.matchMatcher(line) {
val profileName = group("name").lowercase()
- loadProfileSpecific(playerSpecific, profileName, "tab list")
+ loadProfileSpecific(playerSpecific, sackPlayers, profileName, "tab list")
nextProfile = null
return
}
@@ -87,18 +103,20 @@ object ProfileStorageData {
}
}
- private fun loadProfileSpecific(playerSpecific: Storage.PlayerSpecific, profileName: String, reason: String) {
+ private fun loadProfileSpecific(playerSpecific: Storage.PlayerSpecific, sackProfile: SackData.PlayerSpecific, profileName: String, reason: String) {
noTabListTime = -1
profileSpecific = playerSpecific.profiles.getOrPut(profileName) { Storage.ProfileSpecific() }
+ sackProfiles = sackProfile.profiles.getOrPut(profileName) { SackData.ProfileSpecific() }
tryMigrateProfileSpecific()
- ConfigLoadEvent().postAndCatch()
loaded = true
+ ConfigLoadEvent().postAndCatch()
}
@SubscribeEvent
fun onHypixelJoin(event: HypixelJoinEvent) {
val playerUuid = LorenzUtils.getRawPlayerUuid()
playerSpecific = SkyHanniMod.feature.storage.players.getOrPut(playerUuid) { Storage.PlayerSpecific() }
+ sackPlayers = SkyHanniMod.sackData.players.getOrPut(playerUuid) { SackData.PlayerSpecific() }
migratePlayerSpecific()
ConfigLoadEvent().postAndCatch()
}
@@ -137,7 +155,7 @@ object ProfileStorageData {
}
profileSpecific?.garden?.let {
- it.experience = oldHidden.gardenExp
+ it.experience = oldHidden.gardenExp.toLong()
it.cropCounter = oldHidden.gardenCropCounter
it.cropUpgrades = oldHidden.gardenCropUpgrades
diff --git a/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt
new file mode 100644
index 000000000..89363fd7c
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt
@@ -0,0 +1,335 @@
+package at.hannibal2.skyhanni.data
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.events.InventoryCloseEvent
+import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent
+import at.hannibal2.skyhanni.events.LorenzChatEvent
+import at.hannibal2.skyhanni.events.SackChangeEvent
+import at.hannibal2.skyhanni.features.fishing.trophy.TrophyFishManager
+import at.hannibal2.skyhanni.features.fishing.trophy.TrophyRarity
+import at.hannibal2.skyhanni.features.inventory.SackDisplay
+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.editCopy
+import at.hannibal2.skyhanni.utils.NEUInternalName
+import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName
+import at.hannibal2.skyhanni.utils.NEUItems.getNpcPriceOrNull
+import at.hannibal2.skyhanni.utils.NEUItems.getPrice
+import at.hannibal2.skyhanni.utils.NumberUtil.formatNumber
+import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher
+import at.hannibal2.skyhanni.utils.StringUtils.removeColor
+import com.google.gson.annotations.Expose
+import net.minecraft.item.ItemStack
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+
+object SackAPI {
+ private val sackDisplayConfig get() = SkyHanniMod.feature.inventory.sackDisplay
+ private var lastOpenedInventory = ""
+
+ var inSackInventory = false
+ private val sackPattern = "^(.* Sack|Enchanted .* Sack)$".toPattern()
+ private val numPattern =
+ "(?:(?:§[0-9a-f](?<level>I{1,3})§7:)?|(?:§7Stored:)?) (?<color>§[0-9a-f])(?<stored>[0-9.,kKmMbB]+)§7/(?<total>\\d+(?:[0-9.,]+)?[kKmMbB]?)".toPattern()
+ private val gemstonePattern =
+ " §[0-9a-f](?<gemrarity>[A-z]*): §[0-9a-f](?<stored>\\d+(?:\\.\\d+)?(?:(?:,\\d+)?)+[kKmM]?)(?: §[0-9a-f]\\(\\d+(?:\\.\\d+)?(?:(?:,\\d+)?)+[kKmM]?\\))?".toPattern()
+
+ private var isRuneSack = false
+ private var isGemstoneSack = false
+ var isTrophySack = false
+ private var sackRarity: TrophyRarity? = null
+
+ val sackItem = mutableMapOf<String, SackOtherItem>()
+ val runeItem = mutableMapOf<String, SackRune>()
+ val gemstoneItem = mutableMapOf<String, SackGemstone>()
+ private val stackList = mutableMapOf<Int, ItemStack>()
+
+ @SubscribeEvent
+ fun onInventoryClose(event: InventoryCloseEvent) {
+ inSackInventory = false
+ isRuneSack = false
+ isGemstoneSack = false
+ isTrophySack = false
+ runeItem.clear()
+ gemstoneItem.clear()
+ sackItem.clear()
+ stackList.clear()
+ }
+
+ @SubscribeEvent
+ fun onInventoryOpen(event: InventoryFullyOpenedEvent) {
+ val inventoryName = event.inventoryName
+ val isNewInventory = inventoryName != lastOpenedInventory
+ lastOpenedInventory = inventoryName
+ val match = sackPattern.matcher(inventoryName).matches()
+ if (!match) return
+ val stacks = event.inventoryItems
+ isRuneSack = inventoryName == "Runes Sack"
+ isGemstoneSack = inventoryName == "Gemstones Sack"
+ isTrophySack = inventoryName.contains("Trophy Fishing Sack")
+ sackRarity = inventoryName.getTrophyRarity()
+ inSackInventory = true
+ stackList.putAll(stacks)
+ SackDisplay.update(isNewInventory)
+ }
+
+ private fun String.getTrophyRarity(): TrophyRarity? {
+ return if (this.startsWith("Bronze"))
+ TrophyRarity.BRONZE
+ else
+ if (this.startsWith("Silver"))
+ TrophyRarity.SILVER
+ else null
+ }
+
+ private fun NEUInternalName.sackPrice(stored: String) = when (sackDisplayConfig.priceFrom) {
+ 0 -> (getPrice(true) * stored.formatNumber()).toInt().let { if (it < 0) 0 else it }
+
+ 1 -> try {
+ val npcPrice = getNpcPriceOrNull() ?: 0.0
+ (npcPrice * stored.formatNumber()).toInt()
+ } catch (e: Exception) {
+ 0
+ }
+
+ else -> 0
+ }
+
+ fun getSacksData(savingSacks: Boolean) {
+ if (savingSacks) sackData = ProfileStorageData.sackProfiles?.sackContents ?: return
+ for ((_, stack) in stackList) {
+ val name = stack.name ?: continue
+ val lore = stack.getLore()
+ val gem = SackGemstone()
+ val rune = SackRune()
+ val item = SackOtherItem()
+ loop@ for (line in lore) {
+ if (isGemstoneSack) {
+ gemstonePattern.matchMatcher(line) {
+ val rarity = group("gemrarity")
+ val stored = group("stored")
+ gem.internalName = gemstoneMap[name.removeColor()] ?: NEUInternalName.NONE
+ if (gemstoneMap.containsKey(name.removeColor())) {
+ val internalName = "${rarity.uppercase()}_${
+ name.uppercase().split(" ")[0].removeColor()
+ }_GEM".asInternalName()
+
+ when (rarity) {
+ "Rough" -> {
+ gem.rough = stored
+ gem.roughPrice = internalName.sackPrice(stored)
+ if (savingSacks) setSackItem(internalName, stored.formatNumber().toInt())
+ }
+
+ "Flawed" -> {
+ gem.flawed = stored
+ gem.flawedPrice = internalName.sackPrice(stored)
+ if (savingSacks) setSackItem(internalName, stored.formatNumber().toInt())
+ }
+
+ "Fine" -> {
+ gem.fine = stored
+ gem.finePrice = internalName.sackPrice(stored)
+ if (savingSacks) setSackItem(internalName, stored.formatNumber().toInt())
+ }
+
+ "Flawless" -> {
+ gem.flawless = stored
+ gem.flawlessPrice = internalName.sackPrice(stored)
+ if (savingSacks) setSackItem(internalName, stored.formatNumber().toInt())
+ }
+ }
+ gemstoneItem[name] = gem
+ }
+ }
+ } else {
+ numPattern.matchMatcher(line) {
+ val stored = group("stored")
+ val internalName = stack.getInternalName()
+ item.internalName = internalName
+ item.colorCode = group("color")
+ item.stored = stored
+ item.total = group("total")
+ if (savingSacks) setSackItem(item.internalName, item.stored.formatNumber().toInt())
+ item.price = if (isTrophySack) {
+ val trophyName =
+ internalName.asString().lowercase().substringBeforeLast("_").replace("_", "")
+ val filletValue =
+ TrophyFishManager.getInfoByName(trophyName)?.getFilletValue(sackRarity!!) ?: 0
+ val storedNumber = stored.formatNumber().toInt()
+ "MAGMA_FISH".asInternalName().sackPrice((filletValue * storedNumber).toString())
+ } else internalName.sackPrice(stored).coerceAtLeast(0)
+
+ if (isRuneSack) {
+ val level = group("level")
+ rune.stack = stack
+ if (level == "I") {
+ rune.lvl1 = stored
+ continue@loop
+ }
+ if (level == "II") {
+ rune.lvl2 = stored
+ continue@loop
+ }
+ if (level == "III") {
+ rune.lvl3 = stored
+ }
+ runeItem.put(name, rune)
+ } else {
+ sackItem.put(name, item)
+ }
+ }
+ }
+ }
+ }
+ if (savingSacks) saveSackData()
+ }
+
+ private var sackData = mapOf<NEUInternalName, SackItem>()
+
+ data class SackChange(val delta: Int, val internalName: NEUInternalName, val sacks: List<String>)
+
+ private val sackChangeRegex = Regex("""([+-][\d,]+) (.+) \((.+)\)""")
+
+ @SubscribeEvent
+ fun onChat(event: LorenzChatEvent) {
+ if (!event.message.removeColor().startsWith("[Sacks]")) return
+
+ val sackAddText = event.chatComponent.siblings.firstNotNullOfOrNull { sibling ->
+ sibling.chatStyle?.chatHoverEvent?.value?.formattedText?.removeColor()?.takeIf {
+ it.startsWith("Added")
+ }
+ } ?: ""
+ val sackRemoveText = event.chatComponent.siblings.firstNotNullOfOrNull { sibling ->
+ sibling.chatStyle?.chatHoverEvent?.value?.formattedText?.removeColor()?.takeIf {
+ it.startsWith("Removed")
+ }
+ } ?: ""
+
+ val sackChangeText = sackAddText + sackRemoveText
+ if (sackChangeText.isEmpty()) return
+
+ val otherItemsAdded = sackAddText.contains("other items")
+ val otherItemsRemoved = sackRemoveText.contains("other items")
+
+ val sackChanges = ArrayList<SackChange>()
+ for (match in sackChangeRegex.findAll(sackChangeText)) {
+ val delta = match.groups[1]!!.value.replace(",", "").toInt()
+ val item = match.groups[2]!!.value
+ val sacks = match.groups[3]!!.value.split(", ")
+
+ val internalName = NEUInternalName.fromItemName(item)
+ sackChanges.add(SackChange(delta, internalName, sacks))
+ }
+ SackChangeEvent(sackChanges, otherItemsAdded, otherItemsRemoved).postAndCatch()
+ }
+
+ @SubscribeEvent
+ fun sackChange(event: SackChangeEvent) {
+ sackData = ProfileStorageData.sackProfiles?.sackContents ?: return
+
+ // if it gets added and subtracted but only 1 shows it will be outdated
+ val justChanged = mutableMapOf<NEUInternalName, Int>()
+
+ for (change in event.sackChanges) {
+ if (change.internalName in justChanged) {
+ justChanged[change.internalName] = (justChanged[change.internalName] ?: 0) + change.delta
+ } else {
+ justChanged[change.internalName] = change.delta
+ }
+ }
+
+ for (item in justChanged) {
+ if (sackData.containsKey(item.key)) {
+ val oldData = sackData[item.key]
+ var newAmount = oldData!!.amount + item.value
+ var changed = newAmount - oldData.amount
+ if (newAmount < 0) {
+ newAmount = 0
+ changed = 0
+ }
+ sackData = sackData.editCopy { this[item.key] = SackItem(newAmount, changed, oldData.outdatedStatus) }
+ } else {
+ val newAmount = if (item.value > 0) item.value else 0
+ sackData = sackData.editCopy { this[item.key] = SackItem(newAmount, newAmount, 2) }
+ }
+ }
+
+ if (event.otherItemsAdded || event.otherItemsRemoved) {
+ for (item in sackData) {
+ if (item.key in justChanged) continue
+ val oldData = sackData[item.key]
+ sackData = sackData.editCopy { this[item.key] = SackItem(oldData!!.amount, 0, 1) }
+ }
+ }
+ saveSackData()
+ }
+
+ private fun setSackItem(item: NEUInternalName, amount: Int) {
+ sackData = sackData.editCopy { this[item] = SackItem(amount, 0, 0) }
+ }
+
+ fun fetchSackItem(item: NEUInternalName): SackItem {
+ sackData = ProfileStorageData.sackProfiles?.sackContents ?: return SackItem(0, 0, -1)
+
+ if (sackData.containsKey(item)) {
+ return sackData[item] ?: return SackItem(0, 0, -1)
+ }
+
+ sackData = sackData.editCopy { this[item] = SackItem(0, 0, 2) }
+ return sackData[item] ?: return SackItem(0, 0, -1)
+ }
+
+ private fun saveSackData() {
+ ProfileStorageData.sackProfiles?.sackContents = sackData
+ SkyHanniMod.configManager.saveSackData("saving-data")
+ }
+
+ data class SackGemstone(
+ var internalName: NEUInternalName = NEUInternalName.NONE,
+ var rough: String = "0",
+ var flawed: String = "0",
+ var fine: String = "0",
+ var flawless: String = "0",
+ var roughPrice: Int = 0,
+ var flawedPrice: Int = 0,
+ var finePrice: Int = 0,
+ var flawlessPrice: Int = 0,
+ )
+
+ data class SackRune(
+ var stack: ItemStack? = null,
+ var lvl1: String = "0",
+ var lvl2: String = "0",
+ var lvl3: String = "0",
+ )
+
+ data class SackOtherItem(
+ var internalName: NEUInternalName = NEUInternalName.NONE,
+ var colorCode: String = "",
+ var stored: String = "0",
+ var total: String = "0",
+ var price: Int = 0,
+ )
+}
+
+// status -1 = fetching data failed, 0 = < 1% of being wrong, 1 = 10% of being wrong, 2 = is 100% wrong
+// lastChange is set to 0 when value is refreshed in the sacks gui and when being set initially
+// if it didn't change in an update the lastChange value will stay the same and not be set to 0
+data class SackItem(
+ @Expose val amount: Int,
+ @Expose val lastChange: Int,
+ @Expose val outdatedStatus: Int
+)
+
+private val gemstoneMap = mapOf(
+ "Jade Gemstones" to "ROUGH_JADE_GEM".asInternalName(),
+ "Amber Gemstones" to "ROUGH_AMBER_GEM".asInternalName(),
+ "Topaz Gemstones" to "ROUGH_TOPAZ_GEM".asInternalName(),
+ "Sapphire Gemstones" to "ROUGH_SAPPHIRE_GEM".asInternalName(),
+ "Amethyst Gemstones" to "ROUGH_AMETHYST_GEM".asInternalName(),
+ "Jasper Gemstones" to "ROUGH_JASPER_GEM".asInternalName(),
+ "Ruby Gemstones" to "ROUGH_RUBY_GEM".asInternalName(),
+ "Opal Gemstones" to "ROUGH_OPAL_GEM".asInternalName(),
+)
diff --git a/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt
index 3a3bd8b33..2675c27c3 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt
@@ -121,7 +121,11 @@ object SlayerAPI {
}
if (event.isMod(5)) {
- isInSlayerArea = SlayerType.getByArea(LorenzUtils.skyBlockArea) != null
+ isInSlayerArea = if (LorenzUtils.isStrandedProfile) {
+ true
+ } else {
+ SlayerType.getByArea(LorenzUtils.skyBlockArea) != null
+ }
}
}
} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/data/TitleUtils.kt b/src/main/java/at/hannibal2/skyhanni/data/TitleUtils.kt
index d66a321b2..2004a1ed1 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/TitleUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/TitleUtils.kt
@@ -2,34 +2,36 @@ package at.hannibal2.skyhanni.data
import at.hannibal2.skyhanni.events.GuiRenderEvent
import at.hannibal2.skyhanni.events.PreProfileSwitchEvent
+import at.hannibal2.skyhanni.utils.SimpleTimeMark
import io.github.moulberry.moulconfig.internal.TextRenderUtils
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.ScaledResolution
import net.minecraft.client.renderer.GlStateManager
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.time.Duration
class TitleUtils {
companion object {
private var display = ""
- private var endTime = 0L
+ private var endTime = SimpleTimeMark.farPast()
private var heightModifier = 1.8
- fun sendTitle(text: String, duration: Int, height: Double = 1.8) {
+ fun sendTitle(text: String, duration: Duration, height: Double = 1.8) {
display = "§f$text"
- endTime = System.currentTimeMillis() + duration
+ endTime = SimpleTimeMark.now() + duration
heightModifier = height
}
}
@SubscribeEvent
fun onPreProfileSwitch(event: PreProfileSwitchEvent) {
- sendTitle("", 1)
+ endTime = SimpleTimeMark.farPast()
}
@SubscribeEvent
fun onRenderOverlay(event: GuiRenderEvent.GameOverlayRenderEvent) {
- if (System.currentTimeMillis() > endTime) return
+ if (endTime.isInPast()) return
val scaledResolution = ScaledResolution(Minecraft.getMinecraft())
val width = scaledResolution.scaledWidth