aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt
diff options
context:
space:
mode:
authorEmpa <42304516+ItsEmpa@users.noreply.github.com>2024-06-15 22:12:24 +0200
committerGitHub <noreply@github.com>2024-06-15 22:12:24 +0200
commitbfe43b7ebffab551740d32cf919db27504d27ffb (patch)
tree7fb570635c88d98f122d2752be78f135868a9843 /src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt
parent8c91a9b8bf63059e1a8a099ccbdadea8a3676948 (diff)
downloadskyhanni-bfe43b7ebffab551740d32cf919db27504d27ffb.tar.gz
skyhanni-bfe43b7ebffab551740d32cf919db27504d27ffb.tar.bz2
skyhanni-bfe43b7ebffab551740d32cf919db27504d27ffb.zip
Feature: Mineshaft Pity Display + OreMinedEvent (#1655)
Co-authored-by: J10a1n15 <45315647+j10a1n15@users.noreply.github.com> Co-authored-by: Empa <42304516+ItsEmpa@users.noreply.github.com> Co-authored-by: Thunderblade73 <gaidermarkus@gmail.com> Co-authored-by: Thunderblade73 <85900443+Thunderblade73@users.noreply.github.com> Co-authored-by: Cal <cwolfson58@gmail.com> Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt214
1 files changed, 208 insertions, 6 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt
index edb79b894..8fe946833 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt
@@ -1,20 +1,34 @@
package at.hannibal2.skyhanni.data
+import at.hannibal2.skyhanni.events.BlockClickEvent
import at.hannibal2.skyhanni.events.ColdUpdateEvent
+import at.hannibal2.skyhanni.events.DebugDataCollectEvent
import at.hannibal2.skyhanni.events.LorenzChatEvent
+import at.hannibal2.skyhanni.events.LorenzTickEvent
import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent
+import at.hannibal2.skyhanni.events.PlaySoundEvent
import at.hannibal2.skyhanni.events.ScoreboardChangeEvent
+import at.hannibal2.skyhanni.events.ServerBlockChangeEvent
+import at.hannibal2.skyhanni.events.mining.OreMinedEvent
import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardPattern
+import at.hannibal2.skyhanni.features.mining.OreBlock
import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
+import at.hannibal2.skyhanni.utils.CollectionUtils.countBy
+import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer
import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils.inAnyIsland
import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland
+import at.hannibal2.skyhanni.utils.LorenzVec
import at.hannibal2.skyhanni.utils.RegexUtils.matchFirst
import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher
import at.hannibal2.skyhanni.utils.RegexUtils.matches
import at.hannibal2.skyhanni.utils.SimpleTimeMark
+import at.hannibal2.skyhanni.utils.TimeUtils.format
import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
+import net.minecraft.init.Blocks
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import kotlin.math.absoluteValue
+import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
@SkyHanniModule
@@ -22,24 +36,72 @@ object MiningAPI {
private val group = RepoPattern.group("data.miningapi")
private val glaciteAreaPattern by group.pattern("area.glacite", "Glacite Tunnels|Glacite Lake")
- val coldReset by group.pattern(
+ private val dwarvenBaseCampPattern by group.pattern("area.basecamp", "Dwarven Base Camp")
+ private val coldReset by group.pattern(
"cold.reset",
"§6The warmth of the campfire reduced your §r§b❄ Cold §r§6to §r§a0§r§6!|§c ☠ §r§7You froze to death§r§7."
)
- val coldResetDeath by group.pattern(
+ private val coldResetDeath by group.pattern(
"cold.deathreset",
"§c ☠ §r§7§r§.(?<name>.+)§r§7 (?<reason>.+)"
)
- private var cold = 0
+ data class MinedBlock(val ore: OreBlock, var position: LorenzVec, var confirmed: Boolean, val time: SimpleTimeMark)
+
+ private var lastInitSound = SimpleTimeMark.farPast()
+
+ private var waitingForInitBlock = false
+ private var waitingForInitBlockPos: LorenzVec? = null
+ private var waitingForInitSound = true
+
+ private var waitingForEffMinerSound = false
+ private var waitingForEffMinerBlock = false
+
+ var inGlacite = false
+ var inDwarvenMines = false
+ var inCrystalHollows = false
+ var inCrimsonIsle = false
+ var inEnd = false
+ var inSpidersDen = false
+
+ var currentAreaOreBlocks = setOf<OreBlock>()
+
+ private var lastSkyblockArea: String? = null
+
+ private var recentClickedBlocks = mutableListOf<MinedBlock>()
+ private var surroundingMinedBlocks = mutableListOf<MinedBlock>()
+ private val allowedSoundNames = listOf("dig.glass", "dig.stone", "dig.gravel", "dig.cloth")
+
+ var cold: Int = 0
+ private set
+
var lastColdUpdate = SimpleTimeMark.farPast()
var lastColdReset = SimpleTimeMark.farPast()
- fun inGlaciteArea() = glaciteAreaPattern.matches(HypixelData.skyBlockArea) || IslandType.MINESHAFT.isInIsland()
+ fun inGlaciteArea() = inGlacialTunnels() || IslandType.MINESHAFT.isInIsland()
+
+ fun inDwarvenBaseCamp() =
+ IslandType.DWARVEN_MINES.isInIsland() && dwarvenBaseCampPattern.matches(LorenzUtils.skyBlockArea)
+
+ fun inRegularDwarven() = IslandType.DWARVEN_MINES.isInIsland() && !inGlacialTunnels()
+
+ fun inCrystalHollows() = IslandType.CRYSTAL_HOLLOWS.isInIsland()
- fun inColdIsland() = IslandType.DWARVEN_MINES.isInIsland() || IslandType.MINESHAFT.isInIsland()
+ fun inMineshaft() = IslandType.MINESHAFT.isInIsland()
+
+ fun inGlacialTunnels() =
+ IslandType.DWARVEN_MINES.isInIsland() && glaciteAreaPattern.matches(LorenzUtils.skyBlockArea)
+
+ fun inCustomMiningIsland() = inAnyIsland(
+ IslandType.DWARVEN_MINES,
+ IslandType.MINESHAFT,
+ IslandType.CRYSTAL_HOLLOWS,
+ IslandType.THE_END,
+ IslandType.CRIMSON_ISLE,
+ IslandType.SPIDER_DEN,
+ )
- fun getCold() = cold
+ fun inColdIsland() = inAnyIsland(IslandType.DWARVEN_MINES, IslandType.MINESHAFT)
@SubscribeEvent
fun onScoreboardChange(event: ScoreboardChangeEvent) {
@@ -53,6 +115,16 @@ object MiningAPI {
}
@SubscribeEvent
+ fun onBlockClick(event: BlockClickEvent) {
+ if (!inCustomMiningIsland()) return
+ if (event.clickType != ClickType.LEFT_CLICK) return
+ val position = event.position
+ val blockState = event.getBlockState
+ val ore = OreBlock.getByStateOrNull(blockState) ?: return
+ recentClickedBlocks.add(MinedBlock(ore, position, false, SimpleTimeMark.now()))
+ }
+
+ @SubscribeEvent
fun onChat(event: LorenzChatEvent) {
if (!inColdIsland()) return
if (coldReset.matches(event.message)) {
@@ -68,9 +140,125 @@ object MiningAPI {
}
@SubscribeEvent
+ fun onPlaySound(event: PlaySoundEvent) {
+ if (!inCustomMiningIsland()) return
+ if (waitingForInitSound) {
+ if (event.soundName in allowedSoundNames && event.pitch == 0.7936508f) {
+ val pos = event.location.roundLocationToBlock()
+ if (recentClickedBlocks.none { it.position == pos }) return
+ waitingForInitSound = false
+ waitingForInitBlock = true
+ waitingForInitBlockPos = event.location.roundLocationToBlock()
+ lastInitSound = SimpleTimeMark.now()
+ }
+ return
+ }
+ if (waitingForEffMinerSound) {
+ if (surroundingMinedBlocks.isEmpty()) return
+ if (event.soundName in allowedSoundNames || event.soundName == "random.orb") {
+ if (surroundingMinedBlocks.last().confirmed) return
+ waitingForEffMinerSound = false
+ surroundingMinedBlocks.last().confirmed = true
+ waitingForEffMinerBlock = true
+ }
+ }
+ }
+
+ @SubscribeEvent
+ fun onBlockChange(event: ServerBlockChangeEvent) {
+ if (!inCustomMiningIsland()) return
+ if (event.newState.block != Blocks.air) return
+ if (event.oldState.block == Blocks.air) return
+ if (event.location.distanceToPlayer() > 7) return
+
+ if (lastInitSound.passedSince() > 100.milliseconds) return
+
+ val ore = OreBlock.getByStateOrNull(event.oldState) ?: return
+
+ if (waitingForInitBlock) {
+ if (waitingForInitBlockPos != event.location) return
+ waitingForInitBlock = false
+ surroundingMinedBlocks.add(MinedBlock(ore, event.location, true, SimpleTimeMark.now()))
+ waitingForEffMinerBlock = true
+ return
+ }
+ if (waitingForEffMinerBlock) {
+ if (surroundingMinedBlocks.any { it.position == event.location }) return
+ waitingForEffMinerBlock = false
+ surroundingMinedBlocks.add(MinedBlock(ore, event.location, false, SimpleTimeMark.now()))
+ waitingForEffMinerSound = true
+ return
+ }
+ }
+
+ @SubscribeEvent
+ fun onTick(event: LorenzTickEvent) {
+ if (!inCustomMiningIsland()) return
+
+ if (LorenzUtils.lastWorldSwitch.passedSince() < 4.seconds) return
+ updateLocation()
+
+ if (currentAreaOreBlocks.isEmpty()) return
+
+ // if somehow you take more than 20 seconds to mine a single block, congrats
+ recentClickedBlocks.removeIf { it.time.passedSince() > 20.seconds }
+ surroundingMinedBlocks.removeIf { it.time.passedSince() > 20.seconds }
+
+ if (surroundingMinedBlocks.isEmpty()) return
+ if (lastInitSound.passedSince() < 200.milliseconds) return
+
+ resetOreEvent()
+
+ val originalBlock = surroundingMinedBlocks.firstOrNull { it.confirmed } ?: run {
+ surroundingMinedBlocks = mutableListOf()
+ recentClickedBlocks = mutableListOf()
+ return
+ }
+
+ val extraBlocks = surroundingMinedBlocks.filter { it.confirmed }.countBy { it.ore }
+
+ OreMinedEvent(originalBlock.ore, extraBlocks).post()
+
+ surroundingMinedBlocks = mutableListOf()
+ recentClickedBlocks.removeIf { it.time.passedSince() >= originalBlock.time.passedSince() }
+ }
+
+ @SubscribeEvent
fun onWorldChange(event: LorenzWorldChangeEvent) {
if (cold != 0) updateCold(0)
lastColdReset = SimpleTimeMark.now()
+ recentClickedBlocks = mutableListOf()
+ surroundingMinedBlocks = mutableListOf()
+ currentAreaOreBlocks = setOf()
+ resetOreEvent()
+ }
+
+ private fun resetOreEvent() {
+ lastInitSound = SimpleTimeMark.farPast()
+ waitingForInitSound = true
+ waitingForInitBlock = false
+ waitingForInitBlockPos = null
+ waitingForEffMinerSound = false
+ waitingForEffMinerBlock = false
+ }
+
+ @SubscribeEvent
+ fun onDebugDataCollect(event: DebugDataCollectEvent) {
+ event.title("Mining API")
+ if (!inCustomMiningIsland()) {
+ event.addIrrelevant("not in a mining island")
+ return
+ }
+
+ event.addData {
+ add("lastInitSound: ${lastInitSound.passedSince().format()}")
+ add("waitingForInitSound: $waitingForInitSound")
+ add("waitingForInitBlock: $waitingForInitBlock")
+ add("waitingForInitBlockPos: $waitingForInitBlockPos")
+ add("waitingForEffMinerSound: $waitingForEffMinerSound")
+ add("waitingForEffMinerBlock: $waitingForEffMinerBlock")
+ add("recentClickedBlocks: ${recentClickedBlocks.joinToString { it.position.toCleanString() }}")
+ }
}
private fun updateCold(newCold: Int) {
@@ -81,4 +269,18 @@ object MiningAPI {
cold = newCold
}
+ private fun updateLocation() {
+ val currentArea = LorenzUtils.skyBlockArea
+ if (currentArea == lastSkyblockArea) return
+ lastSkyblockArea = currentArea
+
+ inGlacite = inGlaciteArea()
+ inDwarvenMines = inRegularDwarven()
+ inCrystalHollows = inCrystalHollows()
+ inCrimsonIsle = IslandType.CRIMSON_ISLE.isInIsland()
+ inEnd = IslandType.THE_END.isInIsland()
+ inSpidersDen = IslandType.SPIDER_DEN.isInIsland()
+
+ currentAreaOreBlocks = OreBlock.entries.filter { it.checkArea() }.toSet()
+ }
}