diff options
author | Thunderblade73 <85900443+Thunderblade73@users.noreply.github.com> | 2024-06-05 15:39:55 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-05 15:39:55 +0200 |
commit | 5a04ad230cc4fb94884b34f795124d3b65af07ea (patch) | |
tree | cace8dcaad1c989be42a52bff4a6da233642279f | |
parent | eb4ab6eaafa17581df58a53fb4111fa96933d230 (diff) | |
download | skyhanni-5a04ad230cc4fb94884b34f795124d3b65af07ea.tar.gz skyhanni-5a04ad230cc4fb94884b34f795124d3b65af07ea.tar.bz2 skyhanni-5a04ad230cc4fb94884b34f795124d3b65af07ea.zip |
Improvement: Refactor of /ff for Improved Modularity and Code Reusability (#873)
Co-authored-by: Cal <cwolfson58@gmail.com>
31 files changed, 1553 insertions, 1350 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt index 4f5f0aa50..fdedfdbab 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 = 47 + const val CONFIG_VERSION = 48 fun JsonElement.at(chain: List<String>, init: Boolean): JsonElement? { if (chain.isEmpty()) return this if (this !is JsonObject) return null 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 bd6cc8efe..89980d349 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt @@ -371,17 +371,11 @@ object Commands { "Disables/enables the rendering of all skyhanni guis." ) { SkyHanniDebugsAndTests.toggleRender() } registerCommand( - "shcarrot", - "Toggles receiving the 12 fortune from carrots" - ) { CaptureFarmingGear.reverseCarrotFortune() } - registerCommand( - "shpumpkin", - "Toggles receiving the 12 fortune from pumpkins" - ) { CaptureFarmingGear.reversePumpkinFortune() } - registerCommand( - "shcocoabeans", - "Toggles receiving the 12 fortune from cocoa beans" - ) { CaptureFarmingGear.reverseCocoaBeansFortune() } + "shcarrolyn", + "Toggels if the specified crops effect is active from carrolyn" + ) { + CaptureFarmingGear.handelCarrolyn(it) + } registerCommand( "shrepostatus", "Shows the status of all the mods constants" 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 d88ccb315..cbdc90978 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java +++ b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java @@ -373,13 +373,7 @@ public class ProfileSpecificStorage { public long cakeExpiring = -1L; @Expose - public boolean carrotFortune = false; - - @Expose - public boolean pumpkinFortune = false; - - @Expose - public boolean cocoaBeansFortune = false; + public Map<CropType, Boolean> carrolyn = new HashMap<>(); @Expose public Map<FarmingItems, ItemStack> farmingItems = new HashMap<>(); diff --git a/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/TabComplete.kt b/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/TabComplete.kt index 49bde5993..87130298c 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/TabComplete.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/TabComplete.kt @@ -3,6 +3,7 @@ package at.hannibal2.skyhanni.features.commands.tabcomplete import at.hannibal2.skyhanni.events.TabCompletionEvent import at.hannibal2.skyhanni.features.commands.PartyCommands import at.hannibal2.skyhanni.features.commands.ViewRecipeCommand +import at.hannibal2.skyhanni.features.garden.fortuneguide.CarrolynTable import at.hannibal2.skyhanni.features.misc.CollectionTracker import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @@ -28,6 +29,7 @@ object TabComplete { CollectionTracker.handleTabComplete(command)?.let { return it } PartyCommands.customTabComplete(command)?.let { return it } ViewRecipeCommand.customTabComplete(command)?.let { return it } + CarrolynTable.customTabComplete(command)?.let { return it } return null } 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 b7480f259..3a661161e 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/CropType.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/CropType.kt @@ -1,5 +1,6 @@ package at.hannibal2.skyhanni.features.garden +import at.hannibal2.skyhanni.features.garden.fortuneguide.FarmingItems import net.minecraft.block.state.IBlockState import net.minecraft.init.Blocks import net.minecraft.init.Items @@ -13,48 +14,49 @@ enum class CropType( val baseDrops: Double, iconSupplier: () -> ItemStack, val simpleName: String, + val farmingItem: FarmingItems, val replenish: Boolean = false, ) { WHEAT( "Wheat", "THEORETICAL_HOE_WHEAT", "CROPIE", 1.0, - { ItemStack(Items.wheat) }, "wheat" + { ItemStack(Items.wheat) }, "wheat", FarmingItems.WHEAT ), CARROT( "Carrot", "THEORETICAL_HOE_CARROT", "CROPIE", 3.0, - { ItemStack(Items.carrot) }, "carrot", replenish = true + { ItemStack(Items.carrot) }, "carrot", FarmingItems.CARROT, replenish = true ), POTATO( "Potato", "THEORETICAL_HOE_POTATO", "CROPIE", 3.0, - { ItemStack(Items.potato) }, "potato", replenish = true + { ItemStack(Items.potato) }, "potato", FarmingItems.POTATO, replenish = true ), NETHER_WART( "Nether Wart", "THEORETICAL_HOE_WARTS", "FERMENTO", 2.5, - { ItemStack(Items.nether_wart) }, "wart", replenish = true + { ItemStack(Items.nether_wart) }, "wart", FarmingItems.NETHER_WART, replenish = true ), PUMPKIN( "Pumpkin", "PUMPKIN_DICER", "SQUASH", 1.0, - { ItemStack(Blocks.pumpkin) }, "pumpkin" + { ItemStack(Blocks.pumpkin) }, "pumpkin", FarmingItems.PUMPKIN ), MELON( "Melon", "MELON_DICER", "SQUASH", 5.0, - { ItemStack(Items.melon) }, "melon" + { ItemStack(Items.melon) }, "melon", FarmingItems.MELON ), COCOA_BEANS( "Cocoa Beans", "COCO_CHOPPER", "SQUASH", 3.0, - { ItemStack(Items.dye, 1, EnumDyeColor.BROWN.dyeDamage) }, "cocoa", replenish = true + { ItemStack(Items.dye, 1, EnumDyeColor.BROWN.dyeDamage) }, "cocoa", FarmingItems.COCOA_BEANS, replenish = true ), SUGAR_CANE( "Sugar Cane", "THEORETICAL_HOE_CANE", "FERMENTO", 2.0, - { ItemStack(Items.reeds) }, "cane" + { ItemStack(Items.reeds) }, "cane", FarmingItems.SUGAR_CANE ), CACTUS( "Cactus", "CACTUS_KNIFE", "FERMENTO", 2.0, - { ItemStack(Blocks.cactus) }, "cactus" + { ItemStack(Blocks.cactus) }, "cactus", FarmingItems.CACTUS ), MUSHROOM( "Mushroom", "FUNGI_CUTTER", "FERMENTO", 1.0, - { ItemStack(Blocks.red_mushroom_block) }, "mushroom" + { ItemStack(Blocks.red_mushroom_block) }, "mushroom", FarmingItems.MUSHROOM ), ; @@ -64,6 +66,9 @@ enum class CropType( override fun toString(): String = cropName + val patternKeyName = name.lowercase().replace('_', '.') + val niceName = name.lowercase().replace('_', ' ') + companion object { fun getByNameOrNull(itemName: String): CropType? { 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 0d75c9325..41ea1aa71 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/FarmingFortuneDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/FarmingFortuneDisplay.kt @@ -345,7 +345,8 @@ object FarmingFortuneDisplay { // TODO code cleanup (after ff rework) - for (line in tool?.getLore()!!) { + val lore = tool?.getLore() ?: return + for (line in lore) { tooltipFortunePattern.matchMatcher(line) { displayedFortune = group("display")?.toDouble() ?: 0.0 reforgeFortune = groupOrNull("reforge")?.toDouble() ?: 0.0 diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/FarmingWeightDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/FarmingWeightDisplay.kt index 6f8523c34..0aac3e747 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/FarmingWeightDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/FarmingWeightDisplay.kt @@ -192,8 +192,9 @@ class FarmingWeightDisplay { list.add( Renderable.clickAndHover( "§6Farming Weight§7: $weight$leaderboard", - listOf("§eClick to open your Farming Profile."), - onClick = { openWebsite(LorenzUtils.getPlayerName()) } + listOf("§eClick to open your Farming Profile."), onClick = { + openWebsite(LorenzUtils.getPlayerName()) + } ) ) diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/CaptureFarmingGear.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/CaptureFarmingGear.kt index 55e756780..158d1309e 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/CaptureFarmingGear.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/CaptureFarmingGear.kt @@ -1,17 +1,21 @@ package at.hannibal2.skyhanni.features.garden.fortuneguide +import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.config.storage.ProfileSpecificStorage import at.hannibal2.skyhanni.data.PetAPI import at.hannibal2.skyhanni.data.ProfileStorageData import at.hannibal2.skyhanni.events.GardenToolChangeEvent import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.features.garden.CropType import at.hannibal2.skyhanni.features.garden.FarmingFortuneDisplay import at.hannibal2.skyhanni.features.garden.GardenAPI import at.hannibal2.skyhanni.features.garden.GardenAPI.getCropType import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.ItemCategory import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName +import at.hannibal2.skyhanni.utils.ItemUtils.getItemCategoryOrNull import at.hannibal2.skyhanni.utils.ItemUtils.getItemRarityOrNull import at.hannibal2.skyhanni.utils.ItemUtils.getLore import at.hannibal2.skyhanni.utils.LorenzUtils @@ -29,7 +33,6 @@ import kotlin.math.round import kotlin.time.Duration.Companion.days object CaptureFarmingGear { - private val farmingItems get() = GardenAPI.storage?.fortune?.farmingItems private val outdatedItems get() = GardenAPI.storage?.fortune?.outdatedItems private val patternGroup = RepoPattern.group("garden.fortuneguide.capture") @@ -80,9 +83,24 @@ object CaptureFarmingGear { "RANCHERS", "FARMER", "RABBIT" ) + init { + CarrolynTable.entries.forEach { + it.completeMessagePattern + it.thxMessagePattern + } + } + // TODO upadte armor on equpment/wardeobe update as well fun captureFarmingGear() { - val farmingItems = farmingItems ?: return + for (armor in InventoryUtils.getArmor()) { + if (armor == null) continue + val split = armor.getInternalName().asString().split("_") + if (split.first() in farmingSets) { + val category = armor.getItemCategoryOrNull() ?: continue + FarmingItems.getFromItemCategoryOne(category)?.setItem(armor) + } + } + val itemStack = InventoryUtils.getItemInHand() ?: return val currentCrop = itemStack.getCropType() @@ -91,22 +109,7 @@ object CaptureFarmingGear { //todo better fall back items //todo Daedalus axe } else { - for (item in FarmingItems.entries) { - if (item.name == currentCrop.name) { - farmingItems[item] = itemStack - } - } - } - for (armor in InventoryUtils.getArmor()) { - if (armor == null) continue - val split = armor.getInternalName().asString().split("_") - if (split.first() in farmingSets) { - for (item in FarmingItems.entries) { - if (item.name == split.last()) { - farmingItems[item] = armor - } - } - } + currentCrop.farmingItem.setItem(itemStack) } TabListData.getTabList().matchFirst(strengthPattern) { @@ -114,22 +117,13 @@ object CaptureFarmingGear { } } - fun reverseCarrotFortune() { - val storage = GardenAPI.storage?.fortune ?: return - storage.carrotFortune = !storage.carrotFortune - ChatUtils.chat("Toggled exportable carrot fortune to: ${storage.carrotFortune}") - } - - fun reversePumpkinFortune() { - val storage = GardenAPI.storage?.fortune ?: return - storage.pumpkinFortune = !storage.pumpkinFortune - ChatUtils.chat("Toggled expired pumpkin fortune to: ${storage.pumpkinFortune}") - } - - fun reverseCocoaBeansFortune() { - val storage = GardenAPI.storage?.fortune ?: return - storage.cocoaBeansFortune = !storage.cocoaBeansFortune - ChatUtils.chat("Toggled supreme chocolate bar fortune to: ${storage.cocoaBeansFortune}") + fun handelCarrolyn(input: Array<String>) { + val string = input.joinToString("_").uppercase() + val crop = CropType.entries.firstOrNull { it.name == string } + ?: ChatUtils.userError("Invalid Argument, no crop with the name: $string").run { return } + val carrolyn = CarrolynTable.getByCrop(crop) + ?: ChatUtils.userError("Invalid Argument, crop is not valid").run { return } + carrolyn.setVisibleActive(!carrolyn.get()) } private fun getUniqueVisitorsForTier(tier: Int): Int { @@ -151,15 +145,14 @@ object CaptureFarmingGear { fun onInventoryOpen(event: InventoryFullyOpenedEvent) { if (!LorenzUtils.inSkyBlock) return val storage = GardenAPI.storage?.fortune ?: return - val farmingItems = farmingItems ?: return val outdatedItems = outdatedItems ?: return val items = event.inventoryItems if (PetAPI.isPetMenu(event.inventoryName)) { - pets(farmingItems, items, outdatedItems) + pets(items, outdatedItems) return } when (event.inventoryName) { - "Your Equipment and Stats" -> equipmentAndStats(items, farmingItems, outdatedItems) + "Your Equipment and Stats" -> equipmentAndStats(items, outdatedItems) "Your Skills" -> skills(items, storage) "Community Shop" -> communityShop(items) "Configure Plots" -> configurePlots(items, storage) @@ -248,69 +241,54 @@ object CaptureFarmingGear { } private fun pets( - farmingItems: MutableMap<FarmingItems, ItemStack>, items: Map<Int, ItemStack>, outdatedItems: MutableMap<FarmingItems, Boolean>, ) { // If they've 2 of same pet, one will be overwritten - // optimize - - for (pet in listOf( - FarmingItems.ELEPHANT, - FarmingItems.MOOSHROOM_COW, - FarmingItems.RABBIT, - FarmingItems.BEE - )) { - if (farmingItems[pet] == null) { - farmingItems[pet] = FFGuideGUI.getFallbackItem(pet) - } - } // setting to current saved level -1 to stop later pages saving low rarity pets - var highestElephantRarity = (farmingItems[FarmingItems.ELEPHANT]?.getItemRarityOrNull()?.id ?: -1) - 1 - var highestMooshroomRarity = (farmingItems[FarmingItems.MOOSHROOM_COW]?.getItemRarityOrNull()?.id ?: -1) - 1 - var highestRabbitRarity = (farmingItems[FarmingItems.RABBIT]?.getItemRarityOrNull()?.id ?: -1) - 1 - var highestBeeRarity = (farmingItems[FarmingItems.BEE]?.getItemRarityOrNull()?.id ?: -1) - 1 + var highestElephantRarity = (FarmingItems.ELEPHANT.getItemOrNull()?.getItemRarityOrNull()?.id ?: -1) - 1 + var highestMooshroomRarity = (FarmingItems.MOOSHROOM_COW.getItemOrNull()?.getItemRarityOrNull()?.id ?: -1) - 1 + var highestRabbitRarity = (FarmingItems.RABBIT.getItemOrNull()?.getItemRarityOrNull()?.id ?: -1) - 1 + var highestBeeRarity = (FarmingItems.BEE.getItemOrNull()?.getItemRarityOrNull()?.id ?: -1) - 1 for ((_, item) in items) { - val split = item.getInternalName().asString().split(";") - if (split.first() == "ELEPHANT" && split.last().toInt() > highestElephantRarity) { - farmingItems[FarmingItems.ELEPHANT] = item + if (item.getItemCategoryOrNull() != ItemCategory.PET) continue + val (name, rarity) = item.getInternalName().asString().split(";") + if (name == "ELEPHANT" && rarity.toInt() > highestElephantRarity) { + FarmingItems.ELEPHANT.setItem(item) outdatedItems[FarmingItems.ELEPHANT] = false - highestElephantRarity = split.last().toInt() + highestElephantRarity = rarity.toInt() } - if (split.first() == "MOOSHROOM_COW" && split.last().toInt() > highestMooshroomRarity) { - farmingItems[FarmingItems.MOOSHROOM_COW] = item + if (name == "MOOSHROOM_COW" && rarity.toInt() > highestMooshroomRarity) { + FarmingItems.MOOSHROOM_COW.setItem(item) outdatedItems[FarmingItems.MOOSHROOM_COW] = false - highestMooshroomRarity = split.last().toInt() + highestMooshroomRarity = rarity.toInt() } - if (split.first() == "RABBIT" && split.last().toInt() > highestRabbitRarity) { - farmingItems[FarmingItems.RABBIT] = item + if (name == "RABBIT" && rarity.toInt() > highestRabbitRarity) { + FarmingItems.RABBIT.setItem(item) outdatedItems[FarmingItems.RABBIT] = false - highestRabbitRarity = split.last().toInt() + highestRabbitRarity = rarity.toInt() } - if (split.first() == "BEE" && split.last().toInt() > highestBeeRarity) { - farmingItems[FarmingItems.BEE] = item + if (name == "BEE" && rarity.toInt() > highestBeeRarity) { + FarmingItems.BEE.setItem(item) outdatedItems[FarmingItems.BEE] = false - highestBeeRarity = split.last().toInt() + highestBeeRarity = rarity.toInt() } } } private fun equipmentAndStats( items: Map<Int, ItemStack>, - farmingItems: MutableMap<FarmingItems, ItemStack>, outdatedItems: MutableMap<FarmingItems, Boolean>, ) { for ((_, slot) in items) { val split = slot.getInternalName().asString().split("_") + val category = slot.getItemCategoryOrNull() ?: continue if (split.first() == "LOTUS") { - for (item in FarmingItems.entries) { - if (item.name == split.last()) { - farmingItems[item] = slot - outdatedItems[item] = false - } - } + val item = FarmingItems.getFromItemCategoryOne(category) ?: continue + item.setItem(slot) + outdatedItems[item] = false FarmingFortuneDisplay.loadFortuneLineData(slot, 0.0) val enchantments = slot.getEnchantments() ?: emptyMap() val greenThumbLvl = (enchantments["green_thumb"] ?: continue) @@ -328,12 +306,15 @@ object CaptureFarmingGear { val msg = event.message.removeColor().trim() fortuneUpgradePattern.matchMatcher(msg) { ProfileStorageData.playerSpecific?.gardenCommunityUpgrade = group("level").romanToDecimal() + return } farmingLevelUpPattern.matchMatcher(msg) { storage.farmingLevel = group("level").romanToDecimalIfNecessary() + return } anitaBuffPattern.matchMatcher(msg) { storage.anitaUpgrade = group("level").toInt() / 4 + return } lotusUpgradePattern.matchMatcher(msg) { val piece = group("piece").uppercase() @@ -342,6 +323,7 @@ object CaptureFarmingGear { outdatedItems[item] = true } } + return } petLevelUpPattern.matchMatcher(msg) { val pet = group("pet").uppercase().replace("✦", "").trim().replace(" ", "_") @@ -350,30 +332,29 @@ object CaptureFarmingGear { outdatedItems[item] = true } } + return } cakePattern.matchMatcher(msg) { storage.cakeExpiring = System.currentTimeMillis() + 2.days.inWholeMilliseconds + return } - if (msg == "CARROTS EXPORTATION COMPLETE!") { - storage.carrotFortune = true - } - if (msg == "PUMPKINS EXPORTATION COMPLETE!") { - storage.pumpkinFortune = true - } - if (msg == "CHOCOLATE BARS EXPORTATION COMPLETE!") { - storage.cocoaBeansFortune = true - } - if (msg == "[NPC] Carrolyn: Thank you for the carrots.") { - storage.carrotFortune = true - ChatUtils.chat("§aYou have already given Carrolyn enough Exportable Carrots.") - } - if (msg == "[NPC] Carrolyn: Thank you for the pumpkins.") { - storage.pumpkinFortune = true - ChatUtils.chat("§aYou have already given Carrolyn enough Expired Pumpkins.") - } - if (msg == "[NPC] Carrolyn: Thank you for the chocolate.") { - storage.cocoaBeansFortune = true - ChatUtils.chat("§aYou have already given Carrolyn enough Supreme Chocolate Bars.") + CarrolynTable.entries.forEach { + it.completeMessagePattern.matchMatcher(msg) { + it.set(true) + return + } + it.thxMessagePattern.matchMatcher(msg) { + it.set(true) + ChatUtils.chat(it.thxResponse) + return + } } } + + @SubscribeEvent + fun onConfigUpdaterMigratorConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { + event.move(48, "#profile.garden.fortune.carrotFortune", "#profile.garden.fortune.carrolyn.CARROT") + event.move(48, "#profile.garden.fortune.pumpkinFortune", "#profile.garden.fortune.carrolyn.PUMPKIN") + event.move(48, "#profile.garden.fortune.cocoaBeansFortune", "#profile.garden.fortune.carrolyn.COCOA_BEANS") + } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/CarrolynTable.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/CarrolynTable.kt new file mode 100644 index 000000000..b7163768b --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/CarrolynTable.kt @@ -0,0 +1,58 @@ +package at.hannibal2.skyhanni.features.garden.fortuneguide + +import at.hannibal2.skyhanni.features.garden.CropType +import at.hannibal2.skyhanni.features.garden.GardenAPI +import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern + +enum class CarrolynTable(val crop: CropType, val label: String, completeMessage: String, thxMessage: String) { + EXPORTABLE_CARROTS( + CropType.CARROT, + "Exportable Carrots", + "CARROTS EXPORTATION COMPLETE!", + "[NPC] Carrolyn: Thank you for the carrots." + ), + EXPIRED_PUMPKIN( + CropType.PUMPKIN, + "Expired Pumpkin", + "PUMPKINS EXPORTATION COMPLETE!", + "[NPC] Carrolyn: Thank you for the pumpkins." + ), + SUPREME_CHOCOLATE_BAR( + CropType.COCOA_BEANS, + "Supreme Chocolate Bar", + "CHOCOLATE BARS EXPORTATION COMPLETE!", + "[NPC] Carrolyn: Thank you for the chocolate." + ), + ; + + val completeMessagePattern by RepoPattern.pattern( + "garden.ff.carrolyn.complete.${crop.patternKeyName}", completeMessage + ) + val thxMessagePattern by RepoPattern.pattern( + "garden.ff.carrolyn.thx.${crop.patternKeyName}", thxMessage + ) + + val thxResponse = "§aYou have already given Carrolyn enough $label." + + fun get() = GardenAPI.storage?.fortune?.carrolyn?.get(crop) ?: false + fun set(value: Boolean) = GardenAPI.storage?.fortune?.carrolyn?.set(crop, value) + + fun setVisibleActive(value: Boolean) { + set(value) + ChatUtils.chat("Toggled $label fortune to: ${get()}") + } + + companion object { + fun getByCrop(crop: CropType?) = if (crop == null) null else entries.firstOrNull { it.crop == crop } + + fun isCarrolynCrop(crop: CropType): Boolean = CarrolynTable.getByCrop(crop) != null + fun customTabComplete(command: String): List<String>? { + if (command == "shcarrolyn") { + return entries.map { it.crop.name } + } + + return null + } + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFGuideGUI.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFGuideGUI.kt index 0cafabd1c..ff81cae6d 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFGuideGUI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFGuideGUI.kt @@ -2,528 +2,95 @@ package at.hannibal2.skyhanni.features.garden.fortuneguide import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.features.garden.CropType -import at.hannibal2.skyhanni.features.garden.GardenAPI import at.hannibal2.skyhanni.features.garden.fortuneguide.pages.CropPage import at.hannibal2.skyhanni.features.garden.fortuneguide.pages.OverviewPage import at.hannibal2.skyhanni.features.garden.fortuneguide.pages.UpgradePage -import at.hannibal2.skyhanni.utils.ChatUtils -import at.hannibal2.skyhanni.utils.GuiRenderUtils -import at.hannibal2.skyhanni.utils.ItemUtils.name -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.OSUtils -import at.hannibal2.skyhanni.utils.SoundUtils +import at.hannibal2.skyhanni.utils.guide.GuideGUI +import at.hannibal2.skyhanni.utils.guide.GuideTab +import at.hannibal2.skyhanni.utils.renderables.Renderable import net.minecraft.client.Minecraft -import net.minecraft.client.gui.GuiScreen -import net.minecraft.client.renderer.GlStateManager import net.minecraft.init.Blocks import net.minecraft.init.Items import net.minecraft.item.ItemStack -import org.lwjgl.input.Mouse -import java.io.IOException -open class FFGuideGUI : GuiScreen() { - companion object { - - private var firefoxTrials = 0 - - fun open() { - if (LorenzUtils.isAprilFoolsDay) { - when (firefoxTrials) { - 0 -> { - ChatUtils.chat("Are you looking for the FF browser?", prefix = false) - } - - 1 -> { - ChatUtils.chat("Quickly, download Firefox! NOW!", prefix = false) - OSUtils.openBrowser("https://www.mozilla.org/en-US/firefox/new/") - } - - 2 -> { - ChatUtils.chat("Have you tried Firefix from Mozilla already?", prefix = false) - } - - 10 -> { - ChatUtils.chat("Firefox is simply the best!", prefix = false) - } - - 20 -> { - ChatUtils.chat( - "What do you mean with \"farming fortune\"? This is a web browser!", - prefix = false - ) - } - - 30 -> { - ChatUtils.chat("What are you still doing here? get Firefox!", prefix = false) - } - - else -> { - CaptureFarmingGear.captureFarmingGear() - SkyHanniMod.screenToOpen = FFGuideGUI() - } - } - firefoxTrials++ - } else { - CaptureFarmingGear.captureFarmingGear() - SkyHanniMod.screenToOpen = FFGuideGUI() - } - } - - val pages = mutableMapOf<FortuneGuidePage, FFGuidePage>() - - var guiLeft = 0 - var guiTop = 0 - var screenHeight = 0 - - const val sizeX = 360 - const val sizeY = 180 +class FFGuideGUI : GuideGUI<FFGuideGUI.FortuneGuidePage>(FortuneGuidePage.OVERVIEW) { - var selectedPage = FortuneGuidePage.OVERVIEW - var currentCrop: CropType? = null + override val sizeX = 360 + override val sizeY = 180 - // todo set this to what they have equip - var currentPet = FarmingItems.ELEPHANT - var currentArmor = 0 - var currentEquipment = 0 - - var mouseX = 0 - var mouseY = 0 - var lastMouseScroll = 0 - var noMouseScrollFrames = 0 - var lastClickedHeight = 0 - - var tooltipToDisplay = mutableListOf<String>() + companion object { fun isInGui() = Minecraft.getMinecraft().currentScreen is FFGuideGUI - fun FarmingItems.getItem(): ItemStack { - val fortune = GardenAPI.storage?.fortune ?: return getFallbackItem(this) - - val farmingItems = fortune.farmingItems - farmingItems[this]?.let { return it } - - val fallbackItem = getFallbackItem(this) - farmingItems[this] = fallbackItem - return fallbackItem + fun open() { + CaptureFarmingGear.captureFarmingGear() + SkyHanniMod.screenToOpen = FFGuideGUI() } - private val fallbackItems = mutableMapOf<FarmingItems, ItemStack>() - - fun getFallbackItem(item: FarmingItems) = fallbackItems.getOrPut(item) { - val name = "§cNo saved ${item.name.lowercase().replace("_", " ")}" - ItemStack(Blocks.barrier).setStackDisplayName(name) + fun updateDisplay() { + with(Minecraft.getMinecraft().currentScreen) { + if (this !is FFGuideGUI) return + this.refreshPage() + } } - - fun isFallbackItem(item: ItemStack) = item.name.startsWith("§cNo saved ") } + /** Value for which crop page is active */ + private var currentCrop: CropType? = null + init { FFStats.loadFFData() FortuneUpgrades.generateGenericUpgrades() - pages[FortuneGuidePage.OVERVIEW] = OverviewPage() - pages[FortuneGuidePage.CROP] = CropPage() - pages[FortuneGuidePage.UPGRADES] = UpgradePage() + FarmingItems.setDefaultPet() - if (currentCrop != null) { - for (item in FarmingItems.entries) { - if (item.name == currentCrop?.name) { - FFStats.getCropStats(currentCrop!!, item.getItem()) + pageList = mapOf( + FortuneGuidePage.OVERVIEW to OverviewPage(sizeX, sizeY), + FortuneGuidePage.CROP to CropPage({ currentCrop!! }, sizeX, sizeY), + FortuneGuidePage.UPGRADES to UpgradePage({ currentCrop }, sizeX, sizeY - 2), + ) + verticalTabs = listOf( + vTab(ItemStack(Items.gold_ingot), Renderable.string("§eBreakdown")) { + currentPage = if (currentCrop == null) FortuneGuidePage.OVERVIEW else FortuneGuidePage.CROP + }, + vTab(ItemStack(Items.map), Renderable.string("§eUpgrades")) { + currentPage = FortuneGuidePage.UPGRADES + }) + horizontalTabs = buildList { + add( + hTab(ItemStack(Blocks.grass), Renderable.string("§eOverview")) { + currentCrop = null + + it.pageSwitchHorizontal() } - } - } - } - - override fun drawScreen(unusedX: Int, unusedY: Int, partialTicks: Float) { - super.drawScreen(unusedX, unusedY, partialTicks) - drawDefaultBackground() - screenHeight = height - guiLeft = (width - sizeX) / 2 - guiTop = (height - sizeY) / 2 - - mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth - mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1 - - GlStateManager.pushMatrix() - drawRect(guiLeft, guiTop, guiLeft + sizeX, guiTop + sizeY, 0x50000000) - renderTabs() - - if (selectedPage == FortuneGuidePage.UPGRADES) { - // - } else { - GuiRenderUtils.drawStringCentered("§7SkyHanni", guiLeft + 325, guiTop + 170) - if (currentCrop == null) { - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.HELMET.getItem(), guiLeft + 142, guiTop + 5, mouseX, mouseY, - if (currentArmor == 1) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt() - ) - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.CHESTPLATE.getItem(), guiLeft + 162, guiTop + 5, mouseX, mouseY, - if (currentArmor == 2) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt() - ) - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.LEGGINGS.getItem(), guiLeft + 182, guiTop + 5, mouseX, mouseY, - if (currentArmor == 3) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt() - ) - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.BOOTS.getItem(), guiLeft + 202, guiTop + 5, mouseX, mouseY, - if (currentArmor == 4) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt() - ) + ) + for (crop in CropType.entries) { + add( + hTab(crop.icon, Renderable.string("§e${crop.cropName}")) { + currentCrop = crop - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.NECKLACE.getItem(), guiLeft + 262, guiTop + 5, mouseX, mouseY, - if (currentEquipment == 1) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt() - ) - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.CLOAK.getItem(), guiLeft + 282, guiTop + 5, mouseX, mouseY, - if (currentEquipment == 2) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt() - ) - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.BELT.getItem(), guiLeft + 302, guiTop + 5, mouseX, mouseY, - if (currentEquipment == 3) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt() - ) - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.BRACELET.getItem(), guiLeft + 322, guiTop + 5, mouseX, mouseY, - if (currentEquipment == 4) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt() - ) - - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.ELEPHANT.getItem(), guiLeft + 142, guiTop + 130, mouseX, mouseY, - if (currentPet == FarmingItems.ELEPHANT) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt() - ) - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.MOOSHROOM_COW.getItem(), guiLeft + 162, guiTop + 130, mouseX, mouseY, - if (currentPet == FarmingItems.MOOSHROOM_COW) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt() - ) - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.RABBIT.getItem(), guiLeft + 182, guiTop + 130, mouseX, mouseY, - if (currentPet == FarmingItems.RABBIT) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt() - ) - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.BEE.getItem(), guiLeft + 202, guiTop + 130, mouseX, mouseY, - if (currentPet == FarmingItems.BEE) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt() - ) - } else { - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.ELEPHANT.getItem(), guiLeft + 142, guiTop + 160, mouseX, mouseY, - if (currentPet == FarmingItems.ELEPHANT) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt() - ) - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.MOOSHROOM_COW.getItem(), guiLeft + 162, guiTop + 160, mouseX, mouseY, - if (currentPet == FarmingItems.MOOSHROOM_COW) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt() - ) - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.RABBIT.getItem(), guiLeft + 182, guiTop + 160, mouseX, mouseY, - if (currentPet == FarmingItems.RABBIT) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt() - ) - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.BEE.getItem(), guiLeft + 202, guiTop + 160, mouseX, mouseY, - if (currentPet == FarmingItems.BEE) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt() - ) - - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.HELMET.getItem(), guiLeft + 162, guiTop + 80, mouseX, mouseY - ) - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.CHESTPLATE.getItem(), guiLeft + 162, guiTop + 100, mouseX, mouseY - ) - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.LEGGINGS.getItem(), guiLeft + 162, guiTop + 120, mouseX, mouseY - ) - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.BOOTS.getItem(), guiLeft + 162, guiTop + 140, mouseX, mouseY - ) - - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.NECKLACE.getItem(), guiLeft + 182, guiTop + 80, mouseX, mouseY - ) - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.CLOAK.getItem(), guiLeft + 182, guiTop + 100, mouseX, mouseY - ) - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.BELT.getItem(), guiLeft + 182, guiTop + 120, mouseX, mouseY - ) - GuiRenderUtils.renderItemAndTip( - tooltipToDisplay, - FarmingItems.BRACELET.getItem(), guiLeft + 182, guiTop + 140, mouseX, mouseY + it.pageSwitchHorizontal() + } ) } } - pages[selectedPage]?.drawPage(mouseX, mouseY, partialTicks) + horizontalTabs.firstOrNull()?.fakeClick() + verticalTabs.firstOrNull()?.fakeClick() - GlStateManager.popMatrix() - - if (tooltipToDisplay.isNotEmpty()) { - GuiRenderUtils.drawTooltip(tooltipToDisplay, mouseX, mouseY, height) - tooltipToDisplay.clear() - } } - override fun handleMouseInput() { - super.handleMouseInput() - - if (Mouse.getEventButtonState()) { - mouseClickEvent() - } - if (!Mouse.getEventButtonState() && Mouse.getEventDWheel() != 0) { - lastMouseScroll = Mouse.getEventDWheel() - noMouseScrollFrames = 0 - } - } - - @Throws(IOException::class) - fun mouseClickEvent() { - var x = guiLeft + 15 - var y = guiTop - 28 - if (isMouseIn(x, y, 25, 28)) { - SoundUtils.playClickSound() - if (currentCrop != null) { - currentCrop = null - if (selectedPage != FortuneGuidePage.UPGRADES) { - selectedPage = FortuneGuidePage.OVERVIEW - } - } else { - if (selectedPage == FortuneGuidePage.UPGRADES) { - selectedPage = FortuneGuidePage.OVERVIEW - } else { - selectedPage = FortuneGuidePage.UPGRADES - } - } - } - for (crop in CropType.entries) { - x += 30 - if (isMouseIn(x, y, 25, 28)) { - SoundUtils.playClickSound() - if (currentCrop != crop) { - currentCrop = crop - if (selectedPage == FortuneGuidePage.OVERVIEW) { - selectedPage = FortuneGuidePage.CROP - } - for (item in FarmingItems.entries) { - if (item.name == crop.name) { - FFStats.getCropStats(crop, item.getItem()) - FortuneUpgrades.getCropSpecific(item.getItem()) - } - } - } else { - if (selectedPage == FortuneGuidePage.CROP) { - selectedPage = FortuneGuidePage.UPGRADES - for (item in FarmingItems.entries) { - if (item.name == crop.name) { - FortuneUpgrades.getCropSpecific(item.getItem()) - } - } - } else { - selectedPage = FortuneGuidePage.CROP - for (item in FarmingItems.entries) { - if (item.name == crop.name) { - FFStats.getCropStats(crop, item.getItem()) - } - } - } - } - } - } - - x = guiLeft - 28 - y = guiTop + 15 - if (isMouseIn(x, y, 28, 25) && - selectedPage != FortuneGuidePage.CROP && selectedPage != FortuneGuidePage.OVERVIEW - ) { - SoundUtils.playClickSound() - selectedPage = if (currentCrop == null) { - FortuneGuidePage.OVERVIEW - } else { - FortuneGuidePage.CROP - } - } - y += 30 - if (isMouseIn(x, y, 28, 25) && selectedPage != FortuneGuidePage.UPGRADES) { - selectedPage = FortuneGuidePage.UPGRADES - SoundUtils.playClickSound() - } - - if (selectedPage != FortuneGuidePage.UPGRADES) { - if (currentCrop == null) { - when { - isMouseInRect(guiLeft + 142, guiTop + 130) && currentPet != FarmingItems.ELEPHANT -> { - SoundUtils.playClickSound() - currentPet = FarmingItems.ELEPHANT - FFStats.getTotalFF() - } - - isMouseInRect(guiLeft + 162, guiTop + 130) && currentPet != FarmingItems.MOOSHROOM_COW -> { - SoundUtils.playClickSound() - currentPet = FarmingItems.MOOSHROOM_COW - FFStats.getTotalFF() - } - - isMouseInRect(guiLeft + 182, guiTop + 130) && currentPet != FarmingItems.RABBIT -> { - SoundUtils.playClickSound() - currentPet = FarmingItems.RABBIT - FFStats.getTotalFF() - } - - isMouseInRect(guiLeft + 202, guiTop + 130) && currentPet != FarmingItems.BEE -> { - SoundUtils.playClickSound() - currentPet = FarmingItems.BEE - FFStats.getTotalFF() - } - - isMouseInRect(guiLeft + 142, guiTop + 5) -> { - SoundUtils.playClickSound() - currentArmor = if (currentArmor == 1) 0 else 1 - } - - isMouseInRect(guiLeft + 162, guiTop + 5) -> { - SoundUtils.playClickSound() - currentArmor = if (currentArmor == 2) 0 else 2 - } - - isMouseInRect(guiLeft + 182, guiTop + 5) -> { - SoundUtils.playClickSound() - currentArmor = if (currentArmor == 3) 0 else 3 - } - - isMouseInRect(guiLeft + 202, guiTop + 5) -> { - SoundUtils.playClickSound() - currentArmor = if (currentArmor == 4) 0 else 4 - } - - isMouseInRect(guiLeft + 262, guiTop + 5) -> { - SoundUtils.playClickSound() - currentEquipment = if (currentEquipment == 1) 0 else 1 - } - - isMouseInRect(guiLeft + 282, guiTop + 5) -> { - SoundUtils.playClickSound() - currentEquipment = if (currentEquipment == 2) 0 else 2 - } - - isMouseInRect(guiLeft + 302, guiTop + 5) -> { - SoundUtils.playClickSound() - currentEquipment = if (currentEquipment == 3) 0 else 3 - } - - isMouseInRect(guiLeft + 322, guiTop + 5) -> { - SoundUtils.playClickSound() - currentEquipment = if (currentEquipment == 4) 0 else 4 - } - } - } else { - when { - isMouseInRect(guiLeft + 142, guiTop + 160) && currentPet != FarmingItems.ELEPHANT -> { - SoundUtils.playClickSound() - currentPet = FarmingItems.ELEPHANT - FFStats.getTotalFF() - } - - isMouseInRect(guiLeft + 162, guiTop + 160) && currentPet != FarmingItems.MOOSHROOM_COW -> { - SoundUtils.playClickSound() - currentPet = FarmingItems.MOOSHROOM_COW - FFStats.getTotalFF() - } - - isMouseInRect(guiLeft + 182, guiTop + 160) && currentPet != FarmingItems.RABBIT -> { - SoundUtils.playClickSound() - currentPet = FarmingItems.RABBIT - FFStats.getTotalFF() - } - - isMouseInRect(guiLeft + 202, guiTop + 160) && currentPet != FarmingItems.BEE -> { - SoundUtils.playClickSound() - currentPet = FarmingItems.BEE - FFStats.getTotalFF() - } - } - } + private fun GuideTab.pageSwitchHorizontal() { + if (isSelected()) { + verticalTabs.first { it != lastVerticalTabWrapper.tab }.fakeClick() // Double Click Logic } else { - if (isMouseIn(guiLeft, guiTop, sizeX, sizeY)) { - lastClickedHeight = mouseY - } - } - } - - private fun isMouseInRect(left: Int, top: Int) = isMouseIn(left, top, 16, 16) - - private fun isMouseIn(x: Int, y: Int, width: Int, height: Int) = - GuiRenderUtils.isPointInRect(mouseX, mouseY, x, y, width, height) - - private fun renderTabs() { - var x = guiLeft + 15 - var y = guiTop - 28 - val selectedColor = 0x50000000 - val notSelectedColor = 0x50303030 - drawRect(x, y, x + 25, y + 28, if (currentCrop == null) selectedColor else notSelectedColor) - GuiRenderUtils.renderItemStack(ItemStack(Blocks.grass), x + 5, y + 5) - if (isMouseIn(x, y, 25, 28)) { - tooltipToDisplay.add("§eOverview") - } - - for (crop in CropType.entries) { - x += 30 - drawRect(x, y, x + 25, y + 28, if (currentCrop == crop) selectedColor else notSelectedColor) - GuiRenderUtils.renderItemStack(crop.icon, x + 5, y + 5) - if (isMouseIn(x, y, 25, 28)) { - tooltipToDisplay.add("§e${crop.cropName}") - } - } - - x = guiLeft - 28 - y = guiTop + 15 - - drawRect( - x, y, - x + 28, y + 25, - if (selectedPage != FortuneGuidePage.UPGRADES) selectedColor else notSelectedColor - ) - GuiRenderUtils.renderItemStack(ItemStack(Items.gold_ingot), x + 5, y + 5) - if (isMouseIn(x, y, 28, 25)) { - tooltipToDisplay.add("§eBreakdown") - } - y += 30 - drawRect( - x, y, - x + 28, y + 25, - if (selectedPage == FortuneGuidePage.UPGRADES) selectedColor else notSelectedColor - ) - GuiRenderUtils.renderItemStack(ItemStack(Items.map), x + 5, y + 5) - if (isMouseIn(x, y, 28, 25)) { - tooltipToDisplay.add("§eUpgrades") + lastVerticalTabWrapper.tab?.fakeClick() // First Click Logic } } enum class FortuneGuidePage { OVERVIEW, CROP, - UPGRADES - } - - abstract class FFGuidePage { + UPGRADES, - abstract fun drawPage(mouseX: Int, mouseY: Int, partialTicks: Float) } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFInfos.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFInfos.kt new file mode 100644 index 000000000..19597e6db --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFInfos.kt @@ -0,0 +1,153 @@ +package at.hannibal2.skyhanni.features.garden.fortuneguide + +import at.hannibal2.skyhanni.utils.GuiRenderUtils + +internal enum class FFInfos( + val sumTo: FFInfos?, + private val currentF: () -> Number, + private val maxF: (FFInfos) -> Number, +) { + UNIVERSAL(null, { FFStats.totalBaseFF }, FFTypes.TOTAL, { + val backupArmor = FarmingItems.currentArmor + val backupEquip = FarmingItems.currentEquip + FarmingItems.currentArmor = null + FarmingItems.currentEquip = null + val total = maxSumToThis(it) + 100 + FarmingItems.currentArmor = backupArmor + FarmingItems.currentEquip = backupEquip + total + }), + ANITA_BUFF(UNIVERSAL, { FFStats.baseFF }, FFTypes.ANITA, 60), + FARMING_LEVEL(UNIVERSAL, { FFStats.baseFF }, FFTypes.FARMING_LVL, 240), + COMMUNITY_SHOP(UNIVERSAL, { FFStats.baseFF }, FFTypes.COMMUNITY_SHOP, 40), + GARDEN_PLOTS(UNIVERSAL, { FFStats.baseFF }, FFTypes.PLOTS, 72), + CAKE_BUFF(UNIVERSAL, { FFStats.baseFF }, FFTypes.CAKE, 5), + TOTAL_ARMOR(UNIVERSAL, { FarmingItems.currentArmor?.getFFData() ?: FFStats.armorTotalFF }, FFTypes.TOTAL), + BASE_ARMOR(TOTAL_ARMOR, { FarmingItems.currentArmor?.getFFData() ?: FFStats.armorTotalFF }, FFTypes.BASE, { + when (FarmingItems.currentArmor) { + FarmingItems.HELMET -> 30 + FarmingItems.CHESTPLATE, FarmingItems.LEGGINGS -> 35 + FarmingItems.BOOTS -> if (FFStats.usingSpeedBoots) 60 else 30 + else -> if (FFStats.usingSpeedBoots) 160 else 130 + } + }), + ABILITY_ARMOR(TOTAL_ARMOR, { FarmingItems.currentArmor?.getFFData() ?: FFStats.armorTotalFF }, FFTypes.ABILITY, { + when (FarmingItems.currentArmor) { + FarmingItems.HELMET, FarmingItems.CHESTPLATE, FarmingItems.LEGGINGS -> if (FFStats.usingSpeedBoots) 16.667 else 18.75 + FarmingItems.BOOTS -> if (FFStats.usingSpeedBoots) 0 else 18.75 + else -> if (FFStats.usingSpeedBoots) 50 else 75 + } + }), + REFORGE_ARMOR(TOTAL_ARMOR, { FarmingItems.currentArmor?.getFFData() ?: FFStats.armorTotalFF }, FFTypes.REFORGE, { + when (FarmingItems.currentArmor) { + FarmingItems.HELMET, FarmingItems.CHESTPLATE, FarmingItems.LEGGINGS -> 30 + FarmingItems.BOOTS -> if (FFStats.usingSpeedBoots) 25 else 30 + else -> if (FFStats.usingSpeedBoots) 115 else 120 + } + }), + ENCHANT_ARMOR( + sumTo = TOTAL_ARMOR, + from = { FarmingItems.currentArmor?.getFFData() ?: FFStats.armorTotalFF }, + what = FFTypes.PESTERMINATOR, + x4 = { FarmingItems.currentArmor == null }, + max = 5 + ), + GEMSTONE_ARMOR(TOTAL_ARMOR, { FarmingItems.currentArmor?.getFFData() ?: FFStats.armorTotalFF }, FFTypes.GEMSTONE, { + when (FarmingItems.currentArmor) { + FarmingItems.HELMET, FarmingItems.CHESTPLATE, FarmingItems.LEGGINGS -> 20 + FarmingItems.BOOTS -> if (FFStats.usingSpeedBoots) 16 else 20 + else -> if (FFStats.usingSpeedBoots) 76 else 80 + } + }), + TOTAL_PET(UNIVERSAL, { FarmingItems.currentPet.getFFData() }, FFTypes.TOTAL), + PET_BASE(TOTAL_PET, { FarmingItems.currentPet.getFFData() }, FFTypes.BASE, { + when (FarmingItems.currentPet) { + FarmingItems.ELEPHANT -> 150 + FarmingItems.MOOSHROOM_COW -> 157 + FarmingItems.BEE -> 30 + else -> 0 + } + }), + PET_ITEM(TOTAL_PET, { FarmingItems.currentPet.getFFData() }, FFTypes.PET_ITEM, 60), + TOTAL_EQUIP( + sumTo = UNIVERSAL, + from = { FarmingItems.currentEquip?.getFFData() ?: FFStats.equipmentTotalFF }, + what = FFTypes.TOTAL + ), + BASE_EQUIP( + sumTo = TOTAL_EQUIP, + from = { FarmingItems.currentEquip?.getFFData() ?: FFStats.equipmentTotalFF }, + what = FFTypes.BASE, + x4 = { FarmingItems.currentEquip == null }, + max = 5.0 + ), + ABILITY_EQUIP( + sumTo = TOTAL_EQUIP, + from = { FarmingItems.currentEquip?.getFFData() ?: FFStats.equipmentTotalFF }, + what = FFTypes.ABILITY, + x4 = { FarmingItems.currentEquip == null }, + max = 15.0 + ), + REFORGE_EQUIP( + sumTo = TOTAL_EQUIP, + from = { FarmingItems.currentEquip?.getFFData() ?: FFStats.equipmentTotalFF }, + what = FFTypes.REFORGE, + x4 = { FarmingItems.currentEquip == null }, + max = 15.0 + ), + ENCHANT_EQUIP( + sumTo = TOTAL_EQUIP, + from = { FarmingItems.currentEquip?.getFFData() ?: FFStats.equipmentTotalFF }, + what = FFTypes.GREEN_THUMB, + x4 = { FarmingItems.currentEquip == null }, + max = { at.hannibal2.skyhanni.features.garden.GardenAPI.totalAmountVisitorsExisting.toDouble() / 4.0 } + ), + ; + + val current get() = currentF().toDouble() + val max get() = maxF(this).toDouble() + + fun bar(label: String, tooltip: String) = GuiRenderUtils.getFarmingBar(label, tooltip, current, max, 90) + + constructor(sumTo: FFInfos?, current: () -> Number, max: Number) : this(sumTo, current, { max }) + constructor(sumTo: FFInfos?, from: () -> Map<FFTypes, Double>, what: FFTypes, max: Number) : this(sumTo, { + from()[what] ?: 0.0 + }, { max } + ) + + constructor( + sumTo: FFInfos?, + from: () -> Map<FFTypes, Double>, + what: FFTypes, + x4: () -> Boolean, + max: Number, + ) : this(sumTo, { from()[what] ?: 0.0 }, { if (x4()) max.toDouble() * 4 else max } + ) + + constructor( + sumTo: FFInfos?, + from: () -> Map<FFTypes, Double>, + what: FFTypes, + x4: () -> Boolean, + max: () -> Number, + ) : this(sumTo, { from()[what] ?: 0.0 }, { if (x4()) max().toDouble() * 4 else max() } + ) + + constructor( + sumTo: FFInfos?, + from: () -> Map<FFTypes, Double>, + what: FFTypes, + max: (FFInfos) -> Number, + ) : this( + sumTo, { from()[what] ?: 0.0 }, max + ) + + constructor( + sumTo: FFInfos?, + from: () -> Map<FFTypes, Double>, + what: FFTypes, + ) : this(sumTo, { from()[what] ?: 0.0 }, ::maxSumToThis) + +} + +private fun maxSumToThis(self: FFInfos): Double = FFInfos.entries.filter { it.sumTo == self }.sumOf { it.max } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFStats.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFStats.kt index 2f1ce1860..772177c82 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFStats.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFStats.kt @@ -6,8 +6,8 @@ import at.hannibal2.skyhanni.data.ProfileStorageData import at.hannibal2.skyhanni.features.garden.CropType import at.hannibal2.skyhanni.features.garden.FarmingFortuneDisplay import at.hannibal2.skyhanni.features.garden.GardenAPI -import at.hannibal2.skyhanni.features.garden.fortuneguide.FFGuideGUI.Companion.getItem import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName +import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getFarmingForDummiesCount import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getPetItem import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getPetLevel @@ -16,225 +16,166 @@ import kotlin.math.floor object FFStats { - private val mathCrops = + private val mathCrops by lazy { listOf(CropType.WHEAT, CropType.CARROT, CropType.POTATO, CropType.SUGAR_CANE, CropType.NETHER_WART) - private val dicerCrops = listOf(CropType.PUMPKIN, CropType.MELON) + } + private val dicerCrops by lazy { listOf(CropType.PUMPKIN, CropType.MELON) } private val farmingBoots = arrayListOf("RANCHERS_BOOTS", "FARMER_BOOTS") - var cakeExpireTime = 0L + var cakeExpireTime = SimpleTimeMark.farPast() - val necklaceFF = mutableMapOf<FFTypes, Double>() - val cloakFF = mutableMapOf<FFTypes, Double>() - val beltFF = mutableMapOf<FFTypes, Double>() - val braceletFF = mutableMapOf<FFTypes, Double>() - var equipmentTotalFF = mutableMapOf<FFTypes, Double>() + var equipmentTotalFF = mapOf<FFTypes, Double>() - val helmetFF = mutableMapOf<FFTypes, Double>() - val chestplateFF = mutableMapOf<FFTypes, Double>() - val leggingsFF = mutableMapOf<FFTypes, Double>() - val bootsFF = mutableMapOf<FFTypes, Double>() - var armorTotalFF = mutableMapOf<FFTypes, Double>() + var armorTotalFF = mapOf<FFTypes, Double>() var usingSpeedBoots = false - val elephantFF = mutableMapOf<FFTypes, Double>() - val mooshroomFF = mutableMapOf<FFTypes, Double>() - val rabbitFF = mutableMapOf<FFTypes, Double>() - val beeFF = mutableMapOf<FFTypes, Double>() var currentPetItem = "" - var baseFF = mutableMapOf<FFTypes, Double>() - - var totalBaseFF = mutableMapOf<FFTypes, Double>() + var baseFF = mapOf<FFTypes, Double>() - val cropPage = mutableMapOf<FortuneStats, Pair<Double, Double>>() + var totalBaseFF = mapOf<FFTypes, Double>() fun loadFFData() { - cakeExpireTime = GardenAPI.storage?.fortune?.cakeExpiring ?: -1L - - getEquipmentFFData(FarmingItems.NECKLACE.getItem(), necklaceFF) - getEquipmentFFData(FarmingItems.CLOAK.getItem(), cloakFF) - getEquipmentFFData(FarmingItems.BELT.getItem(), beltFF) - getEquipmentFFData(FarmingItems.BRACELET.getItem(), braceletFF) + cakeExpireTime = SimpleTimeMark(GardenAPI.storage?.fortune?.cakeExpiring ?: -1L) - equipmentTotalFF = - (necklaceFF.toList() + cloakFF.toList() + beltFF.toList() + braceletFF.toList()).groupBy({ it.first }, - { it.second }).map { (key, values) -> key to values.sum() } - .toMap() as MutableMap<FFTypes, Double> + FarmingItems.resetFFData() - getArmorFFData(FarmingItems.HELMET.getItem(), helmetFF) - getArmorFFData(FarmingItems.CHESTPLATE.getItem(), chestplateFF) - getArmorFFData(FarmingItems.LEGGINGS.getItem(), leggingsFF) - getArmorFFData(FarmingItems.BOOTS.getItem(), bootsFF) + equipmentTotalFF = FarmingItems.equip.getFFData() - armorTotalFF = - (helmetFF.toList() + chestplateFF.toList() + leggingsFF.toList() + bootsFF.toList()).groupBy({ it.first }, - { it.second }).map { (key, values) -> key to values.sum() } - .toMap() as MutableMap<FFTypes, Double> + armorTotalFF = FarmingItems.armor.getFFData() - usingSpeedBoots = FarmingItems.BOOTS.getItem().getInternalName().asString() in farmingBoots + usingSpeedBoots = FarmingItems.BOOTS.getItem()?.getInternalName()?.asString() in farmingBoots - getPetFFData(FarmingItems.ELEPHANT.getItem(), elephantFF) - getPetFFData(FarmingItems.MOOSHROOM_COW.getItem(), mooshroomFF) - getPetFFData(FarmingItems.RABBIT.getItem(), rabbitFF) - getPetFFData(FarmingItems.BEE.getItem(), beeFF) - - getGenericFF(baseFF) + baseFF = getGenericFF() getTotalFF() } - fun getCropStats(crop: CropType, tool: ItemStack) { - cropPage.clear() - cropPage[FortuneStats.BASE] = Pair(totalBaseFF[FFTypes.TOTAL] ?: 100.0, if (usingSpeedBoots) 1373.0 else 1377.0) - cropPage[FortuneStats.CROP_UPGRADE] = Pair((crop.getUpgradeLevel()?.toDouble() ?: 0.0) * 5.0, 45.0) - cropPage[FortuneStats.ACCESSORY] = Pair(CropAccessoryData.cropAccessory.getFortune(crop), 30.0) - cropPage[FortuneStats.FFD] = Pair((tool.getFarmingForDummiesCount() ?: 0).toDouble(), 5.0) - cropPage[FortuneStats.TURBO] = Pair(FarmingFortuneDisplay.getTurboCropFortune(tool, crop), 25.0) - cropPage[FortuneStats.DEDICATION] = Pair(FarmingFortuneDisplay.getDedicationFortune(tool, crop), 92.0) - cropPage[FortuneStats.CULTIVATING] = Pair(FarmingFortuneDisplay.getCultivatingFortune(tool), 20.0) + fun getCropStats(crop: CropType, tool: ItemStack?) { + FortuneStats.reset() + + FortuneStats.BASE.set(FFInfos.UNIVERSAL.current, FFInfos.UNIVERSAL.max) + FortuneStats.CROP_UPGRADE.set((crop.getUpgradeLevel()?.toDouble() ?: 0.0) * 5.0, 45.0) + FortuneStats.ACCESSORY.set(CropAccessoryData.cropAccessory.getFortune(crop), 30.0) + FortuneStats.FFD.set((tool?.getFarmingForDummiesCount() ?: 0).toDouble(), 5.0) + FortuneStats.TURBO.set(FarmingFortuneDisplay.getTurboCropFortune(tool, crop), 25.0) + FortuneStats.DEDICATION.set(FarmingFortuneDisplay.getDedicationFortune(tool, crop), 92.0) + FortuneStats.CULTIVATING.set(FarmingFortuneDisplay.getCultivatingFortune(tool), 20.0) FarmingFortuneDisplay.loadFortuneLineData(tool, 0.0) when (crop) { in mathCrops -> { - cropPage[FortuneStats.BASE_TOOL] = Pair(FarmingFortuneDisplay.getToolFortune(tool), 50.0) - cropPage[FortuneStats.COUNTER] = Pair(FarmingFortuneDisplay.getCounterFortune(tool), 96.0) - cropPage[FortuneStats.HARVESTING] = Pair(FarmingFortuneDisplay.getHarvestingFortune(tool), 75.0) - cropPage[FortuneStats.COLLECTION] = Pair(FarmingFortuneDisplay.getCollectionFortune(tool), 48.0) - cropPage[FortuneStats.REFORGE] = Pair(FarmingFortuneDisplay.reforgeFortune, 20.0) - cropPage[FortuneStats.GEMSTONE] = Pair(FarmingFortuneDisplay.gemstoneFortune, 30.0) + FortuneStats.BASE_TOOL.set(FarmingFortuneDisplay.getToolFortune(tool), 50.0) + FortuneStats.COUNTER.set(FarmingFortuneDisplay.getCounterFortune(tool), 96.0) + FortuneStats.HARVESTING.set(FarmingFortuneDisplay.getHarvestingFortune(tool), 75.0) + FortuneStats.COLLECTION.set(FarmingFortuneDisplay.getCollectionFortune(tool), 48.0) + FortuneStats.REFORGE.set(FarmingFortuneDisplay.reforgeFortune, 20.0) + FortuneStats.GEMSTONE.set(FarmingFortuneDisplay.gemstoneFortune, 30.0) } in dicerCrops -> { - cropPage[FortuneStats.SUNDER] = Pair(FarmingFortuneDisplay.getSunderFortune(tool), 75.0) - cropPage[FortuneStats.REFORGE] = Pair(FarmingFortuneDisplay.reforgeFortune, 20.0) - cropPage[FortuneStats.GEMSTONE] = Pair(FarmingFortuneDisplay.gemstoneFortune, 20.0) + FortuneStats.SUNDER.set(FarmingFortuneDisplay.getSunderFortune(tool), 75.0) + FortuneStats.REFORGE.set(FarmingFortuneDisplay.reforgeFortune, 20.0) + FortuneStats.GEMSTONE.set(FarmingFortuneDisplay.gemstoneFortune, 20.0) } CropType.MUSHROOM -> { - cropPage[FortuneStats.BASE_TOOL] = Pair(FarmingFortuneDisplay.getToolFortune(tool), 30.0) - cropPage[FortuneStats.HARVESTING] = Pair(FarmingFortuneDisplay.getHarvestingFortune(tool), 75.0) - cropPage[FortuneStats.REFORGE] = Pair(FarmingFortuneDisplay.reforgeFortune, 16.0) - cropPage[FortuneStats.GEMSTONE] = Pair(FarmingFortuneDisplay.gemstoneFortune, 16.0) + FortuneStats.BASE_TOOL.set(FarmingFortuneDisplay.getToolFortune(tool), 30.0) + FortuneStats.HARVESTING.set(FarmingFortuneDisplay.getHarvestingFortune(tool), 75.0) + FortuneStats.REFORGE.set(FarmingFortuneDisplay.reforgeFortune, 16.0) + FortuneStats.GEMSTONE.set(FarmingFortuneDisplay.gemstoneFortune, 16.0) } CropType.COCOA_BEANS -> { - cropPage[FortuneStats.BASE_TOOL] = Pair(FarmingFortuneDisplay.getToolFortune(tool), 20.0) - cropPage[FortuneStats.SUNDER] = Pair(FarmingFortuneDisplay.getSunderFortune(tool), 75.0) - cropPage[FortuneStats.REFORGE] = Pair(FarmingFortuneDisplay.reforgeFortune, 16.0) - cropPage[FortuneStats.GEMSTONE] = Pair(FarmingFortuneDisplay.gemstoneFortune, 16.0) + FortuneStats.BASE_TOOL.set(FarmingFortuneDisplay.getToolFortune(tool), 20.0) + FortuneStats.SUNDER.set(FarmingFortuneDisplay.getSunderFortune(tool), 75.0) + FortuneStats.REFORGE.set(FarmingFortuneDisplay.reforgeFortune, 16.0) + FortuneStats.GEMSTONE.set(FarmingFortuneDisplay.gemstoneFortune, 16.0) } CropType.CACTUS -> { - cropPage[FortuneStats.HARVESTING] = Pair(FarmingFortuneDisplay.getHarvestingFortune(tool), 75.0) - cropPage[FortuneStats.REFORGE] = Pair(FarmingFortuneDisplay.reforgeFortune, 16.0) - cropPage[FortuneStats.GEMSTONE] = Pair(FarmingFortuneDisplay.gemstoneFortune, 16.0) + FortuneStats.HARVESTING.set(FarmingFortuneDisplay.getHarvestingFortune(tool), 75.0) + FortuneStats.REFORGE.set(FarmingFortuneDisplay.reforgeFortune, 16.0) + FortuneStats.GEMSTONE.set(FarmingFortuneDisplay.gemstoneFortune, 16.0) } else -> {} } - if (crop == CropType.CARROT) { - val storage = GardenAPI.storage?.fortune ?: return - val carrotFortune = if (storage.carrotFortune) 12.0 else 0.0 - cropPage[FortuneStats.EXPORTED_CARROT] = Pair(carrotFortune, 12.0) - } - if (crop == CropType.PUMPKIN) { - val storage = GardenAPI.storage?.fortune ?: return - val pumpkinFortune = if (storage.pumpkinFortune) 12.0 else 0.0 - cropPage[FortuneStats.EXPIRED_PUMPKIN] = Pair(pumpkinFortune, 12.0) - } - if (crop == CropType.COCOA_BEANS) { - val storage = GardenAPI.storage?.fortune ?: return - val cocoaBeansFortune = if (storage.cocoaBeansFortune) 12.0 else 0.0 - cropPage[FortuneStats.SUPREME_CHOCOLATE_BAR] = Pair(cocoaBeansFortune, 12.0) + CarrolynTable.getByCrop(crop)?.let { + val ff = if (it.get()) 12.0 else 0.0 + FortuneStats.CARROLYN.set(ff, 12.0) } - cropPage[FortuneStats.CROP_TOTAL] = Pair( - cropPage.toList().sumOf { it.second.first }, - cropPage.toList().sumOf { it.second.second }) + FortuneStats.CROP_TOTAL.set(FortuneStats.getTotal()) } - private fun getEquipmentFFData(item: ItemStack, out: MutableMap<FFTypes, Double>) { + fun getEquipmentFFData(item: ItemStack?): Map<FFTypes, Double> = buildMap { FarmingFortuneDisplay.loadFortuneLineData(item, 0.0) - out[FFTypes.TOTAL] = 0.0 - out[FFTypes.BASE] = FarmingFortuneDisplay.itemBaseFortune - out[FFTypes.REFORGE] = FarmingFortuneDisplay.reforgeFortune - out[FFTypes.GREEN_THUMB] = FarmingFortuneDisplay.greenThumbFortune - out[FFTypes.ABILITY] = FarmingFortuneDisplay.getAbilityFortune(item) - out[FFTypes.TOTAL] = out.values.sum() + this[FFTypes.BASE] = FarmingFortuneDisplay.itemBaseFortune + this[FFTypes.REFORGE] = FarmingFortuneDisplay.reforgeFortune + this[FFTypes.GREEN_THUMB] = FarmingFortuneDisplay.greenThumbFortune + this[FFTypes.ABILITY] = FarmingFortuneDisplay.getAbilityFortune(item) + this[FFTypes.TOTAL] = this.values.sum() } - private fun getArmorFFData(item: ItemStack, out: MutableMap<FFTypes, Double>) { + fun getArmorFFData(item: ItemStack?): Map<FFTypes, Double> = buildMap { FarmingFortuneDisplay.loadFortuneLineData(item, 0.0) - out[FFTypes.TOTAL] = 0.0 - out[FFTypes.BASE] = FarmingFortuneDisplay.itemBaseFortune - out[FFTypes.REFORGE] = FarmingFortuneDisplay.reforgeFortune - out[FFTypes.GEMSTONE] = FarmingFortuneDisplay.gemstoneFortune - out[FFTypes.PESTERMINATOR] = FarmingFortuneDisplay.pesterminatorFortune - out[FFTypes.ABILITY] = FarmingFortuneDisplay.getAbilityFortune(item) - out[FFTypes.TOTAL] = out.values.sum() + this[FFTypes.BASE] = FarmingFortuneDisplay.itemBaseFortune + this[FFTypes.REFORGE] = FarmingFortuneDisplay.reforgeFortune + this[FFTypes.GEMSTONE] = FarmingFortuneDisplay.gemstoneFortune + this[FFTypes.PESTERMINATOR] = FarmingFortuneDisplay.pesterminatorFortune + this[FFTypes.ABILITY] = FarmingFortuneDisplay.getAbilityFortune(item) + this[FFTypes.TOTAL] = this.values.sum() } - private fun getPetFFData(item: ItemStack, out: MutableMap<FFTypes, Double>) { + fun getPetFFData(item: ItemStack?): Map<FFTypes, Double> = buildMap { val gardenLvl = GardenAPI.getGardenLevel(overflow = false) - out[FFTypes.TOTAL] = 0.0 - out[FFTypes.BASE] = getPetFF(item) - out[FFTypes.PET_ITEM] = when (item.getPetItem()) { + this[FFTypes.BASE] = getPetFF(item) + this[FFTypes.PET_ITEM] = when (item?.getPetItem()) { "GREEN_BANDANA" -> 4.0 * gardenLvl "YELLOW_BANDANA" -> 30.0 - "MINOS_RELIC" -> (out[FFTypes.BASE] ?: 0.0) * .33 + "MINOS_RELIC" -> (this[FFTypes.BASE] ?: 0.0) * .33 else -> 0.0 } - out[FFTypes.TOTAL] = out.values.sum() + this[FFTypes.TOTAL] = this.values.sum() } - private fun getGenericFF(out: MutableMap<FFTypes, Double>) { - val storage = GardenAPI.storage?.fortune ?: return - out[FFTypes.TOTAL] = 0.0 - out[FFTypes.BASE_FF] = 100.0 - out[FFTypes.FARMING_LVL] = storage.farmingLevel.toDouble() * 4 - out[FFTypes.COMMUNITY_SHOP] = (ProfileStorageData.playerSpecific?.gardenCommunityUpgrade ?: -1).toDouble() * 4 - out[FFTypes.PLOTS] = storage.plotsUnlocked.toDouble() * 3 - out[FFTypes.ANITA] = storage.anitaUpgrade.toDouble() * 4 - if (cakeExpireTime - System.currentTimeMillis() > 0 || cakeExpireTime == -1L) { - out[FFTypes.CAKE] = 5.0 + private fun getGenericFF(): Map<FFTypes, Double> = buildMap { + val storage = GardenAPI.storage?.fortune ?: return emptyMap() + this[FFTypes.BASE_FF] = 100.0 + this[FFTypes.FARMING_LVL] = storage.farmingLevel.toDouble() * 4 + this[FFTypes.COMMUNITY_SHOP] = (ProfileStorageData.playerSpecific?.gardenCommunityUpgrade ?: -1).toDouble() * 4 + this[FFTypes.PLOTS] = storage.plotsUnlocked.toDouble() * 3 + this[FFTypes.ANITA] = storage.anitaUpgrade.toDouble() * 4 + if (cakeExpireTime.isInPast() || cakeExpireTime.isFarPast()) { + this[FFTypes.CAKE] = 5.0 } else { - out[FFTypes.CAKE] = 0.0 + this[FFTypes.CAKE] = 0.0 } - out[FFTypes.TOTAL] = out.values.sum() + this[FFTypes.TOTAL] = this.values.sum() } fun getTotalFF() { - var petList = mutableMapOf<FFTypes, Double>() - when (FFGuideGUI.currentPet) { - FarmingItems.ELEPHANT -> { - petList = elephantFF - } - FarmingItems.MOOSHROOM_COW -> { - petList = mooshroomFF - } + currentPetItem = FarmingItems.currentPet.getItem()?.getPetItem().toString() - FarmingItems.RABBIT -> { - petList = rabbitFF - } - - FarmingItems.BEE -> { - petList = beeFF - } + totalBaseFF = combineFFData( + baseFF, armorTotalFF, equipmentTotalFF, FarmingItems.currentPet.getFFData() + ) + FFGuideGUI.updateDisplay() + } - else -> {} - } - currentPetItem = FFGuideGUI.currentPet.getItem().getPetItem().toString() + fun List<FarmingItems>.getFFData(): Map<FFTypes, Double> = combineFFData(this.map { it.getFFData() }) - totalBaseFF = - (baseFF.toList() + armorTotalFF.toList() + equipmentTotalFF.toList() + petList.toList()).groupBy({ it.first }, - { it.second }).map { (key, values) -> key to values.sum() } - .toMap() as MutableMap<FFTypes, Double> - } + fun combineFFData(vararg value: Map<FFTypes, Double>) = combineFFData(value.toList()) + fun combineFFData(value: List<Map<FFTypes, Double>>) = + value.map { it.toList() }.flatten().groupBy({ it.first }, { it.second }) + .mapValues { (_, values) -> values.sum() } - private fun getPetFF(pet: ItemStack): Double { + private fun getPetFF(pet: ItemStack?): Double { + if (pet == null) return 0.0 val petLevel = pet.getPetLevel() val strength = (GardenAPI.storage?.fortune?.farmingStrength) if (strength != null) { @@ -253,4 +194,5 @@ object FFStats { } return 0.0 } + } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FarmingItems.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FarmingItems.kt index f2bd6b360..46b5d1e07 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FarmingItems.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FarmingItems.kt @@ -1,26 +1,166 @@ package at.hannibal2.skyhanni.features.garden.fortuneguide -enum class FarmingItems { - WHEAT, - CARROT, - POTATO, - NETHER_WART, - PUMPKIN, - MELON, - COCOA_BEANS, - SUGAR_CANE, - CACTUS, - MUSHROOM, - HELMET, - CHESTPLATE, - LEGGINGS, - BOOTS, - NECKLACE, - CLOAK, - BELT, - BRACELET, - ELEPHANT, - MOOSHROOM_COW, - RABBIT, - BEE, +import at.hannibal2.skyhanni.data.ProfileStorageData +import at.hannibal2.skyhanni.utils.ItemCategory +import at.hannibal2.skyhanni.utils.RenderUtils +import at.hannibal2.skyhanni.utils.SoundUtils +import at.hannibal2.skyhanni.utils.renderables.Renderable +import net.minecraft.client.gui.GuiScreen +import net.minecraft.init.Blocks +import net.minecraft.item.ItemStack + +enum class FarmingItems( + val itemCategory: ItemCategory, + private val ffCalculation: (ItemStack?) -> Map<FFTypes, Double> = { emptyMap() }, +) { + WHEAT(ItemCategory.HOE), + CARROT(ItemCategory.HOE), + POTATO(ItemCategory.HOE), + NETHER_WART(ItemCategory.HOE), + PUMPKIN(ItemCategory.AXE), + MELON(ItemCategory.AXE), + COCOA_BEANS(ItemCategory.AXE), + SUGAR_CANE(ItemCategory.HOE), + CACTUS(ItemCategory.HOE), + MUSHROOM(ItemCategory.HOE), + HELMET(ItemCategory.HELMET, FFStats::getArmorFFData), + CHESTPLATE(ItemCategory.CHESTPLATE, FFStats::getArmorFFData), + LEGGINGS(ItemCategory.LEGGINGS, FFStats::getArmorFFData), + BOOTS(ItemCategory.BOOTS, FFStats::getArmorFFData), + NECKLACE(ItemCategory.NECKLACE, FFStats::getEquipmentFFData), + CLOAK(ItemCategory.CLOAK, FFStats::getEquipmentFFData), + BELT(ItemCategory.BELT, FFStats::getEquipmentFFData), + BRACELET(ItemCategory.BRACELET, FFStats::getEquipmentFFData), + ELEPHANT(ItemCategory.PET, FFStats::getPetFFData), + MOOSHROOM_COW(ItemCategory.PET, FFStats::getPetFFData), + RABBIT(ItemCategory.PET, FFStats::getPetFFData), + BEE(ItemCategory.PET, FFStats::getPetFFData), + ; + + var selectedState = false + + fun getItem() = getItemOrNull() ?: fallbackItem + + private val fallbackItem: ItemStack by lazy { + val name = "§cNo saved ${name.lowercase().replace("_", " ")}" + ItemStack(Blocks.barrier).setStackDisplayName(name) + } + + fun getItemOrNull() = ProfileStorageData.profileSpecific?.garden?.fortune?.farmingItems?.get(this) + fun setItem(value: ItemStack) = ProfileStorageData.profileSpecific?.garden?.fortune?.farmingItems?.set(this, value) + + private fun onClick(): () -> Unit = when (this) { + in armor -> { + { + SoundUtils.playClickSound() + currentArmor = if (selectedState) null else this + armor.forEach { + it.selectedState = it == currentArmor + } + FFGuideGUI.updateDisplay() + } + } + + in equip -> { + { + SoundUtils.playClickSound() + currentEquip = if (selectedState) null else this + equip.forEach { + it.selectedState = it == currentEquip + } + FFGuideGUI.updateDisplay() + } + } + + in pets -> { + { + val prev = currentPet + currentPet = if (selectedState) lastEquippedPet else this + if (prev != currentPet) { + SoundUtils.playClickSound() + } + pets.forEach { + it.selectedState = it == currentPet + } + FFStats.getTotalFF() + } + } + + else -> { + {} + } + } + + fun getDisplay(clickEnabled: Boolean = false) = object : Renderable { + + val content = Renderable.clickable( + Renderable.itemStackWithTip( + getItem(), 1.0, 0, 0, false + ), + onClick = onClick(), + condition = { clickEnabled }) + + override val width = content.width + override val height = content.height + override val horizontalAlign = RenderUtils.HorizontalAlignment.CENTER + override val verticalAlign = RenderUtils.VerticalAlignment.CENTER + + override fun render(posX: Int, posY: Int) { + GuiScreen.drawRect( + 0, + 0, + width, + height, + if (this@FarmingItems.selectedState) 0xFFB3FFB3.toInt() else 0xFF43464B.toInt() + ) + content.render(posX, posY) + } + } + + private var ffData: Map<FFTypes, Double>? = null + + fun getFFData() = ffData ?: run { + val data = ffCalculation(getItemOrNull()) + ffData = data + data + } + + companion object { + + // TODO + var lastEquippedPet = ELEPHANT + + var currentPet: FarmingItems = lastEquippedPet + var currentArmor: FarmingItems? = null + var currentEquip: FarmingItems? = null + + val armor = listOf(HELMET, CHESTPLATE, LEGGINGS, BOOTS) + val equip = listOf(NECKLACE, CLOAK, BELT, BRACELET) + val pets = listOf(ELEPHANT, MOOSHROOM_COW, RABBIT, BEE) + + fun getArmorDisplay(clickEnabled: Boolean = false): List<Renderable> = armor.map { it.getDisplay(clickEnabled) } + + fun getEquipmentDisplay(clickEnabled: Boolean = false): List<Renderable> = + equip.map { it.getDisplay(clickEnabled) } + + fun getPetsDisplay(clickEnabled: Boolean = false): List<Renderable> = pets.map { it.getDisplay(clickEnabled) } + fun resetClickState() { + entries.filterNot { pets.contains(it) }.forEach { it.selectedState = false } + } + + fun resetFFData() { + entries.forEach { it.ffData = null } + } + + fun setDefaultPet(): FarmingItems { + currentPet = lastEquippedPet + pets.forEach { + it.selectedState = it == currentPet + } + return lastEquippedPet + } + + fun getFromItemCategory(category: ItemCategory) = entries.filter { it.itemCategory == category } + fun getFromItemCategoryOne(category: ItemCategory) = entries.firstOrNull { it.itemCategory == category } + } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FarmingReforges.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FarmingReforges.kt index 1e911688a..6ac7171fb 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FarmingReforges.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FarmingReforges.kt @@ -1,5 +1,6 @@ package at.hannibal2.skyhanni.features.garden.fortuneguide +// TODO replace with ReforgeAPI enum class FarmingReforges( val reforgeName: String, val reforgeItem: String, diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneStats.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneStats.kt index 863bc9518..b5558b638 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneStats.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneStats.kt @@ -1,12 +1,21 @@ package at.hannibal2.skyhanni.features.garden.fortuneguide -enum class FortuneStats(val label: String, val tooltip: String) { +import at.hannibal2.skyhanni.features.garden.CropType +import at.hannibal2.skyhanni.utils.CollectionUtils.sumOfPair +import at.hannibal2.skyhanni.utils.StringUtils.firstLetterUppercase + +enum class FortuneStats( + private val label0: (CropType) -> String, + private val tooltip0: (CropType) -> String, + val onClick: (CropType) -> Unit = {}, +) { BASE( "§2Universal Farming Fortune", - "§7§2Farming fortune in that is\n§2applied to every crop\n§eNot the same as tab FF\n" + - "§eSee on the grass block page" + "§7§2Farming fortune in that is\n§2applied to every crop\n§eNot the same as tab FF\n" + "§eSee on the grass block page" ), - CROP_TOTAL("§6Crop Farming Fortune", "§7§2Farming fortune for this crop"), + CROP_TOTAL( + { crop -> "§6${crop.niceName.firstLetterUppercase()} Farming Fortune" }, + { "§7§2Farming fortune for this crop" }), ACCESSORY("§2Talisman Bonus", "§7§2Fortune from your talisman\n§2You get 10☘ per talisman tier"), CROP_UPGRADE("§2Crop Upgrade", "§7§2Fortune from Desk crop upgrades\n§2You get 5☘ per level"), BASE_TOOL("§2Base tool fortune", "§7§2Crop specific fortune from your tool"), @@ -20,19 +29,53 @@ enum class FortuneStats(val label: String, val tooltip: String) { CULTIVATING("§2Cultivating Enchantment", "§7§2Fortune for each enchantment level\n§2You get 2☘ per level"), TURBO("§2Turbo-Crop Enchantment", "§7§2Fortune for each enchantment level\n§2You get 5☘ per level"), DEDICATION("§2Dedication Enchantment", "§7§2Fortune for each enchantment level\n§2and crop milestone"), - EXPORTED_CARROT( - "§2Exportable Carrots", - "§7§2Gain 12☘ from giving 3,000 to Carrolyn in Scarleton!\n" + - "§eRun /shcarrot to toggle the stat" - ), - EXPIRED_PUMPKIN( - "§2Expired Pumpkin", - "§7§2Gain 12☘ from giving 3,000 to Carrolyn in Scarleton!\n" + - "§eRun /shpumpkin to toggle the stat" - ), - SUPREME_CHOCOLATE_BAR( - "§2Supreme Chocolate Bar", - "§7§2Gain 12☘ from giving 3,000 to Carrolyn in Scarleton!\n" + - "§eRun /shcocoabeans to toggle the stat" - ), + CARROLYN(::carrolynLabel, ::carrolynToolTip, ::carrolynOnClick), + ; + + constructor(label: String, tooltip: String) : this({ label }, { tooltip }) + + var current: Double = 0.0 + var max: Double = -1.0 + + fun label(crop: CropType) = label0(crop) + fun tooltip(crop: CropType) = tooltip0(crop) + + fun reset() { + current = 0.0 + max = -1.0 + } + + fun set(value: Pair<Double, Double>) { + current = value.first + max = value.second + } + + fun set(current: Double, max: Double) { + this.current = current + this.max = max + } + + fun isActive() = max != -1.0 + + companion object { + + fun getTotal(): Pair<Double, Double> = entries.filter { it.isActive() }.sumOfPair { it.current to it.max } + + fun reset() = entries.forEach { it.reset() } + } } + +private fun carrolynLabel(crop: CropType): String = + CarrolynTable.getByCrop(crop)?.label?.let { "§2$it" } ?: "§cError" + +private fun carrolynToolTip(crop: CropType): String = + "§7§2Gain 12☘ from giving 3,000\n§2 to Carrolyn in Scarleton!\n §e`Run /shcarrolyn ${ + crop.niceName + }` to toggle the stat\n §eor click the value" + +private fun carrolynOnClick(crop: CropType) = + CarrolynTable.getByCrop(crop)?.let { + it.setVisibleActive(!it.get()) + FFGuideGUI.updateDisplay() + } + diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneUpgrade.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneUpgrade.kt index 43b0c37d3..769253538 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneUpgrade.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneUpgrade.kt @@ -1,12 +1,16 @@ package at.hannibal2.skyhanni.features.garden.fortuneguide +import at.hannibal2.skyhanni.utils.NEUInternalName +import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName + data class FortuneUpgrade( val description: String, val costCopper: Int?, - //todo make into NEUInternalName - val requiredItem: String, + private val requiredItemName: String, val itemQuantity: Int, val fortuneIncrease: Double, var cost: Int? = null, var costPerFF: Int? = null, // also the same as time to repay -) +) { + val requiredItem: NEUInternalName = requiredItemName.asInternalName() +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneUpgrades.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneUpgrades.kt index 191b9b7e5..43289dc62 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneUpgrades.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneUpgrades.kt @@ -9,12 +9,9 @@ import at.hannibal2.skyhanni.features.garden.CropType.Companion.getTurboCrop import at.hannibal2.skyhanni.features.garden.FarmingFortuneDisplay import at.hannibal2.skyhanni.features.garden.GardenAPI import at.hannibal2.skyhanni.features.garden.GardenAPI.getCropType -import at.hannibal2.skyhanni.features.garden.fortuneguide.FFGuideGUI.Companion.currentPet -import at.hannibal2.skyhanni.features.garden.fortuneguide.FFGuideGUI.Companion.getItem import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName import at.hannibal2.skyhanni.utils.ItemUtils.getItemRarityOrCommon import at.hannibal2.skyhanni.utils.ItemUtils.itemName -import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName import at.hannibal2.skyhanni.utils.NEUItems.getPrice import at.hannibal2.skyhanni.utils.NumberUtil.addSuffix import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getEnchantments @@ -25,8 +22,6 @@ import net.minecraft.item.ItemStack object FortuneUpgrades { - private val equipment = listOf(FarmingItems.NECKLACE, FarmingItems.CLOAK, FarmingItems.BELT, FarmingItems.BRACELET) - private val armor = listOf(FarmingItems.HELMET, FarmingItems.CHESTPLATE, FarmingItems.LEGGINGS, FarmingItems.BOOTS) private val axeCrops = listOf(CropType.MELON, CropType.PUMPKIN, CropType.COCOA_BEANS) val genericUpgrades = mutableListOf<FortuneUpgrade>() @@ -64,7 +59,7 @@ object FortuneUpgrades { // todo fix NEU price data not being loaded if run too early private fun MutableList<FortuneUpgrade>.populateAndSort(style: Int) { this.map { upgrade -> - val cost = (upgrade.requiredItem.asInternalName().getPrice() * upgrade.itemQuantity).toInt() + val cost = (upgrade.requiredItem.getPrice() * upgrade.itemQuantity).toInt() upgrade.cost = cost upgrade.costPerFF = (cost / upgrade.fortuneIncrease).toInt() } @@ -94,8 +89,8 @@ object FortuneUpgrades { private fun getEquipmentUpgrades() { val visitors = GardenAPI.storage?.uniqueVisitors?.toDouble() ?: 0.0 - for (piece in equipment) { - val item = piece.getItem() + for (piece in FarmingItems.equip) { + val item = piece.getItem() ?: return // todo tell them to buy the missing item if (!item.getInternalName().contains("LOTUS")) return val enchantments = item.getEnchantments() ?: emptyMap() @@ -124,11 +119,8 @@ object FortuneUpgrades { // todo adding armor tier upgrades later private fun getArmorUpgrades() { - for (piece in armor) { - val item = piece.getItem() - // todo skip if it doesnt exist -> tell them to buy it later - - if (FFGuideGUI.isFallbackItem(item)) return + for (piece in FarmingItems.armor) { + val item = piece.getItemOrNull() ?: return // todo tell them to buy it later recombobulateItem(item, genericUpgrades) when (item.getReforgeName()) { @@ -146,7 +138,7 @@ object FortuneUpgrades { // todo needs to be called when switching pets private fun getPetUpgrades() { - if (currentPet.getItem().getInternalName().contains(";")) { + if (FarmingItems.currentPet.getItemOrNull()?.getInternalName()?.contains(";") == true) { when (FFStats.currentPetItem) { "GREEN_BANDANA" -> {} "YELLOW_BANDANA" -> { @@ -160,11 +152,11 @@ object FortuneUpgrades { } } - fun getCropSpecific(tool: ItemStack) { + fun getCropSpecific(tool: ItemStack?) { cropSpecificUpgrades.clear() cropSpecificUpgrades.addAll(genericUpgrades) // todo tell them to get the tool if it is missing - val crop = tool.getCropType() ?: return + val crop = tool?.getCropType() ?: return val enchantments = tool.getEnchantments() ?: emptyMap() val turboCropLvl = enchantments[crop.getTurboCrop()] ?: 0 val dedicationLvl = enchantments["dedication"] ?: 0 diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/pages/CropPage.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/pages/CropPage.kt index d9558cd2f..ca813a4ae 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/pages/CropPage.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/pages/CropPage.kt @@ -1,53 +1,87 @@ package at.hannibal2.skyhanni.features.garden.fortuneguide.pages -import at.hannibal2.skyhanni.features.garden.fortuneguide.FFGuideGUI -import at.hannibal2.skyhanni.features.garden.fortuneguide.FFGuideGUI.Companion.getItem +import at.hannibal2.skyhanni.features.garden.CropType import at.hannibal2.skyhanni.features.garden.fortuneguide.FFStats import at.hannibal2.skyhanni.features.garden.fortuneguide.FarmingItems import at.hannibal2.skyhanni.features.garden.fortuneguide.FortuneStats +import at.hannibal2.skyhanni.utils.CollectionUtils.split import at.hannibal2.skyhanni.utils.GuiRenderUtils -import at.hannibal2.skyhanni.utils.StringUtils.firstLetterUppercase - -class CropPage : FFGuideGUI.FFGuidePage() { - - override fun drawPage(mouseX: Int, mouseY: Int, partialTicks: Float) { - for (item in FarmingItems.entries) { - if (item.name == FFGuideGUI.currentCrop?.name) { - GuiRenderUtils.renderItemAndTip( - FFGuideGUI.tooltipToDisplay, - item.getItem(), - FFGuideGUI.guiLeft + 172, - FFGuideGUI.guiTop + 60, - mouseX, - mouseY - ) - } - } - - var x: Int - var y = FFGuideGUI.guiTop - 20 - var i = 0 - FFStats.cropPage.forEach { (key, value) -> - if (key == FortuneStats.CROP_TOTAL) { - val newLine = - key.label.replace("Crop", FFGuideGUI.currentCrop?.name?.replace("_", " ")?.firstLetterUppercase()!!) - GuiRenderUtils.drawFarmingBar( - newLine, key.tooltip, value.first, value.second, FFGuideGUI.guiLeft + 135, - FFGuideGUI.guiTop + 5, 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay - ) - } else { - if (i % 2 == 0) { - x = FFGuideGUI.guiLeft + 15 - y += 25 - } else { - x = FFGuideGUI.guiLeft + 255 - } - i++ - GuiRenderUtils.drawFarmingBar( - key.label, key.tooltip, value.first, value.second, x, y, - 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay +import at.hannibal2.skyhanni.utils.RenderUtils +import at.hannibal2.skyhanni.utils.guide.GuideTablePage +import at.hannibal2.skyhanni.utils.renderables.Renderable + +class CropPage(val crop0: () -> CropType, sizeX: Int, sizeY: Int, paddingX: Int = 15, paddingY: Int = 7) : + GuideTablePage( + sizeX, + sizeY, + paddingX, + paddingY + ) { + + val crop get() = crop0() + + override fun onEnter() { + val item = crop.farmingItem + FFStats.getCropStats(crop, item.getItemOrNull()) + + FarmingItems.resetClickState() + val toolLines = toolLines().split().map { Renderable.verticalContainer(it, 2) } + update( + listOf( + header(), + listOf( + toolLines[0], + equipDisplay(), + toolLines[1], ) - } - } + ), + emptyList() + ) + } + + private fun header(): List<Renderable> = buildList { + add(FortuneStats.BASE.getFarmingBar()) + + add( + FortuneStats.CROP_TOTAL.getFarmingBar(110) + ) + + add(FortuneStats.CROP_UPGRADE.getFarmingBar()) + } + + private fun FortuneStats.getFarmingBar( + width: Int = 90, + ) = Renderable.clickable( + GuiRenderUtils.getFarmingBar(label(crop), tooltip(crop), current, max, width), + { onClick(crop) }) + + private fun toolLines(): List<Renderable> = + FortuneStats.entries.filter { it.isActive() && it !in headers }.map { it.getFarmingBar() } + + private fun equipDisplay(): Renderable = + Renderable.fixedSizeCollum( + Renderable.verticalContainer( + listOf( + crop.farmingItem.getDisplay(), + Renderable.horizontalContainer( + listOf( + Renderable.verticalContainer(FarmingItems.getArmorDisplay(), 2), + Renderable.verticalContainer(FarmingItems.getEquipmentDisplay(), 2) + ), + 2, + horizontalAlign = RenderUtils.HorizontalAlignment.CENTER + ), + Renderable.horizontalContainer(FarmingItems.getPetsDisplay(true), 2) + ), + 2, + verticalAlign = RenderUtils.VerticalAlignment.BOTTOM + ), + 144, + horizontalAlign = RenderUtils.HorizontalAlignment.CENTER, + verticalAlign = RenderUtils.VerticalAlignment.BOTTOM + ) + + companion object { + private val headers = setOf(FortuneStats.BASE, FortuneStats.CROP_TOTAL, FortuneStats.CROP_UPGRADE) } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/pages/OverviewPage.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/pages/OverviewPage.kt index 605081e4e..577020cfb 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/pages/OverviewPage.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/pages/OverviewPage.kt @@ -1,272 +1,234 @@ package at.hannibal2.skyhanni.features.garden.fortuneguide.pages -import at.hannibal2.skyhanni.features.garden.GardenAPI -import at.hannibal2.skyhanni.features.garden.fortuneguide.FFGuideGUI -import at.hannibal2.skyhanni.features.garden.fortuneguide.FFGuideGUI.Companion.currentArmor -import at.hannibal2.skyhanni.features.garden.fortuneguide.FFGuideGUI.Companion.currentEquipment -import at.hannibal2.skyhanni.features.garden.fortuneguide.FFGuideGUI.Companion.getItem +import at.hannibal2.skyhanni.features.garden.fortuneguide.FFInfos import at.hannibal2.skyhanni.features.garden.fortuneguide.FFStats import at.hannibal2.skyhanni.features.garden.fortuneguide.FFTypes import at.hannibal2.skyhanni.features.garden.fortuneguide.FarmingItems -import at.hannibal2.skyhanni.utils.GuiRenderUtils -import at.hannibal2.skyhanni.utils.TimeUtils - -class OverviewPage : FFGuideGUI.FFGuidePage() { - - private var equipmentFF = mutableMapOf<FFTypes, Double>() - private var armorFF = mutableMapOf<FFTypes, Double>() +import at.hannibal2.skyhanni.utils.CollectionUtils.getOrNull +import at.hannibal2.skyhanni.utils.RenderUtils +import at.hannibal2.skyhanni.utils.TimeUnit +import at.hannibal2.skyhanni.utils.TimeUtils.format +import at.hannibal2.skyhanni.utils.guide.GuideTablePage +import at.hannibal2.skyhanni.utils.renderables.Renderable + +class OverviewPage(sizeX: Int, sizeY: Int, paddingX: Int = 15, paddingY: Int = 7, footerSpacing: Int = 6) : + GuideTablePage( + sizeX, sizeY, paddingX, paddingY, footerSpacing + ) { + + override fun onEnter() { + val (content, footer) = getPage() + update(content, footer) + } // TODO display armor stats for gemstones and pesterminator - override fun drawPage(mouseX: Int, mouseY: Int, partialTicks: Float) { - val timeUntilCakes = TimeUtils.formatDuration(FFStats.cakeExpireTime - System.currentTimeMillis()) - - GuiRenderUtils.drawFarmingBar( - "§6Universal Farming Fortune", - "§7§2Farming fortune in that is\n§2applied to every crop\n§eNot the same as tab FF\n" + - "§eSee on the grass block page", FFStats.totalBaseFF[FFTypes.TOTAL] ?: 0, if (FFStats.usingSpeedBoots) 1373 else 1377, - FFGuideGUI.guiLeft + 15, FFGuideGUI.guiTop + 5, 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay - ) + // TODO display pest bestiary + fun getPage(): Pair<List<List<Renderable>>, List<Renderable>> { + val content = mutableListOf<MutableList<Renderable>>() + val footer = mutableListOf<Renderable>() + val timeUntilCakes = FFStats.cakeExpireTime.passedSince().format(TimeUnit.HOUR, false, false, -1) - var line = if (FFTypes.ANITA.notSaved()) "§cAnita buff not saved\n§eVisit Anita to set it!" - else "§7§2Fortune for levelling your Anita extra crops\n§2You get 4☘ per buff level" - GuiRenderUtils.drawFarmingBar( - "§2Anita Buff", line, FFStats.baseFF[FFTypes.ANITA] ?: 0.0, 60, FFGuideGUI.guiLeft + 15, - FFGuideGUI.guiTop + 30, 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay + content.addTable( + 0, + FFInfos.UNIVERSAL.bar( + "§6Universal Farming Fortune", + "§7§2Farming fortune in that is\n§2applied to every crop\n§eNot the same as tab FF\n" + + "§eSee on the grass block page" + ) + ) + + content.addTable( + 1, + FFInfos.ANITA_BUFF.bar( + "§2Anita Buff", if (FFTypes.ANITA.notSaved()) "§cAnita buff not saved\n§eVisit Anita to set it!" + else "§7§2Fortune for levelling your Anita extra crops\n§2You get 4☘ per buff level" + ) ) - line = if (FFTypes.FARMING_LVL.notSaved()) "§cFarming level not saved\n§eOpen /skills to set it!" - else "§7§2Fortune for levelling your farming skill\n§2You get 4☘ per farming level" - GuiRenderUtils.drawFarmingBar( - "§2Farming Level", line, FFStats.baseFF[FFTypes.FARMING_LVL] ?: 0.0, 240, FFGuideGUI.guiLeft + 15, - FFGuideGUI.guiTop + 55, 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay + content.addTable( + 2, + FFInfos.FARMING_LEVEL.bar( + "§2Farming Level", + if (FFTypes.FARMING_LVL.notSaved()) "§cFarming level not saved\n§eOpen /skills to set it!" + else "§7§2Fortune for levelling your farming skill\n§2You get 4☘ per farming level" + ) ) - line = - if (FFTypes.COMMUNITY_SHOP.notSaved()) "§cCommunity upgrade level not saved\n§eVisit Elizabeth to set it!" - else "§7§2Fortune for community shop upgrades\n§2You get 4☘ per upgrade tier" - GuiRenderUtils.drawFarmingBar( - "§2Community upgrades", line, FFStats.baseFF[FFTypes.COMMUNITY_SHOP] ?: 0.0, - 40, FFGuideGUI.guiLeft + 15, FFGuideGUI.guiTop + 80, 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay + content.addTable( + 3, + FFInfos.COMMUNITY_SHOP.bar( + "§2Community upgrades", + if (FFTypes.COMMUNITY_SHOP.notSaved()) "§cCommunity upgrade level not saved\n§eVisit Elizabeth to set it!" + else "§7§2Fortune for community shop upgrades\n§2You get 4☘ per upgrade tier" + ) ) - line = - if (FFTypes.PLOTS.notSaved()) "§cUnlocked plot count not saved\n§eOpen /desk and view your plots to set it!" - else "§7§2Fortune for unlocking garden plots\n§2You get 3☘ per plot unlocked" - GuiRenderUtils.drawFarmingBar( - "§2Garden Plots", line, FFStats.baseFF[FFTypes.PLOTS] ?: 0.0, 72, FFGuideGUI.guiLeft + 15, - FFGuideGUI.guiTop + 105, 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay + content.addTable( + 4, + FFInfos.GARDEN_PLOTS.bar( + "§2Garden Plots", + if (FFTypes.PLOTS.notSaved()) "§cUnlocked plot count not saved\n§eOpen /desk and view your plots to set it!" + else "§7§2Fortune for unlocking garden plots\n§2You get 3☘ per plot unlocked" + ) ) - line = when (FFStats.cakeExpireTime) { - -1L -> "§eYou have not eaten a cake since\n§edownloading this update, assuming the\n§ebuff is active!" - else -> "§7§2Fortune for eating cake\n§2You get 5☘ for eating cake\n§2Time until cake buff runs out: $timeUntilCakes" - } - if (FFStats.cakeExpireTime - System.currentTimeMillis() < 0 && FFStats.cakeExpireTime != -1L) { - line = "§cYour cake buff has run out\nGo eat some cake!" - } - GuiRenderUtils.drawFarmingBar( - "§2Cake Buff", line, FFStats.baseFF[FFTypes.CAKE] ?: 0.0, 5, FFGuideGUI.guiLeft + 15, - FFGuideGUI.guiTop + 130, 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay - ) + content.addTable( + 5, + FFInfos.CAKE_BUFF.bar( + "§2Cake Buff", when { + FFStats.cakeExpireTime.isFarPast() -> "§eYou have not eaten a cake since\n§edownloading this update, assuming the\n§ebuff is active!" + FFStats.cakeExpireTime.isInPast() -> "§cYour cake buff has run out\nGo eat some cake!" + else -> "§7§2Fortune for eating cake\n§2You get 5☘ for eating cake\n§2Time until cake buff runs out: $timeUntilCakes" + } + ) + ) + + val armorName = FarmingItems.currentArmor?.getItem()?.displayName ?: "" + + val wordArmor = if (FarmingItems.currentArmor == null) "Armor" else "Piece" + + + content.addTable( + 1, + FFInfos.TOTAL_ARMOR.bar( + "§2Total $wordArmor Fortune", + if (FarmingItems.currentArmor == null) "§7§2Total fortune from your armor\n§2Select a piece for more info" + else "§7§2Total fortune from your\n$armorName" + ) + ) + + content.addTable( + 2, + FFInfos.BASE_ARMOR.bar( + "§2Base $wordArmor Fortune", + if (FarmingItems.currentArmor == null) "§7§2The base fortune from your armor\n§2Select a piece for more info" + else "§7§2Base fortune from your\n$armorName" + ) + ) + + content.addTable( + 3, + FFInfos.ABILITY_ARMOR.bar( + "§2$wordArmor Ability", + if (FarmingItems.currentArmor == null) "§7§2The fortune from your armor's ability\n§2Select a piece for more info" + else "§7§2Ability fortune from your\n$armorName" + ) + ) + + content.addTable( + 4, + FFInfos.REFORGE_ARMOR.bar( + "§2$wordArmor Reforge", + if (FarmingItems.currentArmor == null) "§7§2The fortune from your armor's reforge\n§2Select a piece for more info" + else "§7§2Total fortune from your\n$armorName}" + ) + ) + + footer.add( + FFInfos.TOTAL_PET.bar("§2Total Pet Fortune", "§7§2The total fortune from your pet and its item") + ) - val armorItem = when (currentArmor) { - 1 -> FarmingItems.HELMET - 2 -> FarmingItems.CHESTPLATE - 3 -> FarmingItems.LEGGINGS - else -> FarmingItems.BOOTS - } - - armorFF = when (currentArmor) { - 1 -> FFStats.helmetFF - 2 -> FFStats.chestplateFF - 3 -> FFStats.leggingsFF - 4 -> FFStats.bootsFF - else -> FFStats.armorTotalFF - } - - var word = if (currentArmor == 0) "Armor" else "Piece" - - line = if (currentArmor == 0) "§7§2Total fortune from your armor\n§2Select a piece for more info" - else "§7§2Total fortune from your\n${armorItem.getItem().displayName}" - var value = if (FFStats.usingSpeedBoots) { - when (currentArmor) { - 0 -> 421 - 1 -> 101.67 - 2, 3 -> 106.67 - 4 -> 106 - else -> 0 - } - } else { - when (currentArmor) { - 0 -> 425 - 1, 4 -> 103.75 - 2, 3 -> 108.75 - else -> 0 - } - } - GuiRenderUtils.drawFarmingBar( - "§2Total $word Fortune", line, armorFF[FFTypes.TOTAL] ?: 0, value, - FFGuideGUI.guiLeft + 135, FFGuideGUI.guiTop + 30, 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay - ) + footer.add( + FFInfos.PET_ITEM.bar( + "§2Pet Item", when (FFStats.currentPetItem) { + "GREEN_BANDANA" -> "§7§2The fortune from your pet's item\n§2Grants 4☘ per garden level" + "YELLOW_BANDANA" -> "§7§2The fortune from your pet's item" + "MINOS_RELIC" -> "§cGreen Bandana is better for fortune than minos relic!" + else -> "No fortune boosting pet item" + } + ) + ) + + val wordEquip = if (FarmingItems.currentEquip == null) "Equipment" else "Piece" - line = if (currentArmor == 0) "§7§2The base fortune from your armor\n§2Select a piece for more info" - else "§7§2Base fortune from your\n${armorItem.getItem().displayName}" - value = when (currentArmor) { - 0 -> if (FFStats.usingSpeedBoots) 160 else 130 - 1 -> 30 - 2 -> 35 - 3 -> 35 - else -> if (FFStats.usingSpeedBoots) 60 else 30 - } - GuiRenderUtils.drawFarmingBar( - "§2Base $word Fortune", line, armorFF[FFTypes.BASE] ?: 0, - value, FFGuideGUI.guiLeft + 135, - FFGuideGUI.guiTop + 55, 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay - ) + val equipmentName = FarmingItems.currentEquip?.getItem()?.displayName ?: "" - line = if (currentArmor == 0) "§7§2The fortune from your armor's ability\n§2Select a piece for more info" - else "§7§2Ability fortune from your\n${armorItem.getItem().displayName}" - value = if (FFStats.usingSpeedBoots) { - when (currentArmor) { - 0 -> 50 - 4 -> 0 - else -> 16.667 - } - } else { - when (currentArmor) { - 0 -> 75 - else -> 18.75 - } - } - - GuiRenderUtils.drawFarmingBar( - "§2$word Ability", line, armorFF[FFTypes.ABILITY] ?: 0, - value, FFGuideGUI.guiLeft + 135, - FFGuideGUI.guiTop + 80, 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay + content.addTable( + 1, + FFInfos.TOTAL_EQUIP.bar( + "§2Total $wordEquip Fortune", + if (FarmingItems.currentEquip == null) "§7§2Total fortune from all your equipment\n§2Select a piece for more info" + else "§7§2Total fortune from your\n$equipmentName" + ) ) - line = if (currentArmor == 0) "§7§2The fortune from your armor's reforge\n§2Select a piece for more info" - else "§7§2Total fortune from your\n${armorItem.getItem().displayName}" - value = if (currentArmor == 0) { - if (FFStats.usingSpeedBoots) 115 else 120 - } else if (currentArmor == 4) { - if (FFStats.usingSpeedBoots) 25 else 30 - } else 30 - GuiRenderUtils.drawFarmingBar( - "§2$word Reforge", line, armorFF[FFTypes.REFORGE] ?: 0, - value, FFGuideGUI.guiLeft + 135, - FFGuideGUI.guiTop + 105, 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay - ) - var currentPet = FFStats.rabbitFF - var petMaxFF = 60 - when (FFGuideGUI.currentPet) { - FarmingItems.ELEPHANT -> { - currentPet = FFStats.elephantFF - petMaxFF = 210 - } - - FarmingItems.MOOSHROOM_COW -> { - currentPet = FFStats.mooshroomFF - petMaxFF = 217 - } - - FarmingItems.BEE -> { - currentPet = FFStats.beeFF - petMaxFF = 90 - } - - else -> {} - } - - GuiRenderUtils.drawFarmingBar( - "§2Total Pet Fortune", "§7§2The total fortune from your pet and its item", - currentPet[FFTypes.TOTAL] ?: 0, petMaxFF, FFGuideGUI.guiLeft + 105, - FFGuideGUI.guiTop + 155, 70, mouseX, mouseY, FFGuideGUI.tooltipToDisplay + content.addTable( + 2, + FFInfos.BASE_EQUIP.bar( + "§2$wordEquip Base Fortune", + if (FarmingItems.currentEquip == null) "§7§2The base fortune from all your equipment\n§2Select a piece for more info" + else "§7§2Total base fortune from your\n$equipmentName" + ) ) - line = when (FFStats.currentPetItem) { - "GREEN_BANDANA" -> "§7§2The fortune from your pet's item\n§2Grants 4☘ per garden level" - "YELLOW_BANDANA" -> "§7§2The fortune from your pet's item" - "MINOS_RELIC" -> "§cGreen Bandana is better for fortune than minos relic!" - else -> "No fortune boosting pet item" - } - GuiRenderUtils.drawFarmingBar( - "§2Pet Item", line, currentPet[FFTypes.PET_ITEM] ?: 0, 60, FFGuideGUI.guiLeft + 185, - FFGuideGUI.guiTop + 155, 70, mouseX, mouseY, FFGuideGUI.tooltipToDisplay + content.addTable( + 3, + FFInfos.ABILITY_EQUIP.bar( + "§2$wordEquip Ability", + if (FarmingItems.currentEquip == null) "§7§2The fortune from all of your equipment's abilities\n§2Select a piece for more info" + else "§7§2Total ability fortune from your\n$equipmentName" + ) ) - word = if (currentEquipment == 0) "Equipment" else "Piece" - - val equipmentItem = when (currentEquipment) { - 1 -> FarmingItems.NECKLACE - 2 -> FarmingItems.CLOAK - 3 -> FarmingItems.BELT - else -> FarmingItems.BRACELET - } - - equipmentFF = when (currentEquipment) { - 1 -> FFStats.necklaceFF - 2 -> FFStats.cloakFF - 3 -> FFStats.beltFF - 4 -> FFStats.braceletFF - else -> FFStats.equipmentTotalFF - } - - val maxEquipmentBaseFortune = 5.0 - val maxEquipmentAbilityFortune = 15.0 - val maxEquipmentReforgeFortune = 15.0 - val maxGreenThumbFortune = GardenAPI.totalAmountVisitorsExisting.toDouble() / 4 - - val maxFortunePerPiece = - maxEquipmentBaseFortune + maxEquipmentAbilityFortune + maxEquipmentReforgeFortune + maxGreenThumbFortune - - line = if (currentEquipment == 0) "§7§2Total fortune from all your equipment\n§2Select a piece for more info" - else "§7§2Total fortune from your\n${equipmentItem.getItem().displayName}" - GuiRenderUtils.drawFarmingBar( - "§2Total $word Fortune", line, equipmentFF[FFTypes.TOTAL] ?: 0, - if (currentEquipment == 0) maxFortunePerPiece * 4 else maxFortunePerPiece, - - FFGuideGUI.guiLeft + 255, FFGuideGUI.guiTop + 30, 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay + content.addTable( + 4, + FFInfos.REFORGE_EQUIP.bar( + "§2$wordEquip Reforge", + if (FarmingItems.currentEquip == null) "§7§2The fortune from all of your equipment's reforges\n§2Select a piece for more info" + else "§7§2Total reforge fortune from your\n$equipmentName" + ) ) - line = if (currentEquipment == 0) "§7§2The base fortune from all your equipment\n§2Select a piece for more info" - else "§7§2Total base fortune from your\n${equipmentItem.getItem().displayName}" - GuiRenderUtils.drawFarmingBar( - "§2$word Base Fortune", line, equipmentFF[FFTypes.BASE] ?: 0, - if (currentEquipment == 0) maxEquipmentBaseFortune * 4 else maxEquipmentBaseFortune, - FFGuideGUI.guiLeft + 255, FFGuideGUI.guiTop + 55, 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay - ) + content.addTable( + 5, + Renderable.horizontalContainer( + FarmingItems.getPetsDisplay(true), + 4, + horizontalAlign = RenderUtils.HorizontalAlignment.CENTER, + verticalAlign = RenderUtils.VerticalAlignment.CENTER + ) + ) + + content.addTable( + 5, + FFInfos.ENCHANT_EQUIP.bar( + "§2$wordEquip Enchantment", + if (FarmingItems.currentEquip == null) "§7§2The fortune from all of your equipment's enchantments\n§2Select a piece for more info" + else "§7§2Total enchantment fortune from your\n${FarmingItems.currentEquip!!.getItem().displayName}" + ) + ) + + // Displays - line = - if (currentEquipment == 0) "§7§2The fortune from all of your equipment's abilities\n§2Select a piece for more info" - else "§7§2Total ability fortune from your\n${equipmentItem.getItem().displayName}" - GuiRenderUtils.drawFarmingBar( - "§2$word Ability", line, equipmentFF[FFTypes.ABILITY] ?: 0, - if (currentEquipment == 0) maxEquipmentAbilityFortune * 4 else maxEquipmentAbilityFortune, - FFGuideGUI.guiLeft + 255, FFGuideGUI.guiTop + 80, 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay + content.addTable( + 0, + Renderable.horizontalContainer( + FarmingItems.getArmorDisplay(true), + 4, + horizontalAlign = RenderUtils.HorizontalAlignment.CENTER, + verticalAlign = RenderUtils.VerticalAlignment.CENTER + ) ) - - line = - if (currentEquipment == 0) "§7§2The fortune from all of your equipment's reforges\n§2Select a piece for more info" - else "§7§2Total reforge fortune from your\n${equipmentItem.getItem().displayName}" - GuiRenderUtils.drawFarmingBar( - "§2$word Reforge", line, equipmentFF[FFTypes.REFORGE] ?: 0, - if (currentEquipment == 0) maxEquipmentReforgeFortune * 4 else maxEquipmentReforgeFortune, - FFGuideGUI.guiLeft + 255, FFGuideGUI.guiTop + 105, 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay + content.addTable( + 0, + Renderable.horizontalContainer( + FarmingItems.getEquipmentDisplay(true), + 4, + horizontalAlign = RenderUtils.HorizontalAlignment.CENTER, + verticalAlign = RenderUtils.VerticalAlignment.CENTER + ) ) - line = - if (currentEquipment == 0) "§7§2The fortune from all of your equipment's enchantments\n§2Select a piece for more info" - else "§7§2Total enchantment fortune from your\n${equipmentItem.getItem().displayName}" - GuiRenderUtils.drawFarmingBar( - "§2$word Enchantment", line, equipmentFF[FFTypes.GREEN_THUMB] ?: 0, - if (currentEquipment == 0) maxGreenThumbFortune * 4 else maxGreenThumbFortune, - FFGuideGUI.guiLeft + 255, FFGuideGUI.guiTop + 130, 90, mouseX, mouseY, FFGuideGUI.tooltipToDisplay - ) + + return content to footer } private fun FFTypes.notSaved(): Boolean = FFStats.baseFF[this]?.let { it < 0.0 } ?: true } + +private fun MutableList<MutableList<Renderable>>.addTable(row: Int, r: Renderable) { + this.getOrNull(row)?.add(r) ?: mutableListOf(r).let { this.add(row, it) } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/pages/UpgradePage.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/pages/UpgradePage.kt index e8134a337..2323b5e30 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/pages/UpgradePage.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/pages/UpgradePage.kt @@ -1,126 +1,103 @@ package at.hannibal2.skyhanni.features.garden.fortuneguide.pages -import at.hannibal2.skyhanni.features.garden.fortuneguide.FFGuideGUI +import at.hannibal2.skyhanni.features.garden.CropType +import at.hannibal2.skyhanni.features.garden.fortuneguide.FarmingItems +import at.hannibal2.skyhanni.features.garden.fortuneguide.FortuneUpgrade import at.hannibal2.skyhanni.features.garden.fortuneguide.FortuneUpgrades -import at.hannibal2.skyhanni.features.inventory.bazaar.BazaarApi -import at.hannibal2.skyhanni.utils.GuiRenderUtils import at.hannibal2.skyhanni.utils.ItemUtils.itemName -import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName import at.hannibal2.skyhanni.utils.NEUItems.getItemStack import at.hannibal2.skyhanni.utils.NumberUtil -import net.minecraft.client.renderer.GlStateManager -import net.minecraft.util.MathHelper +import at.hannibal2.skyhanni.utils.RenderUtils.HorizontalAlignment +import at.hannibal2.skyhanni.utils.RenderUtils.VerticalAlignment +import at.hannibal2.skyhanni.utils.guide.GuideScrollPage +import at.hannibal2.skyhanni.utils.renderables.Renderable import java.text.DecimalFormat -class UpgradePage : FFGuideGUI.FFGuidePage() { +class UpgradePage(val crop0: () -> CropType?, sizeX: Int, sizeY: Int, paddingX: Int = 15, paddingY: Int = 7) : + GuideScrollPage( + sizeX, + sizeY, + paddingX, + paddingY, + marginY = 10, + hasHeader = true, + ) { - private var pageScroll = 0 - private var scrollVelocity = 0.0 - private val maxNoInputFrames = 100 - private var listLength = 0 + val crop get() = crop0() - override fun drawPage(mouseX: Int, mouseY: Int, partialTicks: Float) { - val adjustedY = FFGuideGUI.guiTop + 20 + pageScroll - val inverseScale = 1 / 0.75f + override fun onEnter() { + crop?.let { + FortuneUpgrades.getCropSpecific(it.farmingItem.getItemOrNull()) + } ?: { + FortuneUpgrades.getCropSpecific(null) // TODO + } - // TODO fix duplicate drawString lines, add guiLeft, guiTop and inverseScale - GlStateManager.scale(0.75f, 0.75f, 1f) - GuiRenderUtils.drawString( - "Upgrade", - (FFGuideGUI.guiLeft + 45) * inverseScale, - (FFGuideGUI.guiTop + 5) * inverseScale - ) - GuiRenderUtils.drawString( - "Item", - (FFGuideGUI.guiLeft + 190) * inverseScale, - (FFGuideGUI.guiTop + 5) * inverseScale - ) - GuiRenderUtils.drawString( - "FF increase", - (FFGuideGUI.guiLeft + 240) * inverseScale, - (FFGuideGUI.guiTop + 5) * inverseScale - ) - GuiRenderUtils.drawString( - "Cost/FF", - (FFGuideGUI.guiLeft + 290) * inverseScale, - (FFGuideGUI.guiTop + 5) * inverseScale + FarmingItems.resetClickState() + update( + content = buildList { + add(header()) + val upgradeList = if (crop == null) + FortuneUpgrades.genericUpgrades + else + FortuneUpgrades.cropSpecificUpgrades + addAll(upgradeList.map { upgrade -> upgrade.print() }) + } ) - GuiRenderUtils.drawString( - "Total", - (FFGuideGUI.guiLeft + 330) * inverseScale, - (FFGuideGUI.guiTop + 5) * inverseScale + } + + private fun header() = listOf("Upgrade", "", "Item", "FF", "Cost/FF", "Total").map { + Renderable.string( + it, + 0.9, + horizontalAlign = HorizontalAlignment.CENTER ) + } - val upgradeList = - if (FFGuideGUI.currentCrop == null) FortuneUpgrades.genericUpgrades else FortuneUpgrades.cropSpecificUpgrades - listLength = upgradeList.size - for ((index, upgrade) in upgradeList.withIndex()) { - if (adjustedY + 25 * index < FFGuideGUI.guiTop + 20) continue - if (adjustedY + 25 * index > FFGuideGUI.guiTop + 160) continue - val upgradeItem = upgrade.requiredItem.asInternalName().getItemStack() - var formattedUpgrade = upgradeItem.itemName - if (adjustedY + 25 * index - 5 < FFGuideGUI.lastClickedHeight && FFGuideGUI.lastClickedHeight < adjustedY + 25 * index + 10) { - FFGuideGUI.lastClickedHeight = 0 - BazaarApi.searchForBazaarItem(formattedUpgrade, upgrade.itemQuantity) - } - if (upgrade.itemQuantity != 1) { - formattedUpgrade = "$formattedUpgrade §fx${upgrade.itemQuantity}" - } - GuiRenderUtils.drawTwoLineString( - upgrade.description, - (FFGuideGUI.guiLeft + 15) * inverseScale, - (adjustedY + 25 * index) * inverseScale + private fun FortuneUpgrade.print() = buildList { + add( + Renderable.wrappedString( + description, + 136, + 0.75, + verticalAlign = VerticalAlignment.CENTER ) - GuiRenderUtils.renderItemAndTip( - FFGuideGUI.tooltipToDisplay, - upgradeItem, - (FFGuideGUI.guiLeft + 155) * inverseScale, - (adjustedY + 25 * index - 5) * inverseScale, - mouseX * inverseScale, - mouseY * inverseScale, - 0x00FFFFFF + ) + add( + Renderable.itemStackWithTip( + requiredItem.getItemStack(), + 8.0 / 9.0, + verticalAlign = VerticalAlignment.CENTER ) - GuiRenderUtils.drawString( - formattedUpgrade, - (FFGuideGUI.guiLeft + 180) * inverseScale, - (adjustedY + 25 * index) * inverseScale + ) + add( + Renderable.wrappedString( + requiredItem.itemName.let { if (itemQuantity == 1) it else "$it §fx$itemQuantity" }, // TODO wtf + 70, + 0.75, + verticalAlign = VerticalAlignment.CENTER ) - GuiRenderUtils.drawString( - "§a${DecimalFormat("0.##").format(upgrade.fortuneIncrease)}", - (FFGuideGUI.guiLeft + 270) * inverseScale, - (adjustedY + 25 * index) * inverseScale + ) + add( + Renderable.string( + "§a${DecimalFormat("0.##").format(fortuneIncrease)}", + horizontalAlign = HorizontalAlignment.CENTER, + verticalAlign = VerticalAlignment.CENTER ) - GuiRenderUtils.drawString( - "§6" + upgrade.costPerFF?.let { NumberUtil.format(it) }, - (FFGuideGUI.guiLeft + 300) * inverseScale, - (adjustedY + 25 * index) * inverseScale + ) // TODO cleaner formating + add( + Renderable.string( + "§6" + costPerFF?.let { NumberUtil.format(it) }, + horizontalAlign = HorizontalAlignment.CENTER, + verticalAlign = VerticalAlignment.CENTER ) - GuiRenderUtils.drawString( - ("§6" + upgrade.cost?.let { NumberUtil.format(it) }), - (FFGuideGUI.guiLeft + 335) * inverseScale, - (adjustedY + 25 * index) * inverseScale + ) + add( + Renderable.string( + "§6" + cost?.let { NumberUtil.format(it) }, + horizontalAlign = HorizontalAlignment.CENTER, + verticalAlign = VerticalAlignment.CENTER ) - } - GlStateManager.scale(inverseScale, inverseScale, 1f) - scrollScreen() - } - - private fun scrollScreen() { - scrollVelocity += FFGuideGUI.lastMouseScroll / 48.0 - scrollVelocity *= 0.95 - pageScroll += scrollVelocity.toInt() + FFGuideGUI.lastMouseScroll / 24 - - FFGuideGUI.noMouseScrollFrames++ - - if (FFGuideGUI.noMouseScrollFrames >= maxNoInputFrames) { - scrollVelocity *= 0.75 - } - - if (pageScroll > 0) { - pageScroll = 0 - } - - pageScroll = MathHelper.clamp_int(pageScroll, -(listLength * 15 - 15), 0) - FFGuideGUI.lastMouseScroll = 0 + ) } } + diff --git a/src/main/java/at/hannibal2/skyhanni/utils/CollectionUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/CollectionUtils.kt index 2e1237fe8..48cf1ccb2 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/CollectionUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/CollectionUtils.kt @@ -2,11 +2,13 @@ package at.hannibal2.skyhanni.utils import at.hannibal2.skyhanni.utils.NEUItems.getItemStack import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.RenderableUtils import net.minecraft.enchantment.Enchantment import net.minecraft.item.ItemStack import java.util.Collections import java.util.Queue import java.util.WeakHashMap +import kotlin.math.ceil object CollectionUtils { @@ -279,6 +281,38 @@ object CollectionUtils { })) } + fun Collection<Collection<Renderable>>.tableStretchXPadding(xSpace: Int): Int { + if (this.isEmpty()) return xSpace + val off = RenderableUtils.calculateTableXOffsets(this as List<List<Renderable?>>, 0) + val xLength = off.size - 1 + val emptySpace = xSpace - off.last() + if (emptySpace < 0) { + // throw IllegalArgumentException("Not enough space for content") + } + return emptySpace / (xLength - 1) + } + + fun Collection<Collection<Renderable>>.tableStretchYPadding(ySpace: Int): Int { + if (this.isEmpty()) return ySpace + val off = RenderableUtils.calculateTableYOffsets(this as List<List<Renderable?>>, 0) + val yLength = off.size - 1 + val emptySpace = ySpace - off.last() + if (emptySpace < 0) { + // throw IllegalArgumentException("Not enough space for content") + } + return emptySpace / (yLength - 1) + } + + /** Splits the input into equal sized lists. If the list can't get divided clean by [subs] then the last entry gets reduced. e.g. 13/4 = [4,4,4,1]*/ + fun <T> Collection<T>.split(subs: Int = 2): List<List<T>> { + if (this.isEmpty()) return listOf(emptyList()) + val list = this.chunked(ceil(this.size.toDouble() / subs.toDouble()).toInt()).toMutableList() + while (list.size < subs) { + list.add(emptyList()) + } + return list + } + inline fun <K, V, R : Any> Map<K, V>.mapKeysNotNull(transform: (Map.Entry<K, V>) -> R?): Map<R, V> { val destination = LinkedHashMap<R, V>() for (element in this) { @@ -290,6 +324,15 @@ object CollectionUtils { return destination } + inline fun <T, C : Number, D : Number> Iterable<T>.sumOfPair(selector: (T) -> Pair<C, D>): Pair<Double, Double> { + var sum = Pair(0.0, 0.0) + for (element in this) { + val add = selector(element) + sum = sum.first + add.first.toDouble() to sum.second + add.second.toDouble() + } + return sum + } + inline fun <T, R> Iterable<T>.zipWithNext3(transform: (a: T, b: T, c: T) -> R): List<R> { val iterator = iterator() if (!iterator.hasNext()) return emptyList() diff --git a/src/main/java/at/hannibal2/skyhanni/utils/GuiRenderUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/GuiRenderUtils.kt index e68af00ca..403484fcd 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/GuiRenderUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/GuiRenderUtils.kt @@ -3,6 +3,10 @@ package at.hannibal2.skyhanni.utils import at.hannibal2.skyhanni.config.features.skillprogress.SkillProgressBarConfig import at.hannibal2.skyhanni.features.chroma.ChromaShaderManager import at.hannibal2.skyhanni.features.chroma.ChromaType +import at.hannibal2.skyhanni.utils.LorenzUtils.round +import at.hannibal2.skyhanni.utils.NumberUtil.fractionOf +import at.hannibal2.skyhanni.utils.RenderUtils.HorizontalAlignment +import at.hannibal2.skyhanni.utils.renderables.Renderable import io.github.moulberry.notenoughupdates.util.Utils import net.minecraft.client.Minecraft import net.minecraft.client.gui.FontRenderer @@ -17,11 +21,11 @@ import java.awt.Color import java.text.DecimalFormat import kotlin.math.ceil import kotlin.math.min -import kotlin.math.roundToInt /** * Some functions taken from NotEnoughUpdates */ +// TODO cleanup of redundant functions object GuiRenderUtils { fun drawStringCentered(str: String?, fr: FontRenderer, x: Float, y: Float, shadow: Boolean, colour: Int) { @@ -71,12 +75,7 @@ object GuiRenderUtils { fun drawStringCentered(str: String?, x: Int, y: Int) { drawStringCentered( - str, - Minecraft.getMinecraft().fontRendererObj, - x.toFloat(), - y.toFloat(), - true, - 0xffffff + str, Minecraft.getMinecraft().fontRendererObj, x.toFloat(), y.toFloat(), true, 0xffffff ) } @@ -126,30 +125,33 @@ object GuiRenderUtils { if (tooltipY + tooltipHeight + 6 > screenHeight) tooltipY = screenHeight - tooltipHeight - 6 // main background GuiScreen.drawRect( - tooltipX - 3, tooltipY - 3, - tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3, -0xfeffff0 + tooltipX - 3, tooltipY - 3, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3, -0xfeffff0 ) // borders GuiScreen.drawRect( - tooltipX - 3, tooltipY - 3 + 1, - tooltipX - 3 + 1, tooltipY + tooltipHeight + 3 - 1, borderColor + tooltipX - 3, tooltipY - 3 + 1, tooltipX - 3 + 1, tooltipY + tooltipHeight + 3 - 1, borderColor ) GuiScreen.drawRect( - tooltipX + tooltipTextWidth + 2, tooltipY - 3 + 1, - tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3 - 1, borderColor + tooltipX + tooltipTextWidth + 2, + tooltipY - 3 + 1, + tooltipX + tooltipTextWidth + 3, + tooltipY + tooltipHeight + 3 - 1, + borderColor ) GuiScreen.drawRect( - tooltipX - 3, tooltipY - 3, - tooltipX + tooltipTextWidth + 3, tooltipY - 3 + 1, borderColor + tooltipX - 3, tooltipY - 3, tooltipX + tooltipTextWidth + 3, tooltipY - 3 + 1, borderColor ) GuiScreen.drawRect( - tooltipX - 3, tooltipY + tooltipHeight + 2, - tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3, borderColor + tooltipX - 3, + tooltipY + tooltipHeight + 2, + tooltipX + tooltipTextWidth + 3, + tooltipY + tooltipHeight + 3, + borderColor ) GlStateManager.translate(0f, 0f, -100f) GlStateManager.disableDepth() @@ -175,109 +177,38 @@ object GuiRenderUtils { fun isPointInRect(x: Int, y: Int, left: Int, top: Int, width: Int, height: Int) = left <= x && x < left + width && top <= y && y < top + height - fun drawProgressBar(x: Int, y: Int, barWidth: Int, progress: Float) { - GuiScreen.drawRect(x, y, x + barWidth, y + 6, 0xFF43464B.toInt()) - val width = barWidth * progress - GuiScreen.drawRect(x + 1, y + 1, (x + width).toInt() + 1, y + 5, 0xFF00FF00.toInt()) - if (progress != 1f) GuiScreen.drawRect( - (x + width).toInt() + 1, - y + 1, - x + barWidth - 1, - y + 5, - 0xFF013220.toInt() - ) - } - - fun renderItemAndTip( - list: MutableList<String>, - item: ItemStack?, - x: Int, - y: Int, - mouseX: Int, - mouseY: Int, - color: Int = 0xFF43464B.toInt(), - ) { - GuiScreen.drawRect(x, y, x + 16, y + 16, color) - if (item != null) { - renderItemStack(item, x, y) - if (isPointInRect(mouseX, mouseY, x, y, 16, 16)) { - val tt: List<String> = item.getTooltip(Minecraft.getMinecraft().thePlayer, false) - list.addAll(tt) - } - } - } - - fun renderItemAndTip( - list: MutableList<String>, - item: ItemStack?, - x: Float, - y: Float, - mouseX: Float, - mouseY: Float, - color: Int = 0xFF43464B.toInt(), - ) { - renderItemAndTip(list, item, x.toInt(), y.toInt(), mouseX.toInt(), mouseY.toInt(), color) - } - - // assuming 70% font size - fun drawFarmingBar( + fun getFarmingBar( label: String, tooltip: String, currentValue: Number, maxValue: Number, - xPos: Int, - yPos: Int, width: Int, - mouseX: Int, - mouseY: Int, - output: MutableList<String>, textScale: Float = .7f, - ) { - var currentVal = currentValue.toDouble() - currentVal = if (currentVal < 0) 0.0 else currentVal - - var barProgress = currentVal / maxValue.toFloat() - if (maxValue == 0) barProgress = 1.0 - barProgress = when { - barProgress > 1 -> 1.0 - barProgress < 0 -> 0.0 - else -> barProgress - } - - val filledWidth = (width * barProgress).toInt() - val current = DecimalFormat("0.##").format(currentVal) - val progressPercentage = (barProgress * 10000).roundToInt() / 100 - val inverseScale = 1 / textScale - val textWidth: Int = Minecraft.getMinecraft().fontRendererObj.getStringWidth("$progressPercentage%") - val barColor = barColorGradient(barProgress) - - GlStateManager.scale(textScale, textScale, 1f) - drawString(label, xPos * inverseScale, yPos * inverseScale) - drawString( - "§2$current / ${DecimalFormat("0.##").format(maxValue)}☘", - xPos * inverseScale, - (yPos + 8) * inverseScale - ) - drawString( - "§2$progressPercentage%", - (xPos + width - textWidth * textScale) * inverseScale, - (yPos + 8) * inverseScale - ) - GlStateManager.scale(inverseScale, inverseScale, 1f) - - GuiScreen.drawRect(xPos, yPos + 16, xPos + width, yPos + 20, 0xFF43464B.toInt()) - GuiScreen.drawRect(xPos + 1, yPos + 17, xPos + width - 1, yPos + 19, barColor.darkenColor()) - GuiScreen.drawRect( - xPos + 1, yPos + 17, - if (filledWidth < 2) xPos + 1 else xPos + filledWidth - 1, yPos + 19, barColor - ) - - if (tooltip != "" && isPointInRect(mouseX, mouseY, xPos - 2, yPos - 2, width + 4, 20 + 4)) { - val split = tooltip.split("\n") - for (line in split) { - output.add(line) - } - } + ): Renderable { + val current = currentValue.toDouble().coerceAtLeast(0.0) + val percent = current.fractionOf(maxValue) + val scale = textScale.toDouble() + return Renderable.hoverTips(Renderable.verticalContainer( + listOf( + Renderable.string(label, scale = scale), + Renderable.fixedSizeLine( + listOf( + Renderable.string( + "§2${DecimalFormat("0.##").format(current)} / ${ + DecimalFormat( + "0.##" + ).format(maxValue) + }☘", scale = scale, horizontalAlign = HorizontalAlignment.LEFT + ), + Renderable.string( + "§2${(percent * 100).round(1)}%", + scale = scale, + horizontalAlign = HorizontalAlignment.RIGHT + ), + ), width + ), Renderable.progressBar(percent, width = width) + ) + ), tooltip.split('\n').map { Renderable.string(it) }) } private fun barColorGradient(double: Double): Int { @@ -293,8 +224,11 @@ object GuiRenderUtils { fun drawScaledRec(left: Int, top: Int, right: Int, bottom: Int, colour: Int, inverseScale: Float) { GuiScreen.drawRect( - (left * inverseScale).toInt(), (top * inverseScale).toInt(), - (right * inverseScale).toInt(), (bottom * inverseScale).toInt(), colour + (left * inverseScale).toInt(), + (top * inverseScale).toInt(), + (right * inverseScale).toInt(), + (bottom * inverseScale).toInt(), + colour ) } @@ -339,15 +273,7 @@ object GuiRenderUtils { Utils.drawTexturedRect(x, y, w_2.toFloat(), height, 0f, w_2 / xSize, vMinEmpty, vMaxEmpty, GL11.GL_NEAREST) Utils.drawTexturedRect( - x + w_2, - y, - w_2.toFloat(), - height, - 1 - w_2 / xSize, - 1f, - vMinEmpty, - vMaxEmpty, - GL11.GL_NEAREST + x + w_2, y, w_2.toFloat(), height, 1 - w_2 / xSize, 1f, vMinEmpty, vMaxEmpty, GL11.GL_NEAREST ) if (useChroma) { diff --git a/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt b/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt index 297a40585..cd75e9cf4 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt @@ -217,9 +217,14 @@ object NEUItems { const val itemFontSize = 2.0 / 3.0 - fun ItemStack.renderOnScreen(x: Float, y: Float, scaleMultiplier: Double = itemFontSize) { + fun ItemStack.renderOnScreen( + x: Float, + y: Float, + scaleMultiplier: Double = itemFontSize, + rescaleSkulls: Boolean = true + ) { val item = checkBlinkItem() - val isSkull = item.item === Items.skull + val isSkull = rescaleSkulls && item.item === Items.skull val baseScale = (if (isSkull) 4f / 3f else 1f) val finalScale = baseScale * scaleMultiplier diff --git a/src/main/java/at/hannibal2/skyhanni/utils/guide/GuideGUI.kt b/src/main/java/at/hannibal2/skyhanni/utils/guide/GuideGUI.kt new file mode 100644 index 000000000..944a3201a --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/utils/guide/GuideGUI.kt @@ -0,0 +1,121 @@ +package at.hannibal2.skyhanni.utils.guide + +import at.hannibal2.skyhanni.test.command.ErrorManager +import at.hannibal2.skyhanni.utils.RenderUtils +import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.renderXYAligned +import net.minecraft.client.gui.GuiScreen +import net.minecraft.client.renderer.GlStateManager +import net.minecraft.item.ItemStack + +const val selectedColor = 0x50000000 +const val notSelectedColor = 0x50303030 +const val tabSpacing = 5 +const val tabShortSide = 25 +const val tabLongSide = 28 + +abstract class GuideGUI<pageEnum : Enum<*>>(defaultScreen: pageEnum) : GuiScreen() { + + abstract val sizeX: Int + abstract val sizeY: Int + lateinit var pageList: Map<pageEnum, GuidePage> + lateinit var horizontalTabs: List<GuideTab> + lateinit var verticalTabs: List<GuideTab> + protected var currentPage: pageEnum = defaultScreen + set(value) { + pageList[field]?.onLeave() + pageList[value]?.onEnter() + field = value + } + + val lastVerticalTabWrapper = object : tabWrapper { + override var tab: GuideTab? = null + } + val lastHorizontalTabWrapper = object : tabWrapper { + override var tab: GuideTab? = null + } + + fun hTab(item: ItemStack, tip: Renderable, onClick: (GuideTab) -> Unit) = + GuideTab(item, tip, false, lastHorizontalTabWrapper, onClick) + + fun vTab(item: ItemStack, tip: Renderable, onClick: (GuideTab) -> Unit) = + GuideTab(item, tip, true, lastVerticalTabWrapper, onClick) + + interface tabWrapper { + var tab: GuideTab? + } + + fun refreshPage() { + pageList[currentPage]?.refresh() + } + + private fun renderHorizontalTabs() { + var offset = Pair(tabSpacing.toFloat() * 3f, -tabLongSide.toFloat()) + GlStateManager.translate(offset.first, offset.second, 0f) + for (tab in horizontalTabs) { + tab.render(offset.first.toInt(), offset.second.toInt()) + val xShift = (tabShortSide + tabSpacing).toFloat() + offset = offset.first + xShift to offset.second + GlStateManager.translate(xShift, 0f, 0f) + } + GlStateManager.translate(-offset.first, -offset.second, 0f) + } + + private fun renderVerticalTabs() { + var offset = Pair(-tabLongSide.toFloat(), tabSpacing.toFloat() * 3f) + GlStateManager.translate(offset.first, offset.second, 0f) + for (tab in verticalTabs) { + tab.render(offset.first.toInt(), offset.second.toInt()) + val yShift = (tabShortSide + tabSpacing).toFloat() + offset = offset.first to offset.second + yShift + GlStateManager.translate(0f, yShift, 0f) + } + GlStateManager.translate(-offset.first, -offset.second, 0f) + } + + override fun drawScreen(mouseX: Int, mouseY: Int, partialTicks: Float) = try { + super.drawScreen(mouseX, mouseY, partialTicks) + drawDefaultBackground() + val guiLeft = (width - sizeX) / 2 + val guiTop = (height - sizeY) / 2 + + /* + val mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth + val mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1 + */ + + val relativeMouseX = mouseX - guiLeft + val relativeMouseY = mouseY - guiTop + + GlStateManager.pushMatrix() + GlStateManager.translate(guiLeft.toFloat(), guiTop.toFloat(), 0f) + drawRect(0, 0, sizeX, sizeY, 0x50000000) + + Renderable.withMousePosition(relativeMouseX, relativeMouseY) { + renderHorizontalTabs() + renderVerticalTabs() + + Renderable.string( + "§7SkyHanni ", + horizontalAlign = RenderUtils.HorizontalAlignment.RIGHT, + verticalAlign = RenderUtils.VerticalAlignment.BOTTOM + ).renderXYAligned(0, 0, sizeX, sizeY) + + val page = pageList[currentPage] + page?.drawPage(relativeMouseX, relativeMouseY) + + GlStateManager.translate(-guiLeft.toFloat(), -guiTop.toFloat(), 0f) + } + + GlStateManager.popMatrix() + + } catch (e: Exception) { + GlStateManager.popMatrix() + ErrorManager.logErrorWithData( + e, "Something broke in GuideGUI", + "Guide" to this.javaClass.typeName, + "Page" to currentPage.name + ) + } +} + diff --git a/src/main/java/at/hannibal2/skyhanni/utils/guide/GuidePage.kt b/src/main/java/at/hannibal2/skyhanni/utils/guide/GuidePage.kt new file mode 100644 index 000000000..a563a531c --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/utils/guide/GuidePage.kt @@ -0,0 +1,15 @@ +package at.hannibal2.skyhanni.utils.guide + +abstract class GuidePage { + abstract fun drawPage(mouseX: Int, mouseY: Int) + + abstract fun onEnter() + + abstract fun onLeave() + + fun refresh() { + onLeave() + onEnter() + } + +} diff --git a/src/main/java/at/hannibal2/skyhanni/utils/guide/GuideRenderablePage.kt b/src/main/java/at/hannibal2/skyhanni/utils/guide/GuideRenderablePage.kt new file mode 100644 index 000000000..ce68a4afe --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/utils/guide/GuideRenderablePage.kt @@ -0,0 +1,23 @@ +package at.hannibal2.skyhanni.utils.guide + +import at.hannibal2.skyhanni.utils.renderables.Renderable +import net.minecraft.client.renderer.GlStateManager + +abstract class GuideRenderablePage( + val paddingX: Int = 0, + val paddingY: Int = 0 +) : GuidePage() { + + protected var renderable: Renderable? = null + + final override fun drawPage(mouseX: Int, mouseY: Int) { + GlStateManager.translate(paddingX.toFloat(), paddingY.toFloat(), 0f) + renderable?.render(paddingX, paddingY) + GlStateManager.translate(-paddingX.toFloat(), -paddingY.toFloat(), 0f) + } + + override fun onLeave() { + renderable = null + } + +} diff --git a/src/main/java/at/hannibal2/skyhanni/utils/guide/GuideScrollPage.kt b/src/main/java/at/hannibal2/skyhanni/utils/guide/GuideScrollPage.kt new file mode 100644 index 000000000..97cf68442 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/utils/guide/GuideScrollPage.kt @@ -0,0 +1,31 @@ +package at.hannibal2.skyhanni.utils.guide + +import at.hannibal2.skyhanni.utils.CollectionUtils.tableStretchXPadding +import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.ScrollValue + +abstract class GuideScrollPage( + val sizeX: Int, + val sizeY: Int, + paddingX: Int = 0, + paddingY: Int = 0, + val marginY: Int = 5, + val velocity: Double = 3.0, + val hasHeader: Boolean = true, +) : GuideRenderablePage(paddingX, paddingY) { + + private val scroll = ScrollValue() + + fun update(content: List<List<Renderable>>) { + renderable = Renderable.scrollTable( + content = content, + height = sizeY - paddingY * 2, + scrollValue = scroll, + velocity = velocity, + xPadding = content.tableStretchXPadding(sizeX - paddingX * 2), + yPadding = marginY, + hasHeader = hasHeader, + button = 0 + ) + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/utils/guide/GuideTab.kt b/src/main/java/at/hannibal2/skyhanni/utils/guide/GuideTab.kt new file mode 100644 index 000000000..acc69c8cc --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/utils/guide/GuideTab.kt @@ -0,0 +1,67 @@ +package at.hannibal2.skyhanni.utils.guide + +import at.hannibal2.skyhanni.utils.RenderUtils.HorizontalAlignment +import at.hannibal2.skyhanni.utils.RenderUtils.VerticalAlignment +import at.hannibal2.skyhanni.utils.SoundUtils +import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.renderXYAligned +import net.minecraft.client.gui.Gui +import net.minecraft.item.ItemStack + +class GuideTab( + val item: ItemStack, + val tip: Renderable, + val isVertical: Boolean = false, + var lastTab: GuideGUI.tabWrapper, + val onClick: (GuideTab) -> Unit +) { + + fun fakeClick() = click() + + private fun click() { + onClick.invoke(this) + this.select() + if (lastTab.tab != this) { + lastTab.tab?.unSelect() + lastTab.tab = this + } + } + + fun select() { + selectColor = selectedColor + } + + fun unSelect() { + selectColor = notSelectedColor + } + + fun isSelected() = selectColor == selectedColor + + val width = if (isVertical) tabLongSide else tabShortSide + val height = if (isVertical) tabShortSide else tabLongSide + + private var selectColor = notSelectedColor + + private val renderable = Renderable.clickAndHover(object : Renderable { + override val width = this@GuideTab.width + override val height = this@GuideTab.height + override val horizontalAlign: HorizontalAlignment = HorizontalAlignment.LEFT + override val verticalAlign: VerticalAlignment = VerticalAlignment.TOP + + val itemRender = Renderable.itemStack( + item, 1.0, horizontalAlign = HorizontalAlignment.CENTER, verticalAlign = VerticalAlignment.CENTER + ) + + override fun render(posX: Int, posY: Int) { + Gui.drawRect(0, 0, width, height, selectColor) + itemRender.renderXYAligned(posX, posY, width, height) + } + }, listOf(tip), onClick = { + click() + SoundUtils.playClickSound() + }) + + fun render(posX: Int, posY: Int) { + renderable.render(posX, posY) + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/utils/guide/GuideTablePage.kt b/src/main/java/at/hannibal2/skyhanni/utils/guide/GuideTablePage.kt new file mode 100644 index 000000000..85dd5bdda --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/utils/guide/GuideTablePage.kt @@ -0,0 +1,33 @@ +package at.hannibal2.skyhanni.utils.guide + +import at.hannibal2.skyhanni.utils.CollectionUtils.tableStretchXPadding +import at.hannibal2.skyhanni.utils.CollectionUtils.tableStretchYPadding +import at.hannibal2.skyhanni.utils.RenderUtils.HorizontalAlignment +import at.hannibal2.skyhanni.utils.renderables.Renderable + +abstract class GuideTablePage( + val sizeX: Int, + val sizeY: Int, + paddingX: Int = 0, + paddingY: Int = 0, + val footerSpacing: Int = 2 +) : GuideRenderablePage(paddingX, paddingY) { + + fun update( + content: List<List<Renderable>>, + footer: List<Renderable> = emptyList() + ) { + val ySpace = (content + listOf(footer)).tableStretchYPadding(sizeY - paddingY * 2) + renderable = + Renderable.verticalContainer( + listOf( + Renderable.table( + content, + xPadding = content.tableStretchXPadding(sizeX - paddingX * 2), + yPadding = ySpace + ), + Renderable.horizontalContainer(footer, footerSpacing, horizontalAlign = HorizontalAlignment.CENTER) + ), spacing = ySpace + ) + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt b/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt index 88b291844..070d7db10 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt @@ -19,6 +19,7 @@ import at.hannibal2.skyhanni.utils.NEUItems.renderOnScreen import at.hannibal2.skyhanni.utils.RenderUtils import at.hannibal2.skyhanni.utils.RenderUtils.HorizontalAlignment import at.hannibal2.skyhanni.utils.RenderUtils.VerticalAlignment +import at.hannibal2.skyhanni.utils.guide.GuideGUI import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.calculateTableXOffsets import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.calculateTableYOffsets import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.renderXAligned @@ -230,18 +231,20 @@ interface Renderable { } private fun shouldAllowLink(debug: Boolean = false, bypassChecks: Boolean): Boolean { - val isGuiScreen = Minecraft.getMinecraft().currentScreen != null + val guiScreen = Minecraft.getMinecraft().currentScreen + + val isGuiScreen = guiScreen != null if (bypassChecks) { return isGuiScreen } val inMenu = Minecraft.getMinecraft().currentScreen !is GuiIngameMenu - val isGuiPositionEditor = Minecraft.getMinecraft().currentScreen !is GuiPositionEditor - val isNotInSignAndOnSlot = if (Minecraft.getMinecraft().currentScreen !is GuiEditSign) { + val isGuiPositionEditor = guiScreen !is GuiPositionEditor + val isNotInSignAndOnSlot = if (guiScreen !is GuiEditSign && guiScreen !is GuideGUI<*>) { ToolTipData.lastSlot == null || GuiData.preDrawEventCanceled } else true - val isConfigScreen = Minecraft.getMinecraft().currentScreen !is GuiScreenElementWrapper + val isConfigScreen = guiScreen !is GuiScreenElementWrapper - val openGui = Minecraft.getMinecraft().currentScreen?.javaClass?.name ?: "none" + val openGui = guiScreen?.javaClass?.name ?: "none" val isInNeuPv = openGui == "io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer" val neuFocus = NEUItems.neuHasFocus() val isInSkyTilsPv = openGui == "gg.skytils.skytilsmod.gui.profile.ProfileGui" @@ -313,20 +316,45 @@ interface Renderable { } } + fun itemStackWithTip( + item: ItemStack, + scale: Double = NEUItems.itemFontSize, + xSpacing: Int = 2, + ySpacing: Int = 0, + rescaleSkulls: Boolean = true, + horizontalAlign: HorizontalAlignment = HorizontalAlignment.LEFT, + verticalAlign: VerticalAlignment = VerticalAlignment.TOP, + ) = + hoverTips( + itemStack( + item, + scale, + xSpacing, + ySpacing, + rescaleSkulls, + horizontalAlign = horizontalAlign, + verticalAlign = verticalAlign + ), + item.getTooltip(Minecraft.getMinecraft().thePlayer, false), + stack = item + ) + fun itemStack( item: ItemStack, scale: Double = NEUItems.itemFontSize, xSpacing: Int = 2, + ySpacing: Int = 1, + rescaleSkulls: Boolean = true, horizontalAlign: HorizontalAlignment = HorizontalAlignment.LEFT, verticalAlign: VerticalAlignment = VerticalAlignment.CENTER, ) = object : Renderable { - override val width = (15.5 * scale + 1.5).toInt() + xSpacing - override val height = (15.5 * scale + 1.5).toInt() + override val width = (15.5 * scale + 0.5).toInt() + xSpacing + override val height = (15.5 * scale + 0.5).toInt() + ySpacing override val horizontalAlign = horizontalAlign override val verticalAlign = verticalAlign override fun render(posX: Int, posY: Int) { - item.renderOnScreen(xSpacing / 2.0f, 0F, scaleMultiplier = scale) + item.renderOnScreen(xSpacing / 2.0f, 0F, scaleMultiplier = scale, rescaleSkulls) } } @@ -379,7 +407,7 @@ interface Renderable { scale: Double = 1.0, color: Color = Color.WHITE, horizontalAlign: HorizontalAlignment = HorizontalAlignment.LEFT, - verticalAlign: VerticalAlignment = VerticalAlignment.TOP, + verticalAlign: VerticalAlignment = VerticalAlignment.CENTER, ) = object : Renderable { val list by lazy { @@ -390,9 +418,9 @@ interface Renderable { override val width by lazy { if (list.size == 1) { - (Minecraft.getMinecraft().fontRendererObj.getStringWidth(text) / scale).toInt() + 1 + (Minecraft.getMinecraft().fontRendererObj.getStringWidth(text) * scale).toInt() + 1 } else { - (width / scale).toInt() + 1 + width } } @@ -431,6 +459,7 @@ interface Renderable { content: List<List<Renderable?>>, xPadding: Int = 1, yPadding: Int = 0, + useEmptySpace: Boolean = false, horizontalAlign: HorizontalAlignment = HorizontalAlignment.LEFT, verticalAlign: VerticalAlignment = VerticalAlignment.TOP, ) = object : Renderable { @@ -442,6 +471,9 @@ interface Renderable { override val width = xOffsets.last() - xPadding override val height = yOffsets.last() - yPadding + val emptySpaceX = if (useEmptySpace) 0 else xPadding + val emptySpaceY = if (useEmptySpace) 0 else yPadding + override fun render(posX: Int, posY: Int) { content.forEachIndexed { rowIndex, row -> row.forEachIndexed { index, renderable -> @@ -450,8 +482,8 @@ interface Renderable { renderable?.renderXYAligned( posX + xOffsets[index], posY + yOffsets[rowIndex], - xOffsets[index + 1] - xOffsets[index], - yOffsets[rowIndex + 1] - yOffsets[rowIndex] + xOffsets[index + 1] - xOffsets[index] - emptySpaceX, + yOffsets[rowIndex + 1] - yOffsets[rowIndex] - emptySpaceY ) GlStateManager.popMatrix() } @@ -557,7 +589,52 @@ interface Renderable { override val horizontalAlign = horizontalAlign override val verticalAlign = verticalAlign override fun render(posX: Int, posY: Int) { - render.renderXAligned(0, 0, width) + render.renderXAligned(posX, posY, width) + } + } + + fun fixedSizeLine( + content: List<Renderable>, + width: Int, + horizontalAlign: HorizontalAlignment = HorizontalAlignment.LEFT, + verticalAlign: VerticalAlignment = VerticalAlignment.TOP, + ) = object : Renderable { + val render = content + + override val width = width + override val height = render.maxOfOrNull { it.height } ?: 0 + override val horizontalAlign = horizontalAlign + override val verticalAlign = verticalAlign + + val emptySpace = width - render.sumOf { it.width } + val spacing = emptySpace / render.size + + override fun render(posX: Int, posY: Int) { + var xOffset = posX + render.forEach { + val x = it.width + spacing + it.renderXYAligned(xOffset, posY, x, height) + xOffset += x + GlStateManager.translate(x.toFloat(), 0f, 0f) + } + GlStateManager.translate(-(xOffset - posX).toFloat(), 0f, 0f) + } + } + + fun fixedSizeCollum( + content: Renderable, + height: Int, + horizontalAlign: HorizontalAlignment = HorizontalAlignment.LEFT, + verticalAlign: VerticalAlignment = VerticalAlignment.TOP, + ) = object : Renderable { + val render = content + + override val width = render.width + override val height = height + override val horizontalAlign = horizontalAlign + override val verticalAlign = verticalAlign + override fun render(posX: Int, posY: Int) { + render.renderYAligned(posX, posY, height) } } @@ -601,7 +678,7 @@ interface Renderable { override fun render(posX: Int, posY: Int) { var yOffset = posY renderables.forEach { - it.renderXAligned(yOffset, posX, width) + it.renderXAligned(posX, yOffset, width) yOffset += it.height + spacing GlStateManager.translate(0f, (it.height + spacing).toFloat(), 0f) } @@ -722,7 +799,15 @@ interface Renderable { yOffsets.indexOfFirst { it >= scroll.asInt() }..<(yOffsets.indexOfFirst { it >= end } .takeIf { it > 0 } ?: yOffsets.size) - 1 - for (rowIndex in range) { + + val range2 = + if (range.last + 3 <= yOffsets.size && yOffsets[range.last + 2] - yOffsets[range.first] <= height - renderY) { + range.first..range.last() + 1 + } else { + range + } + + for (rowIndex in range2) { content[rowIndex].forEachIndexed { index, renderable -> GlStateManager.translate(xOffsets[index].toFloat(), 0f, 0f) renderable?.renderXYAligned( diff --git a/src/main/java/at/hannibal2/skyhanni/utils/renderables/RenderableUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/renderables/RenderableUtils.kt index e1f93574e..cf81fc9ff 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/renderables/RenderableUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/renderables/RenderableUtils.kt @@ -13,22 +13,25 @@ internal object RenderableUtils { buildList { add(0) while (true) { - buffer += content.map { it.getOrNull(index) }.takeIf { it.any { it != null } }?.maxOf { + buffer += content.map { it.getOrNull(index) }.takeIf { it.any { it != null } }?.maxOfOrNull { it?.width ?: 0 }?.let { it + xPadding } ?: break add(buffer) index++ } + if (this.size == 1) { + add(xPadding) + } } } /** Calculates the absolute y position of the rows in a table*/ fun calculateTableYOffsets(content: List<List<Renderable?>>, yPadding: Int) = run { var buffer = 0 - listOf(0) + content.map { row -> - buffer += row.maxOf { it?.height ?: 0 } + yPadding + listOf(0) + (content.takeIf { it.isNotEmpty() }?.map { row -> + buffer += (row.maxOfOrNull { it?.height ?: 0 } ?: 0) + yPadding buffer - } + } ?: listOf(yPadding)) } private fun calculateAlignmentXOffset(renderable: Renderable, xSpace: Int) = when (renderable.horizontalAlign) { |