diff options
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/features/garden')
27 files changed, 502 insertions, 195 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/CropType.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/CropType.kt index 084c8d9e9..3bb3534e3 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/CropType.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/CropType.kt @@ -39,7 +39,7 @@ enum class CropType( return entries.firstOrNull { it.cropName == itemName } } - fun getByName(name: String) = getByNameOrNull(name) ?: throw RuntimeException("No valid crop type '$name'") + fun getByName(name: String) = getByNameOrNull(name) ?: error("No valid crop type '$name'") fun IBlockState.getCropType(): CropType? { return when (block) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/FarmingFortuneDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/FarmingFortuneDisplay.kt index d2c1b2c4d..4a45ed901 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/FarmingFortuneDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/FarmingFortuneDisplay.kt @@ -49,7 +49,7 @@ class FarmingFortuneDisplay { } @SubscribeEvent(priority = EventPriority.LOW) - fun onInventoryUpdate(event: OwnInventorItemUpdateEvent) { + fun onInventoryUpdate(event: OwnInventoryItemUpdateEvent) { if (!GardenAPI.inGarden()) return if (event.itemStack.getCropType() == null) return updateToolFortune(event.itemStack) diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt index 05e407781..d7469416f 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt @@ -38,6 +38,13 @@ object GardenAPI { private var inBarn = false val onBarnPlot get() = inBarn && inGarden() val config get() = ProfileStorageData.profileSpecific?.garden + var gardenExp: Long? + get() = config?.experience + set(value) { + value?.let { + config?.experience = it + } + } private val barnArea = AxisAlignedBB(35.5, 70.0, -4.5, -32.5, 100.0, -46.5) @@ -203,7 +210,8 @@ object GardenAPI { return 0 } - fun getLevelForExp(gardenExp: Long): Int { + fun getGardenLevel(): Int { + val gardenExp = this.gardenExp ?: return 0 var tier = 0 var totalExp = 0L for (tierExp in gardenExperience) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenLevelDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenLevelDisplay.kt index 38e1c319e..09b86deba 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenLevelDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenLevelDisplay.kt @@ -13,19 +13,14 @@ import at.hannibal2.skyhanni.utils.RenderUtils.renderString import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher import at.hannibal2.skyhanni.utils.StringUtils.removeColor import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -import kotlin.math.roundToInt +import kotlin.math.roundToLong import kotlin.time.Duration.Companion.milliseconds class GardenLevelDisplay { private val config get() = SkyHanniMod.feature.garden - private val expToNextLevelPattern = "(?:.*) §e(?<nextLevelExp>.*)§6\\/(?:.*)".toPattern() + private val expToNextLevelPattern = ".* §e(?<nextLevelExp>.*)§6/.*".toPattern() private val overflowPattern = ".*§r §6(?<overflow>.*) XP".toPattern() private val namePattern = "Garden Level (?<currentLevel>.*)".toPattern() - private var gardenExp - get() = GardenAPI.config?.experience ?: -1 - set(value) { - GardenAPI.config?.experience = value - } private var display = "" private var visitorRewardPattern = " {4}§r§8\\+§r§2(?<exp>.*) §r§7Garden Experience".toPattern() @@ -44,15 +39,17 @@ class GardenLevelDisplay { } private fun addExp(moreExp: Int) { - val oldLevel = GardenAPI.getLevelForExp(gardenExp.toLong()) - gardenExp += moreExp - val newLevel = GardenAPI.getLevelForExp(gardenExp.toLong()) + val gardenExp = GardenAPI.gardenExp ?: return + val oldLevel = GardenAPI.getGardenLevel() + GardenAPI.gardenExp = gardenExp + moreExp + val newLevel = GardenAPI.getGardenLevel() if (newLevel == oldLevel + 1) { if (newLevel > 15) { LorenzUtils.runDelayed(50.milliseconds) { - LorenzUtils.chat( + LorenzUtils.clickableChat( " \n§b§lGARDEN LEVEL UP §8$oldLevel ➜ §b$newLevel\n" + - " §8+§aRespect from Elite Farmers and SkyHanni members :)\n " + " §8+§aRespect from Elite Farmers and SkyHanni members :)\n ", + "/gardenlevels" ) } } @@ -68,20 +65,20 @@ class GardenLevelDisplay { namePattern.matchMatcher(item.name!!.removeColor()) { val currentLevel = group("currentLevel").romanToDecimalIfNeeded() - var nextLevelExp = 0 + var nextLevelExp = 0L for (line in item.getLore()) { expToNextLevelPattern.matchMatcher(line) { - nextLevelExp = group("nextLevelExp").replace(",", "").toDouble().roundToInt() + nextLevelExp = group("nextLevelExp").replace(",", "").toDouble().roundToLong() } overflowPattern.matchMatcher(line) { - val overflow = group("overflow").replace(",", "").toDouble().roundToInt() - gardenExp = overflow + val overflow = group("overflow").replace(",", "").toDouble().roundToLong() + GardenAPI.gardenExp = overflow update() return } } val expForLevel = GardenAPI.getExpForLevel(currentLevel).toInt() - gardenExp = expForLevel + nextLevelExp + GardenAPI.gardenExp = expForLevel + nextLevelExp update() } } @@ -91,8 +88,8 @@ class GardenLevelDisplay { } private fun drawDisplay(): String { - if (gardenExp == -1) return "§aGarden Level ? §cOpen the desk!" - val currentLevel = GardenAPI.getLevelForExp(gardenExp.toLong()) + val gardenExp = GardenAPI.gardenExp ?: return "§aGarden Level ? §cOpen the desk!" + val currentLevel = GardenAPI.getGardenLevel() val needForLevel = GardenAPI.getExpForLevel(currentLevel).toInt() val nextLevel = currentLevel + 1 val needForNextLevel = GardenAPI.getExpForLevel(nextLevel).toInt() diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt index 9ec766953..1c02e4cc8 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt @@ -29,6 +29,7 @@ import javax.swing.JButton import javax.swing.JFrame import javax.swing.JOptionPane import javax.swing.UIManager +import kotlin.time.Duration.Companion.seconds object GardenNextJacobContest { private var display = emptyList<Any>() @@ -314,7 +315,7 @@ object GardenNextJacobContest { val cropText = crops.joinToString("§7, ") { "§a${it.cropName}" } LorenzUtils.chat("§e[SkyHanni] Next farming contest: $cropText") - TitleUtils.sendTitle("§eFarming Contest!", 5_000) + TitleUtils.sendTitle("§eFarming Contest!", 5.seconds) SoundUtils.playBeepSound() if (config.nextJacobContestWarnPopup && !Display.isActive()) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenOptimalSpeed.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenOptimalSpeed.kt index 6f5e9abe0..71ac8b321 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenOptimalSpeed.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenOptimalSpeed.kt @@ -16,6 +16,7 @@ import net.minecraft.client.gui.inventory.GuiEditSign import net.minecraftforge.client.event.GuiOpenEvent import net.minecraftforge.client.event.GuiScreenEvent.DrawScreenEvent import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration.Companion.seconds class GardenOptimalSpeed { private val config get() = SkyHanniMod.feature.garden @@ -100,7 +101,7 @@ class GardenOptimalSpeed { if (System.currentTimeMillis() < lastWarnTime + 20_000) return lastWarnTime = System.currentTimeMillis() - TitleUtils.sendTitle("§cWrong speed!", 3_000) + TitleUtils.sendTitle("§cWrong speed!", 3.seconds) cropInHand?.let { LorenzUtils.chat("§e[SkyHanni] Wrong speed for ${it.cropName}: §f$currentSpeed §e(§f$optimalSpeed §eis optimal)") } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenPlotBorders.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenPlotBorders.kt new file mode 100644 index 000000000..00d3461e3 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenPlotBorders.kt @@ -0,0 +1,120 @@ +package at.hannibal2.skyhanni.features.garden + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.LorenzTickEvent +import at.hannibal2.skyhanni.utils.LorenzColor +import at.hannibal2.skyhanni.utils.LorenzVec +import at.hannibal2.skyhanni.utils.RenderUtils.draw3DLine +import net.minecraft.client.Minecraft +import net.minecraftforge.client.event.RenderWorldLastEvent +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import org.lwjgl.input.Keyboard +import java.awt.Color +import kotlin.math.floor + +class GardenPlotBorders { + + private val config get() = SkyHanniMod.feature.garden.plotBorders + private var showBorders = false + private val LINE_COLOR = LorenzColor.YELLOW.toColor() + + private fun LorenzVec.addX(x: Int) = add(x, 0, 0) + private fun LorenzVec.addZ(z: Int) = add(0, 0, z) + private fun LorenzVec.addXZ(x: Int, z: Int) = add(x, 0, z) + + @SubscribeEvent + fun onTick(event: LorenzTickEvent) { + if (!isEnabled()) return + + val keyPressed = if (Keyboard.getEventKey() == 0) Keyboard.getEventCharacter() else Keyboard.getEventKey() + + if (keyPressed == Keyboard.KEY_G && Keyboard.isKeyDown(Keyboard.KEY_F3)) { + showBorders = !showBorders + } + } + + @SubscribeEvent + fun render(event: RenderWorldLastEvent) { + if (!isEnabled()) return + if (!showBorders) return + + val entity = Minecraft.getMinecraft().renderViewEntity + + // Lowest point in garden + val minHeight = 66 + val maxHeight = 256 + + // These don't refer to Minecraft chunks but rather garden plots, but I use + // the word chunk as the logic closely represents how chunk borders are rendered in latter mc versions + val chunkX = floor((entity.posX + 48) / 96).toInt() + val chunkZ = floor((entity.posZ + 48) / 96).toInt() + val chunkMinX = (chunkX * 96) - 48 + val chunkMinZ = (chunkZ * 96) - 48 + + // Render 4 vertical corners + for (i in 0..96 step 96) { + for (j in 0..96 step 96) { + val start = LorenzVec(chunkMinX + i, minHeight, chunkMinZ + j) + val end = LorenzVec(chunkMinX + i, maxHeight, chunkMinZ + j) + event.tryDraw3DLine(start, end, LorenzColor.DARK_BLUE.toColor(), 2, true) + } + } + + // Render vertical on X-Axis + for (x in 4..<96 step 4) { + val start = LorenzVec(chunkMinX + x, minHeight, chunkMinZ) + val end = LorenzVec(chunkMinX + x, maxHeight, chunkMinZ) + // Front lines + event.tryDraw3DLine(start, end, LINE_COLOR, 1, true) + // Back lines + event.tryDraw3DLine(start.addZ(96), end.addZ(96), LINE_COLOR, 1, true) + } + + // Render vertical on Z-Axis + for (z in 4..<96 step 4) { + val start = LorenzVec(chunkMinX, minHeight, chunkMinZ + z) + val end = LorenzVec(chunkMinX, maxHeight, chunkMinZ + z) + // Left lines + event.tryDraw3DLine(start, end, LINE_COLOR, 1, true) + // Right lines + event.tryDraw3DLine(start.addX(96), end.addX(96), LINE_COLOR, 1, true) + } + + // Render horizontal + for (y in minHeight..maxHeight step 4) { + val start = LorenzVec(chunkMinX, y, chunkMinZ) + // (minX, minZ) -> (minX, minZ + 96) + event.tryDraw3DLine(start, start.addZ(96), LINE_COLOR, 1, true) + // (minX, minZ + 96) -> (minX + 96, minZ + 96) + event.tryDraw3DLine(start.addZ(96), start.addXZ(96, 96), LINE_COLOR, 1, true) + // (minX + 96, minZ + 96) -> (minX + 96, minZ) + event.tryDraw3DLine(start.addXZ(96, 96), start.addX(96), LINE_COLOR, 1, true) + // (minX + 96, minZ) -> (minX, minZ) + event.tryDraw3DLine(start.addX(96), start, LINE_COLOR, 1, true) + } + } + + private fun RenderWorldLastEvent.tryDraw3DLine( + p1: LorenzVec, + p2: LorenzVec, + color: Color, + lineWidth: Int, + depth: Boolean + ) { + if (isOutOfBorders(p1)) return + if (isOutOfBorders(p2)) return + draw3DLine(p1, p2, color, lineWidth, depth) + } + + + private fun isOutOfBorders(location: LorenzVec) = when { + location.x > 240 -> true + location.x < -240 -> true + location.z > 240 -> true + location.z < -240 -> true + + else -> false + } + + fun isEnabled() = GardenAPI.inGarden() && config +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/ToolTooltipTweaks.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/ToolTooltipTweaks.kt index 759f9f0ec..e0931cd4c 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/ToolTooltipTweaks.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/ToolTooltipTweaks.kt @@ -104,9 +104,7 @@ class ToolTooltipTweaks { if (removingFarmhandDescription) { iterator.remove() removingFarmhandDescription = line != "§5§o" - } - - if (removingCounterDescription && !line.startsWith("§5§o§7You have")) { + } else if (removingCounterDescription && !line.startsWith("§5§o§7You have")) { iterator.remove() } else { removingCounterDescription = false diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterDisplay.kt index 38132e8b6..aab3b082b 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterDisplay.kt @@ -14,7 +14,9 @@ import at.hannibal2.skyhanni.utils.TimeUtils import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import java.util.* import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds import kotlin.time.DurationUnit +import kotlin.math.floor class ComposterDisplay { private val config get() = SkyHanniMod.feature.garden @@ -68,8 +70,8 @@ class ComposterDisplay { val organicMatterRequired = ComposterAPI.organicMatterRequiredPer(null) val fuelRequired = ComposterAPI.fuelRequiredPer(null) - val organicMatterRemaining = organicMatter / organicMatterRequired - val fuelRemaining = fuel / fuelRequired + val organicMatterRemaining = floor(organicMatter / organicMatterRequired) + val fuelRemaining = floor(fuel / fuelRequired) val endOfOrganicMatter = timePerCompost * organicMatterRemaining val endOfFuel = timePerCompost * fuelRemaining @@ -142,7 +144,7 @@ class ComposterDisplay { if (ComposterAPI.getOrganicMatter() <= config.composterNotifyLowOrganicMatter) { if (System.currentTimeMillis() >= hidden.informedAboutLowMatter) { if (config.composterNotifyLowTitle) { - TitleUtils.sendTitle("§cYour Organic Matter is low", 4_000) + TitleUtils.sendTitle("§cYour Organic Matter is low", 4.seconds) } LorenzUtils.chat("§e[SkyHanni] §cYour Organic Matter is low!") hidden.informedAboutLowMatter = System.currentTimeMillis() + 60_000 * 5 @@ -153,7 +155,7 @@ class ComposterDisplay { System.currentTimeMillis() >= hidden.informedAboutLowFuel ) { if (config.composterNotifyLowTitle) { - TitleUtils.sendTitle("§cYour Fuel is low", 4_000) + TitleUtils.sendTitle("§cYour Fuel is low", 4.seconds) } LorenzUtils.chat("§e[SkyHanni] §cYour Fuel is low!") hidden.informedAboutLowFuel = System.currentTimeMillis() + 60_000 * 5 @@ -203,6 +205,6 @@ class ComposterDisplay { if (System.currentTimeMillis() < storage.lastComposterEmptyWarningTime + 1000 * 60 * 2) return storage.lastComposterEmptyWarningTime = System.currentTimeMillis() LorenzUtils.chat("§e[SkyHanni] $warningMessage") - TitleUtils.sendTitle("§eComposter Warning!", 3_000) + TitleUtils.sendTitle("§eComposter Warning!", 3.seconds) } }
\ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterOverlay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterOverlay.kt index 66c7b2c41..e86d4124a 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterOverlay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterOverlay.kt @@ -201,9 +201,9 @@ class ComposterOverlay { val matterPer = ComposterAPI.organicMatterRequiredPer(null) val matterPerPreview = ComposterAPI.organicMatterRequiredPer(upgrade) - val matterMaxDuration = ComposterAPI.timePerCompost(null) * (maxOrganicMatter / matterPer) + val matterMaxDuration = ComposterAPI.timePerCompost(null) * floor(maxOrganicMatter / matterPer) val matterMaxDurationPreview = - ComposterAPI.timePerCompost(upgrade) * (maxOrganicMatterPreview / matterPerPreview) + ComposterAPI.timePerCompost(upgrade) * floor(maxOrganicMatterPreview / matterPerPreview) var format = formatTime(matterMaxDuration) var formatPreview = @@ -217,9 +217,9 @@ class ComposterOverlay { val fuelRequiredPer = ComposterAPI.fuelRequiredPer(null) val fuelRequiredPerPreview = ComposterAPI.fuelRequiredPer(upgrade) - val fuelMaxDuration = ComposterAPI.timePerCompost(null) * (maxFuel / fuelRequiredPer) + val fuelMaxDuration = ComposterAPI.timePerCompost(null) * floor(maxFuel / fuelRequiredPer) val fuelMaxDurationPreview = - ComposterAPI.timePerCompost(upgrade) * (maxFuelPreview / fuelRequiredPerPreview) + ComposterAPI.timePerCompost(upgrade) * floor(maxFuelPreview / fuelRequiredPerPreview) format = formatTime(fuelMaxDuration) formatPreview = @@ -350,8 +350,8 @@ class ComposterOverlay { val priceCompost = getPrice("COMPOST") - val profit = (priceCompost - (fuelPricePer + organicMatterPricePer)) * multiplier - val profitPreview = (priceCompost - (fuelPricePerPreview + organicMatterPricePerPreview)) * multiplierPreview + val profit = ((priceCompost * multiDropFactor) - (fuelPricePer + organicMatterPricePer)) * timeMultiplier + val profitPreview = ((priceCompost * multiDropFactorPreview) - (fuelPricePerPreview + organicMatterPricePerPreview)) * timeMultiplierPreview val profitFormatPreview = if (profit != profitPreview) " §c➜ §6" + NumberUtil.format(profitPreview) else "" val profitFormat = " §7Profit per $timeText: §6${NumberUtil.format(profit)}$profitFormatPreview" diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobContestTimeNeeded.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobContestTimeNeeded.kt index 7b0f01015..cf304c0db 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobContestTimeNeeded.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobContestTimeNeeded.kt @@ -35,64 +35,7 @@ class JacobContestTimeNeeded { val sorted = mutableMapOf<CropType, Double>() val map = mutableMapOf<CropType, Renderable>() for (crop in CropType.entries) { - val speed = crop.getSpeed() - if (speed == null) { - sorted[crop] = Double.MAX_VALUE - map[crop] = Renderable.hoverTips( - "§9${crop.cropName} §cNo speed data!", - listOf("§cFarm ${crop.cropName} to show data!") - ) - continue - } - - val averages = FarmingContestAPI.calculateAverages(crop).second - if (averages.isEmpty()) { - sorted[crop] = Double.MAX_VALUE - 2 - map[crop] = Renderable.hoverTips( - "§9${crop.cropName} §cNo contest data!", - listOf( - "§cOpen more pages or participate", - "§cin a ${crop.cropName} Contest to show data!" - ) - ) - continue - } - var showLine = "" - val brackets = mutableListOf<String>() - for ((bracket, amount) in averages) { - val timeInMinutes = amount.toDouble() / speed / 60 - val formatDuration = TimeUtils.formatDuration((timeInMinutes * 60 * 1000).toLong()) - val color = if (timeInMinutes < 20) "§b" else "§c" - val line: String - var bracketText = "${bracket.displayName} $color$formatDuration" - if (timeInMinutes < 20) { - line = "§9${crop.cropName} §b$formatDuration" - } else { - line = - "§9${crop.cropName} §cNo ${currentBracket.displayName} §cMedal!" - val cropFF = crop.getLatestTrueFarmingFortune() ?: 0.0 - val blocksPerSecond = crop.getLatestBlocksPerSecond() ?: 20.0 - val cropsPerSecond = amount.toDouble() / blocksPerSecond / 60 - val ffNeeded = cropsPerSecond * 100 / 20 / crop.baseDrops - val missing = (ffNeeded - cropFF).toInt() - bracketText += " §7(${missing.addSeparators()} more FF needed!)" - } - brackets.add(bracketText) - if (bracket == currentBracket) { - sorted[crop] = timeInMinutes - showLine = line - } - } - map[crop] = Renderable.hoverTips(showLine, buildList { - add("§7Time Needed for §9${crop.cropName} Medals§7:") - addAll(brackets) - add("") - val latestFF = crop.getLatestTrueFarmingFortune() ?: 0.0 - add("§7Latest FF: §e${(latestFF).addSeparators()}") - val bps = crop.getLatestBlocksPerSecond()?.round(1) ?: 0 - add("§7Blocks/Second: §e${bps.addSeparators()}") - - }) + testCrop(crop, sorted, map) } this.display = buildList { @@ -115,6 +58,104 @@ class JacobContestTimeNeeded { } } + private fun testCrop( + crop: CropType, + sorted: MutableMap<CropType, Double>, + map: MutableMap<CropType, Renderable> + ) { + val speed = crop.getSpeed() + if (speed == null) { + sorted[crop] = Double.MAX_VALUE + map[crop] = Renderable.hoverTips( + "§9${crop.cropName} §cNo speed data!", + listOf("§cFarm ${crop.cropName} to show data!") + ) + return + } + + val averages = FarmingContestAPI.calculateAverages(crop).second + if (averages.isEmpty()) { + sorted[crop] = Double.MAX_VALUE - 2 + map[crop] = Renderable.hoverTips( + "§9${crop.cropName} §cNo contest data!", + listOf( + "§cOpen more pages or participate", + "§cin a ${crop.cropName} Contest to show data!" + ) + ) + return + } + + renderCrop(speed, crop, averages, sorted, map) + } + + private fun renderCrop( + speed: Int, + crop: CropType, + averages: Map<ContestBracket, Int>, + sorted: MutableMap<CropType, Double>, + map: MutableMap<CropType, Renderable> + ) { + var lowBPSWarning = listOf<String>() + val rawSpeed = speed.toDouble() + val speedForFormular = crop.getLatestBlocksPerSecond()?.let { + if (it < 15) { + val v = rawSpeed / it + (v * 19.9).toInt() + } else speed + } ?: speed + var showLine = "" + val brackets = mutableListOf<String>() + for ((bracket, amount) in averages) { + val timeInMinutes = amount.toDouble() / speedForFormular / 60 + val formatDuration = TimeUtils.formatDuration((timeInMinutes * 60 * 1000).toLong()) + val color = if (timeInMinutes < 20) "§b" else "§c" + var marking = "" + var bracketText = "${bracket.displayName} $color$formatDuration" + var blocksPerSecond = crop.getLatestBlocksPerSecond() + if (blocksPerSecond == null) { + marking += "§0§l !" //hoping this never shows + blocksPerSecond = 19.9 + lowBPSWarning = listOf("§cYour Blocks/second is too low,", "§cshowing 19.9 Blocks/second instead!") + } else { + if (blocksPerSecond < 15.0) { + marking += "§4§l !" + blocksPerSecond = 19.9 + lowBPSWarning = + listOf("§cYour Blocks/second is too low,", "§cshowing 19.9 Blocks/second instead!") + } else { + marking += " " + lowBPSWarning = listOf("§aYour Blocks/second is good :)") + } + } + val line = if (timeInMinutes < 20) { + "§9${crop.cropName} §b$formatDuration" + marking + } else { + val cropFF = crop.getLatestTrueFarmingFortune() ?: 0.0 + val cropsPerSecond = amount.toDouble() / blocksPerSecond / 60 + val ffNeeded = cropsPerSecond * 100 / 20 / crop.baseDrops + val missing = (ffNeeded - cropFF).toInt() + bracketText += " §7(${missing.addSeparators()} more FF needed!)" + "§9${crop.cropName} §cNo ${currentBracket.displayName} §cMedal!" + marking + } + brackets.add(bracketText) + if (bracket == currentBracket) { + sorted[crop] = timeInMinutes + showLine = line + } + } + map[crop] = Renderable.hoverTips(showLine, buildList { + add("§7Time Needed for §9${crop.cropName} Medals§7:") + addAll(brackets) + add("") + val latestFF = crop.getLatestTrueFarmingFortune() ?: 0.0 + add("§7Latest FF: §e${(latestFF).addSeparators()}") + val bps = crop.getLatestBlocksPerSecond()?.round(1) ?: 0 + add("§7Blocks/Second: §e${bps.addSeparators()}") + addAll(lowBPSWarning) + }) + } + @SubscribeEvent fun onRenderOverlay(event: GuiRenderEvent.ChestBackgroundRenderEvent) { if (!isEnabled()) return diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobFarmingContestsInventory.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobFarmingContestsInventory.kt index 61bd56198..29333d205 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobFarmingContestsInventory.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobFarmingContestsInventory.kt |
