diff options
| author | Empa <42304516+ItsEmpa@users.noreply.github.com> | 2024-06-15 22:12:24 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-06-15 22:12:24 +0200 |
| commit | bfe43b7ebffab551740d32cf919db27504d27ffb (patch) | |
| tree | 7fb570635c88d98f122d2752be78f135868a9843 /src/main/java | |
| parent | 8c91a9b8bf63059e1a8a099ccbdadea8a3676948 (diff) | |
| download | skyhanni-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')
20 files changed, 1318 insertions, 196 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt index de4bc2585..22f7e2d28 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt @@ -52,6 +52,7 @@ import at.hannibal2.skyhanni.features.garden.pests.PestFinder import at.hannibal2.skyhanni.features.garden.pests.PestProfitTracker import at.hannibal2.skyhanni.features.garden.visitor.GardenVisitorDropStatistics import at.hannibal2.skyhanni.features.mining.KingTalismanHelper +import at.hannibal2.skyhanni.features.mining.MineshaftPityDisplay import at.hannibal2.skyhanni.features.mining.powdertracker.PowderTracker import at.hannibal2.skyhanni.features.minion.MinionFeatures import at.hannibal2.skyhanni.features.misc.CollectionTracker @@ -547,6 +548,10 @@ object Commands { "shtoggleegglocationdebug", "Shows Hoppity egg locations with their internal API names and status.", ) { HoppityEggLocations.toggleDebug() } + registerCommand( + "shresetmineshaftpitystats", + "Resets the mineshaft pity display stats" + ) { MineshaftPityDisplay.fullResetCounter() } } private fun internalCommands() { diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/dev/DebugConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/dev/DebugConfig.java index db2aa868b..9612ac3b7 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/dev/DebugConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/dev/DebugConfig.java @@ -127,6 +127,16 @@ public class DebugConfig { public boolean currentAreaDebug = true; @Expose + @ConfigOption(name = "Oreblock Name", desc = "Show the OreBlock you are currently looking at.") + @ConfigEditorBoolean + public boolean raytracedOreblock = true; + + @Expose + @ConfigOption(name = "Ore Event Messages", desc = "Shows debug messages every time the Ore Event happens.") + @ConfigEditorBoolean + public boolean oreEventMessages = false; + + @Expose @ConfigOption(name = "Assume Mayor", desc = "Select a mayor to assume.") @ConfigEditorDropdown public Property<Mayor> assumeMayor = Property.of(Mayor.DISABLED); diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/dev/DevConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/dev/DevConfig.java index 041134e41..a42da18c1 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/dev/DevConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/dev/DevConfig.java @@ -8,6 +8,7 @@ import io.github.notenoughupdates.moulconfig.annotations.Category; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorKeybind; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorSlider; +import io.github.notenoughupdates.moulconfig.annotations.ConfigLink; import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; import org.lwjgl.input.Keyboard; @@ -61,6 +62,10 @@ public class DevConfig { public Position debugItemPos = new Position(90, 70); @Expose + @ConfigLink(owner = DebugConfig.class, field = "raytracedOreblock") + public Position debugOrePos = new Position(1, 200, false, true); + + @Expose @ConfigOption( name = "Fancy Contributors", desc = "Marks §cSkyHanni's contributors §7fancy in the tab list. " + diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/mining/MineshaftPityDisplayConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/mining/MineshaftPityDisplayConfig.java new file mode 100644 index 000000000..ab73f060d --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/mining/MineshaftPityDisplayConfig.java @@ -0,0 +1,43 @@ +package at.hannibal2.skyhanni.config.features.mining; + +import at.hannibal2.skyhanni.config.FeatureToggle; +import at.hannibal2.skyhanni.config.core.config.Position; +import at.hannibal2.skyhanni.features.mining.MineshaftPityDisplay.MineshaftPityLines; +import com.google.gson.annotations.Expose; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDraggableList; +import io.github.notenoughupdates.moulconfig.annotations.ConfigLink; +import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class MineshaftPityDisplayConfig { + @Expose + @ConfigOption(name = "Enable Display", desc = "Enable the Mineshaft Pity Display.") + @ConfigEditorBoolean + @FeatureToggle + public boolean enabled = true; + + @Expose + @ConfigOption(name = "Stats List", desc = "Drag text to change the appearance of the display.") + @ConfigEditorDraggableList + public List<MineshaftPityLines> mineshaftPityLines = new ArrayList<>(Arrays.asList( + MineshaftPityLines.TITLE, + MineshaftPityLines.COUNTER, + MineshaftPityLines.CHANCE, + MineshaftPityLines.NEEDED_TO_PITY, + MineshaftPityLines.TIME_SINCE_MINESHAFT + )); + + @Expose + @ConfigOption(name = "Modify Spawn Message", desc = "Modify the Mineshaft spawn message with more stats.") + @ConfigEditorBoolean + @FeatureToggle + public boolean modifyChatMessage = true; + + @Expose + @ConfigLink(owner = MineshaftPityDisplayConfig.class, field = "enabled") + public Position position = new Position(16, 192, false, true); +} 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 870c31929..adbfb32b7 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 @@ -69,6 +69,11 @@ public class MiningConfig { public MineshaftConfig mineshaft = new MineshaftConfig(); @Expose + @ConfigOption(name = "Mineshaft Pity Display", desc = "") + @Accordion + public MineshaftPityDisplayConfig mineshaftPityDisplay = new MineshaftPityDisplayConfig(); + + @Expose @ConfigOption(name = "Highlight Commission Mobs", desc = "Highlight Mobs that are part of active commissions.") @ConfigEditorBoolean @FeatureToggle diff --git a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java index fe0cd58fb..2887d0230 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java +++ b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java @@ -29,6 +29,7 @@ import at.hannibal2.skyhanni.features.garden.pests.PestProfitTracker; import at.hannibal2.skyhanni.features.garden.pests.VinylType; import at.hannibal2.skyhanni.features.garden.visitor.VisitorReward; import at.hannibal2.skyhanni.features.inventory.wardrobe.WardrobeAPI; +import at.hannibal2.skyhanni.features.mining.MineshaftPityDisplay; import at.hannibal2.skyhanni.features.mining.fossilexcavator.ExcavatorProfitTracker; import at.hannibal2.skyhanni.features.mining.powdertracker.PowderTracker; import at.hannibal2.skyhanni.features.misc.trevor.TrevorTracker; @@ -540,6 +541,21 @@ public class ProfileSpecificStorage { @Expose public int availableTokens; + + @Expose + public MineshaftStorage mineshaft = new MineshaftStorage(); + + public static class MineshaftStorage { + + @Expose + public long mineshaftTotalBlocks = 0L; + + @Expose + public int mineshaftTotalCount = 0; + + @Expose + public List<MineshaftPityDisplay.PityData> blocksBroken = new ArrayList<>(); + } } @Expose diff --git a/src/main/java/at/hannibal2/skyhanni/data/HotmData.kt b/src/main/java/at/hannibal2/skyhanni/data/HotmData.kt index 0b51dfa8d..d232e49bb 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/HotmData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/HotmData.kt @@ -16,6 +16,7 @@ import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardPattern import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut import at.hannibal2.skyhanni.utils.ConditionalUtils.transformIf import at.hannibal2.skyhanni.utils.DelayedRun import at.hannibal2.skyhanni.utils.InventoryUtils @@ -36,11 +37,28 @@ import kotlin.math.ceil import kotlin.math.floor import kotlin.math.pow + +private fun calculatePeakOfTheMountainLoot(level: Int): Map<HotmReward, Double> = buildMap { + for (i in 1..level) { + when (i) { + 1, 5, 7 -> addOrPut(HotmReward.EXTRA_TOKENS, 1.0) + 2 -> addOrPut(HotmReward.EXTRA_FORGE_SLOTS, 1.0) + 3 -> addOrPut(HotmReward.EXTRA_COMMISSION_SLOTS, 1.0) + 4 -> addOrPut(HotmReward.MORE_BASE_MITHRIL_POWER, 1.0) + 6 -> addOrPut(HotmReward.MORE_BASE_GEMSTONE_POWER, 2.0) + 8 -> addOrPut(HotmReward.MORE_BASE_GLACITE_POWER, 3.0) + 9 -> addOrPut(HotmReward.MINESHAFT_CHANCE, 10.0) + 10 -> addOrPut(HotmReward.EXTRA_TOKENS, 2.0) + } + } +} + + enum class HotmData( val guiName: String, val maxLevel: Int, - val costFun: ((Int) -> (Double?)), - val rewardFun: ((Int) -> (Map<HotmReward, Double>)), + val costFun: (Int) -> (Double?), + val rewardFun: (Int) -> (Map<HotmReward, Double>), ) { MINING_SPEED( @@ -246,7 +264,10 @@ enum class HotmData( }, ), - PEAK_OF_THE_MOUNTAIN("Peak of the Mountain", 10, { null }, { emptyMap() }), + PEAK_OF_THE_MOUNTAIN( + "Peak of the Mountain", 10, { null }, + { level -> calculatePeakOfTheMountainLoot(level) }, + ), // Mining V3 DAILY_GRIND( @@ -291,7 +312,7 @@ enum class HotmData( "Surveyor", 20, { currentLevel -> (currentLevel + 1.0).pow(4) }, - { level -> mapOf(HotmReward.UNKNOWN to 0.75 * level) }, + { level -> mapOf(HotmReward.MINESHAFT_CHANCE to 0.75 * level) }, ), EAGER_ADVENTURER( "Eager Adventurer", @@ -343,7 +364,7 @@ enum class HotmData( get() = storage?.perks?.get(this.name)?.level ?: 0 var activeLevel: Int - get() = storage?.perks?.get(this.name)?.level?.plus(blueEgg()) ?: 0 + get() = if (enabled) storage?.perks?.get(this.name)?.level?.plus(blueEgg()) ?: 0 else 0 private set(value) { storage?.perks?.computeIfAbsent(this.name) { HotmTree.HotmPerk() }?.level = value.minus(blueEgg()) } @@ -370,7 +391,7 @@ enum class HotmData( fun getLevelUpCost() = costFun(rawLevel) - fun getReward() = rewardFun(activeLevel) + fun getReward() = if (enabled) rewardFun(activeLevel) else emptyMap() fun calculateTotalCost(desiredLevel: Int) = (1 until desiredLevel).sumOf { level -> costFun(level) ?: 0.0 }.toInt() @@ -382,8 +403,7 @@ enum class HotmData( val storage get() = ProfileStorageData.profileSpecific?.mining?.hotmTree - val abilities = - listOf(PICKOBULUS, MINING_SPEED_BOOST, VEIN_SEEKER, MANIAC_MINER, HAZARDOUS_MINER, GEMSTONE_INFUSION) + val abilities = listOf(PICKOBULUS, MINING_SPEED_BOOST, VEIN_SEEKER, MANIAC_MINER, HAZARDOUS_MINER, GEMSTONE_INFUSION) private val inventoryPattern by patternGroup.pattern( "inventory", @@ -407,7 +427,7 @@ enum class HotmData( private val disabledPattern by patternGroup.pattern( "perk.disabled", "§c§lDISABLED|§7§eClick to select!", - ) // unused for now since the assumption is when enabled isn't found it is disabled, + ) // unused for now since the assumption is when enabled isn't found it is disabled, // but the value might be useful in the future or for debugging val perkCostPattern by patternGroup.pattern( @@ -478,6 +498,21 @@ enum class HotmData( HotmAPI.MayhemPerk.entries.forEach { it.chatPattern } + (0..PEAK_OF_THE_MOUNTAIN.maxLevel).forEach { level -> + val map = mutableMapOf<HotmReward, Double>() + if (level >= 1) map.addOrPut(HotmReward.EXTRA_TOKENS, 1.0) + if (level >= 2) map.addOrPut(HotmReward.EXTRA_FORGE_SLOTS, 1.0) + if (level >= 3) map.addOrPut(HotmReward.EXTRA_COMMISSION_SLOTS, 1.0) + if (level >= 4) map.addOrPut(HotmReward.MORE_BASE_MITHRIL_POWER, 1.0) + if (level >= 5) map.addOrPut(HotmReward.EXTRA_TOKENS, 1.0) + if (level >= 6) map.addOrPut(HotmReward.MORE_BASE_GEMSTONE_POWER, 2.0) + if (level >= 7) map.addOrPut(HotmReward.EXTRA_TOKENS, 1.0) + if (level >= 8) map.addOrPut(HotmReward.MORE_BASE_GLACITE_POWER, 3.0) + if (level >= 9) map.addOrPut(HotmReward.MINESHAFT_CHANCE, 10.0) + if (level >= 10) map.addOrPut(HotmReward.EXTRA_TOKENS, 2.0) + + peakOfTheMountainPerks[level] = map + } } fun getPerkByNameOrNull(name: String): HotmData? = entries.find { it.guiName == name } @@ -724,6 +759,8 @@ enum class HotmData( } } +private val peakOfTheMountainPerks = mutableMapOf<Int, Map<HotmReward, Double>>() + private val patternGroup = RepoPattern.group("mining.hotm") enum class HotmReward { @@ -735,6 +772,7 @@ enum class HotmReward { DAILY_POWDER, MORE_BASE_MITHRIL_POWER, MORE_BASE_GEMSTONE_POWER, + MORE_BASE_GLACITE_POWER, MORE_MITHRIL_POWER, MORE_GEMSTONE_POWER, COMBAT_STAT_BOOST, @@ -748,6 +786,10 @@ enum class HotmReward { ABILITY_RADIUS, ABILITY_COOLDOWN, FOSSIL_DUST, + MINESHAFT_CHANCE, + EXTRA_TOKENS, + EXTRA_FORGE_SLOTS, + EXTRA_COMMISSION_SLOTS, UNKNOWN, COLD_RESISTANCE } 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() + } } diff --git a/src/main/java/at/hannibal2/skyhanni/events/ServerBlockChangeEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/ServerBlockChangeEvent.kt index 43941aa36..07aa7630e 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/ServerBlockChangeEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/ServerBlockChangeEvent.kt @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.events import at.hannibal2.skyhanni.utils.BlockUtils.getBlockAt +import at.hannibal2.skyhanni.utils.BlockUtils.getBlockStateAt import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.toLorenzVec import net.minecraft.block.state.IBlockState @@ -10,7 +11,9 @@ class ServerBlockChangeEvent(private val blockPos: BlockPos, private val blockSt val location by lazy { blockPos.toLorenzVec() } val old by lazy { location.getBlockAt().toString().getName() } + val oldState by lazy { location.getBlockStateAt() } val new by lazy { blockState.block.toString().getName() } + val newState by lazy { blockState } companion object { diff --git a/src/main/java/at/hannibal2/skyhanni/events/mining/OreMinedEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/mining/OreMinedEvent.kt new file mode 100644 index 000000000..a97402a41 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/events/mining/OreMinedEvent.kt @@ -0,0 +1,6 @@ +package at.hannibal2.skyhanni.events.mining + +import at.hannibal2.skyhanni.api.event.SkyHanniEvent +import at.hannibal2.skyhanni.features.mining.OreBlock + +class OreMinedEvent(val originalOre: OreBlock, val extraBlocks: Map<OreBlock, Int>) : SkyHanniEvent() 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 aae1e7086..b73df6f14 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 @@ -10,7 +10,7 @@ import at.hannibal2.skyhanni.data.HypixelData.getPlayersOnCurrentServer 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.MiningAPI import at.hannibal2.skyhanni.data.PartyAPI import at.hannibal2.skyhanni.data.PurseAPI import at.hannibal2.skyhanni.data.QuiverAPI @@ -475,7 +475,7 @@ private fun getHeatShowWhen() = inAnyIsland(IslandType.CRYSTAL_HOLLOWS) && ScoreboardData.sidebarLinesFormatted.any { ScoreboardPattern.heatPattern.matches(it) } private fun getColdDisplayPair(): List<ScoreboardElementType> { - val cold = -getCold() + val cold = -MiningAPI.cold return listOf( when { diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/MineshaftPityDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/MineshaftPityDisplay.kt new file mode 100644 index 000000000..731a8ca4a --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/MineshaftPityDisplay.kt @@ -0,0 +1,340 @@ +package at.hannibal2.skyhanni.features.mining + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.event.HandleEvent +import at.hannibal2.skyhanni.data.HotmData |
