aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/garden/pests/PestSpawnEvent.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/garden/pests/PestUpdateEvent.kt5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/GardenPlotAPI.kt33
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestAPI.kt237
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestFinder.kt158
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestSpawn.kt75
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!"