From a0b37ef8029ff0aecf890447e62e92bf2c28c304 Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Date: Mon, 4 Dec 2023 15:14:47 +0100 Subject: changed packages of bingo features --- src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt | 6 +- .../hannibal2/skyhanni/config/commands/Commands.kt | 4 +- .../skyhanni/events/bingo/BingoGoalReachedEvent.kt | 2 +- .../hannibal2/skyhanni/features/bingo/BingoAPI.kt | 6 +- .../skyhanni/features/bingo/BingoCardDisplay.kt | 195 --------- .../skyhanni/features/bingo/BingoCardTips.kt | 83 ---- .../skyhanni/features/bingo/BingoNextStepHelper.kt | 438 -------------------- .../features/bingo/card/BingoCardDisplay.kt | 197 +++++++++ .../features/bingo/card/BingoCardReader.kt | 3 + .../skyhanni/features/bingo/card/BingoCardTips.kt | 84 ++++ .../skyhanni/features/bingo/card/BingoGoal.kt | 12 - .../skyhanni/features/bingo/card/GoalType.kt | 7 - .../skyhanni/features/bingo/card/HiddenGoalData.kt | 5 - .../features/bingo/card/goals/BingoGoal.kt | 12 + .../skyhanni/features/bingo/card/goals/GoalType.kt | 7 + .../features/bingo/card/goals/HiddenGoalData.kt | 5 + .../card/nextstephelper/BingoNextStepHelper.kt | 439 +++++++++++++++++++++ .../card/nextstephelper/steps/ChatMessageStep.kt | 4 + .../card/nextstephelper/steps/CollectionStep.kt | 9 + .../bingo/card/nextstephelper/steps/CraftStep.kt | 3 + .../card/nextstephelper/steps/IslandVisitStep.kt | 5 + .../bingo/card/nextstephelper/steps/ItemsStep.kt | 11 + .../bingo/card/nextstephelper/steps/NextStep.kt | 7 + .../card/nextstephelper/steps/ProgressionStep.kt | 4 + .../card/nextstephelper/steps/SkillLevelStep.kt | 10 + .../features/bingo/nextstep/ChatMessageStep.kt | 4 - .../features/bingo/nextstep/CollectionStep.kt | 9 - .../skyhanni/features/bingo/nextstep/CraftStep.kt | 3 - .../features/bingo/nextstep/IslandVisitStep.kt | 5 - .../skyhanni/features/bingo/nextstep/ItemsStep.kt | 11 - .../skyhanni/features/bingo/nextstep/NextStep.kt | 7 - .../features/bingo/nextstep/ProgressionStep.kt | 4 - .../features/bingo/nextstep/SkillLevelStep.kt | 10 - 33 files changed, 809 insertions(+), 802 deletions(-) delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/BingoCardDisplay.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/BingoCardTips.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/BingoNextStepHelper.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardDisplay.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardTips.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoGoal.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/card/GoalType.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/card/HiddenGoalData.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/card/goals/BingoGoal.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/card/goals/GoalType.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/card/goals/HiddenGoalData.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/card/nextstephelper/BingoNextStepHelper.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/card/nextstephelper/steps/ChatMessageStep.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/card/nextstephelper/steps/CollectionStep.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/card/nextstephelper/steps/CraftStep.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/card/nextstephelper/steps/IslandVisitStep.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/card/nextstephelper/steps/ItemsStep.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/card/nextstephelper/steps/NextStep.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/card/nextstephelper/steps/ProgressionStep.kt create mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/card/nextstephelper/steps/SkillLevelStep.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/nextstep/ChatMessageStep.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/nextstep/CollectionStep.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/nextstep/CraftStep.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/nextstep/IslandVisitStep.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/nextstep/ItemsStep.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/nextstep/NextStep.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/nextstep/ProgressionStep.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/features/bingo/nextstep/SkillLevelStep.kt diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index 75a8ca20f..6dc51b7a6 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -53,12 +53,12 @@ import at.hannibal2.skyhanni.features.bazaar.BazaarCancelledBuyOrderClipboard import at.hannibal2.skyhanni.features.bazaar.BazaarOpenPriceWebsite import at.hannibal2.skyhanni.features.bazaar.BazaarOrderHelper import at.hannibal2.skyhanni.features.bingo.BingoAPI -import at.hannibal2.skyhanni.features.bingo.BingoCardDisplay -import at.hannibal2.skyhanni.features.bingo.BingoCardTips -import at.hannibal2.skyhanni.features.bingo.BingoNextStepHelper import at.hannibal2.skyhanni.features.bingo.CompactBingoChat import at.hannibal2.skyhanni.features.bingo.MinionCraftHelper +import at.hannibal2.skyhanni.features.bingo.card.BingoCardDisplay import at.hannibal2.skyhanni.features.bingo.card.BingoCardReader +import at.hannibal2.skyhanni.features.bingo.card.BingoCardTips +import at.hannibal2.skyhanni.features.bingo.card.nextstephelper.BingoNextStepHelper import at.hannibal2.skyhanni.features.chat.ArachneChatMessageHider import at.hannibal2.skyhanni.features.chat.ChatFilter import at.hannibal2.skyhanni.features.chat.CompactBestiaryChatMessage 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 f3bd55907..1a0b41629 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt @@ -7,8 +7,8 @@ import at.hannibal2.skyhanni.data.ChatManager import at.hannibal2.skyhanni.data.GardenCropMilestonesCommunityFix import at.hannibal2.skyhanni.data.GuiEditManager import at.hannibal2.skyhanni.data.PartyAPI -import at.hannibal2.skyhanni.features.bingo.BingoCardDisplay -import at.hannibal2.skyhanni.features.bingo.BingoNextStepHelper +import at.hannibal2.skyhanni.features.bingo.card.BingoCardDisplay +import at.hannibal2.skyhanni.features.bingo.card.nextstephelper.BingoNextStepHelper import at.hannibal2.skyhanni.features.chat.Translator import at.hannibal2.skyhanni.features.combat.endernodetracker.EnderNodeTracker import at.hannibal2.skyhanni.features.combat.ghostcounter.GhostUtil diff --git a/src/main/java/at/hannibal2/skyhanni/events/bingo/BingoGoalReachedEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/bingo/BingoGoalReachedEvent.kt index 46f0f3722..b091c24f3 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/bingo/BingoGoalReachedEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/bingo/BingoGoalReachedEvent.kt @@ -1,6 +1,6 @@ package at.hannibal2.skyhanni.events.bingo import at.hannibal2.skyhanni.events.LorenzEvent -import at.hannibal2.skyhanni.features.bingo.card.BingoGoal +import at.hannibal2.skyhanni.features.bingo.card.goals.BingoGoal class BingoGoalReachedEvent(val goal: BingoGoal) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoAPI.kt index 17a6fe507..cc5dec6ff 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoAPI.kt @@ -3,8 +3,8 @@ package at.hannibal2.skyhanni.features.bingo import at.hannibal2.skyhanni.data.jsonobjects.repo.BingoJson import at.hannibal2.skyhanni.data.jsonobjects.repo.BingoRanksJson import at.hannibal2.skyhanni.events.RepositoryReloadEvent -import at.hannibal2.skyhanni.features.bingo.card.BingoGoal -import at.hannibal2.skyhanni.features.bingo.card.GoalType +import at.hannibal2.skyhanni.features.bingo.card.goals.BingoGoal +import at.hannibal2.skyhanni.features.bingo.card.goals.GoalType import at.hannibal2.skyhanni.utils.SimpleTimeMark import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @@ -31,7 +31,7 @@ object BingoAPI { fun getTip(itemName: String) = tips.filter { itemName.startsWith(it.key.split(" (Community Goal)")[0]) }.values.firstOrNull() - fun BingoGoal.getTip(): BingoJson.BingoTip? = if (type == GoalType.COMMUNITY) { + fun BingoGoal.getTip(): BingoJson.BingoTip? = if (type == at.hannibal2.skyhanni.features.bingo.card.goals.GoalType.COMMUNITY) { getTip(displayName) } else { tips[displayName] diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoCardDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoCardDisplay.kt deleted file mode 100644 index 98ac19a76..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoCardDisplay.kt +++ /dev/null @@ -1,195 +0,0 @@ -package at.hannibal2.skyhanni.features.bingo - -import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator -import at.hannibal2.skyhanni.events.ConfigLoadEvent -import at.hannibal2.skyhanni.events.GuiRenderEvent -import at.hannibal2.skyhanni.events.LorenzTickEvent -import at.hannibal2.skyhanni.events.bingo.BingoCardUpdateEvent -import at.hannibal2.skyhanni.utils.InventoryUtils -import at.hannibal2.skyhanni.utils.ItemUtils -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.LorenzUtils.onToggle -import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings -import at.hannibal2.skyhanni.utils.StringUtils -import at.hannibal2.skyhanni.utils.TimeUtils.format -import net.minecraft.client.Minecraft -import net.minecraft.client.gui.GuiChat -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -import kotlin.time.Duration.Companion.days - -class BingoCardDisplay { - - private var display = emptyList() - - private var hasHiddenPersonalGoals = false - - init { - update() - } - - companion object { - private const val MAX_PERSONAL_GOALS = 20 - private const val MAX_COMMUNITY_GOALS = 5 - - private val config get() = SkyHanniMod.feature.event.bingo.bingoCard - private var displayMode = 0 - - fun command() { - reload() - } - - private fun reload() { - BingoAPI.bingoGoals.clear() - } - - fun toggleCommand() { - if (!LorenzUtils.isBingoProfile) { - LorenzUtils.userError("This command only works on a bingo profile!") - return - } - if (!config.enabled) { - LorenzUtils.userError("Bingo Card is disabled in the config!") - return - } - toggleMode() - } - - private fun toggleMode() { - displayMode++ - if (displayMode == 3) { - displayMode = 0 - } - } - } - - @SubscribeEvent - fun onTick(event: LorenzTickEvent) { - if (event.repeatSeconds(1)) { - if (hasHiddenPersonalGoals) { - update() - } - } - } - - private fun update() { - display = drawDisplay() - } - - private fun drawDisplay(): MutableList { - val newList = mutableListOf() - - if (BingoAPI.bingoGoals.isEmpty()) { - newList.add("§6Bingo Goals:") - newList.add("§cOpen the §e/bingo §ccard.") - } else { - if (!config.hideCommunityGoals.get()) { - newList.addCommunityGoals() - } - newList.addPersonalGoals() - } - return newList - } - - private fun MutableList.addCommunityGoals() { - add("§6Community Goals:") - val goals = BingoAPI.communityGoals.toMutableList() - var hiddenGoals = 0 - for (goal in goals.toList()) { - if (goal.hiddenGoalData.unknownTip) { - hiddenGoals++ - goals.remove(goal) - } - } - - goals.mapTo(this) { " " + it.description + if (it.done) " §aDONE" else "" } - if (hiddenGoals > 0) { - add("§7+ $hiddenGoals hidden community goals.") - } - add(" ") - } - - private fun MutableList.addPersonalGoals() { - val todo = BingoAPI.personalGoals.filter { !it.done }.toMutableList() - val done = MAX_PERSONAL_GOALS - todo.size - add("§6Personal Goals: ($done/$MAX_PERSONAL_GOALS done)") - - var hiddenGoals = 0 - var nextTip = 7.days - for (goal in todo.toList()) { - val hiddenGoalData = goal.hiddenGoalData - if (hiddenGoalData.unknownTip) { - hiddenGoals++ - todo.remove(goal) - } - - hiddenGoalData.nextHintTime?.let { - if (it < nextTip) { - nextTip = it - } - } - } - - todo.mapTo(this) { " " + it.description } - if (hiddenGoals > 0) { - val name = StringUtils.canBePlural(hiddenGoals, "goal", "goals") - add("§7+ $hiddenGoals more unknown $name.") - } - hasHiddenPersonalGoals = config.nextTipDuration.get() && nextTip != 7.days - if (hasHiddenPersonalGoals) { - val nextTipTime = BingoAPI.lastBingoCardOpenTime + nextTip - if (nextTipTime.isInPast()) { - add("§eThe next hint got unlocked already!") - add("§eOpen the bingo card to update!") - } else { - val until = nextTipTime.timeUntil() - add("§eThe next hint will unlock in §b${until.format(maxUnits = 2)}") - } - } - } - - private var lastSneak = false - - @SubscribeEvent - fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) { - if (!LorenzUtils.isBingoProfile) return - if (!config.enabled) return - - if (config.quickToggle && ItemUtils.isSkyBlockMenuItem(InventoryUtils.getItemInHand())) { - val sneaking = Minecraft.getMinecraft().thePlayer.isSneaking - if (lastSneak != sneaking) { - lastSneak = sneaking - if (sneaking) { - toggleMode() - } - } - } - if (!config.stepHelper && displayMode == 1) { - displayMode = 2 - } - if (displayMode == 0) { - if (Minecraft.getMinecraft().currentScreen !is GuiChat) { - config.bingoCardPos.renderStrings(display, posLabel = "Bingo Card") - } - } else if (displayMode == 1) { - config.bingoCardPos.renderStrings(BingoNextStepHelper.currentHelp, posLabel = "Bingo Card") - } - } - - @SubscribeEvent - fun onBingoCardUpdate(event: BingoCardUpdateEvent) { - if (!config.enabled) return - update() - } - - @SubscribeEvent - fun onConfigLoad(event: ConfigLoadEvent) { - config.hideCommunityGoals.onToggle { update() } - config.nextTipDuration.onToggle { update() } - } - - @SubscribeEvent - fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { - event.move(2, "bingo", "event.bingo") - } -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoCardTips.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoCardTips.kt deleted file mode 100644 index 672dce98c..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoCardTips.kt +++ /dev/null @@ -1,83 +0,0 @@ -package at.hannibal2.skyhanni.features.bingo - -import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.events.GuiContainerEvent -import at.hannibal2.skyhanni.features.bingo.BingoAPI.getTip -import at.hannibal2.skyhanni.features.bingo.card.GoalType -import at.hannibal2.skyhanni.utils.InventoryUtils -import at.hannibal2.skyhanni.utils.LorenzColor -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.RenderUtils.highlight -import net.minecraft.client.Minecraft -import net.minecraft.client.gui.inventory.GuiContainer -import net.minecraft.inventory.ContainerChest -import net.minecraftforge.event.entity.player.ItemTooltipEvent -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent - -class BingoCardTips { - private val config get() = SkyHanniMod.feature.event.bingo.bingoCard - - @SubscribeEvent - fun onItemTooltipLow(event: ItemTooltipEvent) { - if (!isEnabled()) return - if (InventoryUtils.openInventoryName() != "Bingo Card") return - - val gui = Minecraft.getMinecraft().currentScreen as? GuiContainer ?: return - val slot = gui.slotUnderMouse - val goal = BingoAPI.bingoGoals.firstOrNull { it.slot == slot.slotNumber } ?: return - - val toolTip = event.toolTip - val bingoTip = goal.getTip() ?: return - val communityGoal = goal.type == GoalType.COMMUNITY - - val difficulty = Difficulty.valueOf(bingoTip.difficulty.uppercase()) - toolTip[0] = toolTip[0] + " §7(" + difficulty.displayName + "§7) ${goal.done}" - - var index = if (!communityGoal) { - toolTip.indexOf("§5§o§7Reward") - } else { - toolTip.indexOfFirst { it.startsWith("§5§o§7Contribution Rewards") } - } - 1 - - toolTip.add(index++, "") - toolTip.add(index++, "§eGuide:") - for (line in bingoTip.note) { - toolTip.add(index++, " $line") - } - bingoTip.found?.let { - toolTip.add(index++, "§7Found by: §e$it") - } - } - - @SubscribeEvent - fun onBackgroundDrawn(event: GuiContainerEvent.BackgroundDrawnEvent) { - if (!isEnabled()) return - if (InventoryUtils.openInventoryName() != "Bingo Card") return - - val guiChest = event.gui - val chest = guiChest.inventorySlots as ContainerChest - for (slot in chest.inventorySlots) { - if (slot == null) continue - - val goal = BingoAPI.bingoGoals.firstOrNull { it.slot == slot.slotNumber } ?: continue - if (config.hideDoneDifficulty && goal.done) continue - - val color = goal.getTip()?.let { - val difficulty = Difficulty.valueOf(it.difficulty.uppercase()) - difficulty.color - } ?: LorenzColor.GRAY - slot highlight color.addOpacity(120) - } - } - - fun isEnabled() = LorenzUtils.inSkyBlock && config.bingoSplashGuide - - enum class Difficulty(rawName: String, val color: LorenzColor) { - EASY("Easy", LorenzColor.GREEN), - MEDIUM("Medium", LorenzColor.YELLOW), - HARD("Hard", LorenzColor.RED), - ; - - val displayName = color.getChatColor() + rawName - } -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoNextStepHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoNextStepHelper.kt deleted file mode 100644 index e2381524d..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoNextStepHelper.kt +++ /dev/null @@ -1,438 +0,0 @@ -package at.hannibal2.skyhanni.features.bingo - -import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.api.CollectionAPI -import at.hannibal2.skyhanni.data.IslandType -import at.hannibal2.skyhanni.data.SkillExperience -import at.hannibal2.skyhanni.events.LorenzChatEvent -import at.hannibal2.skyhanni.events.LorenzTickEvent -import at.hannibal2.skyhanni.features.bingo.nextstep.ChatMessageStep -import at.hannibal2.skyhanni.features.bingo.nextstep.CollectionStep -import at.hannibal2.skyhanni.features.bingo.nextstep.CraftStep -import at.hannibal2.skyhanni.features.bingo.nextstep.IslandVisitStep -import at.hannibal2.skyhanni.features.bingo.nextstep.ItemsStep -import at.hannibal2.skyhanni.features.bingo.nextstep.NextStep -import at.hannibal2.skyhanni.features.bingo.nextstep.ObtainCrystalStep -import at.hannibal2.skyhanni.features.bingo.nextstep.PartialProgressItemsStep -import at.hannibal2.skyhanni.features.bingo.nextstep.ProgressionStep -import at.hannibal2.skyhanni.features.bingo.nextstep.SkillLevelStep -import at.hannibal2.skyhanni.utils.InventoryUtils -import at.hannibal2.skyhanni.utils.ItemUtils.name -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.LorenzUtils.editCopy -import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher -import at.hannibal2.skyhanni.utils.StringUtils.removeColor -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent - -class BingoNextStepHelper { - private val config get() = SkyHanniMod.feature.event.bingo.bingoCard - private var dirty = true - - // TODO USE SH-REPO - private val crystalObtainedPattern = " *§r§e(?Topaz|Sapphire|Jade|Amethyst|Amber) Crystal".toPattern() - private val itemIslandRequired = mutableMapOf() - private val itemPreconditions = mutableMapOf() - private val islands = mutableMapOf() - private val collectionPattern = "Reach (?[0-9]+(?:,\\d+)*) (?.*) Collection\\.".toPattern() - private val crystalPattern = "Obtain a (?\\w+) Crystal in the Crystal Hollows\\.".toPattern() - private val skillPattern = "Obtain level (?.*) in the (?.*) Skill.".toPattern() - private val crystalFoundPattern = " *§r§5§l✦ CRYSTAL FOUND §r§7\\(.§r§7/5§r§7\\)".toPattern() - private val rhysTaskName = "30x Enchanted Minerals (Redstone, Lapis Lazuli, Coal) (for Rhys)" - - companion object { - private val finalSteps = mutableListOf() - private var currentSteps = emptyList() - var currentHelp = emptyList() - - fun command() { - updateResult(true) - } - - private fun updateResult(print: Boolean = false) { - if (print) println() - currentSteps = listOf() - for (step in finalSteps) { - printRequirements(step, print) - if (print) println() - } - - currentHelp = drawDisplay(print) - } - - private fun drawDisplay(print: Boolean): MutableList { - val newCurrentHelp = mutableListOf() - newCurrentHelp.add("§6Bingo Step Helper:") - - if (currentSteps.isEmpty()) { - newCurrentHelp.add("§cOpen the §e/bingo §ccard.") - } - for (currentStep in currentSteps) { - val text = getName(currentStep) - newCurrentHelp.add(" §7$text") - if (print) println(text) - } - if (print) println() - return newCurrentHelp - } - - private fun printRequirements(step: NextStep, print: Boolean, parentDone: Boolean = false, depth: Int = 0) { - if (print) println(getName(step, parentDone, depth)) - var requirementsToDo = 0 - for (requirement in step.requirements) { - printRequirements(requirement, print, step.done || parentDone, depth + 1) - if (!requirement.done) { - requirementsToDo++ - } - } - - if (!step.done && !parentDone && requirementsToDo == 0 && !currentSteps.contains(step)) { - currentSteps = currentSteps.editCopy { add(step) } - } - } - - private fun getName(step: NextStep, parentDone: Boolean = false, depth: Int = 0): String { - val prefix = " ".repeat(depth) + if (step.done) "[DONE] " else if (parentDone) "[done] " else "" - val suffix = if (step is ProgressionStep) progressDisplay(step) else "" - return prefix + step.displayName + suffix - } - - private fun progressDisplay(step: ProgressionStep): String { - val having = step.amountHaving - return if (having > 0) { - val needed = step.amountNeeded - val percentage = LorenzUtils.formatPercentage(having.toDouble() / needed) - val havingFormat = LorenzUtils.formatInteger(having) - val neededFormat = LorenzUtils.formatInteger(needed) - " $percentage ($havingFormat/$neededFormat)" - } else "" - } - } - - init { - reset() - } - - @SubscribeEvent - fun onTick(event: LorenzTickEvent) { - if (!LorenzUtils.isBingoProfile) return - if (!config.enabled) return - - if (event.repeatSeconds(1)) { - update() - updateIslandsVisited() - } - if (event.isMod(5)) { - updateCurrentSteps() - } - } - - private var nextMessageIsCrystal = false - - @SubscribeEvent - fun onChat(event: LorenzChatEvent) { - if (!LorenzUtils.isBingoProfile) return - if (!config.enabled) return - - for (currentStep in currentSteps) { - if (currentStep is ObtainCrystalStep) { - crystalFoundPattern.matchMatcher(event.message) { - nextMessageIsCrystal = true - return - } - if (nextMessageIsCrystal) { - nextMessageIsCrystal = false - crystalObtainedPattern.matchMatcher(event.message) { - if (group("crystalName") == currentStep.crystalName) - currentStep.done() - } - } - } - if (currentStep is PartialProgressItemsStep && currentStep.displayName == rhysTaskName && event.message == "§e[NPC] §dRhys§f: §rThank you for the items!§r") { - currentStep.amountHavingHidden -= 10 - } - } - //TODO add thys message -// if (event.message == "thys message") { -// thys.done() -// } - } - - private fun updateCurrentSteps() { - for (step in currentSteps.toMutableList()) { - if (step is ItemsStep) { - var totalCount = 0L - for ((itemName, multiplier) in step.variants) { - val count = InventoryUtils.countItemsInLowerInventory { it.name?.removeColor() == itemName } - totalCount += count * multiplier - } - if (step.amountHaving != totalCount) { - step.amountHaving = totalCount - if (totalCount >= step.amountNeeded) { - step.done() - } - updateResult() - } - } - if (step is SkillLevelStep) { - val expForSkill = SkillExperience.getExpForSkill(step.skillName.lowercase()) - if (step.amountHaving != expForSkill) { - step.amountHaving = expForSkill - if (expForSkill >= step.amountNeeded) { - step.done() - } - updateResult() - } - } - if (step is CollectionStep) { - val counter = CollectionAPI.getCollectionCounter(step.internalName) ?: 0 - if (step.amountHaving != counter) { - step.amountHaving = counter - if (counter >= step.amountNeeded) { - step.done() - } - updateResult() - } - } - } - } - - private fun NextStep.done(silent: Boolean = false) { - if (done) return - done = true - updateResult() - if (!silent && config.stepHelper) { - LorenzUtils.chat("A bingo goal step is done! ($displayName)") - } - } - - private fun updateIslandsVisited() { - for (step in islands.values) { - val island = step.island - if (island == LorenzUtils.skyBlockIsland) { - step.done() - } - } - } - - private fun update() { - val personalGoals = BingoAPI.personalGoals.filter { !it.done } - if (personalGoals.isEmpty()) { - if (!dirty) { - reset() - dirty = true - } - return - } - - if (!dirty) return - dirty = false - - for (goal in personalGoals) { - val description = goal.description - val bingoCardStep = readDescription(description.removeColor()) - if (bingoCardStep == null) { -// println("Warning: Could not find bingo steps for $description") - } else { - finalSteps.add(bingoCardStep) - } - } - - updateResult() - } - - private fun readDescription(description: String): NextStep? { - collectionPattern.matchMatcher(description) { - val amount = group("amount").replace(",", "").toInt() - val name = group("name") - - return CollectionStep(name, amount) withItemIslandRequirement name - } - - if (description == "Craft an Emerald Ring.") { - return CraftStep("Emerald Ring") requires ( - ItemsStep( - "32x Enchanted Emerald", - "Emerald", - 160 * 32, - mapOf("Emerald" to 1, "Enchanted Emerald" to 160) - ) requires IslandType.DWARVEN_MINES.getStep()) - } - - if (description == "Obtain a Mathematical Hoe Blueprint.") { - return CraftStep("Mathematical Hoe Blueprint") requires ( - ItemsStep( - "32x Jacob's Ticket", - "Jacob's Ticket", - 32, - mapOf("Jacob's Ticket" to 1) - ).addItemRequirements() requires IslandType.GARDEN.getStep()) - } - - crystalPattern.matchMatcher(description) { - val crystal = group("name") - return ObtainCrystalStep(crystal) requires IslandType.CRYSTAL_HOLLOWS.getStep() - } - - skillPattern.matchMatcher(description) { - val level = group("level").toInt() - val skill = group("skill") - return SkillLevelStep(skill, level) - } - - return null - } - - private fun T.makeFinalStep(): T { - finalSteps.add(this) - return this - } - - private infix fun T.withItemIslandRequirement(itemName: String): T { - itemIslandRequired[itemName]?.let { this requires it } - return this - } - - private infix fun T.requires(other: NextStep): T { - requirements.add(other) - return this - } - - private fun IslandType.getStep() = islands.getOrPut(this) { IslandVisitStep(this) } - - private fun reset() { - islands.clear() - finalSteps.clear() - - itemIslandRequired["Acacia Wood"] = IslandType.THE_PARK.getStep() - itemIslandRequired["Redstone"] = IslandType.DEEP_CAVERNS.getStep() - itemIslandRequired["Lapis Lazuli"] = IslandType.DEEP_CAVERNS.getStep() - itemIslandRequired["Coal"] = IslandType.DEEP_CAVERNS.getStep() - itemIslandRequired["Slimeball"] = IslandType.DEEP_CAVERNS.getStep() - itemIslandRequired["Emerald"] = IslandType.DEEP_CAVERNS.getStep() - itemIslandRequired["Mithril"] = IslandType.DEEP_CAVERNS.getStep() - - IslandType.GOLD_MINES.getStep() requires IslandType.HUB.getStep() - IslandType.GOLD_MINES.getStep() requires SkillLevelStep("Mining", 1) - - IslandType.DEEP_CAVERNS.getStep() requires IslandType.GOLD_MINES.getStep() - IslandType.DEEP_CAVERNS.getStep() requires SkillLevelStep("Mining", 5) - - rhys() - IslandType.DWARVEN_MINES.getStep() requires SkillLevelStep( - "Mining", - 12 - ).also { it requires IslandType.THE_FARMING_ISLANDS.getStep() } - - IslandType.CRYSTAL_HOLLOWS.getStep() requires IslandType.DWARVEN_MINES.getStep() - - // TODO add SkyBlock level requirement -// IslandType.GARDEN.getStep() requires SkyBlockLevelStep(6) - IslandType.GARDEN.getStep() requires IslandType.HUB.getStep() - - val farmingContest = ChatMessageStep("Farming Contest") - farmingContest requires SkillLevelStep("Farming", 10) - itemPreconditions["Jacob's Ticket"] = farmingContest - - IslandType.DWARVEN_MINES.getStep().makeFinalStep() - ChatMessageStep("Get Ender Armor").makeFinalStep() requires IslandType.THE_END.getStep() - IslandType.THE_END.getStep() requires SkillLevelStep( - "Combat", - 12 - ).also { it requires IslandType.DEEP_CAVERNS.getStep() } -// enchantedCharcoal(7) -// compactor(7) - } - - private fun rhys() { - val redstoneForRhys = PartialProgressItemsStep( - rhysTaskName, - "Redstone", - 160 * 10, - mapOf("Redstone" to 1, "Enchanted Redstone" to 160) - ) - redstoneForRhys requires IslandType.DEEP_CAVERNS.getStep() - - val lapisForRhys = PartialProgressItemsStep( - rhysTaskName, - "Lapis Lazuli", - 160 * 10, - mapOf("Lapis Lazuli" to 1, "Enchanted Lapis Lazuli" to 160) - ) - lapisForRhys requires IslandType.DEEP_CAVERNS.getStep() - - val coalForRhys = PartialProgressItemsStep( - rhysTaskName, - "Coal", - 160 * 10, - mapOf("Coal" to 1, "Enchanted Coal" to 160) - ) - coalForRhys requires IslandType.DEEP_CAVERNS.getStep() - - val mines = IslandType.DWARVEN_MINES.getStep() - mines requires redstoneForRhys - mines requires lapisForRhys - mines requires coalForRhys - } - - private fun compactor(amount: Long) { - val compactorForMinions = ItemsStep( - "Compactor (for Minions)", - "Compactor", - amount, - mapOf("Compactor" to 1) - ).apply { finalSteps.add(this) } - - compactorForMinions requires CollectionStep( - "Cobblestone", - 2_500 - ).apply { this requires IslandType.HUB.getStep() } - - compactorForMinions requires ItemsStep( - "" + (7 * amount) + " Enchanted Cobblestone (For Minions)", - "Enchanted Cobblestone", - amount * 7 * 160, - mapOf("Cobblestone" to 1, "Enchanted Cobblestone" to 160) - ) - compactorForMinions requires ItemsStep( - "$amount Enchanted Redstone (For Minions)", - "Enchanted Redstone", - amount * 160, - mapOf("Redstone" to 1, "Enchanted Redstone" to 160) - ) - } - - private fun enchantedCharcoal(amount: Long) { - val enchantedCharcoalForMinions = ItemsStep( - "Enchanted Charcoal (for Minions)", - "Enchanted Charcoal", - amount, - mapOf("Enchanted Charcoal" to 1) - ).apply { finalSteps.add(this) } - - enchantedCharcoalForMinions requires CollectionStep( - "Coal", - 2_500 - ).apply { this requires IslandType.GOLD_MINES.getStep() } - - enchantedCharcoalForMinions requires ItemsStep( - "Oak Wood (For Minions)", - "Oak Wood", - amount * 32, - mapOf("Oak Wood" to 1) - ) - enchantedCharcoalForMinions requires ItemsStep( - "Coal (For Minions)", - "Coal", - amount * 64 * 2, - mapOf("Coal" to 1) - ) - } - - private fun ItemsStep.addItemRequirements(): ItemsStep { - val step = itemPreconditions[itemName] - if (step != null) { - requirements.add(step) - } - return this - } -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardDisplay.kt new file mode 100644 index 000000000..bc6b4de49 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardDisplay.kt @@ -0,0 +1,197 @@ +package at.hannibal2.skyhanni.features.bingo.card + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator +import at.hannibal2.skyhanni.events.ConfigLoadEvent +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.LorenzTickEvent +import at.hannibal2.skyhanni.events.bingo.BingoCardUpdateEvent +import at.hannibal2.skyhanni.features.bingo.BingoAPI +import at.hannibal2.skyhanni.features.bingo.card.nextstephelper.BingoNextStepHelper +import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.ItemUtils +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzUtils.onToggle +import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings +import at.hannibal2.skyhanni.utils.StringUtils +import at.hannibal2.skyhanni.utils.TimeUtils.format +import net.minecraft.client.Minecraft +import net.minecraft.client.gui.GuiChat +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration.Companion.days + +class BingoCardDisplay { + + private var display = emptyList() + + private var hasHiddenPersonalGoals = false + + init { + update() + } + + companion object { + private const val MAX_PERSONAL_GOALS = 20 + private const val MAX_COMMUNITY_GOALS = 5 + + private val config get() = SkyHanniMod.feature.event.bingo.bingoCard + private var displayMode = 0 + + fun command() { + reload() + } + + private fun reload() { + BingoAPI.bingoGoals.clear() + } + + fun toggleCommand() { + if (!LorenzUtils.isBingoProfile) { + LorenzUtils.userError("This command only works on a bingo profile!") + return + } + if (!config.enabled) { + LorenzUtils.userError("Bingo Card is disabled in the config!") + return + } + toggleMode() + } + + private fun toggleMode() { + displayMode++ + if (displayMode == 3) { + displayMode = 0 + } + } + } + + @SubscribeEvent + fun onTick(event: LorenzTickEvent) { + if (event.repeatSeconds(1)) { + if (hasHiddenPersonalGoals) { + update() + } + } + } + + private fun update() { + display = drawDisplay() + } + + private fun drawDisplay(): MutableList { + val newList = mutableListOf() + + if (BingoAPI.bingoGoals.isEmpty()) { + newList.add("§6Bingo Goals:") + newList.add("§cOpen the §e/bingo §ccard.") + } else { + if (!config.hideCommunityGoals.get()) { + newList.addCommunityGoals() + } + newList.addPersonalGoals() + } + return newList + } + + private fun MutableList.addCommunityGoals() { + add("§6Community Goals:") + val goals = BingoAPI.communityGoals.toMutableList() + var hiddenGoals = 0 + for (goal in goals.toList()) { + if (goal.hiddenGoalData.unknownTip) { + hiddenGoals++ + goals.remove(goal) + } + } + + goals.mapTo(this) { " " + it.description + if (it.done) " §aDONE" else "" } + if (hiddenGoals > 0) { + add("§7+ $hiddenGoals hidden community goals.") + } + add(" ") + } + + private fun MutableList.addPersonalGoals() { + val todo = BingoAPI.personalGoals.filter { !it.done }.toMutableList() + val done = MAX_PERSONAL_GOALS - todo.size + add("§6Personal Goals: ($done/$MAX_PERSONAL_GOALS done)") + + var hiddenGoals = 0 + var nextTip = 7.days + for (goal in todo.toList()) { + val hiddenGoalData = goal.hiddenGoalData + if (hiddenGoalData.unknownTip) { + hiddenGoals++ + todo.remove(goal) + } + + hiddenGoalData.nextHintTime?.let { + if (it < nextTip) { + nextTip = it + } + } + } + + todo.mapTo(this) { " " + it.description } + if (hiddenGoals > 0) { + val name = StringUtils.canBePlural(hiddenGoals, "goal", "goals") + add("§7+ $hiddenGoals more unknown $name.") + } + hasHiddenPersonalGoals = config.nextTipDuration.get() && nextTip != 7.days + if (hasHiddenPersonalGoals) { + val nextTipTime = BingoAPI.lastBingoCardOpenTime + nextTip + if (nextTipTime.isInPast()) { + add("§eThe next hint got unlocked already!") + add("§eOpen the bingo card to update!") + } else { + val until = nextTipTime.timeUntil() + add("§eThe next hint will unlock in §b${until.format(maxUnits = 2)}") + } + } + } + + private var lastSneak = false + + @SubscribeEvent + fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) { + if (!LorenzUtils.isBingoProfile) return + if (!config.enabled) return + + if (config.quickToggle && ItemUtils.isSkyBlockMenuItem(InventoryUtils.getItemInHand())) { + val sneaking = Minecraft.getMinecraft().thePlayer.isSneaking + if (lastSneak != sneaking) { + lastSneak = sneaking + if (sneaking) { + toggleMode() + } + } + } + if (!config.stepHelper && displayMode == 1) { + displayMode = 2 + } + if (displayMode == 0) { + if (Minecraft.getMinecraft().currentScreen !is GuiChat) { + config.bingoCardPos.renderStrings(display, posLabel = "Bingo Card") + } + } else if (displayMode == 1) { + config.bingoCardPos.renderStrings(BingoNextStepHelper.currentHelp, posLabel = "Bingo Card") + } + } + + @SubscribeEvent + fun onBingoCardUpdate(event: BingoCardUpdateEvent) { + if (!config.enabled) return + update() + } + + @SubscribeEvent + fun onConfigLoad(event: ConfigLoadEvent) { + config.hideCommunityGoals.onToggle { update() } + config.nextTipDuration.onToggle { update() } + } + + @SubscribeEvent + fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { + event.move(2, "bingo", "event.bingo") + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardReader.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardReader.kt index 5c9c7aa5b..151cb145e 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardReader.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardReader.kt @@ -7,6 +7,9 @@ import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.events.bingo.BingoCardUpdateEvent import at.hannibal2.skyhanni.events.bingo.BingoGoalReachedEvent import at.hannibal2.skyhanni.features.bingo.BingoAPI +import at.hannibal2.skyhanni.features.bingo.card.goals.BingoGoal +import at.hannibal2.skyhanni.features.bingo.card.goals.GoalType +import at.hannibal2.skyhanni.features.bingo.card.goals.HiddenGoalData import at.hannibal2.skyhanni.utils.ItemUtils.getLore import at.hannibal2.skyhanni.utils.ItemUtils.name import at.hannibal2.skyhanni.utils.LorenzUtils diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardTips.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardTips.kt new file mode 100644 index 000000000..2e1af0d1a --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardTips.kt @@ -0,0 +1,84 @@ +package at.hannibal2.skyhanni.features.bingo.card + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.GuiContainerEvent +import at.hannibal2.skyhanni.features.bingo.BingoAPI +import at.hannibal2.skyhanni.features.bingo.BingoAPI.getTip +import at.hannibal2.skyhanni.features.bingo.card.goals.GoalType +import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.LorenzColor +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.RenderUtils.highlight +import net.minecraft.client.Minecraft +import net.minecraft.client.gui.inventory.GuiContainer +import net.minecraft.inventory.ContainerChest +import net.minecraftforge.event.entity.player.ItemTooltipEvent +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +class BingoCardTips { + private val config get() = SkyHanniMod.feature.event.bingo.bingoCard + + @SubscribeEvent + fun onItemTooltipLow(event: ItemTooltipEvent) { + if (!isEnabled()) return + if (InventoryUtils.openInventoryName() != "Bingo Card") return + + val gui = Minecraft.getMinecraft().currentScreen as? GuiContainer ?: return + val slot = gui.slotUnderMouse + val goal = BingoAPI.bingoGoals.firstOrNull { it.slot == slot.slotNumber } ?: return + + val toolTip = event.toolTip + val bingoTip = goal.getTip() ?: return + val communityGoal = goal.type == GoalType.COMMUNITY + + val difficulty = Difficulty.valueOf(bingoTip.difficulty.uppercase()) + toolTip[0] = toolTip[0] + " §7(" + difficulty.displayName + "§7) ${goal.done}" + + var index = if (!communityGoal) { + toolTip.indexOf("§5§o§7Reward") + } else { + toolTip.indexOfFirst { it.startsWith("§5§o§7Contribution Rewards") } + } - 1 + + toolTip.add(index++, "") + toolTip.add(index++, "§eGuide:") + for (line in bingoTip.note) { + toolTip.add(index++, " $line") + } + bingoTip.found?.let { + toolTip.add(index++, "§7Found by: §e$it") + } + } + + @SubscribeEvent + fun onBackgroundDrawn(event: GuiContainerEvent.BackgroundDrawnEvent) { + if (!isEnabled()) return + if (InventoryUtils.openInventoryName() != "Bingo Card") return + + val guiChest = event.gui + val chest = guiChest.inventorySlots as ContainerChest + for (slot in chest.inventorySlots) { + if (slot == null) continue + + val goal = BingoAPI.bingoGoals.firstOrNull { it.slot == slot.slotNumber } ?: continue + if (config.hideDoneDifficulty && goal.done) continue + + val color = goal.getTip()?.let { + val difficulty = Difficulty.valueOf(it.difficulty.uppercase()) + difficulty.color + } ?: LorenzColor.GRAY + slot highlight color.addOpacity(120) + } + } + + fun isEnabled() = LorenzUtils.inSkyBlock && config.bingoSplashGuide + + enum class Difficulty(rawName: String, val color: LorenzColor) { + EASY("Easy", LorenzColor.GREEN), + MEDIUM("Medium", LorenzColor.YELLOW), + HARD("Hard", LorenzColor.RED), + ; + + val displayName = color.getChatColor() + rawName + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoGoal.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoGoal.kt deleted file mode 100644 index 24162fe13..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoGoal.kt +++ /dev/null @@ -1,12 +0,0 @@ -package at.hannibal2.skyhanni.features.bingo.card - -class BingoGoal( - val displayName: String, - val description: String, - val type: GoalType, - val slot: Int, - var done: Boolean, - val hiddenGoalData: HiddenGoalData, -) { - override fun toString(): String = displayName -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/GoalType.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/GoalType.kt deleted file mode 100644 index 01b59e610..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/GoalType.kt +++ /dev/null @@ -1,7 +0,0 @@ -package at.hannibal2.skyhanni.features.bingo.card - -enum class GoalType { - COMMUNITY, - PERSONAL, - ; -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/HiddenGoalData.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/HiddenGoalData.kt deleted file mode 100644 index 8df08906c..000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/HiddenGoalData.kt +++ /dev/null @@ -1,5 +0,0 @@ -package at.hannibal2.skyhanni.features.bingo.card - -import kotlin.time.Duration - -class HiddenGoalData(val unknownTip: Boolean, val nextHintTime: Duration?, val tipNote: String) diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/goals/BingoGoal.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/goals/BingoGoal.kt new file mode 100644 index 000000000..31f01b335 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/goals/BingoGoal.kt @@ -0,0 +1,12 @@ +package at.hannibal2.skyhanni.features.bingo.card.goals + +class BingoGoal( + val displayName: String, + val description: String, + val type: GoalType, + val slot: Int, + var done: Boolean, + val hiddenGoalData: HiddenGoalData, +) { + override fun toString(): String = displayName +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/goals/GoalType.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/goals/GoalType.kt new file mode 100644 index 000000000..b2e4f6d8d --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/goals/GoalType.kt @@ -0,0 +1,7 @@ +package at.hannibal2.skyhanni.features.bingo.card.goals + +enum class GoalType { + COMMUNITY, + PERSONAL, + ; +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/goals/HiddenGoalData.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/goals/HiddenGoalData.kt new file mode 100644 index 000000000..b2ea441d3 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/goals/HiddenGoalData.kt @@ -0,0 +1,5 @@ +package at.hannibal2.skyhanni.features.bingo.card.goals + +import kotlin.time.Duration + +class HiddenGoalData(val unknownTip: Boolean, val nextHintTime: Duration?, val tipNote: String) diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/nextstephelper/BingoNextStepHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/nextstephelper/BingoNextStepHelper.kt new file mode 100644 index 000000000..0cd5df65a --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/nextstephelper/BingoNextStepHelper.kt @@ -0,0 +1,439 @@ +package at.hannibal2.skyhanni.features.bingo.card.nextstephelper + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.CollectionAPI +import at.hannibal2.skyhanni.data.IslandType +import at.hannibal2.skyhanni.data.SkillExperience +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.events.LorenzTickEvent +import at.hannibal2.skyhanni.features.bingo.BingoAPI +import at.hannibal2.skyhanni.features.bingo.card.nextstephelper.steps.ChatMessageStep +import at.hannibal2.skyhanni.features.bingo.card.nextstephelper.steps.CollectionStep +import at.hannibal2.skyhanni.features.bingo.card.nextstephelper.steps.CraftStep +import at.hannibal2.skyhanni.features.bingo.card.nextstephelper.steps.IslandVisitStep +import at.hannibal2.skyhanni.features.bingo.card.nextstephelper.steps.ItemsStep +import at.hannibal2.skyhanni.features.bingo.card.nextstephelper.steps.NextStep +import at.hannibal2.skyhanni.features.bingo.card.nextstephelper.steps.ObtainCrystalStep +import at.hannibal2.skyhanni.features.bingo.card.nextstephelper.steps.PartialProgressItemsStep +import at.hannibal2.skyhanni.features.bingo.card.nextstephelper.steps.ProgressionStep +import at.hannibal2.skyhanni.features.bingo.card.nextstephelper.steps.SkillLevelStep +import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.ItemUtils.name +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzUtils.editCopy +import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher +import at.hannibal2.skyhanni.utils.StringUtils.removeColor +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +class BingoNextStepHelper { + private val config get() = SkyHanniMod.feature.event.bingo.bingoCard + private var dirty = true + + // TODO USE SH-REPO + private val crystalObtainedPattern = " *§r§e(?Topaz|Sapphire|Jade|Amethyst|Amber) Crystal".toPattern() + private val itemIslandRequired = mutableMapOf() + private val itemPreconditions = mutableMapOf() + private val islands = mutableMapOf() + private val collectionPattern = "Reach (?[0-9]+(?:,\\d+)*) (?.*) Collection\\.".toPattern() + private val crystalPattern = "Obtain a (?\\w+) Crystal in the Crystal Hollows\\.".toPattern() + private val skillPattern = "Obtain level (?.*) in the (?.*) Skill.".toPattern() + private val crystalFoundPattern = " *§r§5§l✦ CRYSTAL FOUND §r§7\\(.§r§7/5§r§7\\)".toPattern() + private val rhysTaskName = "30x Enchanted Minerals (Redstone, Lapis Lazuli, Coal) (for Rhys)" + + companion object { + private val finalSteps = mutableListOf() + private var currentSteps = emptyList() + var currentHelp = emptyList() + + fun command() { + updateResult(true) + } + + private fun updateResult(print: Boolean = false) { + if (print) println() + currentSteps = listOf() + for (step in finalSteps) { + printRequirements(step, print) + if (print) println() + } + + currentHelp = drawDisplay(print) + } + + private fun drawDisplay(print: Boolean): MutableList { + val newCurrentHelp = mutableListOf() + newCurrentHelp.add("§6Bingo Step Helper:") + + if (currentSteps.isEmpty()) { + newCurrentHelp.add("§cOpen the §e/bingo §ccard.") + } + for (currentStep in currentSteps) { + val text = getName(currentStep) + newCurrentHelp.add(" §7$text") + if (print) println(text) + } + if (print) println() + return newCurrentHelp + } + + private fun printRequirements(step: NextStep, print: Boolean, parentDone: Boolean = false, depth: Int = 0) { + if (print) println(getName(step, parentDone, depth)) + var requirementsToDo = 0 + for (requirement in step.requirements) { + printRequirements(requirement, print, step.done || parentDone, depth + 1) + if (!requirement.done) { + requirementsToDo++ + } + } + + if (!step.done && !parentDone && requirementsToDo == 0 && !currentSteps.contains(step)) { + currentSteps = currentSteps.editCopy { add(step) } + } + } + + private fun getName(step: NextStep, parentDone: Boolean = false, depth: Int = 0): String { + val prefix = " ".repeat(depth) + if (step.done) "[DONE] " else if (parentDone) "[done] " else "" + val suffix = if (step is ProgressionStep) progressDisplay(step) else "" + return prefix + step.displayName + suffix + } + + private fun progressDisplay(step: ProgressionStep): String { + val having = step.amountHaving + return if (having > 0) { + val needed = step.amountNeeded + val percentage = LorenzUtils.formatPercentage(having.toDouble() / needed) + val havingFormat = LorenzUtils.formatInteger(having) + val neededFormat = LorenzUtils.formatInteger(needed) + " $percentage ($havingFormat/$neededFormat)" + } else "" + } + } + + init { + reset() + } + + @SubscribeEvent + fun onTick(event: LorenzTickEvent) { + if (!LorenzUtils.isBingoProfile) return + if (!config.enabled) return + + if (event.repeatSeconds(1)) { + update() + updateIslandsVisited() + } + if (event.isMod(5)) { + updateCurrentSteps() + } + } + + private var nextMessageIsCrystal = false + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + if (!LorenzUtils.isBingoProfile) return + if (!config.enabled) return + + for (currentStep in currentSteps) { + if (currentStep is ObtainCrystalStep) { + crystalFoundPattern.matchMatcher(event.message) { + nextMessageIsCrystal = true + return + } + if (nextMessageIsCrystal) { + nextMessageIsCrystal = false + crystalObtainedPattern.matchMatcher(event.message) { + if (group("crystalName") == currentStep.crystalName) + currentStep.done() + } + } + } + if (currentStep is PartialProgressItemsStep && currentStep.displayName == rhysTaskName && event.message == "§e[NPC] §dRhys§f: §rThank you for the items!§r") { + currentStep.amountHavingHidden -= 10 + } + } + //TODO add thys message +// if (event.message == "thys message") { +// thys.done() +// } + } + + private fun updateCurrentSteps() { + for (step in currentSteps.toMutableList()) { + if (step is ItemsStep) { + var totalCount = 0L + for ((itemName, multiplier) in step.variants) { + val count = InventoryUtils.countItemsInLowerInventory { it.name?.removeColor() == itemName } + totalCount += count * multiplier + } + if (step.amountHaving != totalCount) { + step.amountHaving = totalCount + if (totalCount >= step.amountNeeded) { + step.done() + } + updateResult() + } + } + if (step is SkillLevelStep) { + val expForSkill = SkillExperience.getExpForSkill(step.skillName.lowercase()) + if (step.amountHaving != expForSkill) { + step.amountHaving = expForSkill + if (expForSkill >= step.amountNeeded) { + step.done() + } + updateResult() + } + } + if (step is CollectionStep) { + val counter = CollectionAPI.getCollectionCounter(step.internalName) ?: 0 + if (step.amountHaving != counter) { + step.amountHaving = counter + if (counter >= step.amountNeeded) { + step.done() + } + updateResult() + } + } + } + } + + private fun NextStep.done(silent: Boolean = false) { + if (done) return + done = true + updateResult() + if (!silent && config.stepHelper) { + LorenzUtils.chat("A bingo goal step is done! ($displayName)") + } + } + + private fun updateIslandsVisited() { + for (step in islands.values) { + val island = step.island + if (island == LorenzUtils.skyBlockIsland) { + step.done() + } + } + } + + private fun update() { + val personalGoals = BingoAPI.personalGoals.filter { !it.done } + if (personalGoals.isEmpty()) { + if (!dirty) { + reset() + dirty = true + } + return + } + + if (!dirty) return + dirty = false + + for (goal in personalGoals) { + val description = goal.description + val bingoCardStep = readDescription(description.removeColor()) + if (bingoCardStep == null) { +// println("Warning: Could not find bingo steps for $description") + } else { + finalSteps.add(bingoCardStep) + } + } + + updateResult() + } + + private fun readDescription(description: String): NextStep? { + collectionPattern.matchMatcher(description) { + val amount = group("amount").replace(",", "").toInt() + val name = group("name") + + return CollectionStep(name, amount) withItemIslandRequirement name + } + + if (description == "Craft an Emerald Ring.") { + return CraftStep("Emerald Ring") requires ( + ItemsStep( + "32x Enchanted Emerald", + "Emerald", + 160 * 32, + mapOf("Emerald" to 1, "Enchanted Emerald" to 160) + ) requires IslandType.DWARVEN_MINES.getStep()) + } + + if (description == "Obtain a Mathematical Hoe Blueprint.") { + return CraftStep("Mathematical Hoe Blueprint") requires ( + ItemsStep( + "32x Jacob's Ticket", + "Jacob's Ticket", + 32, + mapOf("Jacob's Ticket" to 1) + ).addItemRequirements() requires IslandType.GARDEN.getStep()) + } + + crystalPattern.matchMatcher(description) { + val crystal = group("name") + return ObtainCrystalStep(crystal) requires IslandType.CRYSTAL_HOLLOWS.getStep() + } + + skillPattern.matchMatcher(description) { + val level = group("level").toInt() + val skill = group("skill") + return SkillLevelStep(skill, level) + } + + return null + } + + private fun T.makeFinalStep(): T { + finalSteps.add(this) + return this + } + + private infix fun T.withItemIslandRequirement(itemName: String): T { + itemIslandRequired[itemName]?.let { this requires it } + return this + } + + private infix fun T.requires(other: NextStep): T { + requirements.add(other) + return this + } + + private fun IslandType.getStep() = islands.getOrPut(this) { IslandVisitStep(this) } + + private fun reset() { + islands.clear() + finalSteps.clear() + + itemIslandRequired["Acacia Wood"] = IslandType.THE_PARK.getStep() + itemIslandRequired["Redstone"] = IslandType.DEEP_CAVERNS.getStep() + itemIslandRequired["Lapis Lazuli"] = IslandType.DEEP_CAVERNS.getStep() + itemIslandRequired["Coal"] = IslandType.DEEP_CAVERNS.getStep() + itemIslandRequired["Slimeball"] = IslandType.DEEP_CAVERNS.getStep() + itemIslandRequired["Emerald"] = IslandType.DEEP_CAVERNS.getStep() + itemIslandRequired["Mithril"] = IslandType.DEEP_CAVERNS.getStep() + + IslandType.GOLD_MINES.getStep() requires IslandType.HUB.getStep() + IslandType.GOLD_MINES.getStep() requires SkillLevelStep("Mining", 1) + + IslandType.DEEP_CAVERNS.getStep() requires IslandType.GOLD_MINES.getStep() + IslandType.DEEP_CAVERNS.getStep() requires SkillLevelStep("Mining", 5) + + rhys() + IslandType.DWARVEN_MINES.getStep() requires SkillLevelStep( + "Mining", + 12 + ).also { it requires IslandType.THE_FARMING_ISLANDS.getStep() } + + IslandType.CRYSTAL_HOLLOWS.getStep() requires IslandType.DWARVEN_MINES.getStep() + + // TODO add SkyBlock level requirement +