Skip to content

Commit

Permalink
Feature: Highlight More Hoppity's Collection Rabbits (hannibal002#2438)
Browse files Browse the repository at this point in the history
Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
  • Loading branch information
The1Divider and hannibal002 authored Sep 15, 2024
1 parent 8bea71e commit b8f4b63
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 28 deletions.
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

0 comments on commit b8f4b63

Please sign in to comment.