diff --git a/.github/workflows/assign-relevant-labels.yml b/.github/workflows/assign-relevant-labels.yml new file mode 100644 index 000000000000..4118c7172093 --- /dev/null +++ b/.github/workflows/assign-relevant-labels.yml @@ -0,0 +1,64 @@ +name: "Assign relevant labels" +on: + pull_request_target: + types: [ opened, edited ] +jobs: + assign-label: + if: github.event.pull_request.state == 'open' + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + contents: read + steps: + - name: label + env: + TITLE: ${{ github.event.pull_request.title }} + LABEL_FIX: Bug Fix + LABEL_BACKEND: Backend + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN}} + script: | + const labelsToAdd = []; + const labelsToRemove = []; + const title = process.env.TITLE.split(":")[0].toUpperCase(); + + if(title.includes("FIX")){ + labelsToAdd.push(process.env.LABEL_FIX); + } else { + labelsToRemove.push(process.env.LABEL_FIX); + } + + if(title.includes("BACKEND")){ + labelsToAdd.push(process.env.LABEL_BACKEND); + } else { + labelsToRemove.push(process.env.LABEL_BACKEND); + } + + for (const label of labelsToAdd) { + github.rest.issues.addLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: [label] + }); + } + + const {data} = await github.rest.issues.listLabelsOnIssue({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + }); + + for (const label of labelsToRemove) { + const filtered = data.filter(l => l.name == label); + if(filtered.length == 1){ + github.rest.issues.removeLabel({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + name: label + }); + } + } diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7e42909ee297..7ab0e6c7543f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,14 +23,14 @@ jobs: - uses: ./.github/actions/setup-normal-workspace - name: Build with Gradle run: ./gradlew assemble -x test --stacktrace - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 name: Upload development build with: name: "Development Build" path: build/libs/*.jar - name: Test with Gradle run: ./gradlew test - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 name: "Upload test report" if: ${{ !cancelled() }} with: @@ -44,14 +44,15 @@ jobs: # - name: Checkout code # uses: actions/checkout@v4 # - uses: ./.github/actions/setup-normal-workspace - # - name: Run detekt + # # detektMain is a LOT slower than detekt, but it does type analysis + # - name: Run detekt main (w/typing analysis) # run: | - # ./gradlew detekt --stacktrace + # ./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/detekt.sarif + # ./.github/scripts/process_detekt_sarif.sh versions/1.8.9/build/reports/detekt/main.sarif preprocess: diff --git a/.github/workflows/generate-constants.yaml b/.github/workflows/generate-constants.yaml index c589676d0e2f..f6fab6f243ac 100644 --- a/.github/workflows/generate-constants.yaml +++ b/.github/workflows/generate-constants.yaml @@ -29,7 +29,7 @@ jobs: - name: Generate Repo Patterns using Gradle run: | ./gradlew generateRepoPatterns --stacktrace - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 name: Upload generated repo regexes with: name: Repo Regexes @@ -45,7 +45,7 @@ jobs: with: repository: ${{ env.data_repo }} branch: main - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 name: Upload generated repo regexes with: name: Repo Regexes diff --git a/.github/workflows/label-bug-fix.yml b/.github/workflows/label-bug-fix.yml deleted file mode 100644 index dae2980de630..000000000000 --- a/.github/workflows/label-bug-fix.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: "Bug Fix label" -on: - pull_request_target: - types: [ opened, edited ] -jobs: - assign-label: - if: github.event.pull_request.state == 'open' # Condition to check if PR is open - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - contents: read - steps: - - name: label - env: - TITLE: ${{ github.event.pull_request.title }} - LABEL: Bug Fix - Sooner than Very Soon - uses: actions/github-script@v7 - with: - github-token: ${{ secrets.GITHUB_TOKEN}} - script: | - if(process.env.TITLE.split(":")[0].toUpperCase().includes("FIX")){ - github.rest.issues.addLabels({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - labels: [process.env.LABEL] - }) - }else{ - const {data} = await github.rest.issues.listLabelsOnIssue({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - }) - const filtered = data.filter(label => label.name == process.env.LABEL) - if(filtered.length == 1){ - github.rest.issues.removeLabel({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - name: process.env.LABEL - }) - } - } diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml new file mode 100644 index 000000000000..3702088f8387 --- /dev/null +++ b/.github/workflows/pr-check.yml @@ -0,0 +1,57 @@ +name: "PR Changelog Verification" + +on: + pull_request_target: + types: [ opened, edited ] + +jobs: + verify-changelog: + if: github.event.pull_request.state == 'open' && '511310721' == github.repository_id + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - uses: ./.github/actions/setup-normal-workspace + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Run ChangeLog verification + env: + PR_TITLE: ${{ github.event.pull_request.title }} + PR_BODY: ${{ github.event.pull_request.body }} + run: | + ./gradlew checkPrDescription -PprTitle="${PR_TITLE}" -PprBody="${PR_BODY}" + + - name: Add label if changelog verification fails + if: failure() + uses: actions-ecosystem/action-add-labels@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + labels: 'Wrong Title/Changelog' + + - name: Remove label if changelog verification passes + if: success() + uses: actions-ecosystem/action-remove-labels@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + labels: 'Wrong Title/Changelog' + + - name: Add comment to PR if changelog verification fails + if: failure() + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const fs = require('fs'); + const test = fs.readFileSync('versions/1.8.9/build/changelog_errors.txt', 'utf8'); + const commentBody = `${test}` + + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: commentBody + }) diff --git a/.idea/dictionaries/default_user.xml b/.idea/dictionaries/default_user.xml index a0017ca5e3e0..86cfbc3f33b1 100644 --- a/.idea/dictionaries/default_user.xml +++ b/.idea/dictionaries/default_user.xml @@ -149,6 +149,7 @@ mineman mineshafts miniboss + minigame mirrorverse misclick missclick @@ -193,6 +194,8 @@ pling pocalypse polarvoid + powerup + powerups preinitialization procs prospection @@ -251,6 +254,7 @@ supercraft supercrafting superlite + superpair superpairs tablist terracottas diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d68b88f9fe66..fe6410c9d11e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,6 +13,7 @@ We use [IntelliJ](https://www.jetbrains.com/idea/) as an example. - Download IntelliJ from the [JetBrains Website](https://www.jetbrains.com/idea/download/). - Use the Community Edition. (Scroll down a bit.) +- When you encounter any bug with IntelliJ, please make sure to use the version `2024.1.6`, not `2024.2.x` or above. ### Cloning the project @@ -30,6 +31,7 @@ We use [IntelliJ](https://www.jetbrains.com/idea/) as an example. ### Setting up IntelliJ + Once your project is imported into IntelliJ from the previous step, all dependencies like Minecraft, NEU, and so on should be automatically downloaded. If not, you might need to link the Gradle project in the Gradle tab (little elephant) on the right. @@ -101,7 +103,9 @@ format like "- #821" to illustrate the dependency. - `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`. + - If you have such a case, either use `@Supress("rule_name")`, or re-build the `baseline.xml` file, using `./gradlew detektBaselineMain`. + After running detektBaselineMain, you should find a file called `baseline-main.xml` in the `version/1.8.9` folder, rename the file to + `baseline.xml` replacing the old one. You also should copy the new contents of this file to the [main baseline file](detekt/baseline.xml) - 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/README.md b/README.md index 07bf336a172c..3c7721cfb176 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ SkyHanni is a Forge mod for Minecraft 1.8.9 that adds many useful features to [H * **Helpful GUIs:** View important information at a glance. * **Extra Chat Messages:** Receive reminders and tips at the right moment. * **Object Highlighters:** Focus on important items in inventories or highlight mobs in the world. -* **Highly Customizeable Displays:** Personalise your Scoreboard, Tab List or chat format. +* **Highly Customizable Displays:** Personalise your Scoreboard, Tab List or chat format. * [And **much** more!](docs/FEATURES.md) SkyHanni is especially useful when doing farming, slayers, Bingo, Diana, fishing, Rift or mining. @@ -35,7 +35,7 @@ SkyHanni is especially useful when doing farming, slayers, Bingo, Diana, fishing Give feedback or just chat with others on our community Discord! * **Bug Reports:** Use the `#bug-reports` channel when you find broken features (please check out `#faq` and `#known-bugs`). -* **Quick Help** Ask in `#support` for questions and problems with the the mod or Minecraft in general. +* **Quick Help** Ask in `#support` for questions and problems with the mod or Minecraft in general. * **Feature Suggestions:** Feel fre to tell your ideas in `#suggestions` channel for new features and improvements to the mod. (Don't copy from existing mods or break Hypixel rules). * **General Chat:** Chat with other SkyHanni users in `#skyblock-general` channel about the game. diff --git a/build.gradle.kts b/build.gradle.kts index b0e2af2544ed..dde5ac410ed2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,6 +8,7 @@ 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 +import skyhannibuildsystem.ChangelogVerification plugins { idea @@ -39,11 +40,15 @@ val runDirectory = rootProject.file("run") runDirectory.mkdirs() // Minecraft configuration: loom { - if (this.isForgeLike) + if (this.isForgeLike) { forge { - pack200Provider.set(dev.architectury.pack200.java.Pack200Adapter()) + pack200Provider.set( + dev.architectury.pack200.java + .Pack200Adapter(), + ) mixinConfig("mixins.skyhanni.json") } + } mixin { useLegacyMixinAp.set(true) defaultRefmapName.set("mixins.skyhanni.refmap.json") @@ -67,11 +72,12 @@ loom { } } -if (target == ProjectTarget.MAIN) +if (target == ProjectTarget.MAIN) { sourceSets.main { resources.destinationDirectory.set(kotlin.destinationDirectory) output.setResourcesDir(kotlin.destinationDirectory) } +} val shadowImpl: Configuration by configurations.creating { configurations.implementation.get().extendsFrom(this) @@ -91,10 +97,19 @@ val headlessLwjgl by configurations.creating { isVisible = false } tasks.runClient { - this.javaLauncher.set(javaToolchains.launcherFor { - languageVersion.set(target.minecraftVersion.javaLanguageVersion) - }) + this.javaLauncher.set( + javaToolchains.launcherFor { + languageVersion.set(target.minecraftVersion.javaLanguageVersion) + }, + ) } + +tasks.register("checkPrDescription", ChangelogVerification::class) { + this.outputDirectory.set(layout.buildDirectory) + this.prTitle = project.findProperty("prTitle") as String + this.prBody = project.findProperty("prBody") as String +} + val shot = shots.shot("minecraft", rootProject.file("shots.txt")) dependencies { @@ -104,8 +119,9 @@ dependencies { } else { mappings(target.mappingDependency) } - if (target.forgeDep != null) + if (target.forgeDep != null) { "forge"(target.forgeDep!!) + } // Discord RPC client shadowImpl("com.jagrosh:DiscordIPC:0.5.3") { @@ -142,9 +158,9 @@ dependencies { exclude(module = "unspecified") isTransitive = false } - // August 27, 2024, 4:30 PM AEST - // https://github.com/NotEnoughUpdates/NotEnoughUpdates/tree/2.3.3 - devenvMod("com.github.NotEnoughUpdates:NotEnoughUpdates:2.3.3:all") { + // October 3, 2024, 11:43 PM AEST + // https://github.com/NotEnoughUpdates/NotEnoughUpdates/tree/2.4.0 + devenvMod("com.github.NotEnoughUpdates:NotEnoughUpdates:2.4.0:all") { exclude(module = "unspecified") isTransitive = false } @@ -165,6 +181,9 @@ dependencies { implementation("net.hypixel:mod-api:0.3.1") + // getting clock offset + shadowImpl("commons-net:commons-net:3.8.0") + detektPlugins("org.notenoughupdates:detektrules:1.0.0") detektPlugins(project(":detekt")) detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.23.7") @@ -218,10 +237,11 @@ if (target == ProjectTarget.MAIN) { } } -if (target == ProjectTarget.MAIN) +if (target == ProjectTarget.MAIN) { tasks.compileJava { dependsOn(tasks.processResources) } +} if (target.parent == ProjectTarget.MAIN) { val mainRes = project(ProjectTarget.MAIN.projectPath).tasks.getAt("processResources") @@ -272,6 +292,7 @@ tasks.shadowJar { relocate("io.github.notenoughupdates.moulconfig", "at.hannibal2.skyhanni.deps.moulconfig") relocate("moe.nea.libautoupdate", "at.hannibal2.skyhanni.deps.libautoupdate") relocate("com.jagrosh.discordipc", "at.hannibal2.skyhanni.deps.discordipc") + relocate("org.apache.commons.net", "at.hannibal2.skyhanni.deps.commons.net") } tasks.jar { archiveClassifier.set("nodeps") @@ -337,8 +358,7 @@ publishing.publications { } } -// Detekt: TODO: Uncomment this when we're ready to enforce -/*detekt { +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 @@ -346,6 +366,10 @@ publishing.publications { } tasks.withType().configureEach { + onlyIf { + false // TODO: Remove onlyIf when we're ready to enforce + } + 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 @@ -361,4 +385,4 @@ tasks.withType().configureEach { tasks.withType().configureEach { jvmTarget = target.minecraftVersion.formattedJavaLanguageVersion outputs.cacheIf { false } // Custom rules won't work if cached -}*/ +} diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 000000000000..505f438b98c2 --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,17 @@ +plugins { + `kotlin-dsl` +} + +repositories { + mavenCentral() + maven("https://jitpack.io") { + content { + includeGroupByRegex("com\\.github\\..*") + } + } +} + +dependencies { + implementation("org.jetbrains.kotlin:kotlin-stdlib") + implementation("com.github.SkyHanniStudios:SkyHanniChangelogBuilder:1.0.1") +} diff --git a/buildSrc/src/main/kotlin/skyhannibuildsystem/ChangelogVerification.kt b/buildSrc/src/main/kotlin/skyhannibuildsystem/ChangelogVerification.kt new file mode 100644 index 000000000000..8ac54d6fc0b1 --- /dev/null +++ b/buildSrc/src/main/kotlin/skyhannibuildsystem/ChangelogVerification.kt @@ -0,0 +1,64 @@ +package skyhannibuildsystem + +import at.hannibal2.changelog.SkyHanniChangelogBuilder +import org.gradle.api.DefaultTask +import org.gradle.api.GradleException +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.io.File + +abstract class ChangelogVerification : DefaultTask() { + + @get:OutputDirectory + abstract val outputDirectory: DirectoryProperty + + @Input + var prTitle: String = "" + + @Input + var prBody: String = "" + + @get:Internal + val prBodyLines get() = prBody.lines() + + private val prLink = "ignored" + private val templateLocation = "https://github.com/hannibal002/SkyHanni/blob/beta/pull_request_template.md" + + @TaskAction + fun scanChangelog() { + if (prBodyLines.contains("exclude_from_changelog")) { + println("PR is excluded from changelog verification") + return + } + + val (changes, bodyErrors) = SkyHanniChangelogBuilder.findChanges(prBodyLines, prLink) + val titleErrors = SkyHanniChangelogBuilder.findPullRequestNameErrors(prTitle, changes) + + if (bodyErrors.isEmpty() && titleErrors.isEmpty()) { + println("Changelog and title verification successful") + } else { + bodyErrors.forEach { println(it.message) } + titleErrors.forEach { println(it.message) } + + // Export errors so that they can be listed in the PR comment + val errorFile = File(outputDirectory.get().asFile, "changelog_errors.txt") + println("saved error file to: ${errorFile.path}") + + errorFile.appendText("I have detected some issues with your pull request:\n\n") + + if (bodyErrors.isNotEmpty()) { + errorFile.appendText("Body issues:\n${bodyErrors.joinToString("\n") { it.formatLine() }}\n\n") + } + if (titleErrors.isNotEmpty()) { + errorFile.appendText("Title issues:\n${titleErrors.joinToString("\n") { it.message }}\n\n") + } + + errorFile.appendText("Please fix these issues. For the correct format, refer to the [pull request template]($templateLocation).") + + throw GradleException("Changelog verification failed") + } + } +} diff --git a/detekt/detekt.yml b/detekt/detekt.yml index 1b7d3ab05ff8..ac5c9de53bcc 100644 --- a/detekt/detekt.yml +++ b/detekt/detekt.yml @@ -4,7 +4,7 @@ config: GrammarRules: active: true - AvoidColour: # custom rule to prefer color to colour + AvoidBritishSpelling: # custom rule to prefer american spellings over british ones active: true FormattingRules: diff --git a/detekt/src/main/kotlin/grammar/AvoidBritishSpelling.kt b/detekt/src/main/kotlin/grammar/AvoidBritishSpelling.kt new file mode 100644 index 000000000000..6a4ea3d61eb4 --- /dev/null +++ b/detekt/src/main/kotlin/grammar/AvoidBritishSpelling.kt @@ -0,0 +1,46 @@ +package at.hannibal2.skyhanni.detektrules.grammar + +import io.gitlab.arturbosch.detekt.api.CodeSmell +import io.gitlab.arturbosch.detekt.api.Config +import io.gitlab.arturbosch.detekt.api.Debt +import io.gitlab.arturbosch.detekt.api.Entity +import io.gitlab.arturbosch.detekt.api.Issue +import io.gitlab.arturbosch.detekt.api.Rule +import io.gitlab.arturbosch.detekt.api.Severity +import org.jetbrains.kotlin.psi.KtStringTemplateExpression + +/** + * This rule reports all usages of the british spelling over the american spelling in the codebase, + * this will ignore any type annotations, i.e., `@ConfigEditorColour` will not be reported. + */ +class AvoidBritishSpelling(config: Config) : Rule(config) { + override val issue = Issue( + "AvoidBritishSpelling", + Severity.Style, + "Avoid using the word british spelling over american spelling.", + Debt.FIVE_MINS, + ) + + private val scannedWords = mapOf( + "colour" to "color", + "armour" to "armor", + ) + + override fun visitStringTemplateExpression(expression: KtStringTemplateExpression) { + val text = + expression.text // Be aware .getText() returns the entire span of this template, including variable names contained within. This should be rare enough of a problem for us to not care about it. + + for (word in scannedWords) { + if (text.contains(word.key, ignoreCase = true)) { + report( + CodeSmell( + issue, + Entity.from(expression), + "Avoid using the word '${word.key}' in code, '${word.value}' is preferred instead.", + ), + ) + } + } + super.visitStringTemplateExpression(expression) + } +} diff --git a/detekt/src/main/kotlin/grammar/AvoidColour.kt b/detekt/src/main/kotlin/grammar/AvoidColour.kt deleted file mode 100644 index 754148d36f31..000000000000 --- a/detekt/src/main/kotlin/grammar/AvoidColour.kt +++ /dev/null @@ -1,38 +0,0 @@ -package at.hannibal2.skyhanni.detektrules.grammar - -import io.gitlab.arturbosch.detekt.api.CodeSmell -import io.gitlab.arturbosch.detekt.api.Config -import io.gitlab.arturbosch.detekt.api.Debt -import io.gitlab.arturbosch.detekt.api.Entity -import io.gitlab.arturbosch.detekt.api.Issue -import io.gitlab.arturbosch.detekt.api.Rule -import io.gitlab.arturbosch.detekt.api.Severity -import org.jetbrains.kotlin.psi.KtStringTemplateExpression - -/** - * This rule reports all usages of the word "colour" in the codebase, - * preferring the 'American' spelling "color" - this will ignore any - * type annotations, i.e., `@ConfigEditorColour` will not be reported. - */ -class AvoidColour(config: Config) : Rule(config) { - override val issue = Issue( - "AvoidColour", - Severity.Style, - "Avoid using the word 'colour' in code, prefer 'color' instead.", - Debt.FIVE_MINS - ) - - override fun visitStringTemplateExpression(expression: KtStringTemplateExpression) { - val text = expression.text // Be aware .getText() returns the entire span of this template, including variable names contained within. This should be rare enough of a problem for us to not care about it. - if (text.contains("colour", ignoreCase = true)) { - report( - CodeSmell( - issue, - Entity.from(expression), - "Avoid using the word 'colour' in code, prefer 'color' instead." - ) - ) - } - super.visitStringTemplateExpression(expression) - } -} diff --git a/detekt/src/main/kotlin/grammar/GrammarRuleSetProvider.kt b/detekt/src/main/kotlin/grammar/GrammarRuleSetProvider.kt index 957b20147cee..8001fe42b5b2 100644 --- a/detekt/src/main/kotlin/grammar/GrammarRuleSetProvider.kt +++ b/detekt/src/main/kotlin/grammar/GrammarRuleSetProvider.kt @@ -10,8 +10,11 @@ class GrammarRuleSetProvider : RuleSetProvider { override val ruleSetId: String = "GrammarRules" override fun instance(config: Config): RuleSet { - return RuleSet(ruleSetId, listOf( - AvoidColour(config) - )) + return RuleSet( + ruleSetId, + listOf( + AvoidBritishSpelling(config), + ), + ) } } diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 33d0b77c7433..a65aebe3eefb 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,6 +1,101 @@ # SkyHanni - Change Log -## Version 0.27 (in Beta) +## Version 0.28 (in Beta) + +### New Features + +#### Hoppity Features + ++ 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. + +#### Inventory Features + ++ Added Focus Mode. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/2694) + + In Focus Mode, only the name of the item is displayed instead of the full description. + +#### Fishing Features + ++ Added Lava Replacement. - HiZe (https://github.com/hannibal002/SkyHanni/pull/1885) + + Replaces the lava texture with the water texture. + + Primarily used for lava fishing in the Crimson Isle, but can be used anywhere else if the option is enabled. + +#### Mining Features + ++ 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) + +### Improvements + +#### Inventory Improvements + ++ Added Pocket Sack-in-a-Sack support to Estimated Item Value. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2698) + +#### Chat and Command Improvements + ++ 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) + +#### Combat Improvements + ++ Added Totem of Corruption and Enrager to the Ability Cooldown feature. - DungeonHub (https://github.com/hannibal002/SkyHanni/pull/2706) + +#### Misc Improvements + ++ Added distance display to waypoints created by Patcher's Send Coords feature. - jani (https://github.com/hannibal002/SkyHanni/pull/2704) + +### Fixes + +#### Dungeon Fixes + ++ Fixed Magical Power resetting to 0 when opening "Your Bags" in the Catacombs. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2710) + +#### Fishing Fixes + ++ Fixed fishing displays showing in dungeons. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2697) + +#### Inventory Fixes + ++ Fixed "No Guardian Pet warning" not supporting Pet Rule "On open Experimentation Table". - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2699) ++ 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) + +#### Combat Fixes + ++ Fixed Ghost Counter display appearing while in incorrect areas on the map. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2696) + +#### Custom Scoreboard Fixes + ++ Fixed Custom Scoreboard not showing the Second Barbarian Quest. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2709) + +#### Hoppity Fixes + ++ Fixed the chocolate egg share message sometimes displaying the wrong location name. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/2711) + +#### Commands Fixes + ++ Fixed /shtranslate not working in most cases. - Obsidian (https://github.com/hannibal002/SkyHanni/pull/2693) + +### Technical Details + ++ Assigned 'backend' label to PRs with 'backend' in the title. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2690) + + This does not change the functionality of the current bug fix label. ++ Added SuggestionProvider. - ThatGravyBoat (https://github.com/hannibal002/SkyHanni/pull/2637) + + This new class simplifies building suggestion trees. ++ Added Stats API. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/2253) ++ Cleaned up LorenzVec and added drawLineToEye. - Empa (https://github.com/hannibal002/SkyHanni/pull/2056) ++ Added SkyHanni event inheritance. - ThatGravyBoat (https://github.com/hannibal002/SkyHanni/pull/2047) ++ Added /shtranslateadvanced command. - Obsidian (https://github.com/hannibal002/SkyHanni/pull/2693) + + Allows specifying both the source and target language. ++ 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) + +## Version 0.27 ### New Features @@ -24,6 +119,10 @@ + Added Crafting Room Helper. - HiZe (https://github.com/hannibal002/SkyHanni/pull/2178) + Shows a holographic mob at the location where the mob is present in the real room inside the Mirrorverse in Rift. + Added Rift Time Real-Time Nametag Format. - Empa (https://github.com/hannibal002/SkyHanni/pull/2015) ++ Added a helper for tracking the Buttons Enigma Soul in the Rift. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2616) + + Using pathfinding to guide the player to the nearest spot with unpressed buttons and highlights them. ++ Added a route helper for Gunther's Rift Race in the West Village. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2616) ++ Added the ability to mute Wilted Berberis sounds when not farming. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2616) #### Dungeon Features @@ -93,6 +192,8 @@ + Shows attempts and XP since the last ULTRA-RARE. + Added Experiments Profit Tracker. - ILike2WatchMemes (https://github.com/hannibal002/SkyHanni/pull/2171) + Tracks profits in Coins and Enchanting XP. ++ Added Ultimate Enchant Star. - Empa (https://github.com/hannibal002/SkyHanni/pull/2612) + + Shows a star on Enchanted Books with an Ultimate Enchant. #### Chat Features @@ -134,6 +235,11 @@ + Includes an option to warn you when to throw your rod. + Shows how weak the golden fish is, as a nametag. + Also works on Stranded. ++ Added an alert for Gold or Diamond Trophy Fish catches. - ReyMaratov (https://github.com/hannibal002/SkyHanni/pull/2615) + + Displays a popup with the trophy name, rarity, and amount of the catch. + + Optionally, also plays a sound.+ Added an alert for Gold or Diamond Trophy Fish catches. - ReyMaratov (https://github.com/hannibal002/SkyHanni/pull/2615) + + Displays a popup with the trophy name, rarity, and amount of the catch. + + Optionally, also plays a sound. #### Misc Features @@ -171,11 +277,14 @@ + Added an option to hide all tooltips inside the Fossil Excavator. - Cuz_Im_Clicks (https://github.com/hannibal002/SkyHanni/pull/2579) + Added support for using the Pickobulus ability for the Mineshaft Pity Display. - Empa (https://github.com/hannibal002/SkyHanni/pull/2540) + Added Area Navigation support to Glacite Tunnels. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2544) ++ Updated wording in mineshaft pity breakdown ("efficient miner" -> "spread"). - Luna (https://github.com/hannibal002/SkyHanni/pull/2633) ++ Improved the wording of the Mining Event data error chat message. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2671) ++ Added Mining Effects (Powder Pumpkin, Filet O' Fortune, and Chilled Pristine Potato) to the Non-God Effect Display. - jani (https://github.com/hannibal002/SkyHanni/pull/2677) #### Diana Improvements + Added /warp stonks to the Burrow Warp Helper. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2399) -+ Added per-election season Diana Trackers. - !nea (https://github.com/hannibal002/SkyHanni/pull/2487) ++ Added per-election season Diana Trackers. - nea (https://github.com/hannibal002/SkyHanni/pull/2487) + This includes the Diana Profit Tracker and the Mythological Creature Tracker. + The data is stored moving forward, but there is currently no way to view anything other than the current year. + Changed the Diana Profit Tracker and Mythological Creature Tracker to always be visible when holding the Ancestral Spade in hand, even if Diana is not the mayor. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2496) @@ -188,6 +297,7 @@ + Added an opacity slider for the Custom Background Image in the Custom Scoreboard. - Empa (https://github.com/hannibal002/SkyHanni/pull/1837) + Added an Undo message when auto alignment inCustom Scoreboard gets disabled. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2402) + Added an option to show SkyBlock time on the custom scoreboard rounded to 10 minutes, similar to the vanilla scoreboard. - Luna (https://github.com/hannibal002/SkyHanni/pull/2443) ++ Reduced the frequency of scoreboard errors being displayed. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2672) #### Inventory Improvements @@ -200,6 +310,7 @@ + Added exceptions to the enchant parser. - Vixid (https://github.com/hannibal002/SkyHanni/pull/2254) + Stonk and non-mining tools with Efficiency 5 use the maximum enchant color. + Added a short cooldown between Experimentation Table Guardian Pet chat warnings. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2459) ++ Prevented the SB Menu from replacing items from Dungeons and Kuudra that are placed in the item pickup log. - Fazfoxy (https://github.com/hannibal002/SkyHanni/pull/2599) #### Chat Improvements @@ -221,11 +332,13 @@ + Added the required chocolate amount to the tooltip of milestone rabbits in Hoppity's Collection. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2523) + Improved the responsiveness of Hoppity Chat Compacting. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2488) + Added the ability to see how many duplicates you have previously found in Hoppity messages. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2556) ++ Improved the formatting of the Hoppity Event Stats card. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2638) #### Combat Improvements + Made the "Line to Arachne" width configurable. - azurejelly (https://github.com/hannibal002/SkyHanni/pull/2406) + Made the "Line to Miniboss" width configurable. - azurejelly (https://github.com/hannibal002/SkyHanni/pull/2406) ++ Added item cooldown support for Blaze Flares. - minhperry (https://github.com/hannibal002/SkyHanni/pull/2601)+ Added item cooldown support for Blaze Flares. - minhperry (https://github.com/hannibal002/SkyHanni/pull/2601) #### Config Improvements @@ -241,11 +354,15 @@ + Since the cactus knife now allows 500 max speed. + Made the waypoint to the middle of the plot for Pest Waypoint optional (off by default). - Luna (https://github.com/hannibal002/SkyHanni/pull/2469) + Reduced one click for supercrafting visitor materials by using `/viewrecipe` instead of `/recipe` when using the Shopping List button. - Miestiek (https://github.com/hannibal002/SkyHanni/pull/2505) ++ Added ignored crops for the Farming Lane feature. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/2622) ++ Made the Visitor Timer GUI clickable to teleport to the Barn. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/2658) #### Rift Improvements + Updated the description of the config for Enigma Soul Waypoints to help find the Rift Guide in the game. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2433) + Added Path Finder to Enigma Soul waypoints in the Rift. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2515) ++ Added the option to choose the color of the Living Metal Helper highlight. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2616) ++ Added an option to hide players while in Gunther's Rift Race. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2655) #### Dungeon Improvements @@ -254,6 +371,7 @@ #### The Carnival Improvements + Updated the Zombie Shootout Diamond color to be a deeper blue. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2511) ++ Added a cooldown to the Carnival NPC Quickstart feature. - minhperry (https://github.com/hannibal002/SkyHanni/pull/2628) #### Misc Improvements @@ -264,6 +382,16 @@ + Improved the performance of pathfinding logic in Area Navigation. - nea (https://github.com/hannibal002/SkyHanni/pull/2537) + Added a toggle to force the `en_US` locale for number formatting. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/2563) + Queued GfS will now always fall back to a default amount if one is not specified. - Luna (https://github.com/hannibal002/SkyHanni/pull/2584) ++ Improved pathfinding. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2597) + + The line to the target no longer jumps around as much. + + Progress to the target now shows up in chat, displaying blocks remaining and percentage completed. Clicking on the chat message cancels the pathfinding. ++ Added a warning in chat when the computer's time is inaccurate, along with a tutorial on how to fix it. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2623) ++ Improved the way pathfinding lines are rendered. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2634) ++ Automatically starts pathfinding after clicking on SkyHanni reminder chat messages about Carnival Reminder, Hoppity NPC, City Project, and account/profile upgrades. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2635) ++ Greatly improved performance by optimizing SkyHanni Chroma support for Patcher Font Renderer. - nopo (https://github.com/hannibal002/SkyHanni/pull/2666) ++ "Could not find server id" errors are now less common. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2680) ++ Clarified the wording of Bazaar Data Loading error messages. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2681) ++ Indicate in the CF menu when the chocolate amount has reached the cap and is therefore halted. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2688) ### Fixes @@ -276,6 +404,7 @@ #### Bingo Fixes + Fixed "show bingo rank number" feature toggle not functioning. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2445) ++ Fixed Custom Scoreboard not showing Carnival Lines on Bingo. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2631) #### Inventory Fixes @@ -296,6 +425,17 @@ + Fixed Estimated Item Value incorrectly showing all Kuudra armor as starred. - Luna (https://github.com/hannibal002/SkyHanni/pull/2550) + Fixed Experiments Profit Tracker & Superpair Data. - ILike2WatchMemes (https://github.com/hannibal002/SkyHanni/pull/2560) + Fixed price per unit for Stonk of Stonks auction not working for the bracket you are in. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/2572) ++ Fixed bugs in the Experiments Profit Tracker. - ILike2WatchMemes (https://github.com/hannibal002/SkyHanni/pull/2594) + + Corrected the count for bottles applied while being inside the experimentation table. + + Fixed `/shedittracker` support not functioning properly. ++ Fixed an issue where the item stack size on Diamond/Golden Heads and Master Skulls could be incorrect. - Fazfoxy (https://github.com/hannibal002/SkyHanni/pull/2611) ++ Fixed item category detection for recombobulated items. - minhperry (https://github.com/hannibal002/SkyHanni/pull/2608) ++ Fixed bugs in Superpair Data. - ILike2WatchMemes (https://github.com/hannibal002/SkyHanni/pull/2566) + + Fixed pair detection. + + Fixed enchanting XP detection. ++ Fixed Minister in Calendar Perk description sometimes not using the gray color. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2632) ++ Fixed highlighting items in one's own inventory for some Bazaar features, e.g., in the "click to re-order" feature. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2640) ++ Automatically remove incorrect Account/Profile Upgrade warnings by talking to Elizabeth. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2674) #### Mining Fixes @@ -320,6 +460,11 @@ + Fixed some blocks in the Crystal Hollows being detected as Mithril instead of Hard Stone. - Luna (https://github.com/hannibal002/SkyHanni/pull/2580) + Fixed "Mining Commissions Block Color" causing OptiFine connected textures not to connect properly. - nopo (https://github.com/hannibal002/SkyHanni/pull/2577) + Fixed the Mineshaft Pity Counter not working in the Great Glacite Lake. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/2565) ++ Fixed Powder Tracker inaccuracies. - Empa (https://github.com/hannibal002/SkyHanni/pull/2591) ++ Fixed Jasper gemstones not being addressed in the Powder Mining filter. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2618) ++ Fixed the King Talisman Tracker sometimes not displaying the correct data. - martimavocado (https://github.com/hannibal002/SkyHanni/pull/2663) ++ Fixed the Powder Tracker not tracking items correctly. - HiZe (https://github.com/hannibal002/SkyHanni/pull/2645) ++ Fixed an error in Powder Tracker. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2678) #### Scoreboard Fixes @@ -342,6 +487,10 @@ + Fixed a Custom Scoreboard error while in the Dojo. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2519) + Fixed a Custom Scoreboard error during M7 Dragons. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2510) + Fixed Custom Scoreboard error during the Raffle Event. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2545) ++ Fixed both the Custom Scoreboard Active and Starting Soon Tab List events being active simultaneously in the Garden. - Empa, j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2592) ++ Fixed Custom Scoreboard not showing the Perkpocalypse Mayor. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2683) ++ Fixed some scoreboard error messages appearing in chat. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2672) ++ Fixed the custom scoreboard not updating when the Hypixel scoreboard is not updating. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2685) #### Hoppity Fixes @@ -351,15 +500,21 @@ + Fixed minor formatting issues with Hoppity Event Summary. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2416) + Fixed Hoppity Event stats resetting. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2489) + Fixed an issue where Fish the Rabbit and El Dorado did not have compacted chat messages. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2488) ++ Fixed inconsistencies in Hoppity Duplicate Number counts. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2595) ++ Fixed Fish the Rabbit and El Dorado incorrectly counting as unique rabbits during Hoppity's Hunt. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2627) ++ Fixed Hoppity Collection Display not updating the rabbit count in some cases, e.g., when collecting rabbits on alpha or manually changing the config values. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2686) ++ Fixed the chocolate count increasing in other menus even when production is halted. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2688) #### Chat Fixes + Fixed an error with Patcher Coordinate Detection from chat. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2410) + Fixed ultimate enchants not showing in `/show`. - Vixid (https://github.com/hannibal002/SkyHanni/pull/2465) ++ Fixed being unable to shift-click on chat messages. - nopo (https://github.com/hannibal002/SkyHanni/pull/2650) #### Commands Fixes + Fixed the command `/shtps` printing nothing if the TPS display was currently showing nothing. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2446) ++ Fixed "/viewrecipe command replace" breaking pages. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2679) #### Dungeon Fixes @@ -371,10 +526,11 @@ + Fixed the reputation helper not updating after a sack update. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2439) + Fixed Heavy Pearls sometimes not being highlighted. - Luna (https://github.com/hannibal002/SkyHanni/pull/2479) ++ Added a delay to the Pablo helper message so it appears after he finishes his dialogue. - Luna (https://github.com/hannibal002/SkyHanni/pull/2662) #### Garden Fixes -+ Fixed outdated Dicer gemstone fortune in FF guide. - Not_a_cow (https://github.com/hannibal002/SkyHanni/pull/2499) ++ Fixed outdated Dicer gemstone fortune in FF guide. - not_a_cow (https://github.com/hannibal002/SkyHanni/pull/2499) + Fixed some garden messages not being blocked. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2532) + Fixed active sprays not being removed from the GUI when using a washer. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2532) @@ -382,6 +538,11 @@ + Updated Ghost Counter bestiary tiers to reflect Hypixel reducing the max kills needed from 250K to 100K. - Luna (https://github.com/hannibal002/SkyHanni/pull/2533) + Fixed a case where the Broodmother countdown could be wildly inaccurate. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2513) ++ Fixed Flare Display spamming chat with negative values when the server is lagging. - Stella (https://github.com/hannibal002/SkyHanni/pull/2567) ++ Fixed a case where the Imminent stage did not update the Broodmother countdown. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2602)v ++ Fixed some Islands Dummy mob types not being detected by the Damage Indicator. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2646) ++ Fixed the Ender Node Tracker not detecting some items. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2644) ++ Fixed Flare Expiration warnings not appearing in chat or as a title. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2643) #### The Carnival Fixes @@ -390,7 +551,12 @@ #### Fishing Fixes -+ Fixed error messages while using the Chum Bucket Hider feature. - nea89 (https://github.com/hannibal002/SkyHanni/pull/2587) ++ Fixed error messages while using the Chum Bucket Hider feature. - nea (https://github.com/hannibal002/SkyHanni/pull/2587) ++ Fixed the Trophy Fish Title displaying an undefined character in the format. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2670) + +#### Rift Fixes + ++ Fixed the Rift Timer pausing while in Gunther's Rift Race. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2616) #### Misc Fixes @@ -412,6 +578,12 @@ + Fixed reforge display not working with new mining stats. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2555) + Fixed Totem of Corruption expiry warning not working in some cases. - Luna (https://github.com/hannibal002/SkyHanni/pull/2554) + Fixed a few typos in the config. - rdbt (https://github.com/hannibal002/SkyHanni/pull/2585) ++ Fixed Area Navigation distances to player being incorrect. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2634) ++ Fixed item trackers displaying removed item names incorrectly. - CalMWolfs (https://github.com/hannibal002/SkyHanni/pull/2620) ++ Fixed some messages from Pablo NPC not being detected. - Luna (https://github.com/hannibal002/SkyHanni/pull/2636) ++ Fixed SkyHanni re-downloading the repository on every launch. - nopo (https://github.com/hannibal002/SkyHanni/pull/2669) ++ Fixed unknown Perkpocalypse Mayor chat spam. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2683) ++ Fixed the wiki keybind searching for "null" on items with no internal name. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2682) ### Technical Details @@ -443,7 +615,7 @@ + Changed RenderableTooltips to be more consistent with the vanilla ones. - Empa (https://github.com/hannibal002/SkyHanni/pull/1869) + Improved error logging for enchant parser. - Vixid (https://github.com/hannibal002/SkyHanni/pull/2454) + Added renderable search box. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/2475) -+ Added the ability to add more optional display modes to trackers. - !nea (https://github.com/hannibal002/SkyHanni/pull/2487) ++ Added the ability to add more optional display modes to trackers. - nea (https://github.com/hannibal002/SkyHanni/pull/2487) + These extra trackers still need to provide their own storage. + Added perk descriptions to mayor perks. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2342) + These are loaded when checking the active mayor/minister from the API, so most of the perks will initially have no description. @@ -480,6 +652,16 @@ + These are added as a layer between SkyHanni and NEU so that we are not reliant on NEU functions. + Added Blossom Gradle plugin for token replacement in code. - ThatGravyBoat (https://github.com/hannibal002/SkyHanni/pull/2558) + `@MOD_VERSION@` is now a token that will be replaced. ++ Added `detekt` runner to the build process. - Daveed & nea (https://github.com/hannibal002/SkyHanni/pull/2547) ++ Added Clock Offset Millis using an NTP server. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2623) ++ Added `EntityMovementData.onNextTeleport()` logic, which triggers a runnable after the world has changed or the player has teleported. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2635) ++ Added Bazaar Fetch information to `/shdebug`. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2675) ++ Removed the password from the download source check. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2649) ++ Added a missing SkyBlock check for debug commands `/shtrackparticles` and `/shtracksounds`. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2641) ++ Prepared for later migration of correct config name of Plhlegblast. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2684) ++ Added the ability to disable SkyHanni errors via repo configuration. - nopo (https://github.com/hannibal002/SkyHanni/pull/2668) ++ Added current server ID and fetch data to the `/shdebug` command. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2680) ++ Added more `/shdebug` checks for aspects like OS, Java version, and launcher. - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2691) ### Removed Features @@ -489,6 +671,7 @@ + Replaced then with a draggable list of different Hoppity collection highlight options. + Removed "Forge GfS". - hannibal2 (https://github.com/hannibal002/SkyHanni/pull/2564) + Hypixel now pulls directly from sacks when using the forge. ++ Removed Mithril Powder from the Powder Tracker. - j10a1n15 (https://github.com/hannibal002/SkyHanni/pull/2656) ## Version 0.26 diff --git a/docs/FEATURES.md b/docs/FEATURES.md index 0783d9e09f82..24c8e437252f 100644 --- a/docs/FEATURES.md +++ b/docs/FEATURES.md @@ -224,6 +224,10 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + Can be enabled/disabled on the Item Number list. + Item Pickup Log. - catgirlseraid (https://github.com/hannibal002/SkyHanni/pull/1937) + Display the price per Stonk when taking the minimum bid in the Stonks Auction (Richard Menu). - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/2195) ++ Added Ultimate Enchant Star. - Empa (https://github.com/hannibal002/SkyHanni/pull/2612) + + Shows a star on Enchanted Books with an Ultimate Enchant. ++ Added Focus Mode. - Thunderblade73 (https://github.com/hannibal002/SkyHanni/pull/2694) + + In Focus Mode, only the name of the item is displayed instead of the full description.
@@ -369,6 +373,12 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + Includes an option to warn you when to throw your rod. + Shows how weak the golden fish is, as a nametag. + Also works on Stranded. ++ Added an alert for Gold or Diamond Trophy Fish catches. - ReyMaratov (https://github.com/hannibal002/SkyHanni/pull/2615) + + Displays a popup with the trophy name, rarity, and amount of the catch. + + Optionally, also plays a sound. ++ Added Lava Replacement. - HiZe (https://github.com/hannibal002/SkyHanni/pull/1885) + + Replaces the lava texture with the water texture. + + Primarily used for lava fishing in the Crimson Isle, but can be used anywhere else if the option is enabled.
@@ -836,6 +846,10 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + Added Crafting Room Helper. - HiZe (https://github.com/hannibal002/SkyHanni/pull/2178) + Shows a holographic mob at the location where the mob is present in the real room inside the Mirrorverse in Rift. + Added Rift Time Real-Time Nametag Format. - Empa (https://github.com/hannibal002/SkyHanni/pull/2015) ++ Added a helper for tracking the Buttons Enigma Soul in the Rift. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2616) + + Using pathfinding to guide the player to the nearest spot with unpressed buttons and highlights them. ++ Added a route helper for Gunther's Rift Race in the West Village. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2616) ++ Added the ability to mute Wilted Berberis sounds when not farming. - MTOnline (https://github.com/hannibal002/SkyHanni/pull/2616)
@@ -900,6 +914,9 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + Added a "Get from Sack" button in the forge recipe menu to retrieve ingredients. - minhperry (https://github.com/hannibal002/SkyHanni/pull/2106) + Added Tracker for Glacite Corpses. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2306) + Tracks overall loot and loot per type. ++ 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)
@@ -996,6 +1013,9 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + Abi = Dark Green. + Added a toggle to highlight found rabbits in Hoppity's Collection menu. - the1divider (https://github.com/hannibal002/SkyHanni/pull/2438) + Added the ability to change the color of missing rabbit dyes in Hoppity's Collection to reflect rabbit rarity. - Daveed (https://github.com/hannibal002/SkyHanni/pull/2522) ++ 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. ### The Carnival diff --git a/pull_request_template.md b/pull_request_template.md index 2dd04bcec865..02769a0f8470 100644 --- a/pull_request_template.md +++ b/pull_request_template.md @@ -1,4 +1,6 @@ - + + ## Dependencies - pr_number_or_link_here @@ -21,7 +25,7 @@ Describe what this pull request does, including technical details, screenshots, ## Changelog New Features + Cool new feature. - your_name_here - * extra info + * Extra info. ## Changelog Improvements + Improved cool feature. - your_name_here diff --git a/root.gradle.kts b/root.gradle.kts index 01039394234d..f97425b88a97 100644 --- a/root.gradle.kts +++ b/root.gradle.kts @@ -14,7 +14,7 @@ plugins { allprojects { group = "at.hannibal2.skyhanni" - version = "0.27.Beta.12" + version = "0.28.Beta.2" repositories { mavenCentral() mavenLocal() @@ -25,7 +25,8 @@ allprojects { } 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) + maven("https://jitpack.io") { + // NotEnoughUpdates (compiled against) content { includeGroupByRegex("(com|io)\\.github\\..*") } @@ -42,8 +43,9 @@ preprocess { ProjectTarget.activeVersions().forEach { target -> nodes[target] = createNode(target.projectName, target.minecraftVersion.versionNumber, target.mappingStyle.identifier) val p = project(target.projectPath) - if (target.isForge) + if (target.isForge) { p.extra.set("loom.platform", "forge") + } } ProjectTarget.activeVersions().forEach { child -> val parent = child.linkTo ?: return@forEach diff --git a/src/main/java/at/hannibal2/skyhanni/api/DataWatcherAPI.kt b/src/main/java/at/hannibal2/skyhanni/api/DataWatcherAPI.kt index 94931dd8caf8..e7e7fd2b5ac3 100644 --- a/src/main/java/at/hannibal2/skyhanni/api/DataWatcherAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/api/DataWatcherAPI.kt @@ -8,7 +8,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @SkyHanniModule object DataWatcherAPI { - private val DATA_VALUE_CUSTOM_NAME = 2 + private const val DATA_VALUE_CUSTOM_NAME = 2 @SubscribeEvent fun onDataWatcherUpdate(event: DataWatcherUpdatedEvent) { diff --git a/src/main/java/at/hannibal2/skyhanni/api/GetFromSackAPI.kt b/src/main/java/at/hannibal2/skyhanni/api/GetFromSackAPI.kt index 89ccfd656f07..4d7662b4f452 100644 --- a/src/main/java/at/hannibal2/skyhanni/api/GetFromSackAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/api/GetFromSackAPI.kt @@ -163,7 +163,7 @@ object GetFromSackAPI { } private fun bazaarMessage(item: String, amount: Int, isRemaining: Boolean = false) = ChatUtils.clickableChat( - "§lCLICK §r§eto get the ${if (isRemaining) "remaining " else ""}§ax${amount} §9$item §efrom bazaar", + "§lCLICK §r§eto get the ${if (isRemaining) "remaining " else ""}§ax$amount §9$item §efrom bazaar", onClick = { HypixelCommands.bazaar(item.removeColor()) }, "§eClick to find on the bazaar!", ) @@ -182,7 +182,7 @@ object GetFromSackAPI { if (!amountString.isDouble()) return CommandResult.WRONG_AMOUNT to null val itemString = arguments.dropLast(1).joinToString(" ").uppercase().replace(':', '-') - val replacedString = itemString.replace("_"," ") + val replacedString = itemString.replace("_", " ") val item = when { SackAPI.sackListInternalNames.contains(itemString) -> itemString.asInternalName() diff --git a/src/main/java/at/hannibal2/skyhanni/api/HotmAPI.kt b/src/main/java/at/hannibal2/skyhanni/api/HotmAPI.kt index 6217c56c21d0..f2b2756554a3 100644 --- a/src/main/java/at/hannibal2/skyhanni/api/HotmAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/api/HotmAPI.kt @@ -74,7 +74,7 @@ object HotmAPI { /** Use when new powder gets collected*/ fun gain(difference: Long) { - ChatUtils.debug("Gained §a${difference.addSeparators()} §e${displayName} Powder") + ChatUtils.debug("Gained §a${difference.addSeparators()} §e$displayName Powder") addTotal(difference) addCurrent(difference) PowderGainEvent(this, difference).post() diff --git a/src/main/java/at/hannibal2/skyhanni/api/SkillAPI.kt b/src/main/java/at/hannibal2/skyhanni/api/SkillAPI.kt index b40255449226..ba8e42d66ee5 100644 --- a/src/main/java/at/hannibal2/skyhanni/api/SkillAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/api/SkillAPI.kt @@ -392,7 +392,7 @@ object SkillAPI { ChatUtils.chat("§bSkill Custom Goal Level") val map = storage?.filter { it.value.customGoalLevel != 0 } ?: return if (map.isEmpty()) { - ChatUtils.chat("§cYou haven't set any custom goals yet!") + ChatUtils.userError("You haven't set any custom goals yet!") } map.forEach { (skill, data) -> ChatUtils.chat("§e${skill.displayName}: §b${data.customGoalLevel}") @@ -486,7 +486,8 @@ object SkillAPI { 1 -> listOf("levelwithxp", "xpforlevel", "goal") 2 -> if (strings[0].lowercase() == "goal") CommandBase.getListOfStringsMatchingLastWord( strings, - SkillType.entries.map { it.displayName }) + SkillType.entries.map { it.displayName } + ) else listOf() @@ -502,7 +503,8 @@ object SkillAPI { "§6/shskills goal - §bView your current goal", "§6/shskills goal - §bDefine your goal for ", "", - ).joinToString("\n"), prefix = false + ).joinToString("\n"), + prefix = false ) } diff --git a/src/main/java/at/hannibal2/skyhanni/api/event/EventHandler.kt b/src/main/java/at/hannibal2/skyhanni/api/event/EventHandler.kt index 4b4c008523e2..63d3e14cfb21 100644 --- a/src/main/java/at/hannibal2/skyhanni/api/event/EventHandler.kt +++ b/src/main/java/at/hannibal2/skyhanni/api/event/EventHandler.kt @@ -6,78 +6,27 @@ import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.inAnyIsland +import at.hannibal2.skyhanni.utils.StringUtils import at.hannibal2.skyhanni.utils.chat.Text -import java.lang.invoke.LambdaMetafactory -import java.lang.invoke.MethodHandles -import java.lang.invoke.MethodType -import java.lang.reflect.Method -import java.lang.reflect.ParameterizedType -import java.util.function.Consumer -class EventHandler private constructor(val name: String, private val isGeneric: Boolean) { - - private val listeners: MutableList = mutableListOf() - - private var isFrozen = false - private var canReceiveCancelled = false +class EventHandler private constructor( + val name: String, + private val listeners: List, + private val canReceiveCancelled: Boolean, +) { var invokeCount: Long = 0L private set - constructor(event: Class) : this( + constructor(event: Class, listeners: List) : this( (event.name.split(".").lastOrNull() ?: event.name).replace("$", "."), - GenericSkyHanniEvent::class.java.isAssignableFrom(event) + listeners.sortedBy { it.options.priority }.toList(), + listeners.any { it.options.receiveCancelled } ) - fun addListener(method: Method, instance: Any, options: HandleEvent) { - if (isFrozen) throw IllegalStateException("Cannot add listener to frozen event handler") - val generic: Class<*>? = if (isGeneric) { - method.genericParameterTypes - .firstNotNullOfOrNull { it as? ParameterizedType } - ?.let { it.actualTypeArguments.firstOrNull() as? Class<*> } - ?: throw IllegalArgumentException("Generic event handler must have a generic type") - } else { - null - } - val name = "${method.declaringClass.name}.${method.name}${ - method.parameterTypes.joinTo( - StringBuilder(), - prefix = "(", - postfix = ")", - separator = ", ", - transform = Class<*>::getTypeName - ) - }" - listeners.add(Listener(name, createEventConsumer(name, instance, method), options, generic)) - } - - @Suppress("UNCHECKED_CAST") - private fun createEventConsumer(name: String, instance: Any, method: Method): Consumer { - try { - val handle = MethodHandles.lookup().unreflect(method) - return LambdaMetafactory.metafactory( - MethodHandles.lookup(), - "accept", - MethodType.methodType(Consumer::class.java, instance::class.java), - MethodType.methodType(Nothing::class.javaPrimitiveType, Object::class.java), - handle, - MethodType.methodType(Nothing::class.javaPrimitiveType, method.parameterTypes[0]) - ).target.bindTo(instance).invokeExact() as Consumer - } catch (e: Throwable) { - throw IllegalArgumentException("Method $name is not a valid consumer", e) - } - } - - fun freeze() { - isFrozen = true - listeners.sortBy { it.options.priority } - canReceiveCancelled = listeners.any { it.options.receiveCancelled } - } - fun post(event: T, onError: ((Throwable) -> Unit)? = null): Boolean { invokeCount++ if (this.listeners.isEmpty()) return false - if (!isFrozen) error("Cannot invoke event on unfrozen event handler") if (SkyHanniEvents.isDisabledHandler(name)) return false @@ -91,7 +40,8 @@ class EventHandler private constructor(val name: String, priv errors++ if (errors <= 3) { val errorName = throwable::class.simpleName ?: "error" - val message = "Caught an $errorName in ${listener.name} at $name: ${throwable.message}" + val aOrAn = StringUtils.optionalAn(errorName) + val message = "Caught $aOrAn $errorName in ${listener.name} at $name: ${throwable.message}" ErrorManager.logErrorWithData(throwable, message, ignoreErrorCache = onError != null) } onError?.invoke(throwable) @@ -110,7 +60,7 @@ class EventHandler private constructor(val name: String, priv return event.isCancelled } - private fun shouldInvoke(event: SkyHanniEvent, listener: Listener): Boolean { + private fun shouldInvoke(event: SkyHanniEvent, listener: EventListeners.Listener): Boolean { if (SkyHanniEvents.isDisabledInvoker(listener.name)) return false if (listener.options.onlyOnSkyblock && !LorenzUtils.inSkyBlock) return false if (IslandType.ANY !in listener.onlyOnIslandTypes && !inAnyIsland(listener.onlyOnIslandTypes)) return false @@ -124,19 +74,4 @@ class EventHandler private constructor(val name: String, priv } return true } - - private class Listener( - val name: String, - val invoker: Consumer, - val options: HandleEvent, - val generic: Class<*>?, - ) { - val onlyOnIslandTypes: Set = getIslands(options) - - companion object { - private fun getIslands(options: HandleEvent): Set = - if (options.onlyOnIslands.isEmpty()) setOf(options.onlyOnIsland) - else options.onlyOnIslands.toSet() - } - } } diff --git a/src/main/java/at/hannibal2/skyhanni/api/event/EventListeners.kt b/src/main/java/at/hannibal2/skyhanni/api/event/EventListeners.kt new file mode 100644 index 000000000000..ce8194ebc5f3 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/api/event/EventListeners.kt @@ -0,0 +1,78 @@ +package at.hannibal2.skyhanni.api.event + +import at.hannibal2.skyhanni.data.IslandType +import java.lang.invoke.LambdaMetafactory +import java.lang.invoke.MethodHandles +import java.lang.invoke.MethodType +import java.lang.reflect.Method +import java.lang.reflect.ParameterizedType +import java.util.function.Consumer + +class EventListeners private constructor(val name: String, private val isGeneric: Boolean) { + + private val listeners: MutableList = mutableListOf() + + constructor(event: Class<*>) : this( + (event.name.split(".").lastOrNull() ?: event.name).replace("$", "."), + GenericSkyHanniEvent::class.java.isAssignableFrom(event) + ) + + fun addListener(method: Method, instance: Any, options: HandleEvent) { + val generic: Class<*>? = if (isGeneric) { + method.genericParameterTypes + .firstNotNullOfOrNull { it as? ParameterizedType } + ?.let { it.actualTypeArguments.firstOrNull() as? Class<*> } + ?: throw IllegalArgumentException("Generic event handler must have a generic type") + } else { + null + } + val name = "${method.declaringClass.name}.${method.name}${ + method.parameterTypes.joinTo( + StringBuilder(), + prefix = "(", + postfix = ")", + separator = ", ", + transform = Class<*>::getTypeName + ) + }" + listeners.add(Listener(name, createEventConsumer(name, instance, method), options, generic)) + } + + /** + * Creates a consumer using LambdaMetafactory, this is the most efficient way to reflectively call + * a method from within code. + */ + @Suppress("UNCHECKED_CAST") + private fun createEventConsumer(name: String, instance: Any, method: Method): Consumer { + try { + val handle = MethodHandles.lookup().unreflect(method) + return LambdaMetafactory.metafactory( + MethodHandles.lookup(), + "accept", + MethodType.methodType(Consumer::class.java, instance::class.java), + MethodType.methodType(Nothing::class.javaPrimitiveType, Object::class.java), + handle, + MethodType.methodType(Nothing::class.javaPrimitiveType, method.parameterTypes[0]) + ).target.bindTo(instance).invokeExact() as Consumer + } catch (e: Throwable) { + throw IllegalArgumentException("Method $name is not a valid consumer", e) + } + } + + fun getListeners(): List = listeners + + class Listener( + val name: String, + val invoker: Consumer, + val options: HandleEvent, + val generic: Class<*>?, + ) { + val onlyOnIslandTypes: Set = getIslands(options) + + companion object { + private fun getIslands(options: HandleEvent): Set = + if (options.onlyOnIslands.isEmpty()) setOf(options.onlyOnIsland) + else options.onlyOnIslands.toSet() + } + } +} 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 e3dff201485b..ace86b224de4 100644 --- a/src/main/java/at/hannibal2/skyhanni/api/event/SkyHanniEvents.kt +++ b/src/main/java/at/hannibal2/skyhanni/api/event/SkyHanniEvents.kt @@ -11,6 +11,7 @@ import java.lang.reflect.Method @SkyHanniModule object SkyHanniEvents { + private val listeners: MutableMap, EventListeners> = mutableMapOf() private val handlers: MutableMap, EventHandler<*>> = mutableMapOf() private var disabledHandlers = emptySet() private var disabledHandlerInvokers = emptySet() @@ -21,12 +22,14 @@ object SkyHanniEvents { registerMethod(it, instance) } } - handlers.values.forEach { it.freeze() } } @Suppress("UNCHECKED_CAST") fun getEventHandler(event: Class): EventHandler = handlers.getOrPut(event) { - EventHandler(event) + EventHandler( + event, + getEventClasses(event).mapNotNull { listeners[it] }.flatMap(EventListeners::getListeners) + ) } as EventHandler fun isDisabledHandler(handler: String): Boolean = handler in disabledHandlers @@ -38,8 +41,8 @@ object SkyHanniEvents { val options = method.getAnnotation(HandleEvent::class.java) ?: return val event = method.parameterTypes[0] if (!SkyHanniEvent::class.java.isAssignableFrom(event)) return - val handler = getEventHandler(event as Class) - handler.addListener(method, instance, options) + listeners.getOrPut(event as Class) { EventListeners(event) } + .addListener(method, instance, options) } @SubscribeEvent @@ -61,4 +64,23 @@ object SkyHanniEvents { } } } + + /** + * Returns a list of all super classes and the class itself up to [SkyHanniEvent]. + */ + private fun getEventClasses(clazz: Class<*>): List> { + val classes = mutableListOf>() + classes.add(clazz) + + var current = clazz + while (current.superclass != null) { + val superClass = current.superclass + if (superClass == SkyHanniEvent::class.java) break + if (superClass == GenericSkyHanniEvent::class.java) break + if (superClass == CancellableSkyHanniEvent::class.java) break + classes.add(superClass) + current = superClass + } + return classes + } } diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigGuiForgeInterop.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigGuiForgeInterop.kt index 0c112d73a307..3f2d398368d6 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/ConfigGuiForgeInterop.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/ConfigGuiForgeInterop.kt @@ -12,6 +12,7 @@ import java.io.IOException @Suppress("unused") class ConfigGuiForgeInterop : IModGuiFactory { + @Suppress("EmptyFunctionBlock") override fun initialize(minecraft: Minecraft) {} override fun mainConfigGuiClass() = WrappedSkyHanniConfig::class.java diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt index bf0f2ba0a4a4..b00fc7a8f749 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/ConfigManager.kt @@ -66,7 +66,8 @@ class ConfigManager { private fun setConfigHolder(type: ConfigFileType, value: Any) { require(value.javaClass == type.clazz) - @Suppress("UNCHECKED_CAST") (type.property as KMutableProperty0).set(value) + @Suppress("UNCHECKED_CAST") + (type.property as KMutableProperty0).set(value) (jsonHolder as MutableMap)[type] = value } @@ -182,7 +183,7 @@ class ConfigManager { try { run() } catch (e: Throwable) { - e.printStackTrace() + logger.log(e.stackTraceToString()) LorenzUtils.shutdownMinecraft("Config is corrupt inside development environment.") } } else { @@ -194,7 +195,7 @@ class ConfigManager { logger.log("Loaded $fileName from file") } catch (e: Exception) { - e.printStackTrace() + logger.log(e.stackTraceToString()) val backupFile = file.resolveSibling("$fileName-${SimpleTimeMark.now().toMillis()}-backup.json") logger.log("Exception while reading $file. Will load blank $fileName and save backup to $backupFile") logger.log("Exception was $e") @@ -202,7 +203,7 @@ class ConfigManager { file.copyTo(backupFile) } catch (e: Exception) { logger.log("Could not create backup for $fileName file") - e.printStackTrace() + logger.log(e.stackTraceToString()) } } } @@ -239,7 +240,7 @@ class ConfigManager { move(unit, file, reason) } catch (e: IOException) { logger.log("Could not save $fileName file to $file") - e.printStackTrace() + logger.log(e.stackTraceToString()) } } diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt index b9f21ca2255c..c9ae8c2c7e89 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 = 59 + const val CONFIG_VERSION = 61 fun JsonElement.at(chain: List, init: Boolean): JsonElement? { if (chain.isEmpty()) return this if (this !is JsonObject) return null @@ -120,21 +120,27 @@ object ConfigUpdaterMigrator { logger.log("Starting config transformation from $i to ${i + 1}") val storage = accumulator["storage"]?.asJsonObject val dynamicPrefix: Map> = mapOf( - "#profile" to - (storage?.get("players")?.asJsonObject?.entrySet() + "#profile" to ( + storage?.get("players")?.asJsonObject?.entrySet() ?.flatMap { player -> player.value.asJsonObject["profiles"]?.asJsonObject?.entrySet()?.map { "storage.players.${player.key}.profiles.${it.key}" } ?: listOf() } - ?: listOf()), - "#player" to - (storage?.get("players")?.asJsonObject?.entrySet()?.map { "storage.players.${it.key}" } - ?: listOf()), + ?: listOf() + ), + "#player" to ( + storage?.get("players")?.asJsonObject?.entrySet()?.map { "storage.players.${it.key}" } + ?: listOf() + ), ) - val migration = ConfigFixEvent(accumulator, JsonObject().also { - it.add("lastVersion", JsonPrimitive(i + 1)) - }, i, 0, dynamicPrefix).also { it.postAndCatch() } + val migration = ConfigFixEvent( + accumulator, + JsonObject().also { + it.add("lastVersion", JsonPrimitive(i + 1)) + }, + i, 0, dynamicPrefix + ).also { it.postAndCatch() } logger.log("Transformations scheduled: ${migration.new}") val mergesPerformed = merge(migration.old, migration.new) logger.log("Migration done with $mergesPerformed merges and ${migration.movesPerformed} moves performed") 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 9f2e3cc3fd71..bd94a16587f1 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt @@ -186,6 +186,7 @@ object Commands { registerCommand("shnavigate", "Using path finder to go to locatons") { NavigationHelper.onCommand(it) } } + @Suppress("LongMethod") private fun usersNormal() { registerCommand( "shmarkplayer", @@ -251,12 +252,12 @@ object Commands { ) { FarmingWeightDisplay.lookUpCommand(it) } registerCommand( "shcopytranslation", - "Copy the English translation of a message in another language to the clipboard.\n" + "Uses a 2 letter language code that can be found at the end of a translation message.", - ) { Translator.fromEnglish(it) } + "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 English.", - ) { Translator.toEnglish(it) } + "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)", @@ -502,10 +503,13 @@ object Commands { ) { ScoreboardData.toggleMonitor() } } + @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("shtestrabbitpaths", "Tests pathfinding to rabbit eggs. Use a number 0-14.") { + HoppityEggLocator.testPathfind(it) + } registerCommand( "shtestitem", "test item internal name resolving", @@ -615,6 +619,10 @@ object Commands { "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() { diff --git a/src/main/java/at/hannibal2/skyhanni/config/core/config/gui/GuiPositionEditor.kt b/src/main/java/at/hannibal2/skyhanni/config/core/config/gui/GuiPositionEditor.kt index ba3a576754dc..0adf1bed5e56 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/core/config/gui/GuiPositionEditor.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/core/config/gui/GuiPositionEditor.kt @@ -57,7 +57,7 @@ class GuiPositionEditor( } override fun drawScreen(mouseX: Int, mouseY: Int, partialTicks: Float) { - //Items aren't drawn due to a bug in neu rendering + // Items aren't drawn due to a bug in neu rendering drawDefaultBackground() if (oldScreen != null) { val accessor = oldScreen as AccessorGuiContainer diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/chat/PowderMiningFilterConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/chat/PowderMiningFilterConfig.java index 42a53f8dd3bf..cb1aae0e5e9c 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/chat/PowderMiningFilterConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/chat/PowderMiningFilterConfig.java @@ -111,7 +111,7 @@ public String toString() { @Expose @ConfigOption(name = "Gemstones", desc = "") @Accordion - // TODO remove config + // TODO rename to "gemstoneFilter" public PowderMiningGemstoneFilterConfig gemstoneFilterConfig = new PowderMiningGemstoneFilterConfig(); } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/chat/PowderMiningGemstoneFilterConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/chat/PowderMiningGemstoneFilterConfig.java index 3a44738ca6e8..e2b1c5d18143 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/chat/PowderMiningGemstoneFilterConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/chat/PowderMiningGemstoneFilterConfig.java @@ -42,6 +42,11 @@ public class PowderMiningGemstoneFilterConfig { @ConfigEditorDropdown public GemstoneFilterEntry topazGemstones = GemstoneFilterEntry.FINE_UP; + @Expose + @ConfigOption(name = "Jasper", desc = "Hide Jasper gemstones under a certain quality.") + @ConfigEditorDropdown + public GemstoneFilterEntry jasperGemstones = GemstoneFilterEntry.FINE_UP; + public enum GemstoneFilterEntry { SHOW_ALL("Show All"), HIDE_ALL("Hide all"), diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/chat/TranslatorConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/chat/TranslatorConfig.java index 648afbd8739c..fdd678d0b2dc 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/chat/TranslatorConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/chat/TranslatorConfig.java @@ -2,8 +2,10 @@ import at.hannibal2.skyhanni.config.FeatureToggle; import at.hannibal2.skyhanni.features.chat.translation.TranslatableLanguage; +import at.hannibal2.skyhanni.utils.OSUtils; 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.ConfigEditorDropdown; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorText; import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; @@ -14,7 +16,7 @@ public class TranslatorConfig { @Expose @ConfigOption( name = "Translate On Click", - desc = "Click on a message to translate it to English.\n" + + desc = "Click on a message to translate it to your language.\n" + "Use §e/shcopytranslation§7 to translate from English.\n" + "§cTranslation is not guaranteed to be 100% accurate." ) @@ -22,7 +24,7 @@ public class TranslatorConfig { @FeatureToggle public boolean translateOnClick = false; - @ConfigOption(name = "Language Name", desc = "The name of the language selected below. Note that languages marked as unknown might still be supported.") + @ConfigOption(name = "Your Language", desc = "The language that messages should be translated to.") @Expose @ConfigEditorDropdown public Property languageName = Property.of(TranslatableLanguage.ENGLISH); @@ -30,8 +32,18 @@ public class TranslatorConfig { @Expose @ConfigOption( name = "Language Code", - desc = "Enter a language code here to translate on chat click into another language. " + - "E.g. `es` for spanish or 'de' for german. Empty for english.") + desc = "If your language doesn't show in the dropdown, enter your language code here. " + + "E.g. 'es' for Spanish or 'de' for German. Empty will use English." + ) @ConfigEditorText public Property languageCode = Property.of("en"); + + @ConfigOption( + name = "List of Language Codes", + desc = "A list of Google Translate's suppored language codes." + ) + @ConfigEditorButton(buttonText = "Open") + public Runnable langCodesURL = () -> OSUtils.openBrowser( + "https://cloud.google.com/translate/docs/languages#try-it-for-yourself" + ); } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/chroma/ChromaConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/chroma/ChromaConfig.java index 6a02e2ed3061..b3f8577f0c0f 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/chroma/ChromaConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/chroma/ChromaConfig.java @@ -20,7 +20,7 @@ public class ChromaConfig { public boolean chromaPreview = false; @Expose - @ConfigOption(name = "Enabled", desc = "Toggle SkyHanni's chroma. §e(Disables Patcher's Optimized Font Renderer while enabled)") + @ConfigOption(name = "Enabled", desc = "Toggle SkyHanni's chroma.") @ConfigEditorBoolean @FeatureToggle public Property enabled = Property.of(false); @@ -80,7 +80,7 @@ public String toString() { public Runnable resetSettings = ChromaManager::resetChromaSettings; @Expose - @ConfigOption(name = "Everything Chroma", desc = "Render §4§l§oALL §r§7text in chroma. §e(Some enchants may appear white with SBA enchant parsing)") + @ConfigOption(name = "Everything Chroma", desc = "Render §4§l§oALL §r§7text in chroma. §e(Disables Patcher's Optimized Font Renderer while enabled)") @ConfigEditorBoolean public boolean allChroma = false; diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/combat/FerocityDisplayConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/combat/FerocityDisplayConfig.java index d212a4a0797b..605a31a2b4da 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/combat/FerocityDisplayConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/combat/FerocityDisplayConfig.java @@ -13,7 +13,7 @@ public class FerocityDisplayConfig { @ConfigOption( name = "Enabled", desc = "Show ferocity stat as single GUI element.\n" + - "§eRequires tab list widget enabled and ferocity selected to work." + "§eRequires tab list widget enabled and ferocity selected to update live." ) @ConfigEditorBoolean @FeatureToggle diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/commands/BetterWikiCommandConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/commands/BetterWikiCommandConfig.java index fc6d0be06fc2..df0468226e77 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/commands/BetterWikiCommandConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/commands/BetterWikiCommandConfig.java @@ -53,7 +53,7 @@ public class BetterWikiCommandConfig { public boolean menuOpenWiki = false; @Expose - @ConfigOption(name = "Fandom Wiki Key", desc = "Search for an item on Wiki with this keybind.\n" + + @ConfigOption(name = "Wiki Key", desc = "Search for an item's wiki page with this keybind.\n" + "§cFor an optimal experience, do §lNOT §cbind this to a mouse button.") @ConfigEditorKeybind(defaultKey = Keyboard.KEY_NONE) public int wikiKeybind = Keyboard.KEY_NONE; diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/commands/CommandsConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/commands/CommandsConfig.java index 854ed39cc38f..d8626e243b93 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/commands/CommandsConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/commands/CommandsConfig.java @@ -55,8 +55,7 @@ public class CommandsConfig { public boolean transferCooldown = false; @Expose - @ConfigOption(name = "Transfer Cooldown Ended Message", desc = "Sends a message in chat when the transfer cooldown ends.") + @ConfigOption(name = "Transfer Cooldown Message", desc = "Sends a message in chat when the transfer cooldown ends.") @ConfigEditorBoolean - @FeatureToggle public boolean transferCooldownMessage = false; } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/commands/TabCompleteConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/commands/TabCompleteConfig.java index 790224761e1e..388cec87da93 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/commands/TabCompleteConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/commands/TabCompleteConfig.java @@ -36,22 +36,22 @@ public class TabCompleteConfig { public boolean party = true; @Expose - @ConfigOption(name = "VIP Visits", desc = "Tab-complete the visit to special users with cake souls on it.") + @ConfigOption(name = "Guild", desc = "Tab-complete Guild Members.") @ConfigEditorBoolean @FeatureToggle - public boolean vipVisits = true; + public boolean guild = false; @Expose - @ConfigOption(name = "/gfs Sack", desc = "Tab-complete §e/gfs §7sack items.") + @ConfigOption(name = "VIP Visits", desc = "Tab-complete the visit to special users with cake souls on it.") @ConfigEditorBoolean @FeatureToggle - public boolean gfsSack = true; + public boolean vipVisits = true; @Expose - @ConfigOption(name = "Party Commands", desc = "Tab-complete commonly used party commands.") + @ConfigOption(name = "/gfs Sack", desc = "Tab-complete §e/gfs §7sack items.") @ConfigEditorBoolean @FeatureToggle - public boolean partyCommands = true; + public boolean gfsSack = true; @Expose @ConfigOption(name = "View Recipe", desc = "Tab-complete item IDs in the the Hypixel command §e/viewrecipe§7. Only items with recipes are tab completed.") 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 8bbaa962ca26..3fd83db69655 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 @@ -211,4 +211,15 @@ public String toString() { @ConfigEditorBoolean @FeatureToggle 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.") + @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; } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/fishing/FishingConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/fishing/FishingConfig.java index 759da0f0eb34..3cae9f2f569d 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/fishing/FishingConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/fishing/FishingConfig.java @@ -66,6 +66,11 @@ public class FishingConfig { @Accordion public SeaCreatureTrackerConfig seaCreatureTracker = new SeaCreatureTrackerConfig(); + @Expose + @ConfigOption(name = "Lava Replacement", desc = "") + @Accordion + public LavaReplacementConfig lavaReplacement = new LavaReplacementConfig(); + @Expose @ConfigOption( name = "Shark Fish Counter", diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/fishing/LavaReplacementConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/fishing/LavaReplacementConfig.java new file mode 100644 index 000000000000..e1cd4fd33c85 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/fishing/LavaReplacementConfig.java @@ -0,0 +1,23 @@ +package at.hannibal2.skyhanni.config.features.fishing; + +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.ConfigEditorButton; +import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; +import io.github.notenoughupdates.moulconfig.observer.Property; +import net.minecraft.client.Minecraft; + +public class LavaReplacementConfig { + + @Expose + @ConfigOption(name = "Enabled", desc = "Replace the lava texture with the water texture.") + @ConfigEditorBoolean + @FeatureToggle + public Property enabled = Property.of(false); + + @Expose + @ConfigOption(name = "Only In Crimson Isle", desc = "Enable the water texture only in Crimson Isle.") + @ConfigEditorBoolean + public Property onlyInCrimsonIsle = Property.of(true); +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/fishing/trophyfishing/ChatMessagesConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/fishing/trophyfishing/ChatMessagesConfig.java index 0fab8615645c..c5a4dc341307 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/fishing/trophyfishing/ChatMessagesConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/fishing/trophyfishing/ChatMessagesConfig.java @@ -82,4 +82,19 @@ public String toString() { @ConfigOption(name = "Silver Duplicates", desc = "Hide duplicate messages for silver Trophy Fishes from chat.") @ConfigEditorBoolean public boolean silverHider = false; + + @Expose + @ConfigOption(name = "Gold Alert", desc = "Send an alert upon catching a gold Trophy Fish.") + @ConfigEditorBoolean + public boolean goldAlert = false; + + @Expose + @ConfigOption(name = "Diamond Alert", desc = "Send an alert upon catching a diamond Trophy Fish.") + @ConfigEditorBoolean + public boolean diamondAlert = false; + + @Expose + @ConfigOption(name = "Play Sound Alert", desc = "Play a sound effect when rare trophy fishes are caught.") + @ConfigEditorBoolean + public boolean playSound = true; } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/FarmingLaneConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/FarmingLaneConfig.java index 667e3233109d..bb7ea595b94d 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/FarmingLaneConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/garden/laneswitch/FarmingLaneConfig.java @@ -2,13 +2,18 @@ import at.hannibal2.skyhanni.config.FeatureToggle; import at.hannibal2.skyhanni.config.core.config.Position; +import at.hannibal2.skyhanni.features.garden.CropType; import com.google.gson.annotations.Expose; import io.github.notenoughupdates.moulconfig.annotations.Accordion; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDraggableList; import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorInfoText; import io.github.notenoughupdates.moulconfig.annotations.ConfigLink; import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; +import java.util.ArrayList; +import java.util.List; + public class FarmingLaneConfig { @Expose @@ -37,4 +42,11 @@ public class FarmingLaneConfig { @FeatureToggle public boolean cornerWaypoints = false; + @Expose + @ConfigOption( + name = "Ignored Crops", + desc = "Add the crops you wish to not setup a lane for." + ) + @ConfigEditorDraggableList() + public List ignoredCrops = new ArrayList<>(); } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/garden/visitor/TimerConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/garden/visitor/TimerConfig.java index 32bff02debbe..a6b7e509e610 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/garden/visitor/TimerConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/garden/visitor/TimerConfig.java @@ -34,5 +34,6 @@ public class TimerConfig { @Expose @ConfigLink(owner = TimerConfig.class, field = "enabled") + // TODO rename to position public Position pos = new Position(-200, 40, false, true); } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/FocusModeConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/FocusModeConfig.java new file mode 100644 index 000000000000..3211354fec3d --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/FocusModeConfig.java @@ -0,0 +1,22 @@ +package at.hannibal2.skyhanni.config.features.inventory; + +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.ConfigEditorKeybind; +import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; +import org.lwjgl.input.Keyboard; + +public class FocusModeConfig { + + @Expose + @ConfigOption(name = "Enabled", desc = "In focus mode you only see the name of the item instead of the whole description.") + @ConfigEditorBoolean + @FeatureToggle + public boolean enabled = false; + + @Expose + @ConfigOption(name = "Toggle Key", desc = "Key to toggle the focus mode on and off.") + @ConfigEditorKeybind(defaultKey = Keyboard.KEY_NONE) + public int toggleKey = Keyboard.KEY_NONE; +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java index 1d24b15e32e9..6b49d7224f44 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java @@ -84,6 +84,11 @@ public class InventoryConfig { @Accordion public PersonalCompactorConfig personalCompactor = new PersonalCompactorConfig(); + @Expose + @ConfigOption(name = "Focus Mode", desc="") + @Accordion + public FocusModeConfig focusMode = new FocusModeConfig(); + @Expose @ConfigOption(name = "RNG Meter", desc = "") @Accordion @@ -231,6 +236,12 @@ public String toString() { @FeatureToggle public boolean itemStars = false; + @Expose + @ConfigOption(name = "Ultimate Enchant Star", desc = "Show a star on Enchanted Books with an Ultimate Enchant.") + @ConfigEditorBoolean + @FeatureToggle + public boolean ultimateEnchantStar = false; + @Expose @ConfigOption(name = "Missing Tasks", desc = "Highlight missing tasks in the SkyBlock Level Guide inventory.") // TODO move( , "inventory.highlightMissingSkyBlockLevelGuide", "inventory.skyblockGuideConfig.highlightMissingSkyBlockLevelGuide") diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentationTableConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentationTableConfig.java index dfdad248256e..0313498e6829 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentationTableConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/experimentationtable/ExperimentationTableConfig.java @@ -21,7 +21,7 @@ public class ExperimentationTableConfig { public ExperimentsDryStreakConfig dryStreak = new ExperimentsDryStreakConfig(); @Expose - @ConfigOption(name = "Superpair Data", desc = "Shows a display with useful information while doing the Superpair experiment.") + @ConfigOption(name = "Superpair Data", desc = "Displays useful data while doing the Superpair experiment.") @ConfigEditorBoolean @FeatureToggle public boolean superpairDisplay = false; diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/mining/CrystalHighlighterConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/mining/CrystalHighlighterConfig.java new file mode 100644 index 000000000000..06c60b507024 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/mining/CrystalHighlighterConfig.java @@ -0,0 +1,35 @@ +package at.hannibal2.skyhanni.config.features.mining; + +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 CrystalHighlighterConfig { + + @Expose + @ConfigOption( + name = "Highlight Crystal Nucleus barriers", + desc = "Draw visible bounding boxes around the Crystal Nucleus crystal barrier blocks." + ) + @ConfigEditorBoolean + @FeatureToggle + public boolean enabled = true; + + @Expose + @ConfigOption( + name = "Highlight Opacity", + desc = "Set the opacity of the highlighted boxes.\n§70§8: §7Transparent\n§7100§8: §7Solid" + ) + @ConfigEditorSlider(minValue = 0, maxValue = 100, minStep = 1) + public int opacity = 60; + + @Expose + @ConfigOption( + name = "Only Show During Hoppity's", + desc = "Only show the highlighted boxes during Hoppity's Hunt." + ) + @ConfigEditorBoolean + public boolean onlyDuringHoppity = false; +} 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 08c8ec894a71..f6a5a83baca6 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 @@ -73,6 +73,11 @@ public class MiningConfig { @Accordion public MineshaftPityDisplayConfig mineshaftPityDisplay = new MineshaftPityDisplayConfig(); + @Expose + @ConfigOption(name = "Crystal Nucleus Crystal Highlights", desc = "") + @Accordion + public CrystalHighlighterConfig crystalHighlighter = new CrystalHighlighterConfig(); + @Expose @ConfigOption(name = "Highlight Commission Mobs", desc = "Highlight mobs that are part of active commissions.") @ConfigEditorBoolean @@ -96,4 +101,10 @@ public class MiningConfig { @ConfigEditorBoolean @FeatureToggle public boolean highlightYourGoldenGoblin = true; + + @Expose + @ConfigOption(name = "Precision Mining Helper", desc = "Draws a box over the Precision Mining particles.") + @ConfigEditorBoolean + @FeatureToggle + public boolean highlightPrecisionMiningParticles = false; } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/mining/PowderTrackerConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/mining/PowderTrackerConfig.java index 1c32cabc2e95..247da9b546d3 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/mining/PowderTrackerConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/mining/PowderTrackerConfig.java @@ -24,7 +24,6 @@ import static at.hannibal2.skyhanni.config.features.mining.PowderTrackerConfig.PowderDisplayEntry.GOLD_ESSENCE; import static at.hannibal2.skyhanni.config.features.mining.PowderTrackerConfig.PowderDisplayEntry.HARD_STONE; import static at.hannibal2.skyhanni.config.features.mining.PowderTrackerConfig.PowderDisplayEntry.JADE; -import static at.hannibal2.skyhanni.config.features.mining.PowderTrackerConfig.PowderDisplayEntry.MITHRIL_POWDER; import static at.hannibal2.skyhanni.config.features.mining.PowderTrackerConfig.PowderDisplayEntry.ROBOTRON; import static at.hannibal2.skyhanni.config.features.mining.PowderTrackerConfig.PowderDisplayEntry.RUBY; import static at.hannibal2.skyhanni.config.features.mining.PowderTrackerConfig.PowderDisplayEntry.SAPPHIRE; @@ -56,7 +55,6 @@ public class PowderTrackerConfig { public Property> textFormat = Property.of(new ArrayList<>(Arrays.asList( TOTAL_CHESTS, DOUBLE_POWDER, - MITHRIL_POWDER, GEMSTONE_POWDER, SPACER_1, DIAMOND_ESSENCE, @@ -78,7 +76,6 @@ public class PowderTrackerConfig { public enum PowderDisplayEntry implements HasLegacyId { TOTAL_CHESTS("§d852 Total chests Picked §7(950/h)", 2), DOUBLE_POWDER("§bx2 Powder: §aActive!", 3), - MITHRIL_POWDER("§b250,420 §aMithril Powder §7(350,000/h)", 4), GEMSTONE_POWDER("§b250,420 §dGemstone Powder §7(350,000/h)", 5), SPACER_1("", 6), DIAMOND_ESSENCE("§b129 §bDiamond Essence §7(600/h)", 7), diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/misc/EstimatedItemValueConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/misc/EstimatedItemValueConfig.java index 3f5874ac0941..2bdae5c59290 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/misc/EstimatedItemValueConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/misc/EstimatedItemValueConfig.java @@ -106,5 +106,6 @@ public String toString() { @Expose @ConfigLink(owner = EstimatedItemValueConfig.class, field = "enabled") + // TODO rename "position" public Position itemPriceDataPos = new Position(140, 90, false, true); } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java index 9d503c3986be..0869262959c0 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java @@ -15,6 +15,7 @@ import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDraggableList; import io.github.notenoughupdates.moulconfig.annotations.ConfigLink; import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; +import io.github.notenoughupdates.moulconfig.annotations.SearchTag; import io.github.notenoughupdates.moulconfig.observer.Property; import java.util.ArrayList; @@ -226,6 +227,7 @@ public class MiscConfig { @Expose @ConfigOption(name = "Account Upgrade Reminder", desc = "Remind you to claim community shop account and profile upgrades when complete.") @ConfigEditorBoolean + @SearchTag("Elizabeth Community Center") @FeatureToggle public boolean accountUpgradeReminder = true; @@ -334,4 +336,13 @@ public class MiscConfig { @ConfigEditorBoolean @FeatureToggle public boolean userluckEnabled = true; + + @Expose + @ConfigOption(name = "Computer Time Offset Warning", + desc = "Sends a Chat Warning if your computer time is not synchronized with the actual time.\n" + + "§cMaking sure your computer time is correct is important for SkyHanni to display times correctly." + ) + @ConfigEditorBoolean + @FeatureToggle + public boolean warnAboutPcTimeOffset = true; } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/rift/EnigmaSoulConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/rift/EnigmaSoulConfig.java index f64a42506043..69a87bd31660 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/rift/EnigmaSoulConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/rift/EnigmaSoulConfig.java @@ -32,4 +32,9 @@ public class EnigmaSoulConfig { @ConfigOption(name = "Color", desc = "Color of the Enigma Souls.") @ConfigEditorColour public String color = "0:245:219:27:198"; + + @Expose + @ConfigOption(name = "Buttons Helper", desc = "Help find all 56 wooden buttons required for the Buttons soul when tracking it.") + @ConfigEditorBoolean + public boolean showButtonsHelper = true; } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/rift/area/dreadfarm/WiltedBerberisConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/rift/area/dreadfarm/WiltedBerberisConfig.java index eddcb740d96d..2aa89f66ea6d 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/rift/area/dreadfarm/WiltedBerberisConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/rift/area/dreadfarm/WiltedBerberisConfig.java @@ -21,7 +21,10 @@ public class WiltedBerberisConfig { @Expose @ConfigOption(name = "Hide Particles", desc = "Hide the Wilted Berberis particles.") @ConfigEditorBoolean - // TODO fix typo - public boolean hideparticles = false; + public boolean hideParticles = false; + @Expose + @ConfigOption(name = "Mute Others Sounds", desc = "Mute nearby Wilted Berberis sounds while not holding a Wand of Farming or not standing on Farmland blocks.") + @ConfigEditorBoolean + public boolean muteOthersSounds = true; } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/rift/area/livingcave/LivingCaveLivingMetalConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/rift/area/livingcave/LivingCaveLivingMetalConfig.java index 38f60870f5ac..4053070e3375 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/rift/area/livingcave/LivingCaveLivingMetalConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/rift/area/livingcave/LivingCaveLivingMetalConfig.java @@ -3,7 +3,9 @@ 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.ConfigEditorColour; import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; +import io.github.notenoughupdates.moulconfig.observer.Property; public class LivingCaveLivingMetalConfig { @@ -19,4 +21,9 @@ public class LivingCaveLivingMetalConfig { @FeatureToggle public boolean hideParticles = false; + @Expose + @ConfigOption(name = "Color", desc = "Set the color to highlight the blocks in.") + @ConfigEditorColour + public Property color = Property.of("0:255:85:255:255"); + } diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/rift/area/westvillage/GunthersRaceConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/rift/area/westvillage/GunthersRaceConfig.java new file mode 100644 index 000000000000..10d18fa85c05 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/rift/area/westvillage/GunthersRaceConfig.java @@ -0,0 +1,39 @@ +package at.hannibal2.skyhanni.config.features.rift.area.westvillage; + +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.ConfigEditorColour; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorSlider; +import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; +import io.github.notenoughupdates.moulconfig.observer.Property; + +public class GunthersRaceConfig { + + @Expose + @ConfigOption(name = "Enabled", desc = "Show the route for Gunther's rift race.") + @ConfigEditorBoolean + @FeatureToggle + public boolean enabled = true; + + @Expose + @ConfigOption(name = "Look Ahead", desc = "Change how many waypoints should be shown in front of you.") + @ConfigEditorSlider(minStep = 1, maxValue = 30, minValue = 1) + public Property lookAhead = Property.of(3); + + @Expose + @ConfigOption(name = "Rainbow Color", desc = "Show the rainbow color effect instead of a boring monochrome.") + @ConfigEditorBoolean + public Property rainbowColor = Property.of(true); + + @Expose + @ConfigOption(name = "Monochrome Color", desc = "Set a boring monochrome color for the guide waypoints.") + @ConfigEditorColour + public Property monochromeColor = Property.of("0:60:0:0:255"); + + @Expose + @ConfigOption(name = "Hide Other Players", desc = "Hide other players while in the race.") + @ConfigEditorBoolean + @FeatureToggle + public boolean hidePlayers = false; +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/rift/area/westvillage/WestVillageConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/rift/area/westvillage/WestVillageConfig.java index 5dbf1a231eff..fa6db52144b4 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/rift/area/westvillage/WestVillageConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/rift/area/westvillage/WestVillageConfig.java @@ -6,11 +6,6 @@ public class WestVillageConfig { - @ConfigOption(name = "Kloon Hacking", desc = "") - @Accordion - @Expose - public KloonHackingConfig hacking = new KloonHackingConfig(); - @ConfigOption(name = "Vermin Tracker", desc = "Track all vermins collected.") @Accordion @Expose @@ -20,4 +15,14 @@ public class WestVillageConfig { @Accordion @Expose public VerminHighlightConfig verminHighlight = new VerminHighlightConfig(); + + @ConfigOption(name = "Gunther's Race", desc = "") + @Accordion + @Expose + public GunthersRaceConfig gunthersRace = new GunthersRaceConfig(); + + @ConfigOption(name = "Kloon Hacking", desc = "") + @Accordion + @Expose + public KloonHackingConfig hacking = new KloonHackingConfig(); } diff --git a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java index 754eea3bba59..4ad2c8eb300a 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java +++ b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java @@ -6,6 +6,7 @@ import at.hannibal2.skyhanni.data.MaxwellAPI; import at.hannibal2.skyhanni.data.jsonobjects.local.HotmTree; import at.hannibal2.skyhanni.data.model.ComposterUpgrade; +import at.hannibal2.skyhanni.data.model.SkyblockStat; import at.hannibal2.skyhanni.features.combat.endernodetracker.EnderNodeTracker; import at.hannibal2.skyhanni.features.combat.ghostcounter.GhostData; import at.hannibal2.skyhanni.features.dungeon.CroesusChestTracker; @@ -102,6 +103,9 @@ public static class ChocolateFactoryStorage { @Expose public long currentChocolate = 0; + @Expose + public long maxChocolate = 0; + @Expose public long chocolateThisPrestige = 0; @@ -200,6 +204,9 @@ public static class CarnivalStorage { public Map goals = new HashMap<>(); } + @Expose + public Map stats = new HashMap<>(SkyblockStat.getEntries().size()); + @Expose public MaxwellPowerStorage maxwell = new MaxwellPowerStorage(); diff --git a/src/main/java/at/hannibal2/skyhanni/data/EntityMovementData.kt b/src/main/java/at/hannibal2/skyhanni/data/EntityMovementData.kt index 92a36b62363d..d38b6824b864 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/EntityMovementData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/EntityMovementData.kt @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.data 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 @@ -8,22 +9,36 @@ import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.DelayedRun import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland import at.hannibal2.skyhanni.utils.LorenzVec import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.getLorenzVec import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import net.minecraft.client.Minecraft import net.minecraft.entity.Entity import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.seconds @SkyHanniModule object EntityMovementData { private val warpingPattern by RepoPattern.pattern( "data.entity.warping", - "§7(?:Warping|Warping you to your SkyBlock island|Warping using transfer token|Finding player|Sending a visit request)\\.\\.\\." + "§7(?:Warping|Warping you to your SkyBlock island|Warping using transfer token|Finding player|Sending a visit request)\\.\\.\\.", ) + private var nextTeleport: OnNextTeleport? = null + + fun onNextTeleport(island: IslandType, action: () -> Unit) { + nextTeleport = OnNextTeleport(island, action) + } + + class OnNextTeleport(val island: IslandType, val action: () -> Unit) { + val startTime: SimpleTimeMark = SimpleTimeMark.now() + } + private val entityLocation = mutableMapOf() fun addToTrack(entity: Entity) { @@ -32,6 +47,40 @@ object EntityMovementData { } } + @SubscribeEvent + fun onIslandChange(event: IslandChangeEvent) { + val nextData = nextTeleport ?: return + if (nextData.island != event.newIsland) return + val passedSince = nextData.startTime.passedSince() + if (passedSince > 5.seconds) { + nextTeleport = null + return + } + + DelayedRun.runDelayed(100.milliseconds) { + nextData.action() + } + nextTeleport = null + } + + @SubscribeEvent + fun onPlayerMove(event: EntityMoveEvent) { + if (!LorenzUtils.inSkyBlock || event.entity != Minecraft.getMinecraft().thePlayer) return + + val nextData = nextTeleport ?: return + + val passedSince = nextData.startTime.passedSince() + if (passedSince > 5.seconds) { + nextTeleport = null + return + } + if (passedSince > 50.milliseconds && nextData.island.isInIsland()) { + nextData.action() + nextTeleport = null + return + } + } + @SubscribeEvent fun onTick(event: LorenzTickEvent) { if (!LorenzUtils.inSkyBlock) return diff --git a/src/main/java/at/hannibal2/skyhanni/data/GuildAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/GuildAPI.kt index 541eb323cf8f..1e98b61e424a 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/GuildAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/GuildAPI.kt @@ -38,7 +38,7 @@ object GuildAPI { } } - fun isInGuild(name: String) = ProfileStorageData.playerSpecific?.guildMembers?.let { - name in it - } ?: false + fun isInGuild(name: String) = name in getAllMembers() + + fun getAllMembers() = ProfileStorageData.playerSpecific?.guildMembers ?: emptyList() } diff --git a/src/main/java/at/hannibal2/skyhanni/data/HotmData.kt b/src/main/java/at/hannibal2/skyhanni/data/HotmData.kt index 1d8182328b6e..3137458c3bec 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/HotmData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/HotmData.kt @@ -421,7 +421,8 @@ enum class HotmData( val storage get() = ProfileStorageData.profileSpecific?.mining?.hotmTree - val abilities = listOf(PICKOBULUS, MINING_SPEED_BOOST, MANIAC_MINER, GEMSTONE_INFUSION, ANOMALOUS_DESIRE, SHEER_FORCE) + val abilities = + listOf(PICKOBULUS, MINING_SPEED_BOOST, MANIAC_MINER, GEMSTONE_INFUSION, ANOMALOUS_DESIRE, SHEER_FORCE) private val inventoryPattern by patternGroup.pattern( "inventory", diff --git a/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt b/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt index b48805ef5bf5..3707d10af0a7 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt @@ -4,6 +4,7 @@ import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.config.ConfigManager.Companion.gson import at.hannibal2.skyhanni.data.model.TabWidget +import at.hannibal2.skyhanni.events.DebugDataCollectEvent import at.hannibal2.skyhanni.events.HypixelJoinEvent import at.hannibal2.skyhanni.events.IslandChangeEvent import at.hannibal2.skyhanni.events.LorenzChatEvent @@ -119,6 +120,9 @@ object HypixelData { var skyBlock = false var skyBlockIsland = IslandType.UNKNOWN var serverId: String? = null + private var lastSuccessfulServerIdFetchTime = SimpleTimeMark.farPast() + private var lastSuccessfulServerIdFetchType: String? = null + private var failedServerIdFetchCounter = 0 // Ironman, Stranded and Bingo var noTrade = false @@ -159,24 +163,61 @@ object HypixelData { TabWidget.SERVER.matchMatcherFirstLine { serverId = group("serverid") + lastSuccessfulServerIdFetchTime = SimpleTimeMark.now() + lastSuccessfulServerIdFetchType = "tab list" + failedServerIdFetchCounter = 0 return } ScoreboardData.sidebarLinesFormatted.matchFirst(serverIdScoreboardPattern) { val serverType = if (group("servertype") == "M") "mega" else "mini" serverId = "$serverType${group("serverid")}" + lastSuccessfulServerIdFetchTime = SimpleTimeMark.now() + lastSuccessfulServerIdFetchType = "scoreboard" + failedServerIdFetchCounter = 0 return } + failedServerIdFetchCounter++ + if (failedServerIdFetchCounter < 3) return ErrorManager.logErrorWithData( Exception("NoServerId"), "Could not find server id", + "failedServerIdFetchCounter" to failedServerIdFetchCounter, + "lastSuccessfulServerIdFetchTime" to lastSuccessfulServerIdFetchTime, + "lastSuccessfulServerIdFetchType" to lastSuccessfulServerIdFetchType, "islandType" to LorenzUtils.skyBlockIsland, "tablist" to TabListData.getTabList(), "scoreboard" to ScoreboardData.sidebarLinesFormatted, ) } + @SubscribeEvent + fun onDebugDataCollect(event: DebugDataCollectEvent) { + event.title("Server ID") + if (!LorenzUtils.inSkyBlock) { + event.addIrrelevant("not in sb") + return + } + + val id = serverId + if (id == null) { + event.addData { + add("server id is null!") + add("failedServerIdFetchCounter: $failedServerIdFetchCounter") + add("") + add("last successful fetch time: $lastSuccessfulServerIdFetchTime") + add("last successful fetch type: $lastSuccessfulServerIdFetchType") + } + } else { + event.addIrrelevant { + add("Server id: '$id'") + add("fetch time: $lastSuccessfulServerIdFetchTime") + add("fetch type: $lastSuccessfulServerIdFetchType") + } + } + } + fun getPlayersOnCurrentServer(): Int { var amount = 0 val playerPatternList = mutableListOf( @@ -218,7 +259,7 @@ object HypixelData { // This code is modified from NEU, and depends on NEU (or another mod) sending /locraw. private val jsonBracketPattern = "^\\{.+}".toPattern() - //todo convert to proper json object + // todo convert to proper json object fun checkForLocraw(message: String) { jsonBracketPattern.matchMatcher(message.removeColor()) { try { diff --git a/src/main/java/at/hannibal2/skyhanni/data/IslandGraphs.kt b/src/main/java/at/hannibal2/skyhanni/data/IslandGraphs.kt index 1f8e45afb749..386fb8bbf489 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/IslandGraphs.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/IslandGraphs.kt @@ -4,8 +4,8 @@ import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.data.model.Graph import at.hannibal2.skyhanni.data.model.GraphNode -import at.hannibal2.skyhanni.data.model.findShortestPathAsGraphWithDistance import at.hannibal2.skyhanni.data.repo.RepoUtils +import at.hannibal2.skyhanni.events.EntityMoveEvent import at.hannibal2.skyhanni.events.IslandChangeEvent import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent import at.hannibal2.skyhanni.events.LorenzTickEvent @@ -14,25 +14,30 @@ import at.hannibal2.skyhanni.events.RepositoryReloadEvent import at.hannibal2.skyhanni.events.skyblock.ScoreboardAreaChangeEvent import at.hannibal2.skyhanni.features.misc.IslandAreas import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule -import at.hannibal2.skyhanni.test.SkyHanniDebugsAndTests +import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.CollectionUtils.sorted import at.hannibal2.skyhanni.utils.DelayedRun +import at.hannibal2.skyhanni.utils.GraphUtils import at.hannibal2.skyhanni.utils.LocationUtils -import at.hannibal2.skyhanni.utils.LocationUtils.canBeSeen import at.hannibal2.skyhanni.utils.LocationUtils.distanceSqToPlayer import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer import at.hannibal2.skyhanni.utils.LorenzColor import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland import at.hannibal2.skyhanni.utils.LorenzVec +import at.hannibal2.skyhanni.utils.NumberUtil.roundTo import at.hannibal2.skyhanni.utils.RegexUtils.matches import at.hannibal2.skyhanni.utils.RenderUtils.draw3DLine import at.hannibal2.skyhanni.utils.RenderUtils.draw3DPathWithWaypoint -import at.hannibal2.skyhanni.utils.RenderUtils.drawWaypointFilled +import at.hannibal2.skyhanni.utils.chat.Text.asComponent +import at.hannibal2.skyhanni.utils.chat.Text.hover +import at.hannibal2.skyhanni.utils.chat.Text.onClick +import at.hannibal2.skyhanni.utils.chat.Text.send import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern +import net.minecraft.client.Minecraft import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import java.awt.Color import java.io.File -import kotlin.math.abs import kotlin.time.Duration.Companion.milliseconds /** @@ -97,11 +102,17 @@ object IslandGraphs { val existsForThisIsland get() = currentIslandGraph != null - var closedNote: GraphNode? = null + private var pathfindClosestNode: GraphNode? = null + var closestNode: GraphNode? = null + private var secondClosestNode: GraphNode? = null private var currentTarget: LorenzVec? = null + private var currentTargetNode: GraphNode? = null + private var label = "" + private var lastDistance = 0.0 + private var totalDistance = 0.0 private var color = Color.WHITE - private var showGoalExact = false + private var shouldAllowRerouting = false private var onFound: () -> Unit = {} private var goal: GraphNode? = null set(value) { @@ -143,6 +154,9 @@ object IslandGraphs { @SubscribeEvent fun onWorldChange(event: LorenzWorldChangeEvent) { currentIslandGraph = null + if (currentTarget != null) { + "§e[SkyHanni] Navigation stopped because of world switch!".asComponent().send(PATHFIND_ID) + } reset() } @@ -188,43 +202,44 @@ object IslandGraphs { } val graph = RepoUtils.getConstant(SkyHanniMod.repo.repoLocation, constant, Graph.gson, Graph::class.java) + IslandAreas.display = null setNewGraph(graph) } fun setNewGraph(graph: Graph) { - IslandAreas.display = null reset() currentIslandGraph = graph // calling various update functions to make swtiching between deep caverns and glacite tunnels bareable handleTick() - IslandAreas.noteMoved() + IslandAreas.nodeMoved() DelayedRun.runDelayed(150.milliseconds) { IslandAreas.updatePosition() } } private fun reset() { - closedNote = null - currentTarget = null - goal = null - fastestPath = null + stop() + pathfindClosestNode = null + closestNode = null } @SubscribeEvent fun onTick(event: LorenzTickEvent) { if (!LorenzUtils.inSkyBlock) return - handleTick() + if (event.isMod(2)) { + handleTick() + checkMoved() + } } private fun handleTick() { - val prevClosed = closedNote - - val graph = currentIslandGraph ?: return + val prevClosest = pathfindClosestNode currentTarget?.let { if (it.distanceToPlayer() < 3) { onFound() + "§e[SkyHanni] Navigation reached §r$label§e!".asComponent().send(PATHFIND_ID) reset() } if (!condition()) { @@ -232,17 +247,52 @@ object IslandGraphs { } } - val newClosest = if (SkyHanniDebugsAndTests.c == 0.0) { - graph.minBy { it.position.distanceSqToPlayer() } - } else null - if (closedNote == newClosest) return - closedNote = newClosest - onNewNote() - val closest = closedNote ?: return - val goal = goal ?: return - if (closest == prevClosed) return - - val (path, distance) = graph.findShortestPathAsGraphWithDistance(closest, goal) + val graph = currentIslandGraph ?: return + val sortedNodes = graph.sortedBy { it.position.distanceSqToPlayer() } + val newClosest = sortedNodes.first() + if (pathfindClosestNode == newClosest) return + val newPath = !onCurrentPath() + + closestNode = newClosest + secondClosestNode = sortedNodes.getOrNull(1) + onNewNode() + if (newClosest == prevClosest) return + if (newPath) { + pathfindClosestNode = closestNode + findNewPath() + } + } + + private fun onCurrentPath(): Boolean { + val path = fastestPath ?: return false + if (path.isEmpty()) return false + val closest = path.nodes.minBy { it.position.distanceSqToPlayer() } + val distance = closest.position.distanceToPlayer() + if (distance > 7) return false + + val index = path.nodes.indexOf(closest) + val newNodes = path.drop(index) + val newGraph = Graph(newNodes) + fastestPath = skipIfCloser(newGraph) + newNodes.getOrNull(1)?.let { + secondClosestNode = it + } + setFastestPath(newGraph to newGraph.totalLenght(), setPath = false) + return true + } + + private fun skipIfCloser(graph: Graph): Graph = if (graph.nodes.size > 1) { + val hideNearby = if (Minecraft.getMinecraft().thePlayer.onGround) 3 else 5 + Graph(graph.nodes.takeLastWhile { it.position.distanceToPlayer() > hideNearby }) + } else { + graph + } + + private fun findNewPath() { + val goal = IslandGraphs.goal ?: return + val closest = pathfindClosestNode ?: return + + val (path, distance) = GraphUtils.findShortestPathAsGraphWithDistance(closest, goal) val first = path.firstOrNull() val second = path.getOrNull(1) @@ -260,40 +310,167 @@ object IslandGraphs { setFastestPath(path to (distance + nodeDistance)) } - private fun setFastestPath(path: Pair) { - fastestPath = path.takeIf { it.first.isNotEmpty() }?.first + private fun Graph.totalLenght(): Double = nodes.zipWithNext().sumOf { (a, b) -> a.position.distance(b.position) } + + private fun handlePositionChange() { + updateChat() + } + + private var hasMoved = false + + private fun checkMoved() { + if (hasMoved) { + hasMoved = false + if (goal != null) { + handlePositionChange() + } + } + } - fastestPath?.let { - fastestPath = Graph(cutByMaxDistance(it.nodes, 3.0)) + @SubscribeEvent + fun onPlayerMove(event: EntityMoveEvent) { + if (LorenzUtils.inSkyBlock && event.entity == Minecraft.getMinecraft().thePlayer) { + hasMoved = true + } + } + + private fun setFastestPath(path: Pair, setPath: Boolean = true) { + // TODO cleanup + val (fastestPath, distance) = path.takeIf { it.first.isNotEmpty() } ?: return + val nodes = fastestPath.nodes.toMutableList() + if (Minecraft.getMinecraft().thePlayer.onGround) { + nodes.add(0, GraphNode(0, LocationUtils.playerLocation())) + } + if (setPath) { + this.fastestPath = skipIfCloser(Graph(cutByMaxDistance(nodes, 2.0))) } + updateChat() } - private fun onNewNote() { + private fun onNewNode() { // TODO create an event - IslandAreas.noteMoved() + IslandAreas.nodeMoved() + if (shouldAllowRerouting) { + tryRerouting() + } + } + + private fun tryRerouting() { + val target = currentTargetNode ?: return + val closest = pathfindClosestNode ?: return + val map = GraphUtils.findAllShortestDistances(closest).distances.filter { it.key.sameNameAndTags(target) } + val newTarget = map.sorted().keys.firstOrNull() ?: return + if (newTarget != target) { + ChatUtils.debug("Rerouting navigation..") + newTarget.pathFind(label, color, onFound, allowRerouting = true, condition = condition) + } } fun stop() { currentTarget = null goal = null fastestPath = null + currentTargetNode = null + label = "" + totalDistance = 0.0 + lastDistance = 0.0 + } + + /** + * Activates pathfinding, with this graph node as goal. + * + * @param label The name of the naviation goal in chat. + * @param color The color of the lines in world. + * @param onFound The callback that gets fired when the goal is reached. + * @param allowRerouting When a different node with same name and tags as the origianl goal is closer to the player, starts routing to this instead. + * @param condition The pathfinding stops when the condition is no longer valid. + */ + fun GraphNode.pathFind( + label: String, + color: Color = LorenzColor.WHITE.toColor(), + onFound: () -> Unit = {}, + allowRerouting: Boolean = false, + condition: () -> Boolean, + ) { + reset() + currentTargetNode = this + shouldAllowRerouting = allowRerouting + pathFind0(location = position, label, color, onFound, condition) } + /** + * Activates pathfinding to a location in the island. + * + * @param location The goal of the pathfinder. + * @param label The name of the naviation goal in chat. + * @param color The color of the lines in world. + * @param onFound The callback that gets fired when the goal is reached. + * @param condition The pathfinding stops when the condition is no longer valid. + */ fun pathFind( location: LorenzVec, + label: String, color: Color = LorenzColor.WHITE.toColor(), onFound: () -> Unit = {}, - showGoalExact: Boolean = false, - condition: () -> Boolean = { true }, + condition: () -> Boolean, ) { reset() + shouldAllowRerouting = false + pathFind0(location, label, color, onFound, condition) + } + + private fun pathFind0( + location: LorenzVec, + label: String, + color: Color = LorenzColor.WHITE.toColor(), + onFound: () -> Unit = {}, + condition: () -> Boolean, + ) { currentTarget = location + this.label = label this.color = color this.onFound = onFound - this.showGoalExact = showGoalExact this.condition = condition val graph = currentIslandGraph ?: return goal = graph.minBy { it.position.distance(currentTarget!!) } + updateChat() + } + + private const val PATHFIND_ID = -6457563 + + private fun updateChat() { + if (label == "") return + val path = fastestPath ?: return + var distance = 0.0 + if (path.isNotEmpty()) { + for ((a, b) in path.zipWithNext()) { + distance += a.position.distance(b.position) + } + val distanceToPlayer = path.first().position.distanceToPlayer() + distance += distanceToPlayer + distance = distance.roundTo(1) + } + + if (distance == lastDistance) return + lastDistance = distance + if (distance == 0.0) return + if (totalDistance == 0.0 || distance > totalDistance) { + totalDistance = distance + } + sendChatDistance(distance) + } + + private fun sendChatDistance(distance: Double) { + val percentage = (1 - (distance / totalDistance)) * 100 + val componentText = "§e[SkyHanni] Navigating to §r$label §f[§e$distance§f] §f(§c${percentage.roundTo(1)}%§f)".asComponent() + componentText.onClick( + onClick = { + stop() + "§e[SkyHanni] Navigation manually stopped!".asComponent().send(PATHFIND_ID) + }, + ) + componentText.hover = "§eClick to stop navigating!".asComponent() + componentText.send(PATHFIND_ID) } @SubscribeEvent @@ -301,24 +478,23 @@ object IslandGraphs { if (!LorenzUtils.inSkyBlock) return val path = fastestPath ?: return - var graph = path - graph = skipNodes(graph) ?: graph - + // maybe reuse for debuggin +// for ((a, b) in path.nodes.zipWithNext()) { +// val diff = a.position.distance(b.position) +// event.drawString(a.position, "diff: ${diff.roundTo(1)}") +// } event.draw3DPathWithWaypoint( - graph, + path, color, 6, true, - bezierPoint = 2.0, + bezierPoint = 0.6, textSize = 1.0, ) - val lastNode = graph.nodes.last().position + val targetLocation = currentTarget ?: return + val lastNode = path.nodes.lastOrNull()?.position ?: return event.draw3DLine(lastNode.add(0.5, 0.5, 0.5), targetLocation.add(0.5, 0.5, 0.5), color, 4, true) - - if (showGoalExact) { - event.drawWaypointFilled(targetLocation, color) - } } // TODO move into new utils class @@ -350,47 +526,4 @@ object IslandGraphs { return locations.map { GraphNode(index++, it) } } - - // trying to find a faster node-path, if the future nodes are in line of sight and gratly beneift the current path - private fun skipNodes(graph: Graph): Graph? { - val closedNode = closedNote ?: return null - - val playerEyeLocation = LocationUtils.playerEyeLocation() - val playerY = playerEyeLocation.y - 1 - - val distanceToPlayer = closedNode.position.distanceToPlayer() - val skipNodeDistance = distanceToPlayer > 8 - val maxSkipDistance = if (skipNodeDistance) 50.0 else 20.0 - - val nodes = graph.nodes - val potentialSkip = - nodes.lastOrNull { it.position.canBeSeen(maxSkipDistance, -1.0) && abs(it.position.y - playerY) <= 2 } ?: return null - - val angleSkip = if (potentialSkip == nodes.first()) { - false - } else { - val v1 = potentialSkip.position - playerEyeLocation - val v2 = nodes.first().position - playerEyeLocation - val v = v1.angleInRad(v2) - v > 1 - } - - if (!skipNodeDistance && !angleSkip) return null - - val list = mutableListOf() - list.add(potentialSkip) - - var passed = false - for (node in nodes) { - if (passed) { - list.add(node) - } else { - if (node == potentialSkip) { - passed = true - } - } - } - - return Graph(list) - } } diff --git a/src/main/java/at/hannibal2/skyhanni/data/ItemClickData.kt b/src/main/java/at/hannibal2/skyhanni/data/ItemClickData.kt index e7fa75331924..2bcf589a3d50 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/ItemClickData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/ItemClickData.kt @@ -24,23 +24,23 @@ object ItemClickData { packet is C08PacketPlayerBlockPlacement -> { if (packet.placedBlockDirection != 255) { val position = packet.position.toLorenzVec() - BlockClickEvent(ClickType.RIGHT_CLICK, position, packet.stack).postAndCatch() + BlockClickEvent(ClickType.RIGHT_CLICK, position, packet.stack).post() } else { - ItemClickEvent(InventoryUtils.getItemInHand(), ClickType.RIGHT_CLICK).postAndCatch() + ItemClickEvent(InventoryUtils.getItemInHand(), ClickType.RIGHT_CLICK).post() } } packet is C07PacketPlayerDigging && packet.status == C07PacketPlayerDigging.Action.START_DESTROY_BLOCK -> { val position = packet.position.toLorenzVec() val blockClickCancelled = - BlockClickEvent(ClickType.LEFT_CLICK, position, InventoryUtils.getItemInHand()).postAndCatch() + BlockClickEvent(ClickType.LEFT_CLICK, position, InventoryUtils.getItemInHand()).post() ItemClickEvent(InventoryUtils.getItemInHand(), ClickType.LEFT_CLICK).also { - it.isCanceled = blockClickCancelled - }.postAndCatch() + if (blockClickCancelled) it.cancel() + }.post() } packet is C0APacketAnimation -> { - ItemClickEvent(InventoryUtils.getItemInHand(), ClickType.LEFT_CLICK).postAndCatch() + ItemClickEvent(InventoryUtils.getItemInHand(), ClickType.LEFT_CLICK).post() } packet is C02PacketUseEntity -> { @@ -51,7 +51,7 @@ object ItemClickData { else -> return } val clickedEntity = packet.getEntityFromWorld(Minecraft.getMinecraft().theWorld) ?: return - EntityClickEvent(clickType, clickedEntity, InventoryUtils.getItemInHand()).postAndCatch() + EntityClickEvent(clickType, clickedEntity, InventoryUtils.getItemInHand()).post() } else -> { diff --git a/src/main/java/at/hannibal2/skyhanni/data/MaxwellAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/MaxwellAPI.kt index 194664c94886..776a7c808103 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/MaxwellAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/MaxwellAPI.kt @@ -273,11 +273,11 @@ object MaxwellAPI { if (noPowerSelectedPattern.matches(line)) currentPower = NO_POWER inventoryMPPattern.matchMatcher(line) { + foundMagicalPower = true // MagicalPower is boosted in catacombs if (DungeonAPI.inDungeon()) return@matchMatcher magicalPower = group("mp").formatInt() - foundMagicalPower = true } inventoryPowerPattern.matchMatcher(line) { diff --git a/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt index 469c48489245..949e33146ce6 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/MayorAPI.kt @@ -143,6 +143,7 @@ object MayorAPI { ChatUtils.clickableChat( "The Perkpocalypse Mayor is not known! Click here to update the temporary Mayor.", onClick = { HypixelCommands.calendar() }, + replaceSameMessage = true, ) } } @@ -170,7 +171,7 @@ object MayorAPI { } ?: false } ?: return - val perk = stack.getLore().nextAfter({ perkpocalypsePerksPattern.matches(it) }) ?: return + val perk = stack.getLore().nextAfter({ perkpocalypsePerksPattern.matches(it) }, 2) ?: return // This is the first Perk of the Perkpocalypse Mayor val jerryMayor = getMayorFromPerk(getPerkFromName(perk.removeColor()) ?: return)?.addAllPerks() ?: return diff --git a/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt index 9d635b1b9a22..54d186ae52c3 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/MiningAPI.kt @@ -74,7 +74,7 @@ object MiningAPI { */ private val pickobulusFailPattern by pickbobulusGroup.pattern( "fail", - "§7Your §r§aPickobulus §r§7didn't destroy any blocks!" + "§7Your §r§aPickobulus §r§7didn't destroy any blocks!", ) private data class MinedBlock(val ore: OreBlock, var confirmed: Boolean) { @@ -127,6 +127,8 @@ object MiningAPI { var lastColdReset = SimpleTimeMark.farPast() private set + private var lastOreMinedTime = SimpleTimeMark.farPast() + fun inGlaciteArea() = inGlacialTunnels() || IslandType.MINESHAFT.isInIsland() fun inDwarvenBaseCamp() = IslandType.DWARVEN_MINES.isInIsland() && dwarvenBaseCampPattern.matches(LorenzUtils.skyBlockArea) @@ -161,11 +163,10 @@ object MiningAPI { } } - @SubscribeEvent + @HandleEvent fun onBlockClick(event: BlockClickEvent) { if (!inCustomMiningIsland()) return if (event.clickType != ClickType.LEFT_CLICK) return - //println(event.getBlockState.properties) if (OreBlock.getByStateOrNull(event.getBlockState) == null) return recentClickedBlocks += event.position to SimpleTimeMark.now() } @@ -342,6 +343,7 @@ object MiningAPI { currentAreaOreBlocks = setOf() resetOreEvent() resetPickobulusEvent() + lastOreMinedTime = SimpleTimeMark.farPast() } private fun resetOreEvent() { @@ -360,6 +362,11 @@ object MiningAPI { pickobulusWaitingForBlock = false } + @HandleEvent(onlyOnSkyblock = true) + fun onOreMined(event: OreMinedEvent) { + lastOreMinedTime = SimpleTimeMark.now() + } + @SubscribeEvent fun onDebugDataCollect(event: DebugDataCollectEvent) { event.title("Mining API") @@ -367,6 +374,10 @@ object MiningAPI { event.addIrrelevant("not in a mining island") return } + if (lastOreMinedTime.passedSince() > 30.seconds) { + event.addIrrelevant("not mined recently") + return + } event.addData { if (lastInitSound.isFarPast()) { diff --git a/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt index e392699cdbfe..7581b3b1ec94 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt @@ -412,5 +412,5 @@ enum class SackStatus { MISSING, CORRECT, ALRIGHT, - OUTDATED; + OUTDATED, } diff --git a/src/main/java/at/hannibal2/skyhanni/data/bazaar/HypixelBazaarFetcher.kt b/src/main/java/at/hannibal2/skyhanni/data/bazaar/HypixelBazaarFetcher.kt index 13044b7c3151..7a97fca1d19d 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/bazaar/HypixelBazaarFetcher.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/bazaar/HypixelBazaarFetcher.kt @@ -2,6 +2,7 @@ package at.hannibal2.skyhanni.data.bazaar import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.config.ConfigManager +import at.hannibal2.skyhanni.events.DebugDataCollectEvent import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.features.inventory.bazaar.BazaarData import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule @@ -29,10 +30,29 @@ object HypixelBazaarFetcher { private const val HIDDEN_FAILED_ATTEMPTS = 3 var latestProductInformation = mapOf() + private var lastSuccessfulFetch = SimpleTimeMark.farPast() private var nextFetchTime = SimpleTimeMark.farPast() private var failedAttempts = 0 private var nextFetchIsManual = false + @SubscribeEvent + fun onDebugDataCollect(event: DebugDataCollectEvent) { + event.title("Bazaar Data Fetcher from API") + + val data = listOf( + "failedAttempts: $failedAttempts", + "nextFetchIsManual: $nextFetchIsManual", + "nextFetchTime: ${nextFetchTime.timeUntil()}", + "lastSuccessfulFetch: ${lastSuccessfulFetch.passedSince()}", + ) + + if (failedAttempts == 0) { + event.addIrrelevant(data) + } else { + event.addData(data) + } + } + @SubscribeEvent fun onTick(event: LorenzTickEvent) { if (!canFetch()) return @@ -51,6 +71,7 @@ object HypixelBazaarFetcher { if (response.success) { latestProductInformation = process(response.products) failedAttempts = 0 + lastSuccessfulFetch = SimpleTimeMark.now() } else { val rawResponse = jsonResponse.toString() onError(fetchType, Exception("success=false, cause=${response.cause}"), rawResponse) @@ -98,13 +119,20 @@ object HypixelBazaarFetcher { e.printStackTrace() } else { nextFetchTime = SimpleTimeMark.now() + 15.minutes - ErrorManager.logErrorWithData( - e, - userMessage, - "fetchType" to fetchType, - "failedAttempts" to failedAttempts, - "rawResponse" to rawResponse, - ) + if (rawResponse == null || rawResponse.toString() == "{}") { + ChatUtils.chat( + "§cFailed loading Bazaar Price data!\n" + + "Please wait until the Hypixel API is sending correct data again! There is nothing else to do at the moment.", + ) + } else { + ErrorManager.logErrorWithData( + e, + userMessage, + "fetchType" to fetchType, + "failedAttempts" to failedAttempts, + "rawResponse" to rawResponse, + ) + } } } diff --git a/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/PlayerNameFormatter.kt b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/PlayerNameFormatter.kt index 94bc665b6202..35356f32f3bf 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/PlayerNameFormatter.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/PlayerNameFormatter.kt @@ -125,32 +125,38 @@ object PlayerNameFormatter { fun onPrivateChat(event: PrivateMessageChatEvent) { if (!isEnabled()) return event.chatComponent = - StringUtils.replaceIfNeeded(event.chatComponent, Text.text("§d${event.direction}") { - appendText(" ") - appendSibling(nameFormat(event.authorComponent)) - appendText("§f: ") - appendSibling(event.messageComponent.intoComponent()) - }) ?: return + StringUtils.replaceIfNeeded( + event.chatComponent, + Text.text("§d${event.direction}") { + appendText(" ") + appendSibling(nameFormat(event.authorComponent)) + appendText("§f: ") + appendSibling(event.messageComponent.intoComponent()) + } + ) ?: return } @SubscribeEvent fun onPlayerShowItemChat(event: PlayerShowItemChatEvent) { if (!isEnabled()) return - event.chatComponent = StringUtils.replaceIfNeeded(event.chatComponent, Text.text("") { - appendSibling( - nameFormat( - event.authorComponent, - levelColor = event.levelComponent?.sampleStyleAtStart()?.color?.toString(), - level = event.levelComponent + event.chatComponent = StringUtils.replaceIfNeeded( + event.chatComponent, + Text.text("") { + appendSibling( + nameFormat( + event.authorComponent, + levelColor = event.levelComponent?.sampleStyleAtStart()?.color?.toString(), + level = event.levelComponent + ) ) - ) - appendText(" ") - appendSibling(event.action.intoComponent().changeColor(LorenzColor.GRAY)) + appendText(" ") + appendSibling(event.action.intoComponent().changeColor(LorenzColor.GRAY)) - appendText(" ") - appendSibling(event.item.intoComponent()) - }) ?: return + appendText(" ") + appendSibling(event.item.intoComponent()) + } + ) ?: return } private fun nameFormat( @@ -214,7 +220,7 @@ object PlayerNameFormatter { val color = rawColor ?: return null val level = rawLevel?.getText() ?: error("level is null, color is not null") val levelData = "$color$level" - val result = if (config.hideLevelBrackets) levelData else "§8[${levelData}§8]" + val result = if (config.hideLevelBrackets) levelData else "§8[$levelData§8]" return result.applyFormattingFrom(rawLevel) } diff --git a/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PartyChatEvent.kt b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PartyChatEvent.kt index a26af584b8a6..e2b9e04ef3ff 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PartyChatEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PartyChatEvent.kt @@ -1,7 +1,7 @@ package at.hannibal2.skyhanni.data.hypixel.chat.event -import at.hannibal2.skyhanni.utils.StringUtils.cleanPlayerName import at.hannibal2.skyhanni.utils.ComponentSpan +import at.hannibal2.skyhanni.utils.StringUtils.cleanPlayerName import net.minecraft.util.IChatComponent class PartyChatEvent( diff --git a/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PlayerAllChatEvent.kt b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PlayerAllChatEvent.kt index 7d6d1a7ac055..e33165b34acc 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PlayerAllChatEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/hypixel/chat/event/PlayerAllChatEvent.kt @@ -21,11 +21,14 @@ class PlayerAllChatEvent( val isAGuest by lazy { privateIslandGuest != null } companion object { - private val listenerList = ListenerList(AbstractChatEvent( - ComponentSpan.empty(), - ComponentSpan.empty(), - ChatComponentText(""), - "").listenerList) + private val listenerList = ListenerList( + AbstractChatEvent( + ComponentSpan.empty(), + ComponentSpan.empty(), + ChatComponentText(""), + "" + ).listenerList + ) } /** @@ -45,8 +48,10 @@ class PlayerAllChatEvent( * This method is required if [setup] is present. */ @ApiStatus.Internal - constructor() : this(null, null, null, "", - ComponentSpan.empty(), ComponentSpan.empty(), ChatComponentText("")) + constructor() : this( + null, null, null, "", + ComponentSpan.empty(), ComponentSpan.empty(), ChatComponentText("") + ) /** * This method is required if [setup] is present. 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 new file mode 100644 index 000000000000..41d0f701cb15 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/RepoErrorData.kt @@ -0,0 +1,19 @@ +package at.hannibal2.skyhanni.data.jsonobjects.repo + +import com.google.gson.annotations.Expose +import com.google.gson.annotations.SerializedName + +data class RepoErrorJson( + @Expose @SerializedName("changed_error_messages") val changedErrorMessages: List, +) + +data class RepoErrorData( + @Expose @SerializedName("message_exact") private var rawMessageExact: List?, + @Expose @SerializedName("message_starts_with") private var rawMessageStartsWith: List?, + @Expose @SerializedName("replace_message") var replaceMessage: String?, + @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() +} diff --git a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/RiftWoodenButtonsJson.kt b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/RiftWoodenButtonsJson.kt new file mode 100644 index 000000000000..fdc4befe785f --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/RiftWoodenButtonsJson.kt @@ -0,0 +1,13 @@ +package at.hannibal2.skyhanni.data.jsonobjects.repo + +import at.hannibal2.skyhanni.utils.LorenzVec +import com.google.gson.annotations.Expose + +data class RiftWoodenButtonsJson( + @Expose val houses: Map> +) + +data class ButtonSpots( + @Expose val position: LorenzVec, + @Expose val buttons: List +) 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 2acbe3546117..eed2d5e70dba 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/mob/IslandExceptions.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/mob/IslandExceptions.kt @@ -58,26 +58,28 @@ object IslandExceptions { armorStand: EntityArmorStand?, nextEntity: EntityLivingBase?, ) = when { - baseEntity is EntityZombie && armorStand != null && + baseEntity is EntityZombie && + armorStand != null && (armorStand.name == "§e﴾ §c§lThe Watcher§r§r §e﴿" || armorStand.name == "§3§lWatchful Eye§r") -> MobData.MobResult.found( MobFactories.special(baseEntity, armorStand.cleanName(), armorStand), ) - baseEntity is EntityCaveSpider -> MobUtils.getClosedArmorStand(baseEntity, 2.0).takeNonDefault() + baseEntity is EntityCaveSpider -> MobUtils.getClosestArmorStand(baseEntity, 2.0).takeNonDefault() .makeMobResult { MobFactories.dungeon(baseEntity, it) } baseEntity is EntityOtherPlayerMP && baseEntity.isNPC() && baseEntity.name == "Shadow Assassin" -> - MobUtils.getClosedArmorStandWithName(baseEntity, 3.0, "Shadow Assassin") + MobUtils.getClosestArmorStandWithName(baseEntity, 3.0, "Shadow Assassin") .makeMobResult { MobFactories.dungeon(baseEntity, it) } baseEntity is EntityOtherPlayerMP && baseEntity.isNPC() && baseEntity.name == "The Professor" -> MobUtils.getArmorStand(baseEntity, 9) .makeMobResult { MobFactories.boss(baseEntity, it) } - baseEntity is EntityOtherPlayerMP && baseEntity.isNPC() && + baseEntity is EntityOtherPlayerMP && + baseEntity.isNPC() && (nextEntity is EntityGiantZombie || nextEntity == null) && - baseEntity.name.contains("Livid") -> MobUtils.getClosedArmorStandWithName(baseEntity, 6.0, "﴾ Livid") + 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 ?: "") -> @@ -174,7 +176,8 @@ object IslandExceptions { baseEntity: EntityLivingBase, armorStand: EntityArmorStand?, ) = when { - baseEntity is EntityMagmaCube && armorStand != null && + baseEntity is EntityMagmaCube && + armorStand != null && armorStand.cleanName() == "[Lv100] Bal ???❤" -> MobData.MobResult.found( Mob(baseEntity, Mob.Type.BOSS, armorStand, "Bal", levelOrTier = 100), @@ -188,7 +191,8 @@ object IslandExceptions { armorStand: EntityArmorStand?, nextEntity: EntityLivingBase?, ) = when { - baseEntity is EntityOcelot && armorStand?.isDefaultValue() == false && + baseEntity is EntityOcelot && + armorStand?.isDefaultValue() == false && armorStand.name.startsWith("§8[§7Lv155§8] §cAzrael§r") -> MobUtils.getArmorStand(baseEntity, 1) .makeMobResult { MobFactories.basic(baseEntity, it) } @@ -203,7 +207,8 @@ object IslandExceptions { MobUtils.getArmorStand(baseEntity, 2) .makeMobResult { MobFactories.basic(baseEntity, it, listOf(armorStand)) } - baseEntity is EntityZombie && armorStand?.isDefaultValue() == true && + baseEntity is EntityZombie && + armorStand?.isDefaultValue() == true && MobUtils.getNextEntity(baseEntity, 4)?.name?.startsWith("§e") == true -> petCareHandler(baseEntity) @@ -250,7 +255,8 @@ object IslandExceptions { .take(RAT_SEARCH_UP_TO - RAT_SEARCH_START + 1) .map { i -> MobUtils.getArmorStand(baseEntity, i) } .firstOrNull { - it != null && it.distanceTo(baseEntity) < 4.0 && + it != null && + it.distanceTo(baseEntity) < 4.0 && it.inventory?.get(4)?.getSkullTexture() == MobFilter.RAT_SKULL }?.let { MobData.MobResult.found(Mob(baseEntity, mobType = Mob.Type.BASIC, armorStand = it, name = "Rat")) 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 7e7e9f96cdc8..e9eb6729de43 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/mob/Mob.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/mob/Mob.kt @@ -154,9 +154,11 @@ class Mob( relativeBoundingBox = if (extraEntities.isNotEmpty()) makeRelativeBoundingBox() else null // Inlined updateBoundingBox() - owner = (ownerName ?: if (mobType == Type.SLAYER) hologram2?.let { - summonOwnerPattern.matchMatcher(it.cleanName()) { this.group("name") } - } else null)?.let { MobUtils.OwnerShip(it) } + owner = ( + ownerName ?: if (mobType == Type.SLAYER) hologram2?.let { + summonOwnerPattern.matchMatcher(it.cleanName()) { this.group("name") } + } else null + )?.let { MobUtils.OwnerShip(it) } } private fun removeExtraEntitiesFromChecking() = @@ -164,15 +166,16 @@ class Mob( MobData.externRemoveOfRetryAmount += it } - fun updateBoundingBox() { + private fun updateBoundingBox() { relativeBoundingBox = if (extraEntities.isNotEmpty()) makeRelativeBoundingBox() else null } - private fun makeRelativeBoundingBox() = - (baseEntity.entityBoundingBox.union( + private fun makeRelativeBoundingBox() = ( + baseEntity.entityBoundingBox.union( extraEntities.filter { it !is EntityArmorStand } .mapNotNull { it.entityBoundingBox }, - ))?.offset(-baseEntity.posX, -baseEntity.posY, -baseEntity.posZ) + ) + )?.offset(-baseEntity.posX, -baseEntity.posY, -baseEntity.posZ) fun fullEntityList() = baseEntity.toSingletonListOrEmpty() + 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 69b0b85a8c10..d9cb34ed25d7 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/mob/MobDebug.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/mob/MobDebug.kt @@ -42,7 +42,7 @@ object MobDebug { val map = filter { it.canBeSeen() && it.isNotInvisible() } .map { it.boundingBox.getTopCenter() to it.name } for ((location, text) in map) { - event.drawString(location.add(y = 0.5), "§5$text", seeThroughBlocks = true) + event.drawString(location.up(0.5), "§5$text", seeThroughBlocks = true) } } 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 9b7ba2cfd5e1..014e0a846613 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/mob/MobDetection.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/mob/MobDetection.kt @@ -97,8 +97,9 @@ object MobDetection { } private fun Mob.watchdogCheck(world: World): Boolean = - this.baseEntity.worldObj != world || (this.armorStand?.let { it.worldObj != world } - ?: false) || this.extraEntities.any { it.worldObj != world } + this.baseEntity.worldObj != world || ( + this.armorStand?.let { it.worldObj != world } ?: false + ) || this.extraEntities.any { it.worldObj != world } @SubscribeEvent fun onTick(event: LorenzTickEvent) { @@ -126,7 +127,7 @@ object MobDetection { MobData.currentEntityLiving.clear() // Naturally removing the mobs using the despawn } - (MobData.currentEntityLiving - MobData.previousEntityLiving).forEach { addRetry(it) } // Spawn + (MobData.currentEntityLiving - MobData.previousEntityLiving).forEach { addRetry(it) } // Spawn (MobData.previousEntityLiving - MobData.currentEntityLiving).forEach { entityDeSpawn(it) } // Despawn MobData.notSeenMobs.removeIf(::canBeSeen) @@ -302,13 +303,13 @@ object MobDetection { val entity = retry.entity if (retry.times == MAX_RETRIES) { MobData.logger.log( - "`${retry.entity.name}`${retry.entity.entityId} missed {\n " - + "is already Found: ${MobData.entityToMob[retry.entity] != null})." - + "\n Position: ${retry.entity.getLorenzVec()}\n " - + "DistanceC: ${ - entity.getLorenzVec().distanceChebyshevIgnoreY(LocationUtils.playerLocation()) - }\n" - + "Relative Position: ${entity.getLorenzVec() - LocationUtils.playerLocation()}\n " + + "`${retry.entity.name}`${retry.entity.entityId} missed {\n " + + "is already Found: ${MobData.entityToMob[retry.entity] != null})." + + "\n Position: ${retry.entity.getLorenzVec()}\n " + + "DistanceC: ${ + entity.getLorenzVec().distanceChebyshevIgnoreY(LocationUtils.playerLocation()) + }\n" + + "Relative Position: ${entity.getLorenzVec() - LocationUtils.playerLocation()}\n " + "}", ) // Uncomment this to make it closed a loop @@ -338,7 +339,7 @@ object MobDetection { private fun handleEntityUpdate(entityID: Int): Boolean { val entity = EntityUtils.getEntityByID(entityID) as? EntityLivingBase ?: return false - getRetry(entity)?.apply { this.entity = entity } + getRetry(entity)?.entity = entity MobData.currentEntityLiving.refreshReference(entity) MobData.previousEntityLiving.refreshReference(entity) // update map @@ -353,10 +354,10 @@ object MobDetection { 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() - } + { + 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 a9f8a14533ac..5d6111336fbd 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/mob/MobFilter.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/mob/MobFilter.kt @@ -243,8 +243,10 @@ object MobFilter { baseEntity, armorStand, extraEntityList, - ) else (MobFactories.basic(baseEntity, armorStand, extraEntityList) - ?: MobFactories.dojo(baseEntity, armorStand)) + ) else ( + MobFactories.basic(baseEntity, armorStand, extraEntityList) + ?: MobFactories.dojo(baseEntity, armorStand) + ) private fun noArmorStandMobs(baseEntity: EntityLivingBase): MobResult? = when { baseEntity is EntityBat -> createBat(baseEntity) 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 bc4be57a16d4..6e1f1d07f0a2 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/model/Graph.kt @@ -1,5 +1,6 @@ package at.hannibal2.skyhanni.data.model +import at.hannibal2.skyhanni.features.misc.pathfind.NavigationHelper import at.hannibal2.skyhanni.utils.LorenzVec import at.hannibal2.skyhanni.utils.NumberUtil.roundTo import at.hannibal2.skyhanni.utils.json.SkyHanniTypeAdapters.registerTypeAdapter @@ -8,7 +9,6 @@ import com.google.gson.GsonBuilder import com.google.gson.JsonElement import com.google.gson.annotations.Expose import com.google.gson.stream.JsonToken -import java.util.PriorityQueue // TODO: This class should be disambiguated into a NodePath and a Graph class @JvmInline @@ -138,6 +138,10 @@ value class Graph( fun fromJson(json: String): Graph = gson.fromJson(json) fun fromJson(json: JsonElement): Graph = gson.fromJson(json) } + + fun toPositionsList() = this.map { it.position } + + fun toJson(): String = gson.toJson(this) } // The node object that gets parsed from/to json @@ -164,9 +168,11 @@ class GraphNode(val id: Int, val position: LorenzVec, val name: String? = null, return true } -} -fun Graph.findShortestPathAsGraph(start: GraphNode, end: GraphNode): Graph = this.findShortestPathAsGraphWithDistance(start, end).first + fun sameNameAndTags(other: GraphNode): Boolean = name == other.name && allowedTags == other.allowedTags + + private val allowedTags get() = tags.filter { it in NavigationHelper.allowedTags } +} data class DijkstraTree( val origin: GraphNode, @@ -188,57 +194,6 @@ data class DijkstraTree( val lastVisitedNode: GraphNode, ) -/** - * Find a tree of distances to the [start] node using dijkstra's algorithm. - */ -fun Graph.findDijkstraDistances( - start: GraphNode, - /** - * Bail out early before collecting all the distances to all nodes in the graph. This will not collect valid distance data for *all* - * nodes for which bailout matches, but only the closest one. - */ - bailout: (GraphNode) -> Boolean, -): DijkstraTree { - val distances = mutableMapOf() - val previous = mutableMapOf() - val visited = mutableSetOf() - val queue = PriorityQueue(compareBy { distances.getOrDefault(it, Double.MAX_VALUE) }) - var lastVisitedNode: GraphNode = start - - distances[start] = 0.0 - queue.add(start) - - while (queue.isNotEmpty()) { - val current = queue.poll() - lastVisitedNode = current - if (bailout(current)) break - - visited.add(current) - - current.neighbours.forEach { (neighbour, weight) -> - if (neighbour !in visited) { - val newDistance = distances.getValue(current) + weight - if (newDistance < distances.getOrDefault(neighbour, Double.MAX_VALUE)) { - distances[neighbour] = newDistance - previous[neighbour] = current - queue.add(neighbour) - } - } - } - } - - return DijkstraTree( - start, - distances, - previous, - lastVisitedNode, - ) -} - -fun Graph.findAllShortestDistances(start: GraphNode): DijkstraTree { - return findDijkstraDistances(start) { false } -} - fun DijkstraTree.findPathToDestination(end: GraphNode): Pair { val distances = this val reversePath = buildList { @@ -251,16 +206,3 @@ fun DijkstraTree.findPathToDestination(end: GraphNode): Pair { } return Graph(reversePath.reversed()) to distances.distances[end]!! } - -fun Graph.findShortestPathAsGraphWithDistance(start: GraphNode, end: GraphNode): Pair { - val distances = findDijkstraDistances(start) { it == end } - return distances.findPathToDestination(end) -} - -fun Graph.findShortestPath(start: GraphNode, end: GraphNode): List = this.findShortestPathAsGraph(start, end).toPositionsList() - -fun Graph.findShortestDistance(start: GraphNode, end: GraphNode): Double = this.findShortestPathAsGraphWithDistance(start, end).second - -fun Graph.toPositionsList() = this.map { it.position } - -fun Graph.toJson(): String = Graph.gson.toJson(this) 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 6bf00edafcf6..8efcf4621e37 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/model/GraphNodeTag.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/model/GraphNodeTag.kt @@ -42,6 +42,7 @@ 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_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 f31c95958659..d1c6dede0327 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/model/SkyblockStat.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/model/SkyblockStat.kt @@ -1,69 +1,115 @@ package at.hannibal2.skyhanni.data.model +import at.hannibal2.skyhanni.data.ProfileStorageData +import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent +import at.hannibal2.skyhanni.events.WidgetUpdateEvent +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.DelayedRun +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.RegexUtils.groupOrNull +import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.StringUtils.allLettersFirstUppercase +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import net.minecraft.client.Minecraft +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import org.intellij.lang.annotations.Language import java.util.EnumMap +import java.util.regex.Pattern +import kotlin.math.roundToInt -enum class SkyblockStat(val icon: String) { - DAMAGE("§c❁"), - HEALTH("§c❤"), - DEFENSE("§a❈"), - STRENGTH("§c❁"), - INTELLIGENCE("§b✎"), - - CRIT_DAMAGE("§9☠"), - CRIT_CHANCE("§9☣"), - FEROCITY("§c⫽"), - BONUS_ATTACK_SPEED("§e⚔"), - ABILITY_DAMAGE("§c๑"), - HEALTH_REGEN("§c❣"), - VITALITY("§4♨"), - MENDING("§a☄"), - TRUE_DEFENCE("§7❂"), - SWING_RANGE("§eⓈ"), - SPEED("§f✦"), - SEA_CREATURE_CHANCE("§3α"), - MAGIC_FIND("§b✯"), - PET_LUCK("§d♣"), - FISHING_SPEED("§b☂"), - BONUS_PEST_CHANCE("§2ൠ"), - COMBAT_WISDOM("§3☯"), - MINING_WISDOM("§3☯"), - FARMING_WISDOM("§3☯"), - FORAGING_WISDOM("§3☯"), - FISHING_WISDOM("§3☯"), - ENCHANTING_WISDOM("§3☯"), - ALCHEMY_WISDOM("§3☯"), - CARPENTRY_WISDOM("§3☯"), - RUNECRAFTING_WISDOM("§3☯"), - SOCIAL_WISDOM("§3☯"), - TAMING_WISDOM("§3☯"), - MINING_SPEED("§6⸕"), - BREAKING_POWER("§2Ⓟ"), - PRISTINE("§5✧"), - FORAGING_FORTUNE("§☘"), - FARMING_FORTUNE("§6☘"), - - MINING_SPREAD("§e▚"), - MINING_FORTUNE("§6☘"), - ORE_FORTUNE("§6☘"), - DWARVEN_METAL_FORTUNE("§6☘"), - BLOCK_FORTUNE("§6☘"), - GEMSTONE_FORTUNE("§6☘"), - - FEAR("§a☠"), - HEAT_RESISTANCE("§c♨"), - - UNKNOWN("§c?") +enum class SkyblockStat( + val icon: String, + @Language("RegExp") tabListPatternS: String, + @Language("RegExp") menuPatternS: String, +) { + 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(?.*)"), + INTELLIGENCE("§b✎", " Intelligence: §r§b✎(?.*)", " §b✎ Intelligence §f(?.*)"), // TODO get from action bar + CRIT_DAMAGE("§9☠", " Crit Damage: §r§9☠(?.*)", " §9☠ Crit Damage §f(?.*)"), + CRIT_CHANCE("§9☣", " Crit Chance: §r§9☣(?.*)", " §9☣ Crit Chance §f(?.*)"), + FEROCITY("§c⫽", " Ferocity: §r§c⫽(?.*)", " §c⫽ Ferocity §f(?.*)"), + BONUS_ATTACK_SPEED("§e⚔", " Attack Speed: §r§e⚔(?.*)", " §e⚔ Bonus Attack Speed §f(?.*)"), + ABILITY_DAMAGE("§c๑", " Ability Damage: §r§c๑(?.*)", " §c๑ Ability Damage §f(?.*)"), + HEALTH_REGEN("§c❣", " Health Regen: §r§c❣(?.*)", " §c❣ Health Regen §f(?.*)"), + VITALITY("§4♨", " Vitality: §r§4♨(?.*)", " §4♨ Vitality §f(?.*)"), + MENDING("§a☄", " Mending: §r§a☄(?.*)", " §a☄ Mending §f(?.*)"), + TRUE_DEFENCE("§7❂", " True Defense: §r§f❂(?.*)", " §f❂ True Defense §f(?.*)"), + SWING_RANGE("§eⓈ", " Swing Range: §r§eⓈ(?.*)", " §eⓈ Swing Range §f(?.*)"), + SPEED("§f✦", " Speed: §r§f✦(?.*)", " §f✦ Speed §f(?.*)"), // TODO add the way sba did get it (be careful with 500+ Speed) + SEA_CREATURE_CHANCE("§3α", " Sea Creature Chance: §r§3α(?.*)", " §3α Sea Creature Chance §f(?.*)"), + MAGIC_FIND("§b✯", " Magic Find: §r§b✯(?.*)", " §b✯ Magic Find §f(?.*)"), + PET_LUCK("§d♣", " Pet Luck: §r§d♣(?.*)", " §d♣ Pet Luck §f(?.*)"), + FISHING_SPEED("§b☂", " Fishing Speed: §r§b☂(?.*)", " §b☂ Fishing Speed §f(?.*)"), + DOUBLE_HOOK_CHANCE("§9⚓", " Double Hook Chance: §r§9⚓(?.*)", ""), + BONUS_PEST_CHANCE("§2ൠ", " (?:§r§7§m)?Bonus Pest Chance: (?:§r§2)?ൠ(?.*)", " (?:§7§m|§2)ൠ Bonus Pest Chance (?:§f)?(?.*)"), + COMBAT_WISDOM("§3☯", " Combat Wisdom: §r§3☯(?.*)", " §3☯ Combat Wisdom §f(?.*)"), + MINING_WISDOM("§3☯", " Mining Wisdom: §r§3☯(?.*)", " §3☯ Mining Wisdom §f(?.*)"), + FARMING_WISDOM("§3☯", " Farming Wisdom: §r§3☯(?.*)", " §3☯ Farming Wisdom §f(?.*)"), + FORAGING_WISDOM("§3☯", " Foraging Wisdom: §r§3☯(?.*)", " §3☯ Foraging Wisdom §f(?.*)"), + FISHING_WISDOM("§3☯", " Fishing Wisdom: §r§3☯(?.*)", " §3☯ Fishing Wisdom §f(?.*)"), + ENCHANTING_WISDOM("§3☯", " Enchanting Wisdom: §r§3☯(?.*)", " §3☯ Enchanting Wisdom §f(?.*)"), + ALCHEMY_WISDOM("§3☯", " Alchemy Wisdom: §r§3☯(?.*)", " §3☯ Alchemy Wisdom §f(?.*)"), + CARPENTRY_WISDOM("§3☯", " Carpentry Wisdom: §r§3☯(?.*)", " §3☯ Carpentry Wisdom §f(?.*)"), + RUNECRAFTING_WISDOM("§3☯", " Runecrafting Wisdom: §r§3☯(?.*)", " §3☯ Runecrafting Wisdom §f(?.*)"), + SOCIAL_WISDOM("§3☯", " Social Wisdom: §r§3☯(?.*)", " §3☯ Social Wisdom §f(?.*)"), + TAMING_WISDOM("§3☯", " Taming Wisdom: §r§3☯(?.*)", " §3☯ Taming Wisdom §f(?.*)"), + MINING_SPEED("§6⸕", " Mining Speed: §r§6⸕(?.*)", " §6⸕ Mining Speed §f(?.*)"), + BREAKING_POWER("§2Ⓟ", "", " §2Ⓟ Breaking Power §f(?.*)"), + PRISTINE("§5✧", " Pristine: §r§5✧(?.*)", " §5✧ Pristine §f(?.*)"), + FORAGING_FORTUNE("§☘", " Foraging Fortune: §r§6☘(?.*)", " §6☘ Foraging Fortune §f(?.*)"), + FARMING_FORTUNE("§6☘", " (?:§r§7§m)?Farming Fortune: (?:§r§6)?☘(?.*)", " (?:§7§m|§6)☘ Farming Fortune (?:§f)?(?.*)"), + MINING_FORTUNE("§6☘", " Mining Fortune: §r§6☘(?.*)", " §6☘ Mining Fortune §f(?.*)"), + FEAR("§a☠", "", ""), // Skyblock does not like fear. It only shows during Great Spook, therefore no Data. + COLD_RESISTANCE("§b❄", " Cold Resistance: §r§b❄(?.*)", ""), + WHEAT_FORTUNE("§7☘", "", " §7(?:§m)☘ Wheat Fortune (?.*)"), + CARROT_FORTUNE("§7☘", "", " §7(?:§m)☘ Carrot Fortune (?.*)"), + POTATO_FORTUNE("§7☘", "", " §7(?:§m)☘ Potato Fortune (?.*)"), + PUMPKIN_FORTUNE("§7☘", "", " §7(?:§m)☘ Pumpkin Fortune (?.*)"), + MELON_FORTUNE("§7☘", "", " §7(?:§m)☘ Melon Fortune (?.*)"), + MUSHROOM_FORTUNE("§7☘", "", " §7(?:§m)☘ Mushroom Fortune (?.*)"), + CACTUS_FORTUNE("§7☘", "", " §7(?:§m)☘ Cactus Fortune (?.*)"), + NETHER_WART_FORTUNE("§7☘", "", " §7(?:§m)☘ Nether Wart Fortune (?.*)"), + COCOA_BEANS_FORTUNE("§7☘", "", " §7(?:§m)☘ Cocoa Beans Fortune (?.*)"), + SUGAR_CANE_FORTUNE("§7☘", "", " §7(?:§m)☘ Sugar Cane Fortune (?.*)"), + + MINING_SPREAD("§e▚", " (§r§7§m)?Mining Spread: (§r§e)?▚(?.*)", " (§7§m|§e)▚ Mining Spread (§f)?(?.*)"), + GEMSTONE_SPREAD("§e▚", " (§r§7§m)?Mining Spread: (§r§e)?▚(?.*)", " (§7§m|§e)▚ Gemstone Spread (§f)?(?.*)"), + ORE_FORTUNE("§6☘", " Ore Fortune: §r§6☘(?.*)", " §6☘ Ore Fortune §f103"), + DWARVEN_METAL_FORTUNE("§6☘", " Dwarven Metal Fortune: §r§6☘(?.*)", " §6☘ Dwarven Metal Fortune §f(?.*)"), + BLOCK_FORTUNE("§6☘", " Block Fortune: §r§6☘(?.*)", " §6☘ Block Fortune §f(?.*)"), + GEMSTONE_FORTUNE("§6☘", " Gemstone Fortune: §r§6☘(?.*)", " §6☘ Gemstone Fortune §f(?.*)"), + HEAT_RESISTANCE("§c♨", " Heat Resistance: §r§c♨(?.*)", " §c♨ Heat Resistance §f(?.*)"), + + UNKNOWN("§c?", "", "") ; + var lastKnownValue: Double + get() = ProfileStorageData.profileSpecific?.stats?.get(this) ?: 0.0 + set(value) { + ProfileStorageData.profileSpecific?.stats?.set(this, value) + } + + var lastSource: StatSourceType = StatSourceType.UNKNOWN + val capitalizedName = name.lowercase().allLettersFirstUppercase() val iconWithName = "$icon $capitalizedName" + val keyName = name.lowercase().replace('_', '.') + + val displayValue get() = icon + lastKnownValue.roundToInt() + + val tablistPattern by RepoPattern.pattern("stats.tablist.$keyName", tabListPatternS) + val menuPattern by RepoPattern.pattern("stats.menu.$keyName", menuPatternS) + fun asString(value: Int) = (if (value > 0) "+" else "") + value.toString() + " " + this.icon + @SkyHanniModule companion object { + val fontSizeOfLargestIcon by lazy { entries.maxOf { Minecraft.getMinecraft().fontRendererObj.getStringWidth(it.icon) } + 1 } @@ -71,6 +117,59 @@ enum class SkyblockStat(val icon: String) { fun getValueOrNull(string: String): SkyblockStat? = entries.firstOrNull { it.name == string } fun getValue(string: String): SkyblockStat = getValueOrNull(string) ?: UNKNOWN + + init { + entries.forEach { + it.tablistPattern + it.menuPattern + } + } + + @SubscribeEvent + fun onInventory(event: InventoryFullyOpenedEvent) { + if (!LorenzUtils.inSkyBlock) return + onSkyblockMenu(event) + onStatsMenu(event) + } + + private const val PLAYER_STATS_SLOT_INDEX = 13 + + 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 + assignEntry(list, StatSourceType.SKYBLOCK_MENU) { it.menuPattern } + } + } + + private val statsMenuRelevantSlotIndexes = listOf(15, 16, 24, 25) + + private fun onStatsMenu(event: InventoryFullyOpenedEvent) { + 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 + assignEntry(list, StatSourceType.STATS_MENU) { it.menuPattern } + } + } + + @SubscribeEvent + fun onTabList(event: WidgetUpdateEvent) { + if (!event.isWidget(TabWidget.STATS, TabWidget.DUNGEON_SKILLS_AND_STATS)) return + val type = if (event.isWidget(TabWidget.DUNGEON_SKILLS_AND_STATS)) StatSourceType.TABLIST_DUNGEON else StatSourceType.TABLIST + assignEntry(event.lines, type) { it.tablistPattern } + } + + private fun assignEntry(lines: List, type: StatSourceType, pattern: (SkyblockStat) -> Pattern) { + for (line in lines) for (entry in entries) { + val matchResult = pattern(entry).matchMatcher(line) { + groupOrNull("value")?.replace("[,%]".toRegex(), "")?.toDouble() + } ?: continue + entry.lastKnownValue = matchResult + entry.lastSource = type + break // Exit the inner loop once a match is found + } + } } } @@ -93,3 +192,10 @@ class SkyblockStatList : EnumMap(SkyblockStat::class.java) } } +enum class StatSourceType { + UNKNOWN, + SKYBLOCK_MENU, + STATS_MENU, + TABLIST, + TABLIST_DUNGEON, +} 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 ec6f0cbd9ebe..babbb2558def 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt @@ -36,7 +36,7 @@ class RepoManager(private val configLocation: File) { private var latestRepoCommit: String? = null val repoLocation: File = File(configLocation, "repo") private var error = false - private var lastRepoUpdate = SimpleTimeMark.farPast() + private var lastRepoUpdate = SimpleTimeMark.now() companion object { @@ -165,8 +165,8 @@ class RepoManager(private val configLocation: File) { } } - private fun reloadRepository(answerMessage: String = ""): CompletableFuture { - val comp = CompletableFuture() + private fun reloadRepository(answerMessage: String = ""): CompletableFuture { + val comp = CompletableFuture() if (!atomicShouldManuallyReload.get()) return comp ErrorManager.resetCache() DelayedRun.onThread.execute { @@ -232,8 +232,10 @@ class RepoManager(private val configLocation: File) { if (unsuccessfulConstants.isNotEmpty()) { val text = mutableListOf() text.add( - ("§c[SkyHanni-${SkyHanniMod.version}] §7Repo Issue! Some features may not work. " + - "Please report this error on the Discord!").asComponent(), + ( + "§c[SkyHanni-${SkyHanniMod.version}] §7Repo Issue! Some features may not work. " + + "Please report this error on the Discord!" + ).asComponent(), ) text.add("§7Repo Auto Update Value: §c${config.repoAutoUpdate}".asComponent()) text.add("§7If you have Repo Auto Update turned off, please try turning that on.".asComponent()) @@ -286,13 +288,13 @@ class RepoManager(private val configLocation: File) { val repoUser = config.location.user val repoName = config.location.name val repoBranch = config.location.branch - return String.format("https://api.github.com/repos/%s/%s/commits/%s", repoUser, repoName, repoBranch) + return "https://api.github.com/repos/$repoUser/$repoName/commits/$repoBranch" } private fun getDownloadUrl(commitId: String?): String { val repoUser = config.location.user val repoName = config.location.name - return String.format("https://github.com/%s/%s/archive/%s.zip", repoUser, repoName, commitId) + return "https://github.com/$repoUser/$repoName/archive/$commitId.zip" } @Throws(IOException::class) diff --git a/src/main/java/at/hannibal2/skyhanni/events/BlockClickEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/BlockClickEvent.kt index 2822c28a98c5..42587b3909db 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/BlockClickEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/BlockClickEvent.kt @@ -4,9 +4,7 @@ import at.hannibal2.skyhanni.data.ClickType import at.hannibal2.skyhanni.utils.BlockUtils.getBlockStateAt import at.hannibal2.skyhanni.utils.LorenzVec import net.minecraft.item.ItemStack -import net.minecraftforge.fml.common.eventhandler.Cancelable -@Cancelable class BlockClickEvent(clickType: ClickType, val position: LorenzVec, itemInHand: ItemStack?) : WorldClickEvent(itemInHand, clickType) { diff --git a/src/main/java/at/hannibal2/skyhanni/events/BossHealthChangeEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/BossHealthChangeEvent.kt index 10efc2823f20..42a827123411 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/BossHealthChangeEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/BossHealthChangeEvent.kt @@ -2,5 +2,4 @@ package at.hannibal2.skyhanni.events import at.hannibal2.skyhanni.features.combat.damageindicator.EntityData -class BossHealthChangeEvent(val entityData: EntityData, val lastHealth: Long, val health: Long, val maxHealth: Long) : - LorenzEvent() \ No newline at end of file +class BossHealthChangeEvent(val entityData: EntityData, val lastHealth: Long, val health: Long, val maxHealth: Long) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/BurrowDetectEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/BurrowDetectEvent.kt index cca221932138..26e13c42daa6 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/BurrowDetectEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/BurrowDetectEvent.kt @@ -3,4 +3,4 @@ package at.hannibal2.skyhanni.events import at.hannibal2.skyhanni.features.event.diana.BurrowType import at.hannibal2.skyhanni.utils.LorenzVec -class BurrowDetectEvent(val burrowLocation: LorenzVec, val type: BurrowType) : LorenzEvent() \ No newline at end of file +class BurrowDetectEvent(val burrowLocation: LorenzVec, val type: BurrowType) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/BurrowDugEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/BurrowDugEvent.kt index d362cca0901b..3f601fd2bb31 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/BurrowDugEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/BurrowDugEvent.kt @@ -2,4 +2,4 @@ package at.hannibal2.skyhanni.events import at.hannibal2.skyhanni.utils.LorenzVec -class BurrowDugEvent(val burrowLocation: LorenzVec) : LorenzEvent() \ No newline at end of file +class BurrowDugEvent(val burrowLocation: LorenzVec) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/CollectionUpdateEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/CollectionUpdateEvent.kt index b62dcb14925c..f4c46d0b75d5 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/CollectionUpdateEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/CollectionUpdateEvent.kt @@ -1,3 +1,3 @@ package at.hannibal2.skyhanni.events -class CollectionUpdateEvent : LorenzEvent() \ No newline at end of file +class CollectionUpdateEvent : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/ConfigLoadEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/ConfigLoadEvent.kt index b5afff5477b9..4f1efeb9c246 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/ConfigLoadEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/ConfigLoadEvent.kt @@ -1,3 +1,3 @@ package at.hannibal2.skyhanni.events -class ConfigLoadEvent : LorenzEvent() \ No newline at end of file +class ConfigLoadEvent : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/CropMilestoneUpdateEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/CropMilestoneUpdateEvent.kt index 9ca3bd56b843..8da8b20f75ce 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/CropMilestoneUpdateEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/CropMilestoneUpdateEvent.kt @@ -1,3 +1,3 @@ package at.hannibal2.skyhanni.events -class CropMilestoneUpdateEvent : LorenzEvent() \ No newline at end of file +class CropMilestoneUpdateEvent : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/DamageIndicatorDeathEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/DamageIndicatorDeathEvent.kt index 141f293a388d..95b08ec51926 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/DamageIndicatorDeathEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/DamageIndicatorDeathEvent.kt @@ -4,3 +4,4 @@ import at.hannibal2.skyhanni.features.combat.damageindicator.EntityData import net.minecraft.entity.EntityLivingBase class DamageIndicatorDeathEvent(val entity: EntityLivingBase, val data: EntityData) : LorenzEvent() + diff --git a/src/main/java/at/hannibal2/skyhanni/events/DamageIndicatorDetectedEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/DamageIndicatorDetectedEvent.kt index dbf2fd130e9a..2ca276e4c884 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/DamageIndicatorDetectedEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/DamageIndicatorDetectedEvent.kt @@ -2,4 +2,4 @@ package at.hannibal2.skyhanni.events import at.hannibal2.skyhanni.features.combat.damageindicator.EntityData -class DamageIndicatorDetectedEvent(val entityData: EntityData) : LorenzEvent() \ No newline at end of file +class DamageIndicatorDetectedEvent(val entityData: EntityData) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/DamageIndicatorFinalBossEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/DamageIndicatorFinalBossEvent.kt index 88e41538afb3..0d2564005091 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/DamageIndicatorFinalBossEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/DamageIndicatorFinalBossEvent.kt @@ -1,3 +1,3 @@ package at.hannibal2.skyhanni.events -class DamageIndicatorFinalBossEvent(val id: Int) : LorenzEvent() \ No newline at end of file +class DamageIndicatorFinalBossEvent(val id: Int) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/DrawScreenAfterEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/DrawScreenAfterEvent.kt index ba278df24643..822b80419983 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/DrawScreenAfterEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/DrawScreenAfterEvent.kt @@ -2,4 +2,4 @@ package at.hannibal2.skyhanni.events import org.spongepowered.asm.mixin.injection.callback.CallbackInfo -class DrawScreenAfterEvent(val mouseX: Int, val mouseY: Int, val ci: CallbackInfo) : LorenzEvent() \ No newline at end of file +class DrawScreenAfterEvent(val mouseX: Int, val mouseY: Int, val ci: CallbackInfo) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/DungeonClickedBlockEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/DungeonBlockClickEvent.kt similarity index 99% rename from src/main/java/at/hannibal2/skyhanni/events/DungeonClickedBlockEvent.kt rename to src/main/java/at/hannibal2/skyhanni/events/DungeonBlockClickEvent.kt index 9a7f5119aa64..84d1b822f6b4 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/DungeonClickedBlockEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/DungeonBlockClickEvent.kt @@ -5,3 +5,4 @@ import at.hannibal2.skyhanni.data.ClickedBlockType import at.hannibal2.skyhanni.utils.LorenzVec class DungeonBlockClickEvent(val position: LorenzVec, val blockType: ClickedBlockType) : SkyHanniEvent() + diff --git a/src/main/java/at/hannibal2/skyhanni/events/DungeonBossPhaseChangeEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/DungeonBossPhaseChangeEvent.kt new file mode 100644 index 000000000000..92d6be3d5892 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/events/DungeonBossPhaseChangeEvent.kt @@ -0,0 +1,6 @@ +package at.hannibal2.skyhanni.events + +import at.hannibal2.skyhanni.api.event.SkyHanniEvent +import at.hannibal2.skyhanni.features.dungeon.DungeonBossAPI + +class DungeonBossPhaseChangeEvent(val newPhase: DungeonBossAPI.DungeonBossPhase) : SkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/DungeonBossRoomEnterEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/DungeonBossRoomEnterEvent.kt index 243268181e41..9f372d5c31c2 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/DungeonBossRoomEnterEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/DungeonBossRoomEnterEvent.kt @@ -1,3 +1,3 @@ package at.hannibal2.skyhanni.events -class DungeonBossRoomEnterEvent : LorenzEvent() \ No newline at end of file +class DungeonBossRoomEnterEvent : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/DungeonEnterEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/DungeonEnterEvent.kt index b980c75953f1..3b0f09c4a096 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/DungeonEnterEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/DungeonEnterEvent.kt @@ -1,3 +1,3 @@ package at.hannibal2.skyhanni.events -class DungeonEnterEvent(dungeonFloor: String) : LorenzEvent() \ No newline at end of file +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 b4de1e6c90ba..a2b127371089 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/DungeonStartEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/DungeonStartEvent.kt @@ -1,3 +1,3 @@ package at.hannibal2.skyhanni.events -class DungeonStartEvent(dungeonFloor: String) : LorenzEvent() \ No newline at end of file +class DungeonStartEvent(dungeonFloor: String) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/EntityClickEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/EntityClickEvent.kt index d0cf14214789..2c85ef110670 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/EntityClickEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/EntityClickEvent.kt @@ -3,8 +3,6 @@ package at.hannibal2.skyhanni.events import at.hannibal2.skyhanni.data.ClickType import net.minecraft.entity.Entity import net.minecraft.item.ItemStack -import net.minecraftforge.fml.common.eventhandler.Cancelable -@Cancelable class EntityClickEvent(clickType: ClickType, val clickedEntity: Entity?, itemInHand: ItemStack?) : WorldClickEvent(itemInHand, clickType) diff --git a/src/main/java/at/hannibal2/skyhanni/events/EntityHealthUpdateEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/EntityHealthUpdateEvent.kt index 5fbcfb9d7c8a..162efd9caa59 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/EntityHealthUpdateEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/EntityHealthUpdateEvent.kt @@ -2,4 +2,4 @@ package at.hannibal2.skyhanni.events import net.minecraft.entity.EntityLivingBase -class EntityHealthUpdateEvent(val entity: EntityLivingBase, val health: Int) : LorenzEvent() \ No newline at end of file +class EntityHealthUpdateEvent(val entity: EntityLivingBase, val health: Int) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/EntityMaxHealthUpdateEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/EntityMaxHealthUpdateEvent.kt index 116e81797590..943a11cc3720 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/EntityMaxHealthUpdateEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/EntityMaxHealthUpdateEvent.kt @@ -2,4 +2,4 @@ package at.hannibal2.skyhanni.events import net.minecraft.entity.EntityLivingBase -class EntityMaxHealthUpdateEvent(val entity: EntityLivingBase, val maxHealth: Int) : LorenzEvent() \ No newline at end of file +class EntityMaxHealthUpdateEvent(val entity: EntityLivingBase, val maxHealth: Int) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/FarmingContestEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/FarmingContestEvent.kt index 75521bacd506..5a4a83c1f829 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/FarmingContestEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/FarmingContestEvent.kt @@ -3,4 +3,4 @@ package at.hannibal2.skyhanni.events import at.hannibal2.skyhanni.features.garden.CropType import at.hannibal2.skyhanni.features.garden.contest.FarmingContestPhase -class FarmingContestEvent(val crop: CropType, val phase: FarmingContestPhase) : LorenzEvent() \ No newline at end of file +class FarmingContestEvent(val crop: CropType, val phase: FarmingContestPhase) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/GardenToolChangeEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/GardenToolChangeEvent.kt index 742dac58df46..2ad07aad8975 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/GardenToolChangeEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/GardenToolChangeEvent.kt @@ -3,4 +3,4 @@ package at.hannibal2.skyhanni.events import at.hannibal2.skyhanni.features.garden.CropType import net.minecraft.item.ItemStack -class GardenToolChangeEvent(val crop: CropType?, val toolItem: ItemStack?) : LorenzEvent() \ No newline at end of file +class GardenToolChangeEvent(val crop: CropType?, val toolItem: ItemStack?) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/GuiRenderEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/GuiRenderEvent.kt index a9d190f89eba..954bd0733391 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/GuiRenderEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/GuiRenderEvent.kt @@ -3,4 +3,4 @@ package at.hannibal2.skyhanni.events open class GuiRenderEvent : LorenzEvent() { class ChestGuiOverlayRenderEvent : GuiRenderEvent() class GuiOverlayRenderEvent : GuiRenderEvent() -} \ No newline at end of file +} diff --git a/src/main/java/at/hannibal2/skyhanni/events/HypixelJoinEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/HypixelJoinEvent.kt index 044d63daae37..6f7711118be6 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/HypixelJoinEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/HypixelJoinEvent.kt @@ -1,3 +1,3 @@ package at.hannibal2.skyhanni.events -class HypixelJoinEvent : LorenzEvent() \ No newline at end of file +class HypixelJoinEvent : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/IslandChangeEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/IslandChangeEvent.kt index 291ccd995db9..ae22a4c751ad 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/IslandChangeEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/IslandChangeEvent.kt @@ -2,4 +2,4 @@ package at.hannibal2.skyhanni.events import at.hannibal2.skyhanni.data.IslandType -class IslandChangeEvent(val newIsland: IslandType, val oldIsland: IslandType) : LorenzEvent() \ No newline at end of file +class IslandChangeEvent(val newIsland: IslandType, val oldIsland: IslandType) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/ItemClickEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/ItemClickEvent.kt index a34cb43f19de..e0a96d7e5db6 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/ItemClickEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/ItemClickEvent.kt @@ -2,7 +2,5 @@ package at.hannibal2.skyhanni.events import at.hannibal2.skyhanni.data.ClickType import net.minecraft.item.ItemStack -import net.minecraftforge.fml.common.eventhandler.Cancelable -@Cancelable class ItemClickEvent(itemInHand: ItemStack?, clickType: ClickType) : WorldClickEvent(itemInHand, clickType) diff --git a/src/main/java/at/hannibal2/skyhanni/events/LorenzEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/LorenzEvent.kt index 4a294a6779ca..b567d9ae6d06 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/LorenzEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/LorenzEvent.kt @@ -7,6 +7,7 @@ import at.hannibal2.skyhanni.mixins.hooks.setValue import at.hannibal2.skyhanni.mixins.transformers.AccessorEventBus import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.StringUtils import at.hannibal2.skyhanni.utils.chat.Text import at.hannibal2.skyhanni.utils.system.PlatformUtils import net.minecraftforge.common.MinecraftForge @@ -57,7 +58,8 @@ abstract class LorenzEvent : Event() { if (printError && errors <= visibleErrors) { val callerName = listener.toString().split(" ")[1].split("@")[0].split(".").last() val errorName = throwable::class.simpleName ?: "error" - val message = "Caught an $errorName in $callerName at $eventName: ${throwable.message}" + val aOrAn = StringUtils.optionalAn(errorName) + val message = "Caught $aOrAn $errorName in $callerName at $eventName: ${throwable.message}" ErrorManager.logErrorWithData(throwable, message, ignoreErrorCache = ignoreErrorCache) } onError(throwable) diff --git a/src/main/java/at/hannibal2/skyhanni/events/LorenzKeyPressEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/LorenzKeyPressEvent.kt index 70997f0c1abb..e5af23d22ab6 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/LorenzKeyPressEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/LorenzKeyPressEvent.kt @@ -1,3 +1,3 @@ package at.hannibal2.skyhanni.events -class LorenzKeyPressEvent(val keyCode: Int) : LorenzEvent() \ No newline at end of file +class LorenzKeyPressEvent(val keyCode: Int) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/LorenzRenderWorldEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/LorenzRenderWorldEvent.kt index 5ce44df0db15..f61f0e16d35d 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/LorenzRenderWorldEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/LorenzRenderWorldEvent.kt @@ -1,3 +1,3 @@ package at.hannibal2.skyhanni.events -class LorenzRenderWorldEvent(val partialTicks: Float) : LorenzEvent() \ No newline at end of file +class LorenzRenderWorldEvent(val partialTicks: Float) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/LorenzWorldChangeEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/LorenzWorldChangeEvent.kt index c815e96302fd..de67180273b0 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/LorenzWorldChangeEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/LorenzWorldChangeEvent.kt @@ -1,3 +1,3 @@ package at.hannibal2.skyhanni.events -class LorenzWorldChangeEvent : LorenzEvent() \ No newline at end of file +class LorenzWorldChangeEvent : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/RenderBlockInWorldEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/RenderBlockInWorldEvent.kt index 4aa3ef9dc4e7..395d1be2db0c 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/RenderBlockInWorldEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/RenderBlockInWorldEvent.kt @@ -6,5 +6,4 @@ import net.minecraft.world.IBlockAccess import net.minecraftforge.fml.common.eventhandler.Cancelable @Cancelable -data class RenderBlockInWorldEvent(@JvmField var state: IBlockState?, var world: IBlockAccess, var pos: BlockPos?) : - LorenzEvent() \ No newline at end of file +data class RenderBlockInWorldEvent(@JvmField var state: IBlockState?, var world: IBlockAccess, var pos: BlockPos?) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/RenderInventoryItemTipEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/RenderInventoryItemTipEvent.kt index 7bb4692ece5a..0f16dad2a4a1 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/RenderInventoryItemTipEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/RenderInventoryItemTipEvent.kt @@ -11,4 +11,4 @@ class RenderInventoryItemTipEvent( var offsetX: Int = 0, var offsetY: Int = 0, var alignLeft: Boolean = true, -) : LorenzEvent() \ No newline at end of file +) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/SlayerChangeEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/SlayerChangeEvent.kt index 7c70dde5d53e..c7da7f7bd7d3 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/SlayerChangeEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/SlayerChangeEvent.kt @@ -1,3 +1,3 @@ package at.hannibal2.skyhanni.events -class SlayerChangeEvent(val oldSlayer: String, val newSlayer: String) : LorenzEvent() \ No newline at end of file +class SlayerChangeEvent(val oldSlayer: String, val newSlayer: String) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/SlayerProgressChangeEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/SlayerProgressChangeEvent.kt index 95ecf447f706..b87a854e1922 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/SlayerProgressChangeEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/SlayerProgressChangeEvent.kt @@ -1,3 +1,3 @@ package at.hannibal2.skyhanni.events -class SlayerProgressChangeEvent(val oldProgress: String, val newProgress: String) : LorenzEvent() \ No newline at end of file +class SlayerProgressChangeEvent(val oldProgress: String, val newProgress: String) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/SlayerQuestCompleteEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/SlayerQuestCompleteEvent.kt index 8c7aa753ee8b..b7e0edfedd59 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/SlayerQuestCompleteEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/SlayerQuestCompleteEvent.kt @@ -1,3 +1,3 @@ package at.hannibal2.skyhanni.events -class SlayerQuestCompleteEvent : LorenzEvent() \ No newline at end of file +class SlayerQuestCompleteEvent : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/TabListLineRenderEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/TabListLineRenderEvent.kt index 8916c55faa4c..47478959291d 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/TabListLineRenderEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/TabListLineRenderEvent.kt @@ -1,3 +1,3 @@ package at.hannibal2.skyhanni.events -class TabListLineRenderEvent(var text: String) : LorenzEvent() \ No newline at end of file +class TabListLineRenderEvent(var text: String) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/TabListUpdateEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/TabListUpdateEvent.kt index b3ab18bab956..a1b36a667fb3 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/TabListUpdateEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/TabListUpdateEvent.kt @@ -1,3 +1,3 @@ package at.hannibal2.skyhanni.events -class TabListUpdateEvent(val tabList: List) : LorenzEvent() \ No newline at end of file +class TabListUpdateEvent(val tabList: List) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/TitleReceivedEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/TitleReceivedEvent.kt index 2576809cc93e..912a4d8d6564 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/TitleReceivedEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/TitleReceivedEvent.kt @@ -3,4 +3,4 @@ package at.hannibal2.skyhanni.events import net.minecraftforge.fml.common.eventhandler.Cancelable @Cancelable -class TitleReceivedEvent(val title: String) : LorenzEvent() \ No newline at end of file +class TitleReceivedEvent(val title: String) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/WorldClickEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/WorldClickEvent.kt index 4597041a1d32..ff3892859ce4 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/WorldClickEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/WorldClickEvent.kt @@ -1,8 +1,7 @@ package at.hannibal2.skyhanni.events +import at.hannibal2.skyhanni.api.event.CancellableSkyHanniEvent import at.hannibal2.skyhanni.data.ClickType import net.minecraft.item.ItemStack -import net.minecraftforge.fml.common.eventhandler.Cancelable -@Cancelable -open class WorldClickEvent(val itemInHand: ItemStack?, val clickType: ClickType) : LorenzEvent() +open class WorldClickEvent(val itemInHand: ItemStack?, val clickType: ClickType) : CancellableSkyHanniEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorAcceptEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorAcceptEvent.kt index 4a494f35314f..41a429cfd372 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorAcceptEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorAcceptEvent.kt @@ -3,4 +3,4 @@ package at.hannibal2.skyhanni.events.garden.visitor import at.hannibal2.skyhanni.events.LorenzEvent import at.hannibal2.skyhanni.features.garden.visitor.VisitorAPI -class VisitorAcceptEvent(val visitor: VisitorAPI.Visitor) : LorenzEvent() \ No newline at end of file +class VisitorAcceptEvent(val visitor: VisitorAPI.Visitor) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorAcceptedEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorAcceptedEvent.kt index e3bffed8b923..5b894768fb39 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorAcceptedEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorAcceptedEvent.kt @@ -3,4 +3,4 @@ package at.hannibal2.skyhanni.events.garden.visitor import at.hannibal2.skyhanni.events.LorenzEvent import at.hannibal2.skyhanni.features.garden.visitor.VisitorAPI -class VisitorAcceptedEvent(val visitor: VisitorAPI.Visitor) : LorenzEvent() \ No newline at end of file +class VisitorAcceptedEvent(val visitor: VisitorAPI.Visitor) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorArrivalEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorArrivalEvent.kt index 673f45e201b6..f26dbb971275 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorArrivalEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorArrivalEvent.kt @@ -3,4 +3,4 @@ package at.hannibal2.skyhanni.events.garden.visitor import at.hannibal2.skyhanni.events.LorenzEvent import at.hannibal2.skyhanni.features.garden.visitor.VisitorAPI.Visitor -class VisitorArrivalEvent(val visitor: Visitor) : LorenzEvent() \ No newline at end of file +class VisitorArrivalEvent(val visitor: Visitor) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorLeftEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorLeftEvent.kt index f906364ced2b..f5673decd0e4 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorLeftEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorLeftEvent.kt @@ -3,4 +3,4 @@ package at.hannibal2.skyhanni.events.garden.visitor import at.hannibal2.skyhanni.events.LorenzEvent import at.hannibal2.skyhanni.features.garden.visitor.VisitorAPI -class VisitorLeftEvent(val visitor: VisitorAPI.Visitor) : LorenzEvent() \ No newline at end of file +class VisitorLeftEvent(val visitor: VisitorAPI.Visitor) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorOpenEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorOpenEvent.kt index 6abec9865725..c2e7a40b0c3d 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorOpenEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorOpenEvent.kt @@ -3,4 +3,4 @@ package at.hannibal2.skyhanni.events.garden.visitor import at.hannibal2.skyhanni.events.LorenzEvent import at.hannibal2.skyhanni.features.garden.visitor.VisitorAPI -class VisitorOpenEvent(val visitor: VisitorAPI.Visitor) : LorenzEvent() \ No newline at end of file +class VisitorOpenEvent(val visitor: VisitorAPI.Visitor) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorRefusedEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorRefusedEvent.kt index fea24fba9bb8..94de16081b04 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorRefusedEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorRefusedEvent.kt @@ -3,4 +3,4 @@ package at.hannibal2.skyhanni.events.garden.visitor import at.hannibal2.skyhanni.events.LorenzEvent import at.hannibal2.skyhanni.features.garden.visitor.VisitorAPI -class VisitorRefusedEvent(val visitor: VisitorAPI.Visitor) : LorenzEvent() \ No newline at end of file +class VisitorRefusedEvent(val visitor: VisitorAPI.Visitor) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorRenderEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorRenderEvent.kt index 7cbdc8224fb0..9282d3e04fe6 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorRenderEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/garden/visitor/VisitorRenderEvent.kt @@ -5,5 +5,4 @@ import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent import at.hannibal2.skyhanni.features.garden.visitor.VisitorAPI import at.hannibal2.skyhanni.utils.LorenzVec -class VisitorRenderEvent(val visitor: VisitorAPI.Visitor, val location: LorenzVec, val parent: LorenzRenderWorldEvent) : - LorenzEvent() \ No newline at end of file +class VisitorRenderEvent(val visitor: VisitorAPI.Visitor, val location: LorenzVec, val parent: LorenzRenderWorldEvent) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/events/hoppity/EggFoundEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/hoppity/EggFoundEvent.kt index 2cd81811f272..30cd282ac8b4 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/hoppity/EggFoundEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/hoppity/EggFoundEvent.kt @@ -5,6 +5,6 @@ import at.hannibal2.skyhanni.features.event.hoppity.HoppityEggType class EggFoundEvent( val type: HoppityEggType, - val slotIndex: Int?, - val note: String?, + val slotIndex: Int? = null, + val note: String? = null, ) : SkyHanniEvent() 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 94bd4f6dd8dc..b0f883ac240a 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 @@ -85,12 +85,15 @@ object BingoCardDisplay { if (BingoAPI.bingoGoals.isEmpty()) { newList.add(Renderable.string("§6Bingo Goals:")) - newList.add(Renderable.clickAndHover("§cOpen the §e/bingo §ccard.", - listOf("Click to run §e/bingo"), - onClick = { - HypixelCommands.bingo() - } - )) + newList.add( + Renderable.clickAndHover( + "§cOpen the §e/bingo §ccard.", + listOf("Click to run §e/bingo"), + onClick = { + HypixelCommands.bingo() + } + ) + ) } else { if (!config.hideCommunityGoals.get()) { newList.addCommunityGoals() diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardTips.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardTips.kt index abf8bbedc701..83b41d3fd759 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardTips.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardTips.kt @@ -81,9 +81,7 @@ object BingoCardTips { for (line in bingoTip.guide) { toolTip.add(index++, " $line") } - bingoTip.found?.let { - toolTip.add(index++, "§7Found by: §e$it") - } + toolTip.add(index++, "§7Found by: §e${bingoTip.found}") } @SubscribeEvent diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/goals/GoalType.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/goals/GoalType.kt index b2e4f6d8dfbc..6dd666d4e84d 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/goals/GoalType.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/goals/GoalType.kt @@ -3,5 +3,4 @@ package at.hannibal2.skyhanni.features.bingo.card.goals enum class GoalType { COMMUNITY, PERSONAL, - ; } 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 427fbb902b71..69602ec70765 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 @@ -61,7 +61,7 @@ object BingoNextStepHelper { private val itemIslandRequired = mutableMapOf() private val itemPreconditions = mutableMapOf() private val islands = mutableMapOf() - private val rhysTaskName = "30x Enchanted Minerals (Redstone, Lapis Lazuli, Coal) (for Rhys)" + private const val RHYS_TASK_NAME = "30x Enchanted Minerals (Redstone, Lapis Lazuli, Coal) (for Rhys)" private val finalSteps = mutableListOf() private var currentSteps = emptyList() @@ -167,7 +167,7 @@ object BingoNextStepHelper { } } } - if (currentStep is PartialProgressItemsStep && currentStep.displayName == rhysTaskName && 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 } } @@ -275,7 +275,8 @@ object BingoNextStepHelper { "Emerald", 160 * 32, mapOf("Emerald" to 1, "Enchanted Emerald" to 160) - ) requires IslandType.DWARVEN_MINES.getStep()) + ) requires IslandType.DWARVEN_MINES.getStep() + ) } if (description == "Obtain a Mathematical Hoe Blueprint.") { @@ -285,7 +286,8 @@ object BingoNextStepHelper { "Jacob's Ticket", 32, mapOf("Jacob's Ticket" to 1) - ).addItemRequirements() requires IslandType.GARDEN.getStep()) + ).addItemRequirements() requires IslandType.GARDEN.getStep() + ) } crystalPattern.matchMatcher(description) { @@ -365,7 +367,7 @@ object BingoNextStepHelper { private fun rhys() { val redstoneForRhys = PartialProgressItemsStep( - rhysTaskName, + RHYS_TASK_NAME, "Redstone", 160 * 10, mapOf("Redstone" to 1, "Enchanted Redstone" to 160) @@ -373,7 +375,7 @@ object BingoNextStepHelper { redstoneForRhys requires IslandType.DEEP_CAVERNS.getStep() val lapisForRhys = PartialProgressItemsStep( - rhysTaskName, + RHYS_TASK_NAME, "Lapis Lazuli", 160 * 10, mapOf("Lapis Lazuli" to 1, "Enchanted Lapis Lazuli" to 160) @@ -381,7 +383,7 @@ object BingoNextStepHelper { lapisForRhys requires IslandType.DEEP_CAVERNS.getStep() val coalForRhys = PartialProgressItemsStep( - rhysTaskName, + RHYS_TASK_NAME, "Coal", 160 * 10, mapOf("Coal" to 1, "Enchanted Coal" to 160) diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/nextstephelper/steps/CollectionStep.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/nextstephelper/steps/CollectionStep.kt index 7871ae28d512..10c968d845f0 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/nextstephelper/steps/CollectionStep.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/nextstephelper/steps/CollectionStep.kt @@ -6,5 +6,7 @@ import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat class CollectionStep(collectionName: String, amountNeeded: Int) : ProgressionStep(amountNeeded.shortFormat() + " $collectionName Collection", amountNeeded.toLong()) { - val internalName by lazy { NEUInternalName.fromItemName(if (collectionName == "Mushroom") "Red Mushroom" else collectionName) } + val internalName by lazy { + NEUInternalName.fromItemName(if (collectionName == "Mushroom") "Red Mushroom" else collectionName) + } } 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 964b255735af..28a2b4b4f081 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilter.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilter.kt @@ -27,7 +27,7 @@ object ChatFilter { private val config get() = SkyHanniMod.feature.chat.filterType private val dungeonConfig get() = SkyHanniMod.feature.dungeon.messageFilter - /// + // // Lobby Messages private val lobbyPatterns = listOf( // player join @@ -89,15 +89,19 @@ object ChatFilter { ) // Guild EXP + /** + * REGEX-TEST: §aYou earned §r§22 GEXP §r§afrom playing SkyBlock! + * REGEX-TEST: §aYou earned §r§22 GEXP §r§a+ §r§c210 Event EXP §r§afrom playing SkyBlock! + */ private val guildExpPatterns = listOf( - // §aYou earned §r§22 GEXP §r§afrom playing SkyBlock! - // §aYou earned §r§22 GEXP §r§a+ §r§c210 Event EXP §r§afrom playing SkyBlock! "§aYou earned §r§2.* GEXP (§r§a\\+ §r§.* Event EXP )?§r§afrom playing SkyBlock!".toPattern(), ) // Kill Combo + /** + * REGEX-TEST: §a§l+5 Kill Combo §r§8+§r§b3% §r§b? Magic Find + */ private val killComboPatterns = listOf( - //§a§l+5 Kill Combo §r§8+§r§b3% §r§b? Magic Find "§.§l\\+(.*) Kill Combo (.*)".toPattern(), "§cYour Kill Combo has expired! You reached a (.*) Kill Combo!".toPattern(), ) @@ -277,6 +281,7 @@ object ChatFilter { "§6§lGOOD CATCH! §r§bYou found a §r§fSpooky Bait§r§b.", "§e[NPC] Jacob§f: §rMy contest has started!", "§eObtain a §r§6Booster Cookie §r§efrom the community shop in the hub!", + "Unknown command. Type \"/help\" for help. ('uhfdsolguhkjdjfhgkjhdfdlgkjhldkjhlkjhsldkjfhldshkjf')", ) private val skymallMessages = listOf( @@ -500,7 +505,7 @@ object ChatFilter { "slayer" to slayerMessageStartWith, "profile_join" to profileJoinMessageStartsWith, ) - /// + // @SubscribeEvent fun onChat(event: LorenzChatEvent) { @@ -515,6 +520,7 @@ object ChatFilter { * @param message The message to check * @return The reason why the message was blocked, empty if not blocked */ + @Suppress("CyclomaticComplexMethod") private fun block(message: String): String? = when { config.hypixelHub && message.isPresent("lobby") -> "lobby" config.empty && StringUtils.isEmpty(message) -> "empty" diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/ColorFormattingHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/ColorFormattingHelper.kt index 9c7c0380614b..2987d95a680e 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/chat/ColorFormattingHelper.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/ColorFormattingHelper.kt @@ -21,7 +21,7 @@ object ColorFormattingHelper { "§f&k = Obfuscated (like this: §khellspawn§r)\n" + "§f&l = §lBold §r&m = §mStrikethrough \n" + "§f&o = §oItalic §r&n = §nUnderline\n" + - "§f&r = Reset\n"+ + "§f&r = Reset\n" + "§c===================================================" ) ) diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/CompactExperimentRewards.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/CompactExperimentRewards.kt index 286166ee7c0b..8ad277b4a419 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/chat/CompactExperimentRewards.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/CompactExperimentRewards.kt @@ -21,7 +21,7 @@ object CompactExperimentRewards { private val config get() = SkyHanniMod.feature.chat - private var gainedRewards = mutableListOf() + private val gainedRewards = mutableListOf() private var lastTimeTableOpened = SimpleTimeMark.farPast() private var currentMessage = "" @@ -89,7 +89,7 @@ object CompactExperimentRewards { } private fun sendMessage(reward: String?) { - if (gainedRewards.last() != reward || currentMessage == "") return + if (gainedRewards.lastOrNull() != reward || currentMessage == "") return val expList = mutableListOf().apply { gainedRewards.forEach { add("§8+$it") } diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/PlayerDeathMessages.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/PlayerDeathMessages.kt index d256bfe63eb7..2afc9276bbf0 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/chat/PlayerDeathMessages.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/PlayerDeathMessages.kt @@ -35,7 +35,8 @@ object PlayerDeathMessages { if (MarkedPlayerManager.config.highlightInChat && !DungeonAPI.inDungeon() && !LorenzUtils.inKuudraFight && - MarkedPlayerManager.isMarkedPlayer(name)) { + MarkedPlayerManager.isMarkedPlayer(name) + ) { val reason = event.reason val color = MarkedPlayerManager.config.chatColor.getChatColor() ChatUtils.chat(" §c☠ $color$name §7$reason", false) 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 9c100ef47ead..61658a9de62e 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/chat/PowderMiningChatFilter.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/PowderMiningChatFilter.kt @@ -33,6 +33,7 @@ object PowderMiningChatFilter { val patternGroup = RepoPattern.group("filter.powdermining") + // TODO rename to "openedRewards" ? private var unclosedRewards = false /** @@ -61,10 +62,11 @@ 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! */ private val breakingPowerPattern by patternGroup.pattern( "warning.breakingpower", - "§cYou need a tool with a §r§aBreaking Power §r§cof (?:§.)*\\d+§r§c to mine (Ruby|Amethyst|Jade|Amber|Sapphire|Topaz) Gemstone Block§r§c!.+", + "§cYou need a tool with a §r§aBreaking Power §r§cof (?:§.)*\\d+§r§c to mine .+", ) /** @@ -246,12 +248,16 @@ object PowderMiningChatFilter { * REGEX-TEST: §r§a❈ Flawed Amethyst Gemstone §r§8x4 * REGEX-TEST: §r§9⸕ Fine Amber Gemstone * REGEX-TEST: §r§5⸕ Flawless Amber Gemstone + * REGEX-TEST: §r§f❁ Rough Jasper Gemstone §r§8x24 + * REGEX-TEST: §r§a❁ Flawed Jasper Gemstone */ + @Suppress("MaxLineLength") private val gemstonePattern by patternGroup.pattern( "reward.gemstone", - "§r§[fa9][❤❈☘⸕✎✧] (?Rough|Flawed|Fine|Flawless) (?Ruby|Amethyst|Jade|Amber|Sapphire|Topaz) Gemstone( §r§8x(?[\\d,]+))?", + "§r§[fa9][❤❈☘⸕✎✧❁] (?Rough|Flawed|Fine|Flawless) (?Ruby|Amethyst|Jade|Amber|Sapphire|Topaz|Jasper) Gemstone( §r§8x(?[\\d,]+))?", ) + @Suppress("CyclomaticComplexMethod") fun block(message: String): String? { // Generic "you uncovered a chest" message if (uncoverChestPattern.matches(message)) return "powder_mining_chest" @@ -275,7 +281,7 @@ object PowderMiningChatFilter { // To simplify regex statements, this check is done outside val ssMessage = message.takeIf { it.startsWith(" ") }?.substring(4) ?: return null - //Powder + // Powder powderRewardPattern.matchMatcher(ssMessage) { if (config.powderFilterThreshold == 60000) return "powder_mining_powder" val amountStr = groupOrNull("amount") ?: "1" @@ -286,7 +292,7 @@ object PowderMiningChatFilter { } } - //Essence + // Essence essenceRewardPattern.matchMatcher(ssMessage) { if (config.essenceFilterThreshold == 20) return "powder_mining_essence" val amountStr = groupOrNull("amount") ?: "1" @@ -301,11 +307,12 @@ object PowderMiningChatFilter { blockGoblinEggs(ssMessage)?.let { return it } blockGemstones(ssMessage)?.let { return it } - //Fallback default + // Fallback default return null } - var rewardPatterns: Map, String> = emptyMap() + private var rewardPatterns: Map, String> = + emptyMap() @SubscribeEvent(priority = EventPriority.HIGHEST) fun onRepoReload(event: RepositoryReloadEvent) { @@ -339,7 +346,7 @@ object PowderMiningChatFilter { if (config.goblinEggs == PowderMiningFilterConfig.GoblinEggFilterEntry.HIDE_ALL) return "powder_mining_goblin_eggs" return when (val colorStr = groupOrNull("color")?.lowercase()) { - //'Colorless', base goblin eggs will never be shown in this code path + // 'Colorless', base goblin eggs will never be shown in this code path null -> "powder_mining_goblin_eggs" "green" -> if (config.goblinEggs > PowderMiningFilterConfig.GoblinEggFilterEntry.GREEN_UP) { "powder_mining_goblin_eggs" @@ -358,7 +365,7 @@ object PowderMiningChatFilter { else -> { ErrorManager.logErrorWithData( NoSuchElementException(), - "Unknown Goblin Egg color detected in Powder Mining Filter: '${colorStr}' - please report this in the Discord!", + "Unknown Goblin Egg color detected in Powder Mining Filter: '$colorStr' - please report this in the Discord!", noStackTrace = true, ) "no_filter" @@ -380,7 +387,8 @@ object PowderMiningChatFilter { "amethyst" -> gemstoneConfig.amethystGemstones "jade" -> gemstoneConfig.jadeGemstones "topaz" -> gemstoneConfig.topazGemstones - //Failure case that should never be reached + "jasper" -> gemstoneConfig.jasperGemstones + // Failure case that should never be reached else -> return "no_filter" } diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/translation/TranslatableLanguage.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/translation/TranslatableLanguage.kt index 13a19a1dcbc8..7f5db80d1ef8 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/chat/translation/TranslatableLanguage.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/translation/TranslatableLanguage.kt @@ -34,8 +34,8 @@ enum class TranslatableLanguage(private val englishName: String, private val nat TAGALOG("Tagalog", "Tagalog", "tl"), // Major language in the Philippines PUNJABI("Punjabi", "ਪੰਜਾਬੀ", "pa"), // Significant in India and Pakistan - // 5. need better name - UNKNOWN("Unknown Language", "", ""), + // 5. Other Language + UNKNOWN("Other", "", ""), ; // Limit to 20 characters so that the text is not too small in the config 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 24809faac798..ca827432fad9 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 @@ -66,7 +66,7 @@ object Translator { if (text.isEmpty()) { config.languageName.set(TranslatableLanguage.ENGLISH) } else { - for (language in TranslatableLanguage.values()) { + for (language in TranslatableLanguage.entries) { if (language.languageCode.equals(text, ignoreCase = true)) { config.languageName.set(language) return@onToggle @@ -107,102 +107,107 @@ object Translator { * ] * ], * null, - * '"target language as a two-letter code following ISO 639-1"', + * '"target language as a (usually) two-letter code following ISO 639-1"', * ] */ - private fun getJSONResponse(urlString: String) = - APIUtils.getJSONResponseAsElement(urlString, false, "Google Translate API") + private fun getJSONResponse(urlString: String) = APIUtils.getJSONResponseAsElement(urlString, false, "Google Translate API") - private fun getTranslationToEnglish(message: String): String { - val url = - "https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=en&dt=t&q=" + - URLEncoder.encode(message, "UTF-8") + fun getTranslation( + message: String, + targetLanguage: String, + 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") var messageToSend = "" - val layer1 = getJSONResponse(url).asJsonArray - if (layer1.size() <= 2) return "Error!" + val fullResponse = getJSONResponse(url).asJsonArray + if (fullResponse.size() < 3) return null - val language = layer1[2].toString() - if (language == "\"en\"") return "Unable to translate!" - if (language.length != 4) return "Error!" + val language = fullResponse[2].toString() // the detected language the message is in + val sentences = fullResponse[0] as? JsonArray ?: return null - val layer2 = try { - layer1[0] as JsonArray - } catch (_: Exception) { - return "Error!" - } - - for (layer3 in layer2) { - val arrayLayer3 = layer3 as? JsonArray ?: continue - val sentence = arrayLayer3[0].toString() + for (rawSentence in sentences) { + val arrayPhrase = rawSentence as? JsonArray ?: continue + val sentence = arrayPhrase[0].toString() val sentenceWithoutQuotes = sentence.substring(1, sentence.length - 1) messageToSend = "$messageToSend$sentenceWithoutQuotes" } - messageToSend = "$messageToSend §7(Language: $language)" + messageToSend = URLDecoder.decode(messageToSend, "UTF-8").replace("\\", "") // Not sure if this is actually needed + return arrayOf(messageToSend, language) + } - return URLDecoder.decode(messageToSend, "UTF-8").replace("\\", "") + @Deprecated("Use toNativeLanguage() instead", ReplaceWith("Translator.toNativeLanguage(args)")) + fun toEnglish(args: Array) { + toNativeLanguage(args) } - private fun getTranslationFromEnglish(message: String, lang: String): String { - val url = - "https://translate.googleapis.com/translate_a/single?client=gtx&sl=en&tl=$lang&dt=t&q=" + - URLEncoder.encode(message, "UTF-8") - - val layer1 = getJSONResponse(url).asJsonArray - if (layer1.size() < 1) return "Error!" - val layer2 = layer1[0] as? JsonArray - - val firstSentence = (layer2?.get(0) as? JsonArray)?.get(0).toString() - var messageToSend = firstSentence.substring(0, firstSentence.length - 1) - if (layer2 != null) { - for (sentenceIndex in 1..) { + fromNativeLanguage(args) } - fun toEnglish(args: Array) { + fun toNativeLanguage(args: Array) { val message = args.joinToString(" ").removeColor() coroutineScope.launch { - var lang = config.languageCode.get() - val translation = if (lang.isEmpty()) { - getTranslationToEnglish(message) - } else { - getTranslationFromEnglish(message, lang) - } - if (message == translation) { - ChatUtils.userError("Translation is the same as the original message!") - return@launch - } + val translation = getTranslation(message, nativeLanguage()) + val translatedMessage = translation?.get(0) ?: "Error!" + val detectedLanguage = translation?.get(1) ?: "Error!" - if (translation == "Unable to translate!") { - ChatUtils.userError("Unable to translate message :( (is it in English?)") + if (message == translatedMessage) { + ChatUtils.userError("Translation is the same as the original message!") return@launch } - ChatUtils.chat("Found translation: §f$translation") + ChatUtils.clickableChat( + "Found translation: §f$translatedMessage", + onClick = { OSUtils.copyToClipboard(translatedMessage) }, + "§eClick to copy!\n§eOriginal message: §f$message §7(Language: $detectedLanguage)", + ) } } - fun fromEnglish(args: Array) { - if (args.size < 2 || args[0].length != 2) { // args[0] is the language code - ChatUtils.userError("Usage: /shcopytranslation ") + fun fromNativeLanguage(args: Array) { + if (args.size < 2) { + ChatUtils.userError("Usage: /shcopytranslation ") return } val language = args[0] val message = args.drop(1).joinToString(" ") coroutineScope.launch { - val translation = getTranslationFromEnglish(message, language) - ChatUtils.chat("Copied translation to clipboard: §f$translation") - OSUtils.copyToClipboard(translation) + val translation = getTranslation(message, language, nativeLanguage())?.get(0) ?: "Error!" + ChatUtils.clickableChat( + "Copied §f$language §etranslation to clipboard: §f$translation", + onClick = { OSUtils.copyToClipboard(translation) }, + "§eClick to copy!\n§eOriginal message: §f$message", + ) } } + fun translateAdvancedCommand(args: Array) { + if (args.size < 3) { + ChatUtils.userError("Usage: /shtranslateadvanced ") + return + } + val sourceLanguage = args[0] + val targetLanguage = args[1] + val message = args.drop(2).joinToString(" ") + + val translation = getTranslation(message, sourceLanguage, targetLanguage) + val translatedMessage = translation?.get(0) ?: "Error!" + val detectedLanguage = if (sourceLanguage == "auto") " ${translation?.get(1) ?: "Error!"}" else "" + + ChatUtils.clickableChat( + "Found translation from sl: $sourceLanguage: §f$translatedMessage §7(tl: $targetLanguage)", + onClick = { OSUtils.copyToClipboard(translatedMessage) }, + "§eClick to copy!\n§eOriginal message: §f$message §7(sl: $sourceLanguage$detectedLanguage)", + ) + } + + fun nativeLanguage(): String = config.languageCode.get().ifEmpty { "en" } + fun isEnabled() = config.translateOnClick } 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 957f1ecd0b29..f40e437e5403 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/BestiaryData.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/BestiaryData.kt @@ -279,10 +279,12 @@ object BestiaryData { val isUnlocked = mob.actualRealTotalKill != 0.toLong() val isMaxed = mob.percentToMax() >= 1 if (!isUnlocked) { - newDisplay.add(buildList { - add(" §7- ") - add("${mob.name}: §cNot unlocked!") - }) + newDisplay.add( + buildList { + add(" §7- ") + add("${mob.name}: §cNot unlocked!") + } + ) continue } if (isMaxed && config.hideMaxed) continue @@ -358,7 +360,8 @@ object BestiaryData { // todo: avoid ordinal config.numberFormat = BestiaryConfig.NumberFormatEntry.entries[(config.numberFormat.ordinal + 1) % 2] update() - }) + } + ) newDisplay.addButton( prefix = "§7Display Type: ", @@ -367,7 +370,8 @@ object BestiaryData { // todo: avoid ordinal config.displayType = DisplayTypeEntry.entries[(config.displayType.ordinal + 1) % 8] update() - }) + } + ) newDisplay.addButton( prefix = "§7Number Type: ", @@ -377,6 +381,7 @@ object BestiaryData { update() } ) + newDisplay.addButton( prefix = "§7Hide Maxed: ", getName = HideMaxed.entries[if (config.hideMaxed) 1 else 0].type, @@ -391,18 +396,20 @@ object BestiaryData { if (catList.isNotEmpty()) { newDisplay.addAsSingletonList("§7Category") for (cat in catList) { - newDisplay.add(buildList { - add(" §7- ${cat.name}§7: ") - val element = when { - 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" - - else -> continue + newDisplay.add( + buildList { + add(" §7- ${cat.name}§7: ") + val element = when { + 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" + + else -> continue + } + add(element) } - add(element) - }) + ) } } } @@ -441,8 +448,8 @@ object BestiaryData { return true } else if (name == "Search Results") { val loreList = stack.getLore() - if (loreList.size >= 2 && loreList[0].startsWith("§7Query: §a") - && loreList[1].startsWith("§7Results: §a") + if (loreList.size >= 2 && loreList[0].startsWith("§7Query: §a") && + loreList[1].startsWith("§7Results: §a") ) { return true } 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 dd7c088b0b7e..d122ba342fee 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/BroodmotherFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/BroodmotherFeatures.kt @@ -20,6 +20,7 @@ import at.hannibal2.skyhanni.utils.StringUtils import at.hannibal2.skyhanni.utils.TimeUtils.format import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import kotlin.reflect.KMutableProperty0 +import kotlin.time.Duration import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.seconds import kotlin.time.DurationUnit @@ -27,13 +28,13 @@ import kotlin.time.DurationUnit @SkyHanniModule object BroodmotherFeatures { - enum class StageEntry(private val str: String, val minutes: Int) { - SLAIN("§eSlain", 10), - DORMANT("§eDormant", 9), - SOON("§6Soon", 6), - AWAKENING("§6Awakening", 3), - IMMINENT("§4Imminent", 1), - ALIVE("§4Alive!", 0); + enum class StageEntry(private val str: String, val duration: Duration) { + SLAIN("§eSlain", 10.minutes), + DORMANT("§eDormant", 9.minutes), + SOON("§6Soon", 6.minutes), + AWAKENING("§6Awakening", 3.minutes), + IMMINENT("§4Imminent", 1.minutes), + ALIVE("§4Alive!", 0.minutes); override fun toString() = str } @@ -50,7 +51,7 @@ object BroodmotherFeatures { fun onTabListUpdate(event: WidgetUpdateEvent) { if (!event.isWidget(TabWidget.BROODMOTHER)) return val newStage = event.widget.matchMatcherFirstLine { group("stage") } ?: "" - if (newStage.isNotEmpty()) { + if (newStage.isNotEmpty() && newStage != lastStage.toString()) { lastStage = currentStage currentStage = StageEntry.valueOf(newStage.replace("!", "").uppercase()) onStageUpdate() @@ -60,7 +61,7 @@ object BroodmotherFeatures { private fun onStageUpdate() { ChatUtils.debug("New Broodmother stage: $currentStage") - if (lastStage == null && onServerJoin()) return + if (onServerJoin()) return // ignore Hypixel bug where the stage may temporarily revert to Imminent after the Broodmother's death if (currentStage == StageEntry.IMMINENT && lastStage == StageEntry.ALIVE) return @@ -70,15 +71,15 @@ object BroodmotherFeatures { return } + val lastStage = lastStage ?: return + val timeUntilSpawn = currentStage?.duration ?: return + broodmotherSpawnTime = SimpleTimeMark.now() + timeUntilSpawn + if (currentStage == StageEntry.IMMINENT && config.imminentWarning) { playImminentWarning() return } - val lastStage = lastStage ?: return - val timeUntilSpawn = currentStage?.minutes?.minutes ?: return - broodmotherSpawnTime = SimpleTimeMark.now() + timeUntilSpawn - if (currentStage !in config.stages) return if (currentStage == StageEntry.SLAIN) { onBroodmotherSlain() @@ -91,19 +92,19 @@ object BroodmotherFeatures { } private fun onServerJoin(): Boolean { + if (lastStage != null || !config.stageOnJoin) return false // don't send if user has config enabled for either of the alive messages // this is so that two messages aren't immediately sent upon joining a server - if (config.stageOnJoin && !(currentStage == StageEntry.ALIVE && isAliveMessageEnabled())) { - val pluralize = StringUtils.pluralize(currentStage?.minutes ?: 0, "minute") + if (!(currentStage == StageEntry.ALIVE && isAliveMessageEnabled())) { + val duration = currentStage?.duration var message = "The Broodmother's current stage in this server is ${currentStage.toString().replace("!", "")}§e." - if (currentStage?.minutes != 0) { - message += " It will spawn §bwithin ${currentStage?.minutes} $pluralize§e." + if (duration != 0.minutes) { + message += " It will spawn §bwithin $duration§e." } ChatUtils.chat(message) return true - } else { - return false } + return false } private fun onBroodmotherSpawn() { @@ -150,6 +151,9 @@ object BroodmotherFeatures { fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) { if (!isCountdownEnabled()) return if (display.isEmpty()) return + if (broodmotherSpawnTime.isInPast() && !broodmotherSpawnTime.isFarPast()) { + display = "§4Broodmother spawning now!" + } config.countdownPosition.renderString(display, posLabel = "Broodmother Countdown") } @@ -159,7 +163,7 @@ object BroodmotherFeatures { if (!isCountdownEnabled()) return if (broodmotherSpawnTime.isFarPast()) { - if (lastStage != null && currentStage == StageEntry.ALIVE) { + if (currentStage == StageEntry.ALIVE) { display = "§4Broodmother spawned!" } } else { diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/FerocityDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/FerocityDisplay.kt index c30299e4f167..8ea8449f467a 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/FerocityDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/FerocityDisplay.kt @@ -1,14 +1,11 @@ package at.hannibal2.skyhanni.features.combat import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.data.model.TabWidget +import at.hannibal2.skyhanni.data.model.SkyblockStat import at.hannibal2.skyhanni.events.GuiRenderEvent -import at.hannibal2.skyhanni.events.WidgetUpdateEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.RegexUtils.matchFirst import at.hannibal2.skyhanni.utils.RenderUtils.renderString -import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @SkyHanniModule @@ -16,35 +13,11 @@ object FerocityDisplay { private val config get() = SkyHanniMod.feature.combat.ferocityDisplay - /** - * REGEX-TEST: Ferocity: §r§c⫽14 - */ - private val ferocityPattern by RepoPattern.pattern( - "combat.ferocity.tab", - " Ferocity: §r§c⫽(?.*)", - ) - - private var display = "" - - @SubscribeEvent - fun onTabListUpdate(event: WidgetUpdateEvent) { - if (!isEnabled()) return - if (!event.isWidget(TabWidget.STATS, TabWidget.DUNGEON_SKILLS_AND_STATS)) return - display = "" - if (event.isClear()) return - val stat = event.lines.matchFirst(ferocityPattern) { - group("stat") - } ?: return - - display = "§c⫽$stat" - - } - @SubscribeEvent fun onRenderOverlay(event: GuiRenderEvent) { if (!isEnabled()) return - - config.position.renderString(display, posLabel = "Ferocity Display") + if (SkyblockStat.FEROCITY.lastKnownValue == 0.0) return + config.position.renderString(SkyblockStat.FEROCITY.displayValue, posLabel = "Ferocity Display") } fun isEnabled() = LorenzUtils.inSkyBlock && config.enabled 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 fd2b513cf561..c5804ea37c40 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/FlareDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/FlareDisplay.kt @@ -48,7 +48,7 @@ object FlareDisplay { "ewogICJ0aW1lc3RhbXAiIDogMTY0NjY4NzMyNjQzMiwKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOWQyYmY5ODY0NzIwZDg3ZmQwNmI4NGVmYTgwYjc5NWM0OGVkNTM5YjE2NTIzYzNiMWYxOTkwYjQwYzAwM2Y2YiIKICAgIH0KICB9Cn0=" to FlareType.ALERT, "ewogICJ0aW1lc3RhbXAiIDogMTY0NjY4NzM0NzQ4OSwKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzAwNjJjYzk4ZWJkYTcyYTZhNGI4OTc4M2FkY2VmMjgxNWI0ODNhMDFkNzNlYTg3YjNkZjc2MDcyYTg5ZDEzYiIKICAgIH0KICB9Cn0=" - to FlareType.SOS + to FlareType.SOS, ) @SubscribeEvent @@ -92,7 +92,8 @@ object FlareDisplay { val name = type.displayName if (newDisplay == null) { newDisplay = buildList { - add(Renderable.string("$name: §b${remainingTime.format()}")) + val displayTime = if (remainingTime.isNegative()) "§eSoon" else "§b${remainingTime.format()}" + add(Renderable.string("$name: $displayTime")) if (config.showManaBuff) { type.manaBuff?.let { add(Renderable.string(" §b$it §7mana regen")) @@ -100,7 +101,7 @@ object FlareDisplay { } } } - if (remainingTime > 5.seconds) continue + if (remainingTime !in 0.seconds..5.seconds) continue val message = "$name §eexpires in: §b${remainingTime.inWholeSeconds}s" when (config.alertType) { FlareConfig.AlertType.CHAT -> { @@ -194,7 +195,6 @@ object FlareDisplay { SOS("§5SOS Flare", "+125%"), ALERT("§9Alert Flare", "+50%"), WARNING("§aWarning Flare", null), - ; } private fun isEnabled() = LorenzUtils.inSkyBlock && config.enabled 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 7986c55e9d3a..af1dd8430186 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/SpidersDenAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/SpidersDenAPI.kt @@ -1,12 +1,11 @@ package at.hannibal2.skyhanni.features.combat -import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard +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 @SkyHanniModule object SpidersDenAPI { - private fun getSbLines(): List = CustomScoreboard.activeLines - fun isAtTopOfNest(): Boolean = getSbLines().any { ScoreboardPattern.broodmotherPattern.matches(it) } + fun isAtTopOfNest(): Boolean = ScoreboardData.sidebarLinesFormatted.any { ScoreboardPattern.broodmotherPattern.matches(it) } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/BossType.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/BossType.kt index 3d46d3edc5d4..0d542df383b8 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/BossType.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/BossType.kt @@ -21,7 +21,7 @@ enum class BossType( NETHER_VANQUISHER("§5Vanquisher", Type.VANQUISHER), END_ENDSTONE_PROTECTOR("§cEndstone Protector", Type.ENDERSTONE_PROTECTOR), - END_ENDER_DRAGON("Ender Dragon", Type.ENDER_DRAGON),// TODO fix totally + END_ENDER_DRAGON("Ender Dragon", Type.ENDER_DRAGON), // TODO fix totally SLAYER_ZOMBIE_1("§aRevenant Horror 1", Type.REVENANT_HORROR, "§aRev 1", showDeathTime = true), SLAYER_ZOMBIE_2("§eRevenant Horror 2", Type.REVENANT_HORROR, "§eRev 2", showDeathTime = true), @@ -107,7 +107,7 @@ enum class BossType( LEECH_SUPREME("§cLeech Supreme", Type.THE_RIFT_BOSSES), BACTE("§aBacte", Type.THE_RIFT_BOSSES), - WINTER_REINDRAKE("Reindrake", Type.REINDRAKE),// TODO fix totally + WINTER_REINDRAKE("Reindrake", Type.REINDRAKE), // TODO fix totally GARDEN_PEST_BEETLE("§cBeetle", Type.GARDEN_PESTS), GARDEN_PEST_CRICKET("§cCricket", Type.GARDEN_PESTS), 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 0391e40a3697..7f5b42e3c538 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 @@ -67,6 +67,8 @@ import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds @SkyHanniModule +// TODO cut class into smaller pieces +@Suppress("LargeClass") object DamageIndicatorManager { private var mobFinder: MobFinder? = null @@ -75,7 +77,6 @@ object DamageIndicatorManager { private val enderSlayerHitsNumberPattern = ".* §[5fd]§l(?\\d+) Hits?".toPattern() - private var data = mapOf() private val damagePattern = "[✧✯]?(\\d+[⚔+✧❤♞☄✷ﬗ✯]*)".toPattern() @@ -288,7 +289,7 @@ object DamageIndicatorManager { BossType.SLAYER_BLAZE_QUAZII_3, BossType.SLAYER_BLAZE_QUAZII_4, - // TODO f3/m3 4 guardians, f2/m2 4 boss room fighters + // TODO f3/m3 4 guardians, f2/m2 4 boss room fighters -> true else -> false @@ -366,8 +367,8 @@ object DamageIndicatorManager { getCustomHealth(entityData, health, entity, maxHealth) ?: return null } - if (data.containsKey(entity.uniqueID)) { - val lastHealth = data[entity.uniqueID]!!.lastHealth + data[entity.uniqueID]?.let { + val lastHealth = it.lastHealth checkDamage(entityData, health, lastHealth) tickDamage(entityData.damageCounter) 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 975e3b4f8457..44c7608c2b6b 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 @@ -71,8 +71,7 @@ class MobFinder { // F5 private var floor5lividEntity: EntityOtherPlayerMP? = null private var floor5lividEntitySpawnTime = 0L - private val correctLividPattern = - "§c\\[BOSS] (.*) Livid§r§f: Impossible! How did you figure out which one I was\\?!".toPattern() + private val correctLividPattern = "§c\\[BOSS] (.*) Livid§r§f: Impossible! How did you figure out which one I was\\?!".toPattern() // F6 private var floor6Giants = false @@ -86,29 +85,32 @@ class MobFinder { RiftAPI.inRift() -> tryAddRift(entity) GardenAPI.inGarden() -> tryAddGarden(entity) else -> { - when (entity) { - /* + if (entity is EntityLiving && entity.hasNameTagWith(2, "Dummy §a10M§c❤")) { + EntityResult(bossType = BossType.DUMMY) + } else { + when (entity) { + /* * Note that the order does matter here. * For example, if you put EntityZombie before EntityPigZombie, * EntityPigZombie will never be reached because EntityPigZombie extends EntityZombie. * Please take this into consideration if you are to modify this. - */ - is EntityOtherPlayerMP -> tryAddEntityOtherPlayerMP(entity) - is EntityIronGolem -> tryAddEntityIronGolem(entity) - is EntityPigZombie -> tryAddEntityPigZombie(entity) - is EntityMagmaCube -> tryAddEntityMagmaCube(entity) - is EntityEnderman -> tryAddEntityEnderman(entity) - is EntitySkeleton -> tryAddEntitySkeleton(entity) - is EntityGuardian -> tryAddEntityGuardian(entity) - is EntityZombie -> tryAddEntityZombie(entity) - is EntityWither -> tryAddEntityWither(entity) - is EntityDragon -> tryAddEntityDragon(entity) - is EntitySpider -> tryAddEntitySpider(entity) - is EntityHorse -> tryAddEntityHorse(entity) - is EntityBlaze -> tryAddEntityBlaze(entity) - is EntityWolf -> tryAddEntityWolf(entity) - is EntityLiving -> tryAddEntityLiving(entity) - else -> null + */ + is EntityOtherPlayerMP -> tryAddEntityOtherPlayerMP(entity) + is EntityIronGolem -> tryAddEntityIronGolem(entity) + is EntityPigZombie -> tryAddEntityPigZombie(entity) + is EntityMagmaCube -> tryAddEntityMagmaCube(entity) + is EntityEnderman -> tryAddEntityEnderman(entity) + is EntitySkeleton -> tryAddEntitySkeleton(entity) + is EntityGuardian -> tryAddEntityGuardian(entity) + is EntityZombie -> tryAddEntityZombie(entity) + is EntityWither -> tryAddEntityWither(entity) + is EntityDragon -> tryAddEntityDragon(entity) + is EntitySpider -> tryAddEntitySpider(entity) + is EntityHorse -> tryAddEntityHorse(entity) + is EntityBlaze -> tryAddEntityBlaze(entity) + is EntityWolf -> tryAddEntityWolf(entity) + else -> null + } } } } @@ -124,8 +126,7 @@ class MobFinder { private fun tryAddGardenPest(entity: EntityLivingBase): EntityResult? { if (!GardenAPI.inGarden()) return null - return PestType.entries - .firstOrNull { entity.hasNameTagWith(3, it.displayName) } + return PestType.entries.firstOrNull { entity.hasNameTagWith(3, it.displayName) } ?.let { EntityResult(bossType = it.damageIndicatorBoss) } } @@ -170,7 +171,7 @@ class MobFinder { return EntityResult( floor2secondPhaseSpawnTime, finalDungeonBoss = true, - bossType = BossType.DUNGEON_F2_SCARF + bossType = BossType.DUNGEON_F2_SCARF, ) } } @@ -193,14 +194,14 @@ class MobFinder { return EntityResult( floor3ProfessorSpawnTime, floor3ProfessorSpawnTime + 1_000 > System.currentTimeMillis(), - bossType = BossType.DUNGEON_F3_PROFESSOR_1 + bossType = BossType.DUNGEON_F3_PROFESSOR_1, ) } if (floor3ProfessorGuardianPrepare && entity is EntityOtherPlayerMP && entity.name == "The Professor") { return EntityResult( floor3ProfessorGuardianPrepareSpawnTime, true, - bossType = BossType.DUNGEON_F3_PROFESSOR_2 + bossType = BossType.DUNGEON_F3_PROFESSOR_2, ) } @@ -215,7 +216,7 @@ class MobFinder { return EntityResult( bossType = BossType.DUNGEON_F4_THORN, ignoreBlocks = true, - finalDungeonBoss = true + finalDungeonBoss = true, ) } return null @@ -226,7 +227,7 @@ class MobFinder { return EntityResult( bossType = BossType.DUNGEON_F5, ignoreBlocks = true, - finalDungeonBoss = true + finalDungeonBoss = true, ) } return null @@ -239,7 +240,7 @@ class MobFinder { return EntityResult( floor6GiantsSpawnTime + extraDelay, floor6GiantsSpawnTime + extraDelay + 1_000 > System.currentTimeMillis(), - bossType = bossType + bossType = bossType, ) } @@ -274,8 +275,12 @@ class MobFinder { } private fun tryAddEntityBlaze(entity: EntityLivingBase) = when { - entity.name != "Dinnerbone" && entity.hasNameTagWith(2, "§e﴾ §8[§7Lv200§8] §l§8§lAshfang§r ") && - entity.hasMaxHealth(50_000_000, true) -> { + entity.name != "Dinnerbone" && + entity.hasNameTagWith(2, "§e﴾ §8[§7Lv200§8] §l§8§lAshfang§r ") && + entity.hasMaxHealth( + 50_000_000, + true, + ) -> { EntityResult(bossType = BossType.NETHER_ASHFANG) } @@ -312,8 +317,9 @@ class MobFinder { private fun tryAddEntityOtherPlayerMP(entity: EntityLivingBase) = when { entity.name == "Mage Outlaw" -> EntityResult(bossType = BossType.NETHER_MAGE_OUTLAW) - entity.name == "DukeBarb " && entity.getLorenzVec() - .distanceToPlayer() < 30 -> EntityResult(bossType = BossType.NETHER_BARBARIAN_DUKE) + entity.name == "DukeBarb " && + entity.getLorenzVec() + .distanceToPlayer() < 30 -> EntityResult(bossType = BossType.NETHER_BARBARIAN_DUKE) entity.name == "Minos Inquisitor" -> EntityResult(bossType = BossType.MINOS_INQUISITOR) entity.name == "Minos Champion" -> EntityResult(bossType = BossType.MINOS_CHAMPION) @@ -385,15 +391,8 @@ class MobFinder { else -> null } - private fun tryAddEntityLiving(entity: EntityLivingBase) = when { - entity.hasNameTagWith(2, "Dummy §a10M§c❤") -> EntityResult(bossType = BossType.DUMMY) - - else -> null - } - private fun tryAddEntityMagmaCube(entity: EntityLivingBase) = when { - entity.hasNameTagWith(15, "§e﴾ §8[§7Lv500§8] §l§4§lMagma Boss§r ") - && entity.hasMaxHealth(200_000_000, true) -> { + entity.hasNameTagWith(15, "§e﴾ §8[§7Lv500§8] §l§4§lMagma Boss§r ") && entity.hasMaxHealth(200_000_000, true) -> { EntityResult(bossType = BossType.NETHER_MAGMA_BOSS, ignoreBlocks = true) } @@ -401,24 +400,22 @@ class MobFinder { } private fun tryAddEntityHorse(entity: EntityLivingBase) = when { - entity.hasNameTagWith(15, "§8[§7Lv100§8] §c§6Headless Horseman§r ") && - entity.hasMaxHealth(3_000_000, true) -> { + entity.hasNameTagWith(15, "§8[§7Lv100§8] §c§6Headless Horseman§r ") && entity.hasMaxHealth(3_000_000, true) -> { EntityResult(bossType = BossType.HUB_HEADLESS_HORSEMAN) } else -> null } - private fun tryAddEntityPigZombie(entity: EntityLivingBase) = - if (entity.hasNameTagWith(2, "§c☠ §6ⓉⓎⓅⒽⓄⒺⓊⓈ ")) { - when { - entity.hasBossHealth(10_000_000) -> EntityResult(bossType = BossType.SLAYER_BLAZE_TYPHOEUS_4) - entity.hasBossHealth(5_000_000) -> EntityResult(bossType = BossType.SLAYER_BLAZE_TYPHOEUS_3) - entity.hasBossHealth(1_750_000) -> EntityResult(bossType = BossType.SLAYER_BLAZE_TYPHOEUS_2) - entity.hasBossHealth(500_000) -> EntityResult(bossType = BossType.SLAYER_BLAZE_TYPHOEUS_1) - else -> null - } - } else null + private fun tryAddEntityPigZombie(entity: EntityLivingBase) = if (entity.hasNameTagWith(2, "§c☠ §6ⓉⓎⓅⒽⓄⒺⓊⓈ ")) { + when { + entity.hasBossHealth(10_000_000) -> EntityResult(bossType = BossType.SLAYER_BLAZE_TYPHOEUS_4) + entity.hasBossHealth(5_000_000) -> EntityResult(bossType = BossType.SLAYER_BLAZE_TYPHOEUS_3) + entity.hasBossHealth(1_750_000) -> EntityResult(bossType = BossType.SLAYER_BLAZE_TYPHOEUS_2) + entity.hasBossHealth(500_000) -> EntityResult(bossType = BossType.SLAYER_BLAZE_TYPHOEUS_1) + else -> null + } + } else null private fun tryAddEntitySpider(entity: EntityLivingBase): EntityResult? { if (entity.hasNameTagWith(1, "§5☠ §4Tarantula Broodfather ")) { @@ -439,17 +436,13 @@ class MobFinder { } private fun checkArachne(entity: EntitySpider): EntityResult? { - if (entity.hasNameTagWith(1, "[§7Lv300§8] §cArachne") || - entity.hasNameTagWith(1, "[§7Lv300§8] §lArachne") - ) { + if (entity.hasNameTagWith(1, "[§7Lv300§8] §cArachne") || entity.hasNameTagWith(1, "[§7Lv300§8] §lArachne")) { val maxHealth = entity.baseMaxHealth // Ignore the minis if (maxHealth == 12 || maxHealth.derpy() == 4000) return null return EntityResult(bossType = BossType.ARACHNE_SMALL) } - if (entity.hasNameTagWith(1, "[§7Lv500§8] §cArachne") || - entity.hasNameTagWith(1, "[§7Lv500§8] §lArachne") - ) { + if (entity.hasNameTagWith(1, "[§7Lv500§8] §cArachne") || entity.hasNameTagWith(1, "[§7Lv500§8] §lArachne")) { val maxHealth = entity.baseMaxHealth if (maxHealth == 12 || maxHealth.derpy() == 20_000) return null return EntityResult(bossType = BossType.ARACHNE_BIG) @@ -458,16 +451,15 @@ class MobFinder { return null } - private fun tryAddEntityWolf(entity: EntityLivingBase) = - if (entity.hasNameTagWith(1, "§c☠ §fSven Packmaster ")) { - when { - entity.hasMaxHealth(2_000, true) -> EntityResult(bossType = BossType.SLAYER_WOLF_1) - entity.hasMaxHealth(40_000, true) -> EntityResult(bossType = BossType.SLAYER_WOLF_2) - entity.hasMaxHealth(750_000, true) -> EntityResult(bossType = BossType.SLAYER_WOLF_3) - entity.hasMaxHealth(2_000_000, true) -> EntityResult(bossType = BossType.SLAYER_WOLF_4) - else -> null - } - } else null + private fun tryAddEntityWolf(entity: EntityLivingBase) = if (entity.hasNameTagWith(1, "§c☠ §fSven Packmaster ")) { + when { + entity.hasMaxHealth(2_000, true) -> EntityResult(bossType = BossType.SLAYER_WOLF_1) + entity.hasMaxHealth(40_000, true) -> EntityResult(bossType = BossType.SLAYER_WOLF_2) + entity.hasMaxHealth(750_000, true) -> EntityResult(bossType = BossType.SLAYER_WOLF_3) + entity.hasMaxHealth(2_000_000, true) -> EntityResult(bossType = BossType.SLAYER_WOLF_4) + else -> null + } + } else null private fun tryAddEntityGuardian(entity: EntityLivingBase) = if (entity.hasMaxHealth(35_000_000)) { EntityResult(bossType = BossType.THUNDER) diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/OldDamage.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/OldDamage.kt index 77ca2c6c9ee4..5067bac01396 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/OldDamage.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/damageindicator/OldDamage.kt @@ -1,3 +1,3 @@ package at.hannibal2.skyhanni.features.combat.damageindicator -class OldDamage(val time: Long, val damage: Long, val healing: Long) \ No newline at end of file +class OldDamage(val time: Long, val damage: Long, val healing: Long) diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/endernodetracker/EnderNodeTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/endernodetracker/EnderNodeTracker.kt index 51deea2b865d..4a0bed69c6a4 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/endernodetracker/EnderNodeTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/endernodetracker/EnderNodeTracker.kt @@ -26,7 +26,9 @@ import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland import at.hannibal2.skyhanni.utils.NEUItems.getPriceOrNull import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat +import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.renderables.Searchable +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import at.hannibal2.skyhanni.utils.tracker.SkyHanniTracker import at.hannibal2.skyhanni.utils.tracker.TrackerData import com.google.gson.annotations.Expose @@ -40,12 +42,30 @@ object EnderNodeTracker { private var miteGelInInventory = 0 - private val enderNodeRegex = Regex("""ENDER NODE!.+You found (\d+x )?§r(.+)§r§f!""") + private val patternGroup = RepoPattern.group("combat.endernodetracker.chat") + + /** + * REGEX-TEST: §5§lENDER NODE! §r§fYou found §r§8§r§aEnchanted Obsidian§r§f! + */ + private val patternOne by patternGroup.pattern( + "one", + "§5§lENDER NODE! §r§fYou found §r(?:§8§r)?(?.*)§r§f!", + ) + + /** + * REGEX-TEST: §5§lENDER NODE! §r§fYou found §r§85x §r§aEnchanted Ender Pearl§r§f! + */ + private val patternMulti by patternGroup.pattern( + "multi", + "§5§lENDER NODE! §r§fYou found §r§8(?\\d+)x §r(?.*)§r§f!", + ) + + // TODO add abstract logic with ohter pet drop chat messages private val endermanRegex = Regex("""(RARE|PET) DROP! §r(.+) §r§b\(""") private val tracker = SkyHanniTracker("Ender Node Tracker", { Data() }, { it.enderNodeTracker }) { formatDisplay( - drawDisplay(it) + drawDisplay(it), ) } @@ -77,14 +97,17 @@ object EnderNodeTracker { var item: String? = null var amount = 1 - // check whether the loot is from an ender node or an enderman - enderNodeRegex.find(message)?.let { - tracker.modify { storage -> - storage.totalNodesMined++ - } - amount = it.groups[1]?.value?.substringBefore("x")?.toIntOrNull() ?: 1 - item = it.groups[2]?.value - } ?: endermanRegex.find(message)?.let { + patternMulti.matchMatcher(message) { + item = group("name") + amount = group("amount").toInt() + addOneNodeMined() + } ?: patternOne.matchMatcher(message) { + item = group("name") + amount = 1 + addOneNodeMined() + } + + endermanRegex.find(message)?.let { amount = 1 item = it.groups[2]?.value } @@ -106,12 +129,18 @@ object EnderNodeTracker { } } + private fun addOneNodeMined() { + tracker.modify { storage -> + storage.totalNodesMined++ + } + } + @SubscribeEvent fun onIslandChange(event: IslandChangeEvent) { if (!isEnabled()) return - miteGelInInventory = Minecraft.getMinecraft().thePlayer.inventory.mainInventory - .filter { it?.getInternalNameOrNull() == EnderNode.MITE_GEL.internalName } - .sumOf { it.stackSize } + miteGelInInventory = Minecraft.getMinecraft().thePlayer.inventory.mainInventory.filter { + it?.getInternalNameOrNull() == EnderNode.MITE_GEL.internalName + }.sumOf { it.stackSize } } @SubscribeEvent @@ -119,9 +148,9 @@ object EnderNodeTracker { if (!isEnabled()) return if (!ProfileStorageData.loaded) return - val change = event.sackChanges - .firstOrNull { it.internalName == EnderNode.MITE_GEL.internalName && it.delta > 0 } - ?: return + val change = event.sackChanges.firstOrNull { + it.internalName == EnderNode.MITE_GEL.internalName && it.delta > 0 + } ?: return tracker.modify { storage -> storage.lootCount.addOrPut(EnderNode.MITE_GEL, change.delta) @@ -133,9 +162,9 @@ object EnderNodeTracker { if (!isEnabled()) return if (!ProfileStorageData.loaded) return - val newMiteGelInInventory = Minecraft.getMinecraft().thePlayer.inventory.mainInventory - .filter { it?.getInternalNameOrNull() == EnderNode.MITE_GEL.internalName } - .sumOf { it.stackSize } + val newMiteGelInInventory = Minecraft.getMinecraft().thePlayer.inventory.mainInventory.filter { + it?.getInternalNameOrNull() == EnderNode.MITE_GEL.internalName + }.sumOf { it.stackSize } val change = newMiteGelInInventory - miteGelInInventory if (change > 0) { tracker.modify { storage -> @@ -176,18 +205,16 @@ object EnderNodeTracker { val price = if (isEnderArmor(item)) { 10_000.0 } else { - (if (!LorenzUtils.noTradeMode) item.internalName.getPriceOrNull() else 0.0) - ?.coerceAtLeast(item.internalName.getNpcPriceOrNull() ?: 0.0) - ?.coerceAtLeast(georgePrice(item) ?: 0.0) - ?: 0.0 + (if (!LorenzUtils.noTradeMode) item.internalName.getPriceOrNull() else 0.0)?.coerceAtLeast( + item.internalName.getNpcPriceOrNull() ?: 0.0, + )?.coerceAtLeast(georgePrice(item) ?: 0.0) ?: 0.0 } newProfit[item] = price * amount } return newProfit } - private fun isEnabled() = IslandType.THE_END.isInIsland() && config.enabled && - (!config.onlyPickaxe || hasItemInHand()) + private fun isEnabled() = IslandType.THE_END.isInIsland() && config.enabled && (!config.onlyPickaxe || hasItemInHand()) private fun hasItemInHand() = ItemCategory.miningTools.containsItem(InventoryUtils.getItemInHand()) @@ -230,7 +257,7 @@ object EnderNodeTracker { val totalEnderArmor = calculateEnderArmor(data) addSearchString( - "§b${totalEnderArmor.addSeparators()} §5Ender Armor " + "§7(§6${(totalEnderArmor * 10_000).shortFormat()}§7)" + "§b${totalEnderArmor.addSeparators()} §5Ender Armor " + "§7(§6${(totalEnderArmor * 10_000).shortFormat()}§7)", ) for (item in EnderNode.entries.subList(11, 16)) { val count = (data.lootCount[item] ?: 0).addSeparators() @@ -243,10 +270,11 @@ object EnderNodeTracker { addSearchString("§f$c§7-§a$u§7-§9$r§7-§5$e§7-§6$l §fEnderman Pet §7(§6$profit§7)") } - private fun calculateEnderArmor(storage: Data) = - storage.lootCount.filter { isEnderArmor(it.key) } - .map { it.value } - .sum() + private fun calculateEnderArmor(storage: Data) = storage.lootCount.filter { + isEnderArmor(it.key) + }.map { + it.value + }.sum() private fun formatDisplay(map: List): List { if (!ProfileStorageData.loaded) return emptyList() 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 b337d58b1487..2ef652e4a93a 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 @@ -11,6 +11,7 @@ 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 @@ -24,6 +25,7 @@ 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 @@ -71,7 +73,8 @@ object GhostCounter { val config get() = SkyHanniMod.feature.combat.ghostCounter val storage get() = ProfileStorageData.profileSpecific?.ghostCounter private var display = emptyList>() - var ghostCounterV3File = File(FilenameUtils.separatorsToSystem("./config/ChatTriggers/modules/GhostCounterV3/.persistantData.json")) + var ghostCounterV3File = + File(FilenameUtils.separatorsToSystem("./config/ChatTriggers/modules/GhostCounterV3/.persistantData.json")) private val patternGroup = RepoPattern.group("combat.ghostcounter") private val skillXPPattern by patternGroup.pattern( @@ -331,7 +334,6 @@ object GhostCounter { } } - inMist = LorenzUtils.skyBlockArea == "The Mist" update() if (event.repeatSeconds(2)) { @@ -340,6 +342,11 @@ object GhostCounter { } } + @SubscribeEvent + fun onTick(event: LorenzTickEvent) { + inMist = IslandAreas.currentAreaName == "The Mist" + } + @SubscribeEvent fun onActionBarUpdate(event: ActionBarUpdateEvent) { if (!isEnabled()) return @@ -378,7 +385,7 @@ object GhostCounter { } percent = 100f.coerceAtMost(percent) if (!parse) { - sb.append(" (").append(String.format("%.2f", percent)).append("%)") + sb.append(" (").append(String.format(Locale.US, "%.2f", percent)).append("%)") } else { sb.append(" (").append(nf.format(currentSkillXp)) if (totalSkillXp != 0) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/mobs/MobHighlight.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/mobs/MobHighlight.kt index 7c33afcdb653..a4c4dcf8d09b 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/mobs/MobHighlight.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/mobs/MobHighlight.kt @@ -15,8 +15,7 @@ import at.hannibal2.skyhanni.utils.LorenzColor import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.baseMaxHealth import at.hannibal2.skyhanni.utils.LorenzUtils.ignoreDerpy -import at.hannibal2.skyhanni.utils.RenderUtils.draw3DLine -import at.hannibal2.skyhanni.utils.RenderUtils.exactPlayerEyeLocation +import at.hannibal2.skyhanni.utils.RenderUtils.drawLineToEye import at.hannibal2.skyhanni.utils.getLorenzVec import net.minecraft.client.entity.EntityOtherPlayerMP import net.minecraft.entity.EntityLivingBase @@ -42,8 +41,7 @@ object MobHighlight { RenderLivingEntityHelper.setEntityColorWithNoHurtTime( entity, LorenzColor.DARK_PURPLE.toColor().withAlpha(127) - ) - { config.corruptedMobHighlight } + ) { config.corruptedMobHighlight } } } @@ -57,16 +55,14 @@ object MobHighlight { RenderLivingEntityHelper.setEntityColorWithNoHurtTime( entity, LorenzColor.DARK_BLUE.toColor().withAlpha(127) - ) - { config.arachneKeeperHighlight } + ) { config.arachneKeeperHighlight } } if (config.corleoneHighlighter && maxHealth == 1_000_000 && entity is EntityOtherPlayerMP && entity.name == "Team Treasurite") { RenderLivingEntityHelper.setEntityColorWithNoHurtTime( entity, LorenzColor.DARK_PURPLE.toColor().withAlpha(127) - ) - { config.corleoneHighlighter } + ) { config.corleoneHighlighter } } if (entity is EntityEnderman) { @@ -78,8 +74,7 @@ object MobHighlight { RenderLivingEntityHelper.setEntityColorWithNoHurtTime( entity, LorenzColor.DARK_AQUA.toColor().withAlpha(127) - ) - { config.zealotBruiserHighlighter } + ) { config.zealotBruiserHighlighter } } } @@ -89,8 +84,7 @@ object MobHighlight { RenderLivingEntityHelper.setEntityColorWithNoHurtTime( entity, LorenzColor.GREEN.toColor().withAlpha(127) - ) - { config.chestZealotHighlighter } + ) { config.chestZealotHighlighter } } } @@ -99,8 +93,7 @@ object MobHighlight { RenderLivingEntityHelper.setEntityColorWithNoHurtTime( entity, LorenzColor.DARK_RED.toColor().withAlpha(50) - ) - { config.specialZealotHighlighter } + ) { config.specialZealotHighlighter } } } @@ -121,12 +114,11 @@ object MobHighlight { if (arachne.distanceToPlayer() > 10) return - event.draw3DLine( - event.exactPlayerEyeLocation(), - arachne.getLorenzVec().add(y = 1), + event.drawLineToEye( + arachne.getLorenzVec().up(), LorenzColor.RED.toColor(), config.lineToArachneWidth, - true + true, ) } @@ -153,12 +145,16 @@ object MobHighlight { } private fun markArachneMinis(entity: EntityLivingBase) { - RenderLivingEntityHelper.setEntityColorWithNoHurtTime(entity, LorenzColor.GOLD.toColor().withAlpha(50)) - { config.arachneBossHighlighter } + RenderLivingEntityHelper.setEntityColorWithNoHurtTime( + entity, + LorenzColor.GOLD.toColor().withAlpha(50) + ) { config.arachneBossHighlighter } } private fun markArachne(entity: EntityLivingBase) { - RenderLivingEntityHelper.setEntityColorWithNoHurtTime(entity, LorenzColor.RED.toColor().withAlpha(50)) - { config.arachneBossHighlighter } + RenderLivingEntityHelper.setEntityColorWithNoHurtTime( + entity, + LorenzColor.RED.toColor().withAlpha(50) + ) { config.arachneBossHighlighter } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/commands/PartyChatCommands.kt b/src/main/java/at/hannibal2/skyhanni/features/commands/PartyChatCommands.kt index b6bcff3bd13e..4651570e4b8b 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/commands/PartyChatCommands.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/commands/PartyChatCommands.kt @@ -200,8 +200,8 @@ object PartyChatCommands { var message = "Ignored player list:" if (blacklist.size > 15) { message += "\n§e" - blacklist.forEachIndexed { i, it -> - message += it + blacklist.forEachIndexed { i, blacklistedMessage -> + message += blacklistedMessage if (i < blacklist.size - 1) { message += ", " } diff --git a/src/main/java/at/hannibal2/skyhanni/features/commands/PartyCommands.kt b/src/main/java/at/hannibal2/skyhanni/features/commands/PartyCommands.kt index e7b3333dd7eb..3cbd43a785a2 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/commands/PartyCommands.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/commands/PartyCommands.kt @@ -2,7 +2,6 @@ package at.hannibal2.skyhanni.features.commands import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator -import at.hannibal2.skyhanni.data.FriendAPI import at.hannibal2.skyhanni.data.PartyAPI import at.hannibal2.skyhanni.data.PartyAPI.partyLeader import at.hannibal2.skyhanni.data.PartyAPI.transferVoluntaryPattern @@ -11,7 +10,6 @@ import at.hannibal2.skyhanni.events.MessageSendToServerEvent import at.hannibal2.skyhanni.features.misc.limbo.LimboTimeTracker import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils -import at.hannibal2.skyhanni.utils.EntityUtils import at.hannibal2.skyhanni.utils.HypixelCommands import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.RegexUtils.matches @@ -115,25 +113,9 @@ object PartyCommands { if (command == "pk" || command == "pt" || command == "pp" && config.shortCommands) { return PartyAPI.partyMembers } - - if (command == "p" || command == "party") { - val friends = if (config.tabComplete.friends) { - FriendAPI.getAllFriends().filter { it.bestFriend || !config.tabComplete.onlyBestFriends }.map { it.name } - } else { - emptyList() - } - val allOnLobby = EntityUtils.getPlayerEntities().map { it.name } - return friends + getPartyCommands() + allOnLobby - } return null } - private fun getPartyCommands(): List { - return if (config.tabComplete.partyCommands && PartyAPI.partyMembers.isNotEmpty()) { - otherPartyCommands - } else emptyList() - } - @SubscribeEvent fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { event.move(5, "commands.usePartyTransferAlias", "commands.shortCommands") @@ -157,14 +139,3 @@ object PartyCommands { ) } } - -private val otherPartyCommands = listOf( - "Disband", - "KickOffline", - "Leave", - "List", - "Mute", - "Private", - "Warp", - "Settings", -) diff --git a/src/main/java/at/hannibal2/skyhanni/features/commands/ViewRecipeCommand.kt b/src/main/java/at/hannibal2/skyhanni/features/commands/ViewRecipeCommand.kt index e3d6a5713297..dbaf037ca363 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/commands/ViewRecipeCommand.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/commands/ViewRecipeCommand.kt @@ -6,6 +6,7 @@ import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils.senderIsSkyhanni import at.hannibal2.skyhanni.utils.HypixelCommands import at.hannibal2.skyhanni.utils.NEUItems +import at.hannibal2.skyhanni.utils.NumberUtil.isInt import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @@ -30,12 +31,20 @@ object ViewRecipeCommand { if (!config.viewRecipeLowerCase) return if (event.senderIsSkyhanni()) return - val item = pattern.matchMatcher(event.message.lowercase()) { - group("item").uppercase().replace(" ", "_") + val input = pattern.matchMatcher(event.message.lowercase()) { + group("item").uppercase() } ?: return + val args = input.split(" ") + val endsWithPageNumber = args.last().isInt() + val finalCommand = if (endsWithPageNumber) { + "${args.dropLast(1).joinToString("_")} ${args.last()}" + } else { + input.replace(" ", "_") + } + event.cancel() - HypixelCommands.viewRecipe(item) + HypixelCommands.viewRecipe(finalCommand) } val list by lazy { diff --git a/src/main/java/at/hannibal2/skyhanni/features/commands/WikiManager.kt b/src/main/java/at/hannibal2/skyhanni/features/commands/WikiManager.kt index b8e14d280588..e6a1ef4e955e 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/commands/WikiManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/commands/WikiManager.kt @@ -8,7 +8,6 @@ import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName -import at.hannibal2.skyhanni.utils.ItemUtils.itemName import at.hannibal2.skyhanni.utils.KeyboardManager.isKeyHeld import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.NEUItems @@ -50,7 +49,7 @@ object WikiManager { } if (message == ("/wikithis")) { val itemInHand = InventoryUtils.getItemInHand() ?: run { - ChatUtils.chat("§cYou must be holding an item to use this command!") + ChatUtils.userError("You must be holding an item to use this command!") return } wikiTheItem(itemInHand, config.autoOpenWiki) @@ -70,7 +69,7 @@ object WikiManager { private fun wikiTheItem(item: ItemStack, autoOpen: Boolean, useFandom: Boolean = config.useFandom) { val itemDisplayName = - item.itemName.replace("§a✔ ", "").replace("§c✖ ", "") + item.displayName.replace("§a✔ ", "").replace("§c✖ ", "") val internalName = item.getInternalName().asString() val wikiUrlSearch = if (internalName != "NONE") internalName else itemDisplayName.removeColor() @@ -79,16 +78,16 @@ object WikiManager { fun otherWikiCommands(args: Array, useFandom: Boolean, wikithis: Boolean = false) { if (wikithis && !LorenzUtils.inSkyBlock) { - ChatUtils.chat("§cYou must be in SkyBlock to do this!") + ChatUtils.userError("You must be in SkyBlock to do this!") return } var search = "" - for (arg in args) search = "$search${arg}" + for (arg in args) search = "$search$arg" if (wikithis) { val itemInHand = InventoryUtils.getItemInHand() ?: run { - ChatUtils.chat("§cYou must be holding an item to use this command!") + ChatUtils.userError("You must be holding an item to use this command!") return } wikiTheItem(itemInHand, false, useFandom = useFandom) @@ -102,8 +101,10 @@ object WikiManager { } fun sendWikiMessage( - search: String = "", displaySearch: String = search, - autoOpen: Boolean = config.autoOpenWiki, useFandom: Boolean = config.useFandom + search: String = "", + displaySearch: String = search, + autoOpen: Boolean = config.autoOpenWiki, + useFandom: Boolean = config.useFandom, ) { val wiki = if (useFandom) "SkyBlock Fandom Wiki" else "Official SkyBlock Wiki" val urlPrefix = if (useFandom) FANDOM_URL_PREFIX else OFFICIAL_URL_PREFIX diff --git a/src/main/java/at/hannibal2/skyhanni/features/commands/suggestions/SuggestionEntry.kt b/src/main/java/at/hannibal2/skyhanni/features/commands/suggestions/SuggestionEntry.kt new file mode 100644 index 000000000000..74fcb0ef0e01 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/commands/suggestions/SuggestionEntry.kt @@ -0,0 +1,31 @@ +package at.hannibal2.skyhanni.features.commands.suggestions + +interface SuggestionEntry { + + val suggestions: List + + fun isEntryFor(argument: String): Boolean { + return this.suggestions.any { it.equals(argument, ignoreCase = true) } + } +} + +data class LiteralSuggestionEntry(override val suggestions: List) : SuggestionEntry + +data class CompositeSuggestionEntry(val entries: List) : SuggestionEntry { + override val suggestions: List get() = entries.flatMap { it.suggestions } + override fun isEntryFor(argument: String): Boolean = entries.any { it.isEntryFor(argument) } +} + +data class ParentSuggestionEntry(val parent: SuggestionEntry, val children: List) : SuggestionEntry { + override val suggestions: List get() = parent.suggestions + override fun isEntryFor(argument: String): Boolean = parent.isEntryFor(argument) +} + +data class LazySuggestionEntry(val supplier: MutableList.() -> Unit) : SuggestionEntry { + override val suggestions: List get() = mutableListOf().apply { supplier() } +} + +data class ConditionalSuggestionEntry(val condition: () -> Boolean, val entry: SuggestionEntry) : SuggestionEntry { + override val suggestions: List get() = if (condition()) entry.suggestions else emptyList() + override fun isEntryFor(argument: String): Boolean = entry.isEntryFor(argument) +} 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 new file mode 100644 index 000000000000..eda4c704cbcf --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/commands/suggestions/SuggestionProvider.kt @@ -0,0 +1,83 @@ +package at.hannibal2.skyhanni.features.commands.suggestions + +class SuggestionProvider { + + private val entry = mutableListOf() + + fun add(entry: SuggestionEntry) { + this.entry.add(entry) + } + + private fun List.getEntryForPath(path: List): SuggestionEntry? { + val entry = this.firstOrNull { it.isEntryFor(path.first()) } + val remainingPath = path.drop(1) + if (remainingPath.isNotEmpty()) { + if (entry is ParentSuggestionEntry) { + return entry.children.getEntryForPath(remainingPath) + } + return null + } else if (entry is ParentSuggestionEntry) { + return CompositeSuggestionEntry(entry.children) + } + return null + } + + fun getSuggestions(command: String): List { + val arguments = command.lowercase().split(" ") + val last = arguments.lastOrNull() ?: "" + val suggestions = mutableListOf() + if (arguments.size != 1) { + entry.getEntryForPath(arguments.dropLast(1))?.suggestions?.let { suggestions.addAll(it) } + } else { + entry.forEach { suggestions.addAll(it.suggestions) } + } + return suggestions.filter { it.startsWith(last, ignoreCase = true) } + } + + companion object { + + fun build(builder: Builder.() -> Unit): SuggestionProvider { + val b = Builder() + b.builder() + return b.build() + } + } +} + +class Builder { + private val entries = mutableListOf() + + fun add(entry: SuggestionEntry) { + entries.add(entry) + } + + fun conditional(condition: () -> Boolean, builder: Builder.() -> Unit) { + val childBuilder = Builder() + childBuilder.builder() + add(ConditionalSuggestionEntry(condition, CompositeSuggestionEntry(childBuilder.entries))) + } + + fun literal(vararg literals: String) { + add(LiteralSuggestionEntry(literals.toList())) + } + + fun lazy(supplier: () -> List) { + add(LazySuggestionEntry { addAll(supplier()) }) + } + + fun group(vararg children: SuggestionEntry) { + add(CompositeSuggestionEntry(children.toList())) + } + + fun parent(vararg literals: String, children: Builder.() -> Unit) { + val childBuilder = Builder() + childBuilder.children() + add(ParentSuggestionEntry(LiteralSuggestionEntry(literals.toList()), childBuilder.entries)) + } + + fun build(): SuggestionProvider { + val provider = SuggestionProvider() + entries.forEach { provider.add(it) } + return provider + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/GetFromSacksTabComplete.kt b/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/GetFromSacksTabComplete.kt index d6c2e85c23eb..39a1f096acff 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/GetFromSacksTabComplete.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/commands/tabcomplete/GetFromSacksTabComplete.kt @@ -19,7 +19,7 @@ object GetFromSacksTabComplete { return GetFromSackAPI.sackListNames.map { it.replace(" ", "_") } } - //No subscribe since it needs to be called from the GetFromSackAPI + // No subscribe since it needs to be called from the GetFromSackAPI fun handleUnderlineReplace(event: MessageSendToServerEvent): MessageSendToServerEvent { if (!isEnabled()) return event 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 070ab478e083..95acec9a6931 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 @@ -3,9 +3,12 @@ package at.hannibal2.skyhanni.features.commands.tabcomplete import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.data.FriendAPI +import at.hannibal2.skyhanni.data.GuildAPI import at.hannibal2.skyhanni.data.PartyAPI import at.hannibal2.skyhanni.data.jsonobjects.repo.VipVisitsJson import at.hannibal2.skyhanni.events.RepositoryReloadEvent +import at.hannibal2.skyhanni.features.commands.suggestions.LazySuggestionEntry +import at.hannibal2.skyhanni.features.commands.suggestions.SuggestionProvider import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.EntityUtils import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @@ -15,68 +18,97 @@ object PlayerTabComplete { private val config get() = SkyHanniMod.feature.misc.commands.tabComplete private var vipVisits = listOf() - private val ignoredCommandCategories = mapOf( - "f" to listOf(PlayerCategory.FRIENDS), - "friend" to listOf(PlayerCategory.FRIENDS), - "msg" to listOf(), - "w" to listOf(), - "tell" to listOf(), - "boop" to listOf(), + private val friendsEntry = lazyEntry { FriendAPI.getAllFriends().map { it.name } } + private val partyMembersEntry = lazyEntry { PartyAPI.partyMembers } + private val guildMembersEntry = lazyEntry { GuildAPI.getAllMembers() } + private val vipVisitsEntry = lazyEntry { vipVisits } + private val islandPlayersEntry = lazyEntry { EntityUtils.getPlayerEntities().map { it.name } } + + private val suggestions = SuggestionProvider.build { + parent("f", "friend") { + parent("accept", "add", "deny") { add(getExcluding(PlayerCategory.FRIENDS)) } + parent("best") { add(friendsEntry) } + parent("remove", "nickname") { add(friendsEntry) } + parent("list") { literal("best") } + literal("help", "notifications", "removeall", "requests") + } - "visit" to listOf(), - "invite" to listOf(), - "ah" to listOf(), + parent("g", "guild") { + parent("invite") { add(getExcluding(PlayerCategory.GUILD)) } + parent("kick", "transfer", "setrank", "promote", "demote") { add(guildMembersEntry) } + parent("mute", "unmute") { + add(guildMembersEntry) + literal("everyone") + } + parent("member") { add(guildMembersEntry) } + literal( + "top", "toggle", "tagcolor", "tag", "slow", "settings", "rename", "quest", "permissions", "party", "onlinemode", + "online", "officerchat", "notifications", "mypermissions", "motd", "menu", "members", "log", "leave", "info", "history", + "help", "discord", "disband", "create", "chat", "accept", + ) + } - "pv" to listOf(), // NEU's Profile Viewer - "shmarkplayer" to listOf(), // SkyHanni's Mark Player + parent("p", "party") { + parent("accept", "invite") { add(getExcluding(PlayerCategory.PARTY)) } + conditional({ PartyAPI.partyMembers.isNotEmpty() }) { + parent("kick", "demote", "promote", "transfer") { add(partyMembersEntry) } + literal("chat", "disband", "kickoffline", "leave", "list", "mute", "poll", "private", "settings", "warp") + } + } - "trade" to listOf(PlayerCategory.FRIENDS, PlayerCategory.PARTY), - ) + parent("w", "msg", "tell", "boop") { add(getExcluding()) } - @SubscribeEvent - fun onRepoReload(event: RepositoryReloadEvent) { - val data = event.getConstant("VipVisits") - vipVisits = data.vipVisits - } + parent("visit") { + add(getExcluding()) + conditional({ config.vipVisits }) { + add(vipVisitsEntry) + } + } - @SubscribeEvent - fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { - event.move(2, "misc.tabCompleteCommands", "commands.tabComplete") + parent("invite") { add(getExcluding()) } + parent("ah") { add(getExcluding()) } + + parent("pv") { add(getExcluding()) } + parent("shmarkplayer") { add(getExcluding()) } + + parent("trade") { add(islandPlayersEntry) } } enum class PlayerCategory { FRIENDS, ISLAND_PLAYERS, PARTY, + GUILD, } - fun handleTabComplete(command: String): List? { - val ignoredCategories = ignoredCommandCategories[command] ?: return null - - return buildList { + private fun getExcluding(vararg categories: PlayerCategory) = LazySuggestionEntry { + if (config.friends && PlayerCategory.FRIENDS !in categories) { + addAll(FriendAPI.getAllFriends().filter { it.bestFriend || !config.onlyBestFriends }.map { it.name }) + } + if (config.islandPlayers && PlayerCategory.ISLAND_PLAYERS !in categories) { + addAll(EntityUtils.getPlayerEntities().map { it.name }) + } + if (config.party && PlayerCategory.PARTY !in categories) { + addAll(PartyAPI.partyMembers) + } + if (config.guild && PlayerCategory.GUILD !in categories) { + addAll(GuildAPI.getAllMembers()) + } + } - if (config.friends && PlayerCategory.FRIENDS !in ignoredCategories) { - FriendAPI.getAllFriends().filter { it.bestFriend || !config.onlyBestFriends }.forEach { add(it.name) } - } + private fun lazyEntry(getter: () -> List) = LazySuggestionEntry { addAll(getter()) } - if (config.islandPlayers && PlayerCategory.ISLAND_PLAYERS !in ignoredCategories) { - for (entity in EntityUtils.getPlayerEntities()) { - add(entity.name) - } - } + fun handleTabComplete(command: String): List? = suggestions.getSuggestions(command).takeIf { it.isNotEmpty() }?.distinct() - if (config.party && PlayerCategory.PARTY !in ignoredCategories) { - for (member in PartyAPI.partyMembers) { - add(member) - } - } + @SubscribeEvent + fun onRepoReload(event: RepositoryReloadEvent) { + val data = event.getConstant("VipVisits") + vipVisits = data.vipVisits + } - if (config.vipVisits && command == "visit") { - for (visit in vipVisits) { - add(visit) - } - } - } + @SubscribeEvent + fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { + event.move(2, "misc.tabCompleteCommands", "commands.tabComplete") } } 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 602c4a3b9e10..aa66b69377dd 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 @@ -14,20 +14,18 @@ object TabComplete { @SubscribeEvent fun handleTabComplete(event: TabCompletionEvent) { val splits = event.leftOfCursor.split(" ") - if (splits.size > 1) { - var command = splits.first().lowercase() - if (command.startsWith("/")) { - command = command.substring(1) - customTabComplete(command)?.let { - event.addSuggestions(it) - } - } + if (splits.size <= 1) return + var command = splits.first().lowercase() + if (!command.startsWith("/")) return + command = command.substring(1) + customTabComplete(event.leftOfCursor.substring(1), command)?.let { + event.addSuggestions(it) } } - private fun customTabComplete(command: String): List? { + private fun customTabComplete(fullCommand: String, command: String): List? { GetFromSacksTabComplete.handleTabComplete(command)?.let { return it } - PlayerTabComplete.handleTabComplete(command)?.let { return it } + PlayerTabComplete.handleTabComplete(fullCommand)?.let { return it } CollectionTracker.handleTabComplete(command)?.let { return it } PartyCommands.customTabComplete(command)?.let { return it } ViewRecipeCommand.customTabComplete(command)?.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 34e962890553..54ef80f77a4d 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/cosmetics/CosmeticFollowingLine.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/cosmetics/CosmeticFollowingLine.kt @@ -72,7 +72,7 @@ object CosmeticFollowingLine { } private fun updateClose(event: LorenzRenderWorldEvent) { - val playerLocation = event.exactLocation(Minecraft.getMinecraft().thePlayer).add(y = 0.3) + val playerLocation = event.exactLocation(Minecraft.getMinecraft().thePlayer).up(0.3) latestLocations = latestLocations.editCopy { val locationSpot = LocationSpot(SimpleTimeMark.now(), Minecraft.getMinecraft().thePlayer.onGround) @@ -113,7 +113,7 @@ object CosmeticFollowingLine { } if (event.isMod(2)) { - val playerLocation = LocationUtils.playerLocation().add(y = 0.3) + val playerLocation = LocationUtils.playerLocation().up(0.3) locations.keys.lastOrNull()?.let { if (it.distance(playerLocation) < 0.1) return 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 8b2d600695e1..377d7bfd405f 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/CroesusChestTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/CroesusChestTracker.kt @@ -138,9 +138,11 @@ object CroesusChestTracker { val lore = item.getLore() if (run.floor == null) run.floor = - (if (masterPattern.matches(item.name)) "M" else "F") + (lore.firstNotNullOfOrNull { - floorPattern.matchMatcher(it) { group("floor").romanToDecimal() } - } ?: "0") + (if (masterPattern.matches(item.name)) "M" else "F") + ( + lore.firstNotNullOfOrNull { + floorPattern.matchMatcher(it) { group("floor").romanToDecimal() } + } ?: "0" + ) run.openState = when { keyUsedPattern.anyMatches(lore) -> OpenedState.KEY_USED openedPattern.anyMatches(lore) -> OpenedState.OPENED @@ -274,11 +276,12 @@ object CroesusChestTracker { fun generateMaxChestAsList(): List = generateMaxChest().toList() private fun generateMaxChest(): Sequence = generateSequence { DungeonRunInfo() }.take(MAX_CHESTS) - fun getLastActiveChest(includeDungeonKey: Boolean = false): Int = - (croesusChests?.indexOfLast { + private fun getLastActiveChest(includeDungeonKey: Boolean = false): Int = ( + croesusChests?.indexOfLast { it.floor != null && (it.openState == OpenedState.UNOPENED || (includeDungeonKey && it.openState == OpenedState.OPENED)) - } ?: -1) + 1 + } ?: -1 + ) + 1 enum class OpenedState { UNOPENED, 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 f95c846b2a0a..7ea372b20d33 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonAPI.kt @@ -1,5 +1,6 @@ package at.hannibal2.skyhanni.features.dungeon +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.data.ClickType import at.hannibal2.skyhanni.data.ClickedBlockType import at.hannibal2.skyhanni.data.IslandType @@ -360,9 +361,9 @@ object DungeonAPI { } } - @SubscribeEvent + @HandleEvent(onlyOnIsland = IslandType.CATACOMBS) fun onBlockClick(event: BlockClickEvent) { - if (!inDungeon() || event.clickType != ClickType.RIGHT_CLICK) return + if (event.clickType != ClickType.RIGHT_CLICK) return val position = event.position val blockType: ClickedBlockType = when (position.getBlockAt()) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonArchitectFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonArchitectFeatures.kt index 662c366045b1..284f8424ffe2 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonArchitectFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonArchitectFeatures.kt @@ -49,7 +49,8 @@ object DungeonArchitectFeatures { if (architectItemAmount <= 0) return GetFromSackAPI.getFromChatMessageSackItems( - architectsFirstDraft, "§c§lPUZZLE FAILED! §r§b$name §r§efailed a puzzle. \n" + + architectsFirstDraft, + "§c§lPUZZLE FAILED! §r§b$name §r§efailed a puzzle. \n" + "§eClick here to get §5Architect's First Draft §7(§e${architectItemAmount}x left§7)" ) diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonBossAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonBossAPI.kt new file mode 100644 index 000000000000..5a7d0ff313a8 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonBossAPI.kt @@ -0,0 +1,171 @@ +package at.hannibal2.skyhanni.features.dungeon + +import at.hannibal2.skyhanni.events.DungeonBossPhaseChangeEvent +import at.hannibal2.skyhanni.events.DungeonCompleteEvent +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent +import at.hannibal2.skyhanni.features.dungeon.DungeonAPI.dungeonFloor +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +@SkyHanniModule +object DungeonBossAPI { + var bossPhase: DungeonBossPhase? = null + + enum class DungeonBossPhase { + F6_TERRACOTTA, + F6_GIANTS, + F6_SADAN, + F7_MAXOR, + F7_STORM, + F7_GOLDOR_1, + F7_GOLDOR_2, + F7_GOLDOR_3, + F7_GOLDOR_4, + F7_GOLDOR_5, + F7_NECRON, + M7_WITHER_KING, + } + + private val patternGroup = RepoPattern.group("dungeon.boss.message") + + /** + * REGEX-TEST: §c[BOSS] Sadan§r§f: So you made it all the way here... Now you wish to defy me\? Sadan\?! + */ + private val terracottaStartPattern by patternGroup.pattern( + "f6.terracotta", + "§c\\[BOSS] Sadan§r§f: So you made it all the way here\\.\\.\\. Now you wish to defy me\\? Sadan\\?!", + ) + + /** + * REGEX-TEST: §c[BOSS] Sadan§r§f: ENOUGH! + */ + private val giantsStartPattern by patternGroup.pattern( + "f6.giants", + "§c\\[BOSS] Sadan§r§f: ENOUGH!", + ) + + /** + * REGEX-TEST: §c[BOSS] Sadan§r§f: You did it. I understand now, you have earned my respect. + */ + private val sadanStartPattern by patternGroup.pattern( + "f6.sadan", + "§c\\[BOSS] Sadan§r§f: You did it\\. I understand now, you have earned my respect\\.", + ) + + /** + * REGEX-TEST: §4[BOSS] Maxor§r§c: §r§cWELL! WELL! WELL! LOOK WHO'S HERE! + */ + private val maxorStartPattern by patternGroup.pattern( + "f7.maxor", + "§4\\[BOSS] Maxor§r§c: §r§cWELL! WELL! WELL! LOOK WHO'S HERE!", + ) + + /** + * REGEX-TEST: §4[BOSS] Storm§r§c: §r§cPathetic Maxor, just like expected. + */ + private val stormStartPattern by patternGroup.pattern( + "f7.storm", + "§4\\[BOSS] Storm§r§c: §r§cPathetic Maxor, just like expected\\.", + ) + + /** + * REGEX-TEST: §4[BOSS] Goldor§r§c: §r§cWho dares trespass into my domain? + */ + private val goldorStartPattern by patternGroup.pattern( + "f7.goldor.start", + "§4\\[BOSS] Goldor§r§c: §r§cWho dares trespass into my domain\\?", + ) + + /** + * REGEX-TEST: §bmartimavocado§r§a activated a lever! (§r§c7§r§a/7) + * 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( + "f7.goldor.terminalcomplete", + "§.(?\\w+)§r§a (?:activated|completed) a (?lever|terminal|device)! \\(§r§c(?\\d)§r§a/(?\\d)\\)", + ) + + /** + * REGEX-TEST: §aThe Core entrance is opening! + */ + private val goldor5StartPattern by patternGroup.pattern( + "f7.goldor.5", + "§aThe Core entrance is opening!", + ) + + /** + * REGEX-TEST: §4[BOSS] Necron§r§c: §r§cYou went further than any human before, congratulations. + */ + private val necronStartPattern by patternGroup.pattern( + "f7.necron.start", + "§4\\[BOSS] Necron§r§c: §r§cYou went further than any human before, congratulations\\.", + ) + + /** + * REGEX-TEST: §4[BOSS] Necron§r§c: §r§cAll this, for nothing... + */ + private val witherKingStartPattern by patternGroup.pattern( + "m7.witherking", + "§4\\[BOSS] Necron§r§c: §r§cAll this, for nothing\\.\\.\\.", + ) + + private fun handlePhaseMessage(message: String) { + if (dungeonFloor == "F6" || dungeonFloor == "M6") when { //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 + goldorTerminalPattern.matchMatcher(message) { + val currentTerminal = group("currentTerminal").toIntOrNull() ?: return + val totalTerminals = group("total").toIntOrNull() ?: return + if (currentTerminal != totalTerminals) return + changePhase( + when (bossPhase) { + DungeonBossPhase.F7_GOLDOR_1 -> DungeonBossPhase.F7_GOLDOR_2 + DungeonBossPhase.F7_GOLDOR_2 -> DungeonBossPhase.F7_GOLDOR_3 + DungeonBossPhase.F7_GOLDOR_3 -> DungeonBossPhase.F7_GOLDOR_4 + else -> return + }, + ) + } + when { + maxorStartPattern.matches(message) -> changePhase(DungeonBossPhase.F7_MAXOR) + stormStartPattern.matches(message) -> changePhase(DungeonBossPhase.F7_STORM) + goldorStartPattern.matches(message) -> changePhase(DungeonBossPhase.F7_GOLDOR_1) + goldor5StartPattern.matches(message) -> changePhase(DungeonBossPhase.F7_GOLDOR_5) + necronStartPattern.matches(message) -> changePhase(DungeonBossPhase.F7_NECRON) + witherKingStartPattern.matches(message) -> if (bossPhase != null) changePhase(DungeonBossPhase.M7_WITHER_KING) + } + } + } + + private fun changePhase(newPhase: DungeonBossPhase) { + DungeonBossPhaseChangeEvent(newPhase).post() + bossPhase = newPhase + } + + @SubscribeEvent + fun onWorldChange(event: LorenzWorldChangeEvent) { + bossPhase = null + } + + @SubscribeEvent + fun onDungeonEnd(event: DungeonCompleteEvent) { + bossPhase = null + } + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + if (!LorenzUtils.inSkyBlock) return + + handlePhaseMessage(event.message) + } +} 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 a49369d83f74..1a566c22579d 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonChatFilter.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonChatFilter.kt @@ -16,7 +16,7 @@ object DungeonChatFilter { private val config get() = SkyHanniMod.feature.chat - /// + // // TODO USE SH-REPO private val endPatterns = listOf( "(.*) §r§eunlocked §r§d(.*) Essence §r§8x(.*)§r§e!".toPattern(), @@ -140,9 +140,12 @@ object DungeonChatFilter { private val pickupMessages = listOf( "§fYou found a §r§dWither Essence§r§f! Everyone gains an extra essence!" ) + + /** + * REGEX-TEST: §a[Berserk] §r§fMelee Damage §r§c48%§r§f -> §r§a88% + * REGEX-TEST: §a[Berserk] §r§fWalk Speed §r§c38§r§f -> §r§a68 + */ private val startPatterns = listOf( - //§a[Berserk] §r§fMelee Damage §r§c48%§r§f -> §r§a88% - //§a[Berserk] §r§fWalk Speed §r§c38§r§f -> §r§a68 "§a(.*) §r§f(.*) §r§c(.*)§r§f -> §r§a(.*)".toPattern() ) private val startMessages = listOf( @@ -188,7 +191,7 @@ object DungeonChatFilter { private val messagesEndsWithMap: Map> = mapOf( MessageTypes.END to endMessagesEndWith, ) - /// + // @SubscribeEvent fun onChat(event: LorenzChatEvent) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonCleanEnd.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonCleanEnd.kt index eca75bc7014b..308a5b14438f 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonCleanEnd.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonCleanEnd.kt @@ -99,11 +99,11 @@ object DungeonCleanEnd { if (entity == Minecraft.getMinecraft().thePlayer) return - if (config.F3IgnoreGuardians - && DungeonAPI.isOneOf("F3", "M3") - && entity is EntityGuardian - && entity.entityId != lastBossId - && Minecraft.getMinecraft().thePlayer.isSneaking + if (config.F3IgnoreGuardians && + DungeonAPI.isOneOf("F3", "M3") && + entity is EntityGuardian && + entity.entityId != lastBossId && + Minecraft.getMinecraft().thePlayer.isSneaking ) { return } 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 a710e4fd0e94..9151c1d9eee2 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonFinderFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonFinderFeatures.kt @@ -291,7 +291,7 @@ object DungeonFinderFeatures { val name = stack.getLore().firstOrNull()?.removeColor() if (config.showMissingClasses && dungeonFloorPattern.matches(name)) { if (classNames.contains(selectedClass)) { - classNames[classNames.indexOf(selectedClass)] = "§a${selectedClass}§7" + classNames[classNames.indexOf(selectedClass)] = "§a$selectedClass§7" } toolTip.add("") toolTip.add("§cMissing: §7" + classNames.createCommaSeparatedList()) 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 f0ce80b1b18e..4f29aca52eac 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonHideItems.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonHideItems.kt @@ -194,15 +194,17 @@ object DungeonHideItems { if (isSkeletonSkull(entity)) { movingSkeletonSkulls[entity] = System.currentTimeMillis() - RenderLivingEntityHelper.setEntityColorWithNoHurtTime(entity, LorenzColor.GOLD.toColor().withAlpha(60)) - { - shouldColorMovingSkull(entity) - } + RenderLivingEntityHelper.setEntityColorWithNoHurtTime( + entity, + LorenzColor.GOLD.toColor().withAlpha(60) + ) { shouldColorMovingSkull(entity) } } } private fun shouldColorMovingSkull(entity: Entity) = - SkyHanniMod.feature.dungeon.highlightSkeletonSkull && movingSkeletonSkulls[entity]?.let { it + 200 > System.currentTimeMillis() } ?: false + SkyHanniMod.feature.dungeon.highlightSkeletonSkull && movingSkeletonSkulls[entity]?.let { + it + 200 > System.currentTimeMillis() + } ?: false @SubscribeEvent fun onWorldChange(event: LorenzWorldChangeEvent) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonHighlightClickedBlocks.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonHighlightClickedBlocks.kt index 4d494567d4d6..ca9dd8c1f6bc 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonHighlightClickedBlocks.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonHighlightClickedBlocks.kt @@ -97,7 +97,7 @@ object DungeonHighlightClickedBlocks { blocks.forEach { (position, block) -> event.drawColor(position, block.color) if (config.showText) { - event.drawString(position.add(0.5, 0.5, 0.5), block.displayText, true) + event.drawString(position.blockCenter(), block.displayText, true) } } } 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 e1e8fbaf98eb..2a8595af9e8e 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonLividFinder.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonLividFinder.kt @@ -15,11 +15,10 @@ 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.draw3DLine import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText import at.hannibal2.skyhanni.utils.RenderUtils.drawWaypointFilled -import at.hannibal2.skyhanni.utils.RenderUtils.exactPlayerEyeLocation -import at.hannibal2.skyhanni.utils.getLorenzVec +import at.hannibal2.skyhanni.utils.RenderUtils.drawLineToEye +import at.hannibal2.skyhanni.utils.RenderUtils.exactLocation import net.minecraft.block.BlockStainedGlass import net.minecraft.client.Minecraft import net.minecraft.client.entity.EntityOtherPlayerMP @@ -59,11 +58,11 @@ object DungeonLividFinder { val chatColor = color.getChatColor() lividArmorStand = EntityUtils.getEntities() - .firstOrNull { it.name.startsWith("${chatColor}﴾ ${chatColor}§lLivid") } + .firstOrNull { it.name.startsWith("$chatColor﴾ $chatColor§lLivid") } if (event.isMod(20)) { if (lividArmorStand == null) { - val amountArmorStands = EntityUtils.getEntities().filter { it.name.contains("Livid") }.count() + val amountArmorStands = EntityUtils.getEntities().count { it.name.contains("Livid") } if (amountArmorStands >= 8) { ErrorManager.logErrorStateWithData( "Could not find livid", @@ -134,17 +133,16 @@ object DungeonLividFinder { if (!config.enabled) return val livid = getLividAlive() ?: return - val location = livid.getLorenzVec().add(-0.5, 0.0, -0.5) - val lorenzColor = color ?: return - - event.drawDynamicText(location, lorenzColor.getChatColor() + "Livid", 1.5) + val location = event.exactLocation(livid) if (location.distanceSqToPlayer() < 50) return + event.drawDynamicText(location, lorenzColor.getChatColor() + "Livid", 1.5) + val color = lorenzColor.toColor() - event.draw3DLine(event.exactPlayerEyeLocation(), location.add(0.5, 0.0, 0.5), color, 3, true) - event.drawWaypointFilled(location, color, beacon = false, seeThroughBlocks = true) + event.drawLineToEye(location, color, 3, true) + event.drawWaypointFilled(location.add(-0.5, 0.0, -0.5), color, beacon = false, seeThroughBlocks = true) } @SubscribeEvent 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 80a60ba4b8f1..3968a3d18a87 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonRankTabListColor.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonRankTabListColor.kt @@ -34,7 +34,7 @@ object DungeonRankTabListColor { val sbLevel = group("sbLevel") val rank = groupOrNull("rank") ?: "" val playerName = group("playerName") - //val symbols = group("symbols") + // val symbols = group("symbols") val className = group("className") val classLevel = group("classLevel") diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/HighlightDungeonDeathmite.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/HighlightDungeonDeathmite.kt index 26b129dd9574..15848a9bc859 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/HighlightDungeonDeathmite.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/HighlightDungeonDeathmite.kt @@ -21,8 +21,10 @@ object HighlightDungeonDeathmite { val maxHealth = event.maxHealth if (entity is EntitySilverfish && maxHealth == 1_000_000_000) { - RenderLivingEntityHelper.setEntityColorWithNoHurtTime(entity, LorenzColor.DARK_RED.toColor().withAlpha(20)) - { SkyHanniMod.feature.dungeon.highlightDeathmites } + RenderLivingEntityHelper.setEntityColorWithNoHurtTime( + entity, + LorenzColor.DARK_RED.toColor().withAlpha(20) + ) { SkyHanniMod.feature.dungeon.highlightDeathmites } } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/TerracottaPhase.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/TerracottaPhase.kt index 14e359c29114..69b8ab077f6f 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/TerracottaPhase.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/TerracottaPhase.kt @@ -1,7 +1,6 @@ package at.hannibal2.skyhanni.features.dungeon import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.events.ReceiveParticleEvent import at.hannibal2.skyhanni.events.SkyHanniRenderEntityEvent import at.hannibal2.skyhanni.features.combat.damageindicator.DamageIndicatorManager @@ -15,37 +14,23 @@ object TerracottaPhase { private val config get() = SkyHanniMod.feature.dungeon.terracottaPhase - private var inTerracottaPhase = false - - @SubscribeEvent - fun onChat(event: LorenzChatEvent) { - if (!isEnabled()) return - - if (event.message == "§c[BOSS] Sadan§r§f: So you made it all the way here... Now you wish to defy me? Sadan?!") { - inTerracottaPhase = true - } - - if (event.message == "§c[BOSS] Sadan§r§f: ENOUGH!") { - inTerracottaPhase = false - } - } - @SubscribeEvent(priority = EventPriority.HIGH) fun onRenderLiving(event: SkyHanniRenderEntityEvent.Specials.Pre) { - if (isActive() && config.hideDamageSplash && DamageIndicatorManager.isDamageSplash(event.entity)) { + if (isEnabled() && config.hideDamageSplash && DamageIndicatorManager.isDamageSplash(event.entity)) { event.cancel() } } @SubscribeEvent fun onReceiveParticle(event: ReceiveParticleEvent) { - if (isActive() && config.hideParticles) { + if (isEnabled() && config.hideParticles) { event.cancel() } } - private fun isActive() = isEnabled() && inTerracottaPhase - private fun isEnabled() = - DungeonAPI.inDungeon() && DungeonAPI.inBossRoom && DungeonAPI.getCurrentBoss() == DungeonFloor.F6 + DungeonAPI.inDungeon() && + DungeonAPI.inBossRoom && + DungeonAPI.getCurrentBoss() == DungeonFloor.F6 && + DungeonBossAPI.bossPhase == DungeonBossAPI.DungeonBossPhase.F6_TERRACOTTA } 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 e24a66594edb..b1939a793bf3 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/UniqueGiftingOpportunitiesFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/UniqueGiftingOpportunitiesFeatures.kt @@ -57,12 +57,12 @@ object UniqueGiftingOpportunitiesFeatures { private fun isEnabled() = holdingGift - private val hasNotGiftedNametag = "§a§lꤥ" - private val hasGiftedNametag = "§c§lꤥ" + private const val HAS_NOT_GIFTED_NAMETAG = "§a§lꤥ" + private const val HAS_GIFTED_NAMETAG = "§c§lꤥ" private fun analyzeArmorStand(entity: EntityArmorStand) { if (!config.useArmorStandDetection) return - if (entity.name != hasGiftedNametag) return + if (entity.name != HAS_GIFTED_NAMETAG) return val matchedPlayer = EntityUtils.getEntitiesNearby(entity.getLorenzVec(), 2.0) .singleOrNull { !it.isNPC() } ?: return diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalQuickStart.kt b/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalQuickStart.kt index ee2a9028ae7e..fe7a73d09053 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalQuickStart.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalQuickStart.kt @@ -1,6 +1,7 @@ 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.events.EntityClickEvent import at.hannibal2.skyhanni.events.LorenzChatEvent @@ -32,8 +33,9 @@ object CarnivalQuickStart { private val cowboy by repoGroup.pattern("cowboy", "Carnival Cowboy") private var lastChat = SimpleTimeMark.farPast() + private var lastClicked = SimpleTimeMark.farPast() - @SubscribeEvent + @HandleEvent fun onEntityClick(event: EntityClickEvent) { if (!isEnabled()) return if (lastChat.passedSince() > 5.0.seconds) return @@ -44,6 +46,8 @@ object CarnivalQuickStart { pirate.matches(mob.name) -> "carnival_pirateman" else -> return } + if (lastClicked.passedSince() < 1.seconds) return + lastClicked = SimpleTimeMark.now() HypixelCommands.npcOption(type, "r_2_1") event.cancel() } 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 eff7516617b1..d77861872d6d 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 @@ -1,6 +1,9 @@ package at.hannibal2.skyhanni.features.event.carnival import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.EntityMovementData +import at.hannibal2.skyhanni.data.IslandGraphs +import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.data.Perk import at.hannibal2.skyhanni.data.ProfileStorageData import at.hannibal2.skyhanni.events.LorenzChatEvent @@ -11,6 +14,7 @@ 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.LorenzVec import at.hannibal2.skyhanni.utils.RegexUtils.matches import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.SimpleTimeMark.Companion.fromNow @@ -90,6 +94,9 @@ object CarnivalReminder { "warp to The Carnival", ) { HypixelCommands.warp("carnival") + EntityMovementData.onNextTeleport(IslandType.HUB) { + IslandGraphs.pathFind(LorenzVec(-89.5, 71.0, -18.7), "§aCarnival Tickets", condition = { config.reminderDailyTickets }) + } } nextCheckTime = 5.0.minutes.fromNow() } diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalZombieShootout.kt b/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalZombieShootout.kt index ec18d016b561..8a0d4296ff19 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalZombieShootout.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/carnival/CarnivalZombieShootout.kt @@ -61,10 +61,10 @@ object CarnivalZombieShootout { ) enum class ZombieType(val points: Int, val helmet: String, val color: Color) { - LEATHER(30, "Leather Cap", Color(165, 42, 42)), //Brown - IRON(50, "Iron Helmet", Color(192, 192, 192)), //Silver - GOLD(80, "Golden Helmet", Color(255, 215, 0)), //Gold - DIAMOND(120, "Diamond Helmet", Color(44, 214, 250)) //Diamond + LEATHER(30, "Leather Cap", Color(165, 42, 42)), // Brown + IRON(50, "Iron Helmet", Color(192, 192, 192)), // Silver + GOLD(80, "Golden Helmet", Color(255, 215, 0)), // Gold + DIAMOND(120, "Diamond Helmet", Color(44, 214, 250)) // Diamond } @SubscribeEvent @@ -86,9 +86,13 @@ object CarnivalZombieShootout { zombie to type }.toMap() - drawZombies = - if (config.highestOnly) nearbyZombies.filterValues { zombieType -> zombieType == nearbyZombies.values.maxByOrNull { it.points } } - else nearbyZombies + drawZombies = if (config.highestOnly) + nearbyZombies.filterValues { zombieType -> + zombieType == nearbyZombies.values.maxByOrNull { + it.points + } + } + else nearbyZombies lastUpdate.zombie = SimpleTimeMark.now() } @@ -127,7 +131,7 @@ object CarnivalZombieShootout { content = Renderable.horizontalContainer( listOf( Renderable.itemStack(lamp), - Renderable.string("§6Disappears in $prefix${timer}"), + Renderable.string("§6Disappears in $prefix$timer"), ), spacing = 1, verticalAlign = RenderUtils.VerticalAlignment.CENTER, 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 20cf553b802c..aefce4e58088 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 @@ -1,7 +1,9 @@ package at.hannibal2.skyhanni.features.event.diana import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.data.ClickType +import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.events.BurrowGuessEvent import at.hannibal2.skyhanni.events.ItemClickEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent @@ -73,7 +75,8 @@ object DianaFixChat { HypixelCommands.particleQuality("high") errorCounter = 0 ChatUtils.chat("Now try again!") - }) + } + ) } } else { if (!hasSetToggleMusic) { @@ -87,7 +90,8 @@ object DianaFixChat { HypixelCommands.toggleMusic() errorCounter = 0 ChatUtils.chat("Now try again, please!") - }) + } + ) } } else { ErrorManager.logErrorStateWithData( @@ -100,7 +104,7 @@ object DianaFixChat { } } - @SubscribeEvent + @HandleEvent(onlyOnIsland = IslandType.HUB) fun onItemClick(event: ItemClickEvent) { if (!isEnabled()) return if (event.clickType != ClickType.RIGHT_CLICK) return diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowHelper.kt index aa58c3c0f43f..64b33c93418f 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowHelper.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowHelper.kt @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.features.event.diana import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.data.EntityMovementData import at.hannibal2.skyhanni.data.IslandType @@ -31,10 +32,9 @@ import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland import at.hannibal2.skyhanni.utils.LorenzVec import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators -import at.hannibal2.skyhanni.utils.RenderUtils.draw3DLine import at.hannibal2.skyhanni.utils.RenderUtils.drawColor import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText -import at.hannibal2.skyhanni.utils.RenderUtils.exactPlayerEyeLocation +import at.hannibal2.skyhanni.utils.RenderUtils.drawLineToEye import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.TimeUtils.format import at.hannibal2.skyhanni.utils.toLorenzVec @@ -281,34 +281,32 @@ object GriffinBurrowHelper { if (distance > 10) { // TODO use round(1) val formattedDistance = distance.toInt().addSeparators() - event.drawDynamicText(location.add(y = 1), "§d§lInquisitor §e${formattedDistance}m", 1.7) + event.drawDynamicText(location.up(), "§d§lInquisitor §e${formattedDistance}m", 1.7) } else { - event.drawDynamicText(location.add(y = 1), "§d§lInquisitor", 1.7) + event.drawDynamicText(location.up(), "§d§lInquisitor", 1.7) } if (distance < 5) { InquisitorWaypointShare.maybeRemove(inquis) } - event.drawDynamicText(location.add(y = 1), "§eFrom §b${inquis.displayName}", 1.6, yOff = 9f) + event.drawDynamicText(location.up(), "§eFrom §b${inquis.displayName}", 1.6, yOff = 9f) if (config.inquisitorSharing.showDespawnTime) { val spawnTime = inquis.spawnTime val format = (75.seconds - spawnTime.passedSince()).format() - event.drawDynamicText(location.add(y = 1), "§eDespawns in §b$format", 1.6, yOff = 18f) + event.drawDynamicText(location.up(), "§eDespawns in §b$format", 1.6, yOff = 18f) } } } val currentWarp = BurrowWarpHelper.currentWarp if (config.lineToNext) { - val player = event.exactPlayerEyeLocation() - var color: LorenzColor? val renderLocation = if (currentWarp != null) { color = LorenzColor.AQUA currentWarp.location } else { color = if (shouldFocusOnInquis) LorenzColor.LIGHT_PURPLE else LorenzColor.WHITE - targetLocation?.add(0.5, 0.5, 0.5) ?: return + targetLocation?.blockCenter() ?: return } val lineWidth = if (targetLocation in particleBurrows) { @@ -316,7 +314,7 @@ object GriffinBurrowHelper { 3 } else 2 if (currentWarp == null) { - event.draw3DLine(player, renderLocation, color.toColor(), lineWidth, false) + event.drawLineToEye(renderLocation, color.toColor(), lineWidth, false) } } @@ -330,7 +328,7 @@ object GriffinBurrowHelper { val distance = location.distance(playerLocation) val burrowType = burrow.value event.drawColor(location, burrowType.color, distance > 10) - event.drawDynamicText(location.add(y = 1), burrowType.text, 1.5) + event.drawDynamicText(location.up(), burrowType.text, 1.5) } } @@ -340,10 +338,10 @@ object GriffinBurrowHelper { val distance = guessLocation.distance(playerLocation) event.drawColor(guessLocation, LorenzColor.WHITE, distance > 10) val color = if (currentWarp != null && targetLocation == guessLocation) "§b" else "§f" - event.drawDynamicText(guessLocation.add(y = 1), "${color}Guess", 1.5) + event.drawDynamicText(guessLocation.up(), "${color}Guess", 1.5) if (distance > 5) { val formattedDistance = distance.toInt().addSeparators() - event.drawDynamicText(guessLocation.add(y = 1), "§e${formattedDistance}m", 1.7, yOff = 10f) + event.drawDynamicText(guessLocation.up(), "§e${formattedDistance}m", 1.7, yOff = 10f) } } } @@ -361,7 +359,7 @@ object GriffinBurrowHelper { event.move(2, "diana", "event.diana") } - @SubscribeEvent + @HandleEvent(onlyOnIsland = IslandType.HUB) fun onBlockClick(event: BlockClickEvent) { if (!isEnabled()) return 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 80d6ea0e0df9..f3860276ad47 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 @@ -165,7 +165,7 @@ object GriffinBurrowParticleFinder { return true } - @SubscribeEvent + @HandleEvent(onlyOnIsland = IslandType.HUB) fun onBlockClick(event: BlockClickEvent) { if (!isEnabled()) return if (!config.burrowsSoopyGuess) return 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 0bb5e3dc17a4..35016eda3740 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 @@ -175,7 +175,8 @@ object SoopyGuessBurrow { } val (a, b, c) = solveEquationThing( - LorenzVec(slopeThing.size - 5, slopeThing.size - 3, slopeThing.size - 1), LorenzVec( + LorenzVec(slopeThing.size - 5, slopeThing.size - 3, slopeThing.size - 1), + LorenzVec( slopeThing[slopeThing.size - 5], slopeThing[slopeThing.size - 3], slopeThing[slopeThing.size - 1] 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 93c9efc04021..5e1910d0d1c9 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 @@ -9,10 +9,13 @@ import at.hannibal2.skyhanni.events.hoppity.RabbitFoundEvent import at.hannibal2.skyhanni.features.event.hoppity.HoppityEggType.CHOCOLATE_FACTORY_MILESTONE import at.hannibal2.skyhanni.features.event.hoppity.HoppityEggType.CHOCOLATE_SHOP_MILESTONE import at.hannibal2.skyhanni.features.event.hoppity.HoppityEggType.SIDE_DISH +import at.hannibal2.skyhanni.features.event.hoppity.HoppityEggType.STRAY import at.hannibal2.skyhanni.features.event.hoppity.HoppityEggsManager.eggFoundPattern import at.hannibal2.skyhanni.features.event.hoppity.HoppityEggsManager.getEggType import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryAPI 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.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.ItemUtils.getLore @@ -23,8 +26,10 @@ import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.RegexUtils.firstMatcher 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.SkyBlockItemModifierUtils.getMinecraftId import at.hannibal2.skyhanni.utils.SkyblockSeason +import at.hannibal2.skyhanni.utils.StringUtils.removeColor import net.minecraftforge.fml.common.eventhandler.EventPriority import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @@ -54,7 +59,9 @@ object HoppityAPI { fun getLastRabbit(): String = this.lastNameCache fun isHoppityEvent() = (SkyblockSeason.currentSeason == SkyblockSeason.SPRING || SkyHanniMod.feature.dev.debug.alwaysHoppitys) - fun rarityByRabbit(rabbit: String): LorenzRarity? = hoppityRarities.firstOrNull { it.chatColorCode == rabbit.substring(0, 2) } + fun rarityByRabbit(rabbit: String): LorenzRarity? = hoppityRarities.firstOrNull { + it.chatColorCode == rabbit.substring(0, 2) + } /** * REGEX-TEST: §f1st Chocolate Milestone @@ -103,8 +110,20 @@ object HoppityAPI { ChocolateFactoryStrayTracker.strayCaughtPattern.matchMatcher(it.stack.displayName) { ChocolateFactoryStrayTracker.handleStrayClicked(it) when (groupOrNull("name") ?: return@matchMatcher) { - "Fish the Rabbit" -> EggFoundEvent(HoppityEggType.STRAY, it.slotNumber, null).post() - "El Dorado" -> EggFoundEvent(HoppityEggType.STRAY, it.slotNumber, null).post() + "Fish the Rabbit" -> { + EggFoundEvent(STRAY, it.slotNumber).post() + lastName = "§9Fish the Rabbit" + lastMeal = STRAY + 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 } } @@ -121,7 +140,7 @@ object HoppityAPI { val nameText = (if (clickedStack.hasDisplayName()) clickedStack.displayName else clickedStack.itemName) sideDishNamePattern.matchMatcher(nameText) { - EggFoundEvent(SIDE_DISH, index, null).post() + EggFoundEvent(SIDE_DISH, index).post() lastMeal = SIDE_DISH attemptFireRabbitFound() } @@ -129,12 +148,12 @@ object HoppityAPI { clickedStack.getLore().let { if (!it.any { line -> line == "§eClick to claim!" }) return allTimeLorePattern.firstMatcher(it) { - EggFoundEvent(CHOCOLATE_FACTORY_MILESTONE, index, null).post() + EggFoundEvent(CHOCOLATE_FACTORY_MILESTONE, index).post() lastMeal = CHOCOLATE_FACTORY_MILESTONE attemptFireRabbitFound() } shopLorePattern.firstMatcher(it) { - EggFoundEvent(CHOCOLATE_SHOP_MILESTONE, index, null).post() + EggFoundEvent(CHOCOLATE_SHOP_MILESTONE, index).post() lastMeal = CHOCOLATE_SHOP_MILESTONE attemptFireRabbitFound() } @@ -149,14 +168,15 @@ object HoppityAPI { eggFoundPattern.matchMatcher(event.message) { resetRabbitData() lastMeal = getEggType(event) - lastMeal?.let { EggFoundEvent(it, null, groupOrNull("note")).post() } + val note = groupOrNull("note")?.removeColor() + lastMeal?.let { EggFoundEvent(it, note = note).post() } attemptFireRabbitFound() } HoppityEggsManager.eggBoughtPattern.matchMatcher(event.message) { if (group("rabbitname").equals(lastName)) { lastMeal = HoppityEggType.BOUGHT - EggFoundEvent(HoppityEggType.BOUGHT, null, null).post() + EggFoundEvent(HoppityEggType.BOUGHT).post() attemptFireRabbitFound() } } 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 e84d93dfa6a3..6d201e57edcd 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 @@ -213,7 +213,7 @@ object HoppityCollectionStats { val newItemStack = if (config.rarityDyeRecolor) ItemStack( Items.dye, 1, when (rarity) { - LorenzRarity.COMMON -> 7 // Light gray dye + LorenzRarity.COMMON -> 7 // Light gray dye LorenzRarity.UNCOMMON -> 10 // Lime dye LorenzRarity.RARE -> 4 // Lapis lazuli LorenzRarity.EPIC -> 5 // Purple dye @@ -262,7 +262,7 @@ object HoppityCollectionStats { else -> "" // Never happens } - //List indexing is weird + // List indexing is weird existingLore[replaceIndex - 1] = "§7Obtained by $operationFormat §6$displayAmount" existingLore[replaceIndex] = "§7all-time §6Chocolate." return existingLore @@ -505,7 +505,11 @@ object HoppityCollectionStats { val found = !rabbitNotFoundPattern.anyMatches(itemLore) - if (!found) continue + if (!found) { + // if the config has wrong data, remove it + loggedRabbits.remove(itemName) + continue + } val duplicates = duplicatesFoundPattern.firstMatcher(itemLore) { group("duplicates").formatInt() 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 8962208424e4..13c5301126aa 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 @@ -142,9 +142,9 @@ object HoppityEggLocations { val nameColorCode = (if (name != null) LorenzColor.GREEN else LorenzColor.RED).getChatColor() event.drawColor(location, color, false, 0.5f) - event.drawDynamicText(location.add(y = 0.5), "$nameColorCode$name", 1.2) + event.drawDynamicText(location.up(0.5), "$nameColorCode$name", 1.2) if (location.distanceSqToPlayer() < 100) { - event.drawDynamicText(location.add(y = 0.5), location.toCleanString(), 1.0, yOff = 12f) + event.drawDynamicText(location.up(0.5), location.toCleanString(), 1.0, yOff = 12f) } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocator.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocator.kt index 468fecbcb480..92dbd9dcba8f 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocator.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityEggLocator.kt @@ -24,9 +24,9 @@ import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName import at.hannibal2.skyhanni.utils.NumberUtil.formatInt import at.hannibal2.skyhanni.utils.NumberUtil.roundTo import at.hannibal2.skyhanni.utils.RecalculatingValue -import at.hannibal2.skyhanni.utils.RenderUtils.draw3DLine import at.hannibal2.skyhanni.utils.RenderUtils.drawColor 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.exactPlayerEyeLocation import at.hannibal2.skyhanni.utils.SimpleTimeMark @@ -120,11 +120,10 @@ object HoppityEggLocator { } private fun LorenzRenderWorldEvent.drawGuessLocations() { - val eyeLocation = exactPlayerEyeLocation() for ((index, eggLocation) in possibleEggLocations.withIndex()) { drawEggWaypoint(eggLocation, "§aGuess #${index + 1}") if (config.showLine) { - draw3DLine(eyeLocation, eggLocation.add(0.5, 0.5, 0.5), LorenzColor.GREEN.toColor(), 2, false) + drawLineToEye(eggLocation.blockCenter(), LorenzColor.GREEN.toColor(), 2, false) } } } @@ -136,7 +135,7 @@ object HoppityEggLocator { if (dist < 10 && HoppityEggLocations.hasCollectedEgg(eggLocation)) { val alpha = ((10 - dist) / 10).coerceAtMost(0.5).toFloat() drawColor(eggLocation, LorenzColor.RED, false, alpha) - drawDynamicText(eggLocation.add(y = 1), "§cDuplicate Location!", 1.5) + drawDynamicText(eggLocation.up(), "§cDuplicate Location!", 1.5) } } } @@ -152,10 +151,10 @@ object HoppityEggLocator { config.waypointColor.toChromaColor(), seeThroughBlocks = true, ) - drawDynamicText(it.add(y = 1), "§aGuess", 1.5) + drawDynamicText(it.up(), "§aGuess", 1.5) } if (!drawLocations && config.showLine) { - draw3DLine(eyeLocation, it.add(0.5, 0.5, 0.5), LorenzColor.GREEN.toColor(), 2, false) + drawLineToEye(it.blockCenter(), LorenzColor.GREEN.toColor(), 2, false) } } } @@ -170,7 +169,7 @@ object HoppityEggLocator { } else { drawColor(location, LorenzColor.RED.toColor(), false, 0.5f) } - drawDynamicText(location.add(y = 1), possibleDuplicateLabel, 1.5) + drawDynamicText(location.up(), possibleDuplicateLabel, 1.5) } private fun shouldShowAllEggs() = config.showAllWaypoints && !locatorInHotbar && HoppityEggType.eggsRemaining() @@ -209,7 +208,7 @@ object HoppityEggLocator { lastParticlePosition = null } - @SubscribeEvent + @HandleEvent(onlyOnSkyblock = true) fun onItemClick(event: ItemClickEvent) { if (!isEnabled()) return val item = event.itemInHand ?: return @@ -280,10 +279,12 @@ object HoppityEggLocator { val color = config.waypointColor.toChromaColor() - IslandGraphs.pathFind(location, color, condition = { config.showPathFinder }) + IslandGraphs.pathFind(location, "Hoppity Egg", color, condition = { config.showPathFinder }) } - fun isValidEggLocation(location: LorenzVec): Boolean = HoppityEggLocations.islandLocations.any { it.distance(location) < 5.0 } + fun isValidEggLocation(location: LorenzVec): Boolean = HoppityEggLocations.islandLocations.any { + it.distance(location) < 5.0 + } private fun ReceiveParticleEvent.isVillagerParticle() = type == EnumParticleTypes.VILLAGER_HAPPY && speed == 0.0f && count == 1 @@ -333,7 +334,7 @@ object HoppityEggLocator { HoppityEggLocations.apiEggLocations[LorenzUtils.skyBlockIsland]?.let { for ((i, location) in it.values.withIndex()) { if (i == target) { - IslandGraphs.pathFind(location) + IslandGraphs.pathFind(location, "Hoppity Test", condition = { true }) return } } 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 4a33820d8d55..9b9276420efe 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 @@ -95,7 +95,7 @@ object HoppityEggsCompactChat { } ?: "?" val dupeNumberFormat = if (eventConfig.showDuplicateNumber) { - (HoppityCollectionStats.getRabbitCount(this.lastName) - 1).takeIf { it > 1}?.let { + (HoppityCollectionStats.getRabbitCount(this.lastName)).takeIf { it > 0 }?.let { " §7(§b#$it§7)" } ?: "" } else "" @@ -105,7 +105,7 @@ object HoppityEggsCompactChat { "$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)" + "$mealNameFormat! §d§lNEW ${if (showNewRarity) "$lastRarity " else ""}$lastName §7($lastProfit§7)" } else "?" } 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 b8143d311cf2..a69366931886 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 @@ -120,9 +120,11 @@ object HoppityEggsManager { lastNote = event.note } - @HandleEvent + @HandleEvent(priority = HandleEvent.LOWEST) fun onRabbitFound(event: RabbitFoundEvent) { - HoppityCollectionStats.incrementRabbitCount(event.rabbitName) + DelayedRun.runDelayed(1.seconds) { + HoppityCollectionStats.incrementRabbitCount(event.rabbitName) + } } @SubscribeEvent 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 0d4e09b9c518..4a536465c28f 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 @@ -98,8 +98,8 @@ object HoppityEventSummary { if (year < currentYear || (year == currentYear && !isSpring) && config.eventSummary.enabled) { sendStatsMessage(stats, year) - (ProfileStorageData.profileSpecific?.hoppityEventStats?.get(year)?.also { it.summarized = true } - ?: ErrorManager.skyHanniError("Could not save summarization state in Hoppity Event Summarization.")) + ProfileStorageData.profileSpecific?.hoppityEventStats?.get(year)?.also { it.summarized = true } + ?: ErrorManager.skyHanniError("Could not save summarization state in Hoppity Event Summarization.") } } @@ -131,6 +131,10 @@ object HoppityEventSummary { ) } + private fun HoppityEventStats.getMilestoneCount(): Int = + (mealsFound[HoppityEggType.CHOCOLATE_FACTORY_MILESTONE] ?: 0) + + (mealsFound[HoppityEggType.CHOCOLATE_SHOP_MILESTONE] ?: 0) + private val summaryOperationList by lazy { buildMap Unit> { put(HoppityStat.MEAL_EGGS_FOUND) { sb, stats, year -> @@ -155,8 +159,7 @@ object HoppityEventSummary { } put(HoppityStat.MILESTONE_RABBITS) { sb, stats, _ -> - ((stats.mealsFound[HoppityEggType.CHOCOLATE_FACTORY_MILESTONE] ?: 0) + - (stats.mealsFound[HoppityEggType.CHOCOLATE_SHOP_MILESTONE] ?: 0)).takeIf { it > 0 }?.let { + stats.getMilestoneCount().takeIf { it > 0 }?.let { sb.appendHeadedLine("§7You claimed §b$it §6§lMilestone §r§6${StringUtils.pluralize(it, "Rabbit")}§7.") } } @@ -231,12 +234,18 @@ object HoppityEventSummary { config.eventSummary.statDisplayList.forEach { summaryOperationList[it]?.invoke(statsBuilder, stats, eventYear) } + + // If no stats are found, display a message if (statsBuilder.toString().replace("\n", "").isEmpty()) { - statsBuilder.appendHeadedLine("§c§lNothing to show!\n§c§oGo find some eggs!") + statsBuilder.appendHeadedLine("§c§lNothing to show!") + statsBuilder.appendHeadedLine("§c§oGo find some eggs!") } + // Remove any consecutive empty lines in the stats + val statsBuilderString = statsBuilder.toString().replace(Regex("\n{4,}"), "\n".repeat(3)) + // Append stats - summaryBuilder.append(statsBuilder) + summaryBuilder.append(statsBuilderString) // Footer summaryBuilder.append("§d§l${"▬".repeat(64)}") diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityNpc.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityNpc.kt index 70e148aa9732..bf324a8f66b3 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityNpc.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/HoppityNpc.kt @@ -1,5 +1,8 @@ package at.hannibal2.skyhanni.features.event.hoppity +import at.hannibal2.skyhanni.data.EntityMovementData +import at.hannibal2.skyhanni.data.IslandGraphs +import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.events.GuiContainerEvent import at.hannibal2.skyhanni.events.InventoryCloseEvent import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent @@ -15,6 +18,7 @@ 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.LorenzVec import at.hannibal2.skyhanni.utils.RenderUtils.highlight import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.SkyBlockTime @@ -58,7 +62,16 @@ object HoppityNpc { "New rabbits are available at §aHoppity's Shop§e!", config::hoppityShopReminder, actionName = "warp to hub", - action = { HypixelCommands.warp("hub") }, + action = { + HypixelCommands.warp("hub") + EntityMovementData.onNextTeleport(IslandType.HUB) { + IslandGraphs.pathFind( + LorenzVec(6.4, 70.0, 7.4), + "§aHoppity's Shop", + condition = { config.hoppityShopReminder } + ) + } + }, ) lastReminderSent = SimpleTimeMark.now() diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/MythicRabbitPetWarning.kt b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/MythicRabbitPetWarning.kt index 8162f3a05e86..833583ad05bb 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/MythicRabbitPetWarning.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/MythicRabbitPetWarning.kt @@ -7,8 +7,8 @@ import at.hannibal2.skyhanni.utils.SimpleTimeMark import kotlin.time.Duration.Companion.seconds object MythicRabbitPetWarning { - val mythicRabbit = "§dRabbit" - var lastCheck = SimpleTimeMark.farPast() + private const val MYTHIC_RABBIT_DISPLAY_NAME = "§dRabbit" + private var lastCheck = SimpleTimeMark.farPast() fun check() { if (!HoppityEggsManager.config.petWarning) return @@ -21,7 +21,7 @@ object MythicRabbitPetWarning { } } - fun correctPet() = PetAPI.isCurrentPet(mythicRabbit) + fun correctPet() = PetAPI.isCurrentPet(MYTHIC_RABBIT_DISPLAY_NAME) private fun warn() { ChatUtils.chat("Use a §dMythic Rabbit Pet §efor more chocolate!") 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 new file mode 100644 index 000000000000..47ab47a38240 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/NucleusBarriersBox.kt @@ -0,0 +1,81 @@ +package at.hannibal2.skyhanni.features.event.hoppity + +import at.hannibal2.skyhanni.SkyHanniMod +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.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.expandBlock +import net.minecraft.util.AxisAlignedBB +import net.minecraft.util.BlockPos +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +@SkyHanniModule +object NucleusBarriersBox { + private val config get() = SkyHanniMod.feature.mining.crystalHighlighter + + private var inNucleus = false + + private enum class Crystal(val color: LorenzColor, val boundingBox: AxisAlignedBB) { + AMBER( + LorenzColor.GOLD, + AxisAlignedBB( + BlockPos(474.0, 124.0, 524.0), + BlockPos(485.0, 111.0, 535.0), + ).expandBlock(), + ), + AMETHYST( + LorenzColor.DARK_PURPLE, + AxisAlignedBB( + BlockPos(474.0, 124.0, 492.0), + BlockPos(485.0, 111.0, 503.0), + ).expandBlock(), + ), + TOPAZ( + LorenzColor.YELLOW, + AxisAlignedBB( + BlockPos(508.0, 124.0, 473.0), + BlockPos(519.0, 111.0, 484.0), + ).expandBlock(), + ), + JADE( + LorenzColor.GREEN, + AxisAlignedBB( + BlockPos(542.0, 124.0, 492.0), + BlockPos(553.0, 111.0, 503.0), + ).expandBlock(), + ), + SAPPHIRE( + LorenzColor.BLUE, + AxisAlignedBB( + BlockPos(542.0, 124.0, 524.0), + BlockPos(553.0, 111.0, 535.0), + ).expandBlock(), + ), + } + + @SubscribeEvent + fun onTick(event: LorenzTickEvent) { + inNucleus = IslandAreas.currentAreaName == "Crystal Nucleus" + } + + @SubscribeEvent + fun onRenderWorld(event: LorenzRenderWorldEvent) { + if (!isEnabled()) return + + Crystal.entries.forEach { crystal -> + event.drawFilledBoundingBox_nea( + crystal.boundingBox, + crystal.color.addOpacity(config.opacity), + renderRelativeToCamera = false, + ) + } + } + + private fun isEnabled() = + IslandType.CRYSTAL_HOLLOWS.isInIsland() && (HoppityAPI.isHoppityEvent() || !config.onlyDuringHoppity) && config.enabled && inNucleus +} 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 new file mode 100644 index 000000000000..939dea1b702f --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/event/hoppity/WarpMenuUniques.kt @@ -0,0 +1,58 @@ +package at.hannibal2.skyhanni.features.event.hoppity + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.IslandType +import at.hannibal2.skyhanni.events.LorenzToolTipEvent +import at.hannibal2.skyhanni.features.inventory.chocolatefactory.ChocolateFactoryAPI +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzVec +import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +@SkyHanniModule +object WarpMenuUniques { + + /** + * REGEX-TEST: §bSkyBlock Hub + * REGEX-TEST: §aThe Barn§7 - §bSpawn + * REGEX-TEST: §aCrystal Hollows§7 - §bEntrance + */ + private val islandNamePattern by RepoPattern.pattern( + "inventory.warpmenu.island.name", + "§[ab](?[\\w ']+)(?:§7 - §b.*)?", + ) + + private val collectedEggStorage: MutableMap>? + get() = ChocolateFactoryAPI.profileStorage?.collectedEggLocations + + private val config get() = SkyHanniMod.feature.event.hoppityEggs + + @SubscribeEvent + fun onTooltip(event: LorenzToolTipEvent) { + if (!LorenzUtils.inSkyBlock) return + if (!config.uniquesWarpMenu) return + if (!HoppityAPI.isHoppityEvent()) return + if (event.slot.inventory.name != "Fast Travel") return + + val name = islandNamePattern.matchMatcher(event.slot.stack.displayName) { + group("name") + } ?: return + + val island = when (name) { + "SkyBlock Hub" -> IslandType.HUB + "The Barn" -> IslandType.THE_FARMING_ISLANDS + else -> IslandType.getByNameOrNull(name) ?: return + } + if (island == IslandType.DUNGEON_HUB) return + + if (HoppityEggLocations.apiEggLocations[island]?.size == null) return + val maxEggs = 15 + val collectedEggs = collectedEggStorage?.get(island)?.size ?: 0 + + if (collectedEggs >= maxEggs && config.uniquesWarpMenuHideMax) 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/jerry/frozentreasure/FrozenTreasureTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/event/jerry/frozentreasure/FrozenTreasureTracker.kt index 80812c4c563b..e41a61013210 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/jerry/frozentreasure/FrozenTreasureTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/jerry/frozentreasure/FrozenTreasureTracker.kt @@ -42,8 +42,9 @@ object FrozenTreasureTracker { private var icePerSecond = mutableListOf() private var icePerHour = 0 private var stoppedChecks = 0 - private val tracker = SkyHanniTracker("Frozen Treasure Tracker", { Data() }, { it.frozenTreasureTracker }) - { formatDisplay(drawDisplay(it)) } + private val tracker = SkyHanniTracker("Frozen Treasure Tracker", { Data() }, { it.frozenTreasureTracker }) { + formatDisplay(drawDisplay(it)) + } init { FrozenTreasure.entries.forEach { it.chatPattern } 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 2df035702f8c..8250b023db10 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 @@ -91,7 +91,7 @@ object EasterEggWaypoints { /* Title: §e§lHYPIXEL - + '§703/14/24 §8L30A' ' ' 'Rank: §bMVP§d+§b' @@ -106,7 +106,7 @@ object EasterEggWaypoints { 'Easter Eggs: §a0/§a30' ' ' '§ewww.hypixel.net' - */ + */ private fun checkScoreboardEasterSpecific(): Boolean { val a = ScoreboardData.sidebarLinesFormatted.any { it.contains("Hypixel Level") } val b = ScoreboardData.sidebarLinesFormatted.any { it.contains("Easter") } 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 5a1e1361a784..cf5d3ce5a5a2 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fame/CityProjectFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fame/CityProjectFeatures.kt @@ -2,6 +2,9 @@ package at.hannibal2.skyhanni.features.fame import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator +import at.hannibal2.skyhanni.data.EntityMovementData +import at.hannibal2.skyhanni.data.IslandGraphs +import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.data.ProfileStorageData import at.hannibal2.skyhanni.events.GuiContainerEvent import at.hannibal2.skyhanni.events.GuiRenderEvent @@ -20,6 +23,7 @@ import at.hannibal2.skyhanni.utils.ItemUtils.itemName import at.hannibal2.skyhanni.utils.ItemUtils.name import at.hannibal2.skyhanni.utils.LorenzColor import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzVec import at.hannibal2.skyhanni.utils.NEUInternalName import at.hannibal2.skyhanni.utils.NEUItems import at.hannibal2.skyhanni.utils.NEUItems.getItemStack @@ -79,7 +83,16 @@ object CityProjectFeatures { "Daily City Project Reminder!", config::dailyReminder, actionName = "warp to Hub", - action = { HypixelCommands.warp("hub") }, + action = { + HypixelCommands.warp("hub") + EntityMovementData.onNextTeleport(IslandType.HUB) { + IslandGraphs.pathFind( + LorenzVec(9.3, 72.0, -103.4), + "§aCity Project", + condition = { config.dailyReminder }, + ) + } + }, ) } 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 d5f33204ce25..b55aa8f11e7f 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fame/UpgradeReminder.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fame/UpgradeReminder.kt @@ -2,6 +2,9 @@ package at.hannibal2.skyhanni.features.fame import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator +import at.hannibal2.skyhanni.data.EntityMovementData +import at.hannibal2.skyhanni.data.IslandGraphs +import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.data.ProfileStorageData import at.hannibal2.skyhanni.events.GuiContainerEvent import at.hannibal2.skyhanni.events.InventoryCloseEvent @@ -13,6 +16,7 @@ import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.HypixelCommands import at.hannibal2.skyhanni.utils.ItemUtils.getLore import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzVec import at.hannibal2.skyhanni.utils.RegexUtils.anyMatches import at.hannibal2.skyhanni.utils.RegexUtils.matchFirst import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher @@ -92,6 +96,36 @@ object UpgradeReminder { fun onInventoryOpen(event: InventoryFullyOpenedEvent) { if (!LorenzUtils.inSkyBlock) return inInventory = event.inventoryName == "Community Shop" + if (!inInventory) return + + if (currentProfileUpgrade == null && currentAccountUpgrade == null) return + detectWrongAccountUpgradeData(event.inventoryItems) + } + + private fun detectWrongAccountUpgradeData(items: Map) { + val hasProfileUpgrade = foundActiveUpgrade(items, 27..35) + if (!hasProfileUpgrade && currentProfileUpgrade != null) { + ChatUtils.chat("§eRemoved invalid Profile Upgrade information.") + currentProfileUpgrade = null + } + + val hasAccountUpgrade = foundActiveUpgrade(items, 36..44) + if (!hasAccountUpgrade && currentAccountUpgrade != null) { + ChatUtils.chat("§eRemoved invalid Account Upgrade information.") + currentAccountUpgrade = null + } + } + + private fun foundActiveUpgrade(items: Map, slots: IntRange): Boolean { + for (slot in slots) { + val item = items[slot] ?: continue + val isUpgrading = item.getLore().any { it == "§aCurrently upgrading!" } + val isDone = item.getLore().any { it == "§cClick to claim!" } + val isReadyForUpgrade = item.getLore().any { it == "§eClick to start upgrade!" } + if (isUpgrading || isDone) return true + if (isReadyForUpgrade) return false + } + return false } @SubscribeEvent @@ -162,7 +196,16 @@ object UpgradeReminder { "The §a$name §eupgrade has completed!", config::accountUpgradeReminder, actionName = "warp to Hub", - action = { HypixelCommands.warp("hub") }, + action = { + HypixelCommands.warp("hub") + EntityMovementData.onNextTeleport(IslandType.HUB) { + IslandGraphs.pathFind( + LorenzVec(-2.6, 73.0, -101.6), + "§eCommunity Shop", + condition = { config.accountUpgradeReminder }, + ) + } + }, ) } diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/ChumBucketHider.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/ChumBucketHider.kt index 5f64aba8c2d1..3eac15fc675f 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/ChumBucketHider.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/ChumBucketHider.kt @@ -64,7 +64,11 @@ object ChumBucketHider { } // Chum Bucket - if (config.hideBucket.get() && entity.inventory.any { it != null && (it.name == "§fEmpty Chum Bucket" || it.name == "§aEmpty Chumcap Bucket") }) { + if (config.hideBucket.get() && + entity.inventory.any { + it != null && (it.name == "§fEmpty Chum Bucket" || it.name == "§aEmpty Chumcap Bucket") + } + ) { val entityLocation = entity.getLorenzVec() for (title in titleEntity.toSet()) { if (entityLocation.equalsIgnoreY(title.getLorenzVec())) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingAPI.kt index 596d6f49cfd2..89ae7dc18317 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingAPI.kt @@ -9,6 +9,7 @@ import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent import at.hannibal2.skyhanni.events.RepositoryReloadEvent import at.hannibal2.skyhanni.events.entity.EntityEnterWorldEvent +import at.hannibal2.skyhanni.features.dungeon.DungeonAPI import at.hannibal2.skyhanni.features.fishing.trophy.TrophyFishManager import at.hannibal2.skyhanni.features.fishing.trophy.TrophyFishManager.getFilletValue import at.hannibal2.skyhanni.features.fishing.trophy.TrophyRarity @@ -137,7 +138,8 @@ object FishingAPI { return info?.getFilletValue(rarity) ?: 0 } - fun isFishing(checkRodInHand: Boolean = true) = IsFishingDetection.isFishing || (checkRodInHand && holdingRod) + fun isFishing(checkRodInHand: Boolean = true) = + (IsFishingDetection.isFishing || (checkRodInHand && holdingRod)) && !DungeonAPI.inDungeon() fun seaCreatureCount(entity: EntityArmorStand): Int { val name = entity.name diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/LavaReplacement.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/LavaReplacement.kt new file mode 100644 index 000000000000..663f2d87aae1 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/LavaReplacement.kt @@ -0,0 +1,31 @@ +package at.hannibal2.skyhanni.features.fishing + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.IslandType +import at.hannibal2.skyhanni.events.ConfigLoadEvent +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.ConditionalUtils +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland +import net.minecraft.client.Minecraft +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +@SkyHanniModule +object LavaReplacement { + + private val config get() = SkyHanniMod.feature.fishing.lavaReplacement + + @SubscribeEvent + fun onConfigLoad(event: ConfigLoadEvent) { + ConditionalUtils.onToggle(config.enabled, config.onlyInCrimsonIsle) { + Minecraft.getMinecraft().renderGlobal.loadRenderers() + } + } + + @JvmStatic + fun replaceLava(): Boolean { + if (!LorenzUtils.inSkyBlock || !config.enabled.get()) return false + if (config.onlyInCrimsonIsle.get() && !IslandType.CRIMSON_ISLE.isInIsland()) return false + return true + } +} 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 04b4fc7489ce..514d330a4bee 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/ShowFishingItemName.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/ShowFishingItemName.kt @@ -64,7 +64,7 @@ object ShowFishingItemName { if (!isEnabled()) return for ((item, text) in itemsOnGround) { - val location = event.exactLocation(item).add(y = 0.8) + val location = event.exactLocation(item).up(0.8) event.drawString(location, text) } } 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 d1220d7e39be..b84ee2970b0d 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/ThunderSparksHighlight.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/ThunderSparksHighlight.kt @@ -10,7 +10,6 @@ import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.BlockUtils.getBlockAt import at.hannibal2.skyhanni.utils.EntityUtils import at.hannibal2.skyhanni.utils.EntityUtils.hasSkullTexture -import at.hannibal2.skyhanni.utils.LocationUtils import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland @@ -47,7 +46,6 @@ object ThunderSparksHighlight { val special = config.color val color = Color(SpecialColor.specialToChromaRGB(special), true) - val playerLocation = LocationUtils.playerLocation() for (spark in sparks) { if (spark.isDead) continue val sparkLocation = spark.getLorenzVec() @@ -55,10 +53,10 @@ object ThunderSparksHighlight { val seeThroughBlocks = sparkLocation.distanceToPlayer() < 6 && (block == Blocks.flowing_lava || block == Blocks.lava) event.drawWaypointFilled( - sparkLocation.add(-0.5, 0.0, -0.5), color, extraSize = -0.25, seeThroughBlocks = seeThroughBlocks + sparkLocation.add(-0.5, 0.0, -0.5), color, extraSize = -0.25, seeThroughBlocks = seeThroughBlocks, ) - if (sparkLocation.distance(playerLocation) < 10) { - event.drawString(sparkLocation.add(y = 1.5), "Thunder Spark", seeThroughBlocks = seeThroughBlocks) + if (sparkLocation.distanceToPlayer() < 10) { + event.drawString(sparkLocation.up(1.5), "Thunder Spark", seeThroughBlocks = seeThroughBlocks) } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/TotemOfCorruption.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/TotemOfCorruption.kt index 9896580c6b2b..079f1cc630a6 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/TotemOfCorruption.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/TotemOfCorruption.kt @@ -96,11 +96,11 @@ object TotemOfCorruption { // The center of the totem is the upper part of the armor stand when (config.outlineType) { OutlineType.FILLED -> { - event.drawSphereInWorld(color, totem.location.add(y = 1), 16f) + event.drawSphereInWorld(color, totem.location.up(), 16f) } OutlineType.WIREFRAME -> { - event.drawSphereWireframeInWorld(color, totem.location.add(y = 1), 16f) + event.drawSphereWireframeInWorld(color, totem.location.up(), 16f) } else -> return 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 12f3accd1de1..a3e86908762f 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 @@ -98,8 +98,8 @@ object FishingProfitTracker { private val MAGMA_FISH by lazy { "MAGMA_FISH".asInternalName() } - private val nameAll: CategoryName = "All" - private var currentCategory: CategoryName = nameAll + private const val NAME_ALL: CategoryName = "All" + private var currentCategory: CategoryName = NAME_ALL private var itemCategories = mapOf>() @@ -110,7 +110,7 @@ object FishingProfitTracker { private fun getCurrentCategories(data: Data): Map { val map = mutableMapOf() - map[nameAll] = data.items.size + map[NAME_ALL] = data.items.size for ((name, items) in itemCategories) { val amount = items.count { it in data.items } if (amount > 0) { @@ -145,7 +145,7 @@ object FishingProfitTracker { checkMissingItems(data) val list = amounts.keys.toList() if (currentCategory !in list) { - currentCategory = nameAll + currentCategory = NAME_ALL } if (tracker.isInventoryOpen()) { @@ -160,7 +160,7 @@ object FishingProfitTracker { ) } - val filter: (NEUInternalName) -> Boolean = if (currentCategory == nameAll) { + val filter: (NEUInternalName) -> Boolean = if (currentCategory == NAME_ALL) { { true } } else { val items = itemCategories[currentCategory]!! diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/tracker/SeaCreatureTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/tracker/SeaCreatureTracker.kt index b293c2736fbf..e106858012de 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/tracker/SeaCreatureTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/tracker/SeaCreatureTracker.kt @@ -4,11 +4,13 @@ import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.events.ConfigLoadEvent import at.hannibal2.skyhanni.events.FishingBobberCastEvent import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.ProfileJoinEvent import at.hannibal2.skyhanni.events.SeaCreatureFishEvent import at.hannibal2.skyhanni.features.fishing.FishingAPI import at.hannibal2.skyhanni.features.fishing.SeaCreatureManager import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.test.command.ErrorManager +import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString import at.hannibal2.skyhanni.utils.CollectionUtils.sumAllValues @@ -25,11 +27,13 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @SkyHanniModule object SeaCreatureTracker { + private var needMigration = true private val config get() = SkyHanniMod.feature.fishing.seaCreatureTracker - private val tracker = SkyHanniTracker("Sea Creature Tracker", { Data() }, { it.fishing.seaCreatureTracker }) - { drawDisplay(it) } + private val tracker = SkyHanniTracker("Sea Creature Tracker", { Data() }, { it.fishing.seaCreatureTracker }) { + drawDisplay(it) + } class Data : TrackerData() { @@ -55,12 +59,12 @@ object SeaCreatureTracker { } } - private val nameAll: CategoryName = "All" - private var currentCategory: CategoryName = nameAll + private const val NAME_ALL: CategoryName = "All" + private var currentCategory: CategoryName = NAME_ALL private fun getCurrentCategories(data: Data): Map { val map = mutableMapOf() - map[nameAll] = data.amount.size + map[NAME_ALL] = data.amount.size for ((category, names) in SeaCreatureManager.allVariants) { val amount = names.count { it in data.amount } if (amount > 0) { @@ -71,7 +75,15 @@ object SeaCreatureTracker { return map } + @SubscribeEvent + fun onProfileJoin(event: ProfileJoinEvent) { + needMigration = true + } + private fun drawDisplay(data: Data): List = buildList { + // manually migrating from "Phlhlegblast" to "Plhlegblast" when the new name is in the repo + tryToMigrate(data.amount) + addSearchString("§7Sea Creature Tracker:") val filter: (String) -> Boolean = addCategories(data) @@ -84,7 +96,7 @@ object SeaCreatureTracker { "Sea Creature Tracker can not display a name correctly", "Could not find sea creature by name", "SeaCreatureManager.allFishingMobs.keys" to SeaCreatureManager.allFishingMobs.keys, - "name" to name + "name" to name, ) name } @@ -99,11 +111,30 @@ object SeaCreatureTracker { addSearchString(" §7- §e${total.addSeparators()} §7Total Sea Creatures") } + private fun tryToMigrate( + data: MutableMap, + ) { + if (!needMigration) return + needMigration = false + + val oldName = "Phlhlegblast" + val newName = "Plhlegblast" + + // only migrate once the repo contains the new name + if (SeaCreatureManager.allFishingMobs.containsKey(newName)) { + data[oldName]?.let { + ChatUtils.debug("Sea Creature Tracker migrated $it $oldName to $newName") + data[newName] = it + data.remove(oldName) + } + } + } + private fun MutableList.addCategories(data: Data): (String) -> Boolean { val amounts = getCurrentCategories(data) val list = amounts.keys.toList() if (currentCategory !in list) { - currentCategory = nameAll + currentCategory = NAME_ALL } if (tracker.isInventoryOpen()) { @@ -114,11 +145,11 @@ object SeaCreatureTracker { val id = list.indexOf(currentCategory) currentCategory = list[(id + 1) % list.size] tracker.update() - } + }, ) } - return if (currentCategory == nameAll) { + return if (currentCategory == NAME_ALL) { { true } } else filterCurrentCategory() } @@ -160,6 +191,5 @@ object SeaCreatureTracker { tracker.resetCommand() } - private fun isEnabled() = - LorenzUtils.inSkyBlock && config.enabled && !FishingAPI.wearingTrophyArmor && !LorenzUtils.inKuudraFight + private fun isEnabled() = LorenzUtils.inSkyBlock && config.enabled && !FishingAPI.wearingTrophyArmor && !LorenzUtils.inKuudraFight } 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 7a0e2d65f822..b7c67034feab 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 @@ -35,9 +35,7 @@ import at.hannibal2.skyhanni.utils.RenderUtils.exactLocation import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.SoundUtils -import at.hannibal2.skyhanni.utils.TimeLimitedSet import at.hannibal2.skyhanni.utils.TimeUtils.format -import at.hannibal2.skyhanni.utils.getLorenzVec import at.hannibal2.skyhanni.utils.renderables.Renderable import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import net.minecraft.entity.EntityLivingBase 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 fec662f396a6..3a6333a9c150 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 @@ -21,7 +21,7 @@ object TrophyFishAPI { |${TrophyRarity.BRONZE.formattedString}: ${formatCount(counts, TrophyRarity.BRONZE)} | |§7Total: ${bestFishObtained.formatCode}${counts.values.sum().addSeparators()} - """.trimMargin() + """.trimMargin() } private fun formatCount(counts: Map, rarity: TrophyRarity): String { diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishMessages.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishMessages.kt index 7068ef8aa7b4..4a23e84e5d52 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishMessages.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishMessages.kt @@ -14,10 +14,12 @@ import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.NumberUtil.ordinal import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.SoundUtils import at.hannibal2.skyhanni.utils.StringUtils.removeColor import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import net.minecraft.util.ChatComponentText import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration.Companion.seconds @SkyHanniModule object TrophyFishMessages { @@ -38,8 +40,7 @@ object TrophyFishMessages { } ?: return val internalName = getInternalName(displayName) - val rawRarity = displayRarity.lowercase().removeColor() - val rarity = TrophyRarity.getByName(rawRarity) ?: return + val rarity = TrophyRarity.getByName(displayRarity.lowercase().removeColor()) ?: return val trophyFishes = TrophyFishManager.fish ?: return val trophyFishCounts = trophyFishes.getOrPut(internalName) { mutableMapOf() } @@ -50,6 +51,15 @@ object TrophyFishMessages { event.blockedReason = "low_trophy_fish" return } + if (config.goldAlert && rarity == TrophyRarity.GOLD) { + sendTitle(displayName, displayRarity, amount) + if (config.playSound) SoundUtils.playBeepSound() + } + + if (config.diamondAlert && rarity == TrophyRarity.DIAMOND) { + sendTitle(displayName, displayRarity, amount) + if (config.playSound) SoundUtils.playBeepSound() + } val original = event.chatComponent var edited = original @@ -85,14 +95,23 @@ object TrophyFishMessages { } } + private fun sendTitle(displayName: String, displayRarity: String?, amount: Int) { + val text = "$displayName $displayRarity §8$amount§c!" + LorenzUtils.sendTitle(text, 3.seconds, 2.8, 7f) + } + fun getInternalName(displayName: String): String { return displayName.replace("Obfuscated", "Obfuscated Fish") .replace("[- ]".toRegex(), "").lowercase().removeColor() } private fun shouldBlockTrophyFish(rarity: TrophyRarity, amount: Int) = - config.bronzeHider && rarity == TrophyRarity.BRONZE && amount != 1 - || config.silverHider && rarity == TrophyRarity.SILVER && amount != 1 + config.bronzeHider && + rarity == TrophyRarity.BRONZE && + amount != 1 || + config.silverHider && + rarity == TrophyRarity.SILVER && + amount != 1 @SubscribeEvent fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/AnitaMedalProfit.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/AnitaMedalProfit.kt index 3c34c262c1e1..760df643285a 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/AnitaMedalProfit.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/AnitaMedalProfit.kt @@ -38,7 +38,6 @@ object AnitaMedalProfit { GOLD("§6Gold medal", 8), SILVER("§fSilver medal", 2), BRONZE("§cBronze medal", 1), - ; } private fun getMedal(name: String) = MedalType.entries.firstOrNull { it.displayName == name } @@ -77,7 +76,7 @@ object AnitaMedalProfit { } private fun readItem(slot: Int, item: ItemStack, table: MutableList) { - val itemName = getItemName(item) ?: return + val itemName = getItemName(item) if (itemName == " ") return if (itemName == "§cClose") return if (itemName == "§eUnique Gold Medals") return @@ -106,7 +105,7 @@ object AnitaMedalProfit { "§7Item price: §6${itemPrice.shortFormat()} ", // TODO add more exact material cost breakdown "§7Material cost: §6${fullCost.shortFormat()} ", - "§7Final profit: §6${profitFormat} ", + "§7Final profit: §6$profitFormat ", ) table.add( DisplayTableEntry( 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 3a661161e134..290c5427bb6e 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/CropType.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/CropType.kt @@ -74,7 +74,9 @@ enum class CropType( fun getByNameOrNull(itemName: String): 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) } + return entries.firstOrNull { + it.cropName.equals(itemName, ignoreCase = true) || it.simpleName.equals(itemName, ignoreCase = true) + } } fun getByName(name: String) = getByNameOrNull(name) ?: error("No valid crop type '$name'") 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 4e80bdbea678..7e1800931c41 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt @@ -213,10 +213,8 @@ object GardenAPI { private var lastLocation: LorenzVec? = null - @SubscribeEvent + @HandleEvent(onlyOnIsland = IslandType.GARDEN) fun onBlockClick(event: BlockClickEvent) { - if (!inGarden()) return - val blockState = event.getBlockState val cropBroken = blockState.getCropType() ?: return if (cropBroken.multiplier == 1 && blockState.isBabyCrop()) return 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 4285a24af969..d0a386272a1c 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt @@ -441,7 +441,7 @@ object GardenNextJacobContest { SkyHanniMod.coroutineScope.launch { openPopupWindow( "Farming Contest soon!
" + - "Crops: ${cropTextNoColor}" + "Crops: $cropTextNoColor" ) } } @@ -515,8 +515,10 @@ object GardenNextJacobContest { } private fun isEnabled() = - config.display && ((LorenzUtils.inSkyBlock && (GardenAPI.inGarden() || config.showOutsideGarden)) || - (OutsideSbFeature.NEXT_JACOB_CONTEST.isSelected() && !LorenzUtils.inSkyBlock)) + config.display && ( + (LorenzUtils.inSkyBlock && (GardenAPI.inGarden() || config.showOutsideGarden)) || + (OutsideSbFeature.NEXT_JACOB_CONTEST.isSelected() && !LorenzUtils.inSkyBlock) + ) private fun isFetchEnabled() = isEnabled() && config.fetchAutomatically private fun isSendEnabled() = diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenPlotAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenPlotAPI.kt index 8ad8d21dab1a..373eadfe9463 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenPlotAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenPlotAPI.kt @@ -191,7 +191,7 @@ object GardenPlotAPI { } fun Plot.markExpiredSprayAsNotified() { - getData()?.apply { sprayHasNotified = true } + getData()?.sprayHasNotified = true } private fun Plot.setSpray(spray: SprayType, duration: Duration) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenYawAndPitch.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenYawAndPitch.kt index 171df87e70ab..ef1aaa1bd9c4 100755 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenYawAndPitch.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenYawAndPitch.kt @@ -60,8 +60,10 @@ object GardenYawAndPitch { } private fun isEnabled() = - config.enabled && ((OutsideSbFeature.YAW_AND_PITCH.isSelected() && !LorenzUtils.inSkyBlock) || - (LorenzUtils.inSkyBlock && (GardenAPI.inGarden() || config.showOutsideGarden))) + config.enabled && ( + (OutsideSbFeature.YAW_AND_PITCH.isSelected() && !LorenzUtils.inSkyBlock) || + (LorenzUtils.inSkyBlock && (GardenAPI.inGarden() || config.showOutsideGarden)) + ) @SubscribeEvent fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/SensitivityReducer.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/SensitivityReducer.kt index ceec04aa0f20..d8593047ec26 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/SensitivityReducer.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/SensitivityReducer.kt @@ -126,7 +126,7 @@ object SensitivityReducer { fun manualToggle() { if (isToggled) { - ChatUtils.chat("This command is disabled while the Sensitivity is lowered.") + ChatUtils.userError("This command is disabled while the Sensitivity is lowered!") return } isManualToggle = !isManualToggle 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 058ae15909f9..ffc77934b4c0 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 listOf(displayItem, map[this]!!) + return map[this]?.let { listOf(displayItem, it) } ?: emptyList() } } @@ -72,7 +72,6 @@ object ComposterDisplay { val newDisplay = mutableListOf>() newDisplay.addAsSingletonList("§bComposter") - newDisplay.add(DataType.TIME_LEFT.addToList(tabListData)) val list = mutableListOf() 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 fa45e579dfa3..6059eded9a14 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 @@ -39,8 +39,8 @@ import at.hannibal2.skyhanni.utils.NEUItems.getItemStack import at.hannibal2.skyhanni.utils.NEUItems.getPrice import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.NumberUtil.romanToDecimalIfNecessary -import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat import at.hannibal2.skyhanni.utils.NumberUtil.roundTo +import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.RenderUtils.renderStringsAndItems import at.hannibal2.skyhanni.utils.SimpleTimeMark @@ -344,7 +344,7 @@ object ComposterOverlay { newList.addAsSingletonList(" §7$compostPerTitle: §e${multiplier.roundTo(2)}$compostPerTitlePreview") val organicMatterPrice = getPrice(organicMatterItem) - val organicMatterFactor = organicMatterFactors[organicMatterItem]!! + val organicMatterFactor = organicMatterFactors[organicMatterItem] ?: 1.0 val organicMatterRequired = ComposterAPI.organicMatterRequiredPer(null) val organicMatterRequiredPreview = ComposterAPI.organicMatterRequiredPer(upgrade) @@ -353,7 +353,7 @@ object ComposterOverlay { val organicMatterPricePerPreview = organicMatterPrice * (organicMatterRequiredPreview / organicMatterFactor) val fuelPrice = getPrice(fuelItem) - val fuelFactor = fuelFactors[fuelItem]!! + val fuelFactor = fuelFactors[fuelItem] ?: 1.0 val fuelRequired = ComposterAPI.fuelRequiredPer(null) val fuelRequiredPreview = ComposterAPI.fuelRequiredPer(upgrade) @@ -427,7 +427,7 @@ object ComposterOverlay { i++ if (i < testOffset) continue if (first == null) first = internalName - val factor = factors[internalName]!! + val factor = factors[internalName] ?: 1.0 val item = internalName.getItemStack() val price = getPrice(internalName) @@ -488,7 +488,7 @@ object ComposterOverlay { } val havingInInventory = internalName.getAmountInInventory() if (havingInInventory >= itemsNeeded) { - ChatUtils.chat("$itemName §8x${itemsNeeded} §ealready found in inventory!") + ChatUtils.chat("$itemName §8x$itemsNeeded §ealready found in inventory!") return } @@ -564,18 +564,24 @@ object ComposterOverlay { } } + private val blockedItems = listOf( + "POTION_AFFINITY_TALISMAN", + "CROPIE_TALISMAN", + "SPEED_TALISMAN", + "SIMPLE_CARROT_CANDY", + ) + + private fun isBlockedArmor(internalName: String): Boolean { + return internalName.endsWith("_BOOTS") || + internalName.endsWith("_HELMET") || + internalName.endsWith("_CHESTPLATE") || + internalName.endsWith("_LEGGINGS") + } + private fun updateOrganicMatterFactors(baseValues: Map): Map { val map = mutableMapOf() for ((internalName, _) in NEUItems.allNeuRepoItems()) { - if (internalName == "POTION_AFFINITY_TALISMAN" - || internalName == "CROPIE_TALISMAN" - || internalName.endsWith("_BOOTS") - || internalName.endsWith("_HELMET") - || internalName.endsWith("_CHESTPLATE") - || internalName.endsWith("_LEGGINGS") - || internalName == "SPEED_TALISMAN" - || internalName == "SIMPLE_CARROT_CANDY" - ) continue + if (blockedItems.contains(internalName) || isBlockedArmor(internalName)) continue var (newId, amount) = NEUItems.getPrimitiveMultiplier(internalName.asInternalName()) if (amount <= 9) continue @@ -633,20 +639,20 @@ object ComposterOverlay { add("currentOrganicMatterItem: $currentOrganicMatterItem") add("currentFuelItem: $currentFuelItem") - println(" ") + add(" ") val composterUpgrades = ComposterAPI.composterUpgrades if (composterUpgrades == null) { - println("composterUpgrades is null") + add("composterUpgrades is null") } else { for ((a, b) in composterUpgrades) { - println("upgrade $a: $b") + add("upgrade $a: $b") } } - println(" ") + add(" ") val tabListData = ComposterAPI.tabListData for ((a, b) in tabListData) { - println("tabListData $a: $b") + add("tabListData $a: $b") } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/contest/FarmingContest.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/contest/FarmingContest.kt index 5bf2da85c7c7..d3bdcf071913 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/contest/FarmingContest.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/contest/FarmingContest.kt @@ -2,4 +2,4 @@ package at.hannibal2.skyhanni.features.garden.contest import at.hannibal2.skyhanni.features.garden.CropType -data class FarmingContest(val time: Long, val crop: CropType, val brackets: Map) \ No newline at end of file +data class FarmingContest(val time: Long, val crop: CropType, val brackets: Map) diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/contest/FarmingContestPhase.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/contest/FarmingContestPhase.kt index 5d280a960eb3..e1667a20b4c0 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/contest/FarmingContestPhase.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/contest/FarmingContestPhase.kt @@ -4,4 +4,4 @@ enum class FarmingContestPhase { START, STOP, CHANGE -} \ No newline at end of file +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobContestTimeNeeded.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobContestTimeNeeded.kt index bb9f9ea21773..399c4cfadef2 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobContestTimeNeeded.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobContestTimeNeeded.kt @@ -168,16 +168,19 @@ object JacobContestTimeNeeded { showLine = line } } - map[crop] = Renderable.hoverTips(showLine, buildList { - add("§7Time Needed for §9${crop.cropName} Medals§7:") - addAll(brackets) - add("") - val latestFF = crop.getLatestTrueFarmingFortune() ?: 0.0 - add("§7Latest FF: §e${(latestFF).addSeparators()}") - val bps = crop.getBps()?.roundTo(1) ?: 0 - add("§7${addBpsTitle()}§e${bps.addSeparators()}") - addAll(lowBPSWarning) - }) + map[crop] = Renderable.hoverTips( + showLine, + buildList { + add("§7Time Needed for §9${crop.cropName} Medals§7:") + addAll(brackets) + add("") + val latestFF = crop.getLatestTrueFarmingFortune() ?: 0.0 + add("§7Latest FF: §e${(latestFF).addSeparators()}") + val bps = crop.getBps()?.roundTo(1) ?: 0 + add("§7${addBpsTitle()}§e${bps.addSeparators()}") + addAll(lowBPSWarning) + } + ) } private fun addBpsTitle() = if (config.jacobContestCustomBps) "Custom Blocks/Second: " else "Your Blocks/Second: " diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/ArmorDropTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/ArmorDropTracker.kt index 90c68a046980..8a21525c1646 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/ArmorDropTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/ArmorDropTracker.kt @@ -41,8 +41,9 @@ object ArmorDropTracker { private var hasArmor = false - private val tracker = SkyHanniTracker("Armor Drop Tracker", { Data() }, { it.garden.armorDropTracker }) - { drawDisplay(it) } + private val tracker = SkyHanniTracker("Armor Drop Tracker", { Data() }, { it.garden.armorDropTracker }) { + drawDisplay(it) + } class Data : TrackerData() { 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 217da97359ac..87306744e4a8 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 @@ -229,7 +229,7 @@ object CropMoneyDisplay { } val coinsColor = if (isCurrent && config.compact) "§e" else "§6" - val moneyArray = moneyPerHourData[internalName]!! + val moneyArray = moneyPerHourData[internalName] ?: emptyArray() 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 74c59674f580..9a47acaa1064 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 @@ -89,7 +89,7 @@ object CropSpeedMeter { snapshot = emptyList() } else { currentCrop?.let { - val crops = it.getCounter() - startCrops[it]!! + val crops = it.getCounter() - (startCrops[it] ?: 0L) val blocks = currentBlocks val cropsPerBlocks = (crops.toDouble() / blocks.toDouble()).roundTo(3) diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/DicerRngDropTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/DicerRngDropTracker.kt index 9e9e3620b618..af74da0d7fb5 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/DicerRngDropTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/DicerRngDropTracker.kt @@ -31,8 +31,9 @@ object DicerRngDropTracker { private val itemDrops = mutableListOf() private val config get() = GardenAPI.config.dicerCounters - private val tracker = SkyHanniTracker("Dicer RNG Drop Tracker", { Data() }, { it.garden.dicerDropTracker }) - { drawDisplay(it) } + private val tracker = SkyHanniTracker("Dicer RNG Drop Tracker", { Data() }, { it.garden.dicerDropTracker }) { + drawDisplay(it) + } class Data : TrackerData() { 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 da461d749604..3da9945b59d9 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 @@ -123,12 +123,6 @@ object FarmingWeightDisplay { private var nextPlayers = mutableListOf() private val nextPlayer get() = nextPlayers.firstOrNull() - private val recalculate by lazy { - ({ - resetData() - }) - } - private val eliteWeightApiGson by lazy { BaseGsonBuilder.gson() .registerTypeAdapter(CropType::class.java, SkyHanniTypeAdapters.CROP_TYPE.nullSafe()) @@ -141,22 +135,22 @@ object FarmingWeightDisplay { Renderable.clickAndHover( "§cFarming Weight error: Cannot load", listOf("§eClick here to reload the data right now!"), - onClick = recalculate, + onClick = ::resetData, ), Renderable.clickAndHover( "§cdata from Elite Farmers!", listOf("§eClick here to reload the data right now!"), - onClick = recalculate, + onClick = ::resetData, ), Renderable.clickAndHover( "§eRejoin the garden or", listOf("§eClick here to reload the data right now!"), - onClick = recalculate, + onClick = ::resetData, ), Renderable.clickAndHover( "§eclick here to fix it.", listOf("§eClick here to reload the data right now!"), - onClick = recalculate, + onClick = ::resetData, ), ) } @@ -268,7 +262,7 @@ object FarmingWeightDisplay { val nextPlayer = nextPlayer ?: return Renderable.clickAndHover( "§cWaiting for leaderboard update...", listOf("§eClick here to load new data right now!"), - onClick = recalculate, + onClick = ::resetData, ) val showRankGoal = leaderboardPosition == -1 || leaderboardPosition > rankGoal var nextName = @@ -304,7 +298,7 @@ object FarmingWeightDisplay { return Renderable.clickAndHover( "§cRejoin the garden to show ETA!", listOf("Click here to calculate the data right now!"), - onClick = recalculate, + onClick = ::resetData, ) } @@ -366,14 +360,18 @@ object FarmingWeightDisplay { ) } - private fun isEnabled() = ((OutsideSbFeature.FARMING_WEIGHT.isSelected() && !LorenzUtils.inSkyBlock) || - (LorenzUtils.inSkyBlock && (GardenAPI.inGarden() || config.showOutsideGarden))) && config.display + private fun isEnabled() = ( + config.display && ( + OutsideSbFeature.FARMING_WEIGHT.isSelected() && !LorenzUtils.inSkyBlock + ) || + (LorenzUtils.inSkyBlock && (GardenAPI.inGarden() || config.showOutsideGarden)) + ) private fun isEtaEnabled() = config.overtakeETA fun addCrop(crop: CropType, addedCounter: Int) { - //Prevent div-by-0 errors - if (addedCounter == 0) return; + // Prevent div-by-0 errors + if (addedCounter == 0) return val before = getExactWeight() localCounter[crop] = crop.getLocalCounter() + addedCounter 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 7189199a9987..aca1751b0082 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 @@ -156,14 +156,16 @@ object GardenCropMilestoneDisplay { val useCustomGoal = customTargetLevel != 0 && customTargetLevel > currentTier nextTier = if (useCustomGoal) customTargetLevel else nextTier - lineMap[MilestoneTextEntry.MILESTONE_TIER] = Renderable.horizontalContainer(buildList { - addCropIconRenderable(crop) - if (crop.isMaxed(overflowDisplay) && !overflowDisplay) { - addString("§7" + crop.cropName + " §eMAXED") - } else { - addString("§7" + crop.cropName + " §8$currentTier➜§3$nextTier") + lineMap[MilestoneTextEntry.MILESTONE_TIER] = Renderable.horizontalContainer( + buildList { + addCropIconRenderable(crop) + if (crop.isMaxed(overflowDisplay) && !overflowDisplay) { + addString("§7" + crop.cropName + " §eMAXED") + } else { + addString("§7" + crop.cropName + " §8$currentTier➜§3$nextTier") + } } - }) + ) val allowOverflowOrCustom = overflowDisplay || useCustomGoal val cropsForNextTier = GardenCropMilestones.getCropsForTier(nextTier, crop, allowOverflowOrCustom) @@ -302,10 +304,12 @@ object GardenCropMilestoneDisplay { val missing = need - have lineMap[MushroomTextEntry.TITLE] = Renderable.string("§6Mooshroom Cow Perk") - lineMap[MushroomTextEntry.MUSHROOM_TIER] = Renderable.horizontalContainer(buildList { - addCropIconRenderable(mushroom) - addString("§7Mushroom Milestone $nextTier") - }) + lineMap[MushroomTextEntry.MUSHROOM_TIER] = Renderable.horizontalContainer( + buildList { + addCropIconRenderable(mushroom) + addString("§7Mushroom Milestone $nextTier") + } + ) lineMap[MushroomTextEntry.NUMBER_OUT_OF_TOTAL] = Renderable.string("§e$haveFormat§8/§e$needFormat") diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropSpeed.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropSpeed.kt index 141c93ff102c..0ef02361f855 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropSpeed.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropSpeed.kt @@ -4,7 +4,6 @@ import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.data.ClickType import at.hannibal2.skyhanni.data.GardenCropMilestones.getCounter import at.hannibal2.skyhanni.data.GardenCropMilestones.setCounter -import at.hannibal2.skyhanni.data.Perk import at.hannibal2.skyhanni.data.jsonobjects.repo.DicerDropsJson import at.hannibal2.skyhanni.data.jsonobjects.repo.DicerType import at.hannibal2.skyhanni.events.CropClickEvent diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenStartLocation.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenStartLocation.kt index 8dc32fae6b4b..ba422d0f2eab 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenStartLocation.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenStartLocation.kt @@ -10,7 +10,6 @@ import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.LocationUtils import at.hannibal2.skyhanni.utils.LocationUtils.distanceSqToPlayer import at.hannibal2.skyhanni.utils.LorenzColor -import at.hannibal2.skyhanni.utils.LorenzVec import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText import at.hannibal2.skyhanni.utils.RenderUtils.drawWaypointFilled import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @@ -64,7 +63,7 @@ object GardenStartLocation { ChatUtils.chat("Auto updated your Crop Start Location for ${crop.cropName}") } - lastFarmedLocations[crop] = LorenzVec.getBlockBelowPlayer().add(0.0, 1.0, 0.0) + lastFarmedLocations[crop] = LocationUtils.playerLocation().roundLocationToBlock() shouldShowLastFarmedWaypoint = false } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingDirection.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingDirection.kt index 6ce5ebe06c11..06ff155b6cb0 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingDirection.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingDirection.kt @@ -3,5 +3,4 @@ package at.hannibal2.skyhanni.features.garden.farming.lane enum class FarmingDirection { NORTH_SOUTH, EAST_WEST, - ; } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLaneAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLaneAPI.kt index ba0eaee5dd4e..b9b091e53a27 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLaneAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLaneAPI.kt @@ -43,6 +43,7 @@ object FarmingLaneAPI { private fun warnNoLane(crop: CropType?) { if (crop == null || currentLane != null) return + if (crop in config.ignoredCrops) return if (!GardenAPI.hasFarmingToolInHand()) return if (FarmingLaneCreator.detection) return if (!config.distanceDisplay && !config.laneSwitchNotification.enabled) return diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLaneFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLaneFeatures.kt index e407d0ad4deb..ce4ce6a9f8c9 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLaneFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/lane/FarmingLaneFeatures.kt @@ -49,7 +49,6 @@ object FarmingLaneFeatures { TOO_SLOW("§cToo slow!"), CALCULATING("§aCalculating.."), NORMAL(""), - ; } @HandleEvent 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 959ab43e4b13..e8b2d55e4310 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 @@ -112,8 +112,8 @@ object CaptureFarmingGear { val currentCrop = itemStack.getCropType() if (currentCrop == null) { - //todo better fall back items - //todo Daedalus axe + // todo better fall back items + // todo Daedalus axe } else { currentCrop.farmingItem.setItem(itemStack) } 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 660c772ab47f..3771dd112db7 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 @@ -53,9 +53,13 @@ class FFGuideGUI : GuideGUI(FortuneGuidePage.OVERVI vTab(ItemStack(Items.gold_ingot), Renderable.string("§eBreakdown")) { currentPage = if (currentCrop == null) FortuneGuidePage.OVERVIEW else FortuneGuidePage.CROP }, - vTab(ItemStack(Items.map), Renderable.string("§eUpgrades")) { + vTab( + ItemStack(Items.map), + Renderable.string("§eUpgrades") + ) { currentPage = FortuneGuidePage.UPGRADES - }) + } + ) horizontalTabs = buildList { add( hTab(ItemStack(Blocks.grass), Renderable.string("§eOverview")) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneStats.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneStats.kt index b5558b638042..349144299804 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneStats.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FortuneStats.kt @@ -15,7 +15,8 @@ enum class FortuneStats( ), CROP_TOTAL( { crop -> "§6${crop.niceName.firstLetterUppercase()} Farming Fortune" }, - { "§7§2Farming fortune for this crop" }), + { "§7§2Farming fortune for this crop" } + ), ACCESSORY("§2Talisman Bonus", "§7§2Fortune from your talisman\n§2You get 10☘ per talisman tier"), CROP_UPGRADE("§2Crop Upgrade", "§7§2Fortune from Desk crop upgrades\n§2You get 5☘ per level"), BASE_TOOL("§2Base tool fortune", "§7§2Crop specific fortune from your tool"), @@ -23,7 +24,7 @@ enum class FortuneStats( GEMSTONE("§2Tool gemstone", "§7§2Fortune from gemstones on your tool"), FFD("§2Farming for Dummies", "§7§2Fortune for each applied book\n§2You get 1☘ per applied book"), COUNTER("§2Logarithmic Counter", "§7§2Fortune from increasing crop counter\n§2You get 16☘ per digit - 4"), - COLLECTION("§2Collection Analyst", "§7§2Fortune from increasing crop collection\n§2You get 8☘ per digit - 4"), + COLLECTION("§2Collection Analysis", "§7§2Fortune from increasing crop collection\n§2You get 8☘ per digit - 4"), HARVESTING("§2Harvesting Enchantment", "§7§2Fortune for each enchantment level\n§2You get 12.5☘ per level"), SUNDER("§2Sunder Enchantment", "§7§2Fortune for each enchantment level\n§2You get 12.5☘ per level"), CULTIVATING("§2Cultivating Enchantment", "§7§2Fortune for each enchantment level\n§2You get 2☘ per level"), 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 cd76262c06eb..aabee53c8b6c 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 @@ -90,7 +90,7 @@ object FortuneUpgrades { private fun getEquipmentUpgrades() { val visitors = GardenAPI.storage?.uniqueVisitors?.toDouble() ?: 0.0 for (piece in FarmingItems.equip) { - val item = piece.getItem() ?: return + val item = piece.getItem() // todo tell them to buy the missing item if (!item.getInternalName().contains("LOTUS")) return val enchantments = item.getEnchantments() ?: emptyMap() 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 c002284ab072..00e994f7d4f5 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 @@ -21,8 +21,9 @@ class OverviewPage(sizeX: Int, sizeY: Int, paddingX: Int = 15, paddingY: Int = 7 update(content, footer) } - //TODO split up this 240 lines function - fun getPage(): Pair>, List> { + // TODO split up this 240 lines function - remove suppression when done + @Suppress("CyclomaticComplexMethod", "LongMethod") + private fun getPage(): Pair>, List> { val content = mutableListOf>() val footer = mutableListOf() val timeUntilCakes = FFStats.cakeExpireTime.timeUntil().format(TimeUnit.HOUR, maxUnits = 1) diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/SkyMartCopperPrice.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/SkyMartCopperPrice.kt index 078ef16724d2..ea893ecd1b5b 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/SkyMartCopperPrice.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/SkyMartCopperPrice.kt @@ -16,8 +16,8 @@ import at.hannibal2.skyhanni.utils.NEUItems.getPrice import at.hannibal2.skyhanni.utils.NEUItems.getPriceOrNull import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.NumberUtil.formatInt -import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat import at.hannibal2.skyhanni.utils.NumberUtil.roundTo +import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables import at.hannibal2.skyhanni.utils.renderables.Renderable @@ -72,7 +72,7 @@ object SkyMartCopperPrice { add("§7Profit per purchase: §6${profit.shortFormat()} ") add("") add("§7Copper amount: §c${copper.addSeparators()} ") - add("§7Profit per copper: §6${perFormat} ") + add("§7Profit per copper: §6$perFormat ") } table.add( DisplayTableEntry( 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 af84bd7717b4..3ca75b1793b0 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,7 +29,9 @@ 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/PestFinder.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestFinder.kt index d8754fd81e70..690592d52184 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 @@ -157,8 +157,8 @@ object PestFinder { val isInaccurate = plot.isPestCountInaccurate val location = playerLocation.copy(x = middle.x, z = middle.z) event.drawWaypointFilled(location, LorenzColor.RED.toColor()) - val text = "§e" + (if (isInaccurate) "?" else - pests + val text = "§e" + ( + if (isInaccurate) "?" else pests ) + " §c$pestsName §7in §b$plotName" event.drawDynamicText( location, text, 1.5, 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 ff9af9cff523..bd8636b9ff86 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 @@ -1,7 +1,9 @@ package at.hannibal2.skyhanni.features.garden.pests import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.data.ClickType +import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.events.ItemClickEvent import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent import at.hannibal2.skyhanni.events.ReceiveParticleEvent @@ -33,7 +35,7 @@ object PestParticleLine { private var lastPestTrackerUse = SimpleTimeMark.farPast() private val locations = mutableListOf>() - @SubscribeEvent + @HandleEvent(onlyOnIsland = IslandType.GARDEN) fun onItemClick(event: ItemClickEvent) { if (!isEnabled()) return if (PestAPI.hasVacuumInHand()) { 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 d07e55816732..33c9dbea2f57 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 @@ -17,10 +17,9 @@ import at.hannibal2.skyhanni.utils.CollectionUtils.editCopy import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayerIgnoreY import at.hannibal2.skyhanni.utils.LocationUtils.playerLocation import at.hannibal2.skyhanni.utils.LorenzVec -import at.hannibal2.skyhanni.utils.RenderUtils.draw3DLine 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.exactPlayerEyeLocation import at.hannibal2.skyhanni.utils.SimpleTimeMark import net.minecraft.client.Minecraft import net.minecraft.network.play.server.S0EPacketSpawnObject @@ -49,7 +48,7 @@ object PestParticleWaypoint { private var isPointingToPest = false private var color: Color? = null - @SubscribeEvent + @HandleEvent(onlyOnIsland = IslandType.GARDEN) fun onItemClick(event: ItemClickEvent) { if (!isEnabled()) return if (PestAPI.hasVacuumInHand()) { @@ -145,12 +144,7 @@ object PestParticleWaypoint { event.drawWaypointFilled(waypoint, color, beacon = true) event.drawDynamicText(waypoint, text, 1.3) - if (config.drawLine) event.draw3DLine( - event.exactPlayerEyeLocation(), - waypoint, - color, - 3, - false, + if (config.drawLine) event.drawLineToEye(waypoint, color, 3, false, ) } 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 c1b6a3d8fe6a..8cafd5260a1a 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 @@ -56,7 +56,7 @@ object GardenVisitorCompactChat { ) private var visitorAcceptedChat = mutableListOf() - private var visitorNameFormatted = ""; + private var visitorNameFormatted = "" private var rewardsList = mutableListOf() @SubscribeEvent @@ -82,10 +82,10 @@ object GardenVisitorCompactChat { visitorNameFormatted = "$visitorColor$visitorName" } - //If visitor name has not yet been matched, we aren't looking at a visitor accept message, and can ignore this. - if (visitorNameFormatted.isBlank()) return; + // If visitor name has not yet been matched, we aren't looking at a visitor accept message, and can ignore this. + if (visitorNameFormatted.isBlank()) return - //Match rewards and transform + // Match rewards and transform visitorRewardPattern.matchMatcher(transformedMessage) { val rewardColor = groupOrNull("rewardcolor") val amountColor = groupOrNull("amountcolor") @@ -105,7 +105,7 @@ object GardenVisitorCompactChat { if (altAmount == null) "" else "$altAmount " } - //Don't add name for copper, farming XP, garden XP, or bits + // Don't add name for copper, farming XP, garden XP, or bits val rewardString = if (discardRewardNamePattern.matcher(reward).matches()) "" else reward rewardsList.add( @@ -127,8 +127,8 @@ object GardenVisitorCompactChat { } private fun sendCompact() { - //This prevents commission rewards, crop milestone data, etc. from triggering incorrectly - if (visitorNameFormatted.isBlank()) return; + // This prevents commission rewards, crop milestone data, etc. from triggering incorrectly + if (visitorNameFormatted.isBlank()) return if (visitorAcceptedChat.isNotEmpty()) { ChatUtils.hoverableChat(createCompactVisitorMessage(), hover = visitorAcceptedChat, prefix = false) diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorDropStatistics.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorDropStatistics.kt index 6b3620c184c4..2ad6f56b1c05 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorDropStatistics.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorDropStatistics.kt @@ -196,7 +196,7 @@ object GardenVisitorDropStatistics { for (reward in VisitorReward.entries) { val count = rewardsCount[reward] ?: 0 - if (config.displayIcons) {// Icons + if (config.displayIcons) { // Icons val stack = reward.itemStack if (config.displayNumbersFirst) add(listOf("§b${count.addSeparators()} ", stack)) @@ -228,7 +228,7 @@ object GardenVisitorDropStatistics { return "$amount" } - //todo this should just save when changed not once a second + // todo this should just save when changed not once a second @SubscribeEvent fun onSecondPassed(event: SecondPassedEvent) { saveAndUpdate() 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 70392bb46d78..1d5907d85284 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 @@ -361,12 +361,12 @@ object GardenVisitorFeatures { val visitor = event.visitor val text = visitor.status.displayName val location = event.location - event.parent.drawString(location.add(y = 2.23), text) + event.parent.drawString(location.up(2.23), text) if (config.rewardWarning.showOverName) { visitor.hasReward()?.let { reward -> val name = reward.displayName - event.parent.drawString(location.add(y = 2.73), "§c!$name§c!") + event.parent.drawString(location.up(2.73), "§c!$name§c!") } } } @@ -682,7 +682,7 @@ object GardenVisitorFeatures { add("shoppingList: '${visitor.shoppingList}'") } visitor.offer?.offerItem?.getInternalName()?.let { - add("offer: '${it}'") + add("offer: '$it'") } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorTimer.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorTimer.kt index 3a69f2ece3b8..af31448d66e4 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorTimer.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorTimer.kt @@ -11,15 +11,17 @@ import at.hannibal2.skyhanni.features.garden.GardenAPI import at.hannibal2.skyhanni.features.garden.farming.GardenCropSpeed import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.test.command.ErrorManager +import at.hannibal2.skyhanni.utils.HypixelCommands import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.RegexUtils.matchFirst -import at.hannibal2.skyhanni.utils.RenderUtils.renderString +import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderable import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.SoundUtils import at.hannibal2.skyhanni.utils.StringUtils.removeColor import at.hannibal2.skyhanni.utils.TabListData import at.hannibal2.skyhanni.utils.TimeUtils import at.hannibal2.skyhanni.utils.TimeUtils.format +import at.hannibal2.skyhanni.utils.renderables.Renderable import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import kotlin.time.Duration @@ -36,10 +38,10 @@ object GardenVisitorTimer { private val timePattern by RepoPattern.pattern( "garden.visitor.timer.time.new", - " Next Visitor: §r(?.*)" + " Next Visitor: §r(?.*)", ) - private var display = "" + private var display: Renderable? = null private var lastMillis = 0.seconds private var sixthVisitorArrivalTime = SimpleTimeMark.farPast() private var visitorJustArrived = false @@ -65,7 +67,7 @@ object GardenVisitorTimer { @SubscribeEvent fun onProfileJoin(event: ProfileJoinEvent) { - display = "" + display = null lastMillis = 0.seconds sixthVisitorArrivalTime = SimpleTimeMark.farPast() visitorJustArrived = false @@ -84,7 +86,7 @@ object GardenVisitorTimer { TabListData.getTabList().matchFirst(timePattern) { val timeInfo = group("info").removeColor() if (timeInfo == "Not Unlocked!") { - display = "§cVisitors not unlocked!" + display = Renderable.string("§cVisitors not unlocked!") return } if (timeInfo == "Queue Full!") { @@ -97,7 +99,7 @@ object GardenVisitorTimer { millis = TimeUtils.getDuration(timeInfo) } } ?: run { - display = "§cVisitor time info not in tab list" + display = createDisplayText("§cVisitor time info not in tab list") return } @@ -140,7 +142,7 @@ object GardenVisitorTimer { if (lastMillis == Duration.INFINITE) { ErrorManager.logErrorStateWithData( "Found Visitor Timer bug, reset value", "lastMillis was infinite", - "lastMillis" to lastMillis + "lastMillis" to lastMillis, ) lastMillis = 0.seconds } @@ -168,14 +170,20 @@ object GardenVisitorTimer { "Next in §$formatColor$formatDuration$extraSpeed" } val visitorLabel = if (visitorsAmount == 1) "visitor" else "visitors" - display = "§b$visitorsAmount $visitorLabel §7($next§7)" + display = createDisplayText("§b$visitorsAmount $visitorLabel §7($next§7)") } + private fun createDisplayText(text: String) = Renderable.clickAndHover( + text, + listOf("§eClick to teleport to the barn!"), + onClick = { HypixelCommands.teleportToPlot("barn") }, + ) + @SubscribeEvent fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) { if (!isEnabled()) return - config.pos.renderString(display, posLabel = "Garden Visitor Timer") + config.pos.renderRenderable(display, posLabel = "Garden Visitor Timer") } @SubscribeEvent diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/HighlightVisitorsOutsideOfGarden.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/HighlightVisitorsOutsideOfGarden.kt index 8a8c11165564..a3536c1969fd 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/HighlightVisitorsOutsideOfGarden.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/HighlightVisitorsOutsideOfGarden.kt @@ -62,8 +62,8 @@ object HighlightVisitorsOutsideOfGarden { val possibleJsons = visitorJson[mode] ?: return false val skinOrType = getSkinOrTypeFor(entity) return possibleJsons.any { - (it.position == null || it.position.distance(entity.position.toLorenzVec()) < 1) - && it.skinOrType == skinOrType + (it.position == null || it.position.distance(entity.position.toLorenzVec()) < 1) && + it.skinOrType == skinOrType } } @@ -100,7 +100,8 @@ object HighlightVisitorsOutsideOfGarden { if (isVisitor(entity) || (entity is EntityArmorStand && isVisitorNearby(entity.getLorenzVec()))) { event.cancel() if (packet.action == C02PacketUseEntity.Action.INTERACT) { - ChatUtils.chatAndOpenConfig("Blocked you from interacting with a visitor. Sneak to bypass or click here to change settings.", + ChatUtils.chatAndOpenConfig( + "Blocked you from interacting with a visitor. Sneak to bypass or click here to change settings.", GardenAPI.config.visitors::blockInteracting ) } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/VisitorAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/VisitorAPI.kt index d621aa081b37..1565d87d3eba 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/VisitorAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/VisitorAPI.kt @@ -201,7 +201,7 @@ object VisitorAPI { val pricePerCopper = pricePerCopper ?: error("pricePerCopper is null") val totalPrice = totalPrice ?: error("totalPrice is null") val totalReward = totalReward ?: error("totalReward is null") - val loss = totalPrice - totalReward; + val loss = totalPrice - totalReward return when { preventRefusing && hasReward() != null -> VisitorBlockReason.RARE_REWARD preventRefusingNew && offersAccepted == 0 -> VisitorBlockReason.NEVER_ACCEPTED diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/BeaconPower.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/BeaconPower.kt index 76990b37ad98..8c68dc2c100b 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/BeaconPower.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/BeaconPower.kt @@ -58,8 +58,8 @@ object BeaconPower { private var display = "" - private val BEACON_POWER_SLOT = 22 - private val STATS_SLOT = 23 + private const val BEACON_POWER_SLOT = 22 + private const val STATS_SLOT = 23 @SubscribeEvent fun onInventoryUpdate(event: InventoryUpdatedEvent) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/MovableHotBar.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/MovableHotBar.kt index cf49749b27e9..bee90a69694b 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/MovableHotBar.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/MovableHotBar.kt @@ -39,6 +39,6 @@ object MovableHotBar { } fun isEnabled(): Boolean = - (LorenzUtils.inSkyBlock || (Minecraft.getMinecraft().thePlayer != null && config.showOutsideSkyblock)) - && config.editable + (LorenzUtils.inSkyBlock || (Minecraft.getMinecraft().thePlayer != null && config.showOutsideSkyblock)) && + config.editable } 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 a3da970c660f..4a86519c374e 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 @@ -30,6 +30,7 @@ import at.hannibal2.skyhanni.utils.RenderUtils.HorizontalAlignment import at.hannibal2.skyhanni.utils.RenderUtils.VerticalAlignment import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderable import at.hannibal2.skyhanni.utils.SimpleTimeMark +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 @@ -48,14 +49,9 @@ object CustomScoreboard { private var display = emptyList() private var cache = emptyList() - private val guiName = "Custom Scoreboard" + private const val GUI_NAME = "Custom Scoreboard" - // Cached scoreboard data, only update after no change for 300ms - var activeLines = emptyList() - - // Most recent scoreboard state, not in use until cached - private var mostRecentLines = emptyList() - private var lastScoreboardUpdate = SimpleTimeMark.farFuture() + private var nextScoreboardUpdate = SimpleTimeMark.farFuture() @SubscribeEvent fun onRenderOverlay(event: GuiRenderEvent.GuiOverlayRenderEvent) { @@ -80,16 +76,14 @@ object CustomScoreboard { RenderBackground.updatePosition(finalRenderable) - config.position.renderRenderable(finalRenderable, posLabel = guiName) + config.position.renderRenderable(finalRenderable, posLabel = GUI_NAME) } @SubscribeEvent fun onGuiPositionMoved(event: GuiPositionMovedEvent) { - if (event.guiName == guiName) { + if (event.guiName == GUI_NAME) { with(alignmentConfig) { - if (horizontalAlignment != HorizontalAlignment.DONT_ALIGN || - verticalAlignment != VerticalAlignment.DONT_ALIGN - ) { + if (horizontalAlignment != HorizontalAlignment.DONT_ALIGN || verticalAlignment != VerticalAlignment.DONT_ALIGN) { val tempHori = horizontalAlignment val tempVert = verticalAlignment @@ -113,16 +107,9 @@ object CustomScoreboard { fun onTick(event: LorenzTickEvent) { if (!isEnabled()) return - // We want to update the scoreboard as soon as we have new data, not 5 ticks delayed - var dirty = false - if (lastScoreboardUpdate.passedSince() > 300.milliseconds) { - activeLines = mostRecentLines - lastScoreboardUpdate = SimpleTimeMark.farFuture() - dirty = true - } - - // Creating the lines - if (event.isMod(5) || dirty) { + if (dirty || nextScoreboardUpdate.isInPast()) { + nextScoreboardUpdate = 250.milliseconds.fromNow() + dirty = false display = createLines().removeEmptyLinesFromEdges() if (TabListData.fullyLoaded) { cache = display.toList() @@ -135,11 +122,9 @@ object CustomScoreboard { @SubscribeEvent fun onScoreboardChange(event: ScoreboardUpdateEvent) { - mostRecentLines = event.scoreboard - lastScoreboardUpdate = SimpleTimeMark.now() + dirty = true } - internal val config get() = SkyHanniMod.feature.gui.customScoreboard internal val displayConfig get() = config.display internal val alignmentConfig get() = displayConfig.alignment @@ -160,12 +145,12 @@ object CustomScoreboard { private fun addAllNonSkyBlockLines() = buildList { addAll(ScoreboardElement.TITLE.getVisiblePair()) - addAll(activeLines.map { it to HorizontalAlignment.LEFT }) + addAll(ScoreboardData.sidebarLinesFormatted.map { it to HorizontalAlignment.LEFT }) } private fun addDefaultSkyBlockLines() = buildList { add(ScoreboardData.objectiveTitle to displayConfig.titleAndFooter.alignTitleAndFooter) - addAll(activeLines.map { it to HorizontalAlignment.LEFT }) + addAll(ScoreboardData.sidebarLinesFormatted.map { it to HorizontalAlignment.LEFT }) } private fun addCustomSkyBlockLines() = buildList { @@ -175,7 +160,8 @@ object CustomScoreboard { if ( informationFilteringConfig.hideConsecutiveEmptyLines && - lines.first().first == "" && lastOrNull()?.first?.isEmpty() == true + lines.first().first == "" && + lastOrNull()?.first?.isEmpty() == true ) { continue } 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 4cfc403c421f..99fdc4f3fcf6 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,6 +3,7 @@ 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.ScoreboardData import at.hannibal2.skyhanni.features.bingo.BingoAPI import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboard.displayConfig import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators @@ -27,7 +28,7 @@ object CustomScoreboardUtils { fun getProfileTypeSymbol() = when { HypixelData.ironman -> "§7♲ " HypixelData.stranded -> "§a☀ " - HypixelData.bingo -> CustomScoreboard.activeLines.firstNotNullOfOrNull { + HypixelData.bingo -> ScoreboardData.sidebarLinesFormatted.firstNotNullOfOrNull { BingoAPI.getIconFromScoreboard(it)?.plus(" ") } ?: "§e❤ " @@ -43,7 +44,7 @@ object CustomScoreboardUtils { internal fun String.formatNum() = this.formatDouble().formatNum() - internal fun getMotes() = getGroupFromPattern(CustomScoreboard.activeLines, ScoreboardPattern.motesPattern, "motes") + internal fun getMotes() = getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.motesPattern, "motes") internal fun getBank() = getGroupFromPattern(TabListData.getTabList(), ScoreboardPattern.bankPattern, "bank") internal fun getBits() = BitsAPI.bits.coerceAtLeast(0).formatNum() @@ -57,15 +58,15 @@ object CustomScoreboardUtils { } internal fun getCopper() = - getGroupFromPattern(CustomScoreboard.activeLines, ScoreboardPattern.copperPattern, "copper") + getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.copperPattern, "copper") internal fun getGems() = getGroupFromPattern(TabListData.getTabList(), ScoreboardPattern.gemsPattern, "gems") internal fun getHeat() = - getGroupFromPattern(CustomScoreboard.activeLines, ScoreboardPattern.heatPattern, "heat") + getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.heatPattern, "heat") internal fun getNorthStars() = - getGroupFromPattern(CustomScoreboard.activeLines, ScoreboardPattern.northstarsPattern, "northstars") + getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.northstarsPattern, "northstars") class UndetectedScoreboardLines(message: String) : Exception(message) 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 index 7636d43ebabf..f20479b65e44 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardElements.kt @@ -39,8 +39,6 @@ import at.hannibal2.skyhanni.features.gui.customscoreboard.CustomScoreboardUtils 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.test.command.ErrorManager -import at.hannibal2.skyhanni.utils.CollectionUtils.editCopy import at.hannibal2.skyhanni.utils.CollectionUtils.nextAfter import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.inAdvancedMiningIsland @@ -50,41 +48,25 @@ 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.TimeLimitedSet import at.hannibal2.skyhanni.utils.TimeUtils.format import at.hannibal2.skyhanni.utils.TimeUtils.formatted import kotlin.time.Duration.Companion.seconds -internal var confirmedUnknownLines = listOf() -internal var unconfirmedUnknownLines = listOf() -internal var unknownLinesSet = TimeLimitedSet(1.seconds) { onRemoval(it) } - -private fun onRemoval(line: String) { - if (!LorenzUtils.inSkyBlock) return - if (!unconfirmedUnknownLines.contains(line)) return - if (line !in unconfirmedUnknownLines) return - unconfirmedUnknownLines = unconfirmedUnknownLines.filterNot { it == line } - confirmedUnknownLines = confirmedUnknownLines.editCopy { add(line) } - if (!config.unknownLinesWarning) return - val pluralize = pluralize(confirmedUnknownLines.size, "unknown line", withNumber = true) - val message = "CustomScoreboard detected $pluralize" - ErrorManager.logErrorWithData( - CustomScoreboardUtils.UndetectedScoreboardLines(message), - message, - "Unknown Lines" to confirmedUnknownLines, - "Island" to LorenzUtils.skyBlockIsland, - "Area" to HypixelData.skyBlockArea, - "Full Scoreboard" to CustomScoreboard.activeLines, - noStackTrace = true, - betaOnly = true, - ) -} +internal var allUnknownLines = listOf() +internal var lastRecentAlarmWarning = SimpleTimeMark.farPast() -internal var amountOfUnknownLines = 0 +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, @@ -370,10 +352,11 @@ private fun getTitleDisplayPair(): List { } return if (displayConfig.titleAndFooter.useCustomTitle) { - listOf(displayConfig.titleAndFooter.customTitle.get().toString() - .replace("&", "§") - .split("\\n") - .map { it to alignment } + listOf( + displayConfig.titleAndFooter.customTitle.get().toString() + .replace("&", "§") + .split("\\n") + .map { it to alignment } ).flatten() } else { listOf(ScoreboardData.objectiveTitle to alignment) @@ -389,7 +372,7 @@ private fun getPurseDisplayPair(): List { var purse = PurseAPI.currentPurse.formatNum() if (!displayConfig.hideCoinsDifference) { - val earned = getGroupFromPattern(CustomScoreboard.activeLines, PurseAPI.coinsPattern, "earned") + val earned = getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, PurseAPI.coinsPattern, "earned") if (earned != null) purse += " §7(§e+$earned§7)§6" } @@ -491,8 +474,8 @@ private fun getHeatDisplayPair(): List { ) } -private fun getHeatShowWhen() = inAnyIsland(IslandType.CRYSTAL_HOLLOWS) - && CustomScoreboard.activeLines.any { ScoreboardPattern.heatPattern.matches(it) } +private fun getHeatShowWhen() = inAnyIsland(IslandType.CRYSTAL_HOLLOWS) && + ScoreboardData.sidebarLinesFormatted.any { ScoreboardPattern.heatPattern.matches(it) } private fun getColdDisplayPair(): List { val cold = -MiningAPI.cold @@ -507,7 +490,7 @@ private fun getColdDisplayPair(): List { } private fun getColdShowWhen() = inAnyIsland(IslandType.DWARVEN_MINES, IslandType.MINESHAFT) && - CustomScoreboard.activeLines.any { ScoreboardPattern.coldPattern.matches(it) } + ScoreboardData.sidebarLinesFormatted.any { ScoreboardPattern.coldPattern.matches(it) } private fun getNorthStarsDisplayPair(): List { val northStars = getNorthStars()?.formatNum() ?: "0" @@ -550,7 +533,7 @@ private fun getIslandDisplayPair() = private fun getLocationDisplayPair() = buildList { HypixelData.skyBlockAreaWithSymbol?.let { add(it to HorizontalAlignment.LEFT) } - CustomScoreboard.activeLines.firstOrNull { ScoreboardPattern.plotPattern.matches(it) } + ScoreboardData.sidebarLinesFormatted.firstOrNull { ScoreboardPattern.plotPattern.matches(it) } ?.let { add(it to HorizontalAlignment.LEFT) } } @@ -568,12 +551,12 @@ fun getPlayerAmountDisplayPair() = buildList { private fun getVisitDisplayPair() = listOf( - CustomScoreboard.activeLines.first { ScoreboardPattern.visitingPattern.matches(it) } to + ScoreboardData.sidebarLinesFormatted.first { ScoreboardPattern.visitingPattern.matches(it) } to HorizontalAlignment.LEFT, ) private fun getVisitShowWhen() = - CustomScoreboard.activeLines.any { ScoreboardPattern.visitingPattern.matches(it) } + ScoreboardData.sidebarLinesFormatted.any { ScoreboardPattern.visitingPattern.matches(it) } private fun getDateDisplayPair() = listOf( @@ -582,7 +565,7 @@ private fun getDateDisplayPair() = private fun getTimeDisplayPair(): List { val symbol = - getGroupFromPattern(CustomScoreboard.activeLines, ScoreboardPattern.timePattern, "symbol") ?: "" + getGroupFromPattern(ScoreboardData.sidebarLinesFormatted, ScoreboardPattern.timePattern, "symbol") ?: "" return listOf( "§7" + SkyBlockTime.now() .formatted( @@ -603,15 +586,16 @@ private fun getLobbyDisplayPair(): List { } 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, + ( + 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> { @@ -659,10 +643,11 @@ private fun getTuningDisplayPair(): List> { 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, + "§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 { @@ -671,7 +656,7 @@ private fun getCookieShowWhen(): Boolean { } private fun getObjectiveDisplayPair() = buildList { - val formattedLines = CustomScoreboard.activeLines + val formattedLines = ScoreboardData.sidebarLinesFormatted val objective = formattedLines.firstOrNull { ScoreboardPattern.objectivePattern.matches(it) } if (objective != null) { add(objective to HorizontalAlignment.LEFT) @@ -690,7 +675,7 @@ private fun getObjectiveDisplayPair() = buildList { } private fun getObjectiveShowWhen(): Boolean = - ScoreboardPattern.objectivePattern.anyMatches(CustomScoreboard.activeLines) + ScoreboardPattern.objectivePattern.anyMatches(ScoreboardData.sidebarLinesFormatted) private fun getSlayerDisplayPair(): List = buildList { add((if (SlayerAPI.hasActiveSlayerQuest()) "Slayer Quest" else "") to HorizontalAlignment.LEFT) @@ -802,6 +787,11 @@ private fun getMayorDisplayPair() = buildList { } 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) @@ -810,7 +800,9 @@ private fun getMayorDisplayPair() = buildList { add(" §7- §e${perk.perkName}" to HorizontalAlignment.LEFT) } } +} +private fun addPerkpocalypseMayor() = buildList { val jerryExtraMayor = MayorAPI.jerryExtraMayor val extraMayor = jerryExtraMayor.first ?: return@buildList @@ -860,15 +852,12 @@ private fun getFooterDisplayPair(): List = listOf( ).flatten() private fun getExtraDisplayPair(): List { - if (unconfirmedUnknownLines.isEmpty()) return listOf("" to HorizontalAlignment.LEFT) - amountOfUnknownLines = unconfirmedUnknownLines.size - - return listOf("§cUndetected Lines:" to HorizontalAlignment.LEFT) + unconfirmedUnknownLines.map { it to HorizontalAlignment.LEFT } -} + val lines = recentUnknownLines() + if (lines.isEmpty()) return listOf("" to HorizontalAlignment.LEFT) -private fun getExtraShowWhen(): Boolean { - if (unconfirmedUnknownLines.isEmpty()) { - amountOfUnknownLines = 0 + return listOf("§cUndetected Lines:" to HorizontalAlignment.LEFT) + lines.map { + it.line to HorizontalAlignment.LEFT } - return unconfirmedUnknownLines.isNotEmpty() } + +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 index 9f3c009e57f6..8dd3af9f7aec 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/ScoreboardEvent.kt @@ -2,17 +2,19 @@ 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.gui.customscoreboard.ScoreboardPattern 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 @@ -28,7 +30,7 @@ import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardPattern as * because they are visible for a maximum of like 1 minute every 5 days and ~12 hours. */ -private fun getSbLines(): List = CustomScoreboard.activeLines +private fun getSbLines(): List = ScoreboardData.sidebarLinesFormatted enum class ScoreboardEvent( private val displayLine: () -> List, @@ -345,7 +347,7 @@ private fun getTrapperLines() = buildList { } private fun getTrapperShowWhen(): Boolean = - getSbLines().any { ScoreboardPattern.peltsPattern.matches(it) || ScoreboardPattern.mobLocationPattern.matches(it) } + getSbLines().any { SbPattern.peltsPattern.matches(it) || SbPattern.mobLocationPattern.matches(it) } private fun getGardenCleanUpLines(): List = listOf(getSbLines().first { SbPattern.cleanUpPattern.matches(it) }.trim()) @@ -372,9 +374,9 @@ private fun getWinterLines() = buildList { } private fun getWinterShowWhen(): Boolean = getSbLines().any { - ScoreboardPattern.winterEventStartPattern.matches(it) - || (ScoreboardPattern.winterNextWavePattern.matches(it) && !it.endsWith("Soon!")) - || ScoreboardPattern.winterWavePattern.matches(it) + 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) }) @@ -393,7 +395,7 @@ private fun getSpookyLines() = buildList { ) // Candy } -private fun getSpookyShowWhen(): Boolean = getSbLines().any { ScoreboardPattern.spookyPattern.matches(it) } +private fun getSpookyShowWhen(): Boolean = getSbLines().any { SbPattern.spookyPattern.matches(it) } private fun getTablistEvent(): String? = TabListData.getTabList().firstOrNull { SbPattern.eventNamePattern.matches(it) } @@ -411,12 +413,9 @@ private fun getActiveEventLine(): List { val blockedEvents = listOf("Spooky Festival", "Carnival", "5th SkyBlock Anniversary", "New Year Celebration") if (blockedEvents.contains(currentActiveEvent.removeColor())) return emptyList() - val currentActiveEventTime = TabListData.getTabList().firstOrNull { SbPattern.eventTimeEndsPattern.matches(it) } - ?.let { - SbPattern.eventTimeEndsPattern.matchMatcher(it) { - group("time") - } - } + val currentActiveEventTime = SbPattern.eventTimeEndsPattern.firstMatcher(TabWidget.EVENT.lines) { + group("time") + } ?: return emptyList() return listOf(currentActiveEvent, " Ends in: §e$currentActiveEventTime") } @@ -426,12 +425,9 @@ private fun getActiveEventShowWhen(): Boolean = private fun getSoonEventLine(): List { val soonActiveEvent = getTablistEvent() ?: return emptyList() - val soonActiveEventTime = TabListData.getTabList().firstOrNull { SbPattern.eventTimeStartsPattern.matches(it) } - ?.let { - SbPattern.eventTimeStartsPattern.matchMatcher(it) { - group("time") - } - } + val soonActiveEventTime = SbPattern.eventTimeStartsPattern.firstMatcher(TabWidget.EVENT.lines) { + group("time") + } ?: return emptyList() return listOf(soonActiveEvent, " Starts in: §e$soonActiveEventTime") } @@ -444,8 +440,9 @@ private fun getBroodmotherLines(): List = private fun getMiningEventsLines() = buildList { // Wind - if (getSbLines().any { SbPattern.windCompassPattern.matches(it) } - && getSbLines().any { SbPattern.windCompassArrowPattern.matches(it) }) { + 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|") } @@ -457,15 +454,17 @@ private fun getMiningEventsLines() = buildList { } // Zone Events - if (getSbLines().any { SbPattern.miningEventPattern.matches(it) } - && getSbLines().any { SbPattern.miningEventZonePattern.matches(it) }) { + 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) }) { + if (getSbLines().any { SbPattern.miningEventPattern.matches(it) } && + getSbLines().none { SbPattern.miningEventZonePattern.matches(it) } + ) { add( getSbLines().first { SbPattern.miningEventPattern.matches(it) } .removePrefix("Event: "), @@ -473,22 +472,25 @@ private fun getMiningEventsLines() = buildList { } // Mithril Gourmand - if (getSbLines().any { SbPattern.mithrilRemainingPattern.matches(it) } - && getSbLines().any { SbPattern.mithrilYourMithrilPattern.matches(it) }) { + 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) }) { + 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) }) { + 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) }) } @@ -509,17 +511,17 @@ private fun getDamageLines(): List = (getSbLines().first { SbPattern.bossDamagePattern.matches(it) }) private fun getDamageShowWhen(): Boolean = - getSbLines().any { SbPattern.bossHPPattern.matches(it) } - && getSbLines().any { SbPattern.bossDamagePattern.matches(it) } + 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) + 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) @@ -539,18 +541,19 @@ private fun getCarnivalLines() = listOf( getSbLines().firstOrNull { pattern.matches(it) } } -private fun getCarnivalShowWhen(): Boolean = SbPattern.carnivalPattern.anyMatches(getSbLines()) +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) + 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) }) 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 fb014cc29243..f7371d9566c5 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 @@ -428,10 +428,12 @@ object ScoreboardPattern { // this thirdObjectiveLinePattern includes all those weird objective lines that go into a third (and fourth) scoreboard line /** * REGEX-TEST: §eProtect Elle §7(§a98%§7) + * REGEX-TEST: §fFish 1 Flyfish §c✖ + * REGEX-TEST: §fFish 1 Skeleton Fish §c✖ */ val thirdObjectiveLinePattern by miscSb.pattern( "thirdobjectiveline", - "(\\s*§.\\(§.\\w+§./§.\\w+§.\\)|§f Mages.*|§f Barbarians.*|§edefeat Kuudra|§eand stun him)", + "(\\s*§.\\(§.\\w+§.\\/§.\\w+§.\\)|§f Mages.*|§f Barbarians.*|§edefeat Kuudra|§eand stun him|§.Fish \\d .*[fF]ish §.[✖✔])", ) // collection of lines that just randomly exist and I have no clue how on earth to effectively remove them diff --git a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/UnknownLinesHandler.kt b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/UnknownLinesHandler.kt index fa693f648dbc..0dff1f4933dd 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/UnknownLinesHandler.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/gui/customscoreboard/UnknownLinesHandler.kt @@ -1,143 +1,152 @@ package at.hannibal2.skyhanni.features.gui.customscoreboard 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.features.misc.ServerRestartTitle import at.hannibal2.skyhanni.features.rift.area.stillgorechateau.RiftBloodEffigies +import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.CollectionUtils.editCopy import at.hannibal2.skyhanni.utils.CollectionUtils.nextAfter import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.StringUtils.removeResets import java.util.regex.Pattern +import kotlin.time.Duration.Companion.minutes +import kotlin.time.Duration.Companion.seconds import at.hannibal2.skyhanni.features.gui.customscoreboard.ScoreboardPattern as SbPattern object UnknownLinesHandler { internal lateinit var remoteOnlyPatterns: Array + /** + * Remove known lines with patterns + **/ + private val patternsToExclude = mutableListOf( + PurseAPI.coinsPattern, + SbPattern.motesPattern, + BitsAPI.bitsScoreboardPattern, + SbPattern.heatPattern, + SbPattern.copperPattern, + SbPattern.locationPattern, + SbPattern.lobbyCodePattern, + SbPattern.datePattern, + SbPattern.timePattern, + SbPattern.footerPattern, + SbPattern.yearVotesPattern, + SbPattern.votesPattern, + SbPattern.waitingForVotePattern, + SbPattern.northstarsPattern, + SbPattern.profileTypePattern, + SbPattern.autoClosingPattern, + SbPattern.startingInPattern, + SbPattern.timeElapsedPattern, + SbPattern.instanceShutdownPattern, + SbPattern.keysPattern, + SbPattern.clearedPattern, + SbPattern.soloPattern, + SbPattern.teammatesPattern, + SbPattern.floor3GuardiansPattern, + SbPattern.m7dragonsPattern, + SbPattern.wavePattern, + SbPattern.tokensPattern, + SbPattern.submergesPattern, + SbPattern.medalsPattern, + SbPattern.lockedPattern, + SbPattern.cleanUpPattern, + SbPattern.pastingPattern, + SbPattern.peltsPattern, + SbPattern.mobLocationPattern, + SbPattern.jacobsContestPattern, + SbPattern.plotPattern, + SbPattern.powderGreedyPattern, + SbPattern.windCompassPattern, + SbPattern.windCompassArrowPattern, + SbPattern.miningEventPattern, + SbPattern.miningEventZonePattern, + SbPattern.raffleUselessPattern, + SbPattern.raffleTicketsPattern, + SbPattern.rafflePoolPattern, + SbPattern.mithrilUselessPattern, + SbPattern.mithrilRemainingPattern, + SbPattern.mithrilYourMithrilPattern, + SbPattern.nearbyPlayersPattern, + SbPattern.uselessGoblinPattern, + SbPattern.remainingGoblinPattern, + SbPattern.yourGoblinKillsPattern, + SbPattern.magmaBossPattern, + SbPattern.damageSoakedPattern, + SbPattern.killMagmasPattern, + SbPattern.killMagmasDamagedSoakedBarPattern, + SbPattern.reformingPattern, + SbPattern.bossHealthPattern, + SbPattern.bossHealthBarPattern, + SbPattern.broodmotherPattern, + SbPattern.bossHPPattern, + SbPattern.bossDamagePattern, + SbPattern.slayerQuestPattern, + SbPattern.essencePattern, + SbPattern.redstonePattern, + SbPattern.anniversaryPattern, + SbPattern.visitingPattern, + SbPattern.flightDurationPattern, + SbPattern.dojoChallengePattern, + SbPattern.dojoDifficultyPattern, + SbPattern.dojoPointsPattern, + SbPattern.dojoTimePattern, + SbPattern.objectivePattern, + ServerRestartTitle.restartingGreedyPattern, + SbPattern.travelingZooPattern, + SbPattern.newYearPattern, + SbPattern.spookyPattern, + SbPattern.winterEventStartPattern, + SbPattern.winterNextWavePattern, + SbPattern.winterWavePattern, + SbPattern.winterMagmaLeftPattern, + SbPattern.winterTotalDmgPattern, + SbPattern.winterCubeDmgPattern, + SbPattern.riftDimensionPattern, + RiftBloodEffigies.heartsPattern, + SbPattern.wtfAreThoseLinesPattern, + SbPattern.timeLeftPattern, + SbPattern.darkAuctionCurrentItemPattern, + SbPattern.coldPattern, + SbPattern.riftHotdogTitlePattern, + SbPattern.riftHotdogEatenPattern, + SbPattern.mineshaftNotStartedPattern, + SbPattern.queuePattern, + SbPattern.queueTierPattern, + SbPattern.queuePositionPattern, + SbPattern.fortunateFreezingBonusPattern, + SbPattern.riftAveikxPattern, + SbPattern.riftHayEatenPattern, + SbPattern.fossilDustPattern, + SbPattern.cluesPattern, + SbPattern.barryProtestorsQuestlinePattern, + SbPattern.barryProtestorsHandledPattern, + SbPattern.carnivalPattern, + SbPattern.carnivalTasksPattern, + SbPattern.carnivalTokensPattern, + SbPattern.carnivalFruitsPattern, + SbPattern.carnivalScorePattern, + SbPattern.carnivalCatchStreakPattern, + SbPattern.carnivalAccuracyPattern, + SbPattern.carnivalKillsPattern, + ) + private var remoteOnlyPatternsAdded = false + fun handleUnknownLines() { - val sidebarLines = CustomScoreboard.activeLines + val sidebarLines = ScoreboardData.sidebarLinesFormatted var unknownLines = sidebarLines.map { it.removeResets() }.filter { it.isNotBlank() }.filter { it.trim().length > 3 } - /** - * Remove known lines with patterns - **/ - val patternsToExclude = mutableListOf( - PurseAPI.coinsPattern, - SbPattern.motesPattern, - BitsAPI.bitsScoreboardPattern, - SbPattern.heatPattern, - SbPattern.copperPattern, - SbPattern.locationPattern, - SbPattern.lobbyCodePattern, - SbPattern.datePattern, - SbPattern.timePattern, - SbPattern.footerPattern, - SbPattern.yearVotesPattern, - SbPattern.votesPattern, - SbPattern.waitingForVotePattern, - SbPattern.northstarsPattern, - SbPattern.profileTypePattern, - SbPattern.autoClosingPattern, - SbPattern.startingInPattern, - SbPattern.timeElapsedPattern, - SbPattern.instanceShutdownPattern, - SbPattern.keysPattern, - SbPattern.clearedPattern, - SbPattern.soloPattern, - SbPattern.teammatesPattern, - SbPattern.floor3GuardiansPattern, - SbPattern.m7dragonsPattern, - SbPattern.wavePattern, - SbPattern.tokensPattern, - SbPattern.submergesPattern, - SbPattern.medalsPattern, - SbPattern.lockedPattern, - SbPattern.cleanUpPattern, - SbPattern.pastingPattern, - SbPattern.peltsPattern, - SbPattern.mobLocationPattern, - SbPattern.jacobsContestPattern, - SbPattern.plotPattern, - SbPattern.powderGreedyPattern, - SbPattern.windCompassPattern, - SbPattern.windCompassArrowPattern, - SbPattern.miningEventPattern, - SbPattern.miningEventZonePattern, - SbPattern.raffleUselessPattern, - SbPattern.raffleTicketsPattern, - SbPattern.rafflePoolPattern, - SbPattern.mithrilUselessPattern, - SbPattern.mithrilRemainingPattern, - SbPattern.mithrilYourMithrilPattern, - SbPattern.nearbyPlayersPattern, - SbPattern.uselessGoblinPattern, - SbPattern.remainingGoblinPattern, - SbPattern.yourGoblinKillsPattern, - SbPattern.magmaBossPattern, - SbPattern.damageSoakedPattern, - SbPattern.killMagmasPattern, - SbPattern.killMagmasDamagedSoakedBarPattern, - SbPattern.reformingPattern, - SbPattern.bossHealthPattern, - SbPattern.bossHealthBarPattern, - SbPattern.broodmotherPattern, - SbPattern.bossHPPattern, - SbPattern.bossDamagePattern, - SbPattern.slayerQuestPattern, - SbPattern.essencePattern, - SbPattern.redstonePattern, - SbPattern.anniversaryPattern, - SbPattern.visitingPattern, - SbPattern.flightDurationPattern, - SbPattern.dojoChallengePattern, - SbPattern.dojoDifficultyPattern, - SbPattern.dojoPointsPattern, - SbPattern.dojoTimePattern, - SbPattern.objectivePattern, - ServerRestartTitle.restartingGreedyPattern, - SbPattern.travelingZooPattern, - SbPattern.newYearPattern, - SbPattern.spookyPattern, - SbPattern.winterEventStartPattern, - SbPattern.winterNextWavePattern, - SbPattern.winterWavePattern, - SbPattern.winterMagmaLeftPattern, - SbPattern.winterTotalDmgPattern, - SbPattern.winterCubeDmgPattern, - SbPattern.riftDimensionPattern, - RiftBloodEffigies.heartsPattern, - SbPattern.wtfAreThoseLinesPattern, - SbPattern.timeLeftPattern, - SbPattern.darkAuctionCurrentItemPattern, - SbPattern.coldPattern, - SbPattern.riftHotdogTitlePattern, - SbPattern.riftHotdogEatenPattern, - SbPattern.mineshaftNotStartedPattern, - SbPattern.queuePattern, - SbPattern.queueTierPattern, - SbPattern.queuePositionPattern, - SbPattern.fortunateFreezingBonusPattern, - SbPattern.riftAveikxPattern, - SbPattern.riftHayEatenPattern, - SbPattern.fossilDustPattern, - SbPattern.cluesPattern, - SbPattern.barryProtestorsQuestlinePattern, - SbPattern.barryProtestorsHandledPattern, - SbPattern.carnivalPattern, - SbPattern.carnivalTasksPattern, - SbPattern.carnivalTokensPattern, - SbPattern.carnivalFruitsPattern, - SbPattern.carnivalScorePattern, - SbPattern.carnivalCatchStreakPattern, - SbPattern.carnivalAccuracyPattern, - SbPattern.carnivalKillsPattern, - ) - - if (::remoteOnlyPatterns.isInitialized) { + if (::remoteOnlyPatterns.isInitialized && !remoteOnlyPatternsAdded) { patternsToExclude.addAll(remoteOnlyPatterns) + remoteOnlyPatternsAdded = true } unknownLines = unknownLines.filterNot { line -> @@ -203,19 +212,50 @@ object UnknownLinesHandler { /* * Handle broken scoreboard lines */ - confirmedUnknownLines = confirmedUnknownLines.filter { it in unknownLines } - - unknownLines = unknownLines.filter { it !in confirmedUnknownLines } - - unconfirmedUnknownLines = unknownLines + if (unknownLines.isEmpty()) return - unknownLines = unknownLines.filter { it !in unknownLinesSet } + for (line in unknownLines) { + val unknownLine = allUnknownLines.firstOrNull { it.line == line } + if (unknownLine == null) { + if (LorenzUtils.inSkyBlock) { + ChatUtils.debug("Unknown Scoreboard line: '$line'") + } + allUnknownLines = allUnknownLines.editCopy { + add(UnknownLine(line)) + } + } else { + unknownLine.lastFound = SimpleTimeMark.now() + val firstFoundSince = unknownLine.firstFound.passedSince() + val lastWarnedSince = unknownLine.lastWarned.passedSince() + if (firstFoundSince > 3.seconds && lastWarnedSince > 30.minutes) { + unknownLine.lastWarned = SimpleTimeMark.now() + warn(line, "same line active for 3 seconds") + continue + } + } + } - unknownLines.forEach { - if (LorenzUtils.inSkyBlock) { - ChatUtils.debug("Unknown Scoreboard line: '$it'") + if (lastRecentAlarmWarning.passedSince() > 30.minutes) { + val recentAlarms = allUnknownLines.filter { it.firstFound.passedSince() < 6.seconds } + if (recentAlarms.size >= 5) { + warn(recentAlarms.first().line, "5 different lines in 5 seconds") } - unknownLinesSet.add(it) } } + + private fun warn(line: String, reason: String) { + ErrorManager.logErrorWithData( + // line inclucded in chat message to not cache a previous message + CustomScoreboardUtils.UndetectedScoreboardLines(line), + "CustomScoreboard detected a unknown line: '$line'", + "Unknown Line" to line, + "reason" to reason, + "Island" to LorenzUtils.skyBlockIsland, + "Area" to HypixelData.skyBlockArea, + "Full Scoreboard" to ScoreboardData.sidebarLinesFormatted, + noStackTrace = true, + betaOnly = true, + ) + + } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/ChestValue.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/ChestValue.kt index bd032fe66cda..50c5e446fd20 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/ChestValue.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/ChestValue.kt @@ -230,13 +230,11 @@ object ChestValue { enum class SortType(val shortName: String, val longName: String) { PRICE_DESC("Price D", "Price Descending"), PRICE_ASC("Price A", "Price Ascending"), - ; } enum class FormatType(val type: String) { SHORT("Formatted"), LONG("Unformatted"), - ; } enum class DisplayType(val type: String) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/FocusMode.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/FocusMode.kt new file mode 100644 index 000000000000..c02f2993399a --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/FocusMode.kt @@ -0,0 +1,35 @@ +package at.hannibal2.skyhanni.features.inventory + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.LorenzTickEvent +import at.hannibal2.skyhanni.events.LorenzToolTipEvent +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.KeyboardManager.isKeyClicked +import at.hannibal2.skyhanni.utils.LorenzUtils +import net.minecraftforge.fml.common.eventhandler.EventPriority +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +@SkyHanniModule +object FocusMode { + + private val config get() = SkyHanniMod.feature.inventory.focusMode + + private var toggle = true + + @SubscribeEvent(priority = EventPriority.LOWEST) + fun onLorenzToolTip(event: LorenzToolTipEvent) { + if (!isEnabled() || !toggle) return + if(event.toolTip.isEmpty()) return + event.toolTip = mutableListOf(event.toolTip.first()) + } + + @SubscribeEvent + fun onLorenzTick(event: LorenzTickEvent) { + if (!isEnabled()) return + if (!config.toggleKey.isKeyClicked()) return + toggle = !toggle + } + + fun isEnabled() = LorenzUtils.inSkyBlock && InventoryUtils.inContainer() && config.enabled +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/HarpFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/HarpFeatures.kt index d6d79b31a710..dd9e3d91e9ad 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/HarpFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/HarpFeatures.kt @@ -111,7 +111,7 @@ object HarpFeatures { private fun updateScale() { if (Minecraft.getMinecraft().currentScreen == null) { - DelayedRun.runNextTick() { + DelayedRun.runNextTick { updateScale() } return diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/HideNotClickableItems.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/HideNotClickableItems.kt index 2e549313ce3a..f8a16bf50b0b 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/HideNotClickableItems.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/HideNotClickableItems.kt @@ -311,7 +311,7 @@ object HideNotClickableItems { "BRACELET", ) for (type in list) { - if (stack.getLore().any { it.contains("§l") && it.contains(type) }) {// todo use item api + if (stack.getLore().any { it.contains("§l") && it.contains(type) }) { // todo use item api showGreenLine = true return false } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemDisplayOverlayFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemDisplayOverlayFeatures.kt index 1af2c8c88e67..40eb8c4b335b 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemDisplayOverlayFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemDisplayOverlayFeatures.kt @@ -66,11 +66,11 @@ object ItemDisplayOverlayFeatures { private val config get() = SkyHanniMod.feature.inventory private val patternGroup = RepoPattern.group("inventory.item.overlay") - private val masterSkullPattern by patternGroup.pattern( - "masterskull", - "(.*)Master Skull - Tier .", + private val masterSkullIDPattern by patternGroup.pattern( + "masterskull.id", + "MASTER_SKULL_TIER_(?\\d)", ) - private val gardenVacuumPatterm by patternGroup.pattern( + private val gardenVacuumPattern by patternGroup.pattern( "vacuum", "§7Vacuum Bag: §6(?\\d*) Pests?", ) @@ -131,20 +131,20 @@ object ItemDisplayOverlayFeatures { } if (MASTER_SKULL_TIER.isSelected()) { - masterSkullPattern.matchMatcher(itemName) { - return itemName.substring(itemName.length - 1) + masterSkullIDPattern.matchMatcher(internalName.asString()) { + return group("tier") } } - if (DUNGEON_HEAD_FLOOR_NUMBER.isSelected() && (itemName.contains("Golden ") || itemName.contains("Diamond "))) { + if (DUNGEON_HEAD_FLOOR_NUMBER.isSelected() && (internalName.contains("GOLD_") || internalName.contains("DIAMOND_"))) { when { - itemName.contains("Bonzo") -> return "1" - itemName.contains("Scarf") -> return "2" - itemName.contains("Professor") -> return "3" - itemName.contains("Thorn") -> return "4" - itemName.contains("Livid") -> return "5" - itemName.contains("Sadan") -> return "6" - itemName.contains("Necron") -> return "7" + internalName.contains("BONZO") -> return "1" + internalName.contains("SCARF") -> return "2" + internalName.contains("PROFESSOR") -> return "3" + internalName.contains("THORN") -> return "4" + internalName.contains("LIVID") -> return "5" + internalName.contains("SADAN") -> return "6" + internalName.contains("NECRON") -> return "7" } } @@ -252,7 +252,7 @@ object ItemDisplayOverlayFeatures { } if (VACUUM_GARDEN.isSelected() && internalName in PestAPI.vacuumVariants && isOwnItem(lore)) { - lore.matchFirst(gardenVacuumPatterm) { + lore.matchFirst(gardenVacuumPattern) { val pests = group("amount").formatLong() return if (config.vacuumBagCap) { if (pests > 39) "§640+" else "$pests" @@ -298,7 +298,11 @@ object ItemDisplayOverlayFeatures { } } - if (BESTIARY_LEVEL.isSelected() && (chestName.contains("Bestiary ➜") || chestName.contains("Fishing ➜")) && lore.any { it.contains("Deaths: ") }) { + if (BESTIARY_LEVEL.isSelected() && (chestName.contains("Bestiary ➜") || chestName.contains("Fishing ➜")) && + lore.any { + it.contains("Deaths: ") + } + ) { lore.matchFirst(bestiaryStackPattern) { val tier = (group("tier").romanToDecimalIfNecessary() - 1) return tier.toString() diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemPickupLog.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemPickupLog.kt index 05aaeba80703..78e6063ee542 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemPickupLog.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemPickupLog.kt @@ -42,7 +42,7 @@ object ItemPickupLog { "§a+256", { entry, prefix -> val formattedAmount = if (config.shorten) entry.amount.shortFormat() else entry.amount.addSeparators() - Renderable.string("${prefix}${formattedAmount}") + Renderable.string("$prefix$formattedAmount") }, ), ICON( @@ -97,6 +97,9 @@ object ItemPickupLog { "SKYBLOCK_MENU", "CANCEL_PARKOUR_ITEM", "CANCEL_RACE_ITEM", + "MAXOR_ENERGY_CRYSTAL", + "ELLE_SUPPLIES", + "ELLE_FUEL_CELL", ) private val bannedItemsConverted = bannedItemsPattern.map { it.toString().asInternalName() } @@ -148,7 +151,7 @@ object ItemPickupLog { if (cursorItem != null) { val hash = cursorItem.hash() - //this prevents items inside hypixel guis counting when picked up + // this prevents items inside hypixel guis counting when picked up if (oldItemList.contains(hash)) { inventoryItems.add(cursorItem) } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemStars.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemStars.kt index 8e2a5c5927e5..d89c2aca9e3b 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemStars.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/ItemStars.kt @@ -32,7 +32,7 @@ object ItemStars { @SubscribeEvent(priority = EventPriority.LOW) fun onTooltip(event: LorenzToolTipEvent) { if (!isEnabled()) return - val stack = event.itemStack ?: return + val stack = event.itemStack if (stack.stackSize != 1) return val itemName = stack.name diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/MaxPurseItems.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/MaxPurseItems.kt index 517cf4b59346..516ee08fd8d2 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/MaxPurseItems.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/MaxPurseItems.kt @@ -88,7 +88,8 @@ object MaxPurseItems { "§7Max items with purse", "§7Buy order +0.1: §e${buyOrders.addSeparators()}x", "§7Instant buy: §e${buyInstant.addSeparators()}x" - ), posLabel = "Max Items With Purse" + ), + posLabel = "Max Items With Purse" ) } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/MinisterInCalendar.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/MinisterInCalendar.kt index d078f0d1a39f..655f1f91982e 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/MinisterInCalendar.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/MinisterInCalendar.kt @@ -13,6 +13,7 @@ import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName import at.hannibal2.skyhanni.utils.NEUItems.getItemStack import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.StringUtils.removeResets import at.hannibal2.skyhanni.utils.StringUtils.splitLines import net.minecraft.client.player.inventory.ContainerLocalMenu import net.minecraft.item.ItemStack @@ -74,7 +75,7 @@ object MinisterInCalendar { addAll(prefix) for (perk in minister.activePerks) { add("$ministerColor${perk.perkName}") - addAll(perk.description.splitLines(170).removePrefix("§r").split("\n").map { "§7$it" }) + addAll(perk.description.splitLines(170).removeResets().split("\n").map { "§7$it" }) } addAll(suffix) } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/QuickCraftFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/QuickCraftFeatures.kt index 70069a84ea2a..f1235a968af8 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/QuickCraftFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/QuickCraftFeatures.kt @@ -29,7 +29,6 @@ object QuickCraftFeatures { enum class InventoryType(val inventoryName: String) { CRAFT_ITEM("Craft Item"), MORE_QUICK_CRAFT_OPTIONS("Quick Crafting"), - ; } private fun InventoryType.ignoreSlot(slotNumber: Int?): Boolean = when (this) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/ReforgeHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/ReforgeHelper.kt index fcd940d02767..1c098000cce5 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/ReforgeHelper.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/ReforgeHelper.kt @@ -288,7 +288,9 @@ object ReforgeHelper { } else emptyList() } - val addedEffect = getReforgeEffect(reforge, itemRarity)?.let { listOf(renderableString(addEffectText)) + it } ?: emptyList() + val addedEffect = getReforgeEffect(reforge, itemRarity)?.let { + listOf(renderableString(addEffectText)) + it + } ?: emptyList() return listOf(renderableString("§6Reforge Stats")) + stats + removedEffect + addedEffect + click } @@ -379,8 +381,6 @@ object ReforgeHelper { colorReforgeStone(hoverColor, hoveredReforge?.rawReforgeStoneName ?: "Random Basic Reforge") } else { inventoryContainer?.getSlot(reforgeItem)?.highlight(hoverColor) - - //?.get(reforgeItem)?. = hoverColor } hoveredReforge = null } @@ -416,15 +416,17 @@ object ReforgeHelper { private fun SkyblockStatList.print(appliedReforge: SkyblockStatList? = null): List { val diff = appliedReforge?.takeIf { config.showDiff }?.let { this - it } - val main = ((diff ?: this).mapNotNull { - val key = it.key - val value = this[key] ?: 0.0 - buildList { - add(renderableString("§9${value.toStringWithPlus().removeSuffix(".0")}")) - diff?.get(key)?.let { add(renderableString((if (it < 0) "§c" else "§a") + it.toStringWithPlus().removeSuffix(".0"))) } - add(renderableString(key.iconWithName)) + val main = ( + (diff ?: this).mapNotNull { + val key = it.key + val value = this[key] ?: 0.0 + buildList { + add(renderableString("§9${value.toStringWithPlus().removeSuffix(".0")}")) + diff?.get(key)?.let { add(renderableString((if (it < 0) "§c" else "§a") + it.toStringWithPlus().removeSuffix(".0"))) } + add(renderableString(key.iconWithName)) + } } - }) + ) val table = Renderable.table(main, 5) return listOf(table) } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/SackDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/SackDisplay.kt index eb15f6165645..fe14959351d3 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/SackDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/SackDisplay.kt @@ -93,71 +93,73 @@ object SackDisplay { totalPrice += price if (rendered >= config.itemToShow) continue if (stored == 0 && !config.showEmpty) continue - table[buildList { - addString(" §7- ") - addItemStack(internalName) - // TODO move replace into itemName - val nameText = Renderable.optionalLink( - itemName.replace("§k", ""), - onClick = { - if (!SackAPI.isTrophySack) { - BazaarApi.searchForBazaarItem(itemName) + table[ + buildList { + addString(" §7- ") + addItemStack(internalName) + // TODO move replace into itemName + val nameText = Renderable.optionalLink( + itemName.replace("§k", ""), + onClick = { + if (!SackAPI.isTrophySack) { + BazaarApi.searchForBazaarItem(itemName) + } + }, + highlightsOnHoverSlots = listOf(slot) + ) { !NEUItems.neuHasFocus() } + add(nameText) + + + when (config.numberFormat) { + NumberFormatEntry.DEFAULT -> { + addAlignedNumber("$colorCode${stored.addSeparators()}") + addString("§7/") + addAlignedNumber("§b${total.shortFormat()}") } - }, - highlightsOnHoverSlots = listOf(slot) - ) { !NEUItems.neuHasFocus() } - add(nameText) + NumberFormatEntry.FORMATTED -> { + addAlignedNumber("$colorCode${stored.shortFormat()}") + addString("§7/") + addAlignedNumber("§b${total.shortFormat()}") + } - when (config.numberFormat) { - NumberFormatEntry.DEFAULT -> { - addAlignedNumber("$colorCode${stored.addSeparators()}") - addString("§7/") - addAlignedNumber("§b${total.shortFormat()}") - } - - NumberFormatEntry.FORMATTED -> { - addAlignedNumber("$colorCode${stored.shortFormat()}") - addString("§7/") - addAlignedNumber("§b${total.shortFormat()}") - } - - NumberFormatEntry.UNFORMATTED -> { - addAlignedNumber("$colorCode${stored.addSeparators()}") - addString("§7/") - addAlignedNumber("§b${total.addSeparators()}") - } + NumberFormatEntry.UNFORMATTED -> { + addAlignedNumber("$colorCode${stored.addSeparators()}") + addString("§7/") + addAlignedNumber("§b${total.addSeparators()}") + } - else -> { - addAlignedNumber("$colorCode${stored.addSeparators()}") - addString("§7/") - addAlignedNumber("§b${total.addSeparators()}") + else -> { + addAlignedNumber("$colorCode${stored.addSeparators()}") + addString("§7/") + addAlignedNumber("§b${total.addSeparators()}") + } } - } - - // TODO change color of amount if full -// if (colorCode == "§a") addString("§c§l(Full!)") - if (SackAPI.isTrophySack && magmaFish > 0) { - totalMagmaFish += magmaFish - add( - Renderable.hoverTips( - Renderable.string( - "§d${magmaFish}", - horizontalAlign = config.alignment - ), - listOf( - "§6Magmafish: §b${magmaFish.addSeparators()}", - "§6Magmafish value: §b${price / magmaFish}", - "§6Magmafish per: §b${magmaFish / stored}" - ), + // TODO change color of amount if full + // if (colorCode == "§a") addString("§c§l(Full!)") + + if (SackAPI.isTrophySack && magmaFish > 0) { + totalMagmaFish += magmaFish + add( + Renderable.hoverTips( + Renderable.string( + "§d$magmaFish", + horizontalAlign = config.alignment + ), + listOf( + "§6Magmafish: §b${magmaFish.addSeparators()}", + "§6Magmafish value: §b${price / magmaFish}", + "§6Magmafish per: §b${magmaFish / stored}" + ), + ) ) - ) - //TOOD add cache - addItemStack("MAGMA_FISH".asInternalName()) + // TODO add cache + addItemStack("MAGMA_FISH".asInternalName()) + } + if (config.showPrice && price != 0L) addAlignedNumber("§6${format(price)}") } - if (config.showPrice && price != 0L) addAlignedNumber("§6${format(price)}") - }] = itemName + ] = itemName rendered++ } list.add(table.buildSearchableTable()) @@ -187,13 +189,15 @@ object SackDisplay { val name = SortType.entries[config.sortingType.ordinal].longName // todo avoid ordinal list.addString("§7Sorted By: §c$name") - list.addSelector(" ", + list.addSelector( + " ", getName = { type -> type.shortName }, isCurrent = { it.ordinal == config.sortingType.ordinal }, // todo avoid ordinal onChange = { config.sortingType = SortingTypeEntry.entries[it.ordinal] // todo avoid ordinals update(false) - }) + } + ) list.addButton( prefix = "§7Number format: ", @@ -207,13 +211,15 @@ object SackDisplay { ) if (config.showPrice) { - list.addSelector(" ", + list.addSelector( + " ", getName = { type -> type.sellName }, isCurrent = { it.ordinal == config.priceSource.ordinal }, // todo avoid ordinal onChange = { config.priceSource = ItemPriceSource.entries[it.ordinal] // todo avoid ordinal update(false) - }) + } + ) list.addButton( prefix = "§7Price Format: ", getName = PriceFormat.entries[config.priceFormat.ordinal].displayName, // todo avoid ordinal @@ -234,20 +240,22 @@ object SackDisplay { val table = mutableMapOf, String?>() for ((name, rune) in sort(SackAPI.runeItem.toList())) { val (stack, lv1, lv2, lv3) = rune - table[buildList { - addString(" §7- ") - stack?.let { addItemStack(it) } - add( - Renderable.optionalLink( - name, - onClick = {}, - highlightsOnHoverSlots = listOf(rune.slot) + table[ + buildList { + addString(" §7- ") + stack?.let { addItemStack(it) } + add( + Renderable.optionalLink( + name, + onClick = {}, + highlightsOnHoverSlots = listOf(rune.slot) + ) ) - ) - addAlignedNumber("§e$lv1") - addAlignedNumber("§e$lv2") - addAlignedNumber("§e$lv3") - }] = name + addAlignedNumber("§e$lv1") + addAlignedNumber("§e$lv2") + addAlignedNumber("§e$lv3") + } + ] = name } list.add(table.buildSearchableTable()) } @@ -259,23 +267,27 @@ object SackDisplay { val table = mutableMapOf, String?>() for ((name, gem) in sort(SackAPI.gemstoneItem.toList())) { val (internalName, rough, flawed, fine, roughprice, flawedprice, fineprice) = gem - table[buildList { - addString(" §7- ") - addItemStack(internalName) - add(Renderable.optionalLink( - name, - onClick = { - BazaarApi.searchForBazaarItem(name.dropLast(1)) - }, - highlightsOnHoverSlots = listOf(gem.slot) - ) { !NEUItems.neuHasFocus() }) - addAlignedNumber(rough.addSeparators()) - addAlignedNumber("§a${flawed.addSeparators()}") - addAlignedNumber("§9${fine.addSeparators()}") - val price = roughprice + flawedprice + fineprice - totalPrice += price - if (config.showPrice && price != 0L) addAlignedNumber("§7(§6${format(price)}§7)") - }] = name + table[ + buildList { + addString(" §7- ") + addItemStack(internalName) + add( + Renderable.optionalLink( + name, + onClick = { + BazaarApi.searchForBazaarItem(name.dropLast(1)) + }, + highlightsOnHoverSlots = listOf(gem.slot) + ) { !NEUItems.neuHasFocus() } + ) + addAlignedNumber(rough.addSeparators()) + addAlignedNumber("§a${flawed.addSeparators()}") + addAlignedNumber("§9${fine.addSeparators()}") + val price = roughprice + flawedprice + fineprice + totalPrice += price + if (config.showPrice && price != 0L) addAlignedNumber("§7(§6${format(price)}§7)") + } + ] = name } list.add(table.buildSearchableTable()) @@ -299,20 +311,17 @@ object SackDisplay { STORED_ASC("Stored A", "Stored Ascending"), PRICE_DESC("Price D", "Price Descending"), PRICE_ASC("Price A", "Price Ascending"), - ; } enum class PriceFormat(val displayName: String) { - FORMATED("Formatted"), - UNFORMATED("Unformatted"), - ; + FORMATTED("Formatted"), + UNFORMATTED("Unformatted"), } enum class NumberFormat(val displayName: String) { DEFAULT("Default"), FORMATTED("Formatted"), UNFORMATTED("Unformatted"), - ; } @SubscribeEvent diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/SkyblockGuideHighlightFeature.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/SkyblockGuideHighlightFeature.kt index c34b0812538a..c95950a85dcd 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/SkyblockGuideHighlightFeature.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/SkyblockGuideHighlightFeature.kt @@ -21,8 +21,8 @@ import org.intellij.lang.annotations.Language val patternGroup = RepoPattern.group("skyblockguide.highlight") -private const val keyPrefixInventory = "inventory" -private const val keyPrefixCondition = "condition" +private const val KEY_PREFIX_INVENTORY = "inventory" +private const val KEY_PREFIX_CONDITION = "condition" class SkyblockGuideHighlightFeature private constructor( private val config: () -> Boolean, @@ -44,8 +44,8 @@ class SkyblockGuideHighlightFeature private constructor( onTooltip: (LorenzToolTipEvent) -> Unit = {}, ) : this( config, - patternGroup.pattern("$key.$keyPrefixInventory", inventory), - patternGroup.pattern("$key.$keyPrefixCondition", loreCondition), + patternGroup.pattern("$key.$KEY_PREFIX_INVENTORY", inventory), + patternGroup.pattern("$key.$KEY_PREFIX_CONDITION", loreCondition), onSlotClicked, onTooltip ) @@ -59,7 +59,7 @@ class SkyblockGuideHighlightFeature private constructor( onTooltip: (LorenzToolTipEvent) -> Unit = {}, ) : this( config, - patternGroup.pattern("$key.$keyPrefixInventory", inventory), + patternGroup.pattern("$key.$KEY_PREFIX_INVENTORY", inventory), loreCondition, onSlotClicked, onTooltip @@ -132,13 +132,13 @@ class SkyblockGuideHighlightFeature private constructor( } private val taskOnlyCompleteOncePattern = - patternGroup.pattern("$keyPrefixCondition.once", "§7§eThis task can only be completed once!") - private val xPattern = patternGroup.pattern("$keyPrefixCondition.x", "§c ?✖.*") + patternGroup.pattern("$KEY_PREFIX_CONDITION.once", "§7§eThis task can only be completed once!") + private val xPattern = patternGroup.pattern("$KEY_PREFIX_CONDITION.x", "§c ?✖.*") private val totalProgressPattern = - patternGroup.pattern("$keyPrefixCondition.total", "§7Total Progress: §3\\d{1,2}(?:\\.\\d)?%") + patternGroup.pattern("$KEY_PREFIX_CONDITION.total", "§7Total Progress: §3\\d{1,2}(?:\\.\\d)?%") private val categoryProgressPattern = patternGroup.pattern( - "$keyPrefixCondition.category", + "$KEY_PREFIX_CONDITION.category", "§7Progress to Complete Category: §6\\d{1,2}(?:\\.\\d)?%" ) @@ -175,7 +175,9 @@ class SkyblockGuideHighlightFeature private constructor( "travel", "Core ➜ Fast Travels Unlocked", taskOnlyCompleteOncePattern, - { HypixelCommands.wiki("MUSEUM_TRAVEL_SCROLL") }, // The items do not have proper internal names and using the fact that all travel scrolls lead to the same wiki page + { + HypixelCommands.wiki("MUSEUM_TRAVEL_SCROLL") + }, // The items do not have proper internal names and using the fact that all travel scrolls lead to the same wiki page openWikiTooltip ) SkyblockGuideHighlightFeature( diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/UltimateEnchantStar.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/UltimateEnchantStar.kt new file mode 100644 index 000000000000..315d9822b7ba --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/UltimateEnchantStar.kt @@ -0,0 +1,28 @@ +package at.hannibal2.skyhanni.features.inventory + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.RenderItemTipEvent +import at.hannibal2.skyhanni.events.RenderObject +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getEnchantments +import net.minecraft.init.Items +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +@SkyHanniModule +object UltimateEnchantStar { + + private val config get() = SkyHanniMod.feature.inventory + + @SubscribeEvent + fun onRenderItemTip(event: RenderItemTipEvent) { + if (!isEnabled()) return + if (event.stack.item != Items.enchanted_book) return + val enchants = event.stack.getEnchantments() ?: return + if (enchants.size != 1 || !enchants.keys.first().startsWith("ultimate_")) return + event.renderObjects += RenderObject("§d✦", -10, -10) + } + + private fun isEnabled() = LorenzUtils.inSkyBlock && config.ultimateEnchantStar + +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/bazaar/BazaarApi.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/bazaar/BazaarApi.kt index afd5900f7c34..8e8bbb595bb7 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/bazaar/BazaarApi.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/bazaar/BazaarApi.kt @@ -15,7 +15,7 @@ import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.HypixelCommands import at.hannibal2.skyhanni.utils.InventoryUtils -import at.hannibal2.skyhanni.utils.InventoryUtils.getAllItems +import at.hannibal2.skyhanni.utils.InventoryUtils.getUpperItems import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName import at.hannibal2.skyhanni.utils.ItemUtils.getInternalNameOrNull import at.hannibal2.skyhanni.utils.ItemUtils.getLore @@ -66,13 +66,13 @@ object BazaarApi { searchForBazaarItem(internalName.itemNameWithoutColor, amount) } - fun searchForBazaarItem(displayName: String, amount: Int = -1) { + fun searchForBazaarItem(displayName: String, amount: Int? = null) { if (!LorenzUtils.inSkyBlock) return if (NEUItems.neuHasFocus()) return if (LorenzUtils.noTradeMode) return if (DungeonAPI.inDungeon() || LorenzUtils.inKuudraFight) return HypixelCommands.bazaar(displayName.removeColor()) - if (amount != -1) OSUtils.copyToClipboard(amount.toString()) + amount?.let { OSUtils.copyToClipboard(it.toString()) } currentSearchedItem = displayName.removeColor() } @@ -96,12 +96,12 @@ object BazaarApi { orderOptionProduct = internalName } else if (itemName.contains("BUY")) { // pickup items from bazaar order - OwnInventoryData.ignoreItem(1.seconds, { it == internalName }) + OwnInventoryData.ignoreItem(1.seconds) { it == internalName } } } if (InventoryUtils.openInventoryName() == "Order options" && itemName == "§cCancel Order") { // pickup items from own bazaar order - OwnInventoryData.ignoreItem(1.seconds, { it == orderOptionProduct }) + OwnInventoryData.ignoreItem(1.seconds) { it == orderOptionProduct } } } @@ -123,6 +123,7 @@ object BazaarApi { } } + // TODO cache @SubscribeEvent fun onBackgroundDrawn(event: GuiContainerEvent.BackgroundDrawnEvent) { if (!LorenzUtils.inSkyBlock) return @@ -134,7 +135,7 @@ object BazaarApi { val guiChest = event.gui val chest = guiChest.inventorySlots as ContainerChest - for ((slot, stack) in chest.getAllItems()) { + for ((slot, stack) in chest.getUpperItems()) { if (chest.inventorySlots.indexOf(slot) !in 9..44) { continue } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/bazaar/BazaarCancelledBuyOrderClipboard.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/bazaar/BazaarCancelledBuyOrderClipboard.kt index a177d3fe6287..dfd7e38f9b85 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/bazaar/BazaarCancelledBuyOrderClipboard.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/bazaar/BazaarCancelledBuyOrderClipboard.kt @@ -103,7 +103,7 @@ object BazaarCancelledBuyOrderClipboard { event.blockedReason = "bazaar cancelled buy order clipboard" val lastClicked = lastClickedItem ?: error("last clicked bz item is null") - val message = "Bazaar buy order cancelled. Click to reorder. " + + val message = "Bazaar buy order cancelled. Click to re-order. " + "(§8${latestAmount.addSeparators()}x §r${lastClicked.itemName}§e)" ChatUtils.clickableChat( message, diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/bazaar/CraftMaterialsFromBazaar.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/bazaar/CraftMaterialsFromBazaar.kt index adc932cce724..36b5fa505648 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/bazaar/CraftMaterialsFromBazaar.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/bazaar/CraftMaterialsFromBazaar.kt @@ -17,10 +17,8 @@ import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat import at.hannibal2.skyhanni.utils.PrimitiveItemStack import at.hannibal2.skyhanni.utils.PrimitiveItemStack.Companion.makePrimitiveStack -import at.hannibal2.skyhanni.utils.RegexUtils.matches import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables import at.hannibal2.skyhanni.utils.renderables.Renderable -import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @SkyHanniModule @@ -29,10 +27,6 @@ object CraftMaterialsFromBazaar { private val config get() = SkyHanniMod.feature.inventory.bazaar private val materialSlots = listOf(10, 11, 12, 19, 20, 21, 28, 29, 30) - private val inventoryPattern by RepoPattern.pattern( - "inventory.recipe.title", - ".* Recipe" - ) private var inRecipeInventory = false private var purchasing = false @@ -43,11 +37,11 @@ object CraftMaterialsFromBazaar { @SubscribeEvent fun onInventoryOpen(event: InventoryFullyOpenedEvent) { if (!isEnabled()) return - val correctInventoryName = inventoryPattern.matches(event.inventoryName) val items = event.inventoryItems val correctItem = items[23]?.name == "§aCrafting Table" + val correctSuperCraftItem = items[32]?.name == "§aSupercraft" - inRecipeInventory = correctInventoryName && correctItem && !purchasing + inRecipeInventory = correctSuperCraftItem && correctItem && !purchasing if (!inRecipeInventory) return val recipeName = items[25]?.itemName ?: return @@ -79,7 +73,8 @@ object CraftMaterialsFromBazaar { listOf("§eClick here to buy the items from bazaar!"), onClick = { getFromBazaar(neededMaterials) - }) + } + ) ) } } @@ -109,9 +104,14 @@ object CraftMaterialsFromBazaar { val priceMultiplier = amount * multiplier val text = "§8${priceMultiplier.addSeparators()}x " + material.itemName + " §6${(material.getPrice() * priceMultiplier).shortFormat(false)}" - add(Renderable.optionalLink(text, onClick = { - BazaarApi.searchForBazaarItem(material, priceMultiplier) - })) + add( + Renderable.optionalLink( + text, + onClick = { + BazaarApi.searchForBazaarItem(material, priceMultiplier) + } + ) + ) } add( Renderable.clickAndHover( @@ -120,7 +120,8 @@ object CraftMaterialsFromBazaar { onClick = { purchasing = false display = emptyList() - }) + } + ) ) addMultipliers() } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateAmount.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateAmount.kt index 7f0694e2a779..1f1f6d0c0969 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateAmount.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateAmount.kt @@ -31,6 +31,7 @@ enum class ChocolateAmount(val chocolate: () -> Long) { companion object { fun chocolateSinceUpdate(): Long { + if (ChocolateFactoryAPI.isMax()) return 0L val lastUpdate = profileStorage?.lastDataSave ?: return 0 val currentTime = SimpleTimeMark.now() val secondsSinceUpdate = (currentTime - lastUpdate).inWholeSeconds diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryAPI.kt index 112e8a7a7383..195ea51d32f9 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryAPI.kt @@ -239,4 +239,8 @@ object ChocolateFactoryAPI { it.rabbit.removeColor() == rabbitName.removeColor() } } + + fun isMax(): Boolean = profileStorage?.let { + it.maxChocolate == it.currentChocolate + } ?: false } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryBarnManager.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryBarnManager.kt index a2b264b358f5..8ce0047d0aec 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryBarnManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryBarnManager.kt @@ -62,7 +62,7 @@ object ChocolateFactoryBarnManager { HoppityAPI.attemptFireRabbitFound(lastDuplicateAmount = amount) if (hoppityConfig.showDuplicateNumber && !hoppityConfig.compactChat) { - (HoppityCollectionStats.getRabbitCount(HoppityAPI.getLastRabbit()) - 1).takeIf { it > 1 }?.let { + (HoppityCollectionStats.getRabbitCount(HoppityAPI.getLastRabbit())).takeIf { it > 0 }?.let { event.chatComponent = ChatComponentText( event.message.replace("§7§lDUPLICATE RABBIT!", "§7§lDUPLICATE RABBIT! §7(Duplicate §b#$it§7)§r"), ) diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryCustomReminder.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryCustomReminder.kt index b96dc02992fc..8023de822cd1 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryCustomReminder.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryCustomReminder.kt @@ -61,6 +61,8 @@ object ChocolateFactoryCustomReminder { /** * REGEX-TEST: §cYou don't have enough Chocolate! + * REGEX-TEST: §cYou don't have the required items! + * REGEX-TEST: §cYou must collect 300B all-time Chocolate! */ private val chatMessagePattern by patternGroup.list( "chat.hide", @@ -74,11 +76,7 @@ object ChocolateFactoryCustomReminder { if (!isEnabled()) return if (!ChocolateFactoryAPI.inChocolateFactory) return if (configReminder.hideChat) { - if (chatMessagePattern.matches(event.message)) { - //§cYou don't have the required items! - //§cYou must collect 300B all-time Chocolate! -// if (event.message == "§cYou don't have enough Chocolate!") { event.blockedReason = "custom_reminder" } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryDataLoader.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryDataLoader.kt index eebbb19e93a7..64a99a8c911f 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryDataLoader.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryDataLoader.kt @@ -51,6 +51,14 @@ object ChocolateFactoryDataLoader { "chocolate.thisprestige", "§7Chocolate this Prestige: §6(?[\\d,]+)", ) + + /** + * REGEX-TEST: §7Max Chocolate: §660B + */ + private val maxChocolatePattern by ChocolateFactoryAPI.patternGroup.pattern( + "chocolate.max", + "§7Max Chocolate: §6(?.*)", + ) private val chocolateForPrestigePattern by ChocolateFactoryAPI.patternGroup.pattern( "chocolate.forprestige", "§7§cRequires (?\\w+) Chocolate this.*", @@ -230,6 +238,9 @@ object ChocolateFactoryDataLoader { chocolateThisPrestigePattern.matchMatcher(line) { profileStorage.chocolateThisPrestige = group("amount").formatLong() } + maxChocolatePattern.matchMatcher(line) { + profileStorage.maxChocolate = group("max").formatLong() + } chocolateForPrestigePattern.matchMatcher(line) { ChocolateFactoryAPI.chocolateForPrestige = group("amount").formatLong() prestigeCost = ChocolateFactoryAPI.chocolateForPrestige diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStats.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStats.kt index 8d08e485e16f..36c79728cd39 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStats.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStats.kt @@ -76,7 +76,10 @@ object ChocolateFactoryStats { val map = buildMap { put(ChocolateFactoryStat.HEADER, "§6§lChocolate Factory ${ChocolateFactoryAPI.currentPrestige.toRoman()}") - put(ChocolateFactoryStat.CURRENT, "§eCurrent Chocolate: §6${ChocolateAmount.CURRENT.formatted}") + val maxSuffix = if (ChocolateFactoryAPI.isMax()) { + " §cMax!" + } else "" + put(ChocolateFactoryStat.CURRENT, "§eCurrent Chocolate: §6${ChocolateAmount.CURRENT.formatted}$maxSuffix") put(ChocolateFactoryStat.THIS_PRESTIGE, "§eThis Prestige: §6${ChocolateAmount.PRESTIGE.formatted}") put(ChocolateFactoryStat.ALL_TIME, "§eAll-time: §6${ChocolateAmount.ALL_TIME.formatted}") diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStrayTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStrayTracker.kt index 805d2c8617b2..bb4eeaedb20c 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStrayTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStrayTracker.kt @@ -100,6 +100,7 @@ object ChocolateFactoryStrayTracker { "§7You caught a stray §6§lGolden Rabbit§7! §7You gained §6\\+5 Chocolate §7until the §7end of the SkyBlock year!", ) + // TODO: Fix this pattern so it doesn't only match duplicates. /** * REGEX-TEST: §7You caught a stray §9Fish the Rabbit§7! §7You have already found §9Fish the §9Rabbit§7, so you received §655,935,257 §6Chocolate§7! */ @@ -108,8 +109,25 @@ object ChocolateFactoryStrayTracker { "§7You caught a stray (?§.)Fish the Rabbit§7! §7You have already found (?:§.)?Fish the (?:§.)?Rabbit§7, so you received §6(?[\\d,]*) (?:§6)?Chocolate§7!", ) - private val tracker = SkyHanniTracker("Stray Tracker", { Data() }, { it.chocolateFactory.strayTracker }) - { drawDisplay(it) } + /** + * REGEX-TEST: §7You have already found §9Fish the + */ + val duplicatePseudoStrayPattern by ChocolateFactoryAPI.patternGroup.pattern( + "stray.pseudoduplicate", + "(?:§.)*You have already found.*", + ) + + /** + * REGEX-TEST: §7already have captured him before + */ + val duplicateDoradoStrayPattern by ChocolateFactoryAPI.patternGroup.pattern( + "stray.doradoduplicate", + "(?:§.)*already have captured him before.*", + ) + + private val tracker = SkyHanniTracker("Stray Tracker", { Data() }, { it.chocolateFactory.strayTracker }) { + drawDisplay(it) + } class Data : TrackerData() { override fun reset() { @@ -152,7 +170,7 @@ object ChocolateFactoryStrayTracker { add( Renderable.hoverTips( "§6§lStray Tracker", - tips = listOf("§a+§b${formattedExtraTime} §afrom strays§7"), + tips = listOf("§a+§b$formattedExtraTime §afrom strays§7"), ).toSearchable(), ) HoppityAPI.hoppityRarities.forEach { rarity -> @@ -169,7 +187,7 @@ object ChocolateFactoryStrayTracker { val colorCode = rarity.chatColorCode val lineHeader = "$colorCode${rarity.toString().lowercase().replaceFirstChar { it.uppercase() }}§7: §r$colorCode" - val lineFormat = "${lineHeader}${caughtString}" + val lineFormat = "$lineHeader$caughtString" val renderable = rarityExtraChocMs?.let { var tip = "§a+§b$extraChocFormat §afrom $colorCode${rarity.toString().lowercase()} strays§7" @@ -204,14 +222,14 @@ object ChocolateFactoryStrayTracker { // "Base" strays - Common -> Epic, raw choc only reward. strayLorePattern.matchMatcher(loreLine) { - //Pretty sure base strays max at Epic, but... + // Pretty sure base strays max at Legendary, but... val rarity = HoppityAPI.rarityByRabbit(group("rabbit")) ?: return@matchMatcher incrementRarity(rarity, group("amount").formatLong()) } // Fish the Rabbit fishTheRabbitPattern.matchMatcher(loreLine) { - //Also fairly sure that Fish maxes out at Rare, but... + // Also fairly sure that Fish maxes out at Rare, but... val rarity = HoppityAPI.rarityByRabbit(group("color")) ?: return@matchMatcher incrementRarity(rarity, group("amount").formatLong()) } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryTooltip.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryTooltip.kt index 88ac9d4747ae..01b42a130582 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryTooltip.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryTooltip.kt @@ -36,7 +36,7 @@ object ChocolateFactoryTooltip { if (upgradeInfo.effectiveCost == null) return event.toolTip.add("§7Extra: §6${upgradeInfo.extraPerSecond?.roundTo(2) ?: "N/A"} §7choc/s") - event.toolTip.add("§7Effective Cost: §6${upgradeInfo.effectiveCost.addSeparators() ?: "N/A"}") + event.toolTip.add("§7Effective Cost: §6${upgradeInfo.effectiveCost.addSeparators()}") if (slotIndex == ChocolateFactoryAPI.timeTowerIndex) { event.toolTip.add("§7One charge will give: §6${chocPerTimeTower().addSeparators()}") diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateShopPrice.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateShopPrice.kt index 277532aaa667..13757d1b39ff 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateShopPrice.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateShopPrice.kt @@ -132,7 +132,7 @@ object ChocolateShopPrice { add("§7Profit per purchase: §6${profit.shortFormat()} ") add("") add("§7Chocolate amount: §c${product.chocolate.shortFormat()} ") - add("§7Profit per million chocolate: §6${perFormat} ") + add("§7Profit per million chocolate: §6$perFormat ") add("") val formattedTimeUntilGoal = ChocolateAmount.CURRENT.formattedTimeUntilGoal(product.chocolate) add("§7Time until affordable: §6$formattedTimeUntilGoal ") diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/craft/CraftableItemList.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/craft/CraftableItemList.kt index 8612c9795cfc..517a6fd6d9de 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/craft/CraftableItemList.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/craft/CraftableItemList.kt @@ -124,7 +124,9 @@ object CraftableItemList { inInventory = false } - private fun pricePer(neededItems: Map): Double = neededItems.map { it.key.getPrice() * it.value }.sum() + private fun pricePer(neededItems: Map): Double = neededItems.map { + it.key.getPrice() * it.value + }.sum() private fun canCraftAmount( need: Map, diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentationTableAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentationTableAPI.kt index 80433b68e665..be0f08a5bafc 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentationTableAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentationTableAPI.kt @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.features.inventory.experimentationtable import at.hannibal2.skyhanni.data.IslandType +import at.hannibal2.skyhanni.data.PetAPI import at.hannibal2.skyhanni.data.ProfileStorageData import at.hannibal2.skyhanni.events.InventoryUpdatedEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule @@ -35,12 +36,15 @@ object ExperimentationTableAPI { fun onInventoryUpdated(event: InventoryUpdatedEvent) { if (LorenzUtils.skyBlockIsland != IslandType.PRIVATE_ISLAND || !inTable) return - val entity = EntityUtils.getEntities().find { it.hasSkullTexture(experimentationTableSkull) } ?: return + val entity = EntityUtils.getEntities().find { + it.hasSkullTexture(EXPERIMENTATION_TABLE_SKULL) + } ?: return val vec = entity.getLorenzVec() if (storage?.tablePos != vec) storage?.tablePos = vec } - private val experimentationTableSkull = + // TODO: Add to repo + private const val EXPERIMENTATION_TABLE_SKULL = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTUyOWF" + "iYzg4MzA5NTNmNGQ5MWVkZmZmMjQ2OTVhOWY2Mjc1OGZhNGM1MWIyOWFjMjQ2YzM3NDllYWFlODliMyJ9fX0=" @@ -68,7 +72,7 @@ object ExperimentationTableAPI { */ val rewardPattern by patternGroup.pattern( "rewards", - "\\d{1,3}k Enchanting Exp|Enchanted Book|(?:Titanic |Grand |\\b)Experience Bottle|Metaphysical Serum|Experiment The Fish", + "\\d{1,3}k Enchanting Exp|Enchanted Book|(?:Titanic |Grand |\\b)Experience Bottle|Metaphysical Serum|Experiment the Fish", ) /** @@ -117,9 +121,25 @@ object ExperimentationTableAPI { /** * REGEX-TEST: Titanic Experience Bottle */ + val experienceBottleChatPattern by patternGroup.pattern( + "chat.xpbottle", + "(?:Colossal |Titanic |Grand |\\b)Experience Bottle", + ) + + /** + * REGEX-TEST: TITANIC_EXP_BOTTLE + */ val experienceBottlePattern by patternGroup.pattern( "xpbottle", - "(?:Titanic |Grand |\\b)Experience Bottle", + "(?:COLOSSAL_|TITANIC_|GRAND_|\\b)EXP_BOTTLE", + ) + + /** + * REGEX-TEST: Remaining Clicks: 22 + */ + val remainingClicksPattern by patternGroup.pattern( + "clicks", + "Remaining Clicks: (?\\d+)" ) /** @@ -150,8 +170,10 @@ object ExperimentationTableAPI { * REGEX-TEST: §dGuardian * REGEX-TEST: §9Guardian§e */ - val petNamePattern by patternGroup.pattern( + private val petNamePattern by patternGroup.pattern( "guardianpet", "§[956d]Guardian.*", ) + + fun hasGuardianPet(): Boolean = petNamePattern.matches(PetAPI.currentPet) } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentsProfitTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentsProfitTracker.kt index 6e755d874018..79f0304f433f 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentsProfitTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/ExperimentsProfitTracker.kt @@ -1,16 +1,21 @@ package at.hannibal2.skyhanni.features.inventory.experimentationtable import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.data.ClickType import at.hannibal2.skyhanni.data.IslandType +import at.hannibal2.skyhanni.data.ItemAddManager +import at.hannibal2.skyhanni.events.GuiContainerEvent import at.hannibal2.skyhanni.events.GuiRenderEvent import at.hannibal2.skyhanni.events.InventoryCloseEvent import at.hannibal2.skyhanni.events.InventoryUpdatedEvent import at.hannibal2.skyhanni.events.IslandChangeEvent +import at.hannibal2.skyhanni.events.ItemAddEvent import at.hannibal2.skyhanni.events.ItemClickEvent import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentationTableAPI.claimMessagePattern import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentationTableAPI.enchantingExpPattern +import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentationTableAPI.experienceBottleChatPattern import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentationTableAPI.experienceBottlePattern import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentationTableAPI.experimentRenewPattern import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentationTableAPI.experimentsDropPattern @@ -28,7 +33,6 @@ import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzVec import at.hannibal2.skyhanni.utils.NEUInternalName import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators -import at.hannibal2.skyhanni.utils.NumberUtil.roundTo import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.RegexUtils.matches @@ -56,7 +60,7 @@ object ExperimentsProfitTracker { { it.experimentation.experimentsProfitTracker }, ) { drawDisplay(it) } - private var lastSplashes = mutableListOf() + private val lastSplashes = mutableListOf() private var lastSplashTime = SimpleTimeMark.farPast() private var lastBottlesInInventory = mutableMapOf() private var currentBottlesInInventory = mutableMapOf() @@ -95,6 +99,13 @@ object ExperimentsProfitTracker { var startCost = 0L } + @SubscribeEvent + fun onItemAdd(event: ItemAddEvent) { + if (!isEnabled() || event.source != ItemAddManager.Source.COMMAND) return + + tracker.addItem(event.internalName, event.amount, command = true) + } + @SubscribeEvent fun onChat(event: LorenzChatEvent) { if (!isEnabled()) return @@ -120,7 +131,7 @@ object ExperimentsProfitTracker { private fun LorenzChatEvent.handleDrop(reward: String) { blockedReason = when { enchantingExpPattern.matches(reward) && ExperimentMessages.EXPERIENCE.isSelected() -> "EXPERIENCE_DROP" - experienceBottlePattern.matches(reward) && ExperimentMessages.BOTTLES.isSelected() -> "BOTTLE_DROP" + experienceBottleChatPattern.matches(reward) && ExperimentMessages.BOTTLES.isSelected() -> "BOTTLE_DROP" listOf("Metaphysical Serum", "Experiment The Fish").contains(reward) && ExperimentMessages.MISC.isSelected() -> "MISC_DROP" ExperimentMessages.ENCHANTMENTS.isSelected() -> "ENCHANT_DROP" else -> "" @@ -134,37 +145,49 @@ object ExperimentsProfitTracker { } val internalName = NEUInternalName.fromItemNameOrNull(reward) ?: return - if (!experienceBottlePattern.matches(reward)) tracker.addItem(internalName, 1, false) + if (!experienceBottleChatPattern.matches(reward)) tracker.addItem(internalName, 1, false) else DelayedRun.runDelayed(100.milliseconds) { handleExpBottles(true) } } @SubscribeEvent + fun onSlotClick(event: GuiContainerEvent.SlotClickEvent) { + if (!isEnabled() || + InventoryUtils.openInventoryName() != "Bottles of Enchanting" || + !listOf(11, 12, 14, 15).contains(event.slotId) + ) return + val stack = event.slot?.stack ?: return + + val internalName = stack.getInternalName() + if (internalName.isExpBottle()) { + tracker.modify { + it.startCost -= calculateBottlePrice(internalName) + } + } + } + + @HandleEvent fun onItemClick(event: ItemClickEvent) { - if (event.clickType == ClickType.RIGHT_CLICK) { + if (isEnabled() && event.clickType == ClickType.RIGHT_CLICK) { val item = event.itemInHand ?: return - if (experienceBottlePattern.matches(item.displayName.removeColor())) { + if (item.getInternalName().isExpBottle()) { lastSplashTime = SimpleTimeMark.now() lastSplashes.add(item) } } } + private fun NEUInternalName.isExpBottle() = experienceBottlePattern.matches(asString()) + @SubscribeEvent fun onInventoryUpdated(event: InventoryUpdatedEvent) { if (!isEnabled()) return if (inventoriesPattern.matches(event.inventoryName)) { var startCostTemp = 0 - val iterator = lastSplashes.iterator() - while (iterator.hasNext()) { - val item = iterator.next() - val internalName = item.getInternalName() - val price = internalName.getPrice() - val npcPrice = internalName.getNpcPriceOrNull() ?: 0.0 - val maxPrice = npcPrice.coerceAtLeast(price) - startCostTemp += maxPrice.roundTo(0).toInt() - iterator.remove() + for (item in lastSplashes) { + startCostTemp += calculateBottlePrice(item.getInternalName()) } + lastSplashes.clear() tracker.modify { it.startCost -= startCostTemp } @@ -174,6 +197,13 @@ object ExperimentsProfitTracker { handleExpBottles(false) } + private fun calculateBottlePrice(internalName: NEUInternalName): Int { + val price = internalName.getPrice() + val npcPrice = internalName.getNpcPriceOrNull() ?: 0.0 + val maxPrice = npcPrice.coerceAtLeast(price) + return maxPrice.toInt() + } + @SubscribeEvent fun onInventoryClose(event: InventoryCloseEvent) { if (!isEnabled()) return diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/GuardianReminder.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/GuardianReminder.kt index 216cbf7c6ba8..03748c5d5d5a 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/GuardianReminder.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/GuardianReminder.kt @@ -2,16 +2,15 @@ package at.hannibal2.skyhanni.features.inventory.experimentationtable import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator -import at.hannibal2.skyhanni.data.PetAPI import at.hannibal2.skyhanni.events.GuiRenderEvent import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.ColorUtils.withAlpha +import at.hannibal2.skyhanni.utils.DelayedRun import at.hannibal2.skyhanni.utils.HypixelCommands import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.RegexUtils.matches import at.hannibal2.skyhanni.utils.RenderUtils import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.SoundUtils @@ -30,19 +29,20 @@ object GuardianReminder { private val config get() = SkyHanniMod.feature.inventory.experimentationTable private var lastInventoryOpen = SimpleTimeMark.farPast() - private var lastWarn = SimpleTimeMark.farPast() private var lastErrorSound = SimpleTimeMark.farPast() @SubscribeEvent fun onInventory(event: InventoryFullyOpenedEvent) { if (!isEnabled()) return if (event.inventoryName != "Experimentation Table") return - if (ExperimentationTableAPI.petNamePattern.matches(PetAPI.currentPet)) return - lastInventoryOpen = SimpleTimeMark.now() - if (lastWarn.passedSince() < 5.seconds) return - lastWarn = SimpleTimeMark.now() + DelayedRun.runDelayed(200.milliseconds, ::warn) + } + + private fun warn() { + if (ExperimentationTableAPI.hasGuardianPet()) return + ChatUtils.clickToActionOrDisable( "Use a §9§lGuardian Pet §efor more Exp in the Experimentation Table.", config::guardianReminder, @@ -56,6 +56,7 @@ object GuardianReminder { if (!isEnabled()) return if (InventoryUtils.openInventoryName() != "Experimentation Table") return if (lastInventoryOpen.passedSince() > 2.seconds) return + if (ExperimentationTableAPI.hasGuardianPet()) return val gui = Minecraft.getMinecraft().currentScreen as? GuiContainer ?: return sendTitle(gui.width, gui.height) diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairDataDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairDataDisplay.kt new file mode 100644 index 000000000000..f67c7dcf817a --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairDataDisplay.kt @@ -0,0 +1,303 @@ +package at.hannibal2.skyhanni.features.inventory.experimentationtable + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.IslandType +import at.hannibal2.skyhanni.events.GuiContainerEvent.SlotClickEvent +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.InventoryCloseEvent +import at.hannibal2.skyhanni.features.inventory.experimentationtable.ExperimentationTableAPI.remainingClicksPattern +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.CollectionUtils.equalsOneOf +import at.hannibal2.skyhanni.utils.DelayedRun +import at.hannibal2.skyhanni.utils.InventoryUtils +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.LorenzUtils.isAnyOf +import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland +import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.RegexUtils.matches +import at.hannibal2.skyhanni.utils.RenderUtils.renderString +import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings +import at.hannibal2.skyhanni.utils.StringUtils.removeColor +import net.minecraft.item.ItemStack +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration.Companion.milliseconds + +// TODO important: all use cases of listOf in combination with string needs to be gone. no caching, constant new list creation, and bad design. +@SkyHanniModule +object SuperpairDataDisplay { + + private val config get() = SkyHanniMod.feature.inventory.experimentationTable + + private data class SuperpairItem(val index: Int, val reward: String, val damage: Int) + private data class FoundData(val item: SuperpairItem? = null, val first: SuperpairItem? = null, val second: SuperpairItem? = null) + + private enum class FoundType { + NORMAL, + POWERUP, + MATCH, + PAIR + } + + private val sideSpaces1 = listOf(17, 18, 26, 27, 35, 36) + private val sideSpaces2 = listOf(16, 17, 18, 19, 25, 26, 27, 28, 34, 35, 36, 37) + private val emptySuperpairItem = SuperpairItem(-1, "", -1) + + private var display = emptyList() + private var uncoveredItems = mutableMapOf() + private var found = mutableMapOf>() + + @SubscribeEvent + fun onInventoryClose(event: InventoryCloseEvent) { + display = emptyList() + + uncoveredItems = mutableMapOf() + found.clear() + } + + @SubscribeEvent + fun onChestGuiOverlayRendered(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) { + if (!isEnabled()) return + if (InventoryUtils.openInventoryName() == "Experimentation Table") { + // Render here so they can move it around. + config.superpairDisplayPosition.renderString("§6Superpair Experimentation Data", posLabel = "Superpair Experimentation Data") + } + if (ExperimentationTableAPI.getCurrentExperiment() == null) return + + if (display.isEmpty()) display = drawDisplay() + + config.superpairDisplayPosition.renderStrings(display, posLabel = "Superpair Experimentation Data") + } + + @SubscribeEvent + fun onSlotClick(event: SlotClickEvent) { + if (!isEnabled()) return + if (ExperimentationTableAPI.getCurrentExperiment() == null) return + + val currentExperiment = ExperimentationTableAPI.getCurrentExperiment() ?: return + + val item = event.item ?: return + if (isOutOfBounds(event.slotId, currentExperiment) || item.displayName.removeColor() == "?") return + + val clicksItem = InventoryUtils.getItemAtSlotIndex(4) + + // TODO add variable name to indicate what is going on here + if (uncoveredItems.none { it.value.index == event.slotId && it.key == uncoveredItems.keys.max() }) { + if (clicksItem != null) { + remainingClicksPattern.matchMatcher(clicksItem.displayName.removeColor()) { if (group("clicks").toInt() == 0) return } + } + + handleItem(event.slotId) + } + } + + private fun handleItem(slot: Int) = DelayedRun.runDelayed(200.milliseconds) { + val itemNow = InventoryUtils.getItemAtSlotIndex(slot) ?: return@runDelayed + val itemName = itemNow.displayName.removeColor() + val reward = convertToReward(itemNow) + val itemData = SuperpairItem(slot, reward, itemNow.itemDamage) + val uncovered = uncoveredItems.keys.maxOrNull() ?: -1 + + if (isWaiting(itemName)) return@runDelayed + + if (uncoveredItems.none { it.key == uncovered && it.value.index == slot }) uncoveredItems[uncovered + 1] = itemData + + when { + isPowerUp(reward) -> handlePowerUp(itemData, uncovered + 1) + isReward(itemName) -> handleReward(itemData, uncovered + 1) + } + + val since = clicksSinceSeparator(uncoveredItems) + + val lastReward = uncoveredItems.entries.last().value.reward + // TODO use repo patterns for "Instant Find" + if ((since >= 2 || (since == -1 && uncoveredItems.size >= 2)) && lastReward != "Instant Find") uncoveredItems[uncovered + 2] = + emptySuperpairItem + + display = drawDisplay() + } + + private fun handlePowerUp(item: SuperpairItem, uncovered: Int) { + // TODO use repo patterns for "Instant Find" + if (item.reward != "Instant Find") uncoveredItems.remove(uncovered) + + val itemData = FoundData(item = item) + found.getOrPut(FoundType.POWERUP) { mutableListOf(itemData) }.apply { if (!contains(itemData)) add(itemData) } + } + + private fun handleReward(item: SuperpairItem, uncovered: Int) { + val last = uncoveredItems.getOrDefault(uncovered - 1, item) + + if (isWaiting(last.reward)) return + + when { + // TODO use repo patterns for "Instant Find" + last.reward == "Instant Find" -> handleInstantFind(item, uncovered) + hasFoundPair(item, last) -> handleFoundPair(item, last) + hasFoundMatch(item) -> handleFoundMatch(item) + else -> handleNormalReward(item) + } + + println(found) + } + + private fun handleInstantFind(item: SuperpairItem, uncovered: Int) { + uncoveredItems[uncovered - 1] = item + uncoveredItems[uncovered] = emptySuperpairItem + + handleFoundPair(item, emptySuperpairItem) + } + + private fun handleFoundPair( + first: SuperpairItem, + second: SuperpairItem, + ) { + found.entries.forEach { + when (it.key) { + FoundType.MATCH -> it.value.removeIf { data -> data.first?.sameAs(first) ?: false || data.second?.sameAs(first) ?: false } + FoundType.NORMAL -> it.value.removeIf { data -> data.item?.sameAs(first) ?: false || data.item?.sameAs(second) ?: false } + else -> {} + } + } + + val pairData = FoundData(first = first, second = second) + + found.getOrPut(FoundType.PAIR) { mutableListOf(pairData) }.apply { if (!contains(pairData)) add(pairData) } + } + + private fun handleFoundMatch(item: SuperpairItem) { + // TODO better name + val match = uncoveredItems.values.find { it.index != item.index && it.sameAs(item) } ?: return + + found.entries.forEach { + when { + it.key.isAnyOf(FoundType.MATCH, FoundType.PAIR) -> { + // TODO extract logic in some way + if (it.value.any { data -> + (data.first?.index ?: -1).equalsOneOf(item.index, match.index) || + (data.second?.index ?: -1).equalsOneOf(item.index, match.index) + } + ) { + return + } + } + + it.key == FoundType.NORMAL -> it.value.removeIf { data -> + (data.item?.index ?: -1).equalsOneOf(item.index, match.index) + } + + else -> {} + } + } + + val pairData = FoundData(first = item, second = match) + found.getOrPut(FoundType.MATCH) { mutableListOf(pairData) }.apply { if (!contains(pairData)) add(pairData) } + } + + private fun handleNormalReward(item: SuperpairItem) { + for ((key, value) in found.entries) { + when { + key.isAnyOf(FoundType.MATCH, FoundType.PAIR) -> { + if (value.any { data -> + item.index.equalsOneOf(data.first?.index ?: -1, data.second?.index ?: -1) + } + ) return + } + + else -> + if ( + value.any { data -> + (data.item?.index ?: -1) == item.index && data.item?.sameAs(item) == true + } + ) return + } + } + + val itemData = FoundData(item = item) + found.getOrPut(FoundType.NORMAL) { mutableListOf(itemData) }.apply { if (!contains(itemData)) add(itemData) } + } + + private fun drawDisplay() = buildList { + val currentExperiment = ExperimentationTableAPI.getCurrentExperiment() ?: return emptyList() + + add("§6Superpair Experimentation Data") + add("") + + val normals = found.entries.firstOrNull { it.key == FoundType.NORMAL }?.value ?: mutableListOf() + val powerups = found.entries.firstOrNull { it.key == FoundType.POWERUP }?.value ?: mutableListOf() + val matches = found.entries.firstOrNull { it.key == FoundType.MATCH }?.value ?: mutableListOf() + val pairs = found.entries.firstOrNull { it.key == FoundType.PAIR }?.value ?: mutableListOf() + val possiblePairs = calculatePossiblePairs(currentExperiment) + + if (pairs.isNotEmpty()) add("§2Found") + for (pair in pairs) { + val prefix = determinePrefix(pairs.indexOf(pair), pairs.lastIndex) + add(" $prefix §a${pair.first?.reward ?: ""}") + } + if (matches.isNotEmpty()) add("§eMatched") + for (match in matches) { + val prefix = determinePrefix(matches.indexOf(match), matches.lastIndex) + add(" $prefix §e${match.first?.reward ?: ""}") + } + if (powerups.isNotEmpty()) add("§bPowerUp") + for (powerup in powerups) { + val prefix = determinePrefix(powerups.indexOf(powerup), powerups.size - 1) + add(" $prefix §b${powerup.item?.reward ?: ""}") + } + val toAdd = mutableListOf() + if (possiblePairs >= 1) toAdd.add("§ePairs - $possiblePairs") + if (2 - powerups.size >= 1) toAdd.add("§bPowerUps - ${2 - powerups.size}") + if (normals.isNotEmpty()) toAdd.add("§7Normals - ${normals.size}") + + if (toAdd.isNotEmpty()) { + add("") + add("§4Not found") + } + for (string in toAdd) if (string != toAdd.last()) add(" ├ $string") else add(" └ $string") + } + + private fun calculatePossiblePairs(currentExperiment: Experiment) = + ((currentExperiment.gridSize - 2) / 2) - found.filter { it.key != FoundType.POWERUP }.values.sumOf { it.size } + + private fun convertToReward(item: ItemStack) = if (item.displayName.removeColor() == "Enchanted Book") item.getLore()[2].removeColor() + else item.displayName.removeColor() + + private fun determinePrefix(index: Int, lastIndex: Int) = if (index == lastIndex) "└" else "├" + + private fun hasFoundPair( + first: SuperpairItem, + second: SuperpairItem, + ) = first.index != second.index && first.sameAs(second) + + // TODO extract logic greatly + private fun hasFoundMatch(firstItem: SuperpairItem) = + uncoveredItems.any { it.value.index != firstItem.index && it.value.sameAs(firstItem) } && + found.entries.none { + it.key.isAnyOf(FoundType.PAIR, FoundType.MATCH) && + it.value.any { data -> + firstItem.index.equalsOneOf(data.first?.index ?: -1, data.second?.index ?: -1) + } + } + + private fun isPowerUp(reward: String) = ExperimentationTableAPI.powerUpPattern.matches(reward) + + private fun isReward(reward: String) = + ExperimentationTableAPI.rewardPattern.matches(reward) || ExperimentationTableAPI.powerUpPattern.matches(reward) + + // TODO use repo patterns instead + private fun isWaiting(itemName: String) = + listOf("Click any button!", "Click a second button!", "Next button is instantly rewarded!").contains(itemName) + + private fun clicksSinceSeparator(list: MutableMap): Int { + val lastIndex = list.entries.indexOfLast { it.value == emptySuperpairItem } + return if (lastIndex != -1) list.size - 1 - lastIndex else -1 + } + + private fun isOutOfBounds(slot: Int, experiment: Experiment): Boolean = + slot <= experiment.startSlot || + slot >= experiment.endSlot || + (if (experiment.sideSpace == 1) slot in sideSpaces1 else slot in sideSpaces2) + + private fun SuperpairItem?.sameAs(other: SuperpairItem) = this?.reward == other.reward && this.damage == other.damage + + private fun isEnabled() = IslandType.PRIVATE_ISLAND.isInIsland() && config.superpairDisplay +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairExperimentInformationDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairExperimentInformationDisplay.kt deleted file mode 100644 index b1ee566598b3..000000000000 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairExperimentInformationDisplay.kt +++ /dev/null @@ -1,277 +0,0 @@ -package at.hannibal2.skyhanni.features.inventory.experimentationtable - -import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.events.GuiContainerEvent.SlotClickEvent -import at.hannibal2.skyhanni.events.GuiRenderEvent -import at.hannibal2.skyhanni.events.InventoryCloseEvent -import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule -import at.hannibal2.skyhanni.utils.InventoryUtils -import at.hannibal2.skyhanni.utils.ItemUtils.getLore -import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.RegexUtils.matches -import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings -import at.hannibal2.skyhanni.utils.SimpleTimeMark -import at.hannibal2.skyhanni.utils.StringUtils.removeColor -import net.minecraft.item.ItemStack -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -import kotlin.time.Duration.Companion.milliseconds - -@SkyHanniModule -// TODO important: all use cases of listOf in combination with string needs to be gone. no caching, constant new list creation, and bad design. -object SuperpairExperimentInformationDisplay { - - private val config get() = SkyHanniMod.feature.inventory.experimentationTable - - private var display = emptyList() - - private var uncoveredAt = 0 - private var uncoveredItems = mutableListOf>() - private var possiblePairs = 0 - - data class Item(val index: Int, val name: String) - data class ItemPair(val first: Item, val second: Item) - - // TODO remove string. use enum instead! maybe even create new data type instead of map of pairs - private var found = mutableMapOf, String>() - - private var toCheck = mutableListOf>() - private var lastClicked = mutableListOf>() - private var lastClick = SimpleTimeMark.farPast() - private var currentExperiment = Experiment.NONE - private var instantFind = 0 - - private val sideSpaces1 = listOf(17, 18, 26, 27, 35, 36) - private val sideSpaces2 = listOf(16, 17, 18, 19, 25, 26, 27, 28, 34, 35, 36, 37) - - @SubscribeEvent - fun onInventoryClose(event: InventoryCloseEvent) { - display = emptyList() - - uncoveredAt = 0 - uncoveredItems.clear() - possiblePairs = 0 - - found.clear() - toCheck.clear() - lastClicked.clear() - lastClick = SimpleTimeMark.farPast() - currentExperiment = Experiment.NONE - instantFind = 0 - } - - @SubscribeEvent - fun onChestGuiOverlayRendered(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) { - if (!isEnabled()) return - config.superpairDisplayPosition.renderStrings(display, posLabel = "Superpair Experiment Information") - display = checkItems(toCheck) - } - - @SubscribeEvent - fun onSlotClick(event: SlotClickEvent) { - if (!isEnabled()) return - currentExperiment = ExperimentationTableAPI.getCurrentExperiment() ?: return - - if (isOutOfBounds(event.slotId, currentExperiment)) return - val item = event.item ?: return - if (item.displayName.removeColor() == "?") return - val clicksItem = InventoryUtils.getItemAtSlotIndex(4) - - if (lastClicked.none { it.first == event.slotId && it.second == uncoveredAt } && lastClick.passedSince() > 100.milliseconds) { - if (clicksItem != null && clicksItem.displayName.removeColor().split(" ")[1] == "0") return - lastClicked.add(Pair(event.slotId, uncoveredAt)) - lastClick = SimpleTimeMark.now() - toCheck.add(event.slotId to uncoveredAt) - uncoveredAt += 1 - } - } - - private fun checkItems(check: MutableList>): List { - currentExperiment = ExperimentationTableAPI.getCurrentExperiment() ?: return listOf() - if (check.isEmpty()) return drawDisplay() - - for ((slot, uncovered) in check) { - val itemNow = InventoryUtils.getItemAtSlotIndex(slot) ?: return drawDisplay() - val itemName = itemNow.displayName.removeColor() - - if (isWaiting(itemName) || isOutOfBounds(slot, currentExperiment)) return drawDisplay() - - val reward = convertToReward(itemNow) - if (uncoveredItems.none { it.first == slot }) uncoveredItems.add(Pair(slot, reward)) - - when { - isPowerUp(reward) -> handlePowerUp(slot, reward) - isReward(itemName) -> handleReward(slot, uncovered, reward) - } - - possiblePairs = calculatePossiblePairs() - - val since = clicksSinceSeparator(lastClicked) - - if ((since >= 2 || (since == -1 && lastClicked.size >= 2)) && instantFind == 0) { - lastClicked.add(-1 to uncoveredAt) - uncoveredAt += 1 - } - toCheck.removeIf { it.first == slot } - - return drawDisplay() - } - possiblePairs = calculatePossiblePairs() - return drawDisplay() - } - - private fun handlePowerUp(slot: Int, reward: String) { - val item = toEither(Item(slot, reward)) - - found[item] = "Powerup" - possiblePairs-- - lastClicked.removeIf { it.first == slot } - uncoveredAt -= 1 - if (reward == "Instant Find") instantFind += 1 - } - - private fun handleReward(slot: Int, uncovered: Int, reward: String) { - val lastSlotClicked = - if (instantFind == 0 && lastClicked.none { it.first == -1 && it.second == uncovered - 1 } && lastClicked.size != 1) lastClicked.find { it.second == uncovered - 1 } - ?: return else lastClicked.find { it.second == uncovered } ?: return - - val lastItem = InventoryUtils.getItemAtSlotIndex(lastSlotClicked.first) ?: return - val itemClicked = InventoryUtils.getItemAtSlotIndex(slot) ?: return - - val lastItemName = convertToReward(lastItem) - - if (isWaiting(lastItemName)) return - - when { - instantFind >= 1 -> { - handleFoundPair(slot, reward, lastSlotClicked.first) - instantFind -= 1 - lastClicked.add(-1 to uncoveredAt) - uncoveredAt += 1 - } - - hasFoundPair(slot, lastSlotClicked.first, reward, lastItemName) && lastItem.itemDamage == itemClicked.itemDamage -> handleFoundPair( - slot, - reward, - lastSlotClicked.first, - ) - - hasFoundMatch(slot, reward) -> handleFoundMatch(slot, reward) - else -> handleNormalReward(slot, reward) - } - - } - - private fun handleFoundPair( - slot: Int, - reward: String, - lastSlotClicked: Int, - ) { - val pair = toEither(ItemPair(Item(slot, reward), Item(lastSlotClicked, reward))) - - found[pair] = "Pair" - found.entries.removeIf { - it.value == "Match" && right(it.key).first.index == slot - } - found.entries.removeIf { - it.value == "Normal" && (left(it.key).index == slot || left(it.key).index == lastSlotClicked) - } - } - - private fun handleFoundMatch(slot: Int, reward: String) { - val match = uncoveredItems.find { it.second == reward }?.first ?: return - val pair = toEither(ItemPair(Item(slot, reward), Item(match, reward))) - - if (found.none { - listOf("Pair", "Match").contains(it.value) && (right(it.key).first.index == slot) - }) found[pair] = "Match" - found.entries.removeIf { it.value == "Normal" && (left(it.key).index == slot || left(it.key).index == match) } - } - - private fun handleNormalReward(slot: Int, reward: String) { - val item = toEither(Item(slot, reward)) - - if (found.none { - listOf("Match", "Pair").contains(it.value) && (right(it.key).first.index == slot || right(it.key).second.index == slot) - } && found.none { it.value == "Normal" && left(it.key).index == slot }) found[item] = "Normal" - } - - private fun calculatePossiblePairs() = - ((currentExperiment.gridSize - 2) / 2) - found.filter { listOf("Pair", "Match", "Normal").contains(it.value) }.size - - private fun drawDisplay() = buildList { - add("§6Superpair Experimentation Data") - add("") - - val pairs = found.entries.filter { it.value == "Pair" } - val matches = found.entries.filter { it.value == "Match" } - val powerups = found.entries.filter { it.value == "Powerup" } - val normals = found.entries.filter { it.value == "Normal" } - - if (pairs.isNotEmpty()) add("§2Found") - for (pair in pairs) { - val prefix = determinePrefix(pairs.indexOf(pair), pairs.lastIndex) - add(" $prefix §a${right(pair.key).first.name}") - } - if (matches.isNotEmpty()) add("§eMatched") - for (match in matches) { - val prefix = determinePrefix(matches.indexOf(match), matches.lastIndex) - add(" $prefix §e${right(match.key).first.name}") - } - if (powerups.isNotEmpty()) add("§bPowerUp") - for (powerup in powerups) { - val prefix = determinePrefix(powerups.indexOf(powerup), powerups.size - 1) - add(" $prefix §b${left(powerup.key).name}") - } - val toAdd = mutableListOf() - if (possiblePairs >= 1) toAdd.add("§ePairs - $possiblePairs") - if (2 - powerups.size >= 1) toAdd.add("§bPowerUps - ${2 - powerups.size}") - if (normals.isNotEmpty()) toAdd.add("§7Normals - ${normals.size}") - - if (toAdd.isNotEmpty()) { - add("") - add("§4Not found") - } - for (string in toAdd) if (string != toAdd.last()) add(" ├ $string") else add(" └ $string") - } - - private fun convertToReward(item: ItemStack) = if (item.displayName.removeColor() == "Enchanted Book") item.getLore()[2].removeColor() - else item.displayName.removeColor() - - private fun determinePrefix(index: Int, lastIndex: Int) = if (index == lastIndex) "└" else "├" - - private fun hasFoundPair( - firstSlot: Int, - secondSlot: Int, - firstName: String, - secondName: String, - ) = firstSlot != secondSlot && firstName == secondName - - private fun hasFoundMatch(itemSlot: Int, reward: String) = - uncoveredItems.any { (slot, name) -> slot != itemSlot && name == reward } && found.none { - listOf("Pair", "Match").contains(it.value) && (right(it.key).first.index == itemSlot || right(it.key).second.index == itemSlot) - } - - private fun isPowerUp(reward: String) = ExperimentationTableAPI.powerUpPattern.matches(reward) - - private fun isReward(reward: String) = ExperimentationTableAPI.rewardPattern.matches(reward) - - private fun isWaiting(itemName: String) = - listOf("Click any button!", "Click a second button!", "Next button is instantly rewarded!").contains(itemName) - - private fun clicksSinceSeparator(list: MutableList>): Int { - val lastIndex = list.indexOfLast { it.first == -1 } - return if (lastIndex != -1) list.size - 1 - lastIndex else -1 - } - - private fun isOutOfBounds(slot: Int, experiment: Experiment): Boolean = - slot <= experiment.startSlot || slot >= experiment.endSlot || (if (experiment.sideSpace == 1) slot in sideSpaces1 else slot in sideSpaces2) - - // TODO remove left and right, use custom data type instead - private fun left(it: Pair): Item = it.first ?: Item(-1, "") - - private fun right(it: Pair): ItemPair = it.second ?: ItemPair(Item(-1, ""), Item(-1, "")) - - private fun toEither(it: Any): Pair = if (it is Item) it to null else null to it as ItemPair - - private fun isEnabled() = LorenzUtils.inSkyBlock && config.superpairDisplay && ExperimentationTableAPI.getCurrentExperiment() != null -} diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairsClicksAlert.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairsClicksAlert.kt index ef99c40bab97..379d3aa50a71 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairsClicksAlert.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/experimentationtable/SuperpairsClicksAlert.kt @@ -47,15 +47,7 @@ object SuperpairsClicksAlert { if (!targetInventoryNames.any { event.inventoryName.contains(it) }) return if ( // checks if we have succeeded in either minigame - (event.inventoryName.contains("Chronomatron") - && ((event.inventoryItems[4]?.displayName?.removeColor() - ?.let { currentRoundRegex.find(it) } - ?.groups?.get(1)?.value?.toInt() ?: -1) > roundsNeeded)) - - || (event.inventoryName.contains("Ultrasequencer") - && event.inventoryItems.entries - .filter { it.key < 45 } - .any { it.value.stackSize > roundsNeeded }) + isChronomatron(event) || isUltraSequencer(event) ) { SoundUtils.playBeepSound() ChatUtils.chat("You have reached the maximum extra Superpairs clicks from this add-on!") @@ -63,6 +55,22 @@ object SuperpairsClicksAlert { } } + private fun isChronomatron(event: InventoryOpenEvent) = + event.inventoryName.contains("Chronomatron") && + ( + ( + event.inventoryItems[4]?.displayName?.removeColor()?.let { + currentRoundRegex.find(it) + }?.groups?.get(1)?.value?.toInt() ?: -1 + ) > roundsNeeded + ) + + private fun isUltraSequencer(event: InventoryUpdatedEvent) = + event.inventoryName.contains("Ultrasequencer") && + event.inventoryItems.entries + .filter { it.key < 45 } + .any { it.value.stackSize > roundsNeeded } + @SubscribeEvent fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { event.move(46, "misc.superpairsClicksAlert", "inventory.helper.enchanting.superpairsClicksAlert") diff --git a/src/main/java/at/hannibal2/skyhanni/features/itemabilities/CrownOfAvariceCounter.kt b/src/main/java/at/hannibal2/skyhanni/features/itemabilities/CrownOfAvariceCounter.kt index 207e1b92b6a1..df408133a136 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/itemabilities/CrownOfAvariceCounter.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/itemabilities/CrownOfAvariceCounter.kt @@ -40,7 +40,7 @@ object CrownOfAvariceCounter { if (!config.enable) return null val item = InventoryUtils.getHelmet() if (item?.getInternalNameOrNull() != internalName) return null - val count = item.extraAttributes.getLong("collected_coins"); + val count = item.extraAttributes.getLong("collected_coins") return Renderable.horizontalContainer( listOf( Renderable.itemStack(internalName.getItemStack()), diff --git a/src/main/java/at/hannibal2/skyhanni/features/itemabilities/FireVeilWandParticles.kt b/src/main/java/at/hannibal2/skyhanni/features/itemabilities/FireVeilWandParticles.kt index 81477957e4cd..5923433d1b36 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/itemabilities/FireVeilWandParticles.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/itemabilities/FireVeilWandParticles.kt @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.features.itemabilities import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.config.features.itemability.FireVeilWandConfig.DisplayEntry import at.hannibal2.skyhanni.data.ClickType @@ -39,9 +40,8 @@ object FireVeilWandParticles { } } - @SubscribeEvent + @HandleEvent(onlyOnSkyblock = true) fun onItemClick(event: ItemClickEvent) { - if (!LorenzUtils.inSkyBlock) return if (event.clickType != ClickType.RIGHT_CLICK) return val internalName = event.itemInHand?.getInternalName() diff --git a/src/main/java/at/hannibal2/skyhanni/features/itemabilities/abilitycooldown/ItemAbility.kt b/src/main/java/at/hannibal2/skyhanni/features/itemabilities/abilitycooldown/ItemAbility.kt index 020feba76976..6bc24f055ada 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/itemabilities/abilitycooldown/ItemAbility.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/itemabilities/abilitycooldown/ItemAbility.kt @@ -29,6 +29,8 @@ enum class ItemAbility( ATOMSPLIT_KATANA(4, "VORPAL_KATANA", "VOIDEDGE_KATANA", ignoreMageCooldownReduction = true), RAGNAROCK_AXE(20), WAND_OF_ATONEMENT(7, "WAND_OF_HEALING", "WAND_OF_MENDING", "WAND_OF_RESTORATION"), + SOS_FLARE(10), + ALERT_FLARE(20, "WARNING_FLARE"), GOLEM_SWORD(3), END_STONE_SWORD(5), @@ -50,6 +52,8 @@ enum class ItemAbility( ROYAL_PIGEON(5), WAND_OF_STRENGTH(10), TACTICAL_INSERTION(20), + TOTEM_OF_CORRUPTION(20), + ENRAGER(20), // doesn't have a sound ENDER_BOW("Ender Warp", 5, "Ender Bow"), @@ -75,7 +79,7 @@ enum class ItemAbility( cooldownInSeconds, actionBarDetection = false, alternativePosition = alternativePosition, - ignoreMageCooldownReduction = ignoreMageCooldownReduction + ignoreMageCooldownReduction = ignoreMageCooldownReduction, ) { newVariant = true alternateInternalNames.forEach { diff --git a/src/main/java/at/hannibal2/skyhanni/features/itemabilities/abilitycooldown/ItemAbilityCooldown.kt b/src/main/java/at/hannibal2/skyhanni/features/itemabilities/abilitycooldown/ItemAbilityCooldown.kt index 5748220c5e38..fb15bd703a44 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/itemabilities/abilitycooldown/ItemAbilityCooldown.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/itemabilities/abilitycooldown/ItemAbilityCooldown.kt @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.features.itemabilities.abilitycooldown import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.events.ActionBarUpdateEvent import at.hannibal2.skyhanni.events.ItemClickEvent @@ -44,19 +45,25 @@ object ItemAbilityCooldown { private val patternGroup = RepoPattern.group("item.abilities.cooldown") private val youAlignedOthersPattern by patternGroup.pattern( "alignedother", - "§eYou aligned §r§a.* §r§eother player(s)?!" + "§eYou aligned §r§a.* §r§eother player(s)?!", ) private val youBuffedYourselfPattern by patternGroup.pattern( "buffedyourself", - "§aYou buffed yourself for §r§c\\+\\d+❁ Strength" + "§aYou buffed yourself for §r§c\\+\\d+❁ Strength", ) private var lastAbility = "" private var items = mapOf>() private var abilityItems = mapOf>() + private val recentItemsInHand = InventoryUtils.recentItemsInHand.values private val WEIRD_TUBA = "WEIRD_TUBA".asInternalName() private val WEIRDER_TUBA = "WEIRDER_TUBA".asInternalName() private val VOODOO_DOLL_WILTED = "VOODOO_DOLL_WILTED".asInternalName() + private val WARNING_FLARE = "WARNING_FLARE".asInternalName() + private val ALERT_FLARE = "ALERT_FLARE".asInternalName() + private val SOS_FLARE = "SOS_FLARE".asInternalName() + private val TOTEM_OF_CORRUPTION = "TOTEM_OF_CORRUPTION".asInternalName() + @SubscribeEvent fun onPlaySound(event: PlaySoundEvent) { @@ -87,7 +94,7 @@ object ItemAbilityCooldown { val internalName = InventoryUtils.getItemInHand()?.getInternalName() ?: return if (!internalName.equalsOneOf( "SHADOW_FURY".asInternalName(), - "STARRED_SHADOW_FURY".asInternalName() + "STARRED_SHADOW_FURY".asInternalName(), ) ) return @@ -175,7 +182,7 @@ object ItemAbilityCooldown { event.soundName == "mob.bat.idle" && event.pitch == 0.4920635f && event.volume == 1.0f -> { ItemAbility.ROYAL_PIGEON.sound() } - + // Wand of Strength event.soundName == "random.eat" && event.pitch == 0.4920635f && event.volume == 1.0f -> { ItemAbility.WAND_OF_STRENGTH.sound() } @@ -183,13 +190,34 @@ object ItemAbilityCooldown { event.soundName == "fire.ignite" && event.pitch == 0.74603176f && event.volume == 1.0f -> { ItemAbility.TACTICAL_INSERTION.activate(LorenzColor.DARK_PURPLE, 3_000) } + event.soundName == "mob.zombie.remedy" && event.pitch == 1.8888888f && event.volume == 0.7f -> { ItemAbility.TACTICAL_INSERTION.activate(null, 17_000) } + // Totem of Corruption + event.soundName == "random.wood_click" && event.pitch == 0.84126985f && event.volume == 0.5f -> { + if (TOTEM_OF_CORRUPTION in recentItemsInHand) { + ItemAbility.TOTEM_OF_CORRUPTION.sound() + } + } + // Enrager + event.soundName == "mob.enderdragon.growl" && event.pitch == 0.4920635f && event.volume == 2.0f -> { + ItemAbility.ENRAGER.sound() + } + + // Blaze Slayer Flares + event.soundName == "fireworks.launch" && event.pitch == 1.0f && event.volume == 3.0f -> { + if (WARNING_FLARE in recentItemsInHand || ALERT_FLARE in recentItemsInHand) { + ItemAbility.ALERT_FLARE.sound() + } + if (SOS_FLARE in recentItemsInHand) { + ItemAbility.SOS_FLARE.sound() + } + } } } - @SubscribeEvent + @HandleEvent fun onItemClick(event: ItemClickEvent) { if (AshfangFreezeCooldown.isCurrentlyFrozen()) return handleItemClick(event.itemInHand) @@ -276,7 +304,7 @@ object ItemAbilityCooldown { items = abilityItems.entries.associateByTo( mutableMapOf(), { it.key.getIdentifier() }, - { kp -> kp.value.map { createItemText(it) } } + { kp -> kp.value.map { createItemText(it) } }, ).mapKeysNotNull { it.key } } @@ -364,8 +392,8 @@ object ItemAbilityCooldown { if (message == "§dCreeper Veil §r§aActivated!") { ItemAbility.WITHER_CLOAK.activate(LorenzColor.LIGHT_PURPLE) } - if (message == "§dCreeper Veil §r§cDe-activated! §r§8(Expired)" - || message == "§cNot enough mana! §r§dCreeper Veil §r§cDe-activated!" + if (message == "§dCreeper Veil §r§cDe-activated! §r§8(Expired)" || + message == "§cNot enough mana! §r§dCreeper Veil §r§cDe-activated!" ) { ItemAbility.WITHER_CLOAK.activate() } diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/HighlightMiningCommissionMobs.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/HighlightMiningCommissionMobs.kt index cc9f6b7534ba..071c905d53f5 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/HighlightMiningCommissionMobs.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/HighlightMiningCommissionMobs.kt @@ -53,7 +53,6 @@ object HighlightMiningCommissionMobs { CH_GOBLIN_SLAYER("Goblin Slayer", { it.name == "Weakling " }), // new commissions - ; } @SubscribeEvent @@ -67,8 +66,7 @@ object HighlightMiningCommissionMobs { RenderLivingEntityHelper.setEntityColorWithNoHurtTime( entity, LorenzColor.YELLOW.toColor().withAlpha(127) - ) - { isEnabled() && type in active } + ) { isEnabled() && type in active } } } } @@ -99,8 +97,7 @@ object HighlightMiningCommissionMobs { RenderLivingEntityHelper.setEntityColorWithNoHurtTime( entity, LorenzColor.YELLOW.toColor().withAlpha(127) - ) - { isEnabled() && type in active } + ) { isEnabled() && type in active } } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/KingTalismanHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/KingTalismanHelper.kt index 94b292fdf511..b9f205984f38 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/KingTalismanHelper.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/KingTalismanHelper.kt @@ -2,9 +2,11 @@ package at.hannibal2.skyhanni.features.mining import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.data.IslandType +import at.hannibal2.skyhanni.data.MiningAPI 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.SecondPassedEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils @@ -16,6 +18,7 @@ import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland import at.hannibal2.skyhanni.utils.LorenzVec import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.RegexUtils.matches import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings import at.hannibal2.skyhanni.utils.SkyBlockTime import at.hannibal2.skyhanni.utils.TimeUtils.format @@ -31,11 +34,27 @@ object KingTalismanHelper { private val config get() = SkyHanniMod.feature.mining.kingTalisman private val storage get() = ProfileStorageData.profileSpecific?.mining - private val kingPattern by RepoPattern.pattern( - "mining.kingtalisman.king", + private val patternGroup = RepoPattern.group("mining.kingtalisman") + + /** + * REGEX-TEST: §6§lKing Brammor + * REGEX-TEST: §6§lKing Emkam + * REGEX-TEST: §6§lKing Kevin + * REGEX-TEST: §6§lKing Redros + */ + private val kingPattern by patternGroup.pattern( + "king", "§6§lKing (?.*)" ) + /** + * REGEX-TEST: §7You have received a §r§fKing Talisman§r§7! + */ + private val talismanPattern by patternGroup.pattern( + "talisman", + "§7You have received a §r§fKing Talisman§r§7!" + ) + private var currentOffset: Int? = null private var skyblockYear = 0 @@ -66,7 +85,8 @@ object KingTalismanHelper { private var farDisplay = "" private var display = emptyList() - private fun isNearby() = IslandType.DWARVEN_MINES.isInIsland() && LorenzUtils.skyBlockArea == "Royal Palace" && + private fun isNearby() = IslandType.DWARVEN_MINES.isInIsland() && + LorenzUtils.skyBlockArea == "Royal Palace" && kingLocation.distanceToPlayer() < 10 @SubscribeEvent @@ -86,7 +106,7 @@ object KingTalismanHelper { return } - update(kingsTalkedTo) + update() display = if (nearby) allKingsDisplay else Collections.singletonList(farDisplay) } @@ -103,8 +123,9 @@ object KingTalismanHelper { skyblockYear = SkyBlockTime.now().year } - fun isEnabled() = config.enabled && LorenzUtils.inSkyBlock - && (IslandType.DWARVEN_MINES.isInIsland() || config.outsideMines) + fun isEnabled() = config.enabled && + LorenzUtils.inSkyBlock && + (IslandType.DWARVEN_MINES.isInIsland() || config.outsideMines) @SubscribeEvent fun onInventoryOpen(event: InventoryFullyOpenedEvent) { @@ -118,12 +139,13 @@ object KingTalismanHelper { val kingsTalkedTo = storage.kingsTalkedTo if (currentKing !in kingsTalkedTo) { kingsTalkedTo.add(currentKing) - update(kingsTalkedTo) + update() display = allKingsDisplay } } - private fun update(kingsTalkedTo: MutableList) { + private fun update() { + val kingsTalkedTo = storage?.kingsTalkedTo ?: return if (kingsTalkedTo.size == kingCircles.size) { allKingsDisplay = Collections.singletonList("§eAll Kings found.") farDisplay = "" @@ -198,4 +220,15 @@ object KingTalismanHelper { config.position.renderStrings(display, posLabel = "King Talisman Helper") } + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + if (!isEnabled()) return + if (!MiningAPI.inDwarvenMines) return + + if (talismanPattern.matches(event.message)) { + storage?.kingsTalkedTo = kingCircles.toMutableList() + update() + } + } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/MineshaftPityDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/MineshaftPityDisplay.kt index 4415b59f5872..79d838f20c97 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/MineshaftPityDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/MineshaftPityDisplay.kt @@ -45,11 +45,11 @@ object MineshaftPityDisplay { profileStorage?.blocksBroken = value } - private var PityBlock.efficientMiner: Int - get() = minedBlocks.firstOrNull { it.pityBlock == this }?.efficientMiner ?: 0 + private var PityBlock.spreadBlocksBroken: Int + get() = minedBlocks.firstOrNull { it.pityBlock == this }?.spreadBlocksBroken ?: 0 set(value) { - minedBlocks.firstOrNull { it.pityBlock == this }?.let { it.efficientMiner = value } ?: run { - minedBlocks.add(PityData(this, efficientMiner = value)) + minedBlocks.firstOrNull { it.pityBlock == this }?.let { it.spreadBlocksBroken = value } ?: run { + minedBlocks.add(PityData(this, spreadBlocksBroken = value)) } } @@ -92,7 +92,7 @@ object MineshaftPityDisplay { if (originalOre != null) addOrPut(originalOre, -1) } .map { (block, amount) -> - block.getPityBlock()?.let { it.efficientMiner += amount } + block.getPityBlock()?.let { it.spreadBlocksBroken += amount } } update() @@ -105,7 +105,7 @@ object MineshaftPityDisplay { val pityCounter = calculateCounter() val chance = calculateChance(pityCounter) val counterUntilPity = MAX_COUNTER - pityCounter - val totalBlocks = PityBlock.entries.sumOf { it.blocksBroken + it.efficientMiner } + val totalBlocks = PityBlock.entries.sumOf { it.blocksBroken + it.spreadBlocksBroken } mineshaftTotalBlocks += totalBlocks mineshaftTotalCount++ @@ -124,7 +124,7 @@ object MineshaftPityDisplay { minedBlocks.forEach { add( " §7${it.pityBlock.displayName} mined: " + - "§e${it.blocksBroken.addSeparators()} [+${it.efficientMiner.addSeparators()} efficient miner]" + + "§e${it.blocksBroken.addSeparators()} [+${it.spreadBlocksBroken.addSeparators()} spread]" + " §6(${it.pityBlock.getPity().addSeparators()}/${counterUntilPity.addSeparators()})", ) } @@ -283,7 +283,7 @@ object MineshaftPityDisplay { data class PityData( @Expose val pityBlock: PityBlock, @Expose var blocksBroken: Int = 0, - @Expose var efficientMiner: Int = 0, + @Expose var spreadBlocksBroken: Int = 0, ) enum class PityBlock( @@ -301,11 +301,6 @@ object MineshaftPityDisplay { GEMSTONE( "Gemstone", - /*listOf( - OreType.RUBY, OreType.AMBER, OreType.AMETHYST, OreType.JADE, - OreType.SAPPHIRE, OreType.TOPAZ, OreType.JASPER, OreType.OPAL, - OreType.AQUAMARINE, OreType.CITRINE, OreType.ONYX, OreType.PERIDOT, - ),*/ OreType.entries.filter { it.isGemstone() }, 4, ItemStack(Blocks.stained_glass, 1, EnumDyeColor.BLUE.metadata), @@ -344,7 +339,7 @@ object MineshaftPityDisplay { return entries.firstOrNull { oreType in it.oreTypes } } - fun PityBlock.getPity() = (blocksBroken + efficientMiner / 2.0) * multiplier + fun PityBlock.getPity() = (blocksBroken + spreadBlocksBroken / 2.0) * multiplier } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/OreBlock.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/OreBlock.kt index 4275a809ca92..a9e1c18920ac 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/OreBlock.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/OreBlock.kt @@ -117,7 +117,7 @@ enum class OreBlock( checkArea = { inSpidersDen }, ), - //END + // END END_STONE( checkBlock = { it.block == Blocks.end_stone }, checkArea = { inEnd }, diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/PrecisionMiningHighlight.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/PrecisionMiningHighlight.kt new file mode 100644 index 000000000000..462a963489ab --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/PrecisionMiningHighlight.kt @@ -0,0 +1,69 @@ +package at.hannibal2.skyhanni.features.mining + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.MiningAPI +import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent +import at.hannibal2.skyhanni.events.LorenzTickEvent +import at.hannibal2.skyhanni.events.ReceiveParticleEvent +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.RenderUtils.drawFilledBoundingBox_nea +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.SimpleTimeMark.Companion.fromNow +import at.hannibal2.skyhanni.utils.TimeUtils.ticks +import at.hannibal2.skyhanni.utils.toLorenzVec +import net.minecraft.client.Minecraft +import net.minecraft.util.AxisAlignedBB +import net.minecraft.util.EnumParticleTypes +import net.minecraft.util.MovingObjectPosition +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import java.awt.Color + +@SkyHanniModule +object PrecisionMiningHighlight { + + private val config get() = SkyHanniMod.feature.mining.highlightPrecisionMiningParticles + + private var lastParticle: AxisAlignedBB? = null + private var lookingAtParticle: Boolean = false + private var deleteTime: SimpleTimeMark? = null + + @SubscribeEvent + fun onParticle(event: ReceiveParticleEvent) { + if (!isEnabled()) return + if (!(event.type == EnumParticleTypes.CRIT || event.type == EnumParticleTypes.VILLAGER_HAPPY) || + !Minecraft.getMinecraft().gameSettings.keyBindAttack.isKeyDown) return + + val mouseOverObject = Minecraft.getMinecraft().objectMouseOver + if (mouseOverObject.typeOfHit != MovingObjectPosition.MovingObjectType.BLOCK) return + + val particleBoundingBox = event.location.add(-0.12, -0.12, -0.12) + .axisAlignedTo(event.location.clone().add(0.12, 0.12, 0.12)) + + val blockBoundingBox = mouseOverObject.blockPos.toLorenzVec() + .axisAlignedTo(mouseOverObject.blockPos.add(1, 1, 1).toLorenzVec()) + if (!blockBoundingBox.intersectsWith(particleBoundingBox)) return + + lookingAtParticle = event.type == EnumParticleTypes.VILLAGER_HAPPY + lastParticle = particleBoundingBox + deleteTime = 5.ticks.fromNow() + } + + @SubscribeEvent + fun onRender(event: LorenzRenderWorldEvent) { + val particleBoundingBox = lastParticle ?: return + + event.drawFilledBoundingBox_nea(particleBoundingBox, if (lookingAtParticle) Color.GREEN else Color.CYAN) + } + + @SubscribeEvent + fun onTick(event: LorenzTickEvent) { + lastParticle ?: return + val deletionTime = deleteTime ?: return + if (deletionTime.isInPast()) { + deleteTime = null + lastParticle = null + } + } + + fun isEnabled() = MiningAPI.inCustomMiningIsland() && config +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/TunnelsMaps.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/TunnelsMaps.kt index 5214ff162eb5..2d7487ddcb15 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/TunnelsMaps.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/TunnelsMaps.kt @@ -1,12 +1,11 @@ package at.hannibal2.skyhanni.features.mining import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.data.ClickType import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.data.model.Graph import at.hannibal2.skyhanni.data.model.GraphNode -import at.hannibal2.skyhanni.data.model.findShortestDistance -import at.hannibal2.skyhanni.data.model.findShortestPathAsGraphWithDistance import at.hannibal2.skyhanni.events.ConfigLoadEvent import at.hannibal2.skyhanni.events.GuiContainerEvent import at.hannibal2.skyhanni.events.GuiRenderEvent @@ -28,6 +27,7 @@ import at.hannibal2.skyhanni.utils.ColorUtils.getFirstColorCode import at.hannibal2.skyhanni.utils.ColorUtils.toChromaColor import at.hannibal2.skyhanni.utils.ConditionalUtils.onToggle import at.hannibal2.skyhanni.utils.DelayedRun +import at.hannibal2.skyhanni.utils.GraphUtils import at.hannibal2.skyhanni.utils.HypixelCommands import at.hannibal2.skyhanni.utils.ItemUtils.getInternalNameOrNull import at.hannibal2.skyhanni.utils.ItemUtils.getLore @@ -73,7 +73,7 @@ object TunnelsMaps { field = value } - private var closedNote: GraphNode? = null + private var closestNode: GraphNode? = null private var path: Pair? = null private var possibleLocations = mapOf>() @@ -81,6 +81,7 @@ object TunnelsMaps { private var active: String = "" private lateinit var fairySouls: Map + // TODO what is this? why is there a difference? can this be replaced with GraphNodeTag.GRIND_ORES? private lateinit var newGemstones: Map> private lateinit var oldGemstones: Map> @@ -94,11 +95,11 @@ object TunnelsMaps { return it } - val closed = closedNote ?: return null + val closest = closestNode ?: return null val list = possibleLocations[name] ?: return null val offCooldown = list.filter { cooldowns[it]?.isInPast() != false } - val best = offCooldown.minByOrNull { graph.findShortestDistance(closed, it) } ?: list.minBy { + val best = offCooldown.minByOrNull { GraphUtils.findShortestDistance(closest, it) } ?: list.minBy { cooldowns[it] ?: SimpleTimeMark.farPast() } if (cooldowns[best]?.isInPast() != false) { @@ -249,7 +250,8 @@ object TunnelsMaps { this.oldGemstones = oldGemstone normalLocations = other translateTable.clear() - DelayedRun.runNextTick { // Needs to be delayed since the config may not be loaded + DelayedRun.runNextTick { + // Needs to be delayed since the config may not be loaded locationDisplay = generateLocationsDisplay() } } @@ -329,7 +331,7 @@ object TunnelsMaps { Renderable.horizontalContainer( listOf(Renderable.string("§dFairy Souls")) + fairySouls.map { val name = it.key.removePrefix("§dFairy Soul ") - Renderable.clickable(Renderable.string("§d[${name}]"), onClick = guiSetActive(it.key)) + Renderable.clickable(Renderable.string("§d[$name]"), onClick = guiSetActive(it.key)) }, ), Renderable.string("§dFairy Souls"), @@ -365,9 +367,11 @@ object TunnelsMaps { private fun toCompactGemstoneName(it: Map.Entry>): Renderable = Renderable.clickAndHover( Renderable.string( - (it.key.getFirstColorCode()?.let { "§$it" } ?: "") + ("ROUGH_".plus( - it.key.removeColor().removeSuffix("stone"), - ).asInternalName().itemName.takeWhile { it != ' ' }.removeColor()), + (it.key.getFirstColorCode()?.let { "§$it" } ?: "") + ( + "ROUGH_".plus( + it.key.removeColor().removeSuffix("stone"), + ).asInternalName().itemName.takeWhile { it != ' ' }.removeColor() + ), horizontalAlign = RenderUtils.HorizontalAlignment.CENTER, ), tips = listOf(it.key), @@ -393,12 +397,12 @@ object TunnelsMaps { fun onTick(event: LorenzTickEvent) { if (!isEnabled()) return if (checkGoalReached()) return - val prevClosed = closedNote - closedNote = graph.minBy { it.position.distanceSqToPlayer() } - val closest = closedNote ?: return + val prevclosest = closestNode + closestNode = graph.minBy { it.position.distanceSqToPlayer() } + val closest = closestNode ?: return val goal = goal ?: return - if (closest == prevClosed && goal == prevGoal) return - val (path, distance) = graph.findShortestPathAsGraphWithDistance(closest, goal) + if (closest == prevclosest && goal == prevGoal) return + val (path, distance) = GraphUtils.findShortestPathAsGraphWithDistance(closest, goal) val first = path.firstOrNull() val second = path.getOrNull(1) @@ -453,7 +457,7 @@ object TunnelsMaps { true, bezierPoint = 2.0, textSize = config.textSize.toDouble(), - showNoteNames = true, + showNodeNames = true, ) event.drawDynamicText( if (config.distanceFirst) { @@ -481,7 +485,7 @@ object TunnelsMaps { nextSpotKey(event) } - @SubscribeEvent + @HandleEvent fun onItemClick(event: ItemClickEvent) { if (!isEnabled() || !config.leftClickPigeon) return if (event.clickType != ClickType.LEFT_CLICK) return @@ -510,8 +514,8 @@ object TunnelsMaps { @SubscribeEvent fun onIslandChange(event: IslandChangeEvent) { - if (closedNote == null) return // Value that must be none null if it was active - closedNote = null + if (closestNode == null) return // Value that must be none null if it was active + closestNode = null clearPath() cooldowns.clear() goalReached = false diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/eventtracker/MiningEventTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/eventtracker/MiningEventTracker.kt index a076ba68f0c3..d5ee14ec92e3 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/eventtracker/MiningEventTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/eventtracker/MiningEventTracker.kt @@ -200,7 +200,8 @@ object MiningEventTracker { canRequestAt = SimpleTimeMark.now() + 20.minutes if (LorenzUtils.debug) { ErrorManager.logErrorWithData( - e, "Receiving mining event data was unsuccessful", + e, + "Failed to load Mining Event data!", ) } return@launch @@ -208,11 +209,17 @@ object MiningEventTracker { val miningEventData = ConfigManager.gson.fromJson(data, MiningEventDataReceive::class.java) if (!miningEventData.success) { - ErrorManager.logErrorWithData( - Exception("PostFailure"), "Receiving mining event data was unsuccessful", - "cause" to miningEventData.cause, - "recievedData" to data - ) + if (data.toString() == "{}") { + ChatUtils.chat("§cFailed loading Mining Event data!\n" + + "Please wait until the server problem fixes itself! There is nothing else to do at the moment.") + } else { + ErrorManager.logErrorWithData( + Exception("miningEventData.success = false"), + "Failed to load Mining Event data!", + "cause" to miningEventData.cause, + "recievedData" to data + ) + } return@launch } apiErrorCount = 0 diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/fossilexcavator/solver/FossilSolverDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/fossilexcavator/solver/FossilSolverDisplay.kt index cb50e3c85459..f9dd9b8db316 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/fossilexcavator/solver/FossilSolverDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/fossilexcavator/solver/FossilSolverDisplay.kt @@ -188,7 +188,7 @@ object FossilSolverDisplay { if (inExcavatorMenu) { // Render here so they can move it around. As if you press key while doing the excavator you lose the scrap - config.position.renderString("§eExcavator solver gui", posLabel = "Fossil Excavator Solver") + config.position.renderString("§eExcavator solver GUI", posLabel = "Fossil Excavator Solver") return } diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/CorpseLocator.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/CorpseLocator.kt index 3ea9ee4b14ec..6ec32fd2e129 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/CorpseLocator.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/CorpseLocator.kt @@ -59,7 +59,7 @@ object CorpseLocator { MineshaftWaypoints.waypoints.add( MineshaftWaypoint( waypointType = corpseType, - location = entity.getLorenzVec().add(y = 1), + location = entity.getLorenzVec().up(), isCorpse = true, ), ) diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/CorpseTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/CorpseTracker.kt index 3e81a01a9588..bc5e324401bb 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/CorpseTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/CorpseTracker.kt @@ -45,7 +45,11 @@ object CorpseTracker { } override fun getDescription(timesGained: Long): List { - val divisor = 1.coerceAtLeast(getSelectedBucket()?.let { corpsesLooted[it]?.toInt() } ?: corpsesLooted.sumAllValues().toInt()) + val divisor = 1.coerceAtLeast( + getSelectedBucket()?.let { + corpsesLooted[it]?.toInt() + } ?: corpsesLooted.sumAllValues().toInt() + ) val percentage = timesGained.toDouble() / divisor val dropRate = LorenzUtils.formatPercentage(percentage.coerceAtMost(1.0)) return listOf( @@ -85,7 +89,9 @@ object CorpseTracker { if (bucketData.getCorpseCount() == 0L) return@buildList var profit = tracker.drawItems(bucketData, { true }, this) - val applicableKeys: List = bucketData.getSelectedBucket()?.let { listOf(it) } ?: enumValues().toList() + val applicableKeys: List = bucketData.getSelectedBucket()?.let { + listOf(it) + } ?: enumValues().toList() .filter { bucketData.corpsesLooted[it] != null } var totalKeyCost = 0.0 var totalKeyCount = 0 diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/MineshaftWaypoints.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/MineshaftWaypoints.kt index ae17e783bb16..2c05e35251ae 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/MineshaftWaypoints.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/glacitemineshaft/MineshaftWaypoints.kt @@ -9,9 +9,9 @@ import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.HypixelCommands -import at.hannibal2.skyhanni.utils.LocationUtils import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland +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.SimpleTimeMark @@ -38,7 +38,7 @@ object MineshaftWaypoints { fun onIslandChange(event: IslandChangeEvent) { if (event.newIsland != IslandType.MINESHAFT) return - val playerLocation = LocationUtils.playerLocation().roundTo(0).add(y = -1) + val playerLocation = LorenzVec.getBlockBelowPlayer() if (config.mineshaftWaypoints.entranceLocation) { waypoints.add(MineshaftWaypoint(waypointType = MineshaftWaypointType.ENTRANCE, location = playerLocation)) diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/powdertracker/PowderChestReward.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/powdertracker/PowderChestReward.kt index b2b449563a5f..ac824abd38f8 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/powdertracker/PowderChestReward.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/powdertracker/PowderChestReward.kt @@ -4,10 +4,6 @@ import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern enum class PowderChestReward(val displayName: String, pattern: String) { - MITHRIL_POWDER( - "§aMithril Powder", - " {4}§r§2Mithril Powder(?: §r§8x(?.*))?", - ), GEMSTONE_POWDER( "§dGemstone Powder", " {4}§r§dGemstone Powder(?: §r§8x(?.*))?", @@ -119,6 +115,8 @@ enum class PowderChestReward(val displayName: String, pattern: String) { "§9FTX 3070", " {4}§r§9FTX 3070(?: §r§8x(?.*))?", ), + + // TODO: Fix typo ELECTRON_TRANSIMTTER( "§9Electron Transmitter", " {4}§r§9Electron Transmitter(?: §r§8x(?.*))?", diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/powdertracker/PowderTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/powdertracker/PowderTracker.kt index a90b980d9a60..4c27f195a895 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/powdertracker/PowderTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/powdertracker/PowderTracker.kt @@ -1,6 +1,8 @@ package at.hannibal2.skyhanni.features.mining.powdertracker import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.HotmAPI +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.config.features.mining.PowderTrackerConfig.PowderDisplayEntry import at.hannibal2.skyhanni.data.BossbarData @@ -12,7 +14,9 @@ import at.hannibal2.skyhanni.events.IslandChangeEvent import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent import at.hannibal2.skyhanni.events.SecondPassedEvent +import at.hannibal2.skyhanni.events.mining.PowderGainEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString import at.hannibal2.skyhanni.utils.ConditionalUtils.afterChange import at.hannibal2.skyhanni.utils.ConfigUtils @@ -33,6 +37,7 @@ import com.google.gson.annotations.Expose import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import kotlin.time.Duration import kotlin.time.Duration.Companion.minutes +import kotlin.time.Duration.Companion.seconds @SkyHanniModule object PowderTracker { @@ -193,13 +198,11 @@ object PowderTracker { } for (reward in PowderChestReward.entries) { + if (reward == PowderChestReward.GEMSTONE_POWDER) continue reward.chatPattern.matchMatcher(msg) { tracker.modify { val count = it.rewards[reward] ?: 0 - var amount = groupOrNull("amount")?.formatLong() ?: 1 - if ((reward == PowderChestReward.MITHRIL_POWDER || reward == PowderChestReward.GEMSTONE_POWDER) && doublePowder) { - amount *= 2 - } + val amount = groupOrNull("amount")?.formatLong() ?: 1 it.rewards[reward] = count + amount } } @@ -207,6 +210,18 @@ object PowderTracker { tracker.update() } + @HandleEvent(onlyOnIsland = IslandType.CRYSTAL_HOLLOWS) + fun onPowderGain(event: PowderGainEvent) { + if (lastChestPicked.passedSince() > 5.seconds) return + tracker.modify { + val reward = when (event.powder) { + HotmAPI.PowderType.GEMSTONE -> PowderChestReward.GEMSTONE_POWDER + else -> return@modify + } + it.rewards.addOrPut(reward, event.amount) + } + } + @SubscribeEvent fun onConfigLoad(event: ConfigLoadEvent) { config.textFormat.afterChange { @@ -258,6 +273,17 @@ object PowderTracker { } newList } + + event.transform(61, "mining.powderTracker.textFormat") { element -> + val newList = JsonArray() + for (entry in element.asJsonArray) { + if (entry is JsonNull) continue + if (entry.asString.let { it != "MITHRIL_POWDER" }) { + newList.add(entry) + } + } + newList + } } @SubscribeEvent @@ -280,7 +306,6 @@ object PowderTracker { private fun drawDisplay(data: Data): List = buildList { calculate(data, gemstoneInfo, PowderChestReward.GEMSTONE_POWDER) - calculate(data, mithrilInfo, PowderChestReward.MITHRIL_POWDER) calculate(data, diamondEssenceInfo, PowderChestReward.DIAMOND_ESSENCE) calculate(data, goldEssenceInfo, PowderChestReward.GOLD_ESSENCE) calculateChest(data) @@ -290,13 +315,11 @@ object PowderTracker { addSearchString("§d${data.totalChestPicked.addSeparators()} Total Chests Picked §7($chestPerHour/h)") addSearchString("§bDouble Powder: ${if (doublePowder) "§aActive! §7($powderTimer)" else "§cInactive!"}") - val entries = PowderChestReward.entries val rewards = data.rewards - addPerHour(rewards, entries[0], mithrilInfo) - addPerHour(rewards, entries[1], gemstoneInfo) + addPerHour(rewards, PowderChestReward.GEMSTONE_POWDER, gemstoneInfo) addSearchString("") - addPerHour(rewards, entries[46], diamondEssenceInfo) - addPerHour(rewards, entries[47], goldEssenceInfo) + addPerHour(rewards, PowderChestReward.DIAMOND_ESSENCE, diamondEssenceInfo) + addPerHour(rewards, PowderChestReward.GOLD_ESSENCE, goldEssenceInfo) addSearchString("") val hardStonePerHour = format(hardStoneInfo.perHour) addSearchString("§b${data.totalHardStoneCompacted.addSeparators()} §fHard Stone §bCompacted §7($hardStonePerHour/h)", "Hard Stone") @@ -317,11 +340,18 @@ object PowderTracker { } val (flawless, fine, flawed, rough) = convert(totalGemstone) - addSearchString("§5${flawless}§7-§9${fine}§7-§a${flawed}§f-${rough} $color$gem Gemstone", "Gemstone") + addSearchString("§5$flawless§7-§9$fine§7-§a$flawed§f-$rough $color$gem Gemstone", "Gemstone") } var totalParts = 0L - for (reward in entries.subList(26, 32)) { // robots part + for (reward in listOf( + PowderChestReward.FTX_3070, + PowderChestReward.ELECTRON_TRANSIMTTER, + PowderChestReward.ROBOTRON_REFLECTOR, + PowderChestReward.SUPERLITE_MOTOR, + PowderChestReward.CONTROL_SWITCH, + PowderChestReward.SYNTHETIC_HEART, + )) { val count = rewards.getOrDefault(reward, 0) totalParts += count val name = reward.displayName @@ -336,7 +366,17 @@ object PowderTracker { val blueEgg = rewards.getOrDefault(PowderChestReward.BLUE_GOBLIN_EGG, 0) addSearchString("§3$blueEgg§7-§c$redEgg§7-§e$yellowEgg§f-§a$greenEgg§f-§9$goblinEgg §fGoblin Egg") - for (reward in entries.subList(37, 46)) { + for (reward in listOf( + PowderChestReward.WISHING_COMPASS, + PowderChestReward.SLUDGE_JUICE, + PowderChestReward.ASCENSION_ROPE, + PowderChestReward.TREASURITE, + PowderChestReward.JUNGLE_HEART, + PowderChestReward.PICKONIMBUS_2000, + PowderChestReward.YOGGIE, + PowderChestReward.PREHISTORIC_EGG, + PowderChestReward.OIL_BARREL, + )) { val count = rewards.getOrDefault(reward, 0).addSeparators() val name = reward.displayName addSearchString("§b$count $name", name) diff --git a/src/main/java/at/hannibal2/skyhanni/features/minion/MinionFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/minion/MinionFeatures.kt index c0a9c1212d31..a9dc3dce34df 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/minion/MinionFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/minion/MinionFeatures.kt @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.features.minion import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.config.storage.ProfileSpecificStorage import at.hannibal2.skyhanni.data.ClickType @@ -121,7 +122,7 @@ object MinionFeatures { } } - @SubscribeEvent + @HandleEvent(onlyOnSkyblock = true) fun onEntityClick(event: EntityClickEvent) { if (!enableWithHub()) return if (event.clickType != ClickType.RIGHT_CLICK) return @@ -129,7 +130,7 @@ object MinionFeatures { lastClickedEntity = event.clickedEntity?.getLorenzVec() ?: return } - @SubscribeEvent + @HandleEvent(onlyOnSkyblock = true) fun onBlockClick(event: BlockClickEvent) { if (!enableWithHub()) return if (event.clickType != ClickType.RIGHT_CLICK) return @@ -298,7 +299,7 @@ object MinionFeatures { System.currentTimeMillis() - lastClicked } ?: return "§cCan't calculate coins/day: No time data available!" - //§7Held Coins: §b151,389 + // §7Held Coins: §b151,389 // TODO use regex val coins = line.split(": §b")[1].formatDouble() @@ -360,7 +361,7 @@ object MinionFeatures { val playerLocation = LocationUtils.playerLocation() val minions = minions ?: return for (minion in minions) { - val location = minion.key.add(y = 1.0) + val location = minion.key.up() if (location.distanceToPlayer() > 50) continue val lastEmptied = minion.value.lastClicked @@ -371,14 +372,14 @@ object MinionFeatures { val name = "§6" + if (config.nameOnlyTier) { displayName.split(" ").last() } else displayName - event.drawString(location.add(y = 0.65), name, true) + event.drawString(location.up(0.65), name, true) } if (config.emptiedTime.display && lastEmptied != 0L) { val passedSince = SimpleTimeMark(lastEmptied).passedSince() val format = passedSince.format(longName = true) + " ago" val text = "§eHopper Emptied: $format" - event.drawString(location.add(y = 1.15), text, true) + event.drawString(location.up(1.15), text, true) } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/minion/MinionXp.kt b/src/main/java/at/hannibal2/skyhanni/features/minion/MinionXp.kt index a0545dc1ca45..67d54f10be94 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/minion/MinionXp.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/minion/MinionXp.kt @@ -152,8 +152,8 @@ object MinionXp { MinionFeatures.minionInventoryOpen -> { addXpInfoToTooltip(event) if (collectItem == event.itemStack.item) { - collectItemXpList.forEachIndexed { i, it -> - event.toolTip.add(i + 1, it) + collectItemXpList.forEachIndexed { i, item -> + event.toolTip.add(i + 1, item) } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/CarryTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/CarryTracker.kt index bfecbc48f57f..7efce2fcdae5 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/CarryTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/CarryTracker.kt @@ -14,10 +14,10 @@ import at.hannibal2.skyhanni.utils.CollectionUtils.addString import at.hannibal2.skyhanni.utils.HypixelCommands import at.hannibal2.skyhanni.utils.KeyboardManager import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat import at.hannibal2.skyhanni.utils.NumberUtil.formatDouble import at.hannibal2.skyhanni.utils.NumberUtil.formatDoubleOrUserError import at.hannibal2.skyhanni.utils.NumberUtil.formatIntOrUserError +import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables import at.hannibal2.skyhanni.utils.StringUtils.cleanPlayerName @@ -228,7 +228,7 @@ object CarryTracker { add("§7Missing: §e$missing") add("") if (cost != "") { - add("§7Total cost: §e${cost}") + add("§7Total cost: §e$cost") add("§7Cost per carry: §e${formatCost(carry.type.pricePer)}") } else { add("§cNo price set for this carry!") @@ -260,11 +260,11 @@ object CarryTracker { val totalCost = customer.carries.sumOf { it.getCost() ?: 0.0 } val totalCostFormat = formatCost(totalCost) if (totalCostFormat != "") { - val paidFormat = "§6${customer.alreadyPaid.shortFormat()}" + val paidFormat = "§6${customer.alreadyPaid.shortFormat()}" val missingFormat = formatCost(totalCost - customer.alreadyPaid) list.add( Renderable.clickAndHover( - Renderable.string("§b$customerName $paidFormat§8/${totalCostFormat}"), + Renderable.string("§b$customerName $paidFormat§8/$totalCostFormat"), tips = listOf( "§7Carries for §b$customerName", "", diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/CollectionTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/CollectionTracker.kt index ffc2607233e1..948ae70e07ae 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/CollectionTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/CollectionTracker.kt @@ -157,12 +157,14 @@ object CollectionTracker { itemAmount.percentWithColorCode(goalAmount, 1) }§f)" - display = Collections.singletonList(buildList { - internalName?.let { - add(it.getItemStack()) + display = Collections.singletonList( + buildList { + internalName?.let { + add(it.getItemStack()) + } + add("$itemName collection: §e$format$goal $gainText") } - add("$itemName collection: §e$format$goal $gainText") - }) + ) } private fun countCurrentlyInInventory(): Int { diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/IslandAreas.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/IslandAreas.kt index 5ece5897c5df..dfa60478a6c2 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/IslandAreas.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/IslandAreas.kt @@ -2,6 +2,7 @@ package at.hannibal2.skyhanni.features.misc import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.data.IslandGraphs +import at.hannibal2.skyhanni.data.IslandGraphs.pathFind import at.hannibal2.skyhanni.data.model.Graph import at.hannibal2.skyhanni.data.model.GraphNode import at.hannibal2.skyhanni.data.model.GraphNodeTag @@ -13,14 +14,12 @@ import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule -import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString import at.hannibal2.skyhanni.utils.CollectionUtils.sorted import at.hannibal2.skyhanni.utils.ColorUtils.toChromaColor import at.hannibal2.skyhanni.utils.ConditionalUtils import at.hannibal2.skyhanni.utils.GraphUtils import at.hannibal2.skyhanni.utils.LocationUtils.canBeSeen -import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer import at.hannibal2.skyhanni.utils.LorenzColor import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.NumberUtil.roundTo @@ -54,7 +53,7 @@ object IslandAreas { hasMoved = true } - fun noteMoved() { + fun nodeMoved() { SkyHanniMod.coroutineScope.launch { updateNodes() } @@ -63,9 +62,9 @@ object IslandAreas { private fun updateNodes() { if (!isEnabled()) return val graph = IslandGraphs.currentIslandGraph ?: return - val closedNote = IslandGraphs.closedNote ?: return + val closestNode = IslandGraphs.closestNode ?: return - val (paths, map) = GraphUtils.findFastestPaths(graph, closedNote) { it.getAreaTag() != null } + val (paths, map) = GraphUtils.findFastestPaths(graph, closestNode) { it.getAreaTag() != null } this.paths = paths val finalNodes = mutableMapOf() @@ -81,7 +80,7 @@ object IslandAreas { nodes = finalNodes } - var hasMoved = false + private var hasMoved = false @SubscribeEvent fun onTick(event: LorenzTickEvent) { @@ -129,14 +128,11 @@ object IslandAreas { } private fun buildDisplay() = buildList { - val closedNote = IslandGraphs.closedNote ?: return@buildList - val playerDiff = closedNote.position.distanceToPlayer() - var foundCurrentArea = false var foundAreas = 0 for ((node, diff) in nodes) { - val difference = diff + playerDiff + val difference = diff val tag = node.getAreaTag() ?: continue val name = node.name ?: continue @@ -144,12 +140,7 @@ object IslandAreas { val isTarget = node.name == targetNode?.name val color = if (isTarget) LorenzColor.GOLD else tag.color - // trying to find a faster path to the existing target - if (isTarget && node != targetNode) { - ChatUtils.debug("Found a faster node, rerouting...") - setTarget(node) - } - val coloredName = "${color.getChatColor()}${name}" + val coloredName = "${color.getChatColor()}$name" var suffix = "" paths[node]?.let { path -> @@ -159,13 +150,14 @@ object IslandAreas { passedAreas.remove("null") passedAreas.remove(currentAreaName) // so show areas needed to pass thorough + // TODO show this pass through in the /shnavigate command if (passedAreas.isNotEmpty()) { // suffix = " §7${passedAreas.joinToString(", ")}" } } - val distance = difference.roundTo(1) - val text = "${coloredName}§7: §e$distance$suffix" + val distance = difference.roundTo(0).toInt() + val text = "$coloredName§7: §e$distance$suffix" if (!foundCurrentArea) { foundCurrentArea = true @@ -268,17 +260,21 @@ object IslandAreas { private fun setTarget(node: GraphNode) { targetNode = node + val tag = node.getAreaTag() ?: return + val displayName = tag.color.getChatColor() + node.name val color = config.pathfinder.color.get().toChromaColor() - IslandGraphs.pathFind( - node.position, color, + node.pathFind( + displayName, + color, onFound = { targetNode = null updatePosition() }, + allowRerouting = true, condition = { config.pathfinder.enabled }, ) hasMoved = true } - fun isEnabled() = LorenzUtils.inSkyBlock && config.let { it.pathfinder.enabled || it.enterTitle || it.inWorld } + fun isEnabled() = LorenzUtils.inSkyBlock } diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/JoinCrystalHollows.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/JoinCrystalHollows.kt index f8e5fbe32aa0..ff5a5f7ac57d 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/JoinCrystalHollows.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/JoinCrystalHollows.kt @@ -28,7 +28,8 @@ object JoinCrystalHollows { if (message == "§cYou do not have an active Crystal Hollows pass!") { lastWrongPassTime = System.currentTimeMillis() if (!IslandType.DWARVEN_MINES.isInIsland()) { - ChatUtils.clickableChat("Click here to warp to Dwarven Mines!", + ChatUtils.clickableChat( + "Click here to warp to Dwarven Mines!", onClick = { HypixelCommands.warp("mines") }, "§eClick to run /warp mines!" diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/MagicalPowerDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/MagicalPowerDisplay.kt index e7b8ea26c3c8..dedfe3473e90 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/MagicalPowerDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/MagicalPowerDisplay.kt @@ -93,7 +93,7 @@ object MagicalPowerDisplay { else -> if (internalName.isAbicase()) endMP += (contactAmount ?: 0) / 2 } - event.stackTip = "${if (config.colored) rarity.chatColorCode else "§7"}${endMP}" + event.stackTip = "${if (config.colored) rarity.chatColorCode else "§7"}$endMP" } @SubscribeEvent diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/MarkedPlayerManager.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/MarkedPlayerManager.kt index 05b1eaf35853..d5129a5fb420 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/MarkedPlayerManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/MarkedPlayerManager.kt @@ -78,8 +78,8 @@ object MarkedPlayerManager { fun isMarkedPlayer(player: String): Boolean = player.lowercase() in playerNamesToMark - private fun isEnabled() = (LorenzUtils.inSkyBlock || OutsideSbFeature.MARKED_PLAYERS.isSelected()) - && config.highlightInWorld + private fun isEnabled() = (LorenzUtils.inSkyBlock || OutsideSbFeature.MARKED_PLAYERS.isSelected()) && + config.highlightInWorld fun replaceInChat(string: String): String { if (!config.highlightInChat) return string diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/MiscFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/MiscFeatures.kt index c34a49a7d83a..98d4205256e0 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/MiscFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/MiscFeatures.kt @@ -4,7 +4,6 @@ import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.events.ReceiveParticleEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule -import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.LorenzUtils import net.minecraft.util.EnumParticleTypes import net.minecraftforge.client.event.RenderBlockOverlayEvent diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/NonGodPotEffectDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/NonGodPotEffectDisplay.kt index 89db21304472..83f45e535d5c 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/NonGodPotEffectDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/NonGodPotEffectDisplay.kt @@ -76,7 +76,10 @@ object NonGodPotEffectDisplay { CURSE_OF_GREED("§4Curse of Greed I"), COLD_RESISTANCE_4("§bCold Resistance IV"), - ; + + POWDER_PUMPKIN("§fPowder Pumpkin I"), + FILET_O_FORTUNE("§fFilet O' Fortune I"), + CHILLED_PRISTINE_POTATO("§fChilled Pristine Potato I"), } private val effectsCountPattern by RepoPattern.pattern( diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/PatcherSendCoordinates.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/PatcherSendCoordinates.kt index 98232a428d3c..0d300bab1e87 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/PatcherSendCoordinates.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/PatcherSendCoordinates.kt @@ -9,9 +9,11 @@ import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ColorUtils.toChromaColor import at.hannibal2.skyhanni.utils.LocationUtils +import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer import at.hannibal2.skyhanni.utils.LorenzColor import at.hannibal2.skyhanni.utils.LorenzLogger import at.hannibal2.skyhanni.utils.LorenzVec +import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.RenderUtils.drawColor import at.hannibal2.skyhanni.utils.RenderUtils.drawString @@ -67,9 +69,12 @@ object PatcherSendCoordinates { for (beacon in patcherBeacon) { val location = beacon.location + val distance = location.distanceToPlayer() + val formattedDistance = distance.toInt().addSeparators() + event.drawColor(location, LorenzColor.DARK_GREEN, alpha = 1f) event.drawWaypointFilled(location, config.color.toChromaColor(), true, true) - event.drawString(location.add(0.5, 0.5, 0.5), beacon.name, true, LorenzColor.DARK_BLUE.toColor()) + event.drawString(location.blockCenter(), beacon.name + " §e[${formattedDistance}m]", true, LorenzColor.DARK_BLUE.toColor()) } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/PrivateIslandNoPickaxeAbility.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/PrivateIslandNoPickaxeAbility.kt index dc55af349d14..ca735ce2c8ff 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/PrivateIslandNoPickaxeAbility.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/PrivateIslandNoPickaxeAbility.kt @@ -1,29 +1,28 @@ package at.hannibal2.skyhanni.features.misc import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.data.ClickType import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.events.WorldClickEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ItemCategory import at.hannibal2.skyhanni.utils.ItemUtils.getItemCategoryOrNull -import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @SkyHanniModule object PrivateIslandNoPickaxeAbility { private val config get() = SkyHanniMod.feature.mining - @SubscribeEvent + @HandleEvent(onlyOnIsland = IslandType.PRIVATE_ISLAND) fun onClick(event: WorldClickEvent) { - if (!IslandType.PRIVATE_ISLAND.isInIsland()) return if (!config.privateIslandNoPickaxeAbility) return if (event.clickType != ClickType.RIGHT_CLICK) return if (event.itemInHand?.getItemCategoryOrNull()?.let { ItemCategory.miningTools.contains(it) - } == true) { + } == true + ) { event.cancel() } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/RoundedRectangleOutlineShader.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/RoundedRectangleOutlineShader.kt index ea8770081c78..2a5e131fa0da 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/RoundedRectangleOutlineShader.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/RoundedRectangleOutlineShader.kt @@ -27,4 +27,4 @@ object RoundedRectangleOutlineShader : Shader("rounded_rect_outline", "rounded_r registerUniform(Uniform.UniformType.FLOAT, "borderThickness") { borderThickness } registerUniform(Uniform.UniformType.FLOAT, "borderBlur") { borderBlur } } -} \ No newline at end of file +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/TpsCounter.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/TpsCounter.kt index 01d84daa3fdc..1515ee3dcbd1 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/TpsCounter.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/TpsCounter.kt @@ -74,7 +74,7 @@ object TpsCounter { fun tpsCommand() { if (display.isEmpty()) { - ChatUtils.chat("§cNo tps data available, make sure you have the setting on.") + ChatUtils.userError("No tps data available, make sure you have the setting on.") return } ChatUtils.chat(display) @@ -101,7 +101,8 @@ object TpsCounter { config.tpsDisplayPosition.renderString(display, posLabel = "Tps Display") } - private fun isEnabled() = LorenzUtils.onHypixel && config.tpsDisplay && + private fun isEnabled() = LorenzUtils.onHypixel && + config.tpsDisplay && (LorenzUtils.inSkyBlock || OutsideSbFeature.TPS_DISPLAY.isSelected()) @SubscribeEvent diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/UserLuckBreakdown.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/UserLuckBreakdown.kt index f1fad4e63aca..63d64bbb01b7 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/UserLuckBreakdown.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/UserLuckBreakdown.kt @@ -38,19 +38,19 @@ object UserLuckBreakdown { private lateinit var mainLuckItem: ItemStack private val mainLuckID = "ENDER_PEARL".asInternalName() - private val mainLuckName = "§a✴ SkyHanni User Luck" + private const val MAIN_LUCK_NAME = "§a✴ SkyHanni User Luck" private lateinit var fillerItem: ItemStack private var fillerID = "STAINED_GLASS_PANE".asInternalName() - private val fillerName = " " + private const val FILLER_NAME = " " private lateinit var limboItem: ItemStack private var limboID = "ENDER_PEARL".asInternalName() - private val limboName = "§a✴ Limbo Personal Best" + private const val LIMBO_NAME = "§a✴ Limbo Personal Best" private lateinit var skillsItem: ItemStack private var skillsID = "DIAMOND_SWORD".asInternalName() - private val skillsName = "§a✴ Category: Skills" + private const val SKILLS_NAME = "§a✴ Category: Skills" private var showAllStats = true @@ -63,7 +63,7 @@ object UserLuckBreakdown { "§7Show all stats: §.(?.*)", ) - private val luckTooltipString = "§5§o §a✴ SkyHanni User Luck §f" + private const val LUCK_TOOLTIP = "§5§o §a✴ SkyHanni User Luck §f" private var inCustomBreakdown = false private val validItemSlots = (10..53).filter { it !in listOf(17, 18, 26, 27, 35, 36) && it !in 44..53 } @@ -178,7 +178,7 @@ object UserLuckBreakdown { if (lastIndex == -1) return val luckString = tryTruncateFloat(totalLuck) - event.toolTip.add(lastIndex, "$luckTooltipString$luckString") + event.toolTip.add(lastIndex, "$LUCK_TOOLTIP$luckString") } private fun statsBreakdownLoreTooltip(event: LorenzToolTipEvent, limboLuck: Float) { @@ -205,7 +205,7 @@ object UserLuckBreakdown { if (totalLuck == 0f) return val luckString = tryTruncateFloat(totalLuck) - event.toolTip.add(lastIndex, "$luckTooltipString$luckString") + event.toolTip.add(lastIndex, "$LUCK_TOOLTIP$luckString") } private fun tryTruncateFloat(input: Float): String { @@ -239,7 +239,7 @@ object UserLuckBreakdown { private fun createItems() { fillerItem = ItemUtils.createItemStack( fillerID.getItemStack().item, - fillerName, + FILLER_NAME, listOf(), 1, 15, @@ -251,17 +251,17 @@ object UserLuckBreakdown { mainLuckItem = ItemUtils.createItemStack( mainLuckID.getItemStack().item, - "$mainLuckName §f${tryTruncateFloat(totalLuck)}", + "$MAIN_LUCK_NAME §f${tryTruncateFloat(totalLuck)}", *createItemLore("mainMenu", totalLuck), ) limboItem = ItemUtils.createItemStack( limboID.getItemStack().item, - limboName, + LIMBO_NAME, *createItemLore("limbo", limboLuck), ) skillsItem = ItemUtils.createItemStack( skillsID.getItemStack().item, - skillsName, + SKILLS_NAME, *createItemLore("skills"), ) } diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/compacttablist/TabLine.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/compacttablist/TabLine.kt index 96b89ce17a6d..a2c227bd776c 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/compacttablist/TabLine.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/compacttablist/TabLine.kt @@ -35,4 +35,4 @@ class TabLine(val text: String, val type: TabStringType, val customName: String this.entity = entity return entity } -} \ No newline at end of file +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/discordrpc/DiscordLocationKey.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/discordrpc/DiscordLocationKey.kt index 895a04688f80..7f6caba24047 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/discordrpc/DiscordLocationKey.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/discordrpc/DiscordLocationKey.kt @@ -298,16 +298,12 @@ object DiscordLocationKey { fun getDiscordIconKey(location: String): String { val keyIfNormal = location.lowercase().replace(' ', '-') - return if (normalRPC.contains(keyIfNormal)) { - keyIfNormal - } else if (specialRPC.containsKey(location)) { - specialRPC[location]!! - } else if (specialNetherRPC.contains(location)) { - "crimson-isle" - } else if (specialRiftRPC.containsKey(location)) { - specialRiftRPC[location]!! - } else { - getAmbiguousKey(location) // will return skyblock-logo if not found + return when { + normalRPC.contains(keyIfNormal) -> keyIfNormal + specialRPC.containsKey(location) -> specialRPC[location] ?: getAmbiguousKey(location) + specialNetherRPC.contains(location) -> "crimson-isle" + specialRiftRPC.containsKey(location) -> specialRiftRPC[location] ?: getAmbiguousKey(location) + else -> getAmbiguousKey(location) // will return skyblock-logo if not found } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/discordrpc/DiscordRPCManager.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/discordrpc/DiscordRPCManager.kt index 16843ff6d796..29f20fc050ed 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/discordrpc/DiscordRPCManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/discordrpc/DiscordRPCManager.kt @@ -120,21 +120,23 @@ object DiscordRPCManager : IPCListener { private fun updatePresence() { val location = DiscordStatus.LOCATION.getDisplayString() val discordIconKey = DiscordLocationKey.getDiscordIconKey(location) - client?.sendRichPresence(RichPresence.Builder().apply { - setDetails(getStatusByConfigId(config.firstLine.get()).getDisplayString()) - setState(getStatusByConfigId(config.secondLine.get()).getDisplayString()) - setStartTimestamp(startTimestamp) - setLargeImage(discordIconKey, location) - - if (config.showSkyCryptButton.get()) { - addButton( - RichPresenceButton( - "https://sky.shiiyu.moe/stats/${LorenzUtils.getPlayerName()}/${HypixelData.profileName}", - "Open SkyCrypt" + client?.sendRichPresence( + RichPresence.Builder().apply { + setDetails(getStatusByConfigId(config.firstLine.get()).getDisplayString()) + setState(getStatusByConfigId(config.secondLine.get()).getDisplayString()) + setStartTimestamp(startTimestamp) + setLargeImage(discordIconKey, location) + + if (config.showSkyCryptButton.get()) { + addButton( + RichPresenceButton( + "https://sky.shiiyu.moe/stats/${LorenzUtils.getPlayerName()}/${HypixelData.profileName}", + "Open SkyCrypt" + ) ) - ) - } - }.build()) + } + }.build() + ) } override fun onReady(client: IPCClient) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/discordrpc/DiscordStatus.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/discordrpc/DiscordStatus.kt index 47472d2fec20..708704d68c26 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/discordrpc/DiscordStatus.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/discordrpc/DiscordStatus.kt @@ -163,7 +163,7 @@ enum class DiscordStatus(private val displayMessageSupplier: (() -> String?)) { ITEM({ InventoryUtils.getItemInHand()?.let { - String.format("Holding ${it.displayName.removeColor()}") + String.format(java.util.Locale.US, "Holding ${it.displayName.removeColor()}") } ?: "No item in hand" }), @@ -344,5 +344,4 @@ enum class AutoStatus(val placeholderText: String, val correspondingDiscordStatu STACKING("Stacking placeholder (should never be visible)", DiscordStatus.STACKING), DUNGEONS("Dungeons placeholder (should never be visible)", DiscordStatus.DUNGEONS), AFK("This person is not afk (should never be visible)", DiscordStatus.AFK), - ; } diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValue.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValue.kt index 0463257496f0..8b6697a41af8 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValue.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValue.kt @@ -3,6 +3,7 @@ package at.hannibal2.skyhanni.features.misc.items import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator +import at.hannibal2.skyhanni.config.features.misc.EstimatedItemValueConfig import at.hannibal2.skyhanni.data.jsonobjects.repo.ItemsJson import at.hannibal2.skyhanni.events.ConfigLoadEvent import at.hannibal2.skyhanni.events.GuiRenderEvent @@ -39,7 +40,7 @@ import kotlin.math.roundToLong @SkyHanniModule object EstimatedItemValue { - val config get() = SkyHanniMod.feature.inventory.estimatedItemValues + val config: EstimatedItemValueConfig get() = SkyHanniMod.feature.inventory.estimatedItemValues private var display = emptyList>() private val cache = mutableMapOf>>() private var lastToolTipTime = 0L @@ -90,13 +91,14 @@ object EstimatedItemValue { currentlyShowing = checkCurrentlyVisible() if (!currentlyShowing) return - // TODO add "is debug enabled" check once users notice this easteregg - if (Keyboard.KEY_RIGHT.isKeyClicked()) { - EstimatedItemValueCalculator.starChange += 1 - cache.clear() - } else if (Keyboard.KEY_LEFT.isKeyClicked()) { - EstimatedItemValueCalculator.starChange -= 1 - cache.clear() + if (SkyHanniMod.feature.dev.debug.enabled) { + if (Keyboard.KEY_RIGHT.isKeyClicked()) { + EstimatedItemValueCalculator.starChange += 1 + cache.clear() + } else if (Keyboard.KEY_LEFT.isKeyClicked()) { + EstimatedItemValueCalculator.starChange -= 1 + cache.clear() + } } config.itemPriceDataPos.renderStringsAndItems(display, posLabel = "Estimated Item Value") diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt index b0fbc2f31f83..15c55e02e7fc 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt @@ -29,6 +29,7 @@ import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat import at.hannibal2.skyhanni.utils.PrimitiveIngredient import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getAbilityScrolls +import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getAppliedPocketSackInASack import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getArmorDye import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getAttributes import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getBookwormBookCount @@ -62,6 +63,8 @@ import io.github.notenoughupdates.moulconfig.observer.Property import net.minecraft.item.ItemStack import java.util.Locale +// TODO split into smaler sub classes +@Suppress("LargeClass") object EstimatedItemValueCalculator { private val config get() = SkyHanniMod.feature.inventory.estimatedItemValues @@ -69,6 +72,7 @@ object EstimatedItemValueCalculator { private val kuudraSets = listOf("AURORA", "CRIMSON", "TERROR", "HOLLOW", "FERVOR") var starChange = 0 + get() = if (SkyHanniMod.feature.dev.debug.enabled) field else 0 private val additionalCostFunctions = listOf( ::addAttributeCost, @@ -96,6 +100,7 @@ object EstimatedItemValueCalculator { ::addManaDisintegrators, ::addPolarvoidBook, ::addBookwormBook, + ::addPocketSackInASack, // cosmetic ::addHelmetSkin, @@ -129,12 +134,15 @@ object EstimatedItemValueCalculator { return Pair(totalPrice, basePrice) } - private fun isKuudraSet(internalName: String) = (kuudraSets.any { internalName.contains(it) } && listOf( - "CHESTPLATE", - "LEGGINGS", - "HELMET", - "BOOTS", - ).any { internalName.endsWith(it) }) + private fun isKuudraSet(internalName: String) = ( + kuudraSets.any { internalName.contains(it) } && + listOf( + "CHESTPLATE", + "LEGGINGS", + "HELMET", + "BOOTS", + ).any { internalName.endsWith(it) } + ) private fun addAttributeCost(stack: ItemStack, list: MutableList): Double { val attributes = stack.getAttributes() ?: return 0.0 @@ -218,7 +226,9 @@ object EstimatedItemValueCalculator { private fun getPriceOrCompositePriceForAttribute(attributeName: String, level: Int): Double? { val intRange = if (config.useAttributeComposite.get()) 1..10 else level..level return intRange.mapNotNull { lowerLevel -> - "$attributeName;$lowerLevel".asInternalName().getPriceOrNull()?.let { it / (1 shl lowerLevel) * (1 shl level).toDouble() } + "$attributeName;$lowerLevel".asInternalName().getPriceOrNull()?.let { + it / (1 shl lowerLevel) * (1 shl level).toDouble() + } }.minOrNull() } @@ -390,11 +400,20 @@ object EstimatedItemValueCalculator { return price } + private fun addPocketSackInASack(stack: ItemStack, list: MutableList): Double { + val count = stack.getAppliedPocketSackInASack() ?: return 0.0 + + val pocketSackInASack = "POCKET_SACK_IN_A_SACK".asInternalName() + val price = pocketSackInASack.getPrice() * count + list.add("§7Pocket Sack-in-a-Sack: §e$count§7/§e3 §7(§6" + price.shortFormat() + "§7)") + return price + } + private fun addBookwormBook(stack: ItemStack, list: MutableList): Double { val count = stack.getBookwormBookCount() ?: return 0.0 - val tfHardcodedItemAgain = "BOOKWORM_BOOK".asInternalName() - val price = tfHardcodedItemAgain.getPrice() * count + val bookwormBook = "BOOKWORM_BOOK".asInternalName() + val price = bookwormBook.getPrice() * count list.add("§7Bookworm's Favorite Book: §e$count§7/§e5 §7(§6" + price.shortFormat() + "§7)") return price } @@ -431,7 +450,7 @@ object EstimatedItemValueCalculator { var totalStars = stack.getDungeonStarCount() ?: stack.getStarCount() ?: 0 starChange.takeIf { it != 0 }?.let { - list.add("change: $it") + list.add("[Debug] added stars: $it") totalStars += it } @@ -487,13 +506,13 @@ object EstimatedItemValueCalculator { val tiers = mutableMapOf() - for ((id, prices) in EssenceItemUtils.itemPrices) { + for ((id, _) in EssenceItemUtils.itemPrices) { if (!id.contains(removed)) continue tiers[id] = getKuudraTier(id) } - for ((id, tier) in tiers.sorted()) { - val prices = EssenceItemUtils.itemPrices[id]!! + for ((id, _) in tiers.sorted()) { + val prices = EssenceItemUtils.itemPrices[id] ?: emptyMap() maxStars += prices.size if (remainingStars <= 0) continue @@ -738,10 +757,13 @@ object EstimatedItemValueCalculator { var totalPrice = 0.0 val map = mutableMapOf() - //todo use repo - val tieredEnchants = listOf("compact", "cultivating", "champion", "expertise", "hecatomb", "toxophilite") - val onlyTierOnePrices = listOf("ultimate_chimera", "ultimate_fatal_tempo", "smoldering", "ultimate_flash", "divine_gift") - val onlyTierFivePrices = listOf("ferocious_mana", "hardened_mana", "mana_vampire", "strong_mana") + // todo use repo + val tieredEnchants = + listOf("compact", "cultivating", "champion", "expertise", "hecatomb", "toxophilite") + val onlyTierOnePrices = + listOf("ultimate_chimera", "ultimate_fatal_tempo", "smoldering", "ultimate_flash", "divine_gift") + val onlyTierFivePrices = + listOf("ferocious_mana", "hardened_mana", "mana_vampire", "strong_mana") val internalName = stack.getInternalName() for ((rawName, rawLevel) in enchantments) { @@ -917,11 +939,11 @@ object EstimatedItemValueCalculator { fun Pair.getAttributeName(): String { val name = first.fixMending().allLettersFirstUppercase() - return "§b$name ${second} Shard" + return "§b$name $second Shard" } fun Pair.getAttributePrice(): Double? = EstimatedItemValueCalculator.getPriceOrCompositePriceForAttribute( - "ATTRIBUTE_SHARD+ATTRIBUTE_" + first, + "ATTRIBUTE_SHARD+ATTRIBUTE_$first", second, ) } diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/items/enchants/Enchant.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/items/enchants/Enchant.kt index 286560c73fea..6432be2f6572 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/items/enchants/Enchant.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/items/enchants/Enchant.kt @@ -10,8 +10,8 @@ import at.hannibal2.skyhanni.utils.LorenzColor import at.hannibal2.skyhanni.utils.StringUtils.removeColor import com.google.gson.annotations.Expose import io.github.notenoughupdates.moulconfig.observer.Property -import java.util.TreeSet import net.minecraft.item.ItemStack +import java.util.TreeSet open class Enchant : Comparable { @Expose @@ -94,8 +94,7 @@ open class Enchant : Comparable { return if (this.isUltimate()) -1 else 1 } - class Normal : Enchant() { - } + class Normal : Enchant() class Ultimate : Enchant() { override fun getFormat(level: Int, itemStack: ItemStack?) = "§d§l" @@ -111,7 +110,7 @@ open class Enchant : Comparable { @Expose private var stackLevel: TreeSet? = null - override fun toString() = "$nbtNum ${stackLevel.toString()} ${super.toString()}" + override fun toString() = "$nbtNum $stackLevel ${super.toString()}" } class Dummy(name: String) : Enchant() { diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/items/enchants/EnchantParser.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/items/enchants/EnchantParser.kt index 66c4c040716a..162d2adee0e1 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/items/enchants/EnchantParser.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/items/enchants/EnchantParser.kt @@ -22,7 +22,6 @@ import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getEnchantments import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getExtraAttributes import at.hannibal2.skyhanni.utils.StringUtils.removeColor import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern -import java.lang.ArithmeticException import net.minecraft.event.HoverEvent import net.minecraft.item.ItemStack import net.minecraft.util.ChatComponentText diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/items/enchants/EnchantsJson.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/items/enchants/EnchantsJson.kt index 99fb0b3287bb..6e1550a974a2 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/items/enchants/EnchantsJson.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/items/enchants/EnchantsJson.kt @@ -2,22 +2,26 @@ package at.hannibal2.skyhanni.features.misc.items.enchants import at.hannibal2.skyhanni.features.misc.items.enchants.EnchantParser.enchantmentPattern import com.google.gson.annotations.Expose +import com.google.gson.annotations.SerializedName class EnchantsJson { @Expose - var NORMAL: HashMap = hashMapOf() + @SerializedName("NORMAL") + var normal: HashMap = hashMapOf() @Expose - var ULTIMATE: HashMap = hashMapOf() + @SerializedName("ULTIMATE") + var ultimate: HashMap = hashMapOf() @Expose - var STACKING: HashMap = hashMapOf() + @SerializedName("STACKING") + var stacking: HashMap = hashMapOf() fun getFromLore(passedLoreName: String): Enchant { val loreName = passedLoreName.lowercase() - var enchant: Enchant? = NORMAL[loreName] - if (enchant == null) enchant = ULTIMATE[loreName] - if (enchant == null) enchant = STACKING[loreName] + var enchant: Enchant? = normal[loreName] + if (enchant == null) enchant = ultimate[loreName] + if (enchant == null) enchant = stacking[loreName] if (enchant == null) enchant = Enchant.Dummy(passedLoreName) return enchant } @@ -29,13 +33,13 @@ class EnchantsJson { if (enchants.isNotEmpty()) { if (enchants.containsKey(enchant.nbtName)) return true } else { - if (NORMAL.containsKey(enchant.loreName.lowercase())) return true - if (ULTIMATE.containsKey(enchant.loreName.lowercase())) return true - if (STACKING.containsKey(enchant.loreName.lowercase())) return true + if (normal.containsKey(enchant.loreName.lowercase())) return true + if (ultimate.containsKey(enchant.loreName.lowercase())) return true + if (stacking.containsKey(enchant.loreName.lowercase())) return true } } return false } - fun hasEnchantData() = NORMAL.isNotEmpty() && ULTIMATE.isNotEmpty() && STACKING.isNotEmpty() + fun hasEnchantData() = normal.isNotEmpty() && ultimate.isNotEmpty() && stacking.isNotEmpty() } diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboPlaytime.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboPlaytime.kt index 1c46b40d6529..443f5c80b2ff 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboPlaytime.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboPlaytime.kt @@ -43,7 +43,7 @@ object LimboPlaytime { private val enabled get() = SkyHanniMod.feature.misc.showLimboTimeInPlaytimeDetailed private val itemID = "ENDER_PEARL".asInternalName() - private val itemName = "§aLimbo" + private const val ITEM_NAME = "§aLimbo" private lateinit var limboItem: ItemStack private var lastCreateCooldown = SimpleTimeMark.farPast() @@ -60,7 +60,7 @@ object LimboPlaytime { lastCreateCooldown = SimpleTimeMark.now() limboItem = ItemUtils.createItemStack( itemID.getItemStack().item, - itemName, + ITEM_NAME, *createItemLore() ) } diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboTimeTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboTimeTracker.kt index bfb8ce715d2f..120c53e47b82 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboTimeTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/limbo/LimboTimeTracker.kt @@ -144,8 +144,11 @@ object LimboTimeTracker { fun printStats(onlyPlaytime: Boolean = false) { val timeInLimbo: Int = if (inLimbo) limboJoinTime.passedSince().inWholeSeconds.toInt() else 0 - val playtime: Int = if (inLimbo) (storage?.playtime - ?: 0) + limboJoinTime.passedSince().inWholeSeconds.toInt() else storage?.playtime ?: 0 + val playtime: Int = if (inLimbo) ( + storage?.playtime ?: 0 + ) + limboJoinTime.passedSince().inWholeSeconds.toInt() + else storage?.playtime ?: 0 + if (onlyPlaytime) { ChatUtils.chat("§aYou have ${playtime / 3600} hours and ${playtime % 3600 / 60} minutes playtime!", false) } else { diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/Category.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/Category.kt index 3172df6e05db..b69e5913db45 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/Category.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/Category.kt @@ -1,3 +1,3 @@ package at.hannibal2.skyhanni.features.misc.massconfiguration -data class Category(val name: String, val description: String) \ No newline at end of file +data class Category(val name: String, val description: String) diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/DefaultConfigFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/DefaultConfigFeatures.kt index f87146a6f803..745928cee13c 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/DefaultConfigFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/DefaultConfigFeatures.kt @@ -76,8 +76,8 @@ object DefaultConfigFeatures { return } optionList = optionList - .mapValues { it -> - it.value.filter { + .mapValues { option -> + option.value.filter { (togglesInNewVersion == null || it.path in togglesInNewVersion) && (togglesInOldVersion == null || it.path !in togglesInOldVersion) } diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/DefaultConfigOptionGui.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/DefaultConfigOptionGui.kt index bbe40db5cd4a..38ba952d5431 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/DefaultConfigOptionGui.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/DefaultConfigOptionGui.kt @@ -81,8 +81,8 @@ class DefaultConfigOptionGui( fun button(title: String, tooltip: List, func: () -> Unit) { val width = mc.fontRendererObj.getStringWidth(title) var overMouse = false - if (mouseX - ((this.width - xSize) / 2 + padding) in i..(i + width) - && mouseY - (height + ySize) / 2 in -barSize..0 + if (mouseX - ((this.width - xSize) / 2 + padding) in i..(i + width) && + mouseY - (height + ySize) / 2 in -barSize..0 ) { overMouse = true hoveringTextToDraw = tooltip @@ -107,19 +107,25 @@ class DefaultConfigOptionGui( button("Turn all on", listOf()) { for (entry in resetSuggestionState.entries) { entry.setValue(ResetSuggestionState.TURN_ALL_ON) - orderedOptions[entry.key]!!.forEach { it.toggleOverride = null } + orderedOptions[entry.key]?.let { opts -> + opts.forEach { it.toggleOverride = null } + } } } button("Turn all off", listOf()) { for (entry in resetSuggestionState.entries) { entry.setValue(ResetSuggestionState.TURN_ALL_OFF) - orderedOptions[entry.key]!!.forEach { it.toggleOverride = null } + orderedOptions[entry.key]?.let { opts -> + opts.forEach { it.toggleOverride = null } + } } } button("Leave all untouched", listOf()) { for (entry in resetSuggestionState.entries) { entry.setValue(ResetSuggestionState.LEAVE_DEFAULTS) - orderedOptions[entry.key]!!.forEach { it.toggleOverride = null } + orderedOptions[entry.key]?.let { opts -> + opts.forEach { it.toggleOverride = null } + } } } button("Cancel", listOf()) { @@ -165,12 +171,16 @@ class DefaultConfigOptionGui( hoveringTextToDraw = listOf( "§e${cat.name}", "§7${cat.description}", - ) + orderedOptions[cat]!!.map { "§7 - §a" + it.name } + ) + orderedOptions[cat]?.let { opts -> + opts.map { "§7 - §a" + it.name } + }.orEmpty() } if (shouldClick) { resetSuggestionState[cat] = suggestionState.next - orderedOptions[cat]!!.forEach { it.toggleOverride = null } + orderedOptions[cat]?.let { opts -> + opts.forEach { it.toggleOverride = null } + } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/FeatureToggleProcessor.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/FeatureToggleProcessor.kt index 2b33885c1e2a..020004648531 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/FeatureToggleProcessor.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/FeatureToggleProcessor.kt @@ -24,8 +24,8 @@ class FeatureToggleProcessor : ConfigStructureReader { latestCategory = Category(name, description) } - override fun endCategory() { - } + @Suppress("EmptyFunctionBlock") + override fun endCategory() {} override fun beginAccordion(baseObject: Any?, field: Field?, o: ConfigOption?, id: Int) { val option = o ?: return @@ -86,6 +86,6 @@ class FeatureToggleProcessor : ConfigStructureReader { ) } - override fun emitGuiOverlay(baseObject: Any?, field: Field?, option: ConfigOption?) { - } + @Suppress("EmptyFunctionBlock") + override fun emitGuiOverlay(baseObject: Any?, field: Field?, option: ConfigOption?) {} } diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/ResetSuggestionState.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/ResetSuggestionState.kt index 30a78a7b2928..60d809633fa6 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/ResetSuggestionState.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/massconfiguration/ResetSuggestionState.kt @@ -7,4 +7,4 @@ enum class ResetSuggestionState(val label: String) { ; val next get() = entries[(ordinal + 1) % entries.size] -} \ No newline at end of file +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/pathfind/NavigationHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/pathfind/NavigationHelper.kt index e753948bca5e..855a16394bb1 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/pathfind/NavigationHelper.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/pathfind/NavigationHelper.kt @@ -2,11 +2,12 @@ package at.hannibal2.skyhanni.features.misc.pathfind import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.data.IslandGraphs +import at.hannibal2.skyhanni.data.IslandGraphs.pathFind import at.hannibal2.skyhanni.data.model.GraphNode import at.hannibal2.skyhanni.data.model.GraphNodeTag -import at.hannibal2.skyhanni.data.model.findShortestDistance import at.hannibal2.skyhanni.features.misc.IslandAreas import at.hannibal2.skyhanni.utils.CollectionUtils.sorted +import at.hannibal2.skyhanni.utils.GraphUtils import at.hannibal2.skyhanni.utils.NumberUtil.roundTo import at.hannibal2.skyhanni.utils.chat.Text import at.hannibal2.skyhanni.utils.chat.Text.asComponent @@ -57,12 +58,12 @@ object NavigationHelper { val distance = distances[node]!!.roundTo(1) val component = "$name §e$distance".asComponent() component.onClick { - IslandGraphs.pathFind(node.position) + node.pathFind(label = name, allowRerouting = true, condition = { true }) sendNavigateMessage(name, goBack) } val tag = node.tags.first { it in allowedTags } - val d = "Name: $name\n§7Type: §r${tag.displayName}\n§7Distance: §e$distance blocks\n§eClick to start navigating!" - component.hover = d.asComponent() + val hoverText = "Name: $name\n§7Type: §r${tag.displayName}\n§7Distance: §e$distance blocks\n§eClick to start navigating!" + component.hover = hoverText.asComponent() component } } @@ -93,7 +94,7 @@ object NavigationHelper { searchTerm: String, ): Map { val graph = IslandGraphs.currentIslandGraph ?: return emptyMap() - val closedNote = IslandGraphs.closedNote ?: return emptyMap() + val closestNode = IslandGraphs.closestNode ?: return emptyMap() val nodes = graph.nodes val distances = mutableMapOf() @@ -102,7 +103,7 @@ object NavigationHelper { val remainingTags = node.tags.filter { it in allowedTags } if (remainingTags.isEmpty()) continue if (name.lowercase().contains(searchTerm)) { - distances[node] = graph.findShortestDistance(closedNote, node) + distances[node] = GraphUtils.findShortestDistance(closestNode, node) } if (remainingTags.size != 1) { println("found node with invalid amount of tags: ${node.name} (${remainingTags.map { it.cleanName }}") diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/trevor/TrevorFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/trevor/TrevorFeatures.kt index 9d1a1dca24a0..6ca32d610db6 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/trevor/TrevorFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/trevor/TrevorFeatures.kt @@ -254,10 +254,12 @@ object TrevorFeatures { var entityTrapper = EntityUtils.getEntityByID(trapperID) if (entityTrapper !is EntityLivingBase) entityTrapper = EntityUtils.getEntityByID(backupTrapperID) if (entityTrapper is EntityLivingBase && config.trapperTalkCooldown) { - RenderLivingEntityHelper.setEntityColorWithNoHurtTime(entityTrapper, currentStatus.color) { config.trapperTalkCooldown } + RenderLivingEntityHelper.setEntityColorWithNoHurtTime(entityTrapper, currentStatus.color) { + config.trapperTalkCooldown + } entityTrapper.getLorenzVec().let { if (it.distanceToPlayer() < 15) { - event.drawString(it.add(y = 2.23), currentLabel) + event.drawString(it.up(2.23), currentLabel) } } } @@ -273,11 +275,11 @@ object TrevorFeatures { TrevorSolver.currentMob!!.mobName } location = TrevorSolver.mobCoordinates - event.drawWaypointFilled(location.add(y = -2), LorenzColor.GREEN.toColor(), true, true) - event.drawDynamicText(location.add(y = 1), displayName, 1.5) + event.drawWaypointFilled(location.down(2), LorenzColor.GREEN.toColor(), true, true) + event.drawDynamicText(location.up(), displayName, 1.5) } else { event.drawWaypointFilled(location, LorenzColor.GOLD.toColor(), true, true) - event.drawDynamicText(location.add(y = 1), TrevorSolver.mobLocation.location, 1.5) + event.drawDynamicText(location.up(), TrevorSolver.mobLocation.location, 1.5) } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/update/GuiOptionEditorUpdateCheck.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/update/GuiOptionEditorUpdateCheck.kt index f56185aba310..84d86615da3d 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/update/GuiOptionEditorUpdateCheck.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/update/GuiOptionEditorUpdateCheck.kt @@ -49,7 +49,7 @@ class GuiOptionEditorUpdateCheck(option: ProcessedOption) : GuiOptionEditor(opti val sameVersion = currentVersion.equals(nextVersion, true) TextRenderUtils.drawStringCenteredScaledMaxWidth( "${if (UpdateManager.updateState == UpdateManager.UpdateState.NONE) GREEN else RED}$currentVersion" + - if (nextVersion != null && !sameVersion) "➜ ${GREEN}${nextVersion}" else "", + if (nextVersion != null && !sameVersion) "➜ $GREEN$nextVersion" else "", fr, widthRemaining / 4F, 10F, diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/visualwords/ModifyVisualWords.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/visualwords/ModifyVisualWords.kt index 8999ba074941..8f7551573665 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/visualwords/ModifyVisualWords.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/visualwords/ModifyVisualWords.kt @@ -54,7 +54,7 @@ object ModifyVisualWords { it.groupValues[1] + it.groupValues[2].reversed() } } - */ + */ modifiedText } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/nether/MatriarchHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/nether/MatriarchHelper.kt index 1d74e0b96581..7d2240d4dbdd 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/nether/MatriarchHelper.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/nether/MatriarchHelper.kt @@ -62,7 +62,7 @@ object MatriarchHelper { val color = config.lineColor.toChromaColor() var prePoint = event.exactPlayerEyeLocation() for (mob in pearlList) { - val point = mob.baseEntity.getLorenzVec().add(y = 1.2) + val point = mob.baseEntity.getLorenzVec().up(1.2) event.draw3DLine(prePoint, point, color, 10, true) prePoint = point } diff --git a/src/main/java/at/hannibal2/skyhanni/features/nether/PabloHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/nether/PabloHelper.kt index aa7cfcafc130..eb4962549f70 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/nether/PabloHelper.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/nether/PabloHelper.kt @@ -4,6 +4,7 @@ import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.api.GetFromSackAPI import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.DelayedRun import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.ItemUtils.name import at.hannibal2.skyhanni.utils.LorenzUtils @@ -33,8 +34,10 @@ object PabloHelper { // ) private val patterns = listOf( - "\\[NPC] Pablo: (?:✆ )?Could you bring me an (?[\\w ]+).*".toPattern(), + "\\[NPC] Pablo: (?:✆ )?Are you available\\? I desperately need an? (?[\\w ]+) today\\.".toPattern(), "\\[NPC] Pablo: (?:✆ )?Bring me that (?[\\w ]+) as soon as you can!".toPattern(), + "\\[NPC] Pablo: (?:✆ )?Could you bring me an? (?[\\w ]+)\\?".toPattern(), + "\\[NPC] Pablo: (?:✆ )?I really need an? (?[\\w ]+) today, do you have one you could spare\\?".toPattern(), ) private var lastSentMessage = SimpleTimeMark.farPast() @@ -49,10 +52,12 @@ object PabloHelper { if (InventoryUtils.countItemsInLowerInventory { it.name.contains(itemName) } > 0) return - GetFromSackAPI.getFromChatMessageSackItems( - itemName.asInternalName().makePrimitiveStack(), - "Click here to grab an $itemName from sacks!", - ) + DelayedRun.runNextTick { + GetFromSackAPI.getFromChatMessageSackItems( + itemName.asInternalName().makePrimitiveStack(), + "Click here to grab an $itemName from sacks!", + ) + } lastSentMessage = SimpleTimeMark.now() } diff --git a/src/main/java/at/hannibal2/skyhanni/features/nether/ashfang/AshfangBlazingSouls.kt b/src/main/java/at/hannibal2/skyhanni/features/nether/ashfang/AshfangBlazingSouls.kt index 849f9a48a0b0..de4db8f833da 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/nether/ashfang/AshfangBlazingSouls.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/nether/ashfang/AshfangBlazingSouls.kt @@ -50,7 +50,7 @@ object AshfangBlazingSouls { event.drawWaypointFilled(orbLocation.add(-0.5, 1.25, -0.5), color, extraSize = -0.15) if (orbLocation.distance(playerLocation) < 10) { // TODO find way to dynamically change color - event.drawString(orbLocation.add(y = 2.5), "§bBlazing Soul") + event.drawString(orbLocation.up(2.5), "§bBlazing Soul") } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/nether/ashfang/AshfangGravityOrbs.kt b/src/main/java/at/hannibal2/skyhanni/features/nether/ashfang/AshfangGravityOrbs.kt index 6a4b02416ed5..1eaa1dd5e921 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/nether/ashfang/AshfangGravityOrbs.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/nether/ashfang/AshfangGravityOrbs.kt @@ -52,7 +52,7 @@ object AshfangGravityOrbs { if (orbLocation.distance(playerLocation) < 15) { // TODO find way to dynamically change color - event.drawString(orbLocation.add(y = 2.5), "§cGravity Orb") + event.drawString(orbLocation.up(2.5), "§cGravity Orb") } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/nether/ashfang/AshfangNextResetCooldown.kt b/src/main/java/at/hannibal2/skyhanni/features/nether/ashfang/AshfangNextResetCooldown.kt index 98b2d52a02c6..c555ec6d29f3 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/nether/ashfang/AshfangNextResetCooldown.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/nether/ashfang/AshfangNextResetCooldown.kt @@ -30,7 +30,8 @@ object AshfangNextResetCooldown { if (EntityUtils.getEntities().any { it.posY > 145 && (it.name.contains("§c§9Ashfang Acolyte§r") || it.name.contains("§c§cAshfang Underling§r")) - }) { + } + ) { spawnTime = SimpleTimeMark.now() } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/FactionType.kt b/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/FactionType.kt index 389f1ccc084b..d531aa8f4996 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/FactionType.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/FactionType.kt @@ -5,4 +5,4 @@ enum class FactionType { MAGE, NONE -} \ No newline at end of file +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailyquest/quest/MiniBossQuest.kt b/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailyquest/quest/MiniBossQuest.kt index 914f1e92180f..609a22a0ff55 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailyquest/quest/MiniBossQuest.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailyquest/quest/MiniBossQuest.kt @@ -10,4 +10,4 @@ class MiniBossQuest(val miniBoss: CrimsonMiniBoss, state: QuestState, needAmount miniBoss.displayName, state, needAmount - ) \ No newline at end of file + ) diff --git a/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailyquest/quest/QuestCategory.kt b/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailyquest/quest/QuestCategory.kt index f9987fe1c70b..379f0c26b02d 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailyquest/quest/QuestCategory.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailyquest/quest/QuestCategory.kt @@ -9,4 +9,4 @@ enum class QuestCategory(val displayName: String) { KUUDRA("Kuudra Kill"), UNKNOWN("§4Unknown"), -} \ No newline at end of file +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailyquest/quest/QuestState.kt b/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailyquest/quest/QuestState.kt index acde3785d5b4..f98514a6644e 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailyquest/quest/QuestState.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailyquest/quest/QuestState.kt @@ -5,4 +5,4 @@ enum class QuestState(val displayName: String, val color: String) { ACCEPTED("Accepted", "§b"), READY_TO_COLLECT("Ready to collect", "§a"), COLLECTED("Collected", "§7"), -} \ No newline at end of file +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/RiftAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/RiftAPI.kt index 844ac0227da4..af82198bf81e 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/rift/RiftAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/rift/RiftAPI.kt @@ -21,6 +21,11 @@ object RiftAPI { val farmingTool by lazy { "FARMING_WAND".asInternalName() } + private val blowgun by lazy { "BERBERIS_BLOWGUN".asInternalName() } + + val ItemStack?.isBlowgun: Boolean + get() = this?.getInternalName() == blowgun + fun ItemStack.motesNpcPrice(): Double? { val baseMotes = motesPrice[getInternalName()] ?: return null val burgerStacks = config.motes.burgerStacks @@ -28,9 +33,13 @@ object RiftAPI { return pricePer * stackSize } + var inRiftRace = false + var trackingButtons = false + var allButtonsHit = false + fun inLivingCave() = LorenzUtils.skyBlockArea == "Living Cave" fun inLivingStillness() = LorenzUtils.skyBlockArea == "Living Stillness" fun inStillgoreChateau() = LorenzUtils.skyBlockArea.let { it == "Stillgore Château" || it == "Oubliette" } - fun inDreadfarm() = LorenzUtils.skyBlockArea == "Dreadfarm" + fun inWestVillage() = LorenzUtils.skyBlockArea.let { it == "West Village" || it == "Infested House" } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/area/dreadfarm/RiftAgaricusCap.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/area/dreadfarm/RiftAgaricusCap.kt index 161200fedad6..d601601a10e5 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/rift/area/dreadfarm/RiftAgaricusCap.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/rift/area/dreadfarm/RiftAgaricusCap.kt @@ -63,7 +63,7 @@ object RiftAgaricusCap { fun onRenderWorld(event: LorenzRenderWorldEvent) { if (!isEnabled()) return - val location = location?.add(y = 0.6) ?: return + val location = location?.up(0.6) ?: return if (startTime.isFarFuture()) { event.drawDynamicText(location, "§cClick!", 1.5) diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/area/dreadfarm/RiftWiltedBerberisHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/area/dreadfarm/RiftWiltedBerberisHelper.kt index e1664e6c8087..4ac014d3abe1 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/rift/area/dreadfarm/RiftWiltedBerberisHelper.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/rift/area/dreadfarm/RiftWiltedBerberisHelper.kt @@ -1,7 +1,9 @@ package at.hannibal2.skyhanni.features.rift.area.dreadfarm +import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent import at.hannibal2.skyhanni.events.LorenzTickEvent +import at.hannibal2.skyhanni.events.PlaySoundEvent import at.hannibal2.skyhanni.events.ReceiveParticleEvent import at.hannibal2.skyhanni.features.rift.RiftAPI import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule @@ -50,16 +52,15 @@ object RiftWiltedBerberisHelper { hasFarmingToolInHand = InventoryUtils.getItemInHand()?.getInternalName() == RiftAPI.farmingTool if (Minecraft.getMinecraft().thePlayer.onGround) { - val block = LocationUtils.playerLocation().add(y = -1).getBlockAt() + val block = LorenzVec.getBlockBelowPlayer().getBlockAt() val currentY = LocationUtils.playerLocation().y isOnFarmland = block == Blocks.farmland && (currentY % 1 == 0.0) } } - private fun nearestBerberis(location: LorenzVec): WiltedBerberis? { - return list.filter { it.currentParticles.distanceSq(location) < 8 } + private fun nearestBerberis(location: LorenzVec): WiltedBerberis? = + list.filter { it.currentParticles.distanceSq(location) < 8 } .minByOrNull { it.currentParticles.distanceSq(location) } - } @SubscribeEvent fun onReceiveParticle(event: ReceiveParticleEvent) { @@ -70,13 +71,13 @@ object RiftWiltedBerberisHelper { val berberis = nearestBerberis(location) if (event.type != EnumParticleTypes.FIREWORKS_SPARK) { - if (config.hideparticles && berberis != null) { + if (config.hideParticles && berberis != null) { event.cancel() } return } - if (config.hideparticles) { + if (config.hideParticles) { event.cancel() } @@ -106,6 +107,16 @@ object RiftWiltedBerberisHelper { } } + @SubscribeEvent + fun onPlaySound(event: PlaySoundEvent) { + if (!isMuteOthersSoundsEnabled()) return + val soundName = event.soundName + + if (soundName == "mob.horse.donkey.death" || soundName == "mob.horse.donkey.hit") { + event.cancel() + } + } + @SubscribeEvent fun onRenderWorld(event: LorenzRenderWorldEvent) { if (!isEnabled()) return @@ -121,7 +132,7 @@ object RiftWiltedBerberisHelper { val location = currentParticles.fixLocation(berberis) if (!moving) { event.drawFilledBoundingBox_nea(axisAlignedBB(location), Color.YELLOW, 0.7f) - event.drawDynamicText(location.add(y = 1), "§eWilted Berberis", 1.5, ignoreBlocks = false) + event.drawDynamicText(location.up(), "§eWilted Berberis", 1.5, ignoreBlocks = false) } else { event.drawFilledBoundingBox_nea(axisAlignedBB(location), Color.WHITE, 0.5f) previous?.fixLocation(berberis)?.let { @@ -133,6 +144,11 @@ object RiftWiltedBerberisHelper { } } + @SubscribeEvent + fun onConfigFix(event: ConfigUpdaterMigrator.ConfigFixEvent) { + event.move(60, "rift.area.dreadfarm.wiltedBerberis.hideparticles", "rift.area.dreadfarm.wiltedBerberis.hideParticles") + } + private fun axisAlignedBB(loc: LorenzVec) = loc.add(0.1, -0.1, 0.1).boundingToOffset(0.8, 1.0, 0.8).expandBlock() private fun LorenzVec.fixLocation(wiltedBerberis: WiltedBerberis): LorenzVec { @@ -143,4 +159,9 @@ object RiftWiltedBerberisHelper { } private fun isEnabled() = RiftAPI.inRift() && RiftAPI.inDreadfarm() && config.enabled + + private fun isMuteOthersSoundsEnabled() = RiftAPI.inRift() && + config.muteOthersSounds && + (RiftAPI.inDreadfarm() || RiftAPI.inWestVillage()) && + !(hasFarmingToolInHand && isOnFarmland) } diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/area/dreadfarm/VoltHighlighter.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/area/dreadfarm/VoltHighlighter.kt index 4ff57d73d263..50c6593fb9d2 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/rift/area/dreadfarm/VoltHighlighter.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/rift/area/dreadfarm/VoltHighlighter.kt @@ -38,8 +38,8 @@ object VoltHighlighter { fun onArmorChange(event: EntityEquipmentChangeEvent) { if (!RiftAPI.inRift() || !config.voltWarning) return val player = Minecraft.getMinecraft().thePlayer ?: return - if (event.isHead && getVoltState(event.entity) == VoltState.DOING_LIGHTNING - && event.entity.positionVector.squareDistanceTo(player.positionVector) <= LIGHTNING_DISTANCE * LIGHTNING_DISTANCE + if (event.isHead && getVoltState(event.entity) == VoltState.DOING_LIGHTNING && + event.entity.positionVector.squareDistanceTo(player.positionVector) <= LIGHTNING_DISTANCE * LIGHTNING_DISTANCE ) { chargingSince = chargingSince.editCopy { this[event.entity] = SimpleTimeMark.now() @@ -56,7 +56,8 @@ object VoltHighlighter { if (config.voltMoodMeter) RenderLivingEntityHelper.setEntityColorWithNoHurtTime( - entity, when (state) { + entity, + when (state) { VoltState.FRIENDLY -> 0x8000FF00.toInt() VoltState.DOING_LIGHTNING -> 0x800000FF.toInt() VoltState.HOSTILE -> 0x80FF0000.toInt() @@ -77,9 +78,9 @@ object VoltHighlighter { val dischargeTimeLeft = CHARGE_TIME - dischargingSince.passedSince() if (dischargeTimeLeft > Duration.ZERO) { event.drawDynamicText( - event.exactLocation(entity).add(y = 2.5), + event.exactLocation(entity).up(2.5), "§eLightning: ${dischargeTimeLeft.format(showMilliSeconds = true)}", - 2.5 + 2.5, ) } } @@ -91,11 +92,11 @@ object VoltHighlighter { FRIENDLY, HOSTILE, DOING_LIGHTNING, - ; } private fun getVoltState(itemStack: ItemStack): VoltState { return when (itemStack.getSkullTexture()) { + // TODO: Move these textures to the repo "ewogICJ0aW1lc3RhbXAiIDogMTY3Mzg4MzU3MjAzNSwKICAicHJvZmlsZUlkIiA6ICI0MDU4NDhjMmJjNTE0ZDhkOThkOTJkMGIwYzhiZDQ0YiIsCiAgInByb2ZpbGVOYW1lIiA6ICJMb3ZlT3dPIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2UxYjFiZmI1MzZiNjQxNmIyNmEyODNkMmQ4YWQ0YjE3NzFiYmU1Yjc2ODk2ZTI3MjdkNWU4MzNiYzg5NDk4MmQiLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ==" -> { VoltState.DOING_LIGHTNING } diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/area/dreadfarm/WoodenButtonsHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/area/dreadfarm/WoodenButtonsHelper.kt new file mode 100644 index 000000000000..d3fbefa999a7 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/rift/area/dreadfarm/WoodenButtonsHelper.kt @@ -0,0 +1,191 @@ +package at.hannibal2.skyhanni.features.rift.area.dreadfarm + +import at.hannibal2.skyhanni.api.event.HandleEvent +import at.hannibal2.skyhanni.data.ClickType +import at.hannibal2.skyhanni.data.IslandGraphs +import at.hannibal2.skyhanni.data.jsonobjects.repo.RiftWoodenButtonsJson +import at.hannibal2.skyhanni.data.model.GraphNode +import at.hannibal2.skyhanni.data.model.GraphNodeTag +import at.hannibal2.skyhanni.events.BlockClickEvent +import at.hannibal2.skyhanni.events.ItemClickEvent +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent +import at.hannibal2.skyhanni.events.LorenzTickEvent +import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent +import at.hannibal2.skyhanni.events.RepositoryReloadEvent +import at.hannibal2.skyhanni.features.rift.RiftAPI +import at.hannibal2.skyhanni.features.rift.RiftAPI.isBlowgun +import at.hannibal2.skyhanni.features.rift.everywhere.EnigmaSoulWaypoints.soulLocations +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.BlockUtils.getBlockAt +import at.hannibal2.skyhanni.utils.BlockUtils.getBlockStateAt +import at.hannibal2.skyhanni.utils.ColorUtils.toChromaColor +import at.hannibal2.skyhanni.utils.LocationUtils.canBeSeen +import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer +import at.hannibal2.skyhanni.utils.LorenzVec +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.SimpleTimeMark +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern +import net.minecraft.block.BlockButtonWood +import net.minecraft.init.Blocks +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration.Companion.seconds + +@SkyHanniModule +object WoodenButtonsHelper { + + private val config get() = RiftAPI.config.enigmaSoulWaypoints + + private val patternGroup = RepoPattern.group("rift.area.dreadfarm.buttons") + + /** + * REGEX-TEST: §eYou have hit §r§b1/56 §r§eof the wooden buttons! + * REGEX-TEST: §eYou have hit §r§b10/56 §r§eof the wooden buttons! + */ + private val buttonHitPattern by patternGroup.pattern( + "hit", + "§eYou have hit §r§b\\d+/56 §r§eof the wooden buttons!", + ) + + private var buttonLocations = mapOf>() + private var hitButtons = mutableSetOf() + private var lastHitButton: LorenzVec? = null + private var currentSpot: GraphNode? = null + private var lastBlowgunFire = SimpleTimeMark.farPast() + + @SubscribeEvent + fun onRepoReload(event: RepositoryReloadEvent) { + val data = event.getConstant("rift/RiftWoodenButtons") + buttonLocations = mutableMapOf>().apply { + data.houses.forEach { (houseName, spots) -> + spots.forEach { spot -> + this["$houseName House:${spot.position}"] = spot.buttons + } + } + } + } + + @SubscribeEvent + fun onWorldChange(event: LorenzWorldChangeEvent) { + hitButtons.clear() + RiftAPI.allButtonsHit = false + currentSpot = null + } + + @SubscribeEvent + fun onTick(event: LorenzTickEvent) { + findClosestSpot() + checkBlowgunActivatedButtons() + } + + private fun findClosestSpot() { + if (!showButtons()) return + val graph = IslandGraphs.currentIslandGraph ?: return + + val closestNode = graph.nodes + .filter { it.tags.contains(GraphNodeTag.RIFT_BUTTONS_QUEST) } + .filter { node -> + val spotName = "${node.name}:${node.position}" + val buttonsAtSpot = buttonLocations[spotName] ?: return@filter false + buttonsAtSpot.any { !hitButtons.contains(it) } + } + .minByOrNull { it.position.distanceToPlayer() } + + if (closestNode != currentSpot) { + currentSpot = closestNode + currentSpot?.let { + IslandGraphs.pathFind( + it.position, + "Button Spot", + config.color.toChromaColor(), + condition = { config.showPathFinder && config.showButtonsHelper }, + ) + } + } + } + + @HandleEvent + fun onBlockClick(event: BlockClickEvent) { + if (!checkButtons()) return + + val location = event.position + if (location.getBlockAt() == Blocks.wooden_button && !hitButtons.contains(location)) { + lastHitButton = event.position + } + } + + @HandleEvent + fun onItemClick(event: ItemClickEvent) { + if (!checkButtons()) return + if (event.clickType != ClickType.RIGHT_CLICK) return + if (!event.itemInHand.isBlowgun) return + lastBlowgunFire = SimpleTimeMark.now() + } + + private fun checkBlowgunActivatedButtons() { + if (lastBlowgunFire.passedSince() > 2.5.seconds) return + buttonLocations.values.flatten().forEach { buttonLocation -> + val blockState = buttonLocation.getBlockStateAt() + if (blockState.block is BlockButtonWood && + blockState.getValue(BlockButtonWood.POWERED) == true && + buttonLocation.canBeSeen(1..3) && + lastHitButton != buttonLocation && + !hitButtons.contains(buttonLocation) + ) { + lastHitButton = buttonLocation + addLastHitButton() + } + } + } + + private fun addLastHitButton() { + if (lastHitButton !in hitButtons) { + lastHitButton?.let { hitButtons.add(it) } + } + } + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + if (!checkButtons()) return + + buttonHitPattern.matchMatcher(event.message) { + addLastHitButton() + } + + if (event.message != "§eYou've hit all §r§b56 §r§ewooden buttons!") return + RiftAPI.allButtonsHit = true + hitButtons = buttonLocations.values.flatten().toMutableSet() + soulLocations["Buttons"]?.let { + IslandGraphs.pathFind( + it, + "Buttons Enigma Soul", + config.color.toChromaColor(), + condition = { config.showPathFinder }, + ) + } + } + + @SubscribeEvent + fun onRenderWorld(event: LorenzRenderWorldEvent) { + if (!showButtons()) return + + val spot = currentSpot ?: return + val distance = spot.position.distanceToPlayer() + if (distance > 2.5) { + event.drawDynamicText(spot.position.add(y = 1), "Hit Buttons Here!", 1.25) + } + + if (distance > 15.0) return + val spotName = "${spot.name}:${spot.position}" + buttonLocations[spotName]?.forEach { button -> + if (!hitButtons.contains(button)) { + event.drawWaypointFilled(button, config.color.toChromaColor(), inverseAlphaScale = true) + } + } + } + + private fun checkButtons() = RiftAPI.inRift() && !RiftAPI.allButtonsHit + fun showButtons() = checkButtons() && RiftAPI.trackingButtons && config.showButtonsHelper +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/area/livingcave/LivingCaveDefenseBlocks.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/area/livingcave/LivingCaveDefenseBlocks.kt index 275ca3573ac2..dd5910b58c79 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/rift/area/livingcave/LivingCaveDefenseBlocks.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/rift/area/livingcave/LivingCaveDefenseBlocks.kt @@ -17,8 +17,9 @@ import at.hannibal2.skyhanni.utils.LocationUtils.distanceTo import at.hannibal2.skyhanni.utils.LorenzVec import at.hannibal2.skyhanni.utils.RenderUtils.draw3DLine 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.getLorenzVec +import at.hannibal2.skyhanni.utils.RenderUtils.exactLocation import net.minecraft.client.entity.EntityOtherPlayerMP import net.minecraft.util.EnumParticleTypes import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @@ -140,18 +141,16 @@ object LivingCaveDefenseBlocks { fun onRenderWorld(event: LorenzRenderWorldEvent) { if (!isEnabled()) return - for ((block, time) in movingBlocks) { if (block.hidden) continue if (time > System.currentTimeMillis()) { val location = block.location event.drawWaypointFilled(location, color) - event.draw3DLine( - block.entity.getLorenzVec().add(y = 0.5), - location.add(0.5, 0.5, 0.5), + event.drawLineToEye( + location.blockCenter(), color, 1, - false + false, ) } } @@ -161,8 +160,8 @@ object LivingCaveDefenseBlocks { event.drawWaypointFilled(location, color) event.draw3DLine( - block.entity.getLorenzVec().add(y = 0.5), - location.add(0.5, 0.5, 0.5), + event.exactLocation(block.entity).up(0.5), + location.blockCenter(), color, 3, true, diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/area/livingcave/LivingCaveLivingMetalHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/area/livingcave/LivingCaveLivingMetalHelper.kt index 3b64f0fb1c95..08079849e11e 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/rift/area/livingcave/LivingCaveLivingMetalHelper.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/rift/area/livingcave/LivingCaveLivingMetalHelper.kt @@ -1,6 +1,8 @@ package at.hannibal2.skyhanni.features.rift.area.livingcave +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.data.ClickType +import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.events.BlockClickEvent import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent import at.hannibal2.skyhanni.events.ReceiveParticleEvent @@ -8,8 +10,8 @@ import at.hannibal2.skyhanni.events.ServerBlockChangeEvent import at.hannibal2.skyhanni.events.TitleReceivedEvent import at.hannibal2.skyhanni.features.rift.RiftAPI import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.ColorUtils.toChromaColor import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer -import at.hannibal2.skyhanni.utils.LorenzColor import at.hannibal2.skyhanni.utils.LorenzVec import at.hannibal2.skyhanni.utils.RenderUtils.drawWaypointFilled import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @@ -22,7 +24,7 @@ object LivingCaveLivingMetalHelper { private var pair: Pair? = null private var startTime = 0L - @SubscribeEvent + @HandleEvent(onlyOnIsland = IslandType.THE_RIFT) fun onBlockClick(event: BlockClickEvent) { if (!isEnabled()) return if (event.clickType == ClickType.LEFT_CLICK) { @@ -72,8 +74,8 @@ object LivingCaveLivingMetalHelper { } else b event.drawWaypointFilled( location, - LorenzColor.AQUA.toColor(), - seeThroughBlocks = location.distanceToPlayer() < 10 + color, + seeThroughBlocks = location.distanceToPlayer() < 10, ) } @@ -97,5 +99,7 @@ object LivingCaveLivingMetalHelper { } } + val color get() = config.color.get().toChromaColor() + fun isEnabled() = RiftAPI.inRift() && (RiftAPI.inLivingCave() || RiftAPI.inLivingStillness()) && config.enabled } diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/area/livingcave/LivingMetalSuitProgress.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/area/livingcave/LivingMetalSuitProgress.kt index 9c65a273e867..913cfc4bf1a7 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/rift/area/livingcave/LivingMetalSuitProgress.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/rift/area/livingcave/LivingMetalSuitProgress.kt @@ -46,14 +46,18 @@ object LivingMetalSuitProgress { if (config.compactWhenMaxed && isMaxed) return@buildList for ((stack, progress) in progressMap.entries.reversed()) { - add(buildList { - add(" §7- ") - add(stack) - add("${stack.displayName}: ") - add(progress?.let { - drawProgressBar(progress) + " §b${LorenzUtils.formatPercentage(progress)}" - } ?: "§cStart upgrading it!") - }) + add( + buildList { + add(" §7- ") + add(stack) + add("${stack.displayName}: ") + add( + progress?.let { + drawProgressBar(progress) + " §b${LorenzUtils.formatPercentage(progress)}" + } ?: "§cStart upgrading it!" + ) + } + ) } } @@ -63,9 +67,12 @@ object LivingMetalSuitProgress { val old = progressMap progressMap = buildMap { for (armor in InventoryUtils.getArmor().filterNotNull()) { - put(armor, armor.getLivingMetalProgress()?.toDouble()?.let { - it.coerceAtMost(100.0) / 100 - }) + put( + armor, + armor.getLivingMetalProgress()?.toDouble()?.let { + it.coerceAtMost(100.0) / 100 + } + ) } } if (old != progressMap) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/area/mirrorverse/RiftUpsideDownParkour.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/area/mirrorverse/RiftUpsideDownParkour.kt index ac12b43c00cd..2ff0eac9931d 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/rift/area/mirrorverse/RiftUpsideDownParkour.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/rift/area/mirrorverse/RiftUpsideDownParkour.kt @@ -24,10 +24,10 @@ object RiftUpsideDownParkour { fun onRepoReload(event: RepositoryReloadEvent) { val data = event.getConstant("RiftUpsideDownParkour") parkourHelper = ParkourHelper( - data.locations.map { it.add(-1.0, -1.0, -1.0) },// TODO remove offset. change repo instead + data.locations.map { it.add(-1.0, -1.0, -1.0) }, // TODO remove offset. change repo instead data.shortCuts, platformSize = 2.0, - detectionRange = 2.0 + detectionRange = 2.0, ) updateConfig() } diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/area/stillgorechateau/RiftBloodEffigies.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/area/stillgorechateau/RiftBloodEffigies.kt index ccb432f61905..11de17b148c2 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/rift/area/stillgorechateau/RiftBloodEffigies.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/rift/area/stillgorechateau/RiftBloodEffigies.kt @@ -90,7 +90,7 @@ object RiftBloodEffigies { val split = hearts.split("§").drop(1) for ((index, s) in split.withIndex()) { - val time = effigiesTimes[index]!! + val time = effigiesTimes[index] ?: continue if (time.isInPast()) { if (s == "7") { @@ -131,7 +131,7 @@ object RiftBloodEffigies { for ((index, location) in locations.withIndex()) { val name = "Effigy #${index + 1}" - val duration = effigiesTimes[index]!! + val duration = effigiesTimes[index] ?: continue if (duration.isFarPast()) { if (config.unknownTime) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/area/westvillage/RiftGunthersRace.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/area/westvillage/RiftGunthersRace.kt new file mode 100644 index 000000000000..5a3638101a71 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/rift/area/westvillage/RiftGunthersRace.kt @@ -0,0 +1,132 @@ +package at.hannibal2.skyhanni.features.rift.area.westvillage + +import at.hannibal2.skyhanni.data.jsonobjects.repo.ParkourJson +import at.hannibal2.skyhanni.events.CheckRenderEntityEvent +import at.hannibal2.skyhanni.events.ConfigLoadEvent +import at.hannibal2.skyhanni.events.IslandChangeEvent +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent +import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent +import at.hannibal2.skyhanni.events.RepositoryReloadEvent +import at.hannibal2.skyhanni.features.rift.RiftAPI +import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule +import at.hannibal2.skyhanni.utils.ColorUtils.toChromaColor +import at.hannibal2.skyhanni.utils.ConditionalUtils +import at.hannibal2.skyhanni.utils.EntityUtils.isNPC +import at.hannibal2.skyhanni.utils.ParkourHelper +import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern +import net.minecraft.client.entity.EntityOtherPlayerMP +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +@SkyHanniModule +object RiftGunthersRace { + + private val config get() = RiftAPI.config.area.westVillage.gunthersRace + private var parkourHelper: ParkourHelper? = null + + private val patternGroup = RepoPattern.group("rift.area.westvillage.riftrace") + + /** + * REGEX-TEST: §3§lRIFT RACING §r§eRace started! Good luck! + */ + private val raceStartedPattern by patternGroup.pattern( + "start", + "§3§lRIFT RACING §r§eRace started! Good luck!" + ) + + /** + * REGEX-TEST: §3§lRIFT RACING §r§eRace finished in 00:36.539! + * REGEX-TEST: §3§lRIFT RACING §r§eRace finished in §r§300:32.794§r§e! §r§3§lPERSONAL BEST! + */ + private val raceFinishedPattern by patternGroup.pattern( + "finish", + "§3§lRIFT RACING §r§eRace finished in \\d+:\\d+.\\d+!.*" + ) + + /** + * REGEX-TEST: §3§lRIFT RACING §r§cRace cancelled! + * REGEX-TEST: §3§lRIFT RACING §r§cRace cancelled! Time limit reached! + * REGEX-TEST: §3§lRIFT RACING §r§cRace cancelled! You left the racing area! + */ + private val raceCancelledPattern by patternGroup.pattern( + "cancel", + "§3§lRIFT RACING §r§cRace cancelled!.*" + ) + + @SubscribeEvent + fun onIslandChange(event: IslandChangeEvent) { + parkourHelper?.reset() + } + + @SubscribeEvent + fun onWorldChange(event: LorenzWorldChangeEvent) { + RiftAPI.inRiftRace = false + } + + @SubscribeEvent + fun onRepoReload(event: RepositoryReloadEvent) { + val data = event.getConstant("rift/RiftRace") + parkourHelper = ParkourHelper( + data.locations, + data.shortCuts, + detectionRange = 5.0, + goInOrder = true, + ) + updateConfig() + } + + @SubscribeEvent + fun onConfigLoad(event: ConfigLoadEvent) { + ConditionalUtils.onToggle(config.rainbowColor, config.monochromeColor, config.lookAhead) { + updateConfig() + } + } + + private fun updateConfig() { + parkourHelper?.run { + rainbowColor = config.rainbowColor.get() + monochromeColor = config.monochromeColor.get().toChromaColor() + lookAhead = config.lookAhead.get() + 1 + } + } + + @SubscribeEvent + fun onChat(event: LorenzChatEvent) { + if (!isEnabled()) return + + raceStartedPattern.matchMatcher(event.message) { + RiftAPI.inRiftRace = true + } + raceCancelledPattern.matchMatcher(event.message) { + parkourHelper?.reset() + RiftAPI.inRiftRace = false + } + raceFinishedPattern.matchMatcher(event.message) { + parkourHelper?.reset() + RiftAPI.inRiftRace = false + } + } + + @SubscribeEvent + fun onCheckRender(event: CheckRenderEntityEvent<*>) { + if (!isEnabled()) return + if (!config.hidePlayers) return + if (!RiftAPI.inRiftRace) return + + val entity = event.entity + if (entity is EntityOtherPlayerMP && !entity.isNPC()) { + event.cancel() + } + } + + @SubscribeEvent + fun onRenderWorld(event: LorenzRenderWorldEvent) { + if (!isEnabled() || !RiftAPI.inRiftRace) return + + parkourHelper?.render(event) + } + + fun isEnabled() = + RiftAPI.inRift() && RiftAPI.inWestVillage() && config.enabled +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/area/westvillage/VerminHighlighter.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/area/westvillage/VerminHighlighter.kt index 3fa6af42fc0e..c08594c26ea9 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/rift/area/westvillage/VerminHighlighter.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/rift/area/westvillage/VerminHighlighter.kt @@ -11,7 +11,6 @@ import at.hannibal2.skyhanni.utils.ConditionalUtils import at.hannibal2.skyhanni.utils.EntityUtils import at.hannibal2.skyhanni.utils.EntityUtils.hasSkullTexture import at.hannibal2.skyhanni.utils.InventoryUtils -import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.baseMaxHealth import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName import at.hannibal2.skyhanni.utils.TimeLimitedSet @@ -63,10 +62,8 @@ object VerminHighlighter { else -> false } - private fun inArea() = LorenzUtils.skyBlockArea.let { it == "West Village" || it == "Infested House" } - private fun hasItemInHand() = InventoryUtils.itemInHandId == "TURBOMAX_VACUUM".asInternalName() - fun isEnabled() = RiftAPI.inRift() && inArea() && config.enabled && hasItemInHand() + fun isEnabled() = RiftAPI.inRift() && RiftAPI.inWestVillage() && config.enabled && hasItemInHand() } diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/area/westvillage/VerminTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/area/westvillage/VerminTracker.kt index e47fe8002b6d..0f397e6e348f 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/rift/area/westvillage/VerminTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/rift/area/westvillage/VerminTracker.kt @@ -13,7 +13,6 @@ import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName import at.hannibal2.skyhanni.utils.ItemUtils.getLore -import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher @@ -56,8 +55,9 @@ object VerminTracker { private val config get() = RiftAPI.config.area.westVillage.verminTracker - private val tracker = SkyHanniTracker("Vermin Tracker", { Data() }, { it.rift.verminTracker }) - { drawDisplay(it) } + private val tracker = SkyHanniTracker("Vermin Tracker", { Data() }, { it.rift.verminTracker }) { + drawDisplay(it) + } class Data : TrackerData() { @@ -162,9 +162,7 @@ object VerminTracker { @SubscribeEvent fun onRenderOverlay(event: GuiRenderEvent) { if (!isEnabled()) return - if (!config.showOutsideWestVillage && - !LorenzUtils.skyBlockArea.let { it == "Infested House" || it == "West Village" } - ) return + if (!config.showOutsideWestVillage && !RiftAPI.inWestVillage()) return if (!config.showWithoutVacuum && !hasVacuum) return tracker.renderDisplay(config.position) diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/CruxTalismanDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/CruxTalismanDisplay.kt index c333550f6349..9e92b0807129 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/CruxTalismanDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/CruxTalismanDisplay.kt @@ -28,7 +28,7 @@ object CruxTalismanDisplay { ".*(?§[0-9a-z][IV1-4-]+)\\s+(?§[0-9a-z]\\w+)§[0-9a-z]:\\s*(?§[0-9a-z](?:§[0-9a-z])?MAXED|§[0-9a-z]\\d+§[0-9a-z]/§[0-9a-z]\\d+).*" ) - private val partialName = "CRUX_TALISMAN" + private const val PARTIAL_NAME = "CRUX_TALISMAN" private var display = emptyList>() private val displayLine = mutableListOf() private val bonusesLine = mutableListOf() @@ -91,7 +91,7 @@ object CruxTalismanDisplay { fun onSecondPassed(event: SecondPassedEvent) { if (!isEnabled()) return if (!event.repeatSeconds(2)) return - if (!InventoryUtils.getItemsInOwnInventory().any { it.getInternalName().startsWith(partialName) }) return + if (!InventoryUtils.getItemsInOwnInventory().any { it.getInternalName().startsWith(PARTIAL_NAME) }) return displayLine.clear() bonusesLine.clear() diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/EnigmaSoulWaypoints.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/EnigmaSoulWaypoints.kt index 2a4613f7a7bc..24b254736e73 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/EnigmaSoulWaypoints.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/EnigmaSoulWaypoints.kt @@ -10,6 +10,7 @@ import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent import at.hannibal2.skyhanni.events.RepositoryReloadEvent import at.hannibal2.skyhanni.events.render.gui.ReplaceItemEvent import at.hannibal2.skyhanni.features.rift.RiftAPI +import at.hannibal2.skyhanni.features.rift.area.dreadfarm.WoodenButtonsHelper import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils import at.hannibal2.skyhanni.utils.ColorUtils.toChromaColor @@ -36,7 +37,7 @@ object EnigmaSoulWaypoints { private val config get() = RiftAPI.config.enigmaSoulWaypoints private var inInventory = false - private var soulLocations = mapOf() + var soulLocations = mapOf() private val trackedSouls = mutableListOf() private val inventoryUnfound = mutableListOf() private var adding = true @@ -89,6 +90,9 @@ object EnigmaSoulWaypoints { if (event.slotId == 31 && inventoryUnfound.isNotEmpty()) { event.makePickblock() + if (inventoryUnfound.contains("Buttons")) { + RiftAPI.trackingButtons = !RiftAPI.trackingButtons + } if (adding) { trackedSouls.addAll(inventoryUnfound) adding = false @@ -107,11 +111,22 @@ object EnigmaSoulWaypoints { val name = split.last() if (!soulLocations.contains(name)) return + if (name == "Buttons") { + RiftAPI.trackingButtons = !RiftAPI.trackingButtons + } + if (!trackedSouls.contains(name)) { ChatUtils.chat("§5Tracking the $name Enigma Soul!", prefixColor = "§5") if (config.showPathFinder) { soulLocations[name]?.let { - IslandGraphs.pathFind(it, config.color.toChromaColor(), condition = { config.showPathFinder }) + if (!(name == "Buttons" && WoodenButtonsHelper.showButtons())) { + IslandGraphs.pathFind( + it, + "$name Enigma Soul", + config.color.toChromaColor(), + condition = { config.showPathFinder } + ) + } } } trackedSouls.add(name) @@ -148,7 +163,7 @@ object EnigmaSoulWaypoints { for (soul in trackedSouls) { soulLocations[soul]?.let { event.drawWaypointFilled(it, config.color.toChromaColor(), seeThroughBlocks = true, beacon = true) - event.drawDynamicText(it.add(y = 1), "§5${soul.removeSuffix(" Soul")} Soul", 1.5) + event.drawDynamicText(it.up(), "§5${soul.removeSuffix(" Soul")} Soul", 1.5) } } } @@ -188,6 +203,9 @@ object EnigmaSoulWaypoints { if (closestSoul in trackedSouls) { trackedSouls.remove(closestSoul) ChatUtils.chat("§5Found the $closestSoul Enigma Soul!", prefixColor = "§5") + if (closestSoul == "Buttons") { + RiftAPI.trackingButtons = false + } } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/PunchcardHighlight.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/PunchcardHighlight.kt index 10be4a54abd9..d1fcea62e871 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/PunchcardHighlight.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/PunchcardHighlight.kt @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.features.rift.everywhere import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.data.HypixelData import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.data.mob.MobData @@ -169,9 +170,8 @@ object PunchcardHighlight { } } - @SubscribeEvent + @HandleEvent(onlyOnIsland = IslandType.THE_RIFT) fun onPunch(event: EntityClickEvent) { - if (!RiftAPI.inRift()) return val entity = event.clickedEntity if (entity !is AbstractClientPlayer) return if (entity.isNPC()) return diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/RiftTimer.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/RiftTimer.kt index 21f13c1560ee..94fbe5c3e3e8 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/RiftTimer.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/rift/everywhere/RiftTimer.kt @@ -1,20 +1,22 @@ package at.hannibal2.skyhanni.features.rift.everywhere -import at.hannibal2.skyhanni.events.ActionBarUpdateEvent +import at.hannibal2.skyhanni.data.ActionBarStatsData +import at.hannibal2.skyhanni.events.ActionBarValueUpdateEvent import at.hannibal2.skyhanni.events.ConfigLoadEvent import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent import at.hannibal2.skyhanni.events.entity.EntityHealthDisplayEvent import at.hannibal2.skyhanni.features.rift.RiftAPI import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ConditionalUtils import at.hannibal2.skyhanni.utils.LorenzUtils -import at.hannibal2.skyhanni.utils.RegexUtils.matchFirst import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings import at.hannibal2.skyhanni.utils.TimeUtils import at.hannibal2.skyhanni.utils.TimeUtils.format import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern +import net.minecraft.client.Minecraft import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import kotlin.time.Duration import kotlin.time.Duration.Companion.minutes @@ -26,11 +28,6 @@ object RiftTimer { private val config get() = RiftAPI.config.timer private val repoGroup = RepoPattern.group("rift.everywhere") - private val timePattern by repoGroup.pattern( - "timer", - "§(?[a7])(?