diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index ed146902cafa..e87d8c048b4b 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -37,6 +37,7 @@ import at.hannibal2.skyhanni.data.LocationFixData import at.hannibal2.skyhanni.data.MaxwellAPI import at.hannibal2.skyhanni.data.MayorAPI import at.hannibal2.skyhanni.data.MinecraftData +import at.hannibal2.skyhanni.data.MiningAPI import at.hannibal2.skyhanni.data.OtherInventoryData import at.hannibal2.skyhanni.data.OwnInventoryData import at.hannibal2.skyhanni.data.PartyAPI @@ -264,6 +265,7 @@ import at.hannibal2.skyhanni.features.inventory.tiarelay.TiaRelayWaypoints import at.hannibal2.skyhanni.features.itemabilities.ChickenHeadTimer import at.hannibal2.skyhanni.features.itemabilities.FireVeilWandParticles import at.hannibal2.skyhanni.features.itemabilities.abilitycooldown.ItemAbilityCooldown +import at.hannibal2.skyhanni.features.mining.ColdOverlay import at.hannibal2.skyhanni.features.mining.DeepCavernsGuide import at.hannibal2.skyhanni.features.mining.GoldenGoblinHighlight import at.hannibal2.skyhanni.features.mining.HighlightMiningCommissionMobs @@ -546,6 +548,7 @@ class SkyHanniMod { loadModule(LorenzUtils) loadModule(NEUItems) loadModule(PestAPI) + loadModule(MiningAPI) loadModule(FossilExcavatorAPI) // features @@ -851,6 +854,7 @@ class SkyHanniMod { loadModule(DungeonShadowAssassinNotification()) loadModule(PestProfitTracker) loadModule(NoBitsWarning()) + loadModule(ColdOverlay()) loadModule(QuiverDisplay()) loadModule(QuiverWarning()) diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/mining/ColdOverlayConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/mining/ColdOverlayConfig.java new file mode 100644 index 000000000000..11ac9bba0fc7 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/mining/ColdOverlayConfig.java @@ -0,0 +1,43 @@ +package at.hannibal2.skyhanni.config.features.mining; + +import at.hannibal2.skyhanni.config.FeatureToggle; +import com.google.gson.annotations.Expose; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorSlider; +import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; + +public class ColdOverlayConfig { + + @Expose + @ConfigOption( + name = "Enabled", + desc = "Show the cold overlay in Glacite Tunnels." + ) + @ConfigEditorBoolean + @FeatureToggle + public boolean enabled = false; + + @Expose + @ConfigOption( + name = "Cold Threshold", + desc = "The threshold at which the cold overlay will be shown." + ) + @ConfigEditorSlider( + minValue = 0, + maxValue = 100, + minStep = 1 + ) + public int coldThreshold = 25; + + @Expose + @ConfigOption( + name = "Max Alpha", + desc = "The maximum alpha value the overlay will reach." + ) + @ConfigEditorSlider( + minValue = 0f, + maxValue = 100f, + minStep = 0.1f + ) + public float maxAlpha = 100f; +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningConfig.java index aebb842bc0bc..38f05a948f3f 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningConfig.java @@ -33,7 +33,11 @@ public class MiningConfig { @Accordion public AreaWallsConfig crystalHollowsAreaWalls = new AreaWallsConfig(); - // TODO rename to fossilExcavator + @Expose + @ConfigOption(name = "Cold Overlay", desc = "") + @Accordion + public ColdOverlayConfig coldOverlay = new ColdOverlayConfig(); + @Expose @Category(name = "Fossil Excavator", desc = "Settings for the Fossil Excavator Features") public FossilExcavatorConfig fossilExcavator = new FossilExcavatorConfig(); diff --git a/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt new file mode 100644 index 000000000000..89ebe71d6096 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt @@ -0,0 +1,70 @@ +package at.hannibal2.skyhanni.data + +import at.hannibal2.skyhanni.events.ColdUpdateEvent +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent +import at.hannibal2.skyhanni.events.ScoreboardChangeEvent +import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardPattern +import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.StringUtils.matchFirst +import at.hannibal2.skyhanni.utils.StringUtils.matches +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.math.absoluteValue +import kotlin.time.Duration.Companion.seconds + +object MiningAPI { + + private val group = RepoPattern.group("data.miningapi") + private val glaciteAreaPattern by group.pattern("area.glacite", "Glacite Tunnels") + val coldReset by group.pattern( + "cold.reset", + "§cThe warmth of the campfire reduced your §r§b❄ Cold §r§cto 0!|§c ☠ §r§7You froze to death§r§7." + ) + + private var cold = 0 + var lastColdUpdate = SimpleTimeMark.farPast() + var lastColdReset = SimpleTimeMark.farPast() + + fun inGlaciteArea() = glaciteAreaPattern.matches(HypixelData.skyBlockArea) || IslandType.MINESHAFT.isInIsland() + + fun inColdIsland() = IslandType.DWARVEN_MINES.isInIsland() || IslandType.MINESHAFT.isInIsland() + + fun getCold() = cold + + @SubscribeEvent + fun onScoreboardChange(event: ScoreboardChangeEvent) { + val newCold = event.newList.matchFirst(ScoreboardPattern.coldPattern) { + group("cold").toInt().absoluteValue + } ?: return + + if (newCold != cold) { + updateCold(newCold) + } + } + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + if (!inColdIsland()) return + if (coldReset.matches(event.message)) { + updateCold(0) + lastColdReset = SimpleTimeMark.now() + } + } + + @SubscribeEvent + fun onWorldChange(event: LorenzWorldChangeEvent) { + if (cold != 0) updateCold(0) + lastColdReset = SimpleTimeMark.now() + } + + private fun updateCold(newCold: Int) { + // Hypixel sends cold data once in scoreboard even after resetting it + if (cold == 0 && lastColdUpdate.passedSince() < 1.seconds) return + lastColdUpdate = SimpleTimeMark.now() + ColdUpdateEvent(newCold).postAndCatch() + cold = newCold + } + +} diff --git a/src/main/java/at/hannibal2/skyhanni/events/ColdUpdateEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/ColdUpdateEvent.kt new file mode 100644 index 000000000000..9894943b795d --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/events/ColdUpdateEvent.kt @@ -0,0 +1,3 @@ +package at.hannibal2.skyhanni.events + +class ColdUpdateEvent(val cold: Int) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/RenderBackground.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/RenderBackground.kt index 5cd86d99e2a2..50a51042bd14 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/RenderBackground.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/RenderBackground.kt @@ -56,7 +56,7 @@ class RenderBackground { GlStateManager.pushAttrib() GlStateManager.color(1f, 1f, 1f, 1f) - + GL11.glDepthMask(false) if (backgroundConfig.enabled) { if (backgroundConfig.useCustomBackgroundImage) { @@ -81,7 +81,7 @@ class RenderBackground { ) } } - + GL11.glDepthMask(true) GlStateManager.popMatrix() GlStateManager.popAttrib() } diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt index e9b4df0a9d09..b2187a4bd955 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt @@ -8,6 +8,7 @@ import at.hannibal2.skyhanni.data.HypixelData.Companion.getPlayersOnCurrentServe import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.data.MaxwellAPI import at.hannibal2.skyhanni.data.MayorAPI +import at.hannibal2.skyhanni.data.MiningAPI.getCold import at.hannibal2.skyhanni.data.PartyAPI import at.hannibal2.skyhanni.data.PurseAPI import at.hannibal2.skyhanni.data.QuiverAPI @@ -449,11 +450,11 @@ private fun getHeatShowWhen() = inAnyIsland(IslandType.CRYSTAL_HOLLOWS) && ScoreboardData.sidebarLinesFormatted.any { ScoreboardPattern.heatPattern.matches(it) } private fun getColdDisplayPair(): List { - val cold = getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.coldPattern, "cold") + val cold = -getCold() return listOf( when { - informationFilteringConfig.hideEmptyLines && cold == "0" -> "" + informationFilteringConfig.hideEmptyLines && cold == 0 -> "" displayConfig.displayNumbersFirst -> "§b$cold❄ Cold" else -> "Cold: §b$cold❄" } to HorizontalAlignment.LEFT diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/ColdOverlay.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/ColdOverlay.kt new file mode 100644 index 000000000000..196f2f6fbe66 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/ColdOverlay.kt @@ -0,0 +1,67 @@ +package at.hannibal2.skyhanni.features.mining + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.MiningAPI.inColdIsland +import at.hannibal2.skyhanni.events.ColdUpdateEvent +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.utils.DelayedRun +import at.hannibal2.skyhanni.utils.NumberUtil +import at.hannibal2.skyhanni.utils.RenderUtils +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import net.minecraft.client.Minecraft +import net.minecraft.client.renderer.GlStateManager +import net.minecraft.util.ResourceLocation +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import org.lwjgl.opengl.GL11 +import kotlin.time.Duration.Companion.seconds + +class ColdOverlay { + + private val config get() = SkyHanniMod.feature.mining.coldOverlay + + private var cold = 0 + private var lastCold = 0 + private var lastColdUpdate = SimpleTimeMark.farPast() + + private val textureLocation by lazy { ResourceLocation("skyhanni", "cold_overlay.png") } + + @SubscribeEvent + fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) { + if (!isEnabled()) return + val alpha = getColdAlpha() + if (alpha == 0f) return + + Minecraft.getMinecraft().textureManager.bindTexture(textureLocation) + + GlStateManager.pushMatrix() + GlStateManager.pushAttrib() + + GL11.glDepthMask(false) + GlStateManager.translate(0f, 0f, -500f) + GlStateManager.color(1f, 1f, 1f, alpha) + + RenderUtils.drawTexturedRect(0f, 0f) + GL11.glDepthMask(true) + + GlStateManager.popMatrix() + GlStateManager.popAttrib() + } + + private fun getColdAlpha(): Float { + val coldInterp = NumberUtil.interpolate(cold.toFloat(), lastCold.toFloat(), lastColdUpdate.toMillis()) + val coldPercentage = (coldInterp - config.coldThreshold) / (100 - config.coldThreshold) + return coldPercentage.coerceAtLeast(0f) * (config.maxAlpha / 100) + } + + @SubscribeEvent + fun onColdUpdate(event: ColdUpdateEvent) { + val duration = if (event.cold == 0) 1.seconds else 0.seconds + DelayedRun.runDelayed(duration) { + lastCold = cold + cold = event.cold + lastColdUpdate = SimpleTimeMark.now() + } + } + + private fun isEnabled() = inColdIsland() && config.enabled +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/MiningNotifications.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/MiningNotifications.kt index acaa23ff5002..d018deaa9e9f 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/MiningNotifications.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/MiningNotifications.kt @@ -1,21 +1,19 @@ package at.hannibal2.skyhanni.features.mining import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.data.IslandType +import at.hannibal2.skyhanni.data.MiningAPI.getCold +import at.hannibal2.skyhanni.data.MiningAPI.inColdIsland +import at.hannibal2.skyhanni.data.MiningAPI.lastColdReset +import at.hannibal2.skyhanni.events.ColdUpdateEvent import at.hannibal2.skyhanni.events.ConfigLoadEvent import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent -import at.hannibal2.skyhanni.events.ScoreboardChangeEvent -import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardPattern import at.hannibal2.skyhanni.utils.ConditionalUtils import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.SoundUtils -import at.hannibal2.skyhanni.utils.StringUtils.matchFirst import at.hannibal2.skyhanni.utils.StringUtils.matches import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -import kotlin.math.absoluteValue import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.seconds @@ -28,9 +26,7 @@ object MiningNotifications { DIAMOND_GOBLIN("§bDiamond Goblin", "§bDiamond Goblin"), COLD("§bCold", "§bCold"); - override fun toString(): String { - return str - } + override fun toString() = str } private val patternGroup = RepoPattern.group("mining.notifications") @@ -50,16 +46,10 @@ object MiningNotifications { "goblin.diamondspawn", "§6A §r§bDiamond Goblin §r§6has spawned!" ) - private val coldReset by patternGroup.pattern( - "cold.reset", - "§cThe warmth of the campfire reduced your §r§b❄ Cold §r§cto 0!" - ) private val config get() = SkyHanniMod.feature.mining.notifications - private var cold = 0 private var hasSentCold = false - private var coldResetTimer = SimpleTimeMark.farPast() @SubscribeEvent fun onChat(event: LorenzChatEvent) { @@ -71,25 +61,16 @@ object MiningNotifications { scrapDrop.matches(message) -> sendNotification(MiningNotificationList.SCRAP) goldenGoblinSpawn.matches(message) -> sendNotification(MiningNotificationList.GOLDEN_GOBLIN) diamondGoblinSpawn.matches(message) -> sendNotification(MiningNotificationList.DIAMOND_GOBLIN) - coldReset.matches(message) -> { - cold = 0 - hasSentCold = false - coldResetTimer = SimpleTimeMark.now().plus(1.seconds) - } } } @SubscribeEvent - fun onScoreboardChange(event: ScoreboardChangeEvent) { - if (!LorenzUtils.inAnyIsland(IslandType.DWARVEN_MINES, IslandType.MINESHAFT)) return + fun onColdUpdate(event: ColdUpdateEvent) { + if (!inColdIsland()) return if (!config.enabled) return - val newCold = event.newList.matchFirst(ScoreboardPattern.coldPattern) { - group("cold").toInt().absoluteValue - } ?: 0 - if (cold == newCold) return - cold = newCold - if (coldResetTimer.isInFuture()) return - if (cold >= config.coldThreshold.get() && !hasSentCold) { + if (lastColdReset.passedSince() < 1.seconds) return + + if (event.cold >= config.coldThreshold.get() && !hasSentCold) { hasSentCold = true sendNotification(MiningNotificationList.COLD) } @@ -97,14 +78,13 @@ object MiningNotifications { @SubscribeEvent fun onWorldChange(event: LorenzWorldChangeEvent) { - cold = 0 hasSentCold = false } @SubscribeEvent fun onConfigLoad(event: ConfigLoadEvent) { ConditionalUtils.onToggle(config.coldThreshold) { - if (cold != config.coldThreshold.get()) hasSentCold = false + if (getCold() != config.coldThreshold.get()) hasSentCold = false } } diff --git a/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt index 6aa9c5479b91..3e8472d631c7 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt @@ -439,7 +439,7 @@ object RenderUtils { string: String?, offsetX: Int = 0, offsetY: Int = 0, - alignmentEnum: HorizontalAlignment + alignmentEnum: HorizontalAlignment, ): Int { val display = "§f$string" GlStateManager.pushMatrix() @@ -482,7 +482,7 @@ object RenderUtils { fun Position.renderStringsAlignedWidth( list: List>, extraSpace: Int = 0, - posLabel: String + posLabel: String, ) { if (list.isEmpty()) return @@ -558,7 +558,7 @@ object RenderUtils { */ fun Position.renderSingleLineWithItems( list: List, - posLabel: String + posLabel: String, ) { if (list.isEmpty()) return renderRenderables( @@ -590,7 +590,7 @@ object RenderUtils { fun MutableList.addItemIcon( item: ItemStack, highlight: Boolean = false, - scale: Double = NEUItems.itemFontSize + scale: Double = NEUItems.itemFontSize, ) { try { if (highlight) { @@ -1187,7 +1187,7 @@ object RenderUtils { middlePoint: LorenzVec, sidePoint1: LorenzVec, sidePoint2: LorenzVec, - c: Color + c: Color, ) { GlStateManager.color(c.red / 255f, c.green / 255f, c.blue / 255f, c.alpha / 255f) worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION) @@ -1201,7 +1201,7 @@ object RenderUtils { companion object { inline fun draw3D( partialTicks: Float = 0F, - crossinline quads: QuadDrawer.() -> Unit + crossinline quads: QuadDrawer.() -> Unit, ) { GlStateManager.enableBlend() @@ -1457,4 +1457,11 @@ object RenderUtils { ShaderManager.disableShader() GlStateManager.popMatrix() } + + // TODO move off of neu function + fun drawTexturedRect(x: Float, y: Float) { + with(ScaledResolution(Minecraft.getMinecraft())) { + Utils.drawTexturedRect(x, y, scaledWidth.toFloat(), scaledHeight.toFloat(), GL11.GL_NEAREST) + } + } } diff --git a/src/main/resources/assets/skyhanni/cold_overlay.png b/src/main/resources/assets/skyhanni/cold_overlay.png new file mode 100644 index 000000000000..da61958e30a0 Binary files /dev/null and b/src/main/resources/assets/skyhanni/cold_overlay.png differ