diff options
author | nea <nea@nea.moe> | 2023-02-05 22:55:27 +0100 |
---|---|---|
committer | nea <nea@nea.moe> | 2023-02-05 22:55:27 +0100 |
commit | ea0d8c2c85e29f84ac59b86e20b6a7546db63dd8 (patch) | |
tree | 77c9bf3653aa0362170d2b10c4acaf6346d46ef4 | |
parent | a321287e85fb577745647d12049fc1d24997717c (diff) | |
parent | d0f024a0cd2525bc4a79308c4f7275ea2a308ab2 (diff) | |
download | NotEnoughUpdates-ea0d8c2c85e29f84ac59b86e20b6a7546db63dd8.tar.gz NotEnoughUpdates-ea0d8c2c85e29f84ac59b86e20b6a7546db63dd8.tar.bz2 NotEnoughUpdates-ea0d8c2c85e29f84ac59b86e20b6a7546db63dd8.zip |
Merge remote-tracking branch 'origin/master' into museumthing
122 files changed, 3825 insertions, 1140 deletions
diff --git a/.idea/copyright/NotEnoughUpdates.xml b/.idea/copyright/NotEnoughUpdates.xml index c1c6368d..d3ac04b2 100644 --- a/.idea/copyright/NotEnoughUpdates.xml +++ b/.idea/copyright/NotEnoughUpdates.xml @@ -1,7 +1,7 @@ <component name="CopyrightManager"> <copyright> <option name="allowReplaceRegexp" value="Copyright" /> - <option name="notice" value="Copyright (C) 2023 NotEnoughUpdates contributors This file is part of NotEnoughUpdates. NotEnoughUpdates is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. NotEnoughUpdates is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>." /> + <option name="notice" value="Copyright (C) &#36;originalComment.match("Copyright \(C\) (\d+)",1,"-")&#36;today.year NotEnoughUpdates contributors This file is part of NotEnoughUpdates. NotEnoughUpdates is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. NotEnoughUpdates is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>." /> <option name="myName" value="NotEnoughUpdates" /> </copyright> </component> diff --git a/Update Notes/2.1.1.md b/Update Notes/2.1.1.md index 7e41860a..eb6fcc31 100644 --- a/Update Notes/2.1.1.md +++ b/Update Notes/2.1.1.md @@ -10,6 +10,7 @@ - Added Katsitting recipe upgrade - nea89 - Added cheapest museum item overlay - Lulonaut - Added Frozen Treasure Highlighter - heyngra +- Added SkyBlock levels to PV - efefury ### **Minor Changes:** diff --git a/annotations/build.gradle.kts b/annotations/build.gradle.kts new file mode 100644 index 00000000..c9e13173 --- /dev/null +++ b/annotations/build.gradle.kts @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2023 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +plugins { + kotlin("jvm") + java +} + +repositories { + mavenCentral() +} + +tasks.withType<JavaCompile> { + if (JavaVersion.current().isJava9Compatible) { + options.release.set(8) + } +} + +dependencies { + implementation(kotlin("stdlib-jdk8")) + implementation("com.google.devtools.ksp:symbol-processing-api:1.8.0-1.0.8") + implementation("com.squareup:kotlinpoet:1.12.0") + implementation("com.squareup:kotlinpoet-ksp:1.12.0") +} + + + + diff --git a/annotations/src/main/kotlin/io/github/moulberry/notenoughupdates/autosubscribe/NEUAutoSubscribe.kt b/annotations/src/main/kotlin/io/github/moulberry/notenoughupdates/autosubscribe/NEUAutoSubscribe.kt new file mode 100644 index 00000000..1ba6be99 --- /dev/null +++ b/annotations/src/main/kotlin/io/github/moulberry/notenoughupdates/autosubscribe/NEUAutoSubscribe.kt @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2023 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.autosubscribe + +@Retention(AnnotationRetention.SOURCE) +@Target(AnnotationTarget.CLASS) +annotation class NEUAutoSubscribe diff --git a/annotations/src/main/kotlin/io/github/moulberry/notenoughupdates/autosubscribe/NEUAutoSymbolProcessor.kt b/annotations/src/main/kotlin/io/github/moulberry/notenoughupdates/autosubscribe/NEUAutoSymbolProcessor.kt new file mode 100644 index 00000000..157749d0 --- /dev/null +++ b/annotations/src/main/kotlin/io/github/moulberry/notenoughupdates/autosubscribe/NEUAutoSymbolProcessor.kt @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2023 Linnea Gräf + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.autosubscribe + +import com.google.devtools.ksp.getDeclaredFunctions +import com.google.devtools.ksp.getDeclaredProperties +import com.google.devtools.ksp.processing.CodeGenerator +import com.google.devtools.ksp.processing.KSPLogger +import com.google.devtools.ksp.processing.Resolver +import com.google.devtools.ksp.processing.SymbolProcessor +import com.google.devtools.ksp.symbol.ClassKind +import com.google.devtools.ksp.symbol.KSAnnotated +import com.google.devtools.ksp.symbol.KSClassDeclaration +import com.google.devtools.ksp.symbol.Modifier +import com.google.devtools.ksp.validate +import com.squareup.kotlinpoet.FileSpec +import com.squareup.kotlinpoet.FunSpec +import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy +import com.squareup.kotlinpoet.TypeSpec +import com.squareup.kotlinpoet.asTypeName +import com.squareup.kotlinpoet.ksp.toClassName +import com.squareup.kotlinpoet.ksp.writeTo +import java.util.function.Consumer +import java.util.function.Supplier + +internal class NEUAutoSymbolProcessor(val codeGenerator: CodeGenerator, val logger: KSPLogger) : SymbolProcessor { + fun collectSubscribers(elements: List<KSAnnotated>): List<NEUEventSubscriber> = buildList { + for (element in elements) { + if (element !is KSClassDeclaration) { + logger.error("@NEUAutoSubscribe is only valid on class or object declarations", element) + continue + } + if (element.typeParameters.isNotEmpty()) { + logger.error("@NEUAutoSubscribe is not valid on generic classes", element) + continue + } + val name = element.qualifiedName + if (name == null) { + logger.error("@NEUAutoSubscribe could not find name", element) + continue + } + when (element.classKind) { + ClassKind.CLASS -> { + val instanceGetter = element.getDeclaredFunctions().find { + it.simpleName.asString() == "getInstance" + } + val instanceVariable = element.getDeclaredProperties().find { + it.simpleName.asString() == "INSTANCE" + } + if (instanceGetter != null) { + val returnType = instanceGetter.returnType + if (returnType == null || !element.asStarProjectedType().isAssignableFrom(returnType.resolve())) { + logger.error( + "getInstance() does not have the expected return type ${element.asStarProjectedType()}", + instanceGetter + ) + continue + } + add(NEUEventSubscriber(InvocationKind.GET_INSTANCE, element)) + } else if (instanceVariable != null) { + val variableType = instanceVariable.type + if (!element.asStarProjectedType().isAssignableFrom(variableType.resolve())) { + logger.error( + "INSTANCE does not have expected type ${element.asStarProjectedType()}", + instanceVariable + ) + continue + } + add(NEUEventSubscriber(InvocationKind.ACCESS_INSTANCE, element)) + } else { + add(NEUEventSubscriber(InvocationKind.DEFAULT_CONSTRUCTOR, element)) + } + } + + ClassKind.OBJECT -> { + add(NEUEventSubscriber(InvocationKind.OBJECT_INSTANCE, element)) + } + + else -> { + logger.error( + "@NEUAutoSubscribe is only valid on classes and objects, not on ${element.classKind}", + element + ) + continue + } + } + } + + } + + val subscribers = mutableListOf<NEUEventSubscriber>() + override fun process(resolver: Resolver): List<KSAnnotated> { + val candidates = resolver.getSymbolsWithAnnotation(NEUAutoSubscribe::class.qualifiedName!!).toList() + val valid = candidates.filter { it.validate() } + val invalid = candidates.filter { !it.validate() } + + subscribers.addAll(collectSubscribers(valid)) + return invalid + } + + override fun finish() { + if (subscribers.isEmpty()) return + val deps = subscribers.mapNotNull { it.declaration.containingFile } + logger.info("Dependencies: $deps") + FileSpec.builder("io.github.moulberry.notenoughupdates.autosubscribe", "AutoLoad") + .addFileComment("@generated by ${NEUAutoSymbolProcessor::class.simpleName}") + .addType( + TypeSpec.objectBuilder("AutoLoad") + .addFunction( + FunSpec.builder("provide") + .addParameter( + "consumer", + Consumer::class.asTypeName() + .parameterizedBy(Supplier::class.parameterizedBy(Any::class)) + ) + .apply { + subscribers.sortedBy { it.declaration.simpleName.asString() }.forEach { (invocationKind, declaration) -> + when (invocationKind) { + InvocationKind.GET_INSTANCE -> addStatement( + "consumer.accept { %T.getInstance() }", + declaration.toClassName() + ) + + InvocationKind.OBJECT_INSTANCE -> addStatement( + "consumer.accept { %T }", + declaration.toClassName() + ) + + InvocationKind.DEFAULT_CONSTRUCTOR -> addStatement( + "consumer.accept { %T() }", + declaration.toClassName() + ) + + InvocationKind.ACCESS_INSTANCE -> addStatement( + "consumer.accept { %T.INSTANCE }", + declaration.toClassName() + ) + } + } + } + .build() + ) + .build() + ) + .build() + .writeTo(codeGenerator, aggregating = true, originatingKSFiles = deps) + } +} diff --git a/annotations/src/main/kotlin/io/github/moulberry/notenoughupdates/autosubscribe/NEUAutoSymbolProcessorProvider.kt b/annotations/src/main/kotlin/io/github/moulberry/notenoughupdates/autosubscribe/NEUAutoSymbolProcessorProvider.kt new file mode 100644 index 00000000..ef0edd88 --- /dev/null +++ b/annotations/src/main/kotlin/io/github/moulberry/notenoughupdates/autosubscribe/NEUAutoSymbolProcessorProvider.kt @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2023 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.autosubscribe + +import com.google.devtools.ksp.processing.SymbolProcessor +import com.google.devtools.ksp.processing.SymbolProcessorEnvironment +import com.google.devtools.ksp.processing.SymbolProcessorProvider + +class NEUAutoSymbolProcessorProvider : SymbolProcessorProvider { + override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor { + return NEUAutoSymbolProcessor(environment.codeGenerator, environment.logger) + } +} diff --git a/annotations/src/main/kotlin/io/github/moulberry/notenoughupdates/autosubscribe/NEUEventSubscriber.kt b/annotations/src/main/kotlin/io/github/moulberry/notenoughupdates/autosubscribe/NEUEventSubscriber.kt new file mode 100644 index 00000000..d17b6004 --- /dev/null +++ b/annotations/src/main/kotlin/io/github/moulberry/notenoughupdates/autosubscribe/NEUEventSubscriber.kt @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2023 Linnea Gräf + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.autosubscribe + +import com.google.devtools.ksp.symbol.KSClassDeclaration + +internal data class NEUEventSubscriber( + val invocationKind: InvocationKind, + val declaration: KSClassDeclaration, +) + +internal enum class InvocationKind { + GET_INSTANCE, + OBJECT_INSTANCE, + DEFAULT_CONSTRUCTOR, + ACCESS_INSTANCE, +} diff --git a/annotations/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider b/annotations/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider new file mode 100644 index 00000000..eaad70ce --- /dev/null +++ b/annotations/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider @@ -0,0 +1,20 @@ +# +# Copyright (C) 2023 NotEnoughUpdates contributors +# +# This file is part of NotEnoughUpdates. +# +# NotEnoughUpdates is free software: you can redistribute it +# and/or modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation, either +# version 3 of the License, or (at your option) any later version. +# +# NotEnoughUpdates is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. +# + +io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSymbolProcessorProvider diff --git a/build.gradle.kts b/build.gradle.kts index e9e769a8..e41aa513 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -30,8 +30,8 @@ plugins { id("com.github.johnrengelman.shadow") version "7.1.2" id("io.github.juuxel.loom-quiltflower") version "1.7.3" `maven-publish` - id("io.freefair.lombok") version "6.5.1" - kotlin("jvm") version "1.7.20" + kotlin("jvm") version "1.8.0" + id("com.google.devtools.ksp") version "1.8.0-1.0.8" } @@ -62,6 +62,7 @@ loom { pack200Provider.set(dev.architectury.pack200.java.Pack200Adapter()) mixinConfig("mixins.notenoughupdates.json") } + @Suppress("UnstableApiUsage") mixin { defaultRefmapName.set("mixins.notenoughupdates.refmap.json") } @@ -78,44 +79,43 @@ repositories { maven("https://repo.polyfrost.cc/releases") } -lombok { - version.set("1.18.24") -} - - -val shadowImplementation by configurations.creating { +val shadowImplementation: Configuration by configurations.creating { configurations.implementation.get().extendsFrom(this) } -val shadowOnly by configurations.creating { +val shadowOnly: Configuration by configurations.creating { } -val shadowApi by configurations.creating { +val shadowApi: Configuration by configurations.creating { configurations.api.get().extendsFrom(this) } -val devEnv by configurations.creating { +val devEnv: Configuration by configurations.creating { configurations.runtimeClasspath.get().extendsFrom(this) isCanBeResolved = false isCanBeConsumed = false isVisible = false } -val kotlinDependencies by configurations.creating { +val kotlinDependencies: Configuration by configurations.creating { configurations.implementation.get().extendsFrom(this) } -val oneconfigQuarantineSourceSet = sourceSets.create("oneconfig") { +val oneconfigQuarantineSourceSet: SourceSet = sourceSets.create("oneconfig") { java { srcDir(layout.projectDirectory.dir("src/main/oneconfig")) } - kotlin { +} + +configurations { + val main = getByName(sourceSets.main.get().compileClasspathConfigurationName) + "oneconfigImplementation" { + extendsFrom(main) } } dependencies { - implementation("org.projectlombok:lombok:1.18.22") minecraft("com.mojang:minecraft:1.8.9") mappings("de.oceanlabs.mcp:mcp_stable:22-1.8.9") forge("net.minecraftforge:forge:1.8.9-11.15.1.2318-1.8.9") @@ -126,21 +126,27 @@ dependencies { runtimeOnly("cc.polyfrost:oneconfig-wrapper-launchwrapper:1.0.0-alpha+") // Should be included in jar } - "oneconfigImplementation"(sourceSets.main.get().output) - "oneconfigImplementation"(sourceSets.main.get().compileClasspath) "oneconfigCompileOnly"(project(":oneconfigquarantine", configuration = "namedElements")) + "oneconfigImplementation"(sourceSets.main.get().output) "runtimeOnly"(oneconfigQuarantineSourceSet.output) // Please keep this version in sync with KotlinLoadingTweaker - implementation(enforcedPlatform("org.jetbrains.kotlin:kotlin-bom:1.7.21")) + implementation(enforcedPlatform("org.jetbrains.kotlin:kotlin-bom:1.8.0")) kotlinDependencies(kotlin("stdlib")) + compileOnly(ksp(project(":annotations"))!!) + compileOnly("org.projectlombok:lombok:1.18.24") + annotationProcessor("org.projectlombok:lombok:1.18.24") + "oneconfigAnnotationProcessor"("org.projectlombok:lombok:1.18.24") + shadowImplementation("org.spongepowered:mixin:0.7.11-SNAPSHOT") { isTransitive = false // Dependencies of mixin are already bundled by minecraft } annotationProcessor("org.spongepowered:mixin:0.8.4-SNAPSHOT") + + @Suppress("VulnerableLibrariesLocal") shadowApi("info.bliki.wiki:bliki-core:3.1.0") - testImplementation("org.junit.jupiter:junit-jupiter:5.8.2") + testImplementation("org.junit.jupiter:junit-jupiter:5.9.2") testAnnotationProcessor("org.spongepowered:mixin:0.8.4-SNAPSHOT") // modImplementation("io.github.notenoughupdates:MoulConfig:0.0.1") @@ -151,15 +157,24 @@ dependencies { java { withSourcesJar() - toolchain.languageVersion.set(JavaLanguageVersion.of(8)) +// toolchain.languageVersion.set(JavaLanguageVersion.of(8)) } // Tasks: tasks.withType(JavaCompile::class) { options.encoding = "UTF-8" + options.isFork = true + if (JavaVersion.current().isJava9Compatible) + options.release.set(8) +} +tasks.named("compileOneconfigJava", JavaCompile::class) { + doFirst { + println("oneconfig args: ${this@named.options.compilerArgs}") + } } + tasks.named<Test>("test") { useJUnitPlatform() } @@ -189,12 +204,16 @@ val remapJar by tasks.named<net.fabricmc.loom.task.RemapJarTask>("remapJar") { } } +tasks.remapSourcesJar { + this.enabled = false +} + /* Bypassing https://github.com/johnrengelman/shadow/issues/111 */ // Use Zip instead of Jar as to not include META-INF val kotlinDependencyCollectionJar by tasks.creating(Zip::class) { archiveFileName.set("kotlin-libraries-wrapped.jar") destinationDirectory.set(project.layout.buildDirectory.dir("kotlinwrapper")) - from(kotlinDependencies.files) + from(kotlinDependencies) into("neu-kotlin-libraries-wrapped") } @@ -227,6 +246,15 @@ tasks.processResources { } } +idea { + module { + // Not using += due to https://github.com/gradle/gradle/issues/8749 + sourceDirs = sourceDirs + file("build/generated/ksp/main/kotlin") // or tasks["kspKotlin"].destination + testSourceDirs = testSourceDirs + file("build/generated/ksp/test/kotlin") + generatedSourceDirs = generatedSourceDirs + file("build/generated/ksp/main/kotlin") + file("build/generated/ksp/test/kotlin") + } +} + sourceSets.main { output.setResourcesDir(file("$buildDir/classes/java/main")) } diff --git a/buildSrc/src/main/kotlin/neubs/buildflags.kt b/buildSrc/src/main/kotlin/neubs/buildflags.kt index 6b7ab489..27c4bbcf 100644 --- a/buildSrc/src/main/kotlin/neubs/buildflags.kt +++ b/buildSrc/src/main/kotlin/neubs/buildflags.kt @@ -19,8 +19,13 @@ package neubs +import org.gradle.api.DefaultTask import org.gradle.api.Plugin import org.gradle.api.Project +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.MapProperty +import org.gradle.api.tasks.* +import org.gradle.kotlin.dsl.create import org.gradle.kotlin.dsl.the import java.nio.charset.StandardCharsets import java.util.* @@ -28,22 +33,16 @@ import java.util.* const val NEU_BUILDFLAGS_PREFIX = "neu.buildflags." class NEUBuildFlags : Plugin<Project> { + override fun apply(target: Project) { val props = target.properties.filterKeys { it.startsWith(NEU_BUILDFLAGS_PREFIX) }.mapValues { it.value as String } target.extensions.add("buildflags", Extension(props)) - target.tasks.create("generateBuildFlags") { - outputs.upToDateWhen { false } - val t = target.layout.buildDirectory.file("buildflags.properties") - outputs.file(t) - doLast { - val p = Properties() - p.putAll(props) - t.get().asFile.writer(StandardCharsets.UTF_8).use { - p.store(it, "Store build time configuration for NEU") - } - } - + target.tasks.create<WriteProperties>("generateBuildFlags") { + this.encoding = StandardCharsets.UTF_8.name() + this.setProperties(props) + this.comment = "Store build time configuration for NEU" + this.setOutputFile(target.layout.buildDirectory.file("buildflags.properties")) } } diff --git a/gradle.properties b/gradle.properties index 0009739e..0eb2e107 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,7 @@ org.gradle.jvmargs=-Xmx2G +org.gradle.parallel=true +org.gradle.caching=true +kotlin.incremental.useClasspathSnapshot=true loom.platform=forge # NEU Buildflags. Please keep these flags in a commented out form while checked into version control. # See BuildFlags.java for usages of these values. diff --git a/oneconfigquarantine/build.gradle.kts b/oneconfigquarantine/build.gradle.kts index 32bc3b7c..15797e1e 100644 --- a/oneconfigquarantine/build.gradle.kts +++ b/oneconfigquarantine/build.gradle.kts @@ -1,3 +1,5 @@ +import net.fabricmc.loom.task.RemapJarTask + /* * Copyright (C) 2022 NotEnoughUpdates contributors * @@ -43,3 +45,10 @@ dependencies { modApi("cc.polyfrost:oneconfig-1.8.9-forge:0.1.0-alpha+") // Don't you just love 0.1.0-alpha+ } +tasks.withType<JavaCompile> { + this.enabled = false +} +tasks.withType<RemapJarTask> { + println(this) + this.enabled = false +} diff --git a/settings.gradle.kts b/settings.gradle.kts index a910edd3..86073a5b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -40,4 +40,5 @@ pluginManagement { } include("oneconfigquarantine") +include("annotations") rootProject.name = "NotEnoughUpdates" diff --git a/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java b/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java index 754e2dc3..5c851211 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java @@ -54,8 +54,8 @@ public class ItemPriceInformation { private static final NumberFormat format = new DecimalFormat("#,##0.#", new DecimalFormatSymbols(Locale.US)); public static String STACKSIZE_OVERRIDE = "NEU_STACKSIZE_OVERRIDE"; - public static boolean addToTooltip(List<String> tooltip, String internalname, ItemStack stack) { - return addToTooltip(tooltip, internalname, stack, true); + public static void addToTooltip(List<String> tooltip, String internalName, ItemStack stack) { + addToTooltip(tooltip, internalName, stack, true); } public static void init(File saveLocation, Gson neuGson) { @@ -92,16 +92,16 @@ public class ItemPriceInformation { } } - public static boolean addToTooltip(List<String> tooltip, String internalname, ItemStack stack, boolean useStackSize) { + public static void addToTooltip(List<String> tooltip, String internalname, ItemStack stack, boolean useStackSize) { if (stack.getTagCompound().hasKey("disableNeuTooltip") && stack.getTagCompound().getBoolean("disableNeuTooltip")) { - return false; + return; } if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.disablePriceKey && !KeybindHelper.isKeyDown(NotEnoughUpdates.INSTANCE.config.tooltipTweaks.disablePriceKeyKeybind)) { - return false; + return; } if (internalname.equals("SKYBLOCK_MENU")) { - return false; + return; } JsonObject auctionInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(internalname); JsonObject bazaarInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarInfo(internalname); @@ -207,8 +207,7 @@ public class ItemPriceInformation { } } - return added; - } else if (auctionItem) { + } else if (auctionItem && !auctionInfoErrored) { List<Integer> lines = NotEnoughUpdates.INSTANCE.config.tooltipTweaks.priceInfoAuc; boolean added = false; @@ -366,21 +365,16 @@ public class ItemPriceInformation { } } - return added; } else if (auctionInfoErrored && NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) { String message = EnumChatFormatting.RED.toString() + EnumChatFormatting.BOLD + "[NEU] API is down"; if (auctionableItems != null && !auctionableItems.isEmpty()) { if (auctionableItems.contains(internalname)) { tooltip.add(message); - return true; } } else { tooltip.add(message + " and no item data is cached"); - return true; } } - - return false; } private static String formatPrice(String label, double price) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java index 3ecf73c0..ce386b86 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java @@ -748,7 +748,7 @@ public class NEUManager { } } - public String getUUIDFromNBT(NBTTagCompound tag) { + public static String getUUIDFromNBT(NBTTagCompound tag) { String uuid = null; if (tag != null && tag.hasKey("ExtraAttributes", 10)) { NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); @@ -965,7 +965,7 @@ public class NEUManager { .resolveInternalName(); } - public String getUUIDForItem(ItemStack stack) { + public static String getUUIDForItem(ItemStack stack) { if (stack == null) return null; NBTTagCompound tag = stack.getTagCompound(); return getUUIDFromNBT(tag); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java index 6160ac8d..94c7cc2b 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java @@ -23,76 +23,35 @@ import com.google.common.collect.Sets; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.autosubscribe.AutoLoad; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.commands.Commands; import io.github.moulberry.notenoughupdates.core.BackgroundBlur; -import io.github.moulberry.notenoughupdates.cosmetics.CapeManager; import io.github.moulberry.notenoughupdates.cosmetics.ShaderManager; -import io.github.moulberry.notenoughupdates.dungeons.DungeonMap; import io.github.moulberry.notenoughupdates.listener.ChatListener; import io.github.moulberry.notenoughupdates.listener.ItemTooltipEssenceShopListener; import io.github.moulberry.notenoughupdates.listener.ItemTooltipListener; import io.github.moulberry.notenoughupdates.listener.ItemTooltipRngListener; import io.github.moulberry.notenoughupdates.listener.NEUEventListener; -import io.github.moulberry.notenoughupdates.listener.OldAnimationChecker; import io.github.moulberry.notenoughupdates.listener.RenderListener; import io.github.moulberry.notenoughupdates.listener.WorldListener; -import io.github.moulberry.notenoughupdates.miscfeatures.AbiphoneContactHelper; -import io.github.moulberry.notenoughupdates.miscfeatures.AbiphoneFavourites; -import io.github.moulberry.notenoughupdates.miscfeatures.AbiphoneWarning; -import io.github.moulberry.notenoughupdates.miscfeatures.AntiCoopAdd; -import io.github.moulberry.notenoughupdates.miscfeatures.AuctionBINWarning; -import io.github.moulberry.notenoughupdates.miscfeatures.AuctionProfit; -import io.github.moulberry.notenoughupdates.miscfeatures.BetterContainers; -import io.github.moulberry.notenoughupdates.miscfeatures.CrystalOverlay; -import io.github.moulberry.notenoughupdates.miscfeatures.CrystalWishingCompassSolver; -import io.github.moulberry.notenoughupdates.miscfeatures.CustomItemEffects; import io.github.moulberry.notenoughupdates.miscfeatures.CustomSkulls; -import io.github.moulberry.notenoughupdates.miscfeatures.DungeonNpcProfitOverlay; -import io.github.moulberry.notenoughupdates.miscfeatures.DwarvenMinesWaypoints; -import io.github.moulberry.notenoughupdates.miscfeatures.EnchantingSolvers; import io.github.moulberry.notenoughupdates.miscfeatures.FairySouls; -import io.github.moulberry.notenoughupdates.miscfeatures.FishingHelper; -import io.github.moulberry.notenoughupdates.miscfeatures.ItemCooldowns; import io.github.moulberry.notenoughupdates.miscfeatures.ItemCustomizeManager; -import io.github.moulberry.notenoughupdates.miscfeatures.MiningStuff; import io.github.moulberry.notenoughupdates.miscfeatures.NPCRetexturing; import io.github.moulberry.notenoughupdates.miscfeatures.Navigation; -import io.github.moulberry.notenoughupdates.miscfeatures.NullzeeSphere; import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay; -import io.github.moulberry.notenoughupdates.miscfeatures.PowerStoneStatsDisplay; import io.github.moulberry.notenoughupdates.miscfeatures.SlotLocking; import io.github.moulberry.notenoughupdates.miscfeatures.StorageManager; -import io.github.moulberry.notenoughupdates.miscfeatures.SunTzu; -import io.github.moulberry.notenoughupdates.miscfeatures.WardrobeMouseButtons; -import io.github.moulberry.notenoughupdates.miscfeatures.WitherCloakChanger; -import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.CustomBiomes; import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.CustomBlockSounds; -import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.DwarvenMinesTextures; -import io.github.moulberry.notenoughupdates.miscfeatures.inventory.MuseumCheapestItemOverlay; -import io.github.moulberry.notenoughupdates.miscfeatures.inventory.MuseumItemHighlighter; -import io.github.moulberry.notenoughupdates.miscfeatures.item.enchants.EnchantStyleCustomizer; import io.github.moulberry.notenoughupdates.miscfeatures.updater.AutoUpdater; -import io.github.moulberry.notenoughupdates.miscfeatures.world.EnderNodeHighlighter; -import io.github.moulberry.notenoughupdates.miscfeatures.world.FrozenTreasuresHighlighter; -import io.github.moulberry.notenoughupdates.miscfeatures.world.GlowingMushroomHighlighter; -import io.github.moulberry.notenoughupdates.miscgui.CalendarOverlay; -import io.github.moulberry.notenoughupdates.miscgui.InventoryStorageSelector; -import io.github.moulberry.notenoughupdates.miscgui.SignCalculator; -import io.github.moulberry.notenoughupdates.miscgui.TrophyRewardOverlay; -import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager; import io.github.moulberry.notenoughupdates.mixins.AccessorMinecraft; import io.github.moulberry.notenoughupdates.oneconfig.IOneConfigCompat; import io.github.moulberry.notenoughupdates.options.NEUConfig; -import io.github.moulberry.notenoughupdates.overlays.EquipmentOverlay; -import io.github.moulberry.notenoughupdates.overlays.FuelBar; import io.github.moulberry.notenoughupdates.overlays.OverlayManager; import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; import io.github.moulberry.notenoughupdates.recipes.RecipeGenerator; -import io.github.moulberry.notenoughupdates.util.Constants; -import io.github.moulberry.notenoughupdates.util.SBInfo; -import io.github.moulberry.notenoughupdates.util.TitleUtil; import io.github.moulberry.notenoughupdates.util.Utils; -import io.github.moulberry.notenoughupdates.util.XPInformation; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.GuiScreen; @@ -132,6 +91,7 @@ import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Set; +@NEUAutoSubscribe @Mod( modid = NotEnoughUpdates.MODID, version = NotEnoughUpdates.VERSION, clientSideOnly = true, useMetadata = true, guiFactory = "io.github.moulberry.notenoughupdates.core.config.MoulConfigGuiForgeInterop") @@ -299,64 +259,18 @@ public class NotEnoughUpdates { IOneConfigCompat.getInstance().ifPresent(it -> it.initConfig(config, this::saveConfig)); - MinecraftForge.EVENT_BUS.register(this); MinecraftForge.EVENT_BUS.register(new NEUEventListener(this)); MinecraftForge.EVENT_BUS.register(new RecipeGenerator(this)); - MinecraftForge.EVENT_BUS.register(CapeManager.getInstance()); - //MinecraftForge.EVENT_BUS.register(new SBGamemodes()); - MinecraftForge.EVENT_BUS.register(new EnchantingSolvers()); - MinecraftForge.EVENT_BUS.register(new CalendarOverlay()); - MinecraftForge.EVENT_BUS.register(SBInfo.getInstance()); - MinecraftForge.EVENT_BUS.register(CustomItemEffects.INSTANCE); - MinecraftForge.EVENT_BUS.register(new Constants()); - MinecraftForge.EVENT_BUS.register(new DungeonMap()); - MinecraftForge.EVENT_BUS.register(new SunTzu()); - MinecraftForge.EVENT_BUS.register(new WitherCloakChanger()); - MinecraftForge.EVENT_BUS.register(new MiningStuff()); - MinecraftForge.EVENT_BUS.register(FairySouls.getInstance()); - MinecraftForge.EVENT_BUS.register(new CrystalOverlay()); - MinecraftForge.EVENT_BUS.register(new ItemCooldowns()); - MinecraftForge.EVENT_BUS.register(new DwarvenMinesWaypoints()); - MinecraftForge.EVENT_BUS.register(new FuelBar()); - MinecraftForge.EVENT_BUS.register(new AuctionProfit()); - MinecraftForge.EVENT_BUS.register(new DungeonNpcProfitOverlay()); - MinecraftForge.EVENT_BUS.register(XPInformation.getInstance()); MinecraftForge.EVENT_BUS.register(OverlayManager.petInfoOverlay); MinecraftForge.EVENT_BUS.register(OverlayManager.timersOverlay); - MinecraftForge.EVENT_BUS.register(new NullzeeSphere()); - MinecraftForge.EVENT_BUS.register(InventoryStorageSelector.getInstance()); - MinecraftForge.EVENT_BUS.register(SlotLocking.getInstance()); - MinecraftForge.EVENT_BUS.register(FishingHelper.getInstance()); - MinecraftForge.EVENT_BUS.register(CrystalWishingCompassSolver.getInstance()); - MinecraftForge.EVENT_BUS.register(new DwarvenMinesTextures()); - MinecraftForge.EVENT_BUS.register(EquipmentOverlay.INSTANCE); - MinecraftForge.EVENT_BUS.register(CustomBiomes.INSTANCE); MinecraftForge.EVENT_BUS.register(new ChatListener(this)); MinecraftForge.EVENT_BUS.register(new ItemTooltipListener(this)); MinecraftForge.EVENT_BUS.register(new ItemTooltipRngListener(this)); MinecraftForge.EVENT_BUS.register(new ItemTooltipEssenceShopListener(this)); MinecraftForge.EVENT_BUS.register(new RenderListener(this)); - MinecraftForge.EVENT_BUS.register(new OldAnimationChecker()); - MinecraftForge.EVENT_BUS.register(new SignCalculator()); - MinecraftForge.EVENT_BUS.register(TrophyRewardOverlay.getInstance()); - MinecraftForge.EVENT_BUS.register(PowerStoneStatsDisplay.getInstance()); - MinecraftForge.EVENT_BUS.register(AntiCoopAdd.getInstance()); - MinecraftForge.EVENT_BUS.register(AbiphoneWarning.getInstance()); - MinecraftForge.EVENT_BUS.register(new BetterContainers()); - MinecraftForge.EVENT_BUS.register(AuctionBINWarning.getInstance()); - MinecraftForge.EVENT_BUS.register(MinionHelperManager.getInstance()); MinecraftForge.EVENT_BUS.register(navigation); - MinecraftForge.EVENT_BUS.register(new GlowingMushroomHighlighter()); MinecraftForge.EVENT_BUS.register(new WorldListener(this)); - MinecraftForge.EVENT_BUS.register(EnchantStyleCustomizer.INSTANCE); - MinecraftForge.EVENT_BUS.register(TitleUtil.getInstance()); - MinecraftForge.EVENT_BUS.register(EnderNodeHighlighter.getInstance()); - MinecraftForge.EVENT_BUS.register(FrozenTreasuresHighlighter.getInstance()); - MinecraftForge.EVENT_BUS.register(AbiphoneFavourites.getInstance()); - MinecraftForge.EVENT_BUS.register(AbiphoneContactHelper.getInstance()); - MinecraftForge.EVENT_BUS.register(MuseumItemHighlighter.INSTANCE); - MinecraftForge.EVENT_BUS.register(MuseumCheapestItemOverlay.INSTANCE); - MinecraftForge.EVENT_BUS.register(new WardrobeMouseButtons()); + AutoLoad.INSTANCE.provide(supplier -> MinecraftForge.EVENT_BUS.register(supplier.get())); if (Minecraft.getMinecraft().getResourceManager() instanceof IReloadableResourceManager) { IReloadableResourceManager manager = (IReloadableResourceManager) Minecraft.getMinecraft().getResourceManager(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java index e606fc49..5ec3724a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java @@ -731,7 +731,7 @@ public class APIManager { public void updateBazaar() { manager.apiUtils - .newHypixelApiRequest("skyblock/bazaar") + .newAnonymousHypixelApiRequest("skyblock/bazaar") .requestJson() .thenAccept(jsonObject -> { if (!jsonObject.get("success").getAsBoolean()) return; @@ -744,7 +744,9 @@ public class APIManager { JsonObject productInfo = new JsonObject(); JsonObject product = entry.getValue().getAsJsonObject(); - JsonObject quickStatus = product.get("quick_status").getAsJsonObject(); + JsonObject quickStatus = product.getAsJsonObject("quick_status"); + if (!hasData(quickStatus)) continue; + productInfo.addProperty("avg_buy", quickStatus.get("buyPrice").getAsFloat()); productInfo.addProperty("avg_sell", quickStatus.get("sellPrice").getAsFloat()); @@ -771,6 +773,19 @@ public class APIManager { }); } + private static boolean hasData(JsonObject quickStatus) { + for (Map.Entry<String, JsonElement> e : quickStatus.entrySet()) { + String key = e.getKey(); + if (!key.equals("productId")) { + double value = e.getValue().getAsDouble(); + if (value != 0) { + return true; + } + } + } + return false; + } + public void updateAvgPrices() { manager.apiUtils .newMoulberryRequest("auction_averages/3day.json.gz") diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java index cf266dca..0d882358 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java @@ -19,6 +19,9 @@ package io.github.moulberry.notenoughupdates.commands.dev; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.BuildFlags; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; @@ -34,6 +37,7 @@ import io.github.moulberry.notenoughupdates.util.PronounDB; import io.github.moulberry.notenoughupdates.util.SBInfo; import io.github.moulberry.notenoughupdates.util.TabListUtils; import io.github.moulberry.notenoughupdates.util.Utils; +import io.github.moulberry.notenoughupdates.util.hypixelapi.ProfileCollectionInfo; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.command.CommandException; @@ -122,6 +126,32 @@ public class DevTestCommand extends ClientCommandBase { Utils.addChatMessage(EnumChatFormatting.RED + DEV_FAIL_STRINGS[devFailIndex++]); return; } + if (args.length == 1 && args[0].equalsIgnoreCase("testprofile")) { + NotEnoughUpdates.INSTANCE.manager.apiUtils.newHypixelApiRequest("skyblock/profiles") + .queryArgument( + "uuid", + "" + Minecraft.getMinecraft().thePlayer.getUniqueID() + ) + .requestJson() + .thenApply(jsonObject -> { + JsonArray profiles = jsonObject.get("profiles").getAsJsonArray(); + JsonObject cp = null; + for (JsonElement profile : profiles) { + JsonObject asJsonObject = profile.getAsJsonObject(); + if ((asJsonObject.has("selected") && + asJsonObject.get("selected").getAsBoolean()) || cp == null) { + cp = asJsonObject; + } + } + return cp; + }) + .thenCompose(obj -> ProfileCollectionInfo.getCollectionData( + obj, + Minecraft.getMinecraft().thePlayer.getUniqueID().toString() + )) + .thenAccept(it -> + Utils.addChatMessage("Response: " + it)); + } if (args.length >= 1 && args[0].equalsIgnoreCase("profileinfo")) { String currentProfile = SBInfo.getInstance().currentProfile; SBInfo.Gamemode gamemode = SBInfo.getInstance().getGamemodeForProfile(currentProfile); @@ -146,7 +176,8 @@ public class DevTestCommand extends ClientCommandBase { Arrays.copyOfRange(args, 1, args.length) ); } - Utils.addChatMessage("§e[NEU] §fYour external editor is: §Z" + NotEnoughUpdates.INSTANCE.config.hidden.externalEditor); + Utils.addChatMessage( + "§e[NEU] §fYour external editor is: §Z" + NotEnoughUpdates.INSTANCE.config.hidden.externalEditor); return; } if (args.length >= 1 && args[0].equalsIgnoreCase("pricetest")) { @@ -181,7 +212,8 @@ public class DevTestCommand extends ClientCommandBase { } if (args.length == 1 && args[0].equalsIgnoreCase("dev")) { NotEnoughUpdates.INSTANCE.config.hidden.dev = !NotEnoughUpdates.INSTANCE.config.hidden.dev; - Utils.addChatMessage("§e[NEU] Dev mode " + (NotEnoughUpdates.INSTANCE.config.hidden.dev ? "§aenabled": "§cdisabled")); + Utils.addChatMessage( + "§e[NEU] Dev mode " + (NotEnoughUpdates.INSTANCE.config.hidden.dev ? "§aenabled" : "§cdisabled")); return; } if (args.length == 1 && args[0].equalsIgnoreCase("saveconfig")) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/SettingsCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/SettingsCommand.java index 9964b739..1855a2b5 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/SettingsCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/SettingsCommand.java @@ -47,7 +47,7 @@ public class SettingsCommand extends ClientCommandBase { NotEnoughUpdates.INSTANCE.openGui = new GuiScreenElementWrapper(new NEUConfigEditor(NotEnoughUpdates.INSTANCE.config, StringUtils.join(args, " "))); } else { - NotEnoughUpdates.INSTANCE.openGui = new GuiScreenElementWrapper(NEUConfigEditor.editor); + NotEnoughUpdates.INSTANCE.openGui = new GuiScreenElementWrapper(new NEUConfigEditor(NotEnoughUpdates.INSTANCE.config)); } } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/BackgroundBlur.java b/src/main/java/io/github/moulberry/notenoughupdates/core/BackgroundBlur.java index fc2be97b..eaa733e4 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/BackgroundBlur.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/BackgroundBlur.java @@ -120,8 +120,14 @@ public class BackgroundBlur { for (Map.Entry<Float, OutputStuff> entry : blurOutput.entrySet()) { if (remove.contains(entry.getKey())) { entry.getValue().framebuffer.deleteFramebuffer(); - entry.getValue().blurShaderHorz.deleteShader(); - entry.getValue().blurShaderVert.deleteShader(); + Shader blurShaderHorz = entry.getValue().blurShaderHorz; + if (blurShaderHorz != null) { + blurShaderHorz.deleteShader(); + } + Shader blurShaderVert = entry.getValue().blurShaderVert; + if (blurShaderVert != null) { + blurShaderVert.deleteShader(); + } } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditor.java index c3969e35..9edad918 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditor.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditor.java @@ -27,7 +27,7 @@ import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.renderer.GlStateManager; public abstract class GuiOptionEditor { - protected final ConfigProcessor.ProcessedOption option; + public final ConfigProcessor.ProcessedOption option; private static final int HEIGHT = 45; public GuiOptionEditor(ConfigProcessor.ProcessedOption option) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/struct/ConfigProcessor.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/struct/ConfigProcessor.java index 9a75ec19..62b9b8e2 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/struct/ConfigProcessor.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/struct/ConfigProcessor.java @@ -45,6 +45,7 @@ import io.github.moulberry.notenoughupdates.core.config.gui.GuiOptionEditorFSR; import io.github.moulberry.notenoughupdates.core.config.gui.GuiOptionEditorKeybind; import io.github.moulberry.notenoughupdates.core.config.gui.GuiOptionEditorSlider; import io.github.moulberry.notenoughupdates.core.config.gui.GuiOptionEditorText; +import io.github.moulberry.notenoughupdates.miscfeatures.EnforcedConfigValues; import java.lang.reflect.Field; import java.util.LinkedHashMap; @@ -133,6 +134,7 @@ public class ConfigProcessor { boolean optionPresent = optionField.isAnnotationPresent(ConfigOption.class); if (optionPresent) { + String optionPath = categoryField.getName() + "." + optionField.getName(); ConfigOption optionAnnotation = optionField.getAnnotation(ConfigOption.class); ProcessedOption option = new ProcessedOption( optionAnnotation.name(), @@ -231,6 +233,10 @@ public class ConfigProcessor { //System.err.printf("Failed to load config option %s. Could not find suitable editor.\n", optionField.getName()); continue; } + if (EnforcedConfigValues.INSTANCE.isBlockedFromEditing(optionPath)) { + editor = new GuiOptionEditorBlocked(editor); + } + option.editor = editor; cat.options.put(optionField.getName(), option); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/struct/GuiOptionEditorBlocked.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/struct/GuiOptionEditorBlocked.java new file mode 100644 index 00000000..8415cf72 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/struct/GuiOptionEditorBlocked.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.core.config.struct; + +import io.github.moulberry.notenoughupdates.core.config.gui.GuiOptionEditor; +import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; +import io.github.moulberry.notenoughupdates.core.util.render.TextRenderUtils; +import lombok.var; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.util.ResourceLocation; + +public class GuiOptionEditorBlocked extends GuiOptionEditor { + public static final ResourceLocation blockedTexture = new ResourceLocation( + "notenoughupdates:textures/gui/config_blocked.png"); + private final GuiOptionEditor base; + + public GuiOptionEditorBlocked(GuiOptionEditor base) { + super(base.option); + this.base = base; + } + + @Override + public void render(int x, int y, int width) { + // No super. We delegate and overlay ourselves instead. + base.render(x, y, width); + + var mc = Minecraft.getMinecraft(); + + // Depress original option + Gui.drawRect(x, y, x + width, y + getHeight(), 0x80000000); + + GlStateManager.color(1, 1, 1, 1); + mc.getTextureManager().bindTexture(blockedTexture); + + float iconWidth = getHeight() * 96F / 64; + RenderUtils.drawTexturedRect(x, y, iconWidth, getHeight()); + + TextRenderUtils.drawStringScaledMaxWidth( + "This option is currently not available.", + mc.fontRendererObj, + x + iconWidth,y + getHeight() / 2F - mc.fontRendererObj.FONT_HEIGHT / 2F, + true, (int) (width - iconWidth), 0xFFFF4444 + ); + GlStateManager.color(1, 1, 1, 1); + } + + @Override + public boolean mouseInput(int x, int y, int width, int mouseX, int mouseY) { + return false; + } + + @Override + public boolean keyboardInput() { + return false; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/StringUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/StringUtils.java index c19c4826..c7c118bb 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/StringUtils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/StringUtils.java @@ -24,6 +24,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import java.io.UnsupportedEncodingException; +import java.math.BigInteger; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.Set; @@ -71,7 +72,17 @@ public class StringUtils { return shortNumberFormat(n, 0); } - private static final char[] c = new char[] { 'k', 'm', 'b', 't' }; + private static final char[] sizeSuffix = new char[]{'k', 'm', 'b', 't'}; + + public static String shortNumberFormat(BigInteger bigInteger) { + BigInteger THOUSAND = BigInteger.valueOf(1000); + int i = -1; + while (bigInteger.compareTo(THOUSAND) > 0 && i < sizeSuffix.length) { + bigInteger = bigInteger.divide(THOUSAND); + i++; + } + return bigInteger.toString() + (i == -1 ? "" : sizeSuffix[i]); + } public static String shortNumberFormat(double n, int iteration) { if (n < 1000) { @@ -84,7 +95,7 @@ public class StringUtils { double d = ((long) n / 100) / 10.0; boolean isRound = (d * 10) % 10 == 0; - return d < 1000 ? (isRound || d > 9.99 ? (int) d * 10 / 10 : d + "") + "" + c[iteration] : shortNumberFormat(d, iteration + 1); + return d < 1000 ? (isRound || d > 9.99 ? (int) d * 10 / 10 : d + "") + "" + sizeSuffix[iteration] : shortNumberFormat(d, iteration + 1); } public static String urlEncode(String something) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java index 7a609a2a..4a7c1939 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java @@ -24,6 +24,7 @@ import com.google.common.collect.HashBiMap; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.shader.Framebuffer; @@ -44,6 +45,7 @@ import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +@NEUAutoSubscribe public class CapeManager { public static final CapeManager INSTANCE = new CapeManager(); public long lastCapeUpdate = 0; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java index e15168f5..686cef8e 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java @@ -22,6 +22,7 @@ package io.github.moulberry.notenoughupdates.dungeons; import com.google.common.collect.Iterables; import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.core.BackgroundBlur; import io.github.moulberry.notenoughupdates.core.config.Position; import io.github.moulberry.notenoughupdates.util.NEUResourceManager; @@ -73,6 +74,7 @@ import java.util.Map; import java.util.Objects; import java.util.Set; +@NEUAutoSubscribe public class DungeonMap { private static final ResourceLocation GREEN_CHECK = new ResourceLocation( "notenoughupdates:dungeon_map/green_check.png"); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/events/ReplaceItemEvent.java b/src/main/java/io/github/moulberry/notenoughupdates/events/ReplaceItemEvent.java index 2cdcf083..335d8fe0 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/events/ReplaceItemEvent.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/events/ReplaceItemEvent.java @@ -19,17 +19,17 @@ package io.github.moulberry.notenoughupdates.events; -import net.minecraft.inventory.InventoryBasic; +import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; public class ReplaceItemEvent extends NEUEvent { final ItemStack original; - final InventoryBasic inventory; + final IInventory inventory; final int slotNumber; ItemStack replaceWith; - public ReplaceItemEvent(ItemStack original, InventoryBasic inventory, int slotNumber) { + public ReplaceItemEvent(ItemStack original, IInventory inventory, int slotNumber) { this.original = original; this.inventory = inventory; this.slotNumber = slotNumber; @@ -40,7 +40,7 @@ public class ReplaceItemEvent extends NEUEvent { return original; } - public InventoryBasic getInventory() { + public IInventory getInventory() { return inventory; } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/hooks/ThreadDownloadImageHook.java b/src/main/java/io/github/moulberry/notenoughupdates/hooks/ThreadDownloadImageHook.java index 4fa57360..e84fce11 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/hooks/ThreadDownloadImageHook.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/hooks/ThreadDownloadImageHook.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Linnea Gräf + * Copyright (C) 2022-2023 Linnea Gräf * * This file is part of NotEnoughUpdates. * @@ -26,15 +26,22 @@ import javax.net.ssl.HttpsURLConnection; import java.net.HttpURLConnection; public class ThreadDownloadImageHook { + public static String hookThreadImageLink(String originalLink) { + if (!NotEnoughUpdates.INSTANCE.config.misc.fixSteveSkulls || originalLink == null || !originalLink.startsWith( + "http://textures.minecraft.net")) + return originalLink; + return originalLink.replace("http://", "https://"); + } + public static void hookThreadImageConnection(HttpURLConnection connection) { if ((connection instanceof HttpsURLConnection) && NotEnoughUpdates.INSTANCE.config.misc.fixSteveSkulls) { ApiUtil.patchHttpsRequest((HttpsURLConnection) connection); } } - public static String hookThreadImageLink(String originalLink) { - if (!NotEnoughUpdates.INSTANCE.config.misc.fixSteveSkulls || originalLink == null) - return originalLink; - return originalLink.replace("http://", "https://"); + public interface AccessorThreadDownloadImageData { + String getOriginalUrl(); + + String getPatchedUrl(); } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java index 31930b01..8563189c 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java @@ -61,7 +61,7 @@ public class ChatListener { private static final Pattern SLAYER_EXP_PATTERN = Pattern.compile( " (Spider|Zombie|Wolf|Enderman|Blaze) Slayer LVL (\\d) - (?:Next LVL in ([\\d,]+) XP!|LVL MAXED OUT!)"); private static final Pattern SKY_BLOCK_LEVEL_PATTERN = Pattern.compile("\\[(\\d{1,4})\\] .*"); - private final Pattern PARTY_FINDER_PATTERN = Pattern.compile("§dParty Finder §r§f> (.*)§ejoined the dungeon group!"); + private final Pattern PARTY_FINDER_PATTERN = Pattern.compile("§dParty Finder §r§f> (.*)§ejoined the (dungeon )?group!"); private AtomicBoolean missingRecipe = new AtomicBoolean(false); @@ -316,10 +316,7 @@ public class ChatListener { } } - if (unformatted.equals("You uncovered a treasure chest!") || - unformatted.equals("You have successfully picked the lock on this chest!") - || (unformatted.startsWith("You received +") && unformatted.endsWith(" Powder"))) - OverlayManager.powderGrindingOverlay.message(unformatted); + OverlayManager.powderGrindingOverlay.onMessage(unformatted); if (unformatted.startsWith("ENDER NODE!")) EnderNodeHighlighter.getInstance().highlightedBlocks.clear(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/OldAnimationChecker.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/OldAnimationChecker.java index 7858918b..8d62c0aa 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/OldAnimationChecker.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/OldAnimationChecker.java @@ -21,12 +21,14 @@ package io.github.moulberry.notenoughupdates.listener; import com.google.common.collect.Lists; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.util.NotificationHandler; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +@NEUAutoSubscribe public class OldAnimationChecker { private void unregister() { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/loader/KotlinLoadingTweaker.java b/src/main/java/io/github/moulberry/notenoughupdates/loader/KotlinLoadingTweaker.java index 0c63b17d..bf4e746f 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/loader/KotlinLoadingTweaker.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/loader/KotlinLoadingTweaker.java @@ -82,7 +82,7 @@ public class KotlinLoadingTweaker implements ITweaker { * Full version format: [1, 7, 20] (1.7.20) * RC version format: [1, 7, 20, 1] (1.7.20-rc1) */ - public static final int[] BUNDLED_KOTLIN_VERSION = new int[]{1, 7, 20}; + public static final int[] BUNDLED_KOTLIN_VERSION = new int[]{1, 8, 0}; @Override public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AbiphoneContactHelper.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AbiphoneContactHelper.java index d2a5fc84..3178d241 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AbiphoneContactHelper.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AbiphoneContactHelper.java @@ -24,6 +24,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.core.util.StringUtils; import io.github.moulberry.notenoughupdates.events.SlotClickEvent; import io.github.moulberry.notenoughupdates.util.Constants; @@ -36,6 +37,7 @@ import org.lwjgl.input.Keyboard; import java.util.List; import java.util.Map; +@NEUAutoSubscribe public class AbiphoneContactHelper { private static final AbiphoneContactHelper INSTANCE = new AbiphoneContactHelper(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AbiphoneFavourites.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AbiphoneFavourites.java index e6a1399d..750e674d 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AbiphoneFavourites.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AbiphoneFavourites.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.core.config.KeybindHelper; import io.github.moulberry.notenoughupdates.core.util.StringUtils; import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; @@ -45,6 +46,7 @@ import java.awt.*; import java.util.ArrayList; import java.util.List; +@NEUAutoSubscribe public class AbiphoneFavourites { private static final AbiphoneFavourites INSTANCE = new AbiphoneFavourites(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AbiphoneWarning.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AbiphoneWarning.java index 67ac4f4c..2c28bcd1 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AbiphoneWarning.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AbiphoneWarning.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.core.GuiElement; import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; import io.github.moulberry.notenoughupdates.core.util.render.TextRenderUtils; @@ -41,6 +42,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.List; +@NEUAutoSubscribe public class AbiphoneWarning extends GuiElement { private static final AbiphoneWarning INSTANCE = new AbiphoneWarning(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AntiCoopAdd.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AntiCoopAdd.java index aaa13d39..40425560 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AntiCoopAdd.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AntiCoopAdd.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.events.SlotClickEvent; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; @@ -32,6 +33,7 @@ import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +@NEUAutoSubscribe public class AntiCoopAdd { private static final AntiCoopAdd INSTANCE = new AntiCoopAdd(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionBINWarning.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionBINWarning.java index 75813700..7282aad7 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionBINWarning.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionBINWarning.java @@ -21,6 +21,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.core.GuiElement; import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; import io.github.moulberry.notenoughupdates.core.util.render.TextRenderUtils; @@ -43,6 +44,7 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; +@NEUAutoSubscribe public class AuctionBINWarning extends GuiElement { private static final AuctionBINWarning INSTANCE = new AuctionBINWarning(); @@ -105,6 +107,8 @@ public class AuctionBINWarning extends GuiElement { } ItemStack sellStack = event.guiContainer.inventorySlots.getSlot(13).getStack(); + if (sellStack == null) return; + String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(sellStack); sellStackAmount = sellStack.stackSize; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionProfit.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionProfit.java index 82c392e4..c0e40ec9 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionProfit.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionProfit.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.core.util.StringUtils; import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer; import io.github.moulberry.notenoughupdates.util.Utils; @@ -39,6 +40,7 @@ import net.minecraftforge.client.event.GuiScreenEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import org.lwjgl.opengl.GL11; +@NEUAutoSubscribe public class AuctionProfit { public static final ResourceLocation auctionProfitImage = diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BetterContainers.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BetterContainers.java index dc7b0e15..e7331378 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BetterContainers.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BetterContainers.java @@ -21,6 +21,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.events.SlotClickEvent; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.inventory.GuiChest; @@ -47,6 +48,7 @@ import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.HashMap; +@NEUAutoSubscribe public class BetterContainers { private static final ResourceLocation TOGGLE_OFF = new ResourceLocation("notenoughupdates:dynamic_54/toggle_off.png"); private static final ResourceLocation TOGGLE_ON = new ResourceLocation("notenoughupdates:dynamic_54/toggle_on.png"); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalOverlay.java index c0653742..047f3c99 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalOverlay.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.util.ReverseWorldRenderer; import io.github.moulberry.notenoughupdates.util.SpecialColour; import net.minecraft.client.Minecraft; @@ -48,6 +49,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +@NEUAutoSubscribe public class CrystalOverlay { private enum CrystalType { FARMING_MINION(8, 0xDAA520), diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalWishingCompassSolver.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalWishingCompassSolver.java index 50975af9..c6e714fe 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalWishingCompassSolver.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalWishingCompassSolver.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.core.util.Line; import io.github.moulberry.notenoughupdates.core.util.Vec3Comparable; import io.github.moulberry.notenoughupdates.events.SpawnParticleEvent; @@ -52,6 +53,7 @@ import java.util.Locale; import java.util.function.BooleanSupplier; import java.util.function.LongSupplier; +@NEUAutoSubscribe public class CrystalWishingCompassSolver { enum SolverState { NOT_STARTED, diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java index 452f8a9b..e959c761 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.util.SBInfo; import io.github.moulberry.notenoughupdates.util.SpecialColour; import io.github.moulberry.notenoughupdates.util.Utils; @@ -76,6 +77,7 @@ import java.util.TreeMap; import java.util.regex.Matcher; import java.util.regex.Pattern; +@NEUAutoSubscribe public class CustomItemEffects { public static final CustomItemEffects INSTANCE = new CustomItemEffects(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DungeonNpcProfitOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DungeonNpcProfitOverlay.java index 34a40c2f..711d5235 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DungeonNpcProfitOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DungeonNpcProfitOverlay.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 NotEnoughUpdates contributors + * Copyright (C) 2022-2023 NotEnoughUpdates contributors * * This file is part of NotEnoughUpdates. * @@ -22,6 +22,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.core.util.StringUtils; import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer; import io.github.moulberry.notenoughupdates.util.ItemUtils; @@ -52,6 +53,7 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; +@NEUAutoSubscribe public class DungeonNpcProfitOverlay { private static final ResourceLocation dungeonProfitResource = @@ -334,7 +336,7 @@ public class DungeonNpcProfitOverlay { } } } - } else if (essenceMatcher.matches()) { + } else if (essenceMatcher.matches() && NotEnoughUpdates.INSTANCE.config.dungeons.useEssenceCostFromBazaar) { String essenceType = essenceMatcher.group("essenceType"); String essenceAmount = essenceMatcher.group("essenceAmount"); if (essenceType == null || essenceAmount == null) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DwarvenMinesWaypoints.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DwarvenMinesWaypoints.java index 6b2c9ac9..e2eb13b2 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DwarvenMinesWaypoints.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DwarvenMinesWaypoints.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; import io.github.moulberry.notenoughupdates.options.NEUConfig; import io.github.moulberry.notenoughupdates.overlays.MiningOverlay; @@ -46,6 +47,7 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; +@NEUAutoSubscribe public class DwarvenMinesWaypoints { private final HashMap<String, Vector3f> waypointsMap = new HashMap<String, Vector3f>() {{ diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/EnchantingSolvers.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/EnchantingSolvers.java index d5cbfdde..695c9851 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/EnchantingSolvers.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/EnchantingSolvers.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.events.SlotClickEvent; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; @@ -45,6 +46,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +@NEUAutoSubscribe public class EnchantingSolvers { public static SolverType currentSolver = SolverType.NONE; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java index 9e3343a4..5a611178 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java @@ -25,6 +25,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonSyntaxException; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; import io.github.moulberry.notenoughupdates.core.util.StringUtils; import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; @@ -64,6 +65,7 @@ import java.util.Set; import java.util.TreeMap; import java.util.stream.Collectors; +@NEUAutoSubscribe public class FairySouls { private static FairySouls instance = null; private static final String unknownProfile = "unknown"; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FishingHelper.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FishingHelper.java index a7c22b93..800e25b1 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FishingHelper.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FishingHelper.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.core.ChromaColour; import io.github.moulberry.notenoughupdates.events.SpawnParticleEvent; import io.github.moulberry.notenoughupdates.util.SpecialColour; @@ -53,6 +54,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +@NEUAutoSubscribe public class FishingHelper { private static final FishingHelper INSTANCE = new FishingHelper(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCooldowns.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCooldowns.java index e5ee40d0..5651a6ed 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCooldowns.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCooldowns.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.item.ItemStack; @@ -36,6 +37,7 @@ import java.util.TreeMap; import java.util.regex.Matcher; import java.util.regex.Pattern; +@NEUAutoSubscribe public class ItemCooldowns { private static final Pattern COOLDOWN_LORE = Pattern.compile("\\u00a78Cooldown: \\u00a7a(\\d+)s"); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCustomizeManager.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCustomizeManager.java index 15fc8ef8..dad801ec 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCustomizeManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCustomizeManager.java @@ -21,6 +21,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import io.github.moulberry.notenoughupdates.NEUManager; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.core.ChromaColour; import net.minecraft.client.Minecraft; @@ -67,8 +68,6 @@ public class ItemCustomizeManager { private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); private static ItemDataMap itemDataMap = new ItemDataMap(); - private static final HashMap<Integer, String> itemUuidCache = new HashMap<>(); - public static class ItemDataMap { public HashMap<String, ItemData> itemData = new HashMap<>(); } @@ -269,25 +268,10 @@ public class ItemCustomizeManager { return CUSTOM_GLINT_TEXTURE; } - public static String getUuidForItem(ItemStack stack) { - if (!stack.hasTagCompound()) return null; - - int nbtHash = stack.getTagCompound().hashCode(); - - if (itemUuidCache.containsKey(nbtHash)) { - return itemUuidCache.get(nbtHash); - } - - String uuid = NotEnoughUpdates.INSTANCE.manager.getUUIDForItem(stack); - - itemUuidCache.put(nbtHash, uuid); - return uuid; - } - public static ItemData getDataForItem(ItemStack stack) { if (stack == null) return null; - String uuid = getUuidForItem(stack); + String uuid = NEUManager.getUUIDForItem(stack); if (uuid == null) { return null; @@ -297,7 +281,6 @@ public class ItemCustomizeManager { } public static void tick() { - itemUuidCache.clear(); disableTextureBinding = false; } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/MiningStuff.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/MiningStuff.java index 12e0301b..2cbd3125 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/MiningStuff.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/MiningStuff.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.core.util.render.TextRenderUtils; import io.github.moulberry.notenoughupdates.overlays.MiningOverlay; import io.github.moulberry.notenoughupdates.util.SBInfo; @@ -44,6 +45,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import java.util.Map; +@NEUAutoSubscribe public class MiningStuff { private static BlockPos overlayLoc = null; private static long titaniumNotifMillis = 0; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NullzeeSphere.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NullzeeSphere.java index 6302343e..08d48962 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NullzeeSphere.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NullzeeSphere.java @@ -19,6 +19,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.util.ReverseWorldRenderer; import io.github.moulberry.notenoughupdates.util.SpecialColour; import net.minecraft.client.Minecraft; @@ -41,6 +42,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +@NEUAutoSubscribe public class NullzeeSphere { public static boolean enabled = false; public static float size = 20; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java index 37cb14b5..716fb37d 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java @@ -447,13 +447,14 @@ public class PetInfoOverlay extends TextOverlay { if (pet.petLevel.getCurrentLevel() >= pet.petLevel.getMaxLevel()) return 0; if (validXpTypes == null) - validXpTypes = Lists.newArrayList("mining", "foraging", "enchanting", "farming", "combat", "fishing", "alchemy"); + validXpTypes = Lists.newArrayList("mining", "foraging", "enchanting", "farming", "combat", "fishing", "alchemy", "all"); if (!validXpTypes.contains(xpType.toLowerCase())) return 0; float tamingPercent = 1.0f + (config.tamingLevel / 100f); xp = xp * tamingPercent; xp = xp + (xp * config.beastMultiplier / 100f); - if (pet.petXpType != null && !pet.petXpType.equalsIgnoreCase(xpType)) { + + if (pet.petXpType != null && !pet.petXpType.equalsIgnoreCase(xpType) && !pet.petXpType.equalsIgnoreCase("all")) { xp = xp / 3f; if (xpType.equalsIgnoreCase("alchemy") || xpType.equalsIgnoreCase("enchanting")) { @@ -463,6 +464,7 @@ public class PetInfoOverlay extends TextOverlay { if (xpType.equalsIgnoreCase("mining") || xpType.equalsIgnoreCase("fishing")) { xp = xp * 1.5f; } + if (pet.petItem != null) { Matcher petItemMatcher = XP_BOOST_PATTERN.matcher(pet.petItem); if ((petItemMatcher.matches() && petItemMatcher.group(1).equalsIgnoreCase(xpType)) @@ -470,6 +472,11 @@ public class PetInfoOverlay extends TextOverlay { xp = xp * getBoostMultiplier(pet.petItem); } } + JsonObject pets = Constants.PETS; + if (pets != null && pets.has("custom_pet_leveling") && pets.get("custom_pet_leveling").getAsJsonObject().has(pet.petType.toUpperCase()) && + pets.get("custom_pet_leveling").getAsJsonObject().get(pet.petType.toUpperCase()).getAsJsonObject().has("xp_multiplier")) { + xp *= pets.get("custom_pet_leveling").getAsJsonObject().get(pet.petType.toUpperCase()).getAsJsonObject().get("xp_multiplier").getAsFloat(); + } return xp; } @@ -721,16 +728,18 @@ public class PetInfoOverlay extends TextOverlay { JsonObject petItem2 = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get( currentPet2.skin != null ? currentPet2.skin : (currentPet2.petType + ";" + currentPet2.rarity.petId)); if (petItem2 != null) { - Vector2f position = getPosition(overlayWidth, overlayHeight, false); + Vector2f position = getPosition(overlayWidth, overlayHeight, true); int x = (int) position.x; - int y = (int) position.y + NotEnoughUpdates.INSTANCE.config.petOverlay.petOverlayText.size() * 10 + 10; + int y = (int) position.y + NotEnoughUpdates.INSTANCE.config.petOverlay.petOverlayText.size() * 10; ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(petItem2); GlStateManager.enableDepth(); GlStateManager.pushMatrix(); + Utils.pushGuiScale(NotEnoughUpdates.INSTANCE.config.locationedit.guiScale); GlStateManager.translate(x - 2, y - 2, 0); GlStateManager.scale(2, 2, 1); Utils.drawItemStack(stack, 0, 0); + Utils.pushGuiScale(0); GlStateManager.popMatrix(); } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PowerStoneStatsDisplay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PowerStoneStatsDisplay.java index 975bbe6e..31dd71eb 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PowerStoneStatsDisplay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PowerStoneStatsDisplay.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.core.util.StringUtils; import io.github.moulberry.notenoughupdates.options.NEUConfig; import io.github.moulberry.notenoughupdates.util.ItemUtils; @@ -39,6 +40,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Locale; +@NEUAutoSubscribe public class PowerStoneStatsDisplay { private static PowerStoneStatsDisplay instance = null; private final NumberFormat format = NumberFormat.getInstance(Locale.US); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SlotLocking.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SlotLocking.java index 8a487739..b447cf61 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SlotLocking.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SlotLocking.java @@ -22,10 +22,13 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.core.config.KeybindHelper; import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; +import io.github.moulberry.notenoughupdates.events.ReplaceItemEvent; import io.github.moulberry.notenoughupdates.events.SlotClickEvent; import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer; +import io.github.moulberry.notenoughupdates.util.ItemUtils; import io.github.moulberry.notenoughupdates.util.SBInfo; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.ISound; @@ -39,7 +42,10 @@ import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.init.Blocks; import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.event.GuiScreenEvent; import net.minecraftforge.fml.common.eventhandler.EventPriority; @@ -59,6 +65,7 @@ import java.io.OutputStreamWriter; import java.nio.charset.StandardCharsets; import java.util.HashMap; +@NEUAutoSubscribe public class SlotLocking { private static final SlotLocking INSTANCE = new SlotLocking(); @@ -416,6 +423,9 @@ public class SlotLocking { } drawLinkArrow(x1, y1, x2, y2); + setTopHalfBarrier = true; + } else { + setTopHalfBarrier = false; } } @@ -729,4 +739,27 @@ public class SlotLocking { return locked != null && (locked.locked || (NotEnoughUpdates.INSTANCE.config.slotLocking.bindingAlsoLocks && locked.boundTo != -1)); } + + boolean setTopHalfBarrier = false; + @SubscribeEvent + public void barrierInventory(ReplaceItemEvent event) { + if (event.getSlotNumber() < 9 || + (pairingSlot != null && (event.getSlotNumber() == pairingSlot.slotNumber || isArmourSlot(event.getSlotNumber(), pairingSlot.slotNumber))) || + !setTopHalfBarrier || + !(event.getInventory() instanceof InventoryPlayer)) return; + ItemStack stack = new ItemStack(Blocks.barrier); + ItemUtils.getOrCreateTag(stack).setBoolean( + "NEUHIDETOOLIP", + true + ); + event.replaceWith(stack); + } + + boolean isArmourSlot(int eventSlotNumber, int pairingSlotNumber) { + if (eventSlotNumber == 39 && pairingSlotNumber == 5) return true; + if (eventSlotNumber == 38 && pairingSlotNumber == 6) return true; + if (eventSlotNumber == 37 && pairingSlotNumber == 7) return true; + if (eventSlotNumber == 36 && pairingSlotNumber == 8) return true; + return false; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SunTzu.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SunTzu.java index 7fc8beba..736d5058 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SunTzu.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SunTzu.java @@ -19,6 +19,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.ScaledResolution; @@ -30,6 +31,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import java.util.Random; +@NEUAutoSubscribe public class SunTzu { private static boolean enabled = false; private static int quoteNum = 0; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/WardrobeMouseButtons.kt b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/WardrobeMouseButtons.kt index 4e99f5a7..f38d3752 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/WardrobeMouseButtons.kt +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/WardrobeMouseButtons.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 NotEnoughUpdates contributors + * Copyright (C) 2022-2023 NotEnoughUpdates contributors * * This file is part of NotEnoughUpdates. * @@ -19,12 +19,14 @@ package io.github.moulberry.notenoughupdates.miscfeatures import io.github.moulberry.notenoughupdates.NotEnoughUpdates +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe import io.github.moulberry.notenoughupdates.core.config.KeybindHelper import io.github.moulberry.notenoughupdates.util.Utils import net.minecraft.client.gui.inventory.GuiChest import net.minecraftforge.client.event.GuiScreenEvent import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +@NEUAutoSubscribe class WardrobeMouseButtons { private val keybinds: List<Int> get() = listOf( @@ -41,8 +43,17 @@ class WardrobeMouseButtons { private var lastClick = -1L @SubscribeEvent - fun onGui(event: GuiScreenEvent) { - if (!NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.enableWardrobeKeybinds) return + fun onGuiKeyboardInput(event: GuiScreenEvent.KeyboardInputEvent.Pre) { + checkKeybinds(event) + } + + @SubscribeEvent + fun onGuiMouseInput(event: GuiScreenEvent.MouseInputEvent.Pre) { + checkKeybinds(event) + } + + private fun checkKeybinds(event: GuiScreenEvent) { + if (!NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.enableWardrobeKeybinds || !NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return val gui = event.gui as? GuiChest ?: return if (!Utils.getOpenChestName().contains("Wardrobe")) return @@ -51,9 +62,11 @@ class WardrobeMouseButtons { if (System.currentTimeMillis() - lastClick > 300) { Utils.sendLeftMouseClick(gui.inventorySlots.windowId, 36 + i) lastClick = System.currentTimeMillis() + event.isCanceled = true } break } } } + } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/WitherCloakChanger.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/WitherCloakChanger.java index 02d7bf7b..704606bf 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/WitherCloakChanger.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/WitherCloakChanger.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; @@ -33,6 +34,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL14; +@NEUAutoSubscribe public class WitherCloakChanger { public static boolean isCloakActive = false; /** diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/CustomBiomes.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/CustomBiomes.java index 48a01187..dd97a1f0 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/CustomBiomes.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/CustomBiomes.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures.customblockzones; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.events.OnBlockBreakSoundEffect; import io.github.moulberry.notenoughupdates.util.SBInfo; import net.minecraft.block.BlockColored; @@ -37,6 +38,8 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import java.util.HashMap; import java.util.Map; + +@NEUAutoSubscribe public class CustomBiomes { public static final CustomBiomes INSTANCE = new CustomBiomes(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/DwarvenMinesTextures.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/DwarvenMinesTextures.java index 1c6acc1d..df437fee 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/DwarvenMinesTextures.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/DwarvenMinesTextures.java @@ -24,6 +24,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.init.Blocks; @@ -46,6 +47,7 @@ import java.util.Set; import static io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.CustomBiomes.isMithril; import static io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.CustomBiomes.isTitanium; +@NEUAutoSubscribe public class DwarvenMinesTextures implements IslandZoneSubdivider { private static class IgnoreColumn { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/item/enchants/EnchantStyleCustomizer.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/item/enchants/EnchantStyleCustomizer.java index 47acfa60..82db0b30 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/item/enchants/EnchantStyleCustomizer.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/item/enchants/EnchantStyleCustomizer.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures.item.enchants; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.util.LRUCache; import io.github.moulberry.notenoughupdates.util.LateBindingChroma; import io.github.moulberry.notenoughupdates.util.Utils; @@ -33,6 +34,7 @@ import java.util.List; import java.util.Set; import java.util.regex.Matcher; +@NEUAutoSubscribe public class EnchantStyleCustomizer { public static EnchantStyleCustomizer INSTANCE = new EnchantStyleCustomizer(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/world/EnderNodeHighlighter.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/world/EnderNodeHighlighter.java index ce0e6a25..51fc950c 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/world/EnderNodeHighlighter.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/world/EnderNodeHighlighter.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures.world; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.events.SpawnParticleEvent; import io.github.moulberry.notenoughupdates.util.SBInfo; import io.github.moulberry.notenoughupdates.util.SpecialColour; @@ -33,6 +34,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import static io.github.moulberry.notenoughupdates.util.MathUtil.basicallyEqual; +@NEUAutoSubscribe public class EnderNodeHighlighter extends GenericBlockHighlighter { private static final EnderNodeHighlighter INSTANCE = new EnderNodeHighlighter(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/world/FrozenTreasuresHighlighter.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/world/FrozenTreasuresHighlighter.java index a7a8706a..2f8071a0 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/world/FrozenTreasuresHighlighter.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/world/FrozenTreasuresHighlighter.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures.world; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.util.SBInfo; import io.github.moulberry.notenoughupdates.util.SpecialColour; import net.minecraft.block.Block; @@ -34,6 +35,7 @@ import net.minecraftforge.fml.common.gameevent.TickEvent; import java.util.List; +@NEUAutoSubscribe public class FrozenTreasuresHighlighter extends GenericBlockHighlighter { private static final FrozenTreasuresHighlighter INSTANCE = new FrozenTreasuresHighlighter(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/world/GlowingMushroomHighlighter.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/world/GlowingMushroomHighlighter.java index fa5794ea..17f5f527 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/world/GlowingMushroomHighlighter.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/world/GlowingMushroomHighlighter.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures.world; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.events.SpawnParticleEvent; import io.github.moulberry.notenoughupdates.util.SBInfo; import io.github.moulberry.notenoughupdates.util.SpecialColour; @@ -33,6 +34,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import static io.github.moulberry.notenoughupdates.util.MathUtil.isDecimalPartApproximately; +@NEUAutoSubscribe public class GlowingMushroomHighlighter extends GenericBlockHighlighter { @SubscribeEvent diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java index 5f5c4832..48d37f2f 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java @@ -24,6 +24,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.core.BackgroundBlur; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; @@ -66,6 +67,7 @@ import java.util.regex.Pattern; import static io.github.moulberry.notenoughupdates.util.GuiTextures.help; +@NEUAutoSubscribe public class CalendarOverlay { private static final ResourceLocation BACKGROUND = new ResourceLocation("notenoughupdates:calendar/background.png"); private static final ResourceLocation DISPLAYBAR = new ResourceLocation("notenoughupdates:calendar/displaybar.png"); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java index aa977413..e81834d3 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java @@ -28,7 +28,6 @@ import io.github.moulberry.notenoughupdates.recipes.RecipeHistory; import io.github.moulberry.notenoughupdates.recipes.RecipeSlot; import io.github.moulberry.notenoughupdates.recipes.RecipeType; import io.github.moulberry.notenoughupdates.util.Utils; -import lombok.var; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.GuiButton; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/InventoryStorageSelector.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/InventoryStorageSelector.java index 205dcd83..8ee68457 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/InventoryStorageSelector.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/InventoryStorageSelector.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscgui; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.core.config.KeybindHelper; import io.github.moulberry.notenoughupdates.miscfeatures.StorageManager; import io.github.moulberry.notenoughupdates.util.Utils; @@ -39,7 +40,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.InputEvent; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; - +@NEUAutoSubscribe public class InventoryStorageSelector { private static final InventoryStorageSelector INSTANCE = new InventoryStorageSelector(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/SignCalculator.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/SignCalculator.java index ac676a98..4f01e551 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/SignCalculator.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/SignCalculator.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscgui; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.events.SignSubmitEvent; import io.github.moulberry.notenoughupdates.mixins.AccessorGuiEditSign; import io.github.moulberry.notenoughupdates.util.Calculator; @@ -35,6 +36,7 @@ import java.text.DecimalFormat; import java.math.BigDecimal; import java.util.Objects; +@NEUAutoSubscribe public class SignCalculator { String lastSource = null; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/StorageOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/StorageOverlay.java index 8878c284..5dd8bd9c 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/StorageOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/StorageOverlay.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 NotEnoughUpdates contributors + * Copyright (C) 2022-2023 NotEnoughUpdates contributors * * This file is part of NotEnoughUpdates. * @@ -55,7 +55,6 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; -import net.minecraft.util.IChatComponent; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.ClientCommandHandler; import org.lwjgl.input.Keyboard; @@ -392,6 +391,10 @@ public class StorageOverlay extends GuiElement { searchTextColour = 0xa0a0a0; } + if (NotEnoughUpdates.INSTANCE.config.storageGUI.useCustomTextColour) { + textColour = ChromaColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.storageGUI.customTextColour); + } + long currentTime = System.currentTimeMillis(); if (lastMillis > 0) { long deltaTime = currentTime - lastMillis; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/TrophyRewardOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/TrophyRewardOverlay.java index 828e50b1..e13934e1 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/TrophyRewardOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/TrophyRewardOverlay.java @@ -22,6 +22,7 @@ package io.github.moulberry.notenoughupdates.miscgui; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.events.RepositoryReloadEvent; import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer; import io.github.moulberry.notenoughupdates.util.Constants; @@ -50,6 +51,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +@NEUAutoSubscribe public class TrophyRewardOverlay { private static TrophyRewardOverlay instance = null; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/MinionHelperManager.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/MinionHelperManager.java index 512ebb8f..03eb227c 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/MinionHelperManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/MinionHelperManager.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscgui.minionhelper; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.miscgui.minionhelper.loaders.MinionHelperApiLoader; import io.github.moulberry.notenoughupdates.miscgui.minionhelper.loaders.MinionHelperChatLoader; import io.github.moulberry.notenoughupdates.miscgui.minionhelper.loaders.MinionHelperInventoryLoader; @@ -41,6 +42,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +@NEUAutoSubscribe public class MinionHelperManager { private static MinionHelperManager instance = null; private final Map<String, Minion> minions = new HashMap<>(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperChatLoader.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperChatLoader.java index bef633d2..95277c6a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperChatLoader.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperChatLoader.java @@ -60,6 +60,7 @@ public class MinionHelperChatLoader { String rawTier = ownMatcher.group(1); int tier = Utils.parseRomanNumeral(rawTier); String name = ownMatcher.group(2) + " Minion"; + name = Utils.cleanColour(name); setCrafted(manager.getMinionByName(name, tier)); } @@ -80,7 +81,7 @@ public class MinionHelperChatLoader { } catch (Exception e) { Utils.addChatMessage( - "[NEU] §cMinion Helper failed reading the minion upgrade message. See the logs for more info!"); + "§c[NEU] Minion Helper failed reading the minion upgrade message. See the logs for more info!"); e.printStackTrace(); } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/MinionHelperOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/MinionHelperOverlay.java index 33753d6c..1a625794 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/MinionHelperOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/MinionHelperOverlay.java @@ -19,6 +19,7 @@ package io.github.moulberry.notenoughupdates.miscgui.minionhelper.render; +import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Lists; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.core.util.ArrowPagesUtils; @@ -28,6 +29,8 @@ import io.github.moulberry.notenoughupdates.miscgui.minionhelper.Minion; import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager; import io.github.moulberry.notenoughupdates.miscgui.minionhelper.render.renderables.OverviewLine; import io.github.moulberry.notenoughupdates.miscgui.minionhelper.render.renderables.OverviewText; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources.MinionSource; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources.NpcSource; import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer; import io.github.moulberry.notenoughupdates.util.ItemUtils; import io.github.moulberry.notenoughupdates.util.NotificationHandler; @@ -72,7 +75,7 @@ public class MinionHelperOverlay { private boolean filterEnabled = true; private boolean useInstantBuyPrice = true; - private int maxPerPage = 8; + private int maxPerPage = 7; private int currentPage = 0; public MinionHelperOverlay(MinionHelperManager manager) { @@ -262,18 +265,34 @@ public class MinionHelperOverlay { for (Map.Entry<String, OverviewLine> entry : renderMap.entrySet()) { String line = entry.getKey(); + /* + * Renders the part of the string after '§6' and before '§7' with shadows. + * + * I don't know how to tell mixin to "only capture part x if part y is present" + * Therefore I use these bad splits. I'm Sorry! + */ if (line.contains("§6")) { String[] split = line.split("§6"); line = split[0]; String price = "§6§l" + split[1]; + + if (price.contains("§8")) { + split = price.split("§8"); + String newPrice = split[0]; + String stuffBehindPricePart = "§8" + price.substring(newPrice.length() + 2); + price = newPrice; + int lineLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line + price); + fontRendererObj.drawString(stuffBehindPricePart, x + lineLen, y, -1, false); + } + int lineLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line); fontRendererObj.drawString(price, x + lineLen, y, -1, true); } fontRendererObj.drawString(line, x, y, -1, false); i++; - if (i == 2) { - y += 15; + if (i == 3) { + y += 13; } else { y += 10; } @@ -302,13 +321,14 @@ public class MinionHelperOverlay { LinkedHashMap<String, OverviewLine> renderMap ) { int neededForNextSlot = manager.getNeedForNextSlot(); - String color = "§8"; if (neededForNextSlot == -1) { - renderMap.put(color + "Next slot: ?", new OverviewText(Collections.emptyList(), () -> {})); + renderMap.put("§8Next slot: ?", new OverviewText(Collections.emptyList(), () -> {})); return; } double priceNeeded = 0; + int peltsNeeded = 0; + int northStarsNeeded = 0; int xpGain = 0; int index = 0; for (Minion minion : TrophyRewardOverlay.sortByValue(prices).keySet()) { @@ -316,12 +336,20 @@ public class MinionHelperOverlay { priceNeeded += price; xpGain += minion.getXpGain(); index++; + peltsNeeded += getSpecialItemNeeds(minion, "SKYBLOCK_PELT"); + northStarsNeeded += getSpecialItemNeeds(minion, "SKYBLOCK_NORTH_STAR"); if (index == neededForNextSlot) break; } - String format = manager.getPriceCalculation().formatCoins(priceNeeded); - format = format.replace(" coins", ""); - String text = - color + "Next slot: §3" + neededForNextSlot + " minions §8- " + format; + String costFormat = manager.getPriceCalculation().formatCoins(priceNeeded); + costFormat = costFormat.replace(" coins", ""); + + if (peltsNeeded > 0) { + costFormat = costFormat + " §8+ §5" + peltsNeeded + " Pelts"; + } + if (northStarsNeeded > 0) { + costFormat = costFormat + " §8+ §d" + northStarsNeeded + " North Stars"; + } + List<String> lore; if (xpGain == 0) { if (index == 0) { @@ -334,7 +362,25 @@ public class MinionHelperOverlay { "§8DISCLAIMER: This only works if", "§8you follow the helper." ); } - renderMap.put(text, new OverviewText(lore, () -> {})); + OverviewText overviewText = new OverviewText(lore, () -> {}); + renderMap.put("§8Next slot: §3" + neededForNextSlot + " minions", overviewText); + renderMap.put("§8Cost: " + costFormat, overviewText); + } + + private static int getSpecialItemNeeds(Minion minion, String specialItem) { + int count = 0; + MinionSource minionSource = minion.getMinionSource(); + + if (minionSource instanceof NpcSource) { + NpcSource source = (NpcSource) minionSource; + ArrayListMultimap<String, Integer> items = source.getItems(); + if (items.containsKey(specialItem)) { + for (Integer amount : items.get(specialItem)) { + count += amount; + } + } + } + return count; } private void addTitle(Map<Minion, Double> prices, LinkedHashMap<String, OverviewLine> renderMap) { @@ -424,8 +470,8 @@ public class MinionHelperOverlay { return entry.getValue(); } i++; - if (i == 2) { - y += 15; + if (i == 3) { + y += 13; } else { y += 10; } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/util/MinionHelperPriceCalculation.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/util/MinionHelperPriceCalculation.java index cb43100b..e3614627 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/util/MinionHelperPriceCalculation.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/util/MinionHelperPriceCalculation.java @@ -80,13 +80,14 @@ public class MinionHelperPriceCalculation { if (source instanceof NpcSource) { ArrayListMultimap<String, Integer> items = ((NpcSource) source).getItems(); + // Please hypixel never ever add a minion recipe with pelts and north stars at the same time! Thank you :) if (items.containsKey("SKYBLOCK_PELT")) { int amount = items.get("SKYBLOCK_PELT").get(0); - result += " §7+ §5" + amount + " Pelts"; + result += " §8+ §5" + amount + " Pelts"; } if (items.containsKey("SKYBLOCK_NORTH_STAR")) { int amount = items.get("SKYBLOCK_NORTH_STAR").get(0); - result += " §7+ §d" + amount + " North Stars"; + result += " §8+ §d" + amount + " North Stars"; } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java index bd1dff63..8aca73d1 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java @@ -295,8 +295,9 @@ public abstract class MixinGuiContainer extends GuiScreen { @Redirect(method = "drawScreen", at = @At(value = "INVOKE", target = TARGET_CANBEHOVERED)) public boolean drawScreen_canBeHovered(Slot slot) { - if (NotEnoughUpdates.INSTANCE.config.improvedSBMenu.hideEmptyPanes && - BetterContainers.isOverriding() && BetterContainers.isBlankStack(slot.slotNumber, slot.getStack())) { + if ((NotEnoughUpdates.INSTANCE.config.improvedSBMenu.hideEmptyPanes && + BetterContainers.isOverriding() && BetterContainers.isBlankStack(slot.slotNumber, slot.getStack())) || + slot.getStack() != null && slot.getStack().hasTagCompound() && slot.getStack().getTagCompound().getBoolean("NEUHIDETOOLIP")) { return false; } return slot.canBeHovered(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiUtils.java new file mode 100644 index 00000000..0ad2a098 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiUtils.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2023 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.mixins; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraftforge.fml.client.config.GuiUtils; +import org.lwjgl.input.Mouse; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; + +@Mixin(value = GuiUtils.class, remap = false) +public class MixinGuiUtils { + @Inject(method = "drawHoveringText", at = @At("HEAD")) + private static void drawHoveringText_head( + List<String> textLines, int mouseX, int mouseY, int screenWidth, int screenHeight, int maxTextWidth, FontRenderer font, CallbackInfo ci) { + Utils.pushGuiScale(NotEnoughUpdates.INSTANCE.config.tooltipTweaks.guiScale); + } + + @ModifyVariable(method = "drawHoveringText", at = @At(value = "HEAD"), ordinal = 0, argsOnly = true) + private static int drawHoveringText_modifyMouseX(int mouseX) { + return Mouse.getX() * Utils.pushGuiScale(NotEnoughUpdates.INSTANCE.config.tooltipTweaks.guiScale).getScaledWidth() / Minecraft.getMinecraft().displayWidth; + } + + @ModifyVariable(method = "drawHoveringText", at = @At(value = "HEAD"), ordinal = 1, argsOnly = true) + private static int drawHoveringText_modifyMouseY(int mouseY) { + return Utils.pushGuiScale(NotEnoughUpdates.INSTANCE.config.tooltipTweaks.guiScale).getScaledHeight() - + Mouse.getY() * Utils.pushGuiScale(NotEnoughUpdates.INSTANCE.config.tooltipTweaks.guiScale).getScaledHeight() / Minecraft.getMinecraft().displayHeight; + } + + + @ModifyVariable(method = "drawHoveringText", at = @At(value = "HEAD"), ordinal = 2, argsOnly = true) + private static int drawHoveringText_modifyWidth(int width) { + return Utils.pushGuiScale(NotEnoughUpdates.INSTANCE.config.tooltipTweaks.guiScale).getScaledWidth(); + } + + @ModifyVariable(method = "drawHoveringText", at = @At(value = "HEAD"), ordinal = 3, argsOnly = true) + private static int drawHoveringText_modifyHeight(int height) { + return Utils.pushGuiScale(NotEnoughUpdates.INSTANCE.config.tooltipTweaks.guiScale).getScaledHeight(); + } + + @Inject(method = "drawHoveringText", at = @At("TAIL")) + private static void drawHoveringText_tail( + List<String> textLines, int mouseX, int mouseY, int screenWidth, int screenHeight, int maxTextWidth, FontRenderer font, CallbackInfo ci) { + Utils.resetGuiScale(); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryPlayer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryPlayer.java index de117002..22e53ae1 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryPlayer.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryPlayer.java @@ -19,13 +19,17 @@ package io.github.moulberry.notenoughupdates.mixins; +import io.github.moulberry.notenoughupdates.events.ReplaceItemEvent; import io.github.moulberry.notenoughupdates.miscfeatures.SlotLocking; import io.github.moulberry.notenoughupdates.miscgui.InventoryStorageSelector; import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(InventoryPlayer.class) public class MixinInventoryPlayer { @@ -42,4 +46,24 @@ public class MixinInventoryPlayer { SlotLocking.getInstance().changedSlot($this.currentItem); } + + @Shadow public ItemStack[] mainInventory; + @Shadow public ItemStack[] armorInventory; + + @Inject(method = "getStackInSlot", at = @At("HEAD"), cancellable = true) + public void on(int index, CallbackInfoReturnable<ItemStack> cir) { + ItemStack itemStack = + index < mainInventory.length + ? this.mainInventory[index] + : this.armorInventory[index - mainInventory.length]; + ReplaceItemEvent replaceItemEventInventory = new ReplaceItemEvent( + itemStack, + ((InventoryPlayer) (Object) this), + index + ); + replaceItemEventInventory.post(); + if (replaceItemEventInventory.getReplacement() != replaceItemEventInventory.getOriginal()) { + cir.setReturnValue(replaceItemEventInventory.getReplacement()); + } + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLayerDeadmau5Head.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLayerDeadmau5Head.java new file mode 100644 index 00000000..14ae9c74 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLayerDeadmau5Head.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2023 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.mixins; + +import io.github.moulberry.notenoughupdates.miscfeatures.entityviewer.GUIClientPlayer; +import net.minecraft.client.entity.AbstractClientPlayer; +import net.minecraft.client.renderer.entity.layers.LayerDeadmau5Head; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(LayerDeadmau5Head.class) +public class MixinLayerDeadmau5Head { + + @Inject(method = "doRenderLayer(Lnet/minecraft/client/entity/AbstractClientPlayer;FFFFFFF)V", at = @At("HEAD"), cancellable = true) + public void doRenderLayer( + AbstractClientPlayer entitylivingbaseIn, float f, float g, float partialTicks, float h, float i, float j, float scale, CallbackInfo ci) { + if (entitylivingbaseIn instanceof GUIClientPlayer) ci.cancel(); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinThreadDownloadImageData.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinThreadDownloadImageData.java index c6d25a9e..fd4ee495 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinThreadDownloadImageData.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinThreadDownloadImageData.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Linnea Gräf + * Copyright (C) 2022-2023 Linnea Gräf * * This file is part of NotEnoughUpdates. * @@ -30,12 +30,14 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(ThreadDownloadImageData.class) -public class MixinThreadDownloadImageData { +public class MixinThreadDownloadImageData implements ThreadDownloadImageHook.AccessorThreadDownloadImageData{ @Mutable @Shadow @Final private String imageUrl; + private String originalUrl; + @Redirect( method = "<init>", at = @At( @@ -44,5 +46,16 @@ public class MixinThreadDownloadImageData { opcode = Opcodes.PUTFIELD)) public void useHttpsDownloadLinks(ThreadDownloadImageData instance, String value) { this.imageUrl = ThreadDownloadImageHook.hookThreadImageLink(value); + this.originalUrl = value; + } + + @Override + public String getOriginalUrl() { + return originalUrl; + } + + @Override + public String getPatchedUrl() { + return imageUrl; } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Mining.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Mining.java index b82b44c2..74400f59 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Mining.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Mining.java @@ -233,12 +233,31 @@ public class Mining { @ConfigOption( name = "Star Cult Tab", desc = "Only show the star cult timer when tab list is open\n" + - "\u00A7cThis only works outside of Dwarven Caves!" + "§cThis only works outside of Dwarven Caves!" ) @ConfigEditorBoolean @ConfigAccordionId(id = 2) public boolean starCultDisplayOnlyShowTab = false; + @Expose + @ConfigOption( + name = "Commission Task Tips", + desc = "Show tips to help complete commission tasks" + ) + @ConfigEditorDropdown( + values = {"Off", "Only while sneaking", "Always"} + ) + @ConfigAccordionId(id = 2) + public int commissionTaskTips = 0; + + @Expose + @ConfigOption( + name = "Tips in New Line", + desc = "Show the Commission Task Tips in the next line.") + @ConfigEditorBoolean + @ConfigAccordionId(id = 2) + public boolean commissionTaskTipNewLine = true; + @ConfigOption( name = "Metal Detector Solver", desc = "" @@ -738,7 +757,7 @@ public class Mining { @Expose @ConfigOption( name = "Enable Tracker", - desc = "Show an Overlay with useful information related to Power Grinding" + desc = "Show an Overlay with useful information related to Powder Grinding" ) @ConfigAccordionId(id = 9) @ConfigEditorBoolean diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Misc.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Misc.java index b72610b8..47e51eec 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Misc.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Misc.java @@ -305,8 +305,8 @@ public class Misc { @Expose @ConfigOption( - name = "Dungeon Groups PV", - desc = "View another player's profile by clicking on the chat message when they join in a dungeon group." + name = "Group Join PV", + desc = "View another player's profile by clicking on the chat message when they join in a dungeon or kuudra group." ) @ConfigEditorBoolean public boolean dungeonGroupsPV = true; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ProfileViewer.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ProfileViewer.java index 30915daa..42a52639 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ProfileViewer.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ProfileViewer.java @@ -103,4 +103,12 @@ public class ProfileViewer { ) @ConfigEditorBoolean public boolean useSoopyNetworth = true; + + @Expose + @ConfigOption( + name = "Display Weight", + desc = "Display Lily and Senither Weight in the Basic PV page" + ) + @ConfigEditorBoolean + public boolean displayWeight = true; } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/StorageGUI.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/StorageGUI.java index 08c48945..131ac669 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/StorageGUI.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/StorageGUI.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 NotEnoughUpdates contributors + * Copyright (C) 2022-2023 NotEnoughUpdates contributors * * This file is part of NotEnoughUpdates. * @@ -155,6 +155,26 @@ public class StorageGUI { @Expose @ConfigOption( + name = "Custom Text Colour", + desc = "Use a custom default text colour.\nOverrides the colour set by the overlay style.\nCan be overridden by using colour codes in the page title.", + searchTags = "color" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 1) + public boolean useCustomTextColour = false; + + @Expose + @ConfigOption( + name = "Custom Text Colour", + desc = "Requires the above option to be set to true", + searchTags = "color" + ) + @ConfigEditorColour + @ConfigAccordionId(id = 1) + public String customTextColour = "0:255:144:144:144"; + + @Expose + @ConfigOption( name = "Scrollable Tooltips", desc = "Support for scrolling tooltips for users with small monitors\n" + "This will prevent the menu from scrolling while holding the key, allowing you to scroll tooltips" diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TooltipTweaks.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TooltipTweaks.java index 8539c3c4..45a96577 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TooltipTweaks.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TooltipTweaks.java @@ -24,6 +24,7 @@ import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigAccord import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorAccordion; import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean; import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDraggableList; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown; import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorKeybind; import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider; import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption; @@ -147,6 +148,16 @@ public class TooltipTweaks { @Expose @ConfigOption( + name = "Resize tooltips", + desc = "Resizes tooltips to make them readable" + ) + @ConfigEditorDropdown( + values = {"Default", "Small", "Normal", "Large", "Auto"} + ) + public int guiScale = 0; + + @Expose + @ConfigOption( name = "Expand Pet Exp Requirement", desc = "Show which the full amount of pet xp required" ) diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/EquipmentOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/EquipmentOverlay.java index 5cd8f6b3..db81bfa4 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/EquipmentOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/EquipmentOverlay.java @@ -24,6 +24,7 @@ import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import io.github.moulberry.notenoughupdates.NEUManager; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.events.GuiInventoryBackgroundDrawnEvent; import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay; import io.github.moulberry.notenoughupdates.miscgui.GuiInvButtonEditor; @@ -54,6 +55,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; +@NEUAutoSubscribe public class EquipmentOverlay { public static EquipmentOverlay INSTANCE = new EquipmentOverlay(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/FuelBar.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/FuelBar.java index f2e485f2..9212eb6f 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/FuelBar.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/FuelBar.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.overlays; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.core.config.Position; import io.github.moulberry.notenoughupdates.core.config.gui.GuiPositionEditor; import io.github.moulberry.notenoughupdates.util.SBInfo; @@ -38,6 +39,7 @@ import org.lwjgl.opengl.GL14; import java.awt.*; +@NEUAutoSubscribe public class FuelBar { public static final ResourceLocation FUEL_BAR = new ResourceLocation("notenoughupdates:fuel_bar.png"); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/MiningOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/MiningOverlay.java index f25407b6..ea253e94 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/MiningOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/MiningOverlay.java @@ -31,7 +31,6 @@ import io.github.moulberry.notenoughupdates.util.StarCultCalculator; import io.github.moulberry.notenoughupdates.util.TabListUtils; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiChat; import net.minecraft.client.gui.inventory.GuiChest; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.init.Items; @@ -39,10 +38,6 @@ import net.minecraft.inventory.ContainerChest; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumChatFormatting; -import net.minecraft.world.WorldSettings; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -import org.lwjgl.input.Keyboard; import org.lwjgl.util.vector.Vector2f; import java.util.ArrayList; @@ -379,22 +374,35 @@ public class MiningOverlay extends TextTabOverlay { } else if (entry.getValue() >= 0.25) { col = GOLD; } + String tips = getTipPart(entry.getKey()); + boolean newLine = NotEnoughUpdates.INSTANCE.config.mining.commissionTaskTipNewLine; + String newLineTip = null; + if (newLine) { + if (!tips.isEmpty()) { + newLineTip = " " + tips; + tips = ""; + } + } NEUConfig.HiddenLocationSpecific locationSpecific = NotEnoughUpdates.INSTANCE.config.getLocationSpecific(); int max; if (-1 != (max = locationSpecific.commissionMaxes.getOrDefault(entry.getKey(), -1))) { commissionsStrings.add( - DARK_AQUA + entry.getKey() + ": " + col + Math.round(entry.getValue() * max) + "/" + max); + DARK_AQUA + entry.getKey() + ": " + col + Math.round(entry.getValue() * max) + "/" + max + tips); } else { String valS = Utils.floatToString(entry.getValue() * 100, 1); - commissionsStrings.add(DARK_AQUA + entry.getKey() + ": " + col + valS + "%"); + commissionsStrings.add(DARK_AQUA + entry.getKey() + ": " + col + valS + "%" + tips); + } + if (newLineTip != null) { + commissionsStrings.add(newLineTip); } } } if (ItemCooldowns.firstLoadMillis > 0) { //set cooldown on first skyblock load. - ItemCooldowns.pickaxeUseCooldownMillisRemaining = 60 * 1000 - (System.currentTimeMillis() - ItemCooldowns.firstLoadMillis); + ItemCooldowns.pickaxeUseCooldownMillisRemaining = + 60 * 1000 - (System.currentTimeMillis() - ItemCooldowns.firstLoadMillis); ItemCooldowns.firstLoadMillis = 0; } @@ -449,7 +457,7 @@ public class MiningOverlay extends TextTabOverlay { } if (starCultDisplay) { - if(overlayStrings == null) overlayStrings = new ArrayList<>(); + if (overlayStrings == null) overlayStrings = new ArrayList<>(); if (!NotEnoughUpdates.INSTANCE.config.mining.starCultDisplayOnlyShowTab || lastTabState) { @@ -467,7 +475,7 @@ public class MiningOverlay extends TextTabOverlay { } if (forgeDisplay) { - if(overlayStrings == null) overlayStrings = new ArrayList<>(); + if (overlayStrings == null) overlayStrings = new ArrayList<>(); if (!NotEnoughUpdates.INSTANCE.config.mining.forgeDisplayOnlyShowTab || lastTabState) { @@ -484,14 +492,97 @@ public class MiningOverlay extends TextTabOverlay { if (overlayStrings != null && overlayStrings.isEmpty()) overlayStrings = null; } + private String getTipPart(String name) { + int settings = NotEnoughUpdates.INSTANCE.config.mining.commissionTaskTips; + if (settings == 0) return ""; + + if (!Minecraft.getMinecraft().thePlayer.isSneaking() && settings == 1) return ""; + + String tip = getTip(name); + if (tip == null) return " §4???"; + + return " §8§l>§7 " + tip; + } + + private String getTip(String name) { + if (SBInfo.getInstance().getLocation().equals("mining_3")) { // Dwarven Mines + if (name.equals("First Event")) return "Participate in any §6Mining Event"; + + // During Event + if (name.equals("Lucky Raffle")) return "Collect 20 Raffle Tickets during §6Raffle Event"; + if (name.equals("Goblin Raid Slayer")) return "Kill 20 Goblins during §6Goblin Raid Event"; + if (name.equals("Raffle")) return "Participate in §6Raffle Event"; + if (name.equals("Goblin Raid")) return "Participate in §6Goblin Raid event"; + if (name.equals("2x Mithril Powder Collector")) return "Collect 500 Mithril Powder during §62x Powder event"; + + // Slay + if (name.equals("Ice Walker Slayer")) return "Kill 50 Ice Walkers §b(Great Ice Wall)"; + if (name.equals("Goblin Slayer")) return "Kill 100 Goblins §b(Goblin Borrows)"; + if (name.equals("Golden Goblin Slayer")) return "Kill 1 Golden Goblin (anywhere)"; + if (name.equals("Star Sentry Puncher")) return "Damage Star Sentries 10 times (anywhere)"; + + // Mining + if (name.equals("Mithril Miner")) return "Break 500 Mithril (anywhere)"; + if (name.equals("Titanium Miner")) return "Break 15 Titanium (anywhere)"; + + if (name.equals("Cliffside Veins Mithril")) return "Break 350 Mithril §b(Cliffside Veins)"; + if (name.equals("Royal Mines Mithril")) return "Break 350 Mithril §b(Royal Mines)"; + if (name.equals("Lava Springs Mithril")) return "Break 350 Mithril §b(Lava Springs)"; + if (name.equals("Rampart's Quarry Mithril")) return "Break 350 Mithril §b(Rampart's Quarry)"; + if (name.equals("Upper Mines Mithril")) return "Break 350 Mithril §b(Upper Mines)"; + + if (name.equals("Cliffside Veins Titanium")) return "Break 10 Titanium §b(Cliffside Veins)"; + if (name.equals("Lava Springs Titanium")) return "Break 10 Titanium §b(Lava Springs)"; + if (name.equals("Royal Mines Titanium")) return "Break 10 Titanium §b(Royal Mines)"; + if (name.equals("Rampart's Quarry Titanium")) return "Break 10 Titanium §b(Rampart's Quarry)"; + if (name.equals("Upper Mines Titanium")) return "Break 10 Titanium §b(Upper Mines)"; + + } else if (SBInfo.getInstance().getLocation().equals("crystal_hollows")) { // Crystal Hollows + if (name.equals("Chest Looter")) return "Open 3 chests"; + if (name.equals("Hard Stone Miner")) return "Break 1,000 Hard Stone"; + + String jungle = " §a(Jungle)"; + String goblin = " §6(Golbin Holdout)"; + String mithril = " §b(Mithril Deposits)"; + String precursor = " §8(Precursor Remenants)"; + String magma = " §c(Magma Fields)"; + + if (name.equals("Goblin Slayer")) return "Kill 13 Goblins" + goblin; + if (name.equals("Sludge Slayer")) return "Kill 25 Sludges" + jungle; + if (name.equals("Thyst Slayer")) return "Kill 5 Thysts, when breaking Amethysts" + jungle; + if (name.equals("Boss Corleone Slayer")) return "Find and kill Corleone" + mithril; + if (name.equals("Yog Slayer")) return "Kill 13 Yogs" + magma; + if (name.equals("Automaton Slayer")) return "Kill 13 Automatons" + precursor; + if (name.equals("Team Treasurite Member Slayer")) return "Kill 13 Team Treasurite Members" + mithril; + + if (name.endsWith("Crystal Hunter")) { + if (name.startsWith("Amethyst")) return "Temple Jump & Run" + jungle; + if (name.startsWith("Jade")) return "4 weapons from Mines of Divan" + mithril; + if (name.startsWith("Amber")) return "King and Queen" + goblin; + if (name.startsWith("Sapphire")) return "6 Robot Parts in Precursor City" + precursor; + if (name.startsWith("Topaz")) return "Kill Bal" + magma; + } + + if (name.endsWith("Gemstone Collector")) { + if (name.startsWith("Amber")) return "Break orange glass" + goblin; + if (name.startsWith("Sapphire")) return "Break blue glass" + precursor; + if (name.startsWith("Jade")) return "Break green glass" + mithril; + if (name.startsWith("Amethyst")) return "Break purple glass" + jungle; + if (name.startsWith("Ruby")) return "Break red glass (anywhere)"; + if (name.startsWith("Topaz")) return "Break yellow glass" + magma; + } + } + + return null; + } + private static List<String> getForgeStrings(List<ForgeItem> forgeItems) { List<String> forgeString = new ArrayList<>(); long currentTimeMillis = System.currentTimeMillis(); forgeIDLabel: for (int i = 0; i < 5; i++) { - for (ForgeItem forgeItem : forgeItems) { - if (forgeItem.forgeID == i) { - ForgeItem item = forgeItem; + for (ForgeItem item : forgeItems) { + if (item.forgeID == i) { if (NotEnoughUpdates.INSTANCE.config.mining.forgeDisplay == 0) { if (item.status == 2 && item.finishTime < currentTimeMillis) { @@ -541,7 +632,6 @@ public class MiningOverlay extends TextTabOverlay { } } forgeItems.add(item); - return; } public static class ForgeItem { @@ -617,6 +707,9 @@ public class MiningOverlay extends TextTabOverlay { if (!NotEnoughUpdates.INSTANCE.config.mining.dwarvenOverlayIcons) return; GlStateManager.enableDepth(); + // No icon for the tip line + if (line.contains(">")) return; + ItemStack icon = null; String cleaned = Utils.cleanColour(line); String beforeColon = cleaned.split(":")[0]; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/PowderGrindingOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/PowderGrindingOverlay.java index 50ecce90..ad8755e3 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/PowderGrindingOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/PowderGrindingOverlay.java @@ -19,8 +19,6 @@ package io.github.moulberry.notenoughupdates.overlays; -import com.google.gson.Gson; -import com.google.gson.JsonObject; import com.google.gson.JsonParser; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.core.config.Position; @@ -28,26 +26,19 @@ import io.github.moulberry.notenoughupdates.core.util.lerp.LerpUtils; import io.github.moulberry.notenoughupdates.options.NEUConfig; import io.github.moulberry.notenoughupdates.util.SBInfo; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.nio.charset.StandardCharsets; import java.text.NumberFormat; import java.util.ArrayList; import java.util.List; import java.util.function.Supplier; -import java.util.stream.Collectors; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class PowderGrindingOverlay extends TextTabOverlay { private final static JsonParser PARSER = new JsonParser(); + private final static Pattern pattern = + Pattern.compile("You received \\+([0-9]+(?:,\\d+)*) (Mithril|Gemstone) Powder\\."); public int chestCount = 0; public int openedChestCount = 0; @@ -112,7 +103,8 @@ public class PowderGrindingOverlay extends TextTabOverlay { overlayStrings.add("\u00a73Opened Chests: \u00a7a" + format.format(this.openedChestCount)); break; case 2: - overlayStrings.add("\u00a73Unopened Chests: \u00a7c" + format.format(this.chestCount - this.openedChestCount)); + overlayStrings.add( + "\u00a73Unopened Chests: \u00a7c" + format.format(this.chestCount - this.openedChestCount)); break; case 3: overlayStrings.add("\u00a73Mithril Powder Found: \u00a72" + @@ -141,21 +133,26 @@ public class PowderGrindingOverlay extends TextTabOverlay { if (overlayStrings != null && overlayStrings.isEmpty()) overlayStrings = null; } - public void message(String message) { + public void onMessage(String message) { if (message.equals("You uncovered a treasure chest!")) { this.chestCount++; } else if (message.equals("You have successfully picked the lock on this chest!")) { this.openedChestCount++; } else { - boolean mithril = message.endsWith(" Mithril Powder"); - boolean gemstone = message.endsWith(" Gemstone Powder"); - if (!(mithril || gemstone)) return; - try { - int amount = Integer.parseInt(message.split(" ")[2].replaceAll("\\+", "")); - if (mithril) this.mithrilPowderFound += amount; - else this.gemstonePowderFound += amount; - } catch (NumberFormatException | IndexOutOfBoundsException e) { - e.printStackTrace(); + Matcher matcher = pattern.matcher(message); + if (matcher.matches()) { + String rawNumber = matcher.group(1).replace(",", ""); + try { + int amount = Integer.parseInt(rawNumber); + String type = matcher.group(2); + if (type.equals("Mithril")) { + this.mithrilPowderFound += amount; + } else if (type.equals("Gemstone")) { + this.gemstonePowderFound += amount; + } + } catch (NumberFormatException e) { + e.printStackTrace(); + } } } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java index 873ee9f2..8a48dd2c 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java @@ -19,13 +19,13 @@ package io.github.moulberry.notenoughupdates.profileviewer; -import com.google.common.base.Splitter; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.mojang.authlib.GameProfile; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.core.util.StringUtils; +import io.github.moulberry.notenoughupdates.profileviewer.level.LevelPage; import io.github.moulberry.notenoughupdates.profileviewer.weight.lily.LilyWeight; import io.github.moulberry.notenoughupdates.profileviewer.weight.senither.SenitherWeight; import io.github.moulberry.notenoughupdates.util.Constants; @@ -53,11 +53,12 @@ import org.apache.commons.lang3.text.WordUtils; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL14; import java.awt.*; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Optional; @@ -72,6 +73,34 @@ import static io.github.moulberry.notenoughupdates.util.Utils.roundToNearestInt; public class BasicPage extends GuiProfileViewerPage { private static final ResourceLocation pv_basic = new ResourceLocation("notenoughupdates:pv_basic.png"); + + public static final ItemStack skull = Utils.createSkull( + "egirlefe", + "152de44a-43a3-46e1-badc-66cca2793471", + "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODdkODg1YjMyYjBkZDJkNmI3ZjFiNTgyYTM0MTg2ZjhhNTM3M2M0NjU4OWEyNzM0MjMxMzJiNDQ4YjgwMzQ2MiJ9fX0=" + ); + + private static final LinkedHashMap<String, ItemStack> dungeonsModeIcons = new LinkedHashMap<String, ItemStack>() { + { + put( + "first_page", + Utils.editItemStackInfo( + new ItemStack(Items.paper), + EnumChatFormatting.GRAY + "Front Page", + true + ) + ); + put( + "second_page", + Utils.editItemStackInfo( + skull, + EnumChatFormatting.GRAY + "Level Page", + true + ) + ); + } + }; + private static final ExecutorService profileLoader = Executors.newFixedThreadPool(1); public EntityOtherPlayerMP entityPlayer = null; private ResourceLocation playerLocationSkin = null; @@ -88,9 +117,14 @@ public class BasicPage extends GuiProfileViewerPage { private int backgroundClickedX = -1; + private boolean onSecondPage; + + private final LevelPage levelPage; + public BasicPage(GuiProfileViewer instance) { super(instance); this.guiProfileViewer = instance; + this.levelPage = new LevelPage(guiProfileViewer, this); } @Override @@ -101,6 +135,11 @@ public class BasicPage extends GuiProfileViewerPage { int guiLeft = GuiProfileViewer.getGuiLeft(); int guiTop = GuiProfileViewer.getGuiTop(); + if (onSecondPage) { + levelPage.drawPage(mouseX, mouseY); + return; + } + String location = null; JsonObject status = profile.getPlayerStatus(); if (status != null && status.has("mode")) { @@ -280,7 +319,7 @@ public class BasicPage extends GuiProfileViewerPage { EnumChatFormatting.GREEN + "Net Worth: " + EnumChatFormatting.GOLD + GuiProfileViewer.numberFormat.format(networth), fr, - guiLeft + 63, + guiLeft + 165, guiTop + 38, true, 0 @@ -297,11 +336,10 @@ public class BasicPage extends GuiProfileViewerPage { ); String networthIRLMoney = GuiProfileViewer.numberFormat.format(Math.round( ((networthInCookies * 325) / 675) * 4.99)); - if ( - mouseX > guiLeft + 8 && - mouseX < guiLeft + 8 + fr.getStringWidth("Net Worth: " + GuiProfileViewer.numberFormat.format(networth)) - ) { - if (mouseY > guiTop + 32 && mouseY < guiTop + 32 + fr.FONT_HEIGHT) { + + int fontWidth = fr.getStringWidth("Net Worth: " + GuiProfileViewer.numberFormat.format(networth)); + if (mouseX > guiLeft + 165 - fontWidth / 2 && mouseX < guiLeft + 165 + fontWidth / 2) { + if (mouseY > guiTop + 32 && mouseY < guiTop + 38 + fr.FONT_HEIGHT) { getInstance().tooltipToDisplay = new ArrayList<>(); getInstance() .tooltipToDisplay.add( @@ -349,7 +387,7 @@ public class BasicPage extends GuiProfileViewerPage { Utils.drawStringCentered( EnumChatFormatting.GREEN + "Net Worth: " + stateStr, fr, - guiLeft + 63, + guiLeft + 165, guiTop + 38, true, 0 @@ -534,116 +572,29 @@ public class BasicPage extends GuiProfileViewerPage { ); } - PlayerStats.Stats stats = profile.getStats(profileId); + // sb lvlL - if (stats != null) { - Splitter splitter = Splitter.on(" ").omitEmptyStrings().limit(2); - for (int i = 0; i < PlayerStats.defaultStatNames.length; i++) { - String statName = PlayerStats.defaultStatNames[i]; - //if (statName.equals("mining_fortune") || statName.equals("mining_speed")) continue; - String statNamePretty = PlayerStats.defaultStatNamesPretty[i]; + int sbLevelX = guiLeft + 162; + int sbLevelY = guiTop + 90; - int val = Math.round(stats.get(statName)); + double skyblockLevel = profile.getSkyblockLevel(profileId); + EnumChatFormatting skyblockLevelColour = profile.getSkyblockLevelColour(profileId); - GlStateManager.color(1, 1, 1, 1); - GlStateManager.enableBlend(); - GL14.glBlendFuncSeparate( - GL11.GL_SRC_ALPHA, - GL11.GL_ONE_MINUS_SRC_ALPHA, - GL11.GL_ONE, - GL11.GL_ONE_MINUS_SRC_ALPHA - ); - Utils.renderAlignedString( - statNamePretty, - EnumChatFormatting.WHITE.toString() + val, - guiLeft + 132, - guiTop + 21 + 11f * i, - 80 - ); + GlStateManager.pushMatrix(); + GlStateManager.translate(sbLevelX, sbLevelY, 0); + GlStateManager.scale(1.5f, 1.5f, 1); + Utils.drawItemStack(skull, 0, 0); + GlStateManager.popMatrix(); + Utils.drawStringScaled(skyblockLevelColour.toString() + (int) skyblockLevel, fr, + sbLevelX - 2, sbLevelY - 15, true, 0, 1.5f + ); - if (mouseX > guiLeft + 132 && mouseX < guiLeft + 212) { - if (mouseY > guiTop + 21 + 11f * i && mouseY < guiTop + 37 + 11f * i) { - List<String> split = splitter.splitToList(statNamePretty); - PlayerStats.Stats baseStats = PlayerStats.getBaseStats(); - getInstance().tooltipToDisplay = new ArrayList<>(); - getInstance().tooltipToDisplay.add(statNamePretty); - int base = Math.round(baseStats.get(statName)); - getInstance() - .tooltipToDisplay.add( - EnumChatFormatting.GRAY + - "Base " + - split.get(1) + - ": " + - EnumChatFormatting.GREEN + - base + - " " + - split.get(0) - ); - int passive = Math.round(profile.getPassiveStats(profileId).get(statName) - baseStats.get(statName)); - getInstance() - .tooltipToDisplay.add( - EnumChatFormatting.GRAY + - "Passive " + - split.get(1) + - " Bonus: +" + - EnumChatFormatting.YELLOW + - passive + - " " + - split.get(0) - ); - int itemBonus = Math.round(stats.get(statName) - profile.getPassiveStats(profileId).get(statName)); - getInstance() - .tooltipToDisplay.add( - EnumChatFormatting.GRAY + - "Item " + - split.get(1) + - " Bonus: +" + - EnumChatFormatting.DARK_PURPLE + - itemBonus + - " " + - split.get(0) - ); - int finalStat = Math.round(stats.get(statName)); - getInstance() - .tooltipToDisplay.add( - EnumChatFormatting.GRAY + - "Final " + - split.get(1) + - ": +" + - EnumChatFormatting.RED + - finalStat + - " " + - split.get(0) - ); - } - } - } - } else { - Utils.drawStringCentered( - EnumChatFormatting.RED + "Skill/Inv/Coll", - Minecraft.getMinecraft().fontRendererObj, - guiLeft + 172, - guiTop + 101 - 10, - true, - 0 - ); - Utils.drawStringCentered( - EnumChatFormatting.RED + "APIs not", - Minecraft.getMinecraft().fontRendererObj, - guiLeft + 172, - guiTop + 101, - true, - 0 - ); - Utils.drawStringCentered( - EnumChatFormatting.RED + "enabled!", - Minecraft.getMinecraft().fontRendererObj, - guiLeft + 172, - guiTop + 101 + 10, - true, - 0 - ); - } + float progress = (float) (skyblockLevel - (long) skyblockLevel); + getInstance().renderBar(sbLevelX - 30, sbLevelY + 30, 80, progress); + + Utils.drawStringScaled(EnumChatFormatting.YELLOW.toString() + (int) (progress * 100) + "/100", fr, + sbLevelX - 30, sbLevelY + 20, true, 0, 0.9f + ); if (skyblockInfo != null) { int position = 0; @@ -672,6 +623,12 @@ public class BasicPage extends GuiProfileViewerPage { getInstance().renderBar(x, y + 6, 80, level.level % 1); } + if (mouseX >= guiLeft + 128 && mouseX <= guiLeft + 216) { + if (mouseY >= guiTop + 69 && mouseY <= guiTop + 131) { + if (Mouse.isButtonDown(0)) onSecondPage = true; + } + } + if (mouseX > x && mouseX < x + 80) { if (mouseY > y - 4 && mouseY < y + 13) { getInstance().tooltipToDisplay = new ArrayList<>(); @@ -691,7 +648,7 @@ public class BasicPage extends GuiProfileViewerPage { "/" + StringUtils.shortNumberFormat(maxXp)); } - String totalXpS = GuiProfileViewer.numberFormat.format((int) level.totalXp); + String totalXpS = GuiProfileViewer.numberFormat.format((long) level.totalXp); tooltipToDisplay.add(EnumChatFormatting.GRAY + "Total XP: " + EnumChatFormatting.DARK_PURPLE + totalXpS + EnumChatFormatting.DARK_GRAY + " (" + DECIMAL_FORMAT.format(guiProfileViewer.getPercentage(entry.getKey().toLowerCase(), level)) + @@ -759,7 +716,8 @@ public class BasicPage extends GuiProfileViewerPage { ); } - renderWeight(mouseX, mouseY, skyblockInfo, profileInfo); + drawSideButtons(); + if (NotEnoughUpdates.INSTANCE.config.profileViewer.displayWeight) renderWeight(mouseX, mouseY, skyblockInfo, profileInfo); } private String getIcon(String gameModeType) { @@ -830,14 +788,13 @@ public class BasicPage extends GuiProfileViewerPage { weight = profile.getSoopyWeightLeaderboardPosition(); } - Utils.drawStringCentered( EnumChatFormatting.GREEN + "Senither Weight: " + EnumChatFormatting.GOLD + GuiProfileViewer.numberFormat.format(roundToNearestInt(senitherWeight.getTotalWeight().getRaw())), fr, - guiLeft + 63, + guiLeft + 165, guiTop + 18, true, 0 @@ -847,7 +804,7 @@ public class BasicPage extends GuiProfileViewerPage { "Senither Weight: " + GuiProfileViewer.numberFormat.format(roundToNearestInt(senitherWeight.getTotalWeight().getRaw())) ); - if (mouseX > guiLeft + 63 - textWidth / 2 && mouseX < guiLeft + 63 + textWidth / 2) { + if (mouseX > guiLeft + 165 - textWidth / 2 && mouseX < guiLeft + 165 + textWidth / 2) { if (mouseY > guiTop + 12 && mouseY < guiTop + 12 + fr.FONT_HEIGHT) { getInstance().tooltipToDisplay = new ArrayList<>(); getInstance() @@ -905,7 +862,7 @@ public class BasicPage extends GuiProfileViewerPage { EnumChatFormatting.GOLD + GuiProfileViewer.numberFormat.format(roundToNearestInt(lilyWeight.getTotalWeight().getRaw())), fr, - guiLeft + 63, + guiLeft + 165, guiTop + 28, true, 0 @@ -914,7 +871,7 @@ public class BasicPage extends GuiProfileViewerPage { int fontWidth = fr.getStringWidth( "Lily Weight: " + GuiProfileViewer.numberFormat.format(roundToNearestInt(lilyWeight.getTotalWeight().getRaw())) ); - if (mouseX > guiLeft + 63 - fontWidth / 2 && mouseX < guiLeft + 63 + fontWidth / 2) { + if (mouseX > guiLeft + 165 - fontWidth / 2 && mouseX < guiLeft + 165 + fontWidth / 2) { if (mouseY > guiTop + 22 && mouseY < guiTop + 22 + fr.FONT_HEIGHT) { getInstance().tooltipToDisplay = new ArrayList<>(); getInstance() @@ -992,10 +949,62 @@ public class BasicPage extends GuiProfileViewerPage { GlStateManager.setActiveTexture(OpenGlHelper.defaultTexUnit); } + @Override + public boolean mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + super.mouseClicked(mouseX, mouseY, mouseButton); + int guiLeft = GuiProfileViewer.getGuiLeft(); + int guiTop = GuiProfileViewer.getGuiTop(); + + int i = onSlotToChangePage(mouseX, mouseY, guiLeft, guiTop); + switch (i) { + case 1: + onSecondPage = false; + break; + case 2: + onSecondPage = true; + break; + + default: + break; + } + + return false; + } + + public int onSlotToChangePage(int mouseX, int mouseY, int guiLeft, int guiTop) { + if (mouseX >= guiLeft - 29 && mouseX <= guiLeft) { + if (mouseY >= guiTop && mouseY <= guiTop + 28) { + return 1; + } else if (mouseY + 28 >= guiTop && mouseY <= guiTop + 28 * 2) { + return 2; + } + } + return 0; + } + public String getGameModeType(JsonObject profileInfo) { if (profileInfo != null && profileInfo.has("game_mode")) { return profileInfo.get("game_mode").getAsString(); } return ""; } + + public void drawSideButtons() { + GlStateManager.enableDepth(); + GlStateManager.translate(0, 0, 5); + if (onSecondPage) { + Utils.drawPvSideButton(1, dungeonsModeIcons.get("second_page"), true, guiProfileViewer); + } else { + Utils.drawPvSideButton(0, dungeonsModeIcons.get("first_page"), true, guiProfileViewer); + } + GlStateManager.translate(0, 0, -3); + + GlStateManager.translate(0, 0, -2); + if (!onSecondPage) { + Utils.drawPvSideButton(1, dungeonsModeIcons.get("second_page"), false, guiProfileViewer); + } else { + Utils.drawPvSideButton(0, dungeonsModeIcons.get("first_page"), false, guiProfileViewer); + } + GlStateManager.disableDepth(); + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/CollectionsPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/CollectionsPage.java index 554e204c..45d9370b 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/CollectionsPage.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/CollectionsPage.java @@ -24,6 +24,7 @@ import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.core.util.StringUtils; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.Utils; +import io.github.moulberry.notenoughupdates.util.hypixelapi.ProfileCollectionInfo; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.item.ItemStack; @@ -35,6 +36,9 @@ import org.lwjgl.opengl.GL11; import java.awt.*; import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.RoundingMode; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Iterator; @@ -87,7 +91,8 @@ public class CollectionsPage extends GuiProfileViewerPage { Minecraft.getMinecraft().getTextureManager().bindTexture(pv_cols); Utils.drawTexturedRect(guiLeft, guiTop, getInstance().sizeX, getInstance().sizeY, GL11.GL_NEAREST); - JsonObject collectionInfo = GuiProfileViewer.getProfile().getCollectionInfo(GuiProfileViewer.getProfileId()); + ProfileCollectionInfo collectionInfo = + GuiProfileViewer.getProfile().getCollectionInfo(GuiProfileViewer.getProfileId()); if (collectionInfo == null) { Utils.drawStringCentered( EnumChatFormatting.RED + "Collection API not enabled!", @@ -197,110 +202,114 @@ public class CollectionsPage extends GuiProfileViewerPage { 4210752 ); - JsonObject minionTiers = collectionInfo.get("minion_tiers").getAsJsonObject(); - JsonObject collectionTiers = collectionInfo.get("collection_tiers").getAsJsonObject(); - JsonObject maxAmounts = collectionInfo.get("max_amounts").getAsJsonObject(); - JsonObject totalAmounts = collectionInfo.get("total_amounts").getAsJsonObject(); - JsonObject personalAmounts = collectionInfo.get("personal_amounts").getAsJsonObject(); - if (collections != null) { for (int i = page * 20, j = 0; i < Math.min((page + 1) * 20, collections.size()); i++, j++) { String collection = collections.get(i); - if (collection != null) { - ItemStack collectionItem = ProfileViewer.getCollectionToCollectionDisplayMap().get(collection); - if (collectionItem != null) { - int xIndex = j % COLLS_XCOUNT; - int yIndex = j / COLLS_XCOUNT; - - float x = 39 + COLLS_XPADDING + (COLLS_XPADDING + 20) * xIndex; - float y = 7 + COLLS_YPADDING + (COLLS_YPADDING + 20) * yIndex; - - String tierString; - int tier = (int) Utils.getElementAsFloat(collectionTiers.get(collection), 0); - if (tier > 20 || tier < 0) { - tierString = String.valueOf(tier); - } else { - tierString = romans[tier]; - } - float amount = Utils.getElementAsFloat(totalAmounts.get(collection), 0); - float maxAmount = Utils.getElementAsFloat(maxAmounts.get(collection), 0); - Color color = new Color(128, 128, 128, 255); - int tierStringColour = color.getRGB(); - float completedness = 0; - if (maxAmount > 0) { - completedness = amount / maxAmount; - } - completedness = Math.min(1, completedness); - if (maxAmounts.has(collection) && completedness >= 1) { - tierStringColour = new Color(255, 215, 0).getRGB(); - } - - GlStateManager.color(1, 1, 1, 1); - Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); - Utils.drawTexturedRect( - guiLeft + x, - guiTop + y, - 20, - 20 * (1 - completedness), - 0, - 20 / 256f, - 0, - 20 * (1 - completedness) / 256f, - GL11.GL_NEAREST - ); - GlStateManager.color(1, 185 / 255f, 0, 1); - Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); - Utils.drawTexturedRect( - guiLeft + x, - guiTop + y + 20 * (1 - completedness), - 20, - 20 * (completedness), - 0, - 20 / 256f, - 20 * (1 - completedness) / 256f, - 20 / 256f, - GL11.GL_NEAREST + if (collection == null) { + continue; + } + ProfileCollectionInfo.CollectionInfo thisCollection = collectionInfo.getCollections().get(collection); + if (thisCollection == null) { + Utils.showOutdatedRepoNotification(); + continue; + } + ItemStack collectionItem = ProfileViewer.getCollectionToCollectionDisplayMap().get(collection); + if (collectionItem == null) { + continue; + } + int xIndex = j % COLLS_XCOUNT; + int yIndex = j / COLLS_XCOUNT; + + float x = 39 + COLLS_XPADDING + (COLLS_XPADDING + 20) * xIndex; + float y = 7 + COLLS_YPADDING + (COLLS_YPADDING + 20) * yIndex; + + String tierString; + int tier = thisCollection.getUnlockedTiers().size(); + if (tier > 20 || tier == 0) { + tierString = String.valueOf(tier); + } else { + tierString = romans[tier - 1]; + } + BigInteger amount = thisCollection.getTotalCollectionCount(); + BigInteger maxAmount = BigInteger.valueOf(thisCollection.getCollection().getTiers().get(thisCollection.getCollection().getTiers().size() - 1).getAmountRequired()); + Color color = new Color(128, 128, 128, 255); + int tierStringColour = color.getRGB(); + float completedness = 0; + if (maxAmount.compareTo(BigInteger.ZERO) > 0) { + if (amount.compareTo(maxAmount) > 0) { + completedness = 1; + } else { + completedness = amount.floatValue() / maxAmount.floatValue(); + } + } + if (completedness >= 1) { + tierStringColour = new Color(255, 215, 0).getRGB(); + } + + GlStateManager.color(1, 1, 1, 1); + Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); + Utils.drawTexturedRect( + guiLeft + x, + guiTop + y, + 20, + 20 * (1 - completedness), + 0, + 20 / 256f, + 0, + 20 * (1 - completedness) / 256f, + GL11.GL_NEAREST + ); + GlStateManager.color(1, 185 / 255f, 0, 1); + Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); + Utils.drawTexturedRect( + guiLeft + x, + guiTop + y + 20 * (1 - completedness), + 20, + 20 * (completedness), + 0, + 20 / 256f, + 20 * (1 - completedness) / 256f, + 20 / 256f, + GL11.GL_NEAREST + ); + Utils.drawItemStack(collectionItem, guiLeft + (int) x + 2, guiTop + (int) y + 2); + + if (mouseX > guiLeft + (int) x + 2 && mouseX < guiLeft + (int) x + 18) { + if (mouseY > guiTop + (int) y + 2 && mouseY < guiTop + (int) y + 18) { + tooltipToDisplay = new ArrayList<>(); + tooltipToDisplay.add( + collectionItem.getDisplayName() + + " " + + (completedness >= 1 ? EnumChatFormatting.GOLD : EnumChatFormatting.GRAY) + + tierString ); - Utils.drawItemStack(collectionItem, guiLeft + (int) x + 2, guiTop + (int) y + 2); - - if (mouseX > guiLeft + (int) x + 2 && mouseX < guiLeft + (int) x + 18) { - if (mouseY > guiTop + (int) y + 2 && mouseY < guiTop + (int) y + 18) { - tooltipToDisplay = new ArrayList<>(); - tooltipToDisplay.add( - collectionItem.getDisplayName() + - " " + - (completedness >= 1 ? EnumChatFormatting.GOLD : EnumChatFormatting.GRAY) + - tierString - ); - tooltipToDisplay.add( - "Collected: " + numberFormat.format(Utils.getElementAsFloat(personalAmounts.get(collection), 0)) - ); - tooltipToDisplay.add("Total Collected: " + numberFormat.format(amount)); - } - } - - GlStateManager.color(1, 1, 1, 1); - if (tier >= 0) { - Utils.drawStringCentered( - tierString, - Minecraft.getMinecraft().fontRendererObj, - guiLeft + x + 10, - guiTop + y - 4, - true, - tierStringColour - ); - } - - Utils.drawStringCentered( - StringUtils.shortNumberFormat(amount) + "", - Minecraft.getMinecraft().fontRendererObj, - guiLeft + x + 10, - guiTop + y + 26, - true, - color.getRGB() + tooltipToDisplay.add( + "Collected: " + numberFormat.format(thisCollection.getPersonalCollectionCount()) ); + tooltipToDisplay.add("Total Collected: " + numberFormat.format(amount)); } } + + GlStateManager.color(1, 1, 1, 1); + if (tier >= 0) { + Utils.drawStringCentered( + tierString, + Minecraft.getMinecraft().fontRendererObj, + guiLeft + x + 10, + guiTop + y - 4, + true, + tierStringColour + ); + } + + Utils.drawStringCentered( + StringUtils.shortNumberFormat(amount) + "", + Minecraft.getMinecraft().fontRendererObj, + guiLeft + x + 10, + guiTop + y + 26, + true, + color.getRGB() + ); } } @@ -316,97 +325,99 @@ public class CollectionsPage extends GuiProfileViewerPage { if (minions != null) { for (int i = page * 20, j = 0; i < Math.min((page + 1) * 20, minions.size()); i++, j++) { String minion = minions.get(i); - if (minion != null) { - JsonObject misc = Constants.MISC; - float MAX_MINION_TIER = Utils.getElementAsFloat(Utils.getElement(misc, "minions." + minion + "_GENERATOR"), 11); - - int tier = (int) Utils.getElementAsFloat(minionTiers.get(minion), 0); - JsonObject minionJson; - if (tier == 0) { - minionJson = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(minion + "_GENERATOR_1"); - } else { - minionJson = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(minion + "_GENERATOR_" + tier); - } + if (minion == null) { + continue; + } + JsonObject misc = Constants.MISC; + float MAX_MINION_TIER = Utils.getElementAsFloat(Utils.getElement(misc, "minions." + minion + "_GENERATOR"), 11); - if (minionJson != null) { - int xIndex = j % COLLS_XCOUNT; - int yIndex = j / COLLS_XCOUNT; - - float x = 231 + COLLS_XPADDING + (COLLS_XPADDING + 20) * xIndex; - float y = 7 + COLLS_YPADDING + (COLLS_YPADDING + 20) * yIndex; - - String tierString; - - if (tier - 1 >= romans.length || tier - 1 < 0) { - tierString = String.valueOf(tier); - } else { - tierString = romans[tier - 1]; - } - - Color color = new Color(128, 128, 128, 255); - int tierStringColour = color.getRGB(); - float completedness = tier / MAX_MINION_TIER; - - completedness = Math.min(1, completedness); - if (completedness >= 1) { - tierStringColour = new Color(255, 215, 0).getRGB(); - } - - GlStateManager.color(1, 1, 1, 1); - Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); - Utils.drawTexturedRect( - guiLeft + x, - guiTop + y, - 20, - 20 * (1 - completedness), - 0, - 20 / 256f, - 0, - 20 * (1 - completedness) / 256f, - GL11.GL_NEAREST - ); - GlStateManager.color(1, 185 / 255f, 0, 1); - Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); - Utils.drawTexturedRect( - guiLeft + x, - guiTop + y + 20 * (1 - completedness), - 20, - 20 * (completedness), - 0, - 20 / 256f, - 20 * (1 - completedness) / 256f, - 20 / 256f, - GL11.GL_NEAREST - ); + int tier = collectionInfo.getCraftedGenerators().getOrDefault(minion, 0); + JsonObject minionJson; + if (tier == 0) { + minionJson = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(minion + "_GENERATOR_1"); + } else { + minionJson = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(minion + "_GENERATOR_" + tier); + } - Utils.drawItemStack( - NotEnoughUpdates.INSTANCE.manager.jsonToStack(minionJson), - guiLeft + (int) x + 2, - guiTop + (int) y + 2 - ); + if (minionJson == null) { + continue; + } + int xIndex = j % COLLS_XCOUNT; + int yIndex = j / COLLS_XCOUNT; + + float x = 231 + COLLS_XPADDING + (COLLS_XPADDING + 20) * xIndex; + float y = 7 + COLLS_YPADDING + (COLLS_YPADDING + 20) * yIndex; + + String tierString; + + if (tier - 1 >= romans.length || tier - 1 < 0) { + tierString = String.valueOf(tier); + } else { + tierString = romans[tier - 1]; + } + + Color color = new Color(128, 128, 128, 255); + int tierStringColour = color.getRGB(); + float completedness = tier / MAX_MINION_TIER; + + completedness = Math.min(1, completedness); + if (completedness >= 1) { + tierStringColour = new Color(255, 215, 0).getRGB(); + } - if (mouseX > guiLeft + (int) x + 2 && mouseX < guiLeft + (int) x + 18) { - if (mouseY > guiTop + (int) y + 2 && mouseY < guiTop + (int) y + 18) { - tooltipToDisplay = - NotEnoughUpdates.INSTANCE.manager - .jsonToStack(minionJson) - .getTooltip(Minecraft.getMinecraft().thePlayer, false); - } - } - - GlStateManager.color(1, 1, 1, 1); - if (tier >= 0) { - Utils.drawStringCentered( - tierString, - Minecraft.getMinecraft().fontRendererObj, - guiLeft + x + 10, - guiTop + y - 4, - true, - tierStringColour - ); - } + GlStateManager.color(1, 1, 1, 1); + Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); + Utils.drawTexturedRect( + guiLeft + x, + guiTop + y, + 20, + 20 * (1 - completedness), + 0, + 20 / 256f, + 0, + 20 * (1 - completedness) / 256f, + GL11.GL_NEAREST + ); + GlStateManager.color(1, 185 / 255f, 0, 1); + Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); + Utils.drawTexturedRect( + guiLeft + x, + guiTop + y + 20 * (1 - completedness), + 20, + 20 * (completedness), + 0, + 20 / 256f, + 20 * (1 - completedness) / 256f, + 20 / 256f, + GL11.GL_NEAREST + ); + + Utils.drawItemStack( + NotEnoughUpdates.INSTANCE.manager.jsonToStack(minionJson), + guiLeft + (int) x + 2, + guiTop + (int) y + 2 + ); + + if (mouseX > guiLeft + (int) x + 2 && mouseX < guiLeft + (int) x + 18) { + if (mouseY > guiTop + (int) y + 2 && mouseY < guiTop + (int) y + 18) { + tooltipToDisplay = + NotEnoughUpdates.INSTANCE.manager + .jsonToStack(minionJson) + .getTooltip(Minecraft.getMinecraft().thePlayer, false); } } + + GlStateManager.color(1, 1, 1, 1); + if (tier >= 0) { + Utils.drawStringCentered( + tierString, + Minecraft.getMinecraft().fontRendererObj, + guiLeft + x + 10, + guiTop + y - 4, + true, + tierStringColour + ); + } } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/CrimsonIslePage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/CrimsonIslePage.java index 95009b1d..6460003a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/CrimsonIslePage.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/CrimsonIslePage.java @@ -55,15 +55,12 @@ public class CrimsonIslePage extends GuiProfileViewerPage { NotEnoughUpdates.INSTANCE.manager.createItem("KUUDRA_INFERNAL_TIER_KEY"), }; - public static final String[] KUUDRA_TIERS = { - "Basic", - "Hot", - "Burning", - "Fiery", - "Infernal" - }; + private static final String[] KUUDRA_TIERS_NAME = {"Basic", "Hot", "Burning", "Fiery", "Infernal"}; + + // This is different to the one above as these refer to the names of the tiers in the API + public static final String[] KUUDRA_TIERS = {"none", "hot", "burning", "fiery", "infernal"}; - private static final LinkedHashMap<String, String> apiDojoTestNames = new LinkedHashMap<String, String>() {{ + public static final LinkedHashMap<String, String> apiDojoTestNames = new LinkedHashMap<String, String>() {{ put("mob_kb", EnumChatFormatting.GOLD + "Test of Force"); put("wall_jump", EnumChatFormatting.LIGHT_PURPLE + "Test of Stamina"); put("archer", EnumChatFormatting.YELLOW + "Test of Mastery"); @@ -73,7 +70,7 @@ public class CrimsonIslePage extends GuiProfileViewerPage { put("fireball", EnumChatFormatting.GOLD + "Test of Tenacity"); }}; - private static final LinkedHashMap<Integer, String> dojoPointsToRank = new LinkedHashMap<Integer, String>() {{ + public static final LinkedHashMap<Integer, String> dojoPointsToRank = new LinkedHashMap<Integer, String>() {{ put(0, EnumChatFormatting.GRAY + "None"); put(1000, EnumChatFormatting.YELLOW + "Yellow"); put(2000, EnumChatFormatting.GREEN + "Green"); @@ -151,21 +148,18 @@ public class CrimsonIslePage extends GuiProfileViewerPage { JsonObject kuudraCompletedTiers = data.getAsJsonObject("kuudra_completed_tiers"); - // This is different to the one initialised at the start of the class as these refer to the names of the tiers in the API - String[] kuudraTiers = {"none", "hot", "burning", "fiery", "infernal"}; - RenderHelper.enableGUIStandardItemLighting(); for (int i = 0; i < 5; i++) { // Checking the player has completions for each tier // and get the number of completions if they do int completions = - kuudraCompletedTiers.has(kuudraTiers[i]) ? kuudraCompletedTiers.get(kuudraTiers[i]).getAsInt() : 0; + kuudraCompletedTiers.has(KUUDRA_TIERS[i]) ? kuudraCompletedTiers.get(KUUDRA_TIERS[i]).getAsInt() : 0; // Get the highest wave for this tier of kuudra if they have completed a run // since infernal kuudra was released - int highestWaveCompleted = kuudraCompletedTiers.has("highest_wave_" + kuudraTiers[i]) ? - kuudraCompletedTiers.get("highest_wave_" + kuudraTiers[i]).getAsInt() : 0; + int highestWaveCompleted = kuudraCompletedTiers.has("highest_wave_" + KUUDRA_TIERS[i]) ? + kuudraCompletedTiers.get("highest_wave_" + KUUDRA_TIERS[i]).getAsInt() : 0; Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI( KUUDRA_KEYS[i], @@ -174,7 +168,7 @@ public class CrimsonIslePage extends GuiProfileViewerPage { ); Utils.renderAlignedString( - EnumChatFormatting.RED + KUUDRA_TIERS[i] + ": ", + EnumChatFormatting.RED + KUUDRA_TIERS_NAME[i] + ": ", EnumChatFormatting.WHITE + String.valueOf(completions), guiLeft + 23, guiTop + 30 + (i * 30), @@ -190,7 +184,8 @@ public class CrimsonIslePage extends GuiProfileViewerPage { ); if (highestWaveCompleted == 0) { - if (mouseX > guiLeft + 23 && mouseX < guiLeft + 133 && mouseY < guiTop + 50 + (i*30) && mouseY > guiTop + 42 + (i*30)) { + if (mouseX > guiLeft + 23 && mouseX < guiLeft + 133 && mouseY < guiTop + 50 + (i * 30) && + mouseY > guiTop + 42 + (i * 30)) { getInstance().tooltipToDisplay = new ArrayList<>(); getInstance().tooltipToDisplay.add(EnumChatFormatting.RED + "N/A will only show for highest wave"); getInstance().tooltipToDisplay.add(EnumChatFormatting.RED + "if you have not completed a run for"); @@ -278,7 +273,7 @@ public class CrimsonIslePage extends GuiProfileViewerPage { ); } - public String getRank(int points) { + public static String getRank(int points) { int lastRank = 0; for (Map.Entry<Integer, String> rank : dojoPointsToRank.entrySet()) { if (points < rank.getKey()) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/DungeonPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/DungeonPage.java index cbebb6f4..9d227daf 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/DungeonPage.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/DungeonPage.java @@ -42,7 +42,6 @@ import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.ResourceLocation; import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL14; import java.io.IOException; import java.util.Base64; @@ -54,7 +53,7 @@ public class DungeonPage extends GuiProfileViewerPage { private static final ResourceLocation pv_dung = new ResourceLocation("notenoughupdates:pv_dung.png"); private static final ItemStack DEADBUSH = new ItemStack(Item.getItemFromBlock(Blocks.deadbush)); - private static final String[] dungSkillsName = { "Healer", "Mage", "Berserk", "Archer", "Tank" }; + private static final String[] dungSkillsName = {"Healer", "Mage", "Berserk", "Archer", "Tank"}; private static final ItemStack[] BOSS_HEADS = new ItemStack[7]; private static final ItemStack[] dungSkillsStack = { new ItemStack(Items.potionitem, 1, 16389), @@ -63,7 +62,7 @@ public class DungeonPage extends GuiProfileViewerPage { new ItemStack(Items.bow), new ItemStack(Items.leather_chestplate), }; - private static final String[] bossFloorArr = { "Bonzo", "Scarf", "Professor", "Thorn", "Livid", "Sadan", "Necron" }; + private static final String[] bossFloorArr = {"Bonzo", "Scarf", "Professor", "Thorn", "Livid", "Sadan", "Necron"}; private static final String[] bossFloorHeads = { "12716ecbf5b8da00b05f316ec6af61e8bd02805b21eb8e440151468dc656549c", "7de7bbbdf22bfe17980d4e20687e386f11d59ee1db6f8b4762391b79a5ac532d", @@ -145,7 +144,7 @@ public class DungeonPage extends GuiProfileViewerPage { //Catacombs level thingy { if (levelObjCata == null) { - float cataXp = Utils.getElementAsFloat(Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.experience"), 0); + float cataXp = getElementAsFloat(profileInfo, "dungeons.dungeon_types.catacombs.experience"); levelObjCata = ProfileViewer.getLevel( Utils.getElementOrDefault(leveling, "catacombs", new JsonArray()).getAsJsonArray(), @@ -181,11 +180,20 @@ public class DungeonPage extends GuiProfileViewerPage { if (mouseX > x && mouseX < x + sectionWidth && mouseY > y + 16 && mouseY < y + 24 && !onMasterMode) { float F5 = - (Utils.getElementAsFloat(Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.tier_completions." + 5), 0)); //this can prob be done better + (Utils.getElementAsFloat(Utils.getElement( + profileInfo, + "dungeons.dungeon_types.catacombs.tier_completions." + 5 + ), 0)); //this can prob be done better float F6 = - (Utils.getElementAsFloat(Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.tier_completions." + 6), 0)); + (Utils.getElementAsFloat(Utils.getElement( + profileInfo, + "dungeons.dungeon_types.catacombs.tier_completions." + 6 + ), 0)); float F7 = - (Utils.getElementAsFloat(Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.tier_completions." + 7), 0)); + (Utils.getElementAsFloat(Utils.getElement( + profileInfo, + "dungeons.dungeon_types.catacombs.tier_completions." + 7 + ), 0)); if (F5 > 150) { F5 = 150; } @@ -208,43 +216,23 @@ public class DungeonPage extends GuiProfileViewerPage { long runsF6 = (int) Math.ceil(floorLevelToXP / xpF6); long runsF7 = (int) Math.ceil(floorLevelToXP / xpF7); - float timeF5 = Utils.getElementAsFloat( - Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.fastest_time_s_plus.5"), - 0 - ); - float timeF6 = Utils.getElementAsFloat( - Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.fastest_time_s_plus.6"), - 0 - ); - float timeF7 = Utils.getElementAsFloat( - Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.fastest_time_s_plus.7"), - 0 - ); + float timeF5 = getElementAsFloat(profileInfo, "dungeons.dungeon_types.catacombs.fastest_time_s_plus.5"); + float timeF6 = getElementAsFloat(profileInfo, "dungeons.dungeon_types.catacombs.fastest_time_s_plus.6"); + float timeF7 = getElementAsFloat(profileInfo, "dungeons.dungeon_types.catacombs.fastest_time_s_plus.7"); getInstance().tooltipToDisplay = Lists.newArrayList( - EnumChatFormatting.YELLOW + "Remaining XP: " + EnumChatFormatting.GRAY + String.format("%,d", floorLevelToXP), + EnumChatFormatting.YELLOW + "Remaining XP: " + EnumChatFormatting.GRAY + + String.format("%,d", floorLevelToXP), String.format("# F5 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpF5), runsF5), String.format("# F6 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpF6), runsF6), String.format("# F7 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpF7), runsF7), "" ); boolean hasTime = false; - if (timeF5 > 1000) { - getInstance() - .tooltipToDisplay.add(String.format("Expected Time (F5) : %s", Utils.prettyTime(runsF5 * (long) (timeF5 * 1.2)))); - hasTime = true; - } - if (timeF6 > 1000) { - getInstance() - .tooltipToDisplay.add(String.format("Expected Time (F6) : %s", Utils.prettyTime(runsF6 * (long) (timeF6 * 1.2)))); - hasTime = true; - } - if (timeF7 > 1000) { - getInstance() - .tooltipToDisplay.add(String.format("Expected Time (F7) : %s", Utils.prettyTime(runsF7 * (long) (timeF7 * 1.2)))); - hasTime = true; - } + hasTime = isHasTime(timeF5, "Expected Time (F5) : %s", runsF5, hasTime); + hasTime = isHasTime(timeF6, "Expected Time (F6) : %s", runsF6, hasTime); + hasTime = isHasTime(timeF7, "Expected Time (F7) : %s", runsF7, hasTime); if (hasTime) { getInstance().tooltipToDisplay.add(""); } @@ -261,19 +249,20 @@ public class DungeonPage extends GuiProfileViewerPage { getInstance() .tooltipToDisplay.add( "The " + - EnumChatFormatting.DARK_PURPLE + - "Catacombs Expert Ring" + - EnumChatFormatting.GRAY + - " is assumed to be used, unless " + - EnumChatFormatting.YELLOW + - "SHIFT" + - EnumChatFormatting.GRAY + - " is held." + EnumChatFormatting.DARK_PURPLE + + "Catacombs Expert Ring" + + EnumChatFormatting.GRAY + + " is assumed to be used, unless " + + EnumChatFormatting.YELLOW + + "SHIFT" + + EnumChatFormatting.GRAY + + " is held." ); getInstance().tooltipToDisplay.add("[Time per run] is calculated using Fastest S+ x 120%"); } else { getInstance() - .tooltipToDisplay.add("[Hold " + EnumChatFormatting.YELLOW + "CTRL" + EnumChatFormatting.GRAY + " to see details]"); + .tooltipToDisplay.add( + "[Hold " + EnumChatFormatting.YELLOW + "CTRL" + EnumChatFormatting.GRAY + " to see details]"); } } @@ -348,63 +337,29 @@ public class DungeonPage extends GuiProfileViewerPage { long runsM6 = (int) Math.ceil(floorLevelToXP / xpM6); long runsM7 = (int) Math.ceil(floorLevelToXP / xpM7); - float timeM3 = Utils.getElementAsFloat( - Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.3"), - 0 - ); - float timeM4 = Utils.getElementAsFloat( - Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.4"), - 0 - ); - float timeM5 = Utils.getElementAsFloat( - Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.5"), - 0 - ); - float timeM6 = Utils.getElementAsFloat( - Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.6"), - 0 - ); - float timeM7 = Utils.getElementAsFloat( - Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.7"), - 0 - ); + float timeM3 = getElementAsFloat(profileInfo, "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.3"); + float timeM4 = getElementAsFloat(profileInfo, "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.4"); + float timeM5 = getElementAsFloat(profileInfo, "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.5"); + float timeM6 = getElementAsFloat(profileInfo, "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.6"); + float timeM7 = getElementAsFloat(profileInfo, "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.7"); getInstance().tooltipToDisplay = Lists.newArrayList( - EnumChatFormatting.YELLOW + "Remaining XP: " + EnumChatFormatting.GRAY + String.format("%,d", floorLevelToXP), + EnumChatFormatting.YELLOW + "Remaining XP: " + EnumChatFormatting.GRAY + + String.format("%,d", floorLevelToXP), String.format("# M3 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpM3), runsM3), String.format("# M4 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpM4), runsM4), String.format("# M5 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpM5), runsM5), String.format("# M6 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpM6), runsM6), - String.format("# M7 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpM7), runsM7), + String.format("# M7 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpM7), runsM7), "" ); boolean hasTime = false; - if (timeM3 > 1000) { - getInstance() - .tooltipToDisplay.add(String.format("Expected Time (M3) : %s", Utils.prettyTime(runsM3 * (long) (timeM3 * 1.2)))); - hasTime = true; - } - if (timeM4 > 1000) { - getInstance() - .tooltipToDisplay.add(String.format("Expected Time (M4) : %s", Utils.prettyTime(runsM4 * (long) (timeM4 * 1.2)))); - hasTime = true; - } - if (timeM5 > 1000) { - getInstance() - .tooltipToDisplay.add(String.format("Expected Time (M5) : %s", Utils.prettyTime(runsM5 * (long) (timeM5 * 1.2)))); - hasTime = true; - } - if (timeM6 > 1000) { - getInstance() - .tooltipToDisplay.add(String.format("Expected Time (M6) : %s", Utils.prettyTime(runsM6 * (long) (timeM6 * 1.2)))); - hasTime = true; - } - if (timeM7 > 1000) { - getInstance() - .tooltipToDisplay.add(String.format("Expected Time (M7) : %s", Utils.prettyTime(runsM7 * (long) (timeM7 * 1.2)))); - hasTime = true; - } + hasTime = isHasTime(timeM3, "Expected Time (M3) : %s", runsM3, hasTime); + hasTime = isHasTime(timeM4, "Expected Time (M4) : %s", runsM4, hasTime); + hasTime = isHasTime(timeM5, "Expected Time (M5) : %s", runsM5, hasTime); + hasTime = isHasTime(timeM6, "Expected Time (M6) : %s", runsM6, hasTime); + hasTime = isHasTime(timeM7, "Expected Time (M7) : %s", runsM7, hasTime); if (hasTime) { getInstance().tooltipToDisplay.add(""); } @@ -421,26 +376,32 @@ public class DungeonPage extends GuiProfileViewerPage { getInstance() .tooltipToDisplay.add( "The " + - EnumChatFormatting.DARK_PURPLE + - "Catacombs Expert Ring" + - EnumChatFormatting.GRAY + - " is assumed to be used, unless " + - EnumChatFormatting.YELLOW + - "SHIFT" + - EnumChatFormatting.GRAY + - " is held." + EnumChatFormatting.DARK_PURPLE + + "Catacombs Expert Ring" + + EnumChatFormatting.GRAY + + " is assumed to be used, unless " + + EnumChatFormatting.YELLOW + + "SHIFT" + + EnumChatFormatting.GRAY + + " is held." ); getInstance().tooltipToDisplay.add("[Time per run] is calculated using Fastest S+ x 120%"); } else { getInstance() - .tooltipToDisplay.add("[Hold " + EnumChatFormatting.YELLOW + "CTRL" + EnumChatFormatting.GRAY + " to see details]"); + .tooltipToDisplay.add( + "[Hold " + EnumChatFormatting.YELLOW + "CTRL" + EnumChatFormatting.GRAY + " to see details]"); } } dungeonLevelTextField.setSize(20, 10); dungeonLevelTextField.render(x + 22, y + 29); int calcLen = fontRendererObj.getStringWidth("Calculate"); - Utils.renderShadowedString(EnumChatFormatting.WHITE + "Calculate", x + sectionWidth - 17 - calcLen / 2f, y + 30, 100); + Utils.renderShadowedString( + EnumChatFormatting.WHITE + "Calculate", + x + sectionWidth - 17 - calcLen / 2f, + y + 30, + 100 + ); //Random stats @@ -451,10 +412,7 @@ public class DungeonPage extends GuiProfileViewerPage { float totalRunsF = 0; float totalRunsF5 = 0; for (int i = 1; i <= 7; i++) { - float runs = Utils.getElementAsFloat( - Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.tier_completions." + i), - 0 - ); + float runs = getElementAsFloat(profileInfo, "dungeons.dungeon_types.catacombs.tier_completions." + i); totalRunsF += runs; if (i >= 5) { totalRunsF5 += runs; @@ -463,10 +421,7 @@ public class DungeonPage extends GuiProfileViewerPage { float totalRunsM = 0; float totalRunsM5 = 0; for (int i = 1; i <= 7; i++) { - float runs = Utils.getElementAsFloat( - Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.tier_completions." + i), - 0 - ); + float runs = getElementAsFloat(profileInfo, "dungeons.dungeon_types.master_catacombs.tier_completions." + i); totalRunsM += runs; if (i >= 5) { totalRunsM5 += runs; @@ -477,18 +432,12 @@ public class DungeonPage extends GuiProfileViewerPage { float mobKills; float mobKillsF = 0; for (int i = 1; i <= 7; i++) { - float kills = Utils.getElementAsFloat( - Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.mobs_killed." + i), - 0 - ); + float kills = getElementAsFloat(profileInfo, "dungeons.dungeon_types.catacombs.mobs_killed." + i); mobKillsF += kills; } float mobKillsM = 0; for (int i = 1; i <= 7; i++) { - float kills = Utils.getElementAsFloat( - Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.mobs_killed." + i), - 0 - ); + float kills = getElementAsFloat(profileInfo, "dungeons.dungeon_types.master_catacombs.mobs_killed." + i); mobKillsM += kills; } mobKills = mobKillsF + mobKillsM; @@ -518,7 +467,8 @@ public class DungeonPage extends GuiProfileViewerPage { ); Utils.renderAlignedString( EnumChatFormatting.YELLOW + "Secrets (/Run) ", - EnumChatFormatting.WHITE.toString() + (secrets == -1 ? "?" : (Math.round(secrets / Math.max(1, totalRuns) * 100) / 100f)), + EnumChatFormatting.WHITE.toString() + (secrets == -1 ? "?" : (Math.round( + secrets / Math.max(1, totalRuns) * 100) / 100f)), x, miscTopY + 30, sectionWidth @@ -538,40 +488,16 @@ public class DungeonPage extends GuiProfileViewerPage { int bx = x + sectionWidth * i / 8 - w / 2; - boolean invert = i == floorTime; - float uMin = 20 / 256f; - float uMax = 29 / 256f; - float vMin = 0 / 256f; - float vMax = 11 / 256f; - GlStateManager.color(1, 1, 1, 1); - Minecraft.getMinecraft().getTextureManager().bindTexture(GuiProfileViewer.pv_elements); - Utils.drawTexturedRect( - bx - 2, - y3 - 2, - 9, - 11, - invert ? uMax : uMin, - invert ? uMin : uMax, - invert ? vMax : vMin, - invert ? vMin : vMax, - GL11.GL_NEAREST - ); Utils.renderShadowedString(EnumChatFormatting.WHITE.toString() + i, bx + w / 2, y3, 10); } - float timeNorm = Utils.getElementAsFloat( - Utils.getElement(profileInfo, "dungeons.dungeon_types." + dungeonString + ".fastest_time." + floorTime), - 0 - ); - float timeS = Utils.getElementAsFloat( - Utils.getElement(profileInfo, "dungeons.dungeon_types." + dungeonString + ".fastest_time_s." + floorTime), - 0 - ); - float timeSPLUS = Utils.getElementAsFloat( - Utils.getElement(profileInfo, "dungeons.dungeon_types." + dungeonString + ".fastest_time_s_plus." + floorTime), - 0 + float timeNorm = getElementAsFloat(profileInfo, "dungeons.dungeon_types." + dungeonString + ".fastest_time." + floorTime); + float timeS = getElementAsFloat(profileInfo, "dungeons.dungeon_types." + dungeonString + ".fastest_time_s." + floorTime); + float timeSPLUS = getElementAsFloat( + profileInfo, + "dungeons.dungeon_types." + dungeonString + ".fastest_time_s_plus." + floorTime ); String timeNormStr = timeNorm <= 0 ? "N/A" : Utils.prettyTime((long) timeNorm); String timeSStr = timeS <= 0 ? "N/A" : Utils.prettyTime((long) timeS); @@ -606,15 +532,13 @@ public class DungeonPage extends GuiProfileViewerPage { Utils.renderShadowedString(EnumChatFormatting.RED + "Boss Collections", x + sectionWidth / 2, y, sectionWidth); for (int i = 1; i <= 7; i++) { - float compl = Utils.getElementAsFloat( - Utils.getElement(profileInfo, "dungeons.dungeon_types." + dungeonString + ".tier_completions." + i), - 0 - ); + float compl = getElementAsFloat(profileInfo, "dungeons.dungeon_types." + dungeonString + ".tier_completions." + i); if (BOSS_HEADS[i - 1] == null) { String textureLink = bossFloorHeads[i - 1]; - String b64Decoded = "{\"textures\":{\"SKIN\":{\"url\":\"http://textures.minecraft.net/texture/" + textureLink + "\"}}}"; + String b64Decoded = + "{\"textures\":{\"SKIN\":{\"url\":\"http://textures.minecraft.net/texture/" + textureLink + "\"}}}"; String b64Encoded = new String(Base64.getEncoder().encode(b64Decoded.getBytes())); ItemStack stack = new ItemStack(Items.skull, 1, 3); @@ -646,7 +570,11 @@ public class DungeonPage extends GuiProfileViewerPage { GlStateManager.popMatrix(); Utils.renderAlignedString( - String.format(EnumChatFormatting.YELLOW + "%s (" + (onMasterMode ? "M" : "F") + "%d) ", bossFloorArr[i - 1], i), + String.format( + EnumChatFormatting.YELLOW + "%s (" + (onMasterMode ? "M" : "F") + "%d) ", + bossFloorArr[i - 1], + i + ), EnumChatFormatting.WHITE.toString() + (int) compl, x + 16, y + 18 + 20 * (i - 1), @@ -662,7 +590,12 @@ public class DungeonPage extends GuiProfileViewerPage { //Gui.drawRect(x, y, x+120, y+147, 0xffffffff); - Utils.renderShadowedString(EnumChatFormatting.DARK_PURPLE + "Class Levels", x + sectionWidth / 2, y, sectionWidth); + Utils.renderShadowedString( + EnumChatFormatting.DARK_PURPLE + "Class Levels", + x + sectionWidth / 2, + y, + sectionWidth + ); JsonElement activeClassElement = Utils.getElement(profileInfo, "dungeons.selected_dungeon_class"); String activeClass = null; @@ -675,12 +608,12 @@ public class DungeonPage extends GuiProfileViewerPage { for (int i = 0; i < dungSkillsName.length; i++) { String skillName = dungSkillsName[i]; - HashMap<String, ProfileViewer.Level> levelObjClasses = levelObjClasseses.computeIfAbsent(profileId, k -> new HashMap<>()); + HashMap<String, ProfileViewer.Level> levelObjClasses = levelObjClasseses.computeIfAbsent( + profileId, + k -> new HashMap<>() + ); if (!levelObjClasses.containsKey(skillName)) { - float cataXp = Utils.getElementAsFloat( - Utils.getElement(profileInfo, "dungeons.player_classes." + skillName.toLowerCase() + ".experience"), - 0 - ); + float cataXp = getElementAsFloat(profileInfo, "dungeons.player_classes." + skillName.toLowerCase() + ".experience"); ProfileViewer.Level levelObj = ProfileViewer.getLevel( Utils.getElementOrDefault(leveling, "catacombs", new JsonArray()).getAsJsonArray(), cataXp, @@ -708,7 +641,16 @@ public class DungeonPage extends GuiProfileViewerPage { ProfileViewer.Level levelObj = levelObjClasses.get(skillName); getInstance() - .renderXpBar(colour + skillName, dungSkillsStack[i], x, y + 20 + 24 * i, sectionWidth, levelObj, mouseX, mouseY); + .renderXpBar( + colour + skillName, + dungSkillsStack[i], + x, + y + 20 + 24 * i, + sectionWidth, + levelObj, + mouseX, + mouseY + ); } getInstance().renderXpBar( @@ -718,12 +660,29 @@ public class DungeonPage extends GuiProfileViewerPage { y + 20 + 24 * 5, sectionWidth, classAverage, - mouseX, mouseY); + mouseX, mouseY + ); } drawSideButtons(); } + private boolean isHasTime(float fastestTime, String format, long runsAmount, boolean hasTime) { + if (fastestTime > 1000) { + getInstance() + .tooltipToDisplay.add(String.format( + format, + Utils.prettyTime(runsAmount * (long) (fastestTime * 1.2)) + )); + hasTime = true; + } + return hasTime; + } + + private static float getElementAsFloat(JsonObject profileInfo, String path) { + return Utils.getElementAsFloat(Utils.getElement(profileInfo, path), 0); + } + @Override public boolean mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { FontRenderer fontRendererObj = Minecraft.getMinecraft().fontRendererObj; @@ -737,7 +696,8 @@ public class DungeonPage extends GuiProfileViewerPage { } int cW = fontRendererObj.getStringWidth("Calculate"); - if (mouseX >= guiLeft + 23 + 110 - 17 - cW && mouseX <= guiLeft + 23 + 110 - 17 && mouseY >= guiTop + 55 && mouseY <= guiTop + 65) { + if (mouseX >= guiLeft + 23 + 110 - 17 - cW && mouseX <= guiLeft + 23 + 110 - 17 && mouseY >= guiTop + 55 && + mouseY <= guiTop + 65) { calculateFloorLevelXP(); } @@ -774,66 +734,21 @@ public class DungeonPage extends GuiProfileViewerPage { GlStateManager.enableDepth(); GlStateManager.translate(0, 0, 5); if (onMasterMode) { - drawSideButton(1, dungeonsModeIcons.get("master_catacombs"), true); + Utils.drawPvSideButton(1, dungeonsModeIcons.get("master_catacombs"), true, getInstance()); } else { - drawSideButton(0, dungeonsModeIcons.get("catacombs"), true); + Utils.drawPvSideButton(0, dungeonsModeIcons.get("catacombs"), true, getInstance()); } GlStateManager.translate(0, 0, -3); GlStateManager.translate(0, 0, -2); if (!onMasterMode) { - drawSideButton(1, dungeonsModeIcons.get("master_catacombs"), false); + Utils.drawPvSideButton(1, dungeonsModeIcons.get("master_catacombs"), false, getInstance()); } else { - drawSideButton(0, dungeonsModeIcons.get("catacombs"), false); + Utils.drawPvSideButton(0, dungeonsModeIcons.get("catacombs"), false, getInstance()); } GlStateManager.disableDepth(); } - private void drawSideButton(int yIndex, ItemStack itemStack, boolean pressed) { - int guiLeft = GuiProfileViewer.getGuiLeft(); - int guiTop = GuiProfileViewer.getGuiTop(); - - GlStateManager.disableLighting(); - GlStateManager.enableBlend(); - GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); - GlStateManager.enableAlpha(); - GlStateManager.alphaFunc(516, 0.1F); - - int x = guiLeft - 28; - int y = guiTop + yIndex * 28; - - float uMin = 193 / 256f; - float uMax = 223 / 256f; - float vMin = 200 / 256f; - float vMax = 228 / 256f; - if (pressed) { - uMin = 224 / 256f; - uMax = 1f; - - if (yIndex != 0) { - vMin = 228 / 256f; - vMax = 1f; - } - - getInstance().renderBlurredBackground(getInstance().width, getInstance().height, x + 2, y + 2, 30, 28 - 4); - } else { - getInstance().renderBlurredBackground(getInstance().width, getInstance().height, x + 2, y + 2, 28 - 2, 28 - 4); - } - - GlStateManager.disableLighting(); - GlStateManager.enableBlend(); - GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); - GlStateManager.enableAlpha(); - GlStateManager.alphaFunc(516, 0.1F); - - Minecraft.getMinecraft().getTextureManager().bindTexture(GuiProfileViewer.pv_elements); - - Utils.drawTexturedRect(x, y, pressed ? 32 : 28, 28, uMin, uMax, vMin, vMax, GL11.GL_NEAREST); - - GlStateManager.enableDepth(); - Utils.drawItemStack(itemStack, x + 8, y + 7); - } - private void calculateFloorLevelXP() { JsonObject leveling = Constants.LEVELING; if (leveling == null) return; @@ -852,7 +767,7 @@ public class DungeonPage extends GuiProfileViewerPage { if (level < Math.floor(levelObjCata.level)) { continue; } - remaining += levelingArray.get(level).getAsFloat(); + remaining += levelingArray.get(level).getAsFloat(); } if (remaining < 0) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ExtraPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ExtraPage.java index 59c78dda..90ffd388 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ExtraPage.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ExtraPage.java @@ -94,7 +94,7 @@ public class ExtraPage extends GuiProfileViewerPage { } // pls update in the future tyvm !!! - final static HashMap<String, Integer> slayers = new HashMap<String, Integer>() { + public final static HashMap<String, Integer> slayers = new HashMap<String, Integer>() { { put("zombie", 5); put("spider", 4); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java index 4bf65cc6..c379c7eb 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java @@ -171,7 +171,10 @@ public class GuiProfileViewer extends GuiScreen { ); public final GuiElementTextField playerNameTextField; public final GuiElementTextField inventoryTextField = new GuiElementTextField("", GuiElementTextField.SCALE_TEXT); - public final GuiElementTextField killDeathSearchTextField = new GuiElementTextField("", GuiElementTextField.SCALE_TEXT); + public final GuiElementTextField killDeathSearchTextField = new GuiElementTextField( + "", + GuiElementTextField.SCALE_TEXT + ); private final Map<ProfileViewerPage, GuiProfileViewerPage> pages = new HashMap<>(); public int sizeX; public int sizeY; @@ -390,7 +393,7 @@ public class GuiProfileViewer extends GuiScreen { GL11.GL_NEAREST ); Utils.drawStringCenteredScaledMaxWidth( - "Open in Skycrypt", + "Open in SkyCrypt", Minecraft.getMinecraft().fontRendererObj, guiLeft + 50 + 100 + 6, guiTop + sizeY + 3 + 10, @@ -838,8 +841,9 @@ public class GuiProfileViewer extends GuiScreen { profileId != null ) { if (mouseY > guiTop + sizeY + 3 && mouseY < guiTop + sizeY + 23) { - String url = "https://sky.shiiyu.moe/stats/" + profile.getHypixelProfile().get("displayname").getAsString() + "/" + - profileId; + String url = + "https://sky.shiiyu.moe/stats/" + profile.getHypixelProfile().get("displayname").getAsString() + "/" + + profileId; Utils.openUrl(url); Utils.playPressSound(); return; @@ -960,14 +964,17 @@ public class GuiProfileViewer extends GuiScreen { String totalXpStr = null; if (skillName.contains("Catacombs")) { totalXpStr = EnumChatFormatting.GRAY + "Total XP: " + EnumChatFormatting.DARK_PURPLE + - numberFormat.format(levelObj.totalXp) + EnumChatFormatting.DARK_GRAY + " (" + + numberFormat.format(levelObj.totalXp) + EnumChatFormatting.DARK_GRAY + " (" + DECIMAL_FORMAT.format(getPercentage(skillName.toLowerCase(), levelObj)) + "% to 50)"; } - // Adds overflow level to each level object that is maxed, avoids hotm level as there is no overflow xp for it + // Adds overflow level to each level object that is maxed, avoids hotm level as there is no overflow xp for it if (levelObj.maxed) { levelStr = levelObj.maxLevel != 7 ? - EnumChatFormatting.GOLD + "MAXED!" + EnumChatFormatting.GRAY + " (Overflow level: " + String.format("%.2f", levelObj.level) + ")" : - EnumChatFormatting.GOLD + "MAXED!"; + EnumChatFormatting.GOLD + "MAXED!" + EnumChatFormatting.GRAY + " (Overflow level: " + String.format( + "%.2f", + levelObj.level + ) + ")" : + EnumChatFormatting.GOLD + "MAXED!"; } else { if (skillName.contains("Class Average")) { levelStr = "Progress: " + EnumChatFormatting.DARK_PURPLE + String.format("%.1f", (level % 1 * 100)) + "%"; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/InventoriesPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/InventoriesPage.java index a981183a..164f5d78 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/InventoriesPage.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/InventoriesPage.java @@ -154,7 +154,7 @@ public class InventoriesPage extends GuiProfileViewerPage { getInstance().tooltipToDisplay = entry.getValue().getTooltip(Minecraft.getMinecraft().thePlayer, false); if (Objects.equals(entry.getKey(), "talisman_bag")) { StringBuilder magicalPowerString = new StringBuilder(EnumChatFormatting.DARK_GRAY + "Magical Power: "); - int magicalPower = PlayerStats.getMagicalPower(inventoryInfo, profileInformation); + int magicalPower = profile.getMagicalPower(profileId); getInstance() .tooltipToDisplay.add( magicalPower == -1 diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PlayerStats.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PlayerStats.java index 56ecd3a2..9be3eaf4 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PlayerStats.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PlayerStats.java @@ -170,12 +170,14 @@ public class PlayerStats { return skillBonus; } - private static Stats getTamingBonus(JsonObject profile) { + public static int getPetScore(JsonObject profile) { JsonObject bonuses = Constants.BONUSES; - if (bonuses == null) return null; - + if (bonuses == null) { + Utils.showOutdatedRepoNotification(); + return 0; + } JsonElement petsElement = Utils.getElement(profile, "pets"); - if (petsElement == null) return new Stats(); + if (petsElement == null) return 0; JsonArray pets = petsElement.getAsJsonArray(); @@ -190,11 +192,19 @@ public class PlayerStats { for (String value : highestRarityMap.values()) { petScore += Utils.getElementAsFloat(Utils.getElement(bonuses, "pet_value." + value.toUpperCase()), 0); } + return petScore; + } + + private static Stats getTamingBonus(JsonObject profile) { + JsonObject bonuses = Constants.BONUSES; + if (bonuses == null) return null; JsonElement petRewardsElement = Utils.getElement(bonuses, "pet_rewards"); if (petRewardsElement == null) return null; JsonObject petRewards = petRewardsElement.getAsJsonObject(); + int petScore = getPetScore(profile); + Stats petBonus = new Stats(); for (int i = 0; i <= petScore; i++) { if (petRewards.has("" + i)) { @@ -287,7 +297,6 @@ public class PlayerStats { private static Stats getSetBonuses( Stats stats, JsonObject inventoryInfo, - JsonObject collectionInfo, Map<String, ProfileViewer.Level> skyblockInfo, JsonObject profile ) { @@ -298,17 +307,11 @@ public class PlayerStats { String fullset = getFullset(armor, -1); if (fullset != null) { + // TODO @nea: repo based stat delivery? (with lisp) switch (fullset) { case "LAPIS_ARMOR_": bonuses.addStat(HEALTH, 60); break; - case "EMERALD_ARMOR_": - { - int bonus = (int) Math.floor(Utils.getElementAsFloat(Utils.getElement(collectionInfo, "EMERALD"), 0) / 3000); - bonuses.addStat(HEALTH, bonus); - bonuses.addStat(DEFENCE, bonus); - } - break; case "FAIRY_": bonuses.addStat(HEALTH, Utils.getElementAsFloat(Utils.getElement(profile, "fairy_souls_collected"), 0)); break; @@ -616,11 +619,10 @@ public class PlayerStats { public static Stats getStats( Map<String, ProfileViewer.Level> skyblockInfo, JsonObject inventoryInfo, - JsonObject collectionInfo, JsonObject petsInfo, JsonObject profile ) { - if (skyblockInfo == null || inventoryInfo == null || collectionInfo == null || profile == null) return null; + if (skyblockInfo == null || inventoryInfo == null || profile == null) return null; JsonArray armor = Utils.getElement(inventoryInfo, "inv_armor").getAsJsonArray(); JsonArray inventory = Utils.getElement(inventoryInfo, "inv_contents").getAsJsonArray(); @@ -645,7 +647,7 @@ public class PlayerStats { stats = stats.add(passiveBonuses).add(armorBonuses).add(talismanBonuses).add(petBonus).add(hotmBonuses); - stats.add(getSetBonuses(stats, inventoryInfo, collectionInfo, skyblockInfo, profile)); + stats.add(getSetBonuses(stats, inventoryInfo, skyblockInfo, profile)); stats.scaleAll(getStatMult(inventoryInfo)); @@ -655,97 +657,6 @@ public class PlayerStats { } /** - * Calculates the amount of Magical Power the player has using the list of accessories - * - * @param inventoryInfo inventory info object - * @return the amount of Magical Power or -1 - * @see io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer.Profile#getInventoryInfo(String) - */ - public static int getMagicalPower(JsonObject inventoryInfo, JsonObject profileInfo) { - if (inventoryInfo == null || !inventoryInfo.has("talisman_bag") || !inventoryInfo.get("talisman_bag").isJsonArray()) { - return -1; - } - - Map<String, Integer> accessories = JsonUtils.getJsonArrayAsStream(inventoryInfo.get("talisman_bag").getAsJsonArray()) - .map(o -> { - try { - return JsonToNBT.getTagFromJson(o.getAsJsonObject().get("nbttag").getAsString()); - } catch (Exception ignored) { - return null; - } - }).filter(Objects::nonNull).map(tag -> { - NBTTagList loreTagList = tag.getCompoundTag("display").getTagList("Lore", 8); - String lastElement = loreTagList.getStringTagAt(loreTagList.tagCount() - 1); - if (lastElement.contains(EnumChatFormatting.OBFUSCATED.toString())) { - lastElement = lastElement.substring(lastElement.indexOf(' ')).trim().substring(4); - } - JsonArray lastElementJsonArray = new JsonArray(); - lastElementJsonArray.add(new JsonPrimitive(lastElement)); - return new AbstractMap.SimpleEntry<>( - tag.getCompoundTag("ExtraAttributes").getString("id"), - Utils.getRarityFromLore(lastElementJsonArray) - ); - }).sorted(Comparator.comparingInt(e -> -e.getValue())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2)->v1, LinkedHashMap::new)); - - Set<String> ignoredTalismans = new HashSet<>(); - int powderAmount = 0; - for (Map.Entry<String, Integer> entry : accessories.entrySet()) { - if (ignoredTalismans.contains(entry.getKey())) { - continue; - } - - JsonArray children = Utils.getElementOrDefault(Constants.PARENTS, entry.getKey(), new JsonArray()).getAsJsonArray(); - for (JsonElement child : children) { - ignoredTalismans.add(child.getAsString()); - } - - if (entry.getKey().equals("HEGEMONY_ARTIFACT")) { - switch (entry.getValue()) { - case 4: - powderAmount += 16; - break; - case 5: - powderAmount += 22; - break; - } - } - if (entry.getKey().equals("ABICASE")) { - if (profileInfo.has("nether_island_player_data") && - profileInfo.get("nether_island_player_data").getAsJsonObject().has("abiphone") && profileInfo.get( - "nether_island_player_data").getAsJsonObject().get("abiphone").getAsJsonObject().has("active_contacts")) { // BatChest - int contact = - profileInfo.get("nether_island_player_data").getAsJsonObject().get("abiphone").getAsJsonObject().get( - "active_contacts").getAsJsonArray().size(); - powderAmount += Math.floor(contact / 2); - } - } - switch (entry.getValue()) { - case 0: - case 6: - powderAmount += 3; - break; - case 1: - case 7: - powderAmount += 5; - break; - case 2: - powderAmount += 8; - break; - case 3: - powderAmount += 12; - break; - case 4: - powderAmount += 16; - break; - case 5: - powderAmount += 22; - break; - } - } - return powderAmount; - } - - /** * Finds the Magical Power the player selected if applicable * * @param profileInfo profile information object diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java index 63c2435a..610e4090 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java @@ -25,14 +25,18 @@ import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import io.github.moulberry.notenoughupdates.NEUManager; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.profileviewer.bestiary.BestiaryData; import io.github.moulberry.notenoughupdates.profileviewer.weight.senither.SenitherWeight; import io.github.moulberry.notenoughupdates.util.Constants; +import io.github.moulberry.notenoughupdates.util.JsonUtils; import io.github.moulberry.notenoughupdates.util.Utils; +import io.github.moulberry.notenoughupdates.util.hypixelapi.ProfileCollectionInfo; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.JsonToNBT; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.util.EnumChatFormatting; @@ -40,19 +44,25 @@ import net.minecraft.util.EnumChatFormatting; import javax.annotation.Nullable; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.util.AbstractMap; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; +import java.util.Locale; import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; -import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; public class ProfileViewer { @@ -247,7 +257,7 @@ public class ProfileViewer { "REDSTONE", "QUARTZ", "OBSIDIAN", - "GLOWSTONE", + "GLOWSTONE_DUST", "GRAVEL", "ICE", null, @@ -444,11 +454,15 @@ public class ProfileViewer { ); } }; + + public static final List<String> SLAYERS = Arrays.asList("zombie", "spider", "wolf", "enderman", "blaze"); + private static final AtomicBoolean updatingResourceCollection = new AtomicBoolean(false); private static JsonObject resourceCollection = null; private final NEUManager manager; private final HashMap<String, JsonObject> uuidToHypixelProfile = new HashMap<>(); private final HashMap<String, Profile> uuidToProfileMap = new HashMap<>(); + private final HashMap<String, String> nameToUuid = new HashMap<>(); public ProfileViewer(NEUManager manager) { @@ -643,11 +657,14 @@ public class ProfileViewer { private final HashMap<String, List<JsonObject>> coopProfileMap = new HashMap<>(); private final HashMap<String, Map<String, Level>> skyblockInfoCache = new HashMap<>(); private final HashMap<String, JsonObject> inventoryCacheMap = new HashMap<>(); - private final HashMap<String, JsonObject> collectionInfoMap = new HashMap<>(); + private final HashMap<String, CompletableFuture<ProfileCollectionInfo>> collectionInfoMap = new HashMap<>(); + private final HashMap<String, Double> skyBlockExperience = new HashMap<>(); + private final HashMap<String, EnumChatFormatting> skyBlockExperienceColour = new HashMap<>(); private final List<String> profileNames = new ArrayList<>(); private final HashMap<String, PlayerStats.Stats> stats = new HashMap<>(); private final HashMap<String, PlayerStats.Stats> passiveStats = new HashMap<>(); private final HashMap<String, Long> networth = new HashMap<>(); + private final HashMap<String, Integer> magicalPower = new HashMap<>(); private final HashMap<String, SoopyNetworthData> soopyNetworth = new HashMap<>(); private final AtomicBoolean updatingSkyblockProfilesState = new AtomicBoolean(false); private final AtomicBoolean updatingGuildInfoState = new AtomicBoolean(false); @@ -671,6 +688,117 @@ public class ProfileViewer { this.uuid = uuid; } + /** + * Calculates the amount of Magical Power the player has using the list of accessories + * + * @return the amount of Magical Power or -1 + * @see io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer.Profile#getInventoryInfo(String) + */ + public int getMagicalPower(String profileId) { + JsonObject inventoryInfo = getInventoryInfo(profileId); + JsonObject profileInfo = getProfileInformation(profileId); + if (magicalPower.containsKey(profileId)) return magicalPower.get(profileId); + if (inventoryInfo == null || !inventoryInfo.has("talisman_bag") || + !inventoryInfo.get("talisman_bag").isJsonArray()) { + return -1; + } + + Map<String, Integer> accessories = JsonUtils.getJsonArrayAsStream(inventoryInfo + .get("talisman_bag") + .getAsJsonArray()).map(o -> { + try { + return JsonToNBT.getTagFromJson(o + .getAsJsonObject() + .get("nbttag") + .getAsString()); + } catch (Exception ignored) { + return null; + } + }).filter(Objects::nonNull).map(tag -> { + NBTTagList loreTagList = tag.getCompoundTag("display").getTagList("Lore", 8); + String lastElement = loreTagList.getStringTagAt(loreTagList.tagCount() - 1); + if (lastElement.contains(EnumChatFormatting.OBFUSCATED.toString())) { + lastElement = lastElement.substring(lastElement.indexOf(' ')).trim().substring(4); + } + JsonArray lastElementJsonArray = new JsonArray(); + lastElementJsonArray.add(new JsonPrimitive(lastElement)); + return new AbstractMap.SimpleEntry<>( + tag.getCompoundTag("ExtraAttributes").getString("id"), + Utils.getRarityFromLore(lastElementJsonArray) + ); + }).sorted(Comparator.comparingInt(e -> -e.getValue())).collect(Collectors.toMap( + Map.Entry::getKey, + Map.Entry::getValue, + (v1, v2) -> v1, + LinkedHashMap::new + )); + + Set<String> ignoredTalismans = new HashSet<>(); + int powerAmount = 0; + for (Map.Entry<String, Integer> entry : accessories.entrySet()) { + if (ignoredTalismans.contains(entry.getKey())) { + continue; + } + + JsonArray children = Utils + .getElementOrDefault(Constants.PARENTS, entry.getKey(), new JsonArray()) + .getAsJsonArray(); + for (JsonElement child : children) { + ignoredTalismans.add(child.getAsString()); + } + + if (entry.getKey().equals("HEGEMONY_ARTIFACT")) { + switch (entry.getValue()) { + case 4: + powerAmount += 16; + break; + case 5: + powerAmount += 22; + break; + } + } + if (entry.getKey().equals("ABICASE")) { + if (profileInfo != null && profileInfo.has("nether_island_player_data") && + profileInfo.get("nether_island_player_data").getAsJsonObject().has("abiphone") && profileInfo + .get( + "nether_island_player_data") + .getAsJsonObject() + .get("abiphone") + .getAsJsonObject() + .has("active_contacts")) { // BatChest + int contact = + profileInfo.get("nether_island_player_data").getAsJsonObject().get("abiphone").getAsJsonObject().get( + "active_contacts").getAsJsonArray().size(); + powerAmount += Math.floor(contact / 2); + } + } + switch (entry.getValue()) { + case 0: + case 6: + powerAmount += 3; + break; + case 1: + case 7: + powerAmount += 5; + break; + case 2: + powerAmount += 8; + break; + case 3: + powerAmount += 12; + break; + case 4: + powerAmount += 16; + break; + case 5: + powerAmount += 22; + break; + } + } + magicalPower.put(profileId, powerAmount); + return powerAmount; + } + public JsonObject getPlayerStatus() { if (playerStatus != null) return playerStatus; if (updatingPlayerStatusState.get()) return null; @@ -924,6 +1052,50 @@ public class ProfileViewer { return null; } + public EnumChatFormatting getSkyblockLevelColour(String profileName) { + if (Constants.SBLEVELS == null) return EnumChatFormatting.WHITE; + if (skyBlockExperienceColour.containsKey(profileName)) { + return skyBlockExperienceColour.get(profileName); + } + + double skyblockLevel = getSkyblockLevel(profileName); + + EnumChatFormatting previousColor = EnumChatFormatting.WHITE; + if (Constants.SBLEVELS == null || !Constants.SBLEVELS.has("sblevel_colours")) { + Utils.showOutdatedRepoNotification(); + return EnumChatFormatting.WHITE; + } + JsonObject sblevelColours = Constants.SBLEVELS.getAsJsonObject("sblevel_colours"); + try { + for (Map.Entry<String, JsonElement> stringJsonElementEntry : sblevelColours.entrySet()) { + int key = Integer.parseInt(stringJsonElementEntry.getKey()); + EnumChatFormatting valueByName = EnumChatFormatting.getValueByName(stringJsonElementEntry + .getValue() + .getAsString()); + if (skyblockLevel <= key) { + skyBlockExperienceColour.put(profileName, previousColor); + return previousColor; + } + previousColor = valueByName; + } + } catch (RuntimeException ignored) { + // catch both numberformat and getValueByName being wrong + } + skyBlockExperienceColour.put(profileName, EnumChatFormatting.WHITE); + return EnumChatFormatting.WHITE; + } + + public double getSkyblockLevel(String profileName) { + if (skyBlockExperience.containsKey(profileName)) { + return skyBlockExperience.get(profileName); + } + final JsonObject profileInfo = getProfileInformation(profileName); + int element = Utils.getElementAsInt(Utils.getElement(profileInfo, "leveling.experience"), 0); + double level = (element / 100F); + skyBlockExperience.put(profileName, level); + return level; + } + public long getNetWorth(String profileName) { if (profileName == null) profileName = latestProfile; if (networth.get(profileName) != null) return networth.get(profileName); @@ -1141,65 +1313,62 @@ public class ProfileViewer { } public JsonObject getProfileInformation(String profileName) { + if (profileName == null) profileName = latestProfile; + if (profileMap.containsKey(profileName)) return profileMap.get(profileName); + JsonObject profile = getRawProfileInformation(profileName); + if (profile == null) return null; + if (!profile.has("members")) return null; + JsonObject members = profile.get("members").getAsJsonObject(); + if (!members.has(uuid)) return null; + JsonObject profileInfo = members.get(uuid).getAsJsonObject(); + if (profile.has("banking")) { + profileInfo.add("banking", profile.get("banking").getAsJsonObject()); + } + if (profile.has("game_mode")) { + profileInfo.add("game_mode", profile.get("game_mode")); + } + if (profile.has("community_upgrades")) { + profileInfo.add("community_upgrades", profile.get("community_upgrades")); + } + profileMap.put(profileName, profileInfo); + return profileInfo; + } + + public JsonObject getRawProfileInformation(String profileName) { JsonArray playerInfo = getSkyblockProfiles(() -> {}); if (playerInfo == null) return null; if (profileName == null) profileName = latestProfile; - if (profileMap.containsKey(profileName)) return profileMap.get(profileName); - for (int i = 0; i < skyblockProfiles.size(); i++) { - if (!skyblockProfiles.get(i).isJsonObject()) { + for (JsonElement skyblockProfile : skyblockProfiles) { + if (!skyblockProfile.isJsonObject()) { skyblockProfiles = null; return null; } - JsonObject profile = skyblockProfiles.get(i).getAsJsonObject(); - if (profile.get("cute_name").getAsString().equalsIgnoreCase(profileName)) { - if (!profile.has("members")) return null; - JsonObject members = profile.get("members").getAsJsonObject(); - if (!members.has(uuid)) continue; - JsonObject profileInfo = members.get(uuid).getAsJsonObject(); - if (profile.has("banking")) { - profileInfo.add("banking", profile.get("banking").getAsJsonObject()); - } - if (profile.has("game_mode")) { - profileInfo.add("game_mode", profile.get("game_mode")); - } - profileMap.put(profileName, profileInfo); - return profileInfo; - } + if (skyblockProfile.getAsJsonObject().get("cute_name").getAsString().equalsIgnoreCase(profileName)) + return skyblockProfile.getAsJsonObject(); } - return null; } public List<JsonObject> getCoopProfileInformation(String profileName) { - JsonArray playerInfo = getSkyblockProfiles(() -> {}); - if (playerInfo == null) return null; if (profileName == null) profileName = latestProfile; if (coopProfileMap.containsKey(profileName)) return coopProfileMap.get(profileName); - - for (int i = 0; i < skyblockProfiles.size(); i++) { - if (!skyblockProfiles.get(i).isJsonObject()) { - skyblockProfiles = null; - return null; - } - JsonObject profile = skyblockProfiles.get(i).getAsJsonObject(); - if (profile.get("cute_name").getAsString().equalsIgnoreCase(profileName)) { - if (!profile.has("members")) return null; - JsonObject members = profile.get("members").getAsJsonObject(); - if (!members.has(uuid)) return null; - List<JsonObject> coopList = new ArrayList<>(); - for (Map.Entry<String, JsonElement> islandMember : members.entrySet()) { - if (!islandMember.getKey().equals(uuid)) { - JsonObject coopProfileInfo = islandMember.getValue().getAsJsonObject(); - coopList.add(coopProfileInfo); - } - } - coopProfileMap.put(profileName, coopList); - return coopList; + JsonObject profile = getRawProfileInformation(profileName); + if (profile == null) return null; + + if (!profile.has("members")) return null; + JsonObject members = profile.get("members").getAsJsonObject(); + if (!members.has(uuid)) return null; + List<JsonObject> coopList = new ArrayList<>(); + for (Map.Entry<String, JsonElement> islandMember : members.entrySet()) { + if (!islandMember.getKey().equals(uuid)) { + JsonObject coopProfileInfo = islandMember.getValue().getAsJsonObject(); + coopList.add(coopProfileInfo); } } + coopProfileMap.put(profileName, coopList); + return coopList; - return null; } public void resetCache() { @@ -1216,6 +1385,9 @@ public class ProfileViewer { inventoryCacheMap.clear(); collectionInfoMap.clear(); networth.clear(); + magicalPower.clear(); + skyBlockExperience.clear(); + skyBlockExperienceColour.clear(); } public int getCap(JsonObject leveling, String skillName) { @@ -1225,6 +1397,40 @@ public class ProfileViewer { : 50; } + public int getBestiaryTiers(JsonObject profileInfo) { + int beLevel = 0; + for (ItemStack items : BestiaryData.getBestiaryLocations().keySet()) { + List<String> mobs = BestiaryData.getBestiaryLocations().get(items); + if (mobs != null) { + for (String mob : mobs) { + if (mob != null) { + float kills = Utils.getElementAsFloat(Utils.getElement(profileInfo, "bestiary.kills_" + mob), 0); + String type; + if (BestiaryData.getMobType().get(mob) != null) { + type = BestiaryData.getMobType().get(mob); + } else { + type = "MOB"; + } + JsonObject leveling = Constants.LEVELING; + ProfileViewer.Level level = null; + if (leveling != null && Utils.getElement(leveling, "bestiary." + type) != null) { + JsonArray levelingArray = Utils.getElement(leveling, "bestiary." + type).getAsJsonArray(); + int levelCap = Utils.getElementAsInt(Utils.getElement(leveling, "bestiary.caps." + type), 0); + level = ProfileViewer.getLevel(levelingArray, kills, levelCap, false); + } + + float levelNum = 0; + if (level != null) { + levelNum = level.level; + } + beLevel += (int) Math.floor(levelNum); + } + } + } + } + return beLevel; + } + public Map<String, Level> getSkyblockInfo(String profileName) { JsonObject profileInfo = getProfileInformation(profileName); @@ -1329,9 +1535,7 @@ public class ProfileViewer { ) ); } - - List<String> slayers = Arrays.asList("zombie", "spider", "wolf", "enderman", "blaze"); - for (String slayerName : slayers) { + for (String slayerName : SLAYERS) { float slayerExperience = Utils.getElementAsFloat(Utils.getElement( profileInfo, "slayer_bosses." + slayerName + ".xp" @@ -1560,134 +1764,15 @@ public class ProfileViewer { return null; } - public JsonObject getCollectionInfo(String profileName) { - JsonObject profileInfo = getProfileInformation(profileName); - if (profileInfo == null) return null; - JsonObject resourceCollectionInfo = getResourceCollectionInformation(); - if (resourceCollectionInfo == null) return null; - if (profileName == null) profileName = latestProfile; - if (collectionInfoMap.containsKey(profileName)) return collectionInfoMap.get(profileName); - - List<JsonObject> coopMembers = getCoopProfileInformation(profileName); - JsonElement unlocked_coll_tiers_element = Utils.getElement(profileInfo, "unlocked_coll_tiers"); - JsonElement crafted_generators_element = Utils.getElement(profileInfo, "crafted_generators"); - JsonObject fakeMember = new JsonObject(); - fakeMember.add("crafted_generators", crafted_generators_element); - coopMembers.add(coopMembers.size(), fakeMember); - JsonElement collectionInfoElement = Utils.getElement(profileInfo, "collection"); - - if (unlocked_coll_tiers_element == null || collectionInfoElement == null) { - return null; - } - - JsonObject collectionInfo = new JsonObject(); - JsonObject collectionTiers = new JsonObject(); - JsonObject minionTiers = new JsonObject(); - JsonObject personalAmounts = new JsonObject(); - JsonObject totalAmounts = new JsonObject(); - - if (collectionInfoElement.isJsonObject()) { - personalAmounts = collectionInfoElement.getAsJsonObject(); - } - - for (Map.Entry<String, JsonElement> entry : personalAmounts.entrySet()) { - totalAmounts.addProperty(entry.getKey(), entry.getValue().getAsLong()); - } - - List<JsonObject> coopProfiles = getCoopProfileInformation(profileName); - if (coopProfiles != null) { - for (JsonObject coopProfile : coopProfiles) { - JsonElement coopCollectionInfoElement = Utils.getElement(coopProfile, "collection"); - if (coopCollectionInfoElement != null && coopCollectionInfoElement.isJsonObject()) { - for (Map.Entry<String, JsonElement> entry : coopCollectionInfoElement.getAsJsonObject().entrySet()) { - float existing = Utils.getElementAsFloat(totalAmounts.get(entry.getKey()), 0); - totalAmounts.addProperty(entry.getKey(), existing + entry.getValue().getAsLong()); - } - } - } - } - - if (unlocked_coll_tiers_element.isJsonArray()) { - JsonArray unlocked_coll_tiers = unlocked_coll_tiers_element.getAsJsonArray(); - for (int i = 0; i < unlocked_coll_tiers.size(); i++) { - String unlocked = unlocked_coll_tiers.get(i).getAsString(); - - Matcher matcher = COLL_TIER_PATTERN.matcher(unlocked); - - if (matcher.find()) { - String tier_str = matcher.group(1); - int tier = Integer.parseInt(tier_str); - String coll = unlocked.substring(0, unlocked.length() - (matcher.group().length())); - if (!collectionTiers.has(coll) || collectionTiers.get(coll).getAsInt() < tier) { - collectionTiers.addProperty(coll, tier); - } - } - } - } - for (JsonObject current_member_info : coopMembers) { - if ( - !current_member_info.has("crafted_generators") || !current_member_info.get("crafted_generators").isJsonArray() - ) continue; - JsonArray crafted_generators = Utils.getElement(current_member_info, "crafted_generators").getAsJsonArray(); - for (int j = 0; j < crafted_generators.size(); j++) { - String unlocked = crafted_generators.get(j).getAsString(); - Matcher matcher = COLL_TIER_PATTERN.matcher(unlocked); - if (matcher.find()) { - String tierString = matcher.group(1); - int tier = Integer.parseInt(tierString); - String coll = unlocked.substring(0, unlocked.length() - (matcher.group().length())); - if (!minionTiers.has(coll) || minionTiers.get(coll).getAsInt() < tier) { - minionTiers.addProperty(coll, tier); - } - } - } - } - - JsonObject maxAmount = new JsonObject(); - JsonObject updatedCollectionTiers = new JsonObject(); - for (Map.Entry<String, JsonElement> totalAmountsEntry : totalAmounts.entrySet()) { - String collName = totalAmountsEntry.getKey(); - int collTier = (int) Utils.getElementAsFloat(collectionTiers.get(collName), 0); - - int currentAmount = (int) Utils.getElementAsFloat(totalAmounts.get(collName), 0); - if (currentAmount > 0) { - for (Map.Entry<String, JsonElement> resourceEntry : resourceCollectionInfo.entrySet()) { - JsonElement tiersElement = Utils.getElement(resourceEntry.getValue(), "items." + collName + ".tiers"); - if (tiersElement != null && tiersElement.isJsonArray()) { - JsonArray tiers = tiersElement.getAsJsonArray(); - int maxTierAcquired = -1; - int maxAmountRequired = -1; - for (int i = 0; i < tiers.size(); i++) { - JsonObject tierInfo = tiers.get(i).getAsJsonObject(); - int tier = tierInfo.get("tier").getAsInt(); - int amountRequired = tierInfo.get("amountRequired").getAsInt(); - if (currentAmount >= amountRequired) { - maxTierAcquired = tier; - } - maxAmountRequired = amountRequired; - } - if (maxTierAcquired >= 0 && maxTierAcquired > collTier) { - updatedCollectionTiers.addProperty(collName, maxTierAcquired); - } - maxAmount.addProperty(collName, maxAmountRequired); - } - } - } - } - - for (Map.Entry<String, JsonElement> collectionTiersEntry : updatedCollectionTiers.entrySet()) { - collectionTiers.add(collectionTiersEntry.getKey(), collectionTiersEntry.getValue()); - } - - collectionInfo.add("minion_tiers", minionTiers); - collectionInfo.add("max_amounts", maxAmount); - collectionInfo.add("personal_amounts", personalAmounts); - collectionInfo.add("total_amounts", totalAmounts); - collectionInfo.add("collection_tiers", collectionTiers); - - collectionInfoMap.put(profileName, collectionInfo); - - return collectionInfo; + public ProfileCollectionInfo getCollectionInfo(String profileName) { + JsonObject rawProfileInformation = getRawProfileInformation(profileName); + if (rawProfileInformation == null) return null; + CompletableFuture<ProfileCollectionInfo> future = + collectionInfoMap.computeIfAbsent( + profileName.toLowerCase(Locale.ROOT), + ignored -> ProfileCollectionInfo.getCollectionData(rawProfileInformation, uuid) + ); + return future.getNow(null); } public PlayerStats.Stats getPassiveStats(String profileName) { @@ -1716,7 +1801,6 @@ public class ProfileViewer { PlayerStats.Stats stats = PlayerStats.getStats( getSkyblockInfo(profileName), getInventoryInfo(profileName), - getCollectionInfo(profileName), getPetsInfo(profileName), profileInfo ); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryPage.java index 70ea051a..7da6c627 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryPage.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryPage.java @@ -117,7 +117,7 @@ public class BestiaryPage extends GuiProfileViewerPage { Color color = new Color(128, 128, 128, 255); Utils.renderAlignedString( EnumChatFormatting.RED + "Bestiary Level: ", - EnumChatFormatting.GRAY + "" + (float) getBestiaryTiers(profileInfo) / 10, + EnumChatFormatting.GRAY + "" + (float) GuiProfileViewer.getProfile().getBestiaryTiers(profileInfo) / 10, guiLeft + 220, guiTop + 50, 110 @@ -265,38 +265,4 @@ public class BestiaryPage extends GuiProfileViewerPage { yIndex++; } } - - private int getBestiaryTiers(JsonObject profileInfo) { - int beLevel = 0; - for (ItemStack items : BestiaryData.getBestiaryLocations().keySet()) { - List<String> mobs = BestiaryData.getBestiaryLocations().get(items); - if (mobs != null) { - for (String mob : mobs) { - if (mob != null) { - float kills = Utils.getElementAsFloat(Utils.getElement(profileInfo, "bestiary.kills_" + mob), 0); - String type; - if (BestiaryData.getMobType().get(mob) != null) { - type = BestiaryData.getMobType().get(mob); - } else { - type = "MOB"; - } - JsonObject leveling = Constants.LEVELING; - ProfileViewer.Level level = null; - if (leveling != null && Utils.getElement(leveling, "bestiary." + type) != null) { - JsonArray levelingArray = Utils.getElement(leveling, "bestiary." + type).getAsJsonArray(); - int levelCap = Utils.getElementAsInt(Utils.getElement(leveling, "bestiary.caps." + type), 0); - level = ProfileViewer.getLevel(levelingArray, kills, levelCap, false); - } - - float levelNum = 0; - if (level != null) { - levelNum = level.level; - } - beLevel += (int) Math.floor(levelNum); - } - } - } - } - return beLevel; - } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/LevelPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/LevelPage.java new file mode 100644 index 00000000..16abf251 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/LevelPage.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2023 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.profileviewer.level; + +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.profileviewer.BasicPage; +import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer; +import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; +import io.github.moulberry.notenoughupdates.profileviewer.level.task.CoreTaskLevel; +import io.github.moulberry.notenoughupdates.profileviewer.level.task.DungeonTaskLevel; +import io.github.moulberry.notenoughupdates.profileviewer.level.task.EssenceTaskLevel; +import io.github.moulberry.notenoughupdates.profileviewer.level.task.MiscTaskLevel; +import io.github.moulberry.notenoughupdates.profileviewer.level.task.SkillRelatedTaskLevel; +import io.github.moulberry.notenoughupdates.profileviewer.level.task.SlayingTaskLevel; +import io.github.moulberry.notenoughupdates.profileviewer.level.task.StoryTaskLevel; +import io.github.moulberry.notenoughupdates.util.Constants; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; + +import java.text.NumberFormat; +import java.util.Collections; +import java.util.List; + +public class LevelPage { + + private final GuiProfileViewer instance; + private final BasicPage basicPage; + private ProfileViewer.Profile profile; + + private String profileId; + + private final JsonObject constant; + + private final CoreTaskLevel coreTaskLevel; + private final DungeonTaskLevel dungeonTaskLevel; + private final EssenceTaskLevel essenceTaskLevel; + private final MiscTaskLevel miscTaskLevel; + private final SkillRelatedTaskLevel skillRelatedTaskLevel; + private final SlayingTaskLevel slayingTaskLevel; + private final StoryTaskLevel storyTaskLevel; + + private static final ResourceLocation pv_levels = new ResourceLocation("notenoughupdates:pv_levels.png"); + + public LevelPage(GuiProfileViewer instance, BasicPage basicPage) { + this.instance = instance; + this.basicPage = basicPage; + constant = Constants.SBLEVELS; + + coreTaskLevel = new CoreTaskLevel(this); + dungeonTaskLevel = new DungeonTaskLevel(this); + essenceTaskLevel = new EssenceTaskLevel(this); + miscTaskLevel = new MiscTaskLevel(this); + skillRelatedTaskLevel = new SkillRelatedTaskLevel(this); + slayingTaskLevel = new SlayingTaskLevel(this); + storyTaskLevel = new StoryTaskLevel(this); + } + + public void drawPage(int mouseX, int mouseY) { + int guiLeft = GuiProfileViewer.getGuiLeft(); + int guiTop = GuiProfileViewer.getGuiTop(); + this.profile = GuiProfileViewer.getProfile(); + this.profileId = GuiProfileViewer.getProfileId(); + + basicPage.drawSideButtons(); + + if (constant == null) { + Utils.showOutdatedRepoNotification(); + return; + } + + Minecraft.getMinecraft().getTextureManager().bindTexture(pv_levels); + Utils.drawTexturedRect(guiLeft, guiTop, instance.sizeX, instance.sizeY, GL11.GL_NEAREST); + + double skyblockLevel = profile.getSkyblockLevel(profileId); + JsonObject profileInfo = profile.getProfileInformation(profileId); + + drawMainBar(skyblockLevel, mouseX, mouseY, guiLeft, guiTop); + coreTaskLevel.drawTask(profileInfo, mouseX, mouseY, guiLeft, guiTop); + dungeonTaskLevel.drawTask(profileInfo, mouseX, mouseY, guiLeft, guiTop); + essenceTaskLevel.drawTask(profileInfo, mouseX, mouseY, guiLeft, guiTop); + miscTaskLevel.drawTask(profileInfo, mouseX, mouseY, guiLeft, guiTop); + skillRelatedTaskLevel.drawTask(profileInfo, mouseX, mouseY, guiLeft, guiTop); + slayingTaskLevel.drawTask(profileInfo, mouseX, mouseY, guiLeft, guiTop); + storyTaskLevel.drawTask(profileInfo, mouseX, mouseY, guiLeft, guiTop); + } + + public void renderLevelBar( + String name, + ItemStack stack, + int x, + int y, + int xSize, + double level, + double xp, + double max, + int mouseX, + int mouseY, + boolean percentage, + List<String> tooltip + ) { + + if (xp < 0) xp = 0; + double experienceRequired = (xp / max); + + String second = EnumChatFormatting.WHITE.toString() + (int) level; + if (percentage) { + second = EnumChatFormatting.WHITE.toString() + (int) (experienceRequired * 100) + "%"; + } + Utils.renderAlignedString( + EnumChatFormatting.RED + name, + second, + x + 14, + y - 4, + xSize - 20 + ); + + if (xp >= max) { + getInstance().renderGoldBar(x, y + 6, xSize); + } else { + getInstance().renderBar(x, y + 6, xSize, (float) experienceRequired); + } + String levelStr; + if (mouseX > x && mouseX < x + 120) { + if (mouseY > y - 4 && mouseY < y + 13) { + NumberFormat numberFormat = NumberFormat.getInstance(); + String xpFormatted = numberFormat.format((int) xp); + String maxFormatted = numberFormat.format((int) max); + + levelStr = + EnumChatFormatting.GRAY + "Progress: " + EnumChatFormatting.DARK_PURPLE + (int) (experienceRequired * 100) + + "%" + + " §8(" + xpFormatted + "/" + maxFormatted + " XP)"; + if (tooltip != null && !tooltip.isEmpty()) { + tooltip.add(""); + tooltip.add(levelStr); + getInstance().tooltipToDisplay = tooltip; + } else { + getInstance().tooltipToDisplay = Utils.createList(levelStr); + } + } + } + + GlStateManager.enableDepth(); + GL11.glTranslatef((x), (y - 6f), 0); + GL11.glScalef(0.7f, 0.7f, 1); + Utils.drawItemStackLinear(stack, 0, 0); + GL11.glScalef(1 / 0.7f, 1 / 0.7f, 1); + GL11.glTranslatef(-(x), -(y - 6f), 0); + GlStateManager.disableDepth(); + } + + private void drawMainBar(double skyblockLevel, int mouseX, int mouseY, int guiLeft, int guiTop) { + renderLevelBar( + "Level", + BasicPage.skull, + guiLeft + 163, + guiTop + 30, + 110, + skyblockLevel, + (skyblockLevel - (long) skyblockLevel) * 100, + 100, + mouseX, + mouseY, + false, + Collections.emptyList() + ); + } + + public String buildLore(String name, double xpGotten, double xpGainful, boolean hasNoLimit) { + String xpGottenFormatted = NumberFormat.getInstance().format((int) xpGotten); + String xpGainfulFormatted = NumberFormat.getInstance().format((int) xpGainful); + + if (xpGainful == 0 && xpGotten == 0 && !hasNoLimit) { + return EnumChatFormatting.GOLD + name + ": §c§lNOT DETECTABLE!"; + } + if (hasNoLimit) { + return EnumChatFormatting.GOLD + name + ": " + EnumChatFormatting.YELLOW + xpGottenFormatted + " XP"; + } + int percentage = (int) ((xpGotten / xpGainful) * 100); + if (xpGotten >= xpGainful) { + return EnumChatFormatting.GOLD + name + ": " + EnumChatFormatting.GREEN + + percentage + "%" + " §8(" + xpGottenFormatted + "/" + xpGainfulFormatted + " XP)"; + } else if (xpGotten == -1) { + return EnumChatFormatting.GOLD + name + ": §c§lCOLLECTION DISABLED!"; + } else { + + return EnumChatFormatting.GOLD + name + ": " + EnumChatFormatting.YELLOW + + percentage + "%" + " §8(" + xpGottenFormatted + "/" + xpGainfulFormatted + " XP)"; + } + } + + public JsonObject getConstant() { + return constant; + } + + public ProfileViewer.Profile getProfile() { + return profile; + } + + public String getProfileId() { + return profileId; + } + + public GuiProfileViewer getInstance() { + return instance; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/CoreTaskLevel.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/CoreTaskLevel.java new file mode 100644 index 00000000..be333359 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/CoreTaskLevel.java @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2023 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.profileviewer.level.task; + +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.profileviewer.PlayerStats; +import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; +import io.github.moulberry.notenoughupdates.profileviewer.level.LevelPage; +import io.github.moulberry.notenoughupdates.util.Constants; +import io.github.moulberry.notenoughupdates.util.hypixelapi.ProfileCollectionInfo; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class CoreTaskLevel { + + private final LevelPage levelPage; + + public CoreTaskLevel(LevelPage levelPage) {this.levelPage = levelPage;} + + private final List<String> skills = Arrays.asList( + "taming", + "mining", + "foraging", + "enchanting", + "carpentry", + "farming", + "combat", + "fishing", + "alchemy" + ); + + public void drawTask(JsonObject object, int mouseX, int mouseY, int guiLeft, int guiTop) { + JsonObject coreTask = levelPage.getConstant().get("core_task").getAsJsonObject(); + // skills + Map<String, ProfileViewer.Level> skyblockInfo = levelPage.getProfile().getSkyblockInfo(levelPage.getProfileId()); + + int sbXpGainedSkillLVL = 0; + if (skyblockInfo != null) { + for (String skill : skills) { + ProfileViewer.Level level = skyblockInfo.get(skill); + for (int i = 1; i <= level.level; i++) { + if (i <= 10) { + sbXpGainedSkillLVL += 5; + } + if (i <= 25 && i > 10) { + sbXpGainedSkillLVL += 10; + } + if (i <= 50 && i > 25) { + sbXpGainedSkillLVL += 20; + } + if (i <= 60 && i > 50) { + sbXpGainedSkillLVL += 30; + } + } + } + } else { + sbXpGainedSkillLVL = -1; + } + + // mp acc + int sbXpGainedMp = levelPage.getProfile().getMagicalPower(levelPage.getProfileId()); + + // pets + + int petScore = PlayerStats.getPetScore(object); + int sbXpPetScore = petScore * coreTask.get("pet_score_xp").getAsInt(); + + // museum is not possible + + // fairy soul + int fairySoulsCollected = object.get("fairy_souls_collected").getAsInt(); + int sbXpGainedFairy = ((fairySoulsCollected / 5)) * coreTask.get("fairy_souls_xp").getAsInt(); + + int sbXpCollection = -1; + int sbXpMinionTier = -1; // keeping at -1 here because cobblestone 1 minion XP isn't included for some reason? + JsonObject minionXp = Constants.MISC.get("minionXp").getAsJsonObject(); + int collectionsXp = coreTask.get("collections_xp").getAsInt(); + ProfileCollectionInfo collection; + collection = levelPage.getProfile().getCollectionInfo( + levelPage.getProfileId() + ); + if (collection != null) { + sbXpCollection = 0; + for (Map.Entry<String, ProfileCollectionInfo.CollectionInfo> stringCollectionInfoEntry : collection + .getCollections() + .entrySet()) { + ProfileCollectionInfo.CollectionInfo value = stringCollectionInfoEntry.getValue(); + sbXpCollection += value.getUnlockedTiers().size() * collectionsXp; + } + + for (int tier : collection.getCraftedGenerators().values()) { + for (int i = 1; i <= tier; i++) { + if (minionXp.has(i + "")) sbXpMinionTier += minionXp.get(i + "").getAsInt(); + } + } + } + List<String> lore = new ArrayList<>(); + + lore.add(levelPage.buildLore("Skill Level Up", + sbXpGainedSkillLVL, coreTask.get("skill_level_up").getAsInt(), false + )); + lore.add(levelPage.buildLore("Museum Progression", + 0, 0, false + )); + lore.add(levelPage.buildLore( + "Fairy Soul", + sbXpGainedFairy, coreTask.get("fairy_souls").getAsInt(), false + )); + lore.add(levelPage.buildLore("Accessory Bag", + sbXpGainedMp, 0, true + )); + lore.add(levelPage.buildLore("Pet Score", + sbXpPetScore, 0, true + )); + lore.add(levelPage.buildLore("Collections", + sbXpCollection, coreTask.get("collections").getAsInt(), false + )); + lore.add(levelPage.buildLore("Craft Minions", + sbXpMinionTier, coreTask.get("craft_minions").getAsInt(), false + )); + lore.add(levelPage.buildLore("Bank Upgrade", + 0, 0, false + )); + + levelPage.renderLevelBar( + "Core Task", + new ItemStack(Items.nether_star), + guiLeft + 23, + guiTop + 25, + 110, + 0, + sbXpGainedSkillLVL + sbXpGainedFairy + + sbXpCollection + sbXpMinionTier, + levelPage.getConstant().getAsJsonObject("category_xp").get("core_task").getAsInt(), + mouseX, + mouseY, + true, + lore + ); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/DungeonTaskLevel.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/DungeonTaskLevel.java new file mode 100644 index 00000000..157c8362 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/DungeonTaskLevel.java @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2023 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.profileviewer.level.task; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; +import io.github.moulberry.notenoughupdates.profileviewer.level.LevelPage; +import io.github.moulberry.notenoughupdates.util.Utils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class DungeonTaskLevel { + + private final LevelPage levelPage; + + public DungeonTaskLevel(LevelPage levelPage) {this.levelPage = levelPage;} + + public void drawTask(JsonObject object, int mouseX, int mouseY, int guiLeft, int guiTop) { + JsonObject dungeonTask = levelPage.getConstant().get("dungeon_task").getAsJsonObject(); + + Map<String, ProfileViewer.Level> skyblockInfo = + levelPage.getProfile().getSkyblockInfo(levelPage.getProfileId()); + + double sbLevelGainedFloor = 0; + double sbXpGainedClass = 0; + double sbXpGainedLvl = 0; + int catacombsLvl = 0; + if (skyblockInfo != null && skyblockInfo.containsKey("catacombs")) { + ProfileViewer.Level catacombs = skyblockInfo.get("catacombs"); + + catacombsLvl = (int) catacombs.level; + for (int i = 1; i <= catacombs.level; i++) { + if (40 > i) { + sbXpGainedLvl += 20; + } else { + sbXpGainedLvl += 40; + } + } + + List<String> dungeonClasses = Arrays.asList("healer", "tank", "mage", "archer", "berserk"); + for (String dungeonClass : dungeonClasses) { + ProfileViewer.Level level = skyblockInfo.get(dungeonClass); + for (int i = 1; i <= level.level; i++) { + if (i <= 50) sbXpGainedClass += dungeonTask.get("class_xp").getAsInt(); + } + } + + JsonArray completeCatacombs = dungeonTask.get("complete_catacombs").getAsJsonArray(); + int index = 0; + for (JsonElement completeCatacomb : completeCatacombs) { + int value = completeCatacomb.getAsInt(); + JsonObject normalCompletions = Utils + .getElement(object, "dungeons.dungeon_types.catacombs.tier_completions") + .getAsJsonObject(); + if (normalCompletions.has(index + "")) { + sbLevelGainedFloor = sbLevelGainedFloor + value; + } + index++; + } + + int masterCatacombs = dungeonTask.get("complete_master_catacombs").getAsInt(); + for (int i = 0; i <= 7; i++) { + JsonElement masterCompletions = Utils + .getElementOrDefault(object, "dungeons.dungeon_types.master_catacombs.tier_completions", null); + if (masterCompletions != null) { + if (masterCompletions.getAsJsonObject().has(i + "")) { + sbLevelGainedFloor = sbLevelGainedFloor + masterCatacombs; + } + } + } + } + + int catacombsLevelUp = dungeonTask.get("catacombs_level_up").getAsInt(); + int classLevelUp = dungeonTask.get("class_level_up").getAsInt(); + int completeDungeon = dungeonTask.get("complete_dungeon").getAsInt(); + int totalGainful = catacombsLevelUp + classLevelUp + completeDungeon; + double totalXp = sbXpGainedLvl + sbXpGainedClass + sbLevelGainedFloor; + + List<String> lore = new ArrayList<>(); + + lore.add(levelPage.buildLore("Catacombs Level Up", sbXpGainedLvl, catacombsLevelUp, false)); + lore.add(levelPage.buildLore("Class Level Up", sbXpGainedClass, classLevelUp, false)); + lore.add(levelPage.buildLore("Complete Dungeons", sbLevelGainedFloor, completeDungeon, false)); + + levelPage.renderLevelBar( + "Dungeon", + NotEnoughUpdates.INSTANCE.manager + .createItemResolutionQuery() + .withKnownInternalName("WITHER_RELIC") + .resolveToItemStack(), + guiLeft + 23, + guiTop + 55, + 110, + catacombsLvl, + totalXp, + totalGainful, + mouseX, + mouseY, + true, + lore + ); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/EssenceTaskLevel.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/EssenceTaskLevel.java new file mode 100644 index 00000000..d64f54c1 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/EssenceTaskLevel.java @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2023 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.profileviewer.level.task; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.profileviewer.level.LevelPage; +import io.github.moulberry.notenoughupdates.util.Constants; +import net.minecraft.util.EnumChatFormatting; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class EssenceTaskLevel { + + private final LevelPage levelPage; + + public EssenceTaskLevel(LevelPage levelPage) {this.levelPage = levelPage;} + + public void drawTask(JsonObject object, int mouseX, int mouseY, int guiLeft, int guiTop) { + List<String> lore = new ArrayList<>(); + + JsonObject categoryXp = levelPage.getConstant().get("category_xp").getAsJsonObject(); + JsonObject essenceShopTask = levelPage.getConstant().get("essence_shop_task").getAsJsonObject(); + JsonArray essenceSteps = essenceShopTask.get("essence_shop_xp").getAsJsonArray(); + JsonObject essencePerks = object.get("perks").getAsJsonObject(); + + Map<String, EssenceShop> loreMap = new HashMap<>(); + for (Map.Entry<String, JsonElement> stringJsonElementEntry : Constants.ESSENCESHOPS.entrySet()) { + String name = stringJsonElementEntry.getKey(); + JsonObject individualObjects = stringJsonElementEntry.getValue().getAsJsonObject(); + for (Map.Entry<String, JsonElement> jsonElementEntry : individualObjects.entrySet()) { + String key = jsonElementEntry.getKey(); + if (!essencePerks.has(key)) { + continue; + } + + int essenceAmount = essencePerks.get(key).getAsInt(); + + int amountReceivedForEach = 0; + for (int i = essenceAmount - 1; i >= 0; i--) { + amountReceivedForEach += essenceSteps.get(i).getAsInt(); + } + if (!loreMap.containsKey(name)) { + EssenceShop value = new EssenceShop(); + value.current += amountReceivedForEach; + value.name = name; + loreMap.put(name, value); + } else { + EssenceShop essenceShop = loreMap.get(name); + essenceShop.current += amountReceivedForEach; + } + } + } + + // bad workaround (pls fix later maybe) + for (Map.Entry<String, JsonElement> stringJsonElementEntry : essenceShopTask.entrySet()) { + String key = stringJsonElementEntry.getKey(); + if (!key.endsWith("_shop")) continue; + String name = key.split("_shop")[0].toUpperCase(); + if (!loreMap.containsKey(name)) { + loreMap.put(name, new EssenceShop().setName(name).setCurrent(0)); + } + } + + int total = 0; + for (Map.Entry<String, EssenceShop> stringEssenceShopEntry : loreMap.entrySet()) { + String key = stringEssenceShopEntry.getKey(); + EssenceShop value = stringEssenceShopEntry.getValue(); + value.name = NotEnoughUpdates.INSTANCE.manager + .createItemResolutionQuery() + .withKnownInternalName(key) + .resolveToItemListJson() + .get("displayname") + .getAsString(); + value.max = essenceShopTask.get(key.toLowerCase() + "_shop").getAsInt(); + lore.add(levelPage.buildLore( + EnumChatFormatting.getTextWithoutFormattingCodes(value.name), + value.current, + value.max, + false + )); + total += value.current; + } + + levelPage.renderLevelBar( + "Essence", + NotEnoughUpdates.INSTANCE.manager.createItemResolutionQuery() + .withKnownInternalName("ESSENCE_WITHER") + .resolveToItemStack(), + guiLeft + 299, + guiTop + 25, + 110, + total, + total, + categoryXp.get("essence_shop_task").getAsInt(), + mouseX, + mouseY, + true, + lore + ); + } + + class EssenceShop { + String name; + double max; + double current; + + public EssenceShop setCurrent(double current) { + this.current = current; + return this; + } + + public EssenceShop setName(String name) { + this.name = name; + return this; + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/MiscTaskLevel.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/MiscTaskLevel.java new file mode 100644 index 00000000..a717664d --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/MiscTaskLevel.java @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2023 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.profileviewer.level.task; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.profileviewer.CrimsonIslePage; +import io.github.moulberry.notenoughupdates.profileviewer.level.LevelPage; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +public class MiscTaskLevel { + + private final LevelPage levelPage; + + public MiscTaskLevel(LevelPage levelPage) {this.levelPage = levelPage;} + + public void drawTask(JsonObject object, int mouseX, int mouseY, int guiLeft, int guiTop) { + JsonObject miscellaneousTask = levelPage.getConstant().getAsJsonObject("miscellaneous_task"); + // I love doing this on god!!! + + int sbXpAccessoryUpgrade = 0; + int sbXpReaperPeppers = 0; + int sbXpUnlockedPowers = 0; + int sbXpAbiphone = 0; + if (object.has("accessory_bag_storage")) { + JsonObject accessoryBagStorage = object.getAsJsonObject("accessory_bag_storage"); + + sbXpAccessoryUpgrade = Utils.getElementAsInt(Utils.getElement( + accessoryBagStorage, + "bag_upgrades_purchased" + ), 0) * miscellaneousTask.get("accessory_bag_upgrades_xp").getAsInt(); + sbXpReaperPeppers = + miscellaneousTask.get("reaper_peppers_xp").getAsInt() * Utils.getElementAsInt(Utils.getElement( + object, + "reaper_peppers_eaten" + ), 0); + if (accessoryBagStorage.has("unlocked_powers")) sbXpUnlockedPowers = accessoryBagStorage.getAsJsonArray( + "unlocked_powers").size() * miscellaneousTask.get("unlocking_powers_xp").getAsInt(); + } + + int sbXpDojo = 0; + if (object.has("nether_island_player_data")) { + JsonObject netherIslandPlayerData = object.getAsJsonObject("nether_island_player_data"); + if (netherIslandPlayerData.has("dojo")) { + JsonObject dojoScoresObj = netherIslandPlayerData.getAsJsonObject("dojo"); + + int pointsTotal = 0; + for (int i = 0; i < CrimsonIslePage.apiDojoTestNames.size(); i++) { + for (Map.Entry<String, JsonElement> dojoData : dojoScoresObj.entrySet()) { + if (dojoData.getKey().equals("dojo_points_" + CrimsonIslePage.apiDojoTestNames.keySet().toArray()[i])) { + pointsTotal += dojoData.getValue().getAsInt(); + } + } + } + int index = getRankIndex(pointsTotal); + JsonArray theDojoXp = miscellaneousTask.getAsJsonArray("the_dojo_xp"); + for (int i = 0; i < index; i++) { + sbXpDojo += theDojoXp.get(i).getAsInt(); + } + } + + // abiphone + if (netherIslandPlayerData.has("abiphone")) { + JsonObject abiphone = netherIslandPlayerData.getAsJsonObject("abiphone"); + if (abiphone.has("active_contacts")) sbXpAbiphone = + abiphone.getAsJsonArray("active_contacts").size() * miscellaneousTask.get("abiphone_contacts_xp").getAsInt(); + } + } + + // harp + int sbXpGainedHarp = 0; + JsonObject harpSongsNames = miscellaneousTask.get("harp_songs_names").getAsJsonObject(); + if (object.has("harp_quest")) { + JsonObject harpQuest = object.get("harp_quest").getAsJsonObject(); + for (Map.Entry<String, JsonElement> stringJsonElementEntry : harpSongsNames.entrySet()) { + String key = stringJsonElementEntry.getKey(); + int value = stringJsonElementEntry.getValue().getAsInt(); + if (harpQuest.has(key)) { + sbXpGainedHarp += value; + } + } + } + + // community upgrades + int sbXpCommunityUpgrade = 0; + JsonObject profileInformation = levelPage.getProfile().getProfileInformation(levelPage.getProfileId()); + if (profileInformation != null && profileInformation.has("community_upgrades")) { + JsonObject communityUpgrades = profileInformation.getAsJsonObject("community_upgrades"); + JsonArray upgradeStates = communityUpgrades.getAsJsonArray("upgrade_states"); + JsonObject communityShopUpgradesMax = miscellaneousTask.getAsJsonObject("community_shop_upgrades_max"); + + int communityShopUpgradesXp = miscellaneousTask.get("community_shop_upgrades_xp").getAsInt(); + + for ( + JsonElement upgradeState : upgradeStates) { + if (!upgradeState.isJsonObject()) continue; + JsonObject value = upgradeState.getAsJsonObject(); + String upgrade = value.get("upgrade").getAsString(); + int tier = value.get("tier").getAsInt(); + if (communityShopUpgradesMax.has(upgrade)) { + int max = communityShopUpgradesMax.get(upgrade).getAsInt(); + if (max >= tier) { + sbXpCommunityUpgrade += communityShopUpgradesXp; + } + } + } + } + + // personal bank + int sbXpPersonalBank = 0; + if (object.has("personal_bank_upgrade")) { + int personalBankUpgrade = object.get("personal_bank_upgrade").getAsInt(); + JsonArray personalBankUpgradesXpArr = miscellaneousTask.getAsJsonArray("personal_bank_upgrades_xp"); + for (int i = 1; i <= personalBankUpgrade; i++) { + sbXpPersonalBank += personalBankUpgradesXpArr.get(i - 1).getAsInt(); + } + } + + List<String> lore = new ArrayList<>(); + + lore.add(levelPage.buildLore("Accessory Bag Upgrades", + sbXpAccessoryUpgrade, 0, true + )); + lore.add(levelPage.buildLore("Reaper Peppers", + sbXpReaperPeppers, miscellaneousTask.get("reaper_peppers").getAsInt(), false + )); + lore.add(levelPage.buildLore("Unlocking Powers", + sbXpUnlockedPowers, 0, true + )); + lore.add(levelPage.buildLore("The Dojo", + sbXpDojo, miscellaneousTask.get("the_dojo").getAsInt(), false + )); + lore.add(levelPage.buildLore( + EnumChatFormatting.ITALIC + "Harp Songs", + sbXpGainedHarp, miscellaneousTask.get("harp_songs").getAsInt(), false + )); + lore.add(levelPage.buildLore(EnumChatFormatting.ITALIC + "Abiphone Contacts", + sbXpAbiphone, miscellaneousTask.get("abiphone_contacts").getAsInt(), false + )); + lore.add(levelPage.buildLore("Community Shop Upgrades", + sbXpCommunityUpgrade, miscellaneousTask.get("community_shop_upgrades").getAsInt(), false + )); + lore.add(levelPage.buildLore("Personal Bank Upgrades", + sbXpPersonalBank, miscellaneousTask.get("personal_bank_upgrades").getAsInt(), false + )); + + levelPage.renderLevelBar( + "Misc. Task", + new ItemStack(Items.map), + guiLeft + 299, + guiTop + 55, + 110, + 0, + sbXpReaperPeppers + sbXpDojo + sbXpGainedHarp + sbXpAbiphone + + sbXpCommunityUpgrade + sbXpPersonalBank, + levelPage.getConstant().getAsJsonObject("category_xp").get("miscellaneous_task").getAsInt(), + mouseX, + mouseY, + true, + lore + ); + + } + + private int getRankIndex(int pointsTotal) { + AtomicInteger index = new AtomicInteger(); + CrimsonIslePage.dojoPointsToRank.forEach((required, name) -> { + if (pointsTotal > required) { + index.getAndIncrement(); + } + }); + return index.get(); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/SkillRelatedTaskLevel.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/SkillRelatedTaskLevel.java new file mode 100644 index 00000000..4ba7951c --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/SkillRelatedTaskLevel.java @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2023 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.profileviewer.level.task; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; +import io.github.moulberry.notenoughupdates.profileviewer.level.LevelPage; +import io.github.moulberry.notenoughupdates.util.Constants; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class SkillRelatedTaskLevel { + + private final LevelPage levelPage; + + public SkillRelatedTaskLevel(LevelPage levelPage) {this.levelPage = levelPage;} + + public void drawTask(JsonObject object, int mouseX, int mouseY, int guiLeft, int guiTop) { + JsonObject skillRelatedTask = levelPage.getConstant().get("skill_related_task").getAsJsonObject(); + JsonObject miningObj = skillRelatedTask.get("mining").getAsJsonObject(); + + float mithrilPowder = Utils.getElementAsFloat(Utils.getElement(object, "mining_core.powder_mithril"), 0); + float gemstonePowder = Utils.getElementAsFloat(Utils.getElement(object, "mining_core.powder_gemstone"), 0); + float mithril = Utils.getElementAsFloat(Utils.getElement(object, "mining_core.powder_spent_mithril"), 0) + + mithrilPowder; + float gemstone = (Utils.getElementAsFloat(Utils.getElement(object, "mining_core.powder_spent_gemstone"), 0)) + + gemstonePowder; + + float hotmXp = Utils.getElementAsFloat(Utils.getElement(object, "mining_core.experience"), 0); + ProfileViewer.Level levelObjHotm = + ProfileViewer.getLevel( + Utils.getElementOrDefault(Constants.LEVELING, "HOTM", new JsonArray()).getAsJsonArray(), + hotmXp, + 7, + false + ); + + int hotmXP = 0; + float level = levelObjHotm.level; + JsonArray hotmXpArray = miningObj.get("hotm_xp").getAsJsonArray(); + for (int i = 1; i <= level; i++) { + hotmXP += hotmXpArray.get(i - 1).getAsInt(); + } + + int gainByFirstMithrilThing; + if (mithril >= 350_000) { + gainByFirstMithrilThing = (int) (350000 / 2400d); + mithril -= 350_000; + } else { + gainByFirstMithrilThing = (int) (mithril / 2400d); + mithril = 0; + } + + int gainByFirstGemstoneThing; + if (gemstone >= 350_000) { + gainByFirstGemstoneThing = (int) (350_000 / 2500d); + gemstone -= 350_000; + } else { + gainByFirstGemstoneThing = (int) (gemstone / 2500d); + gemstone = 0; + } + + int sbXpMithrilPowder = (int) powder(3.75, mithril, 12_500_000); + int sbXpGemstonePowder = (int) powder(4.25, gemstone, 20_000_000); + + double sbXpHotmTier = + (sbXpMithrilPowder + gainByFirstMithrilThing) + (sbXpGemstonePowder + gainByFirstGemstoneThing) + + hotmXP; + + int sbXpPotmTier = 0; + JsonArray potmXpArray = miningObj.get("potm_xp").getAsJsonArray(); + + int potm = ((Utils.getElementAsInt(Utils.getElement(object, "mining_core.nodes.special_0"), 0))); + for (int i = 1; i <= potm; i++) { + sbXpPotmTier += potmXpArray.get(i - 1).getAsInt(); + } + + int sbXpCommissionMilestone = 0; + JsonArray tutorialArray = object.get("tutorial").getAsJsonArray(); + JsonArray commissionMilestoneXpArray = miningObj.get("commission_milestone_xp").getAsJsonArray(); + for (JsonElement jsonElement : tutorialArray) { + if (jsonElement.getAsJsonPrimitive().isString() && jsonElement.getAsString().startsWith( + "commission_milestone_reward_skyblock_xp_tier")) + for (int i = 1; i <= commissionMilestoneXpArray.size(); i++) { + int value = commissionMilestoneXpArray.get(i - 1).getAsInt(); + if (jsonElement.getAsString().equals("commission_milestone_reward_skyblock_xp_tier_" + i)) { + sbXpCommissionMilestone += value; + } + } + } + + // rock mines + float pet_milestone_ores_mined = Utils.getElementAsFloat(Utils.getElement( + object, + "stats.pet_milestone_ores_mined" + ), 0); + + int sbXpRockPet = 0; + int rockMilestoneXp = miningObj.get("rock_milestone_xp").getAsInt(); + JsonArray rockMilestoneRequired = miningObj.get("rock_milestone_required").getAsJsonArray(); + for (JsonElement jsonElement : rockMilestoneRequired) { + int value = jsonElement.getAsInt(); + if (pet_milestone_ores_mined >= value) { + sbXpRockPet += rockMilestoneXp; + } + } + + // farming + JsonObject farmingObj = skillRelatedTask.get("farming").getAsJsonObject(); + int anitaShopUpgradesXp = farmingObj.get("anita_shop_upgrades_xp").getAsInt(); + int doubleDrops = Utils.getElementAsInt(Utils.getElement(object, "jacob2.perks.double_drops"), 0); + int farmingLevelCap = Utils.getElementAsInt(Utils.getElement(object, "jacob2.perks.farming_level_cap"), 0); + + int sbXpGainedByAnita = (doubleDrops + farmingLevelCap) * anitaShopUpgradesXp; + + // fishing + int sbXpTrophyFish = 0; + JsonObject fishingObj = skillRelatedTask.get("fishing").getAsJsonObject(); + + JsonArray trophyFishXpArr = fishingObj.get("trophy_fish_xp").getAsJsonArray(); + if (object.has("trophy_fish")) { + + JsonObject trophyFish = object.get("trophy_fish").getAsJsonObject(); + for (Map.Entry<String, JsonElement> stringJsonElementEntry : trophyFish.entrySet()) { + String key = stringJsonElementEntry.getKey(); + if (stringJsonElementEntry.getValue().isJsonPrimitive()) { + if (key.endsWith("_bronze")) sbXpTrophyFish += trophyFishXpArr.get(0).getAsInt(); + if (key.endsWith("_silver")) sbXpTrophyFish += trophyFishXpArr.get(1).getAsInt(); + if (key.endsWith("_gold")) sbXpTrophyFish += trophyFishXpArr.get(2).getAsInt(); + if (key.endsWith("_diamond")) sbXpTrophyFish += trophyFishXpArr.get(3).getAsInt(); + } + } + + } + float petMilestoneKilled = Utils.getElementAsFloat( + Utils.getElement(object, "stats.pet_milestone_sea_creatures_killed"), + 0 + ); + + int sbXpDolphinPet = 0; + int dolphinMilestoneXp = fishingObj.get("dolphin_milestone_xp").getAsInt(); + JsonArray dolphinMilestoneRequired = fishingObj.get("dolphin_milestone_required").getAsJsonArray(); + for (JsonElement jsonElement : dolphinMilestoneRequired) { + int value = jsonElement.getAsInt(); + if (petMilestoneKilled >= value) { + sbXpDolphinPet += dolphinMilestoneXp; + } + } + + List<String> lore = new ArrayList<>(); + lore.add(levelPage.buildLore("Heart of the Mountain", sbXpHotmTier, miningObj.get("hotm").getAsInt(), false)); + lore.add(levelPage.buildLore( + "Commission Milestones", + sbXpCommissionMilestone, + miningObj.get("commission_milestone").getAsInt(), + false + )); + lore.add(levelPage.buildLore("Crystal Nucleus", 0, 0, false)); + lore.add(levelPage.buildLore( + "Anita's Shop Upgrade", + sbXpGainedByAnita, + farmingObj.get("anita_shop_upgrades").getAsInt(), + false + )); + lore.add(levelPage.buildLore("Peak of the Mountain", sbXpPotmTier, miningObj.get("potm").getAsInt(), false)); + lore.add(levelPage.buildLore("Trophy Fish", sbXpTrophyFish, fishingObj.get("trophy_fish").getAsInt(), false)); + lore.add(levelPage.buildLore("Rock Milestone", sbXpRockPet, miningObj.get("rock_milestone").getAsInt(), false)); + lore.add(levelPage.buildLore( + "Dolphin Milestone", + sbXpDolphinPet, + fishingObj.get("dolphin_milestone").getAsInt(), + false + )); + + levelPage.renderLevelBar( + "Skill Related Task", + new ItemStack(Items.diamond_sword), + guiLeft + 23, + guiTop + 115, + 110, + 0, + sbXpHotmTier + sbXpCommissionMilestone + sbXpGainedByAnita + sbXpPotmTier + sbXpTrophyFish + sbXpRockPet + + sbXpDolphinPet, + levelPage.getConstant().getAsJsonObject("category_xp").get("skill_related_task").getAsInt(), + mouseX, + mouseY, + true, + lore + ); + } + + private static double powder(double multiplier, float left, int CAP) { + double cons = 1758267; + if (left <= 0) return 0; + + left = Math.min(CAP, left); + + return multiplier * (Math.sqrt(1 + 8 * (Math.sqrt((cons / CAP) * left + 9))) - 3); + } + +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/SlayingTaskLevel.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/SlayingTaskLevel.java new file mode 100644 index 00000000..3aded435 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/SlayingTaskLevel.java @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2023 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.profileviewer.level.task; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.profileviewer.CrimsonIslePage; +import io.github.moulberry.notenoughupdates.profileviewer.ExtraPage; +import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer; +import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; +import io.github.moulberry.notenoughupdates.profileviewer.level.LevelPage; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class SlayingTaskLevel { + + private final LevelPage levelPage; + private final int[] bossLow = {25, 50, 100, 150, 250, 1000}; + private final int[] thorn = {25, 50, 150, 250, 400, 1000}; + private final int[] bossHigh = {50, 100, 150, 250, 500, 750, 1000}; + + + public SlayingTaskLevel(LevelPage levelPage) {this.levelPage = levelPage;} + + public void drawTask(JsonObject object, int mouseX, int mouseY, int guiLeft, int guiTop) { + // slayer + JsonObject slayingTask = levelPage.getConstant().get("slaying_task").getAsJsonObject(); + JsonArray slayerLevelUpXp = slayingTask.get("slayer_level_up_xp").getAsJsonArray(); + Map<String, ProfileViewer.Level> skyblockInfo = levelPage.getProfile().getSkyblockInfo(levelPage.getProfileId()); + + int sbXpGainedSlayer = 0; + if (skyblockInfo != null) { + for (String slayer : ProfileViewer.SLAYERS) { + ProfileViewer.Level level = skyblockInfo.get(slayer); + for (int i = 0; i < (int) level.level; i++) { + int asInt = slayerLevelUpXp.get(i).getAsInt(); + sbXpGainedSlayer += asInt; + } + } + } + + JsonObject bossCollectionsXp = slayingTask.getAsJsonObject("boss_collections_xp"); + + HashMap<String, Double> allComps = new HashMap<>(); + JsonElement normalCompletions = Utils + .getElement(object, "dungeons.dungeon_types.catacombs.tier_completions"); + + JsonElement masterCompletions = Utils + .getElement(object, "dungeons.dungeon_types.master_catacombs.tier_completions"); + + if (normalCompletions != null) { + HashMap<String, Double> normalCompMap = NotEnoughUpdates.INSTANCE.manager.gson.fromJson( + normalCompletions.getAsJsonObject(), + HashMap.class + ); + normalCompMap.forEach((floor, value) -> { + if (allComps.containsKey(floor)) { + allComps.put(floor, allComps.get(floor) + value); + } else { + allComps.put(floor, value); + } + }); + } + if (masterCompletions != null) { + HashMap<String, Double> masterCompMap = NotEnoughUpdates.INSTANCE.manager.gson.fromJson( + masterCompletions.getAsJsonObject(), + HashMap.class + ); + + masterCompMap.forEach((floor, value) -> { + if (allComps.containsKey(floor)) { + allComps.put(floor, allComps.get(floor) + value); + } else { + allComps.put(floor, value); + } + }); + } + // THIS SERVER IS AWESOME I LOVE CONSISTENCY!!!!!!! + + int bossCollectionXp = 0; + JsonArray dungeonCollectionXp = bossCollectionsXp.getAsJsonArray("dungeon_collection_xp"); + for (int i = 1; i <= 7; i++) { + if (!allComps.containsKey(i + "")) continue; + double value = allComps.get(i + ""); + switch (i) { + case 1: + case 2: + case 3: + bossCollectionXp += loopThroughCollection(bossLow, value, dungeonCollectionXp); + break; + case 4: + bossCollectionXp += loopThroughCollection(thorn, value, dungeonCollectionXp); + break; + case 5: + case 6: + case 7: + bossCollectionXp += loopThroughCollection(bossHigh, value, dungeonCollectionXp); + break; + } + } + + JsonArray defeatKuudraXp = slayingTask.get("defeat_kuudra_xp").getAsJsonArray(); + // kuudra + + int sbXpDefeatKuudra = 0; + + int kuudraBossCollection = 0; + if (object.has("nether_island_player_data")) { + JsonObject jsonObject = object.getAsJsonObject("nether_island_player_data").getAsJsonObject( + "kuudra_completed_tiers"); + for (Map.Entry<String, JsonElement> stringJsonElementEntry : jsonObject.entrySet()) { + String key = stringJsonElementEntry.getKey(); + int value = stringJsonElementEntry.getValue().getAsInt(); + + int i = 0; + for (String kuudraTier : CrimsonIslePage.KUUDRA_TIERS) { + if (key.equals(kuudraTier)) { + sbXpDefeatKuudra += defeatKuudraXp.get(i).getAsInt(); + kuudraBossCollection += (i + 1) * value; + } + i++; + } + } + if (kuudraBossCollection >= 10) bossCollectionXp += 10; + if (kuudraBossCollection >= 100) bossCollectionXp += 15; + if (kuudraBossCollection >= 500) bossCollectionXp += 20; + if (kuudraBossCollection >= 2000) bossCollectionXp += 25; + if (kuudraBossCollection >= 5000) bossCollectionXp += 30; + } + + int sbXpBestiary = 0; + int bestiaryTiers = GuiProfileViewer.getProfile().getBestiaryTiers(object); + sbXpBestiary += bestiaryTiers; + sbXpBestiary = sbXpBestiary + (sbXpBestiary / 10) * 2; + + int mythologicalKillsXp = 0; + if (object.has("stats")) { + JsonObject stats = object.get("stats").getAsJsonObject(); + if (stats.has("mythos_kills")) mythologicalKillsXp += (stats.get("mythos_kills").getAsLong() / 100); + } + + int mythologicalKillsMax = slayingTask.get("mythological_kills").getAsInt(); + if (mythologicalKillsXp > mythologicalKillsMax) mythologicalKillsXp = mythologicalKillsMax; + + // dragons + int sbXpFromDragonKills = 0; + JsonObject slayDragonsXp = slayingTask.getAsJsonObject("slay_dragons_xp"); + for (Map.Entry<String, JsonElement> stringJsonElementEntry : slayDragonsXp.entrySet()) { + String key = stringJsonElementEntry.getKey(); + int value = stringJsonElementEntry.getValue().getAsInt(); + // kills_superior_dragon_100 + float element = Utils.getElementAsFloat(Utils.getElement(object, "bestiary.kills_" + key + "_100"), 0); + if (element > 0) { + sbXpFromDragonKills += value; + } + } + + // slayer kills + int sbXpFromSlayerDefeat = 0; + + JsonArray defeatSlayersXp = slayingTask.get("defeat_slayers_xp").getAsJsonArray(); + for (String s : ExtraPage.slayers.keySet()) { + int maxLevel = ExtraPage.slayers.get(s); + for (int i = 0; i < 5; i++) { + if (i >= maxLevel) break; + float tier = Utils.getElementAsFloat( + Utils.getElement(object, "slayer_bosses." + s + ".boss_kills_tier_" + i), + 0 + ); + if (tier != 0) { + int value = defeatSlayersXp.get(i).getAsInt(); + sbXpFromSlayerDefeat += value; + } + } + } + + // arachne + JsonArray defeatArachneXp = slayingTask.get("defeat_arachne_xp").getAsJsonArray(); + int sbXpGainedArachne = 0; + + JsonElement tier1 = Utils.getElement(object, "bestiary.kills_arachne_300"); + if (tier1 != null) { + sbXpGainedArachne += defeatArachneXp.get(0).getAsInt(); + } + + JsonElement tier2 = Utils.getElement(object, "bestiary.kills_arachne_500"); + if (tier2 != null) { + sbXpGainedArachne += defeatArachneXp.get(1).getAsInt(); + } + + List<String> lore = new ArrayList<>(); + + int slayerLevelUpMax = slayingTask.get("slayer_level_up").getAsInt(); + int bossCollectionsMax = slayingTask.get("boss_collections").getAsInt(); + int slayDragonsMax = slayingTask.get("slay_dragons").getAsInt(); + int defeatSlayersMax = slayingTask.get("defeat_slayers").getAsInt(); + int defeatKuudraMax = slayingTask.get("defeat_kuudra").getAsInt(); + int defeatArachneMax = slayingTask.get("defeat_arachne").getAsInt(); + + lore.add(levelPage.buildLore("Slayer Level Up", sbXpGainedSlayer, slayerLevelUpMax, false)); + lore.add(levelPage.buildLore("Boss Collections", bossCollectionXp, bossCollectionsMax, false)); + lore.add(levelPage.buildLore("Bestiary Progress", sbXpBestiary, 0, true)); + lore.add(levelPage.buildLore("Mythological Kills", mythologicalKillsXp, mythologicalKillsMax, false)); + lore.add(levelPage.buildLore("Slay Dragons", sbXpFromDragonKills, slayDragonsMax, false)); + lore.add(levelPage.buildLore("Defeat Slayers", sbXpFromSlayerDefeat, defeatSlayersMax, false)); + lore.add(levelPage.buildLore("Defeat Kuudra", sbXpDefeatKuudra, defeatKuudraMax, false)); + lore.add(levelPage.buildLore("Defeat Arachne", sbXpGainedArachne, defeatArachneMax, false)); + + int slayingTaskMax = levelPage.getConstant().getAsJsonObject("category_xp").get("slaying_task").getAsInt(); + + levelPage.renderLevelBar( + "Slaying Task", + new ItemStack(Items.golden_sword), + guiLeft + 23, + guiTop + 85, + 110, + 0, sbXpGainedSlayer + bossCollectionXp + mythologicalKillsXp + + sbXpFromDragonKills + sbXpFromSlayerDefeat + sbXpDefeatKuudra + sbXpGainedArachne, + slayingTaskMax, + mouseX, + mouseY, + true, + lore + ); + } + + private int loopThroughCollection(int[] array, double value, JsonArray jsonArray) { + int i = 0; + int gain = 0; + for (int bossReq : array) { + if (value >= bossReq) { + int gained = jsonArray.get(i).getAsInt(); + gain += gained; + } + i++; + } + return gain; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/StoryTaskLevel.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/StoryTaskLevel.java new file mode 100644 index 00000000..2b1b59cb --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/level/task/StoryTaskLevel.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2023 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.profileviewer.level.task; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.profileviewer.level.LevelPage; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; + +import java.util.ArrayList; +import java.util.List; + +public class StoryTaskLevel { + + private final LevelPage levelPage; + + public StoryTaskLevel(LevelPage levelPage) {this.levelPage = levelPage;} + + public void drawTask(JsonObject object, int mouseX, int mouseY, int guiLeft, int guiTop) { + JsonObject storyTask = levelPage.getConstant().getAsJsonObject("story_task"); + JsonArray storyTaskNames = storyTask.getAsJsonArray("complete_objectives_names"); + + JsonObject objectives = object.getAsJsonObject("objectives"); + + int storyTaskXp = storyTask.get("complete_objectives_xp").getAsInt(); + int sbXpStory = 0; + for (JsonElement storyTaskName : storyTaskNames) { + String value = storyTaskName.getAsString(); + if (objectives.has(value)) { + JsonObject jsonObject = objectives.get(value).getAsJsonObject(); + if (jsonObject.has("status") && jsonObject.get("status").getAsString().equals("COMPLETE")) { + sbXpStory += storyTaskXp; + } + } + } + + List<String> lore = new ArrayList<>(); + lore.add(levelPage.buildLore("Complete Objectives", + sbXpStory, storyTask.get("complete_objectives").getAsInt(), false + )); + + levelPage.renderLevelBar( + "Story Task", + new ItemStack(Items.map), + guiLeft + 299, + guiTop + 85, + 110, + 0, + sbXpStory, + levelPage.getConstant().getAsJsonObject("category_xp").get("story_task").getAsInt(), + mouseX, + mouseY, + true, + lore + ); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/CraftingOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/CraftingOverlay.java index 004ea372..bd45f3e1 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/recipes/CraftingOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/CraftingOverlay.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.recipes; import io.github.moulberry.notenoughupdates.NEUManager; +import io.github.moulberry.notenoughupdates.miscfeatures.EnchantingSolvers; import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; @@ -114,6 +115,8 @@ public class CraftingOverlay { if (!Keyboard.getEventKeyState() || (Keyboard.getEventKey() != Keyboard.KEY_U && Keyboard.getEventKey() != Keyboard.KEY_R)) return; + if (EnchantingSolvers.currentSolver != EnchantingSolvers.SolverType.NONE) return; + runIfCraftingOverlayIsPresent(event.gui, (guiChest, chest) -> { int mouseX = Utils.getMouseX(); int mouseY = Utils.getMouseY(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java b/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java index 0105ba1f..6819ccc4 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java @@ -30,6 +30,7 @@ import com.google.gson.JsonPrimitive; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.events.RepositoryReloadEvent; import io.github.moulberry.notenoughupdates.recipes.EssenceUpgrades; import io.github.moulberry.notenoughupdates.recipes.NeuRecipe; @@ -40,7 +41,9 @@ import java.util.Map; import java.util.concurrent.locks.ReentrantLock; import java.util.regex.Pattern; +@NEUAutoSubscribe public class Constants { + private static class PatternSerializer implements JsonDeserializer<Pattern>, JsonSerializer<Pattern> { @Override public Pattern deserialize( @@ -78,6 +81,7 @@ public class Constants { public static JsonObject RNGSCORE; public static JsonObject ABIPHONE; public static JsonObject ESSENCESHOPS; + public static JsonObject SBLEVELS; private static final ReentrantLock lock = new ReentrantLock(); @@ -102,6 +106,7 @@ public class Constants { RNGSCORE = Utils.getConstant("rngscore", gson); ABIPHONE = Utils.getConstant("abiphone", gson); ESSENCESHOPS = Utils.getConstant("essenceshops", gson); + SBLEVELS = Utils.getConstant("sblevels", gson); parseEssenceCosts(); } catch (Exception ex) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java index bc44f656..f8f42b80 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java @@ -287,16 +287,20 @@ public class ItemUtils { if (secondLastBlankLine != -1) { List<String> petItemLore = new ArrayList<>(); if (heldItem != null) { - petItemLore.add(EnumChatFormatting.GOLD + "Held Item: " + heldItemJson.get("displayname").getAsString()); - List<String> heldItemLore = JsonUtils.getJsonArrayOrEmpty(heldItemJson, "lore", JsonElement::getAsString); - int blanks = 0; - for (String heldItemLoreLine : heldItemLore) { - if (heldItemLoreLine.trim().isEmpty()) { - blanks++; - } else if (blanks == 2) { - petItemLore.add(heldItemLoreLine); - } else if (blanks > 2) { - break; + if (heldItemJson == null) { + petItemLore.add(EnumChatFormatting.RED + "Could not find held item in repo!"); + } else { + petItemLore.add(EnumChatFormatting.GOLD + "Held Item: " + heldItemJson.get("displayname").getAsString()); + List<String> heldItemLore = JsonUtils.getJsonArrayOrEmpty(heldItemJson, "lore", JsonElement::getAsString); + int blanks = 0; + for (String heldItemLoreLine : heldItemLore) { + if (heldItemLoreLine.trim().isEmpty()) { + blanks++; + } else if (blanks == 2) { + petItemLore.add(heldItemLoreLine); + } else if (blanks > 2) { + break; + } } } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java b/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java index ec7ec404..8ce765aa 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java @@ -22,6 +22,7 @@ package io.github.moulberry.notenoughupdates.util; import com.google.common.reflect.TypeToken; import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.listener.ScoreboardLocationChangeListener; import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.LocationChangeEvent; import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager; @@ -65,6 +66,7 @@ import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; +@NEUAutoSubscribe public class SBInfo { private static final SBInfo INSTANCE = new SBInfo(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/TitleUtil.java b/src/main/java/io/github/moulberry/notenoughupdates/util/TitleUtil.java index 59db7cac..71b4e8dc 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/TitleUtil.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/TitleUtil.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.util; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.GlStateManager; @@ -27,6 +28,7 @@ import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.fml.common.eventhandler.EventPriority; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +@NEUAutoSubscribe public class TitleUtil { private static final TitleUtil INSTANCE = new TitleUtil(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java index 571a43f9..952eb50f 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java @@ -28,6 +28,7 @@ import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.miscfeatures.SlotLocking; +import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.PositionedSoundRecord; @@ -569,6 +570,70 @@ public class Utils { drawTexturedRect(x, y, width, height, 0, 1, 0, 1); } + public static void drawPvSideButton( + int yIndex, + ItemStack itemStack, + boolean pressed, + GuiProfileViewer guiProfileViewer + ) { + int guiLeft = GuiProfileViewer.getGuiLeft(); + int guiTop = GuiProfileViewer.getGuiTop(); + + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.enableAlpha(); + GlStateManager.alphaFunc(516, 0.1F); + + int x = guiLeft - 28; + int y = guiTop + yIndex * 28; + + float uMin = 193 / 256f; + float uMax = 223 / 256f; + float vMin = 200 / 256f; + float vMax = 228 / 256f; + if (pressed) { + uMin = 224 / 256f; + uMax = 1f; + + if (yIndex != 0) { + vMin = 228 / 256f; + vMax = 1f; + } + + guiProfileViewer.renderBlurredBackground( + guiProfileViewer.width, + guiProfileViewer.height, + x + 2, + y + 2, + 30, + 28 - 4 + ); + } else { + guiProfileViewer.renderBlurredBackground( + guiProfileViewer.width, + guiProfileViewer.height, + x + 2, + y + 2, + 28 - 2, + 28 - 4 + ); + } + + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.enableAlpha(); + GlStateManager.alphaFunc(516, 0.1F); + + Minecraft.getMinecraft().getTextureManager().bindTexture(GuiProfileViewer.pv_elements); + + Utils.drawTexturedRect(x, y, pressed ? 32 : 28, 28, uMin, uMax, vMin, vMax, GL11.GL_NEAREST); + + GlStateManager.enableDepth(); + Utils.drawItemStack(itemStack, x + 8, y + 7); + } + public static void drawTexturedRect(float x, float y, float width, float height, int filter) { drawTexturedRect(x, y, width, height, 0, 1, 0, 1, filter); } @@ -1961,13 +2026,13 @@ public class Utils { if (NotEnoughUpdates.INSTANCE.config.notifications.outdatedRepo) { NotificationHandler.displayNotification(Lists.newArrayList( EnumChatFormatting.RED + EnumChatFormatting.BOLD.toString() + "Missing repo data", - EnumChatFormatting.RED + - "Data used for many NEU features is not up to date, this should normally not be the case.", - EnumChatFormatting.RED + "You can try " + EnumChatFormatting.BOLD + "/neuresetrepo" + EnumChatFormatting.RESET + - EnumChatFormatting.RED + " and restart your game" + - " to see if that fixes the issue.", - EnumChatFormatting.RED + "If the problem persists please join " + EnumChatFormatting.BOLD + - "discord.gg/moulberry" + + EnumChatFormatting.RED + + "Data used for many NEU features is not up to date, this should normally not be the case.", + EnumChatFormatting.RED + "You can try " + EnumChatFormatting.BOLD + "/neuresetrepo" + EnumChatFormatting.RESET + + EnumChatFormatting.RED + " and restart your game" + + " to see if that fixes the issue.", + EnumChatFormatting.RED + "If the problem persists please join " + EnumChatFormatting.BOLD + + "discord.gg/moulberry" + EnumChatFormatting.RESET + EnumChatFormatting.RED + " and message in " + EnumChatFormatting.BOLD + "#neu-support" + EnumChatFormatting.RESET + EnumChatFormatting.RED + " to get support" ), diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/XPInformation.java b/src/main/java/io/github/moulberry/notenoughupdates/util/XPInformation.java index 81eea343..94bfbee8 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/XPInformation.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/XPInformation.java @@ -22,6 +22,7 @@ package io.github.moulberry.notenoughupdates.util; import com.google.common.base.Splitter; import com.google.gson.JsonArray; import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.core.util.StringUtils; import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; import net.minecraftforge.client.event.ClientChatReceivedEvent; @@ -34,6 +35,7 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; +@NEUAutoSubscribe public class XPInformation { private static final XPInformation INSTANCE = new XPInformation(); diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/EnforcedConfigValues.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/EnforcedConfigValues.kt new file mode 100644 index 00000000..7351a4a0 --- /dev/null +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/EnforcedConfigValues.kt @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2022 Linnea Gräf + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscfeatures + +import com.google.gson.JsonElement +import io.github.moulberry.notenoughupdates.NotEnoughUpdates +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe +import io.github.moulberry.notenoughupdates.events.RepositoryReloadEvent +import io.github.moulberry.notenoughupdates.util.NotificationHandler +import io.github.moulberry.notenoughupdates.util.Shimmy +import io.github.moulberry.notenoughupdates.util.Utils +import io.github.moulberry.notenoughupdates.util.kotlin.fromJson +import net.minecraft.client.Minecraft +import net.minecraftforge.client.event.GuiOpenEvent +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import net.minecraftforge.fml.common.gameevent.TickEvent + +@NEUAutoSubscribe +object EnforcedConfigValues { + + class EnforcedValue { + // lateinit var because we use gson (instead of kotlinx.serialization which can handle data classes) + lateinit var path: String + lateinit var value: JsonElement + } + + class EnforcedValueData { + var enforcedValues: List<EnforcedValue> = listOf() + var notificationPSA: List<String>? = null + var chatPSA: List<String>? = null + lateinit var affectedVersions: List<Int> + } + + + var enforcedValues: List<EnforcedValueData> = listOf() + + @SubscribeEvent + fun onRepoReload(event: RepositoryReloadEvent) { + val fixedValues = event.repositoryRoot.resolve("enforced_values") + enforcedValues = if (fixedValues.exists()) { + fixedValues.listFiles() + .filter { + it != null && it.isFile && it.canRead() + } + .map { + NotEnoughUpdates.INSTANCE.manager.gson.fromJson<EnforcedValueData>(it.readText()) + }.filter { + NotEnoughUpdates.VERSION_ID in it.affectedVersions + } + } else { + listOf() + } + if (!event.isFirstLoad) + sendPSAs() + } + + @SubscribeEvent + fun onGuiClose(event: GuiOpenEvent) { + enforceOntoConfig(NotEnoughUpdates.INSTANCE.config ?: return) + } + + var hasSentPSAsOnce = false + + @SubscribeEvent + fun onTick(tickEvent: TickEvent.ClientTickEvent) { + if (hasSentPSAsOnce || Minecraft.getMinecraft().thePlayer == null || !NotEnoughUpdates.INSTANCE.isOnSkyblock) return + hasSentPSAsOnce = true + sendPSAs() + enforceOntoConfig(NotEnoughUpdates.INSTANCE.config ?: return) + } + + fun sendPSAs() { + val notification = enforcedValues.flatMap { it.notificationPSA ?: emptyList() } + if (notification.isNotEmpty()) { + NotificationHandler.displayNotification(notification, true) + } + val chat = enforcedValues.flatMap { it.chatPSA ?: emptyList() } + if (chat.isNotEmpty()) { + for (line in chat) { + Utils.addChatMessage(line) + } + } + } + + + fun enforceOntoConfig(config: Any) { + for (enforcedValue in enforcedValues.flatMap { it.enforcedValues }) { + val shimmy = Shimmy.makeShimmy(config, enforcedValue.path.split(".")) + if (shimmy == null) { + println("Could not create shimmy for path ${enforcedValue.path}") + continue + } + val currentValue = shimmy.getJson() + if (currentValue != enforcedValue.value) { + println("Resetting ${enforcedValue.path} to ${enforcedValue.value} from $currentValue") + shimmy.setJson(enforcedValue.value) + } + } + } + + fun isBlockedFromEditing(optionPath: String): Boolean { + return enforcedValues.flatMap { it.enforcedValues }.any { it.path == optionPath } + } + + +} diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/inventory/MuseumCheapestItemOverlay.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/inventory/MuseumCheapestItemOverlay.kt index 7485f14d..ccaf5ad8 100644 --- a/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/inventory/MuseumCheapestItemOverlay.kt +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/inventory/MuseumCheapestItemOverlay.kt @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures.inventory import io.github.moulberry.notenoughupdates.NotEnoughUpdates +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe import io.github.moulberry.notenoughupdates.core.util.ArrowPagesUtils import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer import io.github.moulberry.notenoughupdates.util.MuseumUtil @@ -39,7 +40,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import org.lwjgl.input.Mouse import org.lwjgl.opengl.GL11 - +@NEUAutoSubscribe object MuseumCheapestItemOverlay { data class MuseumItem( var name: String, diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/inventory/MuseumItemHighlighter.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/inventory/MuseumItemHighlighter.kt index b809ee9f..945449ba 100644 --- a/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/inventory/MuseumItemHighlighter.kt +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/inventory/MuseumItemHighlighter.kt @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.miscfeatures.inventory import io.github.moulberry.notenoughupdates.NotEnoughUpdates +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe import io.github.moulberry.notenoughupdates.core.ChromaColour import io.github.moulberry.notenoughupdates.core.util.StringUtils import io.github.moulberry.notenoughupdates.events.GuiContainerBackgroundDrawnEvent @@ -37,6 +38,7 @@ import net.minecraft.item.EnumDyeColor import net.minecraft.item.ItemStack import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +@NEUAutoSubscribe object MuseumItemHighlighter { private val manager get() = NotEnoughUpdates.INSTANCE.manager diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/PetLeveling.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/PetLeveling.kt index 200aa3fa..99066e52 100644 --- a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/PetLeveling.kt +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/PetLeveling.kt @@ -23,7 +23,9 @@ import com.google.gson.JsonObject import io.github.moulberry.notenoughupdates.events.RepositoryReloadEvent import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay.Rarity import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe +@NEUAutoSubscribe object PetLeveling { data class ExpLadder( diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/Shimmy.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/Shimmy.kt new file mode 100644 index 00000000..37cdd3ac --- /dev/null +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/Shimmy.kt @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2022 Linnea Gräf + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.util + +import com.google.gson.Gson +import com.google.gson.JsonElement +import java.lang.reflect.Field + +class Shimmy private constructor( + val source: Any, + val field: Field, +) { + companion object { + val gson = Gson() + private fun shimmy(source: Any?, fieldName: String): Any? { + if (source == null) return null + return try { + val declaredField = source.javaClass.getDeclaredField(fieldName) + declaredField.isAccessible = true + declaredField.get(source) + } catch (e: NoSuchFieldException) { + null + } + } + + @JvmStatic + fun makeShimmy(source: Any?, path: List<String>): Shimmy? { + if (path.isEmpty()) + return null + var source = source + for (part in path.dropLast(1)) { + source = shimmy(source, part) + } + if (source == null) return null + val lastName = path.last() + return try { + val field = source.javaClass.getDeclaredField(lastName) + field.isAccessible = true + Shimmy( + source, + field, + ) + } catch (e: NoSuchFieldException) { + null + } + } + + } + + val clazz: Class<*> = field.type + fun get(): Any? { + return field.get(source) + } + + fun set(value: Any?) { + field.set(source, value) + } + + fun getJson(): JsonElement { + return gson.toJsonTree(get()) + } + + fun setJson(element: JsonElement) { + set(gson.fromJson(element, clazz)) + } + + +} diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/hypixelapi/Collection.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/hypixelapi/Collection.kt new file mode 100644 index 00000000..b2c7fcec --- /dev/null +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/hypixelapi/Collection.kt @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2023 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.util.hypixelapi + +import com.google.gson.JsonArray +import com.google.gson.JsonObject +import io.github.moulberry.notenoughupdates.NotEnoughUpdates +import java.math.BigInteger +import java.util.concurrent.CompletableFuture +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.component1 +import kotlin.collections.component2 +import kotlin.collections.filter +import kotlin.collections.flatMap +import kotlin.collections.groupBy +import kotlin.collections.mapNotNull +import kotlin.collections.mapValues +import kotlin.collections.maxOf +import kotlin.collections.sumOf +import kotlin.collections.toList +import kotlin.collections.toMap +import kotlin.collections.toSet + +data class ProfileCollectionInfo( + val collections: Map<String, CollectionInfo>, + val craftedGenerators: Map<String, Int>, +) { + data class CollectionInfo( + val collection: Collection, + val totalCollectionCount: BigInteger, + val personalCollectionCount: BigInteger, + val unlockedTiers: List<CollectionTier>, + ) + + class CollectionMetadata internal constructor() { + lateinit var collections: Map<String, CollectionCategory> + private set + val allCollections by lazy { collections.values.flatMap { it.items.toList() }.toMap() } + } + + class CollectionCategory internal constructor() { + lateinit var items: Map<String, Collection> + private set + } + + class Collection internal constructor() { + lateinit var name: String + private set + var maxTiers: Int = -1 + private set + lateinit var tiers: List<CollectionTier> + private set + + override fun toString(): String { + return "Collection(name=$name, maxTiers=$maxTiers, tiers=$tiers)" + } + } + + class CollectionTier internal constructor() { + var tier: Int = -1 + private set + var amountRequired: Int = -1 + private set + lateinit var unlocks: List<String> + private set + + override fun toString(): String { + return "CollectionTier(tier=$tier, amountRequired=$amountRequired, unlocks=$unlocks)" + } + } + + + companion object { + + + val generatorPattern = "^([^0-9]+)_([0-9]+)$".toRegex() + + val hypixelCollectionInfo: CompletableFuture<CollectionMetadata> by lazy { + NotEnoughUpdates.INSTANCE.manager.apiUtils + .newHypixelApiRequest("resources/skyblock/collections") + .requestJson() + .thenApply { + NotEnoughUpdates.INSTANCE.manager.gson.fromJson(it, CollectionMetadata::class.java) + } + } + + fun getCollectionData( + profileData: JsonObject, + mainPlayer: String, + collectionData: CollectionMetadata + ): ProfileCollectionInfo? { + val mainPlayerUUID = mainPlayer.replace("-", "") + val members = profileData["members"] as? JsonObject ?: return null + val mainPlayerData = + (members[mainPlayerUUID] as? JsonObject ?: return null) + val mainPlayerCollection = mainPlayerData["collection"] as? JsonObject ?: return null + val memberCollections = members.entrySet().mapNotNull { (uuid, data) -> + if (data !is JsonObject) return null + data["collection"] as? JsonObject + } + val generators = members.entrySet().mapNotNull { (uuid, data) -> + if (data !is JsonObject) return null + data["crafted_generators"] as? JsonArray + }.flatMap { it.toList() } + return ProfileCollectionInfo( + collectionData.allCollections.mapValues { (name, collection) -> + val totalCollection = memberCollections.sumOf { it[name]?.asBigInteger ?: BigInteger.ZERO } + val personalCollection = mainPlayerCollection[name]?.asBigInteger ?: BigInteger.ZERO + CollectionInfo( + collection, + totalCollection, + personalCollection, + collection.tiers.filter { BigInteger.valueOf(it.amountRequired.toLong()) <= totalCollection } + ) + }, + generators.toSet() + .mapNotNull { + val pattern = generatorPattern.matchEntire(it.asString) ?: return@mapNotNull null + pattern.groupValues[1] to pattern.groupValues[2].toInt() + } + .groupBy { it.first } + .mapValues { + it.value.maxOf { it.second } + } + .toMap() + ) + } + + /** + * This should be the json object returned by /skyblock/profiles at profiles.<somenumber>. (aka the root tag + * should contain profile_id, members, cute_name, etc.) + */ + @JvmStatic + fun getCollectionData(profileData: JsonObject, mainPlayer: String): CompletableFuture<ProfileCollectionInfo?> { + return hypixelCollectionInfo.thenApply { + getCollectionData(profileData, mainPlayer, it) + } + } + } + +} diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/kotlin/gson.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/kotlin/gson.kt new file mode 100644 index 00000000..00c3d729 --- /dev/null +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/kotlin/gson.kt @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.util.kotlin + +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import java.lang.reflect.Type + + +inline fun <reified T : Any> typeToken(): Type { + return (object : TypeToken<T>() {}).type +} + +inline fun <reified T : Any> Gson.fromJson(string: String): T { + return fromJson(string, typeToken<T>()) +} diff --git a/src/main/resources/assets/notenoughupdates/pv_basic.png b/src/main/resources/assets/notenoughupdates/pv_basic.png Binary files differindex 4d5236f5..de254644 100644 --- a/src/main/resources/assets/notenoughupdates/pv_basic.png +++ b/src/main/resources/assets/notenoughupdates/pv_basic.png diff --git a/src/main/resources/assets/notenoughupdates/pv_levels.png b/src/main/resources/assets/notenoughupdates/pv_levels.png Binary files differnew file mode 100644 index 00000000..21810476 --- /dev/null +++ b/src/main/resources/assets/notenoughupdates/pv_levels.png diff --git a/src/main/resources/assets/notenoughupdates/textures/gui/config_blocked.png b/src/main/resources/assets/notenoughupdates/textures/gui/config_blocked.png Binary files differnew file mode 100644 index 00000000..eb60da5f --- /dev/null +++ b/src/main/resources/assets/notenoughupdates/textures/gui/config_blocked.png diff --git a/src/main/resources/mixins.notenoughupdates.json b/src/main/resources/mixins.notenoughupdates.json index d080d7f5..8877aed8 100644 --- a/src/main/resources/mixins.notenoughupdates.json +++ b/src/main/resources/mixins.notenoughupdates.json @@ -23,6 +23,7 @@ "MixinGuiIngame", "MixinGuiInventory", "MixinGuiScreen", + "MixinGuiUtils", "MixinInventoryBasic", "MixinInventoryEffectRenderer", "MixinInventoryPlayer", @@ -55,6 +56,7 @@ "MixinEntityChargedCreeper", "MixinGuiEditSign", "MixinGuiTextField", + "MixinLayerDeadmau5Head", "MixinThreadDownloadImageData", "MixinThreadDownloadImageDataThread" ] |