Skip to content

Commit

Permalink
Feature: SkyblockXP Bar (#2886)
Browse files Browse the repository at this point in the history
Co-authored-by: CalMWolfs <[email protected]>
Co-authored-by: Cal <[email protected]>
Co-authored-by: hannibal2 <[email protected]>
  • Loading branch information
4 people authored Jan 18, 2025
1 parent 94f5809 commit b8d4c50
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 8 deletions.
91 changes: 91 additions & 0 deletions src/main/java/at/hannibal2/skyhanni/api/SkyBlockXPAPI.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package at.hannibal2.skyhanni.api

import at.hannibal2.skyhanni.api.event.HandleEvent
import at.hannibal2.skyhanni.data.ProfileStorageData
import at.hannibal2.skyhanni.data.model.TabWidget
import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent
import at.hannibal2.skyhanni.events.WidgetUpdateEvent
import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
import at.hannibal2.skyhanni.utils.ItemUtils.getLore
import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher
import at.hannibal2.skyhanni.utils.RegexUtils.matches
import at.hannibal2.skyhanni.utils.UtilsPatterns
import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern

@SkyHanniModule
object SkyBlockXPAPI {

private val group = RepoPattern.group("skyblockxpapi.inventory")

private val itemNamePattern by group.pattern("itemname", "§aSkyBlock Leveling")

/**
* REGEX-TEST: §7Your SkyBlock Level: §8[§9287§8]
*/
private val levelPattern by group.pattern("level", "§7Your SkyBlock Level: §8\\[§.(?<level>\\d+)§8\\]")

/**
* REGEX-TEST: §3§l§m §f§l§m §r §b24§3/§b100 §bXP
*/
private val xpPattern by group.pattern("xp", "\\w\\s]+§b(?<xp>\\d+)§3\\/§b100 §bXP")

val levelXpPair get() = storage?.toLevelXpPair()

// Stored as 12345, 123 is the level, 45 is the xp
private var storage
get() = ProfileStorageData.profileSpecific?.totalSkyBlockXP
set(value) {
ProfileStorageData.profileSpecific?.totalSkyBlockXP = value
}

private fun Int.toLevelXpPair() = this / 100 to this % 100

@HandleEvent
fun onWidgetUpdate(event: WidgetUpdateEvent) {
if (!event.isWidget(TabWidget.SB_LEVEL)) return

TabWidget.SB_LEVEL.matchMatcherFirstLine {
val level = group("level")?.toIntOrNull()
val xp = group("xp")?.toIntOrNull()

updateStorage(level, xp)
}
}

@HandleEvent
fun onInventoryFullyOpened(event: InventoryFullyOpenedEvent) {
if (!UtilsPatterns.skyblockMenuGuiPattern.matches(event.inventoryName)) return

val stack = event.inventoryItems.values.find { itemNamePattern.matches(it.displayName) } ?: return

var level: Int? = null
var xp: Int? = null

loop@ for (line in stack.getLore()) {
if (level != null && xp != null) break@loop

if (level == null) {
levelPattern.matchMatcher(line) {
level = group("level")?.toIntOrNull()
continue@loop
}
}

if (xp == null) {
xpPattern.matchMatcher(line) {
xp = group("xp")?.toIntOrNull()
continue@loop
}
}
}

updateStorage(level, xp)
}

private fun updateStorage(level: Int?, xp: Int?) {
storage = calculateTotalXp(level ?: return, xp ?: return)
}

fun calculateTotalXp(level: Int, xp: Int): Int = level * 100 + xp

}
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,7 @@ public String toString() {
@Expose
@ConfigOption(name = "Quick Craft Confirmation",
desc = "Require Ctrl+Click to craft items that aren't often quick crafted " +
"(e.g. armor, weapons, accessories). " +
"Sack items can be crafted normally."
"(e.g. armor, weapons, accessories). Sack items can be crafted normally."
)
@ConfigEditorBoolean
@FeatureToggle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,13 @@ public class MiscConfig {
@ConfigEditorBoolean
public boolean crashOnDeath = false;

@Expose
@ConfigOption(name = "SkyBlock XP Bar", desc = "Replaces the vanilla XP bar with a SkyBlock XP bar.")
@SearchTag("skyblockxp")
@ConfigEditorBoolean
@FeatureToggle
public boolean skyblockXpBar = false;

// TODO move into scoreboard accordion
@Expose
@ConfigOption(name = "Red Scoreboard Numbers", desc = "Hide the red scoreboard numbers on the right side of the screen.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,9 @@ class ProfileSpecificStorage {
var currentSlot: Int? = null
}

@Expose
var totalSkyBlockXP: Int? = null

@Expose
var draconicSacrificeTracker: DraconicSacrificeTracker.Data = DraconicSacrificeTracker.Data()

Expand Down
8 changes: 2 additions & 6 deletions src/main/java/at/hannibal2/skyhanni/data/BitsAPI.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import at.hannibal2.skyhanni.utils.SimpleTimeMark
import at.hannibal2.skyhanni.utils.StringUtils.removeResets
import at.hannibal2.skyhanni.utils.StringUtils.trimWhiteSpace
import at.hannibal2.skyhanni.utils.TimeUtils
import at.hannibal2.skyhanni.utils.UtilsPatterns
import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import kotlin.time.Duration.Companion.days
Expand Down Expand Up @@ -155,11 +156,6 @@ object BitsAPI {
"§7Fame Rank: §e(?<rank>.*)",
)

private val bitsGuiNamePattern by bitsGuiGroup.pattern(
"mainmenuname",
"^SkyBlock Menu$",
)

private val cookieGuiStackPattern by bitsGuiGroup.pattern(
"mainmenustack",
"^§6Booster Cookie$",
Expand Down Expand Up @@ -258,7 +254,7 @@ object BitsAPI {

val stacks = event.inventoryItems

if (bitsGuiNamePattern.matches(event.inventoryName)) {
if (UtilsPatterns.skyblockMenuGuiPattern.matches(event.inventoryName)) {
val cookieStack = stacks.values.lastOrNull { cookieGuiStackPattern.matches(it.displayName) }

// If the cookie stack is null, then the player should not have any bits to claim
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package at.hannibal2.skyhanni.features.inventory

import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.api.SkyBlockXPAPI
import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
import at.hannibal2.skyhanni.utils.LorenzUtils
import net.minecraft.client.Minecraft
import net.minecraftforge.client.event.RenderGameOverlayEvent
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent

@SkyHanniModule
object SkyBlockXPBar {
private val config get() = SkyHanniMod.feature.misc

@SubscribeEvent
fun onRenderScoreboard(event: RenderGameOverlayEvent.Pre) {
if (!isEnabled()) return
if (event.type != RenderGameOverlayEvent.ElementType.EXPERIENCE) return
val (level, xp) = SkyBlockXPAPI.levelXpPair ?: return
Minecraft.getMinecraft().thePlayer.setXPStats(xp / 100f, 100, level)
}

private fun isEnabled() = LorenzUtils.inSkyBlock && config.skyblockXpBar
}
5 changes: 5 additions & 0 deletions src/main/java/at/hannibal2/skyhanni/utils/UtilsPatterns.kt
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,9 @@ object UtilsPatterns {
"inventory.shopoptions",
"Shop Trading Options",
)

val skyblockMenuGuiPattern by patternGroup.pattern(
"inventory.skyblockmenu",
"SkyBlock Menu",
)
}

0 comments on commit b8d4c50

Please sign in to comment.