diff options
7 files changed, 370 insertions, 142 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index e38172d3a..ab60138af 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -200,6 +200,7 @@ import at.hannibal2.skyhanni.features.garden.inventory.GardenInventoryNumbers import at.hannibal2.skyhanni.features.garden.inventory.GardenNextPlotPrice import at.hannibal2.skyhanni.features.garden.inventory.GardenPlotIcon import at.hannibal2.skyhanni.features.garden.inventory.SkyMartCopperPrice +import at.hannibal2.skyhanni.features.garden.pests.PestAPI import at.hannibal2.skyhanni.features.garden.pests.PestFinder import at.hannibal2.skyhanni.features.garden.pests.PestSpawn import at.hannibal2.skyhanni.features.garden.pests.PestSpawnTimer @@ -508,6 +509,7 @@ class SkyHanniMod { loadModule(IsFishingDetection) loadModule(LorenzUtils) loadModule(NEUItems) + loadModule(PestAPI) // features loadModule(BazaarOrderHelper()) diff --git a/src/main/java/at/hannibal2/skyhanni/events/garden/pests/PestSpawnEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/garden/pests/PestSpawnEvent.kt index 20b80ff4a..a530e4dec 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/garden/pests/PestSpawnEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/garden/pests/PestSpawnEvent.kt @@ -2,4 +2,4 @@ package at.hannibal2.skyhanni.events.garden.pests import at.hannibal2.skyhanni.events.LorenzEvent -class PestSpawnEvent(val amountPests: Int, val plotName: String) : LorenzEvent() +class PestSpawnEvent(val amountPests: Int, val plotNames: List<String>, val unkownAmount: Boolean) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/garden/pests/PestUpdateEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/garden/pests/PestUpdateEvent.kt new file mode 100644 index 000000000..6f444fa86 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/events/garden/pests/PestUpdateEvent.kt @@ -0,0 +1,5 @@ +package at.hannibal2.skyhanni.events.garden.pests + +import at.hannibal2.skyhanni.events.LorenzEvent + +class PestUpdateEvent : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenPlotAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenPlotAPI.kt index cac76452e..5ed6d2434 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenPlotAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenPlotAPI.kt @@ -25,10 +25,21 @@ import kotlin.time.Duration.Companion.minutes object GardenPlotAPI { private val patternGroup = RepoPattern.group("garden.plot") + + /** + * REGEX-TEST: §aPlot §7- §b4 + */ private val plotNamePattern by patternGroup.pattern( "name", "§.Plot §7- §b(?<name>.*)" ) + /** + * REGEX-TEST: §aThe Barn + */ + private val barnNamePattern by patternGroup.pattern( + "barnname", + "§.(?<name>The Barn)" + ) private val plotSprayedPattern by patternGroup.pattern( "spray.target", "§a§lSPRAYONATOR! §r§7You sprayed §r§aPlot §r§7- §r§b(?<plot>.*) §r§7with §r§a(?<spray>.*)§r§7!" @@ -60,6 +71,9 @@ object GardenPlotAPI { @Expose var sprayHasNotified: Boolean, + + @Expose + var isPestCountInaccurate: Boolean, ) data class SprayData( @@ -67,7 +81,7 @@ object GardenPlotAPI { val type: SprayType, ) - private fun Plot.getData() = GardenAPI.storage?.plotData?.getOrPut(id) { PlotData(id, "$id", 0, null, null, false) } + private fun Plot.getData() = GardenAPI.storage?.plotData?.getOrPut(id) { PlotData(id, "$id", 0, null, null, false, false) } var Plot.name: String get() = getData()?.name ?: "$id" @@ -93,6 +107,12 @@ object GardenPlotAPI { !it.sprayHasNotified && it.sprayExpiryTime?.isInPast() == true } == true + var Plot.isPestCountInaccurate: Boolean + get() = this.getData()?.isPestCountInaccurate ?: false + set(value) { + this.getData()?.isPestCountInaccurate = value + } + fun Plot.markExpiredSprayAsNotified() { getData()?.apply { sprayHasNotified = true } } @@ -105,12 +125,13 @@ object GardenPlotAPI { } } - fun Plot.isBarn() = id == -1 + fun Plot.isBarn() = id == 0 fun Plot.isPlayerInside() = box.isPlayerInside() fun Plot.sendTeleportTo() { - ChatUtils.sendCommandToServer("tptoplot $name") + if (isBarn()) ChatUtils.sendCommandToServer("tptoplot barn") + else ChatUtils.sendCommandToServer("tptoplot $name") LockMouseLook.autoDisable() } @@ -118,7 +139,7 @@ object GardenPlotAPI { val plotMap = listOf( listOf(21, 13, 9, 14, 22), listOf(15, 5, 1, 6, 16), - listOf(10, 2, -1, 3, 11), + listOf(10, 2, 0, 3, 11), listOf(17, 7, 4, 8, 18), listOf(23, 19, 12, 20, 24), ) @@ -166,6 +187,10 @@ object GardenPlotAPI { val itemStack = event.inventoryItems[plot.inventorySlot] ?: continue plot.unlocked = itemStack.getLore().all { !it.contains("§7Cost:") } plotNamePattern.matchMatcher(itemStack.name) { + val plotName = group("name") + plot.name = plotName + } + barnNamePattern.matchMatcher(itemStack.name) { plot.name = group("name") } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestAPI.kt index dca966be1..536d78a81 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestAPI.kt @@ -1,8 +1,27 @@ package at.hannibal2.skyhanni.features.garden.pests +import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.events.ScoreboardChangeEvent +import at.hannibal2.skyhanni.events.TabListUpdateEvent +import at.hannibal2.skyhanni.events.garden.pests.PestSpawnEvent +import at.hannibal2.skyhanni.events.garden.pests.PestUpdateEvent import at.hannibal2.skyhanni.features.garden.GardenAPI +import at.hannibal2.skyhanni.features.garden.GardenPlotAPI +import at.hannibal2.skyhanni.features.garden.GardenPlotAPI.isBarn +import at.hannibal2.skyhanni.features.garden.GardenPlotAPI.isPestCountInaccurate +import at.hannibal2.skyhanni.features.garden.GardenPlotAPI.pests +import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.LocationUtils.distanceSqToPlayer import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName +import at.hannibal2.skyhanni.utils.NumberUtil.formatNumber +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher +import at.hannibal2.skyhanni.utils.StringUtils.removeColor +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent object PestAPI { @@ -21,4 +40,222 @@ object PestAPI { fun hasVacuumInHand() = InventoryUtils.itemInHandId in vacuumVariants fun SprayType.getPests() = PestType.entries.filter { it.spray == this } + + private val patternGroup = RepoPattern.group("garden.pestsapi") + private val pestsInScoreboardPattern by patternGroup.pattern( + "scoreboard.pests", + " §7⏣ §[ac]The Garden §4§lൠ§7 x(?<pests>.*)" + ) + /** + * REGEX-TEST: §7⏣ §aPlot §7- §b22a + * REGEX-TEST: §7⏣ §aThe Garden + */ + private val noPestsInScoreboardPattern by patternGroup.pattern( + "scoreboard.nopests", + " §7⏣ §a(?:The Garden|Plot §7- §b.+)$" + ) + /** + * REGEX-TEST: §aPlot §7- §b4 §4§lൠ§7 x1 + */ + private val pestsInPlotScoreboardPattern by patternGroup.pattern( + "scoreboard.plot.pests", + "\\s*(?:§.)*Plot (?:§.)*- (?:§.)*(?<plot>.+) (?:§.)*ൠ(?:§.)* x(?<pests>\\d+)" + ) + /** + * REGEX-TEST: §aPlot §7- §b3 + */ + private val noPestsInPlotScoreboardPattern by patternGroup.pattern( + "scoreboard.plot.nopests", + "\\s*(?:§.)*Plot (?:§.)*- (?:§.)*(?<plot>.{1,3})$" + ) + private val pestInventoryPattern by patternGroup.pattern( + "inventory", + "§4§lൠ §cThis plot has §6(?<amount>\\d) Pests?§c!" + ) + /** + * REGEX-TEST: Infested Plots: §r§b4§r§f, §r§b12§r§f, §r§b13§r§f, §r§b18§r§f, §r§b20 + */ + private val infectedPlotsTablistPattern by patternGroup.pattern( + "tablist.infectedplots", + "\\sInfested Plots: (?<plots>.*)" + ) + + private fun fixPests() { + val accurateAmount = getPlotsWithAccuratePests().sumOf { it.pests } + val inaccurateAmount = getPlotsWithInaccuratePests().size + if (scoreboardPests == accurateAmount + inaccurateAmount) { // if we can assume all inaccurate plots have 1 pest each + for (plot in getPlotsWithInaccuratePests()) { + plot.pests = 1 + plot.isPestCountInaccurate = false + } + } + if (inaccurateAmount == 1) { // if we can assume all the inaccurate pests are in the only inaccurate plot + val plot = getPlotsWithInaccuratePests().firstOrNull() + plot?.pests = scoreboardPests - accurateAmount + plot?.isPestCountInaccurate = false + } + } + + private fun updatePests() { + fixPests() + PestUpdateEvent().postAndCatch() + } + + @SubscribeEvent + fun onPestSpawn(event: PestSpawnEvent) { + if (!GardenAPI.inGarden()) return + PestSpawnTimer.lastSpawnTime = SimpleTimeMark.now() + val plotNames = event.plotNames + for (plotName in plotNames) { + val plot = GardenPlotAPI.getPlotByName(plotName) + if (plot == null) { + ChatUtils.userError("Open Plot Management Menu to load plot names and pest locations!") + return + } + if (event.unkownAmount) { + plot.isPestCountInaccurate = true + } else { + plot.pests += event.amountPests + plot.isPestCountInaccurate = false + } + } + updatePests() + } + + @SubscribeEvent + fun onInventoryOpen(event: InventoryFullyOpenedEvent) { + if (!GardenAPI.inGarden()) return + if (event.inventoryName != "Configure Plots") return + + for (plot in GardenPlotAPI.plots) { + if (plot.isBarn()) continue + plot.pests = 0 + plot.isPestCountInaccurate = false + val item = event.inventoryItems[plot.inventorySlot] ?: continue + for (line in item.getLore()) { + pestInventoryPattern.matchMatcher(line) { + plot.pests = group("amount").toInt() + } + } + } + updatePests() + } + + @SubscribeEvent + fun onTablistUpdate(event: TabListUpdateEvent) { + if (!GardenAPI.inGarden()) return + var previousLine = "" + for (line in event.tabList) { + infectedPlotsTablistPattern.matchMatcher(line) { + if (previousLine == line) return + val plotList = mutableListOf<Int>() + group("plots").removeColor().split(", ").toMutableList().forEach { + plotList.add(it.toInt()) + } + + GardenPlotAPI.plots.forEach { + if (plotList.contains(it.id)) { + if (!it.isPestCountInaccurate && it.pests == 0) { + it.isPestCountInaccurate = true + } + } else { + it.pests = 0 + it.isPestCountInaccurate = false + } + } + previousLine = line + updatePests() + } + } + } + + @SubscribeEvent + fun onScoreboardChange(event: ScoreboardChangeEvent) { + if (!GardenAPI.inGarden()) return + + for (line in event.newList) { + // gets the total amount of pests in the garden + pestsInScoreboardPattern.matchMatcher(line) { + val newPests = group("pests").formatNumber().toInt() + if (newPests != scoreboardPests) { + removePests(scoreboardPests - newPests) + scoreboardPests = newPests + updatePests() + } + } + + // gets if there are no pests remaining in the garden + noPestsInScoreboardPattern.matchMatcher(line) { + if (scoreboardPests != 0) { + resetAllPests() + } + } + + // gets the amount of pests in the current plot + pestsInPlotScoreboardPattern.matchMatcher(line) { + val plotName = group("plot") + val pestsInPlot = group("pests").toInt() + val plot = GardenPlotAPI.getPlotByName(plotName) + if (pestsInPlot != plot?.pests || plot.isPestCountInaccurate) { + plot?.pests = pestsInPlot + plot?.isPestCountInaccurate = false + updatePests() + } + } + + // gets if there are no pests remaining in the current plot + noPestsInPlotScoreboardPattern.matchMatcher(line) { + val plotName = group("plot") + val plot = GardenPlotAPI.getPlotByName(plotName) + if (plot?.pests != 0 || plot.isPestCountInaccurate) { + GardenPlotAPI.getPlotByName(plotName)?.pests = 0 + GardenPlotAPI.getPlotByName(plotName)?.isPestCountInaccurate = false + updatePests() + } + } + } + } + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + if (!GardenAPI.inGarden()) return + if (event.message == "§cThere are not any Pests on your Garden right now! Keep farming!") { + resetAllPests() + } + } + + private fun getPlotsWithAccuratePests() = GardenPlotAPI.plots.filter { it.pests > 0 && !it.isPestCountInaccurate } + + private fun getPlotsWithInaccuratePests() = GardenPlotAPI.plots.filter { it.pests == 0 && it.isPestCountInaccurate } + + fun getInfestedPlots() = GardenPlotAPI.plots.filter { it.pests > 0 || it.isPestCountInaccurate } + + fun getPlotsWithoutPests() = GardenPlotAPI.plots.filter { it.pests == 0 || !it.isPestCountInaccurate } + + fun getNearestInfestedPlot() = getInfestedPlots().minByOrNull { it.middle.distanceSqToPlayer() } + + private fun removePests(removedPests: Int) { + if (removedPests < 1) return + repeat(removedPests) { + removeNearestPest() + } + } + + private fun removeNearestPest() { + val plot = getNearestInfestedPlot() ?: run { + ChatUtils.error("Can not remove nearest pest: No infested plots detected.") + return + } + if (!plot.isPestCountInaccurate) plot.pests-- + updatePests() + } + + private fun resetAllPests() { + scoreboardPests = 0 + GardenPlotAPI.plots.forEach { + it.pests = 0 + it.isPestCountInaccurate = false + } + updatePests() + } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestFinder.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestFinder.kt index ebf293098..2833cc4ed 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestFinder.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestFinder.kt @@ -1,16 +1,13 @@ package at.hannibal2.skyhanni.features.garden.pests import at.hannibal2.skyhanni.events.GuiRenderEvent -import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent import at.hannibal2.skyhanni.events.IslandChangeEvent import at.hannibal2.skyhanni.events.ItemInHandChangeEvent -import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.events.LorenzKeyPressEvent import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent -import at.hannibal2.skyhanni.events.ScoreboardChangeEvent -import at.hannibal2.skyhanni.events.garden.pests.PestSpawnEvent +import at.hannibal2.skyhanni.events.garden.pests.PestUpdateEvent import at.hannibal2.skyhanni.features.garden.GardenAPI -import at.hannibal2.skyhanni.features.garden.GardenPlotAPI +import at.hannibal2.skyhanni.features.garden.GardenPlotAPI.isPestCountInaccurate import at.hannibal2.skyhanni.features.garden.GardenPlotAPI.isPlayerInside import at.hannibal2.skyhanni.features.garden.GardenPlotAPI.name import at.hannibal2.skyhanni.features.garden.GardenPlotAPI.pests @@ -18,19 +15,14 @@ import at.hannibal2.skyhanni.features.garden.GardenPlotAPI.renderPlot import at.hannibal2.skyhanni.features.garden.GardenPlotAPI.sendTeleportTo import at.hannibal2.skyhanni.test.GriffinUtils.drawWaypointFilled import at.hannibal2.skyhanni.utils.ChatUtils -import at.hannibal2.skyhanni.utils.ItemUtils.getLore -import at.hannibal2.skyhanni.utils.LocationUtils.distanceSqToPlayer import at.hannibal2.skyhanni.utils.LorenzColor import at.hannibal2.skyhanni.utils.NEUItems -import at.hannibal2.skyhanni.utils.NumberUtil.formatNumber import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText import at.hannibal2.skyhanni.utils.RenderUtils.exactPlayerEyeLocation import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.StringUtils -import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher import at.hannibal2.skyhanni.utils.renderables.Renderable -import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import net.minecraft.client.Minecraft import net.minecraftforge.fml.common.eventhandler.EventPriority import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @@ -40,46 +32,11 @@ class PestFinder { private val config get() = PestAPI.config.pestFinder - private val patternGroup = RepoPattern.group("garden.pests.finder") - private val pestsInScoreboardPattern by patternGroup.pattern( - "scoreboard", - " §7⏣ §[ac]The Garden §4§lൠ§7 x(?<pests>.*)" - ) - private val pestInventoryPattern by patternGroup.pattern( - "inventory", - "§4§lൠ §cThis plot has §6(?<amount>\\d) Pests?§c!" - ) - private var display = emptyList<Renderable>() private var lastTimeVacuumHold = SimpleTimeMark.farPast() @SubscribeEvent - fun onPestSpawn(event: PestSpawnEvent) { - if (!isEnabled()) return - PestSpawnTimer.lastSpawnTime = SimpleTimeMark.now() - val plot = GardenPlotAPI.getPlotByName(event.plotName) - if (plot == null) { - ChatUtils.userError("Open Desk to load plot names and pest locations!") - return - } - plot.pests += event.amountPests - update() - } - - @SubscribeEvent - fun onInventoryOpen(event: InventoryFullyOpenedEvent) { - if (!isEnabled()) return - if (event.inventoryName != "Configure Plots") return - - for (plot in GardenPlotAPI.plots) { - plot.pests = 0 - val item = event.inventoryItems[plot.inventorySlot] ?: continue - for (line in item.getLore()) { - pestInventoryPattern.matchMatcher(line) { - plot.pests = group("amount").formatNumber().toInt() - } - } - } + fun onPestUpdate(event: PestUpdateEvent) { update() } @@ -90,23 +47,17 @@ class PestFinder { } private fun drawDisplay() = buildList { - val totalAmount = getPlotsWithPests().sumOf { it.pests } - if (totalAmount != PestAPI.scoreboardPests) { - add(Renderable.string("§cIncorrect pest amount!")) - add(Renderable.string("§eOpen Configure Plots Menu!")) - return@buildList - } + add(Renderable.string("§6Total pests in garden: §e${PestAPI.scoreboardPests}§6/§e8")) - add(Renderable.string("§eTotal pests in garden: §c${totalAmount}§7/§c8")) - - for (plot in getPlotsWithPests()) { + for (plot in PestAPI.getInfestedPlots()) { val pests = plot.pests val plotName = plot.name - val pestsName = StringUtils.pluralize(pests, "pest", withNumber = true) + val isInaccurate = plot.isPestCountInaccurate + val pestsName = StringUtils.pluralize(pests, "pest") val renderable = Renderable.clickAndHover( - "§c$pestsName §7in §b$plotName", + "§e" + if (isInaccurate) "1+?" else {pests} + " §c$pestsName §7in §b$plotName", listOf( - "§7Pests Found: §e$pests", + "§7Pests Found: §e" + if (isInaccurate) "Unknown" else pests, "§7In plot §b$plotName", "", "§eClick here to warp!" @@ -117,76 +68,25 @@ class PestFinder { ) add(renderable) } - } - - @SubscribeEvent - fun onIslandChange(event: IslandChangeEvent) { - update() - } - @SubscribeEvent - fun onChat(event: LorenzChatEvent) { - if (!isEnabled()) return - if (event.message == "§cThere are no pests in your Garden right now! Keep farming!") { - GardenPlotAPI.plots.forEach { - it.pests = 0 - } - update() + if (PestAPI.getInfestedPlots().isEmpty() && PestAPI.scoreboardPests != 0) { + add(Renderable.string("§e${PestAPI.scoreboardPests} §6Bugged pests!")) + add(Renderable.clickAndHover( + "§cTry opening your plots menu.", + listOf( + "Runs /desk." + ), + onClick = { + ChatUtils.sendCommandToServer("desk") + } + )) } } @SubscribeEvent - fun onScoreboardChange(event: ScoreboardChangeEvent) { - if (!GardenAPI.inGarden()) return - - var newPests = 0 - for (line in event.newList) { - pestsInScoreboardPattern.matchMatcher(line) { - newPests = group("pests").formatNumber().toInt() - } - } - - if (newPests != PestAPI.scoreboardPests) { - removePests(PestAPI.scoreboardPests - newPests) - PestAPI.scoreboardPests = newPests - update() - } - - resetAllPests(newPests) - } - - // Auto fixing plots marked as pests when killing all pests without SkyHanni earlier. - private fun resetAllPests(newPests: Int) { - if (newPests != 0) return - - var fixed = false - for (plot in GardenPlotAPI.plots) { - if (plot.pests > 0) { - fixed = true - plot.pests = 0 - } - } - if (fixed) { - ChatUtils.debug("Auto fixed all plots with pests.") - } - } - - private fun removePests(removedPests: Int) { - if (!isEnabled()) return - if (removedPests < 1) return - repeat(removedPests) { - removeNearestPest() - } - } - - private fun getNearestInfestedPest() = getPlotsWithPests().minByOrNull { it.middle.distanceSqToPlayer() } - - private fun removeNearestPest() { - val plot = getNearestInfestedPest() ?: run { - ChatUtils.error("Can not remove nearest pest: No infested plots detected.") - return - } - plot.pests-- + fun onIslandChange(event: IslandChangeEvent) { + display = listOf() + update() } @SubscribeEvent @@ -200,8 +100,6 @@ class PestFinder { } } - private fun getPlotsWithPests() = GardenPlotAPI.plots.filter { it.pests > 0 } - // priority to low so that this happens after other renderPlot calls. @SubscribeEvent(priority = EventPriority.LOW) fun onRenderWorld(event: LorenzRenderWorldEvent) { @@ -210,19 +108,21 @@ class PestFinder { if (config.onlyWithVacuum && !PestAPI.hasVacuumInHand() && (lastTimeVacuumHold.passedSince() > config.showBorderForSeconds.seconds)) return val playerLocation = event.exactPlayerEyeLocation() - for (plot in getPlotsWithPests()) { + for (plot in PestAPI.getInfestedPlots()) { if (plot.isPlayerInside()) { event.renderPlot(plot, LorenzColor.RED.toColor(), LorenzColor.DARK_RED.toColor()) continue } event.renderPlot(plot, LorenzColor.GOLD.toColor(), LorenzColor.RED.toColor()) - val pestsName = StringUtils.pluralize(plot.pests, "pest", withNumber = true) + val pests = plot.pests + val pestsName = StringUtils.pluralize(pests, "pest") val plotName = plot.name val middle = plot.middle + val isInaccurate = plot.isPestCountInaccurate val location = playerLocation.copy(x = middle.x, z = middle.z) event.drawWaypointFilled(location, LorenzColor.RED.toColor()) - event.drawDynamicText(location, "§c$pestsName §7in §b$plotName", 1.5) + event.drawDynamicText(location, "§e" + if (isInaccurate) "?" else {pests} + " §c$pestsName §7in §b$plotName", 1.5) } } @@ -238,7 +138,7 @@ class PestFinder { if (lastKeyPress.passedSince() < 2.seconds) return lastKeyPress = SimpleTimeMark.now() - val plot = getNearestInfestedPest() ?: run { + val plot = PestAPI.getNearestInfestedPlot() ?: run { ChatUtils.userError("No infested plots detected to warp to!") return } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestSpawn.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestSpawn.kt index 8a4fd511b..39dc22e5c 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestSpawn.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestSpawn.kt @@ -11,6 +11,7 @@ import at.hannibal2.skyhanni.utils.ConfigUtils import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.StringUtils import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher +import at.hannibal2.skyhanni.utils.StringUtils.removeColor import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import kotlin.time.Duration.Companion.seconds @@ -20,29 +21,84 @@ class PestSpawn { private val config get() = PestAPI.config.pestSpawn private val patternGroup = RepoPattern.group("garden.pests.spawn") + /** + * REGEX-TEST: §6§lGROSS! §7A §6Pest §7has appeared in §aPlot §7- §b4§7! + */ private val onePestPattern by patternGroup.pattern( "one", "§6§l.*! §7A §6Pest §7has appeared in §aPlot §7- §b(?<plot>.*)§7!" ) - private val multiplePestSpawn by patternGroup.pattern( + /** + * REGEX-TEST: §6§lGROSS! §7A §6Pest §7has appeared in §aThe Barn§7! + */ + private val onePestBarnPattern by patternGroup.pattern( + "onebarn", + "§6§l.*! §7A §6Pest §7has appeared in §a(?<plot>The Barn)§7!" + ) + /** + * REGEX-TEST: §6§lEWW! §62 Pests §7have spawned in §aPlot §7- §b2§7! + */ + private val multiplePestsSpawn by patternGroup.pattern( "multiple", "§6§l.*! §6(?<amount>\\d) Pests §7have spawned in §aPlot §7- §b(?<plot>.*)§7!" ) + /** + * REGEX-TEST: §6§lEWW! §62 Pests §7have spawned in §aThe Barn§7! + */ + private val multiplePestsBarnSpawn by patternGroup.pattern( + "multiplebarn", + "§6§l.*! §6(?<amount>\\d) Pests §7have spawned in §a(?<plot>The Barn)§7!" + ) + /** + * REGEX-TEST: §6§lGROSS! §7While you were offline, §6Pests §7spawned in §aPlots §r§b12§r§7, §r§b9§r§7, §r§b5§r§7, §r§b11§r§7 and §r§b3§r§r§7! + */ + private val offlinePestsSpawn by patternGroup.pattern( + "offline", + "§6§l.*! §7While you were offline, §6Pests §7spawned in §aPlots (?<plots>.*)!" + ) + private var plotNames = mutableListOf<String>() @SubscribeEvent fun onChat(event: LorenzChatEvent) { if (!GardenAPI.inGarden()) return - + val message = event.message var blocked = false - onePestPattern.matchMatcher(event.message) { - pestSpawn(1, group("plot")) + plotNames.clear() + + onePestPattern.matchMatcher(message) { + val plotName = group("plot") + plotNames.add(plotName) + pestSpawn(1, plotNames, false) + blocked = true + } + onePestBarnPattern.matchMatcher(message) { + val plotName = group("plot") + plotNames.add(plotName) + pestSpawn(1, plotNames, false) + blocked = true + } + multiplePestsSpawn.matchMatcher(message) { + val plotName = group("plot") + plotNames.add(plotName) + val amount = group("amount").toInt() + pestSpawn(amount, plotNames, false) blocked = true } - multiplePestSpawn.matchMatcher(event.message) { - pestSpawn(group("amount").toInt(), group("plot")) + multiplePestsBarnSpawn.matchMatcher(message) { + val plotName = group("plot") + plotNames.add(plotName) + val amount = group("amount").toInt() + pestSpawn(amount, plotNames, false) blocked = true } + offlinePestsSpawn.matchMatcher(message) { + val plots = group("plots") + plotNames = plots.removeColor().split(", "," and ").toMutableList() + pestSpawn(0, plotNames, true) + // blocked = true + } + if (event.message == " §r§e§lCLICK HERE §eto teleport to the plot!") { if (PestSpawnTimer.lastSpawnTime.passedSince() < 1.seconds) { blocked = true @@ -54,8 +110,11 @@ class PestSpawn { } } - private fun pestSpawn(amount: Int, plotName: String) { - PestSpawnEvent(amount, plotName).postAndCatch() + private fun pestSpawn(amount: Int, plotNames: List<String>, unknownAmount: Boolean) { + PestSpawnEvent(amount, plotNames, unknownAmount).postAndCatch() + + if (unknownAmount) return // todo make this work with offline pest spawn messages + val plotName = plotNames.firstOrNull() val pestName = StringUtils.pluralize(amount, "Pest") val message = "§e$amount §a$pestName Spawned in §b$plotName§a!" |