diff options
| author | Thunderblade73 <85900443+Thunderblade73@users.noreply.github.com> | 2024-09-13 20:23:40 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-13 20:23:40 +0200 |
| commit | 691d2551cf722b76c1894c814d1f6c2e98fe17d6 (patch) | |
| tree | c02fd9edb6c2f1f4cb8791cf7113c8d5a8594a2f /src/main/java/at/hannibal2/skyhanni/features/event | |
| parent | 20081af74fd53f35746ab0d5c974bb5db92bec3b (diff) | |
| download | skyhanni-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/event')
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 +} |
