diff options
| author | David Cole <40234707+DavidArthurCole@users.noreply.github.com> | 2024-09-26 03:56:44 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-26 09:56:44 +0200 |
| commit | 092a29dd8b13c2b04b0b7c259446ab697201dd5e (patch) | |
| tree | f3704e259d34bfccef083834cb9106578695a694 | |
| parent | e90fd65559ef551b29de7d28f4fea3a46cc2a4e6 (diff) | |
| download | skyhanni-092a29dd8b13c2b04b0b7c259446ab697201dd5e.tar.gz skyhanni-092a29dd8b13c2b04b0b7c259446ab697201dd5e.tar.bz2 skyhanni-092a29dd8b13c2b04b0b7c259446ab697201dd5e.zip | |
Backend: Dekekt (#2547)
Co-authored-by: Linnea Gräf <nea@nea.moe>
Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
Co-authored-by: Cal <cwolfson58@gmail.com>
21 files changed, 1085 insertions, 58 deletions
diff --git a/.github/actions/setup-normal-workspace/action.yml b/.github/actions/setup-normal-workspace/action.yml new file mode 100644 index 000000000..a0781d53c --- /dev/null +++ b/.github/actions/setup-normal-workspace/action.yml @@ -0,0 +1,13 @@ +name: 'Setup Java, Gradle and check out the source code' + +runs: + using: composite + steps: + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: 21 + cache: gradle + - name: Setup gradle + uses: gradle/actions/setup-gradle@v4 diff --git a/.github/scripts/process_detekt_sarif.sh b/.github/scripts/process_detekt_sarif.sh new file mode 100644 index 000000000..7fb4f7e4e --- /dev/null +++ b/.github/scripts/process_detekt_sarif.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +# This script processes the Detekt SARIF file and outputs results in a format +# suitable for annotation in CI/CD systems. + +SARIF_FILE="$1" + +# Check if SARIF file exists +if [ ! -f "$SARIF_FILE" ]; then + echo "SARIF file not found: $SARIF_FILE" + exit 1 +fi + +# Define jq command to parse SARIF file +read -r -d '' jq_command <<'EOF' +.runs[].results[] | +{ + "full_path": .locations[].physicalLocation.artifactLocation.uri | sub("file://$(pwd)/"; ""), + "file_name": (.locations[].physicalLocation.artifactLocation.uri | split("/") | last), + "l": .locations[].physicalLocation, + "level": .level, + "message": .message.text, + "ruleId": .ruleId +} | +( + "::" + (.level) + + " file=" + (.full_path) + + ",line=" + (.l.region.startLine|tostring) + + ",title=" + (.ruleId) + + ",col=" + (.l.region.startColumn|tostring) + + ",endColumn=" + (.l.region.endColumn|tostring) + + "::" + (.message.text) +) +EOF + +# Run jq command to format the output +jq -r "$jq_command" < "$SARIF_FILE" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7c75f0eef..7e42909ee 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,15 +18,9 @@ jobs: runs-on: ubuntu-latest name: "Build and test" steps: - - uses: actions/checkout@v3 - - name: Set up JDK 21 - uses: actions/setup-java@v3 - with: - java-version: 21 - distribution: temurin - cache: gradle - - name: Setup gradle - uses: gradle/gradle-build-action@v2 + - name: Checkout code + uses: actions/checkout@v4 + - uses: ./.github/actions/setup-normal-workspace - name: Build with Gradle run: ./gradlew assemble -x test --stacktrace - uses: actions/upload-artifact@v3 @@ -42,19 +36,31 @@ jobs: with: name: "Test Results" path: versions/1.8.9/build/reports/tests/test/ + #detekt: + # name: Run detekt + # runs-on: ubuntu-latest + + # steps: + # - name: Checkout code + # uses: actions/checkout@v4 + # - uses: ./.github/actions/setup-normal-workspace + # - name: Run detekt + # run: | + # ./gradlew detekt --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/detekt.sarif + + preprocess: runs-on: ubuntu-latest name: "Build multi version" steps: - - uses: actions/checkout@v3 - - name: Set up JDK 21 - uses: actions/setup-java@v3 - with: - java-version: 21 - distribution: temurin - cache: gradle - - name: Setup gradle - uses: gradle/gradle-build-action@v2 + - name: Checkout code + uses: actions/checkout@v4 + - uses: ./.github/actions/setup-normal-workspace - name: Enable preprocessor run: | mkdir -p .gradle diff --git a/.github/workflows/check-style.yaml.disabled b/.github/workflows/check-style.yaml.disabled deleted file mode 100644 index ff172208f..000000000 --- a/.github/workflows/check-style.yaml.disabled +++ /dev/null @@ -1,16 +0,0 @@ -name: check-style -on: - - pull_request -jobs: - ktlint: - name: Check Style - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - name: Checkout code - - name: ktlint - uses: ScaCap/action-ktlint@master - with: - github_token: ${{ secrets.github_token }} - reporter: github-pr-check diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fc0f2d5c4..d68b88f9f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -97,6 +97,11 @@ format like "- #821" to illustrate the dependency. - Follow the [Hypixel Rules](https://hypixel.net/rules). - Use the coding conventions for [Kotlin](https://kotlinlang.org/docs/coding-conventions.html) and [Java](https://www.oracle.com/java/technologies/javase/codeconventions-contents.html). +- **My build is failing due to `detekt`, what do I do?** + - `detekt` is our code quality tool. It checks for code smells and style issues. + - If you have a build failure stating `Analysis failed with ... weighted issues.`, you can check `versions/[target version]/build/reports/detekt/` for a comprehensive list of issues. + - **There are valid reasons to deviate from the norm** + - If you have such a case, either use `@Supress("rule_name")`, or re-build the `baseline.xml` file, using `./gradlew detektBaseline`. - Do not copy features from other mods. Exceptions: - Mods that are paid to use. - Mods that have reached their end of life. (Rip SBA, Dulkir and Soopy). diff --git a/build.gradle.kts b/build.gradle.kts index add2df4e7..b0e2af254 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,6 +3,8 @@ import at.skyhanni.sharedvariables.MultiVersionStage import at.skyhanni.sharedvariables.ProjectTarget import at.skyhanni.sharedvariables.SHVersionInfo import at.skyhanni.sharedvariables.versionString +import io.gitlab.arturbosch.detekt.Detekt +import io.gitlab.arturbosch.detekt.DetektCreateBaselineTask import net.fabricmc.loom.task.RunGameTask import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile @@ -18,32 +20,12 @@ plugins { kotlin("plugin.power-assert") `maven-publish` id("moe.nea.shot") version "1.0.0" + id("io.gitlab.arturbosch.detekt") id("net.kyori.blossom") } val target = ProjectTarget.values().find { it.projectPath == project.path }!! -repositories { - mavenCentral() - mavenLocal() - maven("https://maven.minecraftforge.net") { - metadataSources { - artifact() // We love missing POMs - } - } - maven("https://repo.spongepowered.org/maven/") // mixin - maven("https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1") // DevAuth - maven("https://jitpack.io") { // NotEnoughUpdates (compiled against) - content { - includeGroupByRegex("(com|io)\\.github\\..*") - } - } - maven("https://repo.nea.moe/releases") // libautoupdate - maven("https://maven.notenoughupdates.org/releases") // NotEnoughUpdates (dev env) - maven("https://repo.hypixel.net/repository/Hypixel/") // mod-api - maven("https://maven.teamresourceful.com/repository/thatgravyboat/") // DiscordIPC -} - // Toolchains: java { toolchain.languageVersion.set(target.minecraftVersion.javaLanguageVersion) @@ -178,10 +160,14 @@ dependencies { exclude(module = "unspecified") isTransitive = false } - testImplementation("org.junit.jupiter:junit-jupiter:5.10.0") + testImplementation("org.junit.jupiter:junit-jupiter:5.11.0") testImplementation("io.mockk:mockk:1.12.5") implementation("net.hypixel:mod-api:0.3.1") + + detektPlugins("org.notenoughupdates:detektrules:1.0.0") + detektPlugins(project(":detekt")) + detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.23.7") } afterEvaluate { @@ -350,3 +336,29 @@ publishing.publications { } } } + +// Detekt: TODO: Uncomment this when we're ready to enforce +/*detekt { + buildUponDefaultConfig = true // preconfigure defaults + config.setFrom(rootProject.layout.projectDirectory.file("detekt/detekt.yml")) // point to your custom config defining rules to run, overwriting default behavior + baseline = file(layout.projectDirectory.file("detekt/baseline.xml")) // a way of suppressing issues before introducing detekt + source.setFrom(project.sourceSets.named("main").map { it.allSource }) +} + +tasks.withType<Detekt>().configureEach { + reports { + html.required.set(true) // observe findings in your browser with structure and code snippets + xml.required.set(true) // checkstyle like format mainly for integrations like Jenkins + sarif.required.set(true) // standardized SARIF format (https://sarifweb.azurewebsites.net/) to support integrations with GitHub Code Scanning + md.required.set(true) // simple Markdown format + } +} + +tasks.withType<Detekt>().configureEach { + jvmTarget = target.minecraftVersion.formattedJavaLanguageVersion + outputs.cacheIf { false } // Custom rules won't work if cached +} +tasks.withType<DetektCreateBaselineTask>().configureEach { + jvmTarget = target.minecraftVersion.formattedJavaLanguageVersion + outputs.cacheIf { false } // Custom rules won't work if cached +}*/ diff --git a/detekt/baseline.xml b/detekt/baseline.xml new file mode 100644 index 000000000..ac35c2f6d --- /dev/null +++ b/detekt/baseline.xml @@ -0,0 +1,339 @@ +<?xml version="1.0" ?> +<SmellBaseline> + <ManuallySuppressedIssues></ManuallySuppressedIssues> + <CurrentIssues> + <ID>AnnotationOnSeparateLine:GraphEditor.kt$GraphEditor$@Suppress("MapGetWithNotNullAssertionOperator") node.neighbours.map { GraphingEdge( translation[node]!!, translation[it.key]!!, ) }</ID> + <ID>AnnotationOnSeparateLine:GraphEditor.kt$GraphEditor$@Suppress("MapGetWithNotNullAssertionOperator") nodes[indexedTable[otherNode.id]!!]</ID> + <ID>ArrayPrimitive:CropMoneyDisplay.kt$CropMoneyDisplay$Array<Double></ID> + <ID>ArrayPrimitive:CropMoneyDisplay.kt$CropMoneyDisplay$arrayOf(npcPrice)</ID> + <ID>ArrayPrimitive:CropMoneyDisplay.kt$CropMoneyDisplay$arrayOf(sellOffer)</ID> + <ID>ArrayPrimitive:LorenzVec.kt$Array<Double></ID> + <ID>ArrayPrimitive:LorenzVec.kt$LorenzVec$Array<Double></ID> + <ID>ArrayPrimitive:LorenzVec.kt$LorenzVec$Array<Float></ID> + <ID>ArrayPrimitive:LorenzVec.kt$LorenzVec$arrayOf(x, y, z)</ID> + <ID>ArrayPrimitive:LorenzVec.kt$LorenzVec$arrayOf(x.toFloat(), y.toFloat(), z.toFloat())</ID> + <ID>CyclomaticComplexMethod:AdvancedPlayerList.kt$AdvancedPlayerList$fun newSorting(original: List<String>): List<String></ID> + <ID>CyclomaticComplexMethod:CropMoneyDisplay.kt$CropMoneyDisplay$private fun calculateMoneyPerHour(debugList: MutableList<List<Any>>): Map<NEUInternalName, Array<Double>></ID> + <ID>CyclomaticComplexMethod:CropMoneyDisplay.kt$CropMoneyDisplay$private fun drawDisplay(): List<List<Any>></ID> + <ID>CyclomaticComplexMethod:DamageIndicatorManager.kt$DamageIndicatorManager$private fun checkThorn(realHealth: Long, realMaxHealth: Long): String?</ID> + <ID>CyclomaticComplexMethod:EstimatedItemValueCalculator.kt$EstimatedItemValueCalculator$private fun addEnchantments(stack: ItemStack, list: MutableList<String>): Double</ID> + <ID>CyclomaticComplexMethod:GardenBestCropTime.kt$GardenBestCropTime$fun drawBestDisplay(currentCrop: CropType?): List<List<Any>></ID> + <ID>CyclomaticComplexMethod:GardenCropMilestoneDisplay.kt$GardenCropMilestoneDisplay$private fun drawProgressDisplay(crop: CropType): List<Renderable></ID> + <ID>CyclomaticComplexMethod:GardenVisitorFeatures.kt$GardenVisitorFeatures$private fun readToolTip(visitor: VisitorAPI.Visitor, itemStack: ItemStack?, toolTip: MutableList<String>)</ID> + <ID>CyclomaticComplexMethod:GhostCounter.kt$GhostCounter$private fun drawDisplay()</ID> + <ID>CyclomaticComplexMethod:GraphEditor.kt$GraphEditor$private fun input()</ID> + <ID>CyclomaticComplexMethod:GraphEditorBugFinder.kt$GraphEditorBugFinder$private fun asyncTest()</ID> + <ID>CyclomaticComplexMethod:IslandAreas.kt$IslandAreas$private fun buildDisplay()</ID> + <ID>CyclomaticComplexMethod:ItemDisplayOverlayFeatures.kt$ItemDisplayOverlayFeatures$private fun getStackTip(item: ItemStack): String?</ID> + <ID>CyclomaticComplexMethod:ItemNameResolver.kt$ItemNameResolver$internal fun getInternalNameOrNull(itemName: String): NEUInternalName?</ID> + <ID>CyclomaticComplexMethod:MinecraftConsoleFilter.kt$MinecraftConsoleFilter$override fun filter(event: LogEvent?): Filter.Result</ID> + <ID>CyclomaticComplexMethod:OverviewPage.kt$OverviewPage$private fun getPage(): Pair<List<List<Renderable>>, List<Renderable>></ID> + <ID>CyclomaticComplexMethod:PacketTest.kt$PacketTest$private fun Packet<*>.print()</ID> + <ID>CyclomaticComplexMethod:ParkourHelper.kt$ParkourHelper$fun render(event: LorenzRenderWorldEvent)</ID> + <ID>CyclomaticComplexMethod:Renderable.kt$Renderable.Companion$internal fun shouldAllowLink(debug: Boolean = false, bypassChecks: Boolean): Boolean</ID> + <ID>CyclomaticComplexMethod:SkillProgress.kt$SkillProgress$private fun drawDisplay()</ID> + <ID>CyclomaticComplexMethod:VampireSlayerFeatures.kt$VampireSlayerFeatures$private fun EntityOtherPlayerMP.process()</ID> + <ID>CyclomaticComplexMethod:VisualWordGui.kt$VisualWordGui$override fun drawScreen(unusedX: Int, unusedY: Int, partialTicks: Float)</ID> + <ID>DestructuringDeclarationWithTooManyEntries:SackDisplay.kt$SackDisplay$val (internalName, rough, flawed, fine, roughPrice, flawedPrice, finePrice) = gem</ID> + <ID>Filename:AreaChangeEvents.kt$at.hannibal2.skyhanni.events.skyblock.AreaChangeEvents.kt</ID> + <ID>InjectDispatcher:ClipboardUtils.kt$ClipboardUtils$IO</ID> + <ID>InjectDispatcher:GardenNextJacobContest.kt$GardenNextJacobContest$IO</ID> + <ID>InjectDispatcher:HypixelBazaarFetcher.kt$HypixelBazaarFetcher$IO</ID> + <ID>InjectDispatcher:MayorAPI.kt$MayorAPI$IO</ID> + <ID>LongMethod:CopyNearbyEntitiesCommand.kt$CopyNearbyEntitiesCommand$fun command(args: Array<String>)</ID> + <ID>LongMethod:CropMoneyDisplay.kt$CropMoneyDisplay$private fun drawDisplay(): List<List<Any>></ID> + <ID>LongMethod:DefaultConfigOptionGui.kt$DefaultConfigOptionGui$override fun drawScreen(mouseX: Int, mouseY: Int, partialTicks: Float)</ID> + <ID>LongMethod:GhostCounter.kt$GhostCounter$private fun drawDisplay()</ID> + <ID>LongMethod:GraphEditor.kt$GraphEditor$private fun input()</ID> + <ID>LongMethod:ItemDisplayOverlayFeatures.kt$ItemDisplayOverlayFeatures$private fun getStackTip(item: ItemStack): String?</ID> + <ID>LongMethod:MinecraftConsoleFilter.kt$MinecraftConsoleFilter$override fun filter(event: LogEvent?): Filter.Result</ID> + <ID>LongMethod:OverviewPage.kt$OverviewPage$private fun getPage(): Pair<List<List<Renderable>>, List<Renderable>></ID> + <ID>LongMethod:RenderableTooltips.kt$RenderableTooltips$private fun drawHoveringText()</ID> + <ID>LongMethod:TabListRenderer.kt$TabListRenderer$private fun drawTabList()</ID> + <ID>LongMethod:VisualWordGui.kt$VisualWordGui$override fun drawScreen(unusedX: Int, unusedY: Int, partialTicks: Float)</ID> + <ID>LoopWithTooManyJumpStatements:AdvancedPlayerList.kt$AdvancedPlayerList$for</ID> + <ID>LoopWithTooManyJumpStatements:CropMoneyDisplay.kt$CropMoneyDisplay$for</ID> + <ID>LoopWithTooManyJumpStatements:CustomScoreboard.kt$CustomScoreboard$for</ID> + <ID>LoopWithTooManyJumpStatements:EstimatedItemValueCalculator.kt$EstimatedItemValueCalculator$for</ID> + <ID>LoopWithTooManyJumpStatements:GardenComposterInventoryFeatures.kt$GardenComposterInventoryFeatures$for</ID> + <ID>LoopWithTooManyJumpStatements:GardenVisitorFeatures.kt$GardenVisitorFeatures$for</ID> + <ID>LoopWithTooManyJumpStatements:IslandAreas.kt$IslandAreas$for</ID> + <ID>LoopWithTooManyJumpStatements:RiftBloodEffigies.kt$RiftBloodEffigies$for</ID> + <ID>LoopWithTooManyJumpStatements:SkyBlockItemModifierUtils.kt$SkyBlockItemModifierUtils$for</ID> + <ID>LoopWithTooManyJumpStatements:SkyHanniConfigSearchResetCommand.kt$SkyHanniConfigSearchResetCommand$for</ID> + <ID>LoopWithTooManyJumpStatements:SuperpairsClicksAlert.kt$SuperpairsClicksAlert$for</ID> + <ID>MapGetWithNotNullAssertionOperator:NavigationHelper.kt$NavigationHelper$distances[node]!!</ID> + <ID>MatchingDeclarationName:AreaChangeEvents.kt$ScoreboardAreaChangeEvent : SkyHanniEvent</ID> + <ID>MaxLineLength:GraphEditor.kt$GraphEditor$@Suppress("MapGetWithNotNullAssertionOperator") nodes[indexedTable[otherNode.id]!!] to node.position.distance(otherNode.position)</ID> + <ID>MemberNameEqualsClassName:CaptureFarmingGear.kt$CaptureFarmingGear$fun captureFarmingGear()</ID> + <ID>MemberNameEqualsClassName:Commands.kt$Commands$// command -> description private val commands = mutableListOf<CommandInfo>()</ID> + <ID>MemberNameEqualsClassName:FameRanks.kt$FameRanks$var fameRanks = emptyMap<String, FameRank>() private set</ID> + <ID>MemberNameEqualsClassName:FirstMinionTier.kt$FirstMinionTier$fun firstMinionTier( otherItems: Map<NEUInternalName, Int>, minions: MutableMap<String, NEUInternalName>, tierOneMinions: MutableList<NEUInternalName>, tierOneMinionsDone: MutableSet<NEUInternalName>, )</ID> + <ID>MemberNameEqualsClassName:LastServers.kt$LastServers$private val lastServers = mutableMapOf<String, SimpleTimeMark>()</ID> + <ID>MemberNameEqualsClassName:PestSpawn.kt$PestSpawn$private fun pestSpawn(amount: Int, plotNames: List<String>, unknownAmount: Boolean)</ID> + <ID>MemberNameEqualsClassName:Shimmy.kt$Shimmy.Companion$private fun shimmy(source: Any?, fieldName: String): Any?</ID> + <ID>MemberNameEqualsClassName:TestBingo.kt$TestBingo$var testBingo = false</ID> + <ID>MemberNameEqualsClassName:Text.kt$Text$fun text(text: String, init: IChatComponent.() -> Unit = {})</ID> + <ID>NoNameShadowing:BucketedItemTrackerData.kt$BucketedItemTrackerData${ it.hidden = !it.hidden }</ID> + <ID>NoNameShadowing:BurrowWarpHelper.kt$BurrowWarpHelper${ it.startsWith("§bWarp to ") }</ID> + <ID>NoNameShadowing:ChunkedStat.kt$ChunkedStat.Companion${ it.showWhen() }</ID> + <ID>NoNameShadowing:ContributorManager.kt$ContributorManager${ it.isAllowed() }</ID> + <ID>NoNameShadowing:Graph.kt$Graph.Companion${ out.name("Name").value(it) }</ID> + <ID>NoNameShadowing:Graph.kt$Graph.Companion${ out.name("Tags") out.beginArray() for (tagName in it) { out.value(tagName) } out.endArray() }</ID> + <ID>NoNameShadowing:GraphEditorBugFinder.kt$GraphEditorBugFinder${ it.position.distanceSqToPlayer() }</ID> + <ID>NoNameShadowing:GuiOptionEditorUpdateCheck.kt$GuiOptionEditorUpdateCheck$width</ID> + <ID>NoNameShadowing:HoppityCollectionStats.kt$HoppityCollectionStats${ val displayAmount = it.amount.shortFormat() val operationFormat = when (milestoneType) { HoppityEggType.CHOCOLATE_SHOP_MILESTONE -> "spending" HoppityEggType.CHOCOLATE_FACTORY_MILESTONE -> "reaching" else -> "" // Never happens } // List indexing is weird existingLore[replaceIndex - 1] = "§7Obtained by $operationFormat §6$displayAmount" existingLore[replaceIndex] = "§7all-time §6Chocolate." return existingLore }</ID> + <ID>NoNameShadowing:HotmData.kt$HotmData.Companion${ it.setCurrent(it.getTotal()) }</ID> + <ID>NoNameShadowing:LorenzVec.kt$LorenzVec.Companion$pitch</ID> + <ID>NoNameShadowing:LorenzVec.kt$LorenzVec.Companion$yaw</ID> + <ID>NoNameShadowing:Renderable.kt$Renderable.Companion.<no name provided>$posX</ID> + <ID>NoNameShadowing:Renderable.kt$Renderable.Companion.<no name provided>$posY</ID> + <ID>NoNameShadowing:Renderable.kt$Renderable.Companion.<no name provided>${ it.value?.contains(textInput.textBox, ignoreCase = true) ?: true }</ID> + <ID>NoNameShadowing:RenderableUtils.kt$RenderableUtils${ it != null }</ID> + <ID>NoNameShadowing:ReplaceRomanNumerals.kt$ReplaceRomanNumerals${ it.isValidRomanNumeral() && it.removeFormatting().romanToDecimal() != 2000 }</ID> + <ID>NoNameShadowing:RepoManager.kt$RepoManager${ unsuccessfulConstants.add(it) }</ID> + <ID>NoNameShadowing:RepoPatternManager.kt$RepoPatternManager${ it == '.' }</ID> + <ID>NoNameShadowing:Shimmy.kt$Shimmy.Companion$source</ID> + <ID>NoNameShadowing:SkyHanniBucketedItemTracker.kt$SkyHanniBucketedItemTracker${ ItemPriceSource.entries[it.ordinal] }</ID> + <ID>ReturnCount:AnitaMedalProfit.kt$AnitaMedalProfit$private fun readItem(slot: Int, item: ItemStack, table: MutableList<DisplayTableEntry>)</ID> + <ID>ReturnCount:BingoNextStepHelper.kt$BingoNextStepHelper$private fun readDescription(description: String): NextStep?</ID> + <ID>ReturnCount:BroodmotherFeatures.kt$BroodmotherFeatures$private fun onStageUpdate()</ID> + <ID>ReturnCount:ChatPeek.kt$ChatPeek$@JvmStatic fun peek(): Boolean</ID> + <ID>ReturnCount:ChestValue.kt$ChestValue$private fun isValidStorage(): Boolean</ID> + <ID>ReturnCount:CollectionTracker.kt$CollectionTracker$fun command(args: Array<String>)</ID> + <ID>ReturnCount:CompactBingoChat.kt$CompactBingoChat$private fun onSkyBlockLevelUp(message: String): Boolean</ID> + <ID>ReturnCount:CrimsonMinibossRespawnTimer.kt$CrimsonMinibossRespawnTimer$private fun updateArea()</ID> + <ID>ReturnCount:CropMoneyDisplay.kt$CropMoneyDisplay$private fun drawDisplay(): List<List<Any>></ID> + <ID>ReturnCount:DamageIndicatorManager.kt$DamageIndicatorManager$private fun checkThorn(realHealth: Long, realMaxHealth: Long): String?</ID> + <ID>ReturnCount:DamageIndicatorManager.kt$DamageIndicatorManager$private fun getCustomHealth( entityData: EntityData, health: Long, entity: EntityLivingBase, maxHealth: Long, ): String?</ID> + <ID>ReturnCount:EnchantParser.kt$EnchantParser$private fun parseEnchants( loreList: MutableList<String>, enchants: Map<String, Int>, chatComponent: IChatComponent?, )</ID> + <ID>ReturnCount:EstimatedItemValue.kt$EstimatedItemValue$private fun draw(stack: ItemStack): List<List<Any>></ID> + <ID>ReturnCount:EstimatedItemValueCalculator.kt$EstimatedItemValueCalculator$private fun calculateStarPrice( internalName: NEUInternalName, inputStars: Int, ): Pair<EssenceItemUtils.EssenceUpgradePrice, Pair<Int, Int>>?</ID> + <ID>ReturnCount:FishingAPI.kt$FishingAPI$fun seaCreatureCount(entity: EntityArmorStand): Int</ID> + <ID>ReturnCount:GardenVisitorFeatures.kt$GardenVisitorFeatures$private fun showGui(): Boolean</ID> + <ID>ReturnCount:GraphEditor.kt$GraphEditor$private fun input()</ID> + <ID>ReturnCount:HideNotClickableItems.kt$HideNotClickableItems$private fun hideSalvage(chestName: String, stack: ItemStack): Boolean</ID> + <ID>ReturnCount:IslandGraphs.kt$IslandGraphs$private fun handleTick()</ID> + <ID>ReturnCount:ItemDisplayOverlayFeatures.kt$ItemDisplayOverlayFeatures$private fun getStackTip(item: ItemStack): String?</ID> + <ID>ReturnCount:ItemNameResolver.kt$ItemNameResolver$internal fun getInternalNameOrNull(itemName: String): NEUInternalName?</ID> + <ID>ReturnCount:ItemPriceUtils.kt$ItemPriceUtils$fun NEUInternalName.getPriceOrNull( priceSource: ItemPriceSource = ItemPriceSource.BAZAAR_INSTANT_BUY, pastRecipes: List<PrimitiveRecipe> = emptyList(), ): Double?</ID> + <ID>ReturnCount:ItemUtils.kt$ItemUtils$private fun NEUInternalName.grabItemName(): String</ID> + <ID>ReturnCount:MinecraftConsoleFilter.kt$MinecraftConsoleFilter$override fun filter(event: LogEvent?): Filter.Result</ID> + <ID>ReturnCount:MiningEventTracker.kt$MiningEventTracker$private fun sendData(eventName: String, time: String?)</ID> + <ID>ReturnCount:MobDetection.kt$MobDetection$private fun entitySpawn(entity: EntityLivingBase, roughType: Mob.Type): Boolean</ID> + <ID>ReturnCount:MobFilter.kt$MobFilter$internal fun createSkyblockEntity(baseEntity: EntityLivingBase): MobResult</ID> + <ID>ReturnCount:MobFilter.kt$MobFilter$private fun armorStandOnlyMobs(baseEntity: EntityLivingBase, armorStand: EntityArmorStand): MobResult?</ID> + <ID>ReturnCount:MobFilter.kt$MobFilter$private fun exceptions(baseEntity: EntityLivingBase, nextEntity: EntityLivingBase?): MobResult?</ID> + <ID>ReturnCount:MobFinder.kt$MobFinder$private fun tryAddEntitySpider(entity: EntityLivingBase): EntityResult?</ID> + <ID>ReturnCount:MobFinder.kt$MobFinder$private fun tryAddRift(entity: EntityLivingBase): EntityResult?</ID> + <ID>ReturnCount:MultiFilter.kt$MultiFilter$fun matchResult(string: String): String?</ID> + <ID>ReturnCount:PacketTest.kt$PacketTest$private fun Packet<*>.print()</ID> + <ID>ReturnCount:PowderMiningChatFilter.kt$PowderMiningChatFilter$@Suppress("CyclomaticComplexMethod") fun block(message: String): String?</ID> + <ID>ReturnCount:PurseAPI.kt$PurseAPI$private fun getCause(diff: Double): PurseChangeCause</ID> + <ID>ReturnCount:QuestLoader.kt$QuestLoader$private fun addQuest(name: String, state: QuestState, needAmount: Int): Quest</ID> + <ID>ReturnCount:ShowFishingItemName.kt$ShowFishingItemName$fun inCorrectArea(): Boolean</ID> + <ID>ReturnCount:SkillAPI.kt$SkillAPI$fun onCommand(it: Array<String>)</ID> + <ID>ReturnCount:SkyHanniConfigSearchResetCommand.kt$SkyHanniConfigSearchResetCommand$private suspend fun setCommand(args: Array<String>): String</ID> + <ID>ReturnCount:TabComplete.kt$TabComplete$private fun customTabComplete(command: String): List<String>?</ID> + <ID>SpreadOperator:ItemUtils.kt$ItemUtils$(tag, displayName, *lore.toTypedArray())</ID> + <ID>SpreadOperator:LimboPlaytime.kt$LimboPlaytime$( itemID.getItemStack().item, ITEM_NAME, *createItemLore() )</ID> + <ID>SpreadOperator:Text.kt$Text$(*component.toTypedArray(), separator = separator)</ID> + <ID>TooManyFunctions:CollectionUtils.kt$CollectionUtils</ID> + <ID>TooManyFunctions:DailyQuestHelper.kt$DailyQuestHelper</ID> + <ID>TooManyFunctions:EstimatedItemValueCalculator.kt$EstimatedItemValueCalculator</ID> + <ID>TooManyFunctions:GuiRenderUtils.kt$GuiRenderUtils</ID> + <ID>TooManyFunctions:HypixelCommands.kt$HypixelCommands</ID> + <ID>TooManyFunctions:InventoryUtils.kt$InventoryUtils</ID> + <ID>TooManyFunctions:LocationUtils.kt$LocationUtils</ID> + <ID>TooManyFunctions:LorenzUtils.kt$LorenzUtils</ID> + <ID>TooManyFunctions:LorenzVec.kt$LorenzVec</ID> + <ID>TooManyFunctions:MobFinder.kt$MobFinder</ID> + <ID>TooManyFunctions:NumberUtil.kt$NumberUtil</ID> + <ID>TooManyFunctions:RegexUtils.kt$RegexUtils</ID> + <ID>TooManyFunctions:RenderUtils.kt$RenderUtils</ID> + <ID>TooManyFunctions:Renderable.kt$Renderable$Companion</ID> + <ID>TooManyFunctions:ScoreboardElements.kt$at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardElements.kt</ID> + <ID>TooManyFunctions:ScoreboardEvent.kt$at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardEvent.kt</ID> + <ID>TooManyFunctions:SkyBlockItemModifierUtils.kt$SkyBlockItemModifierUtils</ID> + <ID>TooManyFunctions:StringUtils.kt$StringUtils</ID> + <ID>UnsafeCallOnNullableType:BasketWaypoints.kt$BasketWaypoints$Basket.entries.minByOrNull { it.waypoint.distanceSqToPlayer() }!!</ID> + <ID>UnsafeCallOnNullableType:BasketWaypoints.kt$BasketWaypoints$notFoundBaskets.minByOrNull { it.waypoint.distanceSqToPlayer() }!!</ID> + <ID>UnsafeCallOnNullableType:BucketedItemTrackerData.kt$BucketedItemTrackerData$it.value[internalName]?.hidden!!</ID> + <ID>UnsafeCallOnNullableType:ChocolateFactoryDataLoader.kt$ChocolateFactoryDataLoader$upgradeCost!!</ID> + <ID>UnsafeCallOnNullableType:CollectionUtils.kt$CollectionUtils$this.merge(key, number, Double::plus)!!</ID> + <ID>UnsafeCallOnNullableType:CollectionUtils.kt$CollectionUtils$this.merge(key, number, Float::plus)!!</ID> + <ID>UnsafeCallOnNullableType:CollectionUtils.kt$CollectionUtils$this.merge(key, number, Int::plus)!!</ID> + <ID>UnsafeCallOnNullableType:CollectionUtils.kt$CollectionUtils$this.merge(key, number, Long::plus)!!</ID> + <ID>UnsafeCallOnNullableType:CombatUtils.kt$CombatUtils$a!!</ID> + <ID>UnsafeCallOnNullableType:CompactBestiaryChatMessage.kt$CompactBestiaryChatMessage$it.groups[1]!!</ID> + <ID>UnsafeCallOnNullableType:ConfigManager.kt$ConfigManager$file!!</ID> + <ID>UnsafeCallOnNullableType:CorpseTracker.kt$CorpseTracker$applicableKeys.first().key!!</ID> + <ID>UnsafeCallOnNullableType:CosmeticFollowingLine.kt$CosmeticFollowingLine$latestLocations[b]!!</ID> + <ID>UnsafeCallOnNullableType:CosmeticFollowingLine.kt$CosmeticFollowingLine$locations[b]!!</ID> + <ID>UnsafeCallOnNullableType:CropMoneyDisplay.kt$CropMoneyDisplay$cropNames[internalName]!!</ID> + <ID>UnsafeCallOnNullableType:DailyMiniBossHelper.kt$DailyMiniBossHelper$getByDisplayName(name)!!</ID> + <ID>UnsafeCallOnNullableType:DamageIndicatorManager.kt$DamageIndicatorManager$data.deathLocation!!</ID> + <ID>UnsafeCallOnNullableType:DefaultConfigFeatures.kt$DefaultConfigFeatures$resetSuggestionState[cat]!!</ID> + <ID>UnsafeCallOnNullableType:DefaultConfigOptionGui.kt$DefaultConfigOptionGui$resetSuggestionState[cat]!!</ID> + <ID>UnsafeCallOnNullableType:DicerRngDropTracker.kt$DicerRngDropTracker$event.toolItem!!</ID> + <ID>UnsafeCallOnNullableType:DiscordStatus.kt$ownerRegex.find(colorlessLine)!!</ID> + <ID>UnsafeCallOnNullableType:DungeonAPI.kt$DungeonAPI$dungeonFloor!!</ID> + <ID>UnsafeCallOnNullableType:EasterEggWaypoints.kt$EasterEggWaypoints$EasterEgg.entries.minByOrNull { it.waypoint.distanceSqToPlayer() }!!</ID> + <ID>UnsafeCallOnNullableType:EasterEggWaypoints.kt$EasterEggWaypoints$notFoundEggs.minByOrNull { it.waypoint.distanceSqToPlayer() }!!</ID> + <ID>UnsafeCallOnNullableType:EntityMovementData.kt$EntityMovementData$entityLocation[entity]!!</ID> + <ID>UnsafeCallOnNullableType:EntityOutlineRenderer.kt$EntityOutlineRenderer$entityRenderCache.noXrayCache!!</ID> + <ID>UnsafeCallOnNullableType:EntityOutlineRenderer.kt$EntityOutlineRenderer$entityRenderCache.xrayCache!!</ID> + <ID>UnsafeCallOnNullableType:EntityOutlineRenderer.kt$EntityOutlineRenderer$frameToCopy!!</ID> + <ID>UnsafeCallOnNullableType:EntityOutlineRenderer.kt$EntityOutlineRenderer$frameToPaste!!</ID> + <ID>UnsafeCallOnNullableType:EntityOutlineRenderer.kt$EntityOutlineRenderer$isAntialiasing!!</ID> + <ID>UnsafeCallOnNullableType:EntityOutlineRenderer.kt$EntityOutlineRenderer$isFastRender!!</ID> + <ID>UnsafeCallOnNullableType:EntityOutlineRenderer.kt$EntityOutlineRenderer$isShaders!!</ID> + <ID>UnsafeCallOnNullableType:FFGuideGUI.kt$FFGuideGUI$currentCrop!!</ID> + <ID>UnsafeCallOnNullableType:FarmingContestAPI.kt$FarmingContestAPI$contestCrop!!</ID> + <ID>UnsafeCallOnNullableType:FarmingContestAPI.kt$FarmingContestAPI$contests[bracket]!!</ID> + <ID>UnsafeCallOnNullableType:FarmingContestAPI.kt$FarmingContestAPI$currentCrop!!</ID> + <ID>UnsafeCallOnNullableType:FarmingWeightDisplay.kt$FarmingWeightDisplay$weightPerCrop[CropType.CACTUS]!!</ID> + <ID>UnsafeCallOnNullableType:FarmingWeightDisplay.kt$FarmingWeightDisplay$weightPerCrop[CropType.SUGAR_CANE]!!</ID> + <ID>UnsafeCallOnNullableType:FeatureToggleProcessor.kt$FeatureToggleProcessor$latestCategory!!</ID> + <ID>UnsafeCallOnNullableType:FeatureTogglesByDefaultAdapter.kt$FeatureTogglesByDefaultAdapter$gson!!</ID> + <ID>UnsafeCallOnNullableType:FishingProfitTracker.kt$FishingProfitTracker$itemCategories[currentCategory]!!</ID> + <ID>UnsafeCallOnNullableType:FishingProfitTracker.kt$FishingProfitTracker.Data$itemCategories["Trophy Fish"]!!</ID> + <ID>UnsafeCallOnNullableType:FortuneUpgrades.kt$FortuneUpgrades$nextTalisman.upgradeCost?.first!!</ID> + <ID>UnsafeCallOnNullableType:GardenComposterUpgradesData.kt$GardenComposterUpgradesData$ComposterUpgrade.getByName(name)!!</ID> + <ID>UnsafeCallOnNullableType:GardenCropMilestoneDisplay.kt$GardenCropMilestoneDisplay$cultivatingData[crop]!!</ID> + <ID>UnsafeCallOnNullableType:GardenCropMilestonesCommunityFix.kt$GardenCropMilestonesCommunityFix$map[crop]!!</ID> + <ID>UnsafeCallOnNullableType:GardenPlotIcon.kt$GardenPlotIcon$originalStack[index]!!</ID> + <ID>UnsafeCallOnNullableType:GhostCounter.kt$GhostCounter$storage?.totalMF!!</ID> + <ID>UnsafeCallOnNullableType:Graph.kt$Graph.Companion$position!!</ID> + <ID>UnsafeCallOnNullableType:Graph.kt$distances.distances[end]!!</ID> + <ID>UnsafeCallOnNullableType:GriffinBurrowHelper.kt$GriffinBurrowHelper$particleBurrows[targetLocation]!!</ID> + <ID>UnsafeCallOnNullableType:HoppityCallWarning.kt$HoppityCallWarning$acceptUUID!!</ID> + <ID>UnsafeCallOnNullableType:IslandGraphs.kt$IslandGraphs$currentTarget!!</ID> + <ID>UnsafeCallOnNullableType:ItemBlink.kt$ItemBlink$offsets[item]!!</ID> + <ID>UnsafeCallOnNullableType:ItemPickupLog.kt$ItemPickupLog$listToCheckAgainst[key]!!</ID> + <ID>UnsafeCallOnNullableType:ItemPickupLog.kt$ItemPickupLog$listToCheckAgainst[key]?.second!!</ID> + <ID>UnsafeCallOnNullableType:ItemStackTypeAdapterFactory.kt$ItemStackTypeAdapterFactory$gson!!</ID> + <ID>UnsafeCallOnNullableType:ItemUtils.kt$ItemUtils$itemAmountCache[input]!!</ID> + <ID>UnsafeCallOnNullableType:JacobContestTimeNeeded.kt$JacobContestTimeNeeded$map[crop]!!</ID> + <ID>UnsafeCallOnNullableType:KSerializable.kt$K |
