Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Highlight More Hoppity's Collection Rabbits #2438

Merged
merged 15 commits into from
Sep 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import at.hannibal2.skyhanni.config.FeatureToggle;
import at.hannibal2.skyhanni.config.core.config.Position;
import at.hannibal2.skyhanni.features.event.hoppity.HoppityCollectionStats.HighlightRabbitTypes;
import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryStats.ChocolateFactoryStat;
import com.google.gson.annotations.Expose;
import io.github.notenoughupdates.moulconfig.annotations.Accordion;
Expand Down Expand Up @@ -174,18 +175,22 @@ public class ChocolateFactoryConfig {
public boolean hoppityMenuShortcut = true;

@Expose
@ConfigOption(name = "Highlight Requirement Rabbits", desc = "Highlight rabbits that have requirements.\n" +
"§cRed: Requirement not met.\n" +
"§aGreen: Requirement met.")
@ConfigOption(name = "Highlight Found Rabbits", desc = "Highlight rabbits that have already been found.")
@ConfigEditorBoolean
@FeatureToggle
public boolean highlightRabbitsWithRequirement = false;
public boolean highlightFoundRabbits = false;

@Expose
@ConfigOption(name = "Only Requirement Not Met", desc = "Only highlight the rabbits you don't have the requirement for.")
@ConfigEditorBoolean
@FeatureToggle
public boolean onlyHighlightRequirementNotMet = true;
@ConfigOption(name = "Highlight Rabbits", desc = "Highlight specific rabbit types in Hoppity's Collection.")
@ConfigEditorDraggableList
public List<HighlightRabbitTypes> highlightRabbits = new ArrayList<>(Arrays.asList(
HighlightRabbitTypes.ABI,
HighlightRabbitTypes.FACTORY,
HighlightRabbitTypes.MET,
HighlightRabbitTypes.NOT_MET,
HighlightRabbitTypes.SHOP,
HighlightRabbitTypes.STRAYS
));

@Expose
@ConfigOption(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,17 @@ import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName
import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
import at.hannibal2.skyhanni.utils.NumberUtil.formatInt
import at.hannibal2.skyhanni.utils.RegexUtils.anyMatches
import at.hannibal2.skyhanni.utils.RegexUtils.find
import at.hannibal2.skyhanni.utils.RegexUtils.findMatcher
import at.hannibal2.skyhanni.utils.RegexUtils.matchFirst
import at.hannibal2.skyhanni.utils.RegexUtils.firstMatcher
import at.hannibal2.skyhanni.utils.RegexUtils.matches
import at.hannibal2.skyhanni.utils.RenderUtils.highlight
import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables
import at.hannibal2.skyhanni.utils.StringUtils.removeColor
import at.hannibal2.skyhanni.utils.renderables.Renderable
import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
import net.minecraft.item.ItemStack
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import java.util.regex.Pattern

@SkyHanniModule
object HoppityCollectionStats {
Expand Down Expand Up @@ -97,6 +99,30 @@ object HoppityCollectionStats {
"§c✖ §7Requirement §e(?<acquired>[\\d,]+)§7/§a(?<required>[\\d,]+)",
)

/**
* REGEX-TEST: §6Factory Milestones§7.
*/
private val factoryMilestone by RepoPattern.pattern(
"rabbit.requirement.factory",
"§6Factory Milestones§7.",
)

/**
* REGEX-TEST: §6Shop Milestones§7.
*/
private val shopMilestone by RepoPattern.pattern(
"rabbit.requirement.shop",
"§6Shop Milestones§7.",
)

/**
* REGEX-TEST: §7§7Obtained by finding the §aStray Rabbit
*/
private val strayRabbit by RepoPattern.pattern(
"rabbit.requirement.stray",
"§7§7Obtained by finding the §aStray Rabbit",
)

/**
* REGEX-TEST: Find 15 unique egg locations in the Deep Caverns.
*/
Expand All @@ -109,6 +135,21 @@ object HoppityCollectionStats {
private val loggedRabbits
get() = ProfileStorageData.profileSpecific?.chocolateFactory?.rabbitCounts ?: mutableMapOf()

enum class HighlightRabbitTypes(
private val displayName: String,
val color: LorenzColor,
) {
ABI("§2Abi", LorenzColor.DARK_GREEN),
FACTORY("§eFactory Milestones", LorenzColor.YELLOW),
MET("§aRequirement Met", LorenzColor.GREEN),
NOT_MET("§cRequirement Not Met.", LorenzColor.RED),
SHOP("§6Shop Milestones", LorenzColor.GOLD),
STRAYS("§3Stray Rabbits", LorenzColor.DARK_AQUA),
;

override fun toString(): String = displayName
}

@KSerializable
data class LocationRabbit(
val locationName: String,
Expand All @@ -133,17 +174,57 @@ object HoppityCollectionStats {

var inInventory = false

private val highlightConfigMap: Map<Pattern, HighlightRabbitTypes> = mapOf(
factoryMilestone to HighlightRabbitTypes.FACTORY,
requirementMet to HighlightRabbitTypes.MET,
requirementNotMet to HighlightRabbitTypes.NOT_MET,
shopMilestone to HighlightRabbitTypes.SHOP,
strayRabbit to HighlightRabbitTypes.STRAYS,
)

@SubscribeEvent
fun onInventoryOpen(event: InventoryFullyOpenedEvent) {
if (!(LorenzUtils.inSkyBlock)) return
if (!pagePattern.matches(event.inventoryName)) return
if (!pagePattern.matches(event.inventoryName)) {
// Clear highlight cache in case options are toggled
highlightMap.clear()
return
}

inInventory = true
if (config.hoppityCollectionStats) {
display = buildDisplay(event)
}

if (config.highlightRabbits.isNotEmpty()) {
for ((_, stack) in event.inventoryItems) filterRabbitToHighlight(stack)
}
}

private fun filterRabbitToHighlight(stack: ItemStack) {
val lore = stack.getLore()

if (lore.isEmpty()) return
if (!rabbitNotFoundPattern.anyMatches(lore) && !config.highlightFoundRabbits) return

if (highlightMap.containsKey(stack.displayName)) return

if (stack.displayName == "§aAbi" && config.highlightRabbits.contains(HighlightRabbitTypes.ABI)) {
highlightMap[stack.displayName] = HighlightRabbitTypes.ABI.color
return
}

// cache rabbits until collection is closed
for ((pattern, rabbitType) in highlightConfigMap) {
if (pattern.anyMatches(lore) && config.highlightRabbits.contains(rabbitType)) {
highlightMap[stack.displayName] = rabbitType.color
break
}
}
}

private var highlightMap = mutableMapOf<String, LorenzColor>()

@SubscribeEvent
fun onInventoryClose(event: InventoryCloseEvent) {
inInventory = false
Expand All @@ -162,22 +243,17 @@ object HoppityCollectionStats {
)
}

// TODO cache with inventory update event
@SubscribeEvent
fun onBackgroundDrawn(event: GuiContainerEvent.BackgroundDrawnEvent) {
if (!config.highlightRabbitsWithRequirement) return
if (!inInventory) return
if (config.highlightRabbits.isEmpty()) return

for (slot in InventoryUtils.getItemsInOpenChest()) {
val lore = slot.stack.getLore()
if (lore.any { requirementMet.find(it) } && !config.onlyHighlightRequirementNotMet)
slot highlight LorenzColor.GREEN
if (lore.any { requirementNotMet.find(it) }) {
val found = !rabbitNotFoundPattern.anyMatches(lore)
// Hypixel allows purchasing Rabbits from Hoppity NPC even when the requirement is not yet met.
if (!found) {
slot highlight LorenzColor.RED
}
val name = slot.stack.displayName

if (name.isEmpty()) continue
highlightMap[name]?.let {
slot highlight it
}
}
}
Expand All @@ -186,9 +262,10 @@ object HoppityCollectionStats {
if (!config.showLocationRequirementsRabbitsInHoppityStats) return
val missingLocationRabbits = locationRabbitRequirements.values.filter { !it.hasMetRequirements() }

val tips = locationRabbitRequirements.map {
it.key + " §7(§e" + it.value.locationName + "§7): " + (if (it.value.hasMetRequirements()) "§a" else "§c") +
it.value.foundCount + "§7/§a" + it.value.requiredCount
val tips = locationRabbitRequirements.map { (name, rabbit) ->
"$name §7(§e${rabbit.locationName}§7): ${
if (rabbit.hasMetRequirements()) "§a" else "§c"
}${rabbit.foundCount}§7/§a${rabbit.requiredCount}"
}

newList.add(
Expand Down Expand Up @@ -311,7 +388,7 @@ object HoppityCollectionStats {
// used to make sure that mod data is synchronized with Hypixel
private fun getFoundRabbitsFromHypixel(event: InventoryFullyOpenedEvent): Int {
return event.inventoryItems.firstNotNullOf {
it.value.getLore().matchFirst(rabbitsFoundPattern) {
rabbitsFoundPattern.firstMatcher(it.value.getLore()) {
group("current").formatInt()
}
}
Expand Down Expand Up @@ -354,15 +431,14 @@ object HoppityCollectionStats {

if (!found) continue

val duplicates = itemLore.matchFirst(duplicatesFoundPattern) {
val duplicates = duplicatesFoundPattern.firstMatcher(itemLore) {
group("duplicates").formatInt()
} ?: 0

loggedRabbits[itemName] = duplicates + 1
}
}


// bugfix for some weird potential user errors (e.g. if users play on alpha and get rabbits)
fun clearSavedRabbits() {
loggedRabbits.clear()
Expand Down
Loading