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