diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt index 1e8a576e2d63..9a08a23855b8 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt @@ -12,7 +12,7 @@ import com.google.gson.JsonPrimitive object ConfigUpdaterMigrator { val logger = LorenzLogger("ConfigMigration") - const val CONFIG_VERSION = 41 + const val CONFIG_VERSION = 42 fun JsonElement.at(chain: List, init: Boolean): JsonElement? { if (chain.isEmpty()) return this if (this !is JsonObject) return null diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/event/ChocolateFactoryConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/event/ChocolateFactoryConfig.java index f2ca55a55625..d678385329a6 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/event/ChocolateFactoryConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/event/ChocolateFactoryConfig.java @@ -45,6 +45,7 @@ public class ChocolateFactoryConfig { ChocolateFactoryStat.CURRENT, ChocolateFactoryStat.THIS_PRESTIGE, ChocolateFactoryStat.ALL_TIME, + ChocolateFactoryStat.TIME_TO_PRESTIGE, ChocolateFactoryStat.EMPTY, ChocolateFactoryStat.PER_SECOND, ChocolateFactoryStat.PER_MINUTE, @@ -106,11 +107,11 @@ public class ChocolateFactoryConfig { @Expose @ConfigLink(owner = ChocolateFactoryConfig.class, field = "statsDisplay") - public Position position = new Position(183, 160, false, true); + public Position position = new Position(163, 160, false, true); @Expose @ConfigLink(owner = ChocolateFactoryConfig.class, field = "hoppityCollectionStats") - public Position hoppityStatsPosition = new Position(183, 160, false, true); + public Position hoppityStatsPosition = new Position(163, 160, false, true); @Expose @ConfigOption(name = "Compact On Click", desc = "Compact the item toolip when clicking on the chocolate.") 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 12861986e6ef..a353bd88a9d3 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java +++ b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java @@ -56,6 +56,30 @@ public static class ChocolateFactoryStorage { @Expose public int maxRabbits = -1; + @Expose + public long currentChocolate = 0; + + @Expose + public long chocolateThisPrestige = 0; + + @Expose + public long chocolateAllTime = 0; + + @Expose + public int rawChocPerSecond = 0; + + @Expose + public double chocolateMultiplier = 1.0; + + @Expose + public double rawChocolateMultiplier = 1.0; + + @Expose + public int timeTowerLevel = 0; + + @Expose + public long currentTimeTowerEnds = 0; + @Expose public long nextTimeTower = 0; @@ -64,6 +88,9 @@ public static class ChocolateFactoryStorage { @Expose public int maxTimeTowerUses = 3; + + @Expose + public long lastDataSave = 0; } @Expose diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateAmount.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateAmount.kt new file mode 100644 index 000000000000..230799df041a --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateAmount.kt @@ -0,0 +1,40 @@ +package at.hannibal2.skyhanni.features.event.chocolatefactory + +import at.hannibal2.skyhanni.features.event.chocolatefactory.ChocolateFactoryAPI.profileStorage +import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds + +enum class ChocolateAmount(val chocolate: () -> Long) { + CURRENT({ profileStorage?.currentChocolate ?: 0 }), + PRESTIGE({ profileStorage?.chocolateThisPrestige ?: 0 }), + ALL_TIME({ profileStorage?.chocolateAllTime ?: 0 }), + ; + + val formatted get(): String = chocolate().addSeparators() + + fun timeUntilGoal(goal: Long): Duration { + val profileStorage = ChocolateFactoryAPI.profileStorage ?: return Duration.ZERO + + val updatedAgo = SimpleTimeMark(profileStorage.lastDataSave).passedSince().inWholeSeconds + + val baseMultiplier = profileStorage.rawChocolateMultiplier + val baseChocolatePerSecond = profileStorage.rawChocPerSecond + val timeTowerMultiplier = baseMultiplier + profileStorage.timeTowerLevel * 0.1 + + var needed = goal - chocolate() + val secondsUntilTowerExpires = ChocolateFactoryTimeTowerManager.timeTowerActiveDuration().inWholeSeconds + + val timeTowerChocPerSecond = baseChocolatePerSecond * timeTowerMultiplier + + val secondsAtRate = needed / timeTowerChocPerSecond + if (secondsAtRate < secondsUntilTowerExpires) { + return secondsAtRate.seconds - updatedAgo.seconds + } + + needed -= (secondsUntilTowerExpires * timeTowerChocPerSecond).toLong() + val chocPerSecond = baseChocolatePerSecond * baseMultiplier + return (needed / chocPerSecond + secondsUntilTowerExpires).seconds - updatedAgo.seconds + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryAPI.kt index 53c003663f65..84bce4b3dbe7 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryAPI.kt @@ -68,6 +68,10 @@ object ChocolateFactoryAPI { "prestige.level", "§6Chocolate Factory (?[IVX]+)" ) + private val chocolateForPrestigePattern by patternGroup.pattern( + "chocolate.forprestige", + "§7§cRequires (?\\w+) Chocolate this.*" + ) private val clickMeRabbitPattern by patternGroup.pattern( "rabbit.clickme", "§e§lCLICK ME!" @@ -86,7 +90,7 @@ object ChocolateFactoryAPI { ) private val timeTowerStatusPattern by patternGroup.pattern( "timetower.status", - "§7Status: §.§l(?INACTIVE|ACTIVE).*" + "§7Status: §.§l(?INACTIVE|ACTIVE)(?: §f)?(?\\w*)" ) private val timeTowerRechargePattern by patternGroup.pattern( "timetower.recharge", @@ -102,20 +106,16 @@ object ChocolateFactoryAPI { private var prestigeIndex = 28 var milestoneIndex = 53 private var leaderboardIndex = 51 - private var timeTowerIndex = 39 + var timeTowerIndex = 39 var maxRabbits = 395 var inChocolateFactory = false - var currentPrestige = 0 - var chocolateCurrent = 0L - var chocolateAllTime = 0L + var currentPrestige = 1 var chocolatePerSecond = 0.0 - var chocolateThisPrestige = 0L - var chocolateMultiplier = 1.0 var leaderboardPosition: Int? = null var leaderboardPercentile: Double? = null - var timeTowerActive = false + var chocolateForPrestige = 150_000_000L val upgradeableSlots: MutableSet = mutableSetOf() var bestUpgrade: Int? = null @@ -165,7 +165,7 @@ object ChocolateFactoryAPI { val lore = item.getLore() val upgradeCost = lore.getUpgradeCost() ?: continue - val canAfford = upgradeCost <= chocolateCurrent + val canAfford = upgradeCost <= ChocolateAmount.CURRENT.chocolate() if (canAfford) upgradeableSlots.add(slotIndex) if (slotIndex in rabbitSlots) { @@ -194,30 +194,40 @@ object ChocolateFactoryAPI { ) { val profileStorage = profileStorage ?: return - chocolateMultiplier = 1.0 - timeTowerActive = false leaderboardPosition = null leaderboardPercentile = null chocolateAmountPattern.matchMatcher(chocolateItem.name.removeColor()) { - chocolateCurrent = group("amount").formatLong() + profileStorage.currentChocolate = group("amount").formatLong() } for (line in chocolateItem.getLore()) { chocolatePerSecondPattern.matchMatcher(line) { chocolatePerSecond = group("amount").formatDouble() } chocolateAllTimePattern.matchMatcher(line) { - chocolateAllTime = group("amount").formatLong() + profileStorage.chocolateAllTime = group("amount").formatLong() } } prestigeLevelPattern.matchMatcher(prestigeItem.name) { currentPrestige = group("prestige").romanToDecimal() } - prestigeItem.getLore().matchFirst(chocolateThisPrestigePattern) { - chocolateThisPrestige = group("amount").formatLong() + for (line in prestigeItem.getLore()) { + chocolateThisPrestigePattern.matchMatcher(line) { + profileStorage.chocolateThisPrestige = group("amount").formatLong() + } + chocolateForPrestigePattern.matchMatcher(line) { + chocolateForPrestige = group("amount").formatLong() + } } productionItem.getLore().matchFirst(chocolateMultiplierPattern) { - chocolateMultiplier = group("amount").formatDouble() + val currentMultiplier = group("amount").formatDouble() + profileStorage.chocolateMultiplier = currentMultiplier + + if (ChocolateFactoryTimeTowerManager.timeTowerActive()) { + profileStorage.rawChocolateMultiplier = currentMultiplier - profileStorage.timeTowerLevel * 0.1 + } else { + profileStorage.rawChocolateMultiplier = currentMultiplier + } } for (line in leaderboardItem.getLore()) { leaderboardPlacePattern.matchMatcher(line) { @@ -239,7 +249,15 @@ object ChocolateFactoryAPI { ChocolateFactoryTimeTowerManager.checkTimeTowerWarning(true) } timeTowerStatusPattern.matchMatcher(line) { - timeTowerActive = group("status") == "ACTIVE" + val activeTime = group("acitveTime") + if (activeTime.isNotEmpty()) { + // todo in future fix this issue with TimeUtils.getDuration + val formattedGroup = activeTime.replace("h", "h ").replace("m", "m ") + + val activeDuration = TimeUtils.getDuration(formattedGroup) + val activeUntil = SimpleTimeMark.now() + activeDuration + profileStorage.currentTimeTowerEnds = activeUntil.toMillis() + } } timeTowerRechargePattern.matchMatcher(line) { // todo in future fix this issue with TimeUtils.getDuration @@ -250,6 +268,8 @@ object ChocolateFactoryAPI { profileStorage.nextTimeTower = nextTimeTower.toMillis() } } + profileStorage.rawChocPerSecond = (chocolatePerSecond / profileStorage.chocolateMultiplier).toInt() + profileStorage.lastDataSave = SimpleTimeMark.now().toMillis() if (!config.statsDisplay) return ChocolateFactoryStats.updateDisplay() diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryInventory.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryInventory.kt index bad268f96595..b62d437ad279 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryInventory.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryInventory.kt @@ -19,6 +19,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent object ChocolateFactoryInventory { private val config get() = ChocolateFactoryAPI.config + private val profileStorage get() = ChocolateFactoryAPI.profileStorage private val rabbitAmountPattern by ChocolateFactoryAPI.patternGroup.pattern( "rabbit.amount", @@ -64,6 +65,19 @@ object ChocolateFactoryInventory { if (slot.slotIndex == ChocolateFactoryAPI.clickRabbitSlot) { slot highlight LorenzColor.RED } + if (slot.slotIndex == ChocolateFactoryAPI.milestoneIndex) { + slot.stack?.getLore()?.matchFirst(unclaimedRewardsPattern) { + slot highlight LorenzColor.RED + } + } + if (slot.slotIndex == ChocolateFactoryAPI.timeTowerIndex) { + if (ChocolateFactoryTimeTowerManager.timeTowerActive()) { + slot highlight LorenzColor.LIGHT_PURPLE + } + if (ChocolateFactoryTimeTowerManager.timeTowerFull()) { + slot highlight LorenzColor.RED + } + } } } @@ -71,6 +85,7 @@ object ChocolateFactoryInventory { fun onRenderItemTip(event: RenderInventoryItemTipEvent) { if (!ChocolateFactoryAPI.inChocolateFactory) return if (!config.showStackSizes) return + val profileStorage = profileStorage ?: return val item = event.stack val itemName = item.name.removeColor() @@ -93,12 +108,11 @@ object ChocolateFactoryInventory { } if (slotNumber in ChocolateFactoryAPI.otherUpgradeSlots) { upgradeTierPattern.matchMatcher(itemName) { - event.stackTip = group("tier").romanToDecimal().toString() - } - } - if (slotNumber == ChocolateFactoryAPI.milestoneIndex) { - item.getLore().matchFirst(unclaimedRewardsPattern) { - event.stackTip = "§c!!!" + val level = group("tier").romanToDecimal() + + if (slotNumber == ChocolateFactoryAPI.timeTowerIndex) profileStorage.timeTowerLevel = level + + event.stackTip = level.toString() } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryStats.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryStats.kt index ac16b7b148d0..08de9fbf6499 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryStats.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryStats.kt @@ -1,13 +1,17 @@ package at.hannibal2.skyhanni.features.event.chocolatefactory +import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.events.GuiRenderEvent import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings +import at.hannibal2.skyhanni.utils.TimeUtils.format +import com.google.gson.JsonPrimitive import net.minecraftforge.fml.common.eventhandler.SubscribeEvent object ChocolateFactoryStats { private val config get() = ChocolateFactoryAPI.config + private val profileStorage get() = ChocolateFactoryAPI.profileStorage private var displayList = listOf() @@ -20,31 +24,35 @@ object ChocolateFactoryStats { } fun updateDisplay() { + val profileStorage = profileStorage ?: return + val perSecond = ChocolateFactoryAPI.chocolatePerSecond val perMinute = perSecond * 60 val perHour = perMinute * 60 val perDay = perHour * 24 val position = ChocolateFactoryAPI.leaderboardPosition?.addSeparators() ?: "???" val percentile = ChocolateFactoryAPI.leaderboardPercentile?.let { "§7Top §a$it%" } ?: "" - val timeTowerInfo = if (ChocolateFactoryAPI.timeTowerActive) { + val timeTowerInfo = if (ChocolateFactoryTimeTowerManager.timeTowerActive()) { "§d§lActive" } else { "§6${ChocolateFactoryTimeTowerManager.timeTowerCharges()}" } + val timeUntilPrestige = ChocolateAmount.PRESTIGE.timeUntilGoal(ChocolateFactoryAPI.chocolateForPrestige) + displayList = formatList(buildList { add("§6§lChocolate Factory Stats") - add("§eCurrent Chocolate: §6${ChocolateFactoryAPI.chocolateCurrent.addSeparators()}") - add("§eThis Prestige: §6${ChocolateFactoryAPI.chocolateThisPrestige.addSeparators()}") - add("§eAll-time: §6${ChocolateFactoryAPI.chocolateAllTime.addSeparators()}") + add("§eCurrent Chocolate: §6${ChocolateAmount.CURRENT.formatted}") + add("§eThis Prestige: §6${ChocolateAmount.PRESTIGE.formatted}") + add("§eAll-time: §6${ChocolateAmount.ALL_TIME.formatted}") add("§ePer Second: §6${perSecond.addSeparators()}") add("§ePer Minute: §6${perMinute.addSeparators()}") add("§ePer Hour: §6${perHour.addSeparators()}") add("§ePer Day: §6${perDay.addSeparators()}") - add("§eChocolate Multiplier: §6${ChocolateFactoryAPI.chocolateMultiplier}") + add("§eChocolate Multiplier: §6${profileStorage.chocolateMultiplier}") add("§eBarn: §6${ChocolateFactoryBarnManager.barnStatus()}") add("§ePosition: §7#§b$position $percentile") @@ -54,6 +62,8 @@ object ChocolateFactoryStats { add("") add("§eTime Tower: §6$timeTowerInfo") + add("§eTime To Prestige: §6${timeUntilPrestige.format()}") + add("§eRaw Per Second: §6${profileStorage.rawChocPerSecond.addSeparators()}") }) } @@ -63,6 +73,18 @@ object ChocolateFactoryStats { .map { list[it.ordinal] } } + @SubscribeEvent + fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { + event.transform(42, "event.chocolateFactory.statsDisplayList") { element -> + val jsonArray = element.asJsonArray + + jsonArray.add(JsonPrimitive("TIME_TOWER")) + jsonArray.add(JsonPrimitive("TIME_TO_PRESTIGE")) + + jsonArray + } + } + enum class ChocolateFactoryStat(private val display: String, val shouldDisplay: () -> Boolean = { true }) { HEADER("§6§lChocolate Factory Stats"), CURRENT("§eCurrent Chocolate: §65,272,230"), @@ -79,6 +101,8 @@ object ChocolateFactoryStats { EMPTY_2(""), EMPTY_3(""), TIME_TOWER("§eTime Tower: §62/3 Charges", { ChocolateFactoryTimeTowerManager.currentCharges() != -1 }), + TIME_TO_PRESTIGE("§eTime To Prestige: §61d 13h 59m 4s", { ChocolateFactoryAPI.currentPrestige != 5 }), + RAW_PER_SECOND("§eRaw Per Second: §62,136"), ; override fun toString(): String { diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryTimeTowerManager.kt b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryTimeTowerManager.kt index 28f601b66789..55390605d4b9 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryTimeTowerManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/chocolatefactory/ChocolateFactoryTimeTowerManager.kt @@ -9,6 +9,7 @@ import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.SoundUtils import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration import kotlin.time.Duration.Companion.hours import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.seconds @@ -23,9 +24,14 @@ object ChocolateFactoryTimeTowerManager { @SubscribeEvent fun onSecondPassed(event: SecondPassedEvent) { if (!LorenzUtils.inSkyBlock) return - if (ChocolateFactoryAPI.inChocolateFactory) return val profileStorage = profileStorage ?: return + if (SimpleTimeMark(profileStorage.currentTimeTowerEnds).isInPast()) { + profileStorage.currentTimeTowerEnds = SimpleTimeMark.farPast().toMillis() + } + + if (ChocolateFactoryAPI.inChocolateFactory) return + val nextCharge = SimpleTimeMark(profileStorage.nextTimeTower) if (nextCharge.isInPast() && !nextCharge.isFarPast() && currentCharges() < maxCharges()) { @@ -82,7 +88,14 @@ object ChocolateFactoryTimeTowerManager { return profileStorage?.maxTimeTowerUses ?: 3 } - private fun timeTowerFull() = currentCharges() >= maxCharges() + fun timeTowerFull() = currentCharges() >= maxCharges() + + fun timeTowerActive() = profileStorage?.currentTimeTowerEnds != 0L + + fun timeTowerActiveDuration(): Duration { + if (!timeTowerActive()) return Duration.ZERO + return SimpleTimeMark(profileStorage?.currentTimeTowerEnds ?: 0).timeUntil() + } @SubscribeEvent fun onProfileChange(event: ProfileJoinEvent) {