summaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/dev/DebugConfig.java10
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/dev/DevConfig.java5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/mining/MineshaftPityDisplayConfig.java43
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningConfig.java5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java16
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/HotmData.kt60
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt214
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/ServerBlockChangeEvent.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/mining/OreMinedEvent.kt6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/mining/MineshaftPityDisplay.kt340
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/mining/MiningCommissionsBlocksColor.kt197
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/mining/MiningNotifications.kt29
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/mining/OreBlock.kt279
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/mining/OreType.kt213
-rw-r--r--src/main/java/at/hannibal2/skyhanni/mixins/hooks/BlockRendererDispatcherHook.kt11
-rw-r--r--src/main/java/at/hannibal2/skyhanni/test/SkyHanniDebugsAndTests.kt37
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/CollectionUtils.kt35
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/LorenzVec.kt2
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
+import at.hannibal2.skyhanni.data.HotmReward
+import at.hannibal2.skyhanni.data.IslandType
+import at.hannibal2.skyhanni.data.MiningAPI
+import at.hannibal2.skyhanni.data.ProfileStorageData
+import at.hannibal2.skyhanni.events.GuiRenderEvent
+import at.hannibal2.skyhanni.events.IslandChangeEvent
+import at.hannibal2.skyhanni.events.LorenzChatEvent
+import at.hannibal2.skyhanni.events.SecondPassedEvent
+import at.hannibal2.skyhanni.events.mining.OreMinedEvent
+import at.hannibal2.skyhanni.features.mining.MineshaftPityDisplay.PityBlock.Companion.getPity
+import at.hannibal2.skyhanni.features.mining.MineshaftPityDisplay.PityBlock.Companion.getPityBlock
+import at.hannibal2.skyhanni.features.mining.OreType.Companion.getOreType
+import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
+import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut
+import at.hannibal2.skyhanni.utils.LorenzUtils.round
+import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
+import at.hannibal2.skyhanni.utils.RegexUtils.matches
+import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables
+import at.hannibal2.skyhanni.utils.SimpleTimeMark
+import at.hannibal2.skyhanni.utils.TimeUtils.format
+import at.hannibal2.skyhanni.utils.chat.Text
+import at.hannibal2.skyhanni.utils.chat.Text.hover
+import at.hannibal2.skyhanni.utils.renderables.Renderable
+import com.google.gson.annotations.Expose
+import net.minecraft.block.BlockStone
+import net.minecraft.init.Blocks
+import net.minecraft.item.EnumDyeColor
+import net.minecraft.item.ItemStack
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+@SkyHanniModule
+object MineshaftPityDisplay {
+ private val config get() = SkyHanniMod.feature.mining.mineshaftPityDisplay
+
<