diff options
author | CalMWolfs <94038482+CalMWolfs@users.noreply.github.com> | 2023-05-12 23:39:34 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-12 15:39:34 +0200 |
commit | 07064c0b8dcce1a9ca48077f9f7b87c21e1466be (patch) | |
tree | 6a9ac4b084c3fcec904b52fc219bab4c68b2593c /src/main/java/at/hannibal2 | |
parent | 233b5d9b79afce09b830df22b89bc99180b5b991 (diff) | |
download | skyhanni-07064c0b8dcce1a9ca48077f9f7b87c21e1466be.tar.gz skyhanni-07064c0b8dcce1a9ca48077f9f7b87c21e1466be.tar.bz2 skyhanni-07064c0b8dcce1a9ca48077f9f7b87c21e1466be.zip |
Visitor drop counter (#103)
Diffstat (limited to 'src/main/java/at/hannibal2')
9 files changed, 305 insertions, 5 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index 6a0deeb26..e43cf16ec 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -32,6 +32,7 @@ import at.hannibal2.skyhanni.features.garden.contest.JacobFarmingContestsInvento import at.hannibal2.skyhanni.features.garden.farming.* import at.hannibal2.skyhanni.features.garden.inventory.* import at.hannibal2.skyhanni.features.garden.visitor.GardenVisitorColorNames +import at.hannibal2.skyhanni.features.garden.visitor.GardenVisitorDropStatistics import at.hannibal2.skyhanni.features.garden.visitor.GardenVisitorFeatures import at.hannibal2.skyhanni.features.garden.visitor.GardenVisitorTimer import at.hannibal2.skyhanni.features.inventory.* @@ -268,6 +269,7 @@ class SkyHanniMod { loadModule(TrevorFeatures()) loadModule(TrevorSolver) loadModule(BingoCardTips()) + loadModule(GardenVisitorDropStatistics) init() diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/Garden.java b/src/main/java/at/hannibal2/skyhanni/config/features/Garden.java index 304ba66d9..2746cc991 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/Garden.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/Garden.java @@ -174,6 +174,71 @@ public class Garden { @ConfigAccordionId(id = 1) public boolean visitorHideChat = true; + + @Expose + @ConfigOption(name = "Visitor Drops Statistics", desc = "") + @Accordion + public VisitorDrops visitorDropsStatistics = new VisitorDrops(); + + public static class VisitorDrops { + + @Expose + @ConfigOption( + name = "Enabled", + desc = "Tallies up statistic about visitors and the rewards you have received from them.\n" + + "§eThis feature is in beta please report issues on the discord!" + ) + @ConfigEditorBoolean + public boolean enabled = false; + + @Expose + @ConfigOption( + name = "Text Format", + desc = "Drag text to change the appearance of the overlay." + ) + @ConfigEditorDraggableList( + exampleText = { + "§e§lVisitor Statistics", + "§e1,636 Total", + "§a1,172§f-§9382§f-§681§f-§c1", + "§21,382 Accepted", + "§c254 Denied", + " ", + "§c62,072 Copper", + "§23.2m Farming EXP", + "§647.2m Coins Spent", + "§b23 §9Flowering Bouquet", + "§b4 §9Overgrown Grass", + "§b2 §9Green Bandana", + "§b1 §9Dedication IV", + "§b6 §9Music Rune", + "§b1 §cSpace Helmet", + " ", // If they want another empty row + } + ) + public List<Integer> textFormat = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12)); + + @Expose + @ConfigOption(name = "Display Numbers First", desc = "Determines whether the number or drop name displays first. " + + "§eNote: Will not update the preview above!") + @ConfigEditorBoolean + public boolean displayNumbersFirst = true; + + @Expose + @ConfigOption(name = "Display Icons", desc = "Replaces the drop names with icons. " + + "§eNote: Will not update the preview above!") + @ConfigEditorBoolean + public boolean displayIcons = false; + + @Expose + @ConfigOption(name = "Only On Barn Plot", desc = "Only shows the overlay while on the barn plot.") + @ConfigEditorBoolean + public boolean onlyOnBarn = true; + + @Expose + public Position visitorDropPos = new Position(10, 80, false, true); + } + @Expose @ConfigOption(name = "Numbers", desc = "") @ConfigEditorAccordion(id = 5) @@ -1013,7 +1078,7 @@ public class Garden { ) @ConfigEditorBoolean @ConfigAccordionId(id = 22) - public boolean farmingFortuneDropMultiplier = false; + public boolean farmingFortuneDropMultiplier = true; @Expose public Position farmingFortunePos = new Position(-375, -200, false, true); diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/Hidden.java b/src/main/java/at/hannibal2/skyhanni/config/features/Hidden.java index a310ab367..bb5349168 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/Hidden.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/Hidden.java @@ -3,6 +3,7 @@ package at.hannibal2.skyhanni.config.features; import at.hannibal2.skyhanni.data.model.ComposterUpgrade; import at.hannibal2.skyhanni.features.garden.CropAccessory; import at.hannibal2.skyhanni.features.garden.CropType; +import at.hannibal2.skyhanni.features.garden.visitor.VisitorReward; import com.google.gson.annotations.Expose; import java.util.ArrayList; @@ -89,4 +90,31 @@ public class Hidden { @Expose public String gardenComposterCurrentFuelItem = ""; + + + @Expose + public VisitorDrops visitorDrops = new VisitorDrops(); + + public static class VisitorDrops { + @Expose + public int acceptedVisitors = 0; + + @Expose + public int deniedVisitors = 0; + + @Expose + public List<Long> visitorRarities = new ArrayList<>(); + + @Expose + public int copper = 0; + + @Expose + public long farmingExp = 0; + + @Expose + public long coinsSpent = 0; + + @Expose + public Map<VisitorReward, Integer> rewardsCount = new HashMap<>(); + } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt index 4c19346b0..2eb6e4fee 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt @@ -34,7 +34,8 @@ object GardenAPI { var itemInHand: ItemStack? = null var cropInHand: CropType? = null var mushroomCowPet = false - var onBarnPlot = false + var inBarn = false + val onBarnPlot get() = inBarn && inGarden() var tick = 0 @@ -57,7 +58,7 @@ object GardenAPI { if (!inGarden()) return tick++ if (tick % 10 == 0) { - onBarnPlot = ScoreboardData.sidebarLinesFormatted.contains(" §7⏣ §aThe Garden") + inBarn = ScoreboardData.sidebarLinesFormatted.contains(" §7⏣ §aThe Garden") // We ignore random hypixel moments Minecraft.getMinecraft().currentScreen ?: return diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorDropStatistics.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorDropStatistics.kt new file mode 100644 index 000000000..9e8621beb --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorDropStatistics.kt @@ -0,0 +1,177 @@ +package at.hannibal2.skyhanni.features.garden.visitor + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.features.garden.GardenAPI +import at.hannibal2.skyhanni.utils.LorenzUtils.addAsSingletonList +import at.hannibal2.skyhanni.utils.LorenzUtils.editCopy +import at.hannibal2.skyhanni.utils.NEUItems +import at.hannibal2.skyhanni.utils.NumberUtil +import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators +import at.hannibal2.skyhanni.utils.NumberUtil.formatNumber +import at.hannibal2.skyhanni.utils.RenderUtils.renderStringsAndItems +import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher +import at.hannibal2.skyhanni.utils.StringUtils.removeColor +import net.minecraftforge.event.world.WorldEvent +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +object GardenVisitorDropStatistics { + private val config get() = SkyHanniMod.feature.garden.visitorDropsStatistics + private val hidden get() = SkyHanniMod.feature.hidden.visitorDrops + private var display = listOf<List<Any>>() + + private var acceptedVisitors = 0 + var deniedVisitors = 0 + private var totalVisitors = 0 + private var visitorRarities = mutableListOf<Long>() + private var copper = 0 + private var farmingExp = 0L + var coinsSpent = 0L + + private val acceptPattern = "OFFER ACCEPTED with (?<visitor>.*) [(](?<rarity>.*)[)]".toPattern() + private val copperPattern = "[+](?<amount>.*) Copper".toPattern() + private val farmingExpPattern = "[+](?<amount>.*) Farming XP".toPattern() + private var rewardsCount = mapOf<VisitorReward, Int>() + + private fun formatDisplay(map: List<List<Any>>): MutableList<List<Any>> { + val newList = mutableListOf<List<Any>>() + for (index in config.textFormat) { + newList.add(map[index]) + } + return newList + } + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + if (!GardenAPI.onBarnPlot) return + val message = event.message.removeColor().trim() + + copperPattern.matchMatcher(message) { + val amount = group("amount").formatNumber().toInt() + copper += amount + saveAndUpdate() + } + farmingExpPattern.matchMatcher(message) { + val amount = group("amount").formatNumber() + farmingExp += amount + saveAndUpdate() + } + acceptPattern.matchMatcher(message) { + setRarities(group("rarity")) + saveAndUpdate() + } + + for (reward in VisitorReward.values()) { + reward.pattern.matchMatcher(message) { + val old = rewardsCount[reward] ?: 0 + rewardsCount = rewardsCount.editCopy { this[reward] = old + 1 } + saveAndUpdate() + } + } + } + + private fun setRarities(rarity: String) { + acceptedVisitors += 1 + val currentRarity = VisitorRarity.valueOf(rarity) + val temp = visitorRarities[currentRarity.ordinal] + 1 + visitorRarities[currentRarity.ordinal] = temp + saveAndUpdate() + } + + private fun drawVisitorStatsDisplay() = buildList<List<Any>> { + //0 + addAsSingletonList("§e§lVisitor Statistics") + //1 + addAsSingletonList(format(totalVisitors, "Total", "§e", "")) + //2 + addAsSingletonList( + "§a${visitorRarities[0].addSeparators()}§f-" + + "§9${visitorRarities[1].addSeparators()}§f-" + + "§6${visitorRarities[2].addSeparators()}§f-" + + "§c${visitorRarities[3].addSeparators()}" + ) + //3 + addAsSingletonList(format(acceptedVisitors, "Accepted", "§2", "")) + //4 + addAsSingletonList(format(deniedVisitors, "Denied", "§c", "")) + //5 + addAsSingletonList("") + //6 + addAsSingletonList(format(copper, "Copper", "§c", "")) + //7 + addAsSingletonList(format(farmingExp, "Farming EXP", "§3", "§7")) + //8 + addAsSingletonList(format(coinsSpent, "Coins Spent", "§6", "")) + + //9 - 14 + for (reward in VisitorReward.values()) { + val count = rewardsCount[reward] ?: 0 + if (config.displayIcons) {// Icons + val stack = NEUItems.getItemStack(reward.internalName) + if (config.displayNumbersFirst) + add(listOf("§b${count.addSeparators()} ", stack)) + else add(listOf(stack, " §b${count.addSeparators()}")) + } else { // No Icons + addAsSingletonList(format(count, reward.displayName, "§b")) + } + } + } + + fun format(amount: Number, name: String, color: String, amountColor: String = color) = + if (config.displayNumbersFirst) + "$color${format(amount)} $name" + else + "$color$name: $amountColor${format(amount)}" + + fun format(amount: Number): String { + if (amount is Int) return amount.addSeparators() + if (amount is Long) return NumberUtil.format(amount) + return "$amount" + } + + fun saveAndUpdate() { + if (!GardenAPI.inGarden()) return + hidden.acceptedVisitors = acceptedVisitors + hidden.deniedVisitors = deniedVisitors + totalVisitors = acceptedVisitors + deniedVisitors + hidden.visitorRarities = visitorRarities + hidden.copper = copper + hidden.farmingExp = farmingExp + hidden.coinsSpent = coinsSpent + hidden.rewardsCount = rewardsCount + display = formatDisplay(drawVisitorStatsDisplay()) + } + + @SubscribeEvent + fun onWorldLoad(event: WorldEvent.Load) { + if (hidden.visitorRarities.size == 0) { + hidden.visitorRarities.add(0) + hidden.visitorRarities.add(0) + hidden.visitorRarities.add(0) + hidden.visitorRarities.add(0) + } + acceptedVisitors = hidden.acceptedVisitors + deniedVisitors = hidden.deniedVisitors + totalVisitors = acceptedVisitors + deniedVisitors + visitorRarities = hidden.visitorRarities + copper = hidden.copper + farmingExp = hidden.farmingExp + coinsSpent = hidden.coinsSpent + rewardsCount = hidden.rewardsCount + saveAndUpdate() + } + + @SubscribeEvent + fun onRenderOverlay(event: GuiRenderEvent.GameOverlayRenderEvent) { + if (!config.enabled) return + if (!GardenAPI.inGarden()) return + if (GardenAPI.hideExtraGuis()) return + if (config.onlyOnBarn && !GardenAPI.onBarnPlot) return + config.visitorDropPos.renderStringsAndItems(display, posLabel = "Visitor Stats") + } +} + +enum class VisitorRarity { + UNCOMMON, RARE, LEGENDARY, SPECIAL, +}
\ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorFeatures.kt index 057b5f670..14d0920c4 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorFeatures.kt @@ -35,6 +35,7 @@ import net.minecraftforge.event.entity.player.ItemTooltipEvent import net.minecraftforge.fml.common.eventhandler.EventPriority import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import net.minecraftforge.fml.common.gameevent.TickEvent +import kotlin.math.round class GardenVisitorFeatures { private val visitors = mutableMapOf<String, Visitor>() @@ -47,6 +48,7 @@ class GardenVisitorFeatures { private val visitorChatMessagePattern = "§e\\[NPC] (§.)?(?<name>.*)§f: §r.*".toPattern() private val config get() = SkyHanniMod.feature.garden private val logger = LorenzLogger("garden/visitors") + private var price = 0.0 companion object { var inVisitorInventory = false @@ -221,12 +223,15 @@ class GardenVisitorFeatures { if (event.slot.stack?.name != "§cRefuse Offer") return changeStatus(visitor, VisitorStatus.REFUSED, "refused") update() + GardenVisitorDropStatistics.deniedVisitors += 1 + GardenVisitorDropStatistics.saveAndUpdate() return } if (event.slotId == 29) { if (event.slot.stack?.getLore()?.any { it == "§eClick to give!" } == true) { changeStatus(visitor, VisitorStatus.ACCEPTED, "accepted") update() + GardenVisitorDropStatistics.coinsSpent += round(price).toLong() return } } @@ -303,7 +308,7 @@ class GardenVisitorFeatures { LorenzUtils.error(message) return } - val price = NEUItems.getPrice(internalName) * amount + price = NEUItems.getPrice(internalName) * amount totalPrice += price if (config.visitorShowPrice) { val format = NumberUtil.format(price) diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorTimer.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorTimer.kt index 6c43f92f1..e7b55bf14 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorTimer.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorTimer.kt @@ -48,6 +48,9 @@ class GardenVisitorTimer { CopyErrorCommand.errorStackTrace = error.stackTrace.asList() LorenzUtils.chat("§c[SkyHanni] encountered an error when updating visitor display, please run /shcopyerror") } + try { + GardenVisitorDropStatistics.saveAndUpdate() + } catch (_: Throwable) {} // no config yet } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/VisitorReward.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/VisitorReward.kt new file mode 100644 index 000000000..7651a1d3e --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/VisitorReward.kt @@ -0,0 +1,13 @@ +package at.hannibal2.skyhanni.features.garden.visitor + +import java.util.regex.Pattern + +enum class VisitorReward(val displayName: String, val internalName: String, val pattern: Pattern) { + GREEN_BANDANA("§9Green Bandana", "GREEN_BANDANA", "[+]1x Green Bandana".toPattern()), + OVERGROWN_GRASS("§9Overgrown Grass", "OVERGROWN_GRASS", "[+]1x Overgrown Grass".toPattern()), + FLOWERING_BOUQUET("§9Flowering Bouquet", "FLOWERING_BOUQUET", "[+]1x Flowering Bouquet".toPattern()), + DEDICATION("§9Dedication IV", "DEDICATION;4", "Dedication (IV|4) Book".toPattern()), + SPACE_HELMET("§cSpace Helmet", "DCTR_SPACE_HELM", "[+]Space Helmet".toPattern()), + // Pretty sure that the symbol is ◆ but not 100% + MUSIC_RUNE("§9Music Rune", "MUSIC_RUNE;1", "[+]1x ◆ Music Rune [1I]".toPattern()), +}
\ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/utils/NumberUtil.kt b/src/main/java/at/hannibal2/skyhanni/utils/NumberUtil.kt index b776cb1dc..cae0a5896 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/NumberUtil.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/NumberUtil.kt @@ -178,7 +178,12 @@ object NumberUtil { } fun String.formatNumber(): Long { + var hasDecimal = false var text = replace(",", "") + if (text.contains(".")) { + text = replace(".", "") + hasDecimal = true + } val multiplier = if (text.endsWith("k")) { text = text.substring(0, text.length - 1) 1_000 @@ -186,7 +191,8 @@ object NumberUtil { text = text.substring(0, text.length - 1) 1_000_000 } else 1 - val d = text.toDouble() + var d = text.toDouble() + if (hasDecimal) d /= 10 return (d * multiplier).toLong() } }
\ No newline at end of file |