diff options
| author | Roman / Linnea Gräf <nea@nea.moe> | 2023-03-19 17:58:54 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-19 17:58:54 +0100 |
| commit | 86d6cc6bf29172fb13ed6aab2ca0676631336da9 (patch) | |
| tree | d5e0fc0aa6a556c44f497d818f36e674a0f2e317 /src/main/java/at/hannibal2/skyhanni/features/garden | |
| parent | 4d3e68e8777ac174b938ad63c3367a20e99e06ac (diff) | |
| parent | 6913b635b9d20cc6736aef64bad9f5d517a2f644 (diff) | |
| download | SkyHanni-yaw_snapping.tar.gz SkyHanni-yaw_snapping.tar.bz2 SkyHanni-yaw_snapping.zip | |
Merge branch 'beta' into yaw_snappingyaw_snapping
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/features/garden')
15 files changed, 1016 insertions, 186 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/CropMoneyDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/CropMoneyDisplay.kt new file mode 100644 index 000000000..8af8bf742 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/CropMoneyDisplay.kt @@ -0,0 +1,171 @@ +package at.hannibal2.skyhanni.features.garden + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.GardenToolChangeEvent +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.features.bazaar.BazaarApi +import at.hannibal2.skyhanni.utils.ItemUtils.name +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzUtils.sortedDesc +import at.hannibal2.skyhanni.utils.NEUItems +import at.hannibal2.skyhanni.utils.RenderUtils.renderStringsAndItems +import at.hannibal2.skyhanni.utils.StringUtils.removeColor +import io.github.moulberry.notenoughupdates.NotEnoughUpdates +import kotlinx.coroutines.launch +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import net.minecraftforge.fml.common.gameevent.TickEvent +import java.util.* + +class CropMoneyDisplay { + private val display = mutableListOf<List<Any>>() + private val config get() = SkyHanniMod.feature.garden + private var tick = 0 + private var loaded = false + private var ready = false + private val multipliers = mutableMapOf<String, Int>() + private val cropNames = mutableMapOf<String, String>() // internalName -> cropName + private var hasCropInHand = false + + @SubscribeEvent + fun onRenderOverlay(event: GuiRenderEvent.GameOverlayRenderEvent) { + if (!isEnabled()) return + + config.moneyPerHourPos.renderStringsAndItems(display) + } + + @SubscribeEvent + fun onGardenToolChange(event: GardenToolChangeEvent) { + val crop = if (event.isRealCrop) event.crop else null + hasCropInHand = crop != null + update() + } + + @SubscribeEvent + fun onTick(event: TickEvent.ClientTickEvent) { + if (!isEnabled()) return + if (tick++ % (20 * 5) != 0) return + if (!hasCropInHand && !config.moneyPerHourAlwaysOn) return + + update() + } + + private fun update() { + init() + + val newDisplay = drawNewDisplay() + display.clear() + display.addAll(newDisplay) + } + + private fun drawNewDisplay(): MutableList<List<Any>> { + val newDisplay = mutableListOf<List<Any>>() + + if (!ready) { + newDisplay.add(Collections.singletonList("§7Money per hour when selling:")) + newDisplay.add(Collections.singletonList("§eLoading...")) + return newDisplay + } + + if (!hasCropInHand && !config.moneyPerHourAlwaysOn) return newDisplay + + newDisplay.add(Collections.singletonList("§7Money per hour when selling:")) + + var number = 0 + val map = calculateMoneyPerHour() + if (map.isEmpty()) { + newDisplay.add(Collections.singletonList("§cFarm crops to add them to this list!")) + } else { + for ((internalName, moneyPerHour) in map.sortedDesc()) { + number++ + val cropName = cropNames[internalName] + val isCurrent = cropName == GardenAPI.cropInHand + if (number > config.moneyPerHourShowOnlyBest && !isCurrent) continue + + val list = mutableListOf<Any>() + list.add("§7$number# ") + + try { + val itemStack = NEUItems.getItemStack(internalName) + list.add(itemStack) + } catch (e: NullPointerException) { + e.printStackTrace() + } + val format = LorenzUtils.formatInteger(moneyPerHour.toLong()) + val itemName = NEUItems.getItemStack(internalName).name?.removeColor() ?: continue + val color = if (isCurrent) "§e" else "§7" + list.add("$color$itemName§7: §6$format") + + newDisplay.add(list) + } + } + + return newDisplay + } + + private fun calculateMoneyPerHour(): MutableMap<String, Double> { + val moneyPerHours = mutableMapOf<String, Double>() + for ((internalName, amount) in multipliers) { + val price = NEUItems.getPrice(internalName) + val cropName = cropNames[internalName]!! + val speed = GardenAPI.getCropsPerSecond(cropName)!! + + // No speed data for item in hand + if (speed == -1) continue + + // Price not found + if (price == -1.0) continue + + val speedPerHr = speed.toDouble() * 60 * 60 + val blocksPerHour = speedPerHr / amount.toDouble() + val moneyPerHour = price * blocksPerHour + moneyPerHours[internalName] = moneyPerHour + } + return moneyPerHours + } + + private fun init() { + if (loaded) return + + if (BazaarApi.bazaarMap.isEmpty()) { + LorenzUtils.debug("bz not ready for money/time!") + return + } + + loaded = true + + SkyHanniMod.coroutineScope.launch { + val crops = listOf( + "Wheat", + "Carrot", + "Potato", + "Pumpkin", + "Sugar Cane", + "Melon", + "Cactus", + "Cocoa Beans", + "Mushroom", + "Nether Wart", + ) + + for ((internalName, _) in NotEnoughUpdates.INSTANCE.manager.itemInformation) { + if (!BazaarApi.isBazaarItem(internalName)) continue + if (internalName == "ENCHANTED_PAPER") continue + + val (newId, amount) = NEUItems.getMultiplier(internalName) + if (amount < 10) continue + val itemName = NEUItems.getItemStack(newId).name?.removeColor() ?: continue + val cropName = GardenAPI.itemNameToCropName(itemName) + if (crops.contains(cropName)) { + multipliers[internalName] = amount + cropNames[internalName] = cropName + } + } + + + ready = true + update() + } + } + + private fun isEnabled() = GardenAPI.inGarden() && config.moneyPerHourDisplay +}
\ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/DicerRngDropCounter.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/DicerRngDropCounter.kt new file mode 100644 index 000000000..8547f4d51 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/DicerRngDropCounter.kt @@ -0,0 +1,130 @@ +package at.hannibal2.skyhanni.features.garden + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.ConfigLoadEvent +import at.hannibal2.skyhanni.events.GardenToolChangeEvent +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.utils.ItemUtils.name +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzUtils.sortedDesc +import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +class DicerRngDropCounter { + private val display = mutableListOf<String>() + private val drops = mutableMapOf<String, MutableMap<DropRarity, Int>>() + private val itemDrops = mutableListOf<ItemDrop>() + + init { + drops["Melon"] = mutableMapOf() + drops["Pumpkin"] = mutableMapOf() + + itemDrops.add(ItemDrop("Melon", DropRarity.UNCOMMON, "§a§lUNCOMMON DROP! §r§eDicer dropped §r§a1x §r§aEnchanted Melon§r§e!")) + itemDrops.add(ItemDrop("Melon", DropRarity.RARE, "§9§lRARE DROP! §r§eDicer dropped §r§a5x §r§aEnchanted Melon§r§e!")) + itemDrops.add(ItemDrop("Melon", DropRarity.CRAZY_RARE, "§d§lCRAZY RARE DROP! §r§eDicer dropped §r§a50x §r§aEnchanted Melon§r§e!")) + itemDrops.add(ItemDrop("Melon", DropRarity.PRAY_TO_RNGESUS, "§5§lPRAY TO RNGESUS DROP! §r§eDicer dropped §r§92x §r§9Enchanted Melon Block§r§e!")) + + itemDrops.add(ItemDrop("Pumpkin", DropRarity.UNCOMMON, "§a§lUNCOMMON DROP! §r§eDicer dropped §r§f64x §r§fPumpkin§r§e!")) + itemDrops.add(ItemDrop("Pumpkin", DropRarity.RARE, "§9§lRARE DROP! §r§eDicer dropped §r§a1x §r§aEnchanted Pumpkin§r§e!")) + itemDrops.add(ItemDrop("Pumpkin", DropRarity.CRAZY_RARE, "§d§lCRAZY RARE DROP! §r§eDicer dropped §r§a10x §r§aEnchanted Pumpkin§r§e!")) + itemDrops.add(ItemDrop("Pumpkin", DropRarity.PRAY_TO_RNGESUS, "§5§lPRAY TO RNGESUS DROP! §r§eDicer dropped §r§a64x §r§aEnchanted Pumpkin§r§e!")) + } + + enum class DropRarity(val displayName: String) { + UNCOMMON("§a§lUNCOMMON DROP"), + RARE("§9§lRARE DROP"), + CRAZY_RARE("§d§lCRAZY RARE DROP"), + PRAY_TO_RNGESUS("§5§lPRAY TO RNGESUS DROP"), + } + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + if (!isEnabled()) return + + val message = event.message + for (drop in itemDrops) { + if (message == drop.message) { + addDrop(drop.itemName, drop.rarity) + saveConfig() + update() + return + } + } + + if (message.contains("§r§eDicer dropped")) { + LorenzUtils.debug("Unknown dicer drop message!") + println("Unknown dicer drop message: '$message'") + } + } + + private fun update() { + val newDisplay = drawDisplay() + display.clear() + display.addAll(newDisplay) + } + + private fun drawDisplay(): List<String> { + val help = mutableListOf<String>() + val items = drops[itemInHand] ?: return help + help.add("§7RNG Drops for $toolname§7:") + for ((rarity, amount) in items.sortedDesc()) { + val displayName = rarity.displayName + help.add(" §7- §e${amount}x $displayName") + } + + return help + } + + private var itemInHand = "" + private var toolname = "" + + @SubscribeEvent + fun onGardenToolChange(event: GardenToolChangeEvent) { + val crop = event.crop + itemInHand = if (crop == "Melon" || crop == "Pumpkin") crop else "" + if (itemInHand != "") { + toolname = event.heldItem!!.name!! + } + update() + } + + private fun addDrop(item: String, rarity: DropRarity) { + val map = drops[item]!! + val old = map[rarity] ?: 0 + map[rarity] = old + 1 + } + + @SubscribeEvent + fun onRenderOverlay(event: GuiRenderEvent.GameOverlayRenderEvent) { + if (isEnabled()) { + SkyHanniMod.feature.garden.dicerCounterPos.renderStrings(display) + } + } + + class ItemDrop(val itemName: String, val rarity: DropRarity, val message: String) + + private fun saveConfig() { + val list = SkyHanniMod.feature.hidden.gardenDicerRngDrops + list.clear() + for (drop in drops) { + val itemName = drop.key + for ((rarity, amount) in drop.value) { + list[itemName + "." + rarity.name] = amount + } + } + } + + @SubscribeEvent + fun onConfigLoad(event: ConfigLoadEvent) { + for ((internalName, amount) in SkyHanniMod.feature.hidden.gardenDicerRngDrops) { + val split = internalName.split(".") + val itemName = split[0] + val rarityName = split[1] + val rarity = DropRarity.valueOf(rarityName) + drops[itemName]!![rarity] = amount + } + } + + fun isEnabled() = GardenAPI.inGarden() && SkyHanniMod.feature.garden.dicerCounterDisplay +}
\ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/EliteFarmingWeight.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/EliteFarmingWeight.kt new file mode 100644 index 000000000..6676f4f77 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/EliteFarmingWeight.kt @@ -0,0 +1,235 @@ +package at.hannibal2.skyhanni.features.garden + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.CollectionAPI +import at.hannibal2.skyhanni.data.HyPixelData +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.ProfileApiDataLoadedEvent +import at.hannibal2.skyhanni.events.ProfileJoinEvent +import at.hannibal2.skyhanni.utils.APIUtil +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzUtils.round +import at.hannibal2.skyhanni.utils.RenderUtils.renderString +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import net.minecraft.client.Minecraft +import net.minecraftforge.event.world.WorldEvent +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import net.minecraftforge.fml.common.gameevent.TickEvent + +class EliteFarmingWeight { + + @SubscribeEvent + fun onProfileDataLoad(event: ProfileApiDataLoadedEvent) { + // This is still not perfect, but it's definitely better than other alternatives for the moment. + extraCollection.clear() + dirtyCropWeight = true + } + + @SubscribeEvent + fun onRenderOverlay(event: GuiRenderEvent.GameOverlayRenderEvent) { + if (isEnabled()) { + config.eliteFarmingWeightPos.renderString(display) + } + } + + @SubscribeEvent + fun onWorldChange(event: WorldEvent.Load) { + // We want to try to connect to the api again after a world switch. + apiError = false + } + + var tick = 0 + + @SubscribeEvent + fun onTick(event: TickEvent.ClientTickEvent) { + if (tick++ % 5 != 0) return + update() + } + + @SubscribeEvent + fun onProfileJoin(event: ProfileJoinEvent) { + // Supporting profile switches + leaderboardPosition = -1 + bonusWeight = -1 + dirtyCropWeight = true + lastLeaderboardUpdate = 0 + } + + companion object { + private val config get() = SkyHanniMod.feature.garden + private val extraCollection = mutableMapOf<String, Long>() + + private var display = "" + private var profileId = "" + private var lastLeaderboardUpdate = 0L + private var apiError = false + private var leaderboardPosition = -1 + private var bonusWeight = -2 + private var cropWeight = 0.0 + private var dirtyCropWeight = false + private var isLoadingWeight = false + private var isLoadingLeaderboard = false + + private fun update() { + if (!GardenAPI.inGarden()) return + if (apiError) { + display = "§6Farming Weight§7: §cAPI Error!" + return + } + if (bonusWeight == -2) { + display = "§6Farming Weight§7: §eLoading.." + return + } + + if (bonusWeight == -1) { + if (!isLoadingWeight) { + isLoadingWeight = true + SkyHanniMod.coroutineScope.launch { + loadBonusWeight() + isLoadingWeight = false + } + } + return + } + + val weight = getWeight() + val leaderboard = getLeaderboard() + display = "§6Farming Weight§7: $weight$leaderboard" + } + + private fun getLeaderboard(): String { + if (!config.eliteFarmingWeightLeaderboard) return "" + + // Fetching new leaderboard position every 10 minutes + if (System.currentTimeMillis() > lastLeaderboardUpdate + 600_000) { + if (!isLoadingLeaderboard) { + isLoadingLeaderboard = true + SkyHanniMod.coroutineScope.launch { + leaderboardPosition = loadLeaderboardPosition() + lastLeaderboardUpdate = System.currentTimeMillis() + isLoadingLeaderboard = false + } + } + } + + return if (leaderboardPosition != -1) { + val format = LorenzUtils.formatInteger(leaderboardPosition) + " §7[§b#$format§7]" + } else { + if (isLoadingLeaderboard) { + " §7[§b#?§7]" + } else { + "" + } + } + } + + private fun getWeight(): String { + if (dirtyCropWeight) { + val values = calculateCollectionWeight().values + if (values.isNotEmpty()) { + cropWeight = values.sum() + dirtyCropWeight = false + } + } + + val totalWeight = (cropWeight + bonusWeight) + return "§e" + LorenzUtils.formatDouble(totalWeight, 2) + } + + private fun isEnabled() = GardenAPI.inGarden() && config.eliteFarmingWeightDisplay + + fun addCrop(crop: String, diff: Int) { + val old = extraCollection[crop] ?: 0L + extraCollection[crop] = old + diff + dirtyCropWeight = true + } + + private suspend fun loadLeaderboardPosition() = try { + val uuid = Minecraft.getMinecraft().thePlayer.uniqueID.toString().replace("-", "") + val url = "https://elitebot.dev/api/leaderboard/rank/weight/farming/$uuid/$profileId" + val result = withContext(Dispatchers.IO) { APIUtil.getJSONResponse(url) }.asJsonObject + + result["rank"].asInt + } catch (e: Exception) { + apiError = true + LorenzUtils.error("[SkyHanni] Failed to load farming weight data from elitebot.dev! please report this on discord!") + e.printStackTrace() + -1 + } + + private suspend fun loadBonusWeight() { + val uuid = Minecraft.getMinecraft().thePlayer.uniqueID.toString().replace("-", "") + val url = "https://elitebot.dev/api/weight/$uuid" + try { + val result = withContext(Dispatchers.IO) { APIUtil.getJSONResponse(url) }.asJsonObject + val localProfile = HyPixelData.profileName + for (profileEntry in result["profiles"].asJsonObject.entrySet()) { + val profile = profileEntry.value.asJsonObject + val profileName = profile["cute_name"].asString.lowercase() + if (profileName == localProfile) { + profileId = profileEntry.key + bonusWeight = profile["farming"].asJsonObject["bonus"].asInt + return + } + } + println("url: '$url'") + println("result: '$result'") + } catch (e: Exception) { + println("url: '$url'") + e.printStackTrace() + } + apiError = true + LorenzUtils.error("[SkyHanni] Failed to load farming weight data from elitebot.dev! please report this on discord!") + } + + private fun calculateCollectionWeight(): MutableMap<String, Double> { + val weightPerCrop = mutableMapOf<String, Double>() + var totalWeight = 0.0 + for ((cropName, factor) in factorPerCrop) { + val collection = getCollection(cropName) + val weight = (collection / factor).round(2) + weightPerCrop[cropName] = weight + totalWeight += weight + } + if (totalWeight > 0) { + weightPerCrop["Mushroom"] = specialMushroomWeight(weightPerCrop, totalWeight) + } + return weightPerCrop + } + + private fun specialMushroomWeight(weightPerCrop: MutableMap<String, Double>, totalWeight: Double): Double { + val cactusWeight = weightPerCrop["Cactus"]!! + val sugarCaneWeight = weightPerCrop["Sugar Cane"]!! + val doubleBreakRatio = (cactusWeight + sugarCaneWeight) / totalWeight; + val normalRatio = (totalWeight - cactusWeight - sugarCaneWeight) / totalWeight; + + val mushroomFactor = factorPerCrop["Mushroom"]!! + val mushroomCollection = getCollection("Mushroom") + return doubleBreakRatio * (mushroomCollection / (2 * mushroomFactor)) + normalRatio * (mushroomCollection / mushroomFactor) + } + + private fun getCollection(cropName: String): Double { + val real = CollectionAPI.getCollectionCounter(cropName)?.second ?: 0L + val extra = (extraCollection[cropName] ?: 0L) + return (real + extra).toDouble() + } + + private val factorPerCrop by lazy { + mapOf( + "wheat" to 100_000.0, + "Carrot" to 300_000.0, + "Potato" to 300_000.0, + "Sugar Cane" to 200_000.0, + "Nether Wart" to 250_000.0, + "Pumpkin" to 87_095.11, + "Melon" to 435_466.47, + "Mushroom" to 168_925.53, + "Cocoa Beans" to 257_214.64, + "Cactus" to 169_389.33, + ) + } + } +}
\ No newline at end of file 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 a8f8e84a8..37d2e1f18 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt @@ -1,62 +1,97 @@ package at.hannibal2.skyhanni.features.garden +import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.data.GardenCropMilestones import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.events.GardenToolChangeEvent -import at.hannibal2.skyhanni.utils.ItemUtils.name +import at.hannibal2.skyhanni.events.GuiContainerEvent +import at.hannibal2.skyhanni.events.PacketEvent +import at.hannibal2.skyhanni.events.ProfileJoinEvent +import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName import at.hannibal2.skyhanni.utils.LorenzUtils import net.minecraft.client.Minecraft import net.minecraft.item.ItemStack +import net.minecraft.network.play.client.C09PacketHeldItemChange +import net.minecraftforge.fml.common.eventhandler.EventPriority import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import net.minecraftforge.fml.common.gameevent.TickEvent class GardenAPI { - var tick = 0 @SubscribeEvent + fun onSendPacket(event: PacketEvent.SendEvent) { + if (!inGarden()) return + if (event.packet !is C09PacketHeldItemChange) return + checkItemInHand() + } + + @SubscribeEvent + fun onCloseWindow(event: GuiContainerEvent.CloseWindowEvent) { + if (!inGarden()) return + checkItemInHand() + } + + @SubscribeEvent fun onTick(event: TickEvent.ClientTickEvent) { if (event.phase != TickEvent.Phase.START) return if (!inGarden()) return - if (tick++ % 5 != 0) return + if (tick++ % 10 != 0) return + + // We ignore random hypixel moments + Minecraft.getMinecraft().currentScreen ?: return + checkItemInHand() + } - val crop = loadCropInHand() + private fun checkItemInHand() { + val heldItem = Minecraft.getMinecraft().thePlayer.heldItem + val crop = loadCropInHand(heldItem) if (cropInHand != crop) { cropInHand = crop - GardenToolChangeEvent().postAndCatch() + GardenToolChangeEvent(crop, heldItem).postAndCatch() + } + } + + @SubscribeEvent(priority = EventPriority.LOW) + fun onProfileJoin(event: ProfileJoinEvent) { + if (cropsPerSecond.isEmpty()) { + // TODO use enum + for (key in GardenCropMilestones.cropCounter.keys) { + cropsPerSecond[key] = -1 + } } } - private fun loadCropInHand(): String? { - val heldItem = Minecraft.getMinecraft().thePlayer.heldItem ?: return null - if (readCounter(heldItem) == -1) return null - return getCropTypeFromItem(heldItem) + private fun loadCropInHand(heldItem: ItemStack?): String? { + if (heldItem == null) return null + return getCropTypeFromItem(heldItem, true) } companion object { - // TODO use everywhere instead of IslandType.GARDEN fun inGarden() = LorenzUtils.inSkyBlock && LorenzUtils.skyBlockIsland == IslandType.GARDEN var cropInHand: String? = null + val cropsPerSecond: MutableMap<String, Int> get() = SkyHanniMod.feature.hidden.gardenCropsPerSecond - fun getCropTypeFromItem(heldItem: ItemStack): String? { - val name = heldItem.name ?: return null - return getCropTypeFromItem(name) - } + fun getCropTypeFromItem(item: ItemStack, withDaedalus: Boolean = false): String? { + val internalName = item.getInternalName() - fun getCropTypeFromItem(itemName: String): String? { - for ((crop, _) in GardenCropMilestones.cropCounter) { - if (itemName.contains(crop)) { - return crop - } - } - if (itemName.contains("Coco Chopper")) { - return "Cocoa Beans" - } - if (itemName.contains("Fungi Cutter")) { - return "Mushroom" + return when { + internalName.startsWith("THEORETICAL_HOE_WHEAT") -> "Wheat" + internalName.startsWith("THEORETICAL_HOE_CARROT") -> "Carrot" + internalName.startsWith("THEORETICAL_HOE_POTATO") -> "Potato" + internalName.startsWith("PUMPKIN_DICER") -> "Pumpkin" + internalName.startsWith("THEORETICAL_HOE_CANE") -> "Sugar Cane" + internalName.startsWith("MELON_DICER") -> "Melon" + internalName == "CACTUS_KNIFE" -> "Cactus" + internalName == "COCO_CHOPPER" -> "Cocoa Beans" + internalName == "FUNGI_CUTTER" -> "Mushroom" + internalName.startsWith("THEORETICAL_HOE_WARTS") -> "Nether Wart" + + internalName.startsWith("DAEDALUS_AXE") && withDaedalus -> "Daedalus Axe" + + else -> null } - return null } fun readCounter(itemStack: ItemStack): Int { @@ -76,5 +111,16 @@ class GardenAPI { } return -1 } + + fun getCropsPerSecond(itemName: String): Int? { + return cropsPerSecond[itemNameToCropName(itemName)] + } + + fun itemNameToCropName(itemName: String): String { + if (itemName == "Red Mushroom" || itemName == "Brown Mushroom") { + return "Mushroom" + } + return itemName + } } }
\ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenBestCropTime.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenBestCropTime.kt new file mode 100644 index 000000000..bea64af34 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenBestCropTime.kt @@ -0,0 +1,84 @@ +package at.hannibal2.skyhanni.features.garden + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.GardenCropMilestones +import at.hannibal2.skyhanni.utils.LorenzUtils.sorted +import at.hannibal2.skyhanni.utils.TimeUtils +import java.util.* + +class GardenBestCropTime { + val display = mutableListOf<List<Any>>() + val timeTillNextCrop = mutableMapOf<String, Long>() + private val config get() = SkyHanniMod.feature.garden + + fun drawBestDisplay(currentCrop: String?) { + if (timeTillNextCrop.size < GardenAPI.cropsPerSecond.size) { + updateTimeTillNextCrop() + } + + val gardenExp = config.cropMilestoneBestType == 0 + val sorted = if (gardenExp) { + val helpMap = mutableMapOf<String, Long>() + for ((cropName, time) in timeTillNextCrop) { + val crops = GardenCropMilestones.cropCounter[cropName]!! + val currentTier = GardenCropMilestones.getTierForCrops(crops) + val gardenExpForTier = getGardenExpForTier(currentTier + 1) + val fakeTime = time / gardenExpForTier + helpMap[cropName] = fakeTime + } + helpMap.sorted() + } else { + timeTillNextCrop.sorted() + } + + val title = if (gardenExp) "§2Garden Experience" else "§bSkyBlock Level" + display.add(Collections.singletonList("§eBest Crop Time §7($title§7)")) + + if (sorted.isEmpty()) { + display.add(Collections.singletonList("§cFarm crops to add them to this list!")) + } + + var number = 0 + for (cropName in sorted.keys) { + val millis = timeTillNextCrop[cropName]!! + val duration = TimeUtils.formatDuration(millis) + + val isCurrent = cropName == currentCrop + val color = if (isCurrent) "§e" else "" + number++ + if (number > config.cropMilestoneShowOnlyBest && !isCurrent) continue + val cropNameDisplay = "§7$number# $color$cropName" + if (gardenExp) { + val crops = GardenCropMilestones.cropCounter[cropName]!! + val currentTier = GardenCropMilestones.getTierForCrops(crops) + val gardenExpForTier = getGardenExpForTier(currentTier + 1) + display.add(Collections.singletonList("$cropNameDisplay §b$duration §7(§2$gardenExpForTier §7Exp)")) + } else { + display.add(Collections.singletonList("$cropNameDisplay §b$duration")) + } + } + } + + private fun getGardenExpForTier(gardenLevel: Int) = if (gardenLevel > 30) 300 else gardenLevel * 10 + + fun updateTimeTillNextCrop() { + for ((cropName, speed) in GardenAPI.cropsPerSecond) { + if (speed == -1) continue + + val crops = GardenCropMilestones.cropCounter[cropName]!! + val currentTier = GardenCropMilestones.getTierForCrops(crops) + + |
