diff --git a/.github/scripts/process_detekt_sarif.sh b/.github/scripts/process_detekt_sarif.sh index 7fb4f7e4e11f..4d4f2af93298 100644 --- a/.github/scripts/process_detekt_sarif.sh +++ b/.github/scripts/process_detekt_sarif.sh @@ -29,7 +29,7 @@ read -r -d '' jq_command <<'EOF' ",title=" + (.ruleId) + ",col=" + (.l.region.startColumn|tostring) + ",endColumn=" + (.l.region.endColumn|tostring) + - "::" + (.message.text) + "::" + (.message) ) EOF diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7ab0e6c7543f..45d4ecaa912f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,28 +36,30 @@ jobs: with: name: "Test Results" path: versions/1.8.9/build/reports/tests/test/ - #detekt: - # name: Run detekt - # runs-on: ubuntu-latest + detekt: + name: Run detekt + runs-on: ubuntu-latest - # steps: - # - name: Checkout code - # uses: actions/checkout@v4 - # - uses: ./.github/actions/setup-normal-workspace - # # detektMain is a LOT slower than detekt, but it does type analysis - # - name: Run detekt main (w/typing analysis) - # run: | - # ./gradlew detektMain --stacktrace - # - name: Annotate detekt failures - # if: ${{ !cancelled() }} - # run: | - # chmod +x .github/scripts/process_detekt_sarif.sh - # ./.github/scripts/process_detekt_sarif.sh versions/1.8.9/build/reports/detekt/main.sarif + steps: + - name: Checkout code + uses: actions/checkout@v4 + - uses: ./.github/actions/setup-normal-workspace + # detektMain is a LOT slower than detekt, but it does type analysis + - name: Run detekt main (w/typing analysis) + run: | + ./gradlew detektMain --stacktrace + - name: Annotate detekt failures + if: ${{ !cancelled() }} + run: | + chmod +x .github/scripts/process_detekt_sarif.sh + ./.github/scripts/process_detekt_sarif.sh versions/1.8.9/build/reports/detekt/main.sarif preprocess: runs-on: ubuntu-latest name: "Build multi version" + env: + SKIP_DETEKT: "true" steps: - name: Checkout code uses: actions/checkout@v4 diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 3702088f8387..3daad12374c5 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -2,11 +2,11 @@ name: "PR Changelog Verification" on: pull_request_target: - types: [ opened, edited ] + types: [ opened, edited, ready_for_review ] jobs: verify-changelog: - if: github.event.pull_request.state == 'open' && '511310721' == github.repository_id + if: github.event.pull_request.state == 'open' && '511310721' == github.repository_id && github.event.pull_request.draft == false runs-on: ubuntu-latest steps: diff --git a/.idea/dictionaries/default_user.xml b/.idea/dictionaries/default_user.xml index 86cfbc3f33b1..32875a5fbed8 100644 --- a/.idea/dictionaries/default_user.xml +++ b/.idea/dictionaries/default_user.xml @@ -86,6 +86,7 @@ firedust firesale firesales + flowstate framebuffer getfromsacks ghast diff --git a/.live-plugins/module/plugin.kts b/.live-plugins/module/plugin.kts index c0a65d3f431b..f7471e9fd98c 100644 --- a/.live-plugins/module/plugin.kts +++ b/.live-plugins/module/plugin.kts @@ -18,6 +18,7 @@ val forgeEvent = "SubscribeEvent" val handleEvent = "HandleEvent" val skyHanniModule = "SkyHanniModule" +val skyhanniPath = "at.hannibal2.skyhanni" val patternGroup = "at.hannibal2.skyhanni.utils.repopatterns.RepoPatternGroup" val pattern = "java.util.regex.Pattern" @@ -36,12 +37,17 @@ fun isRepoPattern(property: KtProperty): Boolean { return false } +fun isFromSkyhanni(declaration: KtNamedDeclaration): Boolean { + return declaration.fqName?.asString()?.startsWith(skyhanniPath) ?: false +} + class ModuleInspectionKotlin : AbstractKotlinInspection() { override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { val visitor = object : KtVisitorVoid() { override fun visitClass(klass: KtClass) { + if (!isFromSkyhanni(klass)) return val hasAnnotation = klass.annotationEntries.any { it.shortName?.asString() == skyHanniModule } if (hasAnnotation) { @@ -54,6 +60,7 @@ class ModuleInspectionKotlin : AbstractKotlinInspection() { } override fun visitObjectDeclaration(declaration: KtObjectDeclaration) { + if (!isFromSkyhanni(declaration)) return val hasAnnotation = declaration.annotationEntries.any { it.shortName?.asString() == skyHanniModule } if (hasAnnotation) return diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fe6410c9d11e..8229a00d5835 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -85,7 +85,12 @@ out [their guide](https://github.com/NotEnoughUpdates/NotEnoughUpdates/blob/mast If you are not very familiar with git, you might want to try this out: https://learngitbranching.js.org/. -_An explanation how to use intellij and branches will follow here soon._ +Proposed changes are better off being in their own branch, you can do this by doing the following from within IntelliJ with the SkyHanni project already open. +- Click the beta dropdown at the top of IntelliJ +- Click new branch +- Give the branch a name relating to the changes you plan to make + +_A more in depth explanation how to use intellij and branches will follow here soon._ Please use a prefix for the name of the PR (E.g. Feature, Improvement, Fix, Backend, ...). diff --git a/build.gradle.kts b/build.gradle.kts index dde5ac410ed2..e412f9d92fde 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,6 +9,7 @@ import net.fabricmc.loom.task.RunGameTask import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import skyhannibuildsystem.ChangelogVerification +import skyhannibuildsystem.DownloadBackupRepo plugins { idea @@ -96,6 +97,12 @@ val headlessLwjgl by configurations.creating { isTransitive = false isVisible = false } + +val includeBackupRepo by tasks.registering(DownloadBackupRepo::class) { + this.outputDirectory.set(layout.buildDirectory.dir("downloadedRepo")) + this.branch = "main" +} + tasks.runClient { this.javaLauncher.set( javaToolchains.launcherFor { @@ -213,6 +220,7 @@ kotlin { // Tasks: tasks.processResources { + from(includeBackupRepo) inputs.property("version", version) filesMatching(listOf("mcmod.info", "fabric.mod.json")) { expand("version" to version) @@ -367,7 +375,7 @@ detekt { tasks.withType().configureEach { onlyIf { - false // TODO: Remove onlyIf when we're ready to enforce + System.getenv("SKIP_DETEKT") != "true" } reports { diff --git a/buildSrc/src/main/kotlin/skyhannibuildsystem/DownloadBackupRepo.kt b/buildSrc/src/main/kotlin/skyhannibuildsystem/DownloadBackupRepo.kt new file mode 100644 index 000000000000..f59bf34a8c10 --- /dev/null +++ b/buildSrc/src/main/kotlin/skyhannibuildsystem/DownloadBackupRepo.kt @@ -0,0 +1,34 @@ +package skyhannibuildsystem + +import org.gradle.api.DefaultTask +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.TaskAction +import java.net.URL + +// Code taken from NotEnoughUpdates +abstract class DownloadBackupRepo : DefaultTask() { + + @get:OutputDirectory + abstract val outputDirectory: DirectoryProperty + + @get:Input + abstract var branch: String + + @get:Internal + val repoFile get() = outputDirectory.get().asFile.resolve("assets/skyhanni/repo.zip") + + @TaskAction + fun downloadRepo() { + val downloadUrl = URL("https://github.com/hannibal002/SkyHanni-Repo/archive/refs/heads/$branch.zip") + val file = repoFile + file.parentFile.mkdirs() + file.outputStream().use { out -> + downloadUrl.openStream().use { inp -> + inp.copyTo(out) + } + } + } +} diff --git a/detekt/baseline.xml b/detekt/baseline.xml index ac35c2f6d1a8..c9151e8aebd9 100644 --- a/detekt/baseline.xml +++ b/detekt/baseline.xml @@ -2,8 +2,6 @@ - AnnotationOnSeparateLine:GraphEditor.kt$GraphEditor$@Suppress("MapGetWithNotNullAssertionOperator") node.neighbours.map { GraphingEdge( translation[node]!!, translation[it.key]!!, ) } - AnnotationOnSeparateLine:GraphEditor.kt$GraphEditor$@Suppress("MapGetWithNotNullAssertionOperator") nodes[indexedTable[otherNode.id]!!] ArrayPrimitive:CropMoneyDisplay.kt$CropMoneyDisplay$Array<Double> ArrayPrimitive:CropMoneyDisplay.kt$CropMoneyDisplay$arrayOf(npcPrice) ArrayPrimitive:CropMoneyDisplay.kt$CropMoneyDisplay$arrayOf(sellOffer) @@ -22,32 +20,28 @@ CyclomaticComplexMethod:GardenVisitorFeatures.kt$GardenVisitorFeatures$private fun readToolTip(visitor: VisitorAPI.Visitor, itemStack: ItemStack?, toolTip: MutableList<String>) CyclomaticComplexMethod:GhostCounter.kt$GhostCounter$private fun drawDisplay() CyclomaticComplexMethod:GraphEditor.kt$GraphEditor$private fun input() - CyclomaticComplexMethod:GraphEditorBugFinder.kt$GraphEditorBugFinder$private fun asyncTest() - CyclomaticComplexMethod:IslandAreas.kt$IslandAreas$private fun buildDisplay() CyclomaticComplexMethod:ItemDisplayOverlayFeatures.kt$ItemDisplayOverlayFeatures$private fun getStackTip(item: ItemStack): String? CyclomaticComplexMethod:ItemNameResolver.kt$ItemNameResolver$internal fun getInternalNameOrNull(itemName: String): NEUInternalName? CyclomaticComplexMethod:MinecraftConsoleFilter.kt$MinecraftConsoleFilter$override fun filter(event: LogEvent?): Filter.Result - CyclomaticComplexMethod:OverviewPage.kt$OverviewPage$private fun getPage(): Pair<List<List<Renderable>>, List<Renderable>> CyclomaticComplexMethod:PacketTest.kt$PacketTest$private fun Packet<*>.print() CyclomaticComplexMethod:ParkourHelper.kt$ParkourHelper$fun render(event: LorenzRenderWorldEvent) CyclomaticComplexMethod:Renderable.kt$Renderable.Companion$internal fun shouldAllowLink(debug: Boolean = false, bypassChecks: Boolean): Boolean CyclomaticComplexMethod:SkillProgress.kt$SkillProgress$private fun drawDisplay() CyclomaticComplexMethod:VampireSlayerFeatures.kt$VampireSlayerFeatures$private fun EntityOtherPlayerMP.process() CyclomaticComplexMethod:VisualWordGui.kt$VisualWordGui$override fun drawScreen(unusedX: Int, unusedY: Int, partialTicks: Float) - DestructuringDeclarationWithTooManyEntries:SackDisplay.kt$SackDisplay$val (internalName, rough, flawed, fine, roughPrice, flawedPrice, finePrice) = gem Filename:AreaChangeEvents.kt$at.hannibal2.skyhanni.events.skyblock.AreaChangeEvents.kt + ImportOrdering:DungeonLividFinder.kt$import at.hannibal2.skyhanni.events.CheckRenderEntityEvent import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent import at.hannibal2.skyhanni.mixins.hooks.RenderLivingEntityHelper import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.BlockUtils.getBlockStateAt import at.hannibal2.skyhanni.utils.ColorUtils.withAlpha import at.hannibal2.skyhanni.utils.EntityUtils import at.hannibal2.skyhanni.utils.LocationUtils.distanceSqToPlayer import at.hannibal2.skyhanni.utils.LorenzColor import at.hannibal2.skyhanni.utils.LorenzColor.Companion.toLorenzColor import at.hannibal2.skyhanni.utils.LorenzVec import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText import at.hannibal2.skyhanni.utils.RenderUtils.drawLineToEye import at.hannibal2.skyhanni.utils.RenderUtils.drawWaypointFilled import at.hannibal2.skyhanni.utils.RenderUtils.exactLocation import net.minecraft.block.BlockStainedGlass import net.minecraft.client.entity.EntityOtherPlayerMP import net.minecraft.client.entity.EntityPlayerSP import net.minecraft.client.Minecraft import net.minecraft.entity.item.EntityArmorStand import net.minecraft.potion.Potion import net.minecraft.util.AxisAlignedBB import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + ImportOrdering:EntityUtils.kt$import at.hannibal2.skyhanni.data.mob.MobFilter.isRealPlayer import at.hannibal2.skyhanni.events.SkyHanniRenderEntityEvent import at.hannibal2.skyhanni.features.dungeon.DungeonAPI import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ItemUtils.getSkullTexture import at.hannibal2.skyhanni.utils.LocationUtils.canBeSeen import at.hannibal2.skyhanni.utils.LocationUtils.distanceTo import at.hannibal2.skyhanni.utils.LocationUtils.distanceToIgnoreY import at.hannibal2.skyhanni.utils.LorenzUtils.baseMaxHealth import at.hannibal2.skyhanni.utils.LorenzUtils.derpy import at.hannibal2.skyhanni.utils.StringUtils.removeColor import at.hannibal2.skyhanni.utils.compat.getArmorOrFullInventory import at.hannibal2.skyhanni.utils.compat.getLoadedPlayers import at.hannibal2.skyhanni.utils.compat.getNameAsString import at.hannibal2.skyhanni.utils.compat.isOnMainThread import at.hannibal2.skyhanni.utils.compat.normalizeAsArray import net.minecraft.block.state.IBlockState import net.minecraft.client.Minecraft import net.minecraft.client.entity.EntityOtherPlayerMP import net.minecraft.client.multiplayer.WorldClient import net.minecraft.entity.Entity import net.minecraft.entity.EntityLivingBase import net.minecraft.entity.item.EntityArmorStand import net.minecraft.entity.monster.EntityEnderman import net.minecraft.entity.player.EntityPlayer import net.minecraft.item.ItemStack import net.minecraft.potion.Potion import net.minecraft.tileentity.TileEntity import net.minecraft.util.AxisAlignedBB import net.minecraftforge.client.event.RenderLivingEvent //#if FORGE import net.minecraftforge.fml.common.eventhandler.Event import net.minecraftforge.fml.common.eventhandler.SubscribeEvent InjectDispatcher:ClipboardUtils.kt$ClipboardUtils$IO InjectDispatcher:GardenNextJacobContest.kt$GardenNextJacobContest$IO InjectDispatcher:HypixelBazaarFetcher.kt$HypixelBazaarFetcher$IO InjectDispatcher:MayorAPI.kt$MayorAPI$IO LongMethod:CopyNearbyEntitiesCommand.kt$CopyNearbyEntitiesCommand$fun command(args: Array<String>) LongMethod:CropMoneyDisplay.kt$CropMoneyDisplay$private fun drawDisplay(): List<List<Any>> - LongMethod:DefaultConfigOptionGui.kt$DefaultConfigOptionGui$override fun drawScreen(mouseX: Int, mouseY: Int, partialTicks: Float) LongMethod:GhostCounter.kt$GhostCounter$private fun drawDisplay() LongMethod:GraphEditor.kt$GraphEditor$private fun input() LongMethod:ItemDisplayOverlayFeatures.kt$ItemDisplayOverlayFeatures$private fun getStackTip(item: ItemStack): String? LongMethod:MinecraftConsoleFilter.kt$MinecraftConsoleFilter$override fun filter(event: LogEvent?): Filter.Result - LongMethod:OverviewPage.kt$OverviewPage$private fun getPage(): Pair<List<List<Renderable>>, List<Renderable>> LongMethod:RenderableTooltips.kt$RenderableTooltips$private fun drawHoveringText() LongMethod:TabListRenderer.kt$TabListRenderer$private fun drawTabList() LongMethod:VisualWordGui.kt$VisualWordGui$override fun drawScreen(unusedX: Int, unusedY: Int, partialTicks: Float) @@ -64,9 +58,7 @@ LoopWithTooManyJumpStatements:SuperpairsClicksAlert.kt$SuperpairsClicksAlert$for MapGetWithNotNullAssertionOperator:NavigationHelper.kt$NavigationHelper$distances[node]!! MatchingDeclarationName:AreaChangeEvents.kt$ScoreboardAreaChangeEvent : SkyHanniEvent - MaxLineLength:GraphEditor.kt$GraphEditor$@Suppress("MapGetWithNotNullAssertionOperator") nodes[indexedTable[otherNode.id]!!] to node.position.distance(otherNode.position) MemberNameEqualsClassName:CaptureFarmingGear.kt$CaptureFarmingGear$fun captureFarmingGear() - MemberNameEqualsClassName:Commands.kt$Commands$// command -> description private val commands = mutableListOf<CommandInfo>() MemberNameEqualsClassName:FameRanks.kt$FameRanks$var fameRanks = emptyMap<String, FameRank>() private set MemberNameEqualsClassName:FirstMinionTier.kt$FirstMinionTier$fun firstMinionTier( otherItems: Map<NEUInternalName, Int>, minions: MutableMap<String, NEUInternalName>, tierOneMinions: MutableList<NEUInternalName>, tierOneMinionsDone: MutableSet<NEUInternalName>, ) MemberNameEqualsClassName:LastServers.kt$LastServers$private val lastServers = mutableMapOf<String, SimpleTimeMark>() @@ -113,7 +105,6 @@ ReturnCount:GardenVisitorFeatures.kt$GardenVisitorFeatures$private fun showGui(): Boolean ReturnCount:GraphEditor.kt$GraphEditor$private fun input() ReturnCount:HideNotClickableItems.kt$HideNotClickableItems$private fun hideSalvage(chestName: String, stack: ItemStack): Boolean - ReturnCount:IslandGraphs.kt$IslandGraphs$private fun handleTick() ReturnCount:ItemDisplayOverlayFeatures.kt$ItemDisplayOverlayFeatures$private fun getStackTip(item: ItemStack): String? ReturnCount:ItemNameResolver.kt$ItemNameResolver$internal fun getInternalNameOrNull(itemName: String): NEUInternalName? ReturnCount:ItemPriceUtils.kt$ItemPriceUtils$fun NEUInternalName.getPriceOrNull( priceSource: ItemPriceSource = ItemPriceSource.BAZAAR_INSTANT_BUY, pastRecipes: List<PrimitiveRecipe> = emptyList(), ): Double? @@ -134,7 +125,6 @@ ReturnCount:ShowFishingItemName.kt$ShowFishingItemName$fun inCorrectArea(): Boolean ReturnCount:SkillAPI.kt$SkillAPI$fun onCommand(it: Array<String>) ReturnCount:SkyHanniConfigSearchResetCommand.kt$SkyHanniConfigSearchResetCommand$private suspend fun setCommand(args: Array<String>): String - ReturnCount:TabComplete.kt$TabComplete$private fun customTabComplete(command: String): List<String>? SpreadOperator:ItemUtils.kt$ItemUtils$(tag, displayName, *lore.toTypedArray()) SpreadOperator:LimboPlaytime.kt$LimboPlaytime$( itemID.getItemStack().item, ITEM_NAME, *createItemLore() ) SpreadOperator:Text.kt$Text$(*component.toTypedArray(), separator = separator) @@ -168,8 +158,6 @@ UnsafeCallOnNullableType:CompactBestiaryChatMessage.kt$CompactBestiaryChatMessage$it.groups[1]!! UnsafeCallOnNullableType:ConfigManager.kt$ConfigManager$file!! UnsafeCallOnNullableType:CorpseTracker.kt$CorpseTracker$applicableKeys.first().key!! - UnsafeCallOnNullableType:CosmeticFollowingLine.kt$CosmeticFollowingLine$latestLocations[b]!! - UnsafeCallOnNullableType:CosmeticFollowingLine.kt$CosmeticFollowingLine$locations[b]!! UnsafeCallOnNullableType:CropMoneyDisplay.kt$CropMoneyDisplay$cropNames[internalName]!! UnsafeCallOnNullableType:DailyMiniBossHelper.kt$DailyMiniBossHelper$getByDisplayName(name)!! UnsafeCallOnNullableType:DamageIndicatorManager.kt$DamageIndicatorManager$data.deathLocation!! @@ -196,8 +184,6 @@ UnsafeCallOnNullableType:FarmingWeightDisplay.kt$FarmingWeightDisplay$weightPerCrop[CropType.SUGAR_CANE]!! UnsafeCallOnNullableType:FeatureToggleProcessor.kt$FeatureToggleProcessor$latestCategory!! UnsafeCallOnNullableType:FeatureTogglesByDefaultAdapter.kt$FeatureTogglesByDefaultAdapter$gson!! - UnsafeCallOnNullableType:FishingProfitTracker.kt$FishingProfitTracker$itemCategories[currentCategory]!! - UnsafeCallOnNullableType:FishingProfitTracker.kt$FishingProfitTracker.Data$itemCategories["Trophy Fish"]!! UnsafeCallOnNullableType:FortuneUpgrades.kt$FortuneUpgrades$nextTalisman.upgradeCost?.first!! UnsafeCallOnNullableType:GardenComposterUpgradesData.kt$GardenComposterUpgradesData$ComposterUpgrade.getByName(name)!! UnsafeCallOnNullableType:GardenCropMilestoneDisplay.kt$GardenCropMilestoneDisplay$cultivatingData[crop]!! @@ -237,7 +223,6 @@ UnsafeCallOnNullableType:SackAPI.kt$SackAPI$match.groups[2]!! UnsafeCallOnNullableType:SackAPI.kt$SackAPI$match.groups[3]!! UnsafeCallOnNullableType:SackAPI.kt$SackAPI$oldData!! - UnsafeCallOnNullableType:SimpleCommand.kt$SimpleCommand$tabRunnable!! UnsafeCallOnNullableType:SkyHanniBucketedItemTracker.kt$SkyHanniBucketedItemTracker$it.get(DisplayMode.SESSION).getItemsProp()[internalName]!! UnsafeCallOnNullableType:SkyHanniBucketedItemTracker.kt$SkyHanniBucketedItemTracker$it.get(DisplayMode.TOTAL).getItemsProp()[internalName]!! UnsafeCallOnNullableType:SkyHanniMod.kt$SkyHanniMod.Companion$Loader.instance().indexedModList[MODID]!! @@ -267,12 +252,10 @@ VarCouldBeVal:CarnivalZombieShootout.kt$CarnivalZombieShootout$private var lastUpdate = Updates(SimpleTimeMark.farPast(), SimpleTimeMark.farPast()) VarCouldBeVal:ChocolateFactoryStrayTracker.kt$ChocolateFactoryStrayTracker$private var claimedStraysSlots = mutableListOf<Int>() VarCouldBeVal:CompactBestiaryChatMessage.kt$CompactBestiaryChatMessage$private var bestiaryDescription = mutableListOf<String>() - VarCouldBeVal:CompactExperimentRewards.kt$CompactExperimentRewards$private var gainedRewards = mutableListOf<String>() VarCouldBeVal:CraftRoomHolographicMob.kt$CraftRoomHolographicMob$private var entityToHolographicEntity = mapOf( EntityZombie::class.java to HolographicEntities.zombie, EntitySlime::class.java to HolographicEntities.slime, EntityCaveSpider::class.java to HolographicEntities.caveSpider, ) VarCouldBeVal:CustomWardrobe.kt$CustomWardrobe$private var guiName = "Custom Wardrobe" VarCouldBeVal:Enchant.kt$Enchant$@Expose private var goodLevel = 0 VarCouldBeVal:Enchant.kt$Enchant$@Expose private var maxLevel = 0 - VarCouldBeVal:Enchant.kt$Enchant.Stacking$@Expose @Suppress("unused") private var statLabel: String? = null VarCouldBeVal:Enchant.kt$Enchant.Stacking$@Expose private var nbtNum: String? = null VarCouldBeVal:Enchant.kt$Enchant.Stacking$@Expose private var stackLevel: TreeSet<Int>? = null VarCouldBeVal:ErrorManager.kt$ErrorManager$private var cache = TimeLimitedSet<Pair<String, Int>>(10.minutes) @@ -281,7 +264,6 @@ VarCouldBeVal:EstimatedItemValueCalculator.kt$EstimatedItemValueCalculator$var nameColor = if (!useless) "§9" else "§7" VarCouldBeVal:ExperimentsProfitTracker.kt$ExperimentsProfitTracker$private var currentBottlesInInventory = mutableMapOf<NEUInternalName, Int>() VarCouldBeVal:ExperimentsProfitTracker.kt$ExperimentsProfitTracker$private var lastBottlesInInventory = mutableMapOf<NEUInternalName, Int>() - VarCouldBeVal:ExperimentsProfitTracker.kt$ExperimentsProfitTracker$private var lastSplashes = mutableListOf<ItemStack>() VarCouldBeVal:FarmingWeightDisplay.kt$FarmingWeightDisplay$private var nextPlayers = mutableListOf<UpcomingLeaderboardPlayer>() VarCouldBeVal:FlareDisplay.kt$FlareDisplay$private var flares = mutableListOf<Flare>() VarCouldBeVal:FontRendererHook.kt$FontRendererHook$private var CHROMA_COLOR: Int = -0x1 @@ -321,13 +303,8 @@ VarCouldBeVal:SlayerItemsOnGround.kt$SlayerItemsOnGround$private var itemsOnGround = TimeLimitedCache<EntityItem, String>(2.seconds) VarCouldBeVal:SoopyGuessBurrow.kt$SoopyGuessBurrow$private var dingSlope = mutableListOf<Float>() VarCouldBeVal:SoopyGuessBurrow.kt$SoopyGuessBurrow$private var locations = mutableListOf<LorenzVec>() - VarCouldBeVal:SuperpairExperimentInformationDisplay.kt$SuperpairExperimentInformationDisplay$// TODO remove string. use enum instead! maybe even create new data type instead of map of pairs private var found = mutableMapOf<Pair<Item?, ItemPair?>, String>() - VarCouldBeVal:SuperpairExperimentInformationDisplay.kt$SuperpairExperimentInformationDisplay$private var lastClicked = mutableListOf<Pair<Int, Int>>() - VarCouldBeVal:SuperpairExperimentInformationDisplay.kt$SuperpairExperimentInformationDisplay$private var toCheck = mutableListOf<Pair<Int, Int>>() - VarCouldBeVal:SuperpairExperimentInformationDisplay.kt$SuperpairExperimentInformationDisplay$private var uncoveredItems = mutableListOf<Pair<Int, String>>() VarCouldBeVal:TiaRelayHelper.kt$TiaRelayHelper$private var resultDisplay = mutableMapOf<Int, Int>() VarCouldBeVal:TiaRelayHelper.kt$TiaRelayHelper$private var sounds = mutableMapOf<Int, Sound>() - VarCouldBeVal:Translator.kt$Translator$var lang = config.languageCode.get() VarCouldBeVal:TrevorFeatures.kt$TrevorFeatures$private var backupTrapperID: Int = 17 VarCouldBeVal:TrevorFeatures.kt$TrevorFeatures$private var trapperID: Int = 56 VarCouldBeVal:TrophyFishDisplay.kt$TrophyFishDisplay$private var recentlyDroppedTrophies = TimeLimitedCache<NEUInternalName, TrophyRarity>(5.seconds) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index a65aebe3eefb..09734937ee97 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -9,6 +9,9 @@ + Added an easier way to check your unique Hoppity Eggs collected on each island. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/2625) + Shows your progress in the Warp Menu. + Can be automatically hidden when an island is complete. ++ Added the ability to block opening the Chocolate Factory when Booster Cookie is inactive. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2713) ++ Added a feature to block opening Hoppity's trade menu from Abiphone calls if you do not have coins in your purse. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2664) ++ Added the ability to prevent closing Meal Eggs that have Rabbit the Fish inside. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2712) #### Inventory Features @@ -26,6 +29,17 @@ + Added Precision Mining Highlighter. - Cuz_Im_Clicks (https://github.com/hannibal002/SkyHanni/pull/2614) + Draws a box over the Precision Mining particles. + Added highlighting boxes to Crystal Nucleus crystals during Hoppity's Hunt. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2598) ++ Added Flowstate Helper. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/2561) + + Displays stats for the Flowstate enchantment on mining tools. + +#### Dungeon Features + ++ Added Terminal Waypoints. - Stella (https://github.com/hannibal002/SkyHanni/pull/2719) + + Displays waypoints during the F7/M7 Goldor Phase. + +#### Chat Features + ++ Added chat compacting for 'items in stash' warnings. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2639) ### Improvements @@ -38,11 +52,30 @@ + Replaced repeated SkyHanni messages with the previous message. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2700) + Added support for Guilds in player-related tab completions. - ThatGravyBoat (https://github.com/hannibal002/SkyHanni/pull/2637) + Added support for all Guild and Friend commands in tab completions. - ThatGravyBoat (https://github.com/hannibal002/SkyHanni/pull/2637) ++ Reordered commands in categories. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2642) ++ Renamed some commands for clarity. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2642) #### Combat Improvements + Added Totem of Corruption and Enrager to the Ability Cooldown feature. - DungeonHub (https://github.com/hannibal002/SkyHanni/pull/2706) +#### Mining Improvements + ++ Made the "You need a stronger tool to mine ..." chat filter hide every such message, not just Crystal Hollows gemstones. - Luna (https://github.com/hannibal002/SkyHanni/pull/2724) ++ Added an option to draw a line to your golden or diamond goblin. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/2717) + +#### Diana Improvements + ++ Added support for detecting and handling Inquisitor spawn messages from other mods from chat. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2720) + +#### Fishing Improvements + ++ Added an option to always display the Barn Fishing Timer anywhere. - NeoNyaa (https://github.com/hannibal002/SkyHanni/pull/2735) + +#### Hoppity Improvements + ++ Improved the Time Tower Usage Warning so it doesn't spam messages. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2730) + #### Misc Improvements + Added distance display to waypoints created by Patcher's Send Coords feature. - jani (https://github.com/hannibal002/SkyHanni/pull/2704) @@ -63,10 +96,17 @@ + Fixed an error with compact experiment rewards chat messages. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2702) + Fixed Craft Materials Bazaar not working with long item names. - Fazfoxy (https://github.com/hannibal002/SkyHanni/pull/2703) + Fixed the debug feature that allows you to add/remove stars being enabled by default. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2715) ++ Fixed displaying the Guardian warning text in the Experimentation Table even when using a Guardian Pet. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2718) ++ Fixed locked Ultimate enchantments being hidden by Enchant Parsing. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/2732) ++ Fixed Chest Value Display on Carpentry Chests. - fazfoxy (https://github.com/hannibal002/SkyHanni/pull/2743) ++ Fixed Compact Item Stars. - Empa, Fazfoxy (https://github.com/hannibal002/SkyHanni/pull/2741) #### Combat Fixes + Fixed Ghost Counter display appearing while in incorrect areas on the map. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2696) ++ Fixed Ashfang Blazes sometimes being highlighted with the wrong color. - Empa (https://github.com/hannibal002/SkyHanni/pull/2112) ++ Fixed Ashfang Reset Cooldown counting in the wrong direction. - Empa (https://github.com/hannibal002/SkyHanni/pull/2112) ++ Fixed Millennia-Aged Blaze not being highlighted by the Area Boss Highlight feature. - jani (https://github.com/hannibal002/SkyHanni/pull/2707) #### Custom Scoreboard Fixes @@ -75,11 +115,32 @@ #### Hoppity Fixes + Fixed the chocolate egg share message sometimes displaying the wrong location name. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/2711) ++ Fixed El Dorado not receiving a compacted chat message. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2742) + +#### Garden Fixes + ++ Fixed farming weight not disappearing when the config option is off. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2731) + +#### Crimson Isle Fixes + ++ Fixed Replace Lava not working with OptiFine. - CalMWolfs + nopo (https://github.com/hannibal002/SkyHanni/pull/2727) + +#### Diana Fixes + ++ Fixed Griffin Pet Warning not supporting Diana Autopet rules. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2722) #### Commands Fixes + Fixed /shtranslate not working in most cases. - Obsidian (https://github.com/hannibal002/SkyHanni/pull/2693) +#### Mining Fixes + ++ Fixed a crash when attempting to edit the Flowstate Helper config. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2740) + +#### Misc Fixes + ++ Fixed SkyHanni messages being sent twice. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2736) + ### Technical Details + Assigned 'backend' label to PRs with 'backend' in the title. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2690) @@ -94,6 +155,14 @@ + Added changelog verification. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2692) + This action ensures your PR is in the correct format so that it can be used by the release notes tool. + Added dungeon phase detection. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/1865) ++ Added EntityLeaveWorldEvent. - Empa (https://github.com/hannibal002/SkyHanni/pull/2112) ++ Made command registration event-based. - j10a1n15, ThatGravyBoat (https://github.com/hannibal002/SkyHanni/pull/2642) ++ Added "line to the mob" handler. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/2717) ++ No longer use NEU GUI elements for the auto-update button. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2725) ++ Added SkyHanni notifications. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2630) ++ Moved Hoppity Warp Menu config to `HoppityWarpMenuConfig`. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2712) ++ Migrated some LorenzEvents without parameters to SkyHanniEvents. - Empa (https://github.com/hannibal002/SkyHanni/pull/2744) ++ Changed SkyHanniEvents without parameters to be objects. - Empa (https://github.com/hannibal002/SkyHanni/pull/2744) ## Version 0.27 diff --git a/docs/FEATURES.md b/docs/FEATURES.md index 24c8e437252f..e84276478bcd 100644 --- a/docs/FEATURES.md +++ b/docs/FEATURES.md @@ -57,6 +57,7 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + More chat filters. - Mikecraft1224 (https://github.com/hannibal002/SkyHanni/pull/1750) + Filters for rare dungeon chest rewards and sacrifice messages from other players. + Add config option to hide achievement spam on Alpha. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2076) ++ Added chat compacting for 'items in stash' warnings. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2639)
@@ -115,6 +116,8 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + Optionally draws a line to them as well. + Added a Secret Chime for Dungeons with adjustable pitch and sound. - Ovi_1 (https://github.com/hannibal002/SkyHanni/pull/2478) + The sound and pitch of chimes in dungeons are customizable. ++ Added Terminal Waypoints. - Stella (https://github.com/hannibal002/SkyHanni/pull/2719) + + Displays waypoints during the F7/M7 Goldor Phase.
@@ -917,6 +920,8 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + Added Precision Mining Highlighter. - Cuz_Im_Clicks (https://github.com/hannibal002/SkyHanni/pull/2614) + Draws a box over the Precision Mining particles. + Added highlighting boxes to Crystal Nucleus crystals during Hoppity's Hunt. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2598) ++ Added Flowstate Helper. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/2561) + + Displays stats for the Flowstate enchantment on mining tools.
@@ -1016,6 +1021,9 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + Added an easier way to check your unique Hoppity Eggs collected on each island. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/2625) + Shows your progress in the Warp Menu. + Can be automatically hidden when an island is complete. ++ Added the ability to block opening the Chocolate Factory when Booster Cookie is inactive. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2713) ++ Added a feature to block opening Hoppity's trade menu from Abiphone calls if you do not have coins in your purse. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2664) ++ Added the ability to prevent closing Meal Eggs that have Rabbit the Fish inside. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2712) ### The Carnival diff --git a/root.gradle.kts b/root.gradle.kts index f97425b88a97..ba687910cd70 100644 --- a/root.gradle.kts +++ b/root.gradle.kts @@ -14,7 +14,7 @@ plugins { allprojects { group = "at.hannibal2.skyhanni" - version = "0.28.Beta.2" + version = "0.28.Beta.4" repositories { mavenCentral() mavenLocal() diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index 45d02f5445f6..2c14076a93ba 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -5,7 +5,7 @@ import at.hannibal2.skyhanni.config.ConfigFileType import at.hannibal2.skyhanni.config.ConfigManager import at.hannibal2.skyhanni.config.Features import at.hannibal2.skyhanni.config.SackData -import at.hannibal2.skyhanni.config.commands.Commands +import at.hannibal2.skyhanni.config.commands.CommandRegistrationEvent import at.hannibal2.skyhanni.data.OtherInventoryData import at.hannibal2.skyhanni.data.jsonobjects.local.FriendsJson import at.hannibal2.skyhanni.data.jsonobjects.local.JacobContestsJson @@ -59,9 +59,9 @@ class SkyHanniMod { SkyHanniEvents.init(modules) - Commands.init() + CommandRegistrationEvent.post() - PreInitFinishedEvent().post() + PreInitFinishedEvent.post() } @Mod.EventHandler diff --git a/src/main/java/at/hannibal2/skyhanni/api/CollectionAPI.kt b/src/main/java/at/hannibal2/skyhanni/api/CollectionAPI.kt index 1f5adacf70ab..2584b6616406 100644 --- a/src/main/java/at/hannibal2/skyhanni/api/CollectionAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/api/CollectionAPI.kt @@ -60,7 +60,7 @@ object CollectionAPI { val internalName = incorrectCollectionNames[name] ?: NEUInternalName.fromItemName(name) collectionValue[internalName] = counter } - CollectionUpdateEvent().postAndCatch() + CollectionUpdateEvent.post() } if (inventoryName.endsWith(" Collections")) { @@ -83,7 +83,7 @@ object CollectionAPI { collectionValue[internalName] = counter } } - CollectionUpdateEvent().postAndCatch() + CollectionUpdateEvent.post() } } diff --git a/src/main/java/at/hannibal2/skyhanni/api/FmlEventApi.kt b/src/main/java/at/hannibal2/skyhanni/api/FmlEventApi.kt index 5c119fbbbce8..95fd178ccd64 100644 --- a/src/main/java/at/hannibal2/skyhanni/api/FmlEventApi.kt +++ b/src/main/java/at/hannibal2/skyhanni/api/FmlEventApi.kt @@ -14,7 +14,7 @@ object FmlEventApi { @SubscribeEvent fun onDisconnect(event: FMLNetworkEvent.ClientDisconnectionFromServerEvent) { - ClientDisconnectEvent().post() + ClientDisconnectEvent.post() } @SubscribeEvent diff --git a/src/main/java/at/hannibal2/skyhanni/api/ReforgeAPI.kt b/src/main/java/at/hannibal2/skyhanni/api/ReforgeAPI.kt index 534d38d47c82..46d941fe007a 100644 --- a/src/main/java/at/hannibal2/skyhanni/api/ReforgeAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/api/ReforgeAPI.kt @@ -201,7 +201,7 @@ object ReforgeAPI { return Reforge( name = it.reforgeName, type = LorenzUtils.enumValueOf(type.first), - stats = it.reforgeStats ?: emptyMap(), + stats = it.reforgeStats.orEmpty(), reforgeStone = it.internalName, specialItems = type.second.takeIf { it.isNotEmpty() }, extraProperty = it.reforgeAbility, diff --git a/src/main/java/at/hannibal2/skyhanni/api/SkillAPI.kt b/src/main/java/at/hannibal2/skyhanni/api/SkillAPI.kt index ba8e42d66ee5..1cb893dbc9f9 100644 --- a/src/main/java/at/hannibal2/skyhanni/api/SkillAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/api/SkillAPI.kt @@ -28,8 +28,8 @@ import at.hannibal2.skyhanni.utils.NumberUtil.formatDouble import at.hannibal2.skyhanni.utils.NumberUtil.formatLong import at.hannibal2.skyhanni.utils.NumberUtil.formatLongOrUserError import at.hannibal2.skyhanni.utils.NumberUtil.romanToDecimalIfNecessary +import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher 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.TabListData import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern @@ -324,7 +324,14 @@ object SkillAPI { val nextLevelDiff = levelArray.getOrNull(level)?.toDouble() ?: 7_600_000.0 val nextLevelProgress = nextLevelDiff * xpPercentage / 100 val totalXp = levelXp + nextLevelProgress - updateSkillInfo(existingLevel, level, nextLevelProgress.toLong(), nextLevelDiff.toLong(), totalXp.toLong(), matcher.group("gained")) + updateSkillInfo( + existingLevel, + level, + nextLevelProgress.toLong(), + nextLevelDiff.toLong(), + totalXp.toLong(), + matcher.group("gained"), + ) } else { val exactLevel = getLevelExact(needed) val levelXp = calculateLevelXp(existingLevel.level - 1).toLong() + current @@ -430,7 +437,6 @@ object SkillAPI { val neededXp = levelingMap.filter { it.key < level }.values.sum().toLong() ChatUtils.chat("You need §b${neededXp.addSeparators()} §eXP to be level §b${level.toDouble()}") } else { - val base = levelingMap.values.sum().toLong() val neededXP = xpRequiredForLevel(level.toDouble()) ChatUtils.chat("You need §b${neededXP.addSeparators()} §eXP to be level §b${level.toDouble()}") } @@ -468,7 +474,9 @@ object SkillAPI { val skill = storage?.get(skillType) ?: return if (targetLevel <= skill.overflowLevel) { - ChatUtils.userError("Custom goal level ($targetLevel) must be greater than your current level (${skill.overflowLevel}).") + ChatUtils.userError( + "Custom goal level ($targetLevel) must be greater than your current level (${skill.overflowLevel})." + ) return } diff --git a/src/main/java/at/hannibal2/skyhanni/api/event/SkyHanniEvents.kt b/src/main/java/at/hannibal2/skyhanni/api/event/SkyHanniEvents.kt index ace86b224de4..97fcbf3c6f62 100644 --- a/src/main/java/at/hannibal2/skyhanni/api/event/SkyHanniEvents.kt +++ b/src/main/java/at/hannibal2/skyhanni/api/event/SkyHanniEvents.kt @@ -5,6 +5,7 @@ import at.hannibal2.skyhanni.data.jsonobjects.repo.DisabledEventsJson import at.hannibal2.skyhanni.events.DebugDataCollectEvent import at.hannibal2.skyhanni.events.RepositoryReloadEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import java.lang.reflect.Method @@ -60,7 +61,7 @@ object SkyHanniEvents { .filter { it.invokeCount > 0 } .sortedWith(compareBy({ -it.invokeCount }, { it.name })) .forEach { - add("- ${it.name} (${it.invokeCount} ${it.invokeCount / (MinecraftData.totalTicks / 20)}/s)") + add("- ${it.name} (${it.invokeCount.addSeparators()} ${it.invokeCount / (MinecraftData.totalTicks / 20)}/s)") } } } diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigGuiManager.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigGuiManager.kt index ffb3b7256bfc..2aad75a40e3e 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/ConfigGuiManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/ConfigGuiManager.kt @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.config import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.GuiEditManager import io.github.notenoughupdates.moulconfig.gui.GuiScreenElementWrapper import io.github.notenoughupdates.moulconfig.gui.MoulConfigEditor @@ -18,4 +19,16 @@ object ConfigGuiManager { } SkyHanniMod.screenToOpen = GuiScreenElementWrapper(editor) } + + fun onCommand(args: Array) { + if (args.isNotEmpty()) { + if (args[0].lowercase() == "gui") { + GuiEditManager.openGuiPositionEditor(hotkeyReminder = true) + } else { + openConfigGui(args.joinToString(" ")) + } + } else { + openConfigGui() + } + } } diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt index b00fc7a8f749..b82d4d8f9909 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt @@ -151,7 +151,10 @@ class ConfigManager { } if (missingConfigLink) { println("") - println("This crash is here to remind you to fix the missing @ConfigLink annotation over your new config position config element.") + println( + "This crash is here to remind you to fix the missing " + + "@ConfigLink annotation over your new config position config element." + ) println("") println("Steps to fix:") println("1. Search for `WEE WOO WEE WOO` in the console output.") diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt index c9ae8c2c7e89..f8afe645cf85 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt @@ -12,7 +12,7 @@ import com.google.gson.JsonPrimitive object ConfigUpdaterMigrator { val logger = LorenzLogger("ConfigMigration") - const val CONFIG_VERSION = 61 + const val CONFIG_VERSION = 63 fun JsonElement.at(chain: List, init: Boolean): JsonElement? { if (chain.isEmpty()) return this if (this !is JsonObject) return null @@ -81,7 +81,10 @@ object ConfigUpdaterMigrator { } val newParentElement = new.at(np.dropLast(1), true) if (newParentElement !is JsonObject) { - logger.log("Catastrophic: element at path $old could not be relocated to $new, since another element already inhabits that path") + logger.log( + "Catastrophic: element at path $old could not be relocated to $new, " + + "since another element already inhabits that path" + ) return } movesPerformed++ @@ -125,13 +128,11 @@ object ConfigUpdaterMigrator { ?.flatMap { player -> player.value.asJsonObject["profiles"]?.asJsonObject?.entrySet()?.map { "storage.players.${player.key}.profiles.${it.key}" - } ?: listOf() - } - ?: listOf() + }.orEmpty() + }.orEmpty() ), "#player" to ( - storage?.get("players")?.asJsonObject?.entrySet()?.map { "storage.players.${it.key}" } - ?: listOf() + storage?.get("players")?.asJsonObject?.entrySet()?.map { "storage.players.${it.key}" }.orEmpty() ), ) val migration = ConfigFixEvent( diff --git a/src/main/java/at/hannibal2/skyhanni/config/commands/CommandBuilder.kt b/src/main/java/at/hannibal2/skyhanni/config/commands/CommandBuilder.kt new file mode 100644 index 000000000000..98227fc8ccb4 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/commands/CommandBuilder.kt @@ -0,0 +1,20 @@ +package at.hannibal2.skyhanni.config.commands + +class CommandBuilder(val name: String) { + var description: String = "" + var category: CommandCategory = CommandCategory.MAIN + var aliases: List = emptyList() + private var autoComplete: ((Array) -> List) = { listOf() } + private var callback: (Array) -> Unit = {} + + fun callback(callback: (Array) -> Unit) { + this.callback = callback + } + + fun autoComplete(autoComplete: (Array) -> List) { + this.autoComplete = autoComplete + } + + fun toSimpleCommand() = SimpleCommand(name.lowercase(), aliases, callback, autoComplete) +} + diff --git a/src/main/java/at/hannibal2/skyhanni/config/commands/CommandCategory.kt b/src/main/java/at/hannibal2/skyhanni/config/commands/CommandCategory.kt new file mode 100644 index 000000000000..b0474ae47797 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/commands/CommandCategory.kt @@ -0,0 +1,44 @@ +package at.hannibal2.skyhanni.config.commands + +enum class CommandCategory(val color: String, val categoryName: String, val description: String) { + MAIN( + "§6", + "Main Command", + "Most useful commands of SkyHanni", + ), + USERS_ACTIVE( + "§e", + "Normal Command", + "Normal Command for everyone to use", + ), + USERS_RESET( + "§e", + "Normal Reset Command", + "Normal Command that resents some data", + ), + USERS_BUG_FIX( + "§f", + "User Bug Fix", + "A Command to fix small bugs", + ), + DEVELOPER_TEST( + "§5", + "Developer Test Commands", + "A Command to edit/test/change some features. §cIntended for developers only!", + ), + DEVELOPER_DEBUG( + "§9", + "Developer Debug Commands", + "A Command to debug/read/copy/monitor features. §cIntended for developers only!", + ), + INTERNAL( + "§8", + "Internal Command", + "A Command that should §cnever §7be called manually!", + ), + SHORTENED_COMMANDS( + "§b", + "Shortened Commands", + "Commands that shorten or improve existing Hypixel commands!", + ) +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/commands/CommandRegistrationEvent.kt b/src/main/java/at/hannibal2/skyhanni/config/commands/CommandRegistrationEvent.kt new file mode 100644 index 000000000000..5c021a8d41ae --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/commands/CommandRegistrationEvent.kt @@ -0,0 +1,16 @@ +package at.hannibal2.skyhanni.config.commands + +import at.hannibal2.skyhanni.api.event.SkyHanniEvent +import at.hannibal2.skyhanni.config.commands.Commands.commandList +import net.minecraftforge.client.ClientCommandHandler + +object CommandRegistrationEvent : SkyHanniEvent() { + fun register(name: String, block: CommandBuilder.() -> Unit) { + val info = CommandBuilder(name).apply(block) + if (commandList.any { it.name == name }) { + error("The command '$name is already registered!'") + } + ClientCommandHandler.instance.registerCommand(info.toSimpleCommand()) + commandList.add(info) + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt index bd94a16587f1..5ba6d3769430 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt @@ -2,12 +2,11 @@ package at.hannibal2.skyhanni.config.commands import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.api.SkillAPI +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.config.ConfigFileType import at.hannibal2.skyhanni.config.ConfigGuiManager -import at.hannibal2.skyhanni.config.features.About.UpdateStream import at.hannibal2.skyhanni.data.ChatManager import at.hannibal2.skyhanni.data.GardenCropMilestonesCommunityFix -import at.hannibal2.skyhanni.data.GuiEditManager import at.hannibal2.skyhanni.data.PartyAPI import at.hannibal2.skyhanni.data.SackAPI import at.hannibal2.skyhanni.data.ScoreboardData @@ -25,6 +24,7 @@ import at.hannibal2.skyhanni.features.commands.PartyChatCommands import at.hannibal2.skyhanni.features.commands.PartyCommands import at.hannibal2.skyhanni.features.commands.WikiManager import at.hannibal2.skyhanni.features.dungeon.CroesusChestTracker +import at.hannibal2.skyhanni.features.dungeon.floor7.TerminalInfo import at.hannibal2.skyhanni.features.event.diana.AllBurrowsList import at.hannibal2.skyhanni.features.event.diana.BurrowWarpHelper import at.hannibal2.skyhanni.features.event.diana.DianaProfitTracker @@ -79,6 +79,7 @@ import at.hannibal2.skyhanni.features.misc.visualwords.VisualWordGui import at.hannibal2.skyhanni.features.rift.area.westvillage.VerminTracker import at.hannibal2.skyhanni.features.rift.everywhere.PunchcardHighlight import at.hannibal2.skyhanni.features.slayer.SlayerProfitTracker +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.test.DebugCommand import at.hannibal2.skyhanni.test.PacketTest import at.hannibal2.skyhanni.test.SkyBlockIslandTest @@ -96,634 +97,740 @@ import at.hannibal2.skyhanni.test.command.TrackParticlesCommand import at.hannibal2.skyhanni.test.command.TrackSoundsCommand import at.hannibal2.skyhanni.test.graph.GraphEditor import at.hannibal2.skyhanni.utils.APIUtils -import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.ExtendedChatColor import at.hannibal2.skyhanni.utils.ItemPriceUtils -import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.SoundUtils import at.hannibal2.skyhanni.utils.TabListData import at.hannibal2.skyhanni.utils.chat.ChatClickActionManager import at.hannibal2.skyhanni.utils.repopatterns.RepoPatternGui -import net.minecraft.command.ICommandSender -import net.minecraft.util.BlockPos -import net.minecraftforge.client.ClientCommandHandler +@SkyHanniModule +@Suppress("LargeClass", "LongMethod") object Commands { - private val openMainMenu: (Array) -> Unit = { - if (it.isNotEmpty()) { - if (it[0].lowercase() == "gui") { - GuiEditManager.openGuiPositionEditor(hotkeyReminder = true) - } else { - ConfigGuiManager.openConfigGui(it.joinToString(" ")) - } - } else { - ConfigGuiManager.openConfigGui() - } - } - - // command -> description - private val commands = mutableListOf() - - enum class CommandCategory(val color: String, val categoryName: String, val description: String) { - MAIN("§6", "Main Command", "Most useful commands of SkyHanni"), - USERS_NORMAL("§e", "Normal Command", "Normal Command for everyone to use"), - USERS_BUG_FIX("§f", "User Bug Fix", "A Command to fix small bugs"), - DEVELOPER_CODING_HELP( - "§5", - "Developer Coding Help", - "A Command that can help with developing new features. §cIntended for developers only!", - ), - DEVELOPER_DEBUG_FEATURES( - "§9", - "Developer Debug Features", - "A Command that is useful for monitoring/debugging existing features. §cIntended for developers only!", - ), - INTERNAL("§8", "Internal Command", "A Command that should §cnever §7be called manually!"), - SHORTENED_COMMANDS("§b", "Shortened Commands", "Commands that shorten or improve existing Hypixel commands!") - } - - class CommandInfo(val name: String, val description: String, val category: CommandCategory) - - private var currentCategory = CommandCategory.MAIN - - fun init() { - currentCategory = CommandCategory.MAIN - usersMain() - - currentCategory = CommandCategory.USERS_NORMAL - usersNormal() - - currentCategory = CommandCategory.USERS_BUG_FIX - usersBugFix() - - currentCategory = CommandCategory.DEVELOPER_CODING_HELP - developersCodingHelp() - - currentCategory = CommandCategory.DEVELOPER_DEBUG_FEATURES - developersDebugFeatures() - - currentCategory = CommandCategory.INTERNAL - internalCommands() - - currentCategory = CommandCategory.SHORTENED_COMMANDS - shortenedCommands() - } - - private fun usersMain() { - registerCommand("sh", "Opens the main SkyHanni config", openMainMenu) - registerCommand("skyhanni", "Opens the main SkyHanni config", openMainMenu) - registerCommand("ff", "Opens the Farming Fortune Guide") { openFortuneGuide() } - registerCommand("shcommands", "Shows this list") { HelpCommand.onCommand(it, commands) } - registerCommand0( - "shdefaultoptions", - "Select default options", - { DefaultConfigFeatures.onCommand(it) }, - DefaultConfigFeatures::onComplete, - ) - registerCommand("shremind", "Set a reminder for yourself") { ReminderManager.command(it) } - registerCommand("shwords", "Opens the config list for modifying visual words") { openVisualWords() } - registerCommand("shnavigate", "Using path finder to go to locatons") { NavigationHelper.onCommand(it) } - } - - @Suppress("LongMethod") - private fun usersNormal() { - registerCommand( - "shmarkplayer", - "Add a highlight effect to a player for better visibility", - ) { MarkedPlayerManager.command(it) } - registerCommand("shtrackcollection", "Tracks your collection gain over time") { CollectionTracker.command(it) } - registerCommand( - "shcroptime", - "Calculates with your current crop per second speed how long you need to farm a crop to collect this amount of items", - ) { GardenCropTimeCommand.onCommand(it) } - registerCommand( - "shcropsin", - "Calculates with your current crop per second how many items you can collect in this amount of time", - ) { GardenCropsInCommand.onCommand(it) } - registerCommand( - "shrpcstart", - "Manually starts the Discord Rich Presence feature", - ) { DiscordRPCManager.startCommand() } - registerCommand( - "shcropstartlocation", - "Manually sets the crop start location", - ) { GardenStartLocation.setLocationCommand() } - registerCommand( - "shclearslayerprofits", - "Clearing the total slayer profit for the current slayer type", - ) { SlayerProfitTracker.clearProfitCommand(it) } - registerCommand( - "shimportghostcounterdata", - "Manually importing the ghost counter data from GhostCounterV3", - ) { GhostUtil.importCTGhostCounterData() } - registerCommand( - "shclearfarmingitems", - "Clear farming items saved for the Farming Fortune Guide", - ) { clearFarmingItems() } - registerCommand("shresetghostcounter", "Resets the ghost counter") { GhostUtil.reset() } - registerCommand("shresetpowdertracker", "Resets the Powder Tracker") { PowderTracker.resetCommand() } - registerCommand("shresetdicertracker", "Resets the Dicer Drop Tracker") { DicerRngDropTracker.resetCommand() } - registerCommand("shresetcorpsetracker", "Resets the Glacite Mineshaft Corpse Tracker") { CorpseTracker.resetCommand() } - registerCommand( - "shresetendernodetracker", - "Resets the Ender Node Tracker", - ) { EnderNodeTracker.resetCommand() } - registerCommand( - "shresetarmordroptracker", - "Resets the Armor Drop Tracker", - ) { ArmorDropTracker.resetCommand() } - registerCommand( - "shresetfrozentreasuretracker", - "Resets the Frozen Treasure Tracker", - ) { FrozenTreasureTracker.resetCommand() } - registerCommand( - "shresetfishingtracker", - "Resets the Fishing Profit Tracker", - ) { FishingProfitTracker.resetCommand() } - registerCommand( - "shresetvisitordrops", - "Reset the Visitors Drop Statistics", - ) { GardenVisitorDropStatistics.resetCommand() } - registerCommand("shbingotoggle", "Toggle the bingo card display mode") { BingoCardDisplay.toggleCommand() } - registerCommand( - "shfarmingprofile", - "Look up the farming profile from yourself or another player on elitebot.dev", - ) { FarmingWeightDisplay.lookUpCommand(it) } - registerCommand( - "shcopytranslation", - "Copy the translation of a message in another language to your clipboard.\n" + "Uses a language code that can be found at the end of a translation message.", - ) { Translator.fromNativeLanguage(it) } - registerCommand( - "shtranslate", - "Translate a message in another language to your language.", - ) { Translator.toNativeLanguage(it) } - registerCommand( - "shmouselock", - "Lock/Unlock the mouse so it will no longer rotate the player (for farming)", - ) { LockMouseLook.toggleLock() } - registerCommand( - "shsensreduce", - "Lowers the mouse sensitivity for easier small adjustments (for farming)", - ) { SensitivityReducer.manualToggle() } - registerCommand( - "shresetvermintracker", - "Resets the Vermin Tracker", - ) { VerminTracker.resetCommand() } - registerCommand( - "shresetdianaprofittracker", - "Resets the Diana Profit Tracker", - ) { DianaProfitTracker.resetCommand() } - registerCommand( - "shresetpestprofittracker", - "Resets the Pest Profit Tracker", - ) { PestProfitTracker.resetCommand() } - registerCommand( - "shresetexperimentsprofittracker", - "Resets the Experiments Profit Tracker", - ) { ExperimentsProfitTracker.resetCommand() } - registerCommand( - "shresetmythologicalcreaturetracker", - "Resets the Mythological Creature Tracker", - ) { MythologicalCreatureTracker.resetCommand() } - registerCommand( - "shresetseacreaturetracker", - "Resets the Sea Creature Tracker", - ) { SeaCreatureTracker.resetCommand() } - registerCommand( - "shresetstrayrabbittracker", - "Resets the Stray Rabbit Tracker", - ) { ChocolateFactoryStrayTracker.resetCommand() } - registerCommand( - "shresetexcavatortracker", - "Resets the Fossil Excavator Profit Tracker", - ) { ExcavatorProfitTracker.resetCommand() } - registerCommand( - "shfandomwiki", - "Searches the fandom wiki with SkyHanni's own method.", - ) { WikiManager.otherWikiCommands(it, true) } - registerCommand( - "shfandomwikithis", - "Searches the fandom wiki with SkyHanni's own method.", - ) { WikiManager.otherWikiCommands(it, true, true) } - registerCommand( - "shofficialwiki", - "Searches the official wiki with SkyHanni's own method.", - ) { WikiManager.otherWikiCommands(it, false) } - registerCommand( - "shofficialwikithis", - "Searches the official wiki with SkyHanni's own method.", - ) { WikiManager.otherWikiCommands(it, false, true) } - registerCommand0( - "shcalccrop", - "Calculate how many crops need to be farmed between different crop milestones.", - { - FarmingMilestoneCommand.onCommand(it.getOrNull(0), it.getOrNull(1), it.getOrNull(2), false) - }, - FarmingMilestoneCommand::onComplete, - ) - registerCommand0( - "shcalccroptime", - "Calculate how long you need to farm crops between different crop milestones.", - { - FarmingMilestoneCommand.onCommand(it.getOrNull(0), it.getOrNull(1), it.getOrNull(2), true) - }, - FarmingMilestoneCommand::onComplete, - ) - registerCommand0( - "shcropgoal", - "Define a custom milestone goal for a crop.", - { FarmingMilestoneCommand.setGoal(it) }, - FarmingMilestoneCommand::onComplete, - ) - registerCommand0( - "shskills", - "Skills XP/Level related command", - { SkillAPI.onCommand(it) }, - SkillAPI::onComplete, - ) - registerCommand( - "shlimbostats", - "Prints your Limbo Stats.\n §7This includes your Personal Best, Playtime, and §aSkyHanni User Luck§7!", - ) { LimboTimeTracker.printStats() } - registerCommand( - "shlanedetection", - "Detect a farming lane in the Garden", - ) { FarmingLaneCreator.commandLaneDetection() } - registerCommand( - "shignore", - "Add/Remove a user from your", - ) { PartyChatCommands.blacklist(it) } - registerCommand( - "shtpinfested", - "Teleports you to the nearest infested plot", - ) { PestFinder.teleportNearestInfestedPlot() } - registerCommand( - "shhoppitystats", - "Look up stats for a Hoppity's Event (by SkyBlock year).\nRun standalone for a list of years that have stats.", - ) { HoppityEventSummary.sendStatsMessage(it) } - registerCommand( - "shcolors", - "Prints a list of all Minecraft color & formatting codes in chat.", - ) { ColorFormattingHelper.printColorCodeList() } - registerCommand( - "shtps", - "Informs in chat about the server ticks per second (TPS).", - ) { TpsCounter.tpsCommand() } - registerCommand( - "shcarry", - "Keep track of carries you do.", - ) { CarryTracker.onCommand(it) } - } + val commandList = mutableListOf() - private fun usersBugFix() { - registerCommand("shupdaterepo", "Download the SkyHanni repo again") { SkyHanniMod.repo.updateRepo() } - registerCommand( - "shresetburrowwarps", - "Manually resetting disabled diana burrow warp points", - ) { BurrowWarpHelper.resetDisabledWarps() } - registerCommand( - "shtogglehypixelapierrors", - "Show/hide hypixel api error messages in chat", - ) { APIUtils.toggleApiErrorMessages() } - registerCommand( - "shclearcropspeed", - "Reset garden crop speed data and best crop time data", - ) { GardenAPI.clearCropSpeed() } - registerCommand( - "shclearminiondata", - "Removed bugged minion locations from your private island", - ) { MinionFeatures.removeBuggedMinions(isCommand = true) } - registerCommand( - "shwhereami", - "Print current island in chat", - ) { SkyHanniDebugsAndTests.whereAmI() } - registerCommand( - "shclearcontestdata", - "Resets Jacob's Contest Data", - ) { SkyHanniDebugsAndTests.clearContestData() } - registerCommand( - "shconfig", - "Search or reset config elements §c(warning, dangerous!)", - ) { SkyHanniConfigSearchResetCommand.command(it) } - registerCommand( - "shdebug", - "Copies SkyHanni debug data in the clipboard.", - ) { DebugCommand.command(it) } - registerCommand( - "shversion", - "Prints the SkyHanni version in the chat", - ) { SkyHanniDebugsAndTests.debugVersion() } - registerCommand( - "shrendertoggle", - "Disables/enables the rendering of all skyhanni guis.", - ) { SkyHanniDebugsAndTests.toggleRender() } - registerCommand( - "shcarrolyn", - "Toggles if the specified crops effect is active from carrolyn", - ) { - CaptureFarmingGear.handelCarrolyn(it) - } - registerCommand( - "shrepostatus", - "Shows the status of all the mods constants", - ) { SkyHanniMod.repo.displayRepoStatus(false) } - registerCommand( - "shclearkismet", - "Clears the saved values of the applied kismet feathers in Croesus", - ) { CroesusChestTracker.resetChest() } - registerCommand( - "shkingfix", - "Resets the local King Talisman Helper offset.", - ) { KingTalismanHelper.kingFix() } - registerCommand( - "shupdate", - "Updates the mod to the specified update stream.", - ) { forceUpdate(it) } - registerCommand( - "shUpdateBazaarPrices", - "Forcefully updating the bazaar prices right now.", - ) { HypixelBazaarFetcher.fetchNow() } - registerCommand( - "shclearsavedrabbits", - "Clears the saved rabbits on this profile.", - ) { HoppityCollectionStats.clearSavedRabbits() } - registerCommand( - "shresetpunchcard", - "Resets the Rift Punchcard Artifact player list.", - ) { PunchcardHighlight.clearList() } - registerCommand( - "shedittracker", - "Changes the tracked item amount for Diana, Fishing, Pest, Excavator, and Slayer Item Trackers.", - ) { TrackerManager.commandEditTracker(it) } + @HandleEvent + fun onCommandRegistration(event: CommandRegistrationEvent) { + usersMain(event) + usersNormal(event) + usersNormalReset(event) + usersBugFix(event) + devTest(event) + devDebug(event) + internalCommands(event) + shortenedCommands(event) } - private fun developersDebugFeatures() { - registerCommand("shtestbingo", "dev command") { TestBingo.toggle() } - registerCommand("shprintbingohelper", "dev command") { BingoNextStepHelper.command() } - registerCommand("shreloadbingodata", "dev command") { BingoCardDisplay.command() } - registerCommand("shtestgardenvisitors", "dev command") { SkyHanniDebugsAndTests.testGardenVisitors() } - registerCommand("shtestcomposter", "dev command") { ComposterOverlay.onCommand(it) } - registerCommand("shtestinquisitor", "dev command") { InquisitorWaypointShare.test() } - registerCommand("shshowcropmoneycalculation", "dev command") { CropMoneyDisplay.toggleShowCalculation() } - registerCommand("shcropspeedmeter", "Debugs how many crops you collect over time") { CropSpeedMeter.toggle() } - registerCommand0( - "shworldedit", - "Select regions in the world", - { WorldEdit.command(it) }, - { listOf("copy", "reset", "help", "left", "right") }, - ) - registerCommand( - "shconfigsave", - "Manually saving the config", - ) { SkyHanniMod.configManager.saveConfig(ConfigFileType.FEATURES, "manual-command") } - registerCommand( - "shtestburrow", - "Sets a test burrow waypoint at your location", - ) { GriffinBurrowHelper.setTestBurrow(it) } - registerCommand( - "shtestsackapi", - "Get the amount of an item in sacks according to internal feature SackAPI", - ) { SackAPI.testSackAPI(it) } - registerCommand( - "shtestgriffinspots", - "Show potential griffin spots around you.", - ) { GriffinBurrowHelper.testGriffinSpots() } - registerCommand( - "shtestisland", - "Sets the current skyblock island for testing purposes.", - ) { SkyBlockIslandTest.onCommand(it) } - registerCommand( - "shdebugprice", - "Debug different price sources for an item.", - ) { ItemPriceUtils.debugItemPrice(it) } - registerCommand( - "shdebugscoreboard", - "Monitors the scoreboard changes: Prints the raw scoreboard lines in the console after each update, with time since last update.", - ) { ScoreboardData.toggleMonitor() } + private fun usersMain(event: CommandRegistrationEvent) { + event.register("sh") { + aliases = listOf("skyhanni") + description = "Opens the main SkyHanni config" + callback { ConfigGuiManager.onCommand(it) } + } + event.register("ff") { + description = "Opens the Farming Fortune Guide" + callback { FFGuideGUI.onCommand() } + } + event.register("shcommands") { + description = "Shows this list" + callback { HelpCommand.onCommand(it) } + } + event.register("shdefaultoptions") { + description = "Select default options" + callback { DefaultConfigFeatures.onCommand(it) } + autoComplete { DefaultConfigFeatures.onComplete(it) } + } + event.register("shremind") { + description = "Set a reminder for yourself" + callback { ReminderManager.command(it) } + } + event.register("shwords") { + description = "Opens the config list for modifying visual words" + callback { VisualWordGui.onCommand() } + } + event.register("shnavigate") { + description = "Using path finder to go to locations" + callback { NavigationHelper.onCommand(it) } + } + event.register("shcarry") { + description = "Keep track of carries you do." + callback { CarryTracker.onCommand(it) } + } + event.register("shmarkplayer") { + description = "Add a highlight effect to a player for better visibility" + callback { MarkedPlayerManager.command(it) } + } + event.register("shtrackcollection") { + description = "Tracks your collection gain over time" + callback { CollectionTracker.command(it) } + } } @Suppress("LongMethod") - private fun developersCodingHelp() { - registerCommand("shrepopatterns", "See where regexes are loaded from") { RepoPatternGui.open() } - registerCommand("shtest", "Unused test command.") { SkyHanniDebugsAndTests.testCommand(it) } - registerCommand("shtestrabbitpaths", "Tests pathfinding to rabbit eggs. Use a number 0-14.") { - HoppityEggLocator.testPathfind(it) - } - registerCommand( - "shtestitem", - "test item internal name resolving", - ) { SkyHanniDebugsAndTests.testItemCommand(it) } - registerCommand( - "shfindnullconfig", - "Find config elements that are null and prints them into the console", - ) { SkyHanniDebugsAndTests.findNullConfig(it) } - registerCommand("shtestwaypoint", "Set a waypoint on that location") { SkyHanniDebugsAndTests.waypoint(it) } - registerCommand("shtesttablist", "Set your clipboard as a fake tab list.") { TabListData.toggleDebug() } - registerCommand("shreloadlocalrepo", "Reloading the local repo data") { SkyHanniMod.repo.reloadLocalRepo() } - registerCommand("shchathistory", "Show the unfiltered chat history") { ChatManager.openChatFilterGUI(it) } - registerCommand( - "shstoplisteners", - "Unregistering all loaded forge event listeners", - ) { SkyHanniDebugsAndTests.stopListeners() } - registerCommand( - "shreloadlisteners", - "Trying to load all forge event listeners again. Might not work at all", - ) { SkyHanniDebugsAndTests.reloadListeners() } - registerCommand( - "shcopylocation", - "Copies the player location as LorenzVec format to the clipboard", - ) { SkyHanniDebugsAndTests.copyLocation(it) } - registerCommand( - "shcopyentities", - "Copies entities in the specified radius around the player to the clipboard", - ) { CopyNearbyEntitiesCommand.command(it) } - registerCommand( - "shtracksounds", - "Tracks the sounds for the specified duration (in seconds) and copies it to the clipboard", - ) { TrackSoundsCommand.command(it) } - registerCommand( - "shtrackparticles", - "Tracks the particles for the specified duration (in seconds) and copies it to the clipboard", - ) { TrackParticlesCommand.command(it) } - registerCommand( - "shcopytablist", - "Copies the tab list data to the clipboard", - ) { TabListData.copyCommand(it) } - registerCommand( - "shcopyactionbar", - "Copies the action bar to the clipboard, including formatting codes", - ) { CopyActionBarCommand.command(it) } - registerCommand( - "shcopyscoreboard", - "Copies the scoreboard data to the clipboard", - ) { CopyScoreboardCommand.command(it) } - registerCommand( - "shcopybossbar", - "Copies the name of the bossbar to the clipboard, including formatting codes", - ) { CopyBossbarCommand.command(it) } - registerCommand( - "shcopyitem", - "Copies information about the item in hand to the clipboard", - ) { CopyItemCommand.command() } - registerCommand("shtestpacket", "Logs incoming and outgoing packets to the console") { PacketTest.command(it) } - registerCommand( - "shtestmessage", - "Sends a custom chat message client side in the chat", - ) { TestChatCommand.command(it) } - registerCommand( - "shtestrainbow", - "Sends a rainbow in chat", - ) { ExtendedChatColor.testCommand() } - registerCommand( - "shcopyinternalname", - "Copies the internal name of the item in hand to the clipboard.", - ) { SkyHanniDebugsAndTests.copyItemInternalName() } - registerCommand( - "shpartydebug", - "List persons into the chat SkyHanni thinks are in your party.", - ) { PartyAPI.listMembers() } - registerCommand( - "shplaysound", - "Play the specified sound effect at the given pitch and volume.", - ) { SoundUtils.command(it) } - registerCommand( - "shsendtitle", - "Display a title on the screen with the specified settings.", - ) { TitleManager.command(it) } - registerCommand( - "shresetconfig", - "Reloads the config manager and rendering processors of MoulConfig. " + "This §cWILL RESET §7your config, but also updating the java config files " + "(names, description, orderings and stuff).", - ) { SkyHanniDebugsAndTests.resetConfigCommand() } - registerCommand( - "shreadcropmilestonefromclipboard", - "Read crop milestone from clipboard. This helps fixing wrong crop milestone data", - ) { GardenCropMilestonesCommunityFix.readDataFromClipboard() } - registerCommand( - "shcopyfoundburrowlocations", - "Copy all ever found burrow locations to clipboard", - ) { AllBurrowsList.copyToClipboard() } - registerCommand( - "shaddfoundburrowlocationsfromclipboard", - "Add all ever found burrow locations from clipboard", - ) { AllBurrowsList.addFromClipboard() } - registerCommand( - "shgraph", - "Enables the graph editor", - ) { GraphEditor.commandIn() } - registerCommand( - "shtoggleegglocationdebug", - "Shows Hoppity egg locations with their internal API names and status.", - ) { HoppityEggLocations.toggleDebug() } - registerCommand( - "shresetmineshaftpitystats", - "Resets the mineshaft pity display stats", - ) { MineshaftPityDisplay.fullResetCounter() } - registerCommand( - "shtranslateadvanced", - "Translates a message in an inputted language to another inputted language.", - ) { Translator.translateAdvancedCommand(it) } - } - - private fun internalCommands() { - registerCommand("shaction", "") { ChatClickActionManager.onCommand(it) } + private fun usersNormal(event: CommandRegistrationEvent) { + event.register("shimportghostcounterdata") { + description = "Manually importing the ghost counter data from GhostCounterV3" + category = CommandCategory.USERS_ACTIVE + callback { GhostUtil.importCTGhostCounterData() } + } + event.register("shcroptime") { + description = + "Calculates with your current crop per second speed " + "how long you need to farm a crop to collect this amount of items" + category = CommandCategory.USERS_ACTIVE + callback { GardenCropTimeCommand.onCommand(it) } + } + event.register("shcropsin") { + description = "Calculates with your current crop per second how many items you can collect in this amount of time" + category = CommandCategory.USERS_ACTIVE + callback { GardenCropsInCommand.onCommand(it) } + } + event.register("shrpcstart") { + description = "Manually starts the Discord Rich Presence feature" + category = CommandCategory.USERS_ACTIVE + callback { DiscordRPCManager.startCommand() } + } + event.register("shcropstartlocation") { + description = "Manually sets the crop start location" + category = CommandCategory.USERS_ACTIVE + callback { GardenStartLocation.setLocationCommand() } + } + event.register("shbingotoggle") { + description = "Toggle the bingo card display mode" + category = CommandCategory.USERS_ACTIVE + callback { BingoCardDisplay.toggleCommand() } + } + event.register("shfarmingprofile") { + description = "Look up the farming profile from yourself or another player on elitebot.dev" + category = CommandCategory.USERS_ACTIVE + callback { FarmingWeightDisplay.lookUpCommand(it) } + } + event.register("shcopytranslation") { + description = + "Copy the translation of a message in another language to your clipboard.\n" + + "Uses a 2 letter language code that can be found at the end of a translation message." + category = CommandCategory.USERS_ACTIVE + callback { Translator.fromNativeLanguage(it) } + } + event.register("shtranslate") { + description = "Translate a message in another language your language." + category = CommandCategory.USERS_ACTIVE + callback { Translator.toNativeLanguage(it) } + } + event.register("shmouselock") { + description = "Lock/Unlock the mouse so it will no longer rotate the player (for farming)" + category = CommandCategory.USERS_ACTIVE + callback { LockMouseLook.toggleLock() } + } + event.register("shsensreduce") { + description = "Lowers the mouse sensitivity for easier small adjustments (for farming)" + category = CommandCategory.USERS_ACTIVE + callback { SensitivityReducer.manualToggle() } + } + event.register("shfandomwiki") { + description = "Searches the fandom wiki with SkyHanni's own method." + category = CommandCategory.USERS_ACTIVE + callback { WikiManager.otherWikiCommands(it, true) } + } + event.register("shfandomwikithis") { + description = "Searches the fandom wiki with SkyHanni's own method." + category = CommandCategory.USERS_ACTIVE + callback { WikiManager.otherWikiCommands(it, true, true) } + } + event.register("shofficialwiki") { + description = "Searches the official wiki with SkyHanni's own method." + category = CommandCategory.USERS_ACTIVE + callback { WikiManager.otherWikiCommands(it, false) } + } + event.register("shofficialwikithis") { + description = "Searches the official wiki with SkyHanni's own method." + category = CommandCategory.USERS_ACTIVE + callback { WikiManager.otherWikiCommands(it, false, true) } + } + event.register("shcalccrop") { + description = "Calculate how many crops need to be farmed between different crop milestones." + category = CommandCategory.USERS_ACTIVE + autoComplete { FarmingMilestoneCommand.onComplete(it) } + callback { FarmingMilestoneCommand.onCommand(it.getOrNull(0), it.getOrNull(1), it.getOrNull(2), false) } + } + event.register("shcalccroptime") { + description = "Calculate how long you need to farm crops between different crop milestones." + category = CommandCategory.USERS_ACTIVE + autoComplete { FarmingMilestoneCommand.onComplete(it) } + callback { FarmingMilestoneCommand.onCommand(it.getOrNull(0), it.getOrNull(1), it.getOrNull(2), true) } + } + event.register("shcropgoal") { + description = "Define a custom milestone goal for a crop." + category = CommandCategory.USERS_ACTIVE + callback { FarmingMilestoneCommand.setGoal(it) } + autoComplete { FarmingMilestoneCommand.onComplete(it) } + } + event.register("shskills") { + description = "Skills XP/Level related command" + category = CommandCategory.USERS_ACTIVE + callback { SkillAPI.onCommand(it) } + autoComplete { SkillAPI.onComplete(it) } + } + event.register("shlimbostats") { + description = "Prints your Limbo Stats.\n §7This includes your Personal Best, Playtime, and §aSkyHanni User Luck§7!" + category = CommandCategory.USERS_ACTIVE + callback { LimboTimeTracker.printStats() } + } + event.register("shlanedetection") { + description = "Detect a farming lane in the Garden" + category = CommandCategory.USERS_ACTIVE + callback { FarmingLaneCreator.commandLaneDetection() } + } + event.register("shignore") { + description = "Add/Remove a user from your blacklist" + category = CommandCategory.USERS_ACTIVE + callback { PartyChatCommands.blacklist(it) } + } + event.register("shtpinfested") { + description = "Teleports you to the nearest infested plot" + category = CommandCategory.USERS_ACTIVE + callback { PestFinder.teleportNearestInfestedPlot() } + } + event.register("shhoppitystats") { + description = "Look up stats for a Hoppity's Event (by SkyBlock year).\nRun standalone for a list of years that have stats." + category = CommandCategory.USERS_ACTIVE + callback { HoppityEventSummary.sendStatsMessage(it) } + } + event.register("shcolors") { + description = "Prints a list of all Minecraft color & formatting codes in chat." + category = CommandCategory.USERS_ACTIVE + @Suppress("AvoidBritishSpelling") + aliases = listOf("shcolor", "shcolours", "shcolour") + callback { ColorFormattingHelper.printColorCodeList() } + } + event.register("shtps") { + description = "Informs in chat about the server ticks per second (TPS)." + category = CommandCategory.USERS_ACTIVE + callback { TpsCounter.tpsCommand() } + } } - private fun shortenedCommands() { - registerCommand("pko", "Kicks offline party members") { PartyCommands.kickOffline() } - registerCommand("pw", "Warps your party") { PartyCommands.warp() } - registerCommand("pk", "Kick a specific party member") { PartyCommands.kick(it) } - registerCommand("pt", "Transfer the party to another party member") { PartyCommands.transfer(it) } - registerCommand("pp", "Promote a specific party member") { PartyCommands.promote(it) } - registerCommand("pd", "Disbands the party") { PartyCommands.disband() } - registerCommand("rpt", "Reverse transfer party to the previous leader") { PartyCommands.reverseTransfer() } - } + private fun usersNormalReset(event: CommandRegistrationEvent) { - @JvmStatic - fun openFortuneGuide() { - if (!LorenzUtils.inSkyBlock) { - ChatUtils.userError("Join SkyBlock to open the fortune guide!") - } else { - FFGuideGUI.open() + // Trackers + event.register("shresetslayerprofits") { + description = "Resets the total slayer profit for the current slayer type" + category = CommandCategory.USERS_RESET + callback { SlayerProfitTracker.resetCommand() } + } + event.register("shresetpowdertracker") { + description = "Resets the Powder Tracker" + category = CommandCategory.USERS_RESET + callback { PowderTracker.resetCommand() } + } + event.register("shresetdicertracker") { + description = "Resets the Dicer Drop Tracker" + category = CommandCategory.USERS_RESET + callback { DicerRngDropTracker.resetCommand() } + } + event.register("shresetcorpsetracker") { + description = "Resets the Glacite Mineshaft Corpse Tracker" + category = CommandCategory.USERS_RESET + callback { CorpseTracker.resetCommand() } + } + event.register("shresetendernodetracker") { + description = "Resets the Ender Node Tracker" + category = CommandCategory.USERS_RESET + callback { EnderNodeTracker.resetCommand() } + } + event.register("shresetarmordroptracker") { + description = "Resets the Armor Drop Tracker" + category = CommandCategory.USERS_RESET + callback { ArmorDropTracker.resetCommand() } + } + event.register("shresetfrozentreasuretracker") { + description = "Resets the Frozen Treasure Tracker" + category = CommandCategory.USERS_RESET + callback { FrozenTreasureTracker.resetCommand() } + } + event.register("shresetfishingtracker") { + description = "Resets the Fishing Profit Tracker" + category = CommandCategory.USERS_RESET + callback { FishingProfitTracker.resetCommand() } + } + event.register("shresetvisitordrops") { + description = "Resets the Visitors Drop Statistics" + category = CommandCategory.USERS_RESET + callback { GardenVisitorDropStatistics.resetCommand() } + } + event.register("shresetvermintracker") { + description = "Resets the Vermin Tracker" + category = CommandCategory.USERS_RESET + callback { VerminTracker.resetCommand() } + } + event.register("shresetdianaprofittracker") { + description = "Resets the Diana Profit Tracker" + category = CommandCategory.USERS_RESET + callback { DianaProfitTracker.resetCommand() } + } + event.register("shresetpestprofittracker") { + description = "Resets the Pest Profit Tracker" + category = CommandCategory.USERS_RESET + callback { PestProfitTracker.resetCommand() } + } + event.register("shresetexperimentsprofittracker") { + description = "Resets the Experiments Profit Tracker" + category = CommandCategory.USERS_RESET + callback { ExperimentsProfitTracker.resetCommand() } + } + event.register("shresetmythologicalcreaturetracker") { + description = "Resets the Mythological Creature Tracker" + category = CommandCategory.USERS_RESET + callback { MythologicalCreatureTracker.resetCommand() } + } + event.register("shresetseacreaturetracker") { + description = "Resets the Sea Creature Tracker" + category = CommandCategory.USERS_RESET + callback { SeaCreatureTracker.resetCommand() } + } + event.register("shresetstrayrabbittracker") { + description = "Resets the Stray Rabbit Tracker" + category = CommandCategory.USERS_RESET + callback { ChocolateFactoryStrayTracker.resetCommand() } + } + event.register("shresetexcavatortracker") { + description = "Resets the Fossil Excavator Profit Tracker" + category = CommandCategory.USERS_RESET + callback { ExcavatorProfitTracker.resetCommand() } } - } - @JvmStatic - fun openVisualWords() { - if (!LorenzUtils.onHypixel) { - ChatUtils.userError("You need to join Hypixel to use this feature!") - } else { - if (VisualWordGui.sbeConfigPath.exists()) VisualWordGui.drawImport = true - SkyHanniMod.screenToOpen = VisualWordGui() + // non trackers + event.register("shresetghostcounter") { + description = "Resets the ghost counter" + category = CommandCategory.USERS_RESET + callback { GhostUtil.reset() } + } + event.register("shresetcropspeed") { + description = "Resets garden crop speed data and best crop time data" + category = CommandCategory.USERS_RESET + callback { GardenAPI.resetCropSpeed() } + } + event.register("shresetkismet") { + description = "Resets the saved values of the applied kismet feathers in Croesus" + category = CommandCategory.USERS_RESET + callback { CroesusChestTracker.resetChest() } + } + event.register("shresetburrowwarps") { + description = "Manually resetting disabled diana burrow warp points" + category = CommandCategory.USERS_RESET + callback { BurrowWarpHelper.resetDisabledWarps() } + } + event.register("shresetcontestdata") { + description = "Resets Jacob's Contest Data" + category = CommandCategory.USERS_RESET + callback { SkyHanniDebugsAndTests.resetContestData() } + } + event.register("shresetfarmingitems") { + description = "Resets farming items saved for the Farming Fortune Guide" + category = CommandCategory.USERS_RESET + callback { CaptureFarmingGear.onResetGearCommand() } + } + event.register("shresetmineshaftpitystats") { + description = "Resets the mineshaft pity display stats" + category = CommandCategory.USERS_RESET + callback { MineshaftPityDisplay.fullResetCounter() } + } + event.register("shresetterminal") { + description = "Resets terminal highlights in F7." + category = CommandCategory.USERS_RESET + callback { TerminalInfo.resetTerminals() } + } + event.register("shresetsavedrabbits") { + description = "Resets the saved rabbits on this profile." + category = CommandCategory.USERS_RESET + callback { HoppityCollectionStats.resetSavedRabbits() } + } + event.register("shresetpunchcard") { + description = "Resets the Rift Punchcard Artifact player list." + category = CommandCategory.USERS_RESET + callback { PunchcardHighlight.onResetCommand() } } } - private fun clearFarmingItems() { - val storage = GardenAPI.storage?.fortune ?: return - ChatUtils.chat("clearing farming items") - storage.farmingItems.clear() - storage.outdatedItems.clear() + private fun usersBugFix(event: CommandRegistrationEvent) { + event.register("shupdaterepo") { + description = "Download the SkyHanni repo again" + category = CommandCategory.USERS_BUG_FIX + callback { SkyHanniMod.repo.updateRepo() } + } + event.register("shtogglehypixelapierrors") { + description = "Show/hide hypixel api error messages in chat" + category = CommandCategory.USERS_BUG_FIX + callback { APIUtils.toggleApiErrorMessages() } + } + event.register("shfixminions") { + description = "Removed bugged minion locations from your private island" + category = CommandCategory.USERS_BUG_FIX + callback { MinionFeatures.removeBuggedMinions(isCommand = true) } + } + event.register("shwhereami") { + description = "Print current island in chat" + category = CommandCategory.USERS_BUG_FIX + callback { SkyHanniDebugsAndTests.whereAmI() } + } + event.register("shrendertoggle") { + description = "Disables/enables the rendering of all skyhanni guis." + category = CommandCategory.USERS_BUG_FIX + callback { SkyHanniDebugsAndTests.toggleRender() } + } + event.register("shcarrolyn") { + description = "Toggles if the specified crops effect is active from carrolyn" + category = CommandCategory.USERS_BUG_FIX + callback { CaptureFarmingGear.handelCarrolyn(it) } + } + event.register("shrepostatus") { + description = "Shows the status of all the mods constants" + category = CommandCategory.USERS_BUG_FIX + callback { SkyHanniMod.repo.displayRepoStatus(false) } + } + event.register("shkingfix") { + description = "Resets the local King Talisman Helper offset." + category = CommandCategory.USERS_BUG_FIX + callback { KingTalismanHelper.kingFix() } + } + event.register("shupdate") { + description = "Updates the mod to the specified update stream." + category = CommandCategory.USERS_BUG_FIX + callback { UpdateManager.updateCommand(it) } + } + event.register("shupdatebazaarprices") { + description = "Forcefully updating the bazaar prices right now." + category = CommandCategory.USERS_BUG_FIX + callback { HypixelBazaarFetcher.fetchNow() } + } + event.register("shedittracker") { + description = "Changes the tracked item amount for Diana, Fishing, Pest, Excavator, and Slayer Item Trackers." + category = CommandCategory.USERS_BUG_FIX + callback { TrackerManager.commandEditTracker(it) } + } } - private fun forceUpdate(args: Array) { - val currentStream = SkyHanniMod.feature.about.updateStream.get() - val arg = args.firstOrNull() ?: "current" - val updateStream = when { - arg.equals("(?i)(?:full|release)s?".toRegex()) -> UpdateStream.RELEASES - arg.equals("(?i)(?:beta|latest)s?".toRegex()) -> UpdateStream.BETA - else -> currentStream + private fun devDebug(event: CommandRegistrationEvent) { + event.register("shdebug") { + description = "Copies SkyHanni debug data in the clipboard." + category = CommandCategory.DEVELOPER_DEBUG + callback { DebugCommand.command(it) } } - - val switchingToBeta = updateStream == UpdateStream.BETA && (currentStream != UpdateStream.BETA || !UpdateManager.isCurrentlyBeta()) - if (switchingToBeta) { - ChatUtils.clickableChat( - "Are you sure you want to switch to beta? These versions may be less stable.", - onClick = { - UpdateManager.checkUpdate(true, updateStream) - }, - "§eClick to confirm!", - oneTimeClick = true, - ) - } else { - UpdateManager.checkUpdate(true, updateStream) + event.register("shconfig") { + description = "Searches or resets config elements §c(warning, dangerous!)" + category = CommandCategory.DEVELOPER_DEBUG + callback { SkyHanniConfigSearchResetCommand.command(it) } + } + event.register("shversion") { + description = "Prints the SkyHanni version in the chat" + category = CommandCategory.DEVELOPER_DEBUG + callback { SkyHanniDebugsAndTests.debugVersion() } + } + event.register("shtestbingo") { + description = "Toggle the test bingo card display mode" + category = CommandCategory.DEVELOPER_DEBUG + callback { TestBingo.toggle() } + } + event.register("shprintbingohelper") { + description = "Prints the next step helper for the bingo card" + category = CommandCategory.DEVELOPER_DEBUG + callback { BingoNextStepHelper.command() } + } + event.register("shreloadbingodata") { + description = "Reloads the bingo card data" + category = CommandCategory.DEVELOPER_DEBUG + callback { BingoCardDisplay.command() } + } + event.register("shtestgardenvisitors") { + description = "Test the garden visitor drop statistics" + category = CommandCategory.DEVELOPER_DEBUG + callback { SkyHanniDebugsAndTests.testGardenVisitors() } + } + event.register("shtestcomposter") { + description = "Test the composter overlay" + category = CommandCategory.DEVELOPER_DEBUG + callback { ComposterOverlay.onCommand(it) } + } + event.register("shtestinquisitor") { + description = "Test the inquisitor waypoint share" + category = CommandCategory.DEVELOPER_DEBUG + callback { InquisitorWaypointShare.test() } + } + event.register("shshowcropmoneycalculation") { + description = "Show the calculation of the crop money" + category = CommandCategory.DEVELOPER_DEBUG + callback { CropMoneyDisplay.toggleShowCalculation() } + } + event.register("shcropspeedmeter") { + description = "Debugs how many crops you collect over time" + category = CommandCategory.DEVELOPER_DEBUG + callback { CropSpeedMeter.toggle() } + } + event.register("shworldedit") { + description = "Select regions in the world" + category = CommandCategory.DEVELOPER_DEBUG + callback { WorldEdit.command(it) } + autoComplete { listOf("copy", "reset", "help", "left", "right") } + } + event.register("shtestsackapi") { + description = "Get the amount of an item in sacks according to internal feature SackAPI" + category = CommandCategory.DEVELOPER_DEBUG + callback { SackAPI.testSackAPI(it) } + } + event.register("shtestgriffinspots") { + description = "Show potential griffin spots around you." + category = CommandCategory.DEVELOPER_DEBUG + callback { GriffinBurrowHelper.testGriffinSpots() } + } + event.register("shdebugprice") { + description = "Debug different price sources for an item." + category = CommandCategory.DEVELOPER_DEBUG + callback { ItemPriceUtils.debugItemPrice(it) } + } + event.register("shdebugscoreboard") { + description = + "Monitors the scoreboard changes: " + + "Prints the raw scoreboard lines in the console after each update, with time since last update." + category = CommandCategory.DEVELOPER_DEBUG + callback { ScoreboardData.toggleMonitor() } + } + event.register("shcopyinternalname") { + description = "Copies the internal name of the item in hand to the clipboard." + category = CommandCategory.DEVELOPER_DEBUG + callback { SkyHanniDebugsAndTests.copyItemInternalName() } + } + event.register("shcopylocation") { + description = "Copies the player location as LorenzVec format to the clipboard" + category = CommandCategory.DEVELOPER_DEBUG + callback { SkyHanniDebugsAndTests.copyLocation(it) } + } + event.register("shcopyentities") { + description = "Copies entities in the specified radius around the player to the clipboard" + category = CommandCategory.DEVELOPER_DEBUG + callback { CopyNearbyEntitiesCommand.command(it) } + } + event.register("shcopytablist") { + description = "Copies the tab list data to the clipboard" + category = CommandCategory.DEVELOPER_DEBUG + callback { TabListData.copyCommand(it) } + } + event.register("shcopyactionbar") { + description = "Copies the action bar to the clipboard, including formatting codes" + category = CommandCategory.DEVELOPER_DEBUG + callback { CopyActionBarCommand.command(it) } + } + event.register("shcopyscoreboard") { + description = "Copies the scoreboard data to the clipboard" + category = CommandCategory.DEVELOPER_DEBUG + callback { CopyScoreboardCommand.command(it) } + } + event.register("shcopybossbar") { + description = "Copies the name of the bossbar to the clipboard, including formatting codes" + category = CommandCategory.DEVELOPER_DEBUG + callback { CopyBossbarCommand.command(it) } + } + event.register("shcopyitem") { + description = "Copies information about the item in hand to the clipboard" + category = CommandCategory.DEVELOPER_DEBUG + callback { CopyItemCommand.command() } + } + event.register("shcopyfoundburrowlocations") { + description = "Copy all ever found burrow locations to clipboard" + category = CommandCategory.DEVELOPER_DEBUG + callback { AllBurrowsList.copyToClipboard() } } } - private fun registerCommand(rawName: String, description: String, function: (Array) -> Unit) { - val name = rawName.lowercase() - if (commands.any { it.name == name }) { - error("The command '$name is already registered!'") + @Suppress("LongMethod") + private fun devTest(event: CommandRegistrationEvent) { + event.register("shtest") { + description = "Unused test command." + category = CommandCategory.DEVELOPER_TEST + callback { SkyHanniDebugsAndTests.testCommand(it) } + } + event.register("shchathistory") { + description = "Show the unfiltered chat history" + category = CommandCategory.DEVELOPER_TEST + callback { ChatManager.openChatFilterGUI(it) } + } + event.register("shreloadlocalrepo") { + description = "Reloading the local repo data" + category = CommandCategory.DEVELOPER_TEST + callback { SkyHanniMod.repo.reloadLocalRepo() } + } + event.register("shgraph") { + description = "Enables the graph editor" + category = CommandCategory.DEVELOPER_TEST + callback { GraphEditor.commandIn() } + } + event.register("shrepopatterns") { + description = "See where regexes are loaded from" + category = CommandCategory.DEVELOPER_TEST + callback { RepoPatternGui.open() } + } + event.register("shtestrabbitpaths") { + description = "Tests pathfinding to rabbit eggs. Use a number 0-14." + category = CommandCategory.DEVELOPER_TEST + callback { HoppityEggLocator.testPathfind(it) } + } + event.register("shtestitem") { + description = "test item internal name resolving" + category = CommandCategory.DEVELOPER_TEST + callback { SkyHanniDebugsAndTests.testItemCommand(it) } + } + event.register("shfindnullconfig") { + description = "Find config elements that are null and prints them into the console" + category = CommandCategory.DEVELOPER_TEST + callback { SkyHanniDebugsAndTests.findNullConfig(it) } + } + event.register("shtestwaypoint") { + description = "Set a waypoint on that location" + category = CommandCategory.DEVELOPER_TEST + callback { SkyHanniDebugsAndTests.waypoint(it) } + } + event.register("shtesttablist") { + description = "Set your clipboard as a fake tab list." + category = CommandCategory.DEVELOPER_TEST + callback { TabListData.toggleDebug() } + } + event.register("shstoplisteners") { + description = "Unregistering all loaded forge event listeners" + category = CommandCategory.DEVELOPER_TEST + callback { SkyHanniDebugsAndTests.stopListeners() } + } + event.register("shreloadlisteners") { + description = "Trying to load all forge event listeners again. Might not work at all" + category = CommandCategory.DEVELOPER_TEST + callback { SkyHanniDebugsAndTests.reloadListeners() } + } + event.register("shtracksounds") { + description = "Tracks the sounds for the specified duration (in seconds) and copies it to the clipboard" + category = CommandCategory.DEVELOPER_TEST + callback { TrackSoundsCommand.command(it) } + } + event.register("shtrackparticles") { + description = "Tracks the particles for the specified duration (in seconds) and copies it to the clipboard" + category = CommandCategory.DEVELOPER_TEST + callback { TrackParticlesCommand.command(it) } + } + event.register("shtestpacket") { + description = "Logs incoming and outgoing packets to the console" + category = CommandCategory.DEVELOPER_TEST + callback { PacketTest.command(it) } + } + event.register("shtestmessage") { + description = "Sends a custom chat message client side in the chat" + category = CommandCategory.DEVELOPER_TEST + callback { TestChatCommand.command(it) } + } + event.register("shtestrainbow") { + description = "Sends a rainbow in chat" + category = CommandCategory.DEVELOPER_TEST + callback { ExtendedChatColor.testCommand() } + } + event.register("shpartydebug") { + description = "List persons into the chat SkyHanni thinks are in your party." + category = CommandCategory.DEVELOPER_TEST + callback { PartyAPI.listMembers() } + } + event.register("shplaysound") { + description = "Play the specified sound effect at the given pitch and volume." + category = CommandCategory.DEVELOPER_TEST + callback { SoundUtils.command(it) } + } + event.register("shsendtitle") { + description = "Display a title on the screen with the specified settings." + category = CommandCategory.DEVELOPER_TEST + callback { TitleManager.command(it) } + } + event.register("shresetconfig") { + description = + "Reloads the config manager and rendering processors of MoulConfig. " + + "This §cWILL RESET §7your config, but also updating the java config files " + + "(names, description, orderings and stuff)." + category = CommandCategory.DEVELOPER_TEST + callback { SkyHanniDebugsAndTests.resetConfigCommand() } + } + event.register("shreadcropmilestonefromclipboard") { + description = "Read crop milestone from clipboard. This helps fixing wrong crop milestone data" + category = CommandCategory.DEVELOPER_TEST + callback { GardenCropMilestonesCommunityFix.readDataFromClipboard() } + } + event.register("shaddfoundburrowlocationsfromclipboard") { + description = "Add all ever found burrow locations from clipboard" + category = CommandCategory.DEVELOPER_TEST + callback { AllBurrowsList.addFromClipboard() } + } + event.register("shtoggleegglocationdebug") { + description = "Shows Hoppity egg locations with their internal API names and status." + category = CommandCategory.DEVELOPER_TEST + callback { HoppityEggLocations.toggleDebug() } + } + event.register("shtranslateadvanced") { + description = "Translates a message in an inputted language to another inputted language." + category = CommandCategory.DEVELOPER_TEST + callback { Translator.translateAdvancedCommand(it) } + } + event.register("shconfigsave") { + description = "Manually saving the config" + category = CommandCategory.DEVELOPER_TEST + callback { SkyHanniMod.configManager.saveConfig(ConfigFileType.FEATURES, "manual-command") } + } + event.register("shtestburrow") { + description = "Sets a test burrow waypoint at your location" + category = CommandCategory.DEVELOPER_TEST + callback { GriffinBurrowHelper.setTestBurrow(it) } + } + event.register("shtestisland") { + description = "Sets the current skyblock island for testing purposes." + category = CommandCategory.DEVELOPER_TEST + callback { SkyBlockIslandTest.onCommand(it) } } - ClientCommandHandler.instance.registerCommand(SimpleCommand(name, createCommand(function))) - commands.add(CommandInfo(name, description, currentCategory)) } - private fun registerCommand0( - name: String, - description: String, - function: (Array) -> Unit, - autoComplete: ((Array) -> List) = { listOf() }, - ) { - val command = SimpleCommand( - name, - createCommand(function), - object : SimpleCommand.TabCompleteRunnable { - override fun tabComplete( - sender: ICommandSender?, - args: Array?, - pos: BlockPos?, - ): List { - return autoComplete(args ?: emptyArray()) - } - }, - ) - ClientCommandHandler.instance.registerCommand(command) - commands.add(CommandInfo(name, description, currentCategory)) + private fun internalCommands(event: CommandRegistrationEvent) { + event.register("shaction") { + description = "Internal command for chat click actions" + category = CommandCategory.INTERNAL + callback { ChatClickActionManager.onCommand(it) } + } } - private fun createCommand(function: (Array) -> Unit) = object : SimpleCommand.ProcessCommandRunnable() { - override fun processCommand(sender: ICommandSender?, args: Array?) { - if (args != null) function(args.asList().toTypedArray()) + private fun shortenedCommands(event: CommandRegistrationEvent) { + event.register("pko") { + description = "Kicks offline party members" + category = CommandCategory.SHORTENED_COMMANDS + callback { PartyCommands.kickOffline() } + } + event.register("pw") { + description = "Warps your party" + category = CommandCategory.SHORTENED_COMMANDS + callback { PartyCommands.warp() } + } + event.register("pk") { + description = "Kick a specific party member" + category = CommandCategory.SHORTENED_COMMANDS + callback { PartyCommands.kick(it) } + } + event.register("pt") { + description = "Transfer the party to another party member" + category = CommandCategory.SHORTENED_COMMANDS + callback { PartyCommands.transfer(it) } + } + event.register("pp") { + description = "Promote a specific party member" + category = CommandCategory.SHORTENED_COMMANDS + callback { PartyCommands.promote(it) } + } + event.register("pd") { + description = "Disbands the party" + category = CommandCategory.SHORTENED_COMMANDS + callback { PartyCommands.disband() } + } + event.register("rpt") { + description = "Reverse transfer party to the previous leader" + category = CommandCategory.SHORTENED_COMMANDS + callback { PartyCommands.reverseTransfer() } } } } diff --git a/src/main/java/at/hannibal2/skyhanni/config/commands/SimpleCommand.kt b/src/main/java/at/hannibal2/skyhanni/config/commands/SimpleCommand.kt index b8a5871b77a6..6240b43bf8e5 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/commands/SimpleCommand.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/commands/SimpleCommand.kt @@ -5,47 +5,26 @@ import net.minecraft.command.CommandBase import net.minecraft.command.ICommandSender import net.minecraft.util.BlockPos -class SimpleCommand : CommandBase { - - private val commandName: String - private val runnable: ProcessCommandRunnable - private var tabRunnable: TabCompleteRunnable? = null - - constructor(commandName: String, runnable: ProcessCommandRunnable) { - this.commandName = commandName - this.runnable = runnable - } - - constructor(commandName: String, runnable: ProcessCommandRunnable, tabRunnable: TabCompleteRunnable?) { - this.commandName = commandName - this.runnable = runnable - this.tabRunnable = tabRunnable - } - - abstract class ProcessCommandRunnable { - - abstract fun processCommand(sender: ICommandSender?, args: Array?) - } - - interface TabCompleteRunnable { - - fun tabComplete(sender: ICommandSender?, args: Array?, pos: BlockPos?): List - } +class SimpleCommand( + private val name: String, + private val aliases: List, + private val callback: (Array) -> Unit, + private val tabCallback: ((Array) -> List) = { emptyList() }, +) : CommandBase() { override fun canCommandSenderUseCommand(sender: ICommandSender) = true - - override fun getCommandName() = commandName - - override fun getCommandUsage(sender: ICommandSender) = "/$commandName" + override fun getCommandName() = name + override fun getCommandAliases() = aliases + override fun getCommandUsage(sender: ICommandSender) = "/$name" override fun processCommand(sender: ICommandSender, args: Array) { try { - runnable.processCommand(sender, args) + callback(args) } catch (e: Throwable) { - ErrorManager.logErrorWithData(e, "Error while running command /$commandName") + ErrorManager.logErrorWithData(e, "Error while running command /$name") } } override fun addTabCompletionOptions(sender: ICommandSender, args: Array, pos: BlockPos) = - if (tabRunnable != null) tabRunnable!!.tabComplete(sender, args, pos) else null + tabCallback(args).takeIf { it.isNotEmpty() } } diff --git a/src/main/java/at/hannibal2/skyhanni/config/core/elements/GuiElement.kt b/src/main/java/at/hannibal2/skyhanni/config/core/elements/GuiElement.kt new file mode 100644 index 000000000000..e823dc52175f --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/core/elements/GuiElement.kt @@ -0,0 +1,20 @@ +package at.hannibal2.skyhanni.config.core.elements + +import net.minecraft.client.gui.Gui + +@Suppress("EmptyFunctionBlock", "UnusedParameter") +abstract class GuiElement : Gui() { + abstract fun render(x: Int, y: Int) + + abstract val width: Int + + abstract val height: Int + + open fun mouseClicked(mouseX: Int, mouseY: Int, mouseButton: Int) {} + + fun mouseClickMove(mouseX: Int, mouseY: Int, clickedMouseButton: Int, timeSinceLastClick: Long) {} + + fun otherComponentClick() {} + + fun keyTyped(typedChar: Char, keyCode: Int) {} +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/core/elements/GuiElementButton.kt b/src/main/java/at/hannibal2/skyhanni/config/core/elements/GuiElementButton.kt new file mode 100644 index 000000000000..504171ac418f --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/core/elements/GuiElementButton.kt @@ -0,0 +1,22 @@ +package at.hannibal2.skyhanni.config.core.elements + +import java.awt.Color + +class GuiElementButton(text: String, colour: Int, private val callback: Runnable) : GuiElementText(text, colour) { + + override val height: Int + get() = super.height + 5 + + override val width: Int + get() = super.width + 10 + + override fun mouseClicked(mouseX: Int, mouseY: Int, mouseButton: Int) { + callback.run() + } + + override fun render(x: Int, y: Int) { + drawRect(x, y, x + width, y + super.height, Color.WHITE.rgb) + drawRect(x + 1, y + 1, x + width - 1, y + super.height - 1, Color.BLACK.rgb) + super.render(x + 5, y - 1) + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/core/elements/GuiElementText.kt b/src/main/java/at/hannibal2/skyhanni/config/core/elements/GuiElementText.kt new file mode 100644 index 000000000000..541edc49bf0d --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/core/elements/GuiElementText.kt @@ -0,0 +1,21 @@ +package at.hannibal2.skyhanni.config.core.elements + +import net.minecraft.client.Minecraft + +open class GuiElementText(var text: String, private val colour: Int) : GuiElement() { + + override val height: Int + get() = 18 + + override val width: Int + get() { + val fr = Minecraft.getMinecraft().fontRendererObj + return fr.getStringWidth(text) + } + + override fun render(x: Int, y: Int) { + val fr = Minecraft.getMinecraft().fontRendererObj + + fr.drawString(text, x, y + 6, colour) + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/chat/FilterTypesConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/chat/FilterTypesConfig.java index c50a04bae2b6..ae41eae19e94 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/chat/FilterTypesConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/chat/FilterTypesConfig.java @@ -13,6 +13,11 @@ public class FilterTypesConfig { @Accordion public PowderMiningFilterConfig powderMiningFilter = new PowderMiningFilterConfig(); + @Expose + @ConfigOption(name = "Stash Messages", desc = "") + @Accordion + public StashConfig stashMessages = new StashConfig(); + @Expose @ConfigOption(name = "Hypixel Lobbies", desc = "Hide announcements in Hypixel lobbies " + "(player joins, loot boxes, prototype lobby messages, radiating generosity, Hypixel tournaments)") diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/chat/StashConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/chat/StashConfig.java new file mode 100644 index 000000000000..92fdd8c4405d --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/chat/StashConfig.java @@ -0,0 +1,31 @@ +package at.hannibal2.skyhanni.config.features.chat; + +import at.hannibal2.skyhanni.config.FeatureToggle; +import com.google.gson.annotations.Expose; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorSlider; +import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; + +public class StashConfig { + + @Expose + @ConfigOption(name = "Stash Warnings", desc = "Compact warnings relating to items/materials in your stash.") + @ConfigEditorBoolean + @FeatureToggle + public boolean enabled = true; + + @Expose + @ConfigOption(name = "Hide Duplicate Warnings", desc = "Hide duplicate warnings for previously reported stash counts.") + @ConfigEditorBoolean + public boolean hideDuplicateCounts = true; + + @Expose + @ConfigOption(name = "Hide Low Warnings", desc = "Hide warnings with a total count below this number.") + @ConfigEditorSlider(minValue = 0, maxValue = 1000000, minStep = 100) + public int hideLowWarningsThreshold = 0; + + @Expose + @ConfigOption(name = "Use /ViewStash", desc = "Use /viewstash [type] instead of /pickupstash.") + @ConfigEditorBoolean + public boolean useViewStash = false; +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/dungeon/DungeonConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/dungeon/DungeonConfig.java index ec2bc0c4b0f9..0be6c1e853f0 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/dungeon/DungeonConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/dungeon/DungeonConfig.java @@ -138,6 +138,12 @@ public class DungeonConfig { @FeatureToggle public boolean shadowAssassinJumpNotifier = false; + @Expose + @ConfigOption(name = "Terminal Waypoints", desc = "Displays Waypoints in the F7/M7 Goldor Phase.") + @ConfigEditorBoolean + @FeatureToggle + public boolean terminalWaypoints = false; + @Expose @ConfigOption(name = "Dungeon Races Guide", desc = "") @Accordion diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityCallWarningConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityCallWarningConfig.java index 6e4ccf027305..0406b268d8b8 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityCallWarningConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityCallWarningConfig.java @@ -7,6 +7,7 @@ import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorButton; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorColour; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorKeybind; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorSlider; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorText; import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; import io.github.notenoughupdates.moulconfig.observer.Property; @@ -44,4 +45,14 @@ public class HoppityCallWarningConfig { @ConfigOption(name = "Sounds", desc = "Click to open the list of available sounds.") @ConfigEditorButton(buttonText = "OPEN") public Runnable sounds = () -> OSUtils.openBrowser("https://www.minecraftforum.net/forums/mapping-and-modding-java-edition/mapping-and-modding-tutorials/2213619-1-8-all-playsound-sound-arguments"); + + @Expose + @ConfigOption(name = "Ensure Coins Pre-Trade", desc = "Block opening Hoppity's abiphone trade menu if you do not have enough coins in your purse.") + @ConfigEditorBoolean + public boolean ensureCoins = true; + + @Expose + @ConfigOption(name = "Coin Threshold", desc = "The amount of coins you need to have in your purse to be able to open Hoppity's abiphone trade menu.") + @ConfigEditorSlider(minValue = 250000, maxValue = 5000000, minStep = 250000) + public int coinThreshold = 5000000; } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityEggsConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityEggsConfig.java index 3fd83db69655..f34959bd8a97 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityEggsConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityEggsConfig.java @@ -24,6 +24,11 @@ public class HoppityEggsConfig { @Accordion public HoppityEventSummaryConfig eventSummary = new HoppityEventSummaryConfig(); + @Expose + @ConfigOption(name = "Warp Menu", desc = "") + @Accordion + public HoppityWarpMenuConfig warpMenu = new HoppityWarpMenuConfig(); + @Expose @ConfigOption(name = "Hoppity Waypoints", desc = "Toggle guess waypoints for Hoppity's Hunt.") @ConfigEditorBoolean @@ -213,13 +218,8 @@ public String toString() { public boolean petWarning = false; @Expose - @ConfigOption(name = "Show uniques in Warp Menu", desc = "Shows your unique eggs in the Warp Menu during the hoppity event.") + @ConfigOption(name = "Prevent Missing Fish the Rabbit", desc = "Prevent closing a Meal Egg's inventory if Fish the Rabbit is present.") @ConfigEditorBoolean @FeatureToggle - public boolean uniquesWarpMenu = true; - - @Expose - @ConfigOption(name = "Hide when maxed", desc = "Stops the above feature from working when the island is complete.") - @ConfigEditorBoolean - public boolean uniquesWarpMenuHideMax = true; + public boolean preventMissingFish = true; } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityWarpMenuConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityWarpMenuConfig.java new file mode 100644 index 000000000000..680b2918e876 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/event/hoppity/HoppityWarpMenuConfig.java @@ -0,0 +1,20 @@ +package at.hannibal2.skyhanni.config.features.event.hoppity; + +import at.hannibal2.skyhanni.config.FeatureToggle; +import com.google.gson.annotations.Expose; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; +import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; + +public class HoppityWarpMenuConfig { + + @Expose + @ConfigOption(name = "Show uniques in Warp Menu", desc = "Shows your unique eggs in the Warp Menu during the hoppity event.") + @ConfigEditorBoolean + @FeatureToggle + public boolean enabled = true; + + @Expose + @ConfigOption(name = "Hide when maxed", desc = "Stops the above feature from working when the island is complete.") + @ConfigEditorBoolean + public boolean hideWhenMaxed = true; +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/fishing/BarnTimerConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/fishing/BarnTimerConfig.java index d62d066e590f..d06cee6d329f 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/fishing/BarnTimerConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/fishing/BarnTimerConfig.java @@ -21,6 +21,14 @@ public class BarnTimerConfig { @FeatureToggle public Property enabled = Property.of(true); + @Expose + @ConfigOption( + name = "Show Anywhere", + desc = "Show the Barn Fishing Timer whenever you fish up a sea creature, regardless of location." + ) + @ConfigEditorBoolean + public boolean showAnywhere = false; + @Expose @ConfigOption( name = "Worm Fishing", diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/garden/FarmingFortuneConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/garden/FarmingFortuneConfig.java index 6eb4660d6010..a1cb92be0269 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/garden/FarmingFortuneConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/garden/FarmingFortuneConfig.java @@ -1,8 +1,8 @@ package at.hannibal2.skyhanni.config.features.garden; import at.hannibal2.skyhanni.config.FeatureToggle; -import at.hannibal2.skyhanni.config.commands.Commands; import at.hannibal2.skyhanni.config.core.config.Position; +import at.hannibal2.skyhanni.features.garden.fortuneguide.FFGuideGUI; import com.google.gson.annotations.Expose; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorButton; @@ -21,7 +21,7 @@ public class FarmingFortuneConfig { @ConfigOption(name = "Farming Fortune Guide", desc = "Open a guide that breaks down your Farming Fortune.\n§eCommand: /ff") @ConfigEditorButton(buttonText = "Open") - public Runnable open = Commands::openFortuneGuide; + public Runnable open = FFGuideGUI::onCommand; @Expose @ConfigLink(owner = FarmingFortuneConfig.class, field = "display") diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/gui/ModifyWordsConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/gui/ModifyWordsConfig.java index 21cfee5c5c74..5a0db7ac4535 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/gui/ModifyWordsConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/gui/ModifyWordsConfig.java @@ -1,7 +1,7 @@ package at.hannibal2.skyhanni.config.features.gui; import at.hannibal2.skyhanni.config.FeatureToggle; -import at.hannibal2.skyhanni.config.commands.Commands; +import at.hannibal2.skyhanni.features.misc.visualwords.VisualWordGui; import com.google.gson.annotations.Expose; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorButton; @@ -17,6 +17,6 @@ public class ModifyWordsConfig { @ConfigOption(name = "Open Config", desc = "Open the menu to setup the visual words.\n§eCommand: /shwords") @ConfigEditorButton(buttonText = "Open") - public Runnable open = Commands::openVisualWords; + public Runnable open = VisualWordGui::onCommand; } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/ChunkedStatsConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/ChunkedStatsConfig.java index 4293dd168f8b..8e0941d30198 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/ChunkedStatsConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/ChunkedStatsConfig.java @@ -1,6 +1,6 @@ package at.hannibal2.skyhanni.config.features.gui.customscoreboard; -import at.hannibal2.skyhanni.features.gui.customscoreboard.ChunkedStat; +import at.hannibal2.skyhanni.features.gui.customscoreboard.ChunkedStatsLine; import com.google.gson.annotations.Expose; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDraggableList; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorSlider; @@ -17,7 +17,7 @@ public class ChunkedStatsConfig { desc = "Select the stats you want to display chunked on the scoreboard." ) @ConfigEditorDraggableList - public List chunkedStats = new ArrayList<>(ChunkedStat.getEntries()); + public List chunkedStats = new ArrayList<>(ChunkedStatsLine.getEntries()); @Expose @ConfigOption( diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/CustomScoreboardConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/CustomScoreboardConfig.java index 38a749f35029..944b44cd4a86 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/CustomScoreboardConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/CustomScoreboardConfig.java @@ -2,7 +2,8 @@ import at.hannibal2.skyhanni.config.FeatureToggle; import at.hannibal2.skyhanni.config.core.config.Position; -import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardElement; +import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard; +import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardConfigElement; import com.google.gson.annotations.Expose; import io.github.notenoughupdates.moulconfig.annotations.Accordion; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; @@ -28,17 +29,14 @@ public class CustomScoreboardConfig { @Expose @ConfigOption( name = "Appearance", - desc = "Drag text to change the appearance of the advanced scoreboard." // supporting both custom & advanced search + desc = "Drag text to change the appearance of the advanced scoreboard." ) - @ConfigEditorDraggableList() - public List scoreboardEntries = new ArrayList<>(ScoreboardElement.defaultOption); + @ConfigEditorDraggableList + public Property> scoreboardEntries = Property.of(new ArrayList<>(ScoreboardConfigElement.defaultOptions)); @ConfigOption(name = "Reset Appearance", desc = "Reset the appearance of the advanced scoreboard.") @ConfigEditorButton(buttonText = "Reset") - public Runnable reset = () -> { - scoreboardEntries.clear(); - scoreboardEntries.addAll(ScoreboardElement.defaultOption); - }; + public Runnable reset = CustomScoreboard::resetAppearance; @Expose @ConfigOption(name = "Display Options", desc = "") @@ -56,7 +54,11 @@ public class CustomScoreboardConfig { public InformationFilteringConfig informationFiltering = new InformationFilteringConfig(); @Expose - @ConfigOption(name = "Unknown Lines warning", desc = "Give a chat warning when unknown lines are found in the scoreboard.") + @ConfigOption( + name = "Unknown Lines warning", + desc = "Give a chat warning when unknown lines are found in the scoreboard." + + "\n§cReporting these in the Discord Server are very important, so we can know what lines are missing." + ) @ConfigEditorBoolean public boolean unknownLinesWarning = true; diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/DisplayConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/DisplayConfig.java index 2f0eb502e509..39d8c09bfd7a 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/DisplayConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/DisplayConfig.java @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.config.features.gui.customscoreboard; import at.hannibal2.skyhanni.config.FeatureToggle; +import at.hannibal2.skyhanni.utils.RenderUtils; import com.google.gson.annotations.Expose; import io.github.notenoughupdates.moulconfig.annotations.Accordion; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; @@ -51,7 +52,6 @@ public class DisplayConfig { @Accordion public TitleAndFooterConfig titleAndFooter = new TitleAndFooterConfig(); - @Expose @ConfigOption(name = "Hide Vanilla Scoreboard", desc = "Hide the vanilla scoreboard.\n" + "§cMods that add their own scoreboard will not be affected by this setting!") @@ -145,8 +145,16 @@ public String toString() { public int lineSpacing = 10; @Expose - @ConfigOption(name = "Cache Scoreboard on Island Switch", - desc = "Will stop the Scoreboard from updating while switching islands.\nRemoves the shaking when loading data.") + @ConfigOption(name = "Text Alignment", desc = "Will align the text to the left, center or right, while not overriding certain lines, like title or footer.") + @ConfigEditorDropdown + public RenderUtils.HorizontalAlignment textAlignment = RenderUtils.HorizontalAlignment.LEFT; + + @Expose + @ConfigOption( + name = "Cache Scoreboard on Island Switch", + desc = "Will stop the Scoreboard from updating while switching islands.\n" + + "Removes the shaking when loading data." + ) @ConfigEditorBoolean public boolean cacheScoreboardOnIslandSwitch = false; } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/EventsConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/EventsConfig.java index e2663bf55c29..b091c8e90fee 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/EventsConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/EventsConfig.java @@ -1,11 +1,12 @@ package at.hannibal2.skyhanni.config.features.gui.customscoreboard; -import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardEvent; +import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardConfigEventElement; import com.google.gson.annotations.Expose; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorButton; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDraggableList; import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; +import io.github.notenoughupdates.moulconfig.observer.Property; import java.util.ArrayList; import java.util.List; @@ -18,13 +19,15 @@ public class EventsConfig { desc = "Drag your list to select the priority of each event." ) @ConfigEditorDraggableList() - public List eventEntries = new ArrayList<>(ScoreboardEvent.defaultOption); + public Property> eventEntries = Property.of(new ArrayList<>(ScoreboardConfigEventElement.defaultOption)); @ConfigOption(name = "Reset Events Priority", desc = "Reset the priority of all events.") @ConfigEditorButton(buttonText = "Reset") + // TODO move into kotlin public Runnable reset = () -> { - eventEntries.clear(); - eventEntries.addAll(ScoreboardEvent.defaultOption); + eventEntries.get().clear(); + eventEntries.get().addAll(ScoreboardConfigEventElement.defaultOption); + eventEntries.notifyObservers(); }; @Expose diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/PartyConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/PartyConfig.java index 670e9b16b7f5..5a553369f37c 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/PartyConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/PartyConfig.java @@ -11,7 +11,7 @@ public class PartyConfig { @ConfigOption(name = "Max Party List", desc = "Max number of party members to show in the party list (you are not included).") @ConfigEditorSlider( minValue = 1, - maxValue = 25, // why do I even set it so high + maxValue = 25, minStep = 1 ) public Property maxPartyList = Property.of(4); @@ -21,4 +21,9 @@ public class PartyConfig { "If disabled, it will only show in Dungeon Hub, Crimson Isle & Kuudra.") @ConfigEditorBoolean public boolean showPartyEverywhere = false; + + @Expose + @ConfigOption(name = "Show Party Leader", desc = "Show the party leader in the party list.") + @ConfigEditorBoolean + public boolean showPartyLeader = true; } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/TitleAndFooterConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/TitleAndFooterConfig.java index 1c3bb4304509..aae9fe026376 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/TitleAndFooterConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/gui/customscoreboard/TitleAndFooterConfig.java @@ -6,21 +6,19 @@ import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDropdown; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorText; import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; -import io.github.notenoughupdates.moulconfig.observer.Property; public class TitleAndFooterConfig { @Expose - @ConfigOption(name = "Title and Footer Alignment", desc = "Align the title and footer in the scoreboard.") + @ConfigOption(name = "Title Alignment", desc = "Align the title in the scoreboard.") @ConfigEditorDropdown - // TODO rename to "horizontalAlignment" or "alignment" - public RenderUtils.HorizontalAlignment alignTitleAndFooter = RenderUtils.HorizontalAlignment.CENTER; + public RenderUtils.HorizontalAlignment alignTitle = RenderUtils.HorizontalAlignment.CENTER; @Expose @ConfigOption(name = "Custom Title", desc = "What should be displayed as the title of the scoreboard." + - "\nUse & for colors." + + "\nUse && for colors." + "\nUse \"\\n\" for new line.") @ConfigEditorText - public Property customTitle = Property.of("&6&lSKYBLOCK"); + public String customTitle = "&&6&&lSKYBLOCK"; @Expose @ConfigOption(name = "Use Custom Title", desc = "Use a custom title instead of the default Hypixel title.") @@ -32,10 +30,22 @@ public class TitleAndFooterConfig { @ConfigEditorBoolean public boolean useCustomTitleOutsideSkyBlock = false; + @Expose + @ConfigOption(name = "Footer Alignment", desc = "Align the footer in the scoreboard.") + @ConfigEditorDropdown + public RenderUtils.HorizontalAlignment alignFooter = RenderUtils.HorizontalAlignment.LEFT; + @Expose @ConfigOption(name = "Custom Footer", desc = "What should be displayed as the footer of the scoreboard." + - "\nUse & for colors." + + "\nUse && for colors." + + "\nUse \"\\n\" for new line.") + @ConfigEditorText + public String customFooter = "&&ewww.hypixel.net"; + + @Expose + @ConfigOption(name = "Custom Alpha Footer", desc = "What should be displayed as the footer of the scoreboard when on the Alpha Server." + + "\nUse && for colors." + "\nUse \"\\n\" for new line.") @ConfigEditorText - public Property customFooter = Property.of("&ewww.hypixel.net"); + public String customAlphaFooter = "&&ealpha.hypixel.net"; } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/chocolatefactory/ChocolateFactoryConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/chocolatefactory/ChocolateFactoryConfig.java index 5d1c63f8d7e1..93d7d6f61223 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/chocolatefactory/ChocolateFactoryConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/chocolatefactory/ChocolateFactoryConfig.java @@ -232,6 +232,12 @@ public class ChocolateFactoryConfig { @FeatureToggle public boolean mythicRabbitRequirement = false; + @Expose + @ConfigOption(name = "Booster Cookie", desc = "Blocks running /cf without a §6§lBooster Cookie §7active.") + @ConfigEditorBoolean + @FeatureToggle + public boolean boosterCookieRequirement = false; + @Expose @ConfigOption(name = "Stray Tracker", desc = "Track stray rabbits found in the Chocolate Factory menu.") @ConfigEditorBoolean diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/mining/FlowstateHelperConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/mining/FlowstateHelperConfig.java new file mode 100644 index 000000000000..03f2c01fb0bc --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/mining/FlowstateHelperConfig.java @@ -0,0 +1,47 @@ +package at.hannibal2.skyhanni.config.features.mining; + +import at.hannibal2.skyhanni.config.FeatureToggle; +import at.hannibal2.skyhanni.config.core.config.Position; +import at.hannibal2.skyhanni.features.mining.FlowstateElements; +import com.google.gson.annotations.Expose; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDraggableList; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorSlider; +import io.github.notenoughupdates.moulconfig.annotations.ConfigLink; +import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; +import io.github.notenoughupdates.moulconfig.annotations.SearchTag; + +import java.util.ArrayList; +import java.util.List; + +public class FlowstateHelperConfig { + @Expose + @ConfigOption(name = "Enabled", desc = "Shows stats for the Flowstate enchantment on Mining Tools.") + @ConfigEditorBoolean + @FeatureToggle + public boolean enabled = false; + + @Expose + @ConfigOption(name = "Appearance", desc = "Drag text to change the appearance.") + @ConfigEditorDraggableList() + public List appearance = new ArrayList<>(FlowstateElements.defaultOption); + + @Expose + @ConfigOption(name = "Dynamic Color", desc = "Makes the timer's color dynamic.") + @ConfigEditorBoolean + public boolean colorfulTimer = false; + + @Expose + @ConfigOption(name = "Auto Hide", desc = "Automatically hides the GUI after being idle, in seconds.") + @SearchTag("autohide") + @ConfigEditorSlider( + minValue = -1, + maxValue = 30, + minStep = 1 + ) + public int autoHide = 10; + + @Expose + @ConfigLink(owner = FlowstateHelperConfig.class, field = "enabled") + public Position position = new Position(-110 , 9); +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningConfig.java index f6a5a83baca6..7879eb7816bd 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/mining/MiningConfig.java @@ -78,6 +78,11 @@ public class MiningConfig { @Accordion public CrystalHighlighterConfig crystalHighlighter = new CrystalHighlighterConfig(); + @Expose + @ConfigOption(name = "Flowstate Helper", desc = "") + @Accordion + public FlowstateHelperConfig flowstateHelper = new FlowstateHelperConfig(); + @Expose @ConfigOption(name = "Highlight Commission Mobs", desc = "Highlight mobs that are part of active commissions.") @ConfigEditorBoolean @@ -102,6 +107,11 @@ public class MiningConfig { @FeatureToggle public boolean highlightYourGoldenGoblin = true; + @Expose + @ConfigOption(name = "Line to your Golden Goblin", desc = "Also makes a line to your goblin. §eNeeds the option above to work.") + @ConfigEditorBoolean + public boolean lineToYourGoldenGoblin = false; + @Expose @ConfigOption(name = "Precision Mining Helper", desc = "Draws a box over the Precision Mining particles.") @ConfigEditorBoolean diff --git a/src/main/java/at/hannibal2/skyhanni/data/BitsAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/BitsAPI.kt index e9e58fa463d3..022a18d926e3 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/BitsAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/BitsAPI.kt @@ -68,7 +68,8 @@ object BitsAPI { private val bitsFromFameRankUpChatPattern by bitsChatGroup.pattern( "rankup.bits", - "§eYou gained §3(?.*) Bits Available §ecompounded from all your §epreviously eaten §6cookies§e! Click here to open §6cookie menu§e!", + "§eYou gained §3(?.*) Bits Available §ecompounded from all your " + + "§epreviously eaten §6cookies§e! Click here to open §6cookie menu§e!", ) private val fameRankUpPattern by bitsChatGroup.pattern( diff --git a/src/main/java/at/hannibal2/skyhanni/data/BossbarData.kt b/src/main/java/at/hannibal2/skyhanni/data/BossbarData.kt index 77daa26011a2..d63b2aefd1b1 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/BossbarData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/BossbarData.kt @@ -12,7 +12,7 @@ object BossbarData { private var bossbar: String? = null private var previousServerBossbar = "" - fun getBossbar() = bossbar ?: "" + fun getBossbar() = bossbar.orEmpty() @SubscribeEvent fun onWorldChange(event: LorenzWorldChangeEvent) { diff --git a/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt b/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt index 965b4af578b8..8780561921af 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt @@ -38,7 +38,9 @@ object ChatManager { private val loggerFilteredTypes = mutableMapOf() private val messageHistory = object : LinkedHashMap, MessageFilteringResult>() { - override fun removeEldestEntry(eldest: MutableMap.MutableEntry, MessageFilteringResult>?): Boolean { + override fun removeEldestEntry( + eldest: MutableMap.MutableEntry, MessageFilteringResult>?, + ): Boolean { return size > 100 } } diff --git a/src/main/java/at/hannibal2/skyhanni/data/EntityData.kt b/src/main/java/at/hannibal2/skyhanni/data/EntityData.kt index d2f81a6d8191..04147ce7794c 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/EntityData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/EntityData.kt @@ -5,9 +5,9 @@ import at.hannibal2.skyhanni.events.EntityHealthUpdateEvent import at.hannibal2.skyhanni.events.EntityMaxHealthUpdateEvent import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent -import at.hannibal2.skyhanni.events.SecondPassedEvent import at.hannibal2.skyhanni.events.entity.EntityDisplayNameEvent import at.hannibal2.skyhanni.events.entity.EntityHealthDisplayEvent +import at.hannibal2.skyhanni.events.entity.EntityLeaveWorldEvent import at.hannibal2.skyhanni.events.minecraft.packet.PacketReceivedEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.EntityUtils @@ -31,27 +31,35 @@ import kotlin.time.Duration.Companion.milliseconds @SkyHanniModule object EntityData { - private val maxHealthMap = mutableMapOf() + private val maxHealthMap = mutableMapOf() private val nametagCache = TimeLimitedCache(50.milliseconds) private val healthDisplayCache = TimeLimitedCache(50.milliseconds) + private val ignoredEntities = setOf( + EntityArmorStand::class.java, + EntityXPOrb::class.java, + EntityItem::class.java, + EntityItemFrame::class.java, + EntityOtherPlayerMP::class.java, + EntityPlayerSP::class.java, + ) + @SubscribeEvent fun onTick(event: LorenzTickEvent) { - for (entity in EntityUtils.getEntities()) { + for (entity in EntityUtils.getEntities()) { // this completely ignores the ignored entities list? val maxHealth = entity.baseMaxHealth - val oldMaxHealth = maxHealthMap.getOrDefault(entity, -1) + val id = entity.entityId + val oldMaxHealth = maxHealthMap.getOrDefault(id, -1) if (oldMaxHealth != maxHealth) { - maxHealthMap[entity] = maxHealth + maxHealthMap[id] = maxHealth EntityMaxHealthUpdateEvent(entity, maxHealth.derpy()).postAndCatch() } } } - @SubscribeEvent - fun onSecondPassed(event: SecondPassedEvent) { - if (event.repeatSeconds(30)) { - maxHealthMap.keys.removeIf { it.isDead } - } + @HandleEvent + fun onEntityLeaveWorld(event: EntityLeaveWorldEvent) { + maxHealthMap -= event.entity.entityId } @SubscribeEvent @@ -69,26 +77,11 @@ object EntityData { val entityId = packet.entityId val entity = EntityUtils.getEntityByID(entityId) ?: return - if (entity is EntityArmorStand) return - if (entity is EntityXPOrb) return - if (entity is EntityItem) return - if (entity is EntityItemFrame) return - - if (entity is EntityOtherPlayerMP) return - if (entity is EntityPlayerSP) return - - for (watchableObject in watchableObjects) { - - val dataValueId = watchableObject.dataValueId - val any = watchableObject.`object` - if (dataValueId != 6) continue - - val health = (any as Float).toInt() - - if (entity is EntityWither && health == 300 && entityId < 0) { - return - } + if (entity.javaClass in ignoredEntities) return + watchableObjects.find { it.dataValueId == 6 }?.let { + val health = (it.`object` as Float).toInt() + if (entity is EntityWither && health == 300 && entityId < 0) return if (entity is EntityLivingBase) { EntityHealthUpdateEvent(entity, health.derpy()).postAndCatch() } @@ -100,6 +93,11 @@ object EntityData { return postRenderNametag(entity, oldValue) } + @JvmStatic + fun despawnEntity(entity: Entity) { + EntityLeaveWorldEvent(entity).post() + } + private fun postRenderNametag(entity: Entity, chatComponent: ChatComponentText) = nametagCache.getOrPut(entity) { val event = EntityDisplayNameEvent(entity, chatComponent) event.postAndCatch() diff --git a/src/main/java/at/hannibal2/skyhanni/data/EntityMovementData.kt b/src/main/java/at/hannibal2/skyhanni/data/EntityMovementData.kt index d38b6824b864..83fb0f8cf28e 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/EntityMovementData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/EntityMovementData.kt @@ -4,8 +4,8 @@ import at.hannibal2.skyhanni.events.EntityMoveEvent import at.hannibal2.skyhanni.events.IslandChangeEvent import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.events.LorenzTickEvent -import at.hannibal2.skyhanni.events.LorenzWarpEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent +import at.hannibal2.skyhanni.events.SkyHanniWarpEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.DelayedRun import at.hannibal2.skyhanni.utils.LorenzUtils @@ -104,7 +104,7 @@ object EntityMovementData { if (!LorenzUtils.inSkyBlock) return if (!warpingPattern.matches(event.message)) return DelayedRun.runNextTick { - LorenzWarpEvent().postAndCatch() + SkyHanniWarpEvent.post() } } diff --git a/src/main/java/at/hannibal2/skyhanni/data/EventCounter.kt b/src/main/java/at/hannibal2/skyhanni/data/EventCounter.kt index 6e308c18965f..67aec45cb1f5 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/EventCounter.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/EventCounter.kt @@ -15,7 +15,7 @@ object EventCounter { private val config get() = SkyHanniMod.feature.dev.debug - private var map = mutableMapOf() + private val map = mutableMapOf() private var lastUpdate = SimpleTimeMark.farPast() private var enabled = false diff --git a/src/main/java/at/hannibal2/skyhanni/data/GardenCropMilestones.kt b/src/main/java/at/hannibal2/skyhanni/data/GardenCropMilestones.kt index 5e236c4c5f64..d8fab21f44cf 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/GardenCropMilestones.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/GardenCropMilestones.kt @@ -51,7 +51,7 @@ object GardenCropMilestones { crop.setCounter(amount) } } - CropMilestoneUpdateEvent().postAndCatch() + CropMilestoneUpdateEvent.post() GardenCropMilestonesCommunityFix.openInventory(event.inventoryItems) } diff --git a/src/main/java/at/hannibal2/skyhanni/data/GardenCropMilestonesCommunityFix.kt b/src/main/java/at/hannibal2/skyhanni/data/GardenCropMilestonesCommunityFix.kt index 691a3c8e262b..4eaf3137e61a 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/GardenCropMilestonesCommunityFix.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/GardenCropMilestonesCommunityFix.kt @@ -87,39 +87,17 @@ object GardenCropMilestonesCommunityFix { val lore = stack.getLore() val next = lore.nextAfter({ GardenCropMilestones.totalPattern.matches(it) }, 3) ?: return - val total = lore.nextAfter({ GardenCropMilestones.totalPattern.matches(it) }, 6) ?: return - -// debug(" ") -// debug("crop: $crop") -// debug("realTier: $realTier") val guessNextMax = nextMax(realTier, crop) - // debug("guessNextMax: ${guessNextMax.addSeparators()}") val nextMax = amountPattern.matchMatcher(next) { group("max").formatLong() } ?: return -// debug("nextMax real: ${nextMax.addSeparators()}") + if (nextMax != guessNextMax) { -// debug("wrong, add to list") wrongData.add("$crop:$realTier:${nextMax.addSeparators()}") } - - val guessTotalMax = GardenCropMilestones.getCropsForTier(46, crop) // no need to overflow here -// println("guessTotalMax: ${guessTotalMax.addSeparators()}") - val totalMax = amountPattern.matchMatcher(total) { - group("max").formatLong() - } ?: return -// println("totalMax real: ${totalMax.addSeparators()}") - val totalOffBy = guessTotalMax - totalMax -// debug("$crop total offf by: ${totalOffBy.addSeparators()}") } - // fun debug(message: String) { -// if (SkyHanniMod.feature.dev.debug.enabled) { -// println(message) -// } -// } - /** * This helps to fix wrong crop milestone data * This command reads the clipboard content, diff --git a/src/main/java/at/hannibal2/skyhanni/data/GuiData.kt b/src/main/java/at/hannibal2/skyhanni/data/GuiData.kt index 5f2ca510bfef..688f8cc18c08 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/GuiData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/GuiData.kt @@ -24,7 +24,7 @@ object GuiData { var preDrawEventCancelled = false - @SubscribeEvent(priority = EventPriority.HIGH) + @HandleEvent(priority = HandleEvent.HIGH) fun onNeuRenderEvent(event: NEURenderEvent) { if (preDrawEventCancelled) event.cancel() } diff --git a/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt b/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt index e6dfa7671529..010267609ad4 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt @@ -37,8 +37,8 @@ object GuiEditManager { private var lastHotkeyPressed = SimpleTimeMark.farPast() - private var currentPositions = TimeLimitedCache(15.seconds) - private var currentBorderSize = mutableMapOf>() + private val currentPositions = TimeLimitedCache(15.seconds) + private val currentBorderSize = mutableMapOf>() private var lastMovedGui: String? = null @SubscribeEvent diff --git a/src/main/java/at/hannibal2/skyhanni/data/GuildAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/GuildAPI.kt index 1e98b61e424a..81d2da77fe68 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/GuildAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/GuildAPI.kt @@ -40,5 +40,5 @@ object GuildAPI { fun isInGuild(name: String) = name in getAllMembers() - fun getAllMembers() = ProfileStorageData.playerSpecific?.guildMembers ?: emptyList() + fun getAllMembers() = ProfileStorageData.playerSpecific?.guildMembers.orEmpty() } diff --git a/src/main/java/at/hannibal2/skyhanni/data/HotmData.kt b/src/main/java/at/hannibal2/skyhanni/data/HotmData.kt index 3137458c3bec..beb7581b0d0d 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/HotmData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/HotmData.kt @@ -447,6 +447,7 @@ enum class HotmData( "perk.enable", "§a§lENABLED|(§.)*SELECTED", ) + @Suppress("UnusedPrivateProperty") private val disabledPattern by patternGroup.pattern( "perk.disabled", "§c§lDISABLED|§7§eClick to select!", @@ -530,7 +531,7 @@ enum class HotmData( HotmAPI.MayhemPerk.entries.forEach { it.chatPattern } - (0..CORE_OF_THE_MOUNTAIN.maxLevel).forEach { level -> + for (level in 0..CORE_OF_THE_MOUNTAIN.maxLevel) { val map = mutableMapOf() if (level >= 1) map.addOrPut(HotmReward.EXTRA_TOKENS, 1.0) if (level >= 2) map.addOrPut(HotmReward.ABILITY_LEVEL, 1.0) diff --git a/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt b/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt index 3707d10af0a7..b17c23d4dc33 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt @@ -52,6 +52,7 @@ object HypixelData { "servername.scoreboard", "§e(?.+\\.)?hypixel\\.net", ) + @Suppress("UnusedPrivateProperty") private val islandNamePattern by patternGroup.pattern( "islandname", "(?:§.)*(Area|Dungeon): (?:§.)*(?.*)", @@ -139,7 +140,7 @@ object HypixelData { // Data from locraw var locrawData: JsonObject? = null - private var locraw: MutableMap = listOf( + private val locraw: MutableMap = listOf( "server", "gametype", "lobbyname", @@ -148,12 +149,12 @@ object HypixelData { "map", ).associateWith { "" }.toMutableMap() - val server get() = locraw["server"] ?: "" - val gameType get() = locraw["gametype"] ?: "" - val lobbyName get() = locraw["lobbyname"] ?: "" - val lobbyType get() = locraw["lobbytype"] ?: "" - val mode get() = locraw["mode"] ?: "" - val map get() = locraw["map"] ?: "" + val server get() = locraw["server"].orEmpty() + val gameType get() = locraw["gametype"].orEmpty() + val lobbyName get() = locraw["lobbyname"].orEmpty() + val lobbyType get() = locraw["lobbytype"].orEmpty() + val mode get() = locraw["mode"].orEmpty() + val map get() = locraw["map"].orEmpty() fun checkCurrentServerId() { if (!LorenzUtils.inSkyBlock) return @@ -267,7 +268,7 @@ object HypixelData { if (obj.has("server")) { locrawData = obj for (key in locraw.keys) { - locraw[key] = obj[key]?.asString ?: "" + locraw[key] = obj[key]?.asString.orEmpty() } inLimbo = locraw["server"] == "limbo" inLobby = locraw["lobbyname"] != "" @@ -286,7 +287,7 @@ object HypixelData { } } - private var loggerIslandChange = LorenzLogger("debug/island_change") + private val loggerIslandChange = LorenzLogger("debug/island_change") @SubscribeEvent fun onWorldChange(event: LorenzWorldChangeEvent) { @@ -442,7 +443,7 @@ object HypixelData { } } - serverNameConnectionPattern.matchMatcher(mc.currentServerData?.serverIP ?: "") { + serverNameConnectionPattern.matchMatcher(mc.currentServerData?.serverIP.orEmpty()) { hypixel = true if (group("prefix") == "alpha.") { hypixelAlpha = true @@ -485,32 +486,34 @@ object HypixelData { } private fun checkIsland(event: WidgetUpdateEvent) { - val islandType: IslandType + val newIsland: IslandType val foundIsland: String if (event.isClear()) { TabListData.fullyLoaded = false - islandType = IslandType.NONE + newIsland = IslandType.NONE foundIsland = "" } else { TabListData.fullyLoaded = true // Can not use color coding, because of the color effect (§f§lSKYB§6§lL§e§lOCK§A§L GUEST) val guesting = guestPattern.matches(ScoreboardData.objectiveTitle.removeColor()) - foundIsland = TabWidget.AREA.matchMatcherFirstLine { group("island").removeColor() } ?: "" - islandType = getIslandType(foundIsland, guesting) + foundIsland = TabWidget.AREA.matchMatcherFirstLine { group("island").removeColor() }.orEmpty() + newIsland = getIslandType(foundIsland, guesting) } // TODO don't send events when one of the arguments is none, at least when not on sb anymore - if (skyBlockIsland != islandType) { - IslandChangeEvent(islandType, skyBlockIsland).postAndCatch() - if (islandType == IslandType.UNKNOWN) { + if (skyBlockIsland != newIsland) { + val oldIsland = skyBlockIsland + skyBlockIsland = newIsland + IslandChangeEvent(newIsland, oldIsland).postAndCatch() + + if (newIsland == IslandType.UNKNOWN) { ChatUtils.debug("Unknown island detected: '$foundIsland'") loggerIslandChange.log("Unknown: '$foundIsland'") } else { - loggerIslandChange.log(islandType.name) + loggerIslandChange.log(newIsland.name) } - skyBlockIsland = islandType if (TabListData.fullyLoaded) { TabWidget.reSendEvents() } diff --git a/src/main/java/at/hannibal2/skyhanni/data/ItemAddManager.kt b/src/main/java/at/hannibal2/skyhanni/data/ItemAddManager.kt index 4906f5f80623..b72c38c7f6d6 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/ItemAddManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/ItemAddManager.kt @@ -89,7 +89,7 @@ object ItemAddManager { } private var lastDiceRoll = SimpleTimeMark.farPast() - private var superCraftedItems = TimeLimitedSet(30.seconds) + private val superCraftedItems = TimeLimitedSet(30.seconds) @SubscribeEvent fun onChat(event: LorenzChatEvent) { diff --git a/src/main/java/at/hannibal2/skyhanni/data/LocationFixData.kt b/src/main/java/at/hannibal2/skyhanni/data/LocationFixData.kt index 20dfbb615722..8ec067deb926 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/LocationFixData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/LocationFixData.kt @@ -11,7 +11,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @SkyHanniModule object LocationFixData { - private var locationFixes = mutableMapOf>() + private val locationFixes = mutableMapOf>() private data class LocationFix(val area: AxisAlignedBB, val realLocation: String) diff --git a/src/main/java/at/hannibal2/skyhanni/data/MaxwellAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/MaxwellAPI.kt index 776a7c808103..f94ab310d393 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/MaxwellAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/MaxwellAPI.kt @@ -6,7 +6,7 @@ import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.events.RepositoryReloadEvent import at.hannibal2.skyhanni.features.dungeon.DungeonAPI import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard -import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardElement +import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardConfigElement import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.ChatUtils @@ -52,7 +52,7 @@ object MaxwellAPI { } var favoritePowers: List - get() = storage?.maxwell?.favoritePowers ?: listOf() + get() = storage?.maxwell?.favoritePowers.orEmpty() set(value) { storage?.maxwell?.favoritePowers = value } @@ -135,14 +135,11 @@ object MaxwellAPI { chatPowerPattern.tryReadPower(message) chatPowerUnlockedPattern.tryReadPower(message) - tuningAutoAssignedPattern.matchMatcher(event.message) { - if (tunings.isNullOrEmpty()) return - val tuningsInScoreboard = ScoreboardElement.TUNING in CustomScoreboard.config.scoreboardEntries - if (tuningsInScoreboard) { - ChatUtils.chat( - "Talk to Maxwell and open the Tuning Page again to update the tuning data in scoreboard.", - ) - } + if (!tuningAutoAssignedPattern.matches(event.message)) return + if (tunings.isNullOrEmpty()) return + with(CustomScoreboard.config) { + if (!enabled.get() || ScoreboardConfigElement.TUNING !in scoreboardEntries.get()) return + ChatUtils.chat("Talk to Maxwell and open the Tuning Page again to update the tuning data in scoreboard.") } } diff --git a/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt index 949e33146ce6..1cb023ecd3df 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt @@ -96,7 +96,7 @@ object MayorAPI { private var lastJerryExtraMayorReminder = SimpleTimeMark.farPast() private var lastUpdate = SimpleTimeMark.farPast() - private var dispatcher = Dispatchers.IO + private val dispatcher = Dispatchers.IO private var rawMayorData: MayorJson? = null private var candidates = mapOf() diff --git a/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt index 54d186ae52c3..fbe304098299 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt @@ -14,7 +14,6 @@ import at.hannibal2.skyhanni.events.ServerBlockChangeEvent import at.hannibal2.skyhanni.events.mining.OreMinedEvent import at.hannibal2.skyhanni.events.player.PlayerDeathEvent import at.hannibal2.skyhanni.events.skyblock.ScoreboardAreaChangeEvent -import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardPattern import at.hannibal2.skyhanni.features.mining.OreBlock import at.hannibal2.skyhanni.features.mining.isTitanium import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule @@ -46,12 +45,20 @@ object MiningAPI { private val glaciteAreaPattern by group.pattern("area.glacite", "Glacite Tunnels|Great Glacite Lake") private val dwarvenBaseCampPattern by group.pattern("area.basecamp", "Dwarven Base Camp") - // TODO add regex test + // TODO add regex tests private val coldResetPattern by group.pattern( "cold.reset", "§6The warmth of the campfire reduced your §r§b❄ Cold §r§6to §r§a0§r§6!|§c ☠ §r§7You froze to death§r§7\\.", ) + /** + * REGEX-TEST: Cold: §b-1❄ + */ + val coldPattern by group.pattern( + "cold", + "(?:§.)*Cold: §.(?-?\\d+)❄", + ) + private val pickbobulusGroup = group.group("pickobulus") /** @@ -150,11 +157,15 @@ object MiningAPI { IslandType.SPIDER_DEN, ) + fun inAdvancedMiningIsland() = inAnyIsland(IslandType.DWARVEN_MINES, IslandType.CRYSTAL_HOLLOWS, IslandType.MINESHAFT) + + fun inMiningIsland() = inAdvancedMiningIsland() || inAnyIsland(IslandType.GOLD_MINES, IslandType.DEEP_CAVERNS) + fun inColdIsland() = inAnyIsland(IslandType.DWARVEN_MINES, IslandType.MINESHAFT) @SubscribeEvent fun onScoreboardChange(event: ScoreboardUpdateEvent) { - val newCold = ScoreboardPattern.coldPattern.firstMatcher(event.scoreboard) { + val newCold = coldPattern.firstMatcher(event.scoreboard) { group("cold").toInt().absoluteValue } ?: return diff --git a/src/main/java/at/hannibal2/skyhanni/data/NotificationManager.kt b/src/main/java/at/hannibal2/skyhanni/data/NotificationManager.kt new file mode 100644 index 000000000000..748e46892865 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/NotificationManager.kt @@ -0,0 +1,112 @@ +package at.hannibal2.skyhanni.data + +import at.hannibal2.skyhanni.api.event.HandleEvent +import at.hannibal2.skyhanni.config.commands.CommandCategory +import at.hannibal2.skyhanni.config.commands.CommandRegistrationEvent +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.LorenzKeyPressEvent +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.GuiRenderUtils +import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.TimeUtils.format +import at.hannibal2.skyhanni.utils.compat.GuiScreenUtils +import io.github.notenoughupdates.moulconfig.internal.RenderUtils +import net.minecraft.client.Minecraft +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import org.lwjgl.input.Keyboard +import kotlin.time.Duration +import kotlin.time.Duration.Companion.milliseconds + +@SkyHanniModule +object NotificationManager { + + private val notificationQueue = mutableListOf() + + private var currentNotification: SkyHanniNotification? = null + private var lastNotificationClosed = SimpleTimeMark.farPast() + + private const val CLOSE_TEXT = "§c[X] Close" + + @SubscribeEvent + fun onKeyClick(event: LorenzKeyPressEvent) { + currentNotification ?: return + if (lastNotificationClosed.passedSince() < 200.milliseconds) return + if (event.keyCode != Keyboard.KEY_X) return + currentNotification = null + lastNotificationClosed = SimpleTimeMark.now() + } + + @SubscribeEvent + fun onRenderOverlay(event: GuiRenderEvent) { + val notification = getCurrentNotification() ?: return + + if (InventoryUtils.inInventory() && !notification.showOverInventory) return + + val midX = GuiScreenUtils.scaledWindowWidth / 2 + val topY = (GuiScreenUtils.scaledWindowHeight * 0.75 - notification.height / 2).toInt() + + RenderUtils.drawFloatingRectDark(midX - notification.width / 2, topY, notification.width, notification.height) + val closeTextWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(CLOSE_TEXT) + + GuiRenderUtils.drawString(CLOSE_TEXT, midX + notification.width / 2 - 3 - closeTextWidth, topY + 4) + + if (notification.length.isFinite()) { + val remainingTime = "§8" + notification.endTime.timeUntil().format() + GuiRenderUtils.drawString(remainingTime, midX - notification.width / 2 + 4, topY + 4) + } + + notification.message.forEachIndexed { index, line -> + GuiRenderUtils.drawStringCentered("§7$line", midX, topY + 19 + index * 10) + } + } + + private fun getCurrentNotification(): SkyHanniNotification? { + currentNotification?.let { + if (it.endTime.isInPast()) currentNotification = null + } + if (currentNotification == null) { + currentNotification = notificationQueue.removeFirstOrNull() + currentNotification?.setEndTime() + } + return currentNotification + } + + fun queueNotification(notification: SkyHanniNotification) { + notificationQueue.add(notification) + } + + @HandleEvent + fun onCommandRegistration(event: CommandRegistrationEvent) { + event.register("shtestnotification") { + description = "Shows a test notification" + category = CommandCategory.DEVELOPER_TEST + callback { + val testingText = it.joinToString(" ").replace("\\n", "\n") + queueNotification(SkyHanniNotification(testingText, Duration.INFINITE)) + } + } + } +} + +data class SkyHanniNotification( + val message: List, + val length: Duration, + val showOverInventory: Boolean = false, +) { + constructor(message: String, length: Duration, showOverInventory: Boolean = false) : this( + message.lines(), + length, + showOverInventory, + ) + + var endTime = SimpleTimeMark.farFuture() + + val width by lazy { (message.maxOfOrNull { Minecraft.getMinecraft().fontRendererObj.getStringWidth(it) } ?: 0) + 8 } + val height by lazy { message.size * 10 + 18 } + + fun setEndTime() { + if (length.isInfinite()) return + endTime = SimpleTimeMark.now() + length + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt index 7581b3b1ec94..4978497cf3e8 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt @@ -49,10 +49,12 @@ object SackAPI { "sack", "^(.* Sack|Enchanted .* Sack)\$", ) + @Suppress("MaxLineLength") private val numPattern by patternGroup.pattern( "number", "(?:(?:§[0-9a-f](?I{1,3})§7:)?|(?:§7Stored:)?) (?§[0-9a-f])(?[0-9.,kKmMbB]+)§7/(?\\d+(?:[0-9.,]+)?[kKmMbB]?)", ) + @Suppress("MaxLineLength") private val gemstonePattern by patternGroup.pattern( "gemstone", " §[0-9a-f](?[A-z]*): §[0-9a-f](?\\d+(?:\\.\\d+)?(?:(?:,\\d+)?)+[kKmM]?)(?: §[0-9a-f]\\(\\d+(?:\\.\\d+)?(?:(?:,\\d+)?)+[kKmM]?\\))?", @@ -231,12 +233,12 @@ object SackAPI { sibling.chatStyle?.chatHoverEvent?.value?.formattedText?.removeColor()?.takeIf { it.startsWith("Added") } - } ?: "" + }.orEmpty() val sackRemoveText = event.chatComponent.siblings.firstNotNullOfOrNull { sibling -> sibling.chatStyle?.chatHoverEvent?.value?.formattedText?.removeColor()?.takeIf { it.startsWith("Removed") } - } ?: "" + }.orEmpty() val sackChangeText = sackAddText + sackRemoveText if (sackChangeText.isEmpty()) return @@ -332,7 +334,7 @@ object SackAPI { ProfileStorageData.sackProfiles?.sackContents = sackData SkyHanniMod.configManager.saveConfig(ConfigFileType.SACKS, "saving-data") - SackDataUpdateEvent().postAndCatch() + SackDataUpdateEvent.post() } data class SackGemstone( @@ -343,7 +345,10 @@ object SackAPI { var roughPrice: Long = 0, var flawedPrice: Long = 0, var finePrice: Long = 0, - ) : AbstractSackItem() + ) : AbstractSackItem() { + val priceSum: Long + get() = roughPrice + flawedPrice + finePrice + } data class SackRune( var stack: ItemStack? = null, diff --git a/src/main/java/at/hannibal2/skyhanni/data/ScoreboardData.kt b/src/main/java/at/hannibal2/skyhanni/data/ScoreboardData.kt index a8cafcf3d981..42de7a75b1f1 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/ScoreboardData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/ScoreboardData.kt @@ -25,7 +25,8 @@ object ScoreboardData { private var sidebarLines: List = emptyList() // TODO rename to raw var sidebarLinesRaw: List = emptyList() // TODO delete - val objectiveTitle: String get() = Minecraft.getMinecraft().theWorld?.scoreboard?.getObjectiveInDisplaySlot(1)?.displayName ?: "" + val objectiveTitle: String get() = + Minecraft.getMinecraft().theWorld?.scoreboard?.getObjectiveInDisplaySlot(1)?.displayName.orEmpty() private var dirty = false @@ -48,7 +49,7 @@ object ScoreboardData { * - '§8- §c§6Flame Dr§6agon§a 460M§c❤' * ``` */ - val lastColor = start.lastColorCode() ?: "" + val lastColor = start.lastColorCode().orEmpty() // Generate the list of color suffixes val colorSuffixes = lastColor.chunked(2).toMutableList() diff --git a/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt index 0d91c7f62856..aa9aa1f65bc0 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/SlayerAPI.kt @@ -17,6 +17,7 @@ import at.hannibal2.skyhanni.utils.NEUItems.getPrice import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat import at.hannibal2.skyhanni.utils.RecalculatingValue import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.StringUtils.removeColor import at.hannibal2.skyhanni.utils.TimeLimitedCache import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import kotlin.time.Duration.Companion.minutes @@ -25,7 +26,7 @@ import kotlin.time.Duration.Companion.seconds @SkyHanniModule object SlayerAPI { - private var nameCache = TimeLimitedCache, Pair>(1.minutes) + private val nameCache = TimeLimitedCache, Pair>(1.minutes) var questStartTime = SimpleTimeMark.farPast() var isInCorrectArea = false @@ -69,7 +70,7 @@ object SlayerAPI { add("activeSlayer: $activeSlayer") add("isInCorrectArea: $isInCorrectArea") add("isInAnyArea: $isInAnyArea") - add("latestSlayerProgress: $latestSlayerProgress") + add("latestSlayerProgress: ${latestSlayerProgress.removeColor()}") } } @@ -82,7 +83,7 @@ object SlayerAPI { } if (event.message == " §r§a§lSLAYER QUEST COMPLETE!") { - SlayerQuestCompleteEvent().postAndCatch() + SlayerQuestCompleteEvent.post() } } @@ -107,14 +108,14 @@ object SlayerAPI { // wait with sending SlayerChangeEvent until profile is detected if (ProfileStorageData.profileSpecific == null) return - val slayerQuest = ScoreboardData.sidebarLinesFormatted.nextAfter("Slayer Quest") ?: "" + val slayerQuest = ScoreboardData.sidebarLinesFormatted.nextAfter("Slayer Quest").orEmpty() if (slayerQuest != latestSlayerCategory) { val old = latestSlayerCategory latestSlayerCategory = slayerQuest SlayerChangeEvent(old, latestSlayerCategory).postAndCatch() } - val slayerProgress = ScoreboardData.sidebarLinesFormatted.nextAfter("Slayer Quest", 2) ?: "" + val slayerProgress = ScoreboardData.sidebarLinesFormatted.nextAfter("Slayer Quest", 2).orEmpty() if (latestSlayerProgress != slayerProgress) { SlayerProgressChangeEvent(latestSlayerProgress, slayerProgress).postAndCatch() latestSlayerProgress = slayerProgress diff --git a/src/main/java/at/hannibal2/skyhanni/data/WinterAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/WinterAPI.kt index 9e3a7a9e6ea9..4b430b9c55a6 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/WinterAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/WinterAPI.kt @@ -1,9 +1,12 @@ package at.hannibal2.skyhanni.data +import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland import at.hannibal2.skyhanni.utils.TimeUtils import java.time.Month object WinterAPI { + fun inWorkshop() = IslandType.WINTER.isInIsland() + fun isDecember() = TimeUtils.getCurrentLocalDate().month == Month.DECEMBER } diff --git a/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/PlayerChatManager.kt b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/PlayerChatManager.kt index b6c0e16f9cca..5199e8b7e230 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/PlayerChatManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/PlayerChatManager.kt @@ -88,6 +88,7 @@ object PlayerChatManager { * REGEX-TEST: §b[MVP§c+§b] hannibal2§f§7 has §8[§6Heroic Aspect of the Void§8] * REGEX-TEST: §8[§b209§8] §b[MVP§d+§b] lrg89§f§7 is holding §8[§5Heroic Aspect of the Void§8] */ + @Suppress("MaxLineLength") private val itemShowPattern by patternGroup.pattern( "itemshow", "(?:§8\\[(?§.)(?\\d+)§8] )?(?.*)§f§7 (?is (?:holding|friends with a|wearing)|has) (?.*)" diff --git a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/RepoErrorData.kt b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/RepoErrorData.kt index 41d0f701cb15..5ba59c148231 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/RepoErrorData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/RepoErrorData.kt @@ -14,6 +14,6 @@ data class RepoErrorData( @Expose @SerializedName("custom_message") var customMessage: String?, @Expose @SerializedName("affected_versions") var affectedVersions: List = listOf(), ) { - val messageExact get() = rawMessageExact ?: emptyList() - val messageStartsWith get() = rawMessageStartsWith ?: emptyList() + val messageExact get() = rawMessageExact.orEmpty() + val messageStartsWith get() = rawMessageStartsWith.orEmpty() } diff --git a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/neu/NeuReforgeJson.kt b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/neu/NeuReforgeJson.kt index a8c8f3fe4646..bc92dc189f69 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/neu/NeuReforgeJson.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/neu/NeuReforgeJson.kt @@ -34,7 +34,7 @@ data class NeuReforgeJson( LorenzRarity.valueOf( it.key.uppercase().replace(" ", "_"), ) - } ?: emptyMap() + }.orEmpty() else -> emptyMap() } @@ -53,10 +53,10 @@ data class NeuReforgeJson( is Map<*, *> -> { val type = "SPECIAL_ITEMS" val map = any as? Map> ?: return type to emptyList() - val internalNames = map["internalName"]?.map { it.asInternalName() } ?: emptyList() + val internalNames = map["internalName"]?.map { it.asInternalName() }.orEmpty() val itemType = map["itemid"]?.map { NEUItems.getInternalNamesForItemId(Item.getByNameOrId(it)) - }?.flatten() ?: emptyList() + }?.flatten().orEmpty() type to (internalNames + itemType) } diff --git a/src/main/java/at/hannibal2/skyhanni/data/mob/IslandExceptions.kt b/src/main/java/at/hannibal2/skyhanni/data/mob/IslandExceptions.kt index eed2d5e70dba..428d18de8353 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/mob/IslandExceptions.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/mob/IslandExceptions.kt @@ -82,7 +82,7 @@ object IslandExceptions { baseEntity.name.contains("Livid") -> MobUtils.getClosestArmorStandWithName(baseEntity, 6.0, "﴾ Livid") .makeMobResult { MobFactories.boss(baseEntity, it, overriddenName = "Real Livid") } - baseEntity is EntityIronGolem && MobFilter.wokeSleepingGolemPattern.matches(armorStand?.name ?: "") -> + baseEntity is EntityIronGolem && MobFilter.wokeSleepingGolemPattern.matches(armorStand?.name.orEmpty()) -> MobData.MobResult.found(Mob(baseEntity, Mob.Type.DUNGEON, armorStand, "Sleeping Golem")) // Consistency fix else -> null diff --git a/src/main/java/at/hannibal2/skyhanni/data/mob/LineToMobHandler.kt b/src/main/java/at/hannibal2/skyhanni/data/mob/LineToMobHandler.kt new file mode 100644 index 000000000000..26313efba7a3 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/mob/LineToMobHandler.kt @@ -0,0 +1,44 @@ +package at.hannibal2.skyhanni.data.mob + +import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent +import at.hannibal2.skyhanni.events.MobEvent +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.RenderUtils +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import java.awt.Color + +@SkyHanniModule +object LineToMobHandler { + + data class LineSettings( + val color: Color, + val width: Int, + val depth: Boolean, + ) + + private val lines = mutableMapOf() + + fun register(mob: Mob, color: Color, width: Int, depth: Boolean) = register(mob, LineSettings(color, width, depth)) + + fun register(mob: Mob, settings: LineSettings) { + lines[mob] = settings + } + + @SubscribeEvent + fun onMobDeSpawn(event: MobEvent.DeSpawn) { + lines.remove(event.mob) + } + + @SubscribeEvent + fun onLorenzRenderWorld(event: LorenzRenderWorldEvent) { + if (!LorenzUtils.inSkyBlock) return + if (lines.isEmpty()) return + RenderUtils.LineDrawer.draw3D(event.partialTicks) { + for ((mob, settings) in lines) { + if (!mob.canBeSeen()) continue + draw3DLineFromPlayer(mob.centerCords, settings.color, settings.width, settings.depth) + } + } + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/data/mob/Mob.kt b/src/main/java/at/hannibal2/skyhanni/data/mob/Mob.kt index e9eb6729de43..a486f97991d8 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/mob/Mob.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/mob/Mob.kt @@ -11,6 +11,7 @@ import at.hannibal2.skyhanni.utils.EntityUtils.cleanName import at.hannibal2.skyhanni.utils.EntityUtils.isCorrupted import at.hannibal2.skyhanni.utils.EntityUtils.isRunic import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer +import at.hannibal2.skyhanni.utils.LocationUtils.getCenter import at.hannibal2.skyhanni.utils.LocationUtils.union import at.hannibal2.skyhanni.utils.MobUtils import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher @@ -109,9 +110,9 @@ class Mob( fun isInRender() = baseEntity.distanceToPlayer() < MobData.ENTITY_RENDER_RANGE_IN_BLOCKS - fun canBeSeen() = baseEntity.canBeSeen() + fun canBeSeen(viewDistance: Number = 150) = baseEntity.canBeSeen(viewDistance) - fun isInvisible() = if (baseEntity !is EntityZombie) baseEntity.isInvisible else false + fun isInvisible() = baseEntity !is EntityZombie && baseEntity.isInvisible && baseEntity.inventory.isNullOrEmpty() private var highlightColor: Color? = null @@ -130,9 +131,9 @@ class Mob( private fun internalHighlight() { highlightColor?.let { color -> - RenderLivingEntityHelper.setEntityColorWithNoHurtTime(baseEntity, color.rgb) { true } + RenderLivingEntityHelper.setEntityColorWithNoHurtTime(baseEntity, color.rgb) { !this.isInvisible() } extraEntities.forEach { - RenderLivingEntityHelper.setEntityColorWithNoHurtTime(it, color.rgb) { true } + RenderLivingEntityHelper.setEntityColorWithNoHurtTime(it, color.rgb) { !this.isInvisible() } } } } @@ -226,6 +227,8 @@ class Mob( internalHighlight() } + val centerCords get() = boundingBox.getCenter() + override fun hashCode() = id.hashCode() override fun toString(): String = "$name - ${baseEntity.entityId}" @@ -236,4 +239,8 @@ class Mob( return id == other.id } + + // TODO add max distance + fun lineToPlayer(color: Color, lineWidth: Int = 2, depth: Boolean = true) = LineToMobHandler.register(this, color, lineWidth, depth) + fun distanceToPlayer(): Double = baseEntity.distanceToPlayer() } diff --git a/src/main/java/at/hannibal2/skyhanni/data/mob/MobData.kt b/src/main/java/at/hannibal2/skyhanni/data/mob/MobData.kt index f955384c5f4e..2363945d21df 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/mob/MobData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/mob/MobData.kt @@ -103,11 +103,6 @@ object MobData { notSeenMobs.remove(event.mob) } - @SubscribeEvent - fun onMobFirstSeen(event: MobEvent.FirstSeen) { - notSeenMobs.remove(event.mob) - } - @SubscribeEvent fun onSkyblockMobSpawnEvent(event: MobEvent.Spawn.SkyblockMob) { skyblockMobs.add(event.mob) diff --git a/src/main/java/at/hannibal2/skyhanni/data/mob/MobDebug.kt b/src/main/java/at/hannibal2/skyhanni/data/mob/MobDebug.kt index d9cb34ed25d7..e1da962ffccb 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/mob/MobDebug.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/mob/MobDebug.kt @@ -10,7 +10,7 @@ import at.hannibal2.skyhanni.utils.LocationUtils.getTopCenter import at.hannibal2.skyhanni.utils.LorenzColor import at.hannibal2.skyhanni.utils.LorenzDebug import at.hannibal2.skyhanni.utils.MobUtils -import at.hannibal2.skyhanni.utils.RenderUtils.drawFilledBoundingBox_nea +import at.hannibal2.skyhanni.utils.RenderUtils.drawFilledBoundingBoxNea import at.hannibal2.skyhanni.utils.RenderUtils.drawString import at.hannibal2.skyhanni.utils.RenderUtils.expandBlock import net.minecraft.client.Minecraft @@ -34,7 +34,7 @@ object MobDebug { private fun MobData.MobSet.highlight(event: LorenzRenderWorldEvent, color: (Mob) -> (LorenzColor)) { for (mob in filter { it.isNotInvisible() }) { - event.drawFilledBoundingBox_nea(mob.boundingBox.expandBlock(), color.invoke(mob).toColor(), 0.3f) + event.drawFilledBoundingBoxNea(mob.boundingBox.expandBlock(), color.invoke(mob).toColor(), 0.3f) } } @@ -82,7 +82,7 @@ object MobDebug { } if (config.showRayHit) { lastRayHit?.let { - event.drawFilledBoundingBox_nea(it.boundingBox.expandBlock(), LorenzColor.GOLD.toColor(), 0.5f) + event.drawFilledBoundingBoxNea(it.boundingBox.expandBlock(), LorenzColor.GOLD.toColor(), 0.5f) } } } diff --git a/src/main/java/at/hannibal2/skyhanni/data/mob/MobDetection.kt b/src/main/java/at/hannibal2/skyhanni/data/mob/MobDetection.kt index 014e0a846613..dbfbfe533d4b 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/mob/MobDetection.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/mob/MobDetection.kt @@ -159,13 +159,15 @@ object MobDetection { private fun canBeSeen(mob: Mob): Boolean { val isVisible = !mob.isInvisible() && mob.canBeSeen() - if (isVisible) when (mob.mobType) { - Mob.Type.PLAYER -> MobEvent.FirstSeen.Player(mob) - Mob.Type.SUMMON -> MobEvent.FirstSeen.Summon(mob) - Mob.Type.SPECIAL -> MobEvent.FirstSeen.Special(mob) - Mob.Type.PROJECTILE -> MobEvent.FirstSeen.Projectile(mob) - Mob.Type.DISPLAY_NPC -> MobEvent.FirstSeen.DisplayNPC(mob) - Mob.Type.BASIC, Mob.Type.DUNGEON, Mob.Type.BOSS, Mob.Type.SLAYER -> MobEvent.FirstSeen.SkyblockMob(mob) + if (isVisible) { + when (mob.mobType) { + Mob.Type.PLAYER -> MobEvent.FirstSeen.Player(mob) + Mob.Type.SUMMON -> MobEvent.FirstSeen.Summon(mob) + Mob.Type.SPECIAL -> MobEvent.FirstSeen.Special(mob) + Mob.Type.PROJECTILE -> MobEvent.FirstSeen.Projectile(mob) + Mob.Type.DISPLAY_NPC -> MobEvent.FirstSeen.DisplayNPC(mob) + Mob.Type.BASIC, Mob.Type.DUNGEON, Mob.Type.BOSS, Mob.Type.SLAYER -> MobEvent.FirstSeen.SkyblockMob(mob) + }.postAndCatch() } return isVisible } @@ -353,11 +355,12 @@ object MobDetection { is S0FPacketSpawnMob -> addEntityUpdate(packet.entityID) is S0CPacketSpawnPlayer -> addEntityUpdate(packet.entityID) // is S0EPacketSpawnObject -> addEntityUpdate(packet.entityID) - is S01PacketJoinGame -> // one of the first packets that is sent when switching servers inside the BungeeCord Network (please some prove this, I just found it out via Testing) - { - shouldClear.set(true) - allEntitiesViaPacketId.clear() - } + is S01PacketJoinGame -> { + // one of the first packets that is sent when switching servers inside the BungeeCord Network + // (please some prove this, I just found it out via Testing) + shouldClear.set(true) + allEntitiesViaPacketId.clear() + } } } diff --git a/src/main/java/at/hannibal2/skyhanni/data/mob/MobFilter.kt b/src/main/java/at/hannibal2/skyhanni/data/mob/MobFilter.kt index 5d6111336fbd..6938958e97b4 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/mob/MobFilter.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/mob/MobFilter.kt @@ -120,14 +120,20 @@ object MobFilter { "^§8\\[§7Lv\\d+§8] §.(?Horse|Armadillo|Skeleton Horse|Pig|Rat)$", ) + // TODO: Move all of these to repo + @Suppress("MaxLineLength") internal const val RAT_SKULL = "ewogICJ0aW1lc3RhbXAiIDogMTYxODQxOTcwMTc1MywKICAicHJvZmlsZUlkIiA6ICI3MzgyZGRmYmU0ODU0NTVjODI1ZjkwMGY4OGZkMzJmOCIsCiAgInByb2ZpbGVOYW1lIiA6ICJCdUlJZXQiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYThhYmI0NzFkYjBhYjc4NzAzMDExOTc5ZGM4YjQwNzk4YTk0MWYzYTRkZWMzZWM2MWNiZWVjMmFmOGNmZmU4IiwKICAgICAgIm1ldGFkYXRhIiA6IHsKICAgICAgICAibW9kZWwiIDogInNsaW0iCiAgICAgIH0KICAgIH0KICB9Cn0=" + @Suppress("MaxLineLength") private const val HELLWISP_TENTACLE_SKULL = "ewogICJ0aW1lc3RhbXAiIDogMTY0OTM4MzAyMTQxNiwKICAicHJvZmlsZUlkIiA6ICIzYjgwOTg1YWU4ODY0ZWZlYjA3ODg2MmZkOTRhMTVkOSIsCiAgInByb2ZpbGVOYW1lIiA6ICJLaWVyYW5fVmF4aWxpYW4iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDI3MDQ2Mzg0OTM2MzhiODVjMzhkZDYzZmZkYmUyMjJmZTUzY2ZkNmE1MDk3NzI4NzU2MTE5MzdhZTViNWUyMiIsCiAgICAgICJtZXRhZGF0YSIgOiB7CiAgICAgICAgIm1vZGVsIiA6ICJzbGltIgogICAgICB9CiAgICB9CiAgfQp9" + @Suppress("MaxLineLength") private const val RIFT_EYE_SKULL1 = "ewogICJ0aW1lc3RhbXAiIDogMTY0ODA5MTkzNTcyMiwKICAicHJvZmlsZUlkIiA6ICJhNzdkNmQ2YmFjOWE0NzY3YTFhNzU1NjYxOTllYmY5MiIsCiAgInByb2ZpbGVOYW1lIiA6ICIwOEJFRDUiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjI2YmRlNDUwNDljN2I3ZDM0NjA1ZDgwNmEwNjgyOWI2Zjk1NWI4NTZhNTk5MWZkMzNlN2VhYmNlNDRjMDgzNCIsCiAgICAgICJtZXRhZGF0YSIgOiB7CiAgICAgICAgIm1vZGVsIiA6ICJzbGltIgogICAgICB9CiAgICB9CiAgfQp9" + @Suppress("MaxLineLength") private const val RIFT_EYE_SKULL2 = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTdkYjE5MjNkMDNjNGVmNGU5ZjZlODcyYzVhNmFkMjU3OGIxYWZmMmIyODFmYmMzZmZhNzQ2NmM4MjVmYjkifX19" + @Suppress("MaxLineLength") internal const val NPC_TURD_SKULL = "ewogICJ0aW1lc3RhbXAiIDogMTYzOTUxMjYxNzc5MywKICAicHJvZmlsZUlkIiA6ICIwZjczMDA3NjEyNGU0NGM3YWYxMTE1NDY5YzQ5OTY3OSIsCiAgInByb2ZpbGVOYW1lIiA6ICJPcmVfTWluZXIxMjMiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjM2MzBkOWIwMjA4OGVhMTkyNGE4NzIyNDJhYmM3NWI2MjYyYzJhY2E5MmFlY2Y4NzE0YTU3YTQxZWVhMGI5ZCIKICAgIH0KICB9Cn0=" diff --git a/src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt b/src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt index 6e1f1d07f0a2..5eb71715faba 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt @@ -194,6 +194,7 @@ data class DijkstraTree( val lastVisitedNode: GraphNode, ) +@Suppress("MapGetWithNotNullAssertionOperator") fun DijkstraTree.findPathToDestination(end: GraphNode): Pair { val distances = this val reversePath = buildList { diff --git a/src/main/java/at/hannibal2/skyhanni/data/model/GraphNodeTag.kt b/src/main/java/at/hannibal2/skyhanni/data/model/GraphNodeTag.kt index 8efcf4621e37..2873ac9a4a11 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/model/GraphNodeTag.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/model/GraphNodeTag.kt @@ -17,6 +17,7 @@ enum class GraphNodeTag( AREA("area", LorenzColor.DARK_GREEN, "Area", "A big SkyBlock area."), SMALL_AREA("small_area", LorenzColor.GREEN, "Small Area", "A small SkyBlock area, e.g. a house."), POI("poi", LorenzColor.WHITE, "Point of Interest", "A relevant spot or a landmark on the map."), + // LAUNCH_PAD("launch", LorenzColor.WHITE, "Launch Pad", "Slime blocks sending you to another server."), TELEPORT("teleport", LorenzColor.BLUE, "Teleport", "A spot from/to teleport."), @@ -42,7 +43,13 @@ enum class GraphNodeTag( // Rift RIFT_ENIGMA("rift_enigma", LorenzColor.DARK_PURPLE, "Enigma Soul", "Enigma Souls in the Rift.", onlyIsland = IslandType.THE_RIFT), - RIFT_BUTTONS_QUEST("rift_buttons_quest", LorenzColor.LIGHT_PURPLE, "Wooden Buttons", "A spot to hit wooden buttons for the Dreadfarm Enigma Soul.", onlyIsland = IslandType.THE_RIFT), + RIFT_BUTTONS_QUEST( + "rift_buttons_quest", + LorenzColor.LIGHT_PURPLE, + "Wooden Buttons", + "A spot to hit wooden buttons for the Dreadfarm Enigma Soul.", + onlyIsland = IslandType.THE_RIFT, + ), RIFT_EYE("rift_eye", LorenzColor.DARK_RED, "Rift Eye", "An Eye in the Rift to teleport to.", onlyIsland = IslandType.THE_RIFT), RIFT_MONTEZUMA( "rift_montezuma", diff --git a/src/main/java/at/hannibal2/skyhanni/data/model/SkyblockStat.kt b/src/main/java/at/hannibal2/skyhanni/data/model/SkyblockStat.kt index d1c6dede0327..3f5019509eb3 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/model/SkyblockStat.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/model/SkyblockStat.kt @@ -18,12 +18,13 @@ import java.util.EnumMap import java.util.regex.Pattern import kotlin.math.roundToInt +@Suppress("MaxLineLength") enum class SkyblockStat( val icon: String, @Language("RegExp") tabListPatternS: String, @Language("RegExp") menuPatternS: String, ) { - DAMAGE("§c❁", "", ""), // Weapon only + DAMAGE("§c❁", "", ""), // Weapon only HEALTH("§c❤", " Health: §r§c❤(?.*)", " §c❤ Health §f(?.*)"), // TODO get from action bar DEFENSE("§a❈", " Defense: §r§a❈(?.*)", " §a❈ Defense §f(?.*)"), // TODO get from action bar STRENGTH("§c❁", " Strength: §r§c❁(?.*)", " §c❁ Strength §f(?.*)"), @@ -137,7 +138,7 @@ enum class SkyblockStat( private fun onSkyblockMenu(event: InventoryFullyOpenedEvent) { if (event.inventoryName != "SkyBlock Menu") return val list = event.inventoryItems[PLAYER_STATS_SLOT_INDEX]?.getLore() ?: return - DelayedRun.runNextTick { // Delayed to not impact opening time + DelayedRun.runNextTick { // Delayed to not impact opening time assignEntry(list, StatSourceType.SKYBLOCK_MENU) { it.menuPattern } } } @@ -148,7 +149,7 @@ enum class SkyblockStat( if (event.inventoryName != "Your Equipment and Stats") return val list = statsMenuRelevantSlotIndexes.mapNotNull { event.inventoryItems[it]?.getLore() }.flatten() if (list.isEmpty()) return - DelayedRun.runNextTick { // Delayed to not impact opening time + DelayedRun.runNextTick { // Delayed to not impact opening time assignEntry(list, StatSourceType.STATS_MENU) { it.menuPattern } } } diff --git a/src/main/java/at/hannibal2/skyhanni/data/model/TabWidget.kt b/src/main/java/at/hannibal2/skyhanni/data/model/TabWidget.kt index 85c50528f4e4..7a57de667dd1 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/model/TabWidget.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/model/TabWidget.kt @@ -95,7 +95,7 @@ enum class TabWidget( ), EVENT( // language=RegExp - "(?:§.)*Event: (?:§.)*(?.*)", + "(?:§.)*Event: (?(?:§.)*)(?.*)", ), SKILLS( // language=RegExp @@ -423,11 +423,13 @@ enum class TabWidget( val removeIndexes = mutableListOf() for ((index, header) in headers) when { - PLAYER_LIST.pattern.matches(header) -> if (playerListFound) removeIndexes.add(index - removeIndexes.size) else playerListFound = - true + PLAYER_LIST.pattern.matches(header) -> + if (playerListFound) removeIndexes.add(index - removeIndexes.size) + else playerListFound = true - INFO.pattern.matches(header) -> if (infoFound) removeIndexes.add(index - removeIndexes.size) else infoFound = - true + INFO.pattern.matches(header) -> + if (infoFound) removeIndexes.add(index - removeIndexes.size) + else infoFound = true } return tabList.transformIf({ size > 81 }, { dropLast(size - 80) }).editCopy { diff --git a/src/main/java/at/hannibal2/skyhanni/data/model/TextInput.kt b/src/main/java/at/hannibal2/skyhanni/data/model/TextInput.kt index 15fcbe8a9a62..9b8fc79ca9d1 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/model/TextInput.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/model/TextInput.kt @@ -65,6 +65,7 @@ class TextInput { activeInstance = null } + @Suppress("UnusedParameter") fun onMinecraftInput(keyBinding: KeyBinding, cir: CallbackInfoReturnable) { if (activeInstance != null) { cir.returnValue = false @@ -92,7 +93,7 @@ class TextInput { } private var textBox - get() = activeInstance?.textBox ?: "" + get() = activeInstance?.textBox.orEmpty() set(value) { activeInstance?.textBox = value } diff --git a/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt b/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt index babbb2558def..9434835de98e 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt @@ -2,7 +2,7 @@ package at.hannibal2.skyhanni.data.repo import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.config.ConfigManager -import at.hannibal2.skyhanni.events.DebugDataCollectEvent +import at.hannibal2.skyhanni.config.features.dev.RepositoryConfig import at.hannibal2.skyhanni.events.NeuRepositoryReloadEvent import at.hannibal2.skyhanni.events.RepositoryReloadEvent import at.hannibal2.skyhanni.test.command.ErrorManager @@ -26,6 +26,8 @@ import java.io.InputStreamReader import java.io.OutputStreamWriter import java.net.URL import java.nio.charset.StandardCharsets +import java.nio.file.Files +import java.nio.file.StandardCopyOption import java.util.concurrent.CompletableFuture import java.util.concurrent.atomic.AtomicBoolean import kotlin.time.Duration.Companion.minutes @@ -33,10 +35,10 @@ import kotlin.time.Duration.Companion.minutes class RepoManager(private val configLocation: File) { private val gson get() = ConfigManager.gson - private var latestRepoCommit: String? = null val repoLocation: File = File(configLocation, "repo") private var error = false private var lastRepoUpdate = SimpleTimeMark.now() + private var repoDownloadFailed = false companion object { @@ -44,6 +46,7 @@ class RepoManager(private val configLocation: File) { val successfulConstants = mutableListOf() val unsuccessfulConstants = mutableListOf() + var usingBackupRepo = false private var lastConstant: String? = null @@ -57,12 +60,23 @@ class RepoManager(private val configLocation: File) { fun getRepoLocation(): String { return "${config.location.user}/${config.location.name}/${config.location.branch}" } + + private const val DEFAULT_USER = "hannibal002" + private const val DEFAULT_NAME = "SkyHanni-REPO" + private const val DEFAULT_BRANCH = "main" + + fun RepositoryConfig.RepositoryLocation.hasDefaultSettings() = + user == DEFAULT_USER && name == DEFAULT_NAME && branch == DEFAULT_BRANCH } fun loadRepoInformation() { atomicShouldManuallyReload.set(true) if (config.repoAutoUpdate) { - fetchRepository(false).thenRun(this::reloadRepository) + fetchRepository(false).thenRun { + if (repoDownloadFailed) { + switchToBackupRepo() + } + }.thenRun { reloadRepository() } } else { reloadRepository() } @@ -73,7 +87,10 @@ class RepoManager(private val configLocation: File) { fun updateRepo() { atomicShouldManuallyReload.set(true) checkRepoLocation() - fetchRepository(true).thenRun { this.reloadRepository("Repo updated successfully.") } + fetchRepository(true).thenRun { + if (unsuccessfulConstants.isNotEmpty() || usingBackupRepo) return@thenRun + this.reloadRepository("Repo updated successfully.") + } } fun reloadLocalRepo() { @@ -84,8 +101,8 @@ class RepoManager(private val configLocation: File) { private fun fetchRepository(command: Boolean): CompletableFuture { return CompletableFuture.supplyAsync { try { - val currentCommitJSON: JsonObject? = getJsonFromFile(File(configLocation, "currentCommit.json")) - latestRepoCommit = null + val currentDownloadedCommit = readCurrentCommit() + var latestRepoCommit: String? try { InputStreamReader(URL(getCommitApiUrl()).openStream()) .use { inReader -> @@ -97,13 +114,15 @@ class RepoManager(private val configLocation: File) { e, "Error while loading data from repo", "command" to command, - "currentCommitJSON" to currentCommitJSON, + "currentDownloadedCommit" to currentDownloadedCommit, ) + repoDownloadFailed = true + return@supplyAsync false } - if (latestRepoCommit == null || latestRepoCommit!!.isEmpty()) return@supplyAsync false + val file = File(configLocation, "repo") if (file.exists() && - currentCommitJSON?.get("sha")?.asString == latestRepoCommit && + currentDownloadedCommit == latestRepoCommit && unsuccessfulConstants.isEmpty() && lastRepoUpdate.passedSince() < 1.minutes ) { @@ -114,18 +133,19 @@ class RepoManager(private val configLocation: File) { return@supplyAsync false } lastRepoUpdate = SimpleTimeMark.now() - RepoUtils.recursiveDelete(repoLocation) + repoLocation.mkdirs() val itemsZip = File(repoLocation, "sh-repo-main.zip") - try { - itemsZip.createNewFile() - } catch (e: IOException) { - return@supplyAsync false - } + itemsZip.createNewFile() + val url = URL(getDownloadUrl(latestRepoCommit)) val urlConnection = url.openConnection() urlConnection.connectTimeout = 15000 urlConnection.readTimeout = 30000 + + RepoUtils.recursiveDelete(repoLocation) + repoLocation.mkdirs() + try { urlConnection.getInputStream().use { `is` -> FileUtils.copyInputStreamToFile( @@ -140,19 +160,15 @@ class RepoManager(private val configLocation: File) { "url" to url, "command" to command, ) + repoDownloadFailed = true return@supplyAsync false } RepoUtils.unzipIgnoreFirstFolder( itemsZip.absolutePath, repoLocation.absolutePath, ) - if (currentCommitJSON == null || currentCommitJSON["sha"].asString != latestRepoCommit) { - val newCurrentCommitJSON = JsonObject() - newCurrentCommitJSON.addProperty("sha", latestRepoCommit) - try { - writeJson(newCurrentCommitJSON, File(configLocation, "currentCommit.json")) - } catch (ignored: IOException) { - } + if (currentDownloadedCommit == null || currentDownloadedCommit != latestRepoCommit) { + writeCurrentCommit(latestRepoCommit) } } catch (e: Exception) { ErrorManager.logErrorWithData( @@ -160,7 +176,10 @@ class RepoManager(private val configLocation: File) { "Failed to download SkyHanni Repo", "command" to command, ) + repoDownloadFailed = true } + repoDownloadFailed = false + usingBackupRepo = false true } } @@ -203,28 +222,18 @@ class RepoManager(private val configLocation: File) { return comp } - @SubscribeEvent - fun onDebugDataCollect(event: DebugDataCollectEvent) { - event.title("Repo Status") - - if (unsuccessfulConstants.isEmpty() && successfulConstants.isNotEmpty()) { - event.addIrrelevant("Repo working fine") - return + private fun writeCurrentCommit(commit: String?) { + val newCurrentCommitJSON = JsonObject() + newCurrentCommitJSON.addProperty("sha", commit) + try { + writeJson(newCurrentCommitJSON, File(configLocation, "currentCommit.json")) + } catch (ignored: IOException) { } + } - event.addData { - add("Successful Constants (${successfulConstants.size}):") - - add("Unsuccessful Constants (${unsuccessfulConstants.size}):") - - for ((i, constant) in unsuccessfulConstants.withIndex()) { - add(" - $constant") - if (i == 5) { - add("...") - break - } - } - } + private fun readCurrentCommit(): String? { + val currentCommitJSON: JsonObject? = getJsonFromFile(File(configLocation, "currentCommit.json")) + return currentCommitJSON?.get("sha")?.asString } fun displayRepoStatus(joinEvent: Boolean) { @@ -238,6 +247,7 @@ class RepoManager(private val configLocation: File) { ).asComponent(), ) text.add("§7Repo Auto Update Value: §c${config.repoAutoUpdate}".asComponent()) + text.add("§7Backup Repo Value: §c$usingBackupRepo".asComponent()) text.add("§7If you have Repo Auto Update turned off, please try turning that on.".asComponent()) text.add("§cUnsuccessful Constants §7(${unsuccessfulConstants.size}):".asComponent()) @@ -248,11 +258,12 @@ class RepoManager(private val configLocation: File) { } return } + val currentCommit = readCurrentCommit() if (unsuccessfulConstants.isEmpty() && successfulConstants.isNotEmpty()) { - ChatUtils.chat("Repo working fine! Commit hash: $latestRepoCommit", prefixColor = "§a") + ChatUtils.chat("Repo working fine! Commit hash: $currentCommit", prefixColor = "§a") return } - ChatUtils.chat("Repo has errors! Commit has: ${latestRepoCommit ?: "null"}", prefixColor = "§c") + ChatUtils.chat("Repo has errors! Commit hash: $currentCommit", prefixColor = "§c") if (successfulConstants.isNotEmpty()) ChatUtils.chat( "Successful Constants §7(${successfulConstants.size}):", prefixColor = "§a", @@ -314,21 +325,18 @@ class RepoManager(private val configLocation: File) { } fun resetRepositoryLocation(manual: Boolean = false) { - val defaultUser = "hannibal002" - val defaultName = "SkyHanni-Repo" - val defaultBranch = "main" with(config.location) { - if (user == defaultUser && name == defaultName && branch == defaultBranch) { + if (hasDefaultSettings()) { if (manual) { ChatUtils.chat("Repo settings are already on default!") } return } - user = defaultUser - name = defaultName - branch = defaultBranch + user = DEFAULT_USER + name = DEFAULT_NAME + branch = DEFAULT_BRANCH if (manual) { ChatUtils.clickableChat( "Reset Repo settings to default. " + @@ -343,9 +351,32 @@ class RepoManager(private val configLocation: File) { } private fun checkRepoLocation() { - if (config.location.user.isEmpty() || config.location.name.isEmpty() || config.location.branch.isEmpty()) { + if (config.location.run { user.isEmpty() || name.isEmpty() || branch.isEmpty() }) { ChatUtils.userError("Invalid Repo settings detected, resetting default settings.") resetRepositoryLocation() } } + + // Code taken from NotEnoughUpdates + private fun switchToBackupRepo() { + usingBackupRepo = true + println("Attempting to switch to backup repo") + + try { + repoLocation.mkdirs() + val destinationFile = File(repoLocation, "sh-repo-main.zip").apply { createNewFile() } + val destinationPath = destinationFile.toPath() + + val inputStream = RepoManager::class.java.classLoader.getResourceAsStream("assets/skyhanni/repo.zip") + ?: throw IOException("Failed to find backup repo") + + Files.copy(inputStream, destinationPath, StandardCopyOption.REPLACE_EXISTING) + RepoUtils.unzipIgnoreFirstFolder(destinationPath.toAbsolutePath().toString(), repoLocation.absolutePath) + writeCurrentCommit("backup-repo") + + println("Successfully switched to backup repo") + } catch (e: Exception) { + ErrorManager.logErrorWithData(e, "Failed to switch to backup repo") + } + } } diff --git a/src/main/java/at/hannibal2/skyhanni/data/repo/RepoUtils.kt b/src/main/java/at/hannibal2/skyhanni/data/repo/RepoUtils.kt index 74241946faf2..71c545912803 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/repo/RepoUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/repo/RepoUtils.kt @@ -48,7 +48,8 @@ object RepoUtils { File(newFile.parent).mkdirs() if (!isInTree(dir, newFile)) { throw RuntimeException( - "SkyHanni detected an invalid zip file. This is a potential security risk, please report this on the SkyHanni discord." + "SkyHanni detected an invalid zip file. This is a potential security risk, " + + "please report this on the SkyHanni discord." ) } val fos = FileOutputStream(newFile) diff --git a/src/main/java/at/hannibal2/skyhanni/events/CollectionUpdateEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/CollectionUpdateEvent.kt index f4c46d0b75d5..2dd016e95754 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/CollectionUpdateEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/CollectionUpdateEvent.kt @@ -1,3 +1,5 @@ package at.hannibal2.skyhanni.events -class CollectionUpdateEvent : LorenzEvent() +import at.hannibal2.skyhanni.api.event.SkyHanniEvent + +object CollectionUpdateEvent : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/CropMilestoneUpdateEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/CropMilestoneUpdateEvent.kt index 8da8b20f75ce..feebc16afb54 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/CropMilestoneUpdateEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/CropMilestoneUpdateEvent.kt @@ -1,3 +1,5 @@ package at.hannibal2.skyhanni.events -class CropMilestoneUpdateEvent : LorenzEvent() +import at.hannibal2.skyhanni.api.event.SkyHanniEvent + +object CropMilestoneUpdateEvent : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/DungeonBossRoomEnterEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/DungeonBossRoomEnterEvent.kt index 9f372d5c31c2..ec1f35412f58 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/DungeonBossRoomEnterEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/DungeonBossRoomEnterEvent.kt @@ -1,3 +1,5 @@ package at.hannibal2.skyhanni.events -class DungeonBossRoomEnterEvent : LorenzEvent() +import at.hannibal2.skyhanni.api.event.SkyHanniEvent + +object DungeonBossRoomEnterEvent : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/DungeonEnterEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/DungeonEnterEvent.kt index 3b0f09c4a096..1703b8a00e9a 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/DungeonEnterEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/DungeonEnterEvent.kt @@ -1,3 +1,4 @@ package at.hannibal2.skyhanni.events +@Suppress("UnusedPrivateProperty") class DungeonEnterEvent(dungeonFloor: String) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/DungeonStartEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/DungeonStartEvent.kt index a2b127371089..bb3cb36c3d45 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/DungeonStartEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/DungeonStartEvent.kt @@ -1,3 +1,4 @@ package at.hannibal2.skyhanni.events +@Suppress("UnusedPrivateProperty") class DungeonStartEvent(dungeonFloor: String) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/LorenzWarpEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/LorenzWarpEvent.kt deleted file mode 100644 index 170dcabe941d..000000000000 --- a/src/main/java/at/hannibal2/skyhanni/events/LorenzWarpEvent.kt +++ /dev/null @@ -1,3 +0,0 @@ -package at.hannibal2.skyhanni.events - -class LorenzWarpEvent : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/MobEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/MobEvent.kt index 10172cb5fcd8..07990ff222c5 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/MobEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/MobEvent.kt @@ -21,8 +21,6 @@ open class MobEvent(val mob: Mob) : LorenzEvent() { class Projectile(mob: Mob) : DeSpawn(mob) } - // TODO replace with "isFirstTime" parameter in the Spawn event. Also create an actual "player sees the mob for the first time" event - @Deprecated("Old. Will get replaced soon.") open class FirstSeen(mob: Mob) : MobEvent(mob) { class SkyblockMob(mob: Mob) : FirstSeen(mob) class Summon(mob: Mob) : FirstSeen(mob) diff --git a/src/main/java/at/hannibal2/skyhanni/events/NEURenderEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/NEURenderEvent.kt index c2bcc9b49a0e..af85871783d4 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/NEURenderEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/NEURenderEvent.kt @@ -1,6 +1,5 @@ package at.hannibal2.skyhanni.events -import net.minecraftforge.fml.common.eventhandler.Cancelable +import at.hannibal2.skyhanni.api.event.CancellableSkyHanniEvent -@Cancelable -class NEURenderEvent : LorenzEvent() +class NEURenderEvent : CancellableSkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/SackDataUpdateEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/SackDataUpdateEvent.kt index f9e3831d15f0..f156d31fc5cb 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/SackDataUpdateEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/SackDataUpdateEvent.kt @@ -1,3 +1,5 @@ package at.hannibal2.skyhanni.events -class SackDataUpdateEvent : LorenzEvent() +import at.hannibal2.skyhanni.api.event.SkyHanniEvent + +object SackDataUpdateEvent : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/SkyHanniWarpEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/SkyHanniWarpEvent.kt new file mode 100644 index 000000000000..18560da4c4c0 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/events/SkyHanniWarpEvent.kt @@ -0,0 +1,5 @@ +package at.hannibal2.skyhanni.events + +import at.hannibal2.skyhanni.api.event.SkyHanniEvent + +object SkyHanniWarpEvent : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/SlayerQuestCompleteEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/SlayerQuestCompleteEvent.kt index b7e0edfedd59..6b0185fe10bf 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/SlayerQuestCompleteEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/SlayerQuestCompleteEvent.kt @@ -1,3 +1,5 @@ package at.hannibal2.skyhanni.events -class SlayerQuestCompleteEvent : LorenzEvent() +import at.hannibal2.skyhanni.api.event.SkyHanniEvent + +object SlayerQuestCompleteEvent : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/bingo/BingoCardUpdateEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/bingo/BingoCardUpdateEvent.kt index de9a83214a85..eed37ff0a6a0 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/bingo/BingoCardUpdateEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/bingo/BingoCardUpdateEvent.kt @@ -2,4 +2,4 @@ package at.hannibal2.skyhanni.events.bingo import at.hannibal2.skyhanni.api.event.SkyHanniEvent -class BingoCardUpdateEvent : SkyHanniEvent() +object BingoCardUpdateEvent : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/entity/EntityLeaveWorldEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/entity/EntityLeaveWorldEvent.kt new file mode 100644 index 000000000000..74d885e1190e --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/events/entity/EntityLeaveWorldEvent.kt @@ -0,0 +1,6 @@ +package at.hannibal2.skyhanni.events.entity + +import at.hannibal2.skyhanni.api.event.GenericSkyHanniEvent +import net.minecraft.entity.Entity + +class EntityLeaveWorldEvent(val entity: T) : GenericSkyHanniEvent(entity.javaClass) 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 index c4c299b1338f..54df3b20b0ae 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/garden/pests/PestUpdateEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/garden/pests/PestUpdateEvent.kt @@ -2,4 +2,4 @@ package at.hannibal2.skyhanni.events.garden.pests import at.hannibal2.skyhanni.api.event.SkyHanniEvent -class PestUpdateEvent : SkyHanniEvent() +object PestUpdateEvent : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/minecraft/ClientDisconnectEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/minecraft/ClientDisconnectEvent.kt index 6c7a5e8a1b4c..1a6b31c4c9bf 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/minecraft/ClientDisconnectEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/minecraft/ClientDisconnectEvent.kt @@ -2,4 +2,4 @@ package at.hannibal2.skyhanni.events.minecraft import at.hannibal2.skyhanni.api.event.SkyHanniEvent -class ClientDisconnectEvent : SkyHanniEvent() +object ClientDisconnectEvent : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/skyblock/AreaChangeEvents.kt b/src/main/java/at/hannibal2/skyhanni/events/skyblock/AreaChangeEvents.kt index b262ea9fbe44..340187030f2d 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/skyblock/AreaChangeEvents.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/skyblock/AreaChangeEvents.kt @@ -4,3 +4,4 @@ import at.hannibal2.skyhanni.api.event.SkyHanniEvent // Detect area changes by looking at the scoreboard. class ScoreboardAreaChangeEvent(val area: String, val previousArea: String?) : SkyHanniEvent() +class GraphAreaChangeEvent(val area: String, val previousArea: String?) : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/utils/PreInitFinishedEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/utils/PreInitFinishedEvent.kt index 1d52761ed2dd..e2ab833a7643 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/utils/PreInitFinishedEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/utils/PreInitFinishedEvent.kt @@ -2,4 +2,4 @@ package at.hannibal2.skyhanni.events.utils import at.hannibal2.skyhanni.api.event.SkyHanniEvent -class PreInitFinishedEvent : SkyHanniEvent() +object PreInitFinishedEvent : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoAPI.kt index 5950f484d565..b4ba01d58f0a 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoAPI.kt @@ -111,7 +111,7 @@ object BingoAPI { } + LorenzUtils.formatPercentage(percentage) fun getBingoIcon(rank: Int): String { - val rankIcon = getIcon(rank) ?: "" + val rankIcon = getIcon(rank).orEmpty() return if (rank != -1) { "$rankIcon $rank" } else { diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/MinionCraftHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/MinionCraftHelper.kt index 6f7a062f85e5..24835a458859 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/bingo/MinionCraftHelper.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/MinionCraftHelper.kt @@ -98,7 +98,8 @@ object MinionCraftHelper { return newDisplay } - private fun loadFromInventory(mainInventory: Array): Pair, MutableMap> { + private fun loadFromInventory(mainInventory: Array): + Pair, MutableMap> { init() val minions = mutableMapOf() @@ -115,18 +116,20 @@ object MinionCraftHelper { val allMinions = tierOneMinions.toMutableList() minions.values.mapTo(allMinions) { it.addOneToId() } - for (item in mainInventory) { - val name = item?.name?.removeColor() ?: continue - if (item.hasEnchantments()) continue + for (item in mainInventory.filterNotNull()) { + val name = item.name.removeColor() val rawId = item.getInternalName() - if (!isMinionName(name)) { - if (!allIngredients.contains(rawId)) continue - if (!isAllowed(allMinions, rawId)) continue - val (itemId, multiplier) = NEUItems.getPrimitiveMultiplier(rawId) - val old = otherItems.getOrDefault(itemId, 0) - otherItems[itemId] = old + item.stackSize * multiplier - } + if ( + item.hasEnchantments() || + !isMinionName(name) || + !allIngredients.contains(rawId) || + !isAllowed(allMinions, rawId) + ) continue + + val (itemId, multiplier) = NEUItems.getPrimitiveMultiplier(rawId) + val old = otherItems.getOrDefault(itemId, 0) + otherItems[itemId] = old + item.stackSize * multiplier } FirstMinionTier.firstMinionTier(otherItems, minions, tierOneMinions, tierOneMinionsDone) @@ -144,7 +147,9 @@ object MinionCraftHelper { if (ingredientInternalName == internalName) return true val ingredientPrimitive = NEUItems.getPrimitiveMultiplier(ingredientInternalName) - if (primitiveStack.internalName == ingredientPrimitive.internalName && primitiveStack.amount < ingredientPrimitive.amount) return true + if (primitiveStack.internalName == ingredientPrimitive.internalName && + primitiveStack.amount < ingredientPrimitive.amount + ) return true } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardDisplay.kt index b0f883ac240a..b04133b2abcc 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardDisplay.kt @@ -37,7 +37,6 @@ object BingoCardDisplay { private var hasHiddenPersonalGoals = false private const val MAX_PERSONAL_GOALS = 20 - private const val MAX_COMMUNITY_GOALS = 5 private val config get() = SkyHanniMod.feature.event.bingo.bingoCard private var displayMode = 0 @@ -129,7 +128,7 @@ object BingoCardDisplay { private fun percentageFormat(it: BingoGoal) = it.communtyGoalPercentage?.let { " " + BingoAPI.getCommunityPercentageColor(it) - } ?: "" + }.orEmpty() private fun MutableList.addPersonalGoals() { val todo = BingoAPI.personalGoals.filter { !it.done }.toMutableList() diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardReader.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardReader.kt index 1afa6859dc3f..98b266053e04 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardReader.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardReader.kt @@ -96,7 +96,7 @@ object BingoCardReader { } BingoAPI.lastBingoCardOpenTime = SimpleTimeMark.now() - BingoCardUpdateEvent().post() + BingoCardUpdateEvent.post() } private fun bingoGoalDifference(bingoGoal: BingoGoal, new: Double) { @@ -163,7 +163,7 @@ object BingoCardReader { val goal = BingoAPI.personalGoals.firstOrNull { it.displayName == name } ?: return goal.done = true BingoGoalReachedEvent(goal).post() - BingoCardUpdateEvent().post() + BingoCardUpdateEvent.post() } private fun BingoData.getDescriptionLine() = "§7" + note.joinToString(" ") diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/nextstephelper/BingoNextStepHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/nextstephelper/BingoNextStepHelper.kt index 69602ec70765..128ca00d1fa2 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/nextstephelper/BingoNextStepHelper.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/nextstephelper/BingoNextStepHelper.kt @@ -167,7 +167,9 @@ object BingoNextStepHelper { } } } - if (currentStep is PartialProgressItemsStep && currentStep.displayName == RHYS_TASK_NAME && event.message == "§e[NPC] §dRhys§f: §rThank you for the items!§r") { + if (currentStep is PartialProgressItemsStep && currentStep.displayName == RHYS_TASK_NAME && + event.message == "§e[NPC] §dRhys§f: §rThank you for the items!§r" + ) { currentStep.amountHavingHidden -= 10 } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilter.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilter.kt index 28a2b4b4f081..731c6d7a2b3f 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilter.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilter.kt @@ -11,6 +11,7 @@ import at.hannibal2.skyhanni.features.garden.GardenAPI import at.hannibal2.skyhanni.features.garden.pests.PestFinder import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.RegexUtils.groupOrEmpty import at.hannibal2.skyhanni.utils.RegexUtils.groupOrNull import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.RegexUtils.matches @@ -29,6 +30,7 @@ object ChatFilter { // // Lobby Messages + @Suppress("MaxLineLength") private val lobbyPatterns = listOf( // player join "(?: §b>§c>§a>§r §r)?.* §6(?:joined|(?:spooked|slid) into) the lobby!(?:§r §a<§c<§b<)?".toPattern(), @@ -159,6 +161,7 @@ object ChatFilter { ) // Slayer Drop + @Suppress("MaxLineLength") private val slayerDropPatterns = listOf( // Zombie "§b§lRARE DROP! §r§7\\(§r§f§r§9Revenant Viscera§r§7\\) (.*)".toPattern(), @@ -263,6 +266,7 @@ object ChatFilter { ) // Annoying Spam + @Suppress("MaxLineLength") private val annoyingSpamPatterns = listOf( "§7Your Implosion hit (.*) for §r§c(.*) §r§7damage.".toPattern(), "§7Your Molten Wave hit (.*) for §r§c(.*) §r§7damage.".toPattern(), @@ -520,7 +524,7 @@ object ChatFilter { * @param message The message to check * @return The reason why the message was blocked, empty if not blocked */ - @Suppress("CyclomaticComplexMethod") + @Suppress("CyclomaticComplexMethod", "MaxLineLength") private fun block(message: String): String? = when { config.hypixelHub && message.isPresent("lobby") -> "lobby" config.empty && StringUtils.isEmpty(message) -> "empty" @@ -566,7 +570,7 @@ object ChatFilter { val powderMiningMatchResult = PowderMiningChatFilter.block(event.message) if (powderMiningMatchResult == "no_filter") { genericMiningRewardMessage.matchMatcher(event.message) { - val reward = groupOrNull("reward") ?: "" + val reward = groupOrEmpty("reward") val amountFormat = groupOrNull("amount")?.let { "§a+ §b$it§r" } ?: "§a+§r" @@ -616,10 +620,10 @@ object ChatFilter { * @see messagesContainsMap * @see messagesStartsWithMap */ - private fun String.isPresent(key: String) = this in (messagesMap[key] ?: emptyList()) || - (patternsMap[key] ?: emptyList()).any { it.matches(this) } || - (messagesContainsMap[key] ?: emptyList()).any { this.contains(it) } || - (messagesStartsWithMap[key] ?: emptyList()).any { this.startsWith(it) } + private fun String.isPresent(key: String) = this in (messagesMap[key].orEmpty()) || + (patternsMap[key].orEmpty()).any { it.matches(this) } || + (messagesContainsMap[key].orEmpty()).any { this.contains(it) } || + (messagesStartsWithMap[key].orEmpty()).any { this.startsWith(it) } @SubscribeEvent fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/CompactSplashPotionMessage.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/CompactSplashPotionMessage.kt index 7547ae6ab24b..96c7a8fe97cf 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/chat/CompactSplashPotionMessage.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/CompactSplashPotionMessage.kt @@ -15,6 +15,7 @@ object CompactSplashPotionMessage { private val config get() = SkyHanniMod.feature.chat.compactPotionMessages + @Suppress("MaxLineLength") private val potionEffectPatternList = listOf( "§a§lBUFF! §fYou were splashed by (?.*) §fwith §r(?.*)§r§f! Press TAB or type /effects to view your active effects!".toPattern(), "§a§lBUFF! §fYou have gained §r(?.*)§r§f! Press TAB or type /effects to view your active effects!".toPattern(), @@ -55,7 +56,7 @@ object CompactSplashPotionMessage { val byPlayer = groupOrNull("playerName")?.let { player -> val displayName = player.cleanPlayerName(displayName = true) " §aby $displayName" - } ?: "" + }.orEmpty() sendMessage("§a§lPotion Effect! §r$effectName$byPlayer") } != null } diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/PowderMiningChatFilter.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/PowderMiningChatFilter.kt index 61658a9de62e..22db96d30882 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/chat/PowderMiningChatFilter.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/PowderMiningChatFilter.kt @@ -64,6 +64,7 @@ object PowderMiningChatFilter { * REGEX-TEST: §cYou need a tool with a §r§aBreaking Power §r§cof §r§66§r§c to mine Ruby Gemstone Block§r§c! Speak to §r§dFragilis §r§cby the entrance to the Crystal Hollows to learn more! * REGEX-TEST: §cYou need a tool with a §r§aBreaking Power §r§cof §r§64§r§c to mine Mithril§r§c! Speak to §r§dFragilis §r§cby the entrance to the Crystal Hollows to learn more! */ + @Suppress("MaxLineLength") private val breakingPowerPattern by patternGroup.pattern( "warning.breakingpower", "§cYou need a tool with a §r§aBreaking Power §r§cof (?:§.)*\\d+§r§c to mine .+", @@ -217,6 +218,7 @@ object PowderMiningChatFilter { * REGEX-TEST: §r§9Electron Transmitter * REGEX-TEST: §r§9Superlite Motor */ + @Suppress("MaxLineLength") private val robotPartsPattern by patternGroup.pattern( "reward.robotparts", "§r§9(?:FTX 3070|Synthetic Heart|Control Switch|Robotron Reflector|Electron Transmitter|Superlite Motor)( §r§8x(?[\\d,]+))?", diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/StashCompact.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/StashCompact.kt new file mode 100644 index 000000000000..bcb4f61945bc --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/StashCompact.kt @@ -0,0 +1,122 @@ +package at.hannibal2.skyhanni.features.chat + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.LorenzChatEvent +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.NumberUtil.formatIntOrNull +import at.hannibal2.skyhanni.utils.RegexUtils.groupOrNull +import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.StringUtils +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +@SkyHanniModule +object StashCompact { + + // + private val patternGroup = RepoPattern.group("stash.compact") + + /** + * REGEX-TEST: §f §7You have §3226 §7materials stashed away! + * REGEX-TEST: §f §7You have §31,000 §7items stashed away! + */ + private val materialCountPattern by patternGroup.pattern( + "material.count", + "§f *§7You have §3(?[\\d,]+) (?:§.)+(?item|material)s? stashed away!.*", + ) + + /** + * REGEX-TEST: §f §8(This totals 1 type of material stashed!) + * REGEX-TEST: §f §8(This totals 2 types of items stashed!) + * REGEX-TEST: §f §8(This totals 3 types of materials stashed!) + * REGEX-TEST: §f §8(This totals 4 types of items stashed!) + */ + private val differingMaterialsCountPattern by patternGroup.pattern( + "differing.materials.count", + "§f *§8\\(This totals (?[\\d,]+) types? of (?item|material)s? stashed!\\).*", + ) + + /** + * REGEX-TEST: §f §3§l>>> §3§lCLICK HERE§b to pick them up! §3§l<<< + */ + private val pickupStashPattern by patternGroup.pattern( + "pickup.stash", + "§f *§3§l>>> §3§lCLICK HERE§b to pick (?:them|it) up! §3§l<<<.*", + ) + + /** + * REGEX-TEST: §eOne or more items didn't fit in your inventory and were added to your item stash! §6Click here to pick them up! + * REGEX-TEST: §eOne or more materials didn't fit in your inventory and were added to your material stash! §6Click here to pick them up! + */ + @Suppress("MaxLineLength") + private val genericAddedToStashPattern by patternGroup.pattern( + "generic", + "§eOne or more (?:item|material)s? didn't fit in your inventory and were added to your (?:item|material) stash! §6Click here §eto pick them up!", + ) + // + + private val config get() = SkyHanniMod.feature.chat.filterType.stashMessages + + private var lastMaterialCount = 0 + private var lastDifferingMaterialsCount = 0 + private var lastType = "" + + private var lastSentMaterialCount = 0 + private var lastSentType = "" + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + if (!isEnabled()) return + + genericAddedToStashPattern.matchMatcher(event.message) { + event.blockedReason = "stash_compact" + } + + materialCountPattern.matchMatcher(event.message) { + groupOrNull("count")?.formatIntOrNull()?.let { count -> + lastMaterialCount = count + } + event.blockedReason = "stash_compact" + } + + differingMaterialsCountPattern.matchMatcher(event.message) { + groupOrNull("count")?.formatIntOrNull()?.let { count -> + lastDifferingMaterialsCount = count + } + groupOrNull("type")?.let { type -> + lastType = type + } + event.blockedReason = "stash_compact" + } + + if (pickupStashPattern.matches(event.message)) { + event.blockedReason = "stash_compact" + if (lastMaterialCount <= config.hideLowWarningsThreshold) return + if (config.hideDuplicateCounts && lastMaterialCount == lastSentMaterialCount && lastType == lastSentType) return + + sendCompactedStashMessage() + } + } + + private fun sendCompactedStashMessage() { + val typeNameFormat = StringUtils.pluralize(lastMaterialCount, lastType) + val typeFormat = StringUtils.pluralize(lastDifferingMaterialsCount, "type") + ChatUtils.clickableChat( + "§eYou have §6$lastMaterialCount §e$typeNameFormat in stash§6, " + + "§etotalling §6$lastDifferingMaterialsCount $typeFormat§6. " + + "§eClick to ${if (config.useViewStash) "§6view" else "§6pickup"} §estash§6.", + onClick = { + if (config.useViewStash) HypixelCommands.viewStash(lastType) + else HypixelCommands.pickupStash() + }, + ) + lastSentMaterialCount = lastMaterialCount + lastSentType = lastType + } + + private fun isEnabled() = LorenzUtils.inSkyBlock && config.enabled +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/translation/Translator.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/translation/Translator.kt index ca827432fad9..b4e434c1a2d1 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/chat/translation/Translator.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/translation/Translator.kt @@ -119,8 +119,8 @@ object Translator { sourceLanguage: String = "auto", ): Array? { // TODO add &dj=1 to use named json - val url = "https://translate.googleapis.com/translate_a/single?client=gtx&dt=t&sl=$sourceLanguage&tl=$targetLanguage&q=" + - URLEncoder.encode(message, "UTF-8") + val encode = URLEncoder.encode(message, "UTF-8") + val url = "https://translate.googleapis.com/translate_a/single?client=gtx&dt=t&sl=$sourceLanguage&tl=$targetLanguage&q=$encode" var messageToSend = "" val fullResponse = getJSONResponse(url).asJsonArray diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/ArmorStackDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/ArmorStackDisplay.kt index 942adc20b901..3ca87ef98994 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/ArmorStackDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/ArmorStackDisplay.kt @@ -29,7 +29,7 @@ object ArmorStackDisplay { if (!isEnabled()) return val stacks = armorStackPattern.findMatcher(event.actionBar) { "§6§l" + group("stack") - } ?: "" + }.orEmpty() display = stacks } diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/BestiaryData.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/BestiaryData.kt index f40e437e5403..f89ad8c87d45 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/BestiaryData.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/BestiaryData.kt @@ -403,7 +403,8 @@ object BestiaryData { cat.familiesCompleted == cat.totalFamilies -> "§c§lCompleted!" cat.familiesFound == cat.totalFamilies -> "§b${cat.familiesCompleted}§7/§b${cat.totalFamilies} §7completed" cat.familiesFound < cat.totalFamilies -> - "§b${cat.familiesFound}§7/§b${cat.totalFamilies} §7found, §b${cat.familiesCompleted}§7/§b${cat.totalFamilies} §7completed" + "§b${cat.familiesFound}§7/§b${cat.totalFamilies} §7found, " + + "§b${cat.familiesCompleted}§7/§b${cat.totalFamilies} §7completed" else -> continue } @@ -448,7 +449,8 @@ object BestiaryData { return true } else if (name == "Search Results") { val loreList = stack.getLore() - if (loreList.size >= 2 && loreList[0].startsWith("§7Query: §a") && + if (loreList.size >= 2 && + loreList[0].startsWith("§7Query: §a") && loreList[1].startsWith("§7Results: §a") ) { return true @@ -464,7 +466,7 @@ object BestiaryData { enum class NumberType(val type: String) { INT("Normal (1, 2, 3)"), - ROMAN("Roman (I, II, III") + ROMAN("Roman (I, II, III)") } enum class DisplayType(val type: String) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/BroodmotherFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/BroodmotherFeatures.kt index d122ba342fee..6b324ffdc2fa 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/BroodmotherFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/BroodmotherFeatures.kt @@ -50,7 +50,7 @@ object BroodmotherFeatures { @SubscribeEvent fun onTabListUpdate(event: WidgetUpdateEvent) { if (!event.isWidget(TabWidget.BROODMOTHER)) return - val newStage = event.widget.matchMatcherFirstLine { group("stage") } ?: "" + val newStage = event.widget.matchMatcherFirstLine { group("stage") }.orEmpty() if (newStage.isNotEmpty() && newStage != lastStage.toString()) { lastStage = currentStage currentStage = StageEntry.valueOf(newStage.replace("!", "").uppercase()) diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/FlareDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/FlareDisplay.kt index c5804ea37c40..fe538bb180af 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/FlareDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/FlareDisplay.kt @@ -42,6 +42,8 @@ object FlareDisplay { private val MAX_FLARE_TIME = 3.minutes + // TODO: Move to repo + @Suppress("MaxLineLength") private val flareSkins = mapOf( "ewogICJ0aW1lc3RhbXAiIDogMTY0NjY4NzMwNjIyMywKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjJlMmJmNmMxZWMzMzAyNDc5MjdiYTYzNDc5ZTU4NzJhYzY2YjA2OTAzYzg2YzgyYjUyZGFjOWYxYzk3MTQ1OCIKICAgIH0KICB9Cn0=" to FlareType.WARNING, @@ -120,7 +122,7 @@ object FlareDisplay { else -> {} } } - display = newDisplay ?: emptyList() + display = newDisplay.orEmpty() } private fun getRemainingTime(flare: Flare): Duration { diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/SpidersDenAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/SpidersDenAPI.kt index af1dd8430186..8b9ff035e662 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/SpidersDenAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/SpidersDenAPI.kt @@ -1,11 +1,26 @@ package at.hannibal2.skyhanni.features.combat +import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.data.ScoreboardData -import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardPattern import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule -import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland +import at.hannibal2.skyhanni.utils.RegexUtils.anyMatches +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern @SkyHanniModule object SpidersDenAPI { - fun isAtTopOfNest(): Boolean = ScoreboardData.sidebarLinesFormatted.any { ScoreboardPattern.broodmotherPattern.matches(it) } + + private val repoGroup = RepoPattern.group("combat.spidersden") + + /** + * REGEX-TEST: §4Broodmother§7: §6Soon + */ + val broodmotherPattern by repoGroup.pattern( + "broodmother", + "§4Broodmother§7: §[e64](?:Slain|Dormant|Soon|Awakening|Imminent|Alive!)", + ) + + fun inSpidersDen() = IslandType.SPIDER_DEN.isInIsland() + + fun isAtTopOfNest() = inSpidersDen() && broodmotherPattern.anyMatches(ScoreboardData.sidebarLinesFormatted) } diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/DamageIndicatorManager.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/DamageIndicatorManager.kt index 7f5b42e3c538..1a72056910d3 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/DamageIndicatorManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/DamageIndicatorManager.kt @@ -91,7 +91,7 @@ object DamageIndicatorManager { return damagePattern.matcher(name).matches() } - fun isBossSpawned(type: BossType) = data.entries.find { it.value.bossType == type } != null + fun isBossSpawned(type: BossType) = data.entries.any { it.value.bossType == type } fun isBossSpawned(vararg types: BossType) = types.any { isBossSpawned(it) } diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/MobFinder.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/MobFinder.kt index 44c7608c2b6b..8e0ae7dee60d 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/MobFinder.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/MobFinder.kt @@ -349,6 +349,7 @@ class MobFinder { } // TODO testing and use sidebar data + @Suppress("UnusedParameter") private fun tryAddEntityDragon(entity: EntityLivingBase) = when { IslandType.THE_END.isInIsland() -> EntityResult(bossType = BossType.END_ENDER_DRAGON) IslandType.WINTER.isInIsland() -> EntityResult(bossType = BossType.WINTER_REINDRAKE) diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/ghostcounter/GhostCounter.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/ghostcounter/GhostCounter.kt index 2ef652e4a93a..28020c006510 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/ghostcounter/GhostCounter.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/ghostcounter/GhostCounter.kt @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.features.combat.ghostcounter import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.config.features.combat.ghostcounter.GhostCounterConfig.GhostDisplayEntry import at.hannibal2.skyhanni.data.IslandType @@ -11,11 +12,11 @@ import at.hannibal2.skyhanni.events.ConfigLoadEvent import at.hannibal2.skyhanni.events.GuiRenderEvent import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent import at.hannibal2.skyhanni.events.LorenzChatEvent -import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.events.PurseChangeCause import at.hannibal2.skyhanni.events.PurseChangeEvent import at.hannibal2.skyhanni.events.SecondPassedEvent import at.hannibal2.skyhanni.events.TabListUpdateEvent +import at.hannibal2.skyhanni.events.skyblock.GraphAreaChangeEvent import at.hannibal2.skyhanni.features.combat.ghostcounter.GhostData.Option import at.hannibal2.skyhanni.features.combat.ghostcounter.GhostData.Option.KILLS import at.hannibal2.skyhanni.features.combat.ghostcounter.GhostData.bestiaryData @@ -25,7 +26,6 @@ import at.hannibal2.skyhanni.features.combat.ghostcounter.GhostUtil.isUsingCTGho import at.hannibal2.skyhanni.features.combat.ghostcounter.GhostUtil.preFormat import at.hannibal2.skyhanni.features.combat.ghostcounter.GhostUtil.prettyTime import at.hannibal2.skyhanni.features.inventory.bazaar.BazaarApi.getBazaarData -import at.hannibal2.skyhanni.features.misc.IslandAreas import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.ChatUtils.chat @@ -81,6 +81,8 @@ object GhostCounter { "skillxp", "[+](?[0-9,.]+) \\((?[0-9,.]+)(?:/(?[0-9,.]+))?\\)", ) + + @Suppress("MaxLineLength") private val combatSectionPattern by patternGroup.pattern( "combatsection", ".*[+](?[0-9,.]+) (?[A-Za-z]+) \\((?(?[0-9.,]+)/(?[0-9.,]+)|(?[0-9.]+)%)\\).*", @@ -282,7 +284,10 @@ object GhostCounter { val moneyMadeTips = buildList { for ((name, count, value) in priceMap) { moneyMade += (count.toLong() * value.toLong()) - add("$name: §b${value.addSeparators()} §fx §b${count.addSeparators()} §f= §6${(value.toLong() * count.toLong()).addSeparators()}") + add( + "$name: §b${value.addSeparators()} §fx §b${count.addSeparators()} §f= " + + "§6${(value.toLong() * count.toLong()).addSeparators()}" + ) } add("§bTotal: §6${moneyMade.addSeparators()}") add("§eClick to copy to clipboard!") @@ -342,9 +347,9 @@ object GhostCounter { } } - @SubscribeEvent - fun onTick(event: LorenzTickEvent) { - inMist = IslandAreas.currentAreaName == "The Mist" + @HandleEvent + fun onAreaChange(event: GraphAreaChangeEvent) { + inMist = event.area == "The Mist" } @SubscribeEvent diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/mobs/AreaMiniBossFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/mobs/AreaMiniBossFeatures.kt index 5c480b8a1124..3d5dd3fd75da 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/mobs/AreaMiniBossFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/mobs/AreaMiniBossFeatures.kt @@ -100,7 +100,7 @@ object AreaMiniBossFeatures { LorenzVec(-573, 51, -353), ), MILLENNIA_AGED_BLAZE( - "Millenia-Aged Blaze", LorenzColor.DARK_RED, 60, + "Millennia-Aged Blaze", LorenzColor.DARK_RED, 60, LorenzVec(-292, 97, -999), LorenzVec(-232, 77, -951), LorenzVec(-304, 73, -952), diff --git a/src/main/java/at/hannibal2/skyhanni/features/commands/HelpCommand.kt b/src/main/java/at/hannibal2/skyhanni/features/commands/HelpCommand.kt index 2eb5dc3fb893..f544770985b3 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/commands/HelpCommand.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/commands/HelpCommand.kt @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.features.commands -import at.hannibal2.skyhanni.config.commands.Commands +import at.hannibal2.skyhanni.config.commands.CommandBuilder +import at.hannibal2.skyhanni.config.commands.Commands.commandList import at.hannibal2.skyhanni.utils.StringUtils.splitLines import at.hannibal2.skyhanni.utils.chat.Text import at.hannibal2.skyhanni.utils.chat.Text.hover @@ -12,7 +13,7 @@ object HelpCommand { private const val COMMANDS_PER_PAGE = 15 private const val HELP_ID = -6457563 - private fun createCommandEntry(command: Commands.CommandInfo): IChatComponent { + private fun createCommandEntry(command: CommandBuilder): IChatComponent { val category = command.category val color = category.color val description = command.description.splitLines(200).replace("§r", "§7") @@ -30,7 +31,7 @@ object HelpCommand { } } - private fun showPage(page: Int, search: String, commands: List) { + private fun showPage(page: Int, search: String, commands: List) { val filtered = commands.filter { it.name.contains(search, ignoreCase = true) || it.description.contains(search, ignoreCase = true) } @@ -47,7 +48,7 @@ object HelpCommand { ) { createCommandEntry(it) } } - fun onCommand(args: Array, commands: List) { + fun onCommand(args: Array) { val page: Int val search: String if (args.firstOrNull() == "-p") { @@ -57,6 +58,6 @@ object HelpCommand { page = 1 search = args.joinToString(" ") } - showPage(page, search, commands) + showPage(page, search, commandList) } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/commands/suggestions/SuggestionProvider.kt b/src/main/java/at/hannibal2/skyhanni/features/commands/suggestions/SuggestionProvider.kt index eda4c704cbcf..deb41e6a202b 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/commands/suggestions/SuggestionProvider.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/commands/suggestions/SuggestionProvider.kt @@ -24,7 +24,7 @@ class SuggestionProvider { fun getSuggestions(command: String): List { val arguments = command.lowercase().split(" ") - val last = arguments.lastOrNull() ?: "" + val last = arguments.lastOrNull().orEmpty() val suggestions = mutableListOf() if (arguments.size != 1) { entry.getEntryForPath(arguments.dropLast(1))?.suggestions?.let { suggestions.addAll(it) } diff --git a/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/PlayerTabComplete.kt b/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/PlayerTabComplete.kt index 95acec9a6931..400818ae8450 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/PlayerTabComplete.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/PlayerTabComplete.kt @@ -99,7 +99,9 @@ object PlayerTabComplete { private fun lazyEntry(getter: () -> List) = LazySuggestionEntry { addAll(getter()) } - fun handleTabComplete(command: String): List? = suggestions.getSuggestions(command).takeIf { it.isNotEmpty() }?.distinct() + fun handleTabComplete(command: String): List? = suggestions.getSuggestions(command).takeIf { + it.isNotEmpty() + }?.distinct() @SubscribeEvent fun onRepoReload(event: RepositoryReloadEvent) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/TabComplete.kt b/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/TabComplete.kt index aa66b69377dd..1e2557b93f37 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/TabComplete.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/TabComplete.kt @@ -23,6 +23,7 @@ object TabComplete { } } + @Suppress("ReturnCount") private fun customTabComplete(fullCommand: String, command: String): List? { GetFromSacksTabComplete.handleTabComplete(command)?.let { return it } PlayerTabComplete.handleTabComplete(fullCommand)?.let { return it } diff --git a/src/main/java/at/hannibal2/skyhanni/features/cosmetics/CosmeticFollowingLine.kt b/src/main/java/at/hannibal2/skyhanni/features/cosmetics/CosmeticFollowingLine.kt index 54ef80f77a4d..8e6d42fe9c00 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/cosmetics/CosmeticFollowingLine.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/cosmetics/CosmeticFollowingLine.kt @@ -58,16 +58,17 @@ object CosmeticFollowingLine { val last2 = locations.keys.toList().takeLast(2) locations.keys.zipWithNext { a, b -> - val locationSpot = locations[b]!! - if (firstPerson && !locationSpot.onGround && b in last7) { - // Do not render the line in the face, keep more distance while the line is in the air - return + locations[b]?.let { + if (firstPerson && !it.onGround && b in last7) { + // Do not render the line in the face, keep more distance while the line is in the air + return + } + if (b in last2 && it.time.passedSince() < 400.milliseconds) { + // Do not render the line directly next to the player, prevent laggy design + return + } + event.draw3DLine(a, b, color, it.getWidth(), !config.behindBlocks) } - if (b in last2 && locationSpot.time.passedSince() < 400.milliseconds) { - // Do not render the line directly next to the player, prevent laggy design - return - } - event.draw3DLine(a, b, color, locationSpot.getWidth(), !config.behindBlocks) } } @@ -86,8 +87,9 @@ object CosmeticFollowingLine { latestLocations.keys.zipWithNext { a, b -> - val locationSpot = latestLocations[b]!! - event.draw3DLine(a, b, color, locationSpot.getWidth(), !config.behindBlocks) + latestLocations[b]?.let { + event.draw3DLine(a, b, color, it.getWidth(), !config.behindBlocks) + } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/CroesusChestTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/CroesusChestTracker.kt index 377d7bfd405f..5db28465e554 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/CroesusChestTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/CroesusChestTracker.kt @@ -269,7 +269,7 @@ object CroesusChestTracker { fun resetChest() = croesusChests?.let { it.clear() it.addAll(generateMaxChest()) - ChatUtils.chat("Kismet State was cleared!") + ChatUtils.chat("Kismet State was Reset!") } @JvmStatic diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonAPI.kt index 7ea372b20d33..62e1541c7e88 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonAPI.kt @@ -63,6 +63,8 @@ object DungeonAPI { val bossStorage: MutableMap? get() = ProfileStorageData.profileSpecific?.dungeons?.bosses private val patternGroup = RepoPattern.group("dungeon") + // TODO: Move to repo + @Suppress("MaxLineLength") private const val WITHER_ESSENCE_TEXTURE = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzRkYjRhZGZhOWJmNDhmZjVkNDE3MDdhZTM0ZWE3OGJkMjM3MTY1OWZjZDhjZDg5MzQ3NDlhZjRjY2U5YiJ9fX0=" @@ -121,7 +123,7 @@ object DungeonAPI { val message = rawMessage.removeColor() val bossName = message.substringAfter("[BOSS] ").substringBefore(":").trim() if ((bossName != "The Watcher") && dungeonFloor != null && checkBossName(bossName) && !inBossRoom) { - DungeonBossRoomEnterEvent().postAndCatch() + DungeonBossRoomEnterEvent.post() inBossRoom = true } } @@ -145,7 +147,7 @@ object DungeonAPI { fun getTime(): String = ScoreboardData.sidebarLinesFormatted.matchFirst(timePattern) { "${groupOrNull("minutes") ?: "00"}:${group("seconds")}" - } ?: "" + }.orEmpty() fun getCurrentBoss(): DungeonFloor? { val floor = dungeonFloor ?: return null @@ -182,7 +184,7 @@ object DungeonAPI { if (dungeonFloor != null && playerClass == null) { val playerTeam = TabListData.getTabList().firstOrNull { it.contains(LorenzUtils.getPlayerName()) - }?.removeColor() ?: "" + }?.removeColor().orEmpty() for (dungeonClass in DungeonClass.entries) { if (playerTeam.contains("(${dungeonClass.scoreboardName} ")) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonBossAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonBossAPI.kt index 5a7d0ff313a8..a352248db326 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonBossAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonBossAPI.kt @@ -29,6 +29,9 @@ object DungeonBossAPI { F7_GOLDOR_5, F7_NECRON, M7_WITHER_KING, + ; + + fun isCurrent(): Boolean = bossPhase == this } private val patternGroup = RepoPattern.group("dungeon.boss.message") @@ -86,7 +89,8 @@ object DungeonBossAPI { * REGEX-TEST: §bmartimavocado§r§a completed a device! (§r§c3§r§a/8) * REGEX-TEST: §bmartimavocado§r§a activated a terminal! (§r§c4§r§a/7) */ - private val goldorTerminalPattern by patternGroup.pattern( + @Suppress("MaxLineLength") + val goldorTerminalPattern by patternGroup.pattern( "f7.goldor.terminalcomplete", "§.(?\\w+)§r§a (?:activated|completed) a (?lever|terminal|device)! \\(§r§c(?\\d)§r§a/(?\\d)\\)", ) @@ -116,13 +120,13 @@ object DungeonBossAPI { ) private fun handlePhaseMessage(message: String) { - if (dungeonFloor == "F6" || dungeonFloor == "M6") when { //move to enum + if (dungeonFloor == "F6" || dungeonFloor == "M6") when { // TODO: move to enum terracottaStartPattern.matches(message) -> changePhase(DungeonBossPhase.F6_TERRACOTTA) giantsStartPattern.matches(message) -> changePhase(DungeonBossPhase.F6_GIANTS) sadanStartPattern.matches(message) -> changePhase(DungeonBossPhase.F6_SADAN) } - if (dungeonFloor == "F7" || dungeonFloor == "M7") { //move to enum + if (dungeonFloor == "F7" || dungeonFloor == "M7") { // TODO: move to enum goldorTerminalPattern.matchMatcher(message) { val currentTerminal = group("currentTerminal").toIntOrNull() ?: return val totalTerminals = group("total").toIntOrNull() ?: return diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonChatFilter.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonChatFilter.kt index 1a566c22579d..e8febb8d3ed4 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonChatFilter.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonChatFilter.kt @@ -25,6 +25,7 @@ object DungeonChatFilter { private val endMessagesEndWith = listOf( " Experience §r§b(Team Bonus)" ) + @Suppress("MaxLineLength") private val abilityPatterns = listOf( "§7Your Guided Sheep hit §r§c(.*) §r§7enemy for §r§c(.*) §r§7damage.".toPattern(), "§a§lBUFF! §fYou were splashed by (.*) §fwith §r§cHealing VIII§r§f!".toPattern(), @@ -99,11 +100,13 @@ object DungeonChatFilter { private val buffMessages = listOf( "§a§lBUFF! §fYou have gained §r§cHealing V§r§f!" ) + @Suppress("MaxLineLength") private val puzzlePatterns = listOf( "§a§lPUZZLE SOLVED! (.*) §r§ewasn't fooled by §r§c(.*)§r§e! §r§4G§r§co§r§6o§r§ed§r§a §r§2j§r§bo§r§3b§r§5!".toPattern(), "§a§lPUZZLE SOLVED! (.*) §r§etied Tic Tac Toe! §r§4G§r§co§r§6o§r§ed§r§a §r§2j§r§bo§r§3b§r§5!".toPattern(), "§4\\[STATUE] Oruo the Omniscient§r§f: §r(.*) §r§fthinks the answer is §r§6 . §r(.*)§r§f! §r§fLock in your party's answer in my Chamber!".toPattern(), ) + @Suppress("MaxLineLength") private val puzzleMessages = listOf( "§4[STATUE] Oruo the Omniscient§r§f: §r§fThough I sit stationary in this prison that is §r§cThe Catacombs§r§f, my knowledge knows no bounds.", "§4[STATUE] Oruo the Omniscient§r§f: §r§fProve your knowledge by answering 3 questions and I shall reward you in ways that transcend time!", @@ -122,6 +125,7 @@ object DungeonChatFilter { "§e§lRIGHT CLICK §r§7on §r§7a §r§8WITHER §r§7door§r§7 to open it. This key can only be used to open §r§a1§r§7 door!", "§e§lRIGHT CLICK §r§7on §r§7the §r§cBLOOD DOOR§r§7 to open it. This key can only be used to open §r§a1§r§7 door!" ) + @Suppress("MaxLineLength") private val pickupPatterns = listOf( "(.*) §r§ehas obtained §r§a§r§9Superboom TNT§r§e!".toPattern(), "(.*) §r§ehas obtained §r§a§r§9Superboom TNT §r§8x2§r§e!".toPattern(), @@ -160,6 +164,7 @@ object DungeonChatFilter { "(.*)§a is now ready!".toPattern(), "§aDungeon starts in (.*) seconds.".toPattern(), ) + @Suppress("MaxLineLength") private val prepareMessages = listOf( "§aYour active Potion Effects have been paused and stored. They will be restored when you leave Dungeons! You are not allowed to use existing Potion Effects while in Dungeons.", "§aDungeon starts in 1 second.", @@ -243,8 +248,8 @@ object DungeonChatFilter { * @see messagesEndsWithMap */ private fun String.isPresent(key: MessageTypes): Boolean { - return this in (messagesMap[key] ?: emptyList()) || - (patternsMap[key] ?: emptyList()).any { it.matches(this) } || - (messagesEndsWithMap[key] ?: emptyList()).any { this.endsWith(it) } + return this in (messagesMap[key].orEmpty()) || + (patternsMap[key].orEmpty()).any { it.matches(this) } || + (messagesEndsWithMap[key].orEmpty()).any { this.endsWith(it) } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonCopilot.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonCopilot.kt index 11d749b668fa..e4bc9b0fc838 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonCopilot.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonCopilot.kt @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.features.dungeon import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.events.CheckRenderEntityEvent import at.hannibal2.skyhanni.events.DungeonBossRoomEnterEvent @@ -133,7 +134,7 @@ object DungeonCopilot { searchForKey = true } - @SubscribeEvent + @HandleEvent fun onDungeonBossRoomEnter(event: DungeonBossRoomEnterEvent) { changeNextStep("Defeat the boss! Good luck :)") } diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonFinderFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonFinderFeatures.kt index 9151c1d9eee2..d808ed085587 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonFinderFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonFinderFeatures.kt @@ -124,8 +124,6 @@ object DungeonFinderFeatures { "§7View and select a dungeon class.", ) - private val allowedSlots = (10..34).filter { it !in listOf(17, 18, 26, 27) } - // Variables used private var selectedClass = "" private var floorStackSize = mapOf() @@ -217,6 +215,8 @@ object DungeonFinderFeatures { val map = mutableMapOf() if (!partyFinderTitlePattern.matches(event.inventoryName)) return map inInventory = true + // TODO: Refactor this to not have so many continue statements + @Suppress("LoopWithTooManyJumpStatements") for ((slot, stack) in event.inventoryItems) { val lore = stack.getLore() if (!checkIfPartyPattern.matches(stack.displayName)) continue diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonHideItems.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonHideItems.kt index 4f29aca52eac..967af0dd3d4b 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonHideItems.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonHideItems.kt @@ -29,25 +29,32 @@ object DungeonHideItems { private val movingSkeletonSkulls = mutableMapOf() // TODO put in skull data repo part - + @Suppress("MaxLineLength") private const val SOUL_WEAVER_HIDER = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMmYyNGVkNjg3NTMwNGZhNGExZjBjNzg1YjJjYjZhNmE3MjU2M2U5ZjNlMjRlYTU1ZTE4MTc4NDUyMTE5YWE2NiJ9fX0=" + @Suppress("MaxLineLength") private const val BLESSING_TEXTURE = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTkzZTIwNjg2MTc4NzJjNTQyZWNkYTFkMjdkZjRlY2U5MWM2OTk5MDdiZjMyN2M0ZGRiODUzMDk0MTJkMzkzOSJ9fX0=" + @Suppress("MaxLineLength") private const val REVIVE_STONE_TEXTURE = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjZhNzZjYzIyZTdjMmFiOWM1NDBkMTI0NGVhZGJhNTgxZjVkZDllMThmOWFkYWNmMDUyODBhNWI0OGI4ZjYxOCJ9fX0K" + @Suppress("MaxLineLength") private const val PREMIUM_FLESH_TEXTURE = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMWE3NWU4YjA0NGM3MjAxYTRiMmU4NTZiZTRmYzMxNmE1YWFlYzY2NTc2MTY5YmFiNTg3MmE4ODUzNGI4MDI1NiJ9fX0K" + @Suppress("MaxLineLength") private const val ABILITY_ORB_TEXTURE = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTAxZTA0MGNiMDFjZjJjY2U0NDI4MzU4YWUzMWQyZTI2NjIwN2M0N2NiM2FkMTM5NzA5YzYyMDEzMGRjOGFkNCJ9fX0=" + @Suppress("MaxLineLength") private const val SUPPORT_ORB_TEXTURE = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTMxYTRmYWIyZjg3ZGI1NDMzMDEzNjUxN2I0NTNhYWNiOWQ3YzBmZTc4NDMwMDcwOWU5YjEwOWNiYzUxNGYwMCJ9fX0=" + @Suppress("MaxLineLength") private const val DAMAGE_ORB_TEXTURE = "eyJ0aW1lc3RhbXAiOjE1NzQ5NTEzMTkwNDQsInByb2ZpbGVJZCI6IjE5MjUyMWI0ZWZkYjQyNWM4OTMxZjAyYTg0OTZlMTFiIiwicHJvZmlsZU5hbWUiOiJTZXJpYWxpemFibGUiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2FiODZkYTJlMjQzYzA1ZGMwODk4YjBjYzVkM2U2NDg3NzE3MzE3N2UwYTIzOTQ0MjVjZWMxMDAyNTljYjQ1MjYifX19" + @Suppress("MaxLineLength") private const val HEALER_FAIRY_TEXTURE = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTZjM2UzMWNmYzY2NzMzMjc1YzQyZmNmYjVkOWE0NDM0MmQ2NDNiNTVjZDE0YzljNzdkMjczYTIzNTIifX19" diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonLividFinder.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonLividFinder.kt index 2a8595af9e8e..6049268c8fcc 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonLividFinder.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonLividFinder.kt @@ -1,11 +1,11 @@ package at.hannibal2.skyhanni.features.dungeon -import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.events.CheckRenderEntityEvent import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent import at.hannibal2.skyhanni.mixins.hooks.RenderLivingEntityHelper +import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.BlockUtils.getBlockStateAt @@ -16,13 +16,13 @@ import at.hannibal2.skyhanni.utils.LorenzColor import at.hannibal2.skyhanni.utils.LorenzColor.Companion.toLorenzColor import at.hannibal2.skyhanni.utils.LorenzVec import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText -import at.hannibal2.skyhanni.utils.RenderUtils.drawWaypointFilled import at.hannibal2.skyhanni.utils.RenderUtils.drawLineToEye +import at.hannibal2.skyhanni.utils.RenderUtils.drawWaypointFilled import at.hannibal2.skyhanni.utils.RenderUtils.exactLocation import net.minecraft.block.BlockStainedGlass -import net.minecraft.client.Minecraft import net.minecraft.client.entity.EntityOtherPlayerMP import net.minecraft.client.entity.EntityPlayerSP +import net.minecraft.client.Minecraft import net.minecraft.entity.item.EntityArmorStand import net.minecraft.potion.Potion import net.minecraft.util.AxisAlignedBB diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonMobManager.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonMobManager.kt index 46450a5645d5..d3f85c1661d6 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonMobManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonMobManager.kt @@ -83,7 +83,7 @@ object DungeonMobManager { fun onRenderWorld(event: LorenzRenderWorldEvent) { if (!fel.highlight.get()) return if (fel.line) { - felOnTheGround.filter { it.canBeSeen() }.forEach { + felOnTheGround.filter { it.canBeSeen(30) }.forEach { event.draw3DLine( it.baseEntity.getLorenzVec().add(y = 0.15), event.exactPlayerEyeLocation(), diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonRankTabListColor.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonRankTabListColor.kt index 3968a3d18a87..df33ee6f6c14 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonRankTabListColor.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonRankTabListColor.kt @@ -3,8 +3,8 @@ package at.hannibal2.skyhanni.features.dungeon import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.events.TabListLineRenderEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule -import at.hannibal2.skyhanni.utils.LorenzUtils.groupOrNull import at.hannibal2.skyhanni.utils.NumberUtil.romanToDecimalIfNecessary +import at.hannibal2.skyhanni.utils.RegexUtils.groupOrEmpty import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.StringUtils.cleanPlayerName import at.hannibal2.skyhanni.utils.StringUtils.stripHypixelMessage @@ -21,6 +21,7 @@ object DungeonRankTabListColor { * REGEX-TEST: §8[§r§9319§r§8] §r§bEmpa_ §r§7α §r§f(§r§dMage XXXIV§r§f) * REGEX-TEST: §8[§r§5393§r§8] §r§c[§r§fYOUTUBE§r§c] Remittal§r§f §r§7Σ§r§7♲ §r§f(§r§dMage XL§r§f) */ + @Suppress("MaxLineLength") private val pattern by patternGroup.pattern( "rank", "^(?:§.)*(?\\[(?:§.)*\\d+(?:§.)*]) (?(?:§.)*\\[(?:§.)*[^]]+(?:§.)*])? ?(?\\S+) (?[^(]*)\\((?:§.)*(?\\S+) (?[CLXVI]+)(?:§.)*\\)(?:§.)*$" @@ -32,7 +33,7 @@ object DungeonRankTabListColor { pattern.matchMatcher(event.text.stripHypixelMessage()) { val sbLevel = group("sbLevel") - val rank = groupOrNull("rank") ?: "" + val rank = groupOrEmpty("rank") val playerName = group("playerName") // val symbols = group("symbols") val className = group("className") diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonsRaceGuide.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonsRaceGuide.kt index 34d0621cdf96..b6a9ac59dfc3 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonsRaceGuide.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonsRaceGuide.kt @@ -42,8 +42,8 @@ object DungeonsRaceGuide { for ((key, map) in data.data) { val nothingNoReturn = map["nothing:no_return"] parkourHelpers[key] = ParkourHelper( - nothingNoReturn?.locations ?: listOf(), - nothingNoReturn?.shortCuts ?: listOf(), + nothingNoReturn?.locations.orEmpty(), + nothingNoReturn?.shortCuts.orEmpty(), platformSize = 1.0, detectionRange = 7.0, depth = false, diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/floor7/TerminalInfo.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/floor7/TerminalInfo.kt new file mode 100644 index 000000000000..bd7b8a4ee7a6 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/floor7/TerminalInfo.kt @@ -0,0 +1,52 @@ +package at.hannibal2.skyhanni.features.dungeon.floor7 + +import at.hannibal2.skyhanni.features.dungeon.DungeonBossAPI +import at.hannibal2.skyhanni.utils.LorenzVec + +private typealias BossPhase = DungeonBossAPI.DungeonBossPhase + +enum class TerminalInfo(val location: LorenzVec, val phase: BossPhase, val text: String) { + P1_TERMINAL_1(LorenzVec(111, 113, 73), BossPhase.F7_GOLDOR_1, "Terminal"), + P1_TERMINAL_2(LorenzVec(111, 119, 79), BossPhase.F7_GOLDOR_1, "Terminal"), + P1_TERMINAL_3(LorenzVec(89, 112, 92), BossPhase.F7_GOLDOR_1, "Terminal"), + P1_TERMINAL_4(LorenzVec(89, 122, 101), BossPhase.F7_GOLDOR_1, "Terminal"), + P1_LEVER_1(LorenzVec(106, 124, 113), BossPhase.F7_GOLDOR_1, "Lever"), + P1_LEVER_2(LorenzVec(94, 124, 113), BossPhase.F7_GOLDOR_1, "Lever"), + P1_DEVICE(LorenzVec(110, 119, 93), BossPhase.F7_GOLDOR_1, "Device"), + + P2_TERMINAL_1(LorenzVec(68, 109, 121), BossPhase.F7_GOLDOR_2, "Terminal"), + P2_TERMINAL_2(LorenzVec(59, 120, 122), BossPhase.F7_GOLDOR_2, "Terminal"), + P2_TERMINAL_3(LorenzVec(47, 109, 121), BossPhase.F7_GOLDOR_2, "Terminal"), + P2_TERMINAL_4(LorenzVec(40, 124, 122), BossPhase.F7_GOLDOR_2, "Terminal"), + P2_TERMINAL_5(LorenzVec(39, 108, 143), BossPhase.F7_GOLDOR_2, "Terminal"), + P2_LEVER_1(LorenzVec(23, 132, 138), BossPhase.F7_GOLDOR_2, "Lever"), + P2_LEVER_2(LorenzVec(27, 124, 127), BossPhase.F7_GOLDOR_2, "Lever"), + P2_DEVICE(LorenzVec(60, 131, 142), BossPhase.F7_GOLDOR_2, "Device"), + + P3_TERMINAL_1(LorenzVec(-3, 109, 112), BossPhase.F7_GOLDOR_3, "Terminal"), + P3_TERMINAL_2(LorenzVec(-3, 119, 93), BossPhase.F7_GOLDOR_3, "Terminal"), + P3_TERMINAL_3(LorenzVec(19, 123, 93), BossPhase.F7_GOLDOR_3, "Terminal"), + P3_TERMINAL_4(LorenzVec(-3, 109, 77), BossPhase.F7_GOLDOR_3, "Terminal"), + P3_LEVER_1(LorenzVec(14, 122, 55), BossPhase.F7_GOLDOR_3, "Lever"), + P3_LEVER_2(LorenzVec(2, 122, 55), BossPhase.F7_GOLDOR_3, "Lever"), + P3_DEVICE(LorenzVec(-2, 119, 77), BossPhase.F7_GOLDOR_3, "Device"), + + P4_TERMINAL_1(LorenzVec(41, 109, 29), BossPhase.F7_GOLDOR_4, "Terminal"), + P4_TERMINAL_2(LorenzVec(44, 121, 29), BossPhase.F7_GOLDOR_4, "Terminal"), + P4_TERMINAL_3(LorenzVec(67, 109, 29), BossPhase.F7_GOLDOR_4, "Terminal"), + P4_TERMINAL_4(LorenzVec(72, 115, 48), BossPhase.F7_GOLDOR_4, "Terminal"), + P4_LEVER_1(LorenzVec(84, 121, 34), BossPhase.F7_GOLDOR_4, "Lever"), + P4_LEVER_2(LorenzVec(86, 128, 46), BossPhase.F7_GOLDOR_4, "Lever"), + P4_DEVICE(LorenzVec(63, 126, 35), BossPhase.F7_GOLDOR_4, "Device"), + ; + + var highlight: Boolean = true + + companion object { + fun resetTerminals() = entries.forEach { it.highlight = true } + + fun getClosestTerminal(input: LorenzVec): TerminalInfo? { + return entries.filter { it.highlight }.minByOrNull { it.location.distance(input) } + } + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/floor7/TerminalWaypoints.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/floor7/TerminalWaypoints.kt new file mode 100644 index 000000000000..f8479507a402 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/floor7/TerminalWaypoints.kt @@ -0,0 +1,56 @@ +package at.hannibal2.skyhanni.features.dungeon.floor7 + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent +import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent +import at.hannibal2.skyhanni.features.dungeon.DungeonAPI +import at.hannibal2.skyhanni.features.dungeon.DungeonBossAPI +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.EntityUtils +import at.hannibal2.skyhanni.utils.LorenzColor +import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText +import at.hannibal2.skyhanni.utils.RenderUtils.drawWaypointFilled +import at.hannibal2.skyhanni.utils.getLorenzVec +import net.minecraft.entity.player.EntityPlayerMP +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +@SkyHanniModule +object TerminalWaypoints { + + private val config get() = SkyHanniMod.feature.dungeon + + @SubscribeEvent + fun onRenderWorld(event: LorenzRenderWorldEvent) { + if (!isEnabled()) return + + for (term in TerminalInfo.entries) { + if (!term.highlight || !term.phase.isCurrent()) continue + event.drawWaypointFilled(term.location, LorenzColor.GREEN.toColor(), seeThroughBlocks = true) + event.drawDynamicText(term.location, term.text, 1.0) + } + } + + @SubscribeEvent + fun onWorldChange(event: LorenzWorldChangeEvent) { + TerminalInfo.resetTerminals() + } + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + if (!inBoss()) return + + val playerName = DungeonBossAPI.goldorTerminalPattern.matchMatcher(event.message) { + group("playerName") + } ?: return + + val playerEntity = EntityUtils.getEntities().find { it.name == playerName } ?: return + val terminal = TerminalInfo.getClosestTerminal(playerEntity.getLorenzVec()) + terminal?.highlight = false + } + + private fun inBoss() = DungeonAPI.inBossRoom && DungeonAPI.isOneOf("F7", "M7") + + private fun isEnabled() = inBoss() && config.terminalWaypoints +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/UniqueGiftingOpportunitiesFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/event/UniqueGiftingOpportunitiesFeatures.kt index b1939a793bf3..88af3da60aa7 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/UniqueGiftingOpportunitiesFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/UniqueGiftingOpportunitiesFeatures.kt @@ -57,6 +57,7 @@ object UniqueGiftingOpportunitiesFeatures { private fun isEnabled() = holdingGift + @Suppress("UnusedPrivateProperty") private const val HAS_NOT_GIFTED_NAMETAG = "§a§lꤥ" private const val HAS_GIFTED_NAMETAG = "§c§lꤥ" 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 index beedfd6a5676..393979ebbf4c 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalGoal.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalGoal.kt @@ -1,12 +1,14 @@ package at.hannibal2.skyhanni.features.event.carnival import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.event.HandleEvent 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.events.skyblock.GraphAreaChangeEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ItemUtils.getLore import at.hannibal2.skyhanni.utils.LorenzUtils @@ -192,6 +194,7 @@ enum class CarnivalGoal( } private var display = emptyList() + private var inCarnival = false @SubscribeEvent fun onGuiRenderGuiOverlayRender(event: GuiRenderEvent.GuiOverlayRenderEvent) { @@ -205,8 +208,13 @@ enum class CarnivalGoal( config.goalsPosition.renderRenderables(display, posLabel = "Carnival Goals") } + @HandleEvent + fun onAreaChange(event: GraphAreaChangeEvent) { + inCarnival = event.area == "Carnival" + } + fun isEnabled() = - LorenzUtils.inSkyBlock && config.showGoals && Perk.CHIVALROUS_CARNIVAL.isActive && LorenzUtils.skyBlockArea == "Carnival" + LorenzUtils.inSkyBlock && config.showGoals && Perk.CHIVALROUS_CARNIVAL.isActive && inCarnival private enum class GoalType(val item: Item, display: String) { FRUIT_DIGGING(Item.getItemFromBlock(Blocks.sand), "§6Fruit Digging"), @@ -232,5 +240,4 @@ enum class CarnivalGoal( val getGoals get() = CarnivalGoal.entries.filter { it.type == this } } } - } 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 index d77861872d6d..024d1446451c 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalReminder.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalReminder.kt @@ -49,6 +49,7 @@ object CarnivalReminder { /** 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. */ + @Suppress("MaxLineLength") 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.", diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/diana/DianaFixChat.kt b/src/main/java/at/hannibal2/skyhanni/features/event/diana/DianaFixChat.kt index aefce4e58088..a51e94f8d740 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/diana/DianaFixChat.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/diana/DianaFixChat.kt @@ -59,7 +59,10 @@ object DianaFixChat { errorCounter++ if (errorCounter == 1) { if (successfulCounter < 5) { - ChatUtils.chat("Could not find Diana Guess using sound and particles, please try again. (Was this a funny sound easter egg?)") + ChatUtils.chat( + "Could not find Diana Guess using sound and particles, " + + "please try again. (Was this a funny sound easter egg?)" + ) } return } diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/diana/DianaProfitTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/event/diana/DianaProfitTracker.kt index fb90de9e118e..cd9f48b62c25 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/diana/DianaProfitTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/diana/DianaProfitTracker.kt @@ -139,7 +139,9 @@ object DianaProfitTracker { tryHide(event) } - if (message == "§6§lRARE DROP! §r§eYou dug out a §r§9Griffin Feather§r§e!" || message == "§eFollow the arrows to find the §r§6treasure§r§e!") { + if (message == "§6§lRARE DROP! §r§eYou dug out a §r§9Griffin Feather§r§e!" || + message == "§eFollow the arrows to find the §r§6treasure§r§e!" + ) { BurrowAPI.lastBurrowRelatedChatMessage = SimpleTimeMark.now() tryHide(event) } diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowParticleFinder.kt b/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowParticleFinder.kt index f3860276ad47..a082dfaac6b0 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowParticleFinder.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowParticleFinder.kt @@ -93,20 +93,25 @@ object GriffinBurrowParticleFinder { private enum class ParticleType(val check: S2APacketParticles.() -> Boolean) { EMPTY({ - particleType == net.minecraft.util.EnumParticleTypes.CRIT_MAGIC && particleCount == 4 && particleSpeed == 0.01f && xOffset == 0.5f && yOffset == 0.1f && zOffset == 0.5f + particleType == net.minecraft.util.EnumParticleTypes.CRIT_MAGIC && + particleCount == 4 && particleSpeed == 0.01f && xOffset == 0.5f && yOffset == 0.1f && zOffset == 0.5f }), MOB({ - particleType == net.minecraft.util.EnumParticleTypes.CRIT && particleCount == 3 && particleSpeed == 0.01f && xOffset == 0.5f && yOffset == 0.1f && zOffset == 0.5f + particleType == net.minecraft.util.EnumParticleTypes.CRIT && + particleCount == 3 && particleSpeed == 0.01f && xOffset == 0.5f && yOffset == 0.1f && zOffset == 0.5f }), TREASURE({ - particleType == net.minecraft.util.EnumParticleTypes.DRIP_LAVA && particleCount == 2 && particleSpeed == 0.01f && xOffset == 0.35f && yOffset == 0.1f && zOffset == 0.35f + particleType == net.minecraft.util.EnumParticleTypes.DRIP_LAVA && + particleCount == 2 && particleSpeed == 0.01f && xOffset == 0.35f && yOffset == 0.1f && zOffset == 0.35f }), FOOTSTEP({ - particleType == net.minecraft.util.EnumParticleTypes.FOOTSTEP && particleCount == 1 && particleSpeed == 0.0f && xOffset == 0.05f && yOffset == 0.0f && zOffset == 0.05f + particleType == net.minecraft.util.EnumParticleTypes.FOOTSTEP && + particleCount == 1 && particleSpeed == 0.0f && xOffset == 0.05f && yOffset == 0.0f && zOffset == 0.05f }), ENCHANT({ - particleType == net.minecraft.util.EnumParticleTypes.ENCHANTMENT_TABLE && particleCount == 5 && particleSpeed == 0.05f && xOffset == 0.5f && yOffset == 0.4f && zOffset == 0.5f + particleType == net.minecraft.util.EnumParticleTypes.ENCHANTMENT_TABLE && + particleCount == 5 && particleSpeed == 0.05f && xOffset == 0.5f && yOffset == 0.4f && zOffset == 0.5f }); companion object { diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinPetWarning.kt b/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinPetWarning.kt index f52c34320413..f5ce6675bb98 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinPetWarning.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinPetWarning.kt @@ -1,9 +1,13 @@ package at.hannibal2.skyhanni.features.event.diana import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.BurrowDugEvent +import at.hannibal2.skyhanni.events.IslandChangeEvent import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.DelayedRun +import at.hannibal2.skyhanni.utils.HypixelCommands import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.SimpleTimeMark import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @@ -11,20 +15,52 @@ import kotlin.time.Duration.Companion.seconds @SkyHanniModule object GriffinPetWarning { - + private val config get() = SkyHanniMod.feature.event.diana + private var wasCorrectPetAlready = false private var lastWarnTime = SimpleTimeMark.farPast() @SubscribeEvent fun onTick(event: LorenzTickEvent) { if (!event.isMod(10)) return - if (!SkyHanniMod.feature.event.diana.petWarning) return + if (!config.petWarning) return if (!DianaAPI.isDoingDiana()) return if (!DianaAPI.hasSpadeInHand()) return - if (!DianaAPI.hasGriffinPet() && lastWarnTime.passedSince() > 30.seconds) { + val hasGriffinPet = DianaAPI.hasGriffinPet() + if (hasGriffinPet) { + wasCorrectPetAlready = true + return + } + + if (wasCorrectPetAlready) return + + warn() + } + + @SubscribeEvent + fun onBurrowDug(event: BurrowDugEvent) { + DelayedRun.runDelayed(2.seconds) { + wasCorrectPetAlready = false + } + } + + @SubscribeEvent + fun onIslandChange(event: IslandChangeEvent) { + DelayedRun.runDelayed(5.seconds) { + wasCorrectPetAlready = false + } + } + + private fun warn() { + ChatUtils.clickToActionOrDisable( + "Reminder to use a Griffin pet for Mythological Ritual!", + config::petWarning, + actionName = "open pets menu", + action = { HypixelCommands.pet() }, + ) + if (lastWarnTime.passedSince() > 30.seconds) { lastWarnTime = SimpleTimeMark.now() LorenzUtils.sendTitle("§cGriffin Pet!", 3.seconds) - ChatUtils.chat("Reminder to use a Griffin pet for Mythological Ritual!") } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/diana/InquisitorWaypointShare.kt b/src/main/java/at/hannibal2/skyhanni/features/event/diana/InquisitorWaypointShare.kt index 2d0e2a809e81..eb3c7a24afc9 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/diana/InquisitorWaypointShare.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/diana/InquisitorWaypointShare.kt @@ -53,10 +53,21 @@ object InquisitorWaypointShare { /** * REGEX-TEST: §9Party §8> UserName§f: §rA MINOS INQUISITOR has spawned near [Foraging Island ] at Coords 1 2 3 */ + @Suppress("MaxLineLength") private val partyInquisitorCheckerPattern by patternGroup.pattern( "party.inquisitorchecker", "(?§9Party §8> )?(?.+)§f: §rA MINOS INQUISITOR has spawned near \\[(?.*)] at Coords (?[^ ]+) (?[^ ]+) (?[^ ]+)" ) + + /** + * REGEX-TEST: §9Party §8> §b[MVP§9+§b] _088§f: §rx: 86, y: 73, z: -29 I dug up an inquisitor come over here! + */ + @Suppress("MaxLineLength") + private val odinPattern by patternGroup.pattern( + "party.odin", + "(?§9Party §8> )?(?.+)§f: §rx: (?[^ ]+), y: (?[^ ]+), z: (?[^ ]+) I dug up an inquisitor come over here!" + ) + private val diedPattern by patternGroup.pattern( "died", "(?§9Party §8> )?(?.*)§f: §rInquisitor dead!" @@ -237,6 +248,11 @@ object InquisitorWaypointShare { event.cancel() } } + odinPattern.matchMatcher(message) { + if (detectFromChat()) { + event.cancel() + } + } partyOnlyCoordsPattern.matchMatcher(message) { if (detectFromChat()) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/diana/SoopyGuessBurrow.kt b/src/main/java/at/hannibal2/skyhanni/features/event/diana/SoopyGuessBurrow.kt index 35016eda3740..477371ec2107 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/diana/SoopyGuessBurrow.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/diana/SoopyGuessBurrow.kt @@ -136,6 +136,7 @@ object SoopyGuessBurrow { } } + @Suppress("MaxLineLength") private fun solveEquationThing(x: LorenzVec, y: LorenzVec): LorenzVec { val a = (-y.x * x.y * x.x - y.y * x.y * x.z + y.y * x.y * x.x + x.y * x.z * y.z + x.x * x.z * y.x - x.x * x.z * y.z) / (x.y * y.x - x.y * y.z + x.x * y.z - y.x * x.z + y.y * x.z - y.y * x.x) diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityAPI.kt index 5e1910d0d1c9..8d3ac22c3e76 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityAPI.kt @@ -16,6 +16,7 @@ import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactor import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryStrayTracker import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryStrayTracker.duplicateDoradoStrayPattern import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryStrayTracker.duplicatePseudoStrayPattern +import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryStrayTracker.formLoreToSingleLine import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.ItemUtils.getLore @@ -117,16 +118,19 @@ object HoppityAPI { duplicate = it.stack.getLore().any { line -> duplicatePseudoStrayPattern.matches(line) } attemptFireRabbitFound() } - "El Dorado" -> { - EggFoundEvent(STRAY, it.slotNumber).post() - lastName = "§6El Dorado" - lastMeal = STRAY - duplicate = it.stack.getLore().any { line -> duplicateDoradoStrayPattern.matches(line) } - attemptFireRabbitFound() - } else -> return@matchMatcher } } + ChocolateFactoryStrayTracker.strayDoradoPattern.matchMatcher(formLoreToSingleLine(it.stack.getLore())) { + // We don't need to do a handleStrayClicked here - the lore from El Dorado is already: + // §6§lGolden Rabbit §d§lCAUGHT! + // Which will trigger the above matcher. We only need to check name here to fire the found event for Dorado. + EggFoundEvent(STRAY, it.slotNumber).post() + lastName = "§6El Dorado" + lastMeal = STRAY + duplicate = it.stack.getLore().any { line -> duplicateDoradoStrayPattern.matches(line) } + attemptFireRabbitFound() + } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCallWarning.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCallWarning.kt index 57bc0975fac8..7881af19d3cb 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCallWarning.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCallWarning.kt @@ -1,18 +1,22 @@ package at.hannibal2.skyhanni.features.event.hoppity +import at.hannibal2.skyhanni.data.PurseAPI import at.hannibal2.skyhanni.events.ConfigLoadEvent import at.hannibal2.skyhanni.events.GuiRenderEvent import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.events.LorenzKeyPressEvent +import at.hannibal2.skyhanni.events.MessageSendToServerEvent import at.hannibal2.skyhanni.events.SecondPassedEvent import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryAPI import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.ColorUtils.toChromaColorInt import at.hannibal2.skyhanni.utils.ConditionalUtils import at.hannibal2.skyhanni.utils.DelayedRun 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.SoundUtils import at.hannibal2.skyhanni.utils.StringUtils.isValidUuid import net.minecraft.client.Minecraft @@ -59,6 +63,14 @@ object HoppityCallWarning { "§e\\[NPC] §aHoppity§f: §b✆ §f§rWhat's up, .*§f\\?", ) + /** + * REGEX-TEST: /selectnpcoption hoppity r_2_1 + */ + private val pickupOutgoingCommandPattern by ChocolateFactoryAPI.patternGroup.pattern( + "hoppity.call.pickup.outgoing", + "\\/selectnpcoption hoppity r_2_1", + ) + private val config get() = HoppityEggsManager.config.hoppityCallWarning private var warningSound = SoundUtils.createSound("note.pling", 1f) private var activeWarning = false @@ -66,6 +78,7 @@ object HoppityCallWarning { private var finalWarningTime: Instant? = null private val callLength = 7.seconds private var acceptUUID: String? = null + private var commandSentTimer = SimpleTimeMark.farPast() @SubscribeEvent fun onKeyPress(event: LorenzKeyPressEvent) { @@ -128,6 +141,24 @@ object HoppityCallWarning { GlStateManager.color(1F, 1F, 1F, 1F) } + @SubscribeEvent + fun onCommandSend(event: MessageSendToServerEvent) { + if (!LorenzUtils.inSkyBlock || !config.ensureCoins) return + if (!pickupOutgoingCommandPattern.matches(event.message)) return + if (commandSentTimer.passedSince() < 5.seconds) return + if (PurseAPI.getPurse() >= config.coinThreshold) return + + commandSentTimer = SimpleTimeMark.now() + event.cancel() + ChatUtils.clickToActionOrDisable( + "§cBlocked picking up Hoppity without enough coins!", + config::ensureCoins, + actionName = "open bank menu", + // TODO if no booster cookie active, suggest to warp to hub/path find to bank. ideally into an utils + action = { HypixelCommands.bank() }, + ) + } + private fun readPickupUuid(event: LorenzChatEvent) { val siblings = event.chatComponent.siblings.takeIf { it.size >= 3 } ?: return val clickEvent = siblings[2]?.chatStyle?.chatClickEvent ?: return diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt index 6d201e57edcd..ead632ae6b0d 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityCollectionStats.kt @@ -520,9 +520,9 @@ object HoppityCollectionStats { } // bugfix for some weird potential user errors (e.g. if users play on alpha and get rabbits) - fun clearSavedRabbits() { + fun resetSavedRabbits() { loggedRabbits.clear() - ChatUtils.chat("Cleared saved rabbit data.") + ChatUtils.chat("Reset saved rabbit data.") } fun hasFoundRabbit(rabbit: String): Boolean = loggedRabbits.containsKey(rabbit) diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocations.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocations.kt index 13c5301126aa..becaa31a801e 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocations.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocations.kt @@ -33,13 +33,13 @@ object HoppityEggLocations { var apiEggLocations: Map> = mapOf() val islandLocations - get() = apiEggLocations[LorenzUtils.skyBlockIsland]?.values?.toSet() ?: emptySet() + get() = apiEggLocations[LorenzUtils.skyBlockIsland]?.values?.toSet().orEmpty() val islandCollectedLocations - get() = collectedEggStorage[LorenzUtils.skyBlockIsland]?.toSet() ?: emptySet() + get() = collectedEggStorage[LorenzUtils.skyBlockIsland]?.toSet().orEmpty() fun getEggsIn(islandType: IslandType): Set { - return collectedEggStorage[islandType] ?: emptySet() + return collectedEggStorage[islandType].orEmpty() } fun hasCollectedEgg(location: LorenzVec): Boolean = islandCollectedLocations.contains(location) diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsCompactChat.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsCompactChat.kt index 9b9276420efe..c956e10044c7 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsCompactChat.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsCompactChat.kt @@ -84,7 +84,7 @@ object HoppityEggsCompactChat { SIDE_DISH -> "§6§lSide Dish §r§6Egg" CHOCOLATE_SHOP_MILESTONE, CHOCOLATE_FACTORY_MILESTONE -> "§6§lMilestone Rabbit" STRAY -> "§aStray Rabbit" - else -> "${lastChatMeal?.coloredName ?: ""} Egg" + else -> "${lastChatMeal?.coloredName.orEmpty()} Egg" } val rarityConfig = HoppityEggsManager.config.rarityInCompact @@ -97,12 +97,13 @@ object HoppityEggsCompactChat { val dupeNumberFormat = if (eventConfig.showDuplicateNumber) { (HoppityCollectionStats.getRabbitCount(this.lastName)).takeIf { it > 0 }?.let { " §7(§b#$it§7)" - } ?: "" + }.orEmpty() } else "" val showDupeRarity = rarityConfig.let { it == RarityType.BOTH || it == RarityType.DUPE } val timeStr = if (config.showDuplicateTime) ", §a+§b$timeFormatted§7" else "" - "$mealNameFormat! §7Duplicate ${if (showDupeRarity) "$lastRarity " else ""}$lastName$dupeNumberFormat §7(§6+$format Chocolate§7$timeStr)" + "$mealNameFormat! §7Duplicate ${if (showDupeRarity) "$lastRarity " else ""}" + + "$lastName$dupeNumberFormat §7(§6+$format Chocolate§7$timeStr)" } else if (newRabbit) { val showNewRarity = rarityConfig.let { it == RarityType.BOTH || it == RarityType.NEW } "$mealNameFormat! §d§lNEW ${if (showNewRarity) "$lastRarity " else ""}$lastName §7($lastProfit§7)" diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsManager.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsManager.kt index a69366931886..4b3451514839 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggsManager.kt @@ -259,6 +259,8 @@ object HoppityEggsManager { ) event.move(44, "event.chocolateFactory.hoppityEggs", "event.hoppityEggs") event.move(50, "event.hoppityEggs.showDuringContest", "event.hoppityEggs.showWhileBusy") + event.move(62, "event.hoppityEggs.uniquesWarpMenu", "event.hoppityEggs.warpMenu.enabled") + event.move(62, "event.hoppityEggs.uniquesWarpMenuHideMax", "event.hoppityEggs.warpMenu.hideWhenMaxed") } fun isActive() = (LorenzUtils.inSkyBlock || (LorenzUtils.onHypixel && config.showOutsideSkyblock)) && diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEventSummary.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEventSummary.kt index 4a536465c28f..41d5142d8ca4 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEventSummary.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEventSummary.kt @@ -205,7 +205,8 @@ object HoppityEventSummary { val parsedInt: Int? = if (it.size == 1) it[0].toIntOrNull() else null - val availableYearsFormat = "§eHoppity Event Stats are available for the following years:§r\n${statsYearFormatList.joinToString("§e, ") { it }}" + val availableYearsFormat = + "§eHoppity Event Stats are available for the following years:§r\n${statsYearFormatList.joinToString("§e, ") { it }}" if (parsedInt == null) { if (HoppityAPI.isHoppityEvent()) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityRabbitTheFishChecker.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityRabbitTheFishChecker.kt new file mode 100644 index 000000000000..3565c177827c --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityRabbitTheFishChecker.kt @@ -0,0 +1,99 @@ +package at.hannibal2.skyhanni.features.event.hoppity + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.GuiContainerEvent +import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent +import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryAPI +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.LorenzColor +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.RegexUtils.anyMatches +import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.RenderUtils.highlight +import at.hannibal2.skyhanni.utils.SoundUtils +import net.minecraft.client.Minecraft +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import org.lwjgl.input.Keyboard + +@SkyHanniModule +object HoppityRabbitTheFishChecker { + + // + /** + * REGEX-TEST: Chocolate Breakfast Egg + * REGEX-TEST: Chocolate Lunch Egg + * REGEX-TEST: Chocolate Dinner Egg + */ + private val mealEggInventoryPattern by ChocolateFactoryAPI.patternGroup.pattern( + "inventory.mealegg.name", + "(?:§.)*Chocolate (?:Breakfast|Lunch|Dinner) Egg.*", + ) + + /** + * REGEX-TEST: §cRabbit the Fish + */ + private val rabbitTheFishItemPattern by ChocolateFactoryAPI.patternGroup.pattern( + "item.rabbitthefish", + "(?:§.)*Rabbit the Fish", + ) + + /** + * REGEX-TEST: Click to open Chocolate Factory! + */ + private val openCfSlotLorePattern by ChocolateFactoryAPI.patternGroup.pattern( + "inventory.mealegg.continue", + "(?:§.)*Click to open Chocolate Factory!", + ) + // + + private val config get() = SkyHanniMod.feature.event.hoppityEggs + private var rabbitTheFishIndex: Int? = null + + @SubscribeEvent + fun onBackgroundDrawn(event: GuiContainerEvent.BackgroundDrawnEvent) { + if (!isEnabled()) return + + rabbitTheFishIndex?.let { + InventoryUtils.getItemsInOpenChest()[it] highlight LorenzColor.RED + } + } + + @SubscribeEvent + fun onInventoryOpen(event: InventoryFullyOpenedEvent) { + if (!isEnabled() || !mealEggInventoryPattern.matches(event.inventoryName)) return + + rabbitTheFishIndex = event.inventoryItems.filter { + it.value.hasDisplayName() + }.entries.firstOrNull { + rabbitTheFishItemPattern.matches(it.value.displayName) + }?.key + } + + @SubscribeEvent + fun onSlotClick(event: GuiContainerEvent.SlotClickEvent) { + if (!isEnabled() || rabbitTheFishIndex == null) return + + // Prevent opening chocolate factory when Rabbit the Fish is present + val stack = event.slot?.stack ?: return + if (openCfSlotLorePattern.anyMatches(stack.getLore())) { + event.cancel() + SoundUtils.playErrorSound() + } else if (rabbitTheFishIndex == event.slot.slotNumber) { + rabbitTheFishIndex = null + } + } + + private fun Int.isInventoryClosure(): Boolean = + this == Minecraft.getMinecraft().gameSettings.keyBindInventory.keyCode || this == Keyboard.KEY_ESCAPE + + @JvmStatic + fun shouldContinueWithKeypress(keycode: Int): Boolean { + val shouldContinue = !keycode.isInventoryClosure() || !isEnabled() || rabbitTheFishIndex == null + if (!shouldContinue) SoundUtils.playErrorSound() + return shouldContinue + } + + private fun isEnabled() = LorenzUtils.inSkyBlock && HoppityAPI.isHoppityEvent() && config.preventMissingFish +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/NucleusBarriersBox.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/NucleusBarriersBox.kt index 47ab47a38240..7f769a505751 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/NucleusBarriersBox.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/NucleusBarriersBox.kt @@ -1,14 +1,14 @@ package at.hannibal2.skyhanni.features.event.hoppity import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent -import at.hannibal2.skyhanni.events.LorenzTickEvent -import at.hannibal2.skyhanni.features.misc.IslandAreas +import at.hannibal2.skyhanni.events.skyblock.GraphAreaChangeEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.LorenzColor import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland -import at.hannibal2.skyhanni.utils.RenderUtils.drawFilledBoundingBox_nea +import at.hannibal2.skyhanni.utils.RenderUtils.drawFilledBoundingBoxNea import at.hannibal2.skyhanni.utils.RenderUtils.expandBlock import net.minecraft.util.AxisAlignedBB import net.minecraft.util.BlockPos @@ -58,9 +58,9 @@ object NucleusBarriersBox { ), } - @SubscribeEvent - fun onTick(event: LorenzTickEvent) { - inNucleus = IslandAreas.currentAreaName == "Crystal Nucleus" + @HandleEvent + fun onAreaChange(event: GraphAreaChangeEvent) { + inNucleus = event.area == "Crystal Nucleus" } @SubscribeEvent @@ -68,7 +68,7 @@ object NucleusBarriersBox { if (!isEnabled()) return Crystal.entries.forEach { crystal -> - event.drawFilledBoundingBox_nea( + event.drawFilledBoundingBoxNea( crystal.boundingBox, crystal.color.addOpacity(config.opacity), renderRelativeToCamera = false, diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/WarpMenuUniques.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/WarpMenuUniques.kt index 939dea1b702f..dfd22de9a88f 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/WarpMenuUniques.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/WarpMenuUniques.kt @@ -27,12 +27,12 @@ object WarpMenuUniques { private val collectedEggStorage: MutableMap>? get() = ChocolateFactoryAPI.profileStorage?.collectedEggLocations - private val config get() = SkyHanniMod.feature.event.hoppityEggs + private val config get() = SkyHanniMod.feature.event.hoppityEggs.warpMenu @SubscribeEvent fun onTooltip(event: LorenzToolTipEvent) { if (!LorenzUtils.inSkyBlock) return - if (!config.uniquesWarpMenu) return + if (!config.enabled) return if (!HoppityAPI.isHoppityEvent()) return if (event.slot.inventory.name != "Fast Travel") return @@ -51,7 +51,7 @@ object WarpMenuUniques { val maxEggs = 15 val collectedEggs = collectedEggStorage?.get(island)?.size ?: 0 - if (collectedEggs >= maxEggs && config.uniquesWarpMenuHideMax) return + if (collectedEggs >= maxEggs && config.hideWhenMaxed) return event.toolTip.add(2, "§7Collected Hoppity Eggs: ${if (collectedEggs == maxEggs) "§a" else ""}$collectedEggs/$maxEggs") } diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/lobby/waypoints/easter/EasterEggWaypoints.kt b/src/main/java/at/hannibal2/skyhanni/features/event/lobby/waypoints/easter/EasterEggWaypoints.kt index 8250b023db10..7f0b208e7976 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/lobby/waypoints/easter/EasterEggWaypoints.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/lobby/waypoints/easter/EasterEggWaypoints.kt @@ -29,7 +29,10 @@ object EasterEggWaypoints { if (!isEnabled()) return val message = event.message - if (message.startsWith("§a§lYou found an Easter Egg! §r") || message == "§aYou have received the §bsuper reward§a!" || message == "§cYou already found this egg!") { + if (message.startsWith("§a§lYou found an Easter Egg! §r") || + message == "§aYou have received the §bsuper reward§a!" || + message == "§cYou already found this egg!" + ) { val egg = EasterEgg.entries.minByOrNull { it.waypoint.distanceSqToPlayer() }!! egg.found = true if (closest == egg) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/spook/TheGreatSpook.kt b/src/main/java/at/hannibal2/skyhanni/features/event/spook/TheGreatSpook.kt index 200e01d78cde..7bdc404cecbd 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/spook/TheGreatSpook.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/spook/TheGreatSpook.kt @@ -40,7 +40,7 @@ object TheGreatSpook { } private fun checkTabList(matchString: String): String { - return (TabListData.getTabList().find { it.contains(matchString) } ?: "").trim() + return (TabListData.getTabList().find { it.contains(matchString) }.orEmpty()).trim() } @SubscribeEvent diff --git a/src/main/java/at/hannibal2/skyhanni/features/fame/CityProjectFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/fame/CityProjectFeatures.kt index cf5d3ce5a5a2..b0a1c9cbd193 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fame/CityProjectFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fame/CityProjectFeatures.kt @@ -191,14 +191,15 @@ object CityProjectFeatures { val lore = item.getLore() val completed = lore.lastOrNull()?.let { completedPattern.matches(it) } ?: false if (completed) return + // TODO: Refactor this loop to not have so many jumps + @Suppress("LoopWithTooManyJumpStatements") for (line in lore) { if (line == "§7Cost") { next = true continue } if (!next) continue - if (line == "") break - if (line.contains("Bits")) break + if (line == "" || line.contains("Bits")) break val (name, amount) = ItemUtils.readItemAmount(line) ?: continue val internalName = NEUInternalName.fromItemName(name) diff --git a/src/main/java/at/hannibal2/skyhanni/features/fame/ReminderUtils.kt b/src/main/java/at/hannibal2/skyhanni/features/fame/ReminderUtils.kt index 19e0399ad269..821ac7774d76 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fame/ReminderUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fame/ReminderUtils.kt @@ -11,7 +11,8 @@ object ReminderUtils { // TODO: add arachne fight, add slayer boss spawned, add dragon fight fun isBusy(ignoreFarmingContest: Boolean = false): Boolean = - (DungeonAPI.inDungeon() && !DungeonAPI.completed) || LorenzUtils.inKuudraFight || (FarmingContestAPI.inContest && !ignoreFarmingContest) || + (DungeonAPI.inDungeon() && !DungeonAPI.completed) || + LorenzUtils.inKuudraFight || (FarmingContestAPI.inContest && !ignoreFarmingContest) || RiftAPI.inRift() || IslandType.DARK_AUCTION.isInIsland() || IslandType.MINESHAFT.isInIsland() || IslandType.NONE.isInIsland() || IslandType.UNKNOWN.isInIsland() } diff --git a/src/main/java/at/hannibal2/skyhanni/features/fame/UpgradeReminder.kt b/src/main/java/at/hannibal2/skyhanni/features/fame/UpgradeReminder.kt index b55aa8f11e7f..4fc3c2de24aa 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fame/UpgradeReminder.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fame/UpgradeReminder.kt @@ -56,6 +56,7 @@ object UpgradeReminder { "claimed", "§eYou claimed the §r§a(?.+) §r§eupgrade!", ) + @Suppress("UnusedPrivateProperty") private val upgradePattern by patternGroup.pattern( "upgrade", "§eClick to start upgrade!", diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingTimer.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingTimer.kt index 5be021fbb8a1..c699191a5e26 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingTimer.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingTimer.kt @@ -65,7 +65,7 @@ object FishingTimer { @SubscribeEvent fun onSecondPassed(event: SecondPassedEvent) { if (!isEnabled()) return - updateLocation() + rightLocation = updateLocation() if (startTime.passedSince().inWholeSeconds - config.alertTime in 0..3) { playSound() } @@ -170,8 +170,10 @@ object FishingTimer { display = createDisplay() } - private fun updateLocation() { - rightLocation = when (LorenzUtils.skyBlockIsland) { + private fun updateLocation(): Boolean { + if (config.showAnywhere) return true + + return when (LorenzUtils.skyBlockIsland) { IslandType.CRYSTAL_HOLLOWS -> config.crystalHollows.get() IslandType.CRIMSON_ISLE -> config.crimsonIsle.get() IslandType.WINTER -> config.winterIsland.get() diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/ShowFishingItemName.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/ShowFishingItemName.kt index 514d330a4bee..c25974292321 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/ShowFishingItemName.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/ShowFishingItemName.kt @@ -27,6 +27,8 @@ object ShowFishingItemName { private var itemsOnGround = TimeLimitedCache(750.milliseconds) // Taken from Skytils + // TODO? Move to repo + @Suppress("MaxLineLength") private val cheapCoins = setOf( "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTM4MDcxNzIxY2M1YjRjZDQwNmNlNDMxYTEzZjg2MDgzYTg5NzNlMTA2NGQyZjg4OTc4Njk5MzBlZTZlNTIzNyJ9fX0=", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGZhMDg3ZWI3NmU3Njg3YTgxZTRlZjgxYTdlNjc3MjY0OTk5MGY2MTY3Y2ViMGY3NTBhNGM1ZGViNmM0ZmJhZCJ9fX0=", diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/ThunderSparksHighlight.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/ThunderSparksHighlight.kt index b84ee2970b0d..3ddb00d37050 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/ThunderSparksHighlight.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/ThunderSparksHighlight.kt @@ -26,6 +26,8 @@ import java.awt.Color object ThunderSparksHighlight { private val config get() = SkyHanniMod.feature.fishing.thunderSpark + // TODO: Move to repo + @Suppress("MaxLineLength") private const val TEXTURE = "ewogICJ0aW1lc3RhbXAiIDogMTY0MzUwNDM3MjI1NiwKICAicHJvZmlsZUlkIiA6ICI2MzMyMDgwZTY3YTI0Y2MxYjE3ZGJhNzZmM2MwMGYxZCIsCiAgInByb2ZpbGVOYW1lIiA6ICJUZWFtSHlkcmEiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvN2IzMzI4ZDNlOWQ3MTA0MjAzMjI1NTViMTcyMzkzMDdmMTIyNzBhZGY4MWJmNjNhZmM1MGZhYTA0YjVjMDZlMSIsCiAgICAgICJtZXRhZGF0YSIgOiB7CiAgICAgICAgIm1vZGVsIiA6ICJzbGltIgogICAgICB9CiAgICB9CiAgfQp9" private val sparks = mutableListOf() diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/tracker/FishingProfitTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/tracker/FishingProfitTracker.kt index a3e86908762f..9af4ca7e4e9d 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/tracker/FishingProfitTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/tracker/FishingProfitTracker.kt @@ -83,7 +83,7 @@ object FishingProfitTracker { override fun getCustomPricePer(internalName: NEUInternalName): Double { // TODO find better way to tell if the item is a trophy - val neuInternalNames = itemCategories["Trophy Fish"]!! + val neuInternalNames = itemCategories["Trophy Fish"].orEmpty() return if (internalName in neuInternalNames) { SkyHanniTracker.getPricePer(MAGMA_FISH) * FishingAPI.getFilletPerTrophy(internalName) @@ -163,8 +163,7 @@ object FishingProfitTracker { val filter: (NEUInternalName) -> Boolean = if (currentCategory == NAME_ALL) { { true } } else { - val items = itemCategories[currentCategory]!! - { it in items } + { it in (itemCategories[currentCategory].orEmpty()) } } return filter } diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/GeyserFishing.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/GeyserFishing.kt index ee3838335c45..48ea25c46e3d 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/GeyserFishing.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/GeyserFishing.kt @@ -12,7 +12,7 @@ import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayerIgnoreY import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland import at.hannibal2.skyhanni.utils.LorenzVec -import at.hannibal2.skyhanni.utils.RenderUtils.drawFilledBoundingBox_nea +import at.hannibal2.skyhanni.utils.RenderUtils.drawFilledBoundingBoxNea import at.hannibal2.skyhanni.utils.SpecialColor import net.minecraft.util.AxisAlignedBB import net.minecraft.util.EnumParticleTypes @@ -64,7 +64,7 @@ object GeyserFishing { if (config.onlyWithRod && !FishingAPI.holdingLavaRod) return val color = Color(SpecialColor.specialToChromaRGB(config.boxColor), true) - event.drawFilledBoundingBox_nea(geyserBox, color) + event.drawFilledBoundingBoxNea(geyserBox, color) } private fun hideGeyserParticles(event: ReceiveParticleEvent) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/GoldenFishTimer.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/GoldenFishTimer.kt index b7c67034feab..dd023a7fadf3 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/GoldenFishTimer.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/GoldenFishTimer.kt @@ -93,6 +93,8 @@ object GoldenFishTimer { handle() } + // TODO: Move to repo + @Suppress("MaxLineLength") private const val GOLDEN_FISH_SKULL_TEXTURE = "ewogICJ0aW1lc3RhbXAiIDogMTY0MzgzMTA2MDE5OCwKICAicHJvZmlsZUlkIiA6ICJiN2ZkYmU2N2NkMDA0NjgzYjlmYTllM2UxNzczODI1NCIsCiAgInByb2ZpbGVOYW1lIiA6ICJDVUNGTDE0IiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzEyMGNmM2MwYTQwZmM2N2UwZTVmZTBjNDZiMGFlNDA5YWM3MTAzMGE3NjU2ZGExN2IxMWVkMDAxNjQ1ODg4ZmUiCiAgICB9CiAgfQp9" private val goldenFishSkullItem by lazy { diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishAPI.kt index 3a6333a9c150..f700e7319dc3 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishAPI.kt @@ -8,7 +8,7 @@ object TrophyFishAPI { fun hoverInfo(internalName: String): String? { val trophyFishes = TrophyFishManager.fish ?: return null val info = TrophyFishManager.getInfo(internalName) ?: return null - val counts = trophyFishes[internalName] ?: emptyMap() + val counts = trophyFishes[internalName].orEmpty() val bestFishObtained = counts.keys.maxOrNull() ?: TrophyRarity.BRONZE val rateString = if (info.rate != null) "§8[§7${info.rate}%§8]" else "" return """ diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/CropType.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/CropType.kt index 290c5427bb6e..9403120eb382 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/CropType.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/CropType.kt @@ -75,7 +75,8 @@ enum class CropType( if (itemName == "Red Mushroom" || itemName == "Brown Mushroom") return MUSHROOM if (itemName == "Seeds") return WHEAT return entries.firstOrNull { - it.cropName.equals(itemName, ignoreCase = true) || it.simpleName.equals(itemName, ignoreCase = true) + it.cropName.equals(itemName, ignoreCase = true) || + it.simpleName.equals(itemName, ignoreCase = true) } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/FarmingFortuneDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/FarmingFortuneDisplay.kt index 55898266e440..a6331db11af9 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/FarmingFortuneDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/FarmingFortuneDisplay.kt @@ -54,6 +54,7 @@ object FarmingFortuneDisplay { "collection", "§7You have §6\\+(?\\d{1,3})☘ .*", ) + @Suppress("MaxLineLength") private val tooltipFortunePattern by patternGroup.pattern( "tooltip.new", "^§7Farming Fortune: §a\\+(?[\\d.]+)(?: §2\\(\\+\\d\\))?(?: §9\\(\\+(?\\d+)\\))?(?: §d\\(\\+(?\\d+)\\))?\$", 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 7e1800931c41..460b112540c6 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt @@ -189,12 +189,18 @@ object GardenAPI { addItemStack(crop.icon.copy(), highlight = highlight, scale = scale) } - fun hideExtraGuis() = ComposterOverlay.inInventory || AnitaMedalProfit.inInventory || - SkyMartCopperPrice.inInventory || FarmingContestAPI.inInventory || VisitorAPI.inInventory || - FFGuideGUI.isInGui() || ChocolateShopPrice.inInventory || ChocolateFactoryAPI.inChocolateFactory || - ChocolateFactoryAPI.chocolateFactoryPaused || HoppityCollectionStats.inInventory - - fun clearCropSpeed() { + fun hideExtraGuis() = ComposterOverlay.inInventory || + AnitaMedalProfit.inInventory || + SkyMartCopperPrice.inInventory || + FarmingContestAPI.inInventory || + VisitorAPI.inInventory || + FFGuideGUI.isInGui() || + ChocolateShopPrice.inInventory || + ChocolateFactoryAPI.inChocolateFactory || + ChocolateFactoryAPI.chocolateFactoryPaused || + HoppityCollectionStats.inInventory + + fun resetCropSpeed() { storage?.cropsPerSecond?.clear() GardenBestCropTime.reset() updateGardenTool() diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenCropMilestoneFix.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenCropMilestoneFix.kt index 127ee3f305a1..3c2ca657813d 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenCropMilestoneFix.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenCropMilestoneFix.kt @@ -29,6 +29,7 @@ object GardenCropMilestoneFix { * REGEX-TEST: Cocoa Beans 31: §r§a68% * REGEX-TEST: Potato 32: §r§a97.7% */ + @Suppress("MaxLineLength") private val tabListPattern by patternGroup.pattern( "tablist", " (?Wheat|Carrot|Potato|Pumpkin|Sugar Cane|Melon|Cactus|Cocoa Beans|Mushroom|Nether Wart) (?\\d+): §r§a(?.*)%" diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt index d0a386272a1c..e8a2c18c3f9b 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt @@ -57,7 +57,7 @@ import kotlin.time.Duration.Companion.seconds @SkyHanniModule object GardenNextJacobContest { - private var dispatcher = Dispatchers.IO + private val dispatcher = Dispatchers.IO private var display = emptyList() private var simpleDisplay = emptyList() var contests = mutableMapOf() @@ -565,7 +565,10 @@ object GardenNextJacobContest { newContests[timeMark + contestDuration] = FarmingContest(timeMark + contestDuration, crops) } } else { - ChatUtils.chat("This year's contests aren't available to fetch automatically yet, please load them from your calendar or wait 10 minutes.") + ChatUtils.chat( + "This year's contests aren't available to fetch automatically yet, " + + "please load them from your calendar or wait 10 minutes." + ) ChatUtils.clickableChat( "Click here to open your calendar!", onClick = { HypixelCommands.calendar() }, diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/ToolTooltipTweaks.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/ToolTooltipTweaks.kt index 8700e49425be..95bcbbea74d2 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/ToolTooltipTweaks.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/ToolTooltipTweaks.kt @@ -86,9 +86,12 @@ object ToolTooltipTweaks { val cropString = if (hiddenFortune != 0.0) " §6[+${hiddenFortune.roundToInt()}]" else "" val fortuneLine = when (config.cropTooltipFortune) { - CropTooltipFortuneEntry.DEFAULT -> "§7Farming Fortune: §a+${displayedFortune.formatStat()}$ffdString$reforgeString" - CropTooltipFortuneEntry.SHOW -> "§7Farming Fortune: §a+${displayedFortune.formatStat()}$ffdString$reforgeString$cropString" - else -> "§7Farming Fortune: §a+${totalFortune.formatStat()}$ffdString$reforgeString$cropString" + CropTooltipFortuneEntry.DEFAULT -> + "§7Farming Fortune: §a+${displayedFortune.formatStat()}$ffdString$reforgeString" + CropTooltipFortuneEntry.SHOW -> + "§7Farming Fortune: §a+${displayedFortune.formatStat()}$ffdString$reforgeString$cropString" + else -> + "§7Farming Fortune: §a+${totalFortune.formatStat()}$ffdString$reforgeString$cropString" } iterator.set(fortuneLine) diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterDisplay.kt index ffc77934b4c0..57c3a1977fa3 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterDisplay.kt @@ -49,7 +49,7 @@ object ComposterDisplay { val pattern by lazy { rawPattern.toPattern() } fun addToList(map: Map): List { - return map[this]?.let { listOf(displayItem, it) } ?: emptyList() + return map[this]?.let { listOf(displayItem, it) }.orEmpty() } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterOverlay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterOverlay.kt index 6059eded9a14..184a4836afe7 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterOverlay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterOverlay.kt @@ -386,7 +386,7 @@ object ComposterOverlay { bigList: MutableList>, factors: Map, missing: Double, - testOffset_: Int = 0, + testOffsetRec: Int = 0, onClick: (NEUInternalName) -> Unit, ): NEUInternalName { val map = mutableMapOf() @@ -394,11 +394,11 @@ object ComposterOverlay { map[internalName] = factor / getPrice(internalName) } - val testOffset = if (testOffset_ > map.size) { + val testOffset = if (testOffsetRec > map.size) { ChatUtils.userError("Invalid Composter Overlay Offset! $testOffset cannot be greater than ${map.size}!") ComposterOverlay.testOffset = 0 0 - } else testOffset_ + } else testOffsetRec val first: NEUInternalName? = calculateFirst(map, testOffset, factors, missing, onClick, bigList) if (testOffset != 0) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropMoneyDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropMoneyDisplay.kt index 87306744e4a8..cd9c2eac0077 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropMoneyDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropMoneyDisplay.kt @@ -160,7 +160,8 @@ object CropMoneyDisplay { } val bazaarData = internalName.getBazaarData() val price = - if (LorenzUtils.noTradeMode || bazaarData == null) internalName.getNpcPrice() / 160 else (bazaarData.instantBuyPrice + bazaarData.sellOfferPrice) / 320 + if (LorenzUtils.noTradeMode || bazaarData == null) internalName.getNpcPrice() / 160 + else (bazaarData.instantBuyPrice + bazaarData.sellOfferPrice) / 320 extraDicerCoins = 60 * 60 * GardenCropSpeed.getRecentBPS() * dicerDrops * price } @@ -229,7 +230,7 @@ object CropMoneyDisplay { } val coinsColor = if (isCurrent && config.compact) "§e" else "§6" - val moneyArray = moneyPerHourData[internalName] ?: emptyArray() + val moneyArray = moneyPerHourData[internalName].orEmpty() for (price in moneyArray) { val finalPrice = price + extraMushroomCowPerkCoins + extraDicerCoins + extraArmorCoins diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropSpeedMeter.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropSpeedMeter.kt index 9a47acaa1064..924ea00f7f8d 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropSpeedMeter.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/CropSpeedMeter.kt @@ -1,5 +1,6 @@ package at.hannibal2.skyhanni.features.garden.farming +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.data.GardenCropMilestones.getCounter import at.hannibal2.skyhanni.events.CropClickEvent import at.hannibal2.skyhanni.events.CropMilestoneUpdateEvent @@ -76,7 +77,7 @@ object CropSpeedMeter { return list } - @SubscribeEvent + @HandleEvent fun onCropMilestoneUpdate(event: CropMilestoneUpdateEvent) { if (!isEnabled()) return val counters = mutableMapOf() diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/FarmingWeightDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/FarmingWeightDisplay.kt index 3da9945b59d9..640661bd9797 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/FarmingWeightDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/FarmingWeightDisplay.kt @@ -360,12 +360,9 @@ object FarmingWeightDisplay { ) } - private fun isEnabled() = ( - config.display && ( - OutsideSbFeature.FARMING_WEIGHT.isSelected() && !LorenzUtils.inSkyBlock - ) || - (LorenzUtils.inSkyBlock && (GardenAPI.inGarden() || config.showOutsideGarden)) - ) + private fun isEnabled() = config.display && (outsideEnabled() || inGardenEnabled()) + private fun outsideEnabled() = OutsideSbFeature.FARMING_WEIGHT.isSelected() && !LorenzUtils.inSkyBlock + private fun inGardenEnabled() = (LorenzUtils.inSkyBlock && GardenAPI.inGarden()) || config.showOutsideGarden private fun isEtaEnabled() = config.overtakeETA diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropMilestoneDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropMilestoneDisplay.kt index aca1751b0082..734df7630c47 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropMilestoneDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropMilestoneDisplay.kt @@ -1,5 +1,6 @@ package at.hannibal2.skyhanni.features.garden.farming +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.config.features.garden.cropmilestones.CropMilestonesConfig.MilestoneTextEntry import at.hannibal2.skyhanni.config.features.garden.cropmilestones.CropMilestonesConfig.TimeFormatEntry @@ -99,7 +100,7 @@ object GardenCropMilestoneDisplay { } } - @SubscribeEvent + @HandleEvent fun onCropMilestoneUpdate(event: CropMilestoneUpdateEvent) { needsInventory = false GardenBestCropTime.updateTimeTillNextCrop() diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/CaptureFarmingGear.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/CaptureFarmingGear.kt index e8b2d55e4310..b8337ad15a8c 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/CaptureFarmingGear.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/CaptureFarmingGear.kt @@ -322,7 +322,7 @@ object CaptureFarmingGear { item.setItem(slot) outdatedItems[item] = false FarmingFortuneDisplay.loadFortuneLineData(slot, 0.0) - val enchantments = slot.getEnchantments() ?: emptyMap() + val enchantments = slot.getEnchantments().orEmpty() val greenThumbLvl = (enchantments["green_thumb"] ?: continue) val visitors = FarmingFortuneDisplay.greenThumbFortune / (greenThumbLvl * 0.05) GardenAPI.storage?.uniqueVisitors = round(visitors).toInt() @@ -387,6 +387,13 @@ object CaptureFarmingGear { } } + fun onResetGearCommand() { + val storage = GardenAPI.storage?.fortune ?: return + ChatUtils.chat("Resets farming items") + storage.farmingItems.clear() + storage.outdatedItems.clear() + } + @SubscribeEvent fun onConfigUpdaterMigratorConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { event.move(48, "#profile.garden.fortune.carrotFortune", "#profile.garden.fortune.carrolyn.CARROT") diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFGuideGUI.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFGuideGUI.kt index 3771dd112db7..8912bd4d1618 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFGuideGUI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFGuideGUI.kt @@ -5,6 +5,8 @@ import at.hannibal2.skyhanni.features.garden.CropType import at.hannibal2.skyhanni.features.garden.fortuneguide.pages.CropPage import at.hannibal2.skyhanni.features.garden.fortuneguide.pages.OverviewPage import at.hannibal2.skyhanni.features.garden.fortuneguide.pages.UpgradePage +import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.guide.GuideGUI import at.hannibal2.skyhanni.utils.guide.GuideTab import at.hannibal2.skyhanni.utils.renderables.Renderable @@ -20,6 +22,15 @@ class FFGuideGUI : GuideGUI(FortuneGuidePage.OVERVI companion object { + @JvmStatic + fun onCommand() { + if (!LorenzUtils.inSkyBlock) { + ChatUtils.userError("Join SkyBlock to open the fortune guide!") + } else { + open() + } + } + fun isInGui() = Minecraft.getMinecraft().currentScreen is FFGuideGUI fun open() { diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneUpgrades.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneUpgrades.kt index aabee53c8b6c..73f3e8b3dbc1 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneUpgrades.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneUpgrades.kt @@ -93,7 +93,7 @@ object FortuneUpgrades { val item = piece.getItem() // todo tell them to buy the missing item if (!item.getInternalName().contains("LOTUS")) return - val enchantments = item.getEnchantments() ?: emptyMap() + val enchantments = item.getEnchantments().orEmpty() val greenThumbLvl = enchantments["green_thumb"] ?: 0 if (greenThumbLvl != 5 && visitors != 0.0) { genericUpgrades.add( @@ -157,7 +157,7 @@ object FortuneUpgrades { cropSpecificUpgrades.addAll(genericUpgrades) // todo tell them to get the tool if it is missing val crop = tool?.getCropType() ?: return - val enchantments = tool.getEnchantments() ?: emptyMap() + val enchantments = tool.getEnchantments().orEmpty() val turboCropLvl = enchantments[crop.getTurboCrop()] ?: 0 val dedicationLvl = enchantments["dedication"] ?: 0 val cultivatingLvl = enchantments["cultivating"] ?: 0 @@ -287,8 +287,6 @@ object FortuneUpgrades { else -> 8 } - private val cropUpgrades = listOf(5, 10, 20, 50, 100, 500, 1000, 5000, 10000) - // If they unlock in a weird order for example getting a corner before a cheaper one won't work properly private val compostNeeded = listOf( 1, 2, 4, 8, 16, 24, 32, 48, 64, 96, 128, 160, 160, diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/pages/OverviewPage.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/pages/OverviewPage.kt index 00e994f7d4f5..bd70d96cf18b 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/pages/OverviewPage.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/pages/OverviewPage.kt @@ -104,7 +104,7 @@ class OverviewPage(sizeX: Int, sizeY: Int, paddingX: Int = 15, paddingY: Int = 7 val moreInfo = "§2Select a piece for more info" val wordArmor = if (FarmingItems.currentArmor == null) "Armor" else "Piece" - val armorName = FarmingItems.currentArmor?.getItem()?.displayName ?: "" + val armorName = FarmingItems.currentArmor?.getItem()?.displayName.orEmpty() content.addTable( 1, @@ -162,7 +162,7 @@ class OverviewPage(sizeX: Int, sizeY: Int, paddingX: Int = 15, paddingY: Int = 7 val wordEquip = if (FarmingItems.currentEquip == null) "Equipment" else "Piece" - val equipmentName = FarmingItems.currentEquip?.getItem()?.displayName ?: "" + val equipmentName = FarmingItems.currentEquip?.getItem()?.displayName.orEmpty() content.addTable( 1, diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenCropMilestoneInventory.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenCropMilestoneInventory.kt index e0cb070739b9..826913669b01 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenCropMilestoneInventory.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenCropMilestoneInventory.kt @@ -1,5 +1,6 @@ package at.hannibal2.skyhanni.features.garden.inventory +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.data.GardenCropMilestones import at.hannibal2.skyhanni.data.GardenCropMilestones.getCounter @@ -24,7 +25,7 @@ object GardenCropMilestoneInventory { private var average = -1.0 private val config get() = GardenAPI.config - @SubscribeEvent + @HandleEvent fun onCropMilestoneUpdate(event: CropMilestoneUpdateEvent) { if (!config.number.averageCropMilestone) return diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/plots/GardenPlotMenuHighlighting.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/plots/GardenPlotMenuHighlighting.kt index 3ca75b1793b0..d4e3933ce074 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/plots/GardenPlotMenuHighlighting.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/plots/GardenPlotMenuHighlighting.kt @@ -29,9 +29,8 @@ object GardenPlotMenuHighlighting { val list = mutableListOf() val plot = GardenPlotAPI.plots.find { it.inventorySlot == slot.slotIndex } ?: continue - val (pestsEnabled, spraysEnabled, locksEnabled, currentEnabled, pastesEnabled) = PlotStatusType.entries.map { - it in config.deskPlotStatusTypes - } + val (pestsEnabled, spraysEnabled, locksEnabled, currentEnabled, pastesEnabled) = + PlotStatusType.entries.map { it in config.deskPlotStatusTypes } if (plot.pests >= 1 && pestsEnabled) list.add(PlotStatusType.PESTS) if (plot.currentSpray != null && spraysEnabled) list.add(PlotStatusType.SPRAYS) 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 d49de324c851..e239caeab5b3 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 @@ -155,7 +155,7 @@ object PestAPI { private fun updatePests() { if (!firstScoreboardCheck) return fixPests() - PestUpdateEvent().post() + PestUpdateEvent.post() } @HandleEvent(onlyOnIsland = IslandType.GARDEN) 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 690592d52184..d32393e8156a 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 @@ -118,12 +118,15 @@ object PestFinder { } } + private fun heldItemDisabled() = config.onlyWithVacuum && !PestAPI.hasVacuumInHand() + private fun timePassedDisabled() = PestAPI.lastTimeVacuumHold.passedSince() > config.showBorderForSeconds.seconds + // priority to low so that this happens after other renderPlot calls. @SubscribeEvent(priority = EventPriority.LOW) fun onRenderWorld(event: LorenzRenderWorldEvent) { if (!isEnabled()) return if (!config.showPlotInWorld) return - if (config.onlyWithVacuum && !PestAPI.hasVacuumInHand() && (PestAPI.lastTimeVacuumHold.passedSince() > config.showBorderForSeconds.seconds)) return + if (heldItemDisabled() && timePassedDisabled()) return val playerLocation = event.exactPlayerEyeLocation() val visibility = config.visibilityType diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestParticleLine.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestParticleLine.kt index bd8636b9ff86..393eb82480f3 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestParticleLine.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestParticleLine.kt @@ -16,7 +16,7 @@ import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer import at.hannibal2.skyhanni.utils.LorenzColor import at.hannibal2.skyhanni.utils.LorenzUtils.isAnyOf import at.hannibal2.skyhanni.utils.LorenzVec -import at.hannibal2.skyhanni.utils.RenderUtils.draw3DLine_nea +import at.hannibal2.skyhanni.utils.RenderUtils.draw3DLineNea import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText import at.hannibal2.skyhanni.utils.RenderUtils.drawWaypointFilled import at.hannibal2.skyhanni.utils.SimpleTimeMark @@ -112,7 +112,7 @@ object PestParticleLine { // TODO time in config if (next.spawnTime.passedSince() > 5.seconds) continue val location = next.location - event.draw3DLine_nea( + event.draw3DLineNea( prev.location, location, color, diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestParticleWaypoint.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestParticleWaypoint.kt index 33c9dbea2f57..3d24240d101d 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestParticleWaypoint.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestParticleWaypoint.kt @@ -144,7 +144,11 @@ object PestParticleWaypoint { event.drawWaypointFilled(waypoint, color, beacon = true) event.drawDynamicText(waypoint, text, 1.3) - if (config.drawLine) event.drawLineToEye(waypoint, color, 3, false, + if (config.drawLine) event.drawLineToEye( + waypoint, + color, + 3, + false, ) } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/pests/SprayDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/pests/SprayDisplay.kt index 62301f5d73b9..b7db28d37ca9 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/pests/SprayDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/pests/SprayDisplay.kt @@ -37,7 +37,7 @@ object SprayDisplay { val timer = it.expiry.timeUntil() "§eSprayed with §a${it.type.displayName} §7- ${timer.timerColor("§b")}${timer.format()}" } ?: if (config.showNotSprayed) "§cNot sprayed!" else "" - } ?: "" + }.orEmpty() } if (config.expiryNotification) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorCompactChat.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorCompactChat.kt index 8cafd5260a1a..1524084546dd 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorCompactChat.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorCompactChat.kt @@ -32,6 +32,7 @@ object GardenVisitorCompactChat { * REGEX-TEST: §7§8+§d1,241 Gemstone Powder * REGEX-TEST: §7§8+§2Crystal Hollows Pass */ + @Suppress("MaxLineLength") private val visitorRewardPattern by patternGroup.pattern( "visitorreward", "^ {4}(?:(?:§.)+\\+)?(?:(?§.)(?[\\d,]+(?:\\.?(?:\\d)?k)?)x? )?(?:(?(?:§.)+)?(?.*?))(?: (?:(?:§.)?)?x(?\\d+))?\$" 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 1d5907d85284..88394a0f8eb2 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 @@ -1,5 +1,6 @@ package at.hannibal2.skyhanni.features.garden.visitor +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.config.features.garden.visitor.VisitorConfig.HighlightMode import at.hannibal2.skyhanni.data.IslandType @@ -252,7 +253,7 @@ object GardenVisitorFeatures { val ingredients = NEUItems.getRecipes(internalName) // TODO describe what this line does .firstOrNull { !it.ingredients.first().internalName.contains("PEST") } - ?.ingredients ?: emptySet() + ?.ingredients.orEmpty() if (ingredients.isEmpty()) return val requiredIngredients = mutableMapOf() @@ -336,7 +337,7 @@ object GardenVisitorFeatures { } } - @SubscribeEvent + @HandleEvent fun onSackUpdate(event: SackDataUpdateEvent) { update() } @@ -582,7 +583,9 @@ object GardenVisitorFeatures { } } - if ((config.highlightStatus == HighlightMode.COLOR || config.highlightStatus == HighlightMode.BOTH) && entity is EntityLivingBase) { + if ((config.highlightStatus == HighlightMode.COLOR || config.highlightStatus == HighlightMode.BOTH) && + entity is EntityLivingBase + ) { val color = visitor.status.color if (color != -1) { RenderLivingEntityHelper.setEntityColor( diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ChunkedStat.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ChunkedStatsLine.kt similarity index 52% rename from src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ChunkedStat.kt rename to src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ChunkedStatsLine.kt index 4acfcb81db57..57000be68b86 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ChunkedStat.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ChunkedStatsLine.kt @@ -4,67 +4,86 @@ import at.hannibal2.skyhanni.data.MiningAPI import at.hannibal2.skyhanni.data.PurseAPI import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.chunkedConfig import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.informationFilteringConfig -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.formatNum +import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.formatNumber import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getBank import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getBits +import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getBitsAvailable import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getBitsLine -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getBitsToClaim import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getCopper import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getGems import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getHeat import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getMotes import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getNorthStars +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementBank +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementBits +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementCold +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementCopper +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementGems +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementHeat +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementMotes +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementNorthStars +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementPurse private val hideEmptyLines get() = informationFilteringConfig.hideEmptyLines -enum class ChunkedStat( +enum class ChunkedStatsLine( private val displayPair: () -> String, - val showWhen: () -> Boolean, + private val showWhen: () -> Boolean, + private val showIsland: () -> Boolean, private val configLine: String, ) { PURSE( - displayPair = { "§6${PurseAPI.currentPurse.formatNum()}" }, - showWhen = { !(hideEmptyLines && PurseAPI.currentPurse.toInt() == 0) && ScoreboardElement.PURSE.showWhen() }, + displayPair = { "§6${formatNumber(PurseAPI.currentPurse)}" }, + showWhen = { !(hideEmptyLines && PurseAPI.currentPurse.toInt() == 0) && ScoreboardElementPurse.showWhen() }, + showIsland = { ScoreboardElementPurse.showIsland() }, configLine = "§6Purse", ), MOTES( displayPair = { "§b${getMotes()}" }, - showWhen = { !(hideEmptyLines && getMotes() == "0") && ScoreboardElement.MOTES.showWhen() }, + showWhen = { !(hideEmptyLines && getMotes() == "0") && ScoreboardElementMotes.showWhen() }, + showIsland = { ScoreboardElementMotes.showIsland() }, configLine = "§dMotes", ), BANK( displayPair = { "§6${getBank()}" }, - showWhen = { !(hideEmptyLines && (getBank() == "0" || getBank() == "0§7 / §60")) && ScoreboardElement.BANK.showWhen() }, + showWhen = { !(hideEmptyLines && (getBank() == "0" || getBank() == "0§7 / §60")) && ScoreboardElementBank.showWhen() }, + showIsland = { ScoreboardElementBank.showIsland() }, configLine = "§6Bank", ), BITS( displayPair = { getBitsLine() }, - showWhen = { !(hideEmptyLines && getBits() == "0" && getBitsToClaim() == "0") && ScoreboardElement.BITS.showWhen() }, + showWhen = { !(hideEmptyLines && getBits() == "0" && getBitsAvailable() == "0") && ScoreboardElementBits.showWhen() }, + showIsland = { ScoreboardElementBits.showIsland() }, configLine = "§bBits", ), COPPER( displayPair = { "§c${getCopper()}" }, - showWhen = { !(hideEmptyLines && getCopper() == "0") && ScoreboardElement.COPPER.showWhen() }, + showWhen = { !(hideEmptyLines && getCopper() == "0") && ScoreboardElementCopper.showWhen() }, + showIsland = { ScoreboardElementCopper.showIsland() }, configLine = "§cCopper", ), GEMS( displayPair = { "§a${getGems()}" }, - showWhen = { !(hideEmptyLines && getGems() == "0") && ScoreboardElement.GEMS.showWhen() }, + showWhen = { !(hideEmptyLines && getGems() == "0") && ScoreboardElementGems.showWhen() }, + showIsland = { ScoreboardElementGems.showIsland() }, configLine = "§aGems", ), HEAT( displayPair = { "§c${getHeat()}" }, - showWhen = { !(hideEmptyLines && getHeat() == "§c♨ 0") && ScoreboardElement.HEAT.showWhen() }, + showWhen = { !(hideEmptyLines && getHeat() == "§c♨ 0") && ScoreboardElementHeat.showWhen() }, + showIsland = { ScoreboardElementHeat.showIsland() }, configLine = "§cHeat", ), COLD( displayPair = { "§b${MiningAPI.cold}❄" }, - showWhen = { !(hideEmptyLines && MiningAPI.cold == 0) && ScoreboardElement.COLD.showWhen() }, + showWhen = { !(hideEmptyLines && MiningAPI.cold == 0) && ScoreboardElementCold.showWhen() }, + showIsland = { ScoreboardElementCold.showIsland() }, configLine = "§bCold", ), NORTH_STARS( displayPair = { "§d${getNorthStars()}" }, - showWhen = { !(hideEmptyLines && getNorthStars() == "0") && ScoreboardElement.NORTH_STARS.showWhen() }, + showWhen = { !(hideEmptyLines && getNorthStars() == "0") && ScoreboardElementNorthStars.showWhen() }, + showIsland = { ScoreboardElementNorthStars.showIsland() }, configLine = "§dNorth Stars", ), ; @@ -72,10 +91,22 @@ enum class ChunkedStat( override fun toString() = configLine companion object { - fun getChunkedStats() = chunkedConfig.chunkedStats.mapNotNull { - it.takeIf { it.showWhen() }?.displayPair?.invoke() + + private var currentIslandStats = listOf() + + fun getChunkedStats() = buildList { + currentIslandStats.forEach { stat -> + if (stat.showWhen()) { + add(stat.displayPair.invoke()) + } + } } - fun shouldShowChunkedStats() = chunkedConfig.chunkedStats.any { it.showWhen() } + fun shouldShowChunkedStats() = currentIslandStats.any { it.showWhen() } + + fun showChunkedStatsIsland(): Boolean { + currentIslandStats = chunkedConfig.chunkedStats.filter { it.showIsland() } + return currentIslandStats.isNotEmpty() + } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboard.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboard.kt index 4a86519c374e..14f311aad281 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboard.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboard.kt @@ -1,28 +1,33 @@ -// -// TODO LIST -// V2 RELEASE -// - Bank API (actually maybe not, I like the current design) -// - countdown events like fishing festival + fiesta when its not on tablist -// - improve hide coin difference to also work with bits, motes, etc -// - color options in the purse etc lines -// - choose the amount of decimal places in shorten nums -// +/** + * TODO LIST + * - Bank API (actually maybe not, I like the current design) + * - countdown events like fishing festival + fiesta when its not on tablist + * - improve hide coin difference to also work with bits, motes, etc + * - color options in the purse etc lines + * - choose the amount of decimal places in shorten nums + * - heavily optimize elements and events by only updating them when absolutely needed + */ package at.hannibal2.skyhanni.features.gui.customscoreboard import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.config.enums.OutsideSbFeature import at.hannibal2.skyhanni.data.ScoreboardData import at.hannibal2.skyhanni.events.ConfigLoadEvent import at.hannibal2.skyhanni.events.DebugDataCollectEvent import at.hannibal2.skyhanni.events.GuiPositionMovedEvent import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.IslandChangeEvent import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent import at.hannibal2.skyhanni.events.ScoreboardUpdateEvent +import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardLine.Companion.align +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElement +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementTitle +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.CollectionUtils.takeIfNotEmpty import at.hannibal2.skyhanni.utils.ConditionalUtils import at.hannibal2.skyhanni.utils.DelayedRun.runDelayed import at.hannibal2.skyhanni.utils.LorenzUtils @@ -34,21 +39,22 @@ import at.hannibal2.skyhanni.utils.SimpleTimeMark.Companion.fromNow import at.hannibal2.skyhanni.utils.StringUtils.firstLetterUppercase import at.hannibal2.skyhanni.utils.TabListData import at.hannibal2.skyhanni.utils.renderables.Renderable -import com.google.gson.JsonArray -import com.google.gson.JsonPrimitive import net.minecraftforge.client.GuiIngameForge import net.minecraftforge.client.event.RenderGameOverlayEvent import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.seconds -typealias ScoreboardElementType = Pair - @SkyHanniModule object CustomScoreboard { - private var display = emptyList() - private var cache = emptyList() + private var display: Renderable? = null + private var cache: Renderable? = null + + private var currentIslandEntries = listOf() + var currentIslandEvents = listOf() + private set + private const val GUI_NAME = "Custom Scoreboard" private var nextScoreboardUpdate = SimpleTimeMark.farFuture() @@ -56,25 +62,16 @@ object CustomScoreboard { @SubscribeEvent fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) { if (!isEnabled()) return - if (display.isEmpty()) return + display ?: return val render = - if (LorenzUtils.inSkyBlock && !TabListData.fullyLoaded && displayConfig.cacheScoreboardOnIslandSwitch && cache.isNotEmpty()) { - cache - } else { - display - } - - val textRenderable = Renderable.verticalContainer( - render.map { Renderable.string(it.first, horizontalAlign = it.second) }, - displayConfig.lineSpacing - 10, - horizontalAlign = HorizontalAlignment.CENTER, - verticalAlign = VerticalAlignment.CENTER, - ) + if (LorenzUtils.inSkyBlock && !TabListData.fullyLoaded && displayConfig.cacheScoreboardOnIslandSwitch && cache != null) cache + else display - val finalRenderable = RenderBackground.addBackground(textRenderable) + render ?: return - RenderBackground.updatePosition(finalRenderable) + // We want to update the background every time, so we can have a smooth transition when using chroma as the color + val finalRenderable = RenderBackground.addBackground(render) config.position.renderRenderable(finalRenderable, posLabel = GUI_NAME) } @@ -110,9 +107,9 @@ object CustomScoreboard { if (dirty || nextScoreboardUpdate.isInPast()) { nextScoreboardUpdate = 250.milliseconds.fromNow() dirty = false - display = createLines().removeEmptyLinesFromEdges() + display = createLines().removeEmptyLinesFromEdges().createRenderable() if (TabListData.fullyLoaded) { - cache = display.toList() + cache = display } } @@ -144,53 +141,47 @@ object CustomScoreboard { } private fun addAllNonSkyBlockLines() = buildList { - addAll(ScoreboardElement.TITLE.getVisiblePair()) - addAll(ScoreboardData.sidebarLinesFormatted.map { it to HorizontalAlignment.LEFT }) + addAll(ScoreboardElementTitle.getLines()) + addAll(ScoreboardData.sidebarLinesFormatted.map { it.align() }) } private fun addDefaultSkyBlockLines() = buildList { - add(ScoreboardData.objectiveTitle to displayConfig.titleAndFooter.alignTitleAndFooter) - addAll(ScoreboardData.sidebarLinesFormatted.map { it to HorizontalAlignment.LEFT }) + add(ScoreboardData.objectiveTitle align displayConfig.titleAndFooter.alignTitle) + addAll(ScoreboardData.sidebarLinesFormatted.map { it.align() }) } - private fun addCustomSkyBlockLines() = buildList { - for (element in config.scoreboardEntries) { - val lines = element.getVisiblePair() + private fun addCustomSkyBlockLines() = buildList { + for (element in currentIslandEntries) { + val lines = element.getLines() if (lines.isEmpty()) continue if ( informationFilteringConfig.hideConsecutiveEmptyLines && - lines.first().first == "" && - lastOrNull()?.first?.isEmpty() == true + lines.first().display.isEmpty() && + lastOrNull()?.display?.isEmpty() == true ) { continue } - if (lines.first().first == "") { - add("" to HorizontalAlignment.LEFT) - continue - } - - if (lines.any { it.first == "" }) { - continue - } - addAll(lines) } } - private fun List.removeEmptyLinesFromEdges(): List { - if (config.informationFiltering.hideEmptyLinesAtTopAndBottom) { - return this - .dropWhile { it.first.isEmpty() } - .dropLastWhile { it.first.isEmpty() } - } - return this - } + private fun List.createRenderable() = Renderable.verticalContainer( + map { Renderable.string(it.display, horizontalAlign = it.alignment) }, + displayConfig.lineSpacing - 10, + horizontalAlign = HorizontalAlignment.CENTER, + verticalAlign = VerticalAlignment.CENTER, + ) + + private fun List.removeEmptyLinesFromEdges(): List = + takeIf { !informationFilteringConfig.hideEmptyLinesAtTopAndBottom } + ?: dropWhile { it.display.isBlank() }.dropLastWhile { it.display.isBlank() } private var dirty = false - // Thank you Apec for showing that the ElementType of the stupid scoreboard is FUCKING HELMET WTF + // The ElementType for the Vanilla Scoreboard is called HELMET + // Thanks to APEC for showing this @SubscribeEvent fun onRenderScoreboard(event: RenderGameOverlayEvent.Post) { if (event.type == RenderGameOverlayEvent.ElementType.HELMET) { @@ -213,6 +204,12 @@ object CustomScoreboard { ) { if (!isHideVanillaScoreboardEnabled()) dirty = true } + ConditionalUtils.onToggle( + config.scoreboardEntries, + eventsConfig.eventEntries, + ) { + updateIslandEntries() + } } @SubscribeEvent @@ -222,6 +219,16 @@ object CustomScoreboard { } } + @SubscribeEvent + fun onIslandChange(event: IslandChangeEvent) { + updateIslandEntries() + } + + private fun updateIslandEntries() { + currentIslandEntries = config.scoreboardEntries.get().map { it.element }.filter { it.showIsland() } + currentIslandEvents = eventsConfig.eventEntries.get().map { it.event }.filter { it.showIsland() } + } + @SubscribeEvent fun onDebugDataCollect(event: DebugDataCollectEvent) { event.title("Custom Scoreboard") @@ -229,117 +236,34 @@ object CustomScoreboard { if (!config.enabled.get()) { add("Custom Scoreboard disabled.") } else { - ScoreboardElement.entries.map { element -> + add("Custom Scoreboard Lines:") + ScoreboardConfigElement.entries.forEach { entry -> add( - "${element.name.firstLetterUppercase()} - " + - "${element.showWhen.invoke()} - " + - "${element.getVisiblePair().map { it.first }}", + " ${entry.name.firstLetterUppercase()} - " + + "island: ${entry.element.showIsland()} - " + + "show: ${entry.element.showWhen()} - " + + "${entry.element.getLines().map { it.display }}", ) } + allUnknownLines.takeIfNotEmpty()?.let { set -> + add("Recent Unknown Lines:") + set.forEach { add(" ${it.line}") } + } } } } + @JvmStatic + fun resetAppearance() { + with(config.scoreboardEntries) { + get().clear() + get().addAll(ScoreboardConfigElement.defaultOptions) + notifyObservers() + } + } + private fun isEnabled() = (LorenzUtils.inSkyBlock || (OutsideSbFeature.CUSTOM_SCOREBOARD.isSelected() && LorenzUtils.onHypixel)) && config.enabled.get() private fun isHideVanillaScoreboardEnabled() = isEnabled() && displayConfig.hideVanillaScoreboard.get() - - @SubscribeEvent - fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { - val prefix = "gui.customScoreboard" - val displayConfigPrefix = "$prefix.displayConfig" - val displayPrefix = "$prefix.display" - - event.move( - 28, - "$prefix.displayConfig.showAllActiveEvents", - "$prefix.displayConfig.eventsConfig.showAllActiveEvents", - ) - - event.move(31, "$displayConfigPrefix.arrowAmountDisplay", "$displayPrefix.arrow.amountDisplay") - event.move(31, "$displayConfigPrefix.colorArrowAmount", "$displayPrefix.arrow.colorArrowAmount") - event.move(31, "$displayConfigPrefix.showMagicalPower", "$displayPrefix.maxwell.showMagicalPower") - event.move(31, "$displayConfigPrefix.compactTuning", "$displayPrefix.maxwell.compactTuning") - event.move(31, "$displayConfigPrefix.tuningAmount", "$displayPrefix.maxwell.tuningAmount") - event.move(31, "$displayConfigPrefix.hideVanillaScoreboard", "$displayPrefix.hideVanillaScoreboard") - event.move(31, "$displayConfigPrefix.displayNumbersFirst", "$displayPrefix.displayNumbersFirst") - event.move(31, "$displayConfigPrefix.showUnclaimedBits", "$displayPrefix.showUnclaimedBits") - event.move(31, "$displayConfigPrefix.showMaxIslandPlayers", "$displayPrefix.showMaxIslandPlayers") - event.move(31, "$displayConfigPrefix.numberFormat", "$displayPrefix.numberFormat") - event.move(31, "$displayConfigPrefix.lineSpacing", "$displayPrefix.lineSpacing") - event.move( - 31, - "$displayConfigPrefix.cacheScoreboardOnIslandSwitch", - "$displayPrefix.cacheScoreboardOnIslandSwitch", - ) - // Categories - event.move(31, "$displayConfigPrefix.alignment", "$displayPrefix.alignment") - event.move(31, "$displayConfigPrefix.titleAndFooter", "$displayPrefix.titleAndFooter") - event.move(31, "$prefix.backgroundConfig", "$prefix.background") - event.move(31, "$prefix.informationFilteringConfig", "$prefix.informationFiltering") - event.move(31, "$displayConfigPrefix.eventsConfig", "$displayPrefix.events") - event.move(31, "$prefix.mayorConfig", "$displayPrefix.mayor") - event.move(31, "$prefix.partyConfig", "$displayPrefix.party") - - event.transform(37, "$displayPrefix.events.eventEntries") { element -> - val array = element.asJsonArray - array.add(JsonPrimitive(ScoreboardEvent.QUEUE.name)) - array - } - event.transform(40, "$displayPrefix.events.eventEntries") { element -> - val jsonArray = element.asJsonArray - val newArray = JsonArray() - - for (jsonElement in jsonArray) { - val stringValue = jsonElement.asString - if (stringValue !in listOf("HOT_DOG_CONTEST", "EFFIGIES")) { - newArray.add(jsonElement) - } - } - - if (jsonArray.any { it.asString in listOf("HOT_DOG_CONTEST", "EFFIGIES") }) { - newArray.add(JsonPrimitive(ScoreboardEvent.RIFT.name)) - } - - newArray - } - - event.move(43, "$displayPrefix.alignment.alignRight", "$displayPrefix.alignment.horizontalAlignment") { - JsonPrimitive( - if (it.asBoolean) { - HorizontalAlignment.RIGHT.name - } else { - HorizontalAlignment.DONT_ALIGN.name - }, - ) - } - event.move(43, "$displayPrefix.alignment.alignCenterVertically", "$displayPrefix.alignment.verticalAlignment") { - JsonPrimitive( - if (it.asBoolean) { - VerticalAlignment.CENTER.name - } else { - VerticalAlignment.DONT_ALIGN.name - }, - ) - } - event.transform(50, "$displayPrefix.events.eventEntries") { element -> - val array = element.asJsonArray - array.add(JsonPrimitive(ScoreboardEvent.ANNIVERSARY.name)) - array.add(JsonPrimitive(ScoreboardEvent.CARNIVAL.name)) - array - } - event.transform(51, "$displayPrefix.events.eventEntries") { element -> - val array = element.asJsonArray - array.add(JsonPrimitive(ScoreboardEvent.NEW_YEAR.name)) - array - } - event.move( - 57, - "$displayPrefix.titleAndFooter.useHypixelTitleAnimation", - "$displayPrefix.titleAndFooter.useCustomTitle", - ) { - JsonPrimitive(!it.asBoolean) - } - } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboardConfigFix.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboardConfigFix.kt new file mode 100644 index 000000000000..44dac812764e --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboardConfigFix.kt @@ -0,0 +1,119 @@ +package at.hannibal2.skyhanni.features.gui.customscoreboard + +import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.RenderUtils.HorizontalAlignment +import at.hannibal2.skyhanni.utils.RenderUtils.VerticalAlignment +import com.google.gson.JsonArray +import com.google.gson.JsonElement +import com.google.gson.JsonPrimitive +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +@SkyHanniModule +object CustomScoreboardConfigFix { + + private const val PREFIX = "gui.customScoreboard" + private const val DISPLAY_PREFIX = "$PREFIX.display" + private const val DISPLAY_CONFIG_PREFIX = "$PREFIX.displayConfig" + private const val EVENTS_CONFIG_KEY = "$DISPLAY_CONFIG_PREFIX.eventsConfig" + private const val ALIGNMENT_KEY = "$DISPLAY_PREFIX.alignment" + private const val TITLE_AND_FOOTER_KEY = "$DISPLAY_PREFIX.titleAndFooter" + private const val EVENT_ENTRIES_KEY = "$DISPLAY_PREFIX.events.eventEntries" + + @SubscribeEvent + fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { + + event.move(28, "$DISPLAY_CONFIG_PREFIX.showAllActiveEvents", "$EVENTS_CONFIG_KEY.showAllActiveEvents") + + val configPrefixMappings = mapOf( + "$DISPLAY_CONFIG_PREFIX.showAllActiveEvents" to "$EVENTS_CONFIG_KEY.showAllActiveEvents", + "$DISPLAY_CONFIG_PREFIX.arrowAmountDisplay" to "$DISPLAY_PREFIX.arrow.amountDisplay", + "$DISPLAY_CONFIG_PREFIX.colorArrowAmount" to "$DISPLAY_PREFIX.arrow.colorArrowAmount", + "$DISPLAY_CONFIG_PREFIX.showMagicalPower" to "$DISPLAY_PREFIX.maxwell.showMagicalPower", + "$DISPLAY_CONFIG_PREFIX.compactTuning" to "$DISPLAY_PREFIX.maxwell.compactTuning", + "$DISPLAY_CONFIG_PREFIX.tuningAmount" to "$DISPLAY_PREFIX.maxwell.tuningAmount", + "$DISPLAY_CONFIG_PREFIX.hideVanillaScoreboard" to "$DISPLAY_PREFIX.hideVanillaScoreboard", + "$DISPLAY_CONFIG_PREFIX.displayNumbersFirst" to "$DISPLAY_PREFIX.displayNumbersFirst", + "$DISPLAY_CONFIG_PREFIX.showUnclaimedBits" to "$DISPLAY_PREFIX.showUnclaimedBits", + "$DISPLAY_CONFIG_PREFIX.showMaxIslandPlayers" to "$DISPLAY_PREFIX.showMaxIslandPlayers", + "$DISPLAY_CONFIG_PREFIX.numberFormat" to "$DISPLAY_PREFIX.numberFormat", + "$DISPLAY_CONFIG_PREFIX.lineSpacing" to "$DISPLAY_PREFIX.lineSpacing", + "$DISPLAY_CONFIG_PREFIX.cacheScoreboardOnIslandSwitch" to "$DISPLAY_PREFIX.cacheScoreboardOnIslandSwitch", + "$DISPLAY_CONFIG_PREFIX.alignment" to ALIGNMENT_KEY, + "$PREFIX.backgroundConfig" to "$PREFIX.background", + "$PREFIX.informationFilteringConfig" to "$PREFIX.informationFiltering", + EVENTS_CONFIG_KEY to "$DISPLAY_PREFIX.events", + "$PREFIX.mayorConfig" to "$DISPLAY_PREFIX.mayor", + "$PREFIX.partyConfig" to "$DISPLAY_PREFIX.party", + ) + + configPrefixMappings.forEach { (oldKey, newKey) -> + event.move(31, oldKey, newKey) + } + + event.transform(37, EVENT_ENTRIES_KEY) { + it.asJsonArray.apply { + add(JsonPrimitive(ScoreboardConfigEventElement.QUEUE.name)) + } + } + + event.transform(40, EVENT_ENTRIES_KEY) { element -> + replaceElements(element, listOf("HOT_DOG_CONTEST", "EFFIGIES"), ScoreboardConfigEventElement.RIFT.name) + } + + event.move(43, "$ALIGNMENT_KEY.alignRight", "$ALIGNMENT_KEY.horizontalAlignment") { + JsonPrimitive( + if (it.asBoolean) HorizontalAlignment.RIGHT.name + else HorizontalAlignment.DONT_ALIGN.name, + ) + } + event.move(43, "$ALIGNMENT_KEY.alignCenterVertically", "$ALIGNMENT_KEY.verticalAlignment") { + JsonPrimitive( + if (it.asBoolean) VerticalAlignment.CENTER.name + else VerticalAlignment.DONT_ALIGN.name, + ) + } + + event.transform(50, EVENT_ENTRIES_KEY) { + it.asJsonArray.apply { + add(JsonPrimitive(ScoreboardConfigEventElement.ANNIVERSARY.name)) + add(JsonPrimitive(ScoreboardConfigEventElement.CARNIVAL.name)) + } + } + + event.transform(51, EVENT_ENTRIES_KEY) { + it.asJsonArray.apply { + add(JsonPrimitive(ScoreboardConfigEventElement.NEW_YEAR.name)) + } + } + + event.move(57, "$TITLE_AND_FOOTER_KEY.useHypixelTitleAnimation", "$TITLE_AND_FOOTER_KEY.useCustomTitle") { + JsonPrimitive(!it.asBoolean) + } + + event.transform(63, EVENT_ENTRIES_KEY) { element -> + replaceElements(element, listOf("GARDEN_CLEAN_UP", "GARDEN_PASTING"), ScoreboardConfigEventElement.GARDEN.name) + } + listOf("customTitle", "customFooter").forEach { key -> + event.transform(63, "$TITLE_AND_FOOTER_KEY.$key") { + JsonPrimitive(it.asString.replace("&", "&&")) + } + } + listOf("alignTitle", "alignFooter").forEach { key -> + event.move(63, "$TITLE_AND_FOOTER_KEY.alignTitleAndFooter", "$TITLE_AND_FOOTER_KEY.$key") + } + } + + private fun replaceElements(element: JsonElement, oldElements: List, newElement: String): JsonArray { + val jsonArray = element.asJsonArray + val newArray = JsonArray() + + jsonArray.filterNot { it.asString in oldElements }.forEach(newArray::add) + + if (jsonArray.any { it.asString in oldElements }) { + newArray.add(JsonPrimitive(newElement)) + } + + return newArray + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboardUtils.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboardUtils.kt index 99fdc4f3fcf6..8010208a305f 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboardUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/CustomScoreboardUtils.kt @@ -3,71 +3,88 @@ package at.hannibal2.skyhanni.features.gui.customscoreboard import at.hannibal2.skyhanni.config.features.gui.customscoreboard.DisplayConfig import at.hannibal2.skyhanni.data.BitsAPI import at.hannibal2.skyhanni.data.HypixelData +import at.hannibal2.skyhanni.data.PurseAPI import at.hannibal2.skyhanni.data.ScoreboardData +import at.hannibal2.skyhanni.data.model.TabWidget import at.hannibal2.skyhanni.features.bingo.BingoAPI import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.displayConfig +import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardLine.Companion.align import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.NumberUtil.formatDouble import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat -import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.RegexUtils.groupOrNull +import at.hannibal2.skyhanni.utils.RegexUtils.matchGroup import at.hannibal2.skyhanni.utils.StringUtils.removeResets import at.hannibal2.skyhanni.utils.StringUtils.trimWhiteSpace -import at.hannibal2.skyhanni.utils.TabListData import java.util.regex.Pattern +@Suppress("TooManyFunctions") object CustomScoreboardUtils { - internal fun getGroupFromPattern(list: List, pattern: Pattern, group: String) = list.map { - it.removeResets().trimWhiteSpace() - }.firstNotNullOfOrNull { line -> - pattern.matchMatcher(line) { - group(group) + private fun getGroup(pattern: Pattern, list: List, group: String) = + list.map { it.removeResets().trimWhiteSpace() }.firstNotNullOfOrNull { line -> + pattern.matchGroup(line, group) } - } fun getProfileTypeSymbol() = when { HypixelData.ironman -> "§7♲ " HypixelData.stranded -> "§a☀ " HypixelData.bingo -> ScoreboardData.sidebarLinesFormatted.firstNotNullOfOrNull { - BingoAPI.getIconFromScoreboard(it)?.plus(" ") + BingoAPI.getIconFromScoreboard(it)?.plus(" ") // TODO: add bingo rank to bingo api } ?: "§e❤ " else -> "§e" } - // TODO change to a non extended function - internal fun Number.formatNum(): String = when (displayConfig.numberFormat) { - DisplayConfig.NumberFormat.SHORT -> this.shortFormat() - DisplayConfig.NumberFormat.LONG -> this.addSeparators() + internal fun formatNumber(number: Number): String = when (displayConfig.numberFormat) { + DisplayConfig.NumberFormat.SHORT -> number.shortFormat() + DisplayConfig.NumberFormat.LONG -> number.addSeparators() else -> "0" } - internal fun String.formatNum() = this.formatDouble().formatNum() + internal fun formatStringNum(string: String) = formatNumber(string.formatDouble()) + + internal fun getMotes() = getGroup(ScoreboardPattern.motesPattern, getSbLines(), "motes") ?: "0" + + internal fun getSoulflow() = TabWidget.SOULFLOW.matchMatcherFirstLine { group("amount") } ?: "0" - internal fun getMotes() = getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.motesPattern, "motes") - internal fun getBank() = getGroupFromPattern(TabListData.getTabList(), ScoreboardPattern.bankPattern, "bank") + internal fun getPurseEarned() = getGroup(PurseAPI.coinsPattern, getSbLines(), "earned")?.let { " §7(§e+$it§7)§6" } - internal fun getBits() = BitsAPI.bits.coerceAtLeast(0).formatNum() + internal fun getBank() = TabWidget.BANK.matchMatcherFirstLine { + group("amount") + (groupOrNull("personal")?.let { " §7/ §6$it" }.orEmpty()) + } ?: "0" - internal fun getBitsToClaim() = BitsAPI.bitsAvailable.coerceAtLeast(0).formatNum() + internal fun getBits() = formatNumber(BitsAPI.bits.coerceAtLeast(0)) + + internal fun getBitsAvailable() = formatNumber(BitsAPI.bitsAvailable.coerceAtLeast(0)) internal fun getBitsLine() = if (displayConfig.showUnclaimedBits) { - "§b${getBits()}§7/§b${getBitsToClaim()}" - } else { - "§b${getBits()}" - } + "§b${getBits()}§7/§b${getBitsAvailable()}" + } else "§b${getBits()}" - internal fun getCopper() = - getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.copperPattern, "copper") + internal fun getCopper() = getGroup(ScoreboardPattern.copperPattern, getSbLines(), "copper") ?: "0" - internal fun getGems() = getGroupFromPattern(TabListData.getTabList(), ScoreboardPattern.gemsPattern, "gems") + internal fun getGems() = TabWidget.GEMS.matchMatcherFirstLine { group("gems") } ?: "0" - internal fun getHeat() = - getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.heatPattern, "heat") + internal fun getHeat() = getGroup(ScoreboardPattern.heatPattern, getSbLines(), "heat") - internal fun getNorthStars() = - getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.northstarsPattern, "northstars") + internal fun getNorthStars() = getGroup(ScoreboardPattern.northstarsPattern, getSbLines(), "northStars") ?: "0" + internal fun getTimeSymbol() = getGroup(ScoreboardPattern.timePattern, getSbLines(), "symbol").orEmpty() + + internal fun getTablistEvent() = TabWidget.EVENT.matchMatcherFirstLine { groupOrNull("color") + group("event") } + + internal fun getElementsFromAny(element: Any?): List = when (element) { + null -> listOf() + is List<*> -> element.mapNotNull { it?.toScoreboardElement() } + else -> listOfNotNull(element.toScoreboardElement()) + } + + private fun Any.toScoreboardElement(): ScoreboardLine? = when (this) { + is String -> this.align() + is ScoreboardLine -> this + else -> null + } - class UndetectedScoreboardLines(message: String) : Exception(message) + internal fun getSbLines() = ScoreboardData.sidebarLinesFormatted } diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardConfigElement.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardConfigElement.kt new file mode 100644 index 000000000000..9d9dcb378617 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardConfigElement.kt @@ -0,0 +1,125 @@ +package at.hannibal2.skyhanni.features.gui.customscoreboard + +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElement +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementBank +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementBits +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementChunkedStats +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementCold +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementCookie +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementCopper +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementDate +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementEmptyLine +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementEvents +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementFooter +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementGems +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementHeat +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementIsland +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementLobbyCode +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementLocation +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementMayor +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementMotes +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementNorthStars +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementObjective +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementParty +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementPlayerAmount +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementPowder +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementPower +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementProfile +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementPurse +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementQuiver +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementSlayer +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementSoulflow +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementTime +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementTitle +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementTuning +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementUnknown +import at.hannibal2.skyhanni.features.gui.customscoreboard.elements.ScoreboardElementVisiting + +// TODO once the config can support dynamic lists, remove this enum +enum class ScoreboardConfigElement(val element: ScoreboardElement) { + TITLE(ScoreboardElementTitle), + PROFILE(ScoreboardElementProfile), + PURSE(ScoreboardElementPurse), + MOTES(ScoreboardElementMotes), + BANK(ScoreboardElementBank), + BITS(ScoreboardElementBits), + COPPER(ScoreboardElementCopper), + GEMS(ScoreboardElementGems), + HEAT(ScoreboardElementHeat), + COLD(ScoreboardElementCold), + NORTH_STARS(ScoreboardElementNorthStars), + CHUNKED_STATS(ScoreboardElementChunkedStats), + SOULFLOW(ScoreboardElementSoulflow), + ISLAND(ScoreboardElementIsland), + LOCATION(ScoreboardElementLocation), + PLAYER_AMOUNT(ScoreboardElementPlayerAmount), + VISITING(ScoreboardElementVisiting), + DATE(ScoreboardElementDate), + TIME(ScoreboardElementTime), + LOBBY_CODE(ScoreboardElementLobbyCode), + POWER(ScoreboardElementPower), + TUNING(ScoreboardElementTuning), + COOKIE(ScoreboardElementCookie), + OBJECTIVE(ScoreboardElementObjective), + SLAYER(ScoreboardElementSlayer), + QUIVER(ScoreboardElementQuiver), + POWDER(ScoreboardElementPowder), + EVENTS(ScoreboardElementEvents), + MAYOR(ScoreboardElementMayor), + PARTY(ScoreboardElementParty), + FOOTER(ScoreboardElementFooter), + EXTRA(ScoreboardElementUnknown), + EMPTY_LINE(ScoreboardElementEmptyLine), + EMPTY_LINE2(ScoreboardElementEmptyLine), + EMPTY_LINE3(ScoreboardElementEmptyLine), + EMPTY_LINE4(ScoreboardElementEmptyLine), + EMPTY_LINE5(ScoreboardElementEmptyLine), + EMPTY_LINE6(ScoreboardElementEmptyLine), + EMPTY_LINE7(ScoreboardElementEmptyLine), + EMPTY_LINE8(ScoreboardElementEmptyLine), + EMPTY_LINE9(ScoreboardElementEmptyLine), + EMPTY_LINE10(ScoreboardElementEmptyLine), + ; + + override fun toString() = element.configLine + + companion object { + @JvmField + val defaultOptions = listOf( + TITLE, + PROFILE, + PURSE, + BANK, + MOTES, + BITS, + COPPER, + GEMS, + NORTH_STARS, + HEAT, + COLD, + EMPTY_LINE, + ISLAND, + LOCATION, + LOBBY_CODE, + PLAYER_AMOUNT, + VISITING, + EMPTY_LINE2, + DATE, + TIME, + EVENTS, + COOKIE, + EMPTY_LINE3, + QUIVER, + POWER, + TUNING, + EMPTY_LINE4, + OBJECTIVE, + SLAYER, + POWDER, + MAYOR, + PARTY, + FOOTER, + EXTRA, + ) + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardConfigEventElement.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardConfigEventElement.kt new file mode 100644 index 000000000000..a9d9a8e854a6 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardConfigEventElement.kt @@ -0,0 +1,98 @@ +package at.hannibal2.skyhanni.features.gui.customscoreboard + +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEvent +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventActiveTablist +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventAnniversary +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventBroodmother +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventCarnival +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventDamage +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventDarkAuction +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventDojo +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventDungeons +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventEssence +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventFlightDuration +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventGarden +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventJacobContest +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventJacobMedals +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventKuudra +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventMagmaBoss +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventMining +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventNewYear +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventQueue +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventRedstone +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventRift +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventServerClose +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventSpooky +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventStartingSoonTablist +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventTrapper +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventVoting +import at.hannibal2.skyhanni.features.gui.customscoreboard.events.ScoreboardEventWinter + +/** + * This enum contains all the lines that either are events or other lines that are so rare/not often seen that they + * don't fit in the normal [ScoreboardConfigElement] enum. + * + * We for example have the [ScoreboardEventVoting] Event, while this is clearly not an event, I don't consider them as normal lines + * because they are visible for a maximum of like 1 minute every 5 days and ~12 hours. + */ + +enum class ScoreboardConfigEventElement(val event: ScoreboardEvent) { + VOTING(ScoreboardEventVoting), + SERVER_CLOSE(ScoreboardEventServerClose), + DUNGEONS(ScoreboardEventDungeons), + KUUDRA(ScoreboardEventKuudra), + DOJO(ScoreboardEventDojo), + DARK_AUCTION(ScoreboardEventDarkAuction), + JACOB_CONTEST(ScoreboardEventJacobContest), + JACOB_MEDALS(ScoreboardEventJacobMedals), + TRAPPER(ScoreboardEventTrapper), + GARDEN(ScoreboardEventGarden), + FLIGHT_DURATION(ScoreboardEventFlightDuration), + WINTER(ScoreboardEventWinter), + NEW_YEAR(ScoreboardEventNewYear), + SPOOKY(ScoreboardEventSpooky), + BROODMOTHER(ScoreboardEventBroodmother), + MINING_EVENTS(ScoreboardEventMining), + DAMAGE(ScoreboardEventDamage), + MAGMA_BOSS(ScoreboardEventMagmaBoss), + CARNIVAL(ScoreboardEventCarnival), + RIFT(ScoreboardEventRift), + ESSENCE(ScoreboardEventEssence), + QUEUE(ScoreboardEventQueue), + ANNIVERSARY(ScoreboardEventAnniversary), + ACTIVE_TABLIST_EVENTS(ScoreboardEventActiveTablist), + STARTING_SOON_TABLIST_EVENTS(ScoreboardEventStartingSoonTablist), + REDSTONE(ScoreboardEventRedstone), + ; + + override fun toString() = event.configLine + + companion object { + @JvmField + val defaultOption = listOf( + VOTING, + SERVER_CLOSE, + DUNGEONS, + KUUDRA, + DOJO, + DARK_AUCTION, + JACOB_CONTEST, + JACOB_MEDALS, + TRAPPER, + GARDEN, + FLIGHT_DURATION, + NEW_YEAR, + WINTER, + SPOOKY, + BROODMOTHER, + MINING_EVENTS, + DAMAGE, + MAGMA_BOSS, + CARNIVAL, + RIFT, + ESSENCE, + ACTIVE_TABLIST_EVENTS, + REDSTONE, + ) + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt deleted file mode 100644 index f20479b65e44..000000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt +++ /dev/null @@ -1,863 +0,0 @@ -package at.hannibal2.skyhanni.features.gui.customscoreboard - -import at.hannibal2.skyhanni.api.HotmAPI -import at.hannibal2.skyhanni.config.features.gui.customscoreboard.ArrowConfig.ArrowAmountDisplay -import at.hannibal2.skyhanni.config.features.gui.customscoreboard.DisplayConfig.PowderDisplay -import at.hannibal2.skyhanni.data.BitsAPI -import at.hannibal2.skyhanni.data.HypixelData -import at.hannibal2.skyhanni.data.HypixelData.getMaxPlayersForCurrentServer -import at.hannibal2.skyhanni.data.HypixelData.getPlayersOnCurrentServer -import at.hannibal2.skyhanni.data.IslandType -import at.hannibal2.skyhanni.data.MaxwellAPI -import at.hannibal2.skyhanni.data.MayorAPI -import at.hannibal2.skyhanni.data.MiningAPI -import at.hannibal2.skyhanni.data.MiningAPI.inGlaciteArea -import at.hannibal2.skyhanni.data.PartyAPI -import at.hannibal2.skyhanni.data.PurseAPI -import at.hannibal2.skyhanni.data.QuiverAPI -import at.hannibal2.skyhanni.data.QuiverAPI.NONE_ARROW_TYPE -import at.hannibal2.skyhanni.data.QuiverAPI.asArrowPercentage -import at.hannibal2.skyhanni.data.ScoreboardData -import at.hannibal2.skyhanni.data.SlayerAPI -import at.hannibal2.skyhanni.features.dungeon.DungeonAPI -import at.hannibal2.skyhanni.features.gui.customscoreboard.ChunkedStat.Companion.getChunkedStats -import at.hannibal2.skyhanni.features.gui.customscoreboard.ChunkedStat.Companion.shouldShowChunkedStats -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.arrowConfig -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.chunkedConfig -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.config -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.displayConfig -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.informationFilteringConfig -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.maxwellConfig -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.mayorConfig -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.partyConfig -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.formatNum -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getBank -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getBitsLine -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getCopper -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getGems -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getGroupFromPattern -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getHeat -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getMotes -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils.getNorthStars -import at.hannibal2.skyhanni.utils.CollectionUtils.nextAfter -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.LorenzUtils.inAdvancedMiningIsland -import at.hannibal2.skyhanni.utils.LorenzUtils.inAnyIsland -import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators -import at.hannibal2.skyhanni.utils.NumberUtil.percentageColor -import at.hannibal2.skyhanni.utils.RegexUtils.anyMatches -import at.hannibal2.skyhanni.utils.RegexUtils.matches -import at.hannibal2.skyhanni.utils.RenderUtils.HorizontalAlignment -import at.hannibal2.skyhanni.utils.SimpleTimeMark -import at.hannibal2.skyhanni.utils.SkyBlockTime -import at.hannibal2.skyhanni.utils.StringUtils.firstLetterUppercase -import at.hannibal2.skyhanni.utils.StringUtils.pluralize -import at.hannibal2.skyhanni.utils.TabListData -import at.hannibal2.skyhanni.utils.TimeUtils.format -import at.hannibal2.skyhanni.utils.TimeUtils.formatted -import kotlin.time.Duration.Companion.seconds - -internal var allUnknownLines = listOf() -internal var lastRecentAlarmWarning = SimpleTimeMark.farPast() - -internal fun recentUnknownLines() = allUnknownLines.filter { it.lastFound.passedSince() < 3.seconds } - -internal class UnknownLine(val line: String) { - val firstFound = SimpleTimeMark.now() - var lastFound = SimpleTimeMark.now() - var lastWarned = SimpleTimeMark.farPast() -} - -enum class ScoreboardElement( - private val displayPair: () -> List, - val showWhen: () -> Boolean, - private val configLine: String, -) { - TITLE( - ::getTitleDisplayPair, - { true }, - "§6§lSKYBLOCK", - ), - PROFILE( - ::getProfileDisplayPair, - { true }, - "§7♲ Blueberry", - ), - PURSE( - ::getPurseDisplayPair, - ::getPurseShowWhen, - "Purse: §652,763,737", - ), - MOTES( - ::getMotesDisplayPair, - ::getMotesShowWhen, - "Motes: §d64,647", - ), - BANK( - ::getBankDisplayPair, - ::getBankShowWhen, - "Bank: §6249M", - ), - BITS( - ::getBitsDisplayPair, - ::getBitsShowWhen, - "Bits: §b59,264", - ), - COPPER( - ::getCopperDisplayPair, - ::getCopperShowWhen, - "Copper: §c23,495", - ), - GEMS( - ::getGemsDisplayPair, - ::getGemsShowWhen, - "Gems: §a57,873", - ), - HEAT( - ::getHeatDisplayPair, - ::getHeatShowWhen, - "Heat: §c♨ 0", - ), - COLD( - ::getColdDisplayPair, - ::getColdShowWhen, - "Cold: §b0❄", - ), - NORTH_STARS( - ::getNorthStarsDisplayPair, - ::getNorthStarsShowWhen, - "North Stars: §d756", - ), - CHUNKED_STATS( - ::getChunkedStatsDisplayPair, - ::shouldShowChunkedStats, - "§652,763,737 §7| §d64,647 §7| §6249M\n§b59,264 §7| §c23,495 §7| §a57,873\n§c♨ 0 §7| §b0❄ §7| §d756", - ), - SOULFLOW( - ::getSoulflowDisplayPair, - ::getSoulflowDisplayWhen, - "Soulflow: §3761", - ), - EMPTY_LINE( - ::getEmptyLineDisplayPair, - { true }, - "", - ), - ISLAND( - ::getIslandDisplayPair, - { true }, - "§7㋖ §aHub", - ), - LOCATION( - ::getLocationDisplayPair, - { true }, - "§7⏣ §bVillage", - ), - PLAYER_AMOUNT( - ::getPlayerAmountDisplayPair, - { true }, - "§7Players: §a69§7/§a80", - ), - VISITING( - ::getVisitDisplayPair, - ::getVisitShowWhen, - " §a✌ §7(§a1§7/6)", - ), - DATE( - ::getDateDisplayPair, - { true }, - "Late Summer 11th", - ), - TIME( - ::getTimeDisplayPair, - { true }, - "§710:40pm §b☽", - ), - LOBBY_CODE( - ::getLobbyDisplayPair, - { true }, - "§8mega77CK", - ), - POWER( - ::getPowerDisplayPair, - ::getPowerShowWhen, - "Power: §aSighted §7(§61.263§7)", - ), - TUNING( - ::getTuningDisplayPair, - ::getPowerShowWhen, - "Tuning: §c❁34§7, §e⚔20§7, and §9☣7", - ), - COOKIE( - ::getCookieDisplayPair, - ::getCookieShowWhen, - "§dCookie Buff§f: 3d 17h", - ), - EMPTY_LINE2( - ::getEmptyLineDisplayPair, - { true }, - "", - ), - OBJECTIVE( - ::getObjectiveDisplayPair, - ::getObjectiveShowWhen, - "Objective:\n§eStar SkyHanni on Github", - ), - SLAYER( - ::getSlayerDisplayPair, - ::getSlayerShowWhen, - "Slayer Quest\n §7- §cVoidgloom Seraph III\n §7- §e12§7/§c120 §7Kills", - ), - EMPTY_LINE3( - ::getEmptyLineDisplayPair, - { true }, - "", - ), - QUIVER( - ::getQuiverDisplayPair, - ::getQuiverShowWhen, - "Flint Arrow: §f1,234", - ), - POWDER( - ::getPowderDisplayPair, - ::getPowderShowWhen, - "§9§lPowder\n §7- §fMithril: §254,646\n §7- §fGemstone: §d51,234", - ), - EVENTS( - ::getEventsDisplayPair, - ::getEventsShowWhen, - "§7Wide Range of Events\n§7(too much to show all)", - ), - MAYOR( - ::getMayorDisplayPair, - ::getMayorShowWhen, - "§2Diana:\n §7- §eLucky!\n §7- §eMythological Ritual\n §7- §ePet XP Buff", - ), - PARTY( - ::getPartyDisplayPair, - ::getPartyShowWhen, - "§9§lParty (4):\n §7- §fhannibal2\n §7- §fMoulberry\n §7- §fVahvl\n §7- §fSkirtwearer", - ), - FOOTER( - ::getFooterDisplayPair, - { true }, - "§ewww.hypixel.net", - ), - EXTRA( - ::getExtraDisplayPair, - ::getExtraShowWhen, - "§cUnknown lines the mod is not detecting", - ), - EMPTY_LINE4( - ::getEmptyLineDisplayPair, - { true }, - "", - ), - EMPTY_LINE5( - ::getEmptyLineDisplayPair, - { true }, - "", - ), - EMPTY_LINE6( - ::getEmptyLineDisplayPair, - { true }, - "", - ), - EMPTY_LINE7( - ::getEmptyLineDisplayPair, - { true }, - "", - ), - EMPTY_LINE8( - ::getEmptyLineDisplayPair, - { true }, - "", - ), - EMPTY_LINE9( - ::getEmptyLineDisplayPair, - { true }, - "", - ), - EMPTY_LINE10( - ::getEmptyLineDisplayPair, - { true }, - "", - ), - ; - - override fun toString() = configLine - - fun getVisiblePair() = if (isVisible()) getPair() else listOf("" to HorizontalAlignment.LEFT) - - private fun getPair(): List { - return try { - displayPair() - } catch (e: NoSuchElementException) { - listOf("" to HorizontalAlignment.LEFT) - } - } - - private fun isVisible(): Boolean { - if (!informationFilteringConfig.hideIrrelevantLines) return true - return showWhen() - } - - companion object { - // I don't know why, but this field is needed for it to work - @JvmField - val defaultOption = listOf( - TITLE, - PROFILE, - PURSE, - BANK, - MOTES, - BITS, - COPPER, - GEMS, - NORTH_STARS, - HEAT, - COLD, - EMPTY_LINE, - ISLAND, - LOCATION, - LOBBY_CODE, - PLAYER_AMOUNT, - VISITING, - EMPTY_LINE2, - DATE, - TIME, - EVENTS, - COOKIE, - EMPTY_LINE3, - QUIVER, - POWER, - TUNING, - EMPTY_LINE4, - OBJECTIVE, - SLAYER, - POWDER, - MAYOR, - PARTY, - FOOTER, - EXTRA, - ) - } -} - -private fun getTitleDisplayPair(): List { - val alignment = displayConfig.titleAndFooter.alignTitleAndFooter - - if (!LorenzUtils.inSkyBlock && !displayConfig.titleAndFooter.useCustomTitleOutsideSkyBlock) { - return listOf(ScoreboardData.objectiveTitle to alignment) - } - - return if (displayConfig.titleAndFooter.useCustomTitle) { - listOf( - displayConfig.titleAndFooter.customTitle.get().toString() - .replace("&", "§") - .split("\\n") - .map { it to alignment } - ).flatten() - } else { - listOf(ScoreboardData.objectiveTitle to alignment) - } -} - -private fun getProfileDisplayPair() = listOf( - CustomScoreboardUtils.getProfileTypeSymbol() + HypixelData.profileName.firstLetterUppercase() - to HorizontalAlignment.LEFT, -) - -private fun getPurseDisplayPair(): List { - var purse = PurseAPI.currentPurse.formatNum() - - if (!displayConfig.hideCoinsDifference) { - val earned = getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, PurseAPI.coinsPattern, "earned") - if (earned != null) purse += " §7(§e+$earned§7)§6" - } - - return listOf( - when { - informationFilteringConfig.hideEmptyLines && purse == "0" -> "" - displayConfig.displayNumbersFirst -> "§6$purse Purse" - else -> "Purse: §6$purse" - } to HorizontalAlignment.LEFT, - ) -} - -private fun getPurseShowWhen() = !inAnyIsland(IslandType.THE_RIFT) - -private fun getMotesDisplayPair(): List { - val motes = getMotes()?.formatNum() ?: "0" - - return listOf( - when { - informationFilteringConfig.hideEmptyLines && motes == "0" -> "" - displayConfig.displayNumbersFirst -> "§d$motes Motes" - else -> "Motes: §d$motes" - } to HorizontalAlignment.LEFT, - ) -} - -private fun getMotesShowWhen() = inAnyIsland(IslandType.THE_RIFT) - -private fun getBankDisplayPair(): List { - val bank = getBank() ?: "0" - - return listOf( - when { - informationFilteringConfig.hideEmptyLines && (bank == "0" || bank == "0§7 / §60") -> "" - displayConfig.displayNumbersFirst -> "§6$bank Bank" - else -> "Bank: §6$bank" - } to HorizontalAlignment.LEFT, - ) -} - -private fun getBankShowWhen() = !inAnyIsland(IslandType.THE_RIFT) - -private fun getBitsDisplayPair(): List { - val bits = BitsAPI.bits.coerceAtLeast(0).formatNum() - val bitsToClaim = if (BitsAPI.bitsAvailable == -1) { - "§cOpen Sbmenu§b" - } else { - BitsAPI.bitsAvailable.coerceAtLeast(0).formatNum() - } - - return listOf( - when { - informationFilteringConfig.hideEmptyLines && bits == "0" && bitsToClaim == "0" -> "" - displayConfig.displayNumbersFirst -> "${getBitsLine()} Bits" - else -> "Bits: ${getBitsLine()}" - } to HorizontalAlignment.LEFT, - ) -} - -private fun getBitsShowWhen() = !HypixelData.bingo && !inAnyIsland(IslandType.CATACOMBS, IslandType.KUUDRA_ARENA) - -private fun getCopperDisplayPair(): List { - val copper = getCopper()?.formatNum() ?: "0" - - return listOf( - when { - informationFilteringConfig.hideEmptyLines && copper == "0" -> "" - displayConfig.displayNumbersFirst -> "§c$copper Copper" - else -> "Copper: §c$copper" - } to HorizontalAlignment.LEFT, - ) -} - -private fun getCopperShowWhen() = inAnyIsland(IslandType.GARDEN) - -private fun getGemsDisplayPair(): List { - val gems = getGems() - - return listOf( - when { - informationFilteringConfig.hideEmptyLines && gems == "0" -> "" - displayConfig.displayNumbersFirst -> "§a$gems Gems" - else -> "Gems: §a$gems" - } to HorizontalAlignment.LEFT, - ) -} - -private fun getGemsShowWhen() = !inAnyIsland(IslandType.THE_RIFT, IslandType.CATACOMBS, IslandType.KUUDRA_ARENA) - -private fun getHeatDisplayPair(): List { - val heat = getHeat() - - return listOf( - when { - informationFilteringConfig.hideEmptyLines && heat == "§c♨ 0" -> "" - displayConfig.displayNumbersFirst -> heat?.let { "$heat Heat" } ?: "§c♨ 0 Heat" - else -> heat?.let { "Heat: $heat" } ?: "§c♨ 0 Heat" - } to HorizontalAlignment.LEFT, - ) -} - -private fun getHeatShowWhen() = inAnyIsland(IslandType.CRYSTAL_HOLLOWS) && - ScoreboardData.sidebarLinesFormatted.any { ScoreboardPattern.heatPattern.matches(it) } - -private fun getColdDisplayPair(): List { - val cold = -MiningAPI.cold - - return listOf( - when { - informationFilteringConfig.hideEmptyLines && cold == 0 -> "" - displayConfig.displayNumbersFirst -> "§b$cold❄ Cold" - else -> "Cold: §b$cold❄" - } to HorizontalAlignment.LEFT, - ) -} - -private fun getColdShowWhen() = inAnyIsland(IslandType.DWARVEN_MINES, IslandType.MINESHAFT) && - ScoreboardData.sidebarLinesFormatted.any { ScoreboardPattern.coldPattern.matches(it) } - -private fun getNorthStarsDisplayPair(): List { - val northStars = getNorthStars()?.formatNum() ?: "0" - - return listOf( - when { - informationFilteringConfig.hideEmptyLines && northStars == "0" -> "" - displayConfig.displayNumbersFirst -> "§d$northStars North Stars" - else -> "North Stars: §d$northStars" - } to HorizontalAlignment.LEFT, - ) -} - -private fun getNorthStarsShowWhen() = inAnyIsland(IslandType.WINTER) - -private fun getChunkedStatsDisplayPair(): List = - getChunkedStats() - .chunked(chunkedConfig.maxStatsPerLine) - .map { it.joinToString(" §f| ") to HorizontalAlignment.LEFT } - -private fun getSoulflowDisplayPair(): List { - val soulflow = getGroupFromPattern(TabListData.getTabList(), ScoreboardPattern.soulflowPattern, "soulflow") - ?.formatNum() ?: "0" - return listOf( - when { - informationFilteringConfig.hideEmptyLines && soulflow == "0" -> "" - displayConfig.displayNumbersFirst -> "§3$soulflow Soulflow" - else -> "Soulflow: §3$soulflow" - } to HorizontalAlignment.LEFT, - ) -} - -private fun getSoulflowDisplayWhen() = !inAnyIsland(IslandType.THE_RIFT) - -private fun getEmptyLineDisplayPair() = listOf("" to HorizontalAlignment.LEFT) - -private fun getIslandDisplayPair() = - listOf("§7㋖ §a" + LorenzUtils.skyBlockIsland.displayName to HorizontalAlignment.LEFT) - -private fun getLocationDisplayPair() = buildList { - HypixelData.skyBlockAreaWithSymbol?.let { add(it to HorizontalAlignment.LEFT) } - - ScoreboardData.sidebarLinesFormatted.firstOrNull { ScoreboardPattern.plotPattern.matches(it) } - ?.let { add(it to HorizontalAlignment.LEFT) } -} - -fun getPlayerAmountDisplayPair() = buildList { - val max = if (displayConfig.showMaxIslandPlayers) { - "§7/§a${getMaxPlayersForCurrentServer()}" - } else { - "" - } - if (displayConfig.displayNumbersFirst) - add("§a${getPlayersOnCurrentServer()}$max Players" to HorizontalAlignment.LEFT) - else - add("§7Players: §a${getPlayersOnCurrentServer()}$max" to HorizontalAlignment.LEFT) -} - -private fun getVisitDisplayPair() = - listOf( - ScoreboardData.sidebarLinesFormatted.first { ScoreboardPattern.visitingPattern.matches(it) } to - HorizontalAlignment.LEFT, - ) - -private fun getVisitShowWhen() = - ScoreboardData.sidebarLinesFormatted.any { ScoreboardPattern.visitingPattern.matches(it) } - -private fun getDateDisplayPair() = - listOf( - SkyBlockTime.now().formatted(yearElement = false, hoursAndMinutesElement = false) to HorizontalAlignment.LEFT, - ) - -private fun getTimeDisplayPair(): List { - val symbol = - getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.timePattern, "symbol") ?: "" - return listOf( - "§7" + SkyBlockTime.now() - .formatted( - dayAndMonthElement = false, - yearElement = false, - timeFormat24h = config.display.skyblockTime24hFormat, - exactMinutes = config.display.skyblockTimeExactMinutes, - ) + - " $symbol" to HorizontalAlignment.LEFT, - ) -} - -private fun getLobbyDisplayPair(): List { - val lobbyCode = HypixelData.serverId - val roomId = DungeonAPI.getRoomID()?.let { "§8$it" } ?: "" - val lobbyDisplay = lobbyCode?.let { "§8$it $roomId" } ?: "" - return listOf(lobbyDisplay to HorizontalAlignment.LEFT) -} - -private fun getPowerDisplayPair() = listOf( - ( - MaxwellAPI.currentPower?.let { - val mp = if (maxwellConfig.showMagicalPower) "§7(§6${MaxwellAPI.magicalPower?.addSeparators()}§7)" else "" - if (displayConfig.displayNumbersFirst) { - "§a${it.replace(" Power", "")} Power $mp" - } else { - "Power: §a$it $mp" - } - } ?: "§cOpen \"Your Bags\"!" - ) to HorizontalAlignment.LEFT, -) - -private fun getTuningDisplayPair(): List> { - val tunings = MaxwellAPI.tunings ?: return listOf("§cTalk to \"Maxwell\"!" to HorizontalAlignment.LEFT) - if (tunings.isEmpty()) return listOf("§cNo Maxwell Tunings :(" to HorizontalAlignment.LEFT) - - val title = pluralize(tunings.size, "Tuning", "Tunings") - return if (maxwellConfig.compactTuning) { - val tuning = tunings - .take(3) - .joinToString("§7, ") { tuning -> - with(tuning) { - if (displayConfig.displayNumbersFirst) { - "$color$value$icon" - } else { - "$color$icon$value" - } - } - - } - listOf( - if (displayConfig.displayNumbersFirst) { - "$tuning §f$title" - } else { - "$title: $tuning" - } to HorizontalAlignment.LEFT, - ) - } else { - val tuning = tunings - .take(maxwellConfig.tuningAmount.coerceAtLeast(1)) - .map { tuning -> - with(tuning) { - " §7- §f" + if (displayConfig.displayNumbersFirst) { - "$color$value $icon $name" - } else { - "$name: $color$value$icon" - } - } - - }.toTypedArray() - listOf("$title:", *tuning).map { it to HorizontalAlignment.LEFT } - } -} - -private fun getPowerShowWhen() = !inAnyIsland(IslandType.THE_RIFT) - -private fun getCookieDisplayPair() = listOf( - "§dCookie Buff§f: " + ( - BitsAPI.cookieBuffTime?.let { - if (!BitsAPI.hasCookieBuff()) "§cNot Active" else it.timeUntil().format(maxUnits = 2) - } ?: "§cOpen SbMenu!" - ) to HorizontalAlignment.LEFT, -) - -private fun getCookieShowWhen(): Boolean { - if (HypixelData.bingo) return false - return informationFilteringConfig.hideEmptyLines && BitsAPI.hasCookieBuff() -} - -private fun getObjectiveDisplayPair() = buildList { - val formattedLines = ScoreboardData.sidebarLinesFormatted - val objective = formattedLines.firstOrNull { ScoreboardPattern.objectivePattern.matches(it) } - if (objective != null) { - add(objective to HorizontalAlignment.LEFT) - - val secondLine = formattedLines.nextAfter(objective) ?: "" - add(secondLine to HorizontalAlignment.LEFT) - - formattedLines.nextAfter(objective, 2)?.let { - if (ScoreboardPattern.thirdObjectiveLinePattern.matches(it)) add(it to HorizontalAlignment.LEFT) - } - - formattedLines.nextAfter(objective, 3)?.let { - if (ScoreboardPattern.thirdObjectiveLinePattern.matches(it)) add(it to HorizontalAlignment.LEFT) - } - } -} - -private fun getObjectiveShowWhen(): Boolean = - ScoreboardPattern.objectivePattern.anyMatches(ScoreboardData.sidebarLinesFormatted) - -private fun getSlayerDisplayPair(): List = buildList { - add((if (SlayerAPI.hasActiveSlayerQuest()) "Slayer Quest" else "") to HorizontalAlignment.LEFT) - add(" §7- §e${SlayerAPI.latestSlayerCategory.trim()}" to HorizontalAlignment.LEFT) - add(" §7- §e${SlayerAPI.latestSlayerProgress.trim()}" to HorizontalAlignment.LEFT) -} - -private fun getSlayerShowWhen() = - if (informationFilteringConfig.hideIrrelevantLines) SlayerAPI.isInCorrectArea else true - -private fun getQuiverDisplayPair(): List { - if (QuiverAPI.currentArrow == null) - return listOf("§cChange your Arrow once" to HorizontalAlignment.LEFT) - if (QuiverAPI.currentArrow == NONE_ARROW_TYPE) - return listOf("No Arrows selected" to HorizontalAlignment.LEFT) - - val amountString = ( - if (arrowConfig.colorArrowAmount) { - percentageColor( - QuiverAPI.currentAmount.toLong(), - QuiverAPI.MAX_ARROW_AMOUNT.toLong(), - ).getChatColor() - } else "" - ) + if (QuiverAPI.wearingSkeletonMasterChestplate) { - "∞" - } else { - when (arrowConfig.arrowAmountDisplay) { - ArrowAmountDisplay.NUMBER -> QuiverAPI.currentAmount.addSeparators() - ArrowAmountDisplay.PERCENTAGE -> "${QuiverAPI.currentAmount.asArrowPercentage()}%" - else -> QuiverAPI.currentAmount.addSeparators() - } - } - - return listOf( - if (displayConfig.displayNumbersFirst) { - "$amountString ${QuiverAPI.currentArrow?.arrow}s" - } else { - "Arrows: $amountString ${QuiverAPI.currentArrow?.arrow?.replace(" Arrow", "")}" - } to HorizontalAlignment.LEFT, - ) -} - -private fun getQuiverShowWhen(): Boolean { - if (informationFilteringConfig.hideIrrelevantLines && !QuiverAPI.hasBowInInventory()) return false - return !inAnyIsland(IslandType.THE_RIFT) -} - -private fun getPowderDisplayPair() = buildList { - val powderTypes = HotmAPI.PowderType.values() - if (informationFilteringConfig.hideEmptyLines && powderTypes.all { it.getTotal() == 0L }) { - return listOf("" to HorizontalAlignment.LEFT) - } - - add("§9§lPowder" to HorizontalAlignment.LEFT) - - val displayNumbersFirst = displayConfig.displayNumbersFirst - - for (type in powderTypes) { - val name = type.displayName - val color = type.color - val current = type.getCurrent().formatNum() - val total = type.getTotal().formatNum() - - when (displayConfig.powderDisplay) { - PowderDisplay.AVAILABLE -> { - add(" §7- ${if (displayNumbersFirst) "$color$current $name" else "§f$name: $color$current"}" to HorizontalAlignment.LEFT) - } - - PowderDisplay.TOTAL -> { - add(" §7- ${if (displayNumbersFirst) "$color$total $name" else "§f$name: $color$total"}" to HorizontalAlignment.LEFT) - } - - PowderDisplay.BOTH -> { - add( - " §7- ${if (displayNumbersFirst) "$color$current/$total $name" else "§f$name: $color$current/$total"}" - to HorizontalAlignment.LEFT, - ) - } - - null -> {} - } - } -} - -private fun getPowderShowWhen() = inAdvancedMiningIsland() - -private fun getEventsDisplayPair(): List = ScoreboardEvent.getEvent() - .filterNotNull() - .flatMap { it.getLines().map { i -> i to HorizontalAlignment.LEFT } } - .takeIf { it.isNotEmpty() } ?: listOf("" to HorizontalAlignment.LEFT) - - -private fun getEventsShowWhen() = ScoreboardEvent.getEvent().isNotEmpty() - -private fun getMayorDisplayPair() = buildList { - val currentMayorName = MayorAPI.currentMayor?.mayorName?.let { MayorAPI.mayorNameWithColorCode(it) } ?: return@buildList - val timeTillNextMayor = if (mayorConfig.showTimeTillNextMayor) { - "§7 (§e${MayorAPI.nextMayorTimestamp.timeUntil().format(maxUnits = 2)}§7)" - } else { - "" - } - - add((currentMayorName + timeTillNextMayor) to HorizontalAlignment.LEFT) - - if (mayorConfig.showMayorPerks) { - MayorAPI.currentMayor?.activePerks?.forEach { perk -> - add(" §7- §e${perk.perkName}" to HorizontalAlignment.LEFT) - } - } - - if (!mayorConfig.showExtraMayor) return@buildList - addAll(addMinister()) - addAll(addPerkpocalypseMayor()) -} - -private fun addMinister() = buildList { - val ministerName = MayorAPI.currentMinister?.mayorName?.let { MayorAPI.mayorNameWithColorCode(it) } ?: return@buildList - add(ministerName to HorizontalAlignment.LEFT) - - if (mayorConfig.showMayorPerks) { - MayorAPI.currentMinister?.activePerks?.forEach { perk -> - add(" §7- §e${perk.perkName}" to HorizontalAlignment.LEFT) - } - } -} - -private fun addPerkpocalypseMayor() = buildList { - val jerryExtraMayor = MayorAPI.jerryExtraMayor - val extraMayor = jerryExtraMayor.first ?: return@buildList - - val extraMayorName = extraMayor.mayorName.let { MayorAPI.mayorNameWithColorCode(it) } - val extraTimeTillNextMayor = if (mayorConfig.showTimeTillNextMayor) { - "§7 (§6${jerryExtraMayor.second.timeUntil().format(maxUnits = 2)}§7)" - } else { - "" - } - - add((extraMayorName + extraTimeTillNextMayor) to HorizontalAlignment.LEFT) -} - -private fun getMayorShowWhen() = - !inAnyIsland(IslandType.THE_RIFT) && MayorAPI.currentMayor != null - -private fun getPartyDisplayPair() = - if (PartyAPI.partyMembers.isEmpty() && informationFilteringConfig.hideEmptyLines) { - listOf("" to HorizontalAlignment.LEFT) - } else { - val title = - if (PartyAPI.partyMembers.isEmpty()) "§9§lParty" else "§9§lParty (${PartyAPI.partyMembers.size})" - val partyList = PartyAPI.partyMembers - .take(partyConfig.maxPartyList.get()) - .map { - " §7- §f$it" - } - .toTypedArray() - listOf(title, *partyList).map { it to HorizontalAlignment.LEFT } - } - -private fun getPartyShowWhen() = if (DungeonAPI.inDungeon()) { - false // Hidden bc the scoreboard lines already exist -} else { - if (partyConfig.showPartyEverywhere) { - true - } else { - inAnyIsland(IslandType.DUNGEON_HUB, IslandType.KUUDRA_ARENA, IslandType.CRIMSON_ISLE) || inGlaciteArea() - } -} - -private fun getFooterDisplayPair(): List = listOf( - displayConfig.titleAndFooter.customFooter.get().toString() - .replace("&", "§") - .split("\\n") - .map { it to displayConfig.titleAndFooter.alignTitleAndFooter }, -).flatten() - -private fun getExtraDisplayPair(): List { - val lines = recentUnknownLines() - if (lines.isEmpty()) return listOf("" to HorizontalAlignment.LEFT) - - return listOf("§cUndetected Lines:" to HorizontalAlignment.LEFT) + lines.map { - it.line to HorizontalAlignment.LEFT - } -} - -private fun getExtraShowWhen(): Boolean = recentUnknownLines().isNotEmpty() diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardEvent.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardEvent.kt deleted file mode 100644 index 8dd3af9f7aec..000000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardEvent.kt +++ /dev/null @@ -1,576 +0,0 @@ -package at.hannibal2.skyhanni.features.gui.customscoreboard - -import at.hannibal2.skyhanni.data.HypixelData -import at.hannibal2.skyhanni.data.IslandType -import at.hannibal2.skyhanni.data.ScoreboardData -import at.hannibal2.skyhanni.data.model.TabWidget -import at.hannibal2.skyhanni.features.combat.SpidersDenAPI.isAtTopOfNest -import at.hannibal2.skyhanni.features.dungeon.DungeonAPI -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.eventsConfig -import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardEvent.VOTING -import at.hannibal2.skyhanni.features.misc.ServerRestartTitle -import at.hannibal2.skyhanni.features.rift.area.stillgorechateau.RiftBloodEffigies -import at.hannibal2.skyhanni.utils.CollectionUtils.nextAfter -import at.hannibal2.skyhanni.utils.LorenzUtils.inAdvancedMiningIsland -import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland -import at.hannibal2.skyhanni.utils.RegexUtils.anyMatches -import at.hannibal2.skyhanni.utils.RegexUtils.firstMatcher -import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher -import at.hannibal2.skyhanni.utils.RegexUtils.matches -import at.hannibal2.skyhanni.utils.StringUtils.removeColor -import at.hannibal2.skyhanni.utils.StringUtils.removeResets -import at.hannibal2.skyhanni.utils.TabListData -import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardPattern as SbPattern - -/** - * This enum contains all the lines that either are events or other lines that are so rare/not often seen that they - * don't fit in the normal [ScoreboardElement] enum. - * - * We for example have the [VOTING] Event, while this is clearly not an event, I don't consider them as normal lines - * because they are visible for a maximum of like 1 minute every 5 days and ~12 hours. - */ - -private fun getSbLines(): List = ScoreboardData.sidebarLinesFormatted - -enum class ScoreboardEvent( - private val displayLine: () -> List, - private val showWhen: () -> Boolean, - private val configLine: String, -) { - VOTING( - ::getVotingLines, - ::getVotingShowWhen, - "§7(All Voting Lines)", - ), - SERVER_CLOSE( - ::getServerCloseLines, - ::getServerCloseShowWhen, - "§cServer closing soon!", - ), - DUNGEONS( - ::getDungeonsLines, - ::getDungeonsShowWhen, - "§7(All Dungeons Lines)", - ), - KUUDRA( - ::getKuudraLines, - ::getKuudraShowWhen, - "§7(All Kuudra Lines)", - ), - DOJO( - ::getDojoLines, - ::getDojoShowWhen, - "§7(All Dojo Lines)", - ), - DARK_AUCTION( - ::getDarkAuctionLines, - ::getDarkAuctionShowWhen, - "Time Left: §b11\n" + - "Current Item:\n" + - " §5Travel Scroll to Sirius", - ), - JACOB_CONTEST( - ::getJacobContestLines, - ::getJacobContestShowWhen, - "§eJacob's Contest\n" + - "§e○ §fCarrot §a18m17s\n" + - " Collected §e8,264", - ), - JACOB_MEDALS( - ::getJacobMedalsLines, - ::getJacobMedalsShowWhen, - "§6§lGOLD §fmedals: §613\n" + - "§f§lSILVER §fmedals: §f3\n" + - "§c§lBRONZE §fmedals: §c4", - ), - TRAPPER( - ::getTrapperLines, - ::getTrapperShowWhen, - "Pelts: §5711\n" + - "Tracker Mob Location:\n" + - "§bMushroom Gorge", - ), - GARDEN_CLEAN_UP( - ::getGardenCleanUpLines, - ::getGardenCleanUpShowWhen, - "Cleanup: §c12.6%", - ), - GARDEN_PASTING( - ::getGardenPastingLines, - ::getGardenPastingShowWhen, - "§fBarn Pasting§7: §e12.3%", - ), - FLIGHT_DURATION( - ::getFlightDurationLines, - ::getFlightDurationShowWhen, - "Flight Duration: §a10m 0s", - ), - WINTER( - ::getWinterLines, - ::getWinterShowWhen, - "§7(All Winter Event Lines)", - ), - NEW_YEAR( - ::getNewYearLines, - ::getNewYearShowWhen, - "§dNew Year Event!§f 24:25", - ), - SPOOKY( - ::getSpookyLines, - ::getSpookyShowWhen, - "§6Spooky Festival§f 50:54\n" + - "§7Your Candy:\n" + - "§a1 Green§7, §50 Purple §7(§61 §7pts.)", - ), - BROODMOTHER( - ::getBroodmotherLines, - ::isAtTopOfNest, - "§4Broodmother§7: §eDormant", - ), - MINING_EVENTS( - ::getMiningEventsLines, - { inAdvancedMiningIsland() }, - "§7(All Mining Event Lines)", - ), - DAMAGE( - ::getDamageLines, - ::getDamageShowWhen, - "Dragon HP: §a6,180,925 §c❤\n" + - "Your Damage: §c375,298.5", - ), - MAGMA_BOSS( - ::getMagmaBossLines, - ::getMagmaBossShowWhen, - "§7(All Magma Boss Lines)\n" + - "§7Boss: §c0%\n" + - "§7Damage Soaked:\n" + - "§e▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎§7▎▎▎▎▎", - ), - CARNIVAL( - ::getCarnivalLines, - ::getCarnivalShowWhen, - "§7(All Carnival Lines)", - ), - RIFT( - ::getRiftLines, - { IslandType.THE_RIFT.isInIsland() }, - "§7(All Rift Lines)", - ), - ESSENCE( - ::getEssenceLines, - ::getEssenceShowWhen, - "Dragon Essence: §d1,285", - ), - QUEUE( - ::getQueueLines, - ::getQueueShowWhen, - "Queued: Glacite Mineshafts\n" + - "Position: §b#45 §fSince: §a00:00", - ), - ACTIVE_TABLIST_EVENTS( - ::getActiveEventLine, - ::getActiveEventShowWhen, - "§7(All Active Tablist Events)\n§dHoppity's Hunt\n §fEnds in: §e26h", - ), - STARTING_SOON_TABLIST_EVENTS( - ::getSoonEventLine, - ::getSoonEventShowWhen, - "§7(All Starting Soon Tablist Events)\n§6Mining Fiesta\n §fStarts in: §e52min", - ), - REDSTONE( - ::getRedstoneLines, - ::getRedstoneShowWhen, - "§e§l⚡ §cRedstone: §e§b7%", - ), - ANNIVERSARY( - ::getAnniversaryLines, - ::getAnniversaryShowWhen, - "§d5th Anniversary§f 167:59:54", - ), - ; - - override fun toString() = configLine - - fun getLines(): List = displayLine() - - companion object { - fun getEvent() = buildList { - if (eventsConfig.showAllActiveEvents) { - for (event in eventsConfig.eventEntries) { - if (event.showWhen()) { - add(event) - } - } - } else { - add(eventsConfig.eventEntries.firstOrNull { it.showWhen() && it.getLines().isNotEmpty() }) - } - } - - // I don't know why, but this field is needed for it to work - @JvmField - val defaultOption = listOf( - VOTING, - SERVER_CLOSE, - DUNGEONS, - KUUDRA, - DOJO, - DARK_AUCTION, - JACOB_CONTEST, - JACOB_MEDALS, - TRAPPER, - GARDEN_CLEAN_UP, - GARDEN_PASTING, - FLIGHT_DURATION, - NEW_YEAR, - WINTER, - SPOOKY, - BROODMOTHER, - MINING_EVENTS, - DAMAGE, - MAGMA_BOSS, - CARNIVAL, - RIFT, - ESSENCE, - ACTIVE_TABLIST_EVENTS, - ) - } -} - -private fun getVotingLines() = buildList { - val sbLines = getSbLines() - - val yearLine = sbLines.firstOrNull { SbPattern.yearVotesPattern.matches(it) } ?: return emptyList() - add(yearLine) - - if (sbLines.nextAfter(yearLine) == "§7Waiting for") { - add("§7Waiting for") - add("§7your vote...") - } else { - if (SbPattern.votesPattern.anyMatches(sbLines)) { - addAll(sbLines.filter { SbPattern.votesPattern.matches(it) }) - } - } -} - -private fun getVotingShowWhen(): Boolean = SbPattern.yearVotesPattern.anyMatches(getSbLines()) - -private fun getServerCloseLines() = buildList { - val matchingLine = getSbLines().first { ServerRestartTitle.restartingGreedyPattern.matches(it) } - add(matchingLine.split("§8")[0]) -} - -private fun getServerCloseShowWhen(): Boolean = ServerRestartTitle.restartingGreedyPattern.anyMatches(getSbLines()) - -private fun getDungeonsLines() = listOf( - SbPattern.m7dragonsPattern, - SbPattern.autoClosingPattern, - SbPattern.startingInPattern, - SbPattern.keysPattern, - SbPattern.timeElapsedPattern, - SbPattern.clearedPattern, - SbPattern.soloPattern, - SbPattern.teammatesPattern, - SbPattern.floor3GuardiansPattern, -).let { patterns -> - // BetterMap adds a random §r at the start, making the line go black - getSbLines().filter { line -> patterns.any { it.matches(line) } }.map { it.removePrefix("§r") } -} - -private fun getDungeonsShowWhen(): Boolean = DungeonAPI.inDungeon() - -private fun getKuudraLines() = listOf( - SbPattern.autoClosingPattern, - SbPattern.startingInPattern, - SbPattern.timeElapsedPattern, - SbPattern.instanceShutdownPattern, - SbPattern.wavePattern, - SbPattern.tokensPattern, - SbPattern.submergesPattern, -) - .mapNotNull { pattern -> - getSbLines().firstOrNull { pattern.matches(it) } - } - -private fun getKuudraShowWhen(): Boolean = IslandType.KUUDRA_ARENA.isInIsland() - -private fun getDojoLines() = listOf( - SbPattern.dojoChallengePattern, - SbPattern.dojoDifficultyPattern, - SbPattern.dojoPointsPattern, - SbPattern.dojoTimePattern, -) - .mapNotNull { pattern -> - getSbLines().firstOrNull { pattern.matches(it) } - } - -private fun getDojoShowWhen(): Boolean = SbPattern.dojoChallengePattern.anyMatches(getSbLines()) - -private fun getDarkAuctionLines() = buildList { - getSbLines().firstOrNull { SbPattern.startingInPattern.matches(it) }?.let { add(it) } - getSbLines().firstOrNull { SbPattern.timeLeftPattern.matches(it) }?.let { add(it) } - - val darkAuctionCurrentItemLine = getSbLines().firstOrNull { SbPattern.darkAuctionCurrentItemPattern.matches(it) } - - if (darkAuctionCurrentItemLine != null) { - add(darkAuctionCurrentItemLine) - getSbLines().nextAfter(darkAuctionCurrentItemLine)?.let { add(it) } - } -} - -private fun getDarkAuctionShowWhen(): Boolean = IslandType.DARK_AUCTION.isInIsland() - -private fun getJacobContestLines() = buildList { - getSbLines().firstOrNull { SbPattern.jacobsContestPattern.matches(it) }?.let { line -> - add(line) - getSbLines().nextAfter(line)?.let { add(it) } - getSbLines().nextAfter(line, 2)?.let { add(it) } - getSbLines().nextAfter(line, 3)?.let { - if (!SbPattern.footerPattern.matches(it)) add(it) - } - } -} - -private fun getJacobContestShowWhen(): Boolean = SbPattern.jacobsContestPattern.anyMatches(getSbLines()) - -private fun getJacobMedalsLines(): List = getSbLines().filter { SbPattern.medalsPattern.matches(it) } - -private fun getJacobMedalsShowWhen(): Boolean = SbPattern.medalsPattern.anyMatches(getSbLines()) - -private fun getTrapperLines() = buildList { - getSbLines().firstOrNull { SbPattern.peltsPattern.matches(it) }?.let { add(it) } - - val trapperMobLocationLine = getSbLines().firstOrNull { SbPattern.mobLocationPattern.matches(it) } - if (trapperMobLocationLine != null) { - add("Tracker Mob Location:") - getSbLines().nextAfter(trapperMobLocationLine)?.let { add(it) } - } -} - -private fun getTrapperShowWhen(): Boolean = - getSbLines().any { SbPattern.peltsPattern.matches(it) || SbPattern.mobLocationPattern.matches(it) } - -private fun getGardenCleanUpLines(): List = - listOf(getSbLines().first { SbPattern.cleanUpPattern.matches(it) }.trim()) - -private fun getGardenCleanUpShowWhen(): Boolean = SbPattern.cleanUpPattern.anyMatches(getSbLines()) - -private fun getGardenPastingLines(): List = - listOf(getSbLines().first { SbPattern.pastingPattern.matches(it) }.trim()) - -private fun getGardenPastingShowWhen(): Boolean = SbPattern.pastingPattern.anyMatches(getSbLines()) - -private fun getFlightDurationLines(): List = - listOf(getSbLines().first { SbPattern.flightDurationPattern.matches(it) }.trim()) - -private fun getFlightDurationShowWhen(): Boolean = SbPattern.flightDurationPattern.anyMatches(getSbLines()) - -private fun getWinterLines() = buildList { - getSbLines().firstOrNull { SbPattern.winterEventStartPattern.matches(it) }?.let { add(it) } - getSbLines().firstOrNull { SbPattern.winterNextWavePattern.matches(it) && !it.endsWith("Soon!") }?.let { add(it) } - getSbLines().firstOrNull { SbPattern.winterWavePattern.matches(it) }?.let { add(it) } - getSbLines().firstOrNull { SbPattern.winterMagmaLeftPattern.matches(it) }?.let { add(it) } - getSbLines().firstOrNull { SbPattern.winterTotalDmgPattern.matches(it) }?.let { add(it) } - getSbLines().firstOrNull { SbPattern.winterCubeDmgPattern.matches(it) }?.let { add(it) } -} - -private fun getWinterShowWhen(): Boolean = getSbLines().any { - SbPattern.winterEventStartPattern.matches(it) || - (SbPattern.winterNextWavePattern.matches(it) && !it.endsWith("Soon!")) || - SbPattern.winterWavePattern.matches(it) -} - -private fun getNewYearLines() = listOf(getSbLines().first { SbPattern.newYearPattern.matches(it) }) - -private fun getNewYearShowWhen(): Boolean = SbPattern.newYearPattern.anyMatches(getSbLines()) - -private fun getSpookyLines() = buildList { - getSbLines().firstOrNull { SbPattern.spookyPattern.matches(it) }?.let { add(it) } // Time - add("§7Your Candy: ") - add( - TabListData.getFooter() - .removeResets() - .split("\n") - .firstOrNull { it.startsWith("§7Your Candy:") } - ?.removePrefix("§7Your Candy:") ?: "§cCandy not found", - ) // Candy -} - -private fun getSpookyShowWhen(): Boolean = getSbLines().any { SbPattern.spookyPattern.matches(it) } - -private fun getTablistEvent(): String? = - TabListData.getTabList().firstOrNull { SbPattern.eventNamePattern.matches(it) } - ?.let { - SbPattern.eventNamePattern.matchMatcher(it) { - group("name") - } - } - -private fun getActiveEventLine(): List { - val currentActiveEvent = getTablistEvent() ?: return emptyList() - - // Some Active Events are better not shown from the tablist, - // but from other locations like the scoreboard - val blockedEvents = listOf("Spooky Festival", "Carnival", "5th SkyBlock Anniversary", "New Year Celebration") - if (blockedEvents.contains(currentActiveEvent.removeColor())) return emptyList() - - val currentActiveEventTime = SbPattern.eventTimeEndsPattern.firstMatcher(TabWidget.EVENT.lines) { - group("time") - } ?: return emptyList() - - return listOf(currentActiveEvent, " Ends in: §e$currentActiveEventTime") -} - -private fun getActiveEventShowWhen(): Boolean = - getTablistEvent() != null && TabListData.getTabList().any { SbPattern.eventTimeEndsPattern.matches(it) } - -private fun getSoonEventLine(): List { - val soonActiveEvent = getTablistEvent() ?: return emptyList() - val soonActiveEventTime = SbPattern.eventTimeStartsPattern.firstMatcher(TabWidget.EVENT.lines) { - group("time") - } ?: return emptyList() - - return listOf(soonActiveEvent, " Starts in: §e$soonActiveEventTime") -} - -private fun getSoonEventShowWhen(): Boolean = - getTablistEvent() != null && TabListData.getTabList().any { SbPattern.eventTimeStartsPattern.matches(it) } - -private fun getBroodmotherLines(): List = - listOf(getSbLines().first { SbPattern.broodmotherPattern.matches(it) }) - -private fun getMiningEventsLines() = buildList { - // Wind - if (getSbLines().any { SbPattern.windCompassPattern.matches(it) } && - getSbLines().any { SbPattern.windCompassArrowPattern.matches(it) } - ) { - add(getSbLines().first { SbPattern.windCompassPattern.matches(it) }) - add("| ${getSbLines().first { SbPattern.windCompassArrowPattern.matches(it) }} §f|") - } - - // Better Together - if (getSbLines().any { SbPattern.nearbyPlayersPattern.matches(it) }) { - add("§dBetter Together") - add(" ${getSbLines().first { SbPattern.nearbyPlayersPattern.matches(it) }}") - } - - // Zone Events - if (getSbLines().any { SbPattern.miningEventPattern.matches(it) } && - getSbLines().any { SbPattern.miningEventZonePattern.matches(it) } - ) { - add(getSbLines().first { SbPattern.miningEventPattern.matches(it) }.removePrefix("Event: ")) - add("in ${getSbLines().first { SbPattern.miningEventZonePattern.matches(it) }.removePrefix("Zone: ")}") - } - - // Zone Events but no Zone Line - if (getSbLines().any { SbPattern.miningEventPattern.matches(it) } && - getSbLines().none { SbPattern.miningEventZonePattern.matches(it) } - ) { - add( - getSbLines().first { SbPattern.miningEventPattern.matches(it) } - .removePrefix("Event: "), - ) - } - - // Mithril Gourmand - if (getSbLines().any { SbPattern.mithrilRemainingPattern.matches(it) } && - getSbLines().any { SbPattern.mithrilYourMithrilPattern.matches(it) } - ) { - add(getSbLines().first { SbPattern.mithrilRemainingPattern.matches(it) }) - add(getSbLines().first { SbPattern.mithrilYourMithrilPattern.matches(it) }) - } - - // Raffle - if (getSbLines().any { SbPattern.raffleTicketsPattern.matches(it) } && - getSbLines().any { SbPattern.rafflePoolPattern.matches(it) } - ) { - add(getSbLines().first { SbPattern.raffleTicketsPattern.matches(it) }) - add(getSbLines().first { SbPattern.rafflePoolPattern.matches(it) }) - } - - // Raid - if (getSbLines().any { SbPattern.yourGoblinKillsPattern.matches(it) } && - getSbLines().any { SbPattern.remainingGoblinPattern.matches(it) } - ) { - add(getSbLines().first { SbPattern.yourGoblinKillsPattern.matches(it) }) - add(getSbLines().first { SbPattern.remainingGoblinPattern.matches(it) }) - } - - // Fortunate Freezing - if (getSbLines().any { SbPattern.fortunateFreezingBonusPattern.matches(it) }) { - add(getSbLines().first { SbPattern.fortunateFreezingBonusPattern.matches(it) }) - } - - // Fossil Dust - if (getSbLines().any { SbPattern.fossilDustPattern.matches(it) }) { - add(getSbLines().first { SbPattern.fossilDustPattern.matches(it) }) - } -} - -private fun getDamageLines(): List = - listOf(getSbLines().first { SbPattern.bossHPPattern.matches(it) }) + - (getSbLines().first { SbPattern.bossDamagePattern.matches(it) }) - -private fun getDamageShowWhen(): Boolean = - getSbLines().any { SbPattern.bossHPPattern.matches(it) } && - getSbLines().any { SbPattern.bossDamagePattern.matches(it) } - -private fun getMagmaBossLines() = getSbLines().filter { line -> - SbPattern.magmaBossPattern.matches(line) || - SbPattern.damageSoakedPattern.matches(line) || - SbPattern.killMagmasPattern.matches(line) || - SbPattern.killMagmasDamagedSoakedBarPattern.matches(line) || - SbPattern.reformingPattern.matches(line) || - SbPattern.bossHealthPattern.matches(line) || - SbPattern.bossHealthBarPattern.matches(line) -} - -private fun getMagmaBossShowWhen(): Boolean = SbPattern.magmaChamberPattern.matches(HypixelData.skyBlockArea) - -private fun getCarnivalLines() = listOf( - SbPattern.carnivalPattern, - SbPattern.carnivalTokensPattern, - SbPattern.carnivalTasksPattern, - SbPattern.timeLeftPattern, - SbPattern.carnivalCatchStreakPattern, - SbPattern.carnivalFruitsPattern, - SbPattern.carnivalAccuracyPattern, - SbPattern.carnivalKillsPattern, - SbPattern.carnivalScorePattern, -) - .mapNotNull { pattern -> - getSbLines().firstOrNull { pattern.matches(it) } - } - -private fun getCarnivalShowWhen() = - listOf(SbPattern.carnivalPattern, SbPattern.carnivalTokensPattern, SbPattern.carnivalTasksPattern).anyMatches(getSbLines()) - -private fun getRiftLines() = getSbLines().filter { line -> - RiftBloodEffigies.heartsPattern.matches(line) || - SbPattern.riftHotdogTitlePattern.matches(line) || - SbPattern.timeLeftPattern.matches(line) || - SbPattern.riftHotdogEatenPattern.matches(line) || - SbPattern.riftAveikxPattern.matches(line) || - SbPattern.riftHayEatenPattern.matches(line) || - SbPattern.cluesPattern.matches(line) || - SbPattern.barryProtestorsQuestlinePattern.matches(line) || - SbPattern.barryProtestorsHandledPattern.matches(line) -} - -private fun getEssenceLines(): List = listOf(getSbLines().first { SbPattern.essencePattern.matches(it) }) - -private fun getEssenceShowWhen(): Boolean = SbPattern.essencePattern.anyMatches(getSbLines()) - -private fun getQueueLines(): List = - listOf(getSbLines().first { SbPattern.queuePattern.matches(it) }) + - (getSbLines().first { SbPattern.queueTierPattern.matches(it) }) + - (getSbLines().first { SbPattern.queuePositionPattern.matches(it) }) - -private fun getQueueShowWhen(): Boolean = SbPattern.queuePattern.anyMatches(getSbLines()) - -private fun getRedstoneLines(): List = listOf(getSbLines().first { SbPattern.redstonePattern.matches(it) }) - -private fun getRedstoneShowWhen(): Boolean = SbPattern.redstonePattern.anyMatches(getSbLines()) - -private fun getAnniversaryLines() = listOf(getSbLines().first { SbPattern.anniversaryPattern.matches(it) }) - -private fun getAnniversaryShowWhen(): Boolean = SbPattern.anniversaryPattern.anyMatches(getSbLines()) diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardLine.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardLine.kt new file mode 100644 index 000000000000..3231f2bdf11b --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardLine.kt @@ -0,0 +1,18 @@ +package at.hannibal2.skyhanni.features.gui.customscoreboard + +import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.displayConfig +import at.hannibal2.skyhanni.utils.RenderUtils + +data class ScoreboardLine( + val display: String, + val alignment: RenderUtils.HorizontalAlignment = DEFAULT_ALIGNMENT, +) { + + companion object { + private val DEFAULT_ALIGNMENT get() = displayConfig.textAlignment + + fun String.align(): ScoreboardLine = ScoreboardLine(this, DEFAULT_ALIGNMENT) + + infix fun String.align(alignment: RenderUtils.HorizontalAlignment): ScoreboardLine = ScoreboardLine(this, alignment) + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardPattern.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardPattern.kt index f7371d9566c5..42fc1a55e642 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardPattern.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardPattern.kt @@ -9,7 +9,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent object ScoreboardPattern { private val group = RepoPattern.group("features.gui.customscoreboard") - // Stats from the scoreboard + // Lines from the scoreboard private val scoreboardGroup by group.exclusiveGroup("scoreboard") @SubscribeEvent @@ -17,35 +17,33 @@ object ScoreboardPattern { UnknownLinesHandler.remoteOnlyPatterns = scoreboardGroup.getUnusedPatterns().toTypedArray() } - // main scoreboard + // Main scoreboard private val mainSb = scoreboardGroup.group("main") + + // TODO add regex tests val motesPattern by mainSb.pattern( "motes", - "^(§.)*Motes: (§.)*(?[\\d,]+).*$", + "(?:§.)*Motes: (?:§.)*(?[\\d,]+).*", ) val heatPattern by mainSb.pattern( "heat", - "^Heat: (?.*)$", - ) // this line is weird (either text or number), ill leave it as is; it even has different colors? - val coldPattern by mainSb.pattern( - "cold", - "^(?:§.)*Cold: §.(?-?\\d+)❄$", + "Heat: (?.*)", ) val copperPattern by mainSb.pattern( "copper", - "^(§.)*Copper: (§.)*(?[\\d,]+).*$", + "(?:§.)*Copper: (?:§.)*(?[\\d,]+).*", ) val locationPattern by mainSb.pattern( "location", - "^\\s*(?(§7⏣|§5ф) .*)$", + "\\s*(?(?:§7⏣|§5ф) .*)", ) val lobbyCodePattern by mainSb.pattern( "lobbycode", - "^\\s*§.((\\d{2}/\\d{2}/\\d{2})|Server closing: [\\d:]+) §8(?.*)\$", + "\\s*§.(?:\\d{2}/?){3} §8(?.*)", ) val datePattern by mainSb.pattern( "date", - "^\\s*(Late |Early )?(Spring|Summer|Autumn|Winter) \\d{1,2}(st|nd|rd|th)?.*", + "\\s*(?:(?:Late|Early) )?(?:Spring|Summer|Autumn|Winter) \\d+(?:st|nd|rd|th)?.*", ) /** @@ -54,15 +52,15 @@ object ScoreboardPattern { */ val timePattern by mainSb.pattern( "time", - "^\\s*§7\\d{1,2}:\\d{2}(?:am|pm)\\s*(?(§b☽|§e☀|§.⚡|§.☔))?.*$", + "\\s*§7\\d+:\\d+(?:am|pm)\\s*(?§b☽|§e☀|§.⚡|§.☔)?.*", ) val footerPattern by mainSb.pattern( "footer", - "§e(www|alpha).hypixel.net\$", + "§e(?:www|alpha).hypixel.net", ) val yearVotesPattern by mainSb.pattern( "yearvotes", - "(?^§6Year \\d+ Votes\$)", + "§6Year \\d+ Votes", ) /** @@ -75,65 +73,63 @@ object ScoreboardPattern { ) val waitingForVotePattern by mainSb.pattern( "waitingforvote", - "(§7Waiting for|§7your vote\\.\\.\\.)$", + "§7Waiting for|§7your vote\\.\\.\\.", ) val northstarsPattern by mainSb.pattern( "northstars", - "North Stars: §d(?[\\w,]+).*$", + "North Stars: §d(?[\\w,]+).*", ) val profileTypePattern by mainSb.pattern( "profiletype", - "^\\s*(§7♲ §7Ironman|§a☀ §aStranded|§.Ⓑ §.Bingo).*$", - ) - val emptyLinesPattern by mainSb.pattern( - "emptylines", - "^\\s*$", + "\\s*(?:§7♲ §7Ironman|§a☀ §aStranded|§.Ⓑ §.Bingo).*", ) // multi use private val multiUseSb = scoreboardGroup.group("multiuse") val autoClosingPattern by multiUseSb.pattern( "autoclosing", - "(§.)*Auto-closing in: §c(\\d{1,2}:)?\\d{1,2}$", + "(?:§.)*Auto-closing in: §c(?:\\d+:)?\\d+", ) val startingInPattern by multiUseSb.pattern( "startingin", - "(§.)*Starting in: §.(\\d{1,2}:)?\\d{1,2}$", + "(?:§.)*Starting in: §.(?:\\d+:)?\\d+", ) val timeElapsedPattern by multiUseSb.pattern( "timeelapsed", - "(§.)*Time Elapsed: (§.)*(?