From 9484d930bd52ead1af076fc251aed691226ceee5 Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Date: Thu, 2 Feb 2023 20:43:28 +0100 Subject: Prepare for bingo stuff. --- .../java/at/hannibal2/skyhanni/SkyHanniMod.java | 1 + .../java/at/hannibal2/skyhanni/data/IslandType.kt | 10 +- .../at/hannibal2/skyhanni/data/SkillExperience.kt | 210 +++++++++++++++++++++ .../features/inventory/HideNotClickableItems.kt | 22 +-- .../skyhanni/features/misc/CollectionCounter.kt | 23 +-- .../dailyquest/DailyQuestHelper.kt | 26 +-- .../at/hannibal2/skyhanni/utils/InventoryUtils.kt | 6 + 7 files changed, 245 insertions(+), 53 deletions(-) create mode 100644 src/main/java/at/hannibal2/skyhanni/data/SkillExperience.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 685dc6c9e..f623b22a4 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java @@ -98,6 +98,7 @@ public class SkyHanniMod { loadModule(new SendTitleHelper()); loadModule(new ItemTipHelper()); loadModule(new RenderLivingEntityHelper()); + loadModule(new SkillExperience()); //features loadModule(new BazaarOrderHelper()); diff --git a/src/main/java/at/hannibal2/skyhanni/data/IslandType.kt b/src/main/java/at/hannibal2/skyhanni/data/IslandType.kt index e2e99970c..362060918 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/IslandType.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/IslandType.kt @@ -1,16 +1,20 @@ package at.hannibal2.skyhanni.data -enum class IslandType(val displayName: String) { +enum class IslandType(val displayName: String, val apiName: String = "null") { PRIVATE_ISLAND("Private Island"), PRIVATE_ISLAND_GUEST("Private Island Guest"), THE_END("The End"), KUUDRA_ARENA("Instanced"), CRIMSON_ISLE("Crimson Isle"), DWARVEN_MINES("Dwarven Mines"), - DUNGEON_HUB("Dungeon Hub"), + DUNGEON_HUB("Dungeon Hub", "dungeon_hub"), - HUB("Hub"), + HUB("Hub", "village"), THE_FARMING_ISLANDS("The Farming Islands"), + CRYSTAL_HOLLOWS("Crystal Hollows"), + THE_PARK("The Park", "floating_islands_1"), + DEEP_CAVERNS("Deep Caverns", "deep_caverns"), + GOLD_MINES("Gold Mine", "gold_mine"),//TODO confirm NONE(""), UNKNOWN("???"), diff --git a/src/main/java/at/hannibal2/skyhanni/data/SkillExperience.kt b/src/main/java/at/hannibal2/skyhanni/data/SkillExperience.kt new file mode 100644 index 000000000..7b5df45df --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/SkillExperience.kt @@ -0,0 +1,210 @@ +package at.hannibal2.skyhanni.data + +import at.hannibal2.skyhanni.events.LorenzActionBarEvent +import at.hannibal2.skyhanni.events.ProfileApiDataLoadedEvent +import at.hannibal2.skyhanni.utils.InventoryUtils +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.NumberUtil.romanToDecimal +import at.hannibal2.skyhanni.utils.StringUtils.removeColor +import net.minecraftforge.event.world.WorldEvent +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import net.minecraftforge.fml.common.gameevent.TickEvent +import java.util.regex.Pattern + +class SkillExperience { + + private val actionBarPattern = Pattern.compile("(?:.*)§3\\+(?:.*) (.*) \\((.*)\\/(.*)\\)(?:.*)") + + @SubscribeEvent + fun onProfileDataLoad(event: ProfileApiDataLoadedEvent) { + val profileData = event.profileData + for ((key, value) in profileData.entrySet()) { + if (key.startsWith("experience_skill_")) { + val label = key.substring(17) + val exp = value.asLong + skillExp[label] = exp + } + } + } + + @SubscribeEvent + fun onActionBar(event: LorenzActionBarEvent) { + if (!LorenzUtils.inSkyBlock) return + + val matcher = actionBarPattern.matcher(event.message) + if (!matcher.matches()) return + + val skill = matcher.group(1).lowercase() + val overflow = matcher.group(2).formatNumber() + val neededForNextLevel = matcher.group(3).formatNumber() + val nextLevel = getLevelForExp(neededForNextLevel) + val baseExp = getExpForLevel(nextLevel - 1) + skillExp[skill] = baseExp + overflow + } + + private var tick = 0 + private var dirty = true + + @SubscribeEvent + fun onTick(event: TickEvent.ClientTickEvent) { + if (event.phase != TickEvent.Phase.START) return + + tick++ + if (tick % 20 != 0) return + if (InventoryUtils.openInventoryName() != "Your Skills") return + + if (!dirty) return + dirty = false + + for (slot in InventoryUtils.getItemsInOpenChest()) { + val stack = slot.stack + val name = stack.name?.removeColor() ?: continue + + val lore = stack.getLore() + + var next = false + for (line in lore) { + if (line.contains("Progress to Level")) { + next = true + continue + } + if (next) { + if (!name.contains(" ")) continue + val split = name.split(" ") + val skillName = split[0].lowercase() + val level = split[1].romanToDecimal() + val baseExp = getExpForLevel(level) + val pattern = Pattern.compile("(?:.*) §e(.*)§6\\/(?:.*)") + val matcher = pattern.matcher(line) + if (matcher.matches()) { + val rawNumber = matcher.group(1) + val overflow = rawNumber.formatNumber() + val experience = baseExp + overflow + skillExp[skillName] = experience + } + next = false + } + } + + } + if (skillExp.isNotEmpty()) return + } + + @SubscribeEvent + fun onWorldChange(event: WorldEvent.Load) { + dirty = true + } + + companion object { + private val skillExp = mutableMapOf() + + private fun getLevelForExp(experience: Long): Int { + var level = 1 + for (levelXp in levelingExp) { + if (levelXp.toLong() == experience) { + return level + } + level++ + } + + return 0 + } + + fun getExpForLevel(requestedLevel: Int): Long { + var total = 0L + var level = 0 + for (levelXp in levelingExp) { + total += levelXp + level++ + if (level == requestedLevel) { + return total + } + } + + return 0 + } + + //TODO create additional event + fun getExpForSkill(skillName: String) = skillExp[skillName.lowercase()] ?: 0 + + private val levelingExp = listOf( + 50, + 125, + 200, + 300, + 500, + 750, + 1000, + 1500, + 2000, + 3500, + 5000, + 7500, + 10000, + 15000, + 20000, + 30000, + 50000, + 75000, + 100000, + 200000, + 300000, + 400000, + 500000, + 600000, + 700000, + 800000, + 900000, + 1000000, + 1100000, + 1200000, + 1300000, + 1400000, + 1500000, + 1600000, + 1700000, + 1800000, + 1900000, + 2000000, + 2100000, + 2200000, + 2300000, + 2400000, + 2500000, + 2600000, + 2750000, + 2900000, + 3100000, + 3400000, + 3700000, + 4000000, + 4300000, + 4600000, + 4900000, + 5200000, + 5500000, + 5800000, + 6100000, + 6400000, + 6700000, + 7000000 + ) + } +} + +private fun String.formatNumber(): Long { + var text = replace(",", "") + val multiplier = if (text.endsWith("k")) { + text = text.substring(0, text.length - 1) + 1_000 + } else if (text.endsWith("m")) { + text = text.substring(0, text.length - 1) + 1_000_000 + } else { + 1 + } + val d = text.toDouble() + return (d * multiplier).toLong() +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/HideNotClickableItems.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/HideNotClickableItems.kt index 11994a0c8..7afe83e2b 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/HideNotClickableItems.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/HideNotClickableItems.kt @@ -193,7 +193,7 @@ class HideNotClickableItems { } } - if (isSkyBlockMenuItem(stack)) { + if (ItemUtils.isSkyBlockMenuItem(stack)) { hideReason = "The SkyBlock Menu cannot be put into the potion bag!" return true } @@ -227,7 +227,7 @@ class HideNotClickableItems { private fun hidePotionBag(chestName: String, stack: ItemStack): Boolean { if (!chestName.startsWith("Potion Bag")) return false - if (isSkyBlockMenuItem(stack)) { + if (ItemUtils.isSkyBlockMenuItem(stack)) { hideReason = "The SkyBlock Menu cannot be put into the potion bag!" return true } @@ -242,7 +242,7 @@ class HideNotClickableItems { private fun hideFishingBag(chestName: String, stack: ItemStack): Boolean { if (!chestName.startsWith("Fishing Bag")) return false - if (isSkyBlockMenuItem(stack)) { + if (ItemUtils.isSkyBlockMenuItem(stack)) { hideReason = "The SkyBlock Menu cannot be put into the fishing bag!" return true } @@ -257,7 +257,7 @@ class HideNotClickableItems { private fun hideSackOfSacks(chestName: String, stack: ItemStack): Boolean { if (!chestName.startsWith("Sack of Sacks")) return false - if (isSkyBlockMenuItem(stack)) return false + if (ItemUtils.isSkyBlockMenuItem(stack)) return false val name = stack.cleanName() reverseColor = true @@ -270,7 +270,7 @@ class HideNotClickableItems { private fun hideAccessoryBag(chestName: String, stack: ItemStack): Boolean { if (!chestName.startsWith("Accessory Bag") && !chestName.startsWith("Accessory Bag (")) return false - if (isSkyBlockMenuItem(stack)) return false + if (ItemUtils.isSkyBlockMenuItem(stack)) return false reverseColor = true if (stack.getLore().any { it.contains("ACCESSORY") }) return false @@ -287,7 +287,7 @@ class HideNotClickableItems { return true } - if (isSkyBlockMenuItem(stack)) { + if (ItemUtils.isSkyBlockMenuItem(stack)) { hideReason = "The SkyBlock Menu cannot be traded!" return true } @@ -316,7 +316,7 @@ class HideNotClickableItems { name = name.substring(0, name.length - amountText.length) } - if (isSkyBlockMenuItem(stack)) { + if (ItemUtils.isSkyBlockMenuItem(stack)) { hideReason = "The SkyBlock Menu cannot be sold at the NPC!" return true } @@ -343,7 +343,7 @@ class HideNotClickableItems { private fun hideInStorage(chestName: String, stack: ItemStack): Boolean { if (!chestName.contains("Ender Chest") && !chestName.contains("Backpack") && chestName != "Storage") return false - if (isSkyBlockMenuItem(stack)) { + if (ItemUtils.isSkyBlockMenuItem(stack)) { hideReason = "The SkyBlock Menu cannot be put into the storage!" return true } @@ -376,7 +376,7 @@ class HideNotClickableItems { } } - if (isSkyBlockMenuItem(stack)) { + if (ItemUtils.isSkyBlockMenuItem(stack)) { hideReason = "The SkyBlock Menu cannot be salvaged!" return true } @@ -400,7 +400,7 @@ class HideNotClickableItems { if (!bazaarInventory && !auctionHouseInventory) return false reverseColor = true - if (isSkyBlockMenuItem(stack)) { + if (ItemUtils.isSkyBlockMenuItem(stack)) { if (bazaarInventory) hideReason = "The SkyBlock Menu is not a Bazaar Product!" if (auctionHouseInventory) hideReason = "The SkyBlock Menu cannot be auctioned!" return true @@ -435,6 +435,4 @@ class HideNotClickableItems { if (result) hideReason = "This item cannot be auctioned!" return result } - - private fun isSkyBlockMenuItem(stack: ItemStack): Boolean = stack.getInternalName() == "SKYBLOCK_MENU" } diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/CollectionCounter.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/CollectionCounter.kt index f2b188787..088836401 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/CollectionCounter.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/CollectionCounter.kt @@ -4,6 +4,7 @@ import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.events.ProfileApiDataLoadedEvent import at.hannibal2.skyhanni.features.bazaar.BazaarApi import at.hannibal2.skyhanni.features.bazaar.BazaarData +import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.RenderUtils.renderString @@ -62,9 +63,9 @@ class CollectionCounter { val apiName = data.apiName if (!apiCollectionData.contains(apiName)) { if (apiCollectionData.isEmpty()) { - LorenzUtils.chat("§c[SkyHanni] Collection data not loaded! (API down?)") + LorenzUtils.chat("§c[SkyHanni] No Collection Data! API down?") } else { - LorenzUtils.chat("§c[SkyHanni] Item $name is not in collection data!") + LorenzUtils.chat("§c[SkyHanni] Item $name is not in the collection data!") } return } @@ -104,18 +105,8 @@ class CollectionCounter { display = "$itemName collection: §e$format $gainText" } - private fun countCurrentlyInInventory(): Int { - var currentlyInInventory = 0 - val player = Minecraft.getMinecraft().thePlayer - for (stack in player.inventory.mainInventory) { - if (stack == null) continue - val internalName = stack.getInternalName() - if (internalName == itemApiName) { - currentlyInInventory += stack.stackSize - } - } - return currentlyInInventory - } + private fun countCurrentlyInInventory() = + InventoryUtils.countItemsInLowerInventory { it.getInternalName() == itemApiName } } @SubscribeEvent @@ -168,7 +159,9 @@ class CollectionCounter { @SubscribeEvent fun onProfileDataLoad(event: ProfileApiDataLoadedEvent) { val profileData = event.profileData - val collection = profileData["collection"].asJsonObject + + //new profiles don't have any collections + val collection = profileData["collection"]?.asJsonObject ?: return apiCollectionData.clear() for (entry in collection.entrySet()) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailyquest/DailyQuestHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailyquest/DailyQuestHelper.kt index 5d051b5d2..e8e2acce7 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailyquest/DailyQuestHelper.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailyquest/DailyQuestHelper.kt @@ -12,16 +12,12 @@ import at.hannibal2.skyhanni.features.nether.reputationhelper.dailykuudra.Kuudra import at.hannibal2.skyhanni.features.nether.reputationhelper.dailyquest.quest.* import at.hannibal2.skyhanni.features.nether.reputationhelper.miniboss.CrimsonMiniBoss import at.hannibal2.skyhanni.test.GriffinUtils.drawWaypointFilled +import at.hannibal2.skyhanni.utils.* import at.hannibal2.skyhanni.utils.InventoryUtils.getInventoryName import at.hannibal2.skyhanni.utils.ItemUtils.getLore import at.hannibal2.skyhanni.utils.ItemUtils.name -import at.hannibal2.skyhanni.utils.LorenzColor -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.LorenzVec -import at.hannibal2.skyhanni.utils.NEUItems import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText import at.hannibal2.skyhanni.utils.RenderUtils.highlight -import net.minecraft.client.Minecraft import net.minecraft.client.gui.inventory.GuiChest import net.minecraft.inventory.ContainerChest import net.minecraftforge.client.event.RenderWorldLastEvent @@ -66,15 +62,7 @@ class DailyQuestHelper(val reputationHelper: CrimsonIsleReputationHelper) { if (fishQuest.state != QuestState.ACCEPTED && fishQuest.state != QuestState.READY_TO_COLLECT) return val fishName = fishQuest.fishName - var currentlyInInventory = 0 - val player = Minecraft.getMinecraft().thePlayer - for (stack in player.inventory.mainInventory) { - if (stack == null) continue - val name = stack.name ?: continue - if (name.contains(fishName)) { - currentlyInInventory += stack.stackSize - } - } + val currentlyInInventory = InventoryUtils.countItemsInLowerInventory { it.name?.contains(fishName) ?: false } val diff = currentlyInInventory - latestTrophyFishInInventory if (diff < 1) return latestTrophyFishInInventory = currentlyInInventory @@ -170,15 +158,7 @@ class DailyQuestHelper(val reputationHelper: CrimsonIsleReputationHelper) { val itemName = fetchQuest.itemName - val player = Minecraft.getMinecraft().thePlayer - var count = 0 - for (stack in player.inventory.mainInventory) { - if (stack == null) continue - val name = stack.name ?: continue - if (name.contains(itemName)) { - count += stack.stackSize - } - } + val count = InventoryUtils.countItemsInLowerInventory { it.name?.contains(itemName) ?: false } updateProcessQuest(fetchQuest, count) } diff --git a/src/main/java/at/hannibal2/skyhanni/utils/InventoryUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/InventoryUtils.kt index feaaaa481..da152a2c3 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/InventoryUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/InventoryUtils.kt @@ -4,6 +4,7 @@ import net.minecraft.client.Minecraft import net.minecraft.client.gui.inventory.GuiChest import net.minecraft.inventory.ContainerChest import net.minecraft.inventory.Slot +import net.minecraft.item.ItemStack object InventoryUtils { @@ -48,4 +49,9 @@ object InventoryUtils { fun ContainerChest.getInventoryName(): String { return this.lowerChestInventory.displayName.unformattedText.trim() } + + fun countItemsInLowerInventory(predicate: (ItemStack) -> Boolean) = + Minecraft.getMinecraft().thePlayer.inventory.mainInventory + .filter { it != null && predicate(it) } + .sumOf { it.stackSize } } \ No newline at end of file -- cgit