summaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni/features
diff options
context:
space:
mode:
authorThunderblade73 <85900443+Thunderblade73@users.noreply.github.com>2024-09-13 20:23:40 +0200
committerGitHub <noreply@github.com>2024-09-13 20:23:40 +0200
commit691d2551cf722b76c1894c814d1f6c2e98fe17d6 (patch)
treec02fd9edb6c2f1f4cb8791cf7113c8d5a8594a2f /src/main/java/at/hannibal2/skyhanni/features
parent20081af74fd53f35746ab0d5c974bb5db92bec3b (diff)
downloadskyhanni-691d2551cf722b76c1894c814d1f6c2e98fe17d6.tar.gz
skyhanni-691d2551cf722b76c1894c814d1f6c2e98fe17d6.tar.bz2
skyhanni-691d2551cf722b76c1894c814d1f6c2e98fe17d6.zip
Feature: Carnival QoL (#2498)
Co-authored-by: CalMWolfs <94038482+CalMWolfs@users.noreply.github.com> Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/features')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalGoal.kt236
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalQuickStart.kt60
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalReminder.kt99
3 files changed, 395 insertions, 0 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalGoal.kt b/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalGoal.kt
new file mode 100644
index 000000000..c36212a22
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalGoal.kt
@@ -0,0 +1,236 @@
+package at.hannibal2.skyhanni.features.event.carnival
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.data.Perk
+import at.hannibal2.skyhanni.data.ProfileStorageData
+import at.hannibal2.skyhanni.events.GuiRenderEvent
+import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent
+import at.hannibal2.skyhanni.events.LorenzChatEvent
+import at.hannibal2.skyhanni.events.ProfileJoinEvent
+import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
+import at.hannibal2.skyhanni.utils.ItemUtils.getLore
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.RegexUtils.matches
+import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables
+import at.hannibal2.skyhanni.utils.SkyBlockTime
+import at.hannibal2.skyhanni.utils.renderables.Renderable
+import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
+import net.minecraft.init.Blocks
+import net.minecraft.init.Items
+import net.minecraft.item.Item
+import net.minecraft.item.ItemStack
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import org.intellij.lang.annotations.Language
+
+private val repoGroup = RepoPattern.group("carnvial.goals")
+
+enum class CarnivalGoal(
+ private val type: GoalType,
+ @Language("RegEXP") loreLine: String,
+ @Language("RegEXP") chatLine: String,
+ val display: String,
+) {
+ FRUIT_DIGGING_PLAY(
+ GoalType.FRUIT_DIGGING,
+ "§7Play §a3 games §7of §6Fruit Digging§7.",
+ "(§8 - §r)?§7Play §r§a3 games §r§7of §r§6Fruit Digging§r§7.",
+ "Play §a3 games",
+ ),
+ FRUIT_DIGGING_SCORE(
+ GoalType.FRUIT_DIGGING,
+ "§7Reach §a3,000 score §7in a single game",
+ "(§8 - §r)?§7Reach §r§a3,000 score §r§7in a single game of §r§6Fruit Digging§r§7.",
+ "Reach §a3,000 score",
+ ),
+ DIG_APPLE(
+ GoalType.FRUIT_DIGGING,
+ "§7Dig up §a3 Apples §7in a single game of",
+ "(§8 - §r)?§7Dig up §r§a3 Apples §r§7in a single game of §r§6Fruit Digging§r§7.",
+ "Dig up §a3 Apples",
+ ),
+ UNIQUE_FRUIT(
+ GoalType.FRUIT_DIGGING,
+ "§7Dig up §a5 unique Fruits §7in a single",
+ "(§8 - §r)?§7Dig up §r§a5 unique Fruits §r§7in a single game of §r§6Fruit Digging§r§7.",
+ "Dig up §a5 unique Fruits",
+ ),
+ DRAGONFRUIT(
+ GoalType.FRUIT_DIGGING,
+ "§7Dig up a §dDragonfruit§7.",
+ "(§8 - §r)?§7Dig up a §r§dDragonfruit§r§7.",
+ "Dig up a §dDragonfruit",
+ ),
+ CATCH_A_FISH_PLAY(
+ GoalType.CATCH_A_FISH,
+ "§7Play §a3 games §7of §3Catch a Fish§7.",
+ "(§8 - §r)?§7Play §r§a3 games §r§7of §r§3Catch a Fish§r§7.",
+ "Play §a3 games",
+ ),
+ CATCH_A_FISH_SCORE(
+ GoalType.CATCH_A_FISH,
+ "§7Reach §a3,000 score §7in a single game",
+ "(§8 - §r)?§7Catch §r§a30 Fish §r§7in a single game of §r§3Catch a Fish§r§7.",
+ "Reach §a3,000 score",
+ ),
+ CATCH_FISH(
+ GoalType.CATCH_A_FISH,
+ "§7Catch §a30 Fish §7in a single game of",
+ "(§8 - §r)?§7Reach §r§a3,000 score §r§7in a single game of §r§3Catch a Fish§r§7.",
+ "Catch §a30 Fish",
+ ),
+ CATCH_YELLOW_FISH(
+ GoalType.CATCH_A_FISH,
+ "§7Catch §a5 Yellow Fish §7in a single game",
+ "(§8 - §r)?§7Catch §r§a5 Yellow Fish §r§7in a single game of §r§3Catch a Fish§r§7.",
+ "Catch §a5 Yellow Fish",
+ ),
+ CATCH_STREAK(
+ GoalType.CATCH_A_FISH,
+ "§7Reach a §a5 Catch Streak §7in a single",
+ "(§8 - §r)?§7Reach a §r§a5 Catch Streak §r§7in a single game of §r§3Catch a Fish§r§7.",
+ "Reach a §a5 Catch Streak",
+ ),
+ ZOMBIE_SHOOTOUT_PLAY(
+ GoalType.ZOMBIE_SHOOTOUT,
+ "§7Play §a3 games §7of §cZombie Shootout§7.",
+ "(§8 - §r)?§7Play §r§a3 games §r§7of §r§cZombie Shootout§r§7.",
+ "Play §a3 games",
+ ),
+ ZOMBIE_SHOOTOUT_SCORE(
+ GoalType.ZOMBIE_SHOOTOUT,
+ "§7Reach §a3,000 score §7in a single game",
+ "(§8 - §r)?§7Reach §r§a3,000 score §r§7in a single game of §r§cZombie Shootout§r§7.",
+ "Reach §a3,000 score",
+ ),
+ SHOOT_ZOMBIE(
+ GoalType.ZOMBIE_SHOOTOUT,
+ "§7Shoot §a60 Zombies §7in a single game of",
+ "(§8 - §r)?§7Shoot §r§a60 Zombies §r§7in a single game of §r§cZombie Shootout§r§7.",
+ "Shoot §a60 Zombies",
+ ),
+ SHOOT_DIAMOND_ZOMBIE(
+ GoalType.ZOMBIE_SHOOTOUT,
+ "§7Shoot §a5 Diamond Zombies §7in a single",
+ "(§8 - §r)?§7Shoot §r§a5 Diamond Zombies §r§7in a single game of §r§cZombie Shootout§r§7.",
+ "Shoot §a5 Diamond Zombies",
+ ),
+ SHOOT_LAMPS(
+ GoalType.ZOMBIE_SHOOTOUT,
+ "§7Shoot §a5 Redstone Lamps §7in a single",
+ "(§8 - §r)?§7Shoot §r§a5 Redstone Lamps §r§7in a single game of §r§cZombie Shootout§r§7.",
+ "Shoot §a5 Redstone Lamps",
+ ),
+ ;
+
+ private val patternKeyName = name.lowercase().replace("_", ".")
+
+ private val lorePattern by repoGroup.pattern("lore.$patternKeyName", loreLine)
+ private val chatPattern by repoGroup.pattern("chat.$patternKeyName", chatLine)
+
+ private var isReached: Boolean
+ get() {
+ val year = SkyBlockTime.now().year
+ if (year != storage?.carnivalYear) {
+ storage?.goals?.clear()
+ storage?.carnivalYear = year
+ }
+ return storage?.goals?.get(this) ?: false
+ }
+ set(value) {
+ val year = SkyBlockTime.now().year
+ if (year != storage?.carnivalYear) {
+ storage?.goals?.clear()
+ storage?.carnivalYear = year
+ }
+ storage?.goals?.set(this, value)
+ dirty = true
+ }
+
+ @SkyHanniModule
+ companion object {
+
+ init {
+ entries.forEach {
+ it.chatPattern
+ it.lorePattern
+ }
+ }
+
+ private val config get() = SkyHanniMod.feature.event.carnival
+ private val storage get() = ProfileStorageData.profileSpecific?.carnival
+
+ private val inventoryPattern by repoGroup.pattern("inventory", "Carnival Goals")
+
+ private val completePattern by repoGroup.pattern("complete", "§a§lCOMPLETE")
+
+ private var dirty = true
+
+ private fun getEntry(item: Item, lore: List<String>): CarnivalGoal? =
+ entries.filter { it.type.item == item }.firstOrNull { it.lorePattern.matches(lore.firstOrNull()) }
+
+ @SubscribeEvent
+ fun onProfileJoin(event: ProfileJoinEvent) {
+ dirty = true
+ }
+
+ @SubscribeEvent
+ fun onInventoryFullyOpened(event: InventoryFullyOpenedEvent) {
+ if (!isEnabled()) return
+ if (!inventoryPattern.matches(event.inventoryName)) return
+ for (stack in event.inventoryItems.values) {
+ val lore = stack.getLore()
+ val goal = getEntry(stack.item, lore) ?: continue
+ val lastLine = lore.last()
+ goal.isReached = completePattern.matches(lastLine)
+ }
+ }
+
+ @SubscribeEvent
+ fun onLorenzChat(event: LorenzChatEvent) {
+ if (!isEnabled()) return
+ entries.firstOrNull { it.chatPattern.matches(event.message) }?.isReached = true
+ }
+
+ private var display = emptyList<Renderable>()
+
+ @SubscribeEvent
+ fun onGuiRenderGuiOverlayRender(event: GuiRenderEvent.GuiOverlayRenderEvent) {
+ if (!isEnabled()) return
+ if (dirty) {
+ display = buildList {
+ GoalType.entries.map { it.fullDisplay }.forEach { list -> addAll(list) }
+ }
+ dirty = false
+ }
+ config.goalsPosition.renderRenderables(display, posLabel = "Carnival Goals")
+ }
+
+ fun isEnabled() =
+ LorenzUtils.inSkyBlock && config.showGoals && Perk.CHIVALROUS_CARNIVAL.isActive && LorenzUtils.skyBlockArea == "Carnival"
+
+ private enum class GoalType(val item: Item, display: String) {
+ FRUIT_DIGGING(Item.getItemFromBlock(Blocks.sand), "§6Fruit Digging"),
+ CATCH_A_FISH(Items.fish, "§3Catch a Fish"),
+ ZOMBIE_SHOOTOUT(Items.arrow, "§cZombie Shootout");
+
+ val singleDisplay by lazy {
+ Renderable.horizontalContainer(
+ listOf(
+ Renderable.itemStack(ItemStack(item)),
+ Renderable.string(display),
+ ),
+ )
+ }
+
+ val fullDisplay: List<Renderable>
+ get() {
+ val goals = getGoals.filterNot { it.isReached }
+ if (goals.isEmpty()) return emptyList()
+ return listOf(singleDisplay) + goals.map { Renderable.string(" " + it.display) }
+ }
+
+ val getGoals get() = CarnivalGoal.entries.filter { it.type == this }
+ }
+ }
+
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalQuickStart.kt b/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalQuickStart.kt
new file mode 100644
index 000000000..ee2a9028a
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalQuickStart.kt
@@ -0,0 +1,60 @@
+package at.hannibal2.skyhanni.features.event.carnival
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.data.Perk
+import at.hannibal2.skyhanni.events.EntityClickEvent
+import at.hannibal2.skyhanni.events.LorenzChatEvent
+import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
+import at.hannibal2.skyhanni.utils.HypixelCommands
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.MobUtils.mob
+import at.hannibal2.skyhanni.utils.RegexUtils.matches
+import at.hannibal2.skyhanni.utils.SimpleTimeMark
+import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
+import net.minecraft.entity.EntityLivingBase
+import net.minecraft.util.ChatComponentText
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.time.Duration.Companion.seconds
+
+@SkyHanniModule
+object CarnivalQuickStart {
+
+ private val config get() = SkyHanniMod.feature.event.carnival.doubleClickToStart
+
+ /** REGEX-TEST: §eSelect an option: §r\n§e ➜ §a[Sure thing, partner!] §r\n§e ➜ §b[Could ya tell me the rules again?] §r\n§e ➜ §c[I'd like to do somthin' else fer now.]
+ * */
+ private val chatPattern by RepoPattern.pattern("carnival.select.option.chat", "§eSelect an option:.*")
+
+ private val repoGroup = RepoPattern.group("carnival.npcs")
+
+ private val pirate by repoGroup.pattern("pirate", "Carnival Pirateman")
+ private val fisher by repoGroup.pattern("fisher", "Carnival Fisherman")
+ private val cowboy by repoGroup.pattern("cowboy", "Carnival Cowboy")
+
+ private var lastChat = SimpleTimeMark.farPast()
+
+ @SubscribeEvent
+ fun onEntityClick(event: EntityClickEvent) {
+ if (!isEnabled()) return
+ if (lastChat.passedSince() > 5.0.seconds) return
+ val mob = (event.clickedEntity as? EntityLivingBase)?.mob ?: return
+ val type = when {
+ cowboy.matches(mob.name) -> "carnival_cowboy"
+ fisher.matches(mob.name) -> "carnival_fisherman"
+ pirate.matches(mob.name) -> "carnival_pirateman"
+ else -> return
+ }
+ HypixelCommands.npcOption(type, "r_2_1")
+ event.cancel()
+ }
+
+ @SubscribeEvent
+ fun onLorenzChat(event: LorenzChatEvent) {
+ if (!isEnabled()) return
+ // IDK what is wrong here, but it does not work with event.message
+ if (!chatPattern.matches((event.chatComponent as? ChatComponentText)?.chatComponentText_TextValue)) return
+ lastChat = SimpleTimeMark.now()
+ }
+
+ fun isEnabled() = LorenzUtils.inSkyBlock && config && Perk.CHIVALROUS_CARNIVAL.isActive && LorenzUtils.skyBlockArea == "Carnival"
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalReminder.kt b/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalReminder.kt
new file mode 100644
index 000000000..eff751661
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalReminder.kt
@@ -0,0 +1,99 @@
+package at.hannibal2.skyhanni.features.event.carnival
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.data.Perk
+import at.hannibal2.skyhanni.data.ProfileStorageData
+import at.hannibal2.skyhanni.events.LorenzChatEvent
+import at.hannibal2.skyhanni.events.ProfileJoinEvent
+import at.hannibal2.skyhanni.events.SecondPassedEvent
+import at.hannibal2.skyhanni.features.fame.ReminderUtils
+import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
+import at.hannibal2.skyhanni.utils.ChatUtils
+import at.hannibal2.skyhanni.utils.HypixelCommands
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.RegexUtils.matches
+import at.hannibal2.skyhanni.utils.SimpleTimeMark
+import at.hannibal2.skyhanni.utils.SimpleTimeMark.Companion.fromNow
+import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import java.time.ZoneOffset
+import java.time.ZonedDateTime
+import kotlin.time.Duration.Companion.minutes
+import kotlin.time.Duration.Companion.seconds
+
+@SkyHanniModule
+object CarnivalReminder {
+
+ private val config get() = SkyHanniMod.feature.event.carnival
+ private val storage get() = ProfileStorageData.profileSpecific?.carnival
+
+ private var nextCheckTime = SimpleTimeMark.farFuture()
+
+ private var claimedToday = false
+
+ private var lastClaimedDay
+ get() = storage?.lastClaimedDay
+ set(value) {
+ storage?.lastClaimedDay = value
+ }
+
+ private val repoGroup = RepoPattern.group("carnival.tickets")
+
+ /** REGEX-TEST: §aYou claimed §r§aCarnival Ticket §r§8x25§r§a!
+ */
+ private val ticketClaimedPattern by repoGroup.pattern("claimed", "§aYou claimed §r§aCarnival Ticket §r§8x25§r§a!")
+
+ /** REGEX-TEST: §e[NPC] §aCarnival Leader§f: §rYou've already claimed your §aCarnival Tickets §ffor §btoday§f, but I'm happy to answer any questions you might have.
+ */
+ private val alreadyClaimedPattern by repoGroup.pattern(
+ "already",
+ "§e\\[NPC\\] §aCarnival Leader§f: §rYou've already claimed your §aCarnival Tickets §ffor §btoday§f, but I'm happy to answer any questions you might have.",
+ )
+
+ @SubscribeEvent
+ fun onSecondPassedEvent(event: SecondPassedEvent) {
+ if (!isEnabled() || nextCheckTime.isInFuture()) return
+ check()
+ }
+
+ @SubscribeEvent
+ fun onProfileJoin(event: ProfileJoinEvent) {
+ claimedToday = false
+ if (!isEnabled()) return
+ nextCheckTime = 30.0.seconds.fromNow()
+ checkDate()
+ check()
+ }
+
+ @SubscribeEvent
+ fun onLorenzChat(event: LorenzChatEvent) {
+ if (!isEnabled() && !claimedToday) return
+ if (!ticketClaimedPattern.matches(event.message) && !alreadyClaimedPattern.matches(event.message)) return
+ claimedToday = true
+ lastClaimedDay = ZonedDateTime.now(ZoneOffset.UTC).toLocalDate()
+ }
+
+ private fun checkDate() {
+ val currentDay = ZonedDateTime.now(ZoneOffset.UTC).toLocalDate()
+ val lastClaimedDay = lastClaimedDay
+
+ claimedToday = !(lastClaimedDay == null || currentDay.isAfter(lastClaimedDay))
+ }
+
+ fun check() {
+ if (claimedToday) {
+ checkDate()
+ } else if (!ReminderUtils.isBusy()) {
+ ChatUtils.clickToActionOrDisable(
+ "Carnival Tickets are ready to be claimed!",
+ config::reminderDailyTickets,
+ "warp to The Carnival",
+ ) {
+ HypixelCommands.warp("carnival")
+ }
+ nextCheckTime = 5.0.minutes.fromNow()
+ }
+ }
+
+ fun isEnabled() = LorenzUtils.inSkyBlock && config.reminderDailyTickets && Perk.CHIVALROUS_CARNIVAL.isActive
+}